@webx-ui/module-blocks 0.10.3 → 0.10.4

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/messages.ts","../src/i18n.ts","../src/BlockDataField.vue","../src/api.ts","../src/BlockChecks.vue","../src/BlockHistory.vue","../src/frame.ts","../src/BlockStage.vue","../src/content.ts","../src/completions.ts","../src/lint.ts","../src/preview.ts","../src/schema.ts","../src/BlockEditorPage.vue","../src/BlockMoveDialog.vue","../src/shell.ts","../src/BlockThumb.vue","../src/move.ts","../src/BlockPicker.vue","../src/BlocksPreview.vue","../src/BlocksTree.vue","../src/BlocksField.vue","../src/BlockCard.vue","../src/BlockCreateDialog.vue","../src/BlockDeclaredCard.vue","../src/BlocksPage.vue","../src/module.ts"],"sourcesContent":["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 'on-page': 'on one page',\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 'icon-search': 'Search icons',\n 'icon-none': 'No icon of that name',\n 'icon-unknown': 'This name is not in the icon set, so nothing is drawn',\n 'icon-clear': 'Clear the 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: 'Style order',\n 'sort-help':\n \"The order of the styles on the page: a later block's rules win over an earlier one's. Dragging the cards does not change it.\",\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 examples: 'Examples',\n 'example-handler': 'A handler on something inside the block',\n 'example-values': 'A value the editor filled in',\n 'example-provided': 'A library the site provides',\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 is built from them.',\n 'schema-invalid': 'The schema is not valid JSON: :error',\n sample: 'Sample values',\n preview: 'Preview',\n width: 'Width',\n 'width-desktop': 'Desktop',\n 'width-tablet': 'Tablet',\n 'width-phone': 'Phone',\n usage: 'Where it is used',\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 'delete-used-one': 'The block stands on one page 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 'add-after': 'Add after',\n done: 'Done',\n remove: 'Remove',\n 'remove-title': 'Remove \":title\"?',\n 'remove-text': 'The :count blocks inside it go with it.',\n 'remove-alone': 'It leaves this page. The draft keeps what it was.',\n duplicate: 'Duplicate',\n move: 'Move to…',\n 'move-title': 'Move \":title\" to',\n 'move-page': 'The page itself',\n 'move-none': 'There is nowhere else this block may stand.',\n 'move-full': 'full',\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 previous: 'Previous block',\n next: 'Next block',\n\n preview: 'Preview',\n 'open-site': 'Open on the site',\n fullscreen: 'Full screen',\n close: 'Close',\n width: 'Width',\n 'width-desktop': 'Desktop',\n 'width-tablet': 'Tablet',\n 'width-phone': 'Phone',\n },\n components: {\n kind: 'Kind',\n 'kind-block': 'Block',\n 'kind-block-help':\n 'Editors put it on pages: it is offered in \"Add a block\", and its fields are their form.',\n 'kind-component': 'Component',\n 'kind-component-help':\n 'Called from other templates with <x-webx-block>: its fields are what the caller hands it.',\n 'kind-help': 'A block becomes a component only while it stands on no page.',\n blocks: 'Blocks',\n components: 'Components',\n 'not-called': 'not called yet',\n 'in-block': 'in one block',\n 'in-blocks': 'in :count blocks',\n module: 'module :module',\n standard: 'Standard view · module :module',\n 'standard-help':\n 'The module draws its own view here. Customising makes a draft of it to edit; the site keeps the standard view until you publish.',\n customise: 'Customise',\n customised:\n 'A draft of the standard view is ready. The site shows the old one until you publish.',\n 'customise-failed': 'The component cannot be customised.',\n 'tab-inputs': 'Input data',\n 'inputs-help':\n 'What the caller hands the component: any field, wx-data for a structure passed from code, wx-slot for a piece of markup.',\n call: 'How to call it',\n 'call-help': 'From any block template, a module view or the layout of the site.',\n copy: 'Copy',\n copied: 'Copied.',\n 'site-views':\n 'Calls from the views of the site are not seen here. Give them a fallback, or do not delete what code calls.',\n shape: 'What $:name holds',\n 'shape-free': '$:name is any JSON the caller passes.',\n callers: 'Blocks that call it',\n 'called-by': 'block \":title\"',\n 'module-views': 'views of the module :module',\n 'publish-text': 'The version takes effect in every block that calls it: :count.',\n 'publish-declared':\n 'The site switches to this version wherever the module :module prints it, and in every block that calls it: :count.',\n 'delete-called': 'Blocks call it, so it cannot be deleted: :titles.',\n 'delete-declared': 'Reset to standard',\n 'delete-declared-title': 'Reset \":title\" to the standard view?',\n 'delete-declared-text':\n 'The type and every version of it go, and the module draws its own view again.',\n 'data-invalid': 'Not valid JSON: :error',\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","<script setup lang=\"ts\">\nimport { ref, watch } from 'vue'\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { WxCodeEditor, WxText } from '@webx-ui/core'\nimport { useBlocksMessages } from './i18n'\n\n/**\n * `wx-data` in a component's sample form: a structure the caller passes from code, which nobody\n * edits in the panel except to try the component on something else. So it is JSON, as it\n * travels, in the code editor the rest of this screen is written in (§3.3).\n *\n * The text is kept as typed and the value changes only on JSON that parses: half a bracket is\n * what the text looks like on every keystroke on the way to the next valid one, and a sample\n * that became `null` in the middle of typing would redraw the stage empty each time. An empty\n * editor is the one exception: that is `null` on purpose — the call that passes nothing, which\n * a component has to survive, and which publishing checks when the sample says so.\n */\nconst props = withDefaults(\n defineProps<{\n modelValue?: unknown\n disabled?: boolean\n /** The shape's name (`recipes.card`): the help under the template describes it. */\n shape?: string\n }>(),\n { modelValue: undefined, disabled: false, shape: undefined },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: unknown] }>()\n\nuseBlocksMessages()\nconst t = useTranslate('webx-blocks')\n\nconst text = ref(format(props.modelValue))\nconst error = ref<string | null>(null)\n\nfunction format(value: unknown): string {\n return value === null || value === undefined ? '' : JSON.stringify(value, null, 2)\n}\n\n/** What the text stands for: nothing written is `null`, anything else has to parse. */\nfunction parse(source: string): unknown {\n return source.trim() === '' ? null : (JSON.parse(source) as unknown)\n}\n\nfunction onText(next: string): void {\n text.value = next\n\n try {\n const parsed = parse(next)\n\n error.value = null\n emit('update:modelValue', parsed)\n } catch (failure) {\n error.value = t('components.data-invalid', { error: (failure as Error).message })\n }\n}\n\n/* A value from outside (a restored version, a customised sample) replaces the text; the echo of\n what was just typed does not, or the caret would jump to the end on every keystroke. */\nwatch(\n () => props.modelValue,\n (value) => {\n let same = false\n\n try {\n same = JSON.stringify(parse(text.value)) === JSON.stringify(value ?? null)\n } catch {\n same = false\n }\n\n if (!same) {\n text.value = format(value)\n error.value = null\n }\n },\n { deep: true },\n)\n</script>\n\n<template>\n <div class=\"wx-block-data\">\n <wx-code-editor\n :model-value=\"text\"\n language=\"json\"\n :lint=\"text.trim() !== ''\"\n :readonly=\"disabled\"\n min-height=\"120px\"\n max-height=\"320px\"\n @update:model-value=\"onText\"\n />\n <wx-text v-if=\"error\" size=\"sm\" tone=\"danger\">{{ error }}</wx-text>\n </div>\n</template>\n\n<style scoped>\n.wx-block-data {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-4);\n min-width: 0;\n}\n</style>\n","import type { AdminContext } from '@webx-ui/module-admin'\nimport type {\n BlockInput,\n BlockList,\n BlockType,\n BlockUsage,\n BlockVersion,\n BlockVersionMeta,\n DeclaredComponent,\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 same list with the places modules declared for components beside it. */\n index(): Promise<BlockList>\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 /** A declared place made into the site's own type: an unpublished draft of the module's view. */\n customise(slug: string): Promise<BlockType>\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 /** The new order of some types — a group — in the places they held; the rest stay put. */\n reorder(ids: number[]): Promise<void>\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 // `declared` stands beside `data` rather than in it: it is not a type, and a list of types\n // with something else mixed in is a list every other reader would have to filter.\n index: () =>\n admin.http\n .get<{ data: BlockType[]; declared?: DeclaredComponent[] }>(base)\n .then((body) => ({ blocks: body.data, declared: body.declared ?? [] })),\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 customise: (slug) =>\n admin.http\n .post<{\n data: BlockType\n }>(`${base}/components/${encodeURIComponent(slug)}/customise`, {})\n .then(data),\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 reorder: (ids) => admin.http.post<unknown>(`${base}/reorder`, { ids }).then(() => undefined),\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 * A click inside a block is taken at the document, in the capture phase, and goes no further:\n * stopped there it never reaches a link, a form or the block's own script. What it does\n * instead is choose the block it landed in, which is the one thing the editor wants from it.\n *\n * A click on the site around the blocks goes on to the site, only never anywhere else (see\n * `inert`): the layout may open a newsletter popup or a cookie bar over the page, and one whose\n * close button never hears its click covers the preview for good.\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 onClick(event: MouseEvent): void {\n const key = keyAt(event.target as Node | null)\n\n if (key === null) inert(event)\n else swallow(event)\n\n handlers.select(key)\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', inert, 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', inert, 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\nfunction swallow(event: Event): void {\n event.preventDefault()\n event.stopPropagation()\n}\n\n/**\n * A click that may reach the page's own handlers but not leave it: a link loses its default\n * and nothing else changes. Not `stopPropagation` — that is what kept the close button of the\n * site's popup deaf, and the popup over the stage for good.\n */\nfunction inert(event: Event): void {\n const target = event.target as Node | null\n // By node type, not `instanceof`: the frame's document has an `Element` of its own.\n const element =\n target?.nodeType === Node.ELEMENT_NODE ? (target as Element) : (target?.parentElement ?? null)\n\n if (element?.closest('a[href], area[href]')) event.preventDefault()\n}\n\n/**\n * The same picture without the choosing: nothing in the page navigates, submits or is dragged\n * away. What the block editor's stage needs — the site's header is full of links, and one\n * click on them would leave the frame on another page of the site with the block gone.\n *\n * Clicks themselves still reach the page (see `inert`): the block's own script runs as it will\n * on the site, and the site's popups close.\n */\nexport function freezeFrame(doc: Document): FrameBinding {\n const listeners: [string, (event: Event) => void][] = [\n ['click', inert],\n ['auxclick', inert],\n ['submit', swallow],\n ['dragstart', swallow],\n ]\n\n for (const [name, listener] of listeners) doc.addEventListener(name, listener, true)\n\n return {\n release() {\n for (const [name, listener] of listeners) doc.removeEventListener(name, listener, true)\n },\n }\n}\n\n/** The key the stage draws its block under — `StageController::KEY` on the server. */\nexport const STAGE_KEY = 'sample'\n\n/** The `<style>` of the stage the block's styles go into — `StageController::STYLES`. */\nexport const STAGE_STYLES = 'wx-stage-styles'\n\n/**\n * Put a block on the stage page: its styles into the stage's `<style>`, its markup between the\n * markers. False when the page has no place for it — a layout that dropped its slot.\n *\n * The script is not here on purpose: a script registered in a page cannot be taken back, so\n * a new one means a new page (see `mountScript`).\n */\nexport function fillStage(doc: Document, input: { html: string; styles: string }): boolean {\n let style = doc.getElementById(STAGE_STYLES)\n\n if (style === null) {\n style = doc.createElement('style')\n style.id = STAGE_STYLES\n ;(doc.head ?? doc.documentElement).appendChild(style)\n }\n\n style.textContent = input.styles\n\n /* The render carries its own pair; one that does not would leave the page without a place,\n and the next change would have nowhere to go. */\n const opener = `<!--wx:${STAGE_KEY}-->`\n const html = input.html.trimStart().startsWith(opener)\n ? input.html\n : `${opener}${input.html}<!--/wx:${STAGE_KEY}-->`\n\n return replaceBlock(doc, STAGE_KEY, html)\n}\n\n/**\n * Run a block's script in the page: `webx.block()` registers it and mounts what is already\n * there. Added as an element, since that is what makes a browser run it.\n */\nexport function mountScript(doc: Document, script: string): void {\n const element = doc.createElement('script')\n element.textContent = script\n doc.body.appendChild(element)\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\n/** Where a thumbnail's block goes in a {@link siteShell}. */\nexport const SHELL_PLACE = '<!--wx-thumb-->'\n\n/**\n * The stage page with the page taken out: what a thumbnail needs of the site to look like it.\n *\n * Kept from the head: the stylesheets, the `<style>` elements and the font preloads — the\n * look. Kept from the body: only the chain of elements the block's place sits in, each one\n * empty but for the next, so a rule like `.site-main > section` still finds its parent. The\n * header, the footer, the popups and every script are left behind: a card in a list is a\n * picture, and a site's script in forty of them is forty newsletter popups.\n *\n * Null when the page has no place for a block — then there is nothing to put the block in.\n */\nexport function siteShell(html: string, url: string): string | null {\n const doc = new DOMParser().parseFromString(html, 'text/html')\n const opener = findMarker(doc, `wx:${STAGE_KEY}`)\n\n if (opener === null) return null\n\n const absolute = (value: string | null): string | null =>\n value === null ? null : new URL(value, new URL(url, location.href)).href\n\n const head: string[] = []\n\n for (const element of Array.from(doc.head.children)) {\n const tag = element.tagName.toLowerCase()\n const rel = (element.getAttribute('rel') ?? '').toLowerCase().split(/\\s+/)\n\n if (tag === 'style' && element.id !== STAGE_STYLES) {\n head.push(element.outerHTML)\n } else if (\n tag === 'link' &&\n (rel.includes('stylesheet') ||\n (rel.includes('preload') && element.getAttribute('as') === 'font'))\n ) {\n const copy = element.cloneNode(false) as Element\n copy.setAttribute('href', absolute(element.getAttribute('href')) ?? '')\n head.push(copy.outerHTML)\n }\n }\n\n let inner = SHELL_PLACE\n let parent = opener.parentElement\n\n while (parent !== null && parent !== doc.body && parent !== doc.documentElement) {\n const copy = parent.cloneNode(false) as Element\n copy.innerHTML = inner\n inner = copy.outerHTML\n parent = parent.parentElement\n }\n\n const attributes = (element: Element): string =>\n Array.from(element.attributes)\n .map((attribute) => ` ${attribute.name}=\"${escapeAttribute(attribute.value)}\"`)\n .join('')\n\n return (\n `<!doctype html><html${attributes(doc.documentElement)}><head><meta charset=\"utf-8\">` +\n `<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">${head.join('')}</head>` +\n `<body${attributes(doc.body)}>${inner}</body></html>`\n )\n}\n\n/** A thumbnail's document: the block in the site's shell, its own styles last. */\nexport function thumbDocument(shell: string, input: { html: string; styles: string }): string {\n return shell\n .replace('</head>', () => `<style>${input.styles}</style></head>`)\n .replace(SHELL_PLACE, () => input.html)\n}\n\nfunction findMarker(doc: Document, text: string): Comment | null {\n const walker = doc.createTreeWalker(doc.body ?? doc.documentElement, NodeFilter.SHOW_COMMENT)\n\n for (let node = walker.nextNode(); node !== null; node = walker.nextNode()) {\n if ((node as Comment).data.trim() === text) return node as Comment\n }\n\n return null\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, onBeforeUnmount, ref, watch } from 'vue'\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { useElementWidth, WxSegmented, WxSkeleton } from '@webx-ui/core'\nimport { fillStage, freezeFrame, mountScript, stageDocument, type FrameBinding } from './frame'\n\n/**\n * The block as it will stand on the site, at a chosen width: a desktop scaled down to fit the\n * column, a tablet or a phone at one to one.\n *\n * With `stage` the frame is a page of the site — its layout, header, footer and styles, with\n * an empty place for the block — loaded once; every change after that swaps the block and its\n * styles in place, so the site around it does not redraw under the editor's typing. Without\n * it (a server older than the stage) the frame is the block on a bare document, as before.\n */\nconst props = withDefaults(\n defineProps<{\n html: string\n styles: string\n script?: string | null\n runtime?: string | null\n /** The address of the stage page; null draws the block on a bare document. */\n stage?: string | null\n loading?: boolean\n }>(),\n { script: null, runtime: null, stage: null, loading: false },\n)\n\nconst t = useTranslate('webx-blocks')\n\n/* Pictures on screen and words as the accessible name, the same way the page preview does it:\n a device is one of the few things a picture says faster than a word. */\nconst widths = computed(() => [\n { value: 1280, icon: 'monitor', ariaLabel: t('page.width-desktop') },\n { value: 834, icon: 'tablet', ariaLabel: t('page.width-tablet') },\n { value: 390, icon: 'smartphone', ariaLabel: 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\n/**\n * Which width the stage opens at: the widest one the column can draw at half size or better.\n *\n * A desktop is the right answer on a desktop and the wrong one on a phone, where 1280 in a\n * 340px column is a picture of a page rather than a page — the words in it are two pixels\n * tall. Until the editor picks a width the stage keeps choosing, so a column that grows or a\n * phone that turns gets the picture it can show; from the first click the choice is theirs.\n */\nconst picked = ref(false)\n\nwatch([boxWidth, widths], () => {\n if (picked.value || boxWidth.value === 0) return\n\n /* Under about half size the words in a block stop being words, so a narrower device is a\n better picture of the block than a desktop nobody can read. */\n const fits = widths.value.find((option) => boxWidth.value / option.value >= 0.45)\n\n width.value = (fits ?? widths.value[widths.value.length - 1]).value\n})\n\nfunction pick(value: number): void {\n picked.value = true\n width.value = value\n}\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 props.stage\n ? undefined\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/**\n * A new page for every new script, and only then: a script registered in a page cannot be\n * unregistered, so the old one would keep running beside the new one. Everything else is\n * swapped into the page that is already there.\n */\nconst generation = ref(0)\nlet loadedScript: string | null = null\n\nwatch(\n () => props.script,\n (script) => {\n if (props.stage && script !== loadedScript) generation.value += 1\n },\n)\n\n/**\n * The frame is as tall as the page in it: a stage that scrolls inside itself hides half of it.\n *\n * Measured on the body, never on `documentElement` — that one is never shorter than the\n * frame's own window, so once the frame has been given a height it measures itself and a\n * block that got shorter keeps the height of the one before it, with white under it.\n */\nfunction measure(): void {\n const body = frame.value?.contentDocument?.body\n\n if (!body) return\n\n /* Where the body ends, margin included, and rounded up: a site's layout is fractional and\n may keep a margin on `body`, and a height a pixel short of either gives the frame a\n scrollbar of its own. */\n const view = body.ownerDocument.defaultView\n const margin = view ? parseFloat(view.getComputedStyle(body).marginBottom) || 0 : 0\n const bottom = body.getBoundingClientRect().bottom + margin + (view?.scrollY ?? 0)\n\n contentHeight.value = Math.max(120, Math.ceil(Math.max(body.scrollHeight, bottom)))\n}\n\nlet binding: FrameBinding | null = null\nlet observer: ResizeObserver | null = null\n\nfunction release(): void {\n binding?.release()\n binding = null\n observer?.disconnect()\n observer = null\n}\n\n/** Put the current block on the page — its script once per page, the rest every time. */\nfunction fill(doc: Document): void {\n if (!props.stage) return\n\n if (props.script && loadedScript !== props.script) {\n loadedScript = props.script\n mountScript(doc, props.script)\n }\n\n fillStage(doc, { html: props.html, styles: props.styles })\n}\n\nfunction onLoad(): void {\n release()\n\n const doc = frame.value?.contentDocument\n\n if (!doc?.body) return\n\n if (props.stage) {\n loadedScript = null\n binding = freezeFrame(doc)\n fill(doc)\n }\n\n measure()\n\n /* The observer of the frame's own window: one made out here does not see into another\n document. It follows fonts, images and a block that grows as its script runs. */\n const Observer = (doc.defaultView as (Window & typeof globalThis) | null)?.ResizeObserver\n\n if (Observer) {\n observer = new Observer(() => measure())\n observer.observe(doc.body)\n }\n}\n\nwatch(\n () => [props.html, props.styles] as const,\n () => {\n const doc = frame.value?.contentDocument\n\n if (props.stage && doc?.body && binding !== null) fill(doc)\n },\n)\n\n/* A stage that lives in a tab is measured while that tab is hidden, and a hidden document\n has no height: every redraw made behind another tab would leave the frame at its floor.\n The width coming back is the tab coming back. */\nwatch(boxWidth, (now, before) => {\n if (now > 0 && before === 0) setTimeout(measure, 50)\n})\n\nwatch(width, () => setTimeout(measure, 50))\n\nonBeforeUnmount(release)\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\n :model-value=\"width\"\n :options=\"widths\"\n size=\"sm\"\n :aria-label=\"t('page.width')\"\n @update:model-value=\"pick(Number($event))\"\n />\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 :key=\"generation\"\n class=\"wx-block-stage__frame\"\n :src=\"stage ?? undefined\"\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/*\n * As tall as the page inside, and the panel scrolls — the rule the page preview has (`is-grown`\n * in BlocksPreview). A window of ours over a page is two scrollbars for one document, and the\n * inner one cut the site's footer off under a cap nobody could see past.\n */\n.wx-block-stage__ground {\n padding: var(--wx-space-12);\n background: var(--wx-bg-subtle);\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 {\n autocompletion,\n pickedCompletion,\n snippetCompletion,\n startCompletion,\n type Completion,\n type CompletionContext,\n type CompletionResult,\n type CompletionSource,\n} from '@codemirror/autocomplete'\nimport { EditorState, type Extension } from '@codemirror/state'\nimport type { EditorView } from '@codemirror/view'\nimport type { ScreenNode, TypeRegistry } from '@webx-ui/schema'\n\n/**\n * What the editor of a block type offers as you type, one source per file. Each reads the\n * other files of the same type — the template's fields come from the schema, its classes from\n * the styles, the styles' classes from the template — so the sources take getters, not\n * values: the editor is built once and the files change under it.\n *\n * Registered as language data rather than as an `override`, so that what the language\n * already offers (CSS properties, HTML tags) stays in the list beside ours.\n */\nexport function completions(source: CompletionSource): Extension {\n return [\n autocompletion({ icons: false }),\n EditorState.languageData.of(() => [{ autocomplete: source }]),\n ]\n}\n\n/* ---------------------------------------------------------------------------------------- */\n/* Template */\n/* ---------------------------------------------------------------------------------------- */\n\nexport interface TemplateSources {\n schema: () => ScreenNode[]\n styles: () => string\n /** The types a tag can call, components among them: what `type=\"` offers. */\n types?: () => TagTarget[]\n /**\n * The schema of a type, for the attributes and slots of a tag that calls it. May answer later:\n * the list of types comes without content, and the one schema is asked for when it is needed.\n */\n schemaOf?: (slug: string) => ScreenNode[] | null | Promise<ScreenNode[] | null>\n}\n\n/** A type as a tag names it. */\nexport interface TagTarget {\n slug: string\n title: string\n kind: 'block' | 'component'\n /** The module's view, for a declared place: the tag that calls it should carry it. */\n fallback?: string | null\n}\n\n/** What the renderer hands a template besides its fields (see `lint.ts`, `GIVEN`). */\nconst GIVEN: [string, string][] = [\n ['block', 'key, type, version, depth, value()'],\n ['entity', 'the page or article the block stands on'],\n]\n\nconst BLOCK_MEMBERS = ['key', 'type', 'version', 'depth']\n\n/** The keys of a picked file: `wx-media` holds them, the renderer adds `url`. */\nconst MEDIA_KEYS = ['url', 'alt', 'title', 'path']\n\n/** One item of `wx-gallery` or `wx-files`: a file plus what a list of them is printed with. */\nconst ITEM_KEYS = [...MEDIA_KEYS, 'thumb', 'name', 'extension', 'mime', 'size', 'width', 'height']\n\nconst MEDIA_TYPES = ['wx-media']\nconst LIST_TYPES = ['wx-gallery', 'wx-files']\n\n/**\n * `wx-collection`, as the renderer hands it over: the records and the filter's groups. What else\n * a record holds is its source's business (`question`, `answer` for the FAQ); every source gives\n * these three.\n */\nconst COLLECTION_KEYS = ['items', 'groups', 'filter']\nconst COLLECTION_PARTS: Record<string, string[]> = {\n items: ['id', 'anchor', 'categories'],\n groups: ['id', 'title', 'items'],\n}\n\n/**\n * What a record of the sources the modules of this repository bring holds beyond the three every\n * source gives — the card each one's `Cards` builds. A source a site registers itself offers the\n * three only.\n */\nconst SOURCE_ITEMS: Record<string, string[]> = {\n faq: ['question', 'answer'],\n services: ['title', 'url', 'lead', 'cover', 'fields'],\n reviews: [\n 'name',\n 'initials',\n 'job_title',\n 'text',\n 'rating',\n 'date',\n 'profile',\n 'photo',\n 'fields',\n ],\n recipes: [\n 'title',\n 'url',\n 'lead',\n 'cover',\n 'gallery',\n 'minutes',\n 'servings',\n 'category_links',\n 'service_links',\n 'nutrients',\n 'fields',\n ],\n team: ['name', 'initials', 'job_title', 'text', 'photo', 'socials', 'service_links', 'fields'],\n}\n\nexport function templateCompletions({\n schema,\n styles,\n types = () => [],\n schemaOf = () => null,\n}: TemplateSources): CompletionSource {\n return (context) => {\n const before = context.state.sliceDoc(Math.max(0, context.pos - 200), context.pos)\n\n // The value of `type` first: inside its quotes nothing else applies.\n const called = /<x-webx-block\\b[^<>]*?\\btype\\s*=\\s*([\"'])([\\w-]*)$/.exec(before)\n if (called) return tagTypes(context, called[1]!, called[2]!, types())\n\n const member = /\\$block->(\\w*)$/.exec(before)\n if (member) return blockMembers(context, member[1]!)\n\n const key = /\\$(\\w+)\\[\\s*(['\"]?)(\\w*)$/.exec(before)\n if (key) return arrayKeys(context, key[1]!, key[2]!, key[3]!, schema())\n\n const variable = /\\$(\\w*)$/.exec(before)\n if (variable) {\n return {\n from: context.pos - variable[0].length,\n options: variables(schema(), context.state.doc.toString()),\n validFor: /^\\$\\w*$/,\n }\n }\n\n // Straight after `{{` there is nothing else a template writes, so the fields open there\n // without waiting for the `$` (the one exception, a call like `{{ now() }}`, just types on).\n const echo = /(\\{\\{|\\{!!)(\\s*)(\\w*)$/.exec(before)\n if (echo) return echoed(context, echo[1]!, echo[2]!, echo[3]!, schema())\n\n const tag = openTag(before)\n if (tag !== null) return tagAttributes(context, tag, types(), schemaOf)\n\n const element = /<(x-[\\w:-]*)$/.exec(before)\n if (element) {\n const text = context.state.sliceDoc(0, context.pos - element[0].length)\n\n return tagElements(context, element[1]!, enclosingType(text), schemaOf)\n }\n\n const attribute = /\\bclass\\s*=\\s*\"([^\"]*)$/.exec(before)\n if (attribute) return classNames(context, attribute[1]!, styles())\n\n const directive = /(?:^|[\\s>(])@(\\w*)$/.exec(before)\n if (directive) {\n return {\n from: context.pos - directive[1]!.length - 1,\n options: directives(schema()),\n validFor: /^@\\w*$/,\n }\n }\n\n return null\n }\n}\n\n/* ---------------------------------------------------------------------------------------- */\n/* <x-webx-block> */\n/* ---------------------------------------------------------------------------------------- */\n\n/**\n * `type=\"` of the tag: every type there is, the components first — calling one is what the tag\n * is for, calling a block (a CTA with its values written in) is the rarer case (§2, decision 2).\n */\nfunction tagTypes(\n context: CompletionContext,\n quote: string,\n word: string,\n targets: TagTarget[],\n): CompletionResult | null {\n if (targets.length === 0) return null\n\n return {\n from: context.pos - word.length,\n options: targets.map((target, index) => ({\n label: target.slug,\n detail: target.kind,\n info: target.title,\n type: 'type',\n boost: (target.kind === 'component' ? 50 : 0) - index / 100,\n apply: (view, completion, from, to) => {\n const rest = /^[\\w-]*/.exec(view.state.sliceDoc(to, to + 64))![0]\n const end = to + rest.length\n const closed = view.state.sliceDoc(end, end + 1) === quote\n const insert = `${target.slug}${closed ? '' : quote}`\n\n view.dispatch({\n changes: { from, to: end, insert },\n // Past the closing quote: the attributes come next.\n selection: { anchor: from + insert.length + (closed ? 1 : 0) },\n annotations: pickedCompletion.of(completion),\n userEvent: 'input.complete',\n })\n },\n })),\n validFor: /^[\\w-]*$/,\n }\n}\n\ninterface OpenTag {\n /** The attributes written so far. */\n attributes: string\n /** The type, once it is written among them. */\n type: string | null\n /** `:` typed before the name. */\n bound: boolean\n word: string\n}\n\n/** The caret stands between the attributes of an `<x-webx-block` that is still open. */\nexport function openTag(before: string): OpenTag | null {\n const start = before.lastIndexOf('<x-webx-block')\n if (start === -1) return null\n\n const inside = before.slice(start + '<x-webx-block'.length)\n if (inside.includes('>') || !/^\\s/.test(inside)) return null\n\n // An odd number of quotes: the caret is inside a value, and names do not go there.\n const odd = (quote: string): boolean => (inside.split(quote).length - 1) % 2 === 1\n if (odd('\"') || odd(\"'\")) return null\n\n const name = /\\s(:?)([\\w-]*)$/.exec(inside)\n if (!name) return null\n\n const type = /\\btype\\s*=\\s*[\"']([\\w-]+)[\"']/.exec(inside)\n\n return { attributes: inside, type: type?.[1] ?? null, bound: name[1] === ':', word: name[2]! }\n}\n\n/** Attribute names: the type's inputs by its schema, `:` for a structure, then the reserved two. */\nfunction tagAttributes(\n context: CompletionContext,\n tag: OpenTag,\n targets: TagTarget[],\n schemaOf: NonNullable<TemplateSources['schemaOf']>,\n): CompletionResult | null | Promise<CompletionResult | null> {\n const present = new Set([...tag.attributes.matchAll(/:?([\\w-]+)\\s*=/g)].map((match) => match[1]!))\n const from = context.pos - tag.word.length - (tag.bound ? 1 : 0)\n\n const reserved = (): Completion[] => {\n const options: Completion[] = []\n\n if (!present.has('type')) options.push(attribute('type', false, 'reserved', null, 60))\n\n if (!present.has('fallback') && tag.type !== null) {\n const declared = targets.find((target) => target.slug === tag.type)?.fallback ?? null\n\n options.push(attribute('fallback', false, 'reserved', declared, -10, declared))\n }\n\n return options\n }\n\n const answer = (nodes: ScreenNode[] | null): CompletionResult | null => {\n const inputs = fields(nodes ?? [])\n .filter((node) => node.type !== 'wx-slot' && node.type !== 'wx-blocks')\n .filter((node) => !present.has(node.id))\n .map((node, index) =>\n attribute(node.id, node.type === 'wx-data' || tag.bound, node.type, node.label, 40 - index),\n )\n const options = [...inputs, ...reserved()]\n\n // A space after the tag's name is not yet a request: the list opens on a letter or a colon.\n if (options.length === 0 || (!context.explicit && tag.word === '' && !tag.bound)) return null\n\n return { from, options, validFor: /^:?[\\w-]*$/ }\n }\n\n if (tag.type === null) return answer(null)\n\n const nodes = schemaOf(tag.type)\n\n return nodes instanceof Promise ? nodes.then(answer, () => answer(null)) : answer(nodes)\n}\n\n/** `name=\"\"` or `:name=\"$\"`, with the caret before the closing quote. */\nfunction attribute(\n name: string,\n bound: boolean,\n detail: string,\n info: string | null | undefined,\n boost: number,\n value: string | null = null,\n): Completion {\n const label = `${bound ? ':' : ''}${name}`\n\n return {\n label,\n detail,\n info: info ?? undefined,\n type: 'property',\n boost,\n apply: (view, completion, from, to) => {\n const insert = `${label}=\"${value ?? (bound ? '$' : '')}\"`\n\n view.dispatch({\n changes: { from, to, insert },\n selection: { anchor: from + insert.length - 1 },\n annotations: pickedCompletion.of(completion),\n userEvent: 'input.complete',\n })\n },\n }\n}\n\n/**\n * After `<x-`: the tag itself, and inside a tag's body the named slots its type declares, each\n * written open and closed with the caret between.\n */\nfunction tagElements(\n context: CompletionContext,\n word: string,\n type: string | null,\n schemaOf: NonNullable<TemplateSources['schemaOf']>,\n): CompletionResult | Promise<CompletionResult> {\n const from = context.pos - word.length\n\n const answer = (nodes: ScreenNode[] | null): CompletionResult => {\n const options: Completion[] = [\n snippetCompletion('x-webx-block type=\"${type}\" />', {\n label: 'x-webx-block',\n detail: 'call a block',\n type: 'keyword',\n }),\n ]\n\n for (const node of fields(nodes ?? []).filter((field) => field.type === 'wx-slot')) {\n options.push({\n label: `x-slot:${node.id}`,\n detail: 'slot',\n info: node.label,\n type: 'keyword',\n boost: 20,\n apply: (view, completion, start, end) => {\n const open = `x-slot:${node.id}>`\n\n view.dispatch({\n changes: { from: start, to: end, insert: `${open}</x-slot:${node.id}>` },\n selection: { anchor: start + open.length },\n annotations: pickedCompletion.of(completion),\n userEvent: 'input.complete',\n })\n },\n })\n }\n\n return { from, options, validFor: /^x-[\\w:-]*$/ }\n }\n\n if (type === null) return answer(null)\n\n const nodes = schemaOf(type)\n\n return nodes instanceof Promise ? nodes.then(answer, () => answer(null)) : answer(nodes)\n}\n\n/** The type of the `<x-webx-block>` whose body the end of the text stands in, if any. */\nexport function enclosingType(text: string): string | null {\n const stack: (string | null)[] = []\n\n for (const match of text.matchAll(\n /<x-webx-block\\b((?:[^>\"']|\"[^\"]*\"|'[^']*')*?)(\\/?)>|<\\/x-webx-block\\s*>/g,\n )) {\n if (match[0].startsWith('</')) stack.pop()\n else if (match[2] !== '/') {\n stack.push(/\\btype\\s*=\\s*[\"']([\\w-]+)[\"']/.exec(match[1] ?? '')?.[1] ?? null)\n }\n }\n\n return stack.at(-1) ?? null\n}\n\n/** Every field a template may print: the schema's, in its order, then what is always there. */\nfunction variables(schema: ScreenNode[], template: string): Completion[] {\n const options: Completion[] = printable(schema).map((node, index) => ({\n label: `$${node.id}`,\n detail: node.type,\n info: node.label,\n type: 'variable',\n boost: 50 - index,\n }))\n\n for (const name of loopVariables(template).keys()) {\n options.push({ label: `$${name}`, detail: 'loop', type: 'variable' })\n }\n\n for (const [name, info] of GIVEN) {\n options.push({ label: `$${name}`, detail: 'given', info, type: 'variable', boost: -10 })\n }\n\n // Any type can be called with the tag, and the tag's body arrives as this, empty when there\n // was none: the one given a component is written around.\n options.push({ label: '$slot', detail: 'given', info: 'what the calling tag held', boost: -15 })\n\n options.push({ label: '$loop', detail: 'given', info: 'inside @foreach', boost: -20 })\n\n return options\n}\n\nfunction echoed(\n context: CompletionContext,\n opener: string,\n space: string,\n word: string,\n schema: ScreenNode[],\n): CompletionResult | null {\n const options = printable(schema)\n if (options.length === 0) return null\n\n const closer = opener === '{{' ? '}}' : '!!}'\n\n return {\n from: context.pos - word.length,\n options: options.map((node, index) => ({\n label: node.id,\n displayLabel: `$${node.id}`,\n detail: node.type,\n info: node.label,\n type: 'variable',\n boost: 50 - index,\n apply: (view, completion, from, to) => {\n const rest = view.state.sliceDoc(to, to + 8)\n const closed = new RegExp(`^\\\\s*${escape(closer)}`).exec(rest)\n // `closeBrackets` has usually typed the `}}` already; when it has not, write it.\n const tail = closed ? (/^\\s/.test(rest) ? '' : ' ') : ` ${closer}`\n const insert = `${space === '' ? ' ' : ''}$${node.id}${tail}`\n\n view.dispatch({\n changes: { from, to, insert },\n // Past the closing braces: the echo is finished, the next thing is the markup.\n selection: { anchor: from + insert.length + (closed ? closed[0].length : 0) },\n annotations: pickedCompletion.of(completion),\n userEvent: 'input.complete',\n })\n },\n })),\n validFor: /^\\w*$/,\n }\n}\n\nfunction blockMembers(context: CompletionContext, word: string): CompletionResult {\n return {\n from: context.pos - word.length,\n options: [\n ...BLOCK_MEMBERS.map((label) => ({ label, type: 'property' })),\n snippetCompletion(\"value('${name}', ${default})\", {\n label: 'value',\n detail: \"('name', default)\",\n type: 'method',\n }),\n ],\n validFor: /^\\w*$/,\n }\n}\n\n/** `$image['…']`, `$item['…']`: what a value of that field holds, when the schema says. */\nfunction arrayKeys(\n context: CompletionContext,\n variable: string,\n quote: string,\n word: string,\n schema: ScreenNode[],\n): CompletionResult | null {\n const keys = keysOf(variable, schema, context.state.doc.toString())\n if (keys.length === 0) return null\n\n return {\n from: context.pos - word.length,\n options: keys.map(([label, detail]) => ({\n label,\n detail,\n type: 'property',\n apply: (view, completion, from, to) => {\n const start = quote ? from - 1 : from\n const rest = view.state.sliceDoc(to, to + 2)\n const q = quote || \"'\"\n const end = to + (rest.startsWith(q) ? 1 : 0)\n const closed = view.state.sliceDoc(end, end + 1) === ']'\n const insert = `${q}${label}${q}${closed ? '' : ']'}`\n\n view.dispatch({\n changes: { from: start, to: end, insert },\n selection: { anchor: start + insert.length + (closed ? 1 : 0) },\n annotations: pickedCompletion.of(completion),\n userEvent: 'input.complete',\n })\n },\n })),\n validFor: /^\\w*$/,\n }\n}\n\nfunction keysOf(variable: string, schema: ScreenNode[], template: string): [string, string][] {\n const field = fields(schema).find((node) => node.id === variable)\n if (field && MEDIA_TYPES.includes(field.type)) return MEDIA_KEYS.map((key) => [key, field.type])\n if (field?.type === 'wx-collection') return COLLECTION_KEYS.map((key) => [key, field.type])\n\n const list = loopVariables(template).get(variable)\n const [name, part] = list?.split('.') ?? []\n const source = name ? fields(schema).find((node) => node.id === name) : undefined\n if (!source) return []\n\n if (source.type === 'wx-collection') {\n const origin = typeof source.props?.source === 'string' ? source.props.source : source.type\n const own = part === 'items' ? (SOURCE_ITEMS[origin] ?? []) : []\n return [...(COLLECTION_PARTS[part ?? ''] ?? []), ...own].map((key) => [key, origin])\n }\n\n if (LIST_TYPES.includes(source.type)) return ITEM_KEYS.map((key) => [key, source.type])\n\n if (source.type === 'wx-repeater') {\n return fields(source.children ?? []).map((node) => [node.id, node.type])\n }\n\n return []\n}\n\n/**\n * `@foreach ($items as $item)` → item ⇒ items, and the key variable ⇒ nothing;\n * `@foreach ($questions['items'] as $q)` → q ⇒ questions.items.\n */\nfunction loopVariables(template: string): Map<string, string> {\n const found = new Map<string, string>()\n\n for (const match of template.matchAll(\n /\\$(\\w+)(?:\\[\\s*['\"](\\w+)['\"]\\s*\\])?\\s+as\\s+\\$(\\w+)(?:\\s*=>\\s*\\$(\\w+))?/g,\n )) {\n found.set(match[4] ?? match[3]!, match[2] ? `${match[1]}.${match[2]}` : match[1]!)\n }\n\n return found\n}\n\nfunction classNames(context: CompletionContext, value: string, styles: string): CompletionResult {\n const word = /[\\w-]*$/.exec(value)![0]\n const present = new Set(value.split(/\\s+/))\n\n return {\n from: context.pos - word.length,\n options: styleClasses(styles)\n .filter((name) => !present.has(name) || name === word)\n .map((label) => ({ label, detail: 'styles', type: 'class' })),\n validFor: /^[\\w-]*$/,\n }\n}\n\nfunction directives(schema: ScreenNode[]): Completion[] {\n const blocks = fields(schema).filter((node) => node.type === 'wx-blocks')\n\n return [\n snippetCompletion('@if (${condition})\\n\\t${}\\n@endif', { label: '@if', type: 'keyword' }),\n snippetCompletion('@isset(${value})\\n\\t${}\\n@endisset', { label: '@isset', type: 'keyword' }),\n snippetCompletion('@foreach (${items} as ${item})\\n\\t${}\\n@endforeach', {\n label: '@foreach',\n type: 'keyword',\n }),\n snippetCompletion('@forelse (${items} as ${item})\\n\\t${}\\n@empty\\n\\t${}\\n@endforelse', {\n label: '@forelse',\n type: 'keyword',\n }),\n snippetCompletion('@unless (${condition})\\n\\t${}\\n@endunless', {\n label: '@unless',\n type: 'keyword',\n }),\n snippetCompletion('@class([${}])', { label: '@class', type: 'keyword' }),\n snippetCompletion('@style([${}])', { label: '@style', type: 'keyword' }),\n ...blocks.map((node) =>\n snippetCompletion(`@blocks('${node.id}')`, {\n label: '@blocks',\n detail: `('${node.id}')`,\n type: 'keyword',\n boost: 10,\n }),\n ),\n ...['@elseif', '@else', '@endif', '@endforeach', '@endisset', '@empty', '@endforelse'].map(\n (label) => ({ label, type: 'keyword', boost: -10 }),\n ),\n ]\n}\n\n/* ---------------------------------------------------------------------------------------- */\n/* Styles */\n/* ---------------------------------------------------------------------------------------- */\n\nexport interface StylesSources {\n slug: () => string\n template: () => string\n}\n\nexport function stylesCompletions({ slug, template }: StylesSources): CompletionSource {\n return (context) => {\n const before = context.state.sliceDoc(Math.max(0, context.pos - 200), context.pos)\n const match = /(?:^|[\\s,>+~(}{])\\.([\\w-]*)$/.exec(before)\n if (!match) return null\n\n // A dot in a value (`padding: .5rem`) is not a selector: the text since the last rule\n // boundary reads as `property: …`.\n const statement = /[^{};]*$/.exec(before)![0]\n if (/^\\s*[\\w-]+\\s*:\\s/.test(statement)) return null\n\n const root = `b-${slug()}`\n const styled = new Set(styleClasses(context.state.doc.toString()))\n const used = templateClasses(template())\n const names = [root, ...used.filter((name) => name !== root)]\n\n const options: Completion[] = names.map((name, index) => ({\n label: `.${name}`,\n // A class the template uses and nothing styles yet is the likeliest thing to write.\n detail: styled.has(name) ? 'template' : 'template · no rule yet',\n type: 'class',\n boost: (styled.has(name) ? 0 : 20) + (name === root ? 30 : 0) - index / 100,\n }))\n\n for (const name of styled) {\n if (!names.includes(name))\n options.push({ label: `.${name}`, detail: 'styles', type: 'class' })\n }\n\n return { from: context.pos - match[1]!.length - 1, options, validFor: /^\\.[\\w-]*$/ }\n }\n}\n\n/** Classes a stylesheet declares, nested `&__part` resolved against its parent. */\nexport function styleClasses(styles: string): string[] {\n const source = styles.replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n const found = new Set<string>()\n const stack: string[][] = []\n let prelude = ''\n\n for (const char of source) {\n if (char === '{') {\n const parents = stack.at(-1) ?? ['']\n const selectors = prelude\n .split(',')\n .map((part) => part.trim())\n .filter((part) => part !== '' && !part.startsWith('@'))\n .flatMap((part) =>\n part.includes('&')\n ? parents.map((parent) => part.replaceAll('&', parent))\n : parents.map((parent) => (parent ? `${parent} ${part}` : part)),\n )\n\n for (const selector of selectors) {\n for (const match of selector.matchAll(/\\.(-?[a-zA-Z_][\\w-]*)/g)) found.add(match[1]!)\n }\n\n stack.push(prelude.trim().startsWith('@') ? parents : selectors.length ? selectors : parents)\n prelude = ''\n } else if (char === '}') {\n stack.pop()\n prelude = ''\n } else if (char === ';') {\n prelude = ''\n } else {\n prelude += char\n }\n }\n\n return [...found]\n}\n\n/** Classes the template writes literally; anything Blade computes is left out. */\nexport function templateClasses(template: string): string[] {\n const found = new Set<string>()\n\n for (const match of template.matchAll(/\\bclass\\s*=\\s*\"([^\"]*)\"/g)) {\n const value = match[1]!.replace(/\\{\\{[\\s\\S]*?\\}\\}|\\{!![\\s\\S]*?!!\\}|@\\w+(\\([^)]*\\))?/g, ' ')\n\n for (const name of value.split(/\\s+/)) {\n if (/^-?[a-zA-Z_][\\w-]*$/.test(name)) found.add(name)\n }\n }\n\n return [...found]\n}\n\n/* ---------------------------------------------------------------------------------------- */\n/* Fields */\n/* ---------------------------------------------------------------------------------------- */\n\nexport interface SchemaSources {\n types: () => TypeRegistry\n}\n\n/** The keys of a node (`ScreenNode`), each with what goes after the colon. */\nconst NODE_KEYS: { key: string; value: string; info: string }[] = [\n { key: 'id', value: '\"\"', info: 'The variable the template gets, in snake_case.' },\n { key: 'type', value: '\"\"', info: 'A type from the registry.' },\n { key: 'label', value: '\"\"', info: 'What the editor sees above the field.' },\n { key: 'help', value: '\"\"', info: 'A hint under the field.' },\n { key: 'localized', value: 'true', info: 'Edited per content language.' },\n { key: 'props', value: '{}', info: 'Passed to the component as they are.' },\n { key: 'children', value: '[]', info: 'Nodes inside a layout node or a repeater.' },\n { key: 'visible', value: '', info: '`false`, or a condition on another field.' },\n { key: 'slot', value: '\"\"', info: \"The parent's named slot to land in.\" },\n { key: 'can', value: '\"\"', info: 'The permission the node needs.' },\n]\n\nexport function schemaCompletions({ types }: SchemaSources): CompletionSource {\n return (context) => {\n const at = jsonContext(context.state.doc.toString(), context.pos)\n if (!at || !at.node) return null\n\n const word = at.string\n ? context.state.sliceDoc(at.string, context.pos)\n : /[\\w-]*$/.exec(context.state.sliceDoc(Math.max(0, context.pos - 60), context.pos))![0]\n\n if (!at.string && word === '' && !context.explicit) return null\n\n const from = context.pos - word.length\n const quoted = at.string !== null\n\n if (at.phase === 'key') {\n const options = NODE_KEYS.filter(({ key }) => !at.keys.has(key) || key === word).map(\n ({ key, value, info }, index): Completion => ({\n label: key,\n info,\n type: 'property',\n boost: -index,\n apply: (view, completion, start, end) =>\n applyJson(view, completion, start, end, quoted, `\"${key}\": ${value}`, value),\n }),\n )\n\n return { from, options, validFor: /^[\\w-]*$/ }\n }\n\n if (at.phase === 'value' && at.key === 'type') {\n const options = Object.entries(types()).map(([type, entry]): Completion => ({\n label: type,\n detail: entry.kind,\n type: 'type',\n // Fields first: a block's schema is mostly fields, the layout only groups them.\n boost: entry.kind === 'field' ? 1 : 0,\n apply: (view, completion, start, end) =>\n applyJson(view, completion, start, end, quoted, `\"${type}\"`, ''),\n }))\n\n return { from, options, validFor: /^[\\w-]*$/ }\n }\n\n return null\n }\n}\n\n/**\n * Replaces the word being typed — with its quotes, whichever of them are there — and puts\n * the caret inside the value that follows: between `\"\"`, `{}`, `[]`, or after the colon.\n * A `type` opens the list of types straight away, since that is the next thing to pick.\n */\nfunction applyJson(\n view: EditorView,\n completion: Completion,\n from: number,\n to: number,\n quoted: boolean,\n insert: string,\n value: string,\n): void {\n const start = quoted ? from - 1 : from\n const rest = /^[\\w-]*\"?/.exec(view.state.sliceDoc(to, to + 60))![0]\n const end = to + (quoted ? rest.length : /^[\\w-]*/.exec(rest)![0].length)\n const inside = value === '\"\"' || value === '{}' || value === '[]' ? 1 : 0\n\n view.dispatch({\n changes: { from: start, to: end, insert },\n selection: { anchor: start + insert.length - inside },\n annotations: pickedCompletion.of(completion),\n userEvent: 'input.complete',\n })\n\n if (insert.startsWith('\"type\"')) startCompletion(view)\n}\n\ninterface Frame {\n kind: 'object' | 'array'\n parent: Frame | null\n /** For an array: the key it is the value of. */\n under: string | null\n keys: Set<string>\n phase: 'key' | 'colon' | 'value' | 'after'\n key: string | null\n}\n\nexport interface JsonContext {\n /** The caret stands in an object that is a screen node. */\n node: boolean\n phase: Frame['phase']\n /** The key whose value is being written. */\n key: string | null\n /** Every key the object has, before the caret and after it. */\n keys: Set<string>\n /** Where the string under the caret starts, after its opening quote. */\n string: number | null\n}\n\n/**\n * Where the caret stands in a schema, by one pass over the text — it has to work on a\n * document that is broken right there, which is always the case while typing, and a parser\n * gives up on exactly that.\n */\nexport function jsonContext(doc: string, pos: number): JsonContext | null {\n let top = null as Frame | null\n let snapshot: JsonContext | null = null\n let string: { start: number; key: boolean } | null = null\n let escaped = false\n\n const isNode = (frame: Frame | null): boolean =>\n frame?.kind === 'object' &&\n frame.parent?.kind === 'array' &&\n (frame.parent.parent === null || frame.parent.under === 'children')\n\n for (let i = 0; i <= doc.length; i++) {\n if (i === pos) {\n snapshot =\n top?.kind === 'object'\n ? {\n node: isNode(top),\n phase: string?.key ? 'key' : top.phase,\n key: top.key,\n keys: top.keys,\n string: string ? string.start + 1 : null,\n }\n : null\n }\n\n if (i === doc.length) break\n const char = doc[i]!\n\n if (string) {\n if (escaped) escaped = false\n else if (char === '\\\\') escaped = true\n else if (char === '\"' || char === '\\n') {\n const text = doc.slice(string.start + 1, i)\n\n if (top?.kind === 'object') {\n if (string.key) {\n top.keys.add(text)\n top.key = text\n top.phase = 'colon'\n } else if (top.phase === 'value') {\n top.phase = 'after'\n }\n }\n\n string = null\n }\n continue\n }\n\n if (/\\s/.test(char)) continue\n\n if (char === '\"') {\n string = { start: i, key: top?.kind === 'object' && top.phase === 'key' }\n } else if (char === '{' || char === '[') {\n const frame: Frame = {\n kind: char === '{' ? 'object' : 'array',\n parent: top,\n under: top?.kind === 'object' ? top.key : null,\n keys: new Set(),\n phase: 'key',\n key: null,\n }\n if (top?.kind === 'object') top.phase = 'after'\n top = frame\n } else if (char === '}' || char === ']') {\n top = top?.parent ?? null\n } else if (char === ':') {\n if (top?.kind === 'object') top.phase = 'value'\n } else if (char === ',') {\n if (top?.kind === 'object') {\n top.phase = 'key'\n top.key = null\n }\n }\n // A bare word after a colon keeps the phase: `\"type\": wx` is a type being typed without\n // its quotes, and `true` or `12` has nothing to complete either way.\n }\n\n return snapshot\n}\n\n/* ---------------------------------------------------------------------------------------- */\n\n/** Fields of a schema through its layout, the way the template sees them: flat. */\nfunction fields(schema: ScreenNode[]): ScreenNode[] {\n const found: ScreenNode[] = []\n\n for (const node of schema) {\n if (!node || typeof node !== 'object') continue\n if (LAYOUT.has(node.type)) found.push(...fields(node.children ?? []))\n else if (typeof node.id === 'string' && node.id !== '') found.push(node)\n }\n\n return found\n}\n\n/** A `wx-blocks` value is printed with `@blocks('id')`, never echoed. */\nfunction printable(schema: ScreenNode[]): ScreenNode[] {\n return fields(schema).filter((node) => node.type !== 'wx-blocks')\n}\n\nconst LAYOUT = new Set(['wx-card', 'wx-tabs', 'wx-tab', 'wx-row', 'wx-col', 'wx-divider'])\n\nfunction escape(text: string): string {\n return text.replace(/[.*+?^${}()|[\\]\\\\!]/g, '\\\\$&')\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/**\n * Variables Blade or the renderer hand a template on their own. `$slot` among them: any type can\n * be called with `<x-webx-block>`, and the default slot is there whether or not the tag had a\n * body — empty when it did not (§3.3 of the components spec).\n */\nconst GIVEN = ['block', 'entity', 'loop', 'slot', '__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 { inject, provide, type InjectionKey, type Ref } from 'vue'\nimport type { BlockType } from './types'\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\n/**\n * Set by the block editor around its sample form: the block whose own field that constructor\n * is. Without it the sample's top level reads as a page, so the picker offered every type the\n * page may hold rather than what this block lets inside — and hid a type that may stand only\n * in this block. A ref, because the editor's settings are the draft, not the published type.\n */\nexport const blocksOwnerKey: InjectionKey<Ref<BlockType | null>> = Symbol('wx-blocks-owner')\n","import type { ScreenNode } from '@webx-ui/schema'\nimport type { BlockKind } from './types'\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 * How many entities a type stands on, in words.\n *\n * Three lines rather than one with a number in it: `on :count pages` reads as \"on 1 pages\"\n * exactly when a type has just been put somewhere for the first time, which is the moment an\n * editor is most likely to be looking at it. The panel has no plural forms and does not need\n * them — one is one, and the rest is a number.\n */\nexport function usageWords(\n count: number,\n t: (key: string, params?: Record<string, string | number>) => string,\n): string {\n if (count === 0) return t('page.not-used')\n\n return count === 1 ? t('page.on-page') : t('page.on-pages', { count })\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\n/** What a type is; a server older than components sends no `kind`, and everything was a block. */\nexport function kindOf(type: { kind?: BlockKind }): BlockKind {\n return type.kind ?? 'block'\n}\n\n/**\n * How many types call a component, in words — the component's \"on 3 pages\". Counted in types\n * rather than pages on purpose (§3.10): the pages behind every parent are expensive to count and\n * say little, while the parents are what a change to the component can break.\n */\nexport function callerWords(\n count: number,\n t: (key: string, params?: Record<string, string | number>) => string,\n): string {\n if (count === 0) return t('components.not-called')\n\n return count === 1 ? t('components.in-block') : t('components.in-blocks', { count })\n}\n\n/** Layout nodes: they group fields and are never a value of their own. */\nconst LAYOUT = new Set(['wx-card', 'wx-tabs', 'wx-tab', 'wx-row', 'wx-col', 'wx-divider'])\n\n/** The fields of a schema through its layout, flat — the variables a template gets. */\nexport function schemaFields(schema: ScreenNode[]): ScreenNode[] {\n const found: ScreenNode[] = []\n\n for (const node of schema) {\n if (!node || typeof node !== 'object') continue\n if (LAYOUT.has(node.type)) found.push(...schemaFields(node.children ?? []))\n else if (typeof node.id === 'string' && node.id !== '') found.push(node)\n }\n\n return found\n}\n\n/**\n * The tag that calls a type, with every input it takes — what the help under a component's\n * template offers to copy.\n *\n * `wx-data` is passed from code, so it is bound (`:card=\"$card\"`); a plain field shows its sample\n * when that is a word (`tone=\"accent\"`) and is bound otherwise. Declared slots stand in the body;\n * with none, the tag closes itself — the default `$slot` is there all the same, and a body shown\n * for it would read as something the component needs.\n */\nexport function callTag(\n slug: string,\n schema: ScreenNode[],\n sample: Record<string, unknown> = {},\n fallback: string | null = null,\n): string {\n const fields = schemaFields(schema)\n const attributes = [`type=\"${slug}\"`]\n\n for (const node of fields) {\n if (node.type === 'wx-slot' || node.type === 'wx-blocks') continue\n\n const value = sample[node.id]\n\n attributes.push(\n node.type !== 'wx-data' && (typeof value === 'string' || typeof value === 'number')\n ? `${node.id}=\"${String(value).replace(/\"/g, '&quot;')}\"`\n : `:${node.id}=\"$${variableOf(node.id)}\"`,\n )\n }\n\n if (fallback) attributes.push(`fallback=\"${fallback}\"`)\n\n const slots = fields.filter((node) => node.type === 'wx-slot')\n const head = `<x-webx-block ${attributes.join(' ')}`\n\n if (slots.length === 0) return `${head} />`\n\n return [\n `${head}>`,\n ...slots.map((node) => ` <x-slot:${node.id}>…</x-slot:${node.id}>`),\n '</x-webx-block>',\n ].join('\\n')\n}\n\n/** `cta-label` has no variable of its own; the caller's is written as it would be named. */\nfunction variableOf(id: string): string {\n return id.replace(/-(\\w)/g, (_match, letter: string) => letter.toUpperCase())\n}\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, provide, reactive, ref, watch } from 'vue'\nimport { useRoute, useRouter } from 'vue-router'\nimport {\n useAdmin,\n useErrorText,\n useTranslate,\n WxHelpButton,\n WxRenameButton,\n WxScreenHead,\n type ScreenAction,\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 WxIconPicker,\n WxInput,\n WxInputNumber,\n WxPopover,\n WxSelect,\n WxSkeleton,\n WxSwitch,\n WxTab,\n WxTabs,\n WxTagsInput,\n WxText,\n WxTextarea,\n} from '@webx-ui/core'\nimport { coreTypes, 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 {\n completions,\n schemaCompletions,\n stylesCompletions,\n templateCompletions,\n type TagTarget,\n} from './completions'\nimport { lintBlock } from './lint'\nimport { blocksOwnerKey } from './preview'\nimport {\n callerWords,\n callTag,\n formSchema,\n groupLabel,\n kindOf,\n schemaFields,\n usageWords,\n} from './schema'\nimport type {\n BlockContent,\n BlockKind,\n BlocksMeta,\n BlockType,\n BlockUsage,\n PublishRefusal,\n} from './types'\n\n/**\n * The editor of one type: six tabs across the screen — the four files, the settings and the\n * history — and what each of them needs beside it. The template has the block drawn on its\n * sample; the schema has the form it builds. The rest have nothing, and take the width.\n *\n * Where the type stands is a list behind one word of the subtitle.\n *\n * The loop is closed all the same: edit the schema and the form rebuilds, edit the values and\n * the stage redraws, edit the template or the styles and so does it.\n *\n * A component is edited on the same screen (§3.9 of the components spec). What differs is what\n * its schema means — the input a caller hands it, not a form — so the settings lose what only a\n * block on a page needs, \"Fields\" become \"Input data\", and under the template stands the tag that\n * calls it. Where it is used is the blocks that call it rather than pages.\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 kind: 'block' as BlockKind,\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\n/* The sample form's nested constructors add into this block, as it stands in the settings. */\nprovide(\n blocksOwnerKey,\n computed(() =>\n block.value\n ? {\n ...block.value,\n slug: settings.slug,\n title: settings.title,\n allow: settings.allow.length ? settings.allow : null,\n }\n : null,\n ),\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 stage: 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\n/**\n * What a tag in this template can call: every type, and every place a module declared and the\n * site has not customised — a tag with a `fallback` calls those too. Read once per editor.\n */\nconst targets = ref<TagTarget[]>([])\nconst typeIds = new Map<string, number>()\nconst schemas = new Map<string, Promise<BlockContent['schema'] | null>>()\n\nasync function loadTargets(): Promise<void> {\n try {\n const list = await api.index()\n\n typeIds.clear()\n for (const type of list.blocks) typeIds.set(type.slug, type.id)\n\n targets.value = [\n ...list.blocks.map((type) => ({\n slug: type.slug,\n title: type.title,\n kind: kindOf(type),\n fallback: list.declared.find((place) => place.slug === type.slug)?.fallback ?? null,\n })),\n ...list.declared\n .filter((place) => !place.customised)\n .map((place) => ({\n slug: place.slug,\n title: place.title,\n kind: 'component' as const,\n fallback: place.fallback,\n })),\n ]\n } catch {\n // Only the suggestions go without it; the editor has nothing else to do with the list.\n }\n}\n\n/** A called type's schema, asked for once and kept: its own for the type being edited. */\nfunction schemaOf(\n slug: string,\n): BlockContent['schema'] | null | Promise<BlockContent['schema'] | null> {\n if (slug === settings.slug) return content.schema\n\n const id = typeIds.get(slug)\n if (id === undefined) return null\n\n let found = schemas.get(slug)\n\n if (found === undefined) {\n found = api.get(id).then(\n (type) => type.content?.schema ?? null,\n () => null,\n )\n schemas.set(slug, found)\n }\n\n return found\n}\n\n/* Built once: the sources read the other files of the type when asked, not when made. */\nconst assist = {\n template: [\n completions(\n templateCompletions({\n schema: () => content.schema,\n styles: () => content.styles,\n types: () => targets.value,\n schemaOf,\n }),\n ),\n ],\n styles: [\n completions(stylesCompletions({ slug: () => settings.slug, template: () => content.template })),\n ],\n // The renderer's own types under the panel's, the same merge the sample form is drawn with.\n schema: [completions(schemaCompletions({ types: () => ({ ...coreTypes, ...context.types }) }))],\n}\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 kind: kindOf(loaded),\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 void loadTargets()\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 stage.stage = drawn.stage ?? null\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 // A component stands on no page itself; what a new version reaches is the blocks calling it.\n // A declared place is also printed by the module's views, which the count does not see.\n message: declaredModule.value\n ? t('components.publish-declared', {\n module: declaredModule.value,\n count: callers.value.length,\n })\n : isComponent.value\n ? t('components.publish-text', { count: callers.value.length })\n : 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 // Deleting a customised place is how it goes back to the module's view (§2, decision 5), and\n // the dialog says so: \"cannot be undone\" alone would read as losing the recipe card for good.\n const reset = block.value.declared != null\n\n const agreed = await confirm({\n title: reset\n ? t('components.delete-declared-title', { title: block.value.title })\n : t('page.delete-title', { title: block.value.title }),\n message: reset ? t('components.delete-declared-text') : t('page.delete-text'),\n confirmText: reset ? t('components.delete-declared') : 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\n/** The two tabs the picture belongs to: the markup and the styles both change it. */\nconst withStage = computed(() => tab.value === 'template' || tab.value === 'styles')\n\n/**\n * What the script field is, in three lines of it.\n *\n * The body of `async (el, values) => { … }` is a contract nobody guesses from an empty\n * editor: the sentence under it names `el` and `values`, and these say what they are for.\n * The code is code and stays in English; what each one does is a line of the dictionary.\n */\nconst examples = computed(() => [\n {\n title: t('page.example-handler'),\n code: `el.querySelector('.b-hero__button')?.addEventListener('click', (event) => {\\n event.preventDefault()\\n el.classList.toggle('is-open')\\n})`,\n },\n {\n title: t('page.example-values'),\n /* The one thing the sentence above the examples does not say: values reach the script\n only through the attribute, and a template that never prints it hands over `{}`. */\n code: `// <section data-wx-values=\"{{ json_encode($block->values) }}\">\\nconst seconds = Number(values.delay ?? 5)\\n\\nsetInterval(() => el.classList.toggle('is-second'), seconds * 1000)`,\n },\n {\n title: t('page.example-provided'),\n code: `const Swiper = await webx.use('swiper')\\n\\nnew Swiper(el.querySelector('.b-slider__viewport'), { loop: true })`,\n },\n])\n\nconst shownUsage = computed(() => usage.value.slice(0, 5))\n\nconst isComponent = computed(() => settings.kind === 'component')\n\n/** The blocks whose published version calls this type. */\nconst callers = computed(() => block.value?.used_by ?? [])\n\n/** The module whose views call this slug, by its name in the panel. */\nconst declaredModule = computed(() => {\n const id = block.value?.declared?.module\n\n if (!id) return null\n\n return (\n context.state.manifest?.modules.find((module) => module.id === id)?.title ??\n id.charAt(0).toUpperCase() + id.slice(1)\n )\n})\n\n/** The words of the subtitle: pages for a block, calling blocks for a component. */\nconst whereWords = computed(() =>\n isComponent.value\n ? callerWords(callers.value.length, t)\n : usageWords(block.value?.usage_count ?? 0, t),\n)\n\n/** Anything behind those words: pages, calling blocks, or a module's views. */\nconst hasWhere = computed(\n () =>\n (block.value?.usage_count ?? 0) > 0 ||\n callers.value.length > 0 ||\n declaredModule.value !== null,\n)\n\n/** Why the type cannot be deleted, when it cannot. Pages first: they are what editors see. */\nconst deleteBlocked = computed<string | null>(() => {\n const count = block.value?.usage_count ?? 0\n\n if (count > 0) return count === 1 ? t('page.delete-used-one') : t('page.delete-used', { count })\n\n if (callers.value.length > 0) {\n return t('components.delete-called', {\n titles: callers.value.map((parent) => `\"${parent.title}\"`).join(', '),\n })\n }\n\n return null\n})\n\n/** The tag that calls this type, with its inputs — the help under a component's template. */\nconst call = computed(() =>\n callTag(settings.slug, content.schema, content.sample, block.value?.declared?.fallback ?? null),\n)\n\n/** Each `wx-data` input and what its shape holds, as far as the server described it. */\nconst dataInputs = computed(() =>\n schemaFields(content.schema)\n .filter((node) => node.type === 'wx-data')\n .map((node) => {\n const shape = typeof node.props?.shape === 'string' ? node.props.shape : null\n\n return {\n id: node.id,\n shape,\n fields: shape ? (block.value?.shape?.[shape]?.fields ?? []) : [],\n }\n }),\n)\n\nasync function copyCall(): Promise<void> {\n try {\n await navigator.clipboard.writeText(call.value)\n toast.success(t('components.copied'))\n } catch {\n // No clipboard (an insecure origin, a denied permission): the tag is on the screen to select.\n }\n}\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/* The two things this editor is for. The bar along the bottom repeats them (§3.3). */\nconst kindOptions = computed(() => [\n { value: 'block', label: t('components.kind-block') },\n { value: 'component', label: t('components.kind-component') },\n])\n\nconst actions = computed<ScreenAction[]>(() =>\n canManage.value\n ? [\n { key: 'save', label: t('page.save'), loading: saving.value, run: () => void save() },\n {\n key: 'publish',\n label: t('page.publish'),\n primary: true,\n loading: publishing.value,\n disabled: !block.value?.draft && !dirty.value,\n run: () => void publish(),\n },\n ]\n : [],\n)\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__split\">\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 <!--\n The panel's head, not this editor's: the way out, the name, what state the type is in\n and what can be done with it. Renaming is a control beside the name rather than typing\n into what looks like a heading.\n -->\n <wx-screen-head\n :title=\"settings.title\"\n :back=\"base\"\n :back-label=\"t('page.back')\"\n :actions=\"actions\"\n >\n <template #title-after>\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 <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>\n\n <!--\n Where the type stands is one line of the subtitle and a list behind it: a card of\n five page names took a quarter of the column beside the stage to say what the head\n already says in three words. The words are the door.\n -->\n <template #subtitle>\n <code>{{ settings.slug }}</code>\n ·\n {{ isComponent ? t('components.kind-component') : groupLabel(settings.group, t) }}\n ·\n <wx-popover v-if=\"hasWhere\" :title=\"t('page.usage')\" :width=\"260\" align=\"start\">\n <template #trigger>\n <button type=\"button\" class=\"wx-block-editor__uses\">\n {{ whereWords }}\n </button>\n </template>\n\n <div class=\"wx-block-editor__usage\">\n <!-- The blocks calling it first on a component: those are what a change reaches. -->\n <router-link\n v-for=\"parent in callers\"\n :key=\"`type:${parent.id}`\"\n :to=\"`${base}/${parent.id}`\"\n class=\"wx-block-editor__use\"\n >\n {{ t('components.called-by', { title: parent.title }) }}\n </router-link>\n <div v-if=\"declaredModule\" class=\"wx-block-editor__use\">\n {{ t('components.module-views', { module: declaredModule }) }}\n </div>\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-popover>\n <template v-else>{{ whereWords }}</template>\n </template>\n </wx-screen-head>\n\n <wx-alert\n v-if=\"!meta.editing\"\n type=\"info\"\n variant=\"soft\"\n :description=\"t('page.editing-off')\"\n />\n\n <!--\n The block stands beside the two files that draw it and nowhere else: it used to be a\n column down the whole screen, half the width of the settings and of the history, which\n have nothing to do with how the block looks. One stage and not one per tab — `v-show`,\n because a frame taken out of the document and put back reloads.\n -->\n <div class=\"wx-block-editor__columns\" :class=\"{ 'is-alone': !withStage }\">\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 :extensions=\"assist.template\"\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\n <!--\n How this component is called, ready to copy: the tag with every input it takes, and\n for a structure passed from code, what the structure holds. A component is only\n ever used this way, so the one thing a person needs next is written out here.\n -->\n <wx-card v-if=\"isComponent\" class=\"wx-block-editor__call\" :title=\"t('components.call')\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('components.call-help') }}</wx-text>\n <div class=\"wx-block-editor__call-tag\">\n <pre><code>{{ call }}</code></pre>\n <wx-button size=\"sm\" variant=\"outline\" @click=\"copyCall\">\n {{ t('components.copy') }}\n </wx-button>\n </div>\n\n <div v-for=\"input in dataInputs\" :key=\"input.id\" class=\"wx-block-editor__shape\">\n <wx-text size=\"sm\" tone=\"muted\">\n {{\n input.fields.length\n ? t('components.shape', { name: input.id })\n : t('components.shape-free', { name: input.id })\n }}\n <code v-if=\"input.shape\">{{ input.shape }}</code>\n </wx-text>\n <dl v-if=\"input.fields.length\" class=\"wx-block-editor__shape-fields\">\n <template v-for=\"field in input.fields\" :key=\"field.name\">\n <dt>\n <code>{{ field.name }}</code>\n <span class=\"wx-block-editor__shape-type\">{{ field.type }}</span>\n </dt>\n <dd>{{ field.description }}</dd>\n </template>\n </dl>\n </div>\n\n <wx-text size=\"sm\" tone=\"muted\">{{ t('components.site-views') }}</wx-text>\n </wx-card>\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 :extensions=\"assist.styles\"\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\n <!--\n What the two names in scope are actually for. The examples are code and stay in\n English; what each one is for is a line of the dictionary. Reading, not inserting:\n dropping four lines into the middle of somebody's function is not a favour.\n -->\n <wx-card class=\"wx-block-editor__examples\" :title=\"t('page.examples')\">\n <div\n v-for=\"example in examples\"\n :key=\"example.title\"\n class=\"wx-block-editor__example\"\n >\n <wx-text size=\"sm\" tone=\"muted\">{{ example.title }}</wx-text>\n <pre><code>{{ example.code }}</code></pre>\n </div>\n </wx-card>\n </wx-tab>\n\n <!--\n The schema and the form it builds, side by side: the sample used to stand in the\n column beside the stage, where it pushed the picture up and stood open on every tab\n — including the four where nobody is looking at values. Here it is the other half of\n the tab it belongs to, and editing a field shows what it becomes.\n -->\n <wx-tab\n value=\"fields\"\n :label=\"isComponent ? t('components.tab-inputs') : t('page.tab-fields')\"\n >\n <div class=\"wx-block-editor__split\">\n <div class=\"wx-block-editor__pane\">\n <wx-code-editor\n :model-value=\"schemaText\"\n language=\"json\"\n :extensions=\"assist.schema\"\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\">{{\n isComponent ? t('components.inputs-help') : t('page.fields-help')\n }}</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\n <wx-card class=\"wx-block-editor__sample\" :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-card>\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('components.kind')\"\n :help=\"t('components.kind-help')\"\n :error=\"errorOf('kind')\"\n :disabled=\"!canManage\"\n >\n <wx-select v-model=\"settings.kind\" :options=\"kindOptions\" />\n </wx-form-item>\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 <!-- What only a block on a page needs: where it is picked from, what it may\n hold and stand in, how many a page takes. A component is never picked. -->\n <wx-form-item\n v-if=\"!isComponent\"\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 <!-- Picked, not typed: a name the set does not have draws nothing at all,\n and nothing on the screen would say which of the two it was. -->\n <wx-icon-picker\n :model-value=\"settings.icon\"\n clearable\n :placeholder=\"t('page.icon-search')\"\n :empty-text=\"t('page.icon-none')\"\n :unknown-text=\"t('page.icon-unknown')\"\n :clear-label=\"t('page.icon-clear')\"\n @update:model-value=\"settings.icon = $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 v-if=\"!isComponent\"\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 v-if=\"!isComponent\"\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 v-if=\"!isComponent\"\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 v-if=\"!isComponent\"\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=\"deleteBlocked !== null\"\n @click=\"remove\"\n >\n {{ block.declared ? t('components.delete-declared') : t('page.delete') }}\n </wx-button>\n <wx-text v-if=\"deleteBlocked\" size=\"sm\" tone=\"muted\">{{ deleteBlocked }}</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\n <block-stage\n v-show=\"withStage\"\n class=\"wx-block-editor__stage\"\n :html=\"stage.html\"\n :styles=\"stage.styles\"\n :script=\"stage.script\"\n :runtime=\"stage.runtime\"\n :stage=\"stage.stage\"\n :loading=\"stage.loading\"\n />\n </div>\n\n <!-- The editor is six tabs of code and the stage beside them, so the head is long gone\n by the time there is anything to save: the two buttons stand here as well.\n The three badges do not. What state the type is in is a fact about the type, not\n about the last keystroke, and it is already said once — beside the name, where this\n panel says the state of a record. Twice on one screen is not twice as clear. -->\n <wx-action-bar 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 </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__ghost-head {\n max-width: 420px;\n}\n\n/* The tabs and the block beside them, while a tab that draws the block is the open one.\n `is-alone` is the same grid with the second track taken away: a hidden item still leaves\n its column standing, and the tabs would keep half the screen with nothing in the rest. */\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.wx-block-editor__columns.is-alone {\n grid-template-columns: minmax(0, 1fr);\n}\n\n/* What a tab puts side by side: the schema and the form it builds.\n One column below 1080, where two of anything is two half-width columns of nothing. */\n.wx-block-editor__split {\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 .wx-block-editor__split {\n grid-template-columns: minmax(0, 1fr);\n }\n}\n\n/* The tag to copy: code on the subtle ground, the button beside it — below it on a phone. */\n.wx-block-editor__call {\n min-width: 0;\n}\n\n.wx-block-editor__call :deep(.wx-card__body) {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-10);\n}\n\n.wx-block-editor__call-tag {\n display: flex;\n flex-wrap: wrap;\n align-items: flex-start;\n gap: var(--wx-space-8);\n}\n\n.wx-block-editor__call-tag pre {\n flex: 1 1 240px;\n min-width: 0;\n margin: 0;\n padding: var(--wx-space-10) var(--wx-space-12);\n border-radius: var(--wx-radius-sm);\n background: var(--wx-bg-subtle);\n overflow-x: auto;\n}\n\n.wx-block-editor__call-tag code {\n line-height: 1.6;\n color: var(--wx-text-default);\n white-space: pre;\n}\n\n.wx-block-editor__shape {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-6);\n}\n\n/* Name and type on one line, what it is under them: a glossary, read top to bottom. */\n.wx-block-editor__shape-fields {\n display: grid;\n grid-template-columns: minmax(0, max-content) minmax(0, 1fr);\n gap: var(--wx-space-4) var(--wx-space-12);\n margin: 0;\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-block-editor__shape-fields dt {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--wx-space-6);\n}\n\n.wx-block-editor__shape-fields dd {\n margin: 0;\n color: var(--wx-text-muted);\n}\n\n.wx-block-editor__shape-type {\n font-size: var(--wx-font-size-xs);\n color: var(--wx-text-muted);\n}\n\n@container (max-width: 520px) {\n .wx-block-editor__shape-fields {\n grid-template-columns: minmax(0, 1fr);\n }\n\n .wx-block-editor__shape-fields dd {\n margin-block-end: var(--wx-space-6);\n }\n}\n\n/* Read, not copied: monospace, wrapped, and no box that says \"editor\". */\n.wx-block-editor__examples {\n min-width: 0;\n}\n\n.wx-block-editor__example + .wx-block-editor__example {\n margin-block-start: var(--wx-space-12);\n}\n\n.wx-block-editor__example pre {\n margin: var(--wx-space-4) 0 0;\n padding: var(--wx-space-10) var(--wx-space-12);\n border-radius: var(--wx-radius-sm);\n background: var(--wx-bg-subtle);\n overflow-x: auto;\n}\n\n.wx-block-editor__example code {\n font-family: var(--wx-font-family-mono);\n font-size: var(--wx-font-size-xs);\n line-height: 1.6;\n color: var(--wx-text-default);\n white-space: pre;\n}\n\n/* The picture stays put while the template scrolls under it. */\n.wx-block-editor__stage {\n position: sticky;\n top: var(--wx-space-12);\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__sample {\n min-width: 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/* A word in the subtitle that opens the list: a link, because that is what it does. */\n.wx-block-editor__uses {\n padding: 0;\n border: 0;\n background: none;\n font: inherit;\n color: var(--wx-text-link);\n cursor: pointer;\n}\n\n.wx-block-editor__uses:hover {\n text-decoration: underline;\n text-underline-offset: 0.2em;\n}\n\n.wx-block-editor__uses:focus-visible {\n outline: none;\n border-radius: var(--wx-radius-xs);\n box-shadow: var(--wx-ring-focus);\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\na.wx-block-editor__use {\n color: var(--wx-text-link);\n text-decoration: none;\n}\n\na.wx-block-editor__use:hover {\n text-decoration: underline;\n text-underline-offset: 0.2em;\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 { useTranslate } from '@webx-ui/module-admin'\nimport { useModal, WxButton, WxDialog, WxEmpty, WxIcon, WxText } from '@webx-ui/core'\nimport { useBlocksMessages } from './i18n'\nimport type { Destination } from './move'\n\n/**\n * \"Move to\": the lists a block may go into, each named by the containers down to it.\n *\n * A list rather than a drag across the tree. The places are few and each one is named, the\n * rules are applied before anything is offered rather than at the moment of a drop, and a\n * finger in a sheet can do it as well as a mouse can. The block goes to the end of the list\n * it is moved into; its place there is a drag within that list.\n */\nwithDefaults(\n defineProps<{\n title: string\n destinations: Destination[]\n /** What the top level is called: the page, or the block whose sample this is. */\n topLabel: string\n }>(),\n {},\n)\n\nconst { resolve, dismiss, open } = useModal<Destination>()\nuseBlocksMessages()\n\nconst t = useTranslate('webx-blocks')\n</script>\n\n<template>\n <wx-dialog v-model:open=\"open\" :title=\"t('field.move-title', { title })\" :width=\"520\">\n <wx-empty\n v-if=\"destinations.length === 0\"\n icon=\"grid\"\n :title=\"t('field.move-none')\"\n size=\"sm\"\n />\n\n <div v-else class=\"wx-block-move\">\n <button\n v-for=\"place in destinations\"\n :key=\"`${place.parentKey}:${place.field}`\"\n type=\"button\"\n class=\"wx-block-move__place\"\n :disabled=\"place.full\"\n @click=\"resolve(place)\"\n >\n <wx-icon :name=\"place.parentKey === null ? 'file' : 'folder'\" />\n <span class=\"wx-block-move__trail\">\n <template v-if=\"place.trail.length === 0\">{{ topLabel }}</template>\n <template v-for=\"(step, index) in place.trail\" v-else :key=\"index\">\n <span v-if=\"index > 0\" class=\"wx-block-move__sep\">/</span>\n <span :class=\"{ 'is-last': index === place.trail.length - 1 }\">{{ step }}</span>\n </template>\n </span>\n <wx-text v-if=\"place.full\" size=\"sm\" tone=\"muted\">{{ t('field.move-full') }}</wx-text>\n </button>\n </div>\n\n <template #footer>\n <wx-button variant=\"outline\" @click=\"dismiss()\">{{ t('page.cancel') }}</wx-button>\n </template>\n </wx-dialog>\n</template>\n\n<style scoped>\n.wx-block-move {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-4);\n}\n\n.wx-block-move__place {\n display: flex;\n align-items: center;\n gap: var(--wx-space-10);\n width: 100%;\n padding: var(--wx-space-10) var(--wx-space-12);\n font: inherit;\n text-align: start;\n color: inherit;\n background: transparent;\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-control);\n cursor: pointer;\n}\n\n.wx-block-move__place:hover:not(:disabled),\n.wx-block-move__place:focus-visible {\n border-color: var(--wx-color-primary);\n background: var(--wx-color-primary-soft);\n outline: none;\n}\n\n.wx-block-move__place:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.wx-block-move__trail {\n display: flex;\n flex: 1;\n flex-wrap: wrap;\n gap: var(--wx-space-4);\n min-width: 0;\n color: var(--wx-text-muted);\n}\n\n.wx-block-move__trail .is-last,\n.wx-block-move__trail:not(:has(span)) {\n color: var(--wx-text-default);\n font-weight: var(--wx-font-weight-medium);\n}\n\n.wx-block-move__sep {\n color: var(--wx-text-muted);\n}\n</style>\n","import { computed, inject, ref, watchEffect, type Ref } from 'vue'\nimport { adminKey } from '@webx-ui/module-admin'\nimport { siteShell } from './frame'\n\n/**\n * One request for every thumbnail on the screen: the stage page is the same for all of them,\n * and a list of forty cards asking for it forty times is forty renders of the site's layout.\n * Kept for the life of the panel — a site's stylesheets change with a deploy, and a deploy is\n * a reload of the panel anyway.\n */\nconst shells = new Map<string, Promise<string | null>>()\n\nexport function loadShell(url: string): Promise<string | null> {\n let shell = shells.get(url)\n\n if (shell === undefined) {\n shell = fetch(url, { credentials: 'same-origin', headers: { Accept: 'text/html' } })\n .then((response) => (response.ok ? response.text() : null))\n .then((html) => (html === null ? null : siteShell(html, url)))\n // Not allowed to see the stage, or no stage at all: the thumbnail draws the block bare,\n // which is what it did before there was one.\n .catch(() => null)\n shells.set(url, shell)\n }\n\n return shell\n}\n\n/**\n * The site's shell for thumbnails, once it has arrived; null until then and wherever there is\n * none. Outside a panel (a test, a screen of a project's own) there is no manifest to name the\n * stage, and the thumbnail stays bare rather than failing.\n */\nexport function useSiteShell(): Ref<string | null> {\n const admin = inject(adminKey, null)\n const shell = ref<string | null>(null)\n\n const url = computed(() => {\n const meta = admin?.state.manifest?.modules.find((module) => module.id === 'blocks')?.meta\n const stage = meta?.stage\n\n return typeof stage === 'string' && stage !== '' ? stage : null\n })\n\n watchEffect(() => {\n const current = url.value\n if (current === null) return\n\n void loadShell(current).then((loaded) => {\n if (url.value === current) shell.value = loaded\n })\n })\n\n return shell\n}\n\n/** For tests: forget what was loaded. */\nexport function forgetShells(): void {\n shells.clear()\n}\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, ref } from 'vue'\nimport { useElementWidth, WxIcon } from '@webx-ui/core'\nimport { stageDocument, thumbDocument } from './frame'\nimport { useSiteShell } from './shell'\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 *\n * Drawn in the site's own clothes when the site has a stage: its stylesheets and fonts, and\n * the wrappers the block sits in on a page, without the header, the footer or any script\n * (see `siteShell`). Bare until that arrives, and bare where there is none.\n *\n * `fit` is for components. A block is a band of a page, and the top of it at full width is the\n * right picture; a component is a whole thing — a card taller than it is wide — and cut to the\n * height of the box it shows only its photo. So with `fit` the root of what was drawn is measured\n * inside the frame and scaled to fit the box both ways, in the middle of it.\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 /** Scale what was drawn to fit the box, rather than the width to fill it. */\n fit?: boolean\n }>(),\n { width: 1280, height: 120, fit: false },\n)\n\nconst box = ref<HTMLElement | null>(null)\nconst boxWidth = useElementWidth(box)\n\n/** The root of what was drawn, in the frame's pixels; null until the frame has loaded. */\nconst drawn = ref<{ left: number; top: number; width: number; height: number } | null>(null)\n\n/*\n * How tall the frame is before scaling, when fitting. Tall enough for a card to lay itself out\n * at its own height rather than squeezed into the box's; a layout in `vh` sees this too.\n */\nconst TALL = 1600\n\nconst widthScale = computed(() => (boxWidth.value > 0 ? boxWidth.value / props.width : 0.2))\n\nconst fitted = computed(() => {\n const rect = drawn.value\n\n if (!props.fit || !rect || rect.width <= 0 || rect.height <= 0 || boxWidth.value <= 0) {\n return null\n }\n\n // Never larger than the width scale: a small badge stays small rather than blown up.\n const scale = Math.min(widthScale.value, boxWidth.value / rect.width, props.height / rect.height)\n\n return {\n scale,\n x: (boxWidth.value - rect.width * scale) / 2 - rect.left * scale,\n y: (props.height - rect.height * scale) / 2 - rect.top * scale,\n }\n})\n\nconst shell = useSiteShell()\n\nconst srcdoc = computed(() => {\n if (!props.thumbnail) return ''\n\n const input = { html: props.thumbnail.html, styles: props.thumbnail.styles }\n\n return shell.value ? thumbDocument(shell.value, input) : stageDocument(input)\n})\n\nconst frameStyle = computed(() => {\n const fit = fitted.value\n\n const rect = drawn.value\n\n if (fit && rect) {\n return {\n width: `${props.width}px`,\n height: `${TALL}px`,\n transform: `translate(${fit.x}px, ${fit.y}px) scale(${fit.scale})`,\n // The component alone: the rest of the frame is a white page around it, and moved off\n // the corner it shows as a white slab beside a small badge.\n clipPath: `inset(${rect.top}px ${props.width - rect.left - rect.width}px ${TALL - rect.top - rect.height}px ${rect.left}px)`,\n }\n }\n\n return {\n width: `${props.width}px`,\n height: props.fit ? `${TALL}px` : `${Math.round(props.height / widthScale.value)}px`,\n transform: `scale(${widthScale.value})`,\n // Until it is measured, a fitted frame would flash its top at the wrong scale; measured and\n // found to have no size (a root with `display: contents`), it is drawn the ordinary way.\n visibility: props.fit && drawn.value === null ? ('hidden' as const) : undefined,\n }\n})\n\nlet observer: ResizeObserver | null = null\n\n/*\n * Measured inside the frame, and watched from inside it: a ResizeObserver belongs to its own\n * window and does not see another document's elements, and fonts and pictures arriving late\n * change the card's height after the load event.\n */\nfunction onLoad(event: Event): void {\n if (!props.fit) return\n\n observer?.disconnect()\n\n const frame = event.target as HTMLIFrameElement\n const view = frame.contentWindow as (Window & typeof globalThis) | null\n const doc = frame.contentDocument\n\n if (!view || !doc?.body) return\n\n const root = doc.querySelector<HTMLElement>('[data-wx-block]') ?? doc.body\n\n const measure = (): void => {\n const rect = root.getBoundingClientRect()\n\n drawn.value = { left: rect.left, top: rect.top, width: rect.width, height: rect.height }\n }\n\n measure()\n observer = new view.ResizeObserver(measure)\n observer.observe(root)\n}\n\nonBeforeUnmount(() => observer?.disconnect())\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 @load=\"onLoad\"\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","import type { ScreenNode } from '@webx-ui/schema'\nimport { isNodeList, locate, nestedFields } from './content'\nimport type { BlockNode, BlockType } from './types'\n\n/**\n * May a block of this type stand here: the container's say-so and the type's own, both.\n *\n * `parent` is the block whose field it is, or null for the page; `allow` is what that field\n * narrows it to, when it does. The picker asks this for a new block and \"Move to\" for an\n * existing one, and the two must not disagree about where a block can go.\n */\nexport function allows(type: BlockType, parent: BlockType | null, allow: string[] | null): boolean {\n if (parent === null) {\n const fieldAllows = allow === null || allow.includes(type.slug)\n\n return fieldAllows && (type.allowed_in === null || type.allowed_in.includes('root'))\n }\n\n const parentAllows = allow\n ? allow.includes(type.slug)\n : parent.allow?.includes(type.slug) === true\n const typeAllows = type.allowed_in === null || type.allowed_in.includes(parent.slug)\n\n return parentAllows && typeAllows\n}\n\n/** One list a block could be moved into. */\nexport interface Destination {\n /** The container, or null for the top level. */\n parentKey: string | null\n field: string | null\n /** The containers down to it, in words, outermost first. Empty at the top level. */\n trail: string[]\n /** It already holds as many blocks as its field takes. */\n full: boolean\n}\n\n/** What the top level is: the page, or — in a block's sample form — that block. */\nexport interface TopLevel {\n owner: BlockType | null\n allow: string[] | null\n max: number | null\n}\n\n/**\n * Every list a block may be moved into, in the order the page draws them.\n *\n * Not the list it is in already — that is a drag — and nothing inside the block itself, which\n * would take it out of the tree along with its own children. A block of an unknown type goes\n * nowhere: there is nothing to judge the rules by.\n */\nexport function destinations(\n tree: BlockNode[],\n key: string,\n catalog: BlockType[],\n top: TopLevel,\n): Destination[] {\n const moving = locate(tree, key)\n const type = moving ? catalog.find((entry) => entry.slug === moving.node.type) : undefined\n\n if (!moving || !type) return []\n\n const found: Destination[] = []\n const here = (parentKey: string | null, field: string | null) =>\n (moving.parent?.key ?? null) === parentKey && moving.field === field\n\n if (!here(null, null) && allows(type, top.owner, top.allow)) {\n found.push({\n parentKey: null,\n field: null,\n trail: [],\n full: top.max !== null && tree.length >= top.max,\n })\n }\n\n const visit = (list: BlockNode[], trail: string[]) => {\n for (const node of list) {\n if (node.key === key) continue\n\n const container = catalog.find((entry) => entry.slug === node.type)\n const fields: ScreenNode[] = container?.content ? nestedFields(container.content.schema) : []\n\n for (const slot of fields) {\n const title = container!.title\n const step = fields.length > 1 ? `${title} · ${slot.label ?? slot.id}` : title\n const value = node.values[slot.id]\n const children = isNodeList(value) ? value : []\n const max = (slot.props?.max as number | undefined) ?? null\n const allow = (slot.props?.allow as string[] | undefined) ?? null\n\n if (!here(node.key, slot.id) && allows(type, container!, allow)) {\n found.push({\n parentKey: node.key,\n field: slot.id,\n trail: [...trail, step],\n full: max !== null && children.length >= max,\n })\n }\n\n visit(children, [...trail, step])\n }\n }\n }\n\n visit(tree, [])\n\n return found\n}\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 { allows } from './move'\nimport { useBlocksMessages } from './i18n'\nimport { groupLabel, kindOf } 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 same rule \"Move to\" goes by. */\nfunction allowedHere(type: BlockType): boolean {\n return allows(type, props.parent, props.allow)\n}\n\n/*\n * A component is never put on a page by hand: it is called from a template, and its schema is\n * what the caller passes, not a form an editor could fill. The server's catalogue leaves them\n * out already (§3.10); this is for a catalogue that came from somewhere else.\n */\nconst options = computed<Option[]>(() =>\n props.catalog\n .filter(\n (type) =>\n kindOf(type) !== 'component' &&\n type.is_enabled &&\n type.published !== null &&\n allowedHere(type),\n )\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, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { useElementWidth, WxAction, 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. The whole page at desktop width, unless the bar is asked for a\n * tablet or a phone; full screen is for the panel too narrow to read a desktop in.\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 /** Bumped by the host to reload the page. */\n reload?: number\n /**\n * The preview is the screen rather than a column beside one — the shape the panel takes\n * on a phone. It starts as a phone, and its bar carries the way into the blocks, because\n * there is no tree standing next to it to click.\n */\n compact?: boolean\n }>(),\n { selected: null, reload: 0, compact: 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 /** The way into the blocks was asked for. Only ever emitted while `compact`. */\n edit: []\n}>()\n\nconst t = useTranslate('webx-blocks')\n\nconst frame = ref<HTMLIFrameElement | null>(null)\n/* The bar, measured rather than assumed: it floats over the top of the window, and how much\n of the window it takes is what a block is kept clear of. */\nconst bar = ref<HTMLElement | null>(null)\nconst box = ref<HTMLElement | null>(null)\nconst boxWidth = useElementWidth(box)\nconst fullscreen = ref(false)\nconst ready = ref(false)\n\n/*\n * The width asked for by hand, and null for the whole page.\n *\n * Nothing chooses it but the person looking: the preview used to be squeezed into a phone\n * while a block was open, because the column it stood in was 420 px wide and a desktop does\n * not go in there. It is not squeezed any more — the form took the tree's place instead of\n * taking the preview's room — so there is nothing left to guess at.\n */\nconst picked = ref<number | null>(null)\n\n/*\n * The height of the page inside, so that the frame is exactly as tall as what it shows and\n * nothing scrolls in a box of ours: a block taller than the window is read by scrolling the\n * panel, the way the page it belongs to is read.\n *\n * Zero while it cannot be measured — a page from another origin — and then the frame keeps\n * the window-sized height the stylesheet gives it.\n */\nconst contentHeight = ref(0)\n\n/**\n * Told how tall to be by the page inside — in every mode, full screen included.\n *\n * Full screen used to be the exception, a window of a fixed height with the page scrolling\n * inside it, and that exception is what made it useless on a phone: a frame that does not\n * scale shows a 1280 px page through a 375 px slot. One rule now — the frame is as tall as\n * its page and as wide as it fits — and who scrolls it is all that differs: the panel in a\n * column, the sheet's own ground in full screen.\n */\nconst grown = computed(() => contentHeight.value > 0)\n\n/* Words as the accessible name, pictures on screen: three words do not fit a bar this narrow\n and a device is one of the few things a picture says faster than a word anyway. */\nconst widths = computed(() => [\n { value: 1280, icon: 'monitor', ariaLabel: t('field.width-desktop') },\n { value: 834, icon: 'tablet', ariaLabel: t('field.width-tablet') },\n { value: 390, icon: 'smartphone', ariaLabel: t('field.width-phone') },\n])\n\n/**\n * The width nobody asked for: the one that suits the room.\n *\n * Where the preview is the screen, that screen is usually a phone, and a 1280 px page on it\n * is a page nobody can read at the 0.3 the scale would say. A tablet is the same shape of\n * screen with twice the room, and a phone drawn in the middle of it wastes half — so the\n * middle width is the one it starts at. A column beside a tree starts at the whole page.\n */\nconst width = computed(() => {\n if (picked.value !== null) return picked.value\n if (!props.compact) return 1280\n\n return boxWidth.value > 0 && boxWidth.value < 560 ? 390 : 834\n})\n\nconst scale = computed(() => {\n if (boxWidth.value === 0) return 1\n\n /*\n * Whatever it takes to fit, and never more than one to one. The phone used to be excepted\n * from this, back when the phone was the only narrow width there was and the column it\n * stands in is wider than 390 anyway — the exception said nothing then and lies now, when\n * a tablet can be asked for in that same column.\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 ...(grown.value ? { height: `${contentHeight.value}px` } : {}),\n}))\n\n/*\n * The scale is a transform, and a transform does not move the layout: the frame keeps the\n * box it was given whatever it is drawn at. So the hole it is drawn through is the one that\n * carries the size the column actually sees — the frame's own, times the scale.\n */\nconst clipStyle = computed(() => ({\n width: `${Math.round(width.value * scale.value)}px`,\n ...(grown.value ? { height: `${Math.round(contentHeight.value * scale.value)}px` } : {}),\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/* Watches the page inside grow and shrink; released with the document it was watching. */\nlet watcher: ResizeObserver | null = null\n\n/**\n * How tall the page inside is.\n *\n * Off the body, and never off `documentElement.scrollHeight`: that one is never smaller than\n * the frame's own window, so once the frame has been made as tall as the page it stops being\n * a measurement of the page at all — it measures the frame, and a page that gets shorter\n * never gets its height back. The body is the tallest thing the page actually drew, and its\n * margins are part of what it drew.\n */\n/**\n * Undo any scrolling of the page inside.\n *\n * A frame as tall as its page shows it from the top and from nowhere else, so a scroll in\n * there is always something that got there by accident — and what it leaves behind is a\n * preview missing its beginning, with blank frame under its end and no way to scroll back,\n * because the wheel over it moves the panel.\n */\nfunction pin(page: Document): void {\n if (page.documentElement.scrollTop !== 0) page.documentElement.scrollTop = 0\n}\n\nfunction measure(): void {\n const page = doc()\n const body = page?.body\n\n if (!body || !page?.defaultView) return\n\n pin(page)\n\n const style = page.defaultView.getComputedStyle(body)\n const margins = (parseFloat(style.marginTop) || 0) + (parseFloat(style.marginBottom) || 0)\n const height = Math.ceil(body.scrollHeight + margins)\n\n if (height === contentHeight.value) return\n\n contentHeight.value = height\n\n /* The frame takes the new height on the next tick, and the panel is laid out again after\n that: a block asked for in between has to be asked for once more. */\n if (pending !== null) void nextTick(() => requestAnimationFrame(bring))\n}\n\nfunction watch_(page: Document): void {\n watcher?.disconnect()\n\n const view = page.defaultView\n\n if (!view || !page.body) return\n\n /* The frame's own `ResizeObserver`, not ours: an observer belongs to the window whose\n elements it watches, and one made out here never fires for a document in there. */\n watcher = new view.ResizeObserver(measure)\n watcher.observe(page.body)\n measure()\n}\n\nfunction onLoad(): void {\n ready.value = true\n\n const page = doc()\n\n if (!page) return\n\n watch_(page)\n\n binding?.release()\n binding = bindFrame(page, {\n /* No guard against answering a click with a scroll: `bring` moves nothing that is already\n readable, and a block clicked at the very bottom of the window, half under the action\n bar, is exactly the one worth moving. */\n select: (key) => emit('select', key),\n })\n\n highlightBlock(page, props.selected ?? null)\n reveal(props.selected ?? null)\n}\n\n/*\n * The block to bring into view, and the timer that gives up on it.\n *\n * The page inside can still be settling — a width just changed, a picture just arrived — and\n * every such change moves the block and the frame under it. So the ask is kept for as long as\n * the measured height keeps moving rather than answered once, against a layout that is about\n * to change under it.\n */\nlet pending: string | null = null\nlet forget: number | null = null\n\n/**\n * Bring the selected block into view.\n *\n * `scrollIntoView` and nothing else: a frame as tall as its page has nothing to scroll, and\n * the browser walks out of it and scrolls the panel — which is the whole point of the frame\n * being that tall. A frame that could not be measured still scrolls in its own window, and\n * the same call does that too.\n */\nfunction reveal(key: string | null): void {\n if (key === null) return\n\n pending = key\n\n if (forget !== null) clearTimeout(forget)\n forget = window.setTimeout(() => {\n pending = null\n forget = null\n }, 400)\n\n bring()\n}\n\n/**\n * Where the block stands in the window of the panel, not in the window of the frame.\n *\n * The frame does not scroll — it is as tall as its page — so a rect taken inside it is an\n * offset from the frame's own top, and the scale is a transform, so what the panel sees is\n * that offset times the scale.\n */\nfunction place(el: Element): { top: number; height: number } | null {\n const box = frame.value?.getBoundingClientRect()\n\n if (!box) return null\n\n const rect = el.getBoundingClientRect()\n\n return { top: box.top + rect.top * scale.value, height: rect.height * scale.value }\n}\n\n/**\n * What the panel scrolls with: the box the preview stands in, or the window when nothing\n * between them scrolls. Walked rather than assumed, because the screen decides that, not us.\n */\nfunction scroller(): HTMLElement | null {\n let node = frame.value?.parentElement ?? null\n\n while (node) {\n const overflow = getComputedStyle(node).overflowY\n\n if ((overflow === 'auto' || overflow === 'scroll') && node.scrollHeight > node.clientHeight) {\n return node\n }\n\n node = node.parentElement\n }\n\n return null\n}\n\n/**\n * Bring the selected block into view, by as little as it takes and no more.\n *\n * Emphatically **not** `scrollIntoView`, which is what this used to be and what made the\n * preview lose the top of its page: that one scrolls every scrollable ancestor it can find,\n * and the document inside the frame is one of them. When the panel could not move far enough\n * on its own — a short page, a block near its end — the browser made up the difference by\n * scrolling the page *inside* the frame instead, which is the one thing the frame being as\n * tall as its page is there to prevent. The result was a preview starting in the middle of\n * its page with the rest of the frame blank, and no way to scroll it back.\n *\n * So the panel is moved by hand, and nothing else is touched. Only enough to bring the block\n * in, never to centre it. The window is counted a bar short at each end — this preview's own\n * bar floats over the top of it, the screen's action bar over the bottom — and a block too\n * tall to fit between them is put against the top, where reading it starts.\n */\nfunction bring(): void {\n const page = doc()\n\n if (pending === null || !page) return\n\n /* Before anything is measured against it: the arithmetic below reads a rect taken inside\n the frame as an offset from the frame's top, which it only is while the page in there\n stands where it was put. */\n pin(page)\n\n const el = blockElement(page, pending)\n const at = el ? place(el) : null\n\n if (!at) return\n\n const box = scroller()\n const rect = box?.getBoundingClientRect()\n const room = bar.value?.getBoundingClientRect().height ?? 0\n const band = {\n top: (rect?.top ?? 0) + room,\n bottom: (rect ? rect.bottom : window.innerHeight) - room,\n }\n const foot = at.top + at.height\n const above = at.top < band.top\n const tall = at.height > band.bottom - band.top\n const delta = above || tall ? at.top - band.top : foot > band.bottom ? foot - band.bottom : 0\n\n if (delta === 0) return\n\n ;(box ?? window).scrollBy({ top: delta, behavior: 'smooth' })\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 watcher?.disconnect()\n watcher = null\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(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 if (forget !== null) clearTimeout(forget)\n watcher?.disconnect()\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-grown': grown, 'is-compact': compact }\"\n :style=\"{ '--wx-preview-scale': scale }\"\n >\n <div ref=\"bar\" class=\"wx-blocks-preview__bar\">\n <wx-text size=\"xs\" tone=\"muted\" class=\"wx-blocks-preview__label\" truncate>{{\n label\n }}</wx-text>\n <wx-segmented\n class=\"wx-blocks-preview__widths\"\n :model-value=\"width\"\n :options=\"widths\"\n size=\"sm\"\n :aria-label=\"t('field.width')\"\n @update:model-value=\"picked = Number($event)\"\n />\n <!-- A plain row and not `WxActions`: two buttons that never collapse into anything, and\n a row that can collapse renders a dropdown beside itself — a second root, which no\n scoped rule of ours would then reach. -->\n <div class=\"wx-blocks-preview__tools\">\n <!-- The way into the blocks, and only where the preview is the whole screen: with a\n tree beside it this would be a second door into the room you are standing in. -->\n <wx-action\n v-if=\"compact\"\n size=\"sm\"\n tone=\"primary\"\n icon=\"edit\"\n :title=\"t('field.blocks')\"\n @click=\"emit('edit')\"\n />\n <wx-action\n v-if=\"url\"\n size=\"sm\"\n icon=\"external-link\"\n tone=\"neutral\"\n :title=\"t('field.open-site')\"\n :href=\"url\"\n target=\"_blank\"\n rel=\"noopener\"\n />\n <wx-action\n size=\"sm\"\n :icon=\"fullscreen ? 'minimize' : 'maximize'\"\n tone=\"neutral\"\n :title=\"fullscreen ? t('field.close') : t('field.fullscreen')\"\n @click=\"fullscreen = !fullscreen\"\n />\n </div>\n </div>\n <div ref=\"box\" class=\"wx-blocks-preview__ground\">\n <div class=\"wx-blocks-preview__clip\" :style=\"clipStyle\">\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 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 /*\n * `clip` and not `hidden`, because of the sticky bar below: `hidden` makes the box a scroll\n * container — one that never scrolls, since nothing here overflows it — and a sticky child\n * sticks to the nearest one of those. It would have been pinned to a box that does not\n * move, which looks exactly like `position: sticky` having no effect at all. `clip` cuts\n * the corners off the frame just the same and leaves the page as the thing that scrolls.\n */\n overflow: clip;\n min-width: 0;\n}\n\n/*\n * Over the panel, header and all.\n *\n * It used to carry a bare `40`, which is below everything the panel stacks with — so on a\n * phone, where the preview is the whole screen, it opened *under* the sticky header and its\n * own bar went with it: the way out was behind the burger. The overlay layer is what a sheet\n * covering the page belongs to; toasts still land on top of it, which is right, because a\n * toast is the only thing that has something to say while this is open.\n */\n.wx-blocks-preview.is-fullscreen {\n position: fixed;\n inset: 0;\n z-index: var(--wx-z-index-overlay);\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/*\n * The bar stays while the page under it goes by — the width, the way out and the address\n * belong to the whole preview, and a preview that is now as tall as its page would otherwise\n * take all three off the screen with the first scroll.\n *\n * Against the top of the window and not at the offset the tree and the form stick at: sticking\n * moves the bar, not the page under it, so an offset leaves a gap that the page inside goes on\n * showing through — twelve pixels of a headline sliding past above the bar. It needs a\n * background of its own for the same reason, the card's not travelling to a child.\n *\n * Never in full screen. There the card is `position: fixed`, so nothing inside it scrolls with\n * the document at all, and the offset would simply push the bar 12px down from where it\n * already is.\n */\n.wx-blocks-preview:not(.is-fullscreen) .wx-blocks-preview__bar {\n position: sticky;\n top: 0;\n z-index: 1;\n background: var(--wx-bg-surface);\n}\n\n/*\n * Three parts, and the middle one in the middle: the two sides share whatever the widths\n * control leaves, so it sits at the centre of the bar rather than wherever the address\n * happens to end. `flex: 1 1 0` and not `auto` — from zero, so that a long address takes no\n * more room than the buttons opposite it and the control stays put.\n */\n.wx-blocks-preview__label {\n flex: 1 1 0;\n min-width: 0;\n font-family: var(--wx-font-family-mono);\n}\n\n.wx-blocks-preview__widths {\n flex: none;\n}\n\n.wx-blocks-preview__tools {\n display: flex;\n flex: 1 1 0;\n gap: var(--wx-space-4);\n align-items: center;\n justify-content: flex-end;\n}\n\n/*\n * The cap and the scrollbar are what is left for a page that cannot be measured — one from\n * another origin. A page that can be is given the frame its own height, and then this box\n * has nothing to scroll: see `is-grown` below.\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 * No grey either side of the page where the preview is the screen.\n *\n * Twelve pixels at each edge is a frame around a picture on a desktop and a sixteenth of the\n * screen on a phone — and worse than the width it costs is what it does to the eye: the page\n * ends up narrower than the card it is in, which is the same width as the bar and the header,\n * so the one thing the whole screen is about looks like the one thing that is out of line.\n */\n.is-compact .wx-blocks-preview__ground {\n padding-inline: 0;\n}\n\n/*\n * As tall as the page inside, and the panel scrolls.\n *\n * A window of ours over a page that has its own window is two scrollbars for one document,\n * and the inner one is the one nobody can reach with the wheel over the panel: a block taller\n * than the window could not be seen whole at all. Now there is one scroll, the browser's, and\n * the frame ends where the page does.\n *\n * Full screen keeps its own, because there the sheet is fixed to the window and the page\n * behind it does not move: the ground is the only thing left that can scroll.\n */\n.is-grown:not(.is-fullscreen) .wx-blocks-preview__ground {\n overflow: visible;\n max-height: none;\n}\n\n.wx-blocks-preview__clip {\n margin-inline: auto;\n overflow: hidden;\n box-shadow: var(--wx-shadow-sm);\n}\n\n/* The height here is the fallback for a page that cannot be measured — one from another\n origin. Everything else is told its height in pixels by the measurement. */\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</style>\n","<script setup lang=\"ts\">\nimport { useTranslate, WxRowMenu, type RowAction } from '@webx-ui/module-admin'\nimport { 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 but \"Move to\" in its menu:\n * a drag across allow-rules would need a judge at every drop, and a finger in a sheet has none.\n */\nconst props = withDefaults(\n defineProps<{\n nodes: BlockNode[]\n catalog: BlockType[]\n parentKey?: string | null\n field?: string | null\n /** The field this level is, for its allow-list and limit; none at the top. */\n fieldNode?: ScreenNode | null\n /** How many blocks this level takes; a nested level reads it off its slot. */\n max?: number | null\n selected?: string | null\n disabled?: boolean\n depth?: number\n }>(),\n {\n parentKey: null,\n field: null,\n fieldNode: null,\n max: null,\n selected: null,\n disabled: false,\n depth: 0,\n },\n)\n\nconst emit = defineEmits<{\n select: [key: string]\n /** `index` is where the block goes; without it, at the end of the list. */\n add: [parentKey: string | null, field: string | null, node: ScreenNode | null, index?: number]\n remove: [key: string]\n duplicate: [key: string]\n move: [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\n/**\n * What a block offers, as the panel's own `···` rather than a row of icons.\n *\n * Three bare icons on a row that is itself a click target is three chances to hit the wrong\n * one, and the tree is the narrowest column on the screen: at the width a nested block has,\n * the icons took the name's place and the row read as a dash. The menu also has room for the\n * word, which an icon only says to whoever has already learned it (§20).\n */\nfunction actionsFor(node: BlockNode, index: number): RowAction[] {\n const limit = props.fieldNode\n ? ((props.fieldNode.props?.max as number | undefined) ?? null)\n : props.max\n\n return [\n /*\n * The button under the list only appends, so a block meant for the middle of a long page\n * was a trip to the bottom and a drag all the way back up. This one puts it where the\n * editor already is. Not \"add before\": after the row above is the same place.\n */\n {\n key: 'add-after',\n icon: 'plus',\n label: t('field.add-after'),\n disabled: limit !== null && props.nodes.length >= limit,\n run: () => emit('add', props.parentKey, props.field, props.fieldNode, index + 1),\n },\n {\n key: 'visibility',\n icon: node.hidden === true ? 'eye' : 'eye-off',\n label: node.hidden === true ? t('field.show') : t('field.hide'),\n run: () => emit('visibility', node.key, node.hidden !== true),\n },\n {\n key: 'duplicate',\n icon: 'copy',\n label: t('field.duplicate'),\n run: () => emit('duplicate', node.key),\n },\n {\n key: 'move',\n icon: 'arrow-right',\n label: t('field.move'),\n run: () => emit('move', node.key),\n },\n {\n key: 'remove',\n icon: 'trash',\n label: t('field.remove'),\n danger: true,\n run: () => emit('remove', node.key),\n },\n ]\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, index }\">\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__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\">\n <wx-row-menu :actions=\"actionsFor(item, index)\" :label=\"titleOf(item)\" />\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 :field-node=\"slot\"\n :selected=\"selected\"\n :disabled=\"disabled\"\n :depth=\"depth + 1\"\n @select=\"emit('select', $event)\"\n @add=\"(p, f, n, i) => emit('add', p, f, n, i)\"\n @remove=\"emit('remove', $event)\"\n @duplicate=\"emit('duplicate', $event)\"\n @move=\"emit('move', $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__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 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/*\n * There at rest, not on hover. The icons that used to live here appeared under the pointer,\n * which on a phone is nowhere: a tree that can be built with a finger has to be one a finger\n * can also take a block out of. One quiet `···` is affordable in a way three icons were not.\n */\n.wx-blocks-tree__actions {\n display: flex;\n flex: none;\n}\n\n/*\n * Small to look at, big to hit.\n *\n * A collapsed row of actions gives its menu 44 px on a coarse pointer, which is the size of a\n * fingertip and the right size for the target. It is not the right size for the picture: in a\n * row that is a name and one `···`, a 44 px button reads as a third of the row. So the button\n * is drawn at 32 and the missing twelve are given back as an invisible skirt around it — the\n * target stays a fingertip, the row stops looking like a button with a name beside it.\n *\n * The extra `.wx-actions__menu` in the selector is not decoration: the rule it overrides sets\n * the same property on the same element at the same specificity, and without it the winner\n * would be whichever stylesheet the bundler happened to put last.\n */\n@media (pointer: coarse) {\n .wx-blocks-tree__actions :deep(.wx-actions__menu .wx-action) {\n --wx-action-size: 32px;\n position: relative;\n }\n\n .wx-blocks-tree__actions :deep(.wx-actions__menu .wx-action)::after {\n content: '';\n position: absolute;\n inset: -6px;\n }\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","<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 {\n confirm,\n createModal,\n toast,\n useElementWidth,\n WxAction,\n WxButton,\n WxDrawer,\n WxIcon,\n WxText,\n} 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 BlockMoveDialog from './BlockMoveDialog.vue'\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 walk,\n} from './content'\nimport { useBlocksMessages } from './i18n'\nimport { blocksOwnerKey, blocksPreviewKey, blocksRootKey } from './preview'\nimport { destinations, type Destination } from './move'\nimport { formSchema } from './schema'\nimport type { BlockNode, BlockType } from './types'\n\n/**\n * The constructor — the `wx-blocks` field.\n *\n * Two states (§14), and two columns in both of them. The narrow one holds the tree, or the\n * open block's form in its place; the wide one holds the preview of the whole page, at the\n * width the preview's own bar is set to. One column of the two changes, the other does not:\n * the page under the form is the page the form is about, and it neither moves nor shrinks\n * when a block is opened.\n *\n * Inside a block's own form the same node type means a nested constructor, and those are\n * edited in the tree — 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 {\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 },\n)\n\nconst model = defineModel<BlockNode[]>({ default: () => [] })\n\nconst nested = inject(blocksRootKey, false)\n/* Inside the block editor's sample form, the top level is that block rather than a page. */\nconst owner = inject(blocksOwnerKey, null)\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\n/** What a block is called in the catalogue, falling back to the raw type. */\nfunction titleOf(node: BlockNode): string {\n return catalog.value.find((type) => type.slug === node.type)?.title ?? node.type\n}\n\n/**\n * Every block of the page in the order the page draws them, nested ones included — the tree\n * flattened, which is what \"the next block\" means with the tree off the screen.\n */\nconst order = computed(() => {\n const keys: string[] = []\n\n walk(tree.value, (node) => keys.push(node.key))\n\n return keys\n})\n\n/** The block before the open one and the block after it, null at either end. */\nconst steps = computed(() => {\n const at = selectedKey.value ? order.value.indexOf(selectedKey.value) : -1\n\n return {\n previous: at > 0 ? order.value[at - 1]! : null,\n next: at >= 0 && at < order.value.length - 1 ? order.value[at + 1]! : null,\n }\n})\n\n/** The blocks the open one is inside, outermost first. Empty at the top level. */\nconst trail = computed(() => {\n const steps: { key: string; title: string }[] = []\n\n let at = selected.value?.parent ?? null\n\n while (at) {\n steps.unshift({ key: at.key, title: titleOf(at) })\n at = locate(tree.value, at.key)?.parent ?? null\n }\n\n return steps\n})\n\nconst preview = inject(blocksPreviewKey, null)\nconst previewEl = ref<InstanceType<typeof BlocksPreview> | null>(null)\n\nconst host = ref<HTMLElement | null>(null)\nconst hostWidth = useElementWidth(host)\n\n/**\n * The panel has room for the page and one thing beside it, or for the page alone.\n *\n * Measured and not asked of CSS, because what changes is not the arrangement but where the\n * tree and the form are rendered — a column of the grid, or a sheet over the page. The\n * threshold is the narrow column at its widest plus a preview still worth looking at: below\n * it the preview would be drawn at a third of its size, which is a picture, not a page.\n *\n * Only with a preview, and that is not a detail: the way into the sheet is a button on the\n * preview's bar, so without one the sheet would be a room with no door.\n */\nconst hasPreview = computed(() => preview !== null && preview.url.value !== null)\nconst compact = computed(() => hasPreview.value && hostWidth.value > 0 && hostWidth.value <= 900)\n\n/** Open while the blocks are being worked on over the page. Compact panels only. */\nconst sheet = ref(false)\n\n/** What the sheet is showing: the open block with its containers, or the list. */\nconst sheetTitle = computed(() => {\n if (!selected.value) return undefined\n\n const name = selectedType.value?.title ?? selected.value.node.type\n\n return [...trail.value.map((step) => step.title), name].join(' / ')\n})\n\nconst sideProps = computed(() =>\n compact.value\n ? {\n /* Up from the bottom, and not all the way: the strip of page left above it is what\n says the sheet is over the page rather than instead of it. No heading of its own —\n the panels inside carry theirs, and the × is the one thing the sheet has to add. */\n side: 'bottom' as const,\n size: '88%',\n /* Off, or the size above is ignored on exactly the screens this is for: a drawer\n takes a narrow screen whole unless it is told not to. */\n fullScreen: false,\n closable: true,\n closeLabel: t('field.close'),\n ariaLabel: t('field.blocks'),\n /* The open block's name goes in the sheet's own head, where there is a whole line for\n it: in the form's head it shared a row with four controls and wrapped onto two. With\n the blocks it is inside spelled out in front of it, because the trail that says so\n in the column is part of the heading this replaces. The tree keeps its own heading,\n which already says what it is and how many. */\n title: sheetTitle.value,\n open: sheet.value,\n 'onUpdate:open': (value: boolean) => (sheet.value = value),\n }\n : {},\n)\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 index?: number,\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 : (owner?.value ?? 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, index ?? 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 * Always a question, and the question says what is leaving.\n *\n * A single block used to go without one — one row in a tree that is right there, with a draft\n * that kept a version of it. That was wrong twice over: the row says the block's type and not\n * its words, so what vanished was never named, and a page is edited by pointing at things. A\n * container says how much goes with it, because that part is not on screen: collapse a section\n * 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 const agreed = await confirm({\n title: t('field.remove-title', {\n title: catalog.value.find((type) => type.slug === found.node.type)?.title ?? found.node.type,\n }),\n message: inside > 0 ? t('field.remove-text', { count: inside }) : t('field.remove-alone'),\n confirmText: t('field.remove'),\n cancelText: t('page.cancel'),\n tone: 'danger',\n })\n\n if (!agreed) return\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\nconst chooseDestination = createModal<\n Destination,\n { title: string; destinations: Destination[]; topLabel: string }\n>(BlockMoveDialog)\n\n/**\n * Into another container, or out to the top level, at the end of that list.\n *\n * The block goes whole, children and keys included: it is the same block in a new place, not\n * a copy, so the preview's markers and anything pointing at its key still find it.\n */\nasync function move(key: string): Promise<void> {\n const found = locate(tree.value, key)\n if (!found) return\n\n const place = await chooseDestination({\n title: titleOf(found.node),\n destinations: destinations(tree.value, key, catalog.value, {\n owner: owner?.value ?? null,\n allow: props.allow,\n max: props.max,\n }),\n topLabel: owner?.value?.title ?? t('field.move-page'),\n })\n\n if (!place) return\n\n const without = removeNode(tree.value, key)\n set(insertNode(without, place.parentKey, place.field, Number.MAX_SAFE_INTEGER, found.node))\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 /* On a phone the block clicked in the page opens for editing where the editing lives. */\n if (compact.value) sheet.value = true\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 <div v-else ref=\"host\" class=\"wx-blocks-host\" :class=\"{ 'is-compact': compact }\">\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 <!--\n The tree and the form share one column and take turns in it.\n\n They are two views of the same thing — the blocks of this page — and a page has room\n for one of them beside a preview, not two. Side by side the form took whatever the\n preview was not given, and the preview was given the 420 px a desktop does not fit in:\n every block was edited against a picture of a phone. The way back out is the done\n button, or Escape; the way to the next block is in the form's own head.\n\n On a narrow panel that column is a sheet instead, and the same two panels take turns\n inside it — which is why they are wrapped rather than written twice. A phone has room\n for one thing at a time, and the thing worth the room is the page itself.\n -->\n <component :is=\"compact ? WxDrawer : 'div'\" v-bind=\"sideProps\" class=\"wx-blocks__side\">\n <div v-if=\"!selected\" 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 <div class=\"wx-blocks__list\">\n <blocks-tree\n :nodes=\"tree\"\n :catalog=\"catalog\"\n :max=\"max\"\n :selected=\"selectedKey\"\n :disabled=\"disabled\"\n @select=\"select\"\n @add=\"add\"\n @remove=\"remove\"\n @duplicate=\"duplicate\"\n @move=\"move\"\n @visibility=\"visibility\"\n @reorder=\"reorder\"\n />\n </div>\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 <!-- Not in the sheet: the preview is what the sheet is covering. -->\n <wx-button\n v-if=\"!compact && 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 <!-- The blocks this one is inside, because the tree that used to show them is\n not on screen while it is open. Nothing at all at the top level. -->\n <span v-if=\"trail.length\" class=\"wx-blocks__trail\">\n <template v-for=\"step in trail\" :key=\"step.key\">\n <button type=\"button\" class=\"wx-blocks__trail-step\" @click=\"select(step.key)\">\n {{ step.title }}\n </button>\n <wx-icon name=\"chevron-right\" />\n </template>\n </span>\n <span class=\"wx-blocks__panel-name\">{{\n selectedType?.title ?? selected.node.type\n }}</span>\n </span>\n <span class=\"wx-blocks__panel-extra\">\n <!-- Not in the sheet: the identifier is for whoever writes the block type, and\n the phone is where somebody fills one in. It costs a slot in a row of four\n controls, and the name above already says which block this is. -->\n <code v-if=\"!compact\">{{ selected.node.type }}</code>\n <!-- The tree's next row and previous row, kept where the tree is not. Every block\n of the page in the order the page draws them, nested ones included. -->\n <wx-action\n size=\"sm\"\n tone=\"neutral\"\n icon=\"chevron-up\"\n :title=\"t('field.previous')\"\n :disabled=\"steps.previous === null\"\n @click=\"steps.previous && select(steps.previous)\"\n />\n <wx-action\n size=\"sm\"\n tone=\"neutral\"\n icon=\"chevron-down\"\n :title=\"t('field.next')\"\n :disabled=\"steps.next === null\"\n @click=\"steps.next && select(steps.next)\"\n />\n <!-- The same button the tree's foot carries, and hidden by the same rule: below\n the width where the preview folds away, the tree's foot is not on screen\n while a block is open, and that is exactly when it is needed. -->\n <wx-button\n v-if=\"!compact && preview && preview.url.value\"\n size=\"sm\"\n variant=\"outline\"\n icon=\"eye\"\n class=\"wx-blocks__preview-button\"\n :aria-label=\"t('field.preview')\"\n @click=\"previewEl?.open()\"\n />\n <!-- The key is named only where there is one to press: a sheet on a phone is\n left by the button or by the × above it, and \"Esc\" there is a word about\n furniture nobody in the room has. -->\n <wx-button size=\"sm\" variant=\"outline\" @click=\"done\">{{\n compact ? t('field.done') : `${t('field.done')} · Esc`\n }}</wx-button>\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 </component>\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 :reload=\"preview.reload?.value ?? 0\"\n :compact=\"compact\"\n @select=\"selectFromPreview\"\n @edit=\"sheet = true\"\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 * One width for the tree and for the form, because they stand in the same column and taking\n * turns in it is the whole idea: a column that changed size would move the preview and\n * rescale it on every block opened, which is a bigger thing to watch than the room it saves.\n *\n * Twice what the tree used to have. It was 260, which cut the name of every block that was\n * not called something short, and the form that now shares the column needs more than that\n * anyway. The upper bound is what a form of fields reads well at rather than what is left\n * over, and the percentage is what gives a narrow panel back to the preview.\n */\n.wx-blocks {\n display: grid;\n grid-template-columns: clamp(360px, 34%, 520px) minmax(0, 1fr);\n gap: var(--wx-gap, var(--wx-space-16));\n align-items: start;\n}\n\n/* Without a preview there is no second column to leave room for. */\n.wx-blocks:not(.has-preview) {\n grid-template-columns: minmax(0, 1fr);\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 display: flex;\n align-items: center;\n gap: var(--wx-space-4);\n min-width: 0;\n font-weight: var(--wx-font-weight-semibold);\n}\n\n/* One line and an ellipsis: the head is a row of controls with a name in it, and a name that\n wraps pushes the row into two. The whole of it is one hover away, and in the sheet it is\n spelled out along the top anyway. */\n.wx-blocks__panel-name {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* In the sheet the name is the sheet's heading, on a line of its own. */\n.wx-drawer .wx-blocks__fields .wx-blocks__panel-title {\n display: none;\n}\n\n/* The way back up, and quieter than the block it leads to: the name of the open block is\n what the head is for. */\n.wx-blocks__trail {\n display: flex;\n align-items: center;\n gap: var(--wx-space-4);\n min-width: 0;\n color: var(--wx-text-muted);\n font-weight: var(--wx-font-weight-regular);\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-blocks__trail-step {\n padding: 0;\n border: 0;\n background: none;\n color: inherit;\n font: inherit;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.wx-blocks__trail-step:hover {\n color: var(--wx-text-default);\n text-decoration: underline;\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 * The narrow column stands still and scrolls inside itself. The tree is the one that makes\n * this worth doing: a page of twenty blocks is a column taller than the window, and without\n * 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 * The screen's action bar sticks to the same window and is drawn over this column, so the\n * room it announces comes off the cap as well, and the gap above it is the one at the top.\n *\n * What scrolls is the body of the card, not the column around it. The column used to be the\n * scroller, and the card inside it — border, radius and head — scrolled away with the fields:\n * the head with the done button went off the top, and the fields ran square past the corners\n * the card was supposed to have. So the column only caps, the card shrinks to the cap and clips\n * to its own radius, and its head and foot stay while the middle scrolls.\n */\n.wx-blocks-host:not(.is-compact) .wx-blocks__side {\n min-width: 0;\n position: sticky;\n top: var(--wx-space-12);\n max-height: calc(100dvh - var(--wx-space-24) - var(--wx-action-bar-room, 0px));\n display: flex;\n flex-direction: column;\n}\n\n.wx-blocks-host:not(.is-compact) .wx-blocks__tree,\n.wx-blocks-host:not(.is-compact) .wx-blocks__fields {\n min-height: 0;\n overflow: clip;\n}\n\n.wx-blocks__panel-head {\n flex: none;\n}\n\n/* The breathing room keeps the rows' focus rings inside the scroller, which would clip them. */\n.wx-blocks-host:not(.is-compact) .wx-blocks__list,\n.wx-blocks-host:not(.is-compact) .wx-blocks__form {\n min-height: 0;\n overflow: auto;\n overscroll-behavior: contain;\n}\n\n.wx-blocks-host:not(.is-compact) .wx-blocks__list {\n padding: var(--wx-space-2);\n margin: calc(-1 * var(--wx-space-2));\n}\n\n.wx-blocks__preview {\n min-width: 0;\n position: sticky;\n top: var(--wx-space-12);\n}\n\n/*\n * A preview as tall as the page it shows is taller than the window, and a sticky box taller\n * than the window pins its head and puts its foot out of reach — the end of the page could\n * never be scrolled to. It stands still instead, and the tree beside it is the one that\n * follows.\n *\n * Full screen is in here for a different reason: `position: sticky` makes a stacking context\n * whatever its `z-index` says, so the sheet inside — fixed, and over everything by its own\n * number — could only ever be over what is in this column. It opened *under* the action bar,\n * which sits lower in the panel's stack and higher in the document. Nothing looked wrong in\n * the rule that draws it; the column it came out of was the one that had to move.\n */\n.wx-blocks__preview:has(.is-grown),\n.wx-blocks__preview:has(.is-fullscreen) {\n position: static;\n}\n\n/* The foot of the tree: one row, the adding taking whatever the other one leaves. */\n/*\n * One row while they fit, a column the moment they do not.\n *\n * The tree is the narrowest column on the screen and the words on these two buttons are as\n * long as the language makes them: side by side in a 220px column they ran out over its edge\n * rather than wrapping, because a button is a flex item that does not break. Wrapping is the\n * whole fix — each one keeps its own line and the line is the column's width.\n */\n.wx-blocks__tools {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: var(--wx-space-8);\n flex: none;\n}\n\n.wx-blocks__add,\n.wx-blocks__preview-button {\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/*\n * One column: the preview is a button in either state.\n *\n * The threshold above this one is gone with the layout that needed it — there used to be a\n * width at which three columns no longer fitted and the preview folded away while a block\n * was open. There are two columns now, in both states, so there is one width to speak of.\n *\n * And it is not a container query any more: the narrow panel does not rearrange its columns,\n * it renders the tree and the form somewhere else entirely, which only the component can\n * decide. What is left here is the column the page keeps.\n */\n.wx-blocks-host.is-compact .wx-blocks,\n.wx-blocks-host.is-compact .wx-blocks.has-preview {\n grid-template-columns: minmax(0, 1fr);\n}\n\n/*\n * Inside the sheet a panel is not a card — the sheet is the card, and one inside another is\n * two borders and two paddings for one thing. The sheet's own body brings the room.\n */\n.wx-drawer .wx-blocks__tree,\n.wx-drawer .wx-blocks__fields {\n border: 0;\n padding: 0;\n background: none;\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 { callerWords, kindOf, usageWords } from './schema'\nimport type { BlockType } from './types'\n\n/**\n * One type in the list: its picture, its name, where it stands and which versions it has.\n *\n * A component stands on no page — it stands in other blocks — so its line counts those instead,\n * and one a module declared says which module's view it replaced.\n */\nwithDefaults(\n defineProps<{\n block: BlockType\n /** The name of the module that declared this slug, when one did. */\n module?: string | null\n }>(),\n { module: null },\n)\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 <!-- A component is a piece that stands inside a column — a card, a badge — so it is drawn\n at a column's width: at a desktop's it is a speck in the corner of the picture. And it\n is a whole thing rather than a band of a page, so it is shown whole, in a taller box. -->\n <block-thumb\n :thumbnail=\"block.thumbnail\"\n :height=\"kindOf(block) === 'component' ? 180 : 120\"\n :width=\"kindOf(block) === 'component' ? 360 : undefined\"\n :fit=\"kindOf(block) === 'component'\"\n />\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 <template v-if=\"kindOf(block) === 'component'\">\n {{ callerWords(block.used_by?.length ?? 0, t) }}\n <template v-if=\"module\">· {{ t('components.module', { module }) }}</template>\n </template>\n <template v-else>{{ usageWords(block.usage_count, t) }}</template>\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\n v-if=\"!block.is_enabled && kindOf(block) !== 'component'\"\n type=\"default\"\n variant=\"outline\"\n >\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 WxRadio,\n WxRadioGroup,\n WxSelect,\n WxSpace,\n} from '@webx-ui/core'\nimport { createBlocksApi } from './api'\nimport { useBlocksMessages } from './i18n'\nimport { groupLabel } from './schema'\nimport type { BlockKind, BlockType } from './types'\n\n/**\n * A new type needs a few things to exist — what kind it is, a name, an identifier and, for a\n * block, a group — and gets an empty draft to open. Everything else is the editor's job.\n *\n * The kind is asked first and in words, one line under each: \"component\" means nothing to a\n * person who has not read the guide, and the line is the guide in one sentence.\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({\n kind: 'block' as BlockKind,\n title: '',\n slug: '',\n group: groups.value[0] ?? 'content',\n})\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 // A component is never offered in \"Add a block\", so a group would be a choice about nothing.\n const { group, ...rest } = form.value\n\n resolve(await api.create(form.value.kind === 'component' ? rest : { ...rest, group }))\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('components.kind')\" :error=\"errorOf('kind')\">\n <wx-radio-group v-model=\"form.kind\" class=\"wx-block-create__kinds\">\n <wx-radio value=\"block\">\n <span class=\"wx-block-create__kind\">{{ t('components.kind-block') }}</span>\n <span class=\"wx-block-create__kind-help\">{{ t('components.kind-block-help') }}</span>\n </wx-radio>\n <wx-radio value=\"component\">\n <span class=\"wx-block-create__kind\">{{ t('components.kind-component') }}</span>\n <span class=\"wx-block-create__kind-help\">{{\n t('components.kind-component-help')\n }}</span>\n </wx-radio>\n </wx-radio-group>\n </wx-form-item>\n\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\n v-if=\"form.kind === 'block'\"\n :label=\"t('page.group')\"\n :help=\"t('page.group-help')\"\n :error=\"errorOf('group')\"\n >\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\n.wx-block-create__kinds {\n gap: var(--wx-space-10);\n}\n\n/* The circle beside the name, not beside the middle of name and sentence. */\n.wx-block-create__kinds :deep(.wx-radio) {\n align-items: flex-start;\n}\n\n/* The name on its line and the sentence under it, both inside the radio's label. */\n.wx-block-create__kind {\n display: block;\n font-weight: var(--wx-font-weight-medium);\n}\n\n.wx-block-create__kind-help {\n display: block;\n font-size: var(--wx-font-size-sm);\n color: var(--wx-text-muted);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { WxButton, WxIcon, WxText } from '@webx-ui/core'\nimport { useBlocksMessages } from './i18n'\nimport type { DeclaredComponent } from './types'\n\n/**\n * A place a module declared and the site has not customised: the module draws its own view\n * there. It stands among the components rather than in a settings page, because otherwise nobody\n * learns the place can be changed at all (§3.9).\n *\n * No picture: there is no type to draw yet, and the module's view is drawn with data only the\n * module has. The card says whose view it is and offers the one thing to do with it.\n */\nwithDefaults(\n defineProps<{\n declared: DeclaredComponent\n /** The module's name as the panel shows it. */\n module: string\n canManage?: boolean\n busy?: boolean\n }>(),\n { canManage: false, busy: false },\n)\n\nconst emit = defineEmits<{ customise: [declared: DeclaredComponent] }>()\n\nuseBlocksMessages()\nconst t = useTranslate('webx-blocks')\n</script>\n\n<template>\n <div class=\"wx-block-declared\">\n <div class=\"wx-block-declared__mark\" aria-hidden=\"true\">\n <wx-icon name=\"sliders\" />\n </div>\n <div class=\"wx-block-declared__body\">\n <div class=\"wx-block-declared__title\">{{ declared.title }}</div>\n <wx-text size=\"sm\" tone=\"muted\">\n <code>{{ declared.slug }}</code>\n · {{ t('components.standard', { module }) }}\n </wx-text>\n <wx-text v-if=\"declared.description\" size=\"sm\" tone=\"muted\">\n {{ declared.description }}\n </wx-text>\n <wx-text size=\"sm\" tone=\"muted\" class=\"wx-block-declared__help\">\n {{ t('components.standard-help') }}\n </wx-text>\n <div v-if=\"canManage\" class=\"wx-block-declared__actions\">\n <wx-button size=\"sm\" :loading=\"busy\" @click=\"emit('customise', declared)\">\n {{ t('components.customise') }}\n </wx-button>\n </div>\n </div>\n </div>\n</template>\n\n<style scoped>\n/* The same box as a type's card, with a dashed edge: a place, not yet a thing. */\n.wx-block-declared {\n display: flex;\n flex-direction: column;\n min-width: 0;\n overflow: hidden;\n background: var(--wx-bg-surface);\n border: 1px dashed var(--wx-border-strong);\n border-radius: var(--wx-radius-md);\n}\n\n/* Where a type's card has its picture: the same height, so a row of cards stays level. */\n.wx-block-declared__mark {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 120px;\n font-size: 32px;\n color: var(--wx-text-muted);\n background: var(--wx-bg-subtle);\n border-block-end: 1px dashed var(--wx-border-default);\n}\n\n.wx-block-declared__body {\n display: flex;\n flex: 1 1 auto;\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-declared__title {\n font-weight: var(--wx-font-weight-semibold);\n}\n\n.wx-block-declared__actions {\n margin-block-start: auto;\n padding-block-start: var(--wx-space-4);\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, onMounted, ref } from 'vue'\nimport { useRouter } from 'vue-router'\nimport { VueDraggable } from 'vue-draggable-plus'\nimport {\n useAdmin,\n useErrorText,\n useTranslate,\n WxListScreen,\n type ScreenAction,\n} from '@webx-ui/module-admin'\nimport {\n createModal,\n toast,\n WxAlert,\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 BlockDeclaredCard from './BlockDeclaredCard.vue'\nimport { useBlocksMessages } from './i18n'\nimport { groupLabel, kindOf } from './schema'\nimport type { BlocksMeta, BlockType, DeclaredComponent } 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 *\n * Two kinds, two groups (§3.9 of the components spec): the blocks editors put on pages, then\n * the components templates call. The places modules declared and the site has not customised\n * stand among the components — a place nobody sees is a possibility nobody learns about.\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 types = ref<BlockType[]>([])\nconst declared = ref<DeclaredComponent[]>([])\nconst loading = ref(true)\nconst search = ref('')\n/** Which group is being looked at; `''` is all of them, grouped. */\nconst view = ref<TabValue>('')\n/** The slug being customised, while the request is out. */\nconst customising = ref<string | null>(null)\n\n/** The view of the components. Not a word a site could name a group of its own. */\nconst COMPONENTS = '@components'\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 blocks = computed(() => types.value.filter((type) => kindOf(type) === 'block'))\nconst components = computed(() => types.value.filter((type) => kindOf(type) === 'component'))\n\n/** The places still drawn by their module: a customised one is already a card of its own. */\nconst pending = computed(() => declared.value.filter((place) => !place.customised))\n\nconst hasComponents = computed(() => components.value.length > 0 || pending.value.length > 0)\n\n/** A module's name as the navigation says it; its id, capitalised, for one the panel lacks. */\nfunction moduleName(id: string): string {\n return (\n context.state.manifest?.modules.find((module) => module.id === id)?.title ??\n id.charAt(0).toUpperCase() + id.slice(1)\n )\n}\n\n/** Which module declared a slug, by name: the card of a customised place says whose it was. */\nfunction declaredBy(slug: string): string | null {\n const place = declared.value.find((item) => item.slug === slug)\n\n return place ? moduleName(place.module) : null\n}\n\nfunction matches(fields: (string | null)[]): boolean {\n const needle = search.value.trim().toLowerCase()\n\n return needle === '' || fields.some((field) => (field ?? '').toLowerCase().includes(needle))\n}\n\nconst shown = computed(() => {\n if (view.value === COMPONENTS) return []\n\n const inView =\n view.value === '' ? blocks.value : blocks.value.filter((block) => block.group === view.value)\n\n return inView.filter((block) => matches([block.title, block.slug, block.description]))\n})\n\nconst shownComponents = computed(() =>\n view.value === '' || view.value === COMPONENTS\n ? components.value.filter((type) => matches([type.title, type.slug, type.description]))\n : [],\n)\n\nconst shownPending = computed(() =>\n view.value === '' || view.value === COMPONENTS\n ? pending.value.filter((place) => matches([place.title, place.slug, place.description]))\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 — and the components last, as one view:\n * they have no groups, nobody picks them from a list. With a single group and no components\n * there is nothing to choose between, and the strip would be a control that says one thing.\n */\nconst views = computed<TabItem[]>(() => {\n const groupViews = order.value.map((id) => ({ value: id, label: groupLabel(id, t) }))\n const componentView = hasComponents.value\n ? [{ value: COMPONENTS, label: t('components.components') }]\n : []\n\n return groupViews.length + componentView.length < 2\n ? []\n : [{ value: '', label: t('page.all-groups') }, ...groupViews, ...componentView]\n})\n\n/** What the grid draws for the blocks: 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 if (!flat) return sections\n if (shown.value.length === 0) return []\n\n // Flat, but beside the components: the run of blocks still needs the one word that says\n // which of the two kinds it is.\n const both = view.value === '' && shownComponents.value.length + shownPending.value.length > 0\n\n return [{ id: '', label: both ? t('components.blocks') : '', blocks: shown.value }]\n})\n\n/** The components' heading, unless their own tab already names them or they are all there is. */\nconst componentsLabel = computed(() =>\n view.value === COMPONENTS || shown.value.length === 0 ? '' : t('components.components'),\n)\n\nconst nothing = computed(() => types.value.length === 0 && pending.value.length === 0)\n\n/**\n * The cards are dragged into the order editors see them in, here and in the picker. That is\n * `position`, not `sort`, which is the order of the styles on the page.\n *\n * Not while searching — a filtered run of cards cannot be put in order — and not the components,\n * which nobody picks from a list. A finger holds a card for a moment before it lifts, so that\n * the same finger can still scroll the section.\n */\nconst canDrag = computed(\n () => canManage.value && view.value !== COMPONENTS && search.value.trim() === '',\n)\n\n/*\n * The group takes the places it held, in its new order — the rule the server keeps — so the\n * cards are right at once, and a refusal only has to fetch the list again.\n */\nasync function reorder(list: BlockType[]): Promise<void> {\n const ids = list.map((block) => block.id)\n const next = [...list]\n\n types.value = types.value.map((type) => (ids.includes(type.id) ? next.shift()! : type))\n\n try {\n await api.reorder(ids)\n } catch (error) {\n toast.danger(message(error))\n await load()\n }\n}\n\nasync function load(): Promise<void> {\n loading.value = true\n\n try {\n const list = await api.index()\n\n types.value = list.blocks\n declared.value = list.declared\n } catch (error) {\n toast.danger(message(error))\n } finally {\n loading.value = false\n }\n}\n\n/*\n * When a card was last let go of. A real mouse follows the release with a click on the card it\n * started on — the fallback drag moves a copy, the card itself never left — and that click\n * opened the type the editor had only meant to move. Sortable's own guard does not catch it\n * here. A synthetic drag sends no click, which is why only a real hand ever saw this.\n */\nlet droppedAt = 0\n\nfunction dropped(): void {\n droppedAt = Date.now()\n}\n\nfunction open(block: BlockType | { id: number }): void {\n if (Date.now() - droppedAt < 400) return\n\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\n/**\n * The declared place made the site's own: a draft of the module's view, not published — the site\n * keeps drawing the module's view until someone does (§4.2). So the editor opens on the draft\n * and the toast says the site has not changed yet, because that is the question on everyone's\n * mind after pressing a button called \"Customise\".\n */\nasync function customise(place: DeclaredComponent): Promise<void> {\n customising.value = place.slug\n\n try {\n const type = await api.customise(place.slug)\n\n toast.success(t('components.customised'))\n open(type)\n } catch (error) {\n // Already customised elsewhere (another tab, an agent): the answer names the type to open.\n const body = (error as { status?: number; body?: { id?: number } }).body\n\n if ((error as { status?: number }).status === 409 && typeof body?.id === 'number') {\n open({ id: body.id })\n\n return\n }\n\n toast.danger(message(error, t('components.customise-failed')))\n } finally {\n customising.value = null\n }\n}\n\nonMounted(load)\n\n/* What the section offers. Declared, because on a phone the head folds it into the ···. */\nconst actions = computed<ScreenAction[]>(() =>\n canManage.value\n ? [{ key: 'new', label: t('page.new'), icon: 'plus', primary: true, run: () => void add() }]\n : [],\n)\n</script>\n\n<template>\n <wx-list-screen\n v-model:view=\"view\"\n class=\"wx-blocks-page\"\n :title=\"title\"\n :views=\"views\"\n :actions=\"actions\"\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 || !nothing\" 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=\"nothing\"\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 <!-- The fallback rather than the browser's own drag: Firefox does not drag a button. -->\n <vue-draggable\n :model-value=\"group.blocks\"\n class=\"wx-blocks-page__cards\"\n :disabled=\"!canDrag\"\n :animation=\"160\"\n :delay=\"200\"\n :delay-on-touch-only=\"true\"\n :force-fallback=\"true\"\n ghost-class=\"is-ghost\"\n @end=\"dropped\"\n @update:model-value=\"reorder($event as BlockType[])\"\n >\n <block-card v-for=\"block in group.blocks\" :key=\"block.id\" :block=\"block\" @open=\"open\" />\n </vue-draggable>\n </section>\n\n <section\n v-if=\"shownComponents.length > 0 || shownPending.length > 0\"\n class=\"wx-blocks-page__group\"\n >\n <div v-if=\"componentsLabel\" class=\"wx-blocks-page__group-title\">\n {{ componentsLabel }}\n </div>\n <div class=\"wx-blocks-page__cards\">\n <block-card\n v-for=\"type in shownComponents\"\n :key=\"type.id\"\n :block=\"type\"\n :module=\"declaredBy(type.slug)\"\n @open=\"open\"\n />\n <block-declared-card\n v-for=\"place in shownPending\"\n :key=\"place.slug\"\n :declared=\"place\"\n :module=\"moduleName(place.module)\"\n :can-manage=\"canManage\"\n :busy=\"customising === place.slug\"\n @customise=\"customise\"\n />\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/* The place a dragged card will land: its outline, not a second copy of the picture. */\n.wx-blocks-page__cards :deep(.is-ghost) {\n opacity: 0.35;\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 { WxTextarea } from '@webx-ui/core'\nimport BlockDataField from './BlockDataField.vue'\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 wide: true,\n bind: () => ({ blocksPath: path }),\n },\n // The two inputs only a component's schema has (§3.3): a structure passed from code,\n // edited in the sample form as the JSON it is, and a piece of markup the caller puts\n // between the tags, as HTML. Neither is a field an editor fills on a page.\n 'wx-data': { component: BlockDataField, kind: 'field', wide: true },\n 'wx-slot': {\n component: WxTextarea,\n kind: 'field',\n bind: () => ({ rows: 3, placeholder: '<p>…</p>' }),\n },\n },\n }\n}\n"],"names":["blocksMessages","seeded","useBlocksMessages","i18n","useAdmin","props","__props","emit","__emit","t","useTranslate","text","ref","format","error","value","parse","source","onText","next","parsed","failure","watch","same","_openBlock","_createElementBlock","_hoisted_1","_createVNode","_unref","WxCodeEditor","_createBlock","WxText","createBlocksApi","admin","base","data","body","id","input","slug","number","ids","mine","computed","lint","passed","codes","lines","_hoisted_2","WxIcon","_createElementVNode","_Fragment","_createTextVNode","_toDisplayString","_renderList","line","context","api","message","useErrorText","versions","load","state","version","restore","confirm","block","toast","onMounted","WxSkeleton","_hoisted_3","WxDate","WxBadge","WxButton","$event","SELECTED_CLASS","HOVER_CLASS","STYLE_ID","findRange","root","key","walker","start","node","replaceBlock","doc","html","range","parent","template","anchor","done","fragment","inserted","runtime","child","blockElement","highlightBlock","ensureStyle","element","hoverBlock","keyAt","depth","sibling","bindFrame","handlers","hovered","onClick","event","inert","onMove","onLeave","swallow","target","freezeFrame","listeners","name","listener","STAGE_KEY","STAGE_STYLES","fillStage","style","opener","mountScript","script","stageDocument","escapeAttribute","frame","SHELL_PLACE","siteShell","url","findMarker","absolute","head","tag","rel","copy","inner","attributes","attribute","thumbDocument","shell","widths","width","box","boxWidth","useElementWidth","contentHeight","picked","fits","option","pick","scale","srcdoc","generation","loadedScript","measure","view","margin","bottom","binding","observer","release","fill","onLoad","Observer","now","before","onBeforeUnmount","frameStyle","clipStyle","WxSegmented","_cache","isNode","isNodeList","newKey","makeNode","type","values","locate","tree","find","list","field","index","found","walk","visit","countType","count","countInside","typesIn","seen","nestedFields","schema","cloneNode","clone","setHidden","hidden","listAt","parentKey","existing","insertNode","removeNode","updateValues","replaceList","completions","autocompletion","EditorState","GIVEN","BLOCK_MEMBERS","MEDIA_KEYS","ITEM_KEYS","MEDIA_TYPES","LIST_TYPES","COLLECTION_KEYS","COLLECTION_PARTS","SOURCE_ITEMS","templateCompletions","styles","types","schemaOf","called","tagTypes","member","blockMembers","arrayKeys","variable","variables","echo","echoed","openTag","tagAttributes","tagElements","enclosingType","classNames","directive","directives","quote","word","targets","completion","from","to","rest","end","closed","insert","pickedCompletion","inside","odd","present","match","reserved","options","declared","answer","nodes","fields","bound","detail","info","boost","label","snippetCompletion","open","stack","printable","loopVariables","space","closer","escape","tail","keys","keysOf","q","part","origin","own","styleClasses","blocks","stylesCompletions","statement","styled","used","templateClasses","names","prelude","char","parents","selectors","selector","NODE_KEYS","schemaCompletions","at","jsonContext","quoted","applyJson","entry","pos","top","snapshot","string","escaped","i","LAYOUT","lintBlock","content","lints","missing","undeclared","stray","bare","prefix","few","withoutComments","media","lineAt","fieldIds","trimmed","raw","comment","offset","blocksPreviewKey","provideBlocksPreview","preview","provide","useBlocksPreview","inject","blocksRootKey","blocksOwnerKey","formSchema","usageWords","groupLabel","words","kindOf","callerWords","schemaFields","callTag","sample","fallback","variableOf","slots","_match","letter","route","useRoute","router","useRouter","usage","loading","saving","publishing","tab","meta","module","canManage","settings","reactive","schemaText","schemaError","errors","refusal","stage","current","dirty","typeIds","schemas","loadTargets","place","assist","coreTypes","groupOptions","group","sampleModel","collectIds","take","loaded","stored","onSchemaText","timer","pending","redraw","render","ticket","drawn","templateEditor","pill","insertField","editor","save","saved","publish","declaredModule","callers","isComponent","remove","reset","refusalError","withStage","examples","shownUsage","whereWords","hasWhere","deleteBlocked","call","dataInputs","shape","copyCall","errorOf","leaveGuard","kindOptions","actions","WxCard","WxScreenHead","WxRenameButton","WxPopover","_hoisted_4","_component_router_link","_hoisted_5","entity","WxAlert","_normalizeClass","WxTabs","WxTab","_hoisted_6","_hoisted_7","BlockChecks","_hoisted_9","_hoisted_10","_hoisted_11","_hoisted_12","_hoisted_13","_hoisted_14","_hoisted_15","example","_hoisted_16","_hoisted_17","_hoisted_18","WxHelpButton","WxScreenRenderer","_hoisted_19","WxFormItem","WxSelect","WxInput","WxTextarea","WxIconPicker","WxInputNumber","WxTagsInput","WxSwitch","_hoisted_20","BlockHistory","BlockStage","WxActionBar","resolve","dismiss","useModal","WxDialog","WxEmpty","step","shells","loadShell","response","useSiteShell","adminKey","watchEffect","TALL","widthScale","fitted","rect","fit","allows","allow","parentAllows","typeAllows","destinations","catalog","moving","here","trail","container","slot","title","children","max","search","allowedHere","exhausted","shown","needle","sections","order","grouped","o","section","emptyText","allowed","BlockThumb","bar","fullscreen","ready","grown","watcher","pin","page","margins","height","nextTick","bring","watch_","reveal","forget","el","scroller","overflow","room","band","foot","above","tall","delta","replace","refresh","onKey","__expose","WxAction","typeOf","titleOf","fieldsOf","childrenIn","actionsFor","limit","WxSortableList","_withCtx","item","_hoisted_8","WxRowMenu","_component_blocks_tree","p","f","n","model","_useModel","nested","owner","selectedKey","selected","selectedType","steps","previewEl","host","hostWidth","hasPreview","compact","sheet","sheetTitle","sideProps","groups","m","self","getCurrentInstance","translate","can","createModal","BlockPicker","set","add","parentType","structuredSample","duplicate","chooseDestination","BlockMoveDialog","move","without","visibility","reorder","select","selectFromPreview","onValues","typeId","formRoot","_resolveDynamicComponent","WxDrawer","_mergeProps","BlocksTree","BlocksPreview","form","slugTouched","slugify","WxSpace","WxRadioGroup","WxRadio","COMPONENTS","customising","create","BlockCreateDialog","components","hasComponents","moduleName","declaredBy","matches","shownComponents","shownPending","views","groupViews","componentView","b","componentsLabel","nothing","canDrag","droppedAt","dropped","customise","WxListScreen","WxSkeletonItem","VueDraggable","BlockCard","BlockDeclaredCard","path","BlocksPage","BlockEditorPage","BlocksField","BlockDataField"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/messages.ts","../src/i18n.ts","../src/BlockDataField.vue","../src/api.ts","../src/BlockChecks.vue","../src/BlockHistory.vue","../src/frame.ts","../src/BlockStage.vue","../src/content.ts","../src/completions.ts","../src/lint.ts","../src/preview.ts","../src/schema.ts","../src/BlockEditorPage.vue","../src/BlockMoveDialog.vue","../src/shell.ts","../src/BlockThumb.vue","../src/move.ts","../src/BlockPicker.vue","../src/BlocksPreview.vue","../src/BlocksTree.vue","../src/BlocksField.vue","../src/BlockCard.vue","../src/BlockCreateDialog.vue","../src/BlockDeclaredCard.vue","../src/BlocksPage.vue","../src/module.ts"],"sourcesContent":["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 'on-page': 'on one page',\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 'icon-search': 'Search icons',\n 'icon-none': 'No icon of that name',\n 'icon-unknown': 'This name is not in the icon set, so nothing is drawn',\n 'icon-clear': 'Clear the 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: 'Style order',\n 'sort-help':\n \"The order of the styles on the page: a later block's rules win over an earlier one's. Dragging the cards does not change it.\",\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 examples: 'Examples',\n 'example-handler': 'A handler on something inside the block',\n 'example-values': 'A value the editor filled in',\n 'example-provided': 'A library the site provides',\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 is built from them.',\n 'schema-invalid': 'The schema is not valid JSON: :error',\n sample: 'Sample values',\n preview: 'Preview',\n width: 'Width',\n 'width-desktop': 'Desktop',\n 'width-tablet': 'Tablet',\n 'width-phone': 'Phone',\n usage: 'Where it is used',\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 'delete-used-one': 'The block stands on one page 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 'add-after': 'Add after',\n done: 'Done',\n remove: 'Remove',\n 'remove-title': 'Remove \":title\"?',\n 'remove-text': 'The :count blocks inside it go with it.',\n 'remove-alone': 'It leaves this page. The draft keeps what it was.',\n duplicate: 'Duplicate',\n move: 'Move to…',\n 'move-title': 'Move \":title\" to',\n 'move-page': 'The page itself',\n 'move-none': 'There is nowhere else this block may stand.',\n 'move-full': 'full',\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 previous: 'Previous block',\n next: 'Next block',\n\n preview: 'Preview',\n 'open-site': 'Open on the site',\n fullscreen: 'Full screen',\n close: 'Close',\n width: 'Width',\n 'width-desktop': 'Desktop',\n 'width-tablet': 'Tablet',\n 'width-phone': 'Phone',\n },\n components: {\n kind: 'Kind',\n 'kind-block': 'Block',\n 'kind-block-help':\n 'Editors put it on pages: it is offered in \"Add a block\", and its fields are their form.',\n 'kind-component': 'Component',\n 'kind-component-help':\n 'Called from other templates with <x-webx-block>: its fields are what the caller hands it.',\n 'kind-help': 'A block becomes a component only while it stands on no page.',\n blocks: 'Blocks',\n components: 'Components',\n 'not-called': 'not called yet',\n 'in-block': 'in one block',\n 'in-blocks': 'in :count blocks',\n module: 'module :module',\n standard: 'Standard view · module :module',\n 'standard-help':\n 'The module draws its own view here. Customising makes a draft of it to edit; the site keeps the standard view until you publish.',\n customise: 'Customise',\n customised:\n 'A draft of the standard view is ready. The site shows the old one until you publish.',\n 'customise-failed': 'The component cannot be customised.',\n 'tab-inputs': 'Input data',\n 'inputs-help':\n 'What the caller hands the component: any field, wx-data for a structure passed from code, wx-slot for a piece of markup.',\n call: 'How to call it',\n 'call-help': 'From any block template, a module view or the layout of the site.',\n copy: 'Copy',\n copied: 'Copied.',\n 'site-views':\n 'Calls from the views of the site are not seen here. Give them a fallback, or do not delete what code calls.',\n shape: 'What $:name holds',\n 'shape-free': '$:name is any JSON the caller passes.',\n callers: 'Blocks that call it',\n 'called-by': 'block \":title\"',\n 'module-views': 'views of the module :module',\n 'publish-text': 'The version takes effect in every block that calls it: :count.',\n 'publish-declared':\n 'The site switches to this version wherever the module :module prints it, and in every block that calls it: :count.',\n 'delete-called': 'Blocks call it, so it cannot be deleted: :titles.',\n 'delete-declared': 'Reset to standard',\n 'delete-declared-title': 'Reset \":title\" to the standard view?',\n 'delete-declared-text':\n 'The type and every version of it go, and the module draws its own view again.',\n 'data-invalid': 'Not valid JSON: :error',\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","<script setup lang=\"ts\">\nimport { ref, watch } from 'vue'\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { WxCodeEditor, WxText } from '@webx-ui/core'\nimport { useBlocksMessages } from './i18n'\n\n/**\n * `wx-data` in a component's sample form: a structure the caller passes from code, which nobody\n * edits in the panel except to try the component on something else. So it is JSON, as it\n * travels, in the code editor the rest of this screen is written in (§3.3).\n *\n * The text is kept as typed and the value changes only on JSON that parses: half a bracket is\n * what the text looks like on every keystroke on the way to the next valid one, and a sample\n * that became `null` in the middle of typing would redraw the stage empty each time. An empty\n * editor is the one exception: that is `null` on purpose — the call that passes nothing, which\n * a component has to survive, and which publishing checks when the sample says so.\n */\nconst props = withDefaults(\n defineProps<{\n modelValue?: unknown\n disabled?: boolean\n /** The shape's name (`recipes.card`): the help under the template describes it. */\n shape?: string\n }>(),\n { modelValue: undefined, disabled: false, shape: undefined },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: unknown] }>()\n\nuseBlocksMessages()\nconst t = useTranslate('webx-blocks')\n\nconst text = ref(format(props.modelValue))\nconst error = ref<string | null>(null)\n\nfunction format(value: unknown): string {\n return value === null || value === undefined ? '' : JSON.stringify(value, null, 2)\n}\n\n/** What the text stands for: nothing written is `null`, anything else has to parse. */\nfunction parse(source: string): unknown {\n return source.trim() === '' ? null : (JSON.parse(source) as unknown)\n}\n\nfunction onText(next: string): void {\n text.value = next\n\n try {\n const parsed = parse(next)\n\n error.value = null\n emit('update:modelValue', parsed)\n } catch (failure) {\n error.value = t('components.data-invalid', { error: (failure as Error).message })\n }\n}\n\n/* A value from outside (a restored version, a customised sample) replaces the text; the echo of\n what was just typed does not, or the caret would jump to the end on every keystroke. */\nwatch(\n () => props.modelValue,\n (value) => {\n let same = false\n\n try {\n same = JSON.stringify(parse(text.value)) === JSON.stringify(value ?? null)\n } catch {\n same = false\n }\n\n if (!same) {\n text.value = format(value)\n error.value = null\n }\n },\n { deep: true },\n)\n</script>\n\n<template>\n <div class=\"wx-block-data\">\n <wx-code-editor\n :model-value=\"text\"\n language=\"json\"\n :lint=\"text.trim() !== ''\"\n :readonly=\"disabled\"\n min-height=\"120px\"\n max-height=\"320px\"\n @update:model-value=\"onText\"\n />\n <wx-text v-if=\"error\" size=\"sm\" tone=\"danger\">{{ error }}</wx-text>\n </div>\n</template>\n\n<style scoped>\n.wx-block-data {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-4);\n min-width: 0;\n}\n</style>\n","import type { AdminContext } from '@webx-ui/module-admin'\nimport type {\n BlockInput,\n BlockList,\n BlockType,\n BlockUsage,\n BlockVersion,\n BlockVersionMeta,\n DeclaredComponent,\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 same list with the places modules declared for components beside it. */\n index(): Promise<BlockList>\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 /** A declared place made into the site's own type: an unpublished draft of the module's view. */\n customise(slug: string): Promise<BlockType>\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 /** The new order of some types — a group — in the places they held; the rest stay put. */\n reorder(ids: number[]): Promise<void>\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 // `declared` stands beside `data` rather than in it: it is not a type, and a list of types\n // with something else mixed in is a list every other reader would have to filter.\n index: () =>\n admin.http\n .get<{ data: BlockType[]; declared?: DeclaredComponent[] }>(base)\n .then((body) => ({ blocks: body.data, declared: body.declared ?? [] })),\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 customise: (slug) =>\n admin.http\n .post<{\n data: BlockType\n }>(`${base}/components/${encodeURIComponent(slug)}/customise`, {})\n .then(data),\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 reorder: (ids) => admin.http.post<unknown>(`${base}/reorder`, { ids }).then(() => undefined),\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 * A click inside a block is taken at the document, in the capture phase, and goes no further:\n * stopped there it never reaches a link, a form or the block's own script. What it does\n * instead is choose the block it landed in, which is the one thing the editor wants from it.\n *\n * A click on the site around the blocks goes on to the site, only never anywhere else (see\n * `inert`): the layout may open a newsletter popup or a cookie bar over the page, and one whose\n * close button never hears its click covers the preview for good.\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 onClick(event: MouseEvent): void {\n const key = keyAt(event.target as Node | null)\n\n if (key === null) inert(event)\n else swallow(event)\n\n handlers.select(key)\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', inert, 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', inert, 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\nfunction swallow(event: Event): void {\n event.preventDefault()\n event.stopPropagation()\n}\n\n/**\n * A click that may reach the page's own handlers but not leave it: a link loses its default\n * and nothing else changes. Not `stopPropagation` — that is what kept the close button of the\n * site's popup deaf, and the popup over the stage for good.\n */\nfunction inert(event: Event): void {\n const target = event.target as Node | null\n // By node type, not `instanceof`: the frame's document has an `Element` of its own.\n const element =\n target?.nodeType === Node.ELEMENT_NODE ? (target as Element) : (target?.parentElement ?? null)\n\n if (element?.closest('a[href], area[href]')) event.preventDefault()\n}\n\n/**\n * The same picture without the choosing: nothing in the page navigates, submits or is dragged\n * away. What the block editor's stage needs — the site's header is full of links, and one\n * click on them would leave the frame on another page of the site with the block gone.\n *\n * Clicks themselves still reach the page (see `inert`): the block's own script runs as it will\n * on the site, and the site's popups close.\n */\nexport function freezeFrame(doc: Document): FrameBinding {\n const listeners: [string, (event: Event) => void][] = [\n ['click', inert],\n ['auxclick', inert],\n ['submit', swallow],\n ['dragstart', swallow],\n ]\n\n for (const [name, listener] of listeners) doc.addEventListener(name, listener, true)\n\n return {\n release() {\n for (const [name, listener] of listeners) doc.removeEventListener(name, listener, true)\n },\n }\n}\n\n/** The key the stage draws its block under — `StageController::KEY` on the server. */\nexport const STAGE_KEY = 'sample'\n\n/** The `<style>` of the stage the block's styles go into — `StageController::STYLES`. */\nexport const STAGE_STYLES = 'wx-stage-styles'\n\n/**\n * Put a block on the stage page: its styles into the stage's `<style>`, its markup between the\n * markers. False when the page has no place for it — a layout that dropped its slot.\n *\n * The script is not here on purpose: a script registered in a page cannot be taken back, so\n * a new one means a new page (see `mountScript`).\n */\nexport function fillStage(doc: Document, input: { html: string; styles: string }): boolean {\n let style = doc.getElementById(STAGE_STYLES)\n\n if (style === null) {\n style = doc.createElement('style')\n style.id = STAGE_STYLES\n ;(doc.head ?? doc.documentElement).appendChild(style)\n }\n\n style.textContent = input.styles\n\n /* The render carries its own pair; one that does not would leave the page without a place,\n and the next change would have nowhere to go. */\n const opener = `<!--wx:${STAGE_KEY}-->`\n const html = input.html.trimStart().startsWith(opener)\n ? input.html\n : `${opener}${input.html}<!--/wx:${STAGE_KEY}-->`\n\n return replaceBlock(doc, STAGE_KEY, html)\n}\n\n/**\n * Run a block's script in the page: `webx.block()` registers it and mounts what is already\n * there. Added as an element, since that is what makes a browser run it.\n */\nexport function mountScript(doc: Document, script: string): void {\n const element = doc.createElement('script')\n element.textContent = script\n doc.body.appendChild(element)\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\n/** Where a thumbnail's block goes in a {@link siteShell}. */\nexport const SHELL_PLACE = '<!--wx-thumb-->'\n\n/**\n * The stage page with the page taken out: what a thumbnail needs of the site to look like it.\n *\n * Kept from the head: the stylesheets, the `<style>` elements and the font preloads — the\n * look. Kept from the body: only the chain of elements the block's place sits in, each one\n * empty but for the next, so a rule like `.site-main > section` still finds its parent. The\n * header, the footer, the popups and every script are left behind: a card in a list is a\n * picture, and a site's script in forty of them is forty newsletter popups.\n *\n * Null when the page has no place for a block — then there is nothing to put the block in.\n */\nexport function siteShell(html: string, url: string): string | null {\n const doc = new DOMParser().parseFromString(html, 'text/html')\n const opener = findMarker(doc, `wx:${STAGE_KEY}`)\n\n if (opener === null) return null\n\n const absolute = (value: string | null): string | null =>\n value === null ? null : new URL(value, new URL(url, location.href)).href\n\n const head: string[] = []\n\n for (const element of Array.from(doc.head.children)) {\n const tag = element.tagName.toLowerCase()\n const rel = (element.getAttribute('rel') ?? '').toLowerCase().split(/\\s+/)\n\n if (tag === 'style' && element.id !== STAGE_STYLES) {\n head.push(element.outerHTML)\n } else if (\n tag === 'link' &&\n (rel.includes('stylesheet') ||\n (rel.includes('preload') && element.getAttribute('as') === 'font'))\n ) {\n const copy = element.cloneNode(false) as Element\n copy.setAttribute('href', absolute(element.getAttribute('href')) ?? '')\n head.push(copy.outerHTML)\n }\n }\n\n let inner = SHELL_PLACE\n let parent = opener.parentElement\n\n while (parent !== null && parent !== doc.body && parent !== doc.documentElement) {\n const copy = parent.cloneNode(false) as Element\n copy.innerHTML = inner\n inner = copy.outerHTML\n parent = parent.parentElement\n }\n\n const attributes = (element: Element): string =>\n Array.from(element.attributes)\n .map((attribute) => ` ${attribute.name}=\"${escapeAttribute(attribute.value)}\"`)\n .join('')\n\n return (\n `<!doctype html><html${attributes(doc.documentElement)}><head><meta charset=\"utf-8\">` +\n `<meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">${head.join('')}</head>` +\n `<body${attributes(doc.body)}>${inner}</body></html>`\n )\n}\n\n/** A thumbnail's document: the block in the site's shell, its own styles last. */\nexport function thumbDocument(shell: string, input: { html: string; styles: string }): string {\n return shell\n .replace('</head>', () => `<style>${input.styles}</style></head>`)\n .replace(SHELL_PLACE, () => input.html)\n}\n\nfunction findMarker(doc: Document, text: string): Comment | null {\n const walker = doc.createTreeWalker(doc.body ?? doc.documentElement, NodeFilter.SHOW_COMMENT)\n\n for (let node = walker.nextNode(); node !== null; node = walker.nextNode()) {\n if ((node as Comment).data.trim() === text) return node as Comment\n }\n\n return null\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, onBeforeUnmount, ref, watch } from 'vue'\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { useElementWidth, WxSegmented, WxSkeleton } from '@webx-ui/core'\nimport { fillStage, freezeFrame, mountScript, stageDocument, type FrameBinding } from './frame'\n\n/**\n * The block as it will stand on the site, at a chosen width: a desktop scaled down to fit the\n * column, a tablet or a phone at one to one.\n *\n * With `stage` the frame is a page of the site — its layout, header, footer and styles, with\n * an empty place for the block — loaded once; every change after that swaps the block and its\n * styles in place, so the site around it does not redraw under the editor's typing. Without\n * it (a server older than the stage) the frame is the block on a bare document, as before.\n */\nconst props = withDefaults(\n defineProps<{\n html: string\n styles: string\n script?: string | null\n runtime?: string | null\n /** The address of the stage page; null draws the block on a bare document. */\n stage?: string | null\n loading?: boolean\n }>(),\n { script: null, runtime: null, stage: null, loading: false },\n)\n\nconst t = useTranslate('webx-blocks')\n\n/* Pictures on screen and words as the accessible name, the same way the page preview does it:\n a device is one of the few things a picture says faster than a word. */\nconst widths = computed(() => [\n { value: 1280, icon: 'monitor', ariaLabel: t('page.width-desktop') },\n { value: 834, icon: 'tablet', ariaLabel: t('page.width-tablet') },\n { value: 390, icon: 'smartphone', ariaLabel: 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\n/**\n * Which width the stage opens at: the widest one the column can draw at half size or better.\n *\n * A desktop is the right answer on a desktop and the wrong one on a phone, where 1280 in a\n * 340px column is a picture of a page rather than a page — the words in it are two pixels\n * tall. Until the editor picks a width the stage keeps choosing, so a column that grows or a\n * phone that turns gets the picture it can show; from the first click the choice is theirs.\n */\nconst picked = ref(false)\n\nwatch([boxWidth, widths], () => {\n if (picked.value || boxWidth.value === 0) return\n\n /* Under about half size the words in a block stop being words, so a narrower device is a\n better picture of the block than a desktop nobody can read. */\n const fits = widths.value.find((option) => boxWidth.value / option.value >= 0.45)\n\n width.value = (fits ?? widths.value[widths.value.length - 1]).value\n})\n\nfunction pick(value: number): void {\n picked.value = true\n width.value = value\n}\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 props.stage\n ? undefined\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/**\n * A new page for every new script, and only then: a script registered in a page cannot be\n * unregistered, so the old one would keep running beside the new one. Everything else is\n * swapped into the page that is already there.\n */\nconst generation = ref(0)\nlet loadedScript: string | null = null\n\nwatch(\n () => props.script,\n (script) => {\n if (props.stage && script !== loadedScript) generation.value += 1\n },\n)\n\n/**\n * The frame is as tall as the page in it: a stage that scrolls inside itself hides half of it.\n *\n * Measured on the body, never on `documentElement` — that one is never shorter than the\n * frame's own window, so once the frame has been given a height it measures itself and a\n * block that got shorter keeps the height of the one before it, with white under it.\n */\nfunction measure(): void {\n const body = frame.value?.contentDocument?.body\n\n if (!body) return\n\n /* Where the body ends, margin included, and rounded up: a site's layout is fractional and\n may keep a margin on `body`, and a height a pixel short of either gives the frame a\n scrollbar of its own. */\n const view = body.ownerDocument.defaultView\n const margin = view ? parseFloat(view.getComputedStyle(body).marginBottom) || 0 : 0\n const bottom = body.getBoundingClientRect().bottom + margin + (view?.scrollY ?? 0)\n\n contentHeight.value = Math.max(120, Math.ceil(Math.max(body.scrollHeight, bottom)))\n}\n\nlet binding: FrameBinding | null = null\nlet observer: ResizeObserver | null = null\n\nfunction release(): void {\n binding?.release()\n binding = null\n observer?.disconnect()\n observer = null\n}\n\n/** Put the current block on the page — its script once per page, the rest every time. */\nfunction fill(doc: Document): void {\n if (!props.stage) return\n\n if (props.script && loadedScript !== props.script) {\n loadedScript = props.script\n mountScript(doc, props.script)\n }\n\n fillStage(doc, { html: props.html, styles: props.styles })\n}\n\nfunction onLoad(): void {\n release()\n\n const doc = frame.value?.contentDocument\n\n if (!doc?.body) return\n\n if (props.stage) {\n loadedScript = null\n binding = freezeFrame(doc)\n fill(doc)\n }\n\n measure()\n\n /* The observer of the frame's own window: one made out here does not see into another\n document. It follows fonts, images and a block that grows as its script runs. */\n const Observer = (doc.defaultView as (Window & typeof globalThis) | null)?.ResizeObserver\n\n if (Observer) {\n observer = new Observer(() => measure())\n observer.observe(doc.body)\n }\n}\n\nwatch(\n () => [props.html, props.styles] as const,\n () => {\n const doc = frame.value?.contentDocument\n\n if (props.stage && doc?.body && binding !== null) fill(doc)\n },\n)\n\n/* A stage that lives in a tab is measured while that tab is hidden, and a hidden document\n has no height: every redraw made behind another tab would leave the frame at its floor.\n The width coming back is the tab coming back. */\nwatch(boxWidth, (now, before) => {\n if (now > 0 && before === 0) setTimeout(measure, 50)\n})\n\nwatch(width, () => setTimeout(measure, 50))\n\nonBeforeUnmount(release)\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\n :model-value=\"width\"\n :options=\"widths\"\n size=\"sm\"\n :aria-label=\"t('page.width')\"\n @update:model-value=\"pick(Number($event))\"\n />\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 :key=\"generation\"\n class=\"wx-block-stage__frame\"\n :src=\"stage ?? undefined\"\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/*\n * As tall as the page inside, and the panel scrolls — the rule the page preview has (`is-grown`\n * in BlocksPreview). A window of ours over a page is two scrollbars for one document, and the\n * inner one cut the site's footer off under a cap nobody could see past.\n */\n.wx-block-stage__ground {\n padding: var(--wx-space-12);\n background: var(--wx-bg-subtle);\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 {\n autocompletion,\n pickedCompletion,\n snippetCompletion,\n startCompletion,\n type Completion,\n type CompletionContext,\n type CompletionResult,\n type CompletionSource,\n} from '@codemirror/autocomplete'\nimport { EditorState, type Extension } from '@codemirror/state'\nimport type { EditorView } from '@codemirror/view'\nimport type { ScreenNode, TypeRegistry } from '@webx-ui/schema'\n\n/**\n * What the editor of a block type offers as you type, one source per file. Each reads the\n * other files of the same type — the template's fields come from the schema, its classes from\n * the styles, the styles' classes from the template — so the sources take getters, not\n * values: the editor is built once and the files change under it.\n *\n * Registered as language data rather than as an `override`, so that what the language\n * already offers (CSS properties, HTML tags) stays in the list beside ours.\n */\nexport function completions(source: CompletionSource): Extension {\n return [\n autocompletion({ icons: false }),\n EditorState.languageData.of(() => [{ autocomplete: source }]),\n ]\n}\n\n/* ---------------------------------------------------------------------------------------- */\n/* Template */\n/* ---------------------------------------------------------------------------------------- */\n\nexport interface TemplateSources {\n schema: () => ScreenNode[]\n styles: () => string\n /** The types a tag can call, components among them: what `type=\"` offers. */\n types?: () => TagTarget[]\n /**\n * The schema of a type, for the attributes and slots of a tag that calls it. May answer later:\n * the list of types comes without content, and the one schema is asked for when it is needed.\n */\n schemaOf?: (slug: string) => ScreenNode[] | null | Promise<ScreenNode[] | null>\n}\n\n/** A type as a tag names it. */\nexport interface TagTarget {\n slug: string\n title: string\n kind: 'block' | 'component'\n /** The module's view, for a declared place: the tag that calls it should carry it. */\n fallback?: string | null\n}\n\n/** What the renderer hands a template besides its fields (see `lint.ts`, `GIVEN`). */\nconst GIVEN: [string, string][] = [\n ['block', 'key, type, version, depth, value()'],\n ['entity', 'the page or article the block stands on'],\n]\n\nconst BLOCK_MEMBERS = ['key', 'type', 'version', 'depth']\n\n/** The keys of a picked file: `wx-media` holds them, the renderer adds `url`. */\nconst MEDIA_KEYS = ['url', 'alt', 'title', 'path']\n\n/** One item of `wx-gallery` or `wx-files`: a file plus what a list of them is printed with. */\nconst ITEM_KEYS = [...MEDIA_KEYS, 'thumb', 'name', 'extension', 'mime', 'size', 'width', 'height']\n\nconst MEDIA_TYPES = ['wx-media']\nconst LIST_TYPES = ['wx-gallery', 'wx-files']\n\n/**\n * `wx-collection`, as the renderer hands it over: the records and the filter's groups. What else\n * a record holds is its source's business (`question`, `answer` for the FAQ); every source gives\n * these three.\n */\nconst COLLECTION_KEYS = ['items', 'groups', 'filter']\nconst COLLECTION_PARTS: Record<string, string[]> = {\n items: ['id', 'anchor', 'categories'],\n groups: ['id', 'title', 'items'],\n}\n\n/**\n * What a record of the sources the modules of this repository bring holds beyond the three every\n * source gives — the card each one's `Cards` builds. A source a site registers itself offers the\n * three only.\n */\nconst SOURCE_ITEMS: Record<string, string[]> = {\n faq: ['question', 'answer'],\n services: ['title', 'url', 'lead', 'cover', 'fields'],\n reviews: [\n 'name',\n 'initials',\n 'job_title',\n 'text',\n 'rating',\n 'date',\n 'profile',\n 'photo',\n 'fields',\n ],\n recipes: [\n 'title',\n 'url',\n 'lead',\n 'cover',\n 'gallery',\n 'minutes',\n 'servings',\n 'category_links',\n 'service_links',\n 'nutrients',\n 'fields',\n ],\n team: ['name', 'initials', 'job_title', 'text', 'photo', 'socials', 'service_links', 'fields'],\n}\n\n/**\n * Helpers a template calls by name rather than through a field — what the value they answer\n * holds. Banners have no source for `wx-collection` (decision 7 of their spec): the helper is the\n * only way a template gets them, so it is the one written out here. `banners()` gives the cards\n * of a place, `banners_layout()` the merged options its template draws them with.\n */\nconst HELPER_KEYS: Record<string, string[]> = {\n banners: [\n 'id',\n 'anchor',\n 'place',\n 'title',\n 'text',\n 'image',\n 'image_mobile',\n 'video',\n 'buttons',\n 'fields',\n ],\n banners_layout: [\n 'layout',\n 'interval',\n 'autoplay',\n 'loop',\n 'arrows',\n 'dots',\n 'pause_on_hover',\n 'ratio',\n 'ratio_mobile',\n 'breakpoint',\n 'video_on_mobile',\n ],\n}\n\n/** What a helper's value is named by among the loop variables — no field can be called this. */\nconst HELPER = 'helper:'\n\n/** The parts of a helper's value that are lists in turn: `$banner['buttons']`. */\nconst HELPER_PARTS: Record<string, Record<string, string[]>> = {\n banners: { buttons: ['label', 'url', 'new_tab', 'rel', 'variant'] },\n}\n\n/** The helpers as `@` offers them: the call and the loop around it, the place for the caret. */\nconst HELPER_SNIPPETS: [string, string, string][] = [\n [\n '@foreach banners',\n \"@foreach (banners('${place}')->get() as $banner)\\n\\t${}\\n@endforeach\",\n 'the banners of a place',\n ],\n ['@php banners_layout', \"@php($layout = banners_layout('${place}'))\", 'its layout and options'],\n]\n\nexport function templateCompletions({\n schema,\n styles,\n types = () => [],\n schemaOf = () => null,\n}: TemplateSources): CompletionSource {\n return (context) => {\n const before = context.state.sliceDoc(Math.max(0, context.pos - 200), context.pos)\n\n // The value of `type` first: inside its quotes nothing else applies.\n const called = /<x-webx-block\\b[^<>]*?\\btype\\s*=\\s*([\"'])([\\w-]*)$/.exec(before)\n if (called) return tagTypes(context, called[1]!, called[2]!, types())\n\n const member = /\\$block->(\\w*)$/.exec(before)\n if (member) return blockMembers(context, member[1]!)\n\n const key = /\\$(\\w+)\\[\\s*(['\"]?)(\\w*)$/.exec(before)\n if (key) return arrayKeys(context, key[1]!, key[2]!, key[3]!, schema())\n\n const variable = /\\$(\\w*)$/.exec(before)\n if (variable) {\n return {\n from: context.pos - variable[0].length,\n options: variables(schema(), context.state.doc.toString()),\n validFor: /^\\$\\w*$/,\n }\n }\n\n // Straight after `{{` there is nothing else a template writes, so the fields open there\n // without waiting for the `$` (the one exception, a call like `{{ now() }}`, just types on).\n const echo = /(\\{\\{|\\{!!)(\\s*)(\\w*)$/.exec(before)\n if (echo) return echoed(context, echo[1]!, echo[2]!, echo[3]!, schema())\n\n const tag = openTag(before)\n if (tag !== null) return tagAttributes(context, tag, types(), schemaOf)\n\n const element = /<(x-[\\w:-]*)$/.exec(before)\n if (element) {\n const text = context.state.sliceDoc(0, context.pos - element[0].length)\n\n return tagElements(context, element[1]!, enclosingType(text), schemaOf)\n }\n\n const attribute = /\\bclass\\s*=\\s*\"([^\"]*)$/.exec(before)\n if (attribute) return classNames(context, attribute[1]!, styles())\n\n const directive = /(?:^|[\\s>(])@(\\w*)$/.exec(before)\n if (directive) {\n return {\n from: context.pos - directive[1]!.length - 1,\n options: directives(schema()),\n validFor: /^@\\w*$/,\n }\n }\n\n return null\n }\n}\n\n/* ---------------------------------------------------------------------------------------- */\n/* <x-webx-block> */\n/* ---------------------------------------------------------------------------------------- */\n\n/**\n * `type=\"` of the tag: every type there is, the components first — calling one is what the tag\n * is for, calling a block (a CTA with its values written in) is the rarer case (§2, decision 2).\n */\nfunction tagTypes(\n context: CompletionContext,\n quote: string,\n word: string,\n targets: TagTarget[],\n): CompletionResult | null {\n if (targets.length === 0) return null\n\n return {\n from: context.pos - word.length,\n options: targets.map((target, index) => ({\n label: target.slug,\n detail: target.kind,\n info: target.title,\n type: 'type',\n boost: (target.kind === 'component' ? 50 : 0) - index / 100,\n apply: (view, completion, from, to) => {\n const rest = /^[\\w-]*/.exec(view.state.sliceDoc(to, to + 64))![0]\n const end = to + rest.length\n const closed = view.state.sliceDoc(end, end + 1) === quote\n const insert = `${target.slug}${closed ? '' : quote}`\n\n view.dispatch({\n changes: { from, to: end, insert },\n // Past the closing quote: the attributes come next.\n selection: { anchor: from + insert.length + (closed ? 1 : 0) },\n annotations: pickedCompletion.of(completion),\n userEvent: 'input.complete',\n })\n },\n })),\n validFor: /^[\\w-]*$/,\n }\n}\n\ninterface OpenTag {\n /** The attributes written so far. */\n attributes: string\n /** The type, once it is written among them. */\n type: string | null\n /** `:` typed before the name. */\n bound: boolean\n word: string\n}\n\n/** The caret stands between the attributes of an `<x-webx-block` that is still open. */\nexport function openTag(before: string): OpenTag | null {\n const start = before.lastIndexOf('<x-webx-block')\n if (start === -1) return null\n\n const inside = before.slice(start + '<x-webx-block'.length)\n if (inside.includes('>') || !/^\\s/.test(inside)) return null\n\n // An odd number of quotes: the caret is inside a value, and names do not go there.\n const odd = (quote: string): boolean => (inside.split(quote).length - 1) % 2 === 1\n if (odd('\"') || odd(\"'\")) return null\n\n const name = /\\s(:?)([\\w-]*)$/.exec(inside)\n if (!name) return null\n\n const type = /\\btype\\s*=\\s*[\"']([\\w-]+)[\"']/.exec(inside)\n\n return { attributes: inside, type: type?.[1] ?? null, bound: name[1] === ':', word: name[2]! }\n}\n\n/** Attribute names: the type's inputs by its schema, `:` for a structure, then the reserved two. */\nfunction tagAttributes(\n context: CompletionContext,\n tag: OpenTag,\n targets: TagTarget[],\n schemaOf: NonNullable<TemplateSources['schemaOf']>,\n): CompletionResult | null | Promise<CompletionResult | null> {\n const present = new Set([...tag.attributes.matchAll(/:?([\\w-]+)\\s*=/g)].map((match) => match[1]!))\n const from = context.pos - tag.word.length - (tag.bound ? 1 : 0)\n\n const reserved = (): Completion[] => {\n const options: Completion[] = []\n\n if (!present.has('type')) options.push(attribute('type', false, 'reserved', null, 60))\n\n if (!present.has('fallback') && tag.type !== null) {\n const declared = targets.find((target) => target.slug === tag.type)?.fallback ?? null\n\n options.push(attribute('fallback', false, 'reserved', declared, -10, declared))\n }\n\n return options\n }\n\n const answer = (nodes: ScreenNode[] | null): CompletionResult | null => {\n const inputs = fields(nodes ?? [])\n .filter((node) => node.type !== 'wx-slot' && node.type !== 'wx-blocks')\n .filter((node) => !present.has(node.id))\n .map((node, index) =>\n attribute(node.id, node.type === 'wx-data' || tag.bound, node.type, node.label, 40 - index),\n )\n const options = [...inputs, ...reserved()]\n\n // A space after the tag's name is not yet a request: the list opens on a letter or a colon.\n if (options.length === 0 || (!context.explicit && tag.word === '' && !tag.bound)) return null\n\n return { from, options, validFor: /^:?[\\w-]*$/ }\n }\n\n if (tag.type === null) return answer(null)\n\n const nodes = schemaOf(tag.type)\n\n return nodes instanceof Promise ? nodes.then(answer, () => answer(null)) : answer(nodes)\n}\n\n/** `name=\"\"` or `:name=\"$\"`, with the caret before the closing quote. */\nfunction attribute(\n name: string,\n bound: boolean,\n detail: string,\n info: string | null | undefined,\n boost: number,\n value: string | null = null,\n): Completion {\n const label = `${bound ? ':' : ''}${name}`\n\n return {\n label,\n detail,\n info: info ?? undefined,\n type: 'property',\n boost,\n apply: (view, completion, from, to) => {\n const insert = `${label}=\"${value ?? (bound ? '$' : '')}\"`\n\n view.dispatch({\n changes: { from, to, insert },\n selection: { anchor: from + insert.length - 1 },\n annotations: pickedCompletion.of(completion),\n userEvent: 'input.complete',\n })\n },\n }\n}\n\n/**\n * After `<x-`: the tag itself, and inside a tag's body the named slots its type declares, each\n * written open and closed with the caret between.\n */\nfunction tagElements(\n context: CompletionContext,\n word: string,\n type: string | null,\n schemaOf: NonNullable<TemplateSources['schemaOf']>,\n): CompletionResult | Promise<CompletionResult> {\n const from = context.pos - word.length\n\n const answer = (nodes: ScreenNode[] | null): CompletionResult => {\n const options: Completion[] = [\n snippetCompletion('x-webx-block type=\"${type}\" />', {\n label: 'x-webx-block',\n detail: 'call a block',\n type: 'keyword',\n }),\n ]\n\n for (const node of fields(nodes ?? []).filter((field) => field.type === 'wx-slot')) {\n options.push({\n label: `x-slot:${node.id}`,\n detail: 'slot',\n info: node.label,\n type: 'keyword',\n boost: 20,\n apply: (view, completion, start, end) => {\n const open = `x-slot:${node.id}>`\n\n view.dispatch({\n changes: { from: start, to: end, insert: `${open}</x-slot:${node.id}>` },\n selection: { anchor: start + open.length },\n annotations: pickedCompletion.of(completion),\n userEvent: 'input.complete',\n })\n },\n })\n }\n\n return { from, options, validFor: /^x-[\\w:-]*$/ }\n }\n\n if (type === null) return answer(null)\n\n const nodes = schemaOf(type)\n\n return nodes instanceof Promise ? nodes.then(answer, () => answer(null)) : answer(nodes)\n}\n\n/** The type of the `<x-webx-block>` whose body the end of the text stands in, if any. */\nexport function enclosingType(text: string): string | null {\n const stack: (string | null)[] = []\n\n for (const match of text.matchAll(\n /<x-webx-block\\b((?:[^>\"']|\"[^\"]*\"|'[^']*')*?)(\\/?)>|<\\/x-webx-block\\s*>/g,\n )) {\n if (match[0].startsWith('</')) stack.pop()\n else if (match[2] !== '/') {\n stack.push(/\\btype\\s*=\\s*[\"']([\\w-]+)[\"']/.exec(match[1] ?? '')?.[1] ?? null)\n }\n }\n\n return stack.at(-1) ?? null\n}\n\n/** Every field a template may print: the schema's, in its order, then what is always there. */\nfunction variables(schema: ScreenNode[], template: string): Completion[] {\n const options: Completion[] = printable(schema).map((node, index) => ({\n label: `$${node.id}`,\n detail: node.type,\n info: node.label,\n type: 'variable',\n boost: 50 - index,\n }))\n\n for (const name of loopVariables(template).keys()) {\n options.push({ label: `$${name}`, detail: 'loop', type: 'variable' })\n }\n\n for (const [name, info] of GIVEN) {\n options.push({ label: `$${name}`, detail: 'given', info, type: 'variable', boost: -10 })\n }\n\n // Any type can be called with the tag, and the tag's body arrives as this, empty when there\n // was none: the one given a component is written around.\n options.push({ label: '$slot', detail: 'given', info: 'what the calling tag held', boost: -15 })\n\n options.push({ label: '$loop', detail: 'given', info: 'inside @foreach', boost: -20 })\n\n return options\n}\n\nfunction echoed(\n context: CompletionContext,\n opener: string,\n space: string,\n word: string,\n schema: ScreenNode[],\n): CompletionResult | null {\n const options = printable(schema)\n if (options.length === 0) return null\n\n const closer = opener === '{{' ? '}}' : '!!}'\n\n return {\n from: context.pos - word.length,\n options: options.map((node, index) => ({\n label: node.id,\n displayLabel: `$${node.id}`,\n detail: node.type,\n info: node.label,\n type: 'variable',\n boost: 50 - index,\n apply: (view, completion, from, to) => {\n const rest = view.state.sliceDoc(to, to + 8)\n const closed = new RegExp(`^\\\\s*${escape(closer)}`).exec(rest)\n // `closeBrackets` has usually typed the `}}` already; when it has not, write it.\n const tail = closed ? (/^\\s/.test(rest) ? '' : ' ') : ` ${closer}`\n const insert = `${space === '' ? ' ' : ''}$${node.id}${tail}`\n\n view.dispatch({\n changes: { from, to, insert },\n // Past the closing braces: the echo is finished, the next thing is the markup.\n selection: { anchor: from + insert.length + (closed ? closed[0].length : 0) },\n annotations: pickedCompletion.of(completion),\n userEvent: 'input.complete',\n })\n },\n })),\n validFor: /^\\w*$/,\n }\n}\n\nfunction blockMembers(context: CompletionContext, word: string): CompletionResult {\n return {\n from: context.pos - word.length,\n options: [\n ...BLOCK_MEMBERS.map((label) => ({ label, type: 'property' })),\n snippetCompletion(\"value('${name}', ${default})\", {\n label: 'value',\n detail: \"('name', default)\",\n type: 'method',\n }),\n ],\n validFor: /^\\w*$/,\n }\n}\n\n/** `$image['…']`, `$item['…']`: what a value of that field holds, when the schema says. */\nfunction arrayKeys(\n context: CompletionContext,\n variable: string,\n quote: string,\n word: string,\n schema: ScreenNode[],\n): CompletionResult | null {\n const keys = keysOf(variable, schema, context.state.doc.toString())\n if (keys.length === 0) return null\n\n return {\n from: context.pos - word.length,\n options: keys.map(([label, detail]) => ({\n label,\n detail,\n type: 'property',\n apply: (view, completion, from, to) => {\n const start = quote ? from - 1 : from\n const rest = view.state.sliceDoc(to, to + 2)\n const q = quote || \"'\"\n const end = to + (rest.startsWith(q) ? 1 : 0)\n const closed = view.state.sliceDoc(end, end + 1) === ']'\n const insert = `${q}${label}${q}${closed ? '' : ']'}`\n\n view.dispatch({\n changes: { from: start, to: end, insert },\n selection: { anchor: start + insert.length + (closed ? 1 : 0) },\n annotations: pickedCompletion.of(completion),\n userEvent: 'input.complete',\n })\n },\n })),\n validFor: /^\\w*$/,\n }\n}\n\nfunction keysOf(variable: string, schema: ScreenNode[], template: string): [string, string][] {\n const field = fields(schema).find((node) => node.id === variable)\n if (field && MEDIA_TYPES.includes(field.type)) return MEDIA_KEYS.map((key) => [key, field.type])\n if (field?.type === 'wx-collection') return COLLECTION_KEYS.map((key) => [key, field.type])\n\n const list = loopVariables(template).get(variable)\n const [name, part] = list?.split('.') ?? []\n\n // `$banner` of `banners(…)->get() as $banner`, `$layout` of `$layout = banners_layout(…)`,\n // and one level down: `$button` of `$banner['buttons'] as $button`.\n if (name?.startsWith(HELPER)) {\n const helper = name.slice(HELPER.length)\n const keys = part ? HELPER_PARTS[helper]?.[part] : HELPER_KEYS[helper]\n return (keys ?? []).map((key) => [key, `${helper}()`])\n }\n\n const source = name ? fields(schema).find((node) => node.id === name) : undefined\n if (!source) return []\n\n if (source.type === 'wx-collection') {\n const origin = typeof source.props?.source === 'string' ? source.props.source : source.type\n const own = part === 'items' ? (SOURCE_ITEMS[origin] ?? []) : []\n return [...(COLLECTION_PARTS[part ?? ''] ?? []), ...own].map((key) => [key, origin])\n }\n\n if (LIST_TYPES.includes(source.type)) return ITEM_KEYS.map((key) => [key, source.type])\n\n if (source.type === 'wx-repeater') {\n return fields(source.children ?? []).map((node) => [node.id, node.type])\n }\n\n return []\n}\n\n/**\n * `@foreach ($items as $item)` → item ⇒ items, and the key variable ⇒ nothing;\n * `@foreach ($questions['items'] as $q)` → q ⇒ questions.items.\n */\nfunction loopVariables(template: string): Map<string, string> {\n const found = new Map<string, string>()\n\n // A helper's value, looped over or kept in a variable: named `helper:<name>`, which no field\n // can be called.\n for (const match of template.matchAll(\n /\\b(\\w+)\\([^()]*\\)(?:->\\w+\\([^()]*\\))*\\s+as\\s+\\$(\\w+)|\\$(\\w+)\\s*=\\s*(\\w+)\\(/g,\n )) {\n const helper = match[1] ?? match[4]!\n if (helper in HELPER_KEYS) found.set(match[2] ?? match[3]!, `${HELPER}${helper}`)\n }\n\n for (const match of template.matchAll(\n /\\$(\\w+)(?:\\[\\s*['\"](\\w+)['\"]\\s*\\])?\\s+as\\s+\\$(\\w+)(?:\\s*=>\\s*\\$(\\w+))?/g,\n )) {\n const name = match[1]!\n const outer = found.get(name)\n const value = outer?.startsWith(HELPER) ? outer : name\n\n found.set(match[4] ?? match[3]!, match[2] ? `${value}.${match[2]}` : value)\n }\n\n return found\n}\n\nfunction classNames(context: CompletionContext, value: string, styles: string): CompletionResult {\n const word = /[\\w-]*$/.exec(value)![0]\n const present = new Set(value.split(/\\s+/))\n\n return {\n from: context.pos - word.length,\n options: styleClasses(styles)\n .filter((name) => !present.has(name) || name === word)\n .map((label) => ({ label, detail: 'styles', type: 'class' })),\n validFor: /^[\\w-]*$/,\n }\n}\n\nfunction directives(schema: ScreenNode[]): Completion[] {\n const blocks = fields(schema).filter((node) => node.type === 'wx-blocks')\n\n return [\n snippetCompletion('@if (${condition})\\n\\t${}\\n@endif', { label: '@if', type: 'keyword' }),\n snippetCompletion('@isset(${value})\\n\\t${}\\n@endisset', { label: '@isset', type: 'keyword' }),\n snippetCompletion('@foreach (${items} as ${item})\\n\\t${}\\n@endforeach', {\n label: '@foreach',\n type: 'keyword',\n }),\n snippetCompletion('@forelse (${items} as ${item})\\n\\t${}\\n@empty\\n\\t${}\\n@endforelse', {\n label: '@forelse',\n type: 'keyword',\n }),\n snippetCompletion('@unless (${condition})\\n\\t${}\\n@endunless', {\n label: '@unless',\n type: 'keyword',\n }),\n snippetCompletion('@class([${}])', { label: '@class', type: 'keyword' }),\n snippetCompletion('@style([${}])', { label: '@style', type: 'keyword' }),\n ...blocks.map((node) =>\n snippetCompletion(`@blocks('${node.id}')`, {\n label: '@blocks',\n detail: `('${node.id}')`,\n type: 'keyword',\n boost: 10,\n }),\n ),\n ...HELPER_SNIPPETS.map(([label, template, info]) =>\n snippetCompletion(template, { label, info, type: 'function', boost: -5 }),\n ),\n ...['@elseif', '@else', '@endif', '@endforeach', '@endisset', '@empty', '@endforelse'].map(\n (label) => ({ label, type: 'keyword', boost: -10 }),\n ),\n ]\n}\n\n/* ---------------------------------------------------------------------------------------- */\n/* Styles */\n/* ---------------------------------------------------------------------------------------- */\n\nexport interface StylesSources {\n slug: () => string\n template: () => string\n}\n\nexport function stylesCompletions({ slug, template }: StylesSources): CompletionSource {\n return (context) => {\n const before = context.state.sliceDoc(Math.max(0, context.pos - 200), context.pos)\n const match = /(?:^|[\\s,>+~(}{])\\.([\\w-]*)$/.exec(before)\n if (!match) return null\n\n // A dot in a value (`padding: .5rem`) is not a selector: the text since the last rule\n // boundary reads as `property: …`.\n const statement = /[^{};]*$/.exec(before)![0]\n if (/^\\s*[\\w-]+\\s*:\\s/.test(statement)) return null\n\n const root = `b-${slug()}`\n const styled = new Set(styleClasses(context.state.doc.toString()))\n const used = templateClasses(template())\n const names = [root, ...used.filter((name) => name !== root)]\n\n const options: Completion[] = names.map((name, index) => ({\n label: `.${name}`,\n // A class the template uses and nothing styles yet is the likeliest thing to write.\n detail: styled.has(name) ? 'template' : 'template · no rule yet',\n type: 'class',\n boost: (styled.has(name) ? 0 : 20) + (name === root ? 30 : 0) - index / 100,\n }))\n\n for (const name of styled) {\n if (!names.includes(name))\n options.push({ label: `.${name}`, detail: 'styles', type: 'class' })\n }\n\n return { from: context.pos - match[1]!.length - 1, options, validFor: /^\\.[\\w-]*$/ }\n }\n}\n\n/** Classes a stylesheet declares, nested `&__part` resolved against its parent. */\nexport function styleClasses(styles: string): string[] {\n const source = styles.replace(/\\/\\*[\\s\\S]*?\\*\\//g, '')\n const found = new Set<string>()\n const stack: string[][] = []\n let prelude = ''\n\n for (const char of source) {\n if (char === '{') {\n const parents = stack.at(-1) ?? ['']\n const selectors = prelude\n .split(',')\n .map((part) => part.trim())\n .filter((part) => part !== '' && !part.startsWith('@'))\n .flatMap((part) =>\n part.includes('&')\n ? parents.map((parent) => part.replaceAll('&', parent))\n : parents.map((parent) => (parent ? `${parent} ${part}` : part)),\n )\n\n for (const selector of selectors) {\n for (const match of selector.matchAll(/\\.(-?[a-zA-Z_][\\w-]*)/g)) found.add(match[1]!)\n }\n\n stack.push(prelude.trim().startsWith('@') ? parents : selectors.length ? selectors : parents)\n prelude = ''\n } else if (char === '}') {\n stack.pop()\n prelude = ''\n } else if (char === ';') {\n prelude = ''\n } else {\n prelude += char\n }\n }\n\n return [...found]\n}\n\n/** Classes the template writes literally; anything Blade computes is left out. */\nexport function templateClasses(template: string): string[] {\n const found = new Set<string>()\n\n for (const match of template.matchAll(/\\bclass\\s*=\\s*\"([^\"]*)\"/g)) {\n const value = match[1]!.replace(/\\{\\{[\\s\\S]*?\\}\\}|\\{!![\\s\\S]*?!!\\}|@\\w+(\\([^)]*\\))?/g, ' ')\n\n for (const name of value.split(/\\s+/)) {\n if (/^-?[a-zA-Z_][\\w-]*$/.test(name)) found.add(name)\n }\n }\n\n return [...found]\n}\n\n/* ---------------------------------------------------------------------------------------- */\n/* Fields */\n/* ---------------------------------------------------------------------------------------- */\n\nexport interface SchemaSources {\n types: () => TypeRegistry\n}\n\n/** The keys of a node (`ScreenNode`), each with what goes after the colon. */\nconst NODE_KEYS: { key: string; value: string; info: string }[] = [\n { key: 'id', value: '\"\"', info: 'The variable the template gets, in snake_case.' },\n { key: 'type', value: '\"\"', info: 'A type from the registry.' },\n { key: 'label', value: '\"\"', info: 'What the editor sees above the field.' },\n { key: 'help', value: '\"\"', info: 'A hint under the field.' },\n { key: 'localized', value: 'true', info: 'Edited per content language.' },\n { key: 'props', value: '{}', info: 'Passed to the component as they are.' },\n { key: 'children', value: '[]', info: 'Nodes inside a layout node or a repeater.' },\n { key: 'visible', value: '', info: '`false`, or a condition on another field.' },\n { key: 'slot', value: '\"\"', info: \"The parent's named slot to land in.\" },\n { key: 'can', value: '\"\"', info: 'The permission the node needs.' },\n]\n\nexport function schemaCompletions({ types }: SchemaSources): CompletionSource {\n return (context) => {\n const at = jsonContext(context.state.doc.toString(), context.pos)\n if (!at || !at.node) return null\n\n const word = at.string\n ? context.state.sliceDoc(at.string, context.pos)\n : /[\\w-]*$/.exec(context.state.sliceDoc(Math.max(0, context.pos - 60), context.pos))![0]\n\n if (!at.string && word === '' && !context.explicit) return null\n\n const from = context.pos - word.length\n const quoted = at.string !== null\n\n if (at.phase === 'key') {\n const options = NODE_KEYS.filter(({ key }) => !at.keys.has(key) || key === word).map(\n ({ key, value, info }, index): Completion => ({\n label: key,\n info,\n type: 'property',\n boost: -index,\n apply: (view, completion, start, end) =>\n applyJson(view, completion, start, end, quoted, `\"${key}\": ${value}`, value),\n }),\n )\n\n return { from, options, validFor: /^[\\w-]*$/ }\n }\n\n if (at.phase === 'value' && at.key === 'type') {\n const options = Object.entries(types()).map(([type, entry]): Completion => ({\n label: type,\n detail: entry.kind,\n type: 'type',\n // Fields first: a block's schema is mostly fields, the layout only groups them.\n boost: entry.kind === 'field' ? 1 : 0,\n apply: (view, completion, start, end) =>\n applyJson(view, completion, start, end, quoted, `\"${type}\"`, ''),\n }))\n\n return { from, options, validFor: /^[\\w-]*$/ }\n }\n\n return null\n }\n}\n\n/**\n * Replaces the word being typed — with its quotes, whichever of them are there — and puts\n * the caret inside the value that follows: between `\"\"`, `{}`, `[]`, or after the colon.\n * A `type` opens the list of types straight away, since that is the next thing to pick.\n */\nfunction applyJson(\n view: EditorView,\n completion: Completion,\n from: number,\n to: number,\n quoted: boolean,\n insert: string,\n value: string,\n): void {\n const start = quoted ? from - 1 : from\n const rest = /^[\\w-]*\"?/.exec(view.state.sliceDoc(to, to + 60))![0]\n const end = to + (quoted ? rest.length : /^[\\w-]*/.exec(rest)![0].length)\n const inside = value === '\"\"' || value === '{}' || value === '[]' ? 1 : 0\n\n view.dispatch({\n changes: { from: start, to: end, insert },\n selection: { anchor: start + insert.length - inside },\n annotations: pickedCompletion.of(completion),\n userEvent: 'input.complete',\n })\n\n if (insert.startsWith('\"type\"')) startCompletion(view)\n}\n\ninterface Frame {\n kind: 'object' | 'array'\n parent: Frame | null\n /** For an array: the key it is the value of. */\n under: string | null\n keys: Set<string>\n phase: 'key' | 'colon' | 'value' | 'after'\n key: string | null\n}\n\nexport interface JsonContext {\n /** The caret stands in an object that is a screen node. */\n node: boolean\n phase: Frame['phase']\n /** The key whose value is being written. */\n key: string | null\n /** Every key the object has, before the caret and after it. */\n keys: Set<string>\n /** Where the string under the caret starts, after its opening quote. */\n string: number | null\n}\n\n/**\n * Where the caret stands in a schema, by one pass over the text — it has to work on a\n * document that is broken right there, which is always the case while typing, and a parser\n * gives up on exactly that.\n */\nexport function jsonContext(doc: string, pos: number): JsonContext | null {\n let top = null as Frame | null\n let snapshot: JsonContext | null = null\n let string: { start: number; key: boolean } | null = null\n let escaped = false\n\n const isNode = (frame: Frame | null): boolean =>\n frame?.kind === 'object' &&\n frame.parent?.kind === 'array' &&\n (frame.parent.parent === null || frame.parent.under === 'children')\n\n for (let i = 0; i <= doc.length; i++) {\n if (i === pos) {\n snapshot =\n top?.kind === 'object'\n ? {\n node: isNode(top),\n phase: string?.key ? 'key' : top.phase,\n key: top.key,\n keys: top.keys,\n string: string ? string.start + 1 : null,\n }\n : null\n }\n\n if (i === doc.length) break\n const char = doc[i]!\n\n if (string) {\n if (escaped) escaped = false\n else if (char === '\\\\') escaped = true\n else if (char === '\"' || char === '\\n') {\n const text = doc.slice(string.start + 1, i)\n\n if (top?.kind === 'object') {\n if (string.key) {\n top.keys.add(text)\n top.key = text\n top.phase = 'colon'\n } else if (top.phase === 'value') {\n top.phase = 'after'\n }\n }\n\n string = null\n }\n continue\n }\n\n if (/\\s/.test(char)) continue\n\n if (char === '\"') {\n string = { start: i, key: top?.kind === 'object' && top.phase === 'key' }\n } else if (char === '{' || char === '[') {\n const frame: Frame = {\n kind: char === '{' ? 'object' : 'array',\n parent: top,\n under: top?.kind === 'object' ? top.key : null,\n keys: new Set(),\n phase: 'key',\n key: null,\n }\n if (top?.kind === 'object') top.phase = 'after'\n top = frame\n } else if (char === '}' || char === ']') {\n top = top?.parent ?? null\n } else if (char === ':') {\n if (top?.kind === 'object') top.phase = 'value'\n } else if (char === ',') {\n if (top?.kind === 'object') {\n top.phase = 'key'\n top.key = null\n }\n }\n // A bare word after a colon keeps the phase: `\"type\": wx` is a type being typed without\n // its quotes, and `true` or `12` has nothing to complete either way.\n }\n\n return snapshot\n}\n\n/* ---------------------------------------------------------------------------------------- */\n\n/** Fields of a schema through its layout, the way the template sees them: flat. */\nfunction fields(schema: ScreenNode[]): ScreenNode[] {\n const found: ScreenNode[] = []\n\n for (const node of schema) {\n if (!node || typeof node !== 'object') continue\n if (LAYOUT.has(node.type)) found.push(...fields(node.children ?? []))\n else if (typeof node.id === 'string' && node.id !== '') found.push(node)\n }\n\n return found\n}\n\n/** A `wx-blocks` value is printed with `@blocks('id')`, never echoed. */\nfunction printable(schema: ScreenNode[]): ScreenNode[] {\n return fields(schema).filter((node) => node.type !== 'wx-blocks')\n}\n\nconst LAYOUT = new Set(['wx-card', 'wx-tabs', 'wx-tab', 'wx-row', 'wx-col', 'wx-divider'])\n\nfunction escape(text: string): string {\n return text.replace(/[.*+?^${}()|[\\]\\\\!]/g, '\\\\$&')\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/**\n * Variables Blade or the renderer hand a template on their own. `$slot` among them: any type can\n * be called with `<x-webx-block>`, and the default slot is there whether or not the tag had a\n * body — empty when it did not (§3.3 of the components spec).\n */\nconst GIVEN = ['block', 'entity', 'loop', 'slot', '__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 { inject, provide, type InjectionKey, type Ref } from 'vue'\nimport type { BlockType } from './types'\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\n/**\n * Set by the block editor around its sample form: the block whose own field that constructor\n * is. Without it the sample's top level reads as a page, so the picker offered every type the\n * page may hold rather than what this block lets inside — and hid a type that may stand only\n * in this block. A ref, because the editor's settings are the draft, not the published type.\n */\nexport const blocksOwnerKey: InjectionKey<Ref<BlockType | null>> = Symbol('wx-blocks-owner')\n","import type { ScreenNode } from '@webx-ui/schema'\nimport type { BlockKind } from './types'\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 * How many entities a type stands on, in words.\n *\n * Three lines rather than one with a number in it: `on :count pages` reads as \"on 1 pages\"\n * exactly when a type has just been put somewhere for the first time, which is the moment an\n * editor is most likely to be looking at it. The panel has no plural forms and does not need\n * them — one is one, and the rest is a number.\n */\nexport function usageWords(\n count: number,\n t: (key: string, params?: Record<string, string | number>) => string,\n): string {\n if (count === 0) return t('page.not-used')\n\n return count === 1 ? t('page.on-page') : t('page.on-pages', { count })\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\n/** What a type is; a server older than components sends no `kind`, and everything was a block. */\nexport function kindOf(type: { kind?: BlockKind }): BlockKind {\n return type.kind ?? 'block'\n}\n\n/**\n * How many types call a component, in words — the component's \"on 3 pages\". Counted in types\n * rather than pages on purpose (§3.10): the pages behind every parent are expensive to count and\n * say little, while the parents are what a change to the component can break.\n */\nexport function callerWords(\n count: number,\n t: (key: string, params?: Record<string, string | number>) => string,\n): string {\n if (count === 0) return t('components.not-called')\n\n return count === 1 ? t('components.in-block') : t('components.in-blocks', { count })\n}\n\n/** Layout nodes: they group fields and are never a value of their own. */\nconst LAYOUT = new Set(['wx-card', 'wx-tabs', 'wx-tab', 'wx-row', 'wx-col', 'wx-divider'])\n\n/** The fields of a schema through its layout, flat — the variables a template gets. */\nexport function schemaFields(schema: ScreenNode[]): ScreenNode[] {\n const found: ScreenNode[] = []\n\n for (const node of schema) {\n if (!node || typeof node !== 'object') continue\n if (LAYOUT.has(node.type)) found.push(...schemaFields(node.children ?? []))\n else if (typeof node.id === 'string' && node.id !== '') found.push(node)\n }\n\n return found\n}\n\n/**\n * The tag that calls a type, with every input it takes — what the help under a component's\n * template offers to copy.\n *\n * `wx-data` is passed from code, so it is bound (`:card=\"$card\"`); a plain field shows its sample\n * when that is a word (`tone=\"accent\"`) and is bound otherwise. Declared slots stand in the body;\n * with none, the tag closes itself — the default `$slot` is there all the same, and a body shown\n * for it would read as something the component needs.\n */\nexport function callTag(\n slug: string,\n schema: ScreenNode[],\n sample: Record<string, unknown> = {},\n fallback: string | null = null,\n): string {\n const fields = schemaFields(schema)\n const attributes = [`type=\"${slug}\"`]\n\n for (const node of fields) {\n if (node.type === 'wx-slot' || node.type === 'wx-blocks') continue\n\n const value = sample[node.id]\n\n attributes.push(\n node.type !== 'wx-data' && (typeof value === 'string' || typeof value === 'number')\n ? `${node.id}=\"${String(value).replace(/\"/g, '&quot;')}\"`\n : `:${node.id}=\"$${variableOf(node.id)}\"`,\n )\n }\n\n if (fallback) attributes.push(`fallback=\"${fallback}\"`)\n\n const slots = fields.filter((node) => node.type === 'wx-slot')\n const head = `<x-webx-block ${attributes.join(' ')}`\n\n if (slots.length === 0) return `${head} />`\n\n return [\n `${head}>`,\n ...slots.map((node) => ` <x-slot:${node.id}>…</x-slot:${node.id}>`),\n '</x-webx-block>',\n ].join('\\n')\n}\n\n/** `cta-label` has no variable of its own; the caller's is written as it would be named. */\nfunction variableOf(id: string): string {\n return id.replace(/-(\\w)/g, (_match, letter: string) => letter.toUpperCase())\n}\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, provide, reactive, ref, watch } from 'vue'\nimport { useRoute, useRouter } from 'vue-router'\nimport {\n useAdmin,\n useErrorText,\n useTranslate,\n WxHelpButton,\n WxRenameButton,\n WxScreenHead,\n type ScreenAction,\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 WxIconPicker,\n WxInput,\n WxInputNumber,\n WxPopover,\n WxSelect,\n WxSkeleton,\n WxSwitch,\n WxTab,\n WxTabs,\n WxTagsInput,\n WxText,\n WxTextarea,\n} from '@webx-ui/core'\nimport { coreTypes, 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 {\n completions,\n schemaCompletions,\n stylesCompletions,\n templateCompletions,\n type TagTarget,\n} from './completions'\nimport { lintBlock } from './lint'\nimport { blocksOwnerKey } from './preview'\nimport {\n callerWords,\n callTag,\n formSchema,\n groupLabel,\n kindOf,\n schemaFields,\n usageWords,\n} from './schema'\nimport type {\n BlockContent,\n BlockKind,\n BlocksMeta,\n BlockType,\n BlockUsage,\n PublishRefusal,\n} from './types'\n\n/**\n * The editor of one type: six tabs across the screen — the four files, the settings and the\n * history — and what each of them needs beside it. The template has the block drawn on its\n * sample; the schema has the form it builds. The rest have nothing, and take the width.\n *\n * Where the type stands is a list behind one word of the subtitle.\n *\n * The loop is closed all the same: edit the schema and the form rebuilds, edit the values and\n * the stage redraws, edit the template or the styles and so does it.\n *\n * A component is edited on the same screen (§3.9 of the components spec). What differs is what\n * its schema means — the input a caller hands it, not a form — so the settings lose what only a\n * block on a page needs, \"Fields\" become \"Input data\", and under the template stands the tag that\n * calls it. Where it is used is the blocks that call it rather than pages.\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 kind: 'block' as BlockKind,\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\n/* The sample form's nested constructors add into this block, as it stands in the settings. */\nprovide(\n blocksOwnerKey,\n computed(() =>\n block.value\n ? {\n ...block.value,\n slug: settings.slug,\n title: settings.title,\n allow: settings.allow.length ? settings.allow : null,\n }\n : null,\n ),\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 stage: 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\n/**\n * What a tag in this template can call: every type, and every place a module declared and the\n * site has not customised — a tag with a `fallback` calls those too. Read once per editor.\n */\nconst targets = ref<TagTarget[]>([])\nconst typeIds = new Map<string, number>()\nconst schemas = new Map<string, Promise<BlockContent['schema'] | null>>()\n\nasync function loadTargets(): Promise<void> {\n try {\n const list = await api.index()\n\n typeIds.clear()\n for (const type of list.blocks) typeIds.set(type.slug, type.id)\n\n targets.value = [\n ...list.blocks.map((type) => ({\n slug: type.slug,\n title: type.title,\n kind: kindOf(type),\n fallback: list.declared.find((place) => place.slug === type.slug)?.fallback ?? null,\n })),\n ...list.declared\n .filter((place) => !place.customised)\n .map((place) => ({\n slug: place.slug,\n title: place.title,\n kind: 'component' as const,\n fallback: place.fallback,\n })),\n ]\n } catch {\n // Only the suggestions go without it; the editor has nothing else to do with the list.\n }\n}\n\n/** A called type's schema, asked for once and kept: its own for the type being edited. */\nfunction schemaOf(\n slug: string,\n): BlockContent['schema'] | null | Promise<BlockContent['schema'] | null> {\n if (slug === settings.slug) return content.schema\n\n const id = typeIds.get(slug)\n if (id === undefined) return null\n\n let found = schemas.get(slug)\n\n if (found === undefined) {\n found = api.get(id).then(\n (type) => type.content?.schema ?? null,\n () => null,\n )\n schemas.set(slug, found)\n }\n\n return found\n}\n\n/* Built once: the sources read the other files of the type when asked, not when made. */\nconst assist = {\n template: [\n completions(\n templateCompletions({\n schema: () => content.schema,\n styles: () => content.styles,\n types: () => targets.value,\n schemaOf,\n }),\n ),\n ],\n styles: [\n completions(stylesCompletions({ slug: () => settings.slug, template: () => content.template })),\n ],\n // The renderer's own types under the panel's, the same merge the sample form is drawn with.\n schema: [completions(schemaCompletions({ types: () => ({ ...coreTypes, ...context.types }) }))],\n}\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 kind: kindOf(loaded),\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 void loadTargets()\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 stage.stage = drawn.stage ?? null\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 // A component stands on no page itself; what a new version reaches is the blocks calling it.\n // A declared place is also printed by the module's views, which the count does not see.\n message: declaredModule.value\n ? t('components.publish-declared', {\n module: declaredModule.value,\n count: callers.value.length,\n })\n : isComponent.value\n ? t('components.publish-text', { count: callers.value.length })\n : 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 // Deleting a customised place is how it goes back to the module's view (§2, decision 5), and\n // the dialog says so: \"cannot be undone\" alone would read as losing the recipe card for good.\n const reset = block.value.declared != null\n\n const agreed = await confirm({\n title: reset\n ? t('components.delete-declared-title', { title: block.value.title })\n : t('page.delete-title', { title: block.value.title }),\n message: reset ? t('components.delete-declared-text') : t('page.delete-text'),\n confirmText: reset ? t('components.delete-declared') : 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\n/** The two tabs the picture belongs to: the markup and the styles both change it. */\nconst withStage = computed(() => tab.value === 'template' || tab.value === 'styles')\n\n/**\n * What the script field is, in three lines of it.\n *\n * The body of `async (el, values) => { … }` is a contract nobody guesses from an empty\n * editor: the sentence under it names `el` and `values`, and these say what they are for.\n * The code is code and stays in English; what each one does is a line of the dictionary.\n */\nconst examples = computed(() => [\n {\n title: t('page.example-handler'),\n code: `el.querySelector('.b-hero__button')?.addEventListener('click', (event) => {\\n event.preventDefault()\\n el.classList.toggle('is-open')\\n})`,\n },\n {\n title: t('page.example-values'),\n /* The one thing the sentence above the examples does not say: values reach the script\n only through the attribute, and a template that never prints it hands over `{}`. */\n code: `// <section data-wx-values=\"{{ json_encode($block->values) }}\">\\nconst seconds = Number(values.delay ?? 5)\\n\\nsetInterval(() => el.classList.toggle('is-second'), seconds * 1000)`,\n },\n {\n title: t('page.example-provided'),\n code: `const Swiper = await webx.use('swiper')\\n\\nnew Swiper(el.querySelector('.b-slider__viewport'), { loop: true })`,\n },\n])\n\nconst shownUsage = computed(() => usage.value.slice(0, 5))\n\nconst isComponent = computed(() => settings.kind === 'component')\n\n/** The blocks whose published version calls this type. */\nconst callers = computed(() => block.value?.used_by ?? [])\n\n/** The module whose views call this slug, by its name in the panel. */\nconst declaredModule = computed(() => {\n const id = block.value?.declared?.module\n\n if (!id) return null\n\n return (\n context.state.manifest?.modules.find((module) => module.id === id)?.title ??\n id.charAt(0).toUpperCase() + id.slice(1)\n )\n})\n\n/** The words of the subtitle: pages for a block, calling blocks for a component. */\nconst whereWords = computed(() =>\n isComponent.value\n ? callerWords(callers.value.length, t)\n : usageWords(block.value?.usage_count ?? 0, t),\n)\n\n/** Anything behind those words: pages, calling blocks, or a module's views. */\nconst hasWhere = computed(\n () =>\n (block.value?.usage_count ?? 0) > 0 ||\n callers.value.length > 0 ||\n declaredModule.value !== null,\n)\n\n/** Why the type cannot be deleted, when it cannot. Pages first: they are what editors see. */\nconst deleteBlocked = computed<string | null>(() => {\n const count = block.value?.usage_count ?? 0\n\n if (count > 0) return count === 1 ? t('page.delete-used-one') : t('page.delete-used', { count })\n\n if (callers.value.length > 0) {\n return t('components.delete-called', {\n titles: callers.value.map((parent) => `\"${parent.title}\"`).join(', '),\n })\n }\n\n return null\n})\n\n/** The tag that calls this type, with its inputs — the help under a component's template. */\nconst call = computed(() =>\n callTag(settings.slug, content.schema, content.sample, block.value?.declared?.fallback ?? null),\n)\n\n/** Each `wx-data` input and what its shape holds, as far as the server described it. */\nconst dataInputs = computed(() =>\n schemaFields(content.schema)\n .filter((node) => node.type === 'wx-data')\n .map((node) => {\n const shape = typeof node.props?.shape === 'string' ? node.props.shape : null\n\n return {\n id: node.id,\n shape,\n fields: shape ? (block.value?.shape?.[shape]?.fields ?? []) : [],\n }\n }),\n)\n\nasync function copyCall(): Promise<void> {\n try {\n await navigator.clipboard.writeText(call.value)\n toast.success(t('components.copied'))\n } catch {\n // No clipboard (an insecure origin, a denied permission): the tag is on the screen to select.\n }\n}\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/* The two things this editor is for. The bar along the bottom repeats them (§3.3). */\nconst kindOptions = computed(() => [\n { value: 'block', label: t('components.kind-block') },\n { value: 'component', label: t('components.kind-component') },\n])\n\nconst actions = computed<ScreenAction[]>(() =>\n canManage.value\n ? [\n { key: 'save', label: t('page.save'), loading: saving.value, run: () => void save() },\n {\n key: 'publish',\n label: t('page.publish'),\n primary: true,\n loading: publishing.value,\n disabled: !block.value?.draft && !dirty.value,\n run: () => void publish(),\n },\n ]\n : [],\n)\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__split\">\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 <!--\n The panel's head, not this editor's: the way out, the name, what state the type is in\n and what can be done with it. Renaming is a control beside the name rather than typing\n into what looks like a heading.\n -->\n <wx-screen-head\n :title=\"settings.title\"\n :back=\"base\"\n :back-label=\"t('page.back')\"\n :actions=\"actions\"\n >\n <template #title-after>\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 <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>\n\n <!--\n Where the type stands is one line of the subtitle and a list behind it: a card of\n five page names took a quarter of the column beside the stage to say what the head\n already says in three words. The words are the door.\n -->\n <template #subtitle>\n <code>{{ settings.slug }}</code>\n ·\n {{ isComponent ? t('components.kind-component') : groupLabel(settings.group, t) }}\n ·\n <wx-popover v-if=\"hasWhere\" :title=\"t('page.usage')\" :width=\"260\" align=\"start\">\n <template #trigger>\n <button type=\"button\" class=\"wx-block-editor__uses\">\n {{ whereWords }}\n </button>\n </template>\n\n <div class=\"wx-block-editor__usage\">\n <!-- The blocks calling it first on a component: those are what a change reaches. -->\n <router-link\n v-for=\"parent in callers\"\n :key=\"`type:${parent.id}`\"\n :to=\"`${base}/${parent.id}`\"\n class=\"wx-block-editor__use\"\n >\n {{ t('components.called-by', { title: parent.title }) }}\n </router-link>\n <div v-if=\"declaredModule\" class=\"wx-block-editor__use\">\n {{ t('components.module-views', { module: declaredModule }) }}\n </div>\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-popover>\n <template v-else>{{ whereWords }}</template>\n </template>\n </wx-screen-head>\n\n <wx-alert\n v-if=\"!meta.editing\"\n type=\"info\"\n variant=\"soft\"\n :description=\"t('page.editing-off')\"\n />\n\n <!--\n The block stands beside the two files that draw it and nowhere else: it used to be a\n column down the whole screen, half the width of the settings and of the history, which\n have nothing to do with how the block looks. One stage and not one per tab — `v-show`,\n because a frame taken out of the document and put back reloads.\n -->\n <div class=\"wx-block-editor__columns\" :class=\"{ 'is-alone': !withStage }\">\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 :extensions=\"assist.template\"\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\n <!--\n How this component is called, ready to copy: the tag with every input it takes, and\n for a structure passed from code, what the structure holds. A component is only\n ever used this way, so the one thing a person needs next is written out here.\n -->\n <wx-card v-if=\"isComponent\" class=\"wx-block-editor__call\" :title=\"t('components.call')\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('components.call-help') }}</wx-text>\n <div class=\"wx-block-editor__call-tag\">\n <pre><code>{{ call }}</code></pre>\n <wx-button size=\"sm\" variant=\"outline\" @click=\"copyCall\">\n {{ t('components.copy') }}\n </wx-button>\n </div>\n\n <div v-for=\"input in dataInputs\" :key=\"input.id\" class=\"wx-block-editor__shape\">\n <wx-text size=\"sm\" tone=\"muted\">\n {{\n input.fields.length\n ? t('components.shape', { name: input.id })\n : t('components.shape-free', { name: input.id })\n }}\n <code v-if=\"input.shape\">{{ input.shape }}</code>\n </wx-text>\n <dl v-if=\"input.fields.length\" class=\"wx-block-editor__shape-fields\">\n <template v-for=\"field in input.fields\" :key=\"field.name\">\n <dt>\n <code>{{ field.name }}</code>\n <span class=\"wx-block-editor__shape-type\">{{ field.type }}</span>\n </dt>\n <dd>{{ field.description }}</dd>\n </template>\n </dl>\n </div>\n\n <wx-text size=\"sm\" tone=\"muted\">{{ t('components.site-views') }}</wx-text>\n </wx-card>\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 :extensions=\"assist.styles\"\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\n <!--\n What the two names in scope are actually for. The examples are code and stay in\n English; what each one is for is a line of the dictionary. Reading, not inserting:\n dropping four lines into the middle of somebody's function is not a favour.\n -->\n <wx-card class=\"wx-block-editor__examples\" :title=\"t('page.examples')\">\n <div\n v-for=\"example in examples\"\n :key=\"example.title\"\n class=\"wx-block-editor__example\"\n >\n <wx-text size=\"sm\" tone=\"muted\">{{ example.title }}</wx-text>\n <pre><code>{{ example.code }}</code></pre>\n </div>\n </wx-card>\n </wx-tab>\n\n <!--\n The schema and the form it builds, side by side: the sample used to stand in the\n column beside the stage, where it pushed the picture up and stood open on every tab\n — including the four where nobody is looking at values. Here it is the other half of\n the tab it belongs to, and editing a field shows what it becomes.\n -->\n <wx-tab\n value=\"fields\"\n :label=\"isComponent ? t('components.tab-inputs') : t('page.tab-fields')\"\n >\n <div class=\"wx-block-editor__split\">\n <div class=\"wx-block-editor__pane\">\n <wx-code-editor\n :model-value=\"schemaText\"\n language=\"json\"\n :extensions=\"assist.schema\"\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\">{{\n isComponent ? t('components.inputs-help') : t('page.fields-help')\n }}</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\n <wx-card class=\"wx-block-editor__sample\" :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-card>\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('components.kind')\"\n :help=\"t('components.kind-help')\"\n :error=\"errorOf('kind')\"\n :disabled=\"!canManage\"\n >\n <wx-select v-model=\"settings.kind\" :options=\"kindOptions\" />\n </wx-form-item>\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 <!-- What only a block on a page needs: where it is picked from, what it may\n hold and stand in, how many a page takes. A component is never picked. -->\n <wx-form-item\n v-if=\"!isComponent\"\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 <!-- Picked, not typed: a name the set does not have draws nothing at all,\n and nothing on the screen would say which of the two it was. -->\n <wx-icon-picker\n :model-value=\"settings.icon\"\n clearable\n :placeholder=\"t('page.icon-search')\"\n :empty-text=\"t('page.icon-none')\"\n :unknown-text=\"t('page.icon-unknown')\"\n :clear-label=\"t('page.icon-clear')\"\n @update:model-value=\"settings.icon = $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 v-if=\"!isComponent\"\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 v-if=\"!isComponent\"\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 v-if=\"!isComponent\"\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 v-if=\"!isComponent\"\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=\"deleteBlocked !== null\"\n @click=\"remove\"\n >\n {{ block.declared ? t('components.delete-declared') : t('page.delete') }}\n </wx-button>\n <wx-text v-if=\"deleteBlocked\" size=\"sm\" tone=\"muted\">{{ deleteBlocked }}</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\n <block-stage\n v-show=\"withStage\"\n class=\"wx-block-editor__stage\"\n :html=\"stage.html\"\n :styles=\"stage.styles\"\n :script=\"stage.script\"\n :runtime=\"stage.runtime\"\n :stage=\"stage.stage\"\n :loading=\"stage.loading\"\n />\n </div>\n\n <!-- The editor is six tabs of code and the stage beside them, so the head is long gone\n by the time there is anything to save: the two buttons stand here as well.\n The three badges do not. What state the type is in is a fact about the type, not\n about the last keystroke, and it is already said once — beside the name, where this\n panel says the state of a record. Twice on one screen is not twice as clear. -->\n <wx-action-bar 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 </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__ghost-head {\n max-width: 420px;\n}\n\n/* The tabs and the block beside them, while a tab that draws the block is the open one.\n `is-alone` is the same grid with the second track taken away: a hidden item still leaves\n its column standing, and the tabs would keep half the screen with nothing in the rest. */\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.wx-block-editor__columns.is-alone {\n grid-template-columns: minmax(0, 1fr);\n}\n\n/* What a tab puts side by side: the schema and the form it builds.\n One column below 1080, where two of anything is two half-width columns of nothing. */\n.wx-block-editor__split {\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 .wx-block-editor__split {\n grid-template-columns: minmax(0, 1fr);\n }\n}\n\n/* The tag to copy: code on the subtle ground, the button beside it — below it on a phone. */\n.wx-block-editor__call {\n min-width: 0;\n}\n\n.wx-block-editor__call :deep(.wx-card__body) {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-10);\n}\n\n.wx-block-editor__call-tag {\n display: flex;\n flex-wrap: wrap;\n align-items: flex-start;\n gap: var(--wx-space-8);\n}\n\n.wx-block-editor__call-tag pre {\n flex: 1 1 240px;\n min-width: 0;\n margin: 0;\n padding: var(--wx-space-10) var(--wx-space-12);\n border-radius: var(--wx-radius-sm);\n background: var(--wx-bg-subtle);\n overflow-x: auto;\n}\n\n.wx-block-editor__call-tag code {\n line-height: 1.6;\n color: var(--wx-text-default);\n white-space: pre;\n}\n\n.wx-block-editor__shape {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-6);\n}\n\n/* Name and type on one line, what it is under them: a glossary, read top to bottom. */\n.wx-block-editor__shape-fields {\n display: grid;\n grid-template-columns: minmax(0, max-content) minmax(0, 1fr);\n gap: var(--wx-space-4) var(--wx-space-12);\n margin: 0;\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-block-editor__shape-fields dt {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--wx-space-6);\n}\n\n.wx-block-editor__shape-fields dd {\n margin: 0;\n color: var(--wx-text-muted);\n}\n\n.wx-block-editor__shape-type {\n font-size: var(--wx-font-size-xs);\n color: var(--wx-text-muted);\n}\n\n@container (max-width: 520px) {\n .wx-block-editor__shape-fields {\n grid-template-columns: minmax(0, 1fr);\n }\n\n .wx-block-editor__shape-fields dd {\n margin-block-end: var(--wx-space-6);\n }\n}\n\n/* Read, not copied: monospace, wrapped, and no box that says \"editor\". */\n.wx-block-editor__examples {\n min-width: 0;\n}\n\n.wx-block-editor__example + .wx-block-editor__example {\n margin-block-start: var(--wx-space-12);\n}\n\n.wx-block-editor__example pre {\n margin: var(--wx-space-4) 0 0;\n padding: var(--wx-space-10) var(--wx-space-12);\n border-radius: var(--wx-radius-sm);\n background: var(--wx-bg-subtle);\n overflow-x: auto;\n}\n\n.wx-block-editor__example code {\n font-family: var(--wx-font-family-mono);\n font-size: var(--wx-font-size-xs);\n line-height: 1.6;\n color: var(--wx-text-default);\n white-space: pre;\n}\n\n/* The picture stays put while the template scrolls under it. */\n.wx-block-editor__stage {\n position: sticky;\n top: var(--wx-space-12);\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__sample {\n min-width: 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/* A word in the subtitle that opens the list: a link, because that is what it does. */\n.wx-block-editor__uses {\n padding: 0;\n border: 0;\n background: none;\n font: inherit;\n color: var(--wx-text-link);\n cursor: pointer;\n}\n\n.wx-block-editor__uses:hover {\n text-decoration: underline;\n text-underline-offset: 0.2em;\n}\n\n.wx-block-editor__uses:focus-visible {\n outline: none;\n border-radius: var(--wx-radius-xs);\n box-shadow: var(--wx-ring-focus);\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\na.wx-block-editor__use {\n color: var(--wx-text-link);\n text-decoration: none;\n}\n\na.wx-block-editor__use:hover {\n text-decoration: underline;\n text-underline-offset: 0.2em;\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 { useTranslate } from '@webx-ui/module-admin'\nimport { useModal, WxButton, WxDialog, WxEmpty, WxIcon, WxText } from '@webx-ui/core'\nimport { useBlocksMessages } from './i18n'\nimport type { Destination } from './move'\n\n/**\n * \"Move to\": the lists a block may go into, each named by the containers down to it.\n *\n * A list rather than a drag across the tree. The places are few and each one is named, the\n * rules are applied before anything is offered rather than at the moment of a drop, and a\n * finger in a sheet can do it as well as a mouse can. The block goes to the end of the list\n * it is moved into; its place there is a drag within that list.\n */\nwithDefaults(\n defineProps<{\n title: string\n destinations: Destination[]\n /** What the top level is called: the page, or the block whose sample this is. */\n topLabel: string\n }>(),\n {},\n)\n\nconst { resolve, dismiss, open } = useModal<Destination>()\nuseBlocksMessages()\n\nconst t = useTranslate('webx-blocks')\n</script>\n\n<template>\n <wx-dialog v-model:open=\"open\" :title=\"t('field.move-title', { title })\" :width=\"520\">\n <wx-empty\n v-if=\"destinations.length === 0\"\n icon=\"grid\"\n :title=\"t('field.move-none')\"\n size=\"sm\"\n />\n\n <div v-else class=\"wx-block-move\">\n <button\n v-for=\"place in destinations\"\n :key=\"`${place.parentKey}:${place.field}`\"\n type=\"button\"\n class=\"wx-block-move__place\"\n :disabled=\"place.full\"\n @click=\"resolve(place)\"\n >\n <wx-icon :name=\"place.parentKey === null ? 'file' : 'folder'\" />\n <span class=\"wx-block-move__trail\">\n <template v-if=\"place.trail.length === 0\">{{ topLabel }}</template>\n <template v-for=\"(step, index) in place.trail\" v-else :key=\"index\">\n <span v-if=\"index > 0\" class=\"wx-block-move__sep\">/</span>\n <span :class=\"{ 'is-last': index === place.trail.length - 1 }\">{{ step }}</span>\n </template>\n </span>\n <wx-text v-if=\"place.full\" size=\"sm\" tone=\"muted\">{{ t('field.move-full') }}</wx-text>\n </button>\n </div>\n\n <template #footer>\n <wx-button variant=\"outline\" @click=\"dismiss()\">{{ t('page.cancel') }}</wx-button>\n </template>\n </wx-dialog>\n</template>\n\n<style scoped>\n.wx-block-move {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-4);\n}\n\n.wx-block-move__place {\n display: flex;\n align-items: center;\n gap: var(--wx-space-10);\n width: 100%;\n padding: var(--wx-space-10) var(--wx-space-12);\n font: inherit;\n text-align: start;\n color: inherit;\n background: transparent;\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-control);\n cursor: pointer;\n}\n\n.wx-block-move__place:hover:not(:disabled),\n.wx-block-move__place:focus-visible {\n border-color: var(--wx-color-primary);\n background: var(--wx-color-primary-soft);\n outline: none;\n}\n\n.wx-block-move__place:disabled {\n opacity: 0.6;\n cursor: not-allowed;\n}\n\n.wx-block-move__trail {\n display: flex;\n flex: 1;\n flex-wrap: wrap;\n gap: var(--wx-space-4);\n min-width: 0;\n color: var(--wx-text-muted);\n}\n\n.wx-block-move__trail .is-last,\n.wx-block-move__trail:not(:has(span)) {\n color: var(--wx-text-default);\n font-weight: var(--wx-font-weight-medium);\n}\n\n.wx-block-move__sep {\n color: var(--wx-text-muted);\n}\n</style>\n","import { computed, inject, ref, watchEffect, type Ref } from 'vue'\nimport { adminKey } from '@webx-ui/module-admin'\nimport { siteShell } from './frame'\n\n/**\n * One request for every thumbnail on the screen: the stage page is the same for all of them,\n * and a list of forty cards asking for it forty times is forty renders of the site's layout.\n * Kept for the life of the panel — a site's stylesheets change with a deploy, and a deploy is\n * a reload of the panel anyway.\n */\nconst shells = new Map<string, Promise<string | null>>()\n\nexport function loadShell(url: string): Promise<string | null> {\n let shell = shells.get(url)\n\n if (shell === undefined) {\n shell = fetch(url, { credentials: 'same-origin', headers: { Accept: 'text/html' } })\n .then((response) => (response.ok ? response.text() : null))\n .then((html) => (html === null ? null : siteShell(html, url)))\n // Not allowed to see the stage, or no stage at all: the thumbnail draws the block bare,\n // which is what it did before there was one.\n .catch(() => null)\n shells.set(url, shell)\n }\n\n return shell\n}\n\n/**\n * The site's shell for thumbnails, once it has arrived; null until then and wherever there is\n * none. Outside a panel (a test, a screen of a project's own) there is no manifest to name the\n * stage, and the thumbnail stays bare rather than failing.\n */\nexport function useSiteShell(): Ref<string | null> {\n const admin = inject(adminKey, null)\n const shell = ref<string | null>(null)\n\n const url = computed(() => {\n const meta = admin?.state.manifest?.modules.find((module) => module.id === 'blocks')?.meta\n const stage = meta?.stage\n\n return typeof stage === 'string' && stage !== '' ? stage : null\n })\n\n watchEffect(() => {\n const current = url.value\n if (current === null) return\n\n void loadShell(current).then((loaded) => {\n if (url.value === current) shell.value = loaded\n })\n })\n\n return shell\n}\n\n/** For tests: forget what was loaded. */\nexport function forgetShells(): void {\n shells.clear()\n}\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, ref } from 'vue'\nimport { useElementWidth, WxIcon } from '@webx-ui/core'\nimport { stageDocument, thumbDocument } from './frame'\nimport { useSiteShell } from './shell'\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 *\n * Drawn in the site's own clothes when the site has a stage: its stylesheets and fonts, and\n * the wrappers the block sits in on a page, without the header, the footer or any script\n * (see `siteShell`). Bare until that arrives, and bare where there is none.\n *\n * `fit` is for components. A block is a band of a page, and the top of it at full width is the\n * right picture; a component is a whole thing — a card taller than it is wide — and cut to the\n * height of the box it shows only its photo. So with `fit` the root of what was drawn is measured\n * inside the frame and scaled to fit the box both ways, in the middle of it.\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 /** Scale what was drawn to fit the box, rather than the width to fill it. */\n fit?: boolean\n }>(),\n { width: 1280, height: 120, fit: false },\n)\n\nconst box = ref<HTMLElement | null>(null)\nconst boxWidth = useElementWidth(box)\n\n/** The root of what was drawn, in the frame's pixels; null until the frame has loaded. */\nconst drawn = ref<{ left: number; top: number; width: number; height: number } | null>(null)\n\n/*\n * How tall the frame is before scaling, when fitting. Tall enough for a card to lay itself out\n * at its own height rather than squeezed into the box's; a layout in `vh` sees this too.\n */\nconst TALL = 1600\n\nconst widthScale = computed(() => (boxWidth.value > 0 ? boxWidth.value / props.width : 0.2))\n\nconst fitted = computed(() => {\n const rect = drawn.value\n\n if (!props.fit || !rect || rect.width <= 0 || rect.height <= 0 || boxWidth.value <= 0) {\n return null\n }\n\n // Never larger than the width scale: a small badge stays small rather than blown up.\n const scale = Math.min(widthScale.value, boxWidth.value / rect.width, props.height / rect.height)\n\n return {\n scale,\n x: (boxWidth.value - rect.width * scale) / 2 - rect.left * scale,\n y: (props.height - rect.height * scale) / 2 - rect.top * scale,\n }\n})\n\nconst shell = useSiteShell()\n\nconst srcdoc = computed(() => {\n if (!props.thumbnail) return ''\n\n const input = { html: props.thumbnail.html, styles: props.thumbnail.styles }\n\n return shell.value ? thumbDocument(shell.value, input) : stageDocument(input)\n})\n\nconst frameStyle = computed(() => {\n const fit = fitted.value\n\n const rect = drawn.value\n\n if (fit && rect) {\n return {\n width: `${props.width}px`,\n height: `${TALL}px`,\n transform: `translate(${fit.x}px, ${fit.y}px) scale(${fit.scale})`,\n // The component alone: the rest of the frame is a white page around it, and moved off\n // the corner it shows as a white slab beside a small badge.\n clipPath: `inset(${rect.top}px ${props.width - rect.left - rect.width}px ${TALL - rect.top - rect.height}px ${rect.left}px)`,\n }\n }\n\n return {\n width: `${props.width}px`,\n height: props.fit ? `${TALL}px` : `${Math.round(props.height / widthScale.value)}px`,\n transform: `scale(${widthScale.value})`,\n // Until it is measured, a fitted frame would flash its top at the wrong scale; measured and\n // found to have no size (a root with `display: contents`), it is drawn the ordinary way.\n visibility: props.fit && drawn.value === null ? ('hidden' as const) : undefined,\n }\n})\n\nlet observer: ResizeObserver | null = null\n\n/*\n * Measured inside the frame, and watched from inside it: a ResizeObserver belongs to its own\n * window and does not see another document's elements, and fonts and pictures arriving late\n * change the card's height after the load event.\n */\nfunction onLoad(event: Event): void {\n if (!props.fit) return\n\n observer?.disconnect()\n\n const frame = event.target as HTMLIFrameElement\n const view = frame.contentWindow as (Window & typeof globalThis) | null\n const doc = frame.contentDocument\n\n if (!view || !doc?.body) return\n\n const root = doc.querySelector<HTMLElement>('[data-wx-block]') ?? doc.body\n\n const measure = (): void => {\n const rect = root.getBoundingClientRect()\n\n drawn.value = { left: rect.left, top: rect.top, width: rect.width, height: rect.height }\n }\n\n measure()\n observer = new view.ResizeObserver(measure)\n observer.observe(root)\n}\n\nonBeforeUnmount(() => observer?.disconnect())\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 @load=\"onLoad\"\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","import type { ScreenNode } from '@webx-ui/schema'\nimport { isNodeList, locate, nestedFields } from './content'\nimport type { BlockNode, BlockType } from './types'\n\n/**\n * May a block of this type stand here: the container's say-so and the type's own, both.\n *\n * `parent` is the block whose field it is, or null for the page; `allow` is what that field\n * narrows it to, when it does. The picker asks this for a new block and \"Move to\" for an\n * existing one, and the two must not disagree about where a block can go.\n */\nexport function allows(type: BlockType, parent: BlockType | null, allow: string[] | null): boolean {\n if (parent === null) {\n const fieldAllows = allow === null || allow.includes(type.slug)\n\n return fieldAllows && (type.allowed_in === null || type.allowed_in.includes('root'))\n }\n\n const parentAllows = allow\n ? allow.includes(type.slug)\n : parent.allow?.includes(type.slug) === true\n const typeAllows = type.allowed_in === null || type.allowed_in.includes(parent.slug)\n\n return parentAllows && typeAllows\n}\n\n/** One list a block could be moved into. */\nexport interface Destination {\n /** The container, or null for the top level. */\n parentKey: string | null\n field: string | null\n /** The containers down to it, in words, outermost first. Empty at the top level. */\n trail: string[]\n /** It already holds as many blocks as its field takes. */\n full: boolean\n}\n\n/** What the top level is: the page, or — in a block's sample form — that block. */\nexport interface TopLevel {\n owner: BlockType | null\n allow: string[] | null\n max: number | null\n}\n\n/**\n * Every list a block may be moved into, in the order the page draws them.\n *\n * Not the list it is in already — that is a drag — and nothing inside the block itself, which\n * would take it out of the tree along with its own children. A block of an unknown type goes\n * nowhere: there is nothing to judge the rules by.\n */\nexport function destinations(\n tree: BlockNode[],\n key: string,\n catalog: BlockType[],\n top: TopLevel,\n): Destination[] {\n const moving = locate(tree, key)\n const type = moving ? catalog.find((entry) => entry.slug === moving.node.type) : undefined\n\n if (!moving || !type) return []\n\n const found: Destination[] = []\n const here = (parentKey: string | null, field: string | null) =>\n (moving.parent?.key ?? null) === parentKey && moving.field === field\n\n if (!here(null, null) && allows(type, top.owner, top.allow)) {\n found.push({\n parentKey: null,\n field: null,\n trail: [],\n full: top.max !== null && tree.length >= top.max,\n })\n }\n\n const visit = (list: BlockNode[], trail: string[]) => {\n for (const node of list) {\n if (node.key === key) continue\n\n const container = catalog.find((entry) => entry.slug === node.type)\n const fields: ScreenNode[] = container?.content ? nestedFields(container.content.schema) : []\n\n for (const slot of fields) {\n const title = container!.title\n const step = fields.length > 1 ? `${title} · ${slot.label ?? slot.id}` : title\n const value = node.values[slot.id]\n const children = isNodeList(value) ? value : []\n const max = (slot.props?.max as number | undefined) ?? null\n const allow = (slot.props?.allow as string[] | undefined) ?? null\n\n if (!here(node.key, slot.id) && allows(type, container!, allow)) {\n found.push({\n parentKey: node.key,\n field: slot.id,\n trail: [...trail, step],\n full: max !== null && children.length >= max,\n })\n }\n\n visit(children, [...trail, step])\n }\n }\n }\n\n visit(tree, [])\n\n return found\n}\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 { allows } from './move'\nimport { useBlocksMessages } from './i18n'\nimport { groupLabel, kindOf } 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 same rule \"Move to\" goes by. */\nfunction allowedHere(type: BlockType): boolean {\n return allows(type, props.parent, props.allow)\n}\n\n/*\n * A component is never put on a page by hand: it is called from a template, and its schema is\n * what the caller passes, not a form an editor could fill. The server's catalogue leaves them\n * out already (§3.10); this is for a catalogue that came from somewhere else.\n */\nconst options = computed<Option[]>(() =>\n props.catalog\n .filter(\n (type) =>\n kindOf(type) !== 'component' &&\n type.is_enabled &&\n type.published !== null &&\n allowedHere(type),\n )\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, nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { useElementWidth, WxAction, 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. The whole page at desktop width, unless the bar is asked for a\n * tablet or a phone; full screen is for the panel too narrow to read a desktop in.\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 /** Bumped by the host to reload the page. */\n reload?: number\n /**\n * The preview is the screen rather than a column beside one — the shape the panel takes\n * on a phone. It starts as a phone, and its bar carries the way into the blocks, because\n * there is no tree standing next to it to click.\n */\n compact?: boolean\n }>(),\n { selected: null, reload: 0, compact: 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 /** The way into the blocks was asked for. Only ever emitted while `compact`. */\n edit: []\n}>()\n\nconst t = useTranslate('webx-blocks')\n\nconst frame = ref<HTMLIFrameElement | null>(null)\n/* The bar, measured rather than assumed: it floats over the top of the window, and how much\n of the window it takes is what a block is kept clear of. */\nconst bar = ref<HTMLElement | null>(null)\nconst box = ref<HTMLElement | null>(null)\nconst boxWidth = useElementWidth(box)\nconst fullscreen = ref(false)\nconst ready = ref(false)\n\n/*\n * The width asked for by hand, and null for the whole page.\n *\n * Nothing chooses it but the person looking: the preview used to be squeezed into a phone\n * while a block was open, because the column it stood in was 420 px wide and a desktop does\n * not go in there. It is not squeezed any more — the form took the tree's place instead of\n * taking the preview's room — so there is nothing left to guess at.\n */\nconst picked = ref<number | null>(null)\n\n/*\n * The height of the page inside, so that the frame is exactly as tall as what it shows and\n * nothing scrolls in a box of ours: a block taller than the window is read by scrolling the\n * panel, the way the page it belongs to is read.\n *\n * Zero while it cannot be measured — a page from another origin — and then the frame keeps\n * the window-sized height the stylesheet gives it.\n */\nconst contentHeight = ref(0)\n\n/**\n * Told how tall to be by the page inside — in every mode, full screen included.\n *\n * Full screen used to be the exception, a window of a fixed height with the page scrolling\n * inside it, and that exception is what made it useless on a phone: a frame that does not\n * scale shows a 1280 px page through a 375 px slot. One rule now — the frame is as tall as\n * its page and as wide as it fits — and who scrolls it is all that differs: the panel in a\n * column, the sheet's own ground in full screen.\n */\nconst grown = computed(() => contentHeight.value > 0)\n\n/* Words as the accessible name, pictures on screen: three words do not fit a bar this narrow\n and a device is one of the few things a picture says faster than a word anyway. */\nconst widths = computed(() => [\n { value: 1280, icon: 'monitor', ariaLabel: t('field.width-desktop') },\n { value: 834, icon: 'tablet', ariaLabel: t('field.width-tablet') },\n { value: 390, icon: 'smartphone', ariaLabel: t('field.width-phone') },\n])\n\n/**\n * The width nobody asked for: the one that suits the room.\n *\n * Where the preview is the screen, that screen is usually a phone, and a 1280 px page on it\n * is a page nobody can read at the 0.3 the scale would say. A tablet is the same shape of\n * screen with twice the room, and a phone drawn in the middle of it wastes half — so the\n * middle width is the one it starts at. A column beside a tree starts at the whole page.\n */\nconst width = computed(() => {\n if (picked.value !== null) return picked.value\n if (!props.compact) return 1280\n\n return boxWidth.value > 0 && boxWidth.value < 560 ? 390 : 834\n})\n\nconst scale = computed(() => {\n if (boxWidth.value === 0) return 1\n\n /*\n * Whatever it takes to fit, and never more than one to one. The phone used to be excepted\n * from this, back when the phone was the only narrow width there was and the column it\n * stands in is wider than 390 anyway — the exception said nothing then and lies now, when\n * a tablet can be asked for in that same column.\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 ...(grown.value ? { height: `${contentHeight.value}px` } : {}),\n}))\n\n/*\n * The scale is a transform, and a transform does not move the layout: the frame keeps the\n * box it was given whatever it is drawn at. So the hole it is drawn through is the one that\n * carries the size the column actually sees — the frame's own, times the scale.\n */\nconst clipStyle = computed(() => ({\n width: `${Math.round(width.value * scale.value)}px`,\n ...(grown.value ? { height: `${Math.round(contentHeight.value * scale.value)}px` } : {}),\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/* Watches the page inside grow and shrink; released with the document it was watching. */\nlet watcher: ResizeObserver | null = null\n\n/**\n * How tall the page inside is.\n *\n * Off the body, and never off `documentElement.scrollHeight`: that one is never smaller than\n * the frame's own window, so once the frame has been made as tall as the page it stops being\n * a measurement of the page at all — it measures the frame, and a page that gets shorter\n * never gets its height back. The body is the tallest thing the page actually drew, and its\n * margins are part of what it drew.\n */\n/**\n * Undo any scrolling of the page inside.\n *\n * A frame as tall as its page shows it from the top and from nowhere else, so a scroll in\n * there is always something that got there by accident — and what it leaves behind is a\n * preview missing its beginning, with blank frame under its end and no way to scroll back,\n * because the wheel over it moves the panel.\n */\nfunction pin(page: Document): void {\n if (page.documentElement.scrollTop !== 0) page.documentElement.scrollTop = 0\n}\n\nfunction measure(): void {\n const page = doc()\n const body = page?.body\n\n if (!body || !page?.defaultView) return\n\n pin(page)\n\n const style = page.defaultView.getComputedStyle(body)\n const margins = (parseFloat(style.marginTop) || 0) + (parseFloat(style.marginBottom) || 0)\n const height = Math.ceil(body.scrollHeight + margins)\n\n if (height === contentHeight.value) return\n\n contentHeight.value = height\n\n /* The frame takes the new height on the next tick, and the panel is laid out again after\n that: a block asked for in between has to be asked for once more. */\n if (pending !== null) void nextTick(() => requestAnimationFrame(bring))\n}\n\nfunction watch_(page: Document): void {\n watcher?.disconnect()\n\n const view = page.defaultView\n\n if (!view || !page.body) return\n\n /* The frame's own `ResizeObserver`, not ours: an observer belongs to the window whose\n elements it watches, and one made out here never fires for a document in there. */\n watcher = new view.ResizeObserver(measure)\n watcher.observe(page.body)\n measure()\n}\n\nfunction onLoad(): void {\n ready.value = true\n\n const page = doc()\n\n if (!page) return\n\n watch_(page)\n\n binding?.release()\n binding = bindFrame(page, {\n /* No guard against answering a click with a scroll: `bring` moves nothing that is already\n readable, and a block clicked at the very bottom of the window, half under the action\n bar, is exactly the one worth moving. */\n select: (key) => emit('select', key),\n })\n\n highlightBlock(page, props.selected ?? null)\n reveal(props.selected ?? null)\n}\n\n/*\n * The block to bring into view, and the timer that gives up on it.\n *\n * The page inside can still be settling — a width just changed, a picture just arrived — and\n * every such change moves the block and the frame under it. So the ask is kept for as long as\n * the measured height keeps moving rather than answered once, against a layout that is about\n * to change under it.\n */\nlet pending: string | null = null\nlet forget: number | null = null\n\n/**\n * Bring the selected block into view.\n *\n * `scrollIntoView` and nothing else: a frame as tall as its page has nothing to scroll, and\n * the browser walks out of it and scrolls the panel — which is the whole point of the frame\n * being that tall. A frame that could not be measured still scrolls in its own window, and\n * the same call does that too.\n */\nfunction reveal(key: string | null): void {\n if (key === null) return\n\n pending = key\n\n if (forget !== null) clearTimeout(forget)\n forget = window.setTimeout(() => {\n pending = null\n forget = null\n }, 400)\n\n bring()\n}\n\n/**\n * Where the block stands in the window of the panel, not in the window of the frame.\n *\n * The frame does not scroll — it is as tall as its page — so a rect taken inside it is an\n * offset from the frame's own top, and the scale is a transform, so what the panel sees is\n * that offset times the scale.\n */\nfunction place(el: Element): { top: number; height: number } | null {\n const box = frame.value?.getBoundingClientRect()\n\n if (!box) return null\n\n const rect = el.getBoundingClientRect()\n\n return { top: box.top + rect.top * scale.value, height: rect.height * scale.value }\n}\n\n/**\n * What the panel scrolls with: the box the preview stands in, or the window when nothing\n * between them scrolls. Walked rather than assumed, because the screen decides that, not us.\n */\nfunction scroller(): HTMLElement | null {\n let node = frame.value?.parentElement ?? null\n\n while (node) {\n const overflow = getComputedStyle(node).overflowY\n\n if ((overflow === 'auto' || overflow === 'scroll') && node.scrollHeight > node.clientHeight) {\n return node\n }\n\n node = node.parentElement\n }\n\n return null\n}\n\n/**\n * Bring the selected block into view, by as little as it takes and no more.\n *\n * Emphatically **not** `scrollIntoView`, which is what this used to be and what made the\n * preview lose the top of its page: that one scrolls every scrollable ancestor it can find,\n * and the document inside the frame is one of them. When the panel could not move far enough\n * on its own — a short page, a block near its end — the browser made up the difference by\n * scrolling the page *inside* the frame instead, which is the one thing the frame being as\n * tall as its page is there to prevent. The result was a preview starting in the middle of\n * its page with the rest of the frame blank, and no way to scroll it back.\n *\n * So the panel is moved by hand, and nothing else is touched. Only enough to bring the block\n * in, never to centre it. The window is counted a bar short at each end — this preview's own\n * bar floats over the top of it, the screen's action bar over the bottom — and a block too\n * tall to fit between them is put against the top, where reading it starts.\n */\nfunction bring(): void {\n const page = doc()\n\n if (pending === null || !page) return\n\n /* Before anything is measured against it: the arithmetic below reads a rect taken inside\n the frame as an offset from the frame's top, which it only is while the page in there\n stands where it was put. */\n pin(page)\n\n const el = blockElement(page, pending)\n const at = el ? place(el) : null\n\n if (!at) return\n\n const box = scroller()\n const rect = box?.getBoundingClientRect()\n const room = bar.value?.getBoundingClientRect().height ?? 0\n const band = {\n top: (rect?.top ?? 0) + room,\n bottom: (rect ? rect.bottom : window.innerHeight) - room,\n }\n const foot = at.top + at.height\n const above = at.top < band.top\n const tall = at.height > band.bottom - band.top\n const delta = above || tall ? at.top - band.top : foot > band.bottom ? foot - band.bottom : 0\n\n if (delta === 0) return\n\n ;(box ?? window).scrollBy({ top: delta, behavior: 'smooth' })\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 watcher?.disconnect()\n watcher = null\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(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 if (forget !== null) clearTimeout(forget)\n watcher?.disconnect()\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-grown': grown, 'is-compact': compact }\"\n :style=\"{ '--wx-preview-scale': scale }\"\n >\n <div ref=\"bar\" class=\"wx-blocks-preview__bar\">\n <wx-text size=\"xs\" tone=\"muted\" class=\"wx-blocks-preview__label\" truncate>{{\n label\n }}</wx-text>\n <wx-segmented\n class=\"wx-blocks-preview__widths\"\n :model-value=\"width\"\n :options=\"widths\"\n size=\"sm\"\n :aria-label=\"t('field.width')\"\n @update:model-value=\"picked = Number($event)\"\n />\n <!-- A plain row and not `WxActions`: two buttons that never collapse into anything, and\n a row that can collapse renders a dropdown beside itself — a second root, which no\n scoped rule of ours would then reach. -->\n <div class=\"wx-blocks-preview__tools\">\n <!-- The way into the blocks, and only where the preview is the whole screen: with a\n tree beside it this would be a second door into the room you are standing in. -->\n <wx-action\n v-if=\"compact\"\n size=\"sm\"\n tone=\"primary\"\n icon=\"edit\"\n :title=\"t('field.blocks')\"\n @click=\"emit('edit')\"\n />\n <wx-action\n v-if=\"url\"\n size=\"sm\"\n icon=\"external-link\"\n tone=\"neutral\"\n :title=\"t('field.open-site')\"\n :href=\"url\"\n target=\"_blank\"\n rel=\"noopener\"\n />\n <wx-action\n size=\"sm\"\n :icon=\"fullscreen ? 'minimize' : 'maximize'\"\n tone=\"neutral\"\n :title=\"fullscreen ? t('field.close') : t('field.fullscreen')\"\n @click=\"fullscreen = !fullscreen\"\n />\n </div>\n </div>\n <div ref=\"box\" class=\"wx-blocks-preview__ground\">\n <div class=\"wx-blocks-preview__clip\" :style=\"clipStyle\">\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 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 /*\n * `clip` and not `hidden`, because of the sticky bar below: `hidden` makes the box a scroll\n * container — one that never scrolls, since nothing here overflows it — and a sticky child\n * sticks to the nearest one of those. It would have been pinned to a box that does not\n * move, which looks exactly like `position: sticky` having no effect at all. `clip` cuts\n * the corners off the frame just the same and leaves the page as the thing that scrolls.\n */\n overflow: clip;\n min-width: 0;\n}\n\n/*\n * Over the panel, header and all.\n *\n * It used to carry a bare `40`, which is below everything the panel stacks with — so on a\n * phone, where the preview is the whole screen, it opened *under* the sticky header and its\n * own bar went with it: the way out was behind the burger. The overlay layer is what a sheet\n * covering the page belongs to; toasts still land on top of it, which is right, because a\n * toast is the only thing that has something to say while this is open.\n */\n.wx-blocks-preview.is-fullscreen {\n position: fixed;\n inset: 0;\n z-index: var(--wx-z-index-overlay);\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/*\n * The bar stays while the page under it goes by — the width, the way out and the address\n * belong to the whole preview, and a preview that is now as tall as its page would otherwise\n * take all three off the screen with the first scroll.\n *\n * Against the top of the window and not at the offset the tree and the form stick at: sticking\n * moves the bar, not the page under it, so an offset leaves a gap that the page inside goes on\n * showing through — twelve pixels of a headline sliding past above the bar. It needs a\n * background of its own for the same reason, the card's not travelling to a child.\n *\n * Never in full screen. There the card is `position: fixed`, so nothing inside it scrolls with\n * the document at all, and the offset would simply push the bar 12px down from where it\n * already is.\n */\n.wx-blocks-preview:not(.is-fullscreen) .wx-blocks-preview__bar {\n position: sticky;\n top: 0;\n z-index: 1;\n background: var(--wx-bg-surface);\n}\n\n/*\n * Three parts, and the middle one in the middle: the two sides share whatever the widths\n * control leaves, so it sits at the centre of the bar rather than wherever the address\n * happens to end. `flex: 1 1 0` and not `auto` — from zero, so that a long address takes no\n * more room than the buttons opposite it and the control stays put.\n */\n.wx-blocks-preview__label {\n flex: 1 1 0;\n min-width: 0;\n font-family: var(--wx-font-family-mono);\n}\n\n.wx-blocks-preview__widths {\n flex: none;\n}\n\n.wx-blocks-preview__tools {\n display: flex;\n flex: 1 1 0;\n gap: var(--wx-space-4);\n align-items: center;\n justify-content: flex-end;\n}\n\n/*\n * The cap and the scrollbar are what is left for a page that cannot be measured — one from\n * another origin. A page that can be is given the frame its own height, and then this box\n * has nothing to scroll: see `is-grown` below.\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 * No grey either side of the page where the preview is the screen.\n *\n * Twelve pixels at each edge is a frame around a picture on a desktop and a sixteenth of the\n * screen on a phone — and worse than the width it costs is what it does to the eye: the page\n * ends up narrower than the card it is in, which is the same width as the bar and the header,\n * so the one thing the whole screen is about looks like the one thing that is out of line.\n */\n.is-compact .wx-blocks-preview__ground {\n padding-inline: 0;\n}\n\n/*\n * As tall as the page inside, and the panel scrolls.\n *\n * A window of ours over a page that has its own window is two scrollbars for one document,\n * and the inner one is the one nobody can reach with the wheel over the panel: a block taller\n * than the window could not be seen whole at all. Now there is one scroll, the browser's, and\n * the frame ends where the page does.\n *\n * Full screen keeps its own, because there the sheet is fixed to the window and the page\n * behind it does not move: the ground is the only thing left that can scroll.\n */\n.is-grown:not(.is-fullscreen) .wx-blocks-preview__ground {\n overflow: visible;\n max-height: none;\n}\n\n.wx-blocks-preview__clip {\n margin-inline: auto;\n overflow: hidden;\n box-shadow: var(--wx-shadow-sm);\n}\n\n/* The height here is the fallback for a page that cannot be measured — one from another\n origin. Everything else is told its height in pixels by the measurement. */\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</style>\n","<script setup lang=\"ts\">\nimport { useTranslate, WxRowMenu, type RowAction } from '@webx-ui/module-admin'\nimport { 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 but \"Move to\" in its menu:\n * a drag across allow-rules would need a judge at every drop, and a finger in a sheet has none.\n */\nconst props = withDefaults(\n defineProps<{\n nodes: BlockNode[]\n catalog: BlockType[]\n parentKey?: string | null\n field?: string | null\n /** The field this level is, for its allow-list and limit; none at the top. */\n fieldNode?: ScreenNode | null\n /** How many blocks this level takes; a nested level reads it off its slot. */\n max?: number | null\n selected?: string | null\n disabled?: boolean\n depth?: number\n }>(),\n {\n parentKey: null,\n field: null,\n fieldNode: null,\n max: null,\n selected: null,\n disabled: false,\n depth: 0,\n },\n)\n\nconst emit = defineEmits<{\n select: [key: string]\n /** `index` is where the block goes; without it, at the end of the list. */\n add: [parentKey: string | null, field: string | null, node: ScreenNode | null, index?: number]\n remove: [key: string]\n duplicate: [key: string]\n move: [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\n/**\n * What a block offers, as the panel's own `···` rather than a row of icons.\n *\n * Three bare icons on a row that is itself a click target is three chances to hit the wrong\n * one, and the tree is the narrowest column on the screen: at the width a nested block has,\n * the icons took the name's place and the row read as a dash. The menu also has room for the\n * word, which an icon only says to whoever has already learned it (§20).\n */\nfunction actionsFor(node: BlockNode, index: number): RowAction[] {\n const limit = props.fieldNode\n ? ((props.fieldNode.props?.max as number | undefined) ?? null)\n : props.max\n\n return [\n /*\n * The button under the list only appends, so a block meant for the middle of a long page\n * was a trip to the bottom and a drag all the way back up. This one puts it where the\n * editor already is. Not \"add before\": after the row above is the same place.\n */\n {\n key: 'add-after',\n icon: 'plus',\n label: t('field.add-after'),\n disabled: limit !== null && props.nodes.length >= limit,\n run: () => emit('add', props.parentKey, props.field, props.fieldNode, index + 1),\n },\n {\n key: 'visibility',\n icon: node.hidden === true ? 'eye' : 'eye-off',\n label: node.hidden === true ? t('field.show') : t('field.hide'),\n run: () => emit('visibility', node.key, node.hidden !== true),\n },\n {\n key: 'duplicate',\n icon: 'copy',\n label: t('field.duplicate'),\n run: () => emit('duplicate', node.key),\n },\n {\n key: 'move',\n icon: 'arrow-right',\n label: t('field.move'),\n run: () => emit('move', node.key),\n },\n {\n key: 'remove',\n icon: 'trash',\n label: t('field.remove'),\n danger: true,\n run: () => emit('remove', node.key),\n },\n ]\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, index }\">\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__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\">\n <wx-row-menu :actions=\"actionsFor(item, index)\" :label=\"titleOf(item)\" />\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 :field-node=\"slot\"\n :selected=\"selected\"\n :disabled=\"disabled\"\n :depth=\"depth + 1\"\n @select=\"emit('select', $event)\"\n @add=\"(p, f, n, i) => emit('add', p, f, n, i)\"\n @remove=\"emit('remove', $event)\"\n @duplicate=\"emit('duplicate', $event)\"\n @move=\"emit('move', $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__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 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/*\n * There at rest, not on hover. The icons that used to live here appeared under the pointer,\n * which on a phone is nowhere: a tree that can be built with a finger has to be one a finger\n * can also take a block out of. One quiet `···` is affordable in a way three icons were not.\n */\n.wx-blocks-tree__actions {\n display: flex;\n flex: none;\n}\n\n/*\n * Small to look at, big to hit.\n *\n * A collapsed row of actions gives its menu 44 px on a coarse pointer, which is the size of a\n * fingertip and the right size for the target. It is not the right size for the picture: in a\n * row that is a name and one `···`, a 44 px button reads as a third of the row. So the button\n * is drawn at 32 and the missing twelve are given back as an invisible skirt around it — the\n * target stays a fingertip, the row stops looking like a button with a name beside it.\n *\n * The extra `.wx-actions__menu` in the selector is not decoration: the rule it overrides sets\n * the same property on the same element at the same specificity, and without it the winner\n * would be whichever stylesheet the bundler happened to put last.\n */\n@media (pointer: coarse) {\n .wx-blocks-tree__actions :deep(.wx-actions__menu .wx-action) {\n --wx-action-size: 32px;\n position: relative;\n }\n\n .wx-blocks-tree__actions :deep(.wx-actions__menu .wx-action)::after {\n content: '';\n position: absolute;\n inset: -6px;\n }\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","<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 {\n confirm,\n createModal,\n toast,\n useElementWidth,\n WxAction,\n WxButton,\n WxDrawer,\n WxIcon,\n WxText,\n} 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 BlockMoveDialog from './BlockMoveDialog.vue'\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 walk,\n} from './content'\nimport { useBlocksMessages } from './i18n'\nimport { blocksOwnerKey, blocksPreviewKey, blocksRootKey } from './preview'\nimport { destinations, type Destination } from './move'\nimport { formSchema } from './schema'\nimport type { BlockNode, BlockType } from './types'\n\n/**\n * The constructor — the `wx-blocks` field.\n *\n * Two states (§14), and two columns in both of them. The narrow one holds the tree, or the\n * open block's form in its place; the wide one holds the preview of the whole page, at the\n * width the preview's own bar is set to. One column of the two changes, the other does not:\n * the page under the form is the page the form is about, and it neither moves nor shrinks\n * when a block is opened.\n *\n * Inside a block's own form the same node type means a nested constructor, and those are\n * edited in the tree — 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 {\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 },\n)\n\nconst model = defineModel<BlockNode[]>({ default: () => [] })\n\nconst nested = inject(blocksRootKey, false)\n/* Inside the block editor's sample form, the top level is that block rather than a page. */\nconst owner = inject(blocksOwnerKey, null)\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\n/** What a block is called in the catalogue, falling back to the raw type. */\nfunction titleOf(node: BlockNode): string {\n return catalog.value.find((type) => type.slug === node.type)?.title ?? node.type\n}\n\n/**\n * Every block of the page in the order the page draws them, nested ones included — the tree\n * flattened, which is what \"the next block\" means with the tree off the screen.\n */\nconst order = computed(() => {\n const keys: string[] = []\n\n walk(tree.value, (node) => keys.push(node.key))\n\n return keys\n})\n\n/** The block before the open one and the block after it, null at either end. */\nconst steps = computed(() => {\n const at = selectedKey.value ? order.value.indexOf(selectedKey.value) : -1\n\n return {\n previous: at > 0 ? order.value[at - 1]! : null,\n next: at >= 0 && at < order.value.length - 1 ? order.value[at + 1]! : null,\n }\n})\n\n/** The blocks the open one is inside, outermost first. Empty at the top level. */\nconst trail = computed(() => {\n const steps: { key: string; title: string }[] = []\n\n let at = selected.value?.parent ?? null\n\n while (at) {\n steps.unshift({ key: at.key, title: titleOf(at) })\n at = locate(tree.value, at.key)?.parent ?? null\n }\n\n return steps\n})\n\nconst preview = inject(blocksPreviewKey, null)\nconst previewEl = ref<InstanceType<typeof BlocksPreview> | null>(null)\n\nconst host = ref<HTMLElement | null>(null)\nconst hostWidth = useElementWidth(host)\n\n/**\n * The panel has room for the page and one thing beside it, or for the page alone.\n *\n * Measured and not asked of CSS, because what changes is not the arrangement but where the\n * tree and the form are rendered — a column of the grid, or a sheet over the page. The\n * threshold is the narrow column at its widest plus a preview still worth looking at: below\n * it the preview would be drawn at a third of its size, which is a picture, not a page.\n *\n * Only with a preview, and that is not a detail: the way into the sheet is a button on the\n * preview's bar, so without one the sheet would be a room with no door.\n */\nconst hasPreview = computed(() => preview !== null && preview.url.value !== null)\nconst compact = computed(() => hasPreview.value && hostWidth.value > 0 && hostWidth.value <= 900)\n\n/** Open while the blocks are being worked on over the page. Compact panels only. */\nconst sheet = ref(false)\n\n/** What the sheet is showing: the open block with its containers, or the list. */\nconst sheetTitle = computed(() => {\n if (!selected.value) return undefined\n\n const name = selectedType.value?.title ?? selected.value.node.type\n\n return [...trail.value.map((step) => step.title), name].join(' / ')\n})\n\nconst sideProps = computed(() =>\n compact.value\n ? {\n /* Up from the bottom, and not all the way: the strip of page left above it is what\n says the sheet is over the page rather than instead of it. No heading of its own —\n the panels inside carry theirs, and the × is the one thing the sheet has to add. */\n side: 'bottom' as const,\n size: '88%',\n /* Off, or the size above is ignored on exactly the screens this is for: a drawer\n takes a narrow screen whole unless it is told not to. */\n fullScreen: false,\n closable: true,\n closeLabel: t('field.close'),\n ariaLabel: t('field.blocks'),\n /* The open block's name goes in the sheet's own head, where there is a whole line for\n it: in the form's head it shared a row with four controls and wrapped onto two. With\n the blocks it is inside spelled out in front of it, because the trail that says so\n in the column is part of the heading this replaces. The tree keeps its own heading,\n which already says what it is and how many. */\n title: sheetTitle.value,\n open: sheet.value,\n 'onUpdate:open': (value: boolean) => (sheet.value = value),\n }\n : {},\n)\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 index?: number,\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 : (owner?.value ?? 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, index ?? 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 * Always a question, and the question says what is leaving.\n *\n * A single block used to go without one — one row in a tree that is right there, with a draft\n * that kept a version of it. That was wrong twice over: the row says the block's type and not\n * its words, so what vanished was never named, and a page is edited by pointing at things. A\n * container says how much goes with it, because that part is not on screen: collapse a section\n * 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 const agreed = await confirm({\n title: t('field.remove-title', {\n title: catalog.value.find((type) => type.slug === found.node.type)?.title ?? found.node.type,\n }),\n message: inside > 0 ? t('field.remove-text', { count: inside }) : t('field.remove-alone'),\n confirmText: t('field.remove'),\n cancelText: t('page.cancel'),\n tone: 'danger',\n })\n\n if (!agreed) return\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\nconst chooseDestination = createModal<\n Destination,\n { title: string; destinations: Destination[]; topLabel: string }\n>(BlockMoveDialog)\n\n/**\n * Into another container, or out to the top level, at the end of that list.\n *\n * The block goes whole, children and keys included: it is the same block in a new place, not\n * a copy, so the preview's markers and anything pointing at its key still find it.\n */\nasync function move(key: string): Promise<void> {\n const found = locate(tree.value, key)\n if (!found) return\n\n const place = await chooseDestination({\n title: titleOf(found.node),\n destinations: destinations(tree.value, key, catalog.value, {\n owner: owner?.value ?? null,\n allow: props.allow,\n max: props.max,\n }),\n topLabel: owner?.value?.title ?? t('field.move-page'),\n })\n\n if (!place) return\n\n const without = removeNode(tree.value, key)\n set(insertNode(without, place.parentKey, place.field, Number.MAX_SAFE_INTEGER, found.node))\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 /* On a phone the block clicked in the page opens for editing where the editing lives. */\n if (compact.value) sheet.value = true\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 <div v-else ref=\"host\" class=\"wx-blocks-host\" :class=\"{ 'is-compact': compact }\">\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 <!--\n The tree and the form share one column and take turns in it.\n\n They are two views of the same thing — the blocks of this page — and a page has room\n for one of them beside a preview, not two. Side by side the form took whatever the\n preview was not given, and the preview was given the 420 px a desktop does not fit in:\n every block was edited against a picture of a phone. The way back out is the done\n button, or Escape; the way to the next block is in the form's own head.\n\n On a narrow panel that column is a sheet instead, and the same two panels take turns\n inside it — which is why they are wrapped rather than written twice. A phone has room\n for one thing at a time, and the thing worth the room is the page itself.\n -->\n <component :is=\"compact ? WxDrawer : 'div'\" v-bind=\"sideProps\" class=\"wx-blocks__side\">\n <div v-if=\"!selected\" 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 <div class=\"wx-blocks__list\">\n <blocks-tree\n :nodes=\"tree\"\n :catalog=\"catalog\"\n :max=\"max\"\n :selected=\"selectedKey\"\n :disabled=\"disabled\"\n @select=\"select\"\n @add=\"add\"\n @remove=\"remove\"\n @duplicate=\"duplicate\"\n @move=\"move\"\n @visibility=\"visibility\"\n @reorder=\"reorder\"\n />\n </div>\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 <!-- Not in the sheet: the preview is what the sheet is covering. -->\n <wx-button\n v-if=\"!compact && 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 <!-- The blocks this one is inside, because the tree that used to show them is\n not on screen while it is open. Nothing at all at the top level. -->\n <span v-if=\"trail.length\" class=\"wx-blocks__trail\">\n <template v-for=\"step in trail\" :key=\"step.key\">\n <button type=\"button\" class=\"wx-blocks__trail-step\" @click=\"select(step.key)\">\n {{ step.title }}\n </button>\n <wx-icon name=\"chevron-right\" />\n </template>\n </span>\n <span class=\"wx-blocks__panel-name\">{{\n selectedType?.title ?? selected.node.type\n }}</span>\n </span>\n <span class=\"wx-blocks__panel-extra\">\n <!-- Not in the sheet: the identifier is for whoever writes the block type, and\n the phone is where somebody fills one in. It costs a slot in a row of four\n controls, and the name above already says which block this is. -->\n <code v-if=\"!compact\">{{ selected.node.type }}</code>\n <!-- The tree's next row and previous row, kept where the tree is not. Every block\n of the page in the order the page draws them, nested ones included. -->\n <wx-action\n size=\"sm\"\n tone=\"neutral\"\n icon=\"chevron-up\"\n :title=\"t('field.previous')\"\n :disabled=\"steps.previous === null\"\n @click=\"steps.previous && select(steps.previous)\"\n />\n <wx-action\n size=\"sm\"\n tone=\"neutral\"\n icon=\"chevron-down\"\n :title=\"t('field.next')\"\n :disabled=\"steps.next === null\"\n @click=\"steps.next && select(steps.next)\"\n />\n <!-- The same button the tree's foot carries, and hidden by the same rule: below\n the width where the preview folds away, the tree's foot is not on screen\n while a block is open, and that is exactly when it is needed. -->\n <wx-button\n v-if=\"!compact && preview && preview.url.value\"\n size=\"sm\"\n variant=\"outline\"\n icon=\"eye\"\n class=\"wx-blocks__preview-button\"\n :aria-label=\"t('field.preview')\"\n @click=\"previewEl?.open()\"\n />\n <!-- The key is named only where there is one to press: a sheet on a phone is\n left by the button or by the × above it, and \"Esc\" there is a word about\n furniture nobody in the room has. -->\n <wx-button size=\"sm\" variant=\"outline\" @click=\"done\">{{\n compact ? t('field.done') : `${t('field.done')} · Esc`\n }}</wx-button>\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 </component>\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 :reload=\"preview.reload?.value ?? 0\"\n :compact=\"compact\"\n @select=\"selectFromPreview\"\n @edit=\"sheet = true\"\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 * One width for the tree and for the form, because they stand in the same column and taking\n * turns in it is the whole idea: a column that changed size would move the preview and\n * rescale it on every block opened, which is a bigger thing to watch than the room it saves.\n *\n * Twice what the tree used to have. It was 260, which cut the name of every block that was\n * not called something short, and the form that now shares the column needs more than that\n * anyway. The upper bound is what a form of fields reads well at rather than what is left\n * over, and the percentage is what gives a narrow panel back to the preview.\n */\n.wx-blocks {\n display: grid;\n grid-template-columns: clamp(360px, 34%, 520px) minmax(0, 1fr);\n gap: var(--wx-gap, var(--wx-space-16));\n align-items: start;\n}\n\n/* Without a preview there is no second column to leave room for. */\n.wx-blocks:not(.has-preview) {\n grid-template-columns: minmax(0, 1fr);\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 display: flex;\n align-items: center;\n gap: var(--wx-space-4);\n min-width: 0;\n font-weight: var(--wx-font-weight-semibold);\n}\n\n/* One line and an ellipsis: the head is a row of controls with a name in it, and a name that\n wraps pushes the row into two. The whole of it is one hover away, and in the sheet it is\n spelled out along the top anyway. */\n.wx-blocks__panel-name {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n/* In the sheet the name is the sheet's heading, on a line of its own. */\n.wx-drawer .wx-blocks__fields .wx-blocks__panel-title {\n display: none;\n}\n\n/* The way back up, and quieter than the block it leads to: the name of the open block is\n what the head is for. */\n.wx-blocks__trail {\n display: flex;\n align-items: center;\n gap: var(--wx-space-4);\n min-width: 0;\n color: var(--wx-text-muted);\n font-weight: var(--wx-font-weight-regular);\n font-size: var(--wx-font-size-sm);\n}\n\n.wx-blocks__trail-step {\n padding: 0;\n border: 0;\n background: none;\n color: inherit;\n font: inherit;\n cursor: pointer;\n white-space: nowrap;\n}\n\n.wx-blocks__trail-step:hover {\n color: var(--wx-text-default);\n text-decoration: underline;\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 * The narrow column stands still and scrolls inside itself. The tree is the one that makes\n * this worth doing: a page of twenty blocks is a column taller than the window, and without\n * 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 * The screen's action bar sticks to the same window and is drawn over this column, so the\n * room it announces comes off the cap as well, and the gap above it is the one at the top.\n *\n * What scrolls is the body of the card, not the column around it. The column used to be the\n * scroller, and the card inside it — border, radius and head — scrolled away with the fields:\n * the head with the done button went off the top, and the fields ran square past the corners\n * the card was supposed to have. So the column only caps, the card shrinks to the cap and clips\n * to its own radius, and its head and foot stay while the middle scrolls.\n */\n.wx-blocks-host:not(.is-compact) .wx-blocks__side {\n min-width: 0;\n position: sticky;\n top: var(--wx-space-12);\n max-height: calc(100dvh - var(--wx-space-24) - var(--wx-action-bar-room, 0px));\n display: flex;\n flex-direction: column;\n}\n\n.wx-blocks-host:not(.is-compact) .wx-blocks__tree,\n.wx-blocks-host:not(.is-compact) .wx-blocks__fields {\n min-height: 0;\n overflow: clip;\n}\n\n.wx-blocks__panel-head {\n flex: none;\n}\n\n/* The breathing room keeps the rows' focus rings inside the scroller, which would clip them. */\n.wx-blocks-host:not(.is-compact) .wx-blocks__list,\n.wx-blocks-host:not(.is-compact) .wx-blocks__form {\n min-height: 0;\n overflow: auto;\n overscroll-behavior: contain;\n}\n\n.wx-blocks-host:not(.is-compact) .wx-blocks__list {\n padding: var(--wx-space-2);\n margin: calc(-1 * var(--wx-space-2));\n}\n\n.wx-blocks__preview {\n min-width: 0;\n position: sticky;\n top: var(--wx-space-12);\n}\n\n/*\n * A preview as tall as the page it shows is taller than the window, and a sticky box taller\n * than the window pins its head and puts its foot out of reach — the end of the page could\n * never be scrolled to. It stands still instead, and the tree beside it is the one that\n * follows.\n *\n * Full screen is in here for a different reason: `position: sticky` makes a stacking context\n * whatever its `z-index` says, so the sheet inside — fixed, and over everything by its own\n * number — could only ever be over what is in this column. It opened *under* the action bar,\n * which sits lower in the panel's stack and higher in the document. Nothing looked wrong in\n * the rule that draws it; the column it came out of was the one that had to move.\n */\n.wx-blocks__preview:has(.is-grown),\n.wx-blocks__preview:has(.is-fullscreen) {\n position: static;\n}\n\n/* The foot of the tree: one row, the adding taking whatever the other one leaves. */\n/*\n * One row while they fit, a column the moment they do not.\n *\n * The tree is the narrowest column on the screen and the words on these two buttons are as\n * long as the language makes them: side by side in a 220px column they ran out over its edge\n * rather than wrapping, because a button is a flex item that does not break. Wrapping is the\n * whole fix — each one keeps its own line and the line is the column's width.\n */\n.wx-blocks__tools {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: var(--wx-space-8);\n flex: none;\n}\n\n.wx-blocks__add,\n.wx-blocks__preview-button {\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/*\n * One column: the preview is a button in either state.\n *\n * The threshold above this one is gone with the layout that needed it — there used to be a\n * width at which three columns no longer fitted and the preview folded away while a block\n * was open. There are two columns now, in both states, so there is one width to speak of.\n *\n * And it is not a container query any more: the narrow panel does not rearrange its columns,\n * it renders the tree and the form somewhere else entirely, which only the component can\n * decide. What is left here is the column the page keeps.\n */\n.wx-blocks-host.is-compact .wx-blocks,\n.wx-blocks-host.is-compact .wx-blocks.has-preview {\n grid-template-columns: minmax(0, 1fr);\n}\n\n/*\n * Inside the sheet a panel is not a card — the sheet is the card, and one inside another is\n * two borders and two paddings for one thing. The sheet's own body brings the room.\n */\n.wx-drawer .wx-blocks__tree,\n.wx-drawer .wx-blocks__fields {\n border: 0;\n padding: 0;\n background: none;\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 { callerWords, kindOf, usageWords } from './schema'\nimport type { BlockType } from './types'\n\n/**\n * One type in the list: its picture, its name, where it stands and which versions it has.\n *\n * A component stands on no page — it stands in other blocks — so its line counts those instead,\n * and one a module declared says which module's view it replaced.\n */\nwithDefaults(\n defineProps<{\n block: BlockType\n /** The name of the module that declared this slug, when one did. */\n module?: string | null\n }>(),\n { module: null },\n)\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 <!-- A component is a piece that stands inside a column — a card, a badge — so it is drawn\n at a column's width: at a desktop's it is a speck in the corner of the picture. And it\n is a whole thing rather than a band of a page, so it is shown whole, in a taller box. -->\n <block-thumb\n :thumbnail=\"block.thumbnail\"\n :height=\"kindOf(block) === 'component' ? 180 : 120\"\n :width=\"kindOf(block) === 'component' ? 360 : undefined\"\n :fit=\"kindOf(block) === 'component'\"\n />\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 <template v-if=\"kindOf(block) === 'component'\">\n {{ callerWords(block.used_by?.length ?? 0, t) }}\n <template v-if=\"module\">· {{ t('components.module', { module }) }}</template>\n </template>\n <template v-else>{{ usageWords(block.usage_count, t) }}</template>\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\n v-if=\"!block.is_enabled && kindOf(block) !== 'component'\"\n type=\"default\"\n variant=\"outline\"\n >\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 WxRadio,\n WxRadioGroup,\n WxSelect,\n WxSpace,\n} from '@webx-ui/core'\nimport { createBlocksApi } from './api'\nimport { useBlocksMessages } from './i18n'\nimport { groupLabel } from './schema'\nimport type { BlockKind, BlockType } from './types'\n\n/**\n * A new type needs a few things to exist — what kind it is, a name, an identifier and, for a\n * block, a group — and gets an empty draft to open. Everything else is the editor's job.\n *\n * The kind is asked first and in words, one line under each: \"component\" means nothing to a\n * person who has not read the guide, and the line is the guide in one sentence.\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({\n kind: 'block' as BlockKind,\n title: '',\n slug: '',\n group: groups.value[0] ?? 'content',\n})\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 // A component is never offered in \"Add a block\", so a group would be a choice about nothing.\n const { group, ...rest } = form.value\n\n resolve(await api.create(form.value.kind === 'component' ? rest : { ...rest, group }))\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('components.kind')\" :error=\"errorOf('kind')\">\n <wx-radio-group v-model=\"form.kind\" class=\"wx-block-create__kinds\">\n <wx-radio value=\"block\">\n <span class=\"wx-block-create__kind\">{{ t('components.kind-block') }}</span>\n <span class=\"wx-block-create__kind-help\">{{ t('components.kind-block-help') }}</span>\n </wx-radio>\n <wx-radio value=\"component\">\n <span class=\"wx-block-create__kind\">{{ t('components.kind-component') }}</span>\n <span class=\"wx-block-create__kind-help\">{{\n t('components.kind-component-help')\n }}</span>\n </wx-radio>\n </wx-radio-group>\n </wx-form-item>\n\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\n v-if=\"form.kind === 'block'\"\n :label=\"t('page.group')\"\n :help=\"t('page.group-help')\"\n :error=\"errorOf('group')\"\n >\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\n.wx-block-create__kinds {\n gap: var(--wx-space-10);\n}\n\n/* The circle beside the name, not beside the middle of name and sentence. */\n.wx-block-create__kinds :deep(.wx-radio) {\n align-items: flex-start;\n}\n\n/* The name on its line and the sentence under it, both inside the radio's label. */\n.wx-block-create__kind {\n display: block;\n font-weight: var(--wx-font-weight-medium);\n}\n\n.wx-block-create__kind-help {\n display: block;\n font-size: var(--wx-font-size-sm);\n color: var(--wx-text-muted);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { WxButton, WxIcon, WxText } from '@webx-ui/core'\nimport { useBlocksMessages } from './i18n'\nimport type { DeclaredComponent } from './types'\n\n/**\n * A place a module declared and the site has not customised: the module draws its own view\n * there. It stands among the components rather than in a settings page, because otherwise nobody\n * learns the place can be changed at all (§3.9).\n *\n * No picture: there is no type to draw yet, and the module's view is drawn with data only the\n * module has. The card says whose view it is and offers the one thing to do with it.\n */\nwithDefaults(\n defineProps<{\n declared: DeclaredComponent\n /** The module's name as the panel shows it. */\n module: string\n canManage?: boolean\n busy?: boolean\n }>(),\n { canManage: false, busy: false },\n)\n\nconst emit = defineEmits<{ customise: [declared: DeclaredComponent] }>()\n\nuseBlocksMessages()\nconst t = useTranslate('webx-blocks')\n</script>\n\n<template>\n <div class=\"wx-block-declared\">\n <div class=\"wx-block-declared__mark\" aria-hidden=\"true\">\n <wx-icon name=\"sliders\" />\n </div>\n <div class=\"wx-block-declared__body\">\n <div class=\"wx-block-declared__title\">{{ declared.title }}</div>\n <wx-text size=\"sm\" tone=\"muted\">\n <code>{{ declared.slug }}</code>\n · {{ t('components.standard', { module }) }}\n </wx-text>\n <wx-text v-if=\"declared.description\" size=\"sm\" tone=\"muted\">\n {{ declared.description }}\n </wx-text>\n <wx-text size=\"sm\" tone=\"muted\" class=\"wx-block-declared__help\">\n {{ t('components.standard-help') }}\n </wx-text>\n <div v-if=\"canManage\" class=\"wx-block-declared__actions\">\n <wx-button size=\"sm\" :loading=\"busy\" @click=\"emit('customise', declared)\">\n {{ t('components.customise') }}\n </wx-button>\n </div>\n </div>\n </div>\n</template>\n\n<style scoped>\n/* The same box as a type's card, with a dashed edge: a place, not yet a thing. */\n.wx-block-declared {\n display: flex;\n flex-direction: column;\n min-width: 0;\n overflow: hidden;\n background: var(--wx-bg-surface);\n border: 1px dashed var(--wx-border-strong);\n border-radius: var(--wx-radius-md);\n}\n\n/* Where a type's card has its picture: the same height, so a row of cards stays level. */\n.wx-block-declared__mark {\n display: flex;\n align-items: center;\n justify-content: center;\n height: 120px;\n font-size: 32px;\n color: var(--wx-text-muted);\n background: var(--wx-bg-subtle);\n border-block-end: 1px dashed var(--wx-border-default);\n}\n\n.wx-block-declared__body {\n display: flex;\n flex: 1 1 auto;\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-declared__title {\n font-weight: var(--wx-font-weight-semibold);\n}\n\n.wx-block-declared__actions {\n margin-block-start: auto;\n padding-block-start: var(--wx-space-4);\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, onMounted, ref } from 'vue'\nimport { useRouter } from 'vue-router'\nimport { VueDraggable } from 'vue-draggable-plus'\nimport {\n useAdmin,\n useErrorText,\n useTranslate,\n WxListScreen,\n type ScreenAction,\n} from '@webx-ui/module-admin'\nimport {\n createModal,\n toast,\n WxAlert,\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 BlockDeclaredCard from './BlockDeclaredCard.vue'\nimport { useBlocksMessages } from './i18n'\nimport { groupLabel, kindOf } from './schema'\nimport type { BlocksMeta, BlockType, DeclaredComponent } 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 *\n * Two kinds, two groups (§3.9 of the components spec): the blocks editors put on pages, then\n * the components templates call. The places modules declared and the site has not customised\n * stand among the components — a place nobody sees is a possibility nobody learns about.\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 types = ref<BlockType[]>([])\nconst declared = ref<DeclaredComponent[]>([])\nconst loading = ref(true)\nconst search = ref('')\n/** Which group is being looked at; `''` is all of them, grouped. */\nconst view = ref<TabValue>('')\n/** The slug being customised, while the request is out. */\nconst customising = ref<string | null>(null)\n\n/** The view of the components. Not a word a site could name a group of its own. */\nconst COMPONENTS = '@components'\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 blocks = computed(() => types.value.filter((type) => kindOf(type) === 'block'))\nconst components = computed(() => types.value.filter((type) => kindOf(type) === 'component'))\n\n/** The places still drawn by their module: a customised one is already a card of its own. */\nconst pending = computed(() => declared.value.filter((place) => !place.customised))\n\nconst hasComponents = computed(() => components.value.length > 0 || pending.value.length > 0)\n\n/** A module's name as the navigation says it; its id, capitalised, for one the panel lacks. */\nfunction moduleName(id: string): string {\n return (\n context.state.manifest?.modules.find((module) => module.id === id)?.title ??\n id.charAt(0).toUpperCase() + id.slice(1)\n )\n}\n\n/** Which module declared a slug, by name: the card of a customised place says whose it was. */\nfunction declaredBy(slug: string): string | null {\n const place = declared.value.find((item) => item.slug === slug)\n\n return place ? moduleName(place.module) : null\n}\n\nfunction matches(fields: (string | null)[]): boolean {\n const needle = search.value.trim().toLowerCase()\n\n return needle === '' || fields.some((field) => (field ?? '').toLowerCase().includes(needle))\n}\n\nconst shown = computed(() => {\n if (view.value === COMPONENTS) return []\n\n const inView =\n view.value === '' ? blocks.value : blocks.value.filter((block) => block.group === view.value)\n\n return inView.filter((block) => matches([block.title, block.slug, block.description]))\n})\n\nconst shownComponents = computed(() =>\n view.value === '' || view.value === COMPONENTS\n ? components.value.filter((type) => matches([type.title, type.slug, type.description]))\n : [],\n)\n\nconst shownPending = computed(() =>\n view.value === '' || view.value === COMPONENTS\n ? pending.value.filter((place) => matches([place.title, place.slug, place.description]))\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 — and the components last, as one view:\n * they have no groups, nobody picks them from a list. With a single group and no components\n * there is nothing to choose between, and the strip would be a control that says one thing.\n */\nconst views = computed<TabItem[]>(() => {\n const groupViews = order.value.map((id) => ({ value: id, label: groupLabel(id, t) }))\n const componentView = hasComponents.value\n ? [{ value: COMPONENTS, label: t('components.components') }]\n : []\n\n return groupViews.length + componentView.length < 2\n ? []\n : [{ value: '', label: t('page.all-groups') }, ...groupViews, ...componentView]\n})\n\n/** What the grid draws for the blocks: 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 if (!flat) return sections\n if (shown.value.length === 0) return []\n\n // Flat, but beside the components: the run of blocks still needs the one word that says\n // which of the two kinds it is.\n const both = view.value === '' && shownComponents.value.length + shownPending.value.length > 0\n\n return [{ id: '', label: both ? t('components.blocks') : '', blocks: shown.value }]\n})\n\n/** The components' heading, unless their own tab already names them or they are all there is. */\nconst componentsLabel = computed(() =>\n view.value === COMPONENTS || shown.value.length === 0 ? '' : t('components.components'),\n)\n\nconst nothing = computed(() => types.value.length === 0 && pending.value.length === 0)\n\n/**\n * The cards are dragged into the order editors see them in, here and in the picker. That is\n * `position`, not `sort`, which is the order of the styles on the page.\n *\n * Not while searching — a filtered run of cards cannot be put in order — and not the components,\n * which nobody picks from a list. A finger holds a card for a moment before it lifts, so that\n * the same finger can still scroll the section.\n */\nconst canDrag = computed(\n () => canManage.value && view.value !== COMPONENTS && search.value.trim() === '',\n)\n\n/*\n * The group takes the places it held, in its new order — the rule the server keeps — so the\n * cards are right at once, and a refusal only has to fetch the list again.\n */\nasync function reorder(list: BlockType[]): Promise<void> {\n const ids = list.map((block) => block.id)\n const next = [...list]\n\n types.value = types.value.map((type) => (ids.includes(type.id) ? next.shift()! : type))\n\n try {\n await api.reorder(ids)\n } catch (error) {\n toast.danger(message(error))\n await load()\n }\n}\n\nasync function load(): Promise<void> {\n loading.value = true\n\n try {\n const list = await api.index()\n\n types.value = list.blocks\n declared.value = list.declared\n } catch (error) {\n toast.danger(message(error))\n } finally {\n loading.value = false\n }\n}\n\n/*\n * When a card was last let go of. A real mouse follows the release with a click on the card it\n * started on — the fallback drag moves a copy, the card itself never left — and that click\n * opened the type the editor had only meant to move. Sortable's own guard does not catch it\n * here. A synthetic drag sends no click, which is why only a real hand ever saw this.\n */\nlet droppedAt = 0\n\nfunction dropped(): void {\n droppedAt = Date.now()\n}\n\nfunction open(block: BlockType | { id: number }): void {\n if (Date.now() - droppedAt < 400) return\n\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\n/**\n * The declared place made the site's own: a draft of the module's view, not published — the site\n * keeps drawing the module's view until someone does (§4.2). So the editor opens on the draft\n * and the toast says the site has not changed yet, because that is the question on everyone's\n * mind after pressing a button called \"Customise\".\n */\nasync function customise(place: DeclaredComponent): Promise<void> {\n customising.value = place.slug\n\n try {\n const type = await api.customise(place.slug)\n\n toast.success(t('components.customised'))\n open(type)\n } catch (error) {\n // Already customised elsewhere (another tab, an agent): the answer names the type to open.\n const body = (error as { status?: number; body?: { id?: number } }).body\n\n if ((error as { status?: number }).status === 409 && typeof body?.id === 'number') {\n open({ id: body.id })\n\n return\n }\n\n toast.danger(message(error, t('components.customise-failed')))\n } finally {\n customising.value = null\n }\n}\n\nonMounted(load)\n\n/* What the section offers. Declared, because on a phone the head folds it into the ···. */\nconst actions = computed<ScreenAction[]>(() =>\n canManage.value\n ? [{ key: 'new', label: t('page.new'), icon: 'plus', primary: true, run: () => void add() }]\n : [],\n)\n</script>\n\n<template>\n <wx-list-screen\n v-model:view=\"view\"\n class=\"wx-blocks-page\"\n :title=\"title\"\n :views=\"views\"\n :actions=\"actions\"\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 || !nothing\" 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=\"nothing\"\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 <!-- The fallback rather than the browser's own drag: Firefox does not drag a button. -->\n <vue-draggable\n :model-value=\"group.blocks\"\n class=\"wx-blocks-page__cards\"\n :disabled=\"!canDrag\"\n :animation=\"160\"\n :delay=\"200\"\n :delay-on-touch-only=\"true\"\n :force-fallback=\"true\"\n ghost-class=\"is-ghost\"\n @end=\"dropped\"\n @update:model-value=\"reorder($event as BlockType[])\"\n >\n <block-card v-for=\"block in group.blocks\" :key=\"block.id\" :block=\"block\" @open=\"open\" />\n </vue-draggable>\n </section>\n\n <section\n v-if=\"shownComponents.length > 0 || shownPending.length > 0\"\n class=\"wx-blocks-page__group\"\n >\n <div v-if=\"componentsLabel\" class=\"wx-blocks-page__group-title\">\n {{ componentsLabel }}\n </div>\n <div class=\"wx-blocks-page__cards\">\n <block-card\n v-for=\"type in shownComponents\"\n :key=\"type.id\"\n :block=\"type\"\n :module=\"declaredBy(type.slug)\"\n @open=\"open\"\n />\n <block-declared-card\n v-for=\"place in shownPending\"\n :key=\"place.slug\"\n :declared=\"place\"\n :module=\"moduleName(place.module)\"\n :can-manage=\"canManage\"\n :busy=\"customising === place.slug\"\n @customise=\"customise\"\n />\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/* The place a dragged card will land: its outline, not a second copy of the picture. */\n.wx-blocks-page__cards :deep(.is-ghost) {\n opacity: 0.35;\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 { WxTextarea } from '@webx-ui/core'\nimport BlockDataField from './BlockDataField.vue'\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 wide: true,\n bind: () => ({ blocksPath: path }),\n },\n // The two inputs only a component's schema has (§3.3): a structure passed from code,\n // edited in the sample form as the JSON it is, and a piece of markup the caller puts\n // between the tags, as HTML. Neither is a field an editor fills on a page.\n 'wx-data': { component: BlockDataField, kind: 'field', wide: true },\n 'wx-slot': {\n component: WxTextarea,\n kind: 'field',\n bind: () => ({ rows: 3, placeholder: '<p>…</p>' }),\n },\n },\n }\n}\n"],"names":["blocksMessages","seeded","useBlocksMessages","i18n","useAdmin","props","__props","emit","__emit","t","useTranslate","text","ref","format","error","value","parse","source","onText","next","parsed","failure","watch","same","_openBlock","_createElementBlock","_hoisted_1","_createVNode","_unref","WxCodeEditor","_createBlock","WxText","createBlocksApi","admin","base","data","body","id","input","slug","number","ids","mine","computed","lint","passed","codes","lines","_hoisted_2","WxIcon","_createElementVNode","_Fragment","_createTextVNode","_toDisplayString","_renderList","line","context","api","message","useErrorText","versions","load","state","version","restore","confirm","block","toast","onMounted","WxSkeleton","_hoisted_3","WxDate","WxBadge","WxButton","$event","SELECTED_CLASS","HOVER_CLASS","STYLE_ID","findRange","root","key","walker","start","node","replaceBlock","doc","html","range","parent","template","anchor","done","fragment","inserted","runtime","child","blockElement","highlightBlock","ensureStyle","element","hoverBlock","keyAt","depth","sibling","bindFrame","handlers","hovered","onClick","event","inert","onMove","onLeave","swallow","target","freezeFrame","listeners","name","listener","STAGE_KEY","STAGE_STYLES","fillStage","style","opener","mountScript","script","stageDocument","escapeAttribute","frame","SHELL_PLACE","siteShell","url","findMarker","absolute","head","tag","rel","copy","inner","attributes","attribute","thumbDocument","shell","widths","width","box","boxWidth","useElementWidth","contentHeight","picked","fits","option","pick","scale","srcdoc","generation","loadedScript","measure","view","margin","bottom","binding","observer","release","fill","onLoad","Observer","now","before","onBeforeUnmount","frameStyle","clipStyle","WxSegmented","_cache","isNode","isNodeList","newKey","makeNode","type","values","locate","tree","find","list","field","index","found","walk","visit","countType","count","countInside","typesIn","seen","nestedFields","schema","cloneNode","clone","setHidden","hidden","listAt","parentKey","existing","insertNode","removeNode","updateValues","replaceList","completions","autocompletion","EditorState","GIVEN","BLOCK_MEMBERS","MEDIA_KEYS","ITEM_KEYS","MEDIA_TYPES","LIST_TYPES","COLLECTION_KEYS","COLLECTION_PARTS","SOURCE_ITEMS","HELPER_KEYS","HELPER","HELPER_PARTS","HELPER_SNIPPETS","templateCompletions","styles","types","schemaOf","called","tagTypes","member","blockMembers","arrayKeys","variable","variables","echo","echoed","openTag","tagAttributes","tagElements","enclosingType","classNames","directive","directives","quote","word","targets","completion","from","to","rest","end","closed","insert","pickedCompletion","inside","odd","present","match","reserved","options","declared","answer","nodes","fields","bound","detail","info","boost","label","snippetCompletion","open","stack","printable","loopVariables","space","closer","escape","tail","keys","keysOf","q","part","helper","origin","own","outer","styleClasses","blocks","stylesCompletions","statement","styled","used","templateClasses","names","prelude","char","parents","selectors","selector","NODE_KEYS","schemaCompletions","at","jsonContext","quoted","applyJson","entry","pos","top","snapshot","string","escaped","i","LAYOUT","lintBlock","content","lints","missing","undeclared","stray","bare","prefix","few","withoutComments","media","lineAt","fieldIds","trimmed","raw","comment","offset","blocksPreviewKey","provideBlocksPreview","preview","provide","useBlocksPreview","inject","blocksRootKey","blocksOwnerKey","formSchema","usageWords","groupLabel","words","kindOf","callerWords","schemaFields","callTag","sample","fallback","variableOf","slots","_match","letter","route","useRoute","router","useRouter","usage","loading","saving","publishing","tab","meta","module","canManage","settings","reactive","schemaText","schemaError","errors","refusal","stage","current","dirty","typeIds","schemas","loadTargets","place","assist","coreTypes","groupOptions","group","sampleModel","collectIds","take","loaded","stored","onSchemaText","timer","pending","redraw","render","ticket","drawn","templateEditor","pill","insertField","editor","save","saved","publish","declaredModule","callers","isComponent","remove","reset","refusalError","withStage","examples","shownUsage","whereWords","hasWhere","deleteBlocked","call","dataInputs","shape","copyCall","errorOf","leaveGuard","kindOptions","actions","WxCard","WxScreenHead","WxRenameButton","WxPopover","_hoisted_4","_component_router_link","_hoisted_5","entity","WxAlert","_normalizeClass","WxTabs","WxTab","_hoisted_6","_hoisted_7","BlockChecks","_hoisted_9","_hoisted_10","_hoisted_11","_hoisted_12","_hoisted_13","_hoisted_14","_hoisted_15","example","_hoisted_16","_hoisted_17","_hoisted_18","WxHelpButton","WxScreenRenderer","_hoisted_19","WxFormItem","WxSelect","WxInput","WxTextarea","WxIconPicker","WxInputNumber","WxTagsInput","WxSwitch","_hoisted_20","BlockHistory","BlockStage","WxActionBar","resolve","dismiss","useModal","WxDialog","WxEmpty","step","shells","loadShell","response","useSiteShell","adminKey","watchEffect","TALL","widthScale","fitted","rect","fit","allows","allow","parentAllows","typeAllows","destinations","catalog","moving","here","trail","container","slot","title","children","max","search","allowedHere","exhausted","shown","needle","sections","order","grouped","o","section","emptyText","allowed","BlockThumb","bar","fullscreen","ready","grown","watcher","pin","page","margins","height","nextTick","bring","watch_","reveal","forget","el","scroller","overflow","room","band","foot","above","tall","delta","replace","refresh","onKey","__expose","WxAction","typeOf","titleOf","fieldsOf","childrenIn","actionsFor","limit","WxSortableList","_withCtx","item","_hoisted_8","WxRowMenu","_component_blocks_tree","p","f","n","model","_useModel","nested","owner","selectedKey","selected","selectedType","steps","previewEl","host","hostWidth","hasPreview","compact","sheet","sheetTitle","sideProps","groups","m","self","getCurrentInstance","translate","can","createModal","BlockPicker","set","add","parentType","structuredSample","duplicate","chooseDestination","BlockMoveDialog","move","without","visibility","reorder","select","selectFromPreview","onValues","typeId","formRoot","_resolveDynamicComponent","WxDrawer","_mergeProps","BlocksTree","BlocksPreview","form","slugTouched","slugify","WxSpace","WxRadioGroup","WxRadio","COMPONENTS","customising","create","BlockCreateDialog","components","hasComponents","moduleName","declaredBy","matches","shownComponents","shownPending","views","groupViews","componentView","b","componentsLabel","nothing","canDrag","droppedAt","dropped","customise","WxListScreen","WxSkeletonItem","VueDraggable","BlockCard","BlockDeclaredCard","path","BlocksPage","BlockEditorPage","BlocksField","BlockDataField"],"mappings":"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"}