From 6631fe2af86997ceb5023727d3fb19dda1cbe01e Mon Sep 17 00:00:00 2001 From: Andrew Kingston Date: Wed, 27 Jan 2021 15:52:12 +0000 Subject: [PATCH] Update builder preview to be interactive and improve builder preview experience --- .../design/AppPreview/iframeTemplate.html | 3 -- .../PropertiesPanel/SettingsView.svelte | 2 +- .../design/PropertiesPanel/componentStyles.js | 33 ------------ .../client/src/components/ClientApp.svelte | 11 ++-- .../client/src/components/Component.svelte | 45 ++++++++--------- packages/client/src/components/Router.svelte | 3 -- packages/client/src/utils/hash.js | 12 +++++ packages/client/src/utils/styleable.js | 50 +++++-------------- packages/standard-components/src/Login.svelte | 5 +- .../standard-components/src/Navigation.svelte | 5 +- .../src/forms/OptionsField.svelte | 12 ----- .../src/forms/SpectrumField.svelte | 16 +++++- .../src/forms/StringField.svelte | 50 ++----------------- 13 files changed, 81 insertions(+), 166 deletions(-) create mode 100644 packages/client/src/utils/hash.js diff --git a/packages/builder/src/components/design/AppPreview/iframeTemplate.html b/packages/builder/src/components/design/AppPreview/iframeTemplate.html index 49df3b5c0b..166a978d01 100644 --- a/packages/builder/src/components/design/AppPreview/iframeTemplate.html +++ b/packages/builder/src/components/design/AppPreview/iframeTemplate.html @@ -11,9 +11,6 @@ *, *:before, *:after { box-sizing: border-box; } - * { - pointer-events: none; - } {#if constructor && componentProps} - - {#if children.length} - {#each children as child (getChildKey(child._id))} - - {/each} - {/if} - + {#key propsHash} + + {#if children.length} + {#each children as child (child._id)} + + {/each} + {/if} + + {/key} {/if} diff --git a/packages/client/src/components/Router.svelte b/packages/client/src/components/Router.svelte index 5477d02f86..efa0e321aa 100644 --- a/packages/client/src/components/Router.svelte +++ b/packages/client/src/components/Router.svelte @@ -7,9 +7,6 @@ const { styleable } = getContext("sdk") const component = getContext("component") - // Set context flag so components know that we're now inside the screenslot - setContext("screenslot", true) - // Only wrap this as an array to take advantage of svelte keying, // to ensure the svelte-spa-router is fully remounted when route config // changes diff --git a/packages/client/src/utils/hash.js b/packages/client/src/utils/hash.js new file mode 100644 index 0000000000..2c42007e43 --- /dev/null +++ b/packages/client/src/utils/hash.js @@ -0,0 +1,12 @@ +export const hashString = str => { + if (!str) { + return 0 + } + let hash = 0 + for (let i = 0; i < str.length; i++) { + let char = str.charCodeAt(i) + hash = (hash << 5) - hash + char + hash = hash & hash // Convert to 32bit integer + } + return hash +} diff --git a/packages/client/src/utils/styleable.js b/packages/client/src/utils/styleable.js index 665a3dc92d..6cc387058a 100644 --- a/packages/client/src/utils/styleable.js +++ b/packages/client/src/utils/styleable.js @@ -1,9 +1,6 @@ import { get } from "svelte/store" import { builderStore } from "../store" -const selectedComponentWidth = 2 -const selectedComponentColor = "#4285f4" - /** * Helper to build a CSS string from a style object. */ @@ -23,24 +20,14 @@ const buildStyleString = (styleObject, customStyles) => { * events for any selectable components (overriding the blanket ban on pointer * events in the iframe HTML). */ -const addBuilderPreviewStyles = (styleString, componentId, selectable) => { - let str = styleString - - // Apply extra styles if we're in the builder preview - const state = get(builderStore) - if (state.inBuilder) { - // Allow pointer events and always enable cursor - if (selectable) { - str += ";pointer-events: all !important; cursor: pointer !important;" - } - - // Highlighted selected element - if (componentId === state.selectedComponentId) { - str += `;border: ${selectedComponentWidth}px solid ${selectedComponentColor} !important;` - } +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;` + } else { + return styleString } - - return str } /** @@ -52,17 +39,9 @@ export const styleable = (node, styles = {}) => { let applyHoverStyles let selectComponent - // Kill JS even bubbling - const blockEvent = event => { - event.preventDefault() - event.stopPropagation() - return false - } - // Creates event listeners and applies initial styles const setupStyles = (newStyles = {}) => { const componentId = newStyles.id - const selectable = !!newStyles.allowSelection const customStyles = newStyles.custom || "" const normalStyles = newStyles.normal || {} const hoverStyles = { @@ -70,10 +49,9 @@ export const styleable = (node, styles = {}) => { ...(newStyles.hover || {}), } - // Applies a style string to a DOM node, enriching it for the builder - // preview + // Applies a style string to a DOM node const applyStyles = styleString => { - node.style = addBuilderPreviewStyles(styleString, componentId, selectable) + node.style = addBuilderPreviewStyles(node, styleString, componentId) node.dataset.componentId = componentId } @@ -91,7 +69,9 @@ export const styleable = (node, styles = {}) => { // builder preview selectComponent = event => { builderStore.actions.selectComponent(componentId) - return blockEvent(event) + event.preventDefault() + event.stopPropagation() + return false } // Add listeners to toggle hover styles @@ -101,10 +81,6 @@ export const styleable = (node, styles = {}) => { // Add builder preview click listener if (get(builderStore).inBuilder) { node.addEventListener("click", selectComponent, false) - - // Kill other interaction events - node.addEventListener("mousedown", blockEvent) - node.addEventListener("mouseup", blockEvent) } // Apply initial normal styles @@ -119,8 +95,6 @@ export const styleable = (node, styles = {}) => { // Remove builder preview click listener if (get(builderStore).inBuilder) { node.removeEventListener("click", selectComponent) - node.removeEventListener("mousedown", blockEvent) - node.removeEventListener("mouseup", blockEvent) } } diff --git a/packages/standard-components/src/Login.svelte b/packages/standard-components/src/Login.svelte index 8a4af82320..1502b5c583 100644 --- a/packages/standard-components/src/Login.svelte +++ b/packages/standard-components/src/Login.svelte @@ -1,7 +1,7 @@ diff --git a/packages/standard-components/src/forms/OptionsField.svelte b/packages/standard-components/src/forms/OptionsField.svelte index 2796356027..77d48867f6 100644 --- a/packages/standard-components/src/forms/OptionsField.svelte +++ b/packages/standard-components/src/forms/OptionsField.svelte @@ -92,16 +92,4 @@ {/each} - {#if $fieldState.error} -
{$fieldState.error}
- {/if} - - diff --git a/packages/standard-components/src/forms/SpectrumField.svelte b/packages/standard-components/src/forms/SpectrumField.svelte index 84f1a22ccb..4acda6e921 100644 --- a/packages/standard-components/src/forms/SpectrumField.svelte +++ b/packages/standard-components/src/forms/SpectrumField.svelte @@ -10,7 +10,7 @@ const component = getContext("component") const { labelPosition, formApi } = formContext || {} const formField = formApi?.registerField(field) ?? {} - const { fieldId } = formField + const { fieldId, fieldState } = formField $: labelPositionClass = labelPosition === "top" ? "" : `spectrum-FieldLabel--${labelPosition}` @@ -31,6 +31,20 @@ {/if}
+ {#if $fieldState.error} +
{$fieldState.error}
+ {/if}
{/if} + + diff --git a/packages/standard-components/src/forms/StringField.svelte b/packages/standard-components/src/forms/StringField.svelte index f75a5b1b6f..43ae0c1c13 100644 --- a/packages/standard-components/src/forms/StringField.svelte +++ b/packages/standard-components/src/forms/StringField.svelte @@ -1,7 +1,5 @@ -
-
+
+
{#if !$fieldState.valid} + class="spectrum-Textfield-input" />
- {#if numeric} - - - - - {/if} - {#if $fieldState.error} -
{$fieldState.error}
- {/if}
- -