@ -72,13 +72,18 @@
$: inSelectedPath = $builderStore.selectedComponentPath?.includes(id)
$: inSelectedPath = $builderStore.selectedComponentPath?.includes(id)
$: inDragPath = inSelectedPath & & $builderStore.editMode
$: inDragPath = inSelectedPath & & $builderStore.editMode
// Derive definition properties which can all be optional, so need to be
// coerced to booleans
$: editable = !!definition?.editable
$: hasChildren = !!definition?.hasChildren
$: showEmptyState = !!definition?.showEmptyState
// Interactive components can be selected, dragged and highlighted inside
// Interactive components can be selected, dragged and highlighted inside
// the builder preview
// the builder preview
$: interactive =
$: interactive =
$builderStore.inBuilder & &
$builderStore.inBuilder & &
($builderStore.previewType === "layout" || insideScreenslot) & &
($builderStore.previewType === "layout" || insideScreenslot) & &
!isBlock
!isBlock
$: editable = definition?.editable
$: editing = editable & & selected & & $builderStore.editMode
$: editing = editable & & selected & & $builderStore.editMode
$: draggable = !inDragPath & & interactive & & !isLayout & & !isScreen
$: draggable = !inDragPath & & interactive & & !isLayout & & !isScreen
$: droppable = interactive & & !isLayout & & !isScreen
$: droppable = interactive & & !isLayout & & !isScreen
@ -86,8 +91,8 @@
// Empty components are those which accept children but do not have any.
// Empty components are those which accept children but do not have any.
// Empty states can be shown for these components, but can be disabled
// Empty states can be shown for these components, but can be disabled
// in the component manifest.
// in the component manifest.
$: empty = interactive & & !children.length & & definition?. hasChildren
$: empty = interactive & & !children.length & & hasChildren
$: emptyState = empty & & definition?. showEmptyState !== false
$: emptyState = empty & & showEmptyState
// Raw settings are all settings excluding internal props and children
// Raw settings are all settings excluding internal props and children
$: rawSettings = getRawSettings(instance)
$: rawSettings = getRawSettings(instance)
@ -103,6 +108,9 @@
// Build up the final settings object to be passed to the component
// Build up the final settings object to be passed to the component
$: cacheSettings(enrichedSettings, nestedSettings, conditionalSettings)
$: cacheSettings(enrichedSettings, nestedSettings, conditionalSettings)
// Render key is used to determine when components need to fully remount
$: renderKey = getRenderKey(id, editing)
// Update component context
// Update component context
$: componentStore.set({
$: componentStore.set({
id,
id,
@ -268,35 +276,43 @@
})
})
}
}
}
}
// Generates a key used to determine when components need to fully remount.
// Currently only toggling editing requires remounting.
const getRenderKey = (id, editing) => {
return hashString(`${ id } -${ editing } `)
}
< / script >
< / script >
{ #if constructor && cachedSettings && ( visible || inSelectedPath )}
{ #key renderKey }
<!-- The ID is used as a class because getElementsByClassName is O(1) -->
{ #if constructor && cachedSettings && ( visible || inSelectedPath )}
<!-- and the performance matters for the selection indicators -->
<!-- The ID is used as a class because getElementsByClassName is O(1) -->
< div
<!-- and the performance matters for the selection indicators -->
class={ `component ${ id } ` }
< div
class:draggable
class={ `component ${ id } ` }
class:droppable
class:draggable
class:empty
class:droppable
class:interactive
class:empty
class:editing
class:interactive
class:block={ isBlock }
class:editing
data-id={ id }
class:block={ isBlock }
data-name={ name }
data-id={ id }
>
data-name={ name }
< svelte:component this = { constructor } {... cachedSettings } >
>
{ #if children . length }
< svelte:component this = { constructor } {... cachedSettings } >
{ #each children as child ( child . _id )}
{ #if children . length }
< svelte:self instance = { child } / >
{ #each children as child ( child . _id )}
{ /each }
< svelte:self instance = { child } / >
{ :else if emptyState }
{ /each }
< Placeholder / >
{ :else if emptyState }
{ :else if isBlock }
< Placeholder / >
< slot / >
{ :else if isBlock }
{ /if }
< slot / >
< / svelte:component >
{ /if }
< / div >
< / svelte:component >
{ /if }
< / div >
{ /if }
{ /key }
< style >
< style >
.component {
.component {