diff --git a/packages/client/src/components/ClientApp.svelte b/packages/client/src/components/ClientApp.svelte index 7144105fd8..144b5a8dec 100644 --- a/packages/client/src/components/ClientApp.svelte +++ b/packages/client/src/components/ClientApp.svelte @@ -44,7 +44,7 @@ import MaintenanceScreen from "components/MaintenanceScreen.svelte" import SnippetsProvider from "./context/SnippetsProvider.svelte" import EmbedProvider from "./context/EmbedProvider.svelte" - import GridNewComponentDNDHandler from "components/preview/GridNewComponentDNDHandler.svelte" + import DNDSelectionIndicators from "./preview/DNDSelectionIndicators.svelte" // Provide contexts setContext("sdk", SDK) @@ -267,7 +267,7 @@ {#if $builderStore.inBuilder} - + {/if} diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte index 3e22ffada1..67f8fdc63c 100644 --- a/packages/client/src/components/Component.svelte +++ b/packages/client/src/components/Component.svelte @@ -120,7 +120,7 @@ $: children = instance._children || [] $: id = instance._id $: name = isRoot ? "Screen" : instance._instanceName - $: icon = definition?.icon + $: icon = instance._icon || definition?.icon // Determine if the component is selected or is part of the critical path // leading to the selected component diff --git a/packages/client/src/components/preview/DNDHandler.svelte b/packages/client/src/components/preview/DNDHandler.svelte index f62f21e94c..82db06a623 100644 --- a/packages/client/src/components/preview/DNDHandler.svelte +++ b/packages/client/src/components/preview/DNDHandler.svelte @@ -7,10 +7,10 @@ screenStore, dndStore, dndParent, + dndSource, dndIsDragging, isGridScreen, } from "stores" - import DNDPlaceholderOverlay from "./DNDPlaceholderOverlay.svelte" import { Utils } from "@budibase/frontend-core" import { findComponentById } from "@/utils/components.js" import { isGridEvent } from "@/utils/grid" @@ -92,6 +92,8 @@ bounds: component.children[0].getBoundingClientRect(), parent: parentId, index, + name: component.dataset.name, + icon: component.dataset.icon, }) builderStore.actions.selectComponent(id) @@ -258,10 +260,10 @@ } // Check if we're adding a new component rather than moving one - if (source.newComponentType) { + if (source.isNew) { dropping = true builderStore.actions.dropNewComponent( - source.newComponentType, + source.type, drop.parent, drop.index, $dndStore.meta.newComponentProps @@ -335,16 +337,3 @@ document.removeEventListener("drop", onDrop, false) }) - -{#if !$isGridScreen} - -{/if} - -{#if $dndIsDragging} - -{/if} diff --git a/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte b/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte index 5593fa010d..f06454acce 100644 --- a/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte +++ b/packages/client/src/components/preview/DNDPlaceholderOverlay.svelte @@ -1,96 +1,108 @@ - + + + + + + + -{#if left != null && top != null && width && height && !waitingForGrid} -
-{/if} + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/packages/client/src/components/preview/DNDSelectionIndicators.svelte b/packages/client/src/components/preview/DNDSelectionIndicators.svelte new file mode 100644 index 0000000000..9949f07ace --- /dev/null +++ b/packages/client/src/components/preview/DNDSelectionIndicators.svelte @@ -0,0 +1,27 @@ + + +{#if !$isGridScreen} + +{/if} + +{#if $dndIsDragging} + +{/if} diff --git a/packages/client/src/components/preview/GridDNDHandler.svelte b/packages/client/src/components/preview/GridDNDHandler.svelte index 569a9879a6..58ba92ab07 100644 --- a/packages/client/src/components/preview/GridDNDHandler.svelte +++ b/packages/client/src/components/preview/GridDNDHandler.svelte @@ -4,8 +4,8 @@ builderStore, componentStore, dndIsDragging, - dndIsNewComponent, dndStore, + dndSource, isGridScreen, } from "stores" import { Utils, memo } from "@budibase/frontend-core" @@ -53,7 +53,7 @@ // If dragging a new component on to a grid screen, tick to allow the // real component to render in the new position before updating the DND // store, preventing the green DND overlay from being out of position - if ($dndIsNewComponent && styles) { + if ($dndSource?.isNew && styles) { dndStore.actions.updateNewComponentProps({ _styles: { normal: styles, @@ -222,7 +222,7 @@ const onDragOver = e => { if (!dragInfo) { // Check if we're dragging a new component - if ($dndIsDragging && $dndIsNewComponent && $isGridScreen) { + if ($dndIsDragging && $dndSource?.isNew && $isGridScreen) { startDraggingPlaceholder() } return diff --git a/packages/client/src/components/preview/Indicator.svelte b/packages/client/src/components/preview/Indicator.svelte index dce7945b29..94940285ff 100644 --- a/packages/client/src/components/preview/Indicator.svelte +++ b/packages/client/src/components/preview/Indicator.svelte @@ -14,6 +14,8 @@ export let line = false export let alignRight = false export let showResizeAnchors = false + export let background = null + export let animate = false const AnchorSides = [ "right", @@ -33,10 +35,12 @@ class="indicator" class:flipped class:line - style="top: {top}px; left: {left}px; width: {width}px; height: {height}px; --color: {color}; --zIndex: {zIndex};" + style="top: {top}px; left: {left}px; width: {width}px; height: {height}px; --color: {color}; --zIndex: {zIndex}; --bg: {background || + 'none'};" class:withText={!!text} class:vCompact={height < 40} class:hCompact={width < 40} + class:animate > {#if text || icon}
{ mutationObserver.observe(element, { attributes: true, - attributeFilter: ["style"], }) observingMutations = true } @@ -108,17 +111,19 @@ } // Check if we're inside a grid - if (allowResizeAnchors) { - nextState.insideGrid = elements[0]?.dataset.insideGrid === "true" - } + nextState.insideGrid = elements[0]?.dataset.insideGrid === "true" - // Get text to display - nextState.text = elements[0].dataset.name - if (nextState.prefix) { - nextState.text = `${nextState.prefix} ${nextState.text}` + // Get text and icon to display + if (!text) { + nextState.text = elements[0].dataset.name + if (nextState.prefix) { + nextState.text = `${nextState.prefix} ${nextState.text}` + } } - if (elements[0].dataset.icon) { - nextState.icon = elements[0].dataset.icon + if (!icon) { + if (elements[0].dataset.icon) { + nextState.icon = elements[0].dataset.icon + } } nextState.error = elements[0].classList.contains("error") @@ -205,5 +210,7 @@ color={state.error ? errorColor : state.color} componentId={state.componentId} zIndex={state.zIndex} + {background} + {animate} /> {/each} diff --git a/packages/client/src/stores/dnd.js b/packages/client/src/stores/dnd.js index 38c1e8aab8..f6b8fec48c 100644 --- a/packages/client/src/stores/dnd.js +++ b/packages/client/src/stores/dnd.js @@ -21,10 +21,17 @@ const createDndStore = () => { } const store = writable(initialState) - const startDraggingExistingComponent = ({ id, parent, bounds, index }) => { + const startDraggingExistingComponent = ({ + id, + parent, + bounds, + index, + name, + icon, + }) => { store.set({ ...initialState, - source: { id, parent, bounds, index }, + source: { id, parent, bounds, index, name, icon, isNew: false }, }) } @@ -62,7 +69,10 @@ const createDndStore = () => { parent: null, bounds: { height, width }, index: null, - newComponentType: component, + type: component, + isNew: true, + name: `New ${definition.name}`, + icon: definition.icon, }, target, drop, @@ -118,9 +128,5 @@ export const dndStore = createDndStore() // or components which depend on DND state unless values actually change. export const dndParent = derivedMemo(dndStore, x => x.drop?.parent) export const dndIndex = derivedMemo(dndStore, x => x.drop?.index) -export const dndBounds = derivedMemo(dndStore, x => x.source?.bounds) +export const dndSource = derivedMemo(dndStore, x => x.source) export const dndIsDragging = derivedMemo(dndStore, x => !!x.source) -export const dndIsNewComponent = derivedMemo( - dndStore, - x => x.source?.newComponentType != null -) diff --git a/packages/client/src/stores/index.js b/packages/client/src/stores/index.js index 268b0cc4bf..522fadc643 100644 --- a/packages/client/src/stores/index.js +++ b/packages/client/src/stores/index.js @@ -18,14 +18,7 @@ export { environmentStore } from "./environment" export { eventStore } from "./events" export { orgStore } from "./org" export { roleStore } from "./roles" -export { - dndStore, - dndIndex, - dndParent, - dndBounds, - dndIsNewComponent, - dndIsDragging, -} from "./dnd" +export { dndStore, dndIndex, dndParent, dndIsDragging, dndSource } from "./dnd" export { sidePanelStore } from "./sidePanel" export { modalStore } from "./modal" export { hoverStore } from "./hover" diff --git a/packages/client/src/stores/screens.js b/packages/client/src/stores/screens.js index 99b943fbd2..df0dc0e365 100644 --- a/packages/client/src/stores/screens.js +++ b/packages/client/src/stores/screens.js @@ -3,7 +3,7 @@ import { routeStore } from "./routes" import { builderStore } from "./builder" import { appStore } from "./app" import { orgStore } from "./org" -import { dndIndex, dndParent, dndIsNewComponent, dndBounds } from "./dnd.js" +import { dndIndex, dndParent, dndSource } from "./dnd.js" import { RoleUtils } from "@budibase/frontend-core" import { findComponentById, findComponentParent } from "../utils/components.js" import { Helpers } from "@budibase/bbui" @@ -18,8 +18,7 @@ const createScreenStore = () => { orgStore, dndParent, dndIndex, - dndIsNewComponent, - dndBounds, + dndSource, ], ([ $appStore, @@ -28,8 +27,7 @@ const createScreenStore = () => { $orgStore, $dndParent, $dndIndex, - $dndIsNewComponent, - $dndBounds, + $dndSource, ]) => { let activeLayout, activeScreen let screens @@ -85,7 +83,7 @@ const createScreenStore = () => { // Remove selected component from tree if we are moving an existing // component - if (!$dndIsNewComponent && selectedParent) { + if (!$dndSource.isNew && selectedParent) { selectedParent._children = selectedParent._children?.filter( x => x._id !== selectedComponentId ) @@ -97,11 +95,11 @@ const createScreenStore = () => { _id: DNDPlaceholderID, _styles: { normal: { - width: `${$dndBounds?.width || 400}px`, - height: `${$dndBounds?.height || 200}px`, + width: `${$dndSource?.bounds?.width || 400}px`, + height: `${$dndSource?.bounds?.height || 200}px`, opacity: 0, - "--default-width": $dndBounds?.width || 400, - "--default-height": $dndBounds?.height || 200, + "--default-width": $dndSource?.bounds?.width || 400, + "--default-height": $dndSource?.bounds?.height || 200, }, }, static: true,