87 lines
2.2 KiB
Vue
87 lines
2.2 KiB
Vue
<template>
|
|
<div class="space-y-6">
|
|
<StructureNodeEditor
|
|
:node="localStructure"
|
|
:depth="0"
|
|
:component-types="availableComponentTypes"
|
|
:piece-types="availablePieceTypes"
|
|
is-root
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { reactive, watch, computed, onMounted } from 'vue'
|
|
import StructureNodeEditor from '~/components/StructureNodeEditor.vue'
|
|
import {
|
|
defaultStructure,
|
|
hydrateStructureForEditor,
|
|
cloneStructure,
|
|
} from '~/shared/modelUtils'
|
|
import { usePieceTypes } from '~/composables/usePieceTypes'
|
|
import { useComponentTypes } from '~/composables/useComponentTypes'
|
|
|
|
defineOptions({ name: 'ComponentModelStructureEditor' })
|
|
|
|
const props = defineProps({
|
|
modelValue: {
|
|
type: Object,
|
|
default: () => defaultStructure(),
|
|
},
|
|
})
|
|
|
|
const emit = defineEmits(['update:modelValue'])
|
|
|
|
const localStructure = reactive(hydrateStructureForEditor(props.modelValue))
|
|
|
|
const syncFromProps = (value: any) => {
|
|
const hydrated = hydrateStructureForEditor(value)
|
|
localStructure.customFields = hydrated.customFields
|
|
localStructure.pieces = hydrated.pieces
|
|
localStructure.subComponents = hydrated.subComponents
|
|
lastEmitted = JSON.stringify(cloneStructure(value))
|
|
}
|
|
|
|
watch(
|
|
() => props.modelValue,
|
|
(value) => {
|
|
syncFromProps(value)
|
|
},
|
|
{ deep: true }
|
|
)
|
|
|
|
let lastEmitted = JSON.stringify(cloneStructure(props.modelValue))
|
|
|
|
watch(
|
|
localStructure,
|
|
(value) => {
|
|
const payload = cloneStructure(value)
|
|
const serialized = JSON.stringify(payload)
|
|
if (serialized !== lastEmitted) {
|
|
lastEmitted = serialized
|
|
emit('update:modelValue', payload)
|
|
}
|
|
},
|
|
{ deep: true }
|
|
)
|
|
|
|
const { pieceTypes, loadPieceTypes } = usePieceTypes()
|
|
const { componentTypes, loadComponentTypes } = useComponentTypes()
|
|
|
|
const availablePieceTypes = computed(() => pieceTypes.value ?? [])
|
|
const availableComponentTypes = computed(() => componentTypes.value ?? [])
|
|
|
|
onMounted(async () => {
|
|
const loaders: Promise<any>[] = []
|
|
if (!availablePieceTypes.value.length) {
|
|
loaders.push(loadPieceTypes())
|
|
}
|
|
if (!availableComponentTypes.value.length) {
|
|
loaders.push(loadComponentTypes())
|
|
}
|
|
if (loaders.length) {
|
|
await Promise.allSettled(loaders)
|
|
}
|
|
})
|
|
</script>
|