@webx-ui/module-blocks 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/api.ts","../src/BlockChecks.vue","../src/BlockHistory.vue","../src/frame.ts","../src/BlockStage.vue","../src/content.ts","../src/messages.ts","../src/i18n.ts","../src/lint.ts","../src/schema.ts","../src/BlockEditorPage.vue","../src/BlockThumb.vue","../src/BlockPicker.vue","../src/BlocksPreview.vue","../src/BlocksTree.vue","../src/preview.ts","../src/BlocksField.vue","../src/BlockCard.vue","../src/BlockCreateDialog.vue","../src/BlocksPage.vue","../src/module.ts"],"sourcesContent":["import type { AdminContext } from '@webx-ui/module-admin'\nimport type {\n BlockInput,\n BlockType,\n BlockUsage,\n BlockVersion,\n BlockVersionMeta,\n RenderInput,\n RenderResult,\n} from './types'\n\nexport interface BlocksApi {\n /** Every type, without content: the section's list. */\n list(): Promise<BlockType[]>\n /** The published types with their content: what the constructor and the picker read. */\n catalog(): Promise<BlockType[]>\n get(id: number): Promise<BlockType>\n create(input: BlockInput): Promise<BlockType>\n update(id: number, input: BlockInput): Promise<BlockType>\n remove(id: number): Promise<void>\n publish(id: number): Promise<BlockType>\n render(id: number, input?: RenderInput): Promise<RenderResult>\n usage(id: number): Promise<BlockUsage[]>\n versions(id: number): Promise<BlockVersionMeta[]>\n version(id: number, number: number): Promise<BlockVersion>\n restore(id: number, number: number): Promise<BlockType>\n}\n\n/** Everything under `/blocks`, below the panel's API path. */\nexport function createBlocksApi(admin: AdminContext): BlocksApi {\n const base = `${admin.apiPath}/blocks`\n const data = <T>(body: { data: T }): T => body.data\n\n return {\n list: () => admin.http.get<{ data: BlockType[] }>(base).then(data),\n catalog: () => admin.http.get<{ data: BlockType[] }>(`${base}/catalog`).then(data),\n get: (id) => admin.http.get<{ data: BlockType }>(`${base}/${id}`).then(data),\n create: (input) => admin.http.post<{ data: BlockType }>(base, input).then(data),\n update: (id, input) => admin.http.put<{ data: BlockType }>(`${base}/${id}`, input).then(data),\n remove: (id) => admin.http.delete<void>(`${base}/${id}`),\n publish: (id) => admin.http.post<{ data: BlockType }>(`${base}/${id}/publish`, {}).then(data),\n render: (id, input = {}) =>\n admin.http.post<{ data: RenderResult }>(`${base}/${id}/render`, input).then(data),\n usage: (id) => admin.http.get<{ data: BlockUsage[] }>(`${base}/${id}/usage`).then(data),\n versions: (id) =>\n admin.http.get<{ data: BlockVersionMeta[] }>(`${base}/${id}/versions`).then(data),\n version: (id, number) =>\n admin.http.get<{ data: BlockVersion }>(`${base}/${id}/versions/${number}`).then(data),\n restore: (id, number) =>\n admin.http\n .post<{ data: BlockType }>(`${base}/${id}/versions/${number}/restore`, {})\n .then(data),\n }\n}\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { WxIcon } from '@webx-ui/core'\nimport type { Lint } from './types'\n\n/**\n * The strip under an editor: what was noticed, and what was not — a green line for every\n * check that passed, so that silence reads as \"checked\" rather than \"not looked at\".\n */\nconst props = defineProps<{\n /** Which editor this strip sits under. */\n file: 'template' | 'styles' | 'script' | 'schema'\n lints: Lint[]\n slug: string\n /** A refusal from publishing, shown first and in red. */\n error?: { message: string; line: number | null; where?: string | null } | null\n}>()\n\nconst t = useTranslate('webx-blocks')\n\nconst mine = computed(() => props.lints.filter((lint) => lint.file === props.file))\n\nconst passed = computed(() => {\n const codes = new Set(mine.value.map((lint) => lint.code))\n const lines: string[] = []\n\n if (props.file === 'template') {\n if (!codes.has('no-marker')) lines.push(t('checks.ok-marker'))\n if (!codes.has('variables-missing')) lines.push(t('checks.ok-variables'))\n }\n\n if (props.file === 'styles') {\n if (!codes.has('stray-selectors')) lines.push(t('checks.ok-prefix', { slug: props.slug }))\n if (!codes.has('bare-selectors')) lines.push(t('checks.ok-bare'))\n if (!codes.has('media-query')) lines.push(t('checks.ok-container'))\n }\n\n return lines\n})\n</script>\n\n<template>\n <div class=\"wx-block-checks\">\n <div v-if=\"error\" class=\"wx-block-checks__line is-error\">\n <wx-icon name=\"close-circle\" />\n <span>\n {{ error.message }}\n <template v-if=\"error.line !== null\">\n · {{ t('page.line', { line: error.line }) }}</template\n >\n <template v-if=\"error.where\"> · {{ error.where }}</template>\n </span>\n </div>\n <div v-for=\"lint in mine\" :key=\"lint.code\" class=\"wx-block-checks__line is-warning\">\n <wx-icon name=\"warning\" />\n <span>\n {{ lint.message }}\n <template v-if=\"lint.line !== null\"> · {{ t('page.line', { line: lint.line }) }}</template>\n </span>\n </div>\n <div v-for=\"line in passed\" :key=\"line\" class=\"wx-block-checks__line is-ok\">\n <wx-icon name=\"check\" />\n <span>{{ line }}</span>\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-block-checks {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-4);\n padding: var(--wx-space-8) var(--wx-space-12);\n font-size: var(--wx-font-size-sm);\n border-block-start: 1px solid var(--wx-color-border-muted, var(--wx-border-default));\n}\n\n.wx-block-checks__line {\n display: flex;\n gap: var(--wx-space-8);\n align-items: flex-start;\n}\n\n.wx-block-checks__line .wx-icon {\n flex: none;\n margin-block-start: 2px;\n}\n\n.is-ok {\n color: var(--wx-text-muted);\n}\n\n.is-ok .wx-icon {\n color: var(--wx-color-success);\n}\n\n.is-warning {\n color: var(--wx-color-warning-text, var(--wx-color-warning));\n}\n\n.is-error {\n color: var(--wx-color-danger-text, var(--wx-color-danger));\n}\n</style>\n","<script setup lang=\"ts\">\nimport { onMounted, ref, watch } from 'vue'\nimport { useAdmin, useTranslate } from '@webx-ui/module-admin'\nimport { confirm, toast, WxBadge, WxButton, WxSkeleton, WxText } from '@webx-ui/core'\nimport { createBlocksApi } from './api'\nimport type { BlockType, BlockVersionMeta } from './types'\n\n/**\n * A version per save, newest first, each with who and why. Restoring makes the old version a\n * new draft — publishing it is the same separate step it always is.\n */\nconst props = defineProps<{ block: BlockType; canManage: boolean }>()\n\nconst emit = defineEmits<{ restored: [block: BlockType] }>()\n\nconst context = useAdmin()\nconst api = createBlocksApi(context)\nconst t = useTranslate('webx-blocks')\n\nconst versions = ref<BlockVersionMeta[] | null>(null)\n\nasync function load(): Promise<void> {\n versions.value = await api.versions(props.block.id)\n}\n\nfunction state(version: BlockVersionMeta): 'draft' | 'live' | 'replaced' {\n if (props.block.draft?.number === version.number) return 'draft'\n if (props.block.published?.number === version.number) return 'live'\n\n return 'replaced'\n}\n\nfunction when(version: BlockVersionMeta): string {\n if (!version.created_at) return ''\n\n return new Date(version.created_at).toLocaleString(context.i18n.state.locale)\n}\n\nasync function restore(version: BlockVersionMeta): Promise<void> {\n const agreed = await confirm({\n title: t('page.restore-title', { number: version.number }),\n message: t('page.restore-text'),\n confirmText: t('page.restore'),\n cancelText: t('page.cancel'),\n })\n\n if (!agreed) return\n\n try {\n const block = await api.restore(props.block.id, version.number)\n toast.success(t('page.restored', { number: block.draft?.number ?? version.number }))\n emit('restored', block)\n await load()\n } catch (error) {\n toast.danger((error as { body?: { message?: string } }).body?.message ?? String(error))\n }\n}\n\nonMounted(load)\nwatch(\n () => [props.block.draft?.number, props.block.published?.number],\n () => void load(),\n)\n</script>\n\n<template>\n <div class=\"wx-block-history\">\n <wx-skeleton v-if=\"versions === null\" :rows=\"3\" />\n <div v-for=\"version in versions\" v-else :key=\"version.number\" class=\"wx-block-history__row\">\n <code class=\"wx-block-history__number\">{{\n t('page.version', { number: version.number })\n }}</code>\n <div class=\"wx-block-history__who\">\n <wx-text>{{ t(`page.version-${state(version)}`) }}</wx-text>\n <wx-text size=\"sm\" tone=\"muted\">\n {{ when(version) }}\n · {{ version.author ?? t(`page.source-${version.source}`) }}\n <template v-if=\"version.comment\"> · {{ version.comment }}</template>\n </wx-text>\n </div>\n <wx-badge v-if=\"state(version) === 'draft'\" type=\"warning\" dot>{{\n t('page.version-draft')\n }}</wx-badge>\n <wx-badge v-else-if=\"state(version) === 'live'\" type=\"success\" dot>{{\n t('page.version-live')\n }}</wx-badge>\n <wx-button\n v-if=\"canManage && state(version) === 'replaced'\"\n size=\"sm\"\n variant=\"outline\"\n @click=\"restore(version)\"\n >\n {{ t('page.restore') }}\n </wx-button>\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-block-history {\n display: flex;\n flex-direction: column;\n}\n\n.wx-block-history__row {\n display: flex;\n align-items: center;\n gap: var(--wx-space-12);\n padding: var(--wx-space-10) var(--wx-space-12);\n border-block-end: 1px solid var(--wx-color-border-muted, var(--wx-border-default));\n flex-wrap: wrap;\n}\n\n.wx-block-history__row:last-child {\n border-block-end: 0;\n}\n\n.wx-block-history__number {\n width: 40px;\n font-family: var(--wx-font-family-mono);\n font-size: var(--wx-font-size-sm);\n color: var(--wx-text-muted);\n}\n\n.wx-block-history__who {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-width: 160px;\n}\n</style>\n","/**\n * The preview is a page of the site in an iframe, and the panel's hold on it is a pair of\n * comments around every block — `<!--wx:key-->…<!--/wx:key-->` — printed by the renderer in\n * preview mode. Finding a block is walking the comments; replacing one is swapping what sits\n * between the pair; highlighting one is a class on the first element after the opener.\n *\n * The panel and the site are one application on one domain, so the frame's document is\n * reachable and nothing has to be injected into the site's markup beyond one stylesheet.\n */\n\nexport const SELECTED_CLASS = 'wx-preview-selected'\n\nconst STYLE_ID = 'wx-preview-style'\n\nexport interface MarkerRange {\n start: Comment\n end: Comment\n}\n\n/** The pair of markers around a block, or null when the page does not hold it. */\nexport function findRange(root: Node, key: string): MarkerRange | null {\n const doc = root.ownerDocument ?? (root as Document)\n const walker = doc.createTreeWalker(root, 128 /* NodeFilter.SHOW_COMMENT */)\n let start: Comment | null = null\n\n for (let node = walker.nextNode(); node; node = walker.nextNode()) {\n const text = (node as Comment).data.trim()\n\n if (start === null && text === `wx:${key}`) {\n start = node as Comment\n } else if (start !== null && text === `/wx:${key}`) {\n return { start, end: node as Comment }\n }\n }\n\n return null\n}\n\n/**\n * Swap the block's markup — markers included, since the new HTML carries its own — and let\n * the runtime mount whatever script the new markup needs. False when the key is not on the\n * page, which means the page has to be reloaded rather than patched.\n */\nexport function replaceBlock(doc: Document, key: string, html: string): boolean {\n const range = findRange(doc, key)\n\n if (!range) return false\n\n const parent = range.start.parentNode\n\n if (!parent) return false\n\n const template = doc.createElement('template')\n template.innerHTML = html\n\n // What follows the block stays where it is; the new markup lands in front of it.\n const anchor = range.end.nextSibling\n let node: Node | null = range.start\n\n while (node) {\n const next: Node | null = node.nextSibling\n const done = node === range.end\n parent.removeChild(node)\n if (done) break\n node = next\n }\n\n const fragment = template.content\n const inserted = Array.from(fragment.childNodes)\n parent.insertBefore(fragment, anchor)\n\n const runtime = (doc.defaultView as (Window & { webx?: { mount?: (root: Node) => void } }) | null)\n ?.webx\n\n if (runtime?.mount) {\n for (const child of inserted) {\n if (child.nodeType === 1) runtime.mount(child)\n }\n }\n\n return true\n}\n\n/** The first element a block prints — where a highlight goes. */\nexport function blockElement(root: Node, key: string): Element | null {\n const range = findRange(root, key)\n\n if (!range) return null\n\n for (let node = range.start.nextSibling; node && node !== range.end; node = node.nextSibling) {\n if (node.nodeType === 1) return node as Element\n }\n\n return null\n}\n\n/** Mark one block as the selected one, and nothing else. Null clears the selection. */\nexport function highlightBlock(doc: Document, key: string | null): Element | null {\n ensureStyle(doc)\n\n for (const element of Array.from(doc.querySelectorAll(`.${SELECTED_CLASS}`))) {\n element.classList.remove(SELECTED_CLASS)\n }\n\n if (key === null) return null\n\n const element = blockElement(doc, key)\n element?.classList.add(SELECTED_CLASS)\n\n return element\n}\n\n/** The one thing the panel adds to the site's markup: how a selected block looks. */\nfunction ensureStyle(doc: Document): void {\n if (doc.getElementById(STYLE_ID)) return\n\n const style = doc.createElement('style')\n style.id = STYLE_ID\n style.textContent = `.${SELECTED_CLASS}{outline:2px solid #427edd;outline-offset:-2px;}`\n ;(doc.head ?? doc.documentElement).appendChild(style)\n}\n\nexport interface StageInput {\n html: string\n styles: string\n /** The script wrapped for the runtime, or nothing. */\n script?: string | null\n /** Where the runtime is served; skipped when there is no script to run. */\n runtime?: string | null\n /** Resolves relative addresses the block prints — images, links — against the site. */\n base?: string | null\n /** Styles the site's layout would give the page: fonts, the ground colour. */\n frame?: string | null\n}\n\n/**\n * A whole document for the editor's stage: the block on its own, with its styles, its script\n * and the runtime, and nothing of the panel. `srcdoc` takes it.\n */\nexport function stageDocument(input: StageInput): string {\n const base = input.base ? `<base href=\"${escapeAttribute(input.base)}\">` : ''\n const frame = input.frame ? `<style>${input.frame}</style>` : ''\n const runtime =\n input.script && input.runtime\n ? `<script src=\"${escapeAttribute(input.runtime)}\"></script><script>${input.script}</script>`\n : ''\n\n return (\n `<!doctype html><html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">${base}` +\n `<style>html,body{margin:0}body{container-type:inline-size}</style>${frame}<style>${input.styles}</style></head>` +\n `<body>${input.html}${runtime}</body></html>`\n )\n}\n\nfunction escapeAttribute(value: string): string {\n return value.replace(/&/g, '&amp;').replace(/\"/g, '&quot;').replace(/</g, '&lt;')\n}\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { useElementWidth, WxSegmented, WxSkeleton } from '@webx-ui/core'\nimport { stageDocument } from './frame'\n\n/**\n * The block on its own, at a chosen width: a desktop scaled down to fit the column, a tablet\n * or a phone at one to one. The document is the block, its styles, its script and the\n * runtime, and nothing of the panel — an iframe, so the block's CSS stays the block's.\n */\nconst props = withDefaults(\n defineProps<{\n html: string\n styles: string\n script?: string | null\n runtime?: string | null\n loading?: boolean\n }>(),\n { script: null, runtime: null, loading: false },\n)\n\nconst t = useTranslate('webx-blocks')\n\nconst widths = computed(() => [\n { value: 1280, label: t('page.width-desktop') },\n { value: 834, label: t('page.width-tablet') },\n { value: 390, label: t('page.width-phone') },\n])\n\nconst width = ref<number>(1280)\nconst box = ref<HTMLElement | null>(null)\nconst frame = ref<HTMLIFrameElement | null>(null)\nconst boxWidth = useElementWidth(box)\nconst contentHeight = ref(360)\n\nconst scale = computed(() => {\n if (boxWidth.value === 0) return 1\n\n return Math.min(1, boxWidth.value / width.value)\n})\n\nconst srcdoc = computed(() =>\n stageDocument({\n html: props.html,\n styles: props.styles,\n script: props.script,\n runtime: props.runtime,\n base: typeof location === 'undefined' ? null : location.origin + '/',\n }),\n)\n\n/** The frame grows to its content: a stage that scrolls inside itself hides half the block. */\nfunction measure(): void {\n const doc = frame.value?.contentDocument\n\n if (!doc?.documentElement) return\n\n contentHeight.value = Math.max(120, doc.documentElement.scrollHeight)\n}\n\nfunction onLoad(): void {\n measure()\n // Fonts and images arrive after `load` of the document itself.\n setTimeout(measure, 300)\n}\n\nwatch(width, () => setTimeout(measure, 50))\n\nconst frameStyle = computed(() => ({\n width: `${width.value}px`,\n height: `${contentHeight.value}px`,\n transform: `scale(${scale.value})`,\n}))\n\nconst clipStyle = computed(() => ({\n width: `${Math.round(width.value * scale.value)}px`,\n height: `${Math.round(contentHeight.value * scale.value)}px`,\n}))\n</script>\n\n<template>\n <div class=\"wx-block-stage\">\n <div class=\"wx-block-stage__bar\">\n <wx-segmented v-model=\"width\" :options=\"widths\" size=\"sm\" />\n </div>\n <div ref=\"box\" class=\"wx-block-stage__ground\">\n <wx-skeleton v-if=\"loading && !html\" :rows=\"3\" />\n <div v-else class=\"wx-block-stage__clip\" :style=\"clipStyle\">\n <iframe\n ref=\"frame\"\n class=\"wx-block-stage__frame\"\n :srcdoc=\"srcdoc\"\n :style=\"frameStyle\"\n sandbox=\"allow-same-origin allow-scripts\"\n :title=\"t('page.preview')\"\n @load=\"onLoad\"\n />\n </div>\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-block-stage {\n display: flex;\n flex-direction: column;\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n background: var(--wx-bg-surface);\n overflow: hidden;\n}\n\n.wx-block-stage__bar {\n display: flex;\n justify-content: space-between;\n gap: var(--wx-space-8);\n padding: var(--wx-space-8) var(--wx-space-12);\n border-block-end: 1px solid var(--wx-color-border-muted, var(--wx-border-default));\n}\n\n.wx-block-stage__ground {\n padding: var(--wx-space-12);\n background: var(--wx-bg-subtle);\n overflow: auto;\n max-height: 62vh;\n}\n\n.wx-block-stage__clip {\n overflow: hidden;\n margin-inline: auto;\n box-shadow: var(--wx-shadow-sm);\n}\n\n.wx-block-stage__frame {\n display: block;\n border: 0;\n background: #fff;\n transform-origin: top left;\n}\n</style>\n","import type { ScreenNode } from '@webx-ui/schema'\nimport type { BlockNode } from './types'\n\n/**\n * Walking and rewriting a tree of blocks.\n *\n * A node is `{ key, type, values }`, and a value that is itself a list of such nodes is a\n * nested constructor — recognised by shape rather than by schema, so a tree can be walked\n * for a type nobody can look up any more. Every rewrite returns a new tree and leaves the\n * one it was given alone: the field's model is replaced, never mutated, which is what keeps\n * the renderer's `update` and the preview's swap in step.\n */\n\nexport function isNode(value: unknown): value is BlockNode {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as { type?: unknown }).type === 'string' &&\n (value as { type: string }).type !== ''\n )\n}\n\n/** A list of nodes — a nested constructor's value — as opposed to a list of anything else. */\nexport function isNodeList(value: unknown): value is BlockNode[] {\n return Array.isArray(value) && value.length > 0 && value.every(isNode)\n}\n\n/** An id that survives a drag: random, not positional. */\nexport function newKey(): string {\n const random =\n typeof crypto !== 'undefined' && 'randomUUID' in crypto\n ? crypto.randomUUID().replace(/-/g, '')\n : Math.random().toString(36).slice(2) + Math.random().toString(36).slice(2)\n\n return random.slice(0, 12)\n}\n\nexport function makeNode(type: string, values: Record<string, unknown> = {}): BlockNode {\n return { key: newKey(), type, values }\n}\n\n/** Where a node sits: the list it is in, its index there, and the field of the parent. */\nexport interface Located {\n node: BlockNode\n parent: BlockNode | null\n field: string | null\n list: BlockNode[]\n index: number\n}\n\nexport function locate(tree: BlockNode[], key: string): Located | null {\n return find(tree, key, null, null)\n}\n\nfunction find(\n list: BlockNode[],\n key: string,\n parent: BlockNode | null,\n field: string | null,\n): Located | null {\n for (let index = 0; index < list.length; index++) {\n const node = list[index]!\n\n if (node.key === key) return { node, parent, field, list, index }\n\n for (const [name, value] of Object.entries(node.values ?? {})) {\n if (isNodeList(value)) {\n const found = find(value, key, node, name)\n if (found) return found\n }\n }\n }\n\n return null\n}\n\n/** Every node, parents before children. */\nexport function walk(\n tree: BlockNode[],\n visit: (node: BlockNode, depth: number, parent: BlockNode | null) => void,\n depth = 0,\n parent: BlockNode | null = null,\n): void {\n for (const node of tree) {\n if (!isNode(node)) continue\n\n visit(node, depth, parent)\n\n for (const value of Object.values(node.values ?? {})) {\n if (isNodeList(value)) walk(value, visit, depth + 1, node)\n }\n }\n}\n\n/** How many instances of a type the tree holds, nested ones included. */\nexport function countType(tree: BlockNode[], slug: string): number {\n let count = 0\n walk(tree, (node) => {\n if (node.type === slug) count++\n })\n\n return count\n}\n\n/** The distinct types a tree uses, in first-seen order. */\nexport function typesIn(tree: BlockNode[]): string[] {\n const seen: string[] = []\n walk(tree, (node) => {\n if (!seen.includes(node.type)) seen.push(node.type)\n })\n\n return seen\n}\n\n/** The `wx-blocks` nodes of a schema, through cards and tabs. */\nexport function nestedFields(schema: ScreenNode[]): ScreenNode[] {\n const found: ScreenNode[] = []\n\n for (const node of schema) {\n if (node.type === 'wx-blocks') found.push(node)\n if (node.children) found.push(...nestedFields(node.children))\n }\n\n return found\n}\n\n/** A copy with fresh keys all the way down — what a duplicate is. */\nexport function cloneNode(node: BlockNode): BlockNode {\n const values: Record<string, unknown> = {}\n\n for (const [name, value] of Object.entries(node.values ?? {})) {\n values[name] = isNodeList(value) ? value.map(cloneNode) : clone(value)\n }\n\n return { key: newKey(), type: node.type, values }\n}\n\n/** The list a parent holds in a field, or the root when there is no parent. */\nfunction listAt(\n tree: BlockNode[],\n parentKey: string | null,\n field: string | null,\n): BlockNode[] | null {\n if (parentKey === null) return tree\n\n const parent = locate(tree, parentKey)\n if (!parent || field === null) return null\n\n const existing = parent.node.values[field]\n\n if (!Array.isArray(existing)) {\n parent.node.values[field] = []\n }\n\n return parent.node.values[field] as BlockNode[]\n}\n\nexport function insertNode(\n tree: BlockNode[],\n parentKey: string | null,\n field: string | null,\n index: number,\n node: BlockNode,\n): BlockNode[] {\n const next = clone(tree)\n const list = listAt(next, parentKey, field)\n\n if (!list) return tree\n\n list.splice(Math.max(0, Math.min(index, list.length)), 0, node)\n\n return next\n}\n\nexport function removeNode(tree: BlockNode[], key: string): BlockNode[] {\n const next = clone(tree)\n const found = locate(next, key)\n\n if (!found) return tree\n\n found.list.splice(found.index, 1)\n\n return next\n}\n\nexport function updateValues(\n tree: BlockNode[],\n key: string,\n values: Record<string, unknown>,\n): BlockNode[] {\n const next = clone(tree)\n const found = locate(next, key)\n\n if (!found) return tree\n\n found.node.values = values\n\n return next\n}\n\n/** The list under one parent replaced wholesale — what a sortable list hands back. */\nexport function replaceList(\n tree: BlockNode[],\n parentKey: string | null,\n field: string | null,\n list: BlockNode[],\n): BlockNode[] {\n if (parentKey === null) return clone(list)\n\n const next = clone(tree)\n const parent = locate(next, parentKey)\n\n if (!parent || field === null) return tree\n\n parent.node.values[field] = clone(list)\n\n return next\n}\n\n/** Values are JSON — that is the contract with the server — so a JSON round trip is a clone. */\nexport function clone<T>(value: T): T {\n return value === undefined ? value : (JSON.parse(JSON.stringify(value)) as T)\n}\n","import type { Messages } from '@webx-ui/module-admin'\n\n/**\n * The English this package speaks on its own, before the server's dictionary arrives, or\n * without one. The server ships the same lines in ten languages under `webx-blocks::` and\n * overrides these; `messages.test.ts` keeps the two sets of keys equal.\n */\nexport const blocksMessages: Record<string, Messages> = {\n module: {\n title: 'Blocks',\n },\n page: {\n blocks: 'Blocks',\n new: 'New block',\n search: 'Search by name or identifier',\n empty: 'No block types yet.',\n 'empty-help':\n 'A block type is made here entirely: its fields, its template, its styles and its script.',\n 'editing-off':\n 'Editing is switched off on this site: the types arrive by import, and the section is read-only.',\n 'on-pages': 'on :count pages',\n 'not-used': 'not used yet',\n draft: 'Draft v:number',\n live: 'Live v:number',\n 'never-published': 'Not published',\n hidden: 'Hidden from editors',\n\n identifier: 'Identifier',\n 'identifier-help':\n 'The type in the page content. Renaming it breaks every page the block stands on.',\n title: 'Name',\n description: 'Description',\n 'description-help': 'A hint for the editor, and the instruction an agent reads.',\n icon: 'Icon',\n group: 'Group',\n 'group-help': 'The section of the list an editor picks a block from.',\n allow: 'May hold',\n 'allow-help': 'Types that can be put inside. Empty — the block is not a container.',\n 'allowed-in': 'Allowed in',\n 'allowed-in-help': 'Types that may hold this one. Empty — anywhere, the page itself included.',\n root: 'The page itself',\n 'max-per-entity': 'Per page',\n 'max-per-entity-help': 'How many instances a page may hold. Empty — no limit.',\n sort: 'Order',\n 'sort-help': 'The order in the CSS cascade and in the list.',\n enabled: 'Offered to editors',\n 'enabled-help':\n 'Switched off, the block stays on the pages where it already is but cannot be added.',\n\n 'tab-template': 'Template',\n 'tab-styles': 'Styles',\n 'tab-script': 'Script',\n 'tab-fields': 'Fields',\n 'tab-settings': 'Settings',\n 'tab-history': 'History',\n 'insert-field': 'Insert a field:',\n 'script-help':\n 'The body of an initialiser: el is the root of one instance, values are its values. Called for every instance, and again for a block replaced in the preview.',\n provides: 'This site provides through webx.provide(): :names',\n 'provides-none': 'This site has not declared anything through webx.provide().',\n 'fields-help':\n 'Screen nodes, the same ones described screens are built from. The sample form on the right is built from them.',\n 'schema-invalid': 'The schema is not valid JSON: :error',\n sample: 'Sample values',\n 'sample-help': 'What the thumbnail is drawn on, and what the publish check runs on.',\n preview: 'Preview',\n 'width-desktop': 'Desktop',\n 'width-tablet': 'Tablet',\n 'width-phone': 'Phone',\n usage: 'Where it is used',\n 'usage-empty': 'Not on any page yet.',\n 'usage-more': 'and :count more',\n 'unpublished-page': 'draft',\n\n save: 'Save',\n saved: 'Saved as version :number.',\n unchanged: 'Nothing changed.',\n publish: 'Publish',\n 'publish-title': 'Publish version :number?',\n 'publish-text': 'The version takes effect on every page where the block stands: :count.',\n published: 'Version :number is live.',\n 'publish-failed': 'The version cannot be published.',\n 'failed-on': 'Fails on \":title\".',\n 'no-draft': 'There is no draft to publish.',\n failed: 'Some values were not accepted. Check the highlighted fields.',\n delete: 'Delete',\n 'delete-title': 'Delete \":title\"?',\n 'delete-text': 'Every version goes with it. This cannot be undone.',\n 'delete-used': 'The block stands on :count pages and cannot be deleted.',\n deleted: 'Deleted.',\n cancel: 'Cancel',\n create: 'Create',\n unsaved: 'Unsaved changes',\n back: 'Blocks',\n line: 'line :line',\n\n version: 'v:number',\n 'version-draft': 'Draft',\n 'version-live': 'Live',\n 'version-replaced': 'Replaced',\n restore: 'Restore',\n 'restore-title': 'Restore version :number?',\n 'restore-text': 'It becomes the draft; publishing it is a separate step.',\n restored: 'Version :number is the draft now.',\n 'restored-from': 'Restored from v:number',\n 'source-panel': 'panel',\n 'source-mcp': 'agent',\n 'source-import': 'import',\n },\n field: {\n blocks: 'Blocks',\n add: 'Add a block',\n 'add-inside': 'Add inside',\n done: 'Done',\n remove: 'Remove',\n 'remove-title': 'Remove \":title\"?',\n 'remove-text': 'The blocks inside it go with it.',\n duplicate: 'Duplicate',\n empty: 'No blocks yet. Add the first one.',\n 'nested-note': 'Nested blocks are edited in the tree on the left.',\n 'unknown-type': 'Unknown block type \":type\"',\n 'draft-type': 'The block type has an unpublished version',\n 'disabled-type': 'The block type is hidden from editors',\n\n pick: 'Add a block',\n search: 'Search by name or identifier',\n 'pick-empty': 'Nothing matches.',\n 'pick-none': 'There are no block types yet.',\n 'pick-none-link': 'Make one in the Blocks section.',\n 'pick-limited': 'Only these can go inside \":parent\": :types',\n 'pick-nothing-allowed': 'Nothing can be put inside \":parent\".',\n 'limit-reached': 'Already :count on this page, the limit for this block',\n\n preview: 'Preview',\n 'open-site': 'Open on the site',\n fullscreen: 'Full screen',\n close: 'Close',\n 'width-desktop': 'Desktop',\n 'width-tablet': 'Tablet',\n 'width-phone': 'Phone',\n },\n groups: {\n content: 'Content',\n layout: 'Layout',\n media: 'Media',\n },\n checks: {\n 'no-marker':\n 'No data-wx-block on the root: the script will not run, and the panel cannot highlight the block in the preview.',\n 'stray-selectors': 'Selectors outside the block prefix .b-:slug: :selectors',\n 'bare-selectors': 'Element selectors reach the whole site: :selectors',\n 'media-query': '@media measures the window. A block is sized by its container: use @container.',\n 'variables-missing':\n 'The template uses :variables, which the schema does not declare. Publishing will be refused.',\n 'ok-marker': 'The root carries data-wx-block.',\n 'ok-prefix': 'Every selector starts with .b-:slug.',\n 'ok-bare': 'No bare element selectors.',\n 'ok-container': 'Width is decided by container queries.',\n 'ok-variables': 'Every variable of the template is a field of the schema.',\n },\n}\n","import { useAdmin } from '@webx-ui/module-admin'\nimport { blocksMessages } from './messages'\n\nconst seeded = new WeakSet<object>()\n\n/** Puts this package's English under the panel's dictionary, once per panel. */\nexport function useBlocksMessages(): void {\n try {\n const { i18n } = useAdmin()\n\n if (!seeded.has(i18n)) {\n i18n.defaults('webx-blocks', blocksMessages)\n seeded.add(i18n)\n }\n } catch {\n // Outside a panel there is no dictionary to seed, and `useTranslate` falls back on its own.\n }\n}\n","import type { ScreenNode } from '@webx-ui/schema'\nimport type { Lint } from './types'\n\n/**\n * The checks under the editor, live (§15): the same four the server runs on saving, plus the\n * one that would refuse publication — a variable the schema does not declare. None locks a\n * save; every one is a habit that bites later, on another block or another page.\n *\n * Mirrors `Panel\\Lints` in the composer package, message for message.\n */\n\ntype Translate = (key: string, params?: Record<string, string | number>) => string\n\n/** Variables Blade or the renderer hand a template on their own. */\nconst GIVEN = ['block', 'entity', 'loop', '__env', 'errors', 'app']\n\nexport function lintBlock(\n slug: string,\n content: { template: string; styles: string; schema: ScreenNode[] },\n t: Translate,\n): Lint[] {\n const lints: Lint[] = []\n\n if (!/data-wx-block\\s*=/.test(content.template)) {\n lints.push({ file: 'template', code: 'no-marker', line: null, message: t('checks.no-marker') })\n }\n\n const missing = undeclared(content.template, content.schema)\n\n if (missing.length > 0) {\n lints.push({\n file: 'template',\n code: 'variables-missing',\n line: null,\n message: t('checks.variables-missing', {\n variables: missing.map((name) => `$${name}`).join(', '),\n }),\n })\n }\n\n const stray: [string, number][] = []\n const bare: [string, number][] = []\n const prefix = `.b-${slug}`\n\n for (const [selector, line] of selectors(content.styles)) {\n if (selector.startsWith(prefix) || selector.startsWith('&')) continue\n\n if (/^[a-z][a-z0-9-]*/i.test(selector)) bare.push([selector, line])\n else stray.push([selector, line])\n }\n\n if (stray.length > 0) {\n lints.push({\n file: 'styles',\n code: 'stray-selectors',\n line: stray[0]![1],\n message: t('checks.stray-selectors', { slug, selectors: few(stray) }),\n })\n }\n\n if (bare.length > 0) {\n lints.push({\n file: 'styles',\n code: 'bare-selectors',\n line: bare[0]![1],\n message: t('checks.bare-selectors', { selectors: few(bare) }),\n })\n }\n\n const source = withoutComments(content.styles)\n const media = /@media\\b/.exec(source)\n\n if (media) {\n lints.push({\n file: 'styles',\n code: 'media-query',\n line: lineAt(source, media.index),\n message: t('checks.media-query'),\n })\n }\n\n return lints\n}\n\n/** Every field id a schema declares, through its layout. */\nexport function fieldIds(schema: ScreenNode[]): string[] {\n const ids: string[] = []\n\n for (const node of schema) {\n if (node.id) ids.push(node.id)\n if (node.children) ids.push(...fieldIds(node.children))\n }\n\n return ids\n}\n\n/**\n * Variables the template reads that nothing declares: not the schema, not Blade's own, not\n * a `@foreach (… as $item)` or an `@php $x = …` in the template itself.\n */\nexport function undeclared(template: string, schema: ScreenNode[]): string[] {\n const declared = new Set([...fieldIds(schema), ...GIVEN])\n\n for (const match of template.matchAll(/\\bas\\s+\\$([a-zA-Z_]\\w*)(?:\\s*=>\\s*\\$([a-zA-Z_]\\w*))?/g)) {\n declared.add(match[1]!)\n if (match[2]) declared.add(match[2])\n }\n\n for (const match of template.matchAll(/\\$([a-zA-Z_]\\w*)\\s*(?:=[^=]|\\+\\+|--|\\.=|\\+=|-=)/g)) {\n declared.add(match[1]!)\n }\n\n const used: string[] = []\n\n for (const match of template.matchAll(/\\$([a-zA-Z_]\\w*)/g)) {\n const name = match[1]!\n if (!declared.has(name) && !used.includes(name)) used.push(name)\n }\n\n return used\n}\n\nfunction selectors(styles: string): [string, number][] {\n const source = withoutComments(styles)\n const found: [string, number][] = []\n\n for (const match of source.matchAll(/([^{};]+)\\{/g)) {\n const prelude = match[1]!\n const trimmed = prelude.trim()\n\n if (trimmed === '' || trimmed.startsWith('@')) continue\n\n for (const raw of prelude.split(',')) {\n const selector = raw.trim()\n\n if (selector === '' || selector === 'from' || selector === 'to' || selector.endsWith('%')) {\n continue\n }\n\n found.push([selector, lineAt(source, match.index + prelude.indexOf(selector))])\n }\n }\n\n return found\n}\n\n/** Comments replaced by spaces of the same length, so offsets and lines stay true. */\nfunction withoutComments(styles: string): string {\n return styles.replace(/\\/\\*[\\s\\S]*?\\*\\//g, (comment) => comment.replace(/[^\\n]/g, ' '))\n}\n\nfunction lineAt(source: string, offset: number): number {\n return source.slice(0, Math.max(0, offset)).split('\\n').length\n}\n\nfunction few(selectors: [string, number][]): string {\n const names = [...new Set(selectors.map(([selector]) => selector))]\n\n return names.slice(0, 3).join(', ') + (names.length > 3 ? ', …' : '')\n}\n","import type { ScreenNode } from '@webx-ui/schema'\n\n/**\n * A block's schema names a field by `id` alone — the id is the key in the values, and the\n * variable in the template. The renderer binds a field by `name`. So before a schema is\n * drawn as a form, every node without a name gets its id as one, layout nodes included: the\n * renderer only reads `name` on fields, and a name on a card is a name nobody looks at.\n */\nexport function formSchema(schema: ScreenNode[]): ScreenNode[] {\n return schema.map((node) => ({\n ...node,\n name: node.name ?? node.id,\n children: node.children ? formSchema(node.children) : node.children,\n }))\n}\n\n/**\n * Words for a group id. The dictionary may have one under `groups.<id>`; a site that added\n * a group of its own and no words for it sees the id, capitalised, which is honest.\n */\nexport function groupLabel(\n id: string,\n t: (key: string, params?: Record<string, string | number>) => string,\n): string {\n const key = `groups.${id}`\n const words = t(key)\n\n return words === key || words === `webx-blocks::${key}`\n ? id.charAt(0).toUpperCase() + id.slice(1)\n : words\n}\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, reactive, ref, watch } from 'vue'\nimport { useRoute, useRouter } from 'vue-router'\nimport { useAdmin, useTranslate } from '@webx-ui/module-admin'\nimport {\n confirm,\n toast,\n WxAlert,\n WxBadge,\n WxButton,\n WxCard,\n WxCodeEditor,\n WxFormItem,\n WxInput,\n WxInputNumber,\n WxSelect,\n WxSkeleton,\n WxSwitch,\n WxTab,\n WxTabs,\n WxTagsInput,\n WxText,\n WxTextarea,\n} from '@webx-ui/core'\nimport { WxScreenRenderer, type ScreenModel } from '@webx-ui/schema'\nimport { createBlocksApi } from './api'\nimport BlockChecks from './BlockChecks.vue'\nimport BlockHistory from './BlockHistory.vue'\nimport BlockStage from './BlockStage.vue'\nimport { clone } from './content'\nimport { useBlocksMessages } from './i18n'\nimport { lintBlock } from './lint'\nimport { formSchema, groupLabel } from './schema'\nimport type { BlockContent, BlocksMeta, BlockType, BlockUsage, PublishRefusal } from './types'\n\n/**\n * The editor of one type: two columns. On the left the four files and the settings, on the\n * right the block drawn on its sample, the sample's form built from the schema being edited,\n * and where the type stands. The loop is closed — edit the schema and the form rebuilds,\n * edit the values and the stage redraws, edit the template or the styles and so does it.\n */\nconst props = withDefaults(defineProps<{ base?: string }>(), { base: '/blocks' })\n\nconst context = useAdmin()\nconst api = createBlocksApi(context)\nconst route = useRoute()\nconst router = useRouter()\nuseBlocksMessages()\n\nconst t = useTranslate('webx-blocks')\n\nconst id = computed(() => Number(route.params.id))\n\nconst block = ref<BlockType | null>(null)\nconst usage = ref<BlockUsage[]>([])\nconst loading = ref(true)\nconst saving = ref(false)\nconst publishing = ref(false)\nconst tab = ref('template')\n\nconst meta = computed<BlocksMeta>(() => {\n const found = context.state.manifest?.modules.find((module) => module.id === 'blocks')?.meta\n\n return {\n groups: (found?.groups as string[] | undefined) ?? [],\n editing: (found?.editing as boolean | undefined) ?? true,\n provides: (found?.provides as string[] | undefined) ?? [],\n }\n})\n\nconst canManage = computed(() => context.can('blocks.manage') && meta.value.editing)\n\nconst settings = reactive({\n slug: '',\n title: '',\n description: '' as string | null,\n icon: '' as string | null,\n group: 'content',\n sort: 0,\n allow: [] as string[],\n allowed_in: [] as string[],\n max_per_entity: null as number | null,\n is_enabled: true,\n})\n\nconst content = reactive<BlockContent>({\n schema: [],\n template: '',\n styles: '',\n script: null,\n sample: {},\n})\n\n/** The schema as text, kept as typed: reformatting JSON under the caret moves the caret. */\nconst schemaText = ref('[]')\nconst schemaError = ref<string | null>(null)\n\nconst snapshot = ref('')\nconst errors = ref<Record<string, string[]>>({})\nconst refusal = ref<PublishRefusal | null>(null)\n\nconst stage = reactive({\n html: '',\n styles: '',\n script: null as string | null,\n runtime: null as string | null,\n loading: false,\n})\n\nconst current = computed(() => JSON.stringify({ settings, content }))\nconst dirty = computed(() => snapshot.value !== '' && current.value !== snapshot.value)\n\nconst lints = computed(() => lintBlock(settings.slug, content, t))\n\nconst groupOptions = computed(() => {\n const ids = [...meta.value.groups]\n if (!ids.includes(settings.group)) ids.push(settings.group)\n\n return ids.map((group) => ({ value: group, label: groupLabel(group, t) }))\n})\n\nconst sampleModel = computed<ScreenModel>({\n get: () => content.sample,\n set: (next) => {\n content.sample = next\n },\n})\n\nconst fieldIds = computed(() => collectIds(content.schema))\n\nfunction collectIds(nodes: BlockContent['schema']): string[] {\n const ids: string[] = []\n\n for (const node of nodes) {\n if (node.type !== 'wx-blocks' && !(node.children?.length && !node.name)) ids.push(node.id)\n if (node.children) ids.push(...collectIds(node.children))\n }\n\n return ids\n}\n\nfunction take(loaded: BlockType): void {\n block.value = loaded\n\n Object.assign(settings, {\n slug: loaded.slug,\n title: loaded.title,\n description: loaded.description,\n icon: loaded.icon,\n group: loaded.group,\n sort: loaded.sort,\n allow: loaded.allow ?? [],\n allowed_in: loaded.allowed_in ?? [],\n max_per_entity: loaded.max_per_entity,\n is_enabled: loaded.is_enabled,\n })\n\n const stored = loaded.content ?? {\n schema: [],\n template: '',\n styles: '',\n script: null,\n sample: {},\n }\n\n Object.assign(content, clone(stored))\n schemaText.value = JSON.stringify(stored.schema, null, 2)\n schemaError.value = null\n snapshot.value = current.value\n}\n\nasync function load(): Promise<void> {\n loading.value = true\n\n try {\n take(await api.get(id.value))\n usage.value = await api.usage(id.value)\n } catch (error) {\n toast.danger((error as { body?: { message?: string } }).body?.message ?? String(error))\n } finally {\n loading.value = false\n }\n}\n\nfunction onSchemaText(text: string): void {\n schemaText.value = text\n\n try {\n const parsed: unknown = JSON.parse(text)\n\n if (!Array.isArray(parsed)) throw new Error('not a list')\n\n content.schema = parsed as BlockContent['schema']\n schemaError.value = null\n } catch (error) {\n schemaError.value = t('page.schema-invalid', { error: (error as Error).message })\n }\n}\n\n/* The stage redraws a moment after the last keystroke, not on every one: a render is a\n request, and a request per character is a queue nobody asked for. */\nlet timer: ReturnType<typeof setTimeout> | undefined\nlet pending = 0\n\nfunction redraw(): void {\n clearTimeout(timer)\n timer = setTimeout(() => void render(), 250)\n}\n\nasync function render(): Promise<void> {\n if (!block.value) return\n\n const ticket = ++pending\n stage.loading = true\n\n try {\n const drawn = await api.render(block.value.id, {\n values: content.sample,\n content: canManage.value\n ? {\n template: content.template,\n styles: content.styles,\n script: content.script,\n schema: content.schema,\n }\n : undefined,\n })\n\n if (ticket !== pending) return\n\n stage.html = drawn.html\n stage.styles = drawn.styles\n stage.script = drawn.script\n stage.runtime = drawn.runtime\n } catch (error) {\n if (ticket === pending) {\n toast.danger((error as { body?: { message?: string } }).body?.message ?? String(error))\n }\n } finally {\n if (ticket === pending) stage.loading = false\n }\n}\n\nwatch(\n () => [content.template, content.styles, content.script, content.schema, content.sample],\n redraw,\n { deep: true },\n)\n\nconst templateEditor = ref<{ view: { value: unknown } } | null>(null)\n\n/* Written as a function because the mustaches themselves cannot stand in a template. */\nfunction pill(field: string): string {\n return `{{ $${field} }}`\n}\n\n/** `{{ $field }}` at the caret of the template editor. */\nfunction insertField(field: string): void {\n const view = (templateEditor.value as { view?: { value?: unknown } } | null)?.view as\n | {\n value?: {\n dispatch: (tr: unknown) => void\n state: { replaceSelection: (text: string) => unknown }\n focus: () => void\n }\n }\n | undefined\n const editor = view?.value\n\n if (!editor) {\n content.template += `{{ $${field} }}`\n\n return\n }\n\n editor.dispatch(editor.state.replaceSelection(`{{ $${field} }}`))\n editor.focus()\n}\n\nasync function save(): Promise<void> {\n if (!block.value) return\n\n saving.value = true\n errors.value = {}\n refusal.value = null\n\n const before = block.value.draft?.number ?? null\n\n try {\n const saved = await api.update(block.value.id, {\n ...settings,\n allow: settings.allow.length ? settings.allow : null,\n allowed_in: settings.allowed_in.length ? settings.allowed_in : null,\n description: settings.description || null,\n icon: settings.icon || null,\n content: schemaError.value ? { ...content, schema: undefined } : content,\n })\n\n take(saved)\n\n toast.success(\n saved.draft && saved.draft.number !== before\n ? t('page.saved', { number: saved.draft.number })\n : t('page.unchanged'),\n )\n } catch (error) {\n const body = (error as { body?: { errors?: Record<string, string[]>; message?: string } }).body\n\n if (body?.errors) {\n errors.value = body.errors\n toast.danger(t('page.failed'))\n } else {\n toast.danger(body?.message ?? t('page.failed'))\n }\n } finally {\n saving.value = false\n }\n}\n\nasync function publish(): Promise<void> {\n if (!block.value?.draft) return\n\n if (dirty.value) await save()\n if (!block.value.draft) return\n\n const agreed = await confirm({\n title: t('page.publish-title', { number: block.value.draft.number }),\n message: t('page.publish-text', { count: block.value.usage_count }),\n confirmText: t('page.publish'),\n cancelText: t('page.cancel'),\n })\n\n if (!agreed) return\n\n publishing.value = true\n refusal.value = null\n\n try {\n take(await api.publish(block.value.id))\n toast.success(t('page.published', { number: block.value.published?.number ?? 0 }))\n } catch (error) {\n const body = (error as { status?: number; body?: PublishRefusal }).body\n\n if (body?.errors) {\n refusal.value = body\n tab.value = 'template'\n toast.danger(t('page.publish-failed'))\n } else {\n toast.danger((body as { message?: string } | undefined)?.message ?? t('page.publish-failed'))\n }\n } finally {\n publishing.value = false\n }\n}\n\nasync function remove(): Promise<void> {\n if (!block.value) return\n\n const agreed = await confirm({\n title: t('page.delete-title', { title: block.value.title }),\n message: t('page.delete-text'),\n confirmText: t('page.delete'),\n cancelText: t('page.cancel'),\n tone: 'danger',\n })\n\n if (!agreed) return\n\n try {\n await api.remove(block.value.id)\n toast.success(t('page.deleted'))\n void router.push(props.base)\n } catch (error) {\n toast.danger((error as { body?: { message?: string } }).body?.message ?? String(error))\n }\n}\n\nconst refusalError = computed(() =>\n refusal.value\n ? {\n message: refusal.value.errors.template?.[0] ?? refusal.value.message,\n line: refusal.value.line,\n where: refusal.value.entity\n ? t('page.failed-on', {\n title: refusal.value.entity.title ?? `#${refusal.value.entity.id}`,\n })\n : null,\n }\n : null,\n)\n\nconst shownUsage = computed(() => usage.value.slice(0, 5))\n\nfunction errorOf(field: string): string | undefined {\n return errors.value[field]?.[0]\n}\n\nfunction leaveGuard(event: BeforeUnloadEvent): void {\n if (dirty.value) event.preventDefault()\n}\n\nonMounted(() => {\n void load()\n window.addEventListener('beforeunload', leaveGuard)\n})\n\nonBeforeUnmount(() => {\n clearTimeout(timer)\n window.removeEventListener('beforeunload', leaveGuard)\n})\n\nwatch(id, () => void load())\n</script>\n\n<template>\n <div class=\"wx-block-editor\">\n <!-- Shaped like the page it stands in for: the head on the ground, the rest on cards. -->\n <template v-if=\"loading || !block\">\n <wx-skeleton class=\"wx-block-editor__ghost-head\" title :rows=\"1\" />\n <div class=\"wx-block-editor__columns\">\n <wx-card><wx-skeleton :rows=\"8\" /></wx-card>\n <wx-card><wx-skeleton :rows=\"4\" /></wx-card>\n </div>\n </template>\n\n <template v-else>\n <div class=\"wx-block-editor__head\">\n <div class=\"wx-block-editor__id\">\n <router-link :to=\"base\" class=\"wx-block-editor__back\">‹ {{ t('page.back') }}</router-link>\n <input\n v-model=\"settings.title\"\n class=\"wx-block-editor__title\"\n :aria-label=\"t('page.title')\"\n :disabled=\"!canManage\"\n />\n <wx-text size=\"sm\" tone=\"muted\">\n <code>{{ settings.slug }}</code>\n · {{ groupLabel(settings.group, t) }} ·\n {{\n block.usage_count > 0\n ? t('page.on-pages', { count: block.usage_count })\n : t('page.not-used')\n }}\n </wx-text>\n </div>\n <div class=\"wx-block-editor__actions\">\n <wx-badge v-if=\"dirty\" type=\"primary\" dot>{{ t('page.unsaved') }}</wx-badge>\n <wx-badge v-if=\"block.draft\" type=\"warning\" dot>{{\n t('page.draft', { number: block.draft.number })\n }}</wx-badge>\n <wx-badge v-if=\"block.published\" type=\"success\" dot>{{\n t('page.live', { number: block.published.number })\n }}</wx-badge>\n <wx-badge v-else type=\"default\">{{ t('page.never-published') }}</wx-badge>\n <template v-if=\"canManage\">\n <wx-button variant=\"outline\" :loading=\"saving\" @click=\"save\">{{\n t('page.save')\n }}</wx-button>\n <wx-button\n type=\"primary\"\n :loading=\"publishing\"\n :disabled=\"!block.draft && !dirty\"\n @click=\"publish\"\n >\n {{ t('page.publish') }}\n </wx-button>\n </template>\n </div>\n </div>\n\n <wx-alert\n v-if=\"!meta.editing\"\n type=\"info\"\n variant=\"soft\"\n :description=\"t('page.editing-off')\"\n />\n\n <div class=\"wx-block-editor__columns\">\n <div class=\"wx-block-editor__files\">\n <wx-tabs v-model=\"tab\" keep-alive>\n <wx-tab value=\"template\" :label=\"t('page.tab-template')\">\n <div class=\"wx-block-editor__pane\">\n <wx-code-editor\n ref=\"templateEditor\"\n v-model=\"content.template\"\n language=\"php\"\n :readonly=\"!canManage\"\n min-height=\"340px\"\n max-height=\"70vh\"\n line-wrapping\n />\n <div v-if=\"fieldIds.length\" class=\"wx-block-editor__pills\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('page.insert-field') }}</wx-text>\n <button\n v-for=\"field in fieldIds\"\n :key=\"field\"\n type=\"button\"\n class=\"wx-block-editor__pill\"\n :disabled=\"!canManage\"\n @click=\"insertField(field)\"\n v-text=\"pill(field)\"\n />\n </div>\n <block-checks\n file=\"template\"\n :lints=\"lints\"\n :slug=\"settings.slug\"\n :error=\"refusalError\"\n />\n </div>\n </wx-tab>\n\n <wx-tab value=\"styles\" :label=\"t('page.tab-styles')\">\n <div class=\"wx-block-editor__pane\">\n <wx-code-editor\n v-model=\"content.styles\"\n language=\"css\"\n :readonly=\"!canManage\"\n min-height=\"340px\"\n max-height=\"70vh\"\n />\n <block-checks file=\"styles\" :lints=\"lints\" :slug=\"settings.slug\" />\n </div>\n </wx-tab>\n\n <wx-tab value=\"script\" :label=\"t('page.tab-script')\">\n <div class=\"wx-block-editor__pane\">\n <wx-code-editor\n :model-value=\"content.script ?? ''\"\n language=\"javascript\"\n :readonly=\"!canManage\"\n min-height=\"340px\"\n max-height=\"70vh\"\n @update:model-value=\"content.script = $event || null\"\n />\n <div class=\"wx-block-editor__note\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('page.script-help') }}</wx-text>\n <wx-text size=\"sm\" tone=\"muted\">\n {{\n meta.provides.length\n ? t('page.provides', { names: meta.provides.join(', ') })\n : t('page.provides-none')\n }}\n </wx-text>\n </div>\n </div>\n </wx-tab>\n\n <wx-tab value=\"fields\" :label=\"t('page.tab-fields')\">\n <div class=\"wx-block-editor__pane\">\n <wx-code-editor\n :model-value=\"schemaText\"\n language=\"json\"\n lint\n :readonly=\"!canManage\"\n min-height=\"340px\"\n max-height=\"70vh\"\n @update:model-value=\"onSchemaText\"\n />\n <div class=\"wx-block-editor__note\">\n <wx-text v-if=\"schemaError\" size=\"sm\" tone=\"danger\">{{ schemaError }}</wx-text>\n <wx-text v-else-if=\"errorOf('content.schema')\" size=\"sm\" tone=\"danger\">{{\n errorOf('content.schema')\n }}</wx-text>\n <wx-text v-else size=\"sm\" tone=\"muted\">{{ t('page.fields-help') }}</wx-text>\n </div>\n </div>\n </wx-tab>\n\n <wx-tab value=\"settings\" :label=\"t('page.tab-settings')\">\n <wx-card class=\"wx-block-editor__sheet\">\n <div class=\"wx-block-editor__settings\">\n <wx-form-item\n :label=\"t('page.identifier')\"\n :help=\"t('page.identifier-help')\"\n :error=\"errorOf('slug')\"\n :disabled=\"!canManage\"\n >\n <wx-input v-model=\"settings.slug\" />\n </wx-form-item>\n <wx-form-item\n :label=\"t('page.group')\"\n :help=\"t('page.group-help')\"\n :error=\"errorOf('group')\"\n :disabled=\"!canManage\"\n >\n <wx-select v-model=\"settings.group\" :options=\"groupOptions\" />\n </wx-form-item>\n <wx-form-item\n class=\"is-wide\"\n :label=\"t('page.description')\"\n :help=\"t('page.description-help')\"\n :error=\"errorOf('description')\"\n :disabled=\"!canManage\"\n >\n <wx-textarea\n :model-value=\"settings.description ?? ''\"\n :rows=\"2\"\n @update:model-value=\"settings.description = String($event ?? '')\"\n />\n </wx-form-item>\n <wx-form-item\n :label=\"t('page.icon')\"\n :error=\"errorOf('icon')\"\n :disabled=\"!canManage\"\n >\n <wx-input\n :model-value=\"settings.icon ?? ''\"\n placeholder=\"grid\"\n @update:model-value=\"settings.icon = String($event ?? '')\"\n />\n </wx-form-item>\n <wx-form-item\n :label=\"t('page.sort')\"\n :help=\"t('page.sort-help')\"\n :error=\"errorOf('sort')\"\n :disabled=\"!canManage\"\n >\n <wx-input-number v-model=\"settings.sort\" />\n </wx-form-item>\n <wx-form-item\n :label=\"t('page.allow')\"\n :help=\"t('page.allow-help')\"\n :error=\"errorOf('allow')\"\n :disabled=\"!canManage\"\n >\n <wx-tags-input v-model=\"settings.allow\" allow-create />\n </wx-form-item>\n <wx-form-item\n :label=\"t('page.allowed-in')\"\n :help=\"t('page.allowed-in-help')\"\n :error=\"errorOf('allowed_in')\"\n :disabled=\"!canManage\"\n >\n <wx-tags-input\n v-model=\"settings.allowed_in\"\n allow-create\n :suggestions=\"['root']\"\n />\n </wx-form-item>\n <wx-form-item\n :label=\"t('page.max-per-entity')\"\n :help=\"t('page.max-per-entity-help')\"\n :error=\"errorOf('max_per_entity')\"\n :disabled=\"!canManage\"\n >\n <wx-input-number\n :model-value=\"settings.max_per_entity ?? undefined\"\n :min=\"1\"\n @update:model-value=\"settings.max_per_entity = $event ?? null\"\n />\n </wx-form-item>\n <wx-form-item\n :label=\"t('page.enabled')\"\n :help=\"t('page.enabled-help')\"\n :disabled=\"!canManage\"\n >\n <wx-switch v-model=\"settings.is_enabled\" />\n </wx-form-item>\n <div v-if=\"canManage\" class=\"is-wide wx-block-editor__danger\">\n <wx-button\n type=\"danger\"\n variant=\"outline\"\n :disabled=\"block.usage_count > 0\"\n @click=\"remove\"\n >\n {{ t('page.delete') }}\n </wx-button>\n <wx-text v-if=\"block.usage_count > 0\" size=\"sm\" tone=\"muted\">\n {{ t('page.delete-used', { count: block.usage_count }) }}\n </wx-text>\n </div>\n </div>\n </wx-card>\n </wx-tab>\n\n <wx-tab value=\"history\" :label=\"t('page.tab-history')\">\n <wx-card class=\"wx-block-editor__sheet\" padding=\"none\">\n <block-history :block=\"block\" :can-manage=\"canManage\" @restored=\"take\" />\n </wx-card>\n </wx-tab>\n </wx-tabs>\n </div>\n\n <div class=\"wx-block-editor__side\">\n <block-stage\n :html=\"stage.html\"\n :styles=\"stage.styles\"\n :script=\"stage.script\"\n :runtime=\"stage.runtime\"\n :loading=\"stage.loading\"\n />\n\n <wx-card :title=\"t('page.sample')\">\n <wx-screen-renderer\n v-if=\"content.schema.length\"\n v-model=\"sampleModel\"\n :root=\"formSchema(content.schema)\"\n :types=\"context.types\"\n :translate=\"context.i18n.t\"\n :can=\"context.can\"\n :disabled=\"!canManage\"\n size=\"sm\"\n />\n <wx-text size=\"sm\" tone=\"muted\">{{ t('page.sample-help') }}</wx-text>\n </wx-card>\n\n <wx-card :title=\"t('page.usage')\">\n <wx-text v-if=\"usage.length === 0\" size=\"sm\" tone=\"muted\">{{\n t('page.usage-empty')\n }}</wx-text>\n <div v-else class=\"wx-block-editor__usage\">\n <div\n v-for=\"entity in shownUsage\"\n :key=\"`${entity.model}:${entity.id}`\"\n class=\"wx-block-editor__use\"\n >\n <span>{{ entity.title ?? `#${entity.id}` }}</span>\n <wx-badge v-if=\"!entity.published\" type=\"warning\" size=\"sm\">{{\n t('page.unpublished-page')\n }}</wx-badge>\n </div>\n <wx-text v-if=\"usage.length > shownUsage.length\" size=\"sm\" tone=\"muted\">\n {{ t('page.usage-more', { count: usage.length - shownUsage.length }) }}\n </wx-text>\n </div>\n </wx-card>\n </div>\n </div>\n </template>\n </div>\n</template>\n\n<style scoped>\n.wx-block-editor {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-16);\n container-type: inline-size;\n}\n\n.wx-block-editor__head {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: var(--wx-space-16);\n flex-wrap: wrap;\n}\n\n.wx-block-editor__ghost-head {\n max-width: 420px;\n}\n\n.wx-block-editor__id {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-4);\n flex: 1 1 280px;\n min-width: 0;\n}\n\n.wx-block-editor__back {\n font-size: var(--wx-font-size-sm);\n color: var(--wx-text-muted);\n text-decoration: none;\n}\n\n.wx-block-editor__title {\n width: 100%;\n padding: 0;\n border: 0;\n background: transparent;\n color: inherit;\n font: inherit;\n font-size: var(--wx-font-size-xl);\n font-weight: var(--wx-font-weight-bold);\n}\n\n.wx-block-editor__title:focus-visible {\n outline: 2px solid var(--wx-color-primary);\n outline-offset: 2px;\n border-radius: var(--wx-radius-xs);\n}\n\n.wx-block-editor__actions {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n flex-wrap: wrap;\n}\n\n.wx-block-editor__columns {\n display: grid;\n grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);\n gap: var(--wx-space-16);\n align-items: start;\n}\n\n@container (max-width: 1080px) {\n .wx-block-editor__columns {\n grid-template-columns: minmax(0, 1fr);\n }\n}\n\n.wx-block-editor__files {\n min-width: 0;\n}\n\n.wx-block-editor__pane {\n display: flex;\n flex-direction: column;\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n overflow: hidden;\n}\n\n.wx-block-editor__pane :deep(.wx-code-editor) {\n border: 0;\n border-radius: 0;\n}\n\n.wx-block-editor__pills {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wx-space-6);\n padding: var(--wx-space-8) var(--wx-space-12);\n border-block-start: 1px solid var(--wx-color-border-muted, var(--wx-border-default));\n}\n\n.wx-block-editor__pill {\n padding: 2px var(--wx-space-8);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-full);\n background: var(--wx-bg-surface);\n color: var(--wx-color-primary);\n font-family: var(--wx-font-family-mono);\n font-size: var(--wx-font-size-xs);\n cursor: pointer;\n}\n\n.wx-block-editor__pill:hover:not(:disabled) {\n border-color: var(--wx-color-primary);\n}\n\n.wx-block-editor__note {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-4);\n padding: var(--wx-space-8) var(--wx-space-12);\n border-block-start: 1px solid var(--wx-color-border-muted, var(--wx-border-default));\n}\n\n/* The settings and the history sit on a card, the way the side column does: the code tabs\n bring their own white with the editor, these two would otherwise stand on the grey. */\n.wx-block-editor__sheet {\n min-width: 0;\n}\n\n.wx-block-editor__settings {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));\n gap: var(--wx-space-12) var(--wx-space-16);\n}\n\n.wx-block-editor__settings .is-wide {\n grid-column: 1 / -1;\n}\n\n.wx-block-editor__danger {\n display: flex;\n align-items: center;\n gap: var(--wx-space-12);\n flex-wrap: wrap;\n}\n\n.wx-block-editor__side {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-16);\n min-width: 0;\n position: sticky;\n top: var(--wx-space-12);\n}\n\n.wx-block-editor__usage {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-6);\n}\n\n.wx-block-editor__use {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n}\n\ncode {\n font-family: var(--wx-font-family-mono);\n font-size: var(--wx-font-size-xs);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport { useElementWidth, WxIcon } from '@webx-ui/core'\nimport { stageDocument } from './frame'\nimport type { BlockThumbnail } from './types'\n\n/**\n * A block drawn small: the sample render in an iframe, scaled down to the width it is given.\n *\n * An iframe rather than inline markup because a block's styles are a block's business — a\n * stray `h2 { }` in one type would otherwise restyle the whole list of cards — and because\n * the thumbnail is a picture of the site, not a part of the panel.\n */\nconst props = withDefaults(\n defineProps<{\n thumbnail: BlockThumbnail | null\n /** The width the block is drawn at, before scaling — a desktop. */\n width?: number\n /** How tall the picture is, in the panel's pixels. */\n height?: number\n }>(),\n { width: 1280, height: 120 },\n)\n\nconst box = ref<HTMLElement | null>(null)\nconst boxWidth = useElementWidth(box)\n\nconst scale = computed(() => (boxWidth.value > 0 ? boxWidth.value / props.width : 0.2))\n\nconst srcdoc = computed(() =>\n props.thumbnail\n ? stageDocument({ html: props.thumbnail.html, styles: props.thumbnail.styles })\n : '',\n)\n\nconst frameStyle = computed(() => ({\n width: `${props.width}px`,\n height: `${Math.round(props.height / scale.value)}px`,\n transform: `scale(${scale.value})`,\n}))\n</script>\n\n<template>\n <div ref=\"box\" class=\"wx-block-thumb\" :style=\"{ height: `${height}px` }\">\n <iframe\n v-if=\"thumbnail\"\n class=\"wx-block-thumb__frame\"\n :srcdoc=\"srcdoc\"\n :style=\"frameStyle\"\n sandbox=\"allow-same-origin\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n />\n <div v-else class=\"wx-block-thumb__empty\">\n <wx-icon name=\"grid\" />\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-block-thumb {\n position: relative;\n overflow: hidden;\n background: var(--wx-bg-subtle);\n}\n\n.wx-block-thumb__frame {\n position: absolute;\n inset-block-start: 0;\n inset-inline-start: 0;\n border: 0;\n transform-origin: top left;\n pointer-events: none;\n background: #fff;\n}\n\n.wx-block-thumb__empty {\n display: grid;\n place-items: center;\n height: 100%;\n color: var(--wx-text-muted);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { useModal, WxButton, WxDialog, WxEmpty, WxInput, WxText } from '@webx-ui/core'\nimport BlockThumb from './BlockThumb.vue'\nimport { countType } from './content'\nimport { useBlocksMessages } from './i18n'\nimport { groupLabel } from './schema'\nimport type { BlockNode, BlockType } from './types'\n\n/**\n * \"Add a block\": the types as cards with their pictures, because a name says nothing about\n * whether \"Section\" is a full-width band or a container with columns. Only what may go\n * here is offered; what is exhausted is shown greyed with the reason rather than hidden,\n * or the editor goes looking for a block that vanished.\n */\nconst props = withDefaults(\n defineProps<{\n catalog: BlockType[]\n /** The container a block is being added to, or null at the page level. */\n parent?: BlockType | null\n /** What the container's field allows, when the field narrows it further. */\n allow?: string[] | null\n /** The whole tree, for the per-page limits. */\n tree?: BlockNode[]\n groups?: string[]\n /** Where a person with the right can go and make a type. */\n blocksPath?: string | null\n }>(),\n { parent: null, allow: null, tree: () => [], groups: () => [], blocksPath: null },\n)\n\nconst { resolve, dismiss, open } = useModal<BlockType>()\nuseBlocksMessages()\n\nconst t = useTranslate('webx-blocks')\n\nconst search = ref('')\n\ninterface Option {\n type: BlockType\n reason: string | null\n}\n\n/** Allowed here at all: the parent's say-so and the type's own, both. */\nfunction allowedHere(type: BlockType): boolean {\n if (props.parent === null) {\n return type.allowed_in === null || type.allowed_in.includes('root')\n }\n\n const parentAllows = props.allow\n ? props.allow.includes(type.slug)\n : props.parent.allow?.includes(type.slug) === true\n const typeAllows = type.allowed_in === null || type.allowed_in.includes(props.parent.slug)\n\n return parentAllows && typeAllows\n}\n\nconst options = computed<Option[]>(() =>\n props.catalog\n .filter((type) => type.is_enabled && type.published !== null && allowedHere(type))\n .map((type) => {\n const count = countType(props.tree, type.slug)\n const exhausted = type.max_per_entity !== null && count >= type.max_per_entity\n\n return { type, reason: exhausted ? t('field.limit-reached', { count }) : null }\n }),\n)\n\nconst shown = computed(() => {\n const needle = search.value.trim().toLowerCase()\n\n if (needle === '') return options.value\n\n return options.value.filter(\n ({ type }) =>\n type.title.toLowerCase().includes(needle) ||\n type.slug.includes(needle) ||\n (type.description ?? '').toLowerCase().includes(needle),\n )\n})\n\nconst sections = computed(() => {\n const order = [...props.groups]\n\n for (const { type } of shown.value) {\n if (!order.includes(type.group)) order.push(type.group)\n }\n\n const grouped = order\n .map((id) => ({\n id,\n label: groupLabel(id, t),\n options: shown.value.filter((o) => o.type.group === id),\n }))\n .filter((section) => section.options.length > 0)\n\n const flat = shown.value.length <= 5 || search.value.trim() !== '' || grouped.length < 2\n\n return flat ? [{ id: '', label: '', options: shown.value }] : grouped\n})\n\n/** Why the list is empty, in words: which case it is decides what the person does next. */\nconst emptyText = computed(() => {\n if (props.catalog.length === 0) return t('field.pick-none')\n if (options.value.length === 0 && props.parent) {\n const allowed = (props.allow ?? props.parent.allow ?? []).filter((slug) =>\n props.catalog.some((type) => type.slug === slug),\n )\n\n return allowed.length === 0\n ? t('field.pick-nothing-allowed', { parent: props.parent.title })\n : t('field.pick-limited', { parent: props.parent.title, types: allowed.join(', ') })\n }\n\n return t('field.pick-empty')\n})\n</script>\n\n<template>\n <wx-dialog v-model:open=\"open\" :title=\"t('field.pick')\" :width=\"860\">\n <div class=\"wx-block-picker\">\n <!-- Always there, four types or forty: a person who came to type a name should not\n first have to notice that the field is missing. -->\n <wx-input\n v-if=\"options.length > 0\"\n v-model=\"search\"\n :placeholder=\"t('field.search')\"\n clearable\n autofocus\n />\n\n <wx-empty v-if=\"shown.length === 0\" icon=\"grid\" :title=\"emptyText\" size=\"sm\">\n <router-link v-if=\"catalog.length === 0 && blocksPath\" :to=\"blocksPath\">\n {{ t('field.pick-none-link') }}\n </router-link>\n </wx-empty>\n\n <section v-for=\"section in sections\" :key=\"section.id\" class=\"wx-block-picker__group\">\n <div v-if=\"section.label\" class=\"wx-block-picker__group-title\">{{ section.label }}</div>\n <div class=\"wx-block-picker__cards\">\n <button\n v-for=\"option in section.options\"\n :key=\"option.type.id\"\n type=\"button\"\n class=\"wx-block-picker__card\"\n :class=\"{ 'is-disabled': option.reason !== null }\"\n :disabled=\"option.reason !== null\"\n :title=\"option.reason ?? undefined\"\n @click=\"resolve(option.type)\"\n >\n <block-thumb :thumbnail=\"option.type.thumbnail\" :height=\"96\" />\n <div class=\"wx-block-picker__body\">\n <div class=\"wx-block-picker__title\">{{ option.type.title }}</div>\n <wx-text v-if=\"option.reason\" size=\"sm\" tone=\"warning\">{{ option.reason }}</wx-text>\n <wx-text v-else-if=\"option.type.description\" size=\"sm\" tone=\"muted\">\n {{ option.type.description }}\n </wx-text>\n </div>\n </button>\n </div>\n </section>\n </div>\n\n <template #footer>\n <wx-button variant=\"outline\" @click=\"dismiss()\">{{ t('field.close') }}</wx-button>\n </template>\n </wx-dialog>\n</template>\n\n<style scoped>\n.wx-block-picker {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-16);\n}\n\n.wx-block-picker__group {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n}\n\n.wx-block-picker__group-title {\n font-size: var(--wx-font-size-xs);\n font-weight: var(--wx-font-weight-semibold);\n letter-spacing: 0.06em;\n text-transform: uppercase;\n color: var(--wx-text-muted);\n}\n\n.wx-block-picker__cards {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\n gap: var(--wx-space-12);\n}\n\n.wx-block-picker__card {\n display: flex;\n flex-direction: column;\n padding: 0;\n overflow: hidden;\n text-align: start;\n font: inherit;\n color: inherit;\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n cursor: pointer;\n}\n\n.wx-block-picker__card:hover:not(:disabled),\n.wx-block-picker__card:focus-visible {\n border-color: var(--wx-color-primary);\n outline: none;\n}\n\n.wx-block-picker__card.is-disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.wx-block-picker__body {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-4);\n padding: var(--wx-space-10) var(--wx-space-12);\n}\n\n.wx-block-picker__title {\n font-weight: var(--wx-font-weight-semibold);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { useElementWidth, WxButton, WxSegmented, WxText } from '@webx-ui/core'\nimport { highlightBlock, replaceBlock } from './frame'\n\n/**\n * The page in an iframe, the way it will be: the same handler, the same view, the draft\n * laid over the columns. Two shapes — the whole page wide while nothing is selected, a\n * phone at one to one while a block is being edited — and a full-screen mode for looking\n * at the desktop and the tablet, because a desktop in a 420 px column is a picture nobody\n * can read.\n *\n * The panel and the site are one application on one domain, so the frame's document is\n * reachable: selection is a class, a change is a swap between the marker comments.\n */\nconst props = withDefaults(\n defineProps<{\n url: string | null\n selected?: string | null\n /** `wide` when the page is being looked at, `phone` while a block is being edited. */\n mode?: 'wide' | 'phone'\n /** Bumped by the host to reload the page. */\n reload?: number\n /** Be as tall as what it is drawn in, and scroll the page inside rather than beside. */\n fill?: boolean\n }>(),\n { selected: null, mode: 'wide', reload: 0, fill: false },\n)\n\nconst t = useTranslate('webx-blocks')\n\nconst frame = ref<HTMLIFrameElement | null>(null)\nconst box = ref<HTMLElement | null>(null)\nconst boxWidth = useElementWidth(box)\nconst fullscreen = ref(false)\nconst fullWidth = ref<number>(1280)\nconst ready = ref(false)\n\nconst widths = computed(() => [\n { value: 1280, label: t('field.width-desktop') },\n { value: 834, label: t('field.width-tablet') },\n { value: 390, label: t('field.width-phone') },\n])\n\nconst width = computed(() =>\n fullscreen.value ? fullWidth.value : props.mode === 'phone' ? 390 : 1280,\n)\n\nconst scale = computed(() => {\n if (fullscreen.value || props.mode === 'phone' || boxWidth.value === 0) return 1\n\n return Math.min(1, boxWidth.value / width.value)\n})\n\nconst frameStyle = computed(() => ({\n width: `${width.value}px`,\n transform: `scale(${scale.value})`,\n}))\n\nconst label = computed(() => {\n if (!props.url) return ''\n\n try {\n const parsed = new URL(props.url, location.origin)\n\n return `${parsed.pathname} · ${width.value} px`\n } catch {\n return props.url\n }\n})\n\nfunction doc(): Document | null {\n try {\n return frame.value?.contentDocument ?? null\n } catch {\n return null\n }\n}\n\nfunction onLoad(): void {\n ready.value = true\n const page = doc()\n if (page) highlightBlock(page, props.selected ?? null)\n}\n\n/** Swap one block's markup in place; false when the page has to be reloaded instead. */\nfunction replace(key: string, html: string): boolean {\n const page = doc()\n\n if (!page || !ready.value) return false\n\n const done = replaceBlock(page, key, html)\n if (done) highlightBlock(page, props.selected ?? null)\n\n return done\n}\n\nfunction refresh(): void {\n ready.value = false\n if (frame.value && props.url) frame.value.src = props.url\n}\n\nfunction onKey(event: KeyboardEvent): void {\n if (event.key === 'Escape' && fullscreen.value) {\n fullscreen.value = false\n event.stopPropagation()\n }\n}\n\nwatch(\n () => props.selected,\n (key) => {\n const page = doc()\n if (page && ready.value) highlightBlock(page, key ?? null)\n },\n)\n\nwatch(() => props.reload, refresh)\nwatch(\n () => props.url,\n () => (ready.value = false),\n)\n\nonMounted(() => window.addEventListener('keydown', onKey))\nonBeforeUnmount(() => window.removeEventListener('keydown', onKey))\n\ndefineExpose({ replace, refresh, open: () => (fullscreen.value = true) })\n</script>\n\n<template>\n <div\n class=\"wx-blocks-preview\"\n :class=\"{ 'is-fullscreen': fullscreen, 'is-phone': mode === 'phone', 'is-fill': fill }\"\n >\n <div class=\"wx-blocks-preview__bar\">\n <wx-text size=\"xs\" tone=\"muted\" class=\"wx-blocks-preview__label\" truncate>{{\n label\n }}</wx-text>\n <div class=\"wx-blocks-preview__tools\">\n <wx-segmented v-if=\"fullscreen\" v-model=\"fullWidth\" :options=\"widths\" size=\"sm\" />\n <wx-button\n v-if=\"url\"\n size=\"sm\"\n variant=\"outline\"\n :href=\"url\"\n target=\"_blank\"\n rel=\"noopener\"\n >\n {{ t('field.open-site') }}\n </wx-button>\n <wx-button size=\"sm\" variant=\"outline\" @click=\"fullscreen = !fullscreen\">\n {{ fullscreen ? t('field.close') : t('field.fullscreen') }}\n </wx-button>\n </div>\n </div>\n <div ref=\"box\" class=\"wx-blocks-preview__ground\">\n <div class=\"wx-blocks-preview__clip\" :style=\"{ width: `${Math.round(width * scale)}px` }\">\n <iframe\n v-if=\"url\"\n ref=\"frame\"\n class=\"wx-blocks-preview__frame\"\n :src=\"url\"\n :style=\"frameStyle\"\n :title=\"t('field.preview')\"\n @load=\"onLoad\"\n />\n </div>\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-blocks-preview {\n display: flex;\n flex-direction: column;\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n background: var(--wx-bg-surface);\n overflow: hidden;\n min-width: 0;\n}\n\n.wx-blocks-preview.is-fullscreen {\n position: fixed;\n inset: 0;\n z-index: 40;\n border: 0;\n border-radius: 0;\n}\n\n.wx-blocks-preview__bar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--wx-space-8);\n padding: var(--wx-space-8) var(--wx-space-12);\n border-block-end: 1px solid var(--wx-color-border-muted, var(--wx-border-default));\n}\n\n.wx-blocks-preview__label {\n min-width: 0;\n font-family: var(--wx-font-family-mono);\n}\n\n.wx-blocks-preview__tools {\n display: flex;\n gap: var(--wx-space-8);\n align-items: center;\n flex-wrap: wrap;\n}\n\n.wx-blocks-preview__ground {\n flex: 1;\n padding: var(--wx-space-12);\n background: var(--wx-bg-subtle);\n overflow: auto;\n max-height: calc(100vh - 200px);\n}\n\n.is-fullscreen .wx-blocks-preview__ground {\n max-height: none;\n}\n\n/*\n * Told how tall to be rather than working it out from the window: the two viewport-sized caps\n * below are for a preview standing on a page that scrolls, and inside a panel that already has\n * a height they are a second, smaller box that fights the first.\n */\n.wx-blocks-preview.is-fill {\n height: 100%;\n}\n\n.is-fill .wx-blocks-preview__ground {\n max-height: none;\n min-height: 0;\n}\n\n.wx-blocks-preview__clip {\n margin-inline: auto;\n overflow: hidden;\n box-shadow: var(--wx-shadow-sm);\n}\n\n.wx-blocks-preview__frame {\n display: block;\n border: 0;\n background: #fff;\n height: min(72vh, 720px);\n transform-origin: top left;\n}\n\n.is-fullscreen .wx-blocks-preview__frame {\n height: calc(100vh - 100px);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { WxAction, WxIcon, WxSortableList } from '@webx-ui/core'\nimport type { ScreenNode } from '@webx-ui/schema'\nimport { nestedFields } from './content'\nimport type { BlockNode, BlockType } from './types'\n\n/**\n * One level of the tree, and itself again for every container. Rows reorder among their\n * siblings by drag; a container shows its fields' lists underneath, each with its own\n * \"add inside\". Moving a block between containers is not a drag — a duplicate and a remove\n * do it, and a drag across allow-rules would need a judge at every drop.\n */\nconst props = withDefaults(\n defineProps<{\n nodes: BlockNode[]\n catalog: BlockType[]\n parentKey?: string | null\n field?: string | null\n selected?: string | null\n disabled?: boolean\n depth?: number\n }>(),\n { parentKey: null, field: null, selected: null, disabled: false, depth: 0 },\n)\n\nconst emit = defineEmits<{\n select: [key: string]\n add: [parentKey: string | null, field: string | null, node: ScreenNode | null]\n remove: [key: string]\n duplicate: [key: string]\n reorder: [parentKey: string | null, field: string | null, list: BlockNode[]]\n}>()\n\nconst t = useTranslate('webx-blocks')\n\nfunction typeOf(node: BlockNode): BlockType | null {\n return props.catalog.find((type) => type.slug === node.type) ?? null\n}\n\nfunction titleOf(node: BlockNode): string {\n return typeOf(node)?.title ?? node.type\n}\n\nfunction fieldsOf(node: BlockNode): ScreenNode[] {\n const type = typeOf(node)\n\n return type?.content ? nestedFields(type.content.schema) : []\n}\n\nfunction childrenIn(node: BlockNode, field: ScreenNode): BlockNode[] {\n const value = node.values[field.id]\n\n return Array.isArray(value) ? (value as BlockNode[]) : []\n}\n\nfunction iconOf(node: BlockNode): string {\n return typeOf(node)?.icon ?? 'grid'\n}\n</script>\n\n<template>\n <wx-sortable-list\n :model-value=\"nodes\"\n item-key=\"key\"\n :item-label=\"(node: BlockNode) => titleOf(node)\"\n :disabled=\"disabled\"\n plain\n size=\"sm\"\n :empty-text=\"depth === 0 ? t('field.empty') : ''\"\n class=\"wx-blocks-tree\"\n :class=\"{ 'is-nested': depth > 0 }\"\n @update:model-value=\"emit('reorder', parentKey, field, $event as BlockNode[])\"\n >\n <template #default=\"{ item }\">\n <div class=\"wx-blocks-tree__node\">\n <div\n class=\"wx-blocks-tree__row\"\n :class=\"{ 'is-selected': selected === item.key }\"\n role=\"button\"\n tabindex=\"0\"\n @click=\"emit('select', item.key)\"\n @keydown.enter.prevent=\"emit('select', item.key)\"\n @keydown.space.prevent=\"emit('select', item.key)\"\n >\n <span class=\"wx-blocks-tree__icon\"><wx-icon :name=\"iconOf(item)\" /></span>\n <span class=\"wx-blocks-tree__name\">{{ titleOf(item) }}</span>\n <span\n v-if=\"!typeOf(item)\"\n class=\"wx-blocks-tree__flag is-danger\"\n :title=\"t('field.unknown-type', { type: item.type })\"\n >\n <wx-icon name=\"close-circle\" />\n </span>\n <span\n v-else-if=\"typeOf(item)?.draft\"\n class=\"wx-blocks-tree__flag is-warning\"\n :title=\"t('field.draft-type')\"\n >\n <wx-icon name=\"warning\" />\n </span>\n <span\n v-else-if=\"typeOf(item)?.is_enabled === false\"\n class=\"wx-blocks-tree__flag\"\n :title=\"t('field.disabled-type')\"\n >\n <wx-icon name=\"eye-off\" />\n </span>\n <span v-if=\"!disabled\" class=\"wx-blocks-tree__actions\" @click.stop>\n <wx-action\n icon=\"copy\"\n size=\"sm\"\n :title=\"t('field.duplicate')\"\n @click=\"emit('duplicate', item.key)\"\n />\n <wx-action\n icon=\"trash\"\n size=\"sm\"\n tone=\"danger\"\n :title=\"t('field.remove')\"\n @click=\"emit('remove', item.key)\"\n />\n </span>\n </div>\n\n <div v-for=\"slot in fieldsOf(item)\" :key=\"slot.id\" class=\"wx-blocks-tree__kids\">\n <blocks-tree\n :nodes=\"childrenIn(item, slot)\"\n :catalog=\"catalog\"\n :parent-key=\"item.key\"\n :field=\"slot.id\"\n :selected=\"selected\"\n :disabled=\"disabled\"\n :depth=\"depth + 1\"\n @select=\"emit('select', $event)\"\n @add=\"(p, f, n) => emit('add', p, f, n)\"\n @remove=\"emit('remove', $event)\"\n @duplicate=\"emit('duplicate', $event)\"\n @reorder=\"(p, f, list) => emit('reorder', p, f, list)\"\n />\n <button\n v-if=\"!disabled\"\n type=\"button\"\n class=\"wx-blocks-tree__add is-inner\"\n @click=\"emit('add', item.key, slot.id, slot)\"\n >\n + {{ t('field.add-inside')\n }}<template v-if=\"fieldsOf(item).length > 1\"> · {{ slot.label ?? slot.id }}</template>\n </button>\n </div>\n </div>\n </template>\n </wx-sortable-list>\n</template>\n\n<style scoped>\n.wx-blocks-tree :deep(.wx-sortable-list__content) {\n min-width: 0;\n}\n\n.wx-blocks-tree__node {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-2);\n min-width: 0;\n}\n\n.wx-blocks-tree__row {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n padding: var(--wx-space-6) var(--wx-space-8);\n border: 1px solid transparent;\n border-radius: var(--wx-radius-control);\n cursor: pointer;\n}\n\n.wx-blocks-tree__row:hover {\n background: var(--wx-bg-subtle);\n}\n\n.wx-blocks-tree__row.is-selected {\n background: var(--wx-color-primary-soft);\n border-color: var(--wx-color-primary);\n}\n\n.wx-blocks-tree__icon {\n display: grid;\n place-items: center;\n flex: none;\n width: 24px;\n height: 24px;\n border-radius: var(--wx-radius-sm);\n background: var(--wx-bg-subtle);\n color: var(--wx-text-muted);\n}\n\n.is-selected .wx-blocks-tree__icon {\n background: var(--wx-bg-surface);\n color: var(--wx-color-primary);\n}\n\n.wx-blocks-tree__name {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: var(--wx-font-size-sm);\n font-weight: var(--wx-font-weight-medium);\n}\n\n.wx-blocks-tree__flag {\n display: flex;\n color: var(--wx-text-muted);\n}\n\n.wx-blocks-tree__flag.is-warning {\n color: var(--wx-color-warning);\n}\n\n.wx-blocks-tree__flag.is-danger {\n color: var(--wx-color-danger);\n}\n\n.wx-blocks-tree__actions {\n display: flex;\n gap: var(--wx-space-2);\n opacity: 0;\n}\n\n.wx-blocks-tree__row:hover .wx-blocks-tree__actions,\n.wx-blocks-tree__row:focus-within .wx-blocks-tree__actions,\n.wx-blocks-tree__row.is-selected .wx-blocks-tree__actions {\n opacity: 1;\n}\n\n.wx-blocks-tree__kids {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-2);\n margin-inline-start: var(--wx-space-14);\n padding-inline-start: var(--wx-space-8);\n border-inline-start: 1px dashed var(--wx-border-default);\n}\n\n.wx-blocks-tree__add {\n width: 100%;\n padding: var(--wx-space-6);\n border: 1px dashed var(--wx-color-border-strong, var(--wx-border-default));\n border-radius: var(--wx-radius-control);\n background: transparent;\n color: var(--wx-text-muted);\n font: inherit;\n font-size: var(--wx-font-size-xs);\n cursor: pointer;\n}\n\n.wx-blocks-tree__add:hover {\n color: var(--wx-color-primary);\n border-color: var(--wx-color-primary);\n background: var(--wx-color-primary-soft);\n}\n</style>\n","import { inject, provide, type InjectionKey, type Ref } from 'vue'\n\n/**\n * What the page hosting a constructor knows and the constructor does not: where the preview\n * of the entity is. The address is `Preview::url()` on the server — signed, short-lived, one\n * entity — and it is the consumer module's screen that asks for it, because only that\n * screen knows which entity it is editing.\n *\n * The constructor shows the page in an iframe when this is provided, and works as a tree\n * with a form when it is not.\n */\nexport interface BlocksPreview {\n /** The preview address, or null while there is none — an entity not yet saved. */\n url: Ref<string | null>\n /** Bump to reload the frame: after an autosave, when the tree changed shape. */\n reload?: Ref<number>\n}\n\nexport const blocksPreviewKey: InjectionKey<BlocksPreview> = Symbol('wx-blocks-preview')\n\n/** Called by the hosting screen, above the `wx-blocks` field. */\nexport function provideBlocksPreview(preview: BlocksPreview): void {\n provide(blocksPreviewKey, preview)\n}\n\nexport function useBlocksPreview(): BlocksPreview | null {\n return inject(blocksPreviewKey, null)\n}\n\n/**\n * Set by the constructor for everything it draws, so that a `wx-blocks` node inside a\n * block's own form knows it is nested — and draws a note instead of a second constructor.\n */\nexport const blocksRootKey: InjectionKey<boolean> = Symbol('wx-blocks-root')\n","<script setup lang=\"ts\">\nimport {\n computed,\n getCurrentInstance,\n inject,\n onBeforeUnmount,\n onMounted,\n provide,\n ref,\n watch,\n} from 'vue'\nimport { adminKey, useTranslate, type AdminContext } from '@webx-ui/module-admin'\nimport { createModal, toast, WxButton, WxText } from '@webx-ui/core'\nimport {\n coreTypes,\n WxScreenRenderer,\n type RenderContext,\n type ScreenNode,\n type TypeRegistry,\n} from '@webx-ui/schema'\nimport { createBlocksApi, type BlocksApi } from './api'\nimport BlockPicker from './BlockPicker.vue'\nimport BlocksPreview from './BlocksPreview.vue'\nimport BlocksTree from './BlocksTree.vue'\nimport {\n cloneNode,\n insertNode,\n locate,\n makeNode,\n removeNode,\n replaceList,\n updateValues,\n} from './content'\nimport { useBlocksMessages } from './i18n'\nimport { blocksPreviewKey, blocksRootKey } from './preview'\nimport { formSchema } from './schema'\nimport type { BlockNode, BlockType } from './types'\n\n/**\n * The constructor — the `wx-blocks` field.\n *\n * Two states (§14). Nothing selected: the tree and the preview of the whole page, wide,\n * for looking at the layout, the order and the seams. A block selected: the tree, a wide\n * form of the block's fields, and the preview shrunk to a phone at one to one — a desktop\n * in a 420 px column is unreadable, and a phone is where things break first.\n *\n * Inside a block's own form the same node type means a nested constructor, and those are\n * edited in the tree on the left — so a nested instance draws a note and nothing else.\n */\ndefineOptions({ name: 'WxBlocks', inheritAttrs: false })\n\nconst props = withDefaults(\n defineProps<{\n /** Handed over by the renderer: the node being drawn and the way down. Unused here. */\n node?: ScreenNode\n context?: RenderContext\n name?: string\n localized?: boolean\n /** Narrows what may be added at the top level, beyond what the types themselves allow. */\n allow?: string[] | null\n /** How many blocks the top level may hold. */\n max?: number | null\n /**\n * The published types with their schemas. Fetched from the panel when absent — handed\n * in for a screen outside one, a demo or a test.\n */\n catalog?: BlockType[] | null\n disabled?: boolean\n /** Where the section lives, for the picker's \"make one\" link. */\n blocksPath?: string\n /**\n * Be as tall as what the field is drawn in, and let each of the three panels scroll inside\n * itself.\n *\n * Off by default, because the ordinary case is a field on a form that scrolls: there the\n * constructor is as tall as it needs to be and the preview sticks. A screen that has given\n * the constructor the whole area below its head says so — otherwise the field grows, the\n * page scrolls, and the tree, the form and the preview all leave the screen together.\n */\n fill?: boolean\n }>(),\n {\n node: undefined,\n context: undefined,\n name: undefined,\n localized: false,\n allow: null,\n max: null,\n catalog: null,\n disabled: false,\n blocksPath: '/blocks',\n fill: false,\n },\n)\n\nconst model = defineModel<BlockNode[]>({ default: () => [] })\n\nconst nested = inject(blocksRootKey, false)\nprovide(blocksRootKey, true)\n\nuseBlocksMessages()\nconst t = useTranslate('webx-blocks')\n\n/* The panel, when there is one. A demo page has none, and gets by on the catalog prop —\n which is why this is `inject` and not `useAdmin()`: that throws outside a panel, and a\n field must not. */\nconst admin: AdminContext | null = inject(adminKey, null)\nlet api: BlocksApi | null = null\n\nconst loaded = ref<BlockType[]>([])\nconst catalog = computed(() => props.catalog ?? loaded.value)\n\nconst tree = computed<BlockNode[]>(() => (Array.isArray(model.value) ? model.value : []))\n\nconst selectedKey = ref<string | null>(null)\nconst selected = computed(() => (selectedKey.value ? locate(tree.value, selectedKey.value) : null))\nconst selectedType = computed(() =>\n selected.value\n ? (catalog.value.find((type) => type.slug === selected.value?.node.type) ?? null)\n : null,\n)\n\nconst preview = inject(blocksPreviewKey, null)\nconst previewEl = ref<InstanceType<typeof BlocksPreview> | null>(null)\n\nconst groups = computed<string[]>(\n () =>\n (admin?.state.manifest?.modules.find((m) => m.id === 'blocks')?.meta?.groups as\n string[] | undefined) ?? [],\n)\n\n/** Node types for the block's form: the panel's registry, or the core plus this field. */\nconst self = getCurrentInstance()?.type\nconst types = computed<TypeRegistry>(() => {\n if (props.context?.types) return props.context.types\n if (admin?.types) return { ...coreTypes, ...admin.types }\n\n return self\n ? { ...coreTypes, 'wx-blocks': { component: self, kind: 'field', nested: true } }\n : coreTypes\n})\n\nconst translate = computed(\n () => props.context?.translate ?? admin?.i18n.t ?? ((key: string) => key),\n)\nconst can = computed(() => props.context?.can ?? admin?.can ?? (() => true))\n\nconst pick = createModal<\n BlockType,\n {\n catalog: BlockType[]\n parent: BlockType | null\n allow: string[] | null\n tree: BlockNode[]\n groups: string[]\n blocksPath: string\n }\n>(BlockPicker)\n\nfunction set(next: BlockNode[]): void {\n model.value = next\n}\n\nasync function add(\n parentKey: string | null,\n field: string | null,\n slot: ScreenNode | null,\n): Promise<void> {\n const parent = parentKey ? locate(tree.value, parentKey) : null\n const parentType = parent\n ? (catalog.value.find((type) => type.slug === parent.node.type) ?? null)\n : null\n const allow =\n parentKey === null ? props.allow : ((slot?.props?.allow as string[] | undefined) ?? null)\n const max = parentKey === null ? props.max : ((slot?.props?.max as number | undefined) ?? null)\n const list =\n parentKey === null\n ? tree.value\n : parent && field\n ? ((parent.node.values[field] as BlockNode[] | undefined) ?? [])\n : []\n\n if (max !== null && max !== undefined && list.length >= max) return\n\n const type = await pick({\n catalog: catalog.value,\n parent: parentType,\n allow,\n tree: tree.value,\n groups: groups.value,\n blocksPath: props.blocksPath,\n })\n\n if (!type) return\n\n const node = makeNode(type.slug, structuredSample(type))\n set(insertNode(tree.value, parentKey, field, list.length, node))\n selectedKey.value = node.key\n}\n\n/** A new block starts from the sample rather than empty, so the page shows something. */\nfunction structuredSample(type: BlockType): Record<string, unknown> {\n const sample = type.content?.sample ?? {}\n const values: Record<string, unknown> = {}\n\n for (const [key, value] of Object.entries(sample)) {\n // Nested blocks in a sample are the author's own — a page starts with an empty container.\n if (!Array.isArray(value) || value.length === 0 || typeof value[0] !== 'object')\n values[key] = value\n }\n\n return values\n}\n\nfunction remove(key: string): void {\n if (selectedKey.value === key) selectedKey.value = null\n set(removeNode(tree.value, key))\n}\n\nfunction duplicate(key: string): void {\n const found = locate(tree.value, key)\n if (!found) return\n\n const copy = cloneNode(found.node)\n set(insertNode(tree.value, found.parent?.key ?? null, found.field, found.index + 1, copy))\n selectedKey.value = copy.key\n}\n\nfunction reorder(parentKey: string | null, field: string | null, list: BlockNode[]): void {\n set(replaceList(tree.value, parentKey, field, list))\n}\n\nfunction select(key: string): void {\n selectedKey.value = selectedKey.value === key ? null : key\n}\n\nfunction done(): void {\n selectedKey.value = null\n}\n\nfunction onValues(values: Record<string, unknown>): void {\n if (!selectedKey.value) return\n\n set(updateValues(tree.value, selectedKey.value, values))\n}\n\n/* After a field changed, the block is redrawn on the server and swapped into the page a\n moment after the last keystroke. A swap that finds no markers — the block is new, the\n page has not been saved since — asks the host to reload instead. */\nlet timer: ReturnType<typeof setTimeout> | undefined\n\nwatch(\n () => selected.value?.node.values,\n (values, before) => {\n if (!values || !before || !selectedType.value || !api || !preview) return\n\n const key = selectedKey.value\n const typeId = selectedType.value.id\n\n clearTimeout(timer)\n timer = setTimeout(() => {\n if (!key || !api) return\n\n void api\n .render(typeId, { values, key })\n .then((drawn) => {\n if (!previewEl.value?.replace(key, drawn.html)) previewEl.value?.refresh()\n })\n .catch(() => {})\n }, 300)\n },\n { deep: true },\n)\n\nfunction onKey(event: KeyboardEvent): void {\n if (event.key === 'Escape' && selectedKey.value) done()\n}\n\nonMounted(async () => {\n window.addEventListener('keydown', onKey)\n\n if (props.catalog === null && admin) {\n api = createBlocksApi(admin)\n\n try {\n loaded.value = await api.catalog()\n } catch (error) {\n toast.danger((error as { body?: { message?: string } }).body?.message ?? String(error))\n }\n } else if (admin) {\n api = createBlocksApi(admin)\n }\n})\n\nonBeforeUnmount(() => {\n clearTimeout(timer)\n window.removeEventListener('keydown', onKey)\n})\n\nconst formRoot = computed(() =>\n selectedType.value?.content ? formSchema(selectedType.value.content.schema) : [],\n)\n</script>\n\n<template>\n <div v-if=\"nested\" class=\"wx-blocks-nested\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('field.nested-note') }}</wx-text>\n </div>\n\n <!-- The host is the container the queries below measure: a query on an element's own\n class resolves against its nearest ancestor container, never against itself. -->\n <div v-else class=\"wx-blocks-host\" :class=\"{ 'is-fill': fill }\">\n <div\n class=\"wx-blocks\"\n :class=\"{\n 'is-editing': selected !== null,\n 'has-preview': preview !== null && preview.url.value !== null,\n }\"\n >\n <div class=\"wx-blocks__tree\">\n <div class=\"wx-blocks__panel-head\">\n <span class=\"wx-blocks__panel-title\">{{ t('field.blocks') }}</span>\n <wx-text size=\"sm\" tone=\"muted\">{{ tree.length }}</wx-text>\n </div>\n <blocks-tree\n :nodes=\"tree\"\n :catalog=\"catalog\"\n :selected=\"selectedKey\"\n :disabled=\"disabled\"\n @select=\"select\"\n @add=\"add\"\n @remove=\"remove\"\n @duplicate=\"duplicate\"\n @reorder=\"reorder\"\n />\n <wx-button\n v-if=\"!disabled && (max === null || tree.length < max)\"\n variant=\"outline\"\n block\n icon=\"plus\"\n class=\"wx-blocks__add\"\n @click=\"add(null, null, null)\"\n >\n {{ t('field.add') }}\n </wx-button>\n <wx-button\n v-if=\"preview && preview.url.value\"\n variant=\"text\"\n block\n class=\"wx-blocks__preview-button\"\n @click=\"previewEl?.open()\"\n >\n {{ t('field.preview') }}\n </wx-button>\n </div>\n\n <div v-if=\"selected\" class=\"wx-blocks__fields\">\n <div class=\"wx-blocks__panel-head\">\n <span class=\"wx-blocks__panel-title\">{{\n selectedType?.title ?? selected.node.type\n }}</span>\n <span class=\"wx-blocks__panel-extra\">\n <code>{{ selected.node.type }}</code>\n <wx-button size=\"sm\" variant=\"outline\" @click=\"done\"\n >{{ t('field.done') }} · Esc</wx-button\n >\n </span>\n </div>\n <div class=\"wx-blocks__form\">\n <wx-screen-renderer\n v-if=\"selectedType?.content\"\n :key=\"selected.node.key\"\n :model-value=\"selected.node.values\"\n :root=\"formRoot\"\n :types=\"types\"\n :translate=\"translate\"\n :can=\"can\"\n :disabled=\"disabled\"\n @update:model-value=\"onValues\"\n />\n <wx-text v-else size=\"sm\" tone=\"danger\">{{\n t('field.unknown-type', { type: selected.node.type })\n }}</wx-text>\n </div>\n </div>\n\n <div v-if=\"preview && preview.url.value\" class=\"wx-blocks__preview\">\n <blocks-preview\n ref=\"previewEl\"\n :url=\"preview.url.value\"\n :selected=\"selectedKey\"\n :mode=\"selected ? 'phone' : 'wide'\"\n :reload=\"preview.reload?.value ?? 0\"\n :fill=\"fill\"\n />\n </div>\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-blocks-host {\n container-type: inline-size;\n}\n\n/*\n * Filling the area it was given: the grid stretches to it, and each panel scrolls in itself.\n * The preview stops sticking — there is nothing to stick to when the page does not move — and\n * it is the panels that scroll instead.\n */\n.wx-blocks-host.is-fill,\n.wx-blocks-host.is-fill .wx-blocks {\n height: 100%;\n min-height: 0;\n}\n\n.wx-blocks-host.is-fill .wx-blocks {\n align-items: stretch;\n}\n\n.wx-blocks-host.is-fill .wx-blocks__tree,\n.wx-blocks-host.is-fill .wx-blocks__fields {\n overflow: auto;\n}\n\n.wx-blocks-host.is-fill .wx-blocks__preview {\n position: static;\n min-height: 0;\n}\n\n.wx-blocks {\n display: grid;\n grid-template-columns: minmax(220px, 260px) minmax(0, 1fr);\n gap: var(--wx-space-16);\n align-items: start;\n}\n\n.wx-blocks.is-editing {\n grid-template-columns: minmax(220px, 260px) minmax(0, 1fr);\n}\n\n.wx-blocks.is-editing.has-preview {\n grid-template-columns: minmax(220px, 260px) minmax(360px, 1fr) 420px;\n}\n\n.wx-blocks__tree,\n.wx-blocks__fields {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n padding: var(--wx-space-8);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n background: var(--wx-bg-surface);\n min-width: 0;\n}\n\n.wx-blocks__panel-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--wx-space-8);\n padding: var(--wx-space-4) var(--wx-space-6);\n}\n\n.wx-blocks__panel-title {\n font-weight: var(--wx-font-weight-semibold);\n}\n\n.wx-blocks__panel-extra {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n}\n\n.wx-blocks__form {\n padding: var(--wx-space-6);\n}\n\n.wx-blocks__preview {\n min-width: 0;\n position: sticky;\n top: var(--wx-space-12);\n}\n\n.wx-blocks__preview-button {\n display: none;\n}\n\n/* Below the width where three columns fit, the phone beside the form folds into a button\n that opens it full screen. The two-column state — the tree and the whole page — keeps its\n preview: a laptop's panel is narrower than three columns and wide enough for two. The\n threshold is the three columns at their minimum — 260 + 360 + 420 and the two gaps. */\n@container (max-width: 1080px) {\n .wx-blocks.is-editing.has-preview {\n grid-template-columns: minmax(220px, 260px) minmax(0, 1fr);\n }\n\n .wx-blocks.is-editing .wx-blocks__preview {\n display: none;\n }\n\n .wx-blocks.is-editing.has-preview .wx-blocks__preview-button {\n display: inline-flex;\n }\n\n /* Full screen still needs the node in the tree: it is drawn there, only unstuck. */\n .wx-blocks.is-editing .wx-blocks__preview:has(.is-fullscreen) {\n display: block;\n position: static;\n }\n}\n\n/* One column: the preview is a button in either state. */\n@container (max-width: 720px) {\n .wx-blocks,\n .wx-blocks.is-editing,\n .wx-blocks.has-preview,\n .wx-blocks.is-editing.has-preview {\n grid-template-columns: minmax(0, 1fr);\n }\n\n .wx-blocks__preview {\n display: none;\n }\n\n .wx-blocks.has-preview .wx-blocks__preview-button {\n display: inline-flex;\n }\n\n .wx-blocks__preview:has(.is-fullscreen) {\n display: block;\n position: static;\n }\n}\n\ncode {\n font-family: var(--wx-font-family-mono);\n font-size: var(--wx-font-size-xs);\n color: var(--wx-text-muted);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { WxBadge, WxText } from '@webx-ui/core'\nimport BlockThumb from './BlockThumb.vue'\nimport type { BlockType } from './types'\n\n/** One type in the list: its picture, its name, where it stands and which versions it has. */\ndefineProps<{ block: BlockType }>()\n\nconst emit = defineEmits<{ open: [block: BlockType] }>()\n\nconst t = useTranslate('webx-blocks')\n</script>\n\n<template>\n <button type=\"button\" class=\"wx-block-card\" @click=\"emit('open', block)\">\n <block-thumb :thumbnail=\"block.thumbnail\" :height=\"120\" />\n <div class=\"wx-block-card__body\">\n <div class=\"wx-block-card__title\">{{ block.title }}</div>\n <wx-text size=\"sm\" tone=\"muted\">\n <code>{{ block.slug }}</code>\n ·\n {{\n block.usage_count > 0\n ? t('page.on-pages', { count: block.usage_count })\n : t('page.not-used')\n }}\n </wx-text>\n <div class=\"wx-block-card__chips\">\n <wx-badge v-if=\"block.draft\" type=\"warning\" dot>\n {{ t('page.draft', { number: block.draft.number }) }}\n </wx-badge>\n <wx-badge v-if=\"block.published\" type=\"success\" dot>\n {{ t('page.live', { number: block.published.number }) }}\n </wx-badge>\n <wx-badge v-else type=\"default\">{{ t('page.never-published') }}</wx-badge>\n <wx-badge v-if=\"!block.is_enabled\" type=\"default\" variant=\"outline\">\n {{ t('page.hidden') }}\n </wx-badge>\n </div>\n </div>\n </button>\n</template>\n\n<style scoped>\n.wx-block-card {\n display: flex;\n flex-direction: column;\n width: 100%;\n padding: 0;\n overflow: hidden;\n text-align: start;\n font: inherit;\n color: inherit;\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n cursor: pointer;\n}\n\n.wx-block-card:hover,\n.wx-block-card:focus-visible {\n border-color: var(--wx-color-primary);\n outline: none;\n}\n\n.wx-block-card__body {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-6);\n padding: var(--wx-space-12) var(--wx-space-14);\n}\n\n.wx-block-card__title {\n font-weight: var(--wx-font-weight-semibold);\n}\n\n.wx-block-card__chips {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wx-space-6);\n}\n\ncode {\n font-family: var(--wx-font-family-mono);\n font-size: var(--wx-font-size-xs);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport { useAdmin, useTranslate } from '@webx-ui/module-admin'\nimport {\n toast,\n useModal,\n WxButton,\n WxDialog,\n WxFormItem,\n WxInput,\n WxSelect,\n WxSpace,\n} from '@webx-ui/core'\nimport { createBlocksApi } from './api'\nimport { useBlocksMessages } from './i18n'\nimport { groupLabel } from './schema'\nimport type { BlockType } from './types'\n\n/**\n * A new type needs three things to exist — a name, an identifier and a group — and gets an\n * empty draft to open. Everything else is the editor's job.\n */\nconst { resolve, dismiss, open } = useModal<BlockType>()\n\nconst context = useAdmin()\nconst api = createBlocksApi(context)\nuseBlocksMessages()\n\nconst t = useTranslate('webx-blocks')\n\nconst groups = computed<string[]>(() => {\n const meta = context.state.manifest?.modules.find((module) => module.id === 'blocks')?.meta\n\n return (meta?.groups as string[] | undefined) ?? ['content']\n})\n\nconst form = ref({ title: '', slug: '', group: groups.value[0] ?? 'content' })\nconst errors = ref<Record<string, string[]>>({})\nconst saving = ref(false)\nconst slugTouched = ref(false)\n\nconst groupOptions = computed(() =>\n groups.value.map((id) => ({ value: id, label: groupLabel(id, t) })),\n)\n\n/** A slug from the name, until the person types one of their own. Latin only: the identifier is code. */\nfunction slugify(text: string): string {\n return text\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .replace(/^[^a-z]+/, '')\n .slice(0, 64)\n}\n\nwatch(\n () => form.value.title,\n (title) => {\n if (!slugTouched.value) form.value.slug = slugify(title)\n },\n)\n\nfunction errorOf(field: string): string | undefined {\n return errors.value[field]?.[0]\n}\n\nasync function save(): Promise<void> {\n saving.value = true\n errors.value = {}\n\n try {\n resolve(await api.create(form.value))\n } catch (error) {\n const body = (error as { body?: { errors?: Record<string, string[]>; message?: string } }).body\n\n if (body?.errors) {\n errors.value = body.errors\n } else {\n toast.danger(body?.message ?? t('page.failed'))\n }\n } finally {\n saving.value = false\n }\n}\n</script>\n\n<template>\n <wx-dialog v-model:open=\"open\" :title=\"t('page.new')\" :width=\"520\">\n <div class=\"wx-block-create\">\n <wx-form-item :label=\"t('page.title')\" :error=\"errorOf('title')\">\n <wx-input v-model=\"form.title\" autofocus />\n </wx-form-item>\n\n <wx-form-item\n :label=\"t('page.identifier')\"\n :help=\"t('page.identifier-help')\"\n :error=\"errorOf('slug')\"\n >\n <wx-input v-model=\"form.slug\" placeholder=\"hero\" @input=\"slugTouched = true\" />\n </wx-form-item>\n\n <wx-form-item :label=\"t('page.group')\" :help=\"t('page.group-help')\" :error=\"errorOf('group')\">\n <wx-select v-model=\"form.group\" :options=\"groupOptions\" />\n </wx-form-item>\n </div>\n\n <template #footer>\n <wx-space size=\"sm\">\n <wx-button variant=\"outline\" @click=\"dismiss()\">{{ t('page.cancel') }}</wx-button>\n <wx-button type=\"primary\" :loading=\"saving\" @click=\"save\">{{ t('page.create') }}</wx-button>\n </wx-space>\n </template>\n </wx-dialog>\n</template>\n\n<style scoped>\n.wx-block-create {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-12);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onMounted, ref } from 'vue'\nimport { useRouter } from 'vue-router'\nimport { useAdmin, useTranslate } from '@webx-ui/module-admin'\nimport {\n createModal,\n toast,\n WxAlert,\n WxButton,\n WxEmpty,\n WxHeading,\n WxInput,\n WxSkeleton,\n WxSkeletonItem,\n} from '@webx-ui/core'\nimport { createBlocksApi } from './api'\nimport BlockCard from './BlockCard.vue'\nimport BlockCreateDialog from './BlockCreateDialog.vue'\nimport { useBlocksMessages } from './i18n'\nimport { groupLabel } from './schema'\nimport type { BlocksMeta, BlockType } from './types'\n\n/**\n * The section: every type as a card with a live thumbnail, grouped the way the picker groups\n * them. Cards rather than a table because a block is recognised by its picture — \"Section\"\n * says nothing about whether it is a full-width band or a container with columns.\n */\nconst props = withDefaults(defineProps<{ base?: string }>(), { base: '/blocks' })\n\nconst context = useAdmin()\nconst api = createBlocksApi(context)\nconst router = useRouter()\nuseBlocksMessages()\n\nconst t = useTranslate('webx-blocks')\n\nconst blocks = ref<BlockType[]>([])\nconst loading = ref(true)\nconst search = ref('')\n\nconst create = createModal<BlockType, Record<string, never>>(BlockCreateDialog)\n\nconst meta = computed<BlocksMeta>(() => {\n const found = context.state.manifest?.modules.find((module) => module.id === 'blocks')?.meta\n\n return {\n groups: (found?.groups as string[] | undefined) ?? [],\n editing: (found?.editing as boolean | undefined) ?? true,\n provides: (found?.provides as string[] | undefined) ?? [],\n }\n})\n\nconst canManage = computed(() => context.can('blocks.manage') && meta.value.editing)\n\nconst title = computed(\n () =>\n context.state.manifest?.modules.find((module) => module.id === 'blocks')?.title ??\n t('module.title'),\n)\n\nconst shown = computed(() => {\n const needle = search.value.trim().toLowerCase()\n\n if (needle === '') return blocks.value\n\n return blocks.value.filter(\n (block) =>\n block.title.toLowerCase().includes(needle) ||\n block.slug.includes(needle) ||\n (block.description ?? '').toLowerCase().includes(needle),\n )\n})\n\n/** The groups in the site's order, then any a type named that the config does not. */\nconst groups = computed(() => {\n const order = [...meta.value.groups]\n\n for (const block of shown.value) {\n if (!order.includes(block.group)) order.push(block.group)\n }\n\n const sections = order\n .map((id) => ({\n id,\n label: groupLabel(id, t),\n blocks: shown.value.filter((b) => b.group === id),\n }))\n .filter((section) => section.blocks.length > 0)\n\n // A handful of types needs no headings; a search wants a flat list.\n const flat = shown.value.length <= 5 || search.value.trim() !== '' || sections.length < 2\n\n return flat ? [{ id: '', label: '', blocks: shown.value }] : sections\n})\n\nasync function load(): Promise<void> {\n loading.value = true\n\n try {\n blocks.value = await api.list()\n } catch (error) {\n toast.danger((error as { body?: { message?: string } }).body?.message ?? String(error))\n } finally {\n loading.value = false\n }\n}\n\nfunction open(block: BlockType): void {\n void router.push(`${props.base}/${block.id}`)\n}\n\nasync function add(): Promise<void> {\n const block = await create({})\n\n if (block) open(block)\n}\n\nonMounted(load)\n</script>\n\n<template>\n <div class=\"wx-blocks-page\">\n <div class=\"wx-blocks-page__head\">\n <wx-heading :level=\"2\">{{ title }}</wx-heading>\n <wx-button v-if=\"canManage\" type=\"primary\" icon=\"plus\" @click=\"add\">\n {{ t('page.new') }}\n </wx-button>\n </div>\n\n <wx-alert\n v-if=\"!meta.editing\"\n type=\"info\"\n variant=\"soft\"\n :description=\"t('page.editing-off')\"\n />\n\n <!-- The search stands over the grid it narrows, not in the corner beside the button. -->\n <wx-input\n v-if=\"loading || blocks.length > 0\"\n v-model=\"search\"\n class=\"wx-blocks-page__search\"\n :placeholder=\"t('page.search')\"\n clearable\n />\n\n <!-- The placeholder is shaped like what is coming: a row of cards, not a paragraph. -->\n <wx-skeleton v-if=\"loading\">\n <template #template>\n <div class=\"wx-blocks-page__cards\">\n <div v-for=\"n in 4\" :key=\"n\" class=\"wx-blocks-page__ghost\">\n <wx-skeleton-item variant=\"image\" :height=\"120\" class=\"wx-blocks-page__ghost-thumb\" />\n <div class=\"wx-blocks-page__ghost-body\">\n <wx-skeleton-item variant=\"title\" width=\"45%\" />\n <wx-skeleton-item variant=\"text\" width=\"70%\" />\n <wx-skeleton-item variant=\"button\" width=\"64px\" height=\"22px\" />\n </div>\n </div>\n </div>\n </template>\n </wx-skeleton>\n\n <wx-empty\n v-else-if=\"blocks.length === 0\"\n icon=\"grid\"\n :title=\"t('page.empty')\"\n :description=\"t('page.empty-help')\"\n />\n\n <template v-else>\n <section v-for=\"group in groups\" :key=\"group.id\" class=\"wx-blocks-page__group\">\n <div v-if=\"group.label\" class=\"wx-blocks-page__group-title\">{{ group.label }}</div>\n <div class=\"wx-blocks-page__cards\">\n <block-card v-for=\"block in group.blocks\" :key=\"block.id\" :block=\"block\" @open=\"open\" />\n </div>\n </section>\n </template>\n </div>\n</template>\n\n<style scoped>\n.wx-blocks-page {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-16);\n container-type: inline-size;\n}\n\n.wx-blocks-page__head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--wx-space-12);\n flex-wrap: wrap;\n}\n\n.wx-blocks-page__search {\n max-width: 360px;\n}\n\n.wx-blocks-page__ghost {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n}\n\n.wx-blocks-page__ghost-thumb {\n border-radius: 0;\n}\n\n.wx-blocks-page__ghost-body {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n padding: var(--wx-space-12) var(--wx-space-14);\n}\n\n.wx-blocks-page__group {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-12);\n}\n\n.wx-blocks-page__group-title {\n font-size: var(--wx-font-size-xs);\n font-weight: var(--wx-font-weight-semibold);\n letter-spacing: 0.06em;\n text-transform: uppercase;\n color: var(--wx-text-muted);\n}\n\n.wx-blocks-page__cards {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));\n gap: var(--wx-space-16);\n}\n</style>\n","import type { AdminModule } from '@webx-ui/module-admin'\nimport BlockEditorPage from './BlockEditorPage.vue'\nimport BlocksField from './BlocksField.vue'\nimport BlocksPage from './BlocksPage.vue'\n\nexport interface BlocksOptions {\n /** Where the section lives inside the panel. */\n path?: string\n}\n\n/**\n * The block constructor as a section of the panel, and `wx-blocks` as a field any screen can\n * put on an entity.\n *\n * The id matches the module the server reports, which is what makes the entry appear in the\n * navigation: the section shows up when both halves are installed.\n */\nexport function blocks(options: BlocksOptions = {}): AdminModule {\n const path = options.path ?? '/blocks'\n\n return {\n id: 'blocks',\n path,\n routes: [\n { path, name: 'webx.blocks', component: BlocksPage, props: { base: path } },\n {\n path: `${path}/:id(\\\\d+)`,\n name: 'webx.blocks.edit',\n component: BlockEditorPage,\n props: { base: path },\n },\n ],\n // What a screen means by `wx-blocks`: the content of an entity as a tree of blocks. A\n // nested field, so the renderer hands it the node and the way down — though it never\n // draws its children through the renderer; it needs the node for `props.allow` alone.\n types: {\n 'wx-blocks': {\n component: BlocksField,\n kind: 'field',\n nested: true,\n bind: () => ({ blocksPath: path }),\n },\n },\n }\n}\n"],"names":["createBlocksApi","admin","base","data","body","id","input","number","props","__props","t","useTranslate","mine","computed","lint","passed","codes","lines","_openBlock","_createElementBlock","_hoisted_1","_hoisted_2","_createVNode","_unref","WxIcon","_createElementVNode","_Fragment","_createTextVNode","_toDisplayString","_renderList","line","emit","__emit","context","useAdmin","api","versions","ref","load","state","version","when","restore","confirm","block","toast","error","onMounted","watch","_createBlock","WxSkeleton","_hoisted_3","WxText","WxBadge","WxButton","$event","SELECTED_CLASS","STYLE_ID","findRange","root","key","walker","start","node","text","replaceBlock","doc","html","range","parent","template","anchor","next","done","fragment","inserted","runtime","child","blockElement","highlightBlock","ensureStyle","element","style","stageDocument","escapeAttribute","frame","value","widths","width","box","boxWidth","useElementWidth","contentHeight","scale","srcdoc","measure","onLoad","frameStyle","clipStyle","WxSegmented","isNode","isNodeList","newKey","makeNode","type","values","locate","tree","find","list","field","index","name","found","walk","visit","depth","countType","slug","count","typesIn","seen","nestedFields","schema","cloneNode","clone","listAt","parentKey","existing","insertNode","removeNode","updateValues","replaceList","blocksMessages","seeded","useBlocksMessages","i18n","GIVEN","lintBlock","content","lints","missing","undeclared","stray","bare","prefix","selector","selectors","few","source","withoutComments","media","lineAt","fieldIds","ids","declared","match","used","styles","prelude","trimmed","raw","comment","offset","names","formSchema","groupLabel","words","route","useRoute","router","useRouter","usage","loading","saving","publishing","tab","meta","module","canManage","settings","reactive","schemaText","schemaError","snapshot","errors","refusal","stage","current","dirty","groupOptions","group","sampleModel","collectIds","nodes","take","loaded","stored","onSchemaText","parsed","timer","pending","redraw","render","ticket","drawn","templateEditor","pill","insertField","editor","save","before","saved","publish","remove","refusalError","shownUsage","errorOf","leaveGuard","event","onBeforeUnmount","WxCard","_hoisted_4","_component_router_link","_cache","_vModelText","_hoisted_6","WxAlert","_hoisted_7","_hoisted_8","WxTabs","WxTab","_hoisted_9","WxCodeEditor","_hoisted_10","BlockChecks","_hoisted_12","_hoisted_13","_hoisted_14","_hoisted_15","_hoisted_16","_hoisted_17","WxFormItem","WxInput","WxSelect","WxTextarea","WxInputNumber","WxTagsInput","WxSwitch","_hoisted_18","BlockHistory","_hoisted_19","BlockStage","WxScreenRenderer","_hoisted_20","entity","resolve","dismiss","open","useModal","search","allowedHere","parentAllows","typeAllows","options","exhausted","shown","needle","sections","order","grouped","o","section","emptyText","allowed","WxDialog","WxEmpty","option","_normalizeClass","BlockThumb","_hoisted_5","fullscreen","fullWidth","ready","label","page","replace","refresh","onKey","__expose","typeOf","titleOf","fieldsOf","childrenIn","iconOf","WxSortableList","_withCtx","item","WxAction","slot","_component_blocks_tree","p","f","n","blocksPreviewKey","provideBlocksPreview","preview","provide","useBlocksPreview","inject","blocksRootKey","model","_useModel","nested","adminKey","catalog","selectedKey","selected","selectedType","previewEl","groups","m","self","getCurrentInstance","types","coreTypes","translate","can","pick","createModal","BlockPicker","set","add","parentType","allow","max","structuredSample","sample","duplicate","copy","reorder","select","onValues","typeId","formRoot","BlocksTree","BlocksPreview","form","slugTouched","slugify","title","WxSpace","blocks","create","BlockCreateDialog","b","WxHeading","WxSkeletonItem","BlockCard","path","BlocksPage","BlockEditorPage","BlocksField"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/api.ts","../src/BlockChecks.vue","../src/BlockHistory.vue","../src/frame.ts","../src/BlockStage.vue","../src/content.ts","../src/messages.ts","../src/i18n.ts","../src/lint.ts","../src/schema.ts","../src/BlockEditorPage.vue","../src/BlockThumb.vue","../src/BlockPicker.vue","../src/BlocksPreview.vue","../src/BlocksTree.vue","../src/preview.ts","../src/BlocksField.vue","../src/BlockCard.vue","../src/BlockCreateDialog.vue","../src/BlocksPage.vue","../src/module.ts"],"sourcesContent":["import type { AdminContext } from '@webx-ui/module-admin'\nimport type {\n BlockInput,\n BlockType,\n BlockUsage,\n BlockVersion,\n BlockVersionMeta,\n RenderInput,\n RenderResult,\n} from './types'\n\nexport interface BlocksApi {\n /** Every type, without content: the section's list. */\n list(): Promise<BlockType[]>\n /** The published types with their content: what the constructor and the picker read. */\n catalog(): Promise<BlockType[]>\n get(id: number): Promise<BlockType>\n create(input: BlockInput): Promise<BlockType>\n update(id: number, input: BlockInput): Promise<BlockType>\n remove(id: number): Promise<void>\n publish(id: number): Promise<BlockType>\n render(id: number, input?: RenderInput): Promise<RenderResult>\n usage(id: number): Promise<BlockUsage[]>\n versions(id: number): Promise<BlockVersionMeta[]>\n version(id: number, number: number): Promise<BlockVersion>\n restore(id: number, number: number): Promise<BlockType>\n}\n\n/** Everything under `/blocks`, below the panel's API path. */\nexport function createBlocksApi(admin: AdminContext): BlocksApi {\n const base = `${admin.apiPath}/blocks`\n const data = <T>(body: { data: T }): T => body.data\n\n return {\n list: () => admin.http.get<{ data: BlockType[] }>(base).then(data),\n catalog: () => admin.http.get<{ data: BlockType[] }>(`${base}/catalog`).then(data),\n get: (id) => admin.http.get<{ data: BlockType }>(`${base}/${id}`).then(data),\n create: (input) => admin.http.post<{ data: BlockType }>(base, input).then(data),\n update: (id, input) => admin.http.put<{ data: BlockType }>(`${base}/${id}`, input).then(data),\n remove: (id) => admin.http.delete<void>(`${base}/${id}`),\n publish: (id) => admin.http.post<{ data: BlockType }>(`${base}/${id}/publish`, {}).then(data),\n render: (id, input = {}) =>\n admin.http.post<{ data: RenderResult }>(`${base}/${id}/render`, input).then(data),\n usage: (id) => admin.http.get<{ data: BlockUsage[] }>(`${base}/${id}/usage`).then(data),\n versions: (id) =>\n admin.http.get<{ data: BlockVersionMeta[] }>(`${base}/${id}/versions`).then(data),\n version: (id, number) =>\n admin.http.get<{ data: BlockVersion }>(`${base}/${id}/versions/${number}`).then(data),\n restore: (id, number) =>\n admin.http\n .post<{ data: BlockType }>(`${base}/${id}/versions/${number}/restore`, {})\n .then(data),\n }\n}\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { WxIcon } from '@webx-ui/core'\nimport type { Lint } from './types'\n\n/**\n * The strip under an editor: what was noticed, and what was not — a green line for every\n * check that passed, so that silence reads as \"checked\" rather than \"not looked at\".\n */\nconst props = defineProps<{\n /** Which editor this strip sits under. */\n file: 'template' | 'styles' | 'script' | 'schema'\n lints: Lint[]\n slug: string\n /** A refusal from publishing, shown first and in red. */\n error?: { message: string; line: number | null; where?: string | null } | null\n}>()\n\nconst t = useTranslate('webx-blocks')\n\nconst mine = computed(() => props.lints.filter((lint) => lint.file === props.file))\n\nconst passed = computed(() => {\n const codes = new Set(mine.value.map((lint) => lint.code))\n const lines: string[] = []\n\n if (props.file === 'template') {\n if (!codes.has('no-marker')) lines.push(t('checks.ok-marker'))\n if (!codes.has('variables-missing')) lines.push(t('checks.ok-variables'))\n }\n\n if (props.file === 'styles') {\n if (!codes.has('stray-selectors')) lines.push(t('checks.ok-prefix', { slug: props.slug }))\n if (!codes.has('bare-selectors')) lines.push(t('checks.ok-bare'))\n if (!codes.has('media-query')) lines.push(t('checks.ok-container'))\n }\n\n return lines\n})\n</script>\n\n<template>\n <div class=\"wx-block-checks\">\n <div v-if=\"error\" class=\"wx-block-checks__line is-error\">\n <wx-icon name=\"close-circle\" />\n <span>\n {{ error.message }}\n <template v-if=\"error.line !== null\">\n · {{ t('page.line', { line: error.line }) }}</template\n >\n <template v-if=\"error.where\"> · {{ error.where }}</template>\n </span>\n </div>\n <div v-for=\"lint in mine\" :key=\"lint.code\" class=\"wx-block-checks__line is-warning\">\n <wx-icon name=\"warning\" />\n <span>\n {{ lint.message }}\n <template v-if=\"lint.line !== null\"> · {{ t('page.line', { line: lint.line }) }}</template>\n </span>\n </div>\n <div v-for=\"line in passed\" :key=\"line\" class=\"wx-block-checks__line is-ok\">\n <wx-icon name=\"check\" />\n <span>{{ line }}</span>\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-block-checks {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-4);\n padding: var(--wx-space-8) var(--wx-space-12);\n font-size: var(--wx-font-size-sm);\n border-block-start: 1px solid var(--wx-border-muted);\n}\n\n.wx-block-checks__line {\n display: flex;\n gap: var(--wx-space-8);\n align-items: flex-start;\n}\n\n.wx-block-checks__line .wx-icon {\n flex: none;\n margin-block-start: 2px;\n}\n\n.is-ok {\n color: var(--wx-text-muted);\n}\n\n.is-ok .wx-icon {\n color: var(--wx-color-success);\n}\n\n.is-warning {\n color: var(--wx-color-warning);\n}\n\n.is-error {\n color: var(--wx-color-danger);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { onMounted, ref, watch } from 'vue'\nimport { useAdmin, useErrorText, useTranslate, WxDate } from '@webx-ui/module-admin'\nimport { confirm, toast, WxBadge, WxButton, WxSkeleton, WxText } from '@webx-ui/core'\nimport { createBlocksApi } from './api'\nimport type { BlockType, BlockVersionMeta } from './types'\n\n/**\n * A version per save, newest first, each with who and why. Restoring makes the old version a\n * new draft — publishing it is the same separate step it always is.\n */\nconst props = defineProps<{ block: BlockType; canManage: boolean }>()\n\nconst emit = defineEmits<{ restored: [block: BlockType] }>()\n\nconst context = useAdmin()\nconst api = createBlocksApi(context)\nconst t = useTranslate('webx-blocks')\n/* Not the server's `message`: the panel says how a request failed in its own words (§13.3). */\nconst message = useErrorText()\n\nconst versions = ref<BlockVersionMeta[] | null>(null)\n\nasync function load(): Promise<void> {\n versions.value = await api.versions(props.block.id)\n}\n\nfunction state(version: BlockVersionMeta): 'draft' | 'live' | 'replaced' {\n if (props.block.draft?.number === version.number) return 'draft'\n if (props.block.published?.number === version.number) return 'live'\n\n return 'replaced'\n}\n\nasync function restore(version: BlockVersionMeta): Promise<void> {\n const agreed = await confirm({\n title: t('page.restore-title', { number: version.number }),\n message: t('page.restore-text'),\n confirmText: t('page.restore'),\n cancelText: t('page.cancel'),\n })\n\n if (!agreed) return\n\n try {\n const block = await api.restore(props.block.id, version.number)\n toast.success(t('page.restored', { number: block.draft?.number ?? version.number }))\n emit('restored', block)\n await load()\n } catch (error) {\n toast.danger(message(error))\n }\n}\n\nonMounted(load)\nwatch(\n () => [props.block.draft?.number, props.block.published?.number],\n () => void load(),\n)\n</script>\n\n<template>\n <div class=\"wx-block-history\">\n <!-- Where a row would stand: see the same note on the pages history. -->\n <wx-skeleton v-if=\"versions === null\" class=\"wx-block-history__ghost\" :rows=\"3\" />\n <div v-for=\"version in versions\" v-else :key=\"version.number\" class=\"wx-block-history__row\">\n <code class=\"wx-block-history__number\">{{\n t('page.version', { number: version.number })\n }}</code>\n <div class=\"wx-block-history__who\">\n <wx-text>{{ t(`page.version-${state(version)}`) }}</wx-text>\n <wx-text size=\"sm\" tone=\"muted\">\n <wx-date v-if=\"version.created_at\" :value=\"version.created_at\" />\n · {{ version.author ?? t(`page.source-${version.source}`) }}\n <template v-if=\"version.comment\"> · {{ version.comment }}</template>\n </wx-text>\n </div>\n <wx-badge v-if=\"state(version) === 'draft'\" type=\"warning\" dot>{{\n t('page.version-draft')\n }}</wx-badge>\n <wx-badge v-else-if=\"state(version) === 'live'\" type=\"success\" dot>{{\n t('page.version-live')\n }}</wx-badge>\n <wx-button\n v-if=\"canManage && state(version) === 'replaced'\"\n size=\"sm\"\n variant=\"outline\"\n @click=\"restore(version)\"\n >\n {{ t('page.restore') }}\n </wx-button>\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-block-history {\n display: flex;\n flex-direction: column;\n}\n\n.wx-block-history__ghost {\n padding: var(--wx-space-10) var(--wx-space-12);\n}\n\n.wx-block-history__row {\n display: flex;\n align-items: center;\n gap: var(--wx-space-12);\n padding: var(--wx-space-10) var(--wx-space-12);\n border-block-end: 1px solid var(--wx-border-muted);\n flex-wrap: wrap;\n}\n\n.wx-block-history__row:last-child {\n border-block-end: 0;\n}\n\n.wx-block-history__number {\n width: 40px;\n font-family: var(--wx-font-family-mono);\n font-size: var(--wx-font-size-sm);\n color: var(--wx-text-muted);\n}\n\n.wx-block-history__who {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-width: 160px;\n}\n</style>\n","/**\n * The preview is a page of the site in an iframe, and the panel's hold on it is a pair of\n * comments around every block — `<!--wx:key-->…<!--/wx:key-->` — printed by the renderer in\n * preview mode. Finding a block is walking the comments; replacing one is swapping what sits\n * between the pair; highlighting one is a class on the first element after the opener.\n *\n * The panel and the site are one application on one domain, so the frame's document is\n * reachable and nothing has to be injected into the site's markup beyond one stylesheet.\n */\n\nexport const SELECTED_CLASS = 'wx-preview-selected'\nexport const HOVER_CLASS = 'wx-preview-hover'\n\nconst STYLE_ID = 'wx-preview-style'\n\nexport interface MarkerRange {\n start: Comment\n end: Comment\n}\n\n/** The pair of markers around a block, or null when the page does not hold it. */\nexport function findRange(root: Node, key: string): MarkerRange | null {\n const doc = root.ownerDocument ?? (root as Document)\n const walker = doc.createTreeWalker(root, 128 /* NodeFilter.SHOW_COMMENT */)\n let start: Comment | null = null\n\n for (let node = walker.nextNode(); node; node = walker.nextNode()) {\n const text = (node as Comment).data.trim()\n\n if (start === null && text === `wx:${key}`) {\n start = node as Comment\n } else if (start !== null && text === `/wx:${key}`) {\n return { start, end: node as Comment }\n }\n }\n\n return null\n}\n\n/**\n * Swap the block's markup — markers included, since the new HTML carries its own — and let\n * the runtime mount whatever script the new markup needs. False when the key is not on the\n * page, which means the page has to be reloaded rather than patched.\n */\nexport function replaceBlock(doc: Document, key: string, html: string): boolean {\n const range = findRange(doc, key)\n\n if (!range) return false\n\n const parent = range.start.parentNode\n\n if (!parent) return false\n\n const template = doc.createElement('template')\n template.innerHTML = html\n\n // What follows the block stays where it is; the new markup lands in front of it.\n const anchor = range.end.nextSibling\n let node: Node | null = range.start\n\n while (node) {\n const next: Node | null = node.nextSibling\n const done = node === range.end\n parent.removeChild(node)\n if (done) break\n node = next\n }\n\n const fragment = template.content\n const inserted = Array.from(fragment.childNodes)\n parent.insertBefore(fragment, anchor)\n\n const runtime = (doc.defaultView as (Window & { webx?: { mount?: (root: Node) => void } }) | null)\n ?.webx\n\n if (runtime?.mount) {\n for (const child of inserted) {\n if (child.nodeType === 1) runtime.mount(child)\n }\n }\n\n return true\n}\n\n/** The first element a block prints — where a highlight goes. */\nexport function blockElement(root: Node, key: string): Element | null {\n const range = findRange(root, key)\n\n if (!range) return null\n\n for (let node = range.start.nextSibling; node && node !== range.end; node = node.nextSibling) {\n if (node.nodeType === 1) return node as Element\n }\n\n return null\n}\n\n/** Mark one block as the selected one, and nothing else. Null clears the selection. */\nexport function highlightBlock(doc: Document, key: string | null): Element | null {\n ensureStyle(doc)\n\n for (const element of Array.from(doc.querySelectorAll(`.${SELECTED_CLASS}`))) {\n element.classList.remove(SELECTED_CLASS)\n }\n\n if (key === null) return null\n\n const element = blockElement(doc, key)\n element?.classList.add(SELECTED_CLASS)\n\n return element\n}\n\n/** Mark one block as the one under the pointer. Null clears it. */\nexport function hoverBlock(doc: Document, key: string | null): void {\n ensureStyle(doc)\n\n for (const element of Array.from(doc.querySelectorAll(`.${HOVER_CLASS}`))) {\n element.classList.remove(HOVER_CLASS)\n }\n\n if (key === null) return\n\n blockElement(doc, key)?.classList.add(HOVER_CLASS)\n}\n\n/**\n * Which block an element inside the page belongs to — the innermost one, since a block nested\n * in a container is what somebody pointing at it means.\n *\n * The markers are comments among an element's siblings rather than around it, so this walks\n * back through the previous siblings counting closers: a `/wx:` met on the way out belongs to\n * a block that has already ended, and its opener is not ours. Nothing found at this level\n * means the search carries on in the parent.\n */\nexport function keyAt(node: Node | null): string | null {\n let element: Element | null =\n node?.nodeType === 1 ? (node as Element) : (node?.parentElement ?? null)\n\n while (element) {\n let depth = 0\n\n for (\n let sibling: Node | null = element.previousSibling;\n sibling;\n sibling = sibling.previousSibling\n ) {\n if (sibling.nodeType !== 8) continue\n\n const text = (sibling as Comment).data.trim()\n\n if (text.startsWith('/wx:')) {\n depth += 1\n } else if (text.startsWith('wx:')) {\n if (depth === 0) return text.slice(3)\n\n depth -= 1\n }\n }\n\n element = element.parentElement\n }\n\n return null\n}\n\n/** What was bound to the page, so that a reload can let go of the old document. */\nexport interface FrameBinding {\n release(): void\n}\n\n/**\n * Make the preview a picture of the page rather than the page itself.\n *\n * Every pointer event is taken at the document, in the capture phase, and goes no further:\n * stopped there it never reaches a link, a form or a block's own script, so nothing in the\n * preview navigates, submits or opens anything. What a click does instead is choose the block\n * it landed in, which is the one thing the editor wants from it.\n *\n * Bound per document: an iframe that reloads gets a new one, and the old binding is released\n * with it.\n */\nexport function bindFrame(\n doc: Document,\n handlers: { select: (key: string | null) => void },\n): FrameBinding {\n ensureStyle(doc)\n\n let hovered: string | null = null\n\n function swallow(event: Event): void {\n event.preventDefault()\n event.stopPropagation()\n }\n\n function onClick(event: MouseEvent): void {\n swallow(event)\n handlers.select(keyAt(event.target as Node | null))\n }\n\n function onMove(event: MouseEvent): void {\n const key = keyAt(event.target as Node | null)\n\n if (key === hovered) return\n\n hovered = key\n hoverBlock(doc, key)\n }\n\n function onLeave(): void {\n hovered = null\n hoverBlock(doc, null)\n }\n\n doc.addEventListener('click', onClick, true)\n doc.addEventListener('auxclick', swallow, true)\n doc.addEventListener('submit', swallow, true)\n doc.addEventListener('dragstart', swallow, true)\n doc.addEventListener('mousemove', onMove, true)\n // Not in the capture phase: `mouseleave` does not bubble, so a capturing listener here\n // would be told about every element the pointer leaves on its way across the page.\n doc.addEventListener('mouseleave', onLeave)\n\n return {\n release() {\n doc.removeEventListener('click', onClick, true)\n doc.removeEventListener('auxclick', swallow, true)\n doc.removeEventListener('submit', swallow, true)\n doc.removeEventListener('dragstart', swallow, true)\n doc.removeEventListener('mousemove', onMove, true)\n doc.removeEventListener('mouseleave', onLeave)\n },\n }\n}\n\n/** The one thing the panel adds to the site's markup: how a block looks under the editor. */\nfunction ensureStyle(doc: Document): void {\n if (doc.getElementById(STYLE_ID)) return\n\n const style = doc.createElement('style')\n style.id = STYLE_ID\n // Inside the outline rather than around it: a block flush with the edge of the page would\n // otherwise have half of its mark cut off by the window. The hover is the thinner of the\n // two, so that pointing at the selected block does not look like selecting another one.\n style.textContent =\n `.${SELECTED_CLASS}{outline:2px solid #427edd;outline-offset:-2px;}` +\n `.${HOVER_CLASS}:not(.${SELECTED_CLASS}){outline:1px solid #427edd;outline-offset:-1px;cursor:pointer;}`\n ;(doc.head ?? doc.documentElement).appendChild(style)\n}\n\nexport interface StageInput {\n html: string\n styles: string\n /** The script wrapped for the runtime, or nothing. */\n script?: string | null\n /** Where the runtime is served; skipped when there is no script to run. */\n runtime?: string | null\n /** Resolves relative addresses the block prints — images, links — against the site. */\n base?: string | null\n /** Styles the site's layout would give the page: fonts, the ground colour. */\n frame?: string | null\n}\n\n/**\n * A whole document for the editor's stage: the block on its own, with its styles, its script\n * and the runtime, and nothing of the panel. `srcdoc` takes it.\n */\nexport function stageDocument(input: StageInput): string {\n const base = input.base ? `<base href=\"${escapeAttribute(input.base)}\">` : ''\n const frame = input.frame ? `<style>${input.frame}</style>` : ''\n const runtime =\n input.script && input.runtime\n ? `<script src=\"${escapeAttribute(input.runtime)}\"></script><script>${input.script}</script>`\n : ''\n\n return (\n `<!doctype html><html><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">${base}` +\n `<style>html,body{margin:0}body{container-type:inline-size}</style>${frame}<style>${input.styles}</style></head>` +\n `<body>${input.html}${runtime}</body></html>`\n )\n}\n\nfunction escapeAttribute(value: string): string {\n return value.replace(/&/g, '&amp;').replace(/\"/g, '&quot;').replace(/</g, '&lt;')\n}\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { useElementWidth, WxSegmented, WxSkeleton } from '@webx-ui/core'\nimport { stageDocument } from './frame'\n\n/**\n * The block on its own, at a chosen width: a desktop scaled down to fit the column, a tablet\n * or a phone at one to one. The document is the block, its styles, its script and the\n * runtime, and nothing of the panel — an iframe, so the block's CSS stays the block's.\n */\nconst props = withDefaults(\n defineProps<{\n html: string\n styles: string\n script?: string | null\n runtime?: string | null\n loading?: boolean\n }>(),\n { script: null, runtime: null, loading: false },\n)\n\nconst t = useTranslate('webx-blocks')\n\nconst widths = computed(() => [\n { value: 1280, label: t('page.width-desktop') },\n { value: 834, label: t('page.width-tablet') },\n { value: 390, label: t('page.width-phone') },\n])\n\nconst width = ref<number>(1280)\nconst box = ref<HTMLElement | null>(null)\nconst frame = ref<HTMLIFrameElement | null>(null)\nconst boxWidth = useElementWidth(box)\nconst contentHeight = ref(360)\n\nconst scale = computed(() => {\n if (boxWidth.value === 0) return 1\n\n return Math.min(1, boxWidth.value / width.value)\n})\n\nconst srcdoc = computed(() =>\n stageDocument({\n html: props.html,\n styles: props.styles,\n script: props.script,\n runtime: props.runtime,\n base: typeof location === 'undefined' ? null : location.origin + '/',\n }),\n)\n\n/** The frame grows to its content: a stage that scrolls inside itself hides half the block. */\nfunction measure(): void {\n const doc = frame.value?.contentDocument\n\n if (!doc?.documentElement) return\n\n contentHeight.value = Math.max(120, doc.documentElement.scrollHeight)\n}\n\nfunction onLoad(): void {\n measure()\n // Fonts and images arrive after `load` of the document itself.\n setTimeout(measure, 300)\n}\n\nwatch(width, () => setTimeout(measure, 50))\n\nconst frameStyle = computed(() => ({\n width: `${width.value}px`,\n height: `${contentHeight.value}px`,\n transform: `scale(${scale.value})`,\n}))\n\nconst clipStyle = computed(() => ({\n width: `${Math.round(width.value * scale.value)}px`,\n height: `${Math.round(contentHeight.value * scale.value)}px`,\n}))\n</script>\n\n<template>\n <div class=\"wx-block-stage\">\n <div class=\"wx-block-stage__bar\">\n <wx-segmented v-model=\"width\" :options=\"widths\" size=\"sm\" />\n </div>\n <div ref=\"box\" class=\"wx-block-stage__ground\">\n <wx-skeleton v-if=\"loading && !html\" :rows=\"3\" />\n <div v-else class=\"wx-block-stage__clip\" :style=\"clipStyle\">\n <iframe\n ref=\"frame\"\n class=\"wx-block-stage__frame\"\n :srcdoc=\"srcdoc\"\n :style=\"frameStyle\"\n sandbox=\"allow-same-origin allow-scripts\"\n :title=\"t('page.preview')\"\n @load=\"onLoad\"\n />\n </div>\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-block-stage {\n display: flex;\n flex-direction: column;\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n background: var(--wx-bg-surface);\n overflow: hidden;\n}\n\n.wx-block-stage__bar {\n display: flex;\n justify-content: space-between;\n gap: var(--wx-space-8);\n padding: var(--wx-space-8) var(--wx-space-12);\n border-block-end: 1px solid var(--wx-border-muted);\n}\n\n.wx-block-stage__ground {\n padding: var(--wx-space-12);\n background: var(--wx-bg-subtle);\n overflow: auto;\n max-height: 62vh;\n}\n\n.wx-block-stage__clip {\n overflow: hidden;\n margin-inline: auto;\n box-shadow: var(--wx-shadow-sm);\n}\n\n.wx-block-stage__frame {\n display: block;\n border: 0;\n background: #fff;\n transform-origin: top left;\n}\n</style>\n","import type { ScreenNode } from '@webx-ui/schema'\nimport type { BlockNode } from './types'\n\n/**\n * Walking and rewriting a tree of blocks.\n *\n * A node is `{ key, type, values }`, and a value that is itself a list of such nodes is a\n * nested constructor — recognised by shape rather than by schema, so a tree can be walked\n * for a type nobody can look up any more. Every rewrite returns a new tree and leaves the\n * one it was given alone: the field's model is replaced, never mutated, which is what keeps\n * the renderer's `update` and the preview's swap in step.\n */\n\nexport function isNode(value: unknown): value is BlockNode {\n return (\n typeof value === 'object' &&\n value !== null &&\n typeof (value as { type?: unknown }).type === 'string' &&\n (value as { type: string }).type !== ''\n )\n}\n\n/** A list of nodes — a nested constructor's value — as opposed to a list of anything else. */\nexport function isNodeList(value: unknown): value is BlockNode[] {\n return Array.isArray(value) && value.length > 0 && value.every(isNode)\n}\n\n/** An id that survives a drag: random, not positional. */\nexport function newKey(): string {\n const random =\n typeof crypto !== 'undefined' && 'randomUUID' in crypto\n ? crypto.randomUUID().replace(/-/g, '')\n : Math.random().toString(36).slice(2) + Math.random().toString(36).slice(2)\n\n return random.slice(0, 12)\n}\n\nexport function makeNode(type: string, values: Record<string, unknown> = {}): BlockNode {\n return { key: newKey(), type, values }\n}\n\n/** Where a node sits: the list it is in, its index there, and the field of the parent. */\nexport interface Located {\n node: BlockNode\n parent: BlockNode | null\n field: string | null\n list: BlockNode[]\n index: number\n}\n\nexport function locate(tree: BlockNode[], key: string): Located | null {\n return find(tree, key, null, null)\n}\n\nfunction find(\n list: BlockNode[],\n key: string,\n parent: BlockNode | null,\n field: string | null,\n): Located | null {\n for (let index = 0; index < list.length; index++) {\n const node = list[index]!\n\n if (node.key === key) return { node, parent, field, list, index }\n\n for (const [name, value] of Object.entries(node.values ?? {})) {\n if (isNodeList(value)) {\n const found = find(value, key, node, name)\n if (found) return found\n }\n }\n }\n\n return null\n}\n\n/** Every node, parents before children. */\nexport function walk(\n tree: BlockNode[],\n visit: (node: BlockNode, depth: number, parent: BlockNode | null) => void,\n depth = 0,\n parent: BlockNode | null = null,\n): void {\n for (const node of tree) {\n if (!isNode(node)) continue\n\n visit(node, depth, parent)\n\n for (const value of Object.values(node.values ?? {})) {\n if (isNodeList(value)) walk(value, visit, depth + 1, node)\n }\n }\n}\n\n/** How many instances of a type the tree holds, nested ones included. */\nexport function countType(tree: BlockNode[], slug: string): number {\n let count = 0\n walk(tree, (node) => {\n if (node.type === slug) count++\n })\n\n return count\n}\n\n/** How many blocks sit inside a node, at any depth — what removing it takes with it. */\nexport function countInside(node: BlockNode): number {\n let count = 0\n\n for (const value of Object.values(node.values ?? {})) {\n if (isNodeList(value)) walk(value, () => count++)\n }\n\n return count\n}\n\n/** The distinct types a tree uses, in first-seen order. */\nexport function typesIn(tree: BlockNode[]): string[] {\n const seen: string[] = []\n walk(tree, (node) => {\n if (!seen.includes(node.type)) seen.push(node.type)\n })\n\n return seen\n}\n\n/** The `wx-blocks` nodes of a schema, through cards and tabs. */\nexport function nestedFields(schema: ScreenNode[]): ScreenNode[] {\n const found: ScreenNode[] = []\n\n for (const node of schema) {\n if (node.type === 'wx-blocks') found.push(node)\n if (node.children) found.push(...nestedFields(node.children))\n }\n\n return found\n}\n\n/** A copy with fresh keys all the way down — what a duplicate is. */\nexport function cloneNode(node: BlockNode): BlockNode {\n const values: Record<string, unknown> = {}\n\n for (const [name, value] of Object.entries(node.values ?? {})) {\n values[name] = isNodeList(value) ? value.map(cloneNode) : clone(value)\n }\n\n // A copy of a switched-off block is switched off too: otherwise duplicating one quietly puts\n // it on the site.\n return node.hidden === true\n ? { key: newKey(), type: node.type, hidden: true, values }\n : { key: newKey(), type: node.type, values }\n}\n\n/**\n * Switch a block off, or back on.\n *\n * Showing it removes the key rather than writing `false`, so a block that was never hidden and\n * one that was hidden and shown again are the same content — and the revision that guards a\n * save says so.\n */\nexport function setHidden(tree: BlockNode[], key: string, hidden: boolean): BlockNode[] {\n const next = clone(tree)\n const found = locate(next, key)\n\n if (!found) return tree\n\n if (hidden) {\n found.node.hidden = true\n } else {\n delete found.node.hidden\n }\n\n return next\n}\n\n/** The list a parent holds in a field, or the root when there is no parent. */\nfunction listAt(\n tree: BlockNode[],\n parentKey: string | null,\n field: string | null,\n): BlockNode[] | null {\n if (parentKey === null) return tree\n\n const parent = locate(tree, parentKey)\n if (!parent || field === null) return null\n\n const existing = parent.node.values[field]\n\n if (!Array.isArray(existing)) {\n parent.node.values[field] = []\n }\n\n return parent.node.values[field] as BlockNode[]\n}\n\nexport function insertNode(\n tree: BlockNode[],\n parentKey: string | null,\n field: string | null,\n index: number,\n node: BlockNode,\n): BlockNode[] {\n const next = clone(tree)\n const list = listAt(next, parentKey, field)\n\n if (!list) return tree\n\n list.splice(Math.max(0, Math.min(index, list.length)), 0, node)\n\n return next\n}\n\nexport function removeNode(tree: BlockNode[], key: string): BlockNode[] {\n const next = clone(tree)\n const found = locate(next, key)\n\n if (!found) return tree\n\n found.list.splice(found.index, 1)\n\n return next\n}\n\nexport function updateValues(\n tree: BlockNode[],\n key: string,\n values: Record<string, unknown>,\n): BlockNode[] {\n const next = clone(tree)\n const found = locate(next, key)\n\n if (!found) return tree\n\n found.node.values = values\n\n return next\n}\n\n/** The list under one parent replaced wholesale — what a sortable list hands back. */\nexport function replaceList(\n tree: BlockNode[],\n parentKey: string | null,\n field: string | null,\n list: BlockNode[],\n): BlockNode[] {\n if (parentKey === null) return clone(list)\n\n const next = clone(tree)\n const parent = locate(next, parentKey)\n\n if (!parent || field === null) return tree\n\n parent.node.values[field] = clone(list)\n\n return next\n}\n\n/** Values are JSON — that is the contract with the server — so a JSON round trip is a clone. */\nexport function clone<T>(value: T): T {\n return value === undefined ? value : (JSON.parse(JSON.stringify(value)) as T)\n}\n","import type { Messages } from '@webx-ui/module-admin'\n\n/**\n * The English this package speaks on its own, before the server's dictionary arrives, or\n * without one. The server ships the same lines in ten languages under `webx-blocks::` and\n * overrides these; `messages.test.ts` keeps the two sets of keys equal.\n */\nexport const blocksMessages: Record<string, Messages> = {\n module: {\n title: 'Blocks',\n },\n page: {\n blocks: 'Blocks',\n new: 'New block',\n search: 'Search by name or identifier',\n 'all-groups': 'All groups',\n empty: 'No block types yet.',\n 'empty-help':\n 'A block type is made here entirely: its fields, its template, its styles and its script.',\n 'editing-off':\n 'Editing is switched off on this site: the types arrive by import, and the section is read-only.',\n 'on-pages': 'on :count pages',\n 'not-used': 'not used yet',\n draft: 'Draft v:number',\n live: 'Live v:number',\n 'never-published': 'Not published',\n hidden: 'Hidden from editors',\n\n identifier: 'Identifier',\n 'identifier-help':\n 'The type in the page content. Renaming it breaks every page the block stands on.',\n title: 'Name',\n description: 'Description',\n 'description-help': 'A hint for the editor, and the instruction an agent reads.',\n icon: 'Icon',\n group: 'Group',\n 'group-help': 'The section of the list an editor picks a block from.',\n allow: 'May hold',\n 'allow-help': 'Types that can be put inside. Empty — the block is not a container.',\n 'allowed-in': 'Allowed in',\n 'allowed-in-help': 'Types that may hold this one. Empty — anywhere, the page itself included.',\n root: 'The page itself',\n 'max-per-entity': 'Per page',\n 'max-per-entity-help': 'How many instances a page may hold. Empty — no limit.',\n sort: 'Order',\n 'sort-help': 'The order in the CSS cascade and in the list.',\n enabled: 'Offered to editors',\n 'enabled-help':\n 'Switched off, the block stays on the pages where it already is but cannot be added.',\n\n 'tab-template': 'Template',\n 'tab-styles': 'Styles',\n 'tab-script': 'Script',\n 'tab-fields': 'Fields',\n 'tab-settings': 'Settings',\n 'tab-history': 'History',\n 'insert-field': 'Insert a field:',\n 'script-help':\n 'The body of an initialiser: el is the root of one instance, values are its values. Called for every instance, and again for a block replaced in the preview.',\n provides: 'This site provides through webx.provide(): :names',\n 'provides-none': 'This site has not declared anything through webx.provide().',\n 'fields-help':\n 'Screen nodes, the same ones described screens are built from. The sample form on the right is built from them.',\n 'schema-invalid': 'The schema is not valid JSON: :error',\n sample: 'Sample values',\n 'sample-help': 'What the thumbnail is drawn on, and what the publish check runs on.',\n preview: 'Preview',\n 'width-desktop': 'Desktop',\n 'width-tablet': 'Tablet',\n 'width-phone': 'Phone',\n usage: 'Where it is used',\n 'usage-empty': 'Not on any page yet.',\n 'usage-more': 'and :count more',\n 'unpublished-page': 'draft',\n\n save: 'Save',\n saved: 'Saved as version :number.',\n unchanged: 'Nothing changed.',\n publish: 'Publish',\n 'publish-title': 'Publish version :number?',\n 'publish-text': 'The version takes effect on every page where the block stands: :count.',\n published: 'Version :number is live.',\n 'publish-failed': 'The version cannot be published.',\n 'failed-on': 'Fails on \":title\".',\n 'no-draft': 'There is no draft to publish.',\n failed: 'Some values were not accepted. Check the highlighted fields.',\n delete: 'Delete',\n 'delete-title': 'Delete \":title\"?',\n 'delete-text': 'Every version goes with it. This cannot be undone.',\n 'delete-used': 'The block stands on :count pages and cannot be deleted.',\n deleted: 'Deleted.',\n cancel: 'Cancel',\n create: 'Create',\n unsaved: 'Unsaved changes',\n back: 'Blocks',\n line: 'line :line',\n\n version: 'v:number',\n 'version-draft': 'Draft',\n 'version-live': 'Live',\n 'version-replaced': 'Replaced',\n restore: 'Restore',\n 'restore-title': 'Restore version :number?',\n 'restore-text': 'It becomes the draft; publishing it is a separate step.',\n restored: 'Version :number is the draft now.',\n 'restored-from': 'Restored from v:number',\n 'source-panel': 'panel',\n 'source-mcp': 'agent',\n 'source-import': 'import',\n },\n field: {\n blocks: 'Blocks',\n add: 'Add a block',\n 'add-inside': 'Add inside',\n done: 'Done',\n remove: 'Remove',\n 'remove-title': 'Remove \":title\"?',\n 'remove-text': 'The :count blocks inside it go with it.',\n duplicate: 'Duplicate',\n hide: 'Hide from the site',\n show: 'Show on the site',\n 'hidden-note': 'Hidden: it is not drawn on the site, nor is anything inside it',\n empty: 'No blocks yet. Add the first one.',\n 'nested-note': 'Nested blocks are edited in the tree on the left.',\n 'unknown-type': 'Unknown block type \":type\"',\n 'draft-type': 'The block type has an unpublished version',\n 'disabled-type': 'The block type is hidden from editors',\n\n pick: 'Add a block',\n search: 'Search by name or identifier',\n 'pick-empty': 'Nothing matches.',\n 'pick-none': 'There are no block types yet.',\n 'pick-none-link': 'Make one in the Blocks section.',\n 'pick-limited': 'Only these can go inside \":parent\": :types',\n 'pick-nothing-allowed': 'Nothing can be put inside \":parent\".',\n 'limit-reached': 'Already :count on this page, the limit for this block',\n\n preview: 'Preview',\n 'open-site': 'Open on the site',\n fullscreen: 'Full screen',\n close: 'Close',\n 'width-desktop': 'Desktop',\n 'width-tablet': 'Tablet',\n 'width-phone': 'Phone',\n },\n groups: {\n content: 'Content',\n layout: 'Layout',\n media: 'Media',\n },\n checks: {\n 'no-marker':\n 'No data-wx-block on the root: the script will not run, and the panel cannot highlight the block in the preview.',\n 'stray-selectors': 'Selectors outside the block prefix .b-:slug: :selectors',\n 'bare-selectors': 'Element selectors reach the whole site: :selectors',\n 'media-query': '@media measures the window. A block is sized by its container: use @container.',\n 'variables-missing':\n 'The template uses :variables, which the schema does not declare. Publishing will be refused.',\n 'ok-marker': 'The root carries data-wx-block.',\n 'ok-prefix': 'Every selector starts with .b-:slug.',\n 'ok-bare': 'No bare element selectors.',\n 'ok-container': 'Width is decided by container queries.',\n 'ok-variables': 'Every variable of the template is a field of the schema.',\n },\n}\n","import { useAdmin } from '@webx-ui/module-admin'\nimport { blocksMessages } from './messages'\n\nconst seeded = new WeakSet<object>()\n\n/** Puts this package's English under the panel's dictionary, once per panel. */\nexport function useBlocksMessages(): void {\n try {\n const { i18n } = useAdmin()\n\n if (!seeded.has(i18n)) {\n i18n.defaults('webx-blocks', blocksMessages)\n seeded.add(i18n)\n }\n } catch {\n // Outside a panel there is no dictionary to seed, and `useTranslate` falls back on its own.\n }\n}\n","import type { ScreenNode } from '@webx-ui/schema'\nimport type { Lint } from './types'\n\n/**\n * The checks under the editor, live (§15): the same four the server runs on saving, plus the\n * one that would refuse publication — a variable the schema does not declare. None locks a\n * save; every one is a habit that bites later, on another block or another page.\n *\n * Mirrors `Panel\\Lints` in the composer package, message for message.\n */\n\ntype Translate = (key: string, params?: Record<string, string | number>) => string\n\n/** Variables Blade or the renderer hand a template on their own. */\nconst GIVEN = ['block', 'entity', 'loop', '__env', 'errors', 'app']\n\nexport function lintBlock(\n slug: string,\n content: { template: string; styles: string; schema: ScreenNode[] },\n t: Translate,\n): Lint[] {\n const lints: Lint[] = []\n\n if (!/data-wx-block\\s*=/.test(content.template)) {\n lints.push({ file: 'template', code: 'no-marker', line: null, message: t('checks.no-marker') })\n }\n\n const missing = undeclared(content.template, content.schema)\n\n if (missing.length > 0) {\n lints.push({\n file: 'template',\n code: 'variables-missing',\n line: null,\n message: t('checks.variables-missing', {\n variables: missing.map((name) => `$${name}`).join(', '),\n }),\n })\n }\n\n const stray: [string, number][] = []\n const bare: [string, number][] = []\n const prefix = `.b-${slug}`\n\n for (const [selector, line] of selectors(content.styles)) {\n if (selector.startsWith(prefix) || selector.startsWith('&')) continue\n\n if (/^[a-z][a-z0-9-]*/i.test(selector)) bare.push([selector, line])\n else stray.push([selector, line])\n }\n\n if (stray.length > 0) {\n lints.push({\n file: 'styles',\n code: 'stray-selectors',\n line: stray[0]![1],\n message: t('checks.stray-selectors', { slug, selectors: few(stray) }),\n })\n }\n\n if (bare.length > 0) {\n lints.push({\n file: 'styles',\n code: 'bare-selectors',\n line: bare[0]![1],\n message: t('checks.bare-selectors', { selectors: few(bare) }),\n })\n }\n\n const source = withoutComments(content.styles)\n const media = /@media\\b/.exec(source)\n\n if (media) {\n lints.push({\n file: 'styles',\n code: 'media-query',\n line: lineAt(source, media.index),\n message: t('checks.media-query'),\n })\n }\n\n return lints\n}\n\n/** Every field id a schema declares, through its layout. */\nexport function fieldIds(schema: ScreenNode[]): string[] {\n const ids: string[] = []\n\n for (const node of schema) {\n if (node.id) ids.push(node.id)\n if (node.children) ids.push(...fieldIds(node.children))\n }\n\n return ids\n}\n\n/**\n * Variables the template reads that nothing declares: not the schema, not Blade's own, not\n * a `@foreach (… as $item)` or an `@php $x = …` in the template itself.\n */\nexport function undeclared(template: string, schema: ScreenNode[]): string[] {\n const declared = new Set([...fieldIds(schema), ...GIVEN])\n\n for (const match of template.matchAll(/\\bas\\s+\\$([a-zA-Z_]\\w*)(?:\\s*=>\\s*\\$([a-zA-Z_]\\w*))?/g)) {\n declared.add(match[1]!)\n if (match[2]) declared.add(match[2])\n }\n\n for (const match of template.matchAll(/\\$([a-zA-Z_]\\w*)\\s*(?:=[^=]|\\+\\+|--|\\.=|\\+=|-=)/g)) {\n declared.add(match[1]!)\n }\n\n const used: string[] = []\n\n for (const match of template.matchAll(/\\$([a-zA-Z_]\\w*)/g)) {\n const name = match[1]!\n if (!declared.has(name) && !used.includes(name)) used.push(name)\n }\n\n return used\n}\n\nfunction selectors(styles: string): [string, number][] {\n const source = withoutComments(styles)\n const found: [string, number][] = []\n\n for (const match of source.matchAll(/([^{};]+)\\{/g)) {\n const prelude = match[1]!\n const trimmed = prelude.trim()\n\n if (trimmed === '' || trimmed.startsWith('@')) continue\n\n for (const raw of prelude.split(',')) {\n const selector = raw.trim()\n\n if (selector === '' || selector === 'from' || selector === 'to' || selector.endsWith('%')) {\n continue\n }\n\n found.push([selector, lineAt(source, match.index + prelude.indexOf(selector))])\n }\n }\n\n return found\n}\n\n/** Comments replaced by spaces of the same length, so offsets and lines stay true. */\nfunction withoutComments(styles: string): string {\n return styles.replace(/\\/\\*[\\s\\S]*?\\*\\//g, (comment) => comment.replace(/[^\\n]/g, ' '))\n}\n\nfunction lineAt(source: string, offset: number): number {\n return source.slice(0, Math.max(0, offset)).split('\\n').length\n}\n\nfunction few(selectors: [string, number][]): string {\n const names = [...new Set(selectors.map(([selector]) => selector))]\n\n return names.slice(0, 3).join(', ') + (names.length > 3 ? ', …' : '')\n}\n","import type { ScreenNode } from '@webx-ui/schema'\n\n/**\n * A block's schema names a field by `id` alone — the id is the key in the values, and the\n * variable in the template. The renderer binds a field by `name`. So before a schema is\n * drawn as a form, every node without a name gets its id as one, layout nodes included: the\n * renderer only reads `name` on fields, and a name on a card is a name nobody looks at.\n */\nexport function formSchema(schema: ScreenNode[]): ScreenNode[] {\n return schema.map((node) => ({\n ...node,\n name: node.name ?? node.id,\n children: node.children ? formSchema(node.children) : node.children,\n }))\n}\n\n/**\n * Words for a group id. The dictionary may have one under `groups.<id>`; a site that added\n * a group of its own and no words for it sees the id, capitalised, which is honest.\n */\nexport function groupLabel(\n id: string,\n t: (key: string, params?: Record<string, string | number>) => string,\n): string {\n const key = `groups.${id}`\n const words = t(key)\n\n return words === key || words === `webx-blocks::${key}`\n ? id.charAt(0).toUpperCase() + id.slice(1)\n : words\n}\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, reactive, ref, watch } from 'vue'\nimport { useRoute, useRouter } from 'vue-router'\nimport {\n useAdmin,\n useErrorText,\n useTranslate,\n WxBackButton,\n WxHelpButton,\n WxRenameButton,\n} from '@webx-ui/module-admin'\nimport {\n confirm,\n toast,\n WxActionBar,\n WxAlert,\n WxBadge,\n WxButton,\n WxCard,\n WxCodeEditor,\n WxFormItem,\n WxInput,\n WxInputNumber,\n WxSelect,\n WxSkeleton,\n WxSwitch,\n WxTab,\n WxTabs,\n WxTagsInput,\n WxText,\n WxTextarea,\n} from '@webx-ui/core'\nimport { WxScreenRenderer, type ScreenModel } from '@webx-ui/schema'\nimport { createBlocksApi } from './api'\nimport BlockChecks from './BlockChecks.vue'\nimport BlockHistory from './BlockHistory.vue'\nimport BlockStage from './BlockStage.vue'\nimport { clone } from './content'\nimport { useBlocksMessages } from './i18n'\nimport { lintBlock } from './lint'\nimport { formSchema, groupLabel } from './schema'\nimport type { BlockContent, BlocksMeta, BlockType, BlockUsage, PublishRefusal } from './types'\n\n/**\n * The editor of one type: two columns. On the left the four files and the settings, on the\n * right the block drawn on its sample, the sample's form built from the schema being edited,\n * and where the type stands. The loop is closed — edit the schema and the form rebuilds,\n * edit the values and the stage redraws, edit the template or the styles and so does it.\n */\nconst props = withDefaults(defineProps<{ base?: string }>(), { base: '/blocks' })\n\nconst context = useAdmin()\nconst api = createBlocksApi(context)\nconst route = useRoute()\nconst router = useRouter()\nuseBlocksMessages()\n\nconst t = useTranslate('webx-blocks')\n/* Not the server's `message`: the panel says how a request failed in its own words (§13.3). */\nconst message = useErrorText()\n\nconst id = computed(() => Number(route.params.id))\n\nconst block = ref<BlockType | null>(null)\nconst usage = ref<BlockUsage[]>([])\nconst loading = ref(true)\nconst saving = ref(false)\nconst publishing = ref(false)\nconst tab = ref('template')\n\nconst meta = computed<BlocksMeta>(() => {\n const found = context.state.manifest?.modules.find((module) => module.id === 'blocks')?.meta\n\n return {\n groups: (found?.groups as string[] | undefined) ?? [],\n editing: (found?.editing as boolean | undefined) ?? true,\n provides: (found?.provides as string[] | undefined) ?? [],\n }\n})\n\nconst canManage = computed(() => context.can('blocks.manage') && meta.value.editing)\n\nconst settings = reactive({\n slug: '',\n title: '',\n description: '' as string | null,\n icon: '' as string | null,\n group: 'content',\n sort: 0,\n allow: [] as string[],\n allowed_in: [] as string[],\n max_per_entity: null as number | null,\n is_enabled: true,\n})\n\nconst content = reactive<BlockContent>({\n schema: [],\n template: '',\n styles: '',\n script: null,\n sample: {},\n})\n\n/** The schema as text, kept as typed: reformatting JSON under the caret moves the caret. */\nconst schemaText = ref('[]')\nconst schemaError = ref<string | null>(null)\n\nconst snapshot = ref('')\nconst errors = ref<Record<string, string[]>>({})\nconst refusal = ref<PublishRefusal | null>(null)\n\nconst stage = reactive({\n html: '',\n styles: '',\n script: null as string | null,\n runtime: null as string | null,\n loading: false,\n})\n\nconst current = computed(() => JSON.stringify({ settings, content }))\nconst dirty = computed(() => snapshot.value !== '' && current.value !== snapshot.value)\n\nconst lints = computed(() => lintBlock(settings.slug, content, t))\n\nconst groupOptions = computed(() => {\n const ids = [...meta.value.groups]\n if (!ids.includes(settings.group)) ids.push(settings.group)\n\n return ids.map((group) => ({ value: group, label: groupLabel(group, t) }))\n})\n\nconst sampleModel = computed<ScreenModel>({\n get: () => content.sample,\n set: (next) => {\n content.sample = next\n },\n})\n\nconst fieldIds = computed(() => collectIds(content.schema))\n\nfunction collectIds(nodes: BlockContent['schema']): string[] {\n const ids: string[] = []\n\n for (const node of nodes) {\n if (node.type !== 'wx-blocks' && !(node.children?.length && !node.name)) ids.push(node.id)\n if (node.children) ids.push(...collectIds(node.children))\n }\n\n return ids\n}\n\nfunction take(loaded: BlockType): void {\n block.value = loaded\n\n Object.assign(settings, {\n slug: loaded.slug,\n title: loaded.title,\n description: loaded.description,\n icon: loaded.icon,\n group: loaded.group,\n sort: loaded.sort,\n allow: loaded.allow ?? [],\n allowed_in: loaded.allowed_in ?? [],\n max_per_entity: loaded.max_per_entity,\n is_enabled: loaded.is_enabled,\n })\n\n const stored = loaded.content ?? {\n schema: [],\n template: '',\n styles: '',\n script: null,\n sample: {},\n }\n\n Object.assign(content, clone(stored))\n schemaText.value = JSON.stringify(stored.schema, null, 2)\n schemaError.value = null\n snapshot.value = current.value\n}\n\nasync function load(): Promise<void> {\n loading.value = true\n\n try {\n take(await api.get(id.value))\n usage.value = await api.usage(id.value)\n } catch (error) {\n toast.danger(message(error))\n } finally {\n loading.value = false\n }\n}\n\nfunction onSchemaText(text: string): void {\n schemaText.value = text\n\n try {\n const parsed: unknown = JSON.parse(text)\n\n if (!Array.isArray(parsed)) throw new Error('not a list')\n\n content.schema = parsed as BlockContent['schema']\n schemaError.value = null\n } catch (error) {\n schemaError.value = t('page.schema-invalid', { error: (error as Error).message })\n }\n}\n\n/* The stage redraws a moment after the last keystroke, not on every one: a render is a\n request, and a request per character is a queue nobody asked for. */\nlet timer: ReturnType<typeof setTimeout> | undefined\nlet pending = 0\n\nfunction redraw(): void {\n clearTimeout(timer)\n timer = setTimeout(() => void render(), 250)\n}\n\nasync function render(): Promise<void> {\n if (!block.value) return\n\n const ticket = ++pending\n stage.loading = true\n\n try {\n const drawn = await api.render(block.value.id, {\n values: content.sample,\n content: canManage.value\n ? {\n template: content.template,\n styles: content.styles,\n script: content.script,\n schema: content.schema,\n }\n : undefined,\n })\n\n if (ticket !== pending) return\n\n stage.html = drawn.html\n stage.styles = drawn.styles\n stage.script = drawn.script\n stage.runtime = drawn.runtime\n } catch (error) {\n if (ticket === pending) {\n toast.danger(message(error))\n }\n } finally {\n if (ticket === pending) stage.loading = false\n }\n}\n\nwatch(\n () => [content.template, content.styles, content.script, content.schema, content.sample],\n redraw,\n { deep: true },\n)\n\nconst templateEditor = ref<{ view: { value: unknown } } | null>(null)\n\n/* Written as a function because the mustaches themselves cannot stand in a template. */\nfunction pill(field: string): string {\n return `{{ $${field} }}`\n}\n\n/** `{{ $field }}` at the caret of the template editor. */\nfunction insertField(field: string): void {\n const view = (templateEditor.value as { view?: { value?: unknown } } | null)?.view as\n | {\n value?: {\n dispatch: (tr: unknown) => void\n state: { replaceSelection: (text: string) => unknown }\n focus: () => void\n }\n }\n | undefined\n const editor = view?.value\n\n if (!editor) {\n content.template += `{{ $${field} }}`\n\n return\n }\n\n editor.dispatch(editor.state.replaceSelection(`{{ $${field} }}`))\n editor.focus()\n}\n\nasync function save(): Promise<void> {\n if (!block.value) return\n\n saving.value = true\n errors.value = {}\n refusal.value = null\n\n const before = block.value.draft?.number ?? null\n\n try {\n const saved = await api.update(block.value.id, {\n ...settings,\n allow: settings.allow.length ? settings.allow : null,\n allowed_in: settings.allowed_in.length ? settings.allowed_in : null,\n description: settings.description || null,\n icon: settings.icon || null,\n content: schemaError.value ? { ...content, schema: undefined } : content,\n })\n\n take(saved)\n\n toast.success(\n saved.draft && saved.draft.number !== before\n ? t('page.saved', { number: saved.draft.number })\n : t('page.unchanged'),\n )\n } catch (error) {\n const body = (error as { body?: { errors?: Record<string, string[]>; message?: string } }).body\n\n if (body?.errors) {\n errors.value = body.errors\n toast.danger(t('page.failed'))\n } else {\n toast.danger(message(error, t('page.failed')))\n }\n } finally {\n saving.value = false\n }\n}\n\nasync function publish(): Promise<void> {\n if (!block.value?.draft) return\n\n if (dirty.value) await save()\n if (!block.value.draft) return\n\n const agreed = await confirm({\n title: t('page.publish-title', { number: block.value.draft.number }),\n message: t('page.publish-text', { count: block.value.usage_count }),\n confirmText: t('page.publish'),\n cancelText: t('page.cancel'),\n })\n\n if (!agreed) return\n\n publishing.value = true\n refusal.value = null\n\n try {\n take(await api.publish(block.value.id))\n toast.success(t('page.published', { number: block.value.published?.number ?? 0 }))\n } catch (error) {\n const body = (error as { status?: number; body?: PublishRefusal }).body\n\n if (body?.errors) {\n refusal.value = body\n tab.value = 'template'\n toast.danger(t('page.publish-failed'))\n } else {\n toast.danger(message(error, t('page.publish-failed')))\n }\n } finally {\n publishing.value = false\n }\n}\n\nasync function remove(): Promise<void> {\n if (!block.value) return\n\n const agreed = await confirm({\n title: t('page.delete-title', { title: block.value.title }),\n message: t('page.delete-text'),\n confirmText: t('page.delete'),\n cancelText: t('page.cancel'),\n tone: 'danger',\n })\n\n if (!agreed) return\n\n try {\n await api.remove(block.value.id)\n toast.success(t('page.deleted'))\n void router.push(props.base)\n } catch (error) {\n toast.danger(message(error))\n }\n}\n\nconst refusalError = computed(() =>\n refusal.value\n ? {\n message: refusal.value.errors.template?.[0] ?? refusal.value.message,\n line: refusal.value.line,\n where: refusal.value.entity\n ? t('page.failed-on', {\n title: refusal.value.entity.title ?? `#${refusal.value.entity.id}`,\n })\n : null,\n }\n : null,\n)\n\nconst shownUsage = computed(() => usage.value.slice(0, 5))\n\nfunction errorOf(field: string): string | undefined {\n return errors.value[field]?.[0]\n}\n\nfunction leaveGuard(event: BeforeUnloadEvent): void {\n if (dirty.value) event.preventDefault()\n}\n\nonMounted(() => {\n void load()\n window.addEventListener('beforeunload', leaveGuard)\n})\n\nonBeforeUnmount(() => {\n clearTimeout(timer)\n window.removeEventListener('beforeunload', leaveGuard)\n})\n\nwatch(id, () => void load())\n</script>\n\n<template>\n <div class=\"wx-block-editor\">\n <!-- Shaped like the page it stands in for: the head on the ground, the rest on cards. -->\n <template v-if=\"loading || !block\">\n <wx-skeleton class=\"wx-block-editor__ghost-head\" title :rows=\"1\" />\n <div class=\"wx-block-editor__columns\">\n <wx-card><wx-skeleton :rows=\"8\" /></wx-card>\n <wx-card><wx-skeleton :rows=\"4\" /></wx-card>\n </div>\n </template>\n\n <template v-else>\n <div class=\"wx-block-editor__head\">\n <!--\n The way out, said with a control rather than with a line of small grey type — and\n renaming with a control rather than by typing into what looks like a heading. Both\n are the panel's, not this editor's: every screen that opens one record needs them.\n -->\n <wx-back-button class=\"wx-block-editor__back\" :to=\"base\" :label=\"t('page.back')\" />\n\n <div class=\"wx-block-editor__id\">\n <div class=\"wx-block-editor__name\">\n <h1 class=\"wx-block-editor__title\">{{ settings.title }}</h1>\n <wx-rename-button\n v-if=\"canManage\"\n :name=\"settings.title\"\n :placeholder=\"t('page.title')\"\n @rename=\"(name: string) => (settings.title = name)\"\n />\n </div>\n <wx-text size=\"sm\" tone=\"muted\">\n <code>{{ settings.slug }}</code>\n · {{ groupLabel(settings.group, t) }} ·\n {{\n block.usage_count > 0\n ? t('page.on-pages', { count: block.usage_count })\n : t('page.not-used')\n }}\n </wx-text>\n </div>\n <div class=\"wx-block-editor__actions\">\n <wx-badge v-if=\"dirty\" type=\"primary\" dot>{{ t('page.unsaved') }}</wx-badge>\n <wx-badge v-if=\"block.draft\" type=\"warning\" dot>{{\n t('page.draft', { number: block.draft.number })\n }}</wx-badge>\n <wx-badge v-if=\"block.published\" type=\"success\" dot>{{\n t('page.live', { number: block.published.number })\n }}</wx-badge>\n <wx-badge v-else type=\"default\">{{ t('page.never-published') }}</wx-badge>\n <template v-if=\"canManage\">\n <wx-button variant=\"outline\" :loading=\"saving\" @click=\"save\">{{\n t('page.save')\n }}</wx-button>\n <wx-button\n type=\"primary\"\n :loading=\"publishing\"\n :disabled=\"!block.draft && !dirty\"\n @click=\"publish\"\n >\n {{ t('page.publish') }}\n </wx-button>\n </template>\n </div>\n </div>\n\n <wx-alert\n v-if=\"!meta.editing\"\n type=\"info\"\n variant=\"soft\"\n :description=\"t('page.editing-off')\"\n />\n\n <div class=\"wx-block-editor__columns\">\n <div class=\"wx-block-editor__files\">\n <wx-tabs v-model=\"tab\" keep-alive>\n <wx-tab value=\"template\" :label=\"t('page.tab-template')\">\n <div class=\"wx-block-editor__pane\">\n <wx-code-editor\n ref=\"templateEditor\"\n v-model=\"content.template\"\n language=\"php\"\n :readonly=\"!canManage\"\n min-height=\"340px\"\n max-height=\"70vh\"\n line-wrapping\n />\n <div v-if=\"fieldIds.length\" class=\"wx-block-editor__pills\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('page.insert-field') }}</wx-text>\n <button\n v-for=\"field in fieldIds\"\n :key=\"field\"\n type=\"button\"\n class=\"wx-block-editor__pill\"\n :disabled=\"!canManage\"\n @click=\"insertField(field)\"\n v-text=\"pill(field)\"\n />\n </div>\n <block-checks\n file=\"template\"\n :lints=\"lints\"\n :slug=\"settings.slug\"\n :error=\"refusalError\"\n />\n </div>\n </wx-tab>\n\n <wx-tab value=\"styles\" :label=\"t('page.tab-styles')\">\n <div class=\"wx-block-editor__pane\">\n <wx-code-editor\n v-model=\"content.styles\"\n language=\"css\"\n :readonly=\"!canManage\"\n min-height=\"340px\"\n max-height=\"70vh\"\n />\n <block-checks file=\"styles\" :lints=\"lints\" :slug=\"settings.slug\" />\n </div>\n </wx-tab>\n\n <wx-tab value=\"script\" :label=\"t('page.tab-script')\">\n <div class=\"wx-block-editor__pane\">\n <wx-code-editor\n :model-value=\"content.script ?? ''\"\n language=\"javascript\"\n :readonly=\"!canManage\"\n min-height=\"340px\"\n max-height=\"70vh\"\n @update:model-value=\"content.script = $event || null\"\n />\n <div class=\"wx-block-editor__note\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('page.script-help') }}</wx-text>\n <wx-text size=\"sm\" tone=\"muted\">\n {{\n meta.provides.length\n ? t('page.provides', { names: meta.provides.join(', ') })\n : t('page.provides-none')\n }}\n </wx-text>\n </div>\n </div>\n </wx-tab>\n\n <wx-tab value=\"fields\" :label=\"t('page.tab-fields')\">\n <div class=\"wx-block-editor__pane\">\n <wx-code-editor\n :model-value=\"schemaText\"\n language=\"json\"\n lint\n :readonly=\"!canManage\"\n min-height=\"340px\"\n max-height=\"70vh\"\n @update:model-value=\"onSchemaText\"\n />\n <div class=\"wx-block-editor__note\">\n <wx-text v-if=\"schemaError\" size=\"sm\" tone=\"danger\">{{ schemaError }}</wx-text>\n <wx-text v-else-if=\"errorOf('content.schema')\" size=\"sm\" tone=\"danger\">{{\n errorOf('content.schema')\n }}</wx-text>\n <wx-text v-else size=\"sm\" tone=\"muted\">{{ t('page.fields-help') }}</wx-text>\n\n <!-- The whole of what a schema is, in the one place somebody writing one is\n looking. The same page an agent is handed over MCP, from the same\n `help.schema` line, so that the two cannot drift apart. -->\n <wx-help-button :title=\"t('help.schema-title')\" :body=\"t('help.schema')\" />\n </div>\n </div>\n </wx-tab>\n\n <wx-tab value=\"settings\" :label=\"t('page.tab-settings')\">\n <wx-card class=\"wx-block-editor__sheet\">\n <div class=\"wx-block-editor__settings\">\n <wx-form-item\n :label=\"t('page.identifier')\"\n :help=\"t('page.identifier-help')\"\n :error=\"errorOf('slug')\"\n :disabled=\"!canManage\"\n >\n <wx-input v-model=\"settings.slug\" />\n </wx-form-item>\n <wx-form-item\n :label=\"t('page.group')\"\n :help=\"t('page.group-help')\"\n :error=\"errorOf('group')\"\n :disabled=\"!canManage\"\n >\n <wx-select v-model=\"settings.group\" :options=\"groupOptions\" />\n </wx-form-item>\n <wx-form-item\n class=\"is-wide\"\n :label=\"t('page.description')\"\n :help=\"t('page.description-help')\"\n :error=\"errorOf('description')\"\n :disabled=\"!canManage\"\n >\n <wx-textarea\n :model-value=\"settings.description ?? ''\"\n :rows=\"2\"\n @update:model-value=\"settings.description = String($event ?? '')\"\n />\n </wx-form-item>\n <wx-form-item\n :label=\"t('page.icon')\"\n :error=\"errorOf('icon')\"\n :disabled=\"!canManage\"\n >\n <wx-input\n :model-value=\"settings.icon ?? ''\"\n placeholder=\"grid\"\n @update:model-value=\"settings.icon = String($event ?? '')\"\n />\n </wx-form-item>\n <wx-form-item\n :label=\"t('page.sort')\"\n :help=\"t('page.sort-help')\"\n :error=\"errorOf('sort')\"\n :disabled=\"!canManage\"\n >\n <wx-input-number v-model=\"settings.sort\" />\n </wx-form-item>\n <wx-form-item\n :label=\"t('page.allow')\"\n :help=\"t('page.allow-help')\"\n :error=\"errorOf('allow')\"\n :disabled=\"!canManage\"\n >\n <wx-tags-input v-model=\"settings.allow\" allow-create />\n </wx-form-item>\n <wx-form-item\n :label=\"t('page.allowed-in')\"\n :help=\"t('page.allowed-in-help')\"\n :error=\"errorOf('allowed_in')\"\n :disabled=\"!canManage\"\n >\n <wx-tags-input\n v-model=\"settings.allowed_in\"\n allow-create\n :suggestions=\"['root']\"\n />\n </wx-form-item>\n <wx-form-item\n :label=\"t('page.max-per-entity')\"\n :help=\"t('page.max-per-entity-help')\"\n :error=\"errorOf('max_per_entity')\"\n :disabled=\"!canManage\"\n >\n <wx-input-number\n :model-value=\"settings.max_per_entity ?? undefined\"\n :min=\"1\"\n @update:model-value=\"settings.max_per_entity = $event ?? null\"\n />\n </wx-form-item>\n <wx-form-item\n :label=\"t('page.enabled')\"\n :help=\"t('page.enabled-help')\"\n :disabled=\"!canManage\"\n >\n <wx-switch v-model=\"settings.is_enabled\" />\n </wx-form-item>\n <div v-if=\"canManage\" class=\"is-wide wx-block-editor__danger\">\n <wx-button\n type=\"danger\"\n variant=\"outline\"\n :disabled=\"block.usage_count > 0\"\n @click=\"remove\"\n >\n {{ t('page.delete') }}\n </wx-button>\n <wx-text v-if=\"block.usage_count > 0\" size=\"sm\" tone=\"muted\">\n {{ t('page.delete-used', { count: block.usage_count }) }}\n </wx-text>\n </div>\n </div>\n </wx-card>\n </wx-tab>\n\n <wx-tab value=\"history\" :label=\"t('page.tab-history')\">\n <wx-card class=\"wx-block-editor__sheet\" padding=\"none\">\n <block-history :block=\"block\" :can-manage=\"canManage\" @restored=\"take\" />\n </wx-card>\n </wx-tab>\n </wx-tabs>\n </div>\n\n <div class=\"wx-block-editor__side\">\n <block-stage\n :html=\"stage.html\"\n :styles=\"stage.styles\"\n :script=\"stage.script\"\n :runtime=\"stage.runtime\"\n :loading=\"stage.loading\"\n />\n\n <wx-card :title=\"t('page.sample')\">\n <wx-screen-renderer\n v-if=\"content.schema.length\"\n v-model=\"sampleModel\"\n :root=\"formSchema(content.schema)\"\n :types=\"context.types\"\n :translate=\"context.i18n.t\"\n :can=\"context.can\"\n :disabled=\"!canManage\"\n size=\"sm\"\n />\n <wx-text size=\"sm\" tone=\"muted\">{{ t('page.sample-help') }}</wx-text>\n </wx-card>\n\n <wx-card :title=\"t('page.usage')\">\n <wx-text v-if=\"usage.length === 0\" size=\"sm\" tone=\"muted\">{{\n t('page.usage-empty')\n }}</wx-text>\n <div v-else class=\"wx-block-editor__usage\">\n <div\n v-for=\"entity in shownUsage\"\n :key=\"`${entity.model}:${entity.id}`\"\n class=\"wx-block-editor__use\"\n >\n <span>{{ entity.title ?? `#${entity.id}` }}</span>\n <wx-badge v-if=\"!entity.published\" type=\"warning\" size=\"sm\">{{\n t('page.unpublished-page')\n }}</wx-badge>\n </div>\n <wx-text v-if=\"usage.length > shownUsage.length\" size=\"sm\" tone=\"muted\">\n {{ t('page.usage-more', { count: usage.length - shownUsage.length }) }}\n </wx-text>\n </div>\n </wx-card>\n </div>\n </div>\n\n <!-- The editor is four tabs of code and a column of cards beside them, so the head is\n long gone by the time there is anything to save. Same two buttons, same state. -->\n <wx-action-bar v-if=\"canManage\">\n <template #state>\n <wx-badge v-if=\"dirty\" type=\"primary\" dot>{{ t('page.unsaved') }}</wx-badge>\n <wx-badge v-if=\"block.draft\" type=\"warning\" dot>{{\n t('page.draft', { number: block.draft.number })\n }}</wx-badge>\n <wx-badge v-if=\"block.published\" type=\"success\" dot>{{\n t('page.live', { number: block.published.number })\n }}</wx-badge>\n </template>\n\n <wx-button variant=\"outline\" :loading=\"saving\" @click=\"save\">{{\n t('page.save')\n }}</wx-button>\n <wx-button\n type=\"primary\"\n :loading=\"publishing\"\n :disabled=\"!block.draft && !dirty\"\n @click=\"publish\"\n >\n {{ t('page.publish') }}\n </wx-button>\n </wx-action-bar>\n </template>\n </div>\n</template>\n\n<style scoped>\n.wx-block-editor {\n display: flex;\n flex-direction: column;\n gap: var(--wx-gap, var(--wx-space-16));\n container-type: inline-size;\n}\n\n.wx-block-editor__head {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: var(--wx-space-16);\n flex-wrap: wrap;\n}\n\n.wx-block-editor__ghost-head {\n max-width: 420px;\n}\n\n.wx-block-editor__id {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-4);\n flex: 1 1 280px;\n min-width: 0;\n}\n\n/* Level with the name rather than with the middle of the whole block of text under it. */\n.wx-block-editor__back {\n flex: none;\n margin-block-start: var(--wx-space-2);\n}\n\n.wx-block-editor__name {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n min-width: 0;\n}\n\n.wx-block-editor__title {\n margin: 0;\n min-width: 0;\n overflow: hidden;\n color: var(--wx-text-default);\n font-size: var(--wx-font-size-xl);\n font-weight: var(--wx-font-weight-bold);\n line-height: var(--wx-font-line-height-tight);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.wx-block-editor__actions {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n flex-wrap: wrap;\n}\n\n.wx-block-editor__columns {\n display: grid;\n grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);\n gap: var(--wx-gap, var(--wx-space-16));\n align-items: start;\n}\n\n@container (max-width: 1080px) {\n .wx-block-editor__columns {\n grid-template-columns: minmax(0, 1fr);\n }\n}\n\n.wx-block-editor__files {\n min-width: 0;\n}\n\n.wx-block-editor__pane {\n display: flex;\n flex-direction: column;\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n overflow: hidden;\n}\n\n.wx-block-editor__pane :deep(.wx-code-editor) {\n border: 0;\n border-radius: 0;\n}\n\n.wx-block-editor__pills {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wx-space-6);\n padding: var(--wx-space-8) var(--wx-space-12);\n border-block-start: 1px solid var(--wx-border-muted);\n}\n\n.wx-block-editor__pill {\n padding: 2px var(--wx-space-8);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-full);\n background: var(--wx-bg-surface);\n color: var(--wx-color-primary);\n font-family: var(--wx-font-family-mono);\n font-size: var(--wx-font-size-xs);\n cursor: pointer;\n}\n\n.wx-block-editor__pill:hover:not(:disabled) {\n border-color: var(--wx-color-primary);\n}\n\n/* A row: what the editor is being told, and the `?` that tells it at length, at the end. */\n.wx-block-editor__note {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n padding: var(--wx-space-8) var(--wx-space-12);\n border-block-start: 1px solid var(--wx-border-muted);\n}\n\n.wx-block-editor__note > :first-child {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n/* The settings and the history sit on a card, the way the side column does: the code tabs\n bring their own white with the editor, these two would otherwise stand on the grey. */\n.wx-block-editor__sheet {\n min-width: 0;\n}\n\n.wx-block-editor__settings {\n display: grid;\n grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));\n gap: var(--wx-space-12) var(--wx-space-16);\n}\n\n.wx-block-editor__settings .is-wide {\n grid-column: 1 / -1;\n}\n\n.wx-block-editor__danger {\n display: flex;\n align-items: center;\n gap: var(--wx-space-12);\n flex-wrap: wrap;\n}\n\n.wx-block-editor__side {\n display: flex;\n flex-direction: column;\n gap: var(--wx-gap, var(--wx-space-16));\n min-width: 0;\n position: sticky;\n top: var(--wx-space-12);\n}\n\n.wx-block-editor__usage {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-6);\n}\n\n.wx-block-editor__use {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n}\n\ncode {\n font-family: var(--wx-font-family-mono);\n font-size: var(--wx-font-size-xs);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport { useElementWidth, WxIcon } from '@webx-ui/core'\nimport { stageDocument } from './frame'\nimport type { BlockThumbnail } from './types'\n\n/**\n * A block drawn small: the sample render in an iframe, scaled down to the width it is given.\n *\n * An iframe rather than inline markup because a block's styles are a block's business — a\n * stray `h2 { }` in one type would otherwise restyle the whole list of cards — and because\n * the thumbnail is a picture of the site, not a part of the panel.\n */\nconst props = withDefaults(\n defineProps<{\n thumbnail: BlockThumbnail | null\n /** The width the block is drawn at, before scaling — a desktop. */\n width?: number\n /** How tall the picture is, in the panel's pixels. */\n height?: number\n }>(),\n { width: 1280, height: 120 },\n)\n\nconst box = ref<HTMLElement | null>(null)\nconst boxWidth = useElementWidth(box)\n\nconst scale = computed(() => (boxWidth.value > 0 ? boxWidth.value / props.width : 0.2))\n\nconst srcdoc = computed(() =>\n props.thumbnail\n ? stageDocument({ html: props.thumbnail.html, styles: props.thumbnail.styles })\n : '',\n)\n\nconst frameStyle = computed(() => ({\n width: `${props.width}px`,\n height: `${Math.round(props.height / scale.value)}px`,\n transform: `scale(${scale.value})`,\n}))\n</script>\n\n<template>\n <div ref=\"box\" class=\"wx-block-thumb\" :style=\"{ height: `${height}px` }\">\n <iframe\n v-if=\"thumbnail\"\n class=\"wx-block-thumb__frame\"\n :srcdoc=\"srcdoc\"\n :style=\"frameStyle\"\n sandbox=\"allow-same-origin\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n />\n <div v-else class=\"wx-block-thumb__empty\">\n <wx-icon name=\"grid\" />\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-block-thumb {\n position: relative;\n overflow: hidden;\n background: var(--wx-bg-subtle);\n}\n\n.wx-block-thumb__frame {\n position: absolute;\n inset-block-start: 0;\n inset-inline-start: 0;\n border: 0;\n transform-origin: top left;\n pointer-events: none;\n background: #fff;\n}\n\n.wx-block-thumb__empty {\n display: grid;\n place-items: center;\n height: 100%;\n color: var(--wx-text-muted);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { useModal, WxButton, WxDialog, WxEmpty, WxInput, WxText } from '@webx-ui/core'\nimport BlockThumb from './BlockThumb.vue'\nimport { countType } from './content'\nimport { useBlocksMessages } from './i18n'\nimport { groupLabel } from './schema'\nimport type { BlockNode, BlockType } from './types'\n\n/**\n * \"Add a block\": the types as cards with their pictures, because a name says nothing about\n * whether \"Section\" is a full-width band or a container with columns. Only what may go\n * here is offered; what is exhausted is shown greyed with the reason rather than hidden,\n * or the editor goes looking for a block that vanished.\n */\nconst props = withDefaults(\n defineProps<{\n catalog: BlockType[]\n /** The container a block is being added to, or null at the page level. */\n parent?: BlockType | null\n /** What the container's field allows, when the field narrows it further. */\n allow?: string[] | null\n /** The whole tree, for the per-page limits. */\n tree?: BlockNode[]\n groups?: string[]\n /** Where a person with the right can go and make a type. */\n blocksPath?: string | null\n }>(),\n { parent: null, allow: null, tree: () => [], groups: () => [], blocksPath: null },\n)\n\nconst { resolve, dismiss, open } = useModal<BlockType>()\nuseBlocksMessages()\n\nconst t = useTranslate('webx-blocks')\n\nconst search = ref('')\n\ninterface Option {\n type: BlockType\n reason: string | null\n}\n\n/** Allowed here at all: the parent's say-so and the type's own, both. */\nfunction allowedHere(type: BlockType): boolean {\n if (props.parent === null) {\n return type.allowed_in === null || type.allowed_in.includes('root')\n }\n\n const parentAllows = props.allow\n ? props.allow.includes(type.slug)\n : props.parent.allow?.includes(type.slug) === true\n const typeAllows = type.allowed_in === null || type.allowed_in.includes(props.parent.slug)\n\n return parentAllows && typeAllows\n}\n\nconst options = computed<Option[]>(() =>\n props.catalog\n .filter((type) => type.is_enabled && type.published !== null && allowedHere(type))\n .map((type) => {\n const count = countType(props.tree, type.slug)\n const exhausted = type.max_per_entity !== null && count >= type.max_per_entity\n\n return { type, reason: exhausted ? t('field.limit-reached', { count }) : null }\n }),\n)\n\nconst shown = computed(() => {\n const needle = search.value.trim().toLowerCase()\n\n if (needle === '') return options.value\n\n return options.value.filter(\n ({ type }) =>\n type.title.toLowerCase().includes(needle) ||\n type.slug.includes(needle) ||\n (type.description ?? '').toLowerCase().includes(needle),\n )\n})\n\nconst sections = computed(() => {\n const order = [...props.groups]\n\n for (const { type } of shown.value) {\n if (!order.includes(type.group)) order.push(type.group)\n }\n\n const grouped = order\n .map((id) => ({\n id,\n label: groupLabel(id, t),\n options: shown.value.filter((o) => o.type.group === id),\n }))\n .filter((section) => section.options.length > 0)\n\n const flat = shown.value.length <= 5 || search.value.trim() !== '' || grouped.length < 2\n\n return flat ? [{ id: '', label: '', options: shown.value }] : grouped\n})\n\n/** Why the list is empty, in words: which case it is decides what the person does next. */\nconst emptyText = computed(() => {\n if (props.catalog.length === 0) return t('field.pick-none')\n if (options.value.length === 0 && props.parent) {\n const allowed = (props.allow ?? props.parent.allow ?? []).filter((slug) =>\n props.catalog.some((type) => type.slug === slug),\n )\n\n return allowed.length === 0\n ? t('field.pick-nothing-allowed', { parent: props.parent.title })\n : t('field.pick-limited', { parent: props.parent.title, types: allowed.join(', ') })\n }\n\n return t('field.pick-empty')\n})\n</script>\n\n<template>\n <wx-dialog v-model:open=\"open\" :title=\"t('field.pick')\" :width=\"860\">\n <div class=\"wx-block-picker\">\n <!-- Always there, four types or forty: a person who came to type a name should not\n first have to notice that the field is missing. -->\n <wx-input\n v-if=\"options.length > 0\"\n v-model=\"search\"\n :placeholder=\"t('field.search')\"\n clearable\n autofocus\n />\n\n <wx-empty v-if=\"shown.length === 0\" icon=\"grid\" :title=\"emptyText\" size=\"sm\">\n <router-link v-if=\"catalog.length === 0 && blocksPath\" :to=\"blocksPath\">\n {{ t('field.pick-none-link') }}\n </router-link>\n </wx-empty>\n\n <section v-for=\"section in sections\" :key=\"section.id\" class=\"wx-block-picker__group\">\n <div v-if=\"section.label\" class=\"wx-block-picker__group-title\">{{ section.label }}</div>\n <div class=\"wx-block-picker__cards\">\n <button\n v-for=\"option in section.options\"\n :key=\"option.type.id\"\n type=\"button\"\n class=\"wx-block-picker__card\"\n :class=\"{ 'is-disabled': option.reason !== null }\"\n :disabled=\"option.reason !== null\"\n :title=\"option.reason ?? undefined\"\n @click=\"resolve(option.type)\"\n >\n <block-thumb :thumbnail=\"option.type.thumbnail\" :height=\"96\" />\n <div class=\"wx-block-picker__body\">\n <div class=\"wx-block-picker__title\">{{ option.type.title }}</div>\n <wx-text v-if=\"option.reason\" size=\"sm\" tone=\"warning\">{{ option.reason }}</wx-text>\n <wx-text v-else-if=\"option.type.description\" size=\"sm\" tone=\"muted\">\n {{ option.type.description }}\n </wx-text>\n </div>\n </button>\n </div>\n </section>\n </div>\n\n <template #footer>\n <wx-button variant=\"outline\" @click=\"dismiss()\">{{ t('field.close') }}</wx-button>\n </template>\n </wx-dialog>\n</template>\n\n<style scoped>\n.wx-block-picker {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-16);\n}\n\n.wx-block-picker__group {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n}\n\n.wx-block-picker__group-title {\n font-size: var(--wx-font-size-xs);\n font-weight: var(--wx-font-weight-semibold);\n letter-spacing: 0.06em;\n text-transform: uppercase;\n color: var(--wx-text-muted);\n}\n\n.wx-block-picker__cards {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));\n gap: var(--wx-space-12);\n}\n\n.wx-block-picker__card {\n display: flex;\n flex-direction: column;\n padding: 0;\n overflow: hidden;\n text-align: start;\n font: inherit;\n color: inherit;\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n cursor: pointer;\n}\n\n.wx-block-picker__card:hover:not(:disabled),\n.wx-block-picker__card:focus-visible {\n border-color: var(--wx-color-primary);\n outline: none;\n}\n\n.wx-block-picker__card.is-disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.wx-block-picker__body {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-4);\n padding: var(--wx-space-10) var(--wx-space-12);\n}\n\n.wx-block-picker__title {\n font-weight: var(--wx-font-weight-semibold);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { useElementWidth, WxButton, WxSegmented, WxText } from '@webx-ui/core'\nimport { bindFrame, blockElement, highlightBlock, replaceBlock, type FrameBinding } from './frame'\n\n/**\n * The page in an iframe, the way it will be: the same handler, the same view, the draft\n * laid over the columns. Two shapes — the whole page wide while nothing is selected, a\n * phone at one to one while a block is being edited — and a full-screen mode for looking\n * at the desktop and the tablet, because a desktop in a 420 px column is a picture nobody\n * can read.\n *\n * The panel and the site are one application on one domain, so the frame's document is\n * reachable: selection is a class, a change is a swap between the marker comments.\n */\nconst props = withDefaults(\n defineProps<{\n url: string | null\n selected?: string | null\n /** `wide` when the page is being looked at, `phone` while a block is being edited. */\n mode?: 'wide' | 'phone'\n /** Bumped by the host to reload the page. */\n reload?: number\n /** Be as tall as what it is drawn in, and scroll the page inside rather than beside. */\n fill?: boolean\n }>(),\n { selected: null, mode: 'wide', reload: 0, fill: false },\n)\n\nconst emit = defineEmits<{\n /** A block was clicked in the page. Null when the click landed outside every block. */\n select: [key: string | null]\n}>()\n\nconst t = useTranslate('webx-blocks')\n\nconst frame = ref<HTMLIFrameElement | null>(null)\nconst box = ref<HTMLElement | null>(null)\nconst boxWidth = useElementWidth(box)\nconst fullscreen = ref(false)\nconst fullWidth = ref<number>(1280)\nconst ready = ref(false)\n\nconst widths = computed(() => [\n { value: 1280, label: t('field.width-desktop') },\n { value: 834, label: t('field.width-tablet') },\n { value: 390, label: t('field.width-phone') },\n])\n\nconst width = computed(() =>\n fullscreen.value ? fullWidth.value : props.mode === 'phone' ? 390 : 1280,\n)\n\nconst scale = computed(() => {\n if (fullscreen.value || props.mode === 'phone' || boxWidth.value === 0) return 1\n\n return Math.min(1, boxWidth.value / width.value)\n})\n\nconst frameStyle = computed(() => ({\n width: `${width.value}px`,\n transform: `scale(${scale.value})`,\n}))\n\nconst label = computed(() => {\n if (!props.url) return ''\n\n try {\n const parsed = new URL(props.url, location.origin)\n\n return `${parsed.pathname} · ${width.value} px`\n } catch {\n return props.url\n }\n})\n\nfunction doc(): Document | null {\n try {\n return frame.value?.contentDocument ?? null\n } catch {\n return null\n }\n}\n\n/*\n * What the page was bound with, so that a reload lets go of the document it was bound to. The\n * page inside is the site's, not ours, and a listener left on a document nobody can reach any\n * more keeps that whole document alive.\n */\nlet binding: FrameBinding | null = null\n\n/* Set while the selection is coming out of the page, so that a click is not answered by\n scrolling the very thing that was just clicked back into the middle of the window. */\nlet fromFrame = false\n\nfunction onLoad(): void {\n ready.value = true\n\n const page = doc()\n\n if (!page) return\n\n binding?.release()\n binding = bindFrame(page, {\n select: (key) => {\n fromFrame = true\n emit('select', key)\n fromFrame = false\n },\n })\n\n highlightBlock(page, props.selected ?? null)\n reveal(page, props.selected ?? null)\n}\n\n/**\n * Bring the selected block into the window of the frame.\n *\n * The frame is scaled with a transform, which does not affect what is inside it: the page\n * scrolls in its own window, at its own size, and knows nothing about the scale.\n */\nfunction reveal(page: Document, key: string | null): void {\n if (key === null || fromFrame) return\n\n blockElement(page, key)?.scrollIntoView({ behavior: 'smooth', block: 'center' })\n}\n\n/** Swap one block's markup in place; false when the page has to be reloaded instead. */\nfunction replace(key: string, html: string): boolean {\n const page = doc()\n\n if (!page || !ready.value) return false\n\n const done = replaceBlock(page, key, html)\n if (done) highlightBlock(page, props.selected ?? null)\n\n return done\n}\n\nfunction refresh(): void {\n ready.value = false\n if (frame.value && props.url) frame.value.src = props.url\n}\n\nfunction onKey(event: KeyboardEvent): void {\n if (event.key === 'Escape' && fullscreen.value) {\n fullscreen.value = false\n event.stopPropagation()\n }\n}\n\nwatch(\n () => props.selected,\n (key) => {\n const page = doc()\n\n if (!page || !ready.value) return\n\n highlightBlock(page, key ?? null)\n reveal(page, key ?? null)\n },\n)\n\nwatch(() => props.reload, refresh)\nwatch(\n () => props.url,\n () => (ready.value = false),\n)\n\nonMounted(() => window.addEventListener('keydown', onKey))\nonBeforeUnmount(() => {\n window.removeEventListener('keydown', onKey)\n binding?.release()\n})\n\ndefineExpose({ replace, refresh, open: () => (fullscreen.value = true) })\n</script>\n\n<template>\n <div\n class=\"wx-blocks-preview\"\n :class=\"{ 'is-fullscreen': fullscreen, 'is-phone': mode === 'phone', 'is-fill': fill }\"\n :style=\"{ '--wx-preview-scale': scale }\"\n >\n <div class=\"wx-blocks-preview__bar\">\n <wx-text size=\"xs\" tone=\"muted\" class=\"wx-blocks-preview__label\" truncate>{{\n label\n }}</wx-text>\n <div class=\"wx-blocks-preview__tools\">\n <wx-segmented v-if=\"fullscreen\" v-model=\"fullWidth\" :options=\"widths\" size=\"sm\" />\n <wx-button\n v-if=\"url\"\n size=\"sm\"\n variant=\"outline\"\n :href=\"url\"\n target=\"_blank\"\n rel=\"noopener\"\n >\n {{ t('field.open-site') }}\n </wx-button>\n <wx-button size=\"sm\" variant=\"outline\" @click=\"fullscreen = !fullscreen\">\n {{ fullscreen ? t('field.close') : t('field.fullscreen') }}\n </wx-button>\n </div>\n </div>\n <div ref=\"box\" class=\"wx-blocks-preview__ground\">\n <div class=\"wx-blocks-preview__clip\" :style=\"{ width: `${Math.round(width * scale)}px` }\">\n <iframe\n v-if=\"url\"\n ref=\"frame\"\n class=\"wx-blocks-preview__frame\"\n :src=\"url\"\n :style=\"frameStyle\"\n :title=\"t('field.preview')\"\n @load=\"onLoad\"\n />\n </div>\n </div>\n </div>\n</template>\n\n<style scoped>\n/*\n * `border-box`, and it is `is-fill` below that needs it: `height: 100%` of a content box is\n * the height it was given *plus* its two borders, so the preview stood two pixels taller than\n * the panel holding it and the whole tab grew a scrollbar for them. Measured — 746 against\n * 744, which is exactly a border on each edge.\n */\n.wx-blocks-preview {\n box-sizing: border-box;\n display: flex;\n flex-direction: column;\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n background: var(--wx-bg-surface);\n overflow: hidden;\n min-width: 0;\n}\n\n.wx-blocks-preview.is-fullscreen {\n position: fixed;\n inset: 0;\n z-index: 40;\n border: 0;\n border-radius: 0;\n}\n\n.wx-blocks-preview__bar {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--wx-space-8);\n padding: var(--wx-space-8) var(--wx-space-12);\n border-block-end: 1px solid var(--wx-border-muted);\n}\n\n.wx-blocks-preview__label {\n min-width: 0;\n font-family: var(--wx-font-family-mono);\n}\n\n.wx-blocks-preview__tools {\n display: flex;\n gap: var(--wx-space-8);\n align-items: center;\n flex-wrap: wrap;\n}\n\n.wx-blocks-preview__ground {\n flex: 1;\n padding: var(--wx-space-12);\n background: var(--wx-bg-subtle);\n overflow: auto;\n max-height: calc(100vh - 200px);\n}\n\n.is-fullscreen .wx-blocks-preview__ground {\n max-height: none;\n}\n\n/*\n * Told how tall to be rather than working it out from the window: the two viewport-sized caps\n * below are for a preview standing on a page that scrolls, and inside a panel that already has\n * a height they are a second, smaller box that fights the first.\n */\n.wx-blocks-preview.is-fill {\n height: 100%;\n}\n\n.is-fill .wx-blocks-preview__ground {\n max-height: none;\n min-height: 0;\n}\n\n/*\n * All of the height it was given, and no more: the frame is as tall as the ground once the\n * scale has been applied to it, so the page inside scrolls in its own window rather than in a\n * box of ours. Without the division the frame is drawn at `height × scale` and the rest of the\n * ground is empty — a third of the column, at the scale a 420px preview of a 1280px page runs\n * at, and that emptiness is what the ground used to scroll.\n */\n.is-fill:not(.is-fullscreen) .wx-blocks-preview__ground {\n overflow: hidden;\n}\n\n.is-fill:not(.is-fullscreen) .wx-blocks-preview__clip {\n height: 100%;\n}\n\n.is-fill:not(.is-fullscreen) .wx-blocks-preview__frame {\n height: calc(100% / var(--wx-preview-scale, 1));\n}\n\n.wx-blocks-preview__clip {\n margin-inline: auto;\n overflow: hidden;\n box-shadow: var(--wx-shadow-sm);\n}\n\n.wx-blocks-preview__frame {\n display: block;\n border: 0;\n background: #fff;\n height: min(72vh, 720px);\n transform-origin: top left;\n}\n\n.is-fullscreen .wx-blocks-preview__frame {\n height: calc(100vh - 100px);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { WxAction, WxIcon, WxSortableList } from '@webx-ui/core'\nimport type { ScreenNode } from '@webx-ui/schema'\nimport { nestedFields } from './content'\nimport type { BlockNode, BlockType } from './types'\n\n/**\n * One level of the tree, and itself again for every container. Rows reorder among their\n * siblings by drag; a container shows its fields' lists underneath, each with its own\n * \"add inside\". Moving a block between containers is not a drag — a duplicate and a remove\n * do it, and a drag across allow-rules would need a judge at every drop.\n */\nconst props = withDefaults(\n defineProps<{\n nodes: BlockNode[]\n catalog: BlockType[]\n parentKey?: string | null\n field?: string | null\n selected?: string | null\n disabled?: boolean\n depth?: number\n }>(),\n { parentKey: null, field: null, selected: null, disabled: false, depth: 0 },\n)\n\nconst emit = defineEmits<{\n select: [key: string]\n add: [parentKey: string | null, field: string | null, node: ScreenNode | null]\n remove: [key: string]\n duplicate: [key: string]\n visibility: [key: string, hidden: boolean]\n reorder: [parentKey: string | null, field: string | null, list: BlockNode[]]\n}>()\n\nconst t = useTranslate('webx-blocks')\n\nfunction typeOf(node: BlockNode): BlockType | null {\n return props.catalog.find((type) => type.slug === node.type) ?? null\n}\n\nfunction titleOf(node: BlockNode): string {\n return typeOf(node)?.title ?? node.type\n}\n\nfunction fieldsOf(node: BlockNode): ScreenNode[] {\n const type = typeOf(node)\n\n return type?.content ? nestedFields(type.content.schema) : []\n}\n\nfunction childrenIn(node: BlockNode, field: ScreenNode): BlockNode[] {\n const value = node.values[field.id]\n\n return Array.isArray(value) ? (value as BlockNode[]) : []\n}\n\nfunction iconOf(node: BlockNode): string {\n return typeOf(node)?.icon ?? 'grid'\n}\n</script>\n\n<template>\n <wx-sortable-list\n :model-value=\"nodes\"\n item-key=\"key\"\n :item-label=\"(node: BlockNode) => titleOf(node)\"\n :disabled=\"disabled\"\n plain\n size=\"sm\"\n :empty-text=\"depth === 0 ? t('field.empty') : ''\"\n class=\"wx-blocks-tree\"\n :class=\"{ 'is-nested': depth > 0 }\"\n @update:model-value=\"emit('reorder', parentKey, field, $event as BlockNode[])\"\n >\n <template #default=\"{ item }\">\n <div class=\"wx-blocks-tree__node\">\n <div\n class=\"wx-blocks-tree__row\"\n :class=\"{ 'is-selected': selected === item.key, 'is-hidden': item.hidden === true }\"\n role=\"button\"\n tabindex=\"0\"\n @click=\"emit('select', item.key)\"\n @keydown.enter.prevent=\"emit('select', item.key)\"\n @keydown.space.prevent=\"emit('select', item.key)\"\n >\n <span class=\"wx-blocks-tree__icon\"><wx-icon :name=\"iconOf(item)\" /></span>\n <span class=\"wx-blocks-tree__name\">{{ titleOf(item) }}</span>\n <span\n v-if=\"!typeOf(item)\"\n class=\"wx-blocks-tree__flag is-danger\"\n :title=\"t('field.unknown-type', { type: item.type })\"\n >\n <wx-icon name=\"close-circle\" />\n </span>\n <span\n v-else-if=\"typeOf(item)?.draft\"\n class=\"wx-blocks-tree__flag is-warning\"\n :title=\"t('field.draft-type')\"\n >\n <wx-icon name=\"warning\" />\n </span>\n <span\n v-else-if=\"typeOf(item)?.is_enabled === false\"\n class=\"wx-blocks-tree__flag\"\n :title=\"t('field.disabled-type')\"\n >\n <!-- Not the eye: that one now means this block is off, which is a different thing\n from its type being withdrawn from the catalogue. -->\n <wx-icon name=\"lock\" />\n </span>\n <!-- Always, not only on hover: the actions beside it are invisible at rest, and a\n row that is merely dimmer than its neighbours is not a statement. -->\n <span\n v-if=\"item.hidden === true\"\n class=\"wx-blocks-tree__flag\"\n :title=\"t('field.hidden-note')\"\n >\n <wx-icon name=\"eye-off\" />\n </span>\n <span v-if=\"!disabled\" class=\"wx-blocks-tree__actions\" @click.stop>\n <wx-action\n :icon=\"item.hidden === true ? 'eye-off' : 'eye'\"\n size=\"sm\"\n :title=\"item.hidden === true ? t('field.show') : t('field.hide')\"\n @click=\"emit('visibility', item.key, item.hidden !== true)\"\n />\n <wx-action\n icon=\"copy\"\n size=\"sm\"\n :title=\"t('field.duplicate')\"\n @click=\"emit('duplicate', item.key)\"\n />\n <wx-action\n icon=\"trash\"\n size=\"sm\"\n tone=\"danger\"\n :title=\"t('field.remove')\"\n @click=\"emit('remove', item.key)\"\n />\n </span>\n </div>\n\n <div v-for=\"slot in fieldsOf(item)\" :key=\"slot.id\" class=\"wx-blocks-tree__kids\">\n <blocks-tree\n :nodes=\"childrenIn(item, slot)\"\n :catalog=\"catalog\"\n :parent-key=\"item.key\"\n :field=\"slot.id\"\n :selected=\"selected\"\n :disabled=\"disabled\"\n :depth=\"depth + 1\"\n @select=\"emit('select', $event)\"\n @add=\"(p, f, n) => emit('add', p, f, n)\"\n @remove=\"emit('remove', $event)\"\n @duplicate=\"emit('duplicate', $event)\"\n @visibility=\"(key, hidden) => emit('visibility', key, hidden)\"\n @reorder=\"(p, f, list) => emit('reorder', p, f, list)\"\n />\n <button\n v-if=\"!disabled\"\n type=\"button\"\n class=\"wx-blocks-tree__add is-inner\"\n @click=\"emit('add', item.key, slot.id, slot)\"\n >\n + {{ t('field.add-inside')\n }}<template v-if=\"fieldsOf(item).length > 1\"> · {{ slot.label ?? slot.id }}</template>\n </button>\n </div>\n </div>\n </template>\n </wx-sortable-list>\n</template>\n\n<style scoped>\n.wx-blocks-tree :deep(.wx-sortable-list__content) {\n min-width: 0;\n}\n\n.wx-blocks-tree__node {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-2);\n min-width: 0;\n}\n\n.wx-blocks-tree__row {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n padding: var(--wx-space-6) var(--wx-space-8);\n border: 1px solid transparent;\n border-radius: var(--wx-radius-control);\n cursor: pointer;\n}\n\n.wx-blocks-tree__row:hover {\n background: var(--wx-bg-subtle);\n}\n\n.wx-blocks-tree__row.is-selected {\n background: var(--wx-color-primary-soft);\n border-color: var(--wx-color-primary);\n}\n\n.wx-blocks-tree__icon {\n display: grid;\n place-items: center;\n flex: none;\n width: 24px;\n height: 24px;\n border-radius: var(--wx-radius-sm);\n background: var(--wx-bg-subtle);\n color: var(--wx-text-muted);\n}\n\n.is-selected .wx-blocks-tree__icon {\n background: var(--wx-bg-surface);\n color: var(--wx-color-primary);\n}\n\n.wx-blocks-tree__name {\n flex: 1;\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: var(--wx-font-size-sm);\n font-weight: var(--wx-font-weight-medium);\n}\n\n/*\n * A switched-off block is dimmed, not struck out or greyed to illegibility: it is still the\n * row an editor clicks to edit it, and the eye beside it is what says why it looks different.\n */\n.wx-blocks-tree__row.is-hidden .wx-blocks-tree__name,\n.wx-blocks-tree__row.is-hidden .wx-blocks-tree__icon {\n opacity: 0.55;\n}\n\n.wx-blocks-tree__flag {\n display: flex;\n color: var(--wx-text-muted);\n}\n\n.wx-blocks-tree__flag.is-warning {\n color: var(--wx-color-warning);\n}\n\n.wx-blocks-tree__flag.is-danger {\n color: var(--wx-color-danger);\n}\n\n.wx-blocks-tree__actions {\n display: flex;\n gap: var(--wx-space-2);\n opacity: 0;\n}\n\n.wx-blocks-tree__row:hover .wx-blocks-tree__actions,\n.wx-blocks-tree__row:focus-within .wx-blocks-tree__actions,\n.wx-blocks-tree__row.is-selected .wx-blocks-tree__actions {\n opacity: 1;\n}\n\n.wx-blocks-tree__kids {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-2);\n margin-inline-start: var(--wx-space-14);\n padding-inline-start: var(--wx-space-8);\n border-inline-start: 1px dashed var(--wx-border-default);\n}\n\n.wx-blocks-tree__add {\n width: 100%;\n padding: var(--wx-space-6);\n border: 1px dashed var(--wx-border-strong);\n border-radius: var(--wx-radius-control);\n background: transparent;\n color: var(--wx-text-muted);\n font: inherit;\n font-size: var(--wx-font-size-xs);\n cursor: pointer;\n}\n\n.wx-blocks-tree__add:hover {\n color: var(--wx-color-primary);\n border-color: var(--wx-color-primary);\n background: var(--wx-color-primary-soft);\n}\n</style>\n","import { inject, provide, type InjectionKey, type Ref } from 'vue'\n\n/**\n * What the page hosting a constructor knows and the constructor does not: where the preview\n * of the entity is. The address is `Preview::url()` on the server — signed, short-lived, one\n * entity — and it is the consumer module's screen that asks for it, because only that\n * screen knows which entity it is editing.\n *\n * The constructor shows the page in an iframe when this is provided, and works as a tree\n * with a form when it is not.\n */\nexport interface BlocksPreview {\n /** The preview address, or null while there is none — an entity not yet saved. */\n url: Ref<string | null>\n /** Bump to reload the frame: after an autosave, when the tree changed shape. */\n reload?: Ref<number>\n}\n\nexport const blocksPreviewKey: InjectionKey<BlocksPreview> = Symbol('wx-blocks-preview')\n\n/** Called by the hosting screen, above the `wx-blocks` field. */\nexport function provideBlocksPreview(preview: BlocksPreview): void {\n provide(blocksPreviewKey, preview)\n}\n\nexport function useBlocksPreview(): BlocksPreview | null {\n return inject(blocksPreviewKey, null)\n}\n\n/**\n * Set by the constructor for everything it draws, so that a `wx-blocks` node inside a\n * block's own form knows it is nested — and draws a note instead of a second constructor.\n */\nexport const blocksRootKey: InjectionKey<boolean> = Symbol('wx-blocks-root')\n","<script setup lang=\"ts\">\nimport {\n computed,\n getCurrentInstance,\n inject,\n onBeforeUnmount,\n onMounted,\n provide,\n ref,\n watch,\n} from 'vue'\nimport { adminKey, useErrorText, useTranslate, type AdminContext } from '@webx-ui/module-admin'\nimport { confirm, createModal, toast, WxButton, WxText } from '@webx-ui/core'\nimport {\n coreTypes,\n WxScreenRenderer,\n type RenderContext,\n type ScreenNode,\n type TypeRegistry,\n} from '@webx-ui/schema'\nimport { createBlocksApi, type BlocksApi } from './api'\nimport BlockPicker from './BlockPicker.vue'\nimport BlocksPreview from './BlocksPreview.vue'\nimport BlocksTree from './BlocksTree.vue'\nimport {\n cloneNode,\n countInside,\n insertNode,\n locate,\n makeNode,\n removeNode,\n replaceList,\n setHidden,\n updateValues,\n} from './content'\nimport { useBlocksMessages } from './i18n'\nimport { blocksPreviewKey, blocksRootKey } from './preview'\nimport { formSchema } from './schema'\nimport type { BlockNode, BlockType } from './types'\n\n/**\n * The constructor — the `wx-blocks` field.\n *\n * Two states (§14). Nothing selected: the tree and the preview of the whole page, wide,\n * for looking at the layout, the order and the seams. A block selected: the tree, a wide\n * form of the block's fields, and the preview shrunk to a phone at one to one — a desktop\n * in a 420 px column is unreadable, and a phone is where things break first.\n *\n * Inside a block's own form the same node type means a nested constructor, and those are\n * edited in the tree on the left — so a nested instance draws a note and nothing else.\n */\ndefineOptions({ name: 'WxBlocks', inheritAttrs: false })\n\nconst props = withDefaults(\n defineProps<{\n /** Handed over by the renderer: the node being drawn and the way down. Unused here. */\n node?: ScreenNode\n context?: RenderContext\n name?: string\n localized?: boolean\n /** Narrows what may be added at the top level, beyond what the types themselves allow. */\n allow?: string[] | null\n /** How many blocks the top level may hold. */\n max?: number | null\n /**\n * The published types with their schemas. Fetched from the panel when absent — handed\n * in for a screen outside one, a demo or a test.\n */\n catalog?: BlockType[] | null\n disabled?: boolean\n /** Where the section lives, for the picker's \"make one\" link. */\n blocksPath?: string\n /**\n * Be as tall as what the field is drawn in, and let each of the three panels scroll inside\n * itself.\n *\n * Off by default, because the ordinary case is a field on a form that scrolls: there the\n * constructor is as tall as it needs to be and the preview sticks. A screen that has given\n * the constructor the whole area below its head says so — otherwise the field grows, the\n * page scrolls, and the tree, the form and the preview all leave the screen together.\n */\n fill?: boolean\n }>(),\n {\n node: undefined,\n context: undefined,\n name: undefined,\n localized: false,\n allow: null,\n max: null,\n catalog: null,\n disabled: false,\n blocksPath: '/blocks',\n fill: false,\n },\n)\n\nconst model = defineModel<BlockNode[]>({ default: () => [] })\n\nconst nested = inject(blocksRootKey, false)\nprovide(blocksRootKey, true)\n\nuseBlocksMessages()\nconst t = useTranslate('webx-blocks')\n/* Not the server's `message`: the panel says how a request failed in its own words (§13.3). */\nconst message = useErrorText()\n\n/* The panel, when there is one. A demo page has none, and gets by on the catalog prop —\n which is why this is `inject` and not `useAdmin()`: that throws outside a panel, and a\n field must not. */\nconst admin: AdminContext | null = inject(adminKey, null)\nlet api: BlocksApi | null = null\n\nconst loaded = ref<BlockType[]>([])\nconst catalog = computed(() => props.catalog ?? loaded.value)\n\nconst tree = computed<BlockNode[]>(() => (Array.isArray(model.value) ? model.value : []))\n\nconst selectedKey = ref<string | null>(null)\nconst selected = computed(() => (selectedKey.value ? locate(tree.value, selectedKey.value) : null))\nconst selectedType = computed(() =>\n selected.value\n ? (catalog.value.find((type) => type.slug === selected.value?.node.type) ?? null)\n : null,\n)\n\nconst preview = inject(blocksPreviewKey, null)\nconst previewEl = ref<InstanceType<typeof BlocksPreview> | null>(null)\n\nconst groups = computed<string[]>(\n () =>\n (admin?.state.manifest?.modules.find((m) => m.id === 'blocks')?.meta?.groups as\n string[] | undefined) ?? [],\n)\n\n/** Node types for the block's form: the panel's registry, or the core plus this field. */\nconst self = getCurrentInstance()?.type\nconst types = computed<TypeRegistry>(() => {\n if (props.context?.types) return props.context.types\n if (admin?.types) return { ...coreTypes, ...admin.types }\n\n return self\n ? { ...coreTypes, 'wx-blocks': { component: self, kind: 'field', nested: true } }\n : coreTypes\n})\n\nconst translate = computed(\n () => props.context?.translate ?? admin?.i18n.t ?? ((key: string) => key),\n)\nconst can = computed(() => props.context?.can ?? admin?.can ?? (() => true))\n\nconst pick = createModal<\n BlockType,\n {\n catalog: BlockType[]\n parent: BlockType | null\n allow: string[] | null\n tree: BlockNode[]\n groups: string[]\n blocksPath: string\n }\n>(BlockPicker)\n\nfunction set(next: BlockNode[]): void {\n model.value = next\n}\n\nasync function add(\n parentKey: string | null,\n field: string | null,\n slot: ScreenNode | null,\n): Promise<void> {\n const parent = parentKey ? locate(tree.value, parentKey) : null\n const parentType = parent\n ? (catalog.value.find((type) => type.slug === parent.node.type) ?? null)\n : null\n const allow =\n parentKey === null ? props.allow : ((slot?.props?.allow as string[] | undefined) ?? null)\n const max = parentKey === null ? props.max : ((slot?.props?.max as number | undefined) ?? null)\n const list =\n parentKey === null\n ? tree.value\n : parent && field\n ? ((parent.node.values[field] as BlockNode[] | undefined) ?? [])\n : []\n\n if (max !== null && max !== undefined && list.length >= max) return\n\n const type = await pick({\n catalog: catalog.value,\n parent: parentType,\n allow,\n tree: tree.value,\n groups: groups.value,\n blocksPath: props.blocksPath,\n })\n\n if (!type) return\n\n const node = makeNode(type.slug, structuredSample(type))\n set(insertNode(tree.value, parentKey, field, list.length, node))\n selectedKey.value = node.key\n}\n\n/** A new block starts from the sample rather than empty, so the page shows something. */\nfunction structuredSample(type: BlockType): Record<string, unknown> {\n const sample = type.content?.sample ?? {}\n const values: Record<string, unknown> = {}\n\n for (const [key, value] of Object.entries(sample)) {\n // Nested blocks in a sample are the author's own — a page starts with an empty container.\n if (!Array.isArray(value) || value.length === 0 || typeof value[0] !== 'object')\n values[key] = value\n }\n\n return values\n}\n\n/**\n * A block on its own goes without a question — it is one row in a tree that is right there, and\n * the draft keeps a version of what it was. A container is asked about, because what leaves\n * with it is not on screen: collapse a section and its twelve blocks are one row (§14.2).\n */\nasync function remove(key: string): Promise<void> {\n const found = locate(tree.value, key)\n\n if (!found) return\n\n const inside = countInside(found.node)\n\n if (inside > 0) {\n const agreed = await confirm({\n title: t('field.remove-title', {\n title:\n catalog.value.find((type) => type.slug === found.node.type)?.title ?? found.node.type,\n }),\n message: t('field.remove-text', { count: inside }),\n confirmText: t('field.remove'),\n cancelText: t('page.cancel'),\n tone: 'danger',\n })\n\n if (!agreed) return\n }\n\n if (selectedKey.value === key) selectedKey.value = null\n set(removeNode(tree.value, key))\n}\n\nfunction duplicate(key: string): void {\n const found = locate(tree.value, key)\n if (!found) return\n\n const copy = cloneNode(found.node)\n set(insertNode(tree.value, found.parent?.key ?? null, found.field, found.index + 1, copy))\n selectedKey.value = copy.key\n}\n\n/*\n * No question asked, unlike removing a container: this is one click, it is visible in the row\n * the moment it happens, and the same click puts it back.\n */\nfunction visibility(key: string, hidden: boolean): void {\n set(setHidden(tree.value, key, hidden))\n}\n\nfunction reorder(parentKey: string | null, field: string | null, list: BlockNode[]): void {\n set(replaceList(tree.value, parentKey, field, list))\n}\n\nfunction select(key: string): void {\n selectedKey.value = selectedKey.value === key ? null : key\n}\n\n/**\n * A block clicked in the preview opens for editing.\n *\n * Not a toggle, unlike the row in the tree: pointing at a thing on the page and having it\n * close is not what anybody means by it. A click that lands on no block at all — the margin\n * of the page, the space between two sections — is left alone rather than treated as \"close\",\n * because missing is easy and losing the form over it is not what was meant either.\n */\nfunction selectFromPreview(key: string | null): void {\n if (key === null || !locate(tree.value, key)) return\n\n selectedKey.value = key\n}\n\nfunction done(): void {\n selectedKey.value = null\n}\n\nfunction onValues(values: Record<string, unknown>): void {\n if (!selectedKey.value) return\n\n set(updateValues(tree.value, selectedKey.value, values))\n}\n\n/* After a field changed, the block is redrawn on the server and swapped into the page a\n moment after the last keystroke. A swap that finds no markers — the block is new, the\n page has not been saved since — asks the host to reload instead. */\nlet timer: ReturnType<typeof setTimeout> | undefined\n\nwatch(\n () => selected.value?.node.values,\n (values, before) => {\n if (!values || !before || !selectedType.value || !api || !preview) return\n\n const key = selectedKey.value\n const typeId = selectedType.value.id\n\n clearTimeout(timer)\n timer = setTimeout(() => {\n if (!key || !api) return\n\n void api\n .render(typeId, { values, key })\n .then((drawn) => {\n if (!previewEl.value?.replace(key, drawn.html)) previewEl.value?.refresh()\n })\n .catch(() => {})\n }, 300)\n },\n { deep: true },\n)\n\nfunction onKey(event: KeyboardEvent): void {\n if (event.key === 'Escape' && selectedKey.value) done()\n}\n\nonMounted(async () => {\n window.addEventListener('keydown', onKey)\n\n if (props.catalog === null && admin) {\n api = createBlocksApi(admin)\n\n try {\n loaded.value = await api.catalog()\n } catch (error) {\n toast.danger(message(error))\n }\n } else if (admin) {\n api = createBlocksApi(admin)\n }\n})\n\nonBeforeUnmount(() => {\n clearTimeout(timer)\n window.removeEventListener('keydown', onKey)\n})\n\nconst formRoot = computed(() =>\n selectedType.value?.content ? formSchema(selectedType.value.content.schema) : [],\n)\n</script>\n\n<template>\n <div v-if=\"nested\" class=\"wx-blocks-nested\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('field.nested-note') }}</wx-text>\n </div>\n\n <!-- The host is the container the queries below measure: a query on an element's own\n class resolves against its nearest ancestor container, never against itself. -->\n <div v-else class=\"wx-blocks-host\" :class=\"{ 'is-fill': fill }\">\n <div\n class=\"wx-blocks\"\n :class=\"{\n 'is-editing': selected !== null,\n 'has-preview': preview !== null && preview.url.value !== null,\n }\"\n >\n <div class=\"wx-blocks__tree\">\n <div class=\"wx-blocks__panel-head\">\n <span class=\"wx-blocks__panel-title\">{{ t('field.blocks') }}</span>\n <wx-text size=\"sm\" tone=\"muted\">{{ tree.length }}</wx-text>\n </div>\n <blocks-tree\n :nodes=\"tree\"\n :catalog=\"catalog\"\n :selected=\"selectedKey\"\n :disabled=\"disabled\"\n @select=\"select\"\n @add=\"add\"\n @remove=\"remove\"\n @duplicate=\"duplicate\"\n @visibility=\"visibility\"\n @reorder=\"reorder\"\n />\n <!--\n One row, not two stacked full-width buttons: they are not two steps of the same\n thing, and a column of blocks that ends in a column of buttons reads as two more\n blocks. Adding is the one that grows, because it is the one that is always there.\n -->\n <div class=\"wx-blocks__tools\">\n <wx-button\n v-if=\"!disabled && (max === null || tree.length < max)\"\n variant=\"outline\"\n icon=\"plus\"\n class=\"wx-blocks__add\"\n @click=\"add(null, null, null)\"\n >\n {{ t('field.add') }}\n </wx-button>\n <wx-button\n v-if=\"preview && preview.url.value\"\n variant=\"outline\"\n icon=\"eye\"\n class=\"wx-blocks__preview-button\"\n @click=\"previewEl?.open()\"\n >\n {{ t('field.preview') }}\n </wx-button>\n </div>\n </div>\n\n <div v-if=\"selected\" class=\"wx-blocks__fields\">\n <div class=\"wx-blocks__panel-head\">\n <span class=\"wx-blocks__panel-title\">{{\n selectedType?.title ?? selected.node.type\n }}</span>\n <span class=\"wx-blocks__panel-extra\">\n <code>{{ selected.node.type }}</code>\n <wx-button size=\"sm\" variant=\"outline\" @click=\"done\"\n >{{ t('field.done') }} · Esc</wx-button\n >\n </span>\n </div>\n <div class=\"wx-blocks__form\">\n <wx-screen-renderer\n v-if=\"selectedType?.content\"\n :key=\"selected.node.key\"\n :model-value=\"selected.node.values\"\n :root=\"formRoot\"\n :types=\"types\"\n :translate=\"translate\"\n :can=\"can\"\n :disabled=\"disabled\"\n @update:model-value=\"onValues\"\n />\n <wx-text v-else size=\"sm\" tone=\"danger\">{{\n t('field.unknown-type', { type: selected.node.type })\n }}</wx-text>\n </div>\n </div>\n\n <div v-if=\"preview && preview.url.value\" class=\"wx-blocks__preview\">\n <blocks-preview\n ref=\"previewEl\"\n :url=\"preview.url.value\"\n :selected=\"selectedKey\"\n :mode=\"selected ? 'phone' : 'wide'\"\n :reload=\"preview.reload?.value ?? 0\"\n :fill=\"fill\"\n @select=\"selectFromPreview\"\n />\n </div>\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-blocks-host {\n container-type: inline-size;\n}\n\n/*\n * Filling the area it was given: the grid stretches to it, and each panel scrolls in itself.\n * The preview stops sticking — there is nothing to stick to when the page does not move — and\n * it is the panels that scroll instead.\n */\n.wx-blocks-host.is-fill,\n.wx-blocks-host.is-fill .wx-blocks {\n height: 100%;\n min-height: 0;\n}\n\n.wx-blocks-host.is-fill .wx-blocks {\n align-items: stretch;\n}\n\n.wx-blocks-host.is-fill .wx-blocks__tree,\n.wx-blocks-host.is-fill .wx-blocks__fields {\n overflow: auto;\n}\n\n.wx-blocks-host.is-fill .wx-blocks__preview {\n position: static;\n min-height: 0;\n}\n\n.wx-blocks {\n display: grid;\n grid-template-columns: minmax(220px, 260px) minmax(0, 1fr);\n gap: var(--wx-gap, var(--wx-space-16));\n align-items: start;\n}\n\n.wx-blocks.is-editing {\n grid-template-columns: minmax(220px, 260px) minmax(0, 1fr);\n}\n\n.wx-blocks.is-editing.has-preview {\n grid-template-columns: minmax(220px, 260px) minmax(360px, 1fr) 420px;\n}\n\n.wx-blocks__tree,\n.wx-blocks__fields {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n padding: var(--wx-space-8);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n background: var(--wx-bg-surface);\n min-width: 0;\n}\n\n.wx-blocks__panel-head {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--wx-space-8);\n padding: var(--wx-space-4) var(--wx-space-6);\n}\n\n.wx-blocks__panel-title {\n font-weight: var(--wx-font-weight-semibold);\n}\n\n.wx-blocks__panel-extra {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n}\n\n.wx-blocks__form {\n padding: var(--wx-space-6);\n}\n\n/*\n * On a form that scrolls, all three columns stand still and scroll inside themselves. The tree\n * is the one that makes this worth doing: a page of twenty blocks is a column taller than the\n * window, and without this the way to the block being edited is off the top of it.\n *\n * The cap is the window less the air above and below; the containing block of a sticky grid\n * item is its grid area, which is the whole row, so a short column still stays with a tall one.\n */\n.wx-blocks-host:not(.is-fill) .wx-blocks__tree,\n.wx-blocks-host:not(.is-fill) .wx-blocks__fields {\n position: sticky;\n top: var(--wx-space-12);\n max-height: calc(100dvh - var(--wx-space-24));\n overflow: auto;\n}\n\n.wx-blocks__preview {\n min-width: 0;\n position: sticky;\n top: var(--wx-space-12);\n}\n\n/* The foot of the tree: one row, the adding taking whatever the other one leaves. */\n.wx-blocks__tools {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n flex: none;\n}\n\n.wx-blocks__add {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.wx-blocks__preview-button {\n display: none;\n flex: none;\n}\n\n/* Below the width where three columns fit, the phone beside the form folds into a button\n that opens it full screen. The two-column state — the tree and the whole page — keeps its\n preview: a laptop's panel is narrower than three columns and wide enough for two. The\n threshold is the three columns at their minimum — 260 + 360 + 420 and the two gaps. */\n@container (max-width: 1080px) {\n .wx-blocks.is-editing.has-preview {\n grid-template-columns: minmax(220px, 260px) minmax(0, 1fr);\n }\n\n .wx-blocks.is-editing .wx-blocks__preview {\n display: none;\n }\n\n .wx-blocks.is-editing.has-preview .wx-blocks__preview-button {\n display: inline-flex;\n }\n\n /* Full screen still needs the node in the tree: it is drawn there, only unstuck. */\n .wx-blocks.is-editing .wx-blocks__preview:has(.is-fullscreen) {\n display: block;\n position: static;\n }\n}\n\n/* One column: the preview is a button in either state. */\n@container (max-width: 720px) {\n .wx-blocks,\n .wx-blocks.is-editing,\n .wx-blocks.has-preview,\n .wx-blocks.is-editing.has-preview {\n grid-template-columns: minmax(0, 1fr);\n }\n\n .wx-blocks__preview {\n display: none;\n }\n\n .wx-blocks.has-preview .wx-blocks__preview-button {\n display: inline-flex;\n }\n\n .wx-blocks__preview:has(.is-fullscreen) {\n display: block;\n position: static;\n }\n}\n\ncode {\n font-family: var(--wx-font-family-mono);\n font-size: var(--wx-font-size-xs);\n color: var(--wx-text-muted);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { WxBadge, WxText } from '@webx-ui/core'\nimport BlockThumb from './BlockThumb.vue'\nimport type { BlockType } from './types'\n\n/** One type in the list: its picture, its name, where it stands and which versions it has. */\ndefineProps<{ block: BlockType }>()\n\nconst emit = defineEmits<{ open: [block: BlockType] }>()\n\nconst t = useTranslate('webx-blocks')\n</script>\n\n<template>\n <button type=\"button\" class=\"wx-block-card\" @click=\"emit('open', block)\">\n <block-thumb :thumbnail=\"block.thumbnail\" :height=\"120\" />\n <div class=\"wx-block-card__body\">\n <div class=\"wx-block-card__title\">{{ block.title }}</div>\n <wx-text size=\"sm\" tone=\"muted\">\n <code>{{ block.slug }}</code>\n ·\n {{\n block.usage_count > 0\n ? t('page.on-pages', { count: block.usage_count })\n : t('page.not-used')\n }}\n </wx-text>\n <div class=\"wx-block-card__chips\">\n <wx-badge v-if=\"block.draft\" type=\"warning\" dot>\n {{ t('page.draft', { number: block.draft.number }) }}\n </wx-badge>\n <wx-badge v-if=\"block.published\" type=\"success\" dot>\n {{ t('page.live', { number: block.published.number }) }}\n </wx-badge>\n <wx-badge v-else type=\"default\">{{ t('page.never-published') }}</wx-badge>\n <wx-badge v-if=\"!block.is_enabled\" type=\"default\" variant=\"outline\">\n {{ t('page.hidden') }}\n </wx-badge>\n </div>\n </div>\n </button>\n</template>\n\n<style scoped>\n.wx-block-card {\n display: flex;\n flex-direction: column;\n width: 100%;\n padding: 0;\n overflow: hidden;\n text-align: start;\n font: inherit;\n color: inherit;\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n cursor: pointer;\n}\n\n.wx-block-card:hover,\n.wx-block-card:focus-visible {\n border-color: var(--wx-color-primary);\n outline: none;\n}\n\n.wx-block-card__body {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-6);\n padding: var(--wx-space-12) var(--wx-space-14);\n}\n\n.wx-block-card__title {\n font-weight: var(--wx-font-weight-semibold);\n}\n\n.wx-block-card__chips {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wx-space-6);\n}\n\ncode {\n font-family: var(--wx-font-family-mono);\n font-size: var(--wx-font-size-xs);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport { useAdmin, useErrorText, useTranslate } from '@webx-ui/module-admin'\nimport {\n toast,\n useModal,\n WxButton,\n WxDialog,\n WxFormItem,\n WxInput,\n WxSelect,\n WxSpace,\n} from '@webx-ui/core'\nimport { createBlocksApi } from './api'\nimport { useBlocksMessages } from './i18n'\nimport { groupLabel } from './schema'\nimport type { BlockType } from './types'\n\n/**\n * A new type needs three things to exist — a name, an identifier and a group — and gets an\n * empty draft to open. Everything else is the editor's job.\n */\nconst { resolve, dismiss, open } = useModal<BlockType>()\n\nconst context = useAdmin()\nconst api = createBlocksApi(context)\nuseBlocksMessages()\n\nconst t = useTranslate('webx-blocks')\n/* Not the server's `message`: the panel says how a request failed in its own words (§13.3). */\nconst message = useErrorText()\n\nconst groups = computed<string[]>(() => {\n const meta = context.state.manifest?.modules.find((module) => module.id === 'blocks')?.meta\n\n return (meta?.groups as string[] | undefined) ?? ['content']\n})\n\nconst form = ref({ title: '', slug: '', group: groups.value[0] ?? 'content' })\nconst errors = ref<Record<string, string[]>>({})\nconst saving = ref(false)\nconst slugTouched = ref(false)\n\nconst groupOptions = computed(() =>\n groups.value.map((id) => ({ value: id, label: groupLabel(id, t) })),\n)\n\n/** A slug from the name, until the person types one of their own. Latin only: the identifier is code. */\nfunction slugify(text: string): string {\n return text\n .toLowerCase()\n .replace(/[^a-z0-9]+/g, '-')\n .replace(/^-+|-+$/g, '')\n .replace(/^[^a-z]+/, '')\n .slice(0, 64)\n}\n\nwatch(\n () => form.value.title,\n (title) => {\n if (!slugTouched.value) form.value.slug = slugify(title)\n },\n)\n\nfunction errorOf(field: string): string | undefined {\n return errors.value[field]?.[0]\n}\n\nasync function save(): Promise<void> {\n saving.value = true\n errors.value = {}\n\n try {\n resolve(await api.create(form.value))\n } catch (error) {\n const body = (error as { body?: { errors?: Record<string, string[]>; message?: string } }).body\n\n if (body?.errors) {\n errors.value = body.errors\n } else {\n toast.danger(message(error, t('page.failed')))\n }\n } finally {\n saving.value = false\n }\n}\n</script>\n\n<template>\n <wx-dialog v-model:open=\"open\" :title=\"t('page.new')\" :width=\"520\">\n <div class=\"wx-block-create\">\n <wx-form-item :label=\"t('page.title')\" :error=\"errorOf('title')\">\n <wx-input v-model=\"form.title\" autofocus />\n </wx-form-item>\n\n <wx-form-item\n :label=\"t('page.identifier')\"\n :help=\"t('page.identifier-help')\"\n :error=\"errorOf('slug')\"\n >\n <wx-input v-model=\"form.slug\" placeholder=\"hero\" @input=\"slugTouched = true\" />\n </wx-form-item>\n\n <wx-form-item :label=\"t('page.group')\" :help=\"t('page.group-help')\" :error=\"errorOf('group')\">\n <wx-select v-model=\"form.group\" :options=\"groupOptions\" />\n </wx-form-item>\n </div>\n\n <template #footer>\n <wx-space size=\"sm\">\n <wx-button variant=\"outline\" @click=\"dismiss()\">{{ t('page.cancel') }}</wx-button>\n <wx-button type=\"primary\" :loading=\"saving\" @click=\"save\">{{ t('page.create') }}</wx-button>\n </wx-space>\n </template>\n </wx-dialog>\n</template>\n\n<style scoped>\n.wx-block-create {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-12);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onMounted, ref } from 'vue'\nimport { useRouter } from 'vue-router'\nimport { useAdmin, useErrorText, useTranslate, WxListScreen } from '@webx-ui/module-admin'\nimport {\n createModal,\n toast,\n WxAlert,\n WxButton,\n WxEmpty,\n WxInput,\n WxSkeleton,\n WxSkeletonItem,\n type TabItem,\n type TabValue,\n} from '@webx-ui/core'\nimport { createBlocksApi } from './api'\nimport BlockCard from './BlockCard.vue'\nimport BlockCreateDialog from './BlockCreateDialog.vue'\nimport { useBlocksMessages } from './i18n'\nimport { groupLabel } from './schema'\nimport type { BlocksMeta, BlockType } from './types'\n\n/**\n * The section: every type as a card with a live thumbnail, grouped the way the picker groups\n * them. Cards rather than a table because a block is recognised by its picture — \"Section\"\n * says nothing about whether it is a full-width band or a container with columns.\n */\nconst props = withDefaults(defineProps<{ base?: string }>(), { base: '/blocks' })\n\nconst context = useAdmin()\nconst api = createBlocksApi(context)\nconst router = useRouter()\nuseBlocksMessages()\n\nconst t = useTranslate('webx-blocks')\n/* Not the server's `message`: the panel says how a request failed in its own words (§13.3). */\nconst message = useErrorText()\n\nconst blocks = ref<BlockType[]>([])\nconst loading = ref(true)\nconst search = ref('')\n/** Which group is being looked at; `''` is all of them, grouped. */\nconst view = ref<TabValue>('')\n\nconst create = createModal<BlockType, Record<string, never>>(BlockCreateDialog)\n\nconst meta = computed<BlocksMeta>(() => {\n const found = context.state.manifest?.modules.find((module) => module.id === 'blocks')?.meta\n\n return {\n groups: (found?.groups as string[] | undefined) ?? [],\n editing: (found?.editing as boolean | undefined) ?? true,\n provides: (found?.provides as string[] | undefined) ?? [],\n }\n})\n\nconst canManage = computed(() => context.can('blocks.manage') && meta.value.editing)\n\nconst title = computed(\n () =>\n context.state.manifest?.modules.find((module) => module.id === 'blocks')?.title ??\n t('module.title'),\n)\n\nconst shown = computed(() => {\n const needle = search.value.trim().toLowerCase()\n const inView =\n view.value === '' ? blocks.value : blocks.value.filter((block) => block.group === view.value)\n\n if (needle === '') return inView\n\n return inView.filter(\n (block) =>\n block.title.toLowerCase().includes(needle) ||\n block.slug.includes(needle) ||\n (block.description ?? '').toLowerCase().includes(needle),\n )\n})\n\n/** The groups in the site's order, then any a type named that the config does not. */\nconst order = computed(() => {\n const ids = [...meta.value.groups]\n\n for (const block of blocks.value) {\n if (!ids.includes(block.group)) ids.push(block.group)\n }\n\n return ids.filter((id) => blocks.value.some((block) => block.group === id))\n})\n\n/**\n * The groups as the views of the list (§10), with everything at once first — which is how a\n * section of ten types is read, and what a search wants. Below two groups there is nothing to\n * choose between, and the strip would be a control that says one thing.\n */\nconst views = computed<TabItem[]>(() =>\n order.value.length < 2\n ? []\n : [\n { value: '', label: t('page.all-groups') },\n ...order.value.map((id) => ({ value: id, label: groupLabel(id, t) })),\n ],\n)\n\n/** What the grid draws: sections with headings, or one flat run of cards. */\nconst groups = computed(() => {\n const sections = order.value\n .map((id) => ({\n id,\n label: groupLabel(id, t),\n blocks: shown.value.filter((b) => b.group === id),\n }))\n .filter((section) => section.blocks.length > 0)\n\n // A handful of types needs no headings, a search wants a flat list, and a chosen group is\n // already named by the tab above it.\n const flat =\n view.value !== '' ||\n shown.value.length <= 5 ||\n search.value.trim() !== '' ||\n sections.length < 2\n\n return flat ? [{ id: '', label: '', blocks: shown.value }] : sections\n})\n\nasync function load(): Promise<void> {\n loading.value = true\n\n try {\n blocks.value = await api.list()\n } catch (error) {\n toast.danger(message(error))\n } finally {\n loading.value = false\n }\n}\n\nfunction open(block: BlockType): void {\n void router.push(`${props.base}/${block.id}`)\n}\n\nasync function add(): Promise<void> {\n const block = await create({})\n\n if (block) open(block)\n}\n\nonMounted(load)\n</script>\n\n<template>\n <wx-list-screen v-model:view=\"view\" class=\"wx-blocks-page\" :title=\"title\" :views=\"views\">\n <template v-if=\"canManage\" #actions>\n <wx-button type=\"primary\" icon=\"plus\" @click=\"add\">{{ t('page.new') }}</wx-button>\n </template>\n\n <wx-alert\n v-if=\"!meta.editing\"\n type=\"info\"\n variant=\"soft\"\n :description=\"t('page.editing-off')\"\n />\n\n <!-- Inside the card and along its top, where every other list of the panel keeps its\n search: on `Pages` it is the table's own row, and this grid has no table to put it in. -->\n <div v-if=\"loading || blocks.length > 0\" class=\"wx-blocks-page__toolbar\">\n <wx-input\n v-model=\"search\"\n class=\"wx-blocks-page__search\"\n :placeholder=\"t('page.search')\"\n clearable\n />\n </div>\n\n <!-- The placeholder is shaped like what is coming: a row of cards, not a paragraph. -->\n <wx-skeleton v-if=\"loading\">\n <template #template>\n <div class=\"wx-blocks-page__cards\">\n <div v-for=\"n in 4\" :key=\"n\" class=\"wx-blocks-page__ghost\">\n <wx-skeleton-item variant=\"image\" :height=\"120\" class=\"wx-blocks-page__ghost-thumb\" />\n <div class=\"wx-blocks-page__ghost-body\">\n <wx-skeleton-item variant=\"title\" width=\"45%\" />\n <wx-skeleton-item variant=\"text\" width=\"70%\" />\n <wx-skeleton-item variant=\"button\" width=\"64px\" height=\"22px\" />\n </div>\n </div>\n </div>\n </template>\n </wx-skeleton>\n\n <wx-empty\n v-else-if=\"blocks.length === 0\"\n icon=\"grid\"\n :title=\"t('page.empty')\"\n :description=\"t('page.empty-help')\"\n />\n\n <template v-else>\n <section v-for=\"group in groups\" :key=\"group.id\" class=\"wx-blocks-page__group\">\n <div v-if=\"group.label\" class=\"wx-blocks-page__group-title\">{{ group.label }}</div>\n <div class=\"wx-blocks-page__cards\">\n <block-card v-for=\"block in group.blocks\" :key=\"block.id\" :block=\"block\" @open=\"open\" />\n </div>\n </section>\n </template>\n </wx-list-screen>\n</template>\n\n<style scoped>\n.wx-blocks-page__toolbar {\n display: flex;\n justify-content: flex-end;\n}\n\n.wx-blocks-page__search {\n width: 100%;\n max-width: 280px;\n}\n\n.wx-blocks-page__ghost {\n display: flex;\n flex-direction: column;\n overflow: hidden;\n background: var(--wx-bg-surface);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n}\n\n.wx-blocks-page__ghost-thumb {\n border-radius: 0;\n}\n\n.wx-blocks-page__ghost-body {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n padding: var(--wx-space-12) var(--wx-space-14);\n}\n\n.wx-blocks-page__group {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-12);\n}\n\n.wx-blocks-page__group-title {\n font-size: var(--wx-font-size-xs);\n font-weight: var(--wx-font-weight-semibold);\n letter-spacing: 0.06em;\n text-transform: uppercase;\n color: var(--wx-text-muted);\n}\n\n.wx-blocks-page__cards {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));\n gap: var(--wx-gap, var(--wx-space-16));\n}\n</style>\n","import type { AdminModule } from '@webx-ui/module-admin'\nimport BlockEditorPage from './BlockEditorPage.vue'\nimport BlocksField from './BlocksField.vue'\nimport BlocksPage from './BlocksPage.vue'\n\nexport interface BlocksOptions {\n /** Where the section lives inside the panel. */\n path?: string\n}\n\n/**\n * The block constructor as a section of the panel, and `wx-blocks` as a field any screen can\n * put on an entity.\n *\n * The id matches the module the server reports, which is what makes the entry appear in the\n * navigation: the section shows up when both halves are installed.\n */\nexport function blocks(options: BlocksOptions = {}): AdminModule {\n const path = options.path ?? '/blocks'\n\n return {\n id: 'blocks',\n path,\n routes: [\n { path, name: 'webx.blocks', component: BlocksPage, props: { base: path } },\n {\n path: `${path}/:id(\\\\d+)`,\n name: 'webx.blocks.edit',\n component: BlockEditorPage,\n props: { base: path },\n },\n ],\n // What a screen means by `wx-blocks`: the content of an entity as a tree of blocks. A\n // nested field, so the renderer hands it the node and the way down — though it never\n // draws its children through the renderer; it needs the node for `props.allow` alone.\n types: {\n 'wx-blocks': {\n component: BlocksField,\n kind: 'field',\n nested: true,\n bind: () => ({ blocksPath: path }),\n },\n },\n }\n}\n"],"names":["createBlocksApi","admin","base","data","body","id","input","number","props","__props","t","useTranslate","mine","computed","lint","passed","codes","lines","_openBlock","_createElementBlock","_hoisted_1","_hoisted_2","_createVNode","_unref","WxIcon","_createElementVNode","_Fragment","_createTextVNode","_toDisplayString","_renderList","line","emit","__emit","context","useAdmin","api","message","useErrorText","versions","ref","load","state","version","restore","confirm","block","toast","error","onMounted","watch","_createBlock","WxSkeleton","_hoisted_3","WxText","WxDate","WxBadge","WxButton","$event","SELECTED_CLASS","HOVER_CLASS","STYLE_ID","findRange","root","key","walker","start","node","text","replaceBlock","doc","html","range","parent","template","anchor","next","done","fragment","inserted","runtime","child","blockElement","highlightBlock","ensureStyle","element","hoverBlock","keyAt","depth","sibling","bindFrame","handlers","hovered","swallow","event","onClick","onMove","onLeave","style","stageDocument","escapeAttribute","frame","value","widths","width","box","boxWidth","useElementWidth","contentHeight","scale","srcdoc","measure","onLoad","frameStyle","clipStyle","WxSegmented","isNode","isNodeList","newKey","makeNode","type","values","locate","tree","find","list","field","index","name","found","walk","visit","countType","slug","count","countInside","typesIn","seen","nestedFields","schema","cloneNode","clone","setHidden","hidden","listAt","parentKey","existing","insertNode","removeNode","updateValues","replaceList","blocksMessages","seeded","useBlocksMessages","i18n","GIVEN","lintBlock","content","lints","missing","undeclared","stray","bare","prefix","selector","selectors","few","source","withoutComments","media","lineAt","fieldIds","ids","declared","match","used","styles","prelude","trimmed","raw","comment","offset","names","formSchema","groupLabel","words","route","useRoute","router","useRouter","usage","loading","saving","publishing","tab","meta","module","canManage","settings","reactive","schemaText","schemaError","snapshot","errors","refusal","stage","current","dirty","groupOptions","group","sampleModel","collectIds","nodes","take","loaded","stored","onSchemaText","parsed","timer","pending","redraw","render","ticket","drawn","templateEditor","pill","insertField","editor","save","before","saved","publish","remove","refusalError","shownUsage","errorOf","leaveGuard","onBeforeUnmount","WxCard","WxBackButton","_hoisted_4","_hoisted_5","_hoisted_6","WxRenameButton","_hoisted_7","WxAlert","_hoisted_8","_hoisted_9","WxTabs","WxTab","_hoisted_10","WxCodeEditor","_cache","_hoisted_11","BlockChecks","_hoisted_13","_hoisted_14","_hoisted_15","_hoisted_16","_hoisted_17","WxHelpButton","_hoisted_18","WxFormItem","WxInput","WxSelect","WxTextarea","WxInputNumber","WxTagsInput","WxSwitch","_hoisted_19","BlockHistory","_hoisted_20","BlockStage","WxScreenRenderer","_hoisted_21","entity","WxActionBar","resolve","dismiss","open","useModal","search","allowedHere","parentAllows","typeAllows","options","exhausted","shown","needle","sections","order","grouped","o","section","emptyText","allowed","WxDialog","WxEmpty","_component_router_link","option","_normalizeClass","BlockThumb","fullscreen","fullWidth","ready","label","binding","fromFrame","page","reveal","replace","refresh","onKey","__expose","typeOf","titleOf","fieldsOf","childrenIn","iconOf","WxSortableList","_withCtx","item","WxAction","slot","_component_blocks_tree","p","f","n","blocksPreviewKey","provideBlocksPreview","preview","provide","useBlocksPreview","inject","blocksRootKey","model","_useModel","nested","adminKey","catalog","selectedKey","selected","selectedType","previewEl","groups","m","self","getCurrentInstance","types","coreTypes","translate","can","pick","createModal","BlockPicker","set","add","parentType","allow","max","structuredSample","sample","inside","duplicate","copy","visibility","reorder","select","selectFromPreview","onValues","typeId","formRoot","BlocksTree","BlocksPreview","form","slugTouched","slugify","title","WxSpace","blocks","view","create","BlockCreateDialog","inView","views","b","WxListScreen","WxSkeletonItem","BlockCard","path","BlocksPage","BlockEditorPage","BlocksField"],"mappings":"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"}