From 65e7453fbf7c1f0857a53cebd54526f810cfd45b Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Tue, 8 Jun 2021 14:19:03 +0100 Subject: [PATCH] Render builder preview selection indicators via top level component instead of via styleable healper. Add indiciator on hover and add name to indicator --- .../AppPreview/CurrentItemPreview.svelte | 2 +- .../design/AppPreview/iframeTemplate.js | 7 +- .../client/src/components/ClientApp.svelte | 12 ++- .../client/src/components/Component.svelte | 9 ++- .../src/components/HoverIndicator.svelte | 74 +++++++++++++++++++ .../client/src/components/Indicator.svelte | 53 +++++++++++++ .../src/components/SelectionIndicator.svelte | 52 +++++++++++++ .../client/src/components/SettingsBar.svelte | 31 ++++---- packages/client/src/utils/styleable.js | 21 +----- 9 files changed, 217 insertions(+), 44 deletions(-) create mode 100644 packages/client/src/components/HoverIndicator.svelte create mode 100644 packages/client/src/components/Indicator.svelte create mode 100644 packages/client/src/components/SelectionIndicator.svelte diff --git a/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte b/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte index 6bbf90e936..4929cf5db2 100644 --- a/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte +++ b/packages/builder/src/components/design/AppPreview/CurrentItemPreview.svelte @@ -101,12 +101,12 @@ overflow: hidden; margin: auto; height: 100%; - background-color: white; } .component-container iframe { border: 0; left: 0; top: 0; width: 100%; + background-color: transparent; } diff --git a/packages/builder/src/components/design/AppPreview/iframeTemplate.js b/packages/builder/src/components/design/AppPreview/iframeTemplate.js index da39a6477b..f333359a26 100644 --- a/packages/builder/src/components/design/AppPreview/iframeTemplate.js +++ b/packages/builder/src/components/design/AppPreview/iframeTemplate.js @@ -14,10 +14,13 @@ export default ` diff --git a/packages/client/src/components/SelectionIndicator.svelte b/packages/client/src/components/SelectionIndicator.svelte new file mode 100644 index 0000000000..b34e6cab0d --- /dev/null +++ b/packages/client/src/components/SelectionIndicator.svelte @@ -0,0 +1,52 @@ + + +{#each indicators as indicator, idx} + +{/each} diff --git a/packages/client/src/components/SettingsBar.svelte b/packages/client/src/components/SettingsBar.svelte index 41b546eff6..42d46bcbb2 100644 --- a/packages/client/src/components/SettingsBar.svelte +++ b/packages/client/src/components/SettingsBar.svelte @@ -3,11 +3,15 @@ import SettingsButton from "./SettingsButton.svelte" import { builderStore } from "../store" + const verticalOffset = 28 + const horizontalOffset = 2 + let top = 0 let left = 0 let interval let self let measured = false + $: definition = $builderStore.selectedComponentDefinition $: showBar = definition?.showSettingsBar $: settings = definition?.settings?.filter(setting => setting.showInBar) ?? [] @@ -20,32 +24,35 @@ const parent = document.getElementsByClassName(id)?.[0] const element = parent?.childNodes?.[0] if (element && self) { + // Batch reads to minimize reflow const elBounds = element.getBoundingClientRect() const width = self.offsetWidth const height = self.offsetHeight + const { scrollX, scrollY, innerWidth } = window // Vertically, always render above unless no room, then render inside - let newTop = elBounds.top + window.scrollY - 10 - height + let newTop = elBounds.top + scrollY - verticalOffset - height if (newTop < 0) { - newTop = elBounds.top + window.scrollY + 10 + newTop = elBounds.top + scrollY + verticalOffset } // Horizontally, try to center first. // Failing that, render to left edge of component. // Failing that, render to right edge of component, // Failing that, render to window left edge and accept defeat. - let elCenter = elBounds.left + window.scrollX + elBounds.width / 2 + let elCenter = elBounds.left + scrollX + elBounds.width / 2 let newLeft = elCenter - width / 2 - if (newLeft < 0 || newLeft + width > window.innerWidth) { - newLeft = elBounds.left + window.scrollX - if (newLeft < 0 || newLeft + width > window.innerWidth) { - newLeft = elBounds.left + window.scrollX + elBounds.width - width - if (newLeft < 0 || newLeft + width > window.innerWidth) { + if (newLeft < 0 || newLeft + width > innerWidth) { + newLeft = elBounds.left + scrollX - horizontalOffset + if (newLeft < 0 || newLeft + width > innerWidth) { + newLeft = innerWidth - width - 20 + if (newLeft < 0 || newLeft + width > innerWidth) { newLeft = 0 } } } + // Only update state when things changes to minimize renders if (Math.round(newTop) !== Math.round(top)) { top = newTop } @@ -62,9 +69,7 @@ }) onDestroy(() => { - if (interval) { - clearInterval(interval) - } + clearInterval(interval) }) @@ -97,8 +102,8 @@ .bar { display: flex; position: absolute; - z-index: 999; - padding: 6px 10px; + z-index: 920; + padding: 6px 8px; opacity: 0; flex-direction: row; background: var(--background); diff --git a/packages/client/src/utils/styleable.js b/packages/client/src/utils/styleable.js index 9a89f1d273..4ea92a3acd 100644 --- a/packages/client/src/utils/styleable.js +++ b/packages/client/src/utils/styleable.js @@ -14,25 +14,6 @@ const buildStyleString = (styleObject, customStyles) => { return str + (customStyles || "") } -/** - * Applies styles to enrich the builder preview. - * Applies styles to highlight the selected component, and allows pointer - * events for any selectable components (overriding the blanket ban on pointer - * events in the iframe HTML). - */ -const addBuilderPreviewStyles = (node, styleString, componentId) => { - if (componentId === get(builderStore).selectedComponentId) { - const style = window.getComputedStyle(node) - const property = style?.display === "table-row" ? "outline" : "border" - return ( - styleString + - `;${property}: 2px solid #4285f4 !important; border-radius: 4px !important;` - ) - } else { - return styleString - } -} - /** * Svelte action to apply correct component styles. * This also applies handlers for selecting components from the builder preview. @@ -54,7 +35,7 @@ export const styleable = (node, styles = {}) => { // Applies a style string to a DOM node const applyStyles = styleString => { - node.style = addBuilderPreviewStyles(node, styleString, componentId) + node.style = styleString node.dataset.componentId = componentId }