diff --git a/packages/builder/src/builderStore/store/index.js b/packages/builder/src/builderStore/store/index.js index f4d47064be..6755bc0a7c 100644 --- a/packages/builder/src/builderStore/store/index.js +++ b/packages/builder/src/builderStore/store/index.js @@ -64,11 +64,16 @@ export const getStore = () => { store.getPathToComponent = getPathToComponent(store) store.addTemplatedComponent = addTemplatedComponent(store) store.setMetadataProp = setMetadataProp(store) + store.storeComponentForCopy = storeComponentForCopy(store) + store.pasteComponent = pasteComponent(store) return store } export default getStore +export const getComponentDefinition = (state, name) => + name.startsWith("##") ? getBuiltin(name) : state.components[name] + const setPackage = (store, initial) => async pkg => { const [main_screens, unauth_screens] = await Promise.all([ api @@ -317,8 +322,6 @@ const setCurrentPage = store => pageName => { }) } -// const getComponentDefinition = (components, name) => components.find(c => c.name === name) - /** * @param {string} componentToAdd - name of the component to add to the application * @param {string} presetName - name of the component preset if defined @@ -344,9 +347,7 @@ const addChildComponent = store => (componentToAdd, presetName) => { return state } - const component = componentToAdd.startsWith("##") - ? getBuiltin(componentToAdd) - : state.components[componentToAdd] + const component = getComponentDefinition(componentToAdd) const presetProps = presetName ? component.presets[presetName] : {} @@ -398,14 +399,18 @@ const addTemplatedComponent = store => props => { }) } +const _selectComponent = (state, component) => { + const componentDef = component._component.startsWith("##") + ? component + : state.components[component._component] + state.currentComponentInfo = makePropsSafe(componentDef, component) + state.currentView = "component" + return state +} + const selectComponent = store => component => { store.update(state => { - const componentDef = component._component.startsWith("##") - ? component - : state.components[component._component] - state.currentComponentInfo = makePropsSafe(componentDef, component) - state.currentView = "component" - return state + return _selectComponent(state, component) }) } @@ -534,7 +539,6 @@ const copyComponent = store => component => { p._id = uuid() }) parent._children = [...parent._children, copiedComponent] - s.curren _saveCurrentPreviewItem(s) s.currentComponentInfo = copiedComponent return s @@ -572,10 +576,58 @@ const getPathToComponent = store => component => { return path } +const generateNewIdsForComponent = component => + walkProps(component, p => { + p._id = uuid() + }) + +const storeComponentForCopy = store => (component, cut = false) => { + store.update(s => { + const copiedComponent = cloneDeep(component) + s.componentToPaste = copiedComponent + if (cut) { + const parent = getParent(s.currentPreviewItem.props, component._id) + parent._children = parent._children.filter(c => c._id !== component._id) + _selectComponent(s, parent) + } + + return s + }) +} + +const pasteComponent = store => (targetComponent, mode) => { + store.update(s => { + if (!s.componentToPaste) return s + + const componentToPaste = cloneDeep(s.componentToPaste) + generateNewIdsForComponent(componentToPaste) + delete componentToPaste._cutId + + if (mode === "inside") { + targetComponent._children.push(componentToPaste) + return s + } + + const parent = getParent(s.currentPreviewItem.props, targetComponent) + + const targetIndex = parent._children.indexOf(targetComponent) + const index = mode === "above" ? targetIndex : targetIndex + 1 + parent._children.splice(index, 0, cloneDeep(componentToPaste)) + + _saveCurrentPreviewItem(s) + _selectComponent(s, componentToPaste) + + return s + }) +} + const getParent = (rootProps, child) => { let parent walkProps(rootProps, (p, breakWalk) => { - if (p._children && p._children.includes(child)) { + if ( + p._children && + (p._children.includes(child) || p._children.some(c => c._id === child)) + ) { parent = p breakWalk() } diff --git a/packages/builder/src/components/common/Icons/More.svelte b/packages/builder/src/components/common/Icons/More.svelte new file mode 100644 index 0000000000..f072c48976 --- /dev/null +++ b/packages/builder/src/components/common/Icons/More.svelte @@ -0,0 +1,8 @@ + diff --git a/packages/builder/src/components/common/Icons/index.js b/packages/builder/src/components/common/Icons/index.js index 69b78421da..4e4b41082d 100644 --- a/packages/builder/src/components/common/Icons/index.js +++ b/packages/builder/src/components/common/Icons/index.js @@ -31,3 +31,4 @@ export { default as EmailIcon } from "./Email.svelte" export { default as TwitterIcon } from "./Twitter.svelte" export { default as InfoIcon } from "./Info.svelte" export { default as CloseIcon } from "./Close.svelte" +export { default as MoreIcon } from "./More.svelte" diff --git a/packages/builder/src/components/userInterface/ComponentDropdownMenu.svelte b/packages/builder/src/components/userInterface/ComponentDropdownMenu.svelte new file mode 100644 index 0000000000..5a485f9680 --- /dev/null +++ b/packages/builder/src/components/userInterface/ComponentDropdownMenu.svelte @@ -0,0 +1,116 @@ + + +