From b839325a86e86dbec8adc9b94f9a3c63eda86ab4 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 26 Aug 2022 08:47:50 +0100 Subject: [PATCH 01/32] Add initial work on grid layout --- .../src/builderStore/store/frontend.js | 19 ++- .../[screenId]/_components/AppPreview.svelte | 2 + .../_components/settings/componentStyles.js | 61 ++++++++ .../new/_components/componentStructure.json | 3 +- packages/client/manifest.json | 9 ++ .../client/src/components/Component.svelte | 4 + .../client/src/components/app/Grid.svelte | 81 +++++++++++ packages/client/src/components/app/index.js | 1 + .../src/components/preview/DNDHandler.svelte | 137 ++++++++++++++++-- .../src/components/preview/Indicator.svelte | 100 +++++++++++++ .../components/preview/IndicatorSet.svelte | 1 + packages/client/src/index.js | 4 + packages/client/src/stores/builder.js | 15 +- packages/client/src/utils/styleable.js | 2 +- 14 files changed, 423 insertions(+), 16 deletions(-) create mode 100644 packages/client/src/components/app/Grid.svelte diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index 4d0653208c..9deeef15f1 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -439,7 +439,16 @@ export const getFrontendStore = () => { return { _id: Helpers.uuid(), _component: definition.component, - _styles: { normal: {}, hover: {}, active: {} }, + _styles: { + normal: { + "grid-column-start": 1, + "grid-column-end": 2, + "grid-row-start": 1, + "grid-row-end": 2, + }, + hover: {}, + active: {}, + }, _instanceName: `New ${definition.name}`, ...cloneDeep(props), ...extras, @@ -873,6 +882,14 @@ export const getFrontendStore = () => { } }) }, + updateStyles: async styles => { + await store.actions.components.patch(component => { + component._styles.normal = { + ...component._styles.normal, + ...styles, + } + }) + }, updateCustomStyle: async style => { await store.actions.components.patch(component => { component._styles.custom = style diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte index 9f81effd1d..ba132053b7 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte @@ -143,6 +143,8 @@ } } else if (type === "update-prop") { await store.actions.components.updateSetting(data.prop, data.value) + } else if (type === "update-styles") { + await store.actions.components.updateStyles(data.styles) } else if (type === "delete-component" && data.id) { // Legacy type, can be deleted in future confirmDeleteComponent(data.id) diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/componentStyles.js b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/componentStyles.js index d4912241b3..710cbed9b1 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/componentStyles.js +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/componentStyles.js @@ -1,6 +1,67 @@ import { Input, Select } from "@budibase/bbui" import ColorPicker from "components/design/settings/controls/ColorPicker.svelte" +export const grid = { + label: "Grid", + columns: "1fr 1fr", + settings: [ + { + label: "Col. start", + key: "grid-column-start", + control: Select, + placeholder: "Auto", + options: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], + }, + { + label: "Col. end", + key: "grid-column-end", + control: Select, + placeholder: "Auto", + options: [ + { label: "1", value: 2 }, + { label: "2", value: 3 }, + { label: "3", value: 4 }, + { label: "4", value: 5 }, + { label: "5", value: 6 }, + { label: "6", value: 7 }, + { label: "7", value: 8 }, + { label: "8", value: 9 }, + { label: "9", value: 10 }, + { label: "10", value: 11 }, + { label: "11", value: 12 }, + { label: "12", value: 13 }, + ], + }, + { + label: "Row start", + key: "grid-row-start", + control: Select, + placeholder: "Auto", + options: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], + }, + { + label: "Row end", + key: "grid-row-end", + control: Select, + placeholder: "Auto", + options: [ + { label: "1", value: 2 }, + { label: "2", value: 3 }, + { label: "3", value: 4 }, + { label: "4", value: 5 }, + { label: "5", value: 6 }, + { label: "6", value: 7 }, + { label: "7", value: 8 }, + { label: "8", value: 9 }, + { label: "9", value: 10 }, + { label: "10", value: 11 }, + { label: "11", value: 12 }, + { label: "12", value: 13 }, + ], + }, + ], +} + export const margin = { label: "Margin", columns: "1fr 1fr", diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/new/_components/componentStructure.json b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/new/_components/componentStructure.json index acd28c6a41..fddff9d0d9 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/new/_components/componentStructure.json +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/new/_components/componentStructure.json @@ -13,7 +13,8 @@ "icon": "ClassicGridView", "children": [ "container", - "section" + "section", + "grid" ] }, { diff --git a/packages/client/manifest.json b/packages/client/manifest.json index 87cc8b2567..642b4e0f99 100644 --- a/packages/client/manifest.json +++ b/packages/client/manifest.json @@ -86,6 +86,7 @@ "hasChildren": true, "showSettingsBar": true, "styles": [ + "grid", "padding", "size", "background", @@ -4378,5 +4379,13 @@ "required": true } ] + }, + "grid": { + "name": "Grid", + "icon": "ViewGrid", + "hasChildren": true, + "styles": [ + "size" + ] } } \ No newline at end of file diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte index a7f506a387..e55b5288e5 100644 --- a/packages/client/src/components/Component.svelte +++ b/packages/client/src/components/Component.svelte @@ -151,6 +151,10 @@ children: children.length, styles: { ...instance._styles, + normal: { + ...instance._styles?.normal, + ...(selected ? $builderStore.gridStyles : null), + }, id, empty: emptyState, interactive, diff --git a/packages/client/src/components/app/Grid.svelte b/packages/client/src/components/app/Grid.svelte new file mode 100644 index 0000000000..51c5162386 --- /dev/null +++ b/packages/client/src/components/app/Grid.svelte @@ -0,0 +1,81 @@ + + +
+
+ {#each coords as coord} +
+ {/each} +
+ + {#if $builderStore.isDragging} +
+ {#each coords as coord} +
+ {/each} +
+ {/if} +
+ + diff --git a/packages/client/src/components/app/index.js b/packages/client/src/components/app/index.js index 1c0d868433..b64e074115 100644 --- a/packages/client/src/components/app/index.js +++ b/packages/client/src/components/app/index.js @@ -34,6 +34,7 @@ export { default as spectrumcard } from "./SpectrumCard.svelte" export { default as tag } from "./Tag.svelte" export { default as markdownviewer } from "./MarkdownViewer.svelte" export { default as embeddedmap } from "./embedded-map/EmbeddedMap.svelte" +export { default as grid } from "./Grid.svelte" export * from "./charts" export * from "./forms" export * from "./table" diff --git a/packages/client/src/components/preview/DNDHandler.svelte b/packages/client/src/components/preview/DNDHandler.svelte index c37eb93afa..719f17efe3 100644 --- a/packages/client/src/components/preview/DNDHandler.svelte +++ b/packages/client/src/components/preview/DNDHandler.svelte @@ -12,7 +12,7 @@ import { get } from "svelte/store" import IndicatorSet from "./IndicatorSet.svelte" import DNDPositionIndicator from "./DNDPositionIndicator.svelte" - import { builderStore } from "stores" + import { builderStore, componentStore } from "stores" let dragInfo let dropInfo @@ -35,22 +35,41 @@ const getDOMNodeForComponent = component => { const parent = component.closest(".component") - const children = Array.from(parent.children) - return children[0] + const children = Array.from(parent?.children || []) + return children?.[0] } // Callback when initially starting a drag on a draggable component const onDragStart = e => { - const parent = e.target.closest(".component") - if (!parent?.classList.contains("draggable")) { + var img = new Image() + img.src = + "data:image/gif;base64,R0lGODlhAQABAIAAAAUEBAAAACwAAAAAAQABAAACAkQBADs=" + e.dataTransfer.setDragImage(img, 0, 0) + + // Resize component + if (e.target.classList.contains("anchor")) { + dragInfo = { + target: e.target.dataset.id, + side: e.target.dataset.side, + mode: "resize", + } + } else { + // Drag component + const parent = e.target.closest(".component") + if (!parent?.classList.contains("draggable")) { + return + } + dragInfo = { + target: parent.dataset.id, + parent: parent.dataset.parent, + mode: "move", + } + } + + if (!dragInfo) { return } - // Update state - dragInfo = { - target: parent.dataset.id, - parent: parent.dataset.parent, - } builderStore.actions.selectComponent(dragInfo.target) builderStore.actions.setDragging(true) @@ -71,20 +90,48 @@ } } + // Update grid styles + if ($builderStore.gridStyles) { + builderStore.actions.updateStyles($builderStore.gridStyles) + } + // Reset state and styles dragInfo = null dropInfo = null - builderStore.actions.setDragging(false) } // Callback when on top of a component const onDragOver = e => { // Skip if we aren't validly dragging currently - if (!dragInfo || !dropInfo) { + if (!dragInfo) { return } e.preventDefault() + + // Set drag info for grids if not set + if (!dragInfo.grid) { + const coord = e.target.closest(".grid-coord") + if (coord) { + const row = parseInt(coord.dataset.row) + const col = parseInt(coord.dataset.col) + const component = $componentStore.selectedComponent + const getStyle = x => parseInt(component._styles.normal?.[x] || "0") + dragInfo.grid = { + startRow: row, + startCol: col, + rowDeltaMin: 1 - getStyle("grid-row-start"), + rowDeltaMax: 13 - getStyle("grid-row-end"), + colDeltaMin: 1 - getStyle("grid-column-start"), + colDeltaMax: 13 - getStyle("grid-column-end"), + } + } + } + + if (!dropInfo) { + return + } + const { droppableInside, bounds } = dropInfo const { top, left, height, width } = bounds const mouseY = e.clientY @@ -147,6 +194,72 @@ return } + const coord = e.target.closest(".grid-coord") + if (coord && dragInfo.grid) { + const row = parseInt(coord.dataset.row) + const col = parseInt(coord.dataset.col) + const { mode, side, grid } = dragInfo + const { + startRow, + startCol, + rowDeltaMin, + rowDeltaMax, + colDeltaMin, + colDeltaMax, + } = grid + + const component = $componentStore.selectedComponent + const rowStart = parseInt( + component._styles.normal?.["grid-row-start"] || 0 + ) + const rowEnd = parseInt(component._styles.normal?.["grid-row-end"] || 0) + const colStart = parseInt( + component._styles.normal?.["grid-column-start"] || 0 + ) + const colEnd = parseInt( + component._styles.normal?.["grid-column-end"] || 0 + ) + + let rowDelta = row - startRow + let colDelta = col - startCol + + if (mode === "move") { + rowDelta = Math.min(Math.max(rowDelta, rowDeltaMin), rowDeltaMax) + colDelta = Math.min(Math.max(colDelta, colDeltaMin), colDeltaMax) + builderStore.actions.setGridStyles({ + "grid-row-start": rowStart + rowDelta, + "grid-row-end": rowEnd + rowDelta, + "grid-column-start": colStart + colDelta, + "grid-column-end": colEnd + colDelta, + }) + } else if (mode === "resize") { + let newStyles = {} + if (side === "right") { + newStyles["grid-column-end"] = colEnd + colDelta + } else if (side === "left") { + newStyles["grid-column-start"] = colStart + colDelta + } else if (side === "top") { + newStyles["grid-row-start"] = rowStart + rowDelta + } else if (side === "bottom") { + newStyles["grid-row-end"] = rowEnd + rowDelta + } else if (side === "bottom-right") { + newStyles["grid-column-end"] = colEnd + colDelta + newStyles["grid-row-end"] = rowEnd + rowDelta + } else if (side === "bottom-left") { + newStyles["grid-column-start"] = colStart + colDelta + newStyles["grid-row-end"] = rowEnd + rowDelta + } else if (side === "top-right") { + newStyles["grid-column-end"] = colEnd + colDelta + newStyles["grid-row-start"] = rowStart + rowDelta + } else if (side === "top-left") { + newStyles["grid-column-start"] = colStart + colDelta + newStyles["grid-row-start"] = rowStart + rowDelta + } + builderStore.actions.setGridStyles(newStyles) + } + } + return + const element = e.target.closest(".component:not(.block)") if ( element && diff --git a/packages/client/src/components/preview/Indicator.svelte b/packages/client/src/components/preview/Indicator.svelte index 1cb669bdc4..d450dd666a 100644 --- a/packages/client/src/components/preview/Indicator.svelte +++ b/packages/client/src/components/preview/Indicator.svelte @@ -13,6 +13,7 @@ export let transition = false export let line = false export let alignRight = false + export let componentId $: flipped = top < 24 @@ -40,6 +41,54 @@ {/if}
{/if} +
+
+
+
+
+
+
+
diff --git a/packages/client/src/components/preview/IndicatorSet.svelte b/packages/client/src/components/preview/IndicatorSet.svelte index 662741d100..99db893faa 100644 --- a/packages/client/src/components/preview/IndicatorSet.svelte +++ b/packages/client/src/components/preview/IndicatorSet.svelte @@ -127,6 +127,7 @@ height={indicator.height} text={idx === 0 ? text : null} icon={idx === 0 ? icon : null} + {componentId} {transition} {zIndex} {color} diff --git a/packages/client/src/index.js b/packages/client/src/index.js index b582dab4d3..b590ee9b00 100644 --- a/packages/client/src/index.js +++ b/packages/client/src/index.js @@ -32,6 +32,10 @@ const loadBudibase = () => { const enableDevTools = !get(builderStore).inBuilder && get(appStore).isDevApp devToolsStore.actions.setEnabled(enableDevTools) + if (get(builderStore).gridOffset) { + builderStore.actions.setDragging(false) + } + // Create app if one hasn't been created yet if (!app) { app = new ClientApp({ diff --git a/packages/client/src/stores/builder.js b/packages/client/src/stores/builder.js index 32eb956d52..77540b3205 100644 --- a/packages/client/src/stores/builder.js +++ b/packages/client/src/stores/builder.js @@ -40,6 +40,9 @@ const createBuilderStore = () => { updateProp: (prop, value) => { dispatchEvent("update-prop", { prop, value }) }, + updateStyles: styles => { + dispatchEvent("update-styles", { styles }) + }, keyDown: (key, ctrlKey) => { dispatchEvent("key-down", { key, ctrlKey }) }, @@ -67,7 +70,11 @@ const createBuilderStore = () => { if (dragging === get(store).isDragging) { return } - store.update(state => ({ ...state, isDragging: dragging })) + store.update(state => ({ + ...state, + isDragging: dragging, + gridStyles: null, + })) }, setEditMode: enabled => { if (enabled === get(store).editMode) { @@ -84,6 +91,12 @@ const createBuilderStore = () => { highlightSetting: setting => { dispatchEvent("highlight-setting", { setting }) }, + setGridStyles: styles => { + store.update(state => { + state.gridStyles = styles + return state + }) + }, } return { ...store, diff --git a/packages/client/src/utils/styleable.js b/packages/client/src/utils/styleable.js index b07a3213d9..5cbe74bb68 100644 --- a/packages/client/src/utils/styleable.js +++ b/packages/client/src/utils/styleable.js @@ -27,7 +27,7 @@ export const styleable = (node, styles = {}) => { const setupStyles = (newStyles = {}) => { let baseStyles = {} if (newStyles.empty) { - baseStyles.border = "2px dashed var(--spectrum-global-color-gray-600)" + // baseStyles.border = "2px dashed var(--spectrum-global-color-gray-600)" baseStyles.padding = "var(--spacing-l)" baseStyles.overflow = "hidden" } From 166064f6df8999ca4c3cf6560bba703d8de12342 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Fri, 26 Aug 2022 14:47:29 +0100 Subject: [PATCH 02/32] Don't clear grid dnd state when loading client library --- .../client/src/components/preview/DNDHandler.svelte | 1 + packages/client/src/index.js | 10 ++++++---- packages/client/src/stores/builder.js | 9 +++++++++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/packages/client/src/components/preview/DNDHandler.svelte b/packages/client/src/components/preview/DNDHandler.svelte index 719f17efe3..7a89b958ae 100644 --- a/packages/client/src/components/preview/DNDHandler.svelte +++ b/packages/client/src/components/preview/DNDHandler.svelte @@ -93,6 +93,7 @@ // Update grid styles if ($builderStore.gridStyles) { builderStore.actions.updateStyles($builderStore.gridStyles) + builderStore.actions.clearGridNextLoad() } // Reset state and styles diff --git a/packages/client/src/index.js b/packages/client/src/index.js index b590ee9b00..3c2f375ac8 100644 --- a/packages/client/src/index.js +++ b/packages/client/src/index.js @@ -9,6 +9,10 @@ loadSpectrumIcons() let app const loadBudibase = () => { + if (get(builderStore).clearGridNextLoad) { + builderStore.actions.setDragging(false) + } + // Update builder store with any builder flags builderStore.set({ inBuilder: !!window["##BUDIBASE_IN_BUILDER##"], @@ -21,6 +25,8 @@ const loadBudibase = () => { previewDevice: window["##BUDIBASE_PREVIEW_DEVICE##"], navigation: window["##BUDIBASE_PREVIEW_NAVIGATION##"], hiddenComponentIds: window["##BUDIBASE_HIDDEN_COMPONENT_IDS##"], + gridStyles: get(builderStore).gridStyles, + isDragging: get(builderStore).isDragging, }) // Set app ID - this window flag is set by both the preview and the real @@ -32,10 +38,6 @@ const loadBudibase = () => { const enableDevTools = !get(builderStore).inBuilder && get(appStore).isDevApp devToolsStore.actions.setEnabled(enableDevTools) - if (get(builderStore).gridOffset) { - builderStore.actions.setDragging(false) - } - // Create app if one hasn't been created yet if (!app) { app = new ClientApp({ diff --git a/packages/client/src/stores/builder.js b/packages/client/src/stores/builder.js index 77540b3205..1ab8cdb725 100644 --- a/packages/client/src/stores/builder.js +++ b/packages/client/src/stores/builder.js @@ -19,6 +19,8 @@ const createBuilderStore = () => { isDragging: false, navigation: null, hiddenComponentIds: [], + gridStyles: null, + clearGridNextLoad: false, // Legacy - allow the builder to specify a layout layout: null, @@ -74,6 +76,7 @@ const createBuilderStore = () => { ...state, isDragging: dragging, gridStyles: null, + clearGridNextLoad: false, })) }, setEditMode: enabled => { @@ -97,6 +100,12 @@ const createBuilderStore = () => { return state }) }, + clearGridNextLoad: () => { + store.update(state => { + state.clearGridNextLoad = true + return state + }) + }, } return { ...store, From 15bbc788473c384fc3ed28f6476325de3a6cf6e0 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 18 Oct 2022 16:18:22 +0100 Subject: [PATCH 03/32] Add grid functionality separately to DND --- .../client/src/components/Component.svelte | 5 +- .../client/src/components/app/Grid.svelte | 45 +- .../src/components/preview/DNDHandler.svelte | 39 +- .../components/preview/GridDNDHandler.svelte | 656 ++++-------------- .../components/preview/HoverIndicator.svelte | 4 +- .../src/components/preview/Indicator.svelte | 72 +- .../components/preview/IndicatorSet.svelte | 21 + .../preview/SelectionIndicator.svelte | 5 +- .../src/components/preview/SettingsBar.svelte | 4 +- packages/client/src/index.js | 2 - packages/client/src/stores/builder.js | 7 + packages/client/src/stores/dnd.js | 12 - packages/client/src/stores/index.js | 1 - 13 files changed, 251 insertions(+), 622 deletions(-) diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte index 742b93bb42..fe99c3e4cd 100644 --- a/packages/client/src/components/Component.svelte +++ b/packages/client/src/components/Component.svelte @@ -21,7 +21,6 @@ devToolsStore, componentStore, appStore, - dndIsDragging, dndComponentPath, } from "stores" import { Helpers } from "@budibase/bbui" @@ -163,7 +162,7 @@ // nested layers. Only reset this when dragging stops. let pad = false $: pad = pad || (interactive && hasChildren && inDndPath) - $: $dndIsDragging, (pad = false) + $: $builderStore.dragging, (pad = false) // Update component context $: store.set({ @@ -427,7 +426,7 @@ const scrollIntoView = () => { // Don't scroll into view if we selected this component because we were // starting dragging on it - if (get(dndIsDragging)) { + if (get(builderStore).dragging) { return } const node = document.getElementsByClassName(id)?.[0]?.children[0] diff --git a/packages/client/src/components/app/Grid.svelte b/packages/client/src/components/app/Grid.svelte index 51c5162386..9a588dbf17 100644 --- a/packages/client/src/components/app/Grid.svelte +++ b/packages/client/src/components/app/Grid.svelte @@ -1,11 +1,14 @@ -
+
{#each coords as coord}
{/each}
- {#if $builderStore.isDragging} -
- {#each coords as coord} -
- {/each} -
- {/if}
+{#if $builderStore.inBuilder && node} + +{/if} + diff --git a/packages/client/src/components/preview/SettingsBar.svelte b/packages/client/src/components/preview/SettingsBar.svelte index 8ef0c81af0..757d8b88db 100644 --- a/packages/client/src/components/preview/SettingsBar.svelte +++ b/packages/client/src/components/preview/SettingsBar.svelte @@ -3,7 +3,7 @@ import SettingsButton from "./SettingsButton.svelte" import SettingsColorPicker from "./SettingsColorPicker.svelte" import SettingsPicker from "./SettingsPicker.svelte" - import { builderStore, componentStore } from "stores" + import { builderStore, componentStore, dndIsDragging } from "stores" import { domDebounce } from "utils/domDebounce" const verticalOffset = 36 @@ -16,7 +16,7 @@ let measured = false $: definition = $componentStore.selectedComponentDefinition - $: showBar = definition?.showSettingsBar && !$builderStore.dragging + $: showBar = definition?.showSettingsBar && !$dndIsDragging $: settings = getBarSettings(definition) const getBarSettings = definition => { diff --git a/packages/client/src/stores/builder.js b/packages/client/src/stores/builder.js index 41fd9bb92d..30fcc39bad 100644 --- a/packages/client/src/stores/builder.js +++ b/packages/client/src/stores/builder.js @@ -19,7 +19,6 @@ const createBuilderStore = () => { navigation: null, hiddenComponentIds: [], usedPlugins: null, - dragging: false, // Legacy - allow the builder to specify a layout layout: null, @@ -41,8 +40,8 @@ const createBuilderStore = () => { updateProp: (prop, value) => { dispatchEvent("update-prop", { prop, value }) }, - updateStyles: styles => { - dispatchEvent("update-styles", { styles }) + updateStyles: (styles, id) => { + dispatchEvent("update-styles", { styles, id }) }, keyDown: (key, ctrlKey) => { dispatchEvent("key-down", { key, ctrlKey }) @@ -112,12 +111,6 @@ const createBuilderStore = () => { // Notify the builder so we can reload component definitions dispatchEvent("reload-plugin") }, - setDragging: dragging => { - store.update(state => { - state.dragging = dragging - return state - }) - }, } return { ...store, diff --git a/packages/client/src/stores/dnd.js b/packages/client/src/stores/dnd.js index d9363e4725..9f17a5aa90 100644 --- a/packages/client/src/stores/dnd.js +++ b/packages/client/src/stores/dnd.js @@ -87,3 +87,4 @@ export const dndIsNewComponent = derived( dndStore, $dndStore => $dndStore.source?.newComponentType != null ) +export const dndIsDragging = derived(dndStore, $dndStore => !!$dndStore.source) diff --git a/packages/client/src/stores/index.js b/packages/client/src/stores/index.js index e28ebf7bc4..c431302d43 100644 --- a/packages/client/src/stores/index.js +++ b/packages/client/src/stores/index.js @@ -21,6 +21,7 @@ export { dndParent, dndBounds, dndIsNewComponent, + dndIsDragging, } from "./dnd" // Context stores are layered and duplicated, so it is not a singleton From a367863d43da6255edc2edf20f65e02aef325dfb Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 18 Oct 2022 18:49:24 +0100 Subject: [PATCH 05/32] Allow normal DND in and out of grid children --- packages/client/manifest.json | 4 +++- .../client/src/components/preview/DNDHandler.svelte | 11 +++++++---- .../src/components/preview/GridDNDHandler.svelte | 8 +++++++- .../src/components/preview/HoverIndicator.svelte | 4 ---- .../client/src/components/preview/IndicatorSet.svelte | 5 +++-- 5 files changed, 20 insertions(+), 12 deletions(-) diff --git a/packages/client/manifest.json b/packages/client/manifest.json index 80ed9623cd..16f4bc10c6 100644 --- a/packages/client/manifest.json +++ b/packages/client/manifest.json @@ -4573,7 +4573,9 @@ "hasChildren": true, "styles": [ "size" - ] + ], + "illegalChildren": ["grid", "section"], + "allowedDirectChildren": [""] }, "formblock": { "name": "Form Block", diff --git a/packages/client/src/components/preview/DNDHandler.svelte b/packages/client/src/components/preview/DNDHandler.svelte index 43d1d52480..f556346ad2 100644 --- a/packages/client/src/components/preview/DNDHandler.svelte +++ b/packages/client/src/components/preview/DNDHandler.svelte @@ -23,7 +23,10 @@ $: drop = $dndStore.drop const insideGrid = e => { - return e.target?.closest?.(".grid") != null + return e.target + ?.closest?.(".component") + ?.parentNode?.closest?.(".component") + ?.childNodes[0]?.classList.contains("grid") } // Util to get the inner DOM node by a component ID @@ -218,7 +221,7 @@ // Callback when on top of a component. const onDragOver = e => { - if (!source || !target || insideGrid(e)) { + if (!source || !target) { return } handleEvent(e) @@ -226,7 +229,7 @@ // Callback when entering a potential drop target const onDragEnter = e => { - if (!source || insideGrid(e)) { + if (!source) { return } @@ -249,7 +252,7 @@ // Callback when dropping a drag on top of some component const onDrop = e => { - if (!source || !drop?.parent || drop?.index == null || insideGrid(e)) { + if (!source || !drop?.parent || drop?.index == null) { return } diff --git a/packages/client/src/components/preview/GridDNDHandler.svelte b/packages/client/src/components/preview/GridDNDHandler.svelte index 22fecc9d1d..2b1541e1e4 100644 --- a/packages/client/src/components/preview/GridDNDHandler.svelte +++ b/packages/client/src/components/preview/GridDNDHandler.svelte @@ -11,7 +11,13 @@ $: applyStyles(dragNode, gridStyles) const insideGrid = e => { - return e.target?.closest?.(".grid") || e.target.classList.contains("anchor") + return ( + e.target + ?.closest?.(".component") + ?.parentNode?.closest?.(".component") + ?.childNodes[0]?.classList.contains("grid") || + e.target.classList.contains("anchor") + ) } // Util to get the inner DOM node by a component ID diff --git a/packages/client/src/components/preview/HoverIndicator.svelte b/packages/client/src/components/preview/HoverIndicator.svelte index 380520d469..230edeb70c 100644 --- a/packages/client/src/components/preview/HoverIndicator.svelte +++ b/packages/client/src/components/preview/HoverIndicator.svelte @@ -9,21 +9,17 @@ const onMouseOver = e => { // Ignore if dragging if (e.buttons > 0) { - console.log("ignore") return } let newId - if (e.target.classList.contains("anchor")) { // Handle resize anchors newId = e.target.dataset.id - console.log("anchor", newId) } else { // Handle normal components const element = e.target.closest(".interactive.component") newId = element?.dataset?.id - console.log("normal", newId) } if (newId !== componentId) { diff --git a/packages/client/src/components/preview/IndicatorSet.svelte b/packages/client/src/components/preview/IndicatorSet.svelte index dc4355b30f..51a60ce981 100644 --- a/packages/client/src/components/preview/IndicatorSet.svelte +++ b/packages/client/src/components/preview/IndicatorSet.svelte @@ -34,8 +34,9 @@ return false } - // Check if we're a descendent of a grid - return domNode?.closest(".grid") != null + return component?.parentNode + ?.closest?.(".component") + ?.childNodes[0]?.classList.contains("grid") } const createIntersectionCallback = idx => entries => { From 645235be96283446dcf7d2d26203753456e61276 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 19 Oct 2022 13:16:42 +0100 Subject: [PATCH 06/32] Fix resizing not working inside grids --- .../components/preview/GridDNDHandler.svelte | 200 +++++++++--------- 1 file changed, 100 insertions(+), 100 deletions(-) diff --git a/packages/client/src/components/preview/GridDNDHandler.svelte b/packages/client/src/components/preview/GridDNDHandler.svelte index 2b1541e1e4..802a4c9b46 100644 --- a/packages/client/src/components/preview/GridDNDHandler.svelte +++ b/packages/client/src/components/preview/GridDNDHandler.svelte @@ -10,12 +10,12 @@ $: dragNode = getDOMNode(dragInfo?.id) $: applyStyles(dragNode, gridStyles) - const insideGrid = e => { + const isChildOfGrid = e => { return ( e.target - ?.closest?.(".component") - ?.parentNode?.closest?.(".component") - ?.childNodes[0]?.classList.contains("grid") || + .closest?.(".component") + ?.parentNode.closest(".component") + ?.childNodes[0].classList.contains("grid") || e.target.classList.contains("anchor") ) } @@ -35,101 +35,6 @@ }) } - // Callback when drag stops (whether dropped or not) - const stopDragging = () => { - // Save changes - if (gridStyles) { - builderStore.actions.updateStyles(gridStyles, dragInfo.id) - } - - // Reset listener - if (dragInfo?.domTarget) { - dragInfo.domTarget.removeEventListener("dragend", stopDragging) - } - - // Reset state - dragInfo = null - gridStyles = null - } - - // Callback when initially starting a drag on a draggable component - const onDragStart = e => { - if (!insideGrid(e)) { - return - } - - // Hide drag ghost image - e.dataTransfer.setDragImage(new Image(), 0, 0) - - // Extract state - let mode, id, side - if (e.target.classList.contains("anchor")) { - // Handle resize - mode = "resize" - id = e.target.dataset.id - side = e.target.dataset.side - } else { - // Handle move - mode = "move" - const component = e.target.closest(".component") - id = component.dataset.id - } - - // Find grid parent - const domComponent = getDOMNode(id) - const gridId = domComponent?.closest(".grid")?.parentNode.dataset.id - if (!gridId) { - return - } - - // Update state - dragInfo = { - domTarget: e.target, - id, - gridId, - mode, - side, - } - - // Add event handler to clear all drag state when dragging ends - dragInfo.domTarget.addEventListener("dragend", stopDragging) - } - - // Callback when entering a potential drop target - const onDragEnter = e => { - // Skip if we aren't validly dragging currently - if (!dragInfo || dragInfo.grid || !insideGrid(e)) { - return - } - - const compDef = findComponentById( - $screenStore.activeScreen.props, - dragInfo.id - ) - if (!compDef) { - return - } - const domGrid = getDOMNode(dragInfo.gridId) - if (domGrid) { - const getStyle = x => parseInt(compDef._styles.normal?.[x] || "0") - dragInfo.grid = { - startX: e.clientX, - startY: e.clientY, - rowStart: getStyle("grid-row-start"), - rowEnd: getStyle("grid-row-end"), - colStart: getStyle("grid-column-start"), - colEnd: getStyle("grid-column-end"), - rowDeltaMin: 1 - getStyle("grid-row-start"), - rowDeltaMax: - parseInt(domGrid.dataset.cols) + 1 - getStyle("grid-row-end"), - colDeltaMin: 1 - getStyle("grid-column-start"), - colDeltaMax: - parseInt(domGrid.dataset.cols) + 1 - getStyle("grid-column-end"), - } - handleEvent(e) - } - } - const processEvent = Utils.throttle((mouseX, mouseY) => { if (!dragInfo?.grid) { return @@ -202,13 +107,108 @@ processEvent(e.clientX, e.clientY) } + // Callback when initially starting a drag on a draggable component + const onDragStart = e => { + if (!isChildOfGrid(e)) { + return + } + + // Hide drag ghost image + e.dataTransfer.setDragImage(new Image(), 0, 0) + + // Extract state + let mode, id, side + if (e.target.classList.contains("anchor")) { + // Handle resize + mode = "resize" + id = e.target.dataset.id + side = e.target.dataset.side + } else { + // Handle move + mode = "move" + const component = e.target.closest(".component") + id = component.dataset.id + } + + // Find grid parent + const domComponent = getDOMNode(id) + const gridId = domComponent?.closest(".grid")?.parentNode.dataset.id + if (!gridId) { + return + } + + // Update state + dragInfo = { + domTarget: e.target, + id, + gridId, + mode, + side, + } + + // Add event handler to clear all drag state when dragging ends + dragInfo.domTarget.addEventListener("dragend", stopDragging) + } + + // Callback when entering a potential drop target + const onDragEnter = e => { + // Skip if we aren't validly dragging currently + if (!dragInfo || dragInfo.grid) { + return + } + + const compDef = findComponentById( + $screenStore.activeScreen.props, + dragInfo.id + ) + if (!compDef) { + return + } + const domGrid = getDOMNode(dragInfo.gridId) + if (domGrid) { + const getStyle = x => parseInt(compDef._styles.normal?.[x] || "0") + dragInfo.grid = { + startX: e.clientX, + startY: e.clientY, + rowStart: getStyle("grid-row-start"), + rowEnd: getStyle("grid-row-end"), + colStart: getStyle("grid-column-start"), + colEnd: getStyle("grid-column-end"), + rowDeltaMin: 1 - getStyle("grid-row-start"), + rowDeltaMax: + parseInt(domGrid.dataset.cols) + 1 - getStyle("grid-row-end"), + colDeltaMin: 1 - getStyle("grid-column-start"), + colDeltaMax: + parseInt(domGrid.dataset.cols) + 1 - getStyle("grid-column-end"), + } + handleEvent(e) + } + } + const onDragOver = e => { - if (!dragInfo?.grid || !insideGrid(e)) { + if (!dragInfo?.grid) { return } handleEvent(e) } + // Callback when drag stops (whether dropped or not) + const stopDragging = () => { + // Save changes + if (gridStyles) { + builderStore.actions.updateStyles(gridStyles, dragInfo.id) + } + + // Reset listener + if (dragInfo?.domTarget) { + dragInfo.domTarget.removeEventListener("dragend", stopDragging) + } + + // Reset state + dragInfo = null + gridStyles = null + } + onMount(() => { document.addEventListener("dragstart", onDragStart, false) document.addEventListener("dragenter", onDragEnter, false) From 9a94e9da7c5403f77d89aa54ccfacf5414baf9a5 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 19 Oct 2022 14:39:28 +0100 Subject: [PATCH 07/32] Use a container as the DND placeholder and use approx size when dragging into grids --- .../src/builderStore/store/frontend.js | 7 +- packages/client/manifest.json | 3 +- .../client/src/components/Component.svelte | 94 ++++++++++++++++--- .../components/preview/DNDPlaceholder.svelte | 33 ------- .../preview/DNDPlaceholderOverlay.svelte | 3 +- .../components/preview/GridDNDHandler.svelte | 12 +-- packages/client/src/constants.js | 1 - packages/client/src/stores/components.js | 12 +-- packages/client/src/stores/screens.js | 17 +++- 9 files changed, 108 insertions(+), 74 deletions(-) delete mode 100644 packages/client/src/components/preview/DNDPlaceholder.svelte diff --git a/packages/builder/src/builderStore/store/frontend.js b/packages/builder/src/builderStore/store/frontend.js index 2b8a5ec701..10ed0c71c5 100644 --- a/packages/builder/src/builderStore/store/frontend.js +++ b/packages/builder/src/builderStore/store/frontend.js @@ -446,12 +446,7 @@ export const getFrontendStore = () => { _id: Helpers.uuid(), _component: definition.component, _styles: { - normal: { - "grid-column-start": 1, - "grid-column-end": 2, - "grid-row-start": 1, - "grid-row-end": 2, - }, + normal: {}, hover: {}, active: {}, }, diff --git a/packages/client/manifest.json b/packages/client/manifest.json index 16f4bc10c6..94b3ac36be 100644 --- a/packages/client/manifest.json +++ b/packages/client/manifest.json @@ -87,10 +87,9 @@ "showSettingsBar": true, "size": { "width": 400, - "height": 100 + "height": 200 }, "styles": [ - "grid", "padding", "size", "background", diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte index 6e5d09646a..d9264f93bf 100644 --- a/packages/client/src/components/Component.svelte +++ b/packages/client/src/components/Component.svelte @@ -35,6 +35,7 @@ export let isScreen = false export let isBlock = false export let parent = null + export let parentType = null // Get parent contexts const context = getContext("context") @@ -165,23 +166,35 @@ $: pad = pad || (interactive && hasChildren && inDndPath) $: $dndIsDragging, (pad = false) + // We can apply additional styles automatically if required. + // One use case for this is ensuring grid children have proper styles to + // display properly inside a grid. + $: additionalStyles = getAdditionalStyles( + instance._styles?.normal || {}, + parentType, + definition + ) + + // Compute overall styles + $: styles = { + ...instance._styles, + normal: { + ...instance._styles?.normal, + ...additionalStyles, + }, + custom: customCSS, + id, + empty: emptyState, + interactive, + draggable, + editable, + } + // Update component context $: store.set({ id, children: children.length, - styles: { - ...instance._styles, - normal: { - ...instance._styles?.normal, - ...(selected ? $builderStore.gridStyles : null), - }, - custom: customCSS, - id, - empty: emptyState, - interactive, - draggable, - editable, - }, + styles, empty: emptyState, selected, name, @@ -442,6 +455,54 @@ }) } + const getAdditionalStyles = (styles, parentType, definition) => { + let newStyles = {} + + // Ensure grid styles are set + if (parentType?.endsWith("/grid")) { + newStyles = { + ...newStyles, + overflow: "hidden", + width: "auto", + height: "auto", + } + + // Guess rough grid size from definition size + let columns = 6 + let rows = 4 + if (definition.size?.width) { + columns = Math.round(definition.size.width / 100) + } + if (definition.size?.height) { + rows = Math.round(definition.size.height / 100) + } + + // Ensure grid position styles are set + if (!styles["grid-column-start"]) { + newStyles["grid-column-start"] = 1 + } + if (!styles["grid-column-end"]) { + newStyles["grid-column-end"] = columns + 1 + } + if (!styles["grid-row-start"]) { + newStyles["grid-row-start"] = 1 + } + if (!styles["grid-row-end"]) { + newStyles["grid-row-end"] = rows + 1 + } + + // Ensure grid end styles aren't before grid start styles + if (newStyles["grid-column-end"] <= newStyles["grid-column-start"]) { + newStyles["grid-column-end"] = newStyles["grid-column-start"] + 1 + } + if (newStyles["grid-row-end"] <= newStyles["grid-row-start"]) { + newStyles["grid-row-end"] = newStyles["grid-row-start"] + 1 + } + } + + return newStyles + } + onMount(() => { if ( $appStore.isDevApp && @@ -450,6 +511,7 @@ componentStore.actions.registerInstance(id, { component: instance._component, getSettings: () => cachedSettings, + getStyles: () => styles, getRawSettings: () => ({ ...staticSettings, ...dynamicSettings }), getDataContext: () => get(context), reload: () => initialise(instance, true), @@ -490,7 +552,11 @@ {:else if children.length} {#each children as child (child._id)} - + {/each} {:else if emptyState} {#if isScreen} diff --git a/packages/client/src/components/preview/DNDPlaceholder.svelte b/packages/client/src/components/preview/DNDPlaceholder.svelte deleted file mode 100644 index 3725f9e06e..0000000000 --- a/packages/client/src/components/preview/DNDPlaceholder.svelte +++ /dev/null @@ -1,33 +0,0 @@ - - -{#if style} -
-
-
-{/if} - - diff --git a/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte b/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte index 6ed2df6a87..0be7faff1b 100644 --- a/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte +++ b/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte @@ -6,7 +6,8 @@ let left, top, height, width const updatePosition = () => { - const node = document.getElementById(DNDPlaceholderID) + const node = + document.getElementsByClassName(DNDPlaceholderID)[0]?.childNodes[0] if (!node) { height = 0 width = 0 diff --git a/packages/client/src/components/preview/GridDNDHandler.svelte b/packages/client/src/components/preview/GridDNDHandler.svelte index 802a4c9b46..1cb4f92da6 100644 --- a/packages/client/src/components/preview/GridDNDHandler.svelte +++ b/packages/client/src/components/preview/GridDNDHandler.svelte @@ -1,6 +1,6 @@ Date: Fri, 21 Oct 2022 17:51:35 +0100 Subject: [PATCH 17/32] Fix flashing settings bar in stale position --- packages/client/src/components/preview/SettingsBar.svelte | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/client/src/components/preview/SettingsBar.svelte b/packages/client/src/components/preview/SettingsBar.svelte index 757d8b88db..332409986a 100644 --- a/packages/client/src/components/preview/SettingsBar.svelte +++ b/packages/client/src/components/preview/SettingsBar.svelte @@ -17,6 +17,11 @@ $: definition = $componentStore.selectedComponentDefinition $: showBar = definition?.showSettingsBar && !$dndIsDragging + $: { + if (!showBar) { + measured = false + } + } $: settings = getBarSettings(definition) const getBarSettings = definition => { From ce78c5ecb918935a40c767ef1aba7286aa0e9293 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 24 Oct 2022 09:02:50 +0100 Subject: [PATCH 18/32] Refactor app preview event sending to support async callbacks in client library --- .../[screenId]/_components/AppPreview.svelte | 236 ++++++++---------- .../src/components/preview/DNDHandler.svelte | 24 +- packages/client/src/index.js | 19 +- packages/client/src/stores/builder.js | 36 ++- packages/client/src/stores/dnd.js | 12 - packages/client/src/stores/events.js | 31 +++ packages/client/src/stores/index.js | 2 +- packages/client/src/stores/screens.js | 55 ++-- 8 files changed, 199 insertions(+), 216 deletions(-) create mode 100644 packages/client/src/stores/events.js diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte index 2a606233c2..9cbb283fef 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/_components/AppPreview.svelte @@ -103,7 +103,7 @@ ) // Register handler to send custom to the preview - $: store.actions.preview.registerEventHandler((name, payload) => { + $: sendPreviewEvent = (name, payload) => { iframe?.contentWindow.postMessage( JSON.stringify({ name, @@ -112,37 +112,30 @@ runtimeEvent: true, }) ) - }) + } + $: store.actions.preview.registerEventHandler(sendPreviewEvent) // Update the iframe with the builder info to render the correct preview const refreshContent = message => { iframe?.contentWindow.postMessage(message) } - const receiveMessage = message => { - const handlers = { - [MessageTypes.READY]: () => { - // Initialise the app when mounted - if ($store.clientFeatures.messagePassing) { - if (!loading) return - } - - // Display preview immediately if the intelligent loading feature - // is not supported - if (!$store.clientFeatures.intelligentLoading) { - loading = false - } - refreshContent(json) - }, - [MessageTypes.ERROR]: event => { - // Catch any app errors - loading = false - error = event.error || "An unknown error occurred" - }, + const receiveMessage = async message => { + if (!message?.data?.type) { + return } - const messageHandler = handlers[message.data.type] || handleBudibaseEvent - messageHandler(message) + // Await the event handler + try { + await handleBudibaseEvent(message) + } catch (error) { + notifications.error(error || "Error handling event from app preview") + } + + // Reply that the event has been completed + if (message.data?.id) { + sendPreviewEvent("event-completed", message.data?.id) + } } const handleBudibaseEvent = async event => { @@ -150,83 +143,94 @@ if (!type) { return } - - try { - if (type === "select-component" && data.id) { - $store.selectedComponentId = data.id - if (!$isActive("./components")) { - $goto("./components") - } - } else if (type === "update-prop") { - await store.actions.components.updateSetting(data.prop, data.value) - } else if (type === "update-styles") { - await store.actions.components.updateStyles(data.styles, data.id) - } else if (type === "delete-component" && data.id) { - // Legacy type, can be deleted in future - confirmDeleteComponent(data.id) - } else if (type === "key-down") { - const { key, ctrlKey } = data - document.dispatchEvent(new KeyboardEvent("keydown", { key, ctrlKey })) - } else if (type === "duplicate-component" && data.id) { - const rootComponent = get(currentAsset).props - const component = findComponent(rootComponent, data.id) - store.actions.components.copy(component) - await store.actions.components.paste(component) - } else if (type === "preview-loaded") { - // Wait for this event to show the client library if intelligent - // loading is supported - loading = false - } else if (type === "move-component") { - const { componentId, destinationComponentId } = data - const rootComponent = get(currentAsset).props - - // Get source and destination components - const source = findComponent(rootComponent, componentId) - const destination = findComponent(rootComponent, destinationComponentId) - - // Stop if the target is a child of source - const path = findComponentPath(source, destinationComponentId) - const ids = path.map(component => component._id) - if (ids.includes(data.destinationComponentId)) { - return - } - - // Cut and paste the component to the new destination - if (source && destination) { - store.actions.components.copy(source, true, false) - await store.actions.components.paste(destination, data.mode) - } - } else if (type === "click-nav") { - if (!$isActive("./navigation")) { - $goto("./navigation") - } - } else if (type === "request-add-component") { - toggleAddComponent() - } else if (type === "highlight-setting") { - store.actions.settings.highlight(data.setting) - - // Also scroll setting into view - const selector = `[data-cy="${data.setting}-prop-control"` - const element = document.querySelector(selector)?.parentElement - if (element) { - element.scrollIntoView({ - behavior: "smooth", - block: "center", - }) - } - } else if (type === "eject-block") { - const { id, definition } = data - await store.actions.components.handleEjectBlock(id, definition) - } else if (type === "reload-plugin") { - await store.actions.components.refreshDefinitions() - } else if (type === "drop-new-component") { - const { component, parent, index } = data - await store.actions.components.create(component, null, parent, index) - } else { - console.warn(`Client sent unknown event type: ${type}`) + if (type === MessageTypes.READY) { + // Initialise the app when mounted + if ($store.clientFeatures.messagePassing) { + if (!loading) return } - } catch (error) { - notifications.error(error || "Error handling event from app preview") + + // Display preview immediately if the intelligent loading feature + // is not supported + if (!$store.clientFeatures.intelligentLoading) { + loading = false + } + refreshContent(json) + } else if (type === MessageTypes.ERROR) { + // Catch any app errors + loading = false + error = event.error || "An unknown error occurred" + } else if (type === "select-component" && data.id) { + $store.selectedComponentId = data.id + if (!$isActive("./components")) { + $goto("./components") + } + } else if (type === "update-prop") { + await store.actions.components.updateSetting(data.prop, data.value) + } else if (type === "update-styles") { + await store.actions.components.updateStyles(data.styles, data.id) + } else if (type === "delete-component" && data.id) { + // Legacy type, can be deleted in future + confirmDeleteComponent(data.id) + } else if (type === "key-down") { + const { key, ctrlKey } = data + document.dispatchEvent(new KeyboardEvent("keydown", { key, ctrlKey })) + } else if (type === "duplicate-component" && data.id) { + const rootComponent = get(currentAsset).props + const component = findComponent(rootComponent, data.id) + store.actions.components.copy(component) + await store.actions.components.paste(component) + } else if (type === "preview-loaded") { + // Wait for this event to show the client library if intelligent + // loading is supported + loading = false + } else if (type === "move-component") { + const { componentId, destinationComponentId } = data + const rootComponent = get(currentAsset).props + + // Get source and destination components + const source = findComponent(rootComponent, componentId) + const destination = findComponent(rootComponent, destinationComponentId) + + // Stop if the target is a child of source + const path = findComponentPath(source, destinationComponentId) + const ids = path.map(component => component._id) + if (ids.includes(data.destinationComponentId)) { + return + } + + // Cut and paste the component to the new destination + if (source && destination) { + store.actions.components.copy(source, true, false) + await store.actions.components.paste(destination, data.mode) + } + } else if (type === "click-nav") { + if (!$isActive("./navigation")) { + $goto("./navigation") + } + } else if (type === "request-add-component") { + toggleAddComponent() + } else if (type === "highlight-setting") { + store.actions.settings.highlight(data.setting) + + // Also scroll setting into view + const selector = `[data-cy="${data.setting}-prop-control"` + const element = document.querySelector(selector)?.parentElement + if (element) { + element.scrollIntoView({ + behavior: "smooth", + block: "center", + }) + } + } else if (type === "eject-block") { + const { id, definition } = data + await store.actions.components.handleEjectBlock(id, definition) + } else if (type === "reload-plugin") { + await store.actions.components.refreshDefinitions() + } else if (type === "drop-new-component") { + const { component, parent, index } = data + await store.actions.components.create(component, null, parent, index) + } else { + console.warn(`Client sent unknown event type: ${type}`) } } @@ -259,42 +263,10 @@ onMount(() => { window.addEventListener("message", receiveMessage) - if (!$store.clientFeatures.messagePassing) { - // Legacy - remove in later versions of BB - iframe.contentWindow.addEventListener( - "ready", - () => { - receiveMessage({ data: { type: MessageTypes.READY } }) - }, - { once: true } - ) - iframe.contentWindow.addEventListener( - "error", - event => { - receiveMessage({ - data: { type: MessageTypes.ERROR, error: event.detail }, - }) - }, - { once: true } - ) - // Add listener for events sent by client library in preview - iframe.contentWindow.addEventListener("bb-event", handleBudibaseEvent) - } }) - // Remove all iframe event listeners on component destroy onDestroy(() => { window.removeEventListener("message", receiveMessage) - - if (iframe.contentWindow) { - if (!$store.clientFeatures.messagePassing) { - // Legacy - remove in later versions of BB - iframe.contentWindow.removeEventListener( - "bb-event", - handleBudibaseEvent - ) - } - } }) diff --git a/packages/client/src/components/preview/DNDHandler.svelte b/packages/client/src/components/preview/DNDHandler.svelte index e04bd81750..42a2fafbdd 100644 --- a/packages/client/src/components/preview/DNDHandler.svelte +++ b/packages/client/src/components/preview/DNDHandler.svelte @@ -22,6 +22,9 @@ $: target = $dndStore.target $: drop = $dndStore.drop + // Local flag for whether we are awaiting an async drop event + let dropping = false + const insideGrid = e => { return e.target ?.closest?.(".component") @@ -48,6 +51,10 @@ // Callback when drag stops (whether dropped or not) const stopDragging = () => { + if (dropping) { + return + } + // Reset listener if (source?.id) { const component = document.getElementsByClassName(source?.id)[0] @@ -57,9 +64,7 @@ } // Reset state - if (!$dndStore.dropped) { - dndStore.actions.reset() - } + dndStore.actions.reset() } // Callback when initially starting a drag on a draggable component @@ -253,18 +258,21 @@ } // Callback when dropping a drag on top of some component - const onDrop = () => { + const onDrop = async () => { if (!source || !drop?.parent || drop?.index == null) { return } // Check if we're adding a new component rather than moving one if (source.newComponentType) { - builderStore.actions.dropNewComponent( + dropping = true + await builderStore.actions.dropNewComponent( source.newComponentType, drop.parent, drop.index ) + dropping = false + stopDragging() return } @@ -301,12 +309,14 @@ } if (legacyDropTarget && legacyDropMode) { - dndStore.actions.markDropped() - builderStore.actions.moveComponent( + dropping = true + await builderStore.actions.moveComponent( source.id, legacyDropTarget, legacyDropMode ) + dropping = false + stopDragging() } } diff --git a/packages/client/src/index.js b/packages/client/src/index.js index e61df37d95..80f8754e20 100644 --- a/packages/client/src/index.js +++ b/packages/client/src/index.js @@ -7,6 +7,7 @@ import { componentStore, environmentStore, dndStore, + eventStore, } from "./stores" import loadSpectrumIcons from "@budibase/bbui/spectrum-icons-rollup.js" import { get } from "svelte/store" @@ -42,9 +43,9 @@ const loadBudibase = async () => { }) // Reset DND state if we completed a successful drop - if (get(dndStore).dropped) { - dndStore.actions.reset() - } + // if (get(dndStore).dropped) { + // dndStore.actions.reset() + // } // Set app ID - this window flag is set by both the preview and the real // server rendered app HTML @@ -59,15 +60,17 @@ const loadBudibase = async () => { devToolsStore.actions.setEnabled(enableDevTools) // Register handler for runtime events from the builder - window.handleBuilderRuntimeEvent = (name, payload) => { + window.handleBuilderRuntimeEvent = (type, data) => { if (!window["##BUDIBASE_IN_BUILDER##"]) { return } - if (name === "eject-block") { - const block = blockStore.actions.getBlock(payload) + if (type === "event-completed") { + eventStore.actions.resolveEvent(data) + } else if (type === "eject-block") { + const block = blockStore.actions.getBlock(data) block?.eject() - } else if (name === "dragging-new-component") { - const { dragging, component } = payload + } else if (type === "dragging-new-component") { + const { dragging, component } = data if (dragging) { const definition = componentStore.actions.getComponentDefinition(component) diff --git a/packages/client/src/stores/builder.js b/packages/client/src/stores/builder.js index 30fcc39bad..fdad9a5f88 100644 --- a/packages/client/src/stores/builder.js +++ b/packages/client/src/stores/builder.js @@ -1,10 +1,7 @@ import { writable, get } from "svelte/store" import { API } from "api" import { devToolsStore } from "./devTools.js" - -const dispatchEvent = (type, data = {}) => { - window.parent.postMessage({ type, data }) -} +import { eventStore } from "./events.js" const createBuilderStore = () => { const initialState = { @@ -19,6 +16,7 @@ const createBuilderStore = () => { navigation: null, hiddenComponentIds: [], usedPlugins: null, + eventResolvers: {}, // Legacy - allow the builder to specify a layout layout: null, @@ -35,25 +33,25 @@ const createBuilderStore = () => { selectedComponentId: id, })) devToolsStore.actions.setAllowSelection(false) - dispatchEvent("select-component", { id }) + eventStore.actions.dispatchEvent("select-component", { id }) }, updateProp: (prop, value) => { - dispatchEvent("update-prop", { prop, value }) + eventStore.actions.dispatchEvent("update-prop", { prop, value }) }, updateStyles: (styles, id) => { - dispatchEvent("update-styles", { styles, id }) + eventStore.actions.dispatchEvent("update-styles", { styles, id }) }, keyDown: (key, ctrlKey) => { - dispatchEvent("key-down", { key, ctrlKey }) + eventStore.actions.dispatchEvent("key-down", { key, ctrlKey }) }, duplicateComponent: id => { - dispatchEvent("duplicate-component", { id }) + eventStore.actions.dispatchEvent("duplicate-component", { id }) }, deleteComponent: id => { - dispatchEvent("delete-component", { id }) + eventStore.actions.dispatchEvent("delete-component", { id }) }, notifyLoaded: () => { - dispatchEvent("preview-loaded") + eventStore.actions.dispatchEvent("preview-loaded") }, analyticsPing: async () => { try { @@ -62,15 +60,15 @@ const createBuilderStore = () => { // Do nothing } }, - moveComponent: (componentId, destinationComponentId, mode) => { - dispatchEvent("move-component", { + moveComponent: async (componentId, destinationComponentId, mode) => { + await eventStore.actions.dispatchEvent("move-component", { componentId, destinationComponentId, mode, }) }, dropNewComponent: (component, parent, index) => { - dispatchEvent("drop-new-component", { + eventStore.actions.dispatchEvent("drop-new-component", { component, parent, index, @@ -83,16 +81,16 @@ const createBuilderStore = () => { store.update(state => ({ ...state, editMode: enabled })) }, clickNav: () => { - dispatchEvent("click-nav") + eventStore.actions.dispatchEvent("click-nav") }, requestAddComponent: () => { - dispatchEvent("request-add-component") + eventStore.actions.dispatchEvent("request-add-component") }, highlightSetting: setting => { - dispatchEvent("highlight-setting", { setting }) + eventStore.actions.dispatchEvent("highlight-setting", { setting }) }, ejectBlock: (id, definition) => { - dispatchEvent("eject-block", { id, definition }) + eventStore.actions.dispatchEvent("eject-block", { id, definition }) }, updateUsedPlugin: (name, hash) => { // Check if we used this plugin @@ -109,7 +107,7 @@ const createBuilderStore = () => { } // Notify the builder so we can reload component definitions - dispatchEvent("reload-plugin") + eventStore.actions.dispatchEvent("reload-plugin") }, } return { diff --git a/packages/client/src/stores/dnd.js b/packages/client/src/stores/dnd.js index 532dea0ad5..1bdd510eb7 100644 --- a/packages/client/src/stores/dnd.js +++ b/packages/client/src/stores/dnd.js @@ -11,9 +11,6 @@ const createDndStore = () => { // Info about where the component would be dropped drop: null, - - // Whether the current drop has been completed successfully - dropped: false, } const store = writable(initialState) @@ -63,13 +60,6 @@ const createDndStore = () => { store.set(initialState) } - const markDropped = () => { - store.update(state => { - state.dropped = true - return state - }) - } - return { subscribe: store.subscribe, actions: { @@ -78,7 +68,6 @@ const createDndStore = () => { updateTarget, updateDrop, reset, - markDropped, }, } } @@ -91,7 +80,6 @@ export const dndStore = createDndStore() // or components which depend on DND state unless values actually change. export const dndParent = computed(dndStore, x => x.drop?.parent) export const dndIndex = computed(dndStore, x => x.drop?.index) -export const dndDropped = computed(dndStore, x => x.dropped) export const dndBounds = computed(dndStore, x => x.source?.bounds) export const dndIsDragging = computed(dndStore, x => !!x.source) export const dndIsNewComponent = computed( diff --git a/packages/client/src/stores/events.js b/packages/client/src/stores/events.js new file mode 100644 index 0000000000..6a67554247 --- /dev/null +++ b/packages/client/src/stores/events.js @@ -0,0 +1,31 @@ +import { writable, get } from "svelte/store" + +const createEventStore = () => { + const initialState = { + eventResolvers: {}, + } + const store = writable(initialState) + + const actions = { + dispatchEvent: (type, data) => { + const id = Math.random() + return new Promise(resolve => { + window.parent.postMessage({ type, data, id }) + store.update(state => { + state.eventResolvers[id] = resolve + return state + }) + }) + }, + resolveEvent: data => { + get(store).eventResolvers[data]?.() + }, + } + + return { + subscribe: store.subscribe, + actions, + } +} + +export const eventStore = createEventStore() diff --git a/packages/client/src/stores/index.js b/packages/client/src/stores/index.js index 7a06e55a67..173f3ad4fe 100644 --- a/packages/client/src/stores/index.js +++ b/packages/client/src/stores/index.js @@ -15,6 +15,7 @@ export { uploadStore } from "./uploads.js" export { rowSelectionStore } from "./rowSelection.js" export { blockStore } from "./blocks.js" export { environmentStore } from "./environment" +export { eventStore } from "./events.js" export { dndStore, dndIndex, @@ -22,7 +23,6 @@ export { dndBounds, dndIsNewComponent, dndIsDragging, - dndDropped, } from "./dnd" // Context stores are layered and duplicated, so it is not a singleton diff --git a/packages/client/src/stores/screens.js b/packages/client/src/stores/screens.js index d9d91ad51a..6ef164dc9d 100644 --- a/packages/client/src/stores/screens.js +++ b/packages/client/src/stores/screens.js @@ -2,13 +2,7 @@ import { derived } from "svelte/store" import { routeStore } from "./routes" import { builderStore } from "./builder" import { appStore } from "./app" -import { - dndIndex, - dndParent, - dndIsNewComponent, - dndBounds, - dndDropped, -} from "./dnd.js" +import { dndIndex, dndParent, dndIsNewComponent, dndBounds } from "./dnd.js" import { RoleUtils } from "@budibase/frontend-core" import { findComponentById, findComponentParent } from "../utils/components.js" import { Helpers } from "@budibase/bbui" @@ -24,7 +18,6 @@ const createScreenStore = () => { dndIndex, dndIsNewComponent, dndBounds, - dndDropped, ], ([ $appStore, @@ -34,7 +27,6 @@ const createScreenStore = () => { $dndIndex, $dndIsNewComponent, $dndBounds, - $dndDropped, ]) => { let activeLayout, activeScreen let screens @@ -80,9 +72,6 @@ const createScreenStore = () => { activeScreen.props, selectedComponentId ) - const selectedComponent = selectedParent?._children?.find( - x => x._id === selectedComponentId - ) // Remove selected component from tree if we are moving an existing // component @@ -92,33 +81,25 @@ const createScreenStore = () => { ) } - // Insert placeholder component if dragging, or artificially insert - // the dropped component in the new location if the drop completed - let componentToInsert - if ($dndDropped && !$dndIsNewComponent) { - componentToInsert = selectedComponent - } else { - componentToInsert = { - _component: "@budibase/standard-components/container", - _id: DNDPlaceholderID, - _styles: { - normal: { - width: `${$dndBounds?.width || 400}px`, - height: `${$dndBounds?.height || 200}px`, - opacity: 0, - }, + // Insert placeholder component + const componentToInsert = { + _component: "@budibase/standard-components/container", + _id: DNDPlaceholderID, + _styles: { + normal: { + width: `${$dndBounds?.width || 400}px`, + height: `${$dndBounds?.height || 200}px`, + opacity: 0, }, - static: true, - } + }, + static: true, } - if (componentToInsert) { - let parent = findComponentById(activeScreen.props, $dndParent) - if (parent) { - if (!parent._children?.length) { - parent._children = [componentToInsert] - } else { - parent._children.splice($dndIndex, 0, componentToInsert) - } + let parent = findComponentById(activeScreen.props, $dndParent) + if (parent) { + if (!parent._children?.length) { + parent._children = [componentToInsert] + } else { + parent._children.splice($dndIndex, 0, componentToInsert) } } } From 32bac91dc7bf9340c32784bfcb269cc5398ea3b3 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 24 Oct 2022 09:03:50 +0100 Subject: [PATCH 19/32] Remove spam of environment API calls --- packages/client/src/index.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/client/src/index.js b/packages/client/src/index.js index 80f8754e20..f49e6df5a2 100644 --- a/packages/client/src/index.js +++ b/packages/client/src/index.js @@ -42,17 +42,14 @@ const loadBudibase = async () => { location: window["##BUDIBASE_LOCATION##"], }) - // Reset DND state if we completed a successful drop - // if (get(dndStore).dropped) { - // dndStore.actions.reset() - // } - // Set app ID - this window flag is set by both the preview and the real // server rendered app HTML appStore.actions.setAppId(window["##BUDIBASE_APP_ID##"]) // Fetch environment info - await environmentStore.actions.fetchEnvironment() + if (!get(environmentStore)) { + await environmentStore.actions.fetchEnvironment() + } // Enable dev tools or not. We need to be using a dev app and not inside // the builder preview to enable them. From a11854d9573c2aec6640910ad0fbcea0231f7aeb Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 24 Oct 2022 09:13:05 +0100 Subject: [PATCH 20/32] Fix issue with getting environment details --- packages/client/src/index.js | 2 +- packages/client/src/stores/environment.js | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/client/src/index.js b/packages/client/src/index.js index f49e6df5a2..951c55270b 100644 --- a/packages/client/src/index.js +++ b/packages/client/src/index.js @@ -47,7 +47,7 @@ const loadBudibase = async () => { appStore.actions.setAppId(window["##BUDIBASE_APP_ID##"]) // Fetch environment info - if (!get(environmentStore)) { + if (!get(environmentStore)?.loaded) { await environmentStore.actions.fetchEnvironment() } diff --git a/packages/client/src/stores/environment.js b/packages/client/src/stores/environment.js index ebeb67c622..bcc1493cd9 100644 --- a/packages/client/src/stores/environment.js +++ b/packages/client/src/stores/environment.js @@ -2,6 +2,7 @@ import { API } from "api" import { writable } from "svelte/store" const initialState = { + loaded: false, cloud: false, } @@ -15,6 +16,7 @@ const createEnvironmentStore = () => { store.set({ ...initialState, ...environment, + loaded: true, }) } catch (error) { store.set(initialState) From c111f02e709d8452a54bb84a39fbf650326db983 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 24 Oct 2022 09:38:07 +0100 Subject: [PATCH 21/32] Improve client grid DND event handling --- packages/client/src/components/ClientApp.svelte | 2 ++ packages/client/src/components/Component.svelte | 1 - packages/client/src/components/app/Grid.svelte | 7 +------ .../components/preview/GridDNDHandler.svelte | 17 +++++++++-------- packages/client/src/stores/builder.js | 4 ++-- 5 files changed, 14 insertions(+), 17 deletions(-) diff --git a/packages/client/src/components/ClientApp.svelte b/packages/client/src/components/ClientApp.svelte index 537e963ff3..2fb0a92dab 100644 --- a/packages/client/src/components/ClientApp.svelte +++ b/packages/client/src/components/ClientApp.svelte @@ -30,6 +30,7 @@ import HoverIndicator from "components/preview/HoverIndicator.svelte" import CustomThemeWrapper from "./CustomThemeWrapper.svelte" import DNDHandler from "components/preview/DNDHandler.svelte" + import GridDNDHandler from "components/preview/GridDNDHandler.svelte" import KeyboardManager from "components/preview/KeyboardManager.svelte" import DevToolsHeader from "components/devtools/DevToolsHeader.svelte" import DevTools from "components/devtools/DevTools.svelte" @@ -196,6 +197,7 @@ {/if} {#if $builderStore.inBuilder} + {/if}
diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte index 669cc8afdc..c59ef050cd 100644 --- a/packages/client/src/components/Component.svelte +++ b/packages/client/src/components/Component.svelte @@ -219,7 +219,6 @@ return } else { lastInstanceKey = instanceKey - ephemeralStyles = null } // Pull definition and constructor diff --git a/packages/client/src/components/app/Grid.svelte b/packages/client/src/components/app/Grid.svelte index 7e2ec68627..8348a3ba91 100644 --- a/packages/client/src/components/app/Grid.svelte +++ b/packages/client/src/components/app/Grid.svelte @@ -1,9 +1,8 @@
Date: Mon, 24 Oct 2022 13:24:19 +0100 Subject: [PATCH 28/32] Fix selection indicator appearing while dragging --- .../client/src/components/preview/HoverIndicator.svelte | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/client/src/components/preview/HoverIndicator.svelte b/packages/client/src/components/preview/HoverIndicator.svelte index 7d7d3e0540..f976e2cffb 100644 --- a/packages/client/src/components/preview/HoverIndicator.svelte +++ b/packages/client/src/components/preview/HoverIndicator.svelte @@ -6,11 +6,6 @@ let componentId $: zIndex = componentId === $builderStore.selectedComponentId ? 900 : 920 - $: { - if ($dndIsDragging) { - componentId = null - } - } const onMouseOver = e => { // Ignore if dragging @@ -49,7 +44,7 @@ Date: Mon, 24 Oct 2022 13:28:22 +0100 Subject: [PATCH 29/32] Remove some unnecessary code --- .../_components/settings/componentStyles.js | 61 ------------------- .../client/src/components/Component.svelte | 30 ++++----- 2 files changed, 13 insertions(+), 78 deletions(-) diff --git a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/componentStyles.js b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/componentStyles.js index 710cbed9b1..d4912241b3 100644 --- a/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/componentStyles.js +++ b/packages/builder/src/pages/builder/app/[application]/design/[screenId]/components/[componentId]/_components/settings/componentStyles.js @@ -1,67 +1,6 @@ import { Input, Select } from "@budibase/bbui" import ColorPicker from "components/design/settings/controls/ColorPicker.svelte" -export const grid = { - label: "Grid", - columns: "1fr 1fr", - settings: [ - { - label: "Col. start", - key: "grid-column-start", - control: Select, - placeholder: "Auto", - options: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], - }, - { - label: "Col. end", - key: "grid-column-end", - control: Select, - placeholder: "Auto", - options: [ - { label: "1", value: 2 }, - { label: "2", value: 3 }, - { label: "3", value: 4 }, - { label: "4", value: 5 }, - { label: "5", value: 6 }, - { label: "6", value: 7 }, - { label: "7", value: 8 }, - { label: "8", value: 9 }, - { label: "9", value: 10 }, - { label: "10", value: 11 }, - { label: "11", value: 12 }, - { label: "12", value: 13 }, - ], - }, - { - label: "Row start", - key: "grid-row-start", - control: Select, - placeholder: "Auto", - options: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12], - }, - { - label: "Row end", - key: "grid-row-end", - control: Select, - placeholder: "Auto", - options: [ - { label: "1", value: 2 }, - { label: "2", value: 3 }, - { label: "3", value: 4 }, - { label: "4", value: 5 }, - { label: "5", value: 6 }, - { label: "6", value: 7 }, - { label: "7", value: 8 }, - { label: "8", value: 9 }, - { label: "9", value: 10 }, - { label: "10", value: 11 }, - { label: "11", value: 12 }, - { label: "12", value: 13 }, - ], - }, - ], -} - export const margin = { label: "Margin", columns: "1fr 1fr", diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte index dc2f8c1d5f..e87efacd4c 100644 --- a/packages/client/src/components/Component.svelte +++ b/packages/client/src/components/Component.svelte @@ -170,26 +170,23 @@ $: pad = pad || (interactive && hasChildren && inDndPath) $: $dndIsDragging, (pad = false) - // Compute overall styles - $: styles = { - ...instance._styles, - normal: { - ...instance._styles?.normal, - ...ephemeralStyles, - }, - custom: customCSS, - id, - empty: emptyState, - interactive, - draggable, - editable, - } - // Update component context $: store.set({ id, children: children.length, - styles, + styles: { + ...instance._styles, + normal: { + ...instance._styles?.normal, + ...ephemeralStyles, + }, + custom: customCSS, + id, + empty: emptyState, + interactive, + draggable, + editable, + }, empty: emptyState, selected, name, @@ -458,7 +455,6 @@ componentStore.actions.registerInstance(id, { component: instance._component, getSettings: () => cachedSettings, - getStyles: () => styles, getRawSettings: () => ({ ...staticSettings, ...dynamicSettings }), getDataContext: () => get(context), reload: () => initialise(instance, true), From c888b703ddfbff333b1b2b417f01bf92918c8e2a Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 24 Oct 2022 13:32:48 +0100 Subject: [PATCH 30/32] Improve comments and namimg conventions --- packages/client/src/components/preview/DNDHandler.svelte | 6 ++++-- .../client/src/components/preview/GridDNDHandler.svelte | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/packages/client/src/components/preview/DNDHandler.svelte b/packages/client/src/components/preview/DNDHandler.svelte index 42a2fafbdd..1855166e0c 100644 --- a/packages/client/src/components/preview/DNDHandler.svelte +++ b/packages/client/src/components/preview/DNDHandler.svelte @@ -25,7 +25,9 @@ // Local flag for whether we are awaiting an async drop event let dropping = false - const insideGrid = e => { + // Util to check if a DND event originates from a grid (or inside a grid). + // This is important as we do not handle grid DND in this handler. + const isGridEvent = e => { return e.target ?.closest?.(".component") ?.parentNode?.closest?.(".component") @@ -69,7 +71,7 @@ // Callback when initially starting a drag on a draggable component const onDragStart = e => { - if (insideGrid(e)) { + if (isGridEvent(e)) { return } const component = e.target.closest(".component") diff --git a/packages/client/src/components/preview/GridDNDHandler.svelte b/packages/client/src/components/preview/GridDNDHandler.svelte index 61bd8db08f..46e2e575b0 100644 --- a/packages/client/src/components/preview/GridDNDHandler.svelte +++ b/packages/client/src/components/preview/GridDNDHandler.svelte @@ -17,7 +17,9 @@ ...(gridStyles ? { "z-index": 999 } : null), }) - const isChildOfGrid = e => { + // Util to check if a DND event originates from a grid (or inside a grid). + // This is important as we do not handle grid DND in this handler. + const isGridEvent = e => { return ( e.target .closest?.(".component") @@ -113,7 +115,7 @@ // Callback when initially starting a drag on a draggable component const onDragStart = e => { - if (!isChildOfGrid(e)) { + if (!isGridEvent(e)) { return } From 729c4d082eeb2c0db2b24eaf47b00bc5fbe641d9 Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Mon, 24 Oct 2022 13:33:33 +0100 Subject: [PATCH 31/32] Remove unnecessary code --- packages/client/src/components/Component.svelte | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte index e87efacd4c..18b6488189 100644 --- a/packages/client/src/components/Component.svelte +++ b/packages/client/src/components/Component.svelte @@ -35,7 +35,6 @@ export let isScreen = false export let isBlock = false export let parent = null - export let parentType = null // Get parent contexts const context = getContext("context") @@ -496,11 +495,7 @@ {:else if children.length} {#each children as child (child._id)} - + {/each} {:else if emptyState} {#if isScreen} From 6568e40267bdfa4aba4335dd9829d2ca9252b75c Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 25 Oct 2022 08:01:42 +0100 Subject: [PATCH 32/32] Rename grid component as beta --- packages/client/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/client/manifest.json b/packages/client/manifest.json index cc4034dbca..7da72cefba 100644 --- a/packages/client/manifest.json +++ b/packages/client/manifest.json @@ -4567,7 +4567,7 @@ ] }, "grid": { - "name": "Grid", + "name": "Grid (Beta)", "icon": "ViewGrid", "hasChildren": true, "styles": [