2021-11-02 09:45:27 +01:00
|
|
|
<script>
|
2022-08-23 20:05:38 +02:00
|
|
|
import { getContext, onDestroy, onMount, setContext } from "svelte"
|
|
|
|
import { builderStore } from "stores/builder.js"
|
|
|
|
import { blockStore } from "stores/blocks.js"
|
2021-11-02 09:45:27 +01:00
|
|
|
|
|
|
|
const component = getContext("component")
|
2022-08-24 10:05:08 +02:00
|
|
|
const { styleable } = getContext("sdk")
|
2021-11-02 09:45:27 +01:00
|
|
|
|
2022-06-30 20:31:25 +02:00
|
|
|
let structureLookupMap = {}
|
2022-08-23 16:53:28 +02:00
|
|
|
|
2022-06-30 20:31:25 +02:00
|
|
|
const registerBlockComponent = (id, order, parentId, instance) => {
|
|
|
|
// Ensure child array exists
|
|
|
|
if (!structureLookupMap[parentId]) {
|
2022-08-24 09:21:57 +02:00
|
|
|
structureLookupMap[parentId] = {}
|
2022-06-30 20:31:25 +02:00
|
|
|
}
|
2022-08-24 09:21:57 +02:00
|
|
|
// Add this instance in this order, overwriting any existing instance in
|
|
|
|
// this order in case of repeaters
|
|
|
|
structureLookupMap[parentId][order] = instance
|
2022-06-30 20:31:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
const eject = () => {
|
2022-08-24 10:05:08 +02:00
|
|
|
// Start the new structure with the root component
|
2022-08-24 09:21:57 +02:00
|
|
|
let definition = structureLookupMap[$component.id][0]
|
2022-08-24 10:05:08 +02:00
|
|
|
|
|
|
|
// Copy styles from block to root component
|
|
|
|
definition._styles = {
|
|
|
|
...definition._styles,
|
|
|
|
normal: {
|
|
|
|
...definition._styles?.normal,
|
|
|
|
...$component.styles?.normal,
|
|
|
|
},
|
|
|
|
custom:
|
|
|
|
definition._styles?.custom || "" + $component.styles?.custom || "",
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create component tree
|
2022-06-30 20:31:25 +02:00
|
|
|
attachChildren(definition, structureLookupMap)
|
|
|
|
builderStore.actions.ejectBlock($component.id, definition)
|
|
|
|
}
|
|
|
|
|
|
|
|
const attachChildren = (rootComponent, map) => {
|
2022-08-24 09:21:57 +02:00
|
|
|
// Transform map into children array
|
2022-06-30 20:31:25 +02:00
|
|
|
let id = rootComponent._id
|
2022-08-24 09:21:57 +02:00
|
|
|
const children = Object.entries(map[id] || {}).map(([order, instance]) => ({
|
|
|
|
order,
|
|
|
|
instance,
|
|
|
|
}))
|
|
|
|
if (!children.length) {
|
2022-06-30 20:31:25 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// Sort children by order
|
2022-08-24 09:21:57 +02:00
|
|
|
children.sort((a, b) => (a.order < b.order ? -1 : 1))
|
2022-06-30 20:31:25 +02:00
|
|
|
|
|
|
|
// Attach all children of this component
|
2022-08-24 09:21:57 +02:00
|
|
|
rootComponent._children = children.map(x => x.instance)
|
2022-06-30 20:31:25 +02:00
|
|
|
|
|
|
|
// Recurse for each child
|
|
|
|
rootComponent._children.forEach(child => {
|
|
|
|
attachChildren(child, map)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
setContext("block", {
|
|
|
|
// We need to set a block context to know we're inside a block, but also
|
|
|
|
// to be able to reference the actual component ID of the block from
|
|
|
|
// any depth
|
|
|
|
id: $component.id,
|
|
|
|
|
2022-10-14 20:13:44 +02:00
|
|
|
// Name can be used down the tree in placeholders
|
|
|
|
name: $component.name,
|
|
|
|
|
2022-06-30 20:31:25 +02:00
|
|
|
// We register block components with their raw props so that we can eject
|
|
|
|
// blocks later on
|
|
|
|
registerComponent: registerBlockComponent,
|
|
|
|
})
|
2022-08-23 20:05:38 +02:00
|
|
|
|
|
|
|
onMount(() => {
|
2022-08-24 09:21:57 +02:00
|
|
|
// We register and unregister blocks to the block store when inside the
|
|
|
|
// builder preview to allow for block ejection
|
2022-08-23 20:05:38 +02:00
|
|
|
if ($builderStore.inBuilder) {
|
|
|
|
blockStore.actions.registerBlock($component.id, { eject })
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
|
|
|
onDestroy(() => {
|
|
|
|
if ($builderStore.inBuilder) {
|
|
|
|
blockStore.actions.unregisterBlock($component.id)
|
|
|
|
}
|
|
|
|
})
|
2021-11-02 09:45:27 +01:00
|
|
|
</script>
|
|
|
|
|
2022-08-24 10:05:08 +02:00
|
|
|
<div use:styleable={$component.styles}>
|
|
|
|
<slot />
|
|
|
|
</div>
|