1
0
Fork 0
mirror of synced 2024-07-04 22:11:23 +12:00

Refactor client app data tags to be classnames and simplify logic

This commit is contained in:
Andrew Kingston 2021-09-20 15:34:51 +01:00
parent 8defbd1ed2
commit 9634b021a5
5 changed files with 51 additions and 46 deletions

View file

@ -51,11 +51,11 @@
$: children = instance._children || [] $: children = instance._children || []
$: id = instance._id $: id = instance._id
$: name = instance._instanceName $: name = instance._instanceName
$: empty = $: interactive =
!children.length && $builderStore.inBuilder &&
definition?.hasChildren && ($builderStore.previewType === "layout" || insideScreenslot)
definition?.showEmptyState !== false && $: empty = interactive && !children.length && definition?.hasChildren
$builderStore.inBuilder $: emptyState = empty && definition?.showEmptyState !== false
$: rawProps = getRawProps(instance) $: rawProps = getRawProps(instance)
$: instanceKey = JSON.stringify(rawProps) $: instanceKey = JSON.stringify(rawProps)
$: updateComponentProps(rawProps, instanceKey, $context) $: updateComponentProps(rawProps, instanceKey, $context)
@ -63,9 +63,6 @@
$builderStore.inBuilder && $builderStore.inBuilder &&
$builderStore.selectedComponentId === instance._id $builderStore.selectedComponentId === instance._id
$: inSelectedPath = $builderStore.selectedComponentPath?.includes(id) $: inSelectedPath = $builderStore.selectedComponentPath?.includes(id)
$: interactive =
$builderStore.inBuilder &&
($builderStore.previewType === "layout" || insideScreenslot)
$: evaluateConditions(enrichedSettings?._conditions) $: evaluateConditions(enrichedSettings?._conditions)
$: componentSettings = { ...enrichedSettings, ...conditionalSettings } $: componentSettings = { ...enrichedSettings, ...conditionalSettings }
@ -73,8 +70,8 @@
$: componentStore.set({ $: componentStore.set({
id, id,
children: children.length, children: children.length,
styles: { ...instance._styles, id, empty, interactive }, styles: { ...instance._styles, id, empty: emptyState, interactive },
empty, empty: emptyState,
selected, selected,
name, name,
}) })
@ -177,38 +174,44 @@
// Drag and drop helper tags // Drag and drop helper tags
$: draggable = interactive && !isLayout && !isScreen $: draggable = interactive && !isLayout && !isScreen
$: droppable = interactive && !isLayout && !isScreen $: droppable = interactive && !isLayout && !isScreen
$: dropInside = interactive && definition?.hasChildren && !children.length
</script> </script>
{#key propsHash} {#key propsHash}
{#if constructor && componentSettings && (visible || inSelectedPath)} {#key empty}
<div {#if constructor && componentSettings && (visible || inSelectedPath)}
class={`component ${id}`} <!-- The ID is used as a class because getElementsByClassName is O(1) -->
data-type={interactive ? "component" : "readonly"} <!-- and the performance matters for the selection indicators -->
data-id={id} <div
data-name={name} class={`component ${id}`}
data-draggable={draggable} class:draggable
data-droppable={droppable} class:droppable
data-droppable-inside={dropInside} class:empty
> class:interactive
<svelte:component this={constructor} {...componentSettings}> data-id={id}
{#if children.length} data-name={name}
{#each children as child (child._id)} >
<svelte:self instance={child} /> <svelte:component this={constructor} {...componentSettings}>
{/each} {#if children.length}
{:else if empty} {#each children as child (child._id)}
<Placeholder /> <svelte:self instance={child} />
{/if} {/each}
</svelte:component> {:else if emptyState}
</div> <Placeholder />
{/if} {/if}
</svelte:component>
</div>
{/if}
{/key}
{/key} {/key}
<style> <style>
.component { .component {
display: contents; display: contents;
} }
[data-draggable="true"] :global(*:hover) { .interactive :global(*:hover) {
cursor: pointer;
}
.draggable :global(*:hover) {
cursor: grab; cursor: grab;
} }
</style> </style>

View file

@ -34,7 +34,7 @@
display: flex; display: flex;
max-width: 100%; max-width: 100%;
} }
.valid-container :global([data-type="component"] > *) { .valid-container :global(.component > *) {
max-width: 100%; max-width: 100%;
} }
.direction-row { .direction-row {
@ -46,7 +46,7 @@
/* Grow containers inside a row need 0 width 0 so that they ignore content */ /* Grow containers inside a row need 0 width 0 so that they ignore content */
/* The nested selector for data-type is the wrapper around all components */ /* The nested selector for data-type is the wrapper around all components */
.direction-row :global(> [data-type="component"] > .size-grow) { .direction-row :global(> .component > .size-grow) {
width: 0; width: 0;
} }

View file

@ -9,16 +9,15 @@
let dropInfo let dropInfo
const getDOMNodeForComponent = component => { const getDOMNodeForComponent = component => {
const parent = component.closest("[data-type='component']") const parent = component.closest(".component")
const children = Array.from(parent.childNodes) const children = Array.from(parent.childNodes)
return children?.find(node => node?.nodeType === 1) return children?.find(node => node?.nodeType === 1)
} }
// Callback when initially starting a drag on a draggable component // Callback when initially starting a drag on a draggable component
const onDragStart = e => { const onDragStart = e => {
const parent = e.target.closest("[data-type='component']") const parent = e.target.closest(".component")
const child = getDOMNodeForComponent(e.target) if (!parent?.classList.contains("draggable")) {
if (!parent?.dataset?.id || !child) {
return return
} }
@ -31,7 +30,10 @@
builderStore.actions.setDragging(true) builderStore.actions.setDragging(true)
// Highlight being dragged by setting opacity // Highlight being dragged by setting opacity
child.style.opacity = "0.5" const child = getDOMNodeForComponent(e.target)
if (child) {
child.style.opacity = "0.5"
}
} }
// Callback when drag stops (whether dropped or not) // Callback when drag stops (whether dropped or not)
@ -102,10 +104,10 @@
return return
} }
const element = e.target.closest("[data-type='component']") const element = e.target.closest(".component")
if ( if (
element && element &&
element.dataset.droppable === "true" && element.classList.contains("droppable") &&
element.dataset.id !== dragInfo.target element.dataset.id !== dragInfo.target
) { ) {
// Do nothing if this is the same target // Do nothing if this is the same target
@ -130,7 +132,7 @@
dropInfo = { dropInfo = {
target, target,
name: element.dataset.name, name: element.dataset.name,
droppableInside: element.dataset.droppableInside === "true", droppableInside: element.classList.contains("empty"),
bounds, bounds,
} }
} else { } else {

View file

@ -7,7 +7,7 @@
$: zIndex = componentId === $builderStore.selectedComponentId ? 900 : 920 $: zIndex = componentId === $builderStore.selectedComponentId ? 900 : 920
const onMouseOver = e => { const onMouseOver = e => {
const element = e.target.closest("[data-type='component']") const element = e.target.closest(".interactive.component")
const newId = element?.dataset?.id const newId = element?.dataset?.id
if (newId !== componentId) { if (newId !== componentId) {
componentId = newId componentId = newId

View file

@ -24,8 +24,8 @@ export const styleable = (node, styles = {}) => {
let selectComponent let selectComponent
// Allow dragging if required // Allow dragging if required
const parent = node.closest("[data-type='component']") const parent = node.closest(".component")
if (parent && parent.dataset.draggable === "true") { if (parent && parent.classList.contains("draggable")) {
node.setAttribute("draggable", true) node.setAttribute("draggable", true)
} }