@webx-ui/module-blocks 0.16.2 → 0.16.3
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/BlockEditorPage.d.ts +3 -70
- package/dist/BlockStage.d.ts +4 -0
- package/dist/BlocksField.d.ts +3 -3
- package/dist/BlocksPreview.d.ts +6 -2
- package/dist/frame.d.ts +18 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2116 -2053
- package/dist/index.js.map +1 -1
- package/dist/style.css +1 -1
- package/dist/types.d.ts +8 -0
- package/package.json +4 -4
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/api.ts","../src/messages.ts","../src/i18n.ts","../src/BlockDataField.vue","../src/BlockChecks.vue","../src/schema.ts","../src/BlockExportDialog.vue","../src/BlockHistory.vue","../src/frame.ts","../src/BlockStage.vue","../src/content.ts","../src/completions.ts","../src/css-tokens.ts","../src/lint.ts","../src/preview.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/clipboard.ts","../src/BlocksField.vue","../src/BlockCard.vue","../src/BlockCreateDialog.vue","../src/BlockDeclaredCard.vue","../src/BlockImportDialog.vue","../src/BlocksPage.vue","../src/RegionDraftNotice.vue","../src/BlocksSiteBarTab.vue","../src/FragmentField.vue","../src/region.ts","../src/RegionPagePicker.vue","../src/RegionEditorPage.vue","../src/RegionHistory.vue","../src/RegionsPage.vue","../src/module.ts"],"sourcesContent":["import type { AdminContext } from '@webx-ui/module-admin'\nimport type {\n BlockExport,\n BlockImportRow,\n BlockInput,\n BlockPack,\n BlockList,\n BlockType,\n BlockUsage,\n BlockVersion,\n BlockNode,\n BlockVersionMeta,\n DeclaredComponent,\n RegionAdopted,\n RegionDetail,\n RegionRow,\n RegionVersion,\n RenderInput,\n RenderResult,\n SiteBarBlockEdit,\n SiteBarBlockEdited,\n SiteBarBlocks,\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 /** `dropTranslations` agrees to keep one language where a field stops being localized. */\n publish(id: number, options?: { dropTranslations?: boolean }): Promise<BlockType>\n render(id: number, input?: RenderInput): Promise<RenderResult>\n usage(id: number): Promise<BlockUsage[]>\n /** The shared blocks a page may place, with their state; open to whoever reads the catalog. */\n fragments(): Promise<RegionRow[]>\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 /** A pack of the types named — every type when none is — and the components they call. */\n exportPack(slugs: string[], options?: { draft?: boolean }): Promise<BlockExport>\n /**\n * What the file would do (`dryRun`), or what it did. Drafts, unless `publish` is asked for.\n * The file goes as its text: the server compares it with what is stored, whitespace included.\n */\n importPack(\n file: string,\n options?: { name?: string; dryRun?: boolean; publish?: boolean },\n ): Promise<BlockImportRow[]>\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, options = {}) =>\n admin.http\n .post<{ data: BlockType }>(\n `${base}/${id}/publish`,\n options.dropTranslations ? { drop_translations: true } : {},\n )\n .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 fragments: () => admin.http.get<{ data: RegionRow[] }>(`${base}/fragments`).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 exportPack: (slugs, options = {}) => {\n const query = new URLSearchParams()\n\n for (const slug of slugs) query.append('slugs[]', slug)\n if (options.draft) query.set('draft', '1')\n\n const search = query.toString()\n\n return admin.http\n .get<{\n data: BlockPack\n skipped?: string[]\n missing?: string[]\n }>(`${base}/export${search === '' ? '' : `?${search}`}`)\n .then((body) => ({\n pack: body.data,\n skipped: body.skipped ?? [],\n missing: body.missing ?? [],\n }))\n },\n importPack: (file, options = {}) =>\n admin.http\n .post<{ data: BlockImportRow[] }>(`${base}/import`, {\n file,\n name: options.name,\n dry_run: options.dryRun === true,\n publish: options.publish === true,\n })\n .then(data),\n }\n}\n\nexport interface SiteBarBlocksApi {\n /** A record's blocks: the draft's, or the site's when there is no draft. */\n read(type: string, id: number | string): Promise<SiteBarBlocks>\n /**\n * One block's fields into the record's draft. A revision that moved is answered 409 — the\n * error's body names who moved it.\n */\n edit(type: string, id: number | string, input: SiteBarBlockEdit): Promise<SiteBarBlockEdited>\n}\n\n/** The two addresses of the «Blocks» tab of the panel on the site, by the record's address type. */\nexport function createSiteBarBlocksApi(admin: AdminContext): SiteBarBlocksApi {\n const at = (type: string, id: number | string) =>\n `${admin.apiPath}/blocks/content/${encodeURIComponent(type)}/${encodeURIComponent(String(id))}`\n\n return {\n read: (type, id) =>\n admin.http.get<{ data: SiteBarBlocks }>(at(type, id)).then((body) => body.data),\n edit: (type, id, input) =>\n admin.http\n .post<{ data: SiteBarBlockEdited }>(`${at(type, id)}/edit`, input)\n .then((body) => body.data),\n }\n}\n\nexport interface RegionsApi {\n /** Every region the site's config declares, saved or not. */\n list(): Promise<RegionRow[]>\n get(name: string): Promise<RegionDetail>\n /**\n * Save the draft. Refused with a 409 when the revision is not the current one — the error's\n * body is a {@link RegionConflict}: the region as it now is, to merge with.\n */\n save(name: string, input: { blocks: BlockNode[]; revision?: string }): Promise<RegionDetail>\n /** `revision` is what the editor held: a draft that moved on since is answered 409, not published. */\n publish(name: string, revision?: string): Promise<RegionDetail>\n /** Off the site: the code's view comes back, the blocks stay as the draft. */\n unpublish(name: string): Promise<RegionDetail>\n discardDraft(name: string): Promise<RegionDetail>\n versions(name: string): Promise<RegionVersion[]>\n /** An old publication becomes the draft; putting it on the site is a separate step. */\n restoreVersion(name: string, number: number): Promise<RegionDetail>\n /** The fallback view made into a block type, and one of it put into the draft. */\n adopt(name: string): Promise<RegionAdopted>\n /**\n * A shared block's published tree with fresh keys, to put in a page in its place. Writes nothing;\n * 409 while the shared block is not published.\n */\n copy(name: string): Promise<BlockNode[]>\n}\n\n/** Everything under `/regions`, below the panel's API path. */\nexport function createRegionsApi(admin: AdminContext): RegionsApi {\n const base = `${admin.apiPath}/regions`\n const data = <T>(body: { data: T }): T => body.data\n const at = (name: string) => `${base}/${encodeURIComponent(name)}`\n\n return {\n list: () => admin.http.get<{ data: RegionRow[] }>(base).then(data),\n get: (name) => admin.http.get<{ data: RegionDetail }>(at(name)).then(data),\n save: (name, input) => admin.http.put<{ data: RegionDetail }>(at(name), input).then(data),\n publish: (name, revision) =>\n admin.http\n .post<{ data: RegionDetail }>(`${at(name)}/publish`, revision ? { revision } : {})\n .then(data),\n unpublish: (name) =>\n admin.http.post<{ data: RegionDetail }>(`${at(name)}/unpublish`, {}).then(data),\n discardDraft: (name) =>\n admin.http.delete<{ data: RegionDetail }>(`${at(name)}/draft`).then(data),\n versions: (name) =>\n admin.http.get<{ data: RegionVersion[] }>(`${at(name)}/versions`).then(data),\n restoreVersion: (name, number) =>\n admin.http\n .post<{ data: RegionDetail }>(`${at(name)}/versions/${number}/restore`, {})\n .then(data),\n adopt: (name) =>\n admin.http\n .post<{ data: RegionDetail; block: { id: number; slug: string } }>(`${at(name)}/adopt`, {})\n .then((body) => ({ region: body.data, block: body.block })),\n copy: (name) =>\n admin.http\n .post<{ data: { blocks: BlockNode[] } }>(`${at(name)}/copy`, {})\n .then((body) => body.data.blocks),\n }\n}\n","import type { Messages } from '@webx-ui/module-admin'\n\n/**\n * The English this package speaks on its own, before the server's dictionary arrives, or\n * without one. The server ships the same lines in ten languages under `webx-blocks::` and\n * overrides these; `messages.test.ts` keeps the two sets of keys equal.\n */\nexport const blocksMessages: Record<string, Messages> = {\n module: {\n title: 'Blocks',\n regions: 'Site regions',\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 rewrites every page and region it stands on; it is refused while another template calls it.',\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':\n 'Types that can be put inside a field holding blocks that names none of its own. Empty — any type.',\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 'source-theme': 'theme',\n 'allow-help-none':\n 'The schema has no field of type wx-blocks, so the block holds nothing; this list applies once it has one.',\n 'allow-from-fields':\n 'The fields holding blocks name what they take — :fields — and that wins. This list applies to a field that names nothing.',\n renamed: 'Renamed to :slug. Pages and regions rewritten: :pages; other types: :types.',\n 'settings-saved': 'Settings saved.',\n 'drop-translations-title': 'Keep only the main language?',\n 'drop-translations-confirm': 'Keep the main language and publish',\n 'thumb-empty': 'Prints nothing on its sample: it draws only when there is data to show.',\n 'drops-translations':\n 'This version makes :fields hold one language. :count page(s) hold text in several languages there, and only the main one would be kept: :pages. Publish again agreeing to drop the other languages, or move the text first.',\n 'localized-changes':\n 'Publishing this version changes the language shape of :fields: the values already on :count page(s) will be converted.',\n 'rename-called':\n 'Other types call this one by its identifier: :types. Change their templates first, then rename it.',\n 'rename-declared': 'A module calls this component by its identifier, so it cannot be renamed.',\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 copy: 'Copy',\n 'copy-all': 'Copy all blocks',\n copied: 'Copied: :title',\n 'copied-many': 'Copied, blocks: :count',\n paste: 'Paste: :title',\n 'paste-many': 'Paste (blocks: :count)',\n 'paste-after': 'Paste after: :title',\n 'paste-after-many': 'Paste after (blocks: :count)',\n 'paste-inside': 'Paste inside: :title',\n 'paste-inside-many': 'Paste inside (blocks: :count)',\n pasted: 'Pasted, blocks: :count',\n 'paste-skipped': 'Not pasted: :list',\n 'skip-unknown': 'not available on this site',\n 'skip-place': 'not allowed here',\n 'skip-limit': 'the limit for this block is reached',\n 'skip-full': 'the list is full',\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 'markup-in-text': 'This text holds HTML tags. Change the words and leave the tags as they are.',\n shortcodes: 'Shortcodes',\n 'shortcodes-insert': 'Insert a shortcode',\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 'add-inside-full': 'Full: takes :max',\n invalid: 'Some values were not accepted',\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 region: {\n title: 'Site regions',\n intro:\n \"The parts of the layout every page shares. While a region is empty, the site shows what the site's code draws there.\",\n empty: 'No regions are declared on this site.',\n 'empty-help':\n 'A region is declared under regions in config/webx-blocks.php and printed by the layout with <x-webx-blocks::region>.',\n 'state-live': 'On the site',\n 'state-edits': 'Edits waiting',\n 'state-draft': 'Draft',\n 'state-fallback': 'Fallback from code',\n count: 'Blocks: :count',\n 'fallback-view': 'From code: :view',\n 'fallback-none': 'Nothing from code',\n 'tab-content': 'Content',\n 'tab-history': 'History',\n 'shown-on': 'Shown on',\n home: 'Home page',\n 'choose-page': 'Choose the page to look at the region on',\n 'back-home': 'Back to the home page',\n preview: 'Open the preview',\n 'empty-title': 'The site draws this region from its code',\n 'empty-text':\n 'Right now the site prints the view :view here. Add blocks and publish to replace it.',\n 'empty-text-none':\n 'Right now the site prints nothing here. Add blocks and publish to fill the region.',\n adopt: 'Move the markup into a block',\n adopted: 'Block type :slug made from the view and put into the draft.',\n save: 'Save draft',\n 'save-failed': 'The draft was not saved.',\n publish: 'Publish',\n 'publish-title': 'Put \":title\" on the site?',\n 'publish-text': \"Every page of the site shows these blocks instead of the code's view.\",\n published: 'Published.',\n unpublish: 'Take off the site',\n 'unpublish-title': 'Take \":title\" off the site?',\n 'unpublish-text':\n \"The site goes back to the code's view. The blocks stay here as a draft, and publishing brings them back.\",\n unpublished: \"Taken off the site. It shows the code's view again.\",\n discard: 'Discard draft',\n 'discard-title': 'Discard the draft of \":title\"?',\n 'discard-text': 'The edits go, and the region is again what the site shows now.',\n discarded: 'Draft discarded.',\n 'status-live': 'On the site',\n 'status-modified': 'Edits waiting',\n 'status-fallback': 'Fallback from code',\n 'conflict-title': 'The region changed while you were editing',\n 'conflict-theirs': 'Take the newer version',\n 'conflict-theirs-title': 'Give up what you wrote?',\n 'conflict-theirs-text':\n 'Your edits since the last save go, and the region is loaded as somebody else left it.',\n 'conflict-mine': 'Keep mine',\n 'leave-title': 'Leave without saving?',\n 'leave-text': 'The last edits did not reach the server and will be lost.',\n leave: 'Leave',\n cancel: 'Cancel',\n 'history-empty': 'Nothing published yet.',\n version: 'v:number',\n 'version-live': 'On the site',\n restore: 'Restore',\n 'restore-title': 'Make v:number the draft?',\n 'restore-text':\n 'The draft becomes this version. The site keeps what it shows until you publish.',\n 'restored-version': 'v:number is the draft now.',\n 'source-panel': 'From the panel',\n 'source-mcp': 'By an agent',\n 'source-import': 'Imported',\n },\n fragment: {\n choose: 'Choose a shared block',\n none: 'The site has no shared blocks yet. A developer declares one under regions in config/webx-blocks.php, with fragment set to true.',\n missing: '“:name” is not a shared block of the site any more: nothing is shown here.',\n 'status-live': 'On the site',\n 'status-edits': 'On the site, edits waiting',\n 'status-fallback': 'Not published: the site shows its fallback',\n 'status-empty': 'Empty',\n explain:\n 'This block shows a shared block of the site. Editing it changes it on every page where it stands.',\n edit: 'Edit for all pages',\n detach: 'Make it this page’s own',\n 'detach-title': 'Make “:title” this page’s own?',\n 'detach-text':\n 'Its blocks are copied into this page in its place, as they are on the site. They stop following the shared block: its edits will not reach this page any more.',\n detached: 'The blocks of “:title” are this page’s own now.',\n unpublished: 'The shared block is not published yet: there is nothing to copy.',\n 'group-layout': 'Header and footer',\n 'group-shared': 'Shared blocks',\n 'group-shared-help':\n 'Edited once here and shown wherever a page or a template of the site places them.',\n count: 'Pages: :count',\n 'used-on': 'Where it stands',\n 'used-nowhere': 'No page places it yet.',\n templates: 'Templates of the site that print it with a tag are not listed.',\n 'draft-only': 'In a draft',\n 'show-here': 'Preview on this page',\n 'publish-text': 'Every page that places it shows these blocks instead of the code’s view.',\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 'string-on-text':\n 'With a shortcode in it, :field is HTML: a string function or a cast hands that HTML to {{ }}, which escapes it a second time. Change it through wx_text(): {{ wx_text(:field)->trimEnd(\".\") }} — trim, trimStart, stripPrefix, stripSuffix and map() keep it HTML.',\n 'variables-missing':\n 'The template uses :variables, which the schema does not declare. Publishing will be refused.',\n 'marker-slug':\n 'The root is marked data-wx-block=\":marker\", but the identifier is «:slug»: the script and the panel find the block by the exact identifier. 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 syntax: 'The template does not compile: :reason. Publishing will be refused.',\n 'unknown-field-type':\n 'Fields of a type this site does not know: :fields. The form draws a warning in their place and nothing checks their values.',\n 'field-id': 'Field ids must be letters, digits, _ and -, starting with a letter: :ids.',\n 'literal-colors':\n 'Literal colours: :values. No preset and no change in tokens.json repaints them: use a colour role, var(--site-color-…).',\n 'literal-fonts':\n 'Literal font families: :values. The owner’s font never reaches them: use var(--site-font-body) or var(--site-font-heading), or a generic family.',\n 'unknown-tokens':\n 'Not among the theme’s tokens: :tokens. A variable nobody declares is an empty value — no colour, no border, no error.',\n 'token-fallbacks':\n 'A fallback inside :tokens is a literal value no preset repaints. Every token of the theme has a value: write var() without one.',\n },\n exchange: {\n export: 'Export',\n import: 'Import',\n 'export-title': 'Export blocks',\n 'import-title': 'Import blocks',\n 'export-help':\n 'Choose the types to take. The components they call come along, so the file works on another site as it is.',\n 'select-all': 'Select all',\n drafts: 'Take drafts where there are any',\n 'drafts-help':\n 'Otherwise the published version goes, and a type that was never published is left out.',\n download: 'Download',\n exported: 'Types in the file: :count',\n skipped: 'Never published, left out: :list',\n missing: 'Called, but not on this site: :list',\n nothing: 'Nothing to export: none of the chosen types is published.',\n 'export-failed': 'The export did not go through.',\n 'import-help':\n 'A file exported from this section or by the webx:blocks:export command. Types come in as drafts; a type that is already here gets a new draft version.',\n 'choose-file': 'Choose a file',\n 'other-file': 'Another file',\n publish: 'Publish what passes the checks',\n 'status-created': 'New',\n 'status-updated': 'Updated',\n 'status-unchanged': 'Unchanged',\n 'status-failed': 'Refused',\n run: 'Import',\n imported: 'Types written: :count',\n 'up-to-date': 'Everything in the file is already here; there is nothing to write.',\n 'not-json': 'This file is not JSON.',\n 'not-a-pack': 'This file is not a block type or a pack of them.',\n cycle: 'The types in the file call each other in a circle: :path.',\n 'import-failed': 'The import did not go through.',\n },\n 'site-bar': {\n tab: 'Blocks',\n pick: 'Pick a block',\n 'pick-off': 'Stop picking',\n picking: 'Click a block on the page. Esc stops.',\n hint: 'Pick a block on the page or in the list to change its fields. Changes go into the draft.',\n empty: 'This page has no blocks.',\n temporary: 'Open in panel to edit',\n hidden: 'Hidden',\n all: 'All blocks',\n save: 'Save to draft',\n saved: 'Saved to the draft',\n 'unknown-type': 'There is no form for this block: its type is not published.',\n error: 'Could not read the blocks of this page.',\n retry: 'Try again',\n conflict: 'The page changed after the form read it; the form shows what is there now.',\n 'conflict-by':\n ':name changed the page after the form read it; the form shows what is there now.',\n 'bad-op': 'This change cannot be made from the site.',\n gone: 'This block is not on the page any more.',\n others: 'Also open in the panel: :names',\n 'region-everywhere': 'On every page',\n 'fragment-where': 'Shared block: on every page where it stands',\n 'fragment-everywhere': 'A shared block: an edit here changes it on every page where it stands.',\n 'region-fallback':\n 'The site shows the markup from code here. Set the region up in the panel to edit it from the site.',\n 'open-in-panel': 'Open in panel',\n changes: 'Unpublished changes: :count',\n publish: 'Publish',\n discard: 'Discard',\n 'discard-title': 'Discard the draft of :name?',\n 'discard-text':\n 'Changes nobody has published yet are thrown away; the site keeps what it shows now.',\n cancel: 'Cancel',\n 'draft-other': ':name has a draft here; your edits go into it',\n refused: 'Not saved: what stands around this block has to be put right in the panel first.',\n 'bad-type': 'Blocks of this type cannot be added from the site.',\n 'too-deep': 'Blocks nest no deeper than this on the site. Levels at most: :max',\n add: 'Add block',\n 'add-below': 'Add below',\n 'add-inside': 'Add inside',\n duplicate: 'Duplicate',\n 'move-up': 'Move up',\n 'move-down': 'Move down',\n hide: 'Hide',\n show: 'Show',\n delete: 'Delete',\n actions: 'Block actions',\n 'at-top': 'Already first',\n 'at-bottom': 'Already last',\n full: 'No room for more blocks here. Most it takes: :count',\n limit: 'A page takes no more blocks of this type. Most: :count',\n 'delete-title': 'Delete «:title»?',\n 'delete-text':\n 'It goes from the draft with everything inside it. Visitors see it until the draft is published.',\n preview: 'Preview draft',\n },\n}\n","import { useAdmin, type I18n } from '@webx-ui/module-admin'\nimport { blocksMessages } from './messages'\n\nconst seeded = new WeakSet<object>()\n\n/**\n * Puts this package's English under a panel's dictionary, once per panel. For what runs outside\n * a component's setup — the label of a tab on the panel on the site is asked for by the frame.\n */\nexport function seedBlocksMessages(i18n: I18n): void {\n if (!seeded.has(i18n)) {\n i18n.defaults('webx-blocks', blocksMessages)\n seeded.add(i18n)\n }\n}\n\n/** Puts this package's English under the panel's dictionary, once per panel. */\nexport function useBlocksMessages(): void {\n try {\n seedBlocksMessages(useAdmin().i18n)\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","<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') && !codes.has('marker-slug')) 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","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/**\n * Fields whose sample is words somebody wrote — a heading, a caption, a picture. A block added to\n * a page starts without them: the sample is the author's example, and copied in as the block's own\n * content it went onto the site under the next autosave (\"Quote text sample\", \"John Doe\"). What\n * the other fields hold — a number, a switch, a choice from a list — is a setting, and the sample's\n * setting is as good a start as any.\n */\nconst WORDS = new Set([\n 'wx-input',\n 'wx-textarea',\n 'wx-rich-text',\n 'wx-tags-input',\n 'wx-autocomplete',\n 'wx-code-editor',\n 'wx-media',\n 'wx-gallery',\n 'wx-file',\n 'wx-files',\n 'wx-link',\n 'wx-repeater',\n 'wx-relations',\n 'wx-blocks',\n])\n\n/**\n * What a block added from the picker starts with: the sample's settings, none of its words.\n *\n * @see WORDS\n */\nexport function startValues(\n schema: ScreenNode[],\n sample: Record<string, unknown>,\n): Record<string, unknown> {\n const values: Record<string, unknown> = {}\n\n for (const node of schemaFields(schema)) {\n if (WORDS.has(node.type) || !(node.id in sample)) continue\n\n const value = sample[node.id]\n\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') continue\n\n values[node.id] = value\n }\n\n return values\n}\n\n/** Plain text fields — what shows a value as it is stored, tags and all. */\nconst PLAIN = new Set(['wx-input', 'wx-textarea'])\n\n/** A tag, opening or closing: `<span>`, `</em>`, `<br/>`. A lone `<` in a sentence is not one. */\nconst TAG = /<\\/?[a-z][a-z0-9-]*(\\s[^<>]*)?\\/?>/i\n\n/**\n * Whether a value — or any language of a translated one — holds markup.\n *\n * A heading written with an accent in it (`Deeply heard<span>.</span>`) still sits in a plain\n * input in types that came before the inline rich field, and the input shows it raw: the editor\n * sees the tags and is one stray keystroke away from printing them on the site.\n */\nexport function holdsMarkup(value: unknown): boolean {\n if (typeof value === 'string') return TAG.test(value)\n\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n return Object.values(value as Record<string, unknown>).some(\n (one) => typeof one === 'string' && TAG.test(one),\n )\n }\n\n return false\n}\n\n/** The plain text fields of a block whose values hold markup, by id. */\nexport function markupFields(schema: ScreenNode[], values: Record<string, unknown>): string[] {\n return schemaFields(schema)\n .filter((node) => PLAIN.has(node.type) && holdsMarkup(values[node.id]))\n .map((node) => node.id)\n}\n\n/**\n * The form of a block, with the sample's words shown as placeholders in the empty fields that\n * take words: the editor sees what goes where without the example becoming the content.\n *\n * `marked` are plain fields whose value holds tags ({@see markupFields}); each gets `markupHelp`\n * under it unless the type already says something there. Nothing is changed in the value — the\n * tags are the author's, and the type moving the field to `wx-rich-text` with `inline` is what\n * takes them out of sight.\n */\nexport function withPlaceholders(\n nodes: ScreenNode[],\n sample: Record<string, unknown>,\n marked: string[] = [],\n markupHelp = '',\n): ScreenNode[] {\n return nodes.map((node) => {\n if (LAYOUT.has(node.type)) {\n return node.children\n ? { ...node, children: withPlaceholders(node.children, sample, marked, markupHelp) }\n : node\n }\n\n const inline = node.type === 'wx-rich-text' && node.props?.inline === true\n if (!PLAIN.has(node.type) && !inline) return node\n\n const helped =\n markupHelp !== '' && marked.includes(node.id) && node.help === undefined\n ? { ...node, help: markupHelp }\n : node\n\n if (helped.props?.placeholder !== undefined) return helped\n\n // An inline field's sample is markup itself; its placeholder is the words without it.\n const words = sampleWords(sample[node.id], inline)\n\n return words === null\n ? helped\n : { ...helped, props: { ...(helped.props ?? {}), placeholder: words } }\n })\n}\n\n/**\n * Whether the site reads shortcodes in a field's value: words a person wrote — a line, a\n * paragraph, a rich text. An input typed as an e-mail, an address or a phone is a value the site\n * prints into an attribute, and a `[phone]` there would be a broken link rather than a number.\n */\nfunction takesShortcodes(node: ScreenNode): boolean {\n if (node.type === 'wx-textarea' || node.type === 'wx-rich-text') return true\n if (node.type !== 'wx-input') return false\n\n const type = node.props?.type\n\n return type === undefined || type === 'text'\n}\n\n/**\n * The form of a block, with the site's shortcodes handed to every field the site reads them in —\n * through layout and into a repeater's items, whose children are the fields of one item. A field\n * whose type already set `tokens` keeps its own.\n *\n * Here and not in the panel's field types: the same `wx-input` is a slug or a search box on\n * other screens, and only block content is printed through the shortcodes. `words` are the\n * field's own words for them — core's defaults speak of placeholders, the panel of shortcodes.\n */\nexport function withShortcodes<T>(\n nodes: ScreenNode[],\n tokens: readonly T[],\n words: { tokensTitle?: string; tokensLabel?: string } = {},\n): ScreenNode[] {\n if (tokens.length === 0) return nodes\n\n return nodes.map((node) => {\n const children = node.children ? withShortcodes(node.children, tokens, words) : node.children\n const next = children === node.children ? node : { ...node, children }\n\n return takesShortcodes(node) && next.props?.tokens === undefined\n ? { ...next, props: { ...words, ...(next.props ?? {}), tokens } }\n : next\n })\n}\n\n/** A sample's text: itself, or the first language of a translated one. */\nfunction sampleWords(value: unknown, strip = false): string | null {\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n value = Object.values(value as Record<string, unknown>).find(\n (one) => typeof one === 'string' && one.trim() !== '',\n )\n }\n\n if (typeof value !== 'string') return null\n\n const words = strip ? value.replace(new RegExp(TAG.source, 'gi'), '') : value\n\n return words.trim() === '' ? null : words.slice(0, 160)\n}\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, '"')}\"`\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, onMounted, ref } from 'vue'\nimport { useAdmin, useErrorText, useTranslate } from '@webx-ui/module-admin'\nimport {\n toast,\n useModal,\n WxButton,\n WxCheckbox,\n WxDialog,\n WxSkeleton,\n WxSpace,\n WxSwitch,\n WxText,\n} from '@webx-ui/core'\nimport { createBlocksApi } from './api'\nimport { useBlocksMessages } from './i18n'\nimport { kindOf } from './schema'\nimport type { BlockPack, BlockType } from './types'\n\n/**\n * \"Export\" (§17.1): the types to take, ticked, and one file out — the command's documents in a\n * pack. The components the chosen types call are not offered as a choice: the server adds them,\n * because a block without them draws nothing on the site it lands on, and a person exporting a\n * block for another site would only find that out there.\n *\n * Opened from a type's editor, it comes with that type ticked: a block for the catalogue of\n * ready blocks is made one at a time.\n */\nconst props = defineProps<{ selected?: string[] }>()\n\nconst { resolve, dismiss, open } = useModal<true>()\n\nconst context = useAdmin()\nconst api = createBlocksApi(context)\nuseBlocksMessages()\n\nconst t = useTranslate('webx-blocks')\nconst message = useErrorText()\n\nconst types = ref<BlockType[]>([])\nconst chosen = ref<string[]>([...(props.selected ?? [])])\nconst drafts = ref(false)\nconst loading = ref(true)\nconst exporting = ref(false)\n\n/** Blocks first, then components, each in the list's order — the order the section shows. */\nconst ordered = computed(() => [\n ...types.value.filter((type) => kindOf(type) === 'block'),\n ...types.value.filter((type) => kindOf(type) === 'component'),\n])\n\nconst all = computed(\n () => ordered.value.length > 0 && ordered.value.every((type) => chosen.value.includes(type.slug)),\n)\nconst some = computed(() => chosen.value.length > 0 && !all.value)\n\nfunction toggleAll(on: boolean): void {\n chosen.value = on ? ordered.value.map((type) => type.slug) : []\n}\n\nfunction toggle(slug: string, on: boolean): void {\n chosen.value = on ? [...chosen.value, slug] : chosen.value.filter((one) => one !== slug)\n}\n\n/** What a type would give: the published version, or the draft only when drafts are asked for. */\nfunction versionOf(type: BlockType): string {\n const version = drafts.value ? (type.draft ?? type.published) : type.published\n\n return version === null ? t('page.never-published') : `v${version.number}`\n}\n\n/** One type's file is named after it; several are named after the day they left. */\nfunction fileName(): string {\n if (chosen.value.length === 1) return `${chosen.value[0]}.blocks.json`\n\n return `blocks-${new Date().toISOString().slice(0, 10)}.json`\n}\n\nfunction download(pack: BlockPack, name: string): void {\n const url = URL.createObjectURL(\n new Blob([`${JSON.stringify(pack, null, 2)}\\n`], { type: 'application/json' }),\n )\n const link = document.createElement('a')\n\n link.href = url\n link.download = name\n link.click()\n // After the click has been handled: revoking first would hand the browser a dead address.\n setTimeout(() => URL.revokeObjectURL(url), 0)\n}\n\nasync function run(): Promise<void> {\n exporting.value = true\n\n try {\n const { pack, skipped, missing } = await api.exportPack(chosen.value, { draft: drafts.value })\n\n if (pack.blocks.length === 0) {\n toast.warning(t('exchange.nothing'))\n\n return\n }\n\n download(pack, fileName())\n toast.success(t('exchange.exported', { count: pack.blocks.length }))\n\n if (skipped.length > 0) toast.warning(t('exchange.skipped', { list: skipped.join(', ') }))\n if (missing.length > 0) toast.warning(t('exchange.missing', { list: missing.join(', ') }))\n\n resolve(true)\n } catch (error) {\n toast.danger(message(error, t('exchange.export-failed')))\n } finally {\n exporting.value = false\n }\n}\n\nonMounted(async () => {\n try {\n types.value = await api.list()\n // A type that was never published has nothing to give but its draft: opened on one, the\n // switch starts on, or the file would come out empty.\n drafts.value = types.value.some(\n (type) => chosen.value.includes(type.slug) && type.published === null,\n )\n } catch (error) {\n toast.danger(message(error))\n } finally {\n loading.value = false\n }\n})\n</script>\n\n<template>\n <wx-dialog v-model:open=\"open\" :title=\"t('exchange.export-title')\" :width=\"560\">\n <div class=\"wx-block-export\">\n <wx-text tone=\"muted\" size=\"sm\">{{ t('exchange.export-help') }}</wx-text>\n\n <wx-skeleton v-if=\"loading\" :rows=\"5\" />\n\n <template v-else>\n <wx-checkbox\n :model-value=\"all\"\n :indeterminate=\"some\"\n :label=\"t('exchange.select-all')\"\n class=\"wx-block-export__all\"\n @update:model-value=\"toggleAll(Boolean($event))\"\n />\n\n <ul class=\"wx-block-export__list\">\n <li v-for=\"type in ordered\" :key=\"type.id\" class=\"wx-block-export__row\">\n <!-- The checkbox is the row: its own label stretches across it, the version included,\n so a click anywhere ticks it — a label around the checkbox's label would not. -->\n <wx-checkbox\n :model-value=\"chosen.includes(type.slug)\"\n class=\"wx-block-export__check\"\n @update:model-value=\"toggle(type.slug, Boolean($event))\"\n >\n <span class=\"wx-block-export__type\">\n <span class=\"wx-block-export__title\">{{ type.title }}</span>\n <span class=\"wx-block-export__meta\">\n {{ type.slug }}\n <template v-if=\"kindOf(type) === 'component'\">\n · {{ t('components.kind-component') }}</template\n >\n </span>\n </span>\n <span class=\"wx-block-export__version\">{{ versionOf(type) }}</span>\n </wx-checkbox>\n </li>\n </ul>\n\n <div class=\"wx-block-export__drafts\">\n <wx-switch v-model=\"drafts\" :label=\"t('exchange.drafts')\" />\n <wx-text tone=\"muted\" size=\"sm\">{{ t('exchange.drafts-help') }}</wx-text>\n </div>\n </template>\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\n type=\"primary\"\n icon=\"download\"\n :loading=\"exporting\"\n :disabled=\"chosen.length === 0\"\n @click=\"run\"\n >\n {{ t('exchange.download') }}\n </wx-button>\n </wx-space>\n </template>\n </wx-dialog>\n</template>\n\n<style scoped>\n.wx-block-export {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-12);\n}\n\n.wx-block-export__list {\n display: flex;\n flex-direction: column;\n max-height: 320px;\n margin: 0;\n padding: 0;\n overflow-y: auto;\n list-style: none;\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n}\n\n.wx-block-export__check {\n display: flex;\n width: 100%;\n box-sizing: border-box;\n padding: var(--wx-space-8) var(--wx-space-12);\n}\n\n.wx-block-export__check :deep(.wx-checkbox__label) {\n display: flex;\n flex: 1;\n align-items: center;\n justify-content: space-between;\n gap: var(--wx-space-12);\n min-width: 0;\n}\n\n.wx-block-export__row + .wx-block-export__row {\n border-top: 1px solid var(--wx-border-default);\n}\n\n.wx-block-export__title {\n margin-right: var(--wx-space-6);\n}\n\n.wx-block-export__meta,\n.wx-block-export__version {\n font-size: var(--wx-font-size-xs);\n color: var(--wx-text-muted);\n}\n\n.wx-block-export__version {\n flex-shrink: 0;\n}\n\n.wx-block-export__drafts {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-4);\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 return findPair(root, `wx:${key}`)\n}\n\n/**\n * The pair around a region — `<!--wx-region:name-->` — which the region's own preview prints\n * whatever the region holds, its fallback included.\n */\nexport function findRegion(root: Node, name: string): MarkerRange | null {\n return findPair(root, `wx-region:${name}`)\n}\n\nfunction findPair(root: Node, opener: 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 === opener) {\n start = node as Comment\n } else if (start !== null && text === `/${opener}`) {\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/**\n * What a block prints that is never drawn. A block holding a shared block starts with the\n * region's stylesheet, printed in place — and a `<link>` taken for the block was a box of nothing\n * at the top of the page: the outline went nowhere and the preview never scrolled to it.\n */\nconst UNDRAWN = new Set(['link', 'style', 'script', 'template', 'meta', 'noscript'])\n\n/**\n * The element a block is pointed at by — the outline, the scroll: the first one it prints that\n * takes room on the page. One that draws nothing at all, or where the layout cannot be measured,\n * gives the first it prints that could.\n */\nexport function blockElement(root: Node, key: string): Element | null {\n const range = findRange(root, key)\n\n return range ? (drawnElements(range)[0] ?? null) : null\n}\n\n/** Elements between a pair of markers that could be drawn, the ones that are drawn first. */\nfunction drawnElements(range: MarkerRange): Element[] {\n const drawn: Element[] = []\n const empty: Element[] = []\n\n for (let node = range.start.nextSibling; node && node !== range.end; node = node.nextSibling) {\n if (node.nodeType !== 1) continue\n\n const element = node as Element\n\n if (UNDRAWN.has(element.tagName.toLowerCase())) continue\n\n const rect = element.getBoundingClientRect()\n\n ;(rect.width > 0 || rect.height > 0 ? drawn : empty).push(element)\n }\n\n return [...drawn, ...empty]\n}\n\n/**\n * Where a region stands on the page: one box around everything it printed, in the page's own\n * coordinates. Null when the page does not print it, or it printed nothing that takes room.\n */\nexport function regionRect(\n doc: Document,\n name: string,\n): { top: number; left: number; width: number; height: number } | null {\n const range = findRegion(doc, name)\n\n if (!range) return null\n\n let top = Infinity\n let left = Infinity\n let right = -Infinity\n let bottom = -Infinity\n\n for (const element of drawnElements(range)) {\n const rect = element.getBoundingClientRect()\n\n if (rect.width === 0 && rect.height === 0) continue\n\n top = Math.min(top, rect.top)\n left = Math.min(left, rect.left)\n right = Math.max(right, rect.right)\n bottom = Math.max(bottom, rect.bottom)\n }\n\n return top === Infinity ? null : { top, left, width: right - left, height: bottom - top }\n}\n\nexport const REGION_FRAME_ID = 'wx-preview-region'\n\n/**\n * Draw a frame around a region of the page, or take it away (null).\n *\n * A box laid over the page rather than a class on an element, as a block has: a region is any\n * number of blocks side by side, and wrapping them in an element of ours would break the site's\n * own rules — `.site-main > section` stops matching the moment there is a `div` in between.\n * Hangs off the root element and not the body, which a site may have positioned: there its top\n * is the page's top, whatever the body's margins.\n */\nexport function frameRegion(doc: Document, name: string | null): void {\n const rect = name === null ? null : regionRect(doc, name)\n let box = doc.getElementById(REGION_FRAME_ID)\n\n if (rect === null) {\n box?.remove()\n\n return\n }\n\n if (box === null) {\n box = doc.createElement('div')\n box.id = REGION_FRAME_ID\n box.setAttribute('aria-hidden', 'true')\n doc.documentElement.appendChild(box)\n }\n\n const view = doc.defaultView\n const top = rect.top + (view?.scrollY ?? 0)\n const left = rect.left + (view?.scrollX ?? 0)\n\n box.style.cssText =\n `position:absolute;top:${top}px;left:${left}px;width:${rect.width}px;height:${rect.height}px;` +\n // The selected block's outline, so the two read as one family: what is being edited.\n 'outline:2px solid #427edd;outline-offset:-2px;pointer-events:none;z-index:2147483646;margin:0;'\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\nexport const HIDDEN_CLASS = 'wx-preview-hidden'\n\n/**\n * Mark the blocks switched off. The page drawn under the preview token leaves a hidden block out,\n * but one hidden after the page was drawn is still in the frame until it reloads — and it looked\n * exactly like the blocks that will be on the site.\n */\nexport function markHidden(doc: Document, keys: string[]): void {\n ensureStyle(doc)\n\n for (const element of Array.from(doc.querySelectorAll(`.${HIDDEN_CLASS}`))) {\n element.classList.remove(HIDDEN_CLASS)\n }\n\n for (const key of keys) {\n blockElement(doc, key)?.classList.add(HIDDEN_CLASS)\n }\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 // Dimmed and greyed, not removed: it is still the block an editor clicks to switch back on.\n `.${HIDDEN_CLASS}{opacity:.35;filter:grayscale(1);outline:1px dashed #8a8f98;outline-offset:-1px;}`\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, '&').replace(/\"/g, '"').replace(/</g, '<')\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/**\n * One block taken out and others put where it stood, in its list — what «Make it this page's own»\n * does to a shared block. The tree as it was when the key is not in it.\n */\nexport function swapNode(tree: BlockNode[], key: string, nodes: BlockNode[]): 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, ...clone(nodes))\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 tariffs: [\n 'name',\n 'badge',\n 'price',\n 'amount',\n 'currency',\n 'symbol',\n 'period',\n 'price_text',\n 'features',\n 'description',\n 'button',\n 'featured',\n 'service_links',\n 'fields',\n ],\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: 'default', value: '', info: 'Shown and read until the field is set.' },\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","/**\n * CSS knows only tokens (THEMES §8) — the theme engine's `Checks\\CssCheck`, rule for rule, for\n * the editor's live lints. Not a parser: a walk over braces and semicolons that knows strings,\n * comments and parentheses.\n *\n * Unlike the engine it has no `media-width`: the editor's `media-query` says it of any `@media`.\n */\n\nexport type CssProblem = 'literal-color' | 'literal-font' | 'unknown-token' | 'token-fallback'\n\nexport interface CssFinding {\n problem: CssProblem\n line: number\n subject: string\n}\n\n/** CSS Color 4 — every named colour a browser paints. */\nconst NAMED = [\n 'aliceblue',\n 'antiquewhite',\n 'aqua',\n 'aquamarine',\n 'azure',\n 'beige',\n 'bisque',\n 'black',\n 'blanchedalmond',\n 'blue',\n 'blueviolet',\n 'brown',\n 'burlywood',\n 'cadetblue',\n 'chartreuse',\n 'chocolate',\n 'coral',\n 'cornflowerblue',\n 'cornsilk',\n 'crimson',\n 'cyan',\n 'darkblue',\n 'darkcyan',\n 'darkgoldenrod',\n 'darkgray',\n 'darkgreen',\n 'darkgrey',\n 'darkkhaki',\n 'darkmagenta',\n 'darkolivegreen',\n 'darkorange',\n 'darkorchid',\n 'darkred',\n 'darksalmon',\n 'darkseagreen',\n 'darkslateblue',\n 'darkslategray',\n 'darkslategrey',\n 'darkturquoise',\n 'darkviolet',\n 'deeppink',\n 'deepskyblue',\n 'dimgray',\n 'dimgrey',\n 'dodgerblue',\n 'firebrick',\n 'floralwhite',\n 'forestgreen',\n 'fuchsia',\n 'gainsboro',\n 'ghostwhite',\n 'gold',\n 'goldenrod',\n 'gray',\n 'green',\n 'greenyellow',\n 'grey',\n 'honeydew',\n 'hotpink',\n 'indianred',\n 'indigo',\n 'ivory',\n 'khaki',\n 'lavender',\n 'lavenderblush',\n 'lawngreen',\n 'lemonchiffon',\n 'lightblue',\n 'lightcoral',\n 'lightcyan',\n 'lightgoldenrodyellow',\n 'lightgray',\n 'lightgreen',\n 'lightgrey',\n 'lightpink',\n 'lightsalmon',\n 'lightseagreen',\n 'lightskyblue',\n 'lightslategray',\n 'lightslategrey',\n 'lightsteelblue',\n 'lightyellow',\n 'lime',\n 'limegreen',\n 'linen',\n 'magenta',\n 'maroon',\n 'mediumaquamarine',\n 'mediumblue',\n 'mediumorchid',\n 'mediumpurple',\n 'mediumseagreen',\n 'mediumslateblue',\n 'mediumspringgreen',\n 'mediumturquoise',\n 'mediumvioletred',\n 'midnightblue',\n 'mintcream',\n 'mistyrose',\n 'moccasin',\n 'navajowhite',\n 'navy',\n 'oldlace',\n 'olive',\n 'olivedrab',\n 'orange',\n 'orangered',\n 'orchid',\n 'palegoldenrod',\n 'palegreen',\n 'paleturquoise',\n 'palevioletred',\n 'papayawhip',\n 'peachpuff',\n 'peru',\n 'pink',\n 'plum',\n 'powderblue',\n 'purple',\n 'rebeccapurple',\n 'red',\n 'rosybrown',\n 'royalblue',\n 'saddlebrown',\n 'salmon',\n 'sandybrown',\n 'seagreen',\n 'seashell',\n 'sienna',\n 'silver',\n 'skyblue',\n 'slateblue',\n 'slategray',\n 'slategrey',\n 'snow',\n 'springgreen',\n 'steelblue',\n 'tan',\n 'teal',\n 'thistle',\n 'tomato',\n 'turquoise',\n 'violet',\n 'wheat',\n 'white',\n 'whitesmoke',\n 'yellow',\n 'yellowgreen',\n].join('|')\n\nconst GENERIC_FONTS = [\n 'serif',\n 'sans-serif',\n 'monospace',\n 'cursive',\n 'fantasy',\n 'system-ui',\n 'ui-serif',\n 'ui-sans-serif',\n 'ui-monospace',\n 'ui-rounded',\n 'math',\n 'emoji',\n 'fangsong',\n]\n\nconst WIDE = ['inherit', 'initial', 'unset', 'revert', 'revert-layer']\n\nconst FONT_KEYWORDS = [\n 'normal',\n 'italic',\n 'oblique',\n 'bold',\n 'bolder',\n 'lighter',\n 'small-caps',\n 'ultra-condensed',\n 'extra-condensed',\n 'condensed',\n 'semi-condensed',\n 'semi-expanded',\n 'expanded',\n 'extra-expanded',\n 'ultra-expanded',\n 'xx-small',\n 'x-small',\n 'small',\n 'medium',\n 'large',\n 'x-large',\n 'xx-large',\n 'xxx-large',\n 'smaller',\n 'larger',\n 'caption',\n 'icon',\n 'menu',\n 'message-box',\n 'small-caption',\n 'status-bar',\n]\n\n/** Properties whose values are names, not paint: an animation called `fade`, a grid area `aside`. */\nconst NOT_PAINT =\n /^(?:font|font-[a-z-]+|transition(?:-[a-z-]+)?|animation(?:-[a-z-]+)?|grid(?:-[a-z-]+)?|will-change|content|counter-[a-z-]+|quotes|container(?:-[a-z-]+)?|view-transition-name|list-style-type)$/\n\n/**\n * @param tokens The chain's vocabulary, names without `--site-`.\n */\nexport function cssFindings(css: string, tokens: Iterable<string>): CssFinding[] {\n const vocabulary = new Set(tokens)\n const source = css.replace(/\\/\\*[\\s\\S]*?\\*\\//g, (comment) => comment.replace(/[^\\n]/g, ' '))\n const findings: CssFinding[] = []\n\n for (const [text, offset, inside] of declarations(source)) {\n if (/^@(?:font-face|property)\\b/i.test(inside)) continue\n\n const colon = text.indexOf(':')\n const property = text.slice(0, colon).trim().toLowerCase()\n const start = offset + colon + 1\n\n for (const [problem, at, subject] of declaration(property, text.slice(colon + 1), vocabulary)) {\n findings.push({ problem, line: lineAt(source, start + at), subject })\n }\n }\n\n return findings\n}\n\nfunction declaration(\n property: string,\n value: string,\n vocabulary: Set<string>,\n): [CssProblem, number, string][] {\n const found: [CssProblem, number, string][] = []\n\n for (const reference of value.matchAll(/var\\(\\s*--([A-Za-z0-9_-]+)\\s*([,)])/g)) {\n const name = reference[1]!\n\n // A block's own variable — `var(--team-columns, 3)` — keeps its default.\n if (!name.startsWith('site-')) continue\n\n if (!vocabulary.has(name.slice(5))) found.push(['unknown-token', reference.index, `--${name}`])\n if (reference[2] === ',') found.push(['token-fallback', reference.index, `var(--${name}, …)`])\n }\n\n const paint = value.replace(\n /\"(?:[^\"\\\\]|\\\\.)*\"|'(?:[^'\\\\]|\\\\.)*'|url\\([^)]*\\)|--[A-Za-z0-9_-]+/gi,\n (match) => ' '.repeat(match.length),\n )\n\n for (const color of paint.matchAll(\n /(?<![\\w&-])#[0-9a-f]{3,8}(?![\\w-])|(?<![\\w-])(?:rgba?|hsla?|hwb|lab|lch|oklab|oklch|color)\\(/gi,\n )) {\n found.push(['literal-color', color.index, color[0].endsWith('(') ? `${color[0]}…)` : color[0]])\n }\n\n if (property.startsWith('--')) {\n const whole = new RegExp(`^(\\\\s*)(${NAMED})\\\\s*(?:!important\\\\s*)?$`, 'i').exec(paint)\n if (whole) found.push(['literal-color', whole[1]!.length, whole[2]!])\n } else if (!NOT_PAINT.test(property)) {\n for (const named of paint.matchAll(new RegExp(`(?<![\\\\w-])(${NAMED})(?![\\\\w-])`, 'gi'))) {\n found.push(['literal-color', named.index, named[1]!])\n }\n }\n\n if (property === 'font-family' || property === 'font') {\n for (const [family, at] of families(property, value)) found.push(['literal-font', at, family])\n }\n\n return found.sort((a, b) => a[1] - b[1])\n}\n\nfunction families(property: string, value: string): [string, number][] {\n const bare = value.replace(/var\\([^()]*(?:\\([^()]*\\)[^()]*)*\\)|!important/gi, (match) =>\n ' '.repeat(match.length),\n )\n let allowed = [...GENERIC_FONTS, ...WIDE]\n const found: [string, number][] = []\n\n if (property === 'font-family') {\n for (const item of bare.matchAll(/[^,]+/g)) {\n const family = item[0].trim()\n\n if (family !== '' && !allowed.includes(family.toLowerCase())) {\n found.push([family, item.index + item[0].indexOf(family[0]!)])\n }\n }\n\n return found\n }\n\n // The shorthand: keywords and families share the line; `Open Sans` is two unknown words in a row.\n allowed = [...allowed, ...FONT_KEYWORDS]\n let end: number | null = null\n\n for (const word of bare.matchAll(/\"[^\"]*\"|'[^']*'|(?<![\\w.%#-])[A-Za-z_-][A-Za-z0-9_-]*/g)) {\n const quoted = word[0][0] === '\"' || word[0][0] === \"'\"\n\n if (!quoted && allowed.includes(word[0].toLowerCase())) {\n end = null\n continue\n }\n\n if (!quoted && end !== null && bare.slice(end, word.index).trim() === '') {\n found[found.length - 1]![0] += ` ${word[0]}`\n } else {\n found.push([word[0], word.index])\n }\n\n end = quoted ? null : word.index + word[0].length\n }\n\n return found\n}\n\n/** Declarations — what a `;` or a `}` closes inside a block — with their offset and the at-rule they stand in. */\nfunction declarations(source: string): [string, number, string][] {\n const found: [string, number, string][] = []\n const stack: string[] = []\n let start = 0\n let quote: string | null = null\n let parens = 0\n\n for (let i = 0; i < source.length; i++) {\n const char = source[i]!\n\n if (quote !== null) {\n if (char === '\\\\') i++\n else if (char === quote) quote = null\n continue\n }\n\n if (char === '\"' || char === \"'\") quote = char\n else if (char === '(') parens++\n else if (char === ')') parens = Math.max(0, parens - 1)\n else if (parens === 0 && (char === '{' || char === ';' || char === '}')) {\n const raw = source.slice(start, i)\n const text = raw.trim()\n const offset = start + (raw.length - raw.trimStart().length)\n\n if (char === '{') {\n stack.push(text)\n } else if (stack.length > 0 && text !== '' && !text.startsWith('@') && text.includes(':')) {\n found.push([text, offset, [...stack].reverse().find((p) => p.startsWith('@')) ?? ''])\n }\n\n if (char === '}') stack.pop()\n\n start = i + 1\n }\n }\n\n return found\n}\n\nfunction lineAt(source: string, offset: number): number {\n return source.slice(0, Math.max(0, offset)).split('\\n').length\n}\n","import type { ScreenNode } from '@webx-ui/schema'\nimport { cssFindings, type CssProblem } from './css-tokens'\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 * On a site with a theme, the styles also know only its tokens (`tokenLints`).\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 tokens: string[] | null = null,\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 // The runtime and the panel match the marker to the slug exactly; «Quote» on `quote` never ran.\n const marker = /data-wx-block\\s*=\\s*([\"'])([^\"']*)\\1/.exec(content.template)?.[2]\n\n if (marker !== undefined && !marker.includes('{{') && marker !== slug) {\n lints.push({\n file: 'template',\n code: 'marker-slug',\n line: null,\n message: t('checks.marker-slug', { marker, slug }),\n })\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 for (const [field, line] of stringOnText(content.template, content.schema)) {\n lints.push({\n file: 'template',\n code: 'string-on-text',\n line,\n message: t('checks.string-on-text', { field }),\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, ...tokenLints(content.styles, tokens, t)]\n}\n\n/**\n * CSS knows only tokens (THEMES §8), as warnings: a literal colour or font, a `--site-*` the\n * theme does not have, a fallback inside one — one line per kind, on the first place it stands.\n * Only on a site with a theme (`tokens` is its vocabulary, null without one). `Lints::tokens()`.\n */\nexport function tokenLints(styles: string, tokens: string[] | null, t: Translate): Lint[] {\n if (tokens === null || styles.trim() === '') return []\n\n const codes: Record<CssProblem, [string, 'values' | 'tokens']> = {\n 'literal-color': ['literal-colors', 'values'],\n 'literal-font': ['literal-fonts', 'values'],\n 'unknown-token': ['unknown-tokens', 'tokens'],\n 'token-fallback': ['token-fallbacks', 'tokens'],\n }\n const grouped = new Map<CssProblem, [string, number][]>()\n\n for (const finding of cssFindings(styles, tokens)) {\n grouped.set(finding.problem, [\n ...(grouped.get(finding.problem) ?? []),\n [finding.subject, finding.line],\n ])\n }\n\n const lints: Lint[] = []\n\n for (const [problem, [code, param]] of Object.entries(codes) as [\n CssProblem,\n [string, 'values' | 'tokens'],\n ][]) {\n const subjects = grouped.get(problem)\n\n if (subjects) {\n lints.push({\n file: 'styles',\n code,\n line: subjects[0]![1],\n message: t(`checks.${code}`, { [param]: few(subjects) }),\n })\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 // A closure's parameters and what it `use`s are its own: `wx_text($lead)->map(fn ($text) => …)`.\n for (const closure of template.matchAll(/(?:fn|function)\\s*\\(([^)]*)\\)/g)) {\n for (const name of closure[1]!.matchAll(/\\$([a-zA-Z_]\\w*)/g)) declared.add(name[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\n/**\n * Calls that make a string of what they are given — a field with a shortcode becomes its HTML,\n * which `{{ }}` then escapes again. `STRING_CALLS` in `Panel\\Lints`.\n */\nconst STRING_CALLS =\n 'trim|rtrim|ltrim|chop|strtoupper|strtolower|ucfirst|lcfirst|ucwords|mb_strtoupper|mb_strtolower|mb_convert_case|mb_substr|mb_strimwidth|substr|str_replace|str_ireplace|preg_replace|preg_replace_callback|sprintf|vsprintf|strip_tags|nl2br|wordwrap|str_pad|strrev|html_entity_decode|htmlspecialchars|e|str|Str::\\\\w+'\n\n/**\n * Text fields a template turns into a string and prints with `{{ }}`: `{{ rtrim($heading, '.') }}`\n * prints `Call <a href=…` once the heading holds `[phone]`. `wx_text()` is the fix, and an\n * echo that goes through it is not counted; nor is `$heading->plain()`, which is text.\n */\nexport function stringOnText(template: string, schema: ScreenNode[]): [string, number][] {\n const references = textFields(schema).map(([name, inItem]) => {\n const quoted = name.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n\n return inItem\n ? new RegExp(`\\\\$\\\\w+\\\\[\\\\s*['\"]${quoted}['\"]\\\\s*\\\\](?!\\\\s*->)`, 'g')\n : new RegExp(`\\\\$${quoted}\\\\b(?!\\\\s*(?:->|\\\\[|\\\\())`, 'g')\n })\n\n if (references.length === 0) return []\n\n const found = new Map<string, number>()\n const call = new RegExp(`(?<![\\\\w$>:])(?:${STRING_CALLS})\\\\s*\\\\(|\\\\(\\\\s*string\\\\s*\\\\)`, 'i')\n\n for (const echo of template.matchAll(/(?<!@)\\{\\{(?!--)([\\s\\S]*?)\\}\\}/g)) {\n const expression = echo[1]!\n const offset = echo.index + 2\n\n if (expression.includes('wx_text(')) continue\n\n const start = call.exec(expression)?.index ?? null\n\n for (const pattern of references) {\n for (const use of expression.matchAll(pattern)) {\n const at = use.index\n // Joined with `.` is the same string as a cast.\n const joined =\n /(?<!\\.)\\.\\s*$/.test(expression.slice(0, at)) ||\n /^\\s*\\.(?![.=\\d])/.test(expression.slice(at + use[0].length))\n\n if (((start !== null && at > start) || joined) && !found.has(use[0])) {\n found.set(use[0], lineAt(template, offset + at))\n }\n }\n }\n }\n\n return [...found]\n}\n\n/** The text fields the renderer resolves shortcodes in, and whether each is a repeater item's. */\nfunction textFields(nodes: ScreenNode[], inItem = false): [string, boolean][] {\n const fields: [string, boolean][] = []\n\n for (const node of nodes) {\n const key = node.id ?? node.name\n const kind = node.props?.type ?? 'text'\n const text =\n node.type === 'wx-textarea' ||\n (node.type === 'wx-input' && (kind === 'text' || kind === 'search'))\n\n if (text && typeof key === 'string' && /^[A-Za-z_]\\w*$/.test(key)) {\n fields.push([key, inItem])\n continue\n }\n\n if (node.children) {\n fields.push(...textFields(node.children, inItem || node.type === 'wx-repeater'))\n }\n }\n\n return fields\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 { BlockNode, 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 * What the top level of the constructor is, when it is not a page.\n *\n * A layout region is edited with the same `wx-blocks` field as a page, from a screen described\n * once for every region — so what differs between `header` and `footer` (the name types list in\n * `allowed_in`, and the region's own `allow` and `max` from the site's config) cannot be written\n * into the description. The editor hosting the screen provides it instead, the way it provides\n * the preview.\n */\nexport interface BlocksTop {\n /** The name of the top level in `allowed_in` — `region:header`. */\n root: string\n /** What \"Move to\" calls the top level — the region's title rather than \"The page\". */\n label?: string\n /** What may stand 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 region the preview frames and scrolls to: a shared block, which stands wherever a page\n * put it. A header needs neither — it is at the top of every page.\n */\n frame?: string | null\n}\n\nexport const blocksTopKey: InjectionKey<Readonly<Ref<BlocksTop | null>>> = Symbol('wx-blocks-top')\n\n/** Called by the hosting screen, above the `wx-blocks` field. */\nexport function provideBlocksTop(top: Readonly<Ref<BlocksTop | null>>): void {\n provide(blocksTopKey, top)\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\n/**\n * What a «Shared block» form needs of the constructor it is open in, and a field drawn by the\n * renderer cannot reach otherwise: which block it is, and the way to put others in its place.\n */\nexport interface BlocksFragmentHost {\n /** The key of the block whose form is open — the one a field in that form belongs to. */\n selected: Readonly<Ref<string | null>>\n /** The shared block this constructor edits, when it edits one: never offered inside itself. */\n own: Readonly<Ref<string | null>>\n /**\n * Put these blocks where the block with this key stands, and open the first of them. Whether it\n * was done — the panel on the site writes it to the draft first, and the draft may refuse.\n */\n detach(key: string, nodes: BlockNode[]): boolean | Promise<boolean>\n}\n\nexport const blocksFragmentKey: InjectionKey<BlocksFragmentHost> = Symbol('wx-blocks-fragment')\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 createModal,\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 BlockExportDialog from './BlockExportDialog.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, block.value?.tokens ?? null))\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\n/**\n * What \"Insert a field\" offers: the fields a template can read, as the snippet that reads them.\n *\n * Through layout (cards, tabs, rows) and not into a field: a repeater's children are keys of its\n * rows, not variables, so the repeater is offered as a loop over them; a container is offered as\n * `@blocks('…')`, which is how its blocks are printed. A heading, a note or a divider in the form\n * holds no value and is not offered at all.\n */\nconst fieldSnippets = computed(() => insertable(content.schema))\n\nfunction insertable(nodes: BlockContent['schema']): { id: string; label: string; text: string }[] {\n const found: { id: string; label: string; text: string }[] = []\n\n for (const node of nodes) {\n if (LAYOUT.includes(node.type)) {\n found.push(...insertable(node.children ?? []))\n continue\n }\n\n if (!node.id) continue\n\n if (node.type === 'wx-blocks') {\n found.push({ id: node.id, label: `@blocks('${node.id}')`, text: `@blocks('${node.id}')` })\n } else if (node.type === 'wx-repeater') {\n const keys = (node.children ?? []).filter((child) => child.id && !LAYOUT.includes(child.type))\n const inner = keys.map((child) => `{{ $item['${child.id}'] }}`).join(' ')\n\n found.push({\n id: node.id,\n label: `@foreach ($${node.id} …)`,\n text: `@foreach ($${node.id} ?? [] as $item)\\n ${inner}\\n@endforeach`,\n })\n } else {\n found.push({ id: node.id, label: pill(node.id), text: pill(node.id) })\n }\n }\n\n return found\n}\n\n/** The schema types that arrange or explain fields and hold no value — `Schema::LAYOUT` on the server. */\nconst LAYOUT = [\n 'wx-card',\n 'wx-tabs',\n 'wx-tab',\n 'wx-row',\n 'wx-col',\n 'wx-divider',\n 'wx-heading',\n 'wx-text',\n 'wx-alert',\n]\n\n/**\n * The containers of the schema and what each takes of its own: the settings' \"May hold\" applies\n * to a field that names nothing, and says so when every field names its own.\n */\nconst containerFields = computed(() =>\n schemaFields(content.schema)\n .filter((node) => node.type === 'wx-blocks')\n .map((node) => ({\n id: node.id,\n allow: Array.isArray(node.props?.allow) ? (node.props.allow as string[]) : null,\n })),\n)\n\nconst allowHelp = computed(() => {\n const fields = containerFields.value\n\n if (fields.length === 0) return t('page.allow-help-none')\n\n const own = fields.filter((field) => field.allow !== null)\n\n if (own.length === 0) return t('page.allow-help')\n\n return t('page.allow-from-fields', {\n fields: own.map((field) => `${field.id}: ${field.allow!.join(', ') || '—'}`).join('; '),\n })\n})\n\n/** The row's own settings as a type carries them — what decides whether a save changed any. */\nfunction settingsOf(type: BlockType): Record<string, unknown> {\n return {\n kind: kindOf(type),\n slug: type.slug,\n title: type.title,\n description: type.description,\n icon: type.icon,\n group: type.group,\n sort: type.sort,\n allow: type.allow,\n allowed_in: type.allowed_in,\n max_per_entity: type.max_per_entity,\n is_enabled: type.is_enabled,\n }\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/** A field's snippet at the caret of the template editor. */\nfunction insertField(text: 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 += text\n\n return\n }\n\n editor.dispatch(editor.state.replaceSelection(text))\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 const settingsBefore = JSON.stringify(settingsOf(block.value))\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 // Three different outcomes, three different sentences: a rename (and what it rewrote), a new\n // version, settings alone. \"Nothing changed\" was said after a rename that rewrote every page.\n if (saved.renamed) {\n toast.success(\n t('page.renamed', {\n slug: saved.renamed.to,\n pages: saved.renamed.entities,\n types: saved.renamed.types,\n }),\n )\n } else if (saved.draft && saved.draft.number !== before) {\n toast.success(t('page.saved', { number: saved.draft.number }))\n } else if (JSON.stringify(settingsOf(saved)) !== settingsBefore) {\n toast.success(t('page.settings-saved'))\n } else {\n toast.success(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 publishAsking(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?.translations) {\n // Asked and declined: nothing was published, and nothing more to say.\n return\n }\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\n/**\n * Publish, and when the draft takes `localized` off a field over pages holding several languages,\n * ask whether to keep only the main one — the server refuses with 409 and the pages, and the same\n * request goes again with the answer.\n */\nasync function publishAsking(blockId: number): Promise<BlockType> {\n try {\n return await api.publish(blockId)\n } catch (error) {\n const body = (error as { status?: number; body?: PublishRefusal }).body\n\n if (!body?.translations) throw error\n\n const agreed = await confirm({\n title: t('page.drop-translations-title'),\n message: body.message,\n confirmText: t('page.drop-translations-confirm'),\n cancelText: t('page.cancel'),\n tone: 'danger',\n })\n\n if (!agreed) throw error\n\n return api.publish(blockId, { dropTranslations: true })\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 languageNotice = computed(() => {\n const changes = block.value?.language_changes\n\n if (!changes || changes.flips.length === 0) return null\n\n return t('page.localized-changes', {\n fields: changes.flips\n .map((flip) => (flip.child ? `${flip.field}.*.${flip.child}` : flip.field))\n .join(', '),\n count: changes.entities.length,\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 exportType = createModal<true, { selected?: string[] }>(BlockExportDialog)\n\n/*\n * Export stands here as well as on the list: a block for the catalogue of ready blocks is made\n * and taken one at a time, from the screen it was made on. What is saved goes, not the edits.\n */\nconst actions = computed<ScreenAction[]>(() => [\n ...(block.value\n ? [\n {\n key: 'export',\n label: t('exchange.export'),\n icon: 'download',\n run: () => void exportType({ selected: [block.value!.slug] }),\n },\n ]\n : []),\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 <!-- Said before anybody presses Publish: the draft changes the shape of values already on\n pages, and publishing converts them. -->\n <wx-alert v-if=\"languageNotice\" type=\"warning\" variant=\"soft\" :description=\"languageNotice\" />\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=\"fieldSnippets.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 fieldSnippets\"\n :key=\"field.id\"\n type=\"button\"\n class=\"wx-block-editor__pill\"\n :disabled=\"!canManage\"\n @click=\"insertField(field.text)\"\n v-text=\"field.label\"\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=\"allowHelp\"\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, onMounted, ref } from 'vue'\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { useElementWidth, WxIcon, WxText } 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 t = useTranslate('webx-blocks')\n\nconst box = ref<HTMLElement | null>(null)\nconst boxWidth = useElementWidth(box)\n\n/*\n * Drawn once it is near the screen, and never taken down again. Every frame loads the site's\n * stylesheet and its fonts, and the list of a site with forty types built forty of them at once —\n * most of them below the fold, all of them competing with the one being looked at.\n */\nconst seen = ref(typeof IntersectionObserver === 'undefined')\nlet watcher: IntersectionObserver | null = null\n\nonMounted(() => {\n if (seen.value || !box.value) return\n\n watcher = new IntersectionObserver(\n (entries) => {\n if (entries.some((entry) => entry.isIntersecting)) {\n seen.value = true\n watcher?.disconnect()\n watcher = null\n }\n },\n { rootMargin: '200px' },\n )\n watcher.observe(box.value)\n})\n\n/** Drawn, and nothing came out: a block that prints only with data to print. */\nconst blank = computed(() => props.thumbnail?.empty === true)\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(() => {\n observer?.disconnect()\n watcher?.disconnect()\n})\n</script>\n\n<template>\n <div ref=\"box\" class=\"wx-block-thumb\" :style=\"{ height: `${height}px` }\">\n <div v-if=\"blank\" class=\"wx-block-thumb__empty is-blank\">\n <wx-icon name=\"grid\" />\n <wx-text size=\"xs\" tone=\"muted\">{{ t('page.thumb-empty') }}</wx-text>\n </div>\n <iframe\n v-else-if=\"thumbnail && seen\"\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-if=\"!thumbnail\" 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\n.wx-block-thumb__empty.is-blank {\n place-content: center;\n gap: var(--wx-space-4);\n padding: var(--wx-space-8);\n text-align: center;\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(\n type: BlockType,\n parent: BlockType | null,\n allow: string[] | null,\n root = 'root',\n): 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 * What the top level is called in `allowed_in`: `root` for a page, `region:<name>` for a\n * layout region — a type made for the header must not be offered in the middle of an article.\n */\n root?: string\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, top.root)) {\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 /** What the top level is called in `allowed_in`: a page, or a layout region. */\n root?: string\n }>(),\n {\n parent: null,\n allow: null,\n tree: () => [],\n groups: () => [],\n blocksPath: null,\n root: 'root',\n },\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, props.root)\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 {\n bindFrame,\n blockElement,\n frameRegion,\n highlightBlock,\n markHidden,\n regionRect,\n replaceBlock,\n type FrameBinding,\n} 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 /** Keys of the blocks switched off: marked in the page until it reloads without them. */\n hidden?: string[]\n /**\n * A region to frame and scroll to: a shared block, which is wherever the page placed it and\n * not where a header always is — down the page under the content, more often than not.\n */\n region?: string | null\n }>(),\n { selected: null, reload: 0, compact: false, hidden: () => [], region: null },\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 /* The page moved under the frame drawn around the region — laid over it, not inside it — and\n a width that changed moves it as surely as a height. */\n if (props.region) frameRegion(page, props.region)\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 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 markHidden(page, props.hidden)\n frameRegion(page, props.region)\n reveal(props.selected ?? (props.region ? REGION : null))\n\n /* Measured after the ask, not before: the frame grows to its page on the next tick, and only an\n ask already pending is asked again then. Before, a block or a region further down than the\n window-high frame reached scrolled only as far as that frame let it — and stayed there. */\n watch_(page)\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/* What `pending` holds for the region rather than a block: no key of a block looks like it. */\nconst REGION = '\\u0000region'\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(rect: { top: number; height: number }): { top: number; height: number } | null {\n const box = frame.value?.getBoundingClientRect()\n\n if (!box) return null\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 target =\n pending === REGION\n ? props.region\n ? regionRect(page, props.region)\n : null\n : (blockElement(page, pending)?.getBoundingClientRect() ?? null)\n const at = target ? place(target) : 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) {\n highlightBlock(page, props.selected ?? null)\n markHidden(page, props.hidden)\n frameRegion(page, props.region)\n }\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.hidden,\n (keys) => {\n const page = doc()\n\n if (page && ready.value) markHidden(page, keys)\n },\n)\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, WxTooltip } 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 /** What the last save was refused for, by block key. */\n errors?: Record<string, string[]>\n /** What \"Copy\" put aside, for the paste lines; null while there is nothing. */\n clip?: BlockNode[] | null\n }>(),\n {\n parentKey: null,\n field: null,\n fieldNode: null,\n max: null,\n selected: null,\n disabled: false,\n depth: 0,\n errors: () => ({}),\n clip: null,\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 copy: [key: string]\n /** The clip into this list or a container's field, at `index` or at the end. */\n paste: [parentKey: string | null, field: string | null, node: ScreenNode | null, index?: number]\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\ninterface Flag {\n key: string\n icon: string\n tone: 'danger' | 'warning' | null\n text: string\n}\n\n/**\n * The marks beside a block's name, each with the words it stands for: refused on the last save,\n * a type nobody has, a type with an unpublished version or hidden from editors, a block switched\n * off. The hidden one is always there, not only on hover: the actions beside it are invisible at\n * rest, and a row that is merely dimmer than its neighbours is not a statement.\n */\nfunction flagsOf(node: BlockNode): Flag[] {\n const flags: Flag[] = []\n const refused = props.errors[node.key]\n const type = typeOf(node)\n\n if (refused?.length) {\n flags.push({ key: 'invalid', icon: 'warning', tone: 'danger', text: refused.join(' ') })\n }\n\n if (!type) {\n flags.push({\n key: 'unknown',\n icon: 'close-circle',\n tone: 'danger',\n text: t('field.unknown-type', { type: node.type }),\n })\n } else if (type.draft) {\n flags.push({ key: 'draft', icon: 'warning', tone: 'warning', text: t('field.draft-type') })\n } else if (type.is_enabled === false) {\n // Not the eye: that one means this block is off, which is a different thing from its type\n // being withdrawn from the catalogue.\n flags.push({ key: 'disabled', icon: 'lock', tone: null, text: t('field.disabled-type') })\n }\n\n if (node.hidden === true) {\n flags.push({ key: 'hidden', icon: 'eye-off', tone: null, text: t('field.hidden-note') })\n }\n\n return flags\n}\n\n/** How many blocks a container's field takes, or null for no limit. */\nfunction limitOf(field: ScreenNode): number | null {\n const max = field.props?.max\n\n return typeof max === 'number' ? max : null\n}\n\n/** A field that holds as many blocks as it takes: \"Add inside\" says so instead of doing nothing. */\nfunction isFull(node: BlockNode, field: ScreenNode): boolean {\n const limit = limitOf(field)\n\n return limit !== null && childrenIn(node, field).length >= limit\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 /* Copy is for another page or section; duplicate stays for this one, being one click. */\n {\n key: 'copy',\n icon: 'clipboard',\n label: t('field.copy'),\n run: () => emit('copy', node.key),\n },\n ...pasteActions(node, index, limit),\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\n/** What the clip is, in the words of a menu line: the block's name, or how many. */\nfunction clipLabel(prefix: 'paste-after' | 'paste-inside'): string {\n const clip = props.clip ?? []\n\n return clip.length === 1\n ? t(`field.${prefix}`, { title: titleOf(clip[0]!) })\n : t(`field.${prefix}-many`, { count: clip.length })\n}\n\n/**\n * Paste after this row, and — on a container — into each of its fields, which is the only way\n * into one that is still empty. Only while there is something to paste: a line that can only\n * say \"nothing copied\" is a line to read past every time.\n */\nfunction pasteActions(node: BlockNode, index: number, limit: number | null): RowAction[] {\n if (!props.clip?.length) return []\n\n const slots = fieldsOf(node)\n\n return [\n {\n key: 'paste-after',\n icon: 'clipboard-paste',\n label: clipLabel('paste-after'),\n disabled: limit !== null && props.nodes.length >= limit,\n run: () => emit('paste', props.parentKey, props.field, props.fieldNode, index + 1),\n },\n ...slots.map((slot) => ({\n key: `paste-inside-${slot.id}`,\n icon: 'clipboard-paste',\n label:\n slots.length > 1\n ? `${clipLabel('paste-inside')} · ${slot.label ?? slot.id}`\n : clipLabel('paste-inside'),\n disabled: isFull(node, slot),\n run: () => emit('paste', node.key, slot.id, slot),\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=\"{\n 'is-selected': selected === item.key,\n 'is-hidden': item.hidden === true,\n 'is-invalid': (errors[item.key]?.length ?? 0) > 0,\n }\"\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 <!-- The panel's own tooltip, not the browser's `title`: the same tip, delay and look as\n every other icon of the panel, and one a finger on a phone can open. -->\n <wx-tooltip v-for=\"flag in flagsOf(item)\" :key=\"flag.key\" :content=\"flag.text\">\n <span\n class=\"wx-blocks-tree__flag\"\n :class=\"flag.tone ? `is-${flag.tone}` : undefined\"\n role=\"img\"\n tabindex=\"0\"\n :aria-label=\"flag.text\"\n >\n <wx-icon :name=\"flag.icon\" />\n </span>\n </wx-tooltip>\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 :errors=\"errors\"\n :clip=\"clip\"\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 @copy=\"emit('copy', $event)\"\n @paste=\"(p, f, n, i) => emit('paste', p, f, n, i)\"\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 <!-- A full container says so, the way \"Move to\" marks one: a button that did nothing\n on a click was a button that looked broken. -->\n <button\n v-if=\"!disabled\"\n type=\"button\"\n class=\"wx-blocks-tree__add is-inner\"\n :disabled=\"isFull(item, slot)\"\n @click=\"emit('add', item.key, slot.id, slot)\"\n >\n <template v-if=\"isFull(item, slot)\">{{\n t('field.add-inside-full', { max: limitOf(slot)! })\n }}</template>\n <template v-else>+ {{ t('field.add-inside') }}</template>\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:not(:disabled) {\n color: var(--wx-color-primary);\n border-color: var(--wx-color-primary);\n background: var(--wx-color-primary-soft);\n}\n\n.wx-blocks-tree__add:disabled {\n cursor: not-allowed;\n border-style: solid;\n border-color: var(--wx-border-default);\n}\n\n/* A block a save was refused for: the row says so before anybody opens it. */\n.wx-blocks-tree__row.is-invalid {\n border-color: var(--wx-color-danger);\n}\n</style>\n","import { readonly, ref, type Ref } from 'vue'\nimport type { ScreenNode } from '@webx-ui/schema'\nimport { cloneNode, countType, walk } from './content'\nimport { allows } from './move'\nimport { kindOf } from './schema'\nimport type { BlockNode, BlockType } from './types'\n\n/**\n * Copy and paste of blocks, across pages and across modules of the same panel.\n *\n * The clipboard is the browser's storage rather than the system one: a block is not text, the\n * system clipboard asks for permission to be read, and what is copied here is only ever pasted\n * into a constructor of the same site — every module stores the same `{ key, type, values }`.\n * One entry, kept after a paste, so the same block can go onto several pages; every tab sees\n * what another one copied.\n */\n\nexport const CLIPBOARD_KEY = 'wx-blocks-clipboard'\n\nexport interface BlocksClip {\n format: 'webx-blocks-clip'\n /** Bumped when the shape changes; a clip of another version is treated as empty. */\n format_version: 1\n copied_at: string\n nodes: BlockNode[]\n}\n\nconst clip = ref<BlocksClip | null>(null)\nlet listening = false\n\n/** Storage that may be missing or refuse: a private window, blocked site data, a test. */\nfunction storage(): Storage | null {\n try {\n return typeof window === 'undefined' ? null : window.localStorage\n } catch {\n return null\n }\n}\n\n/** What is stored, if it is a clip this code understands — anything else is no clip at all. */\nexport function parseClip(raw: string | null): BlocksClip | null {\n if (!raw) return null\n\n try {\n const value = JSON.parse(raw) as Partial<BlocksClip> | null\n\n if (\n value?.format !== 'webx-blocks-clip' ||\n value.format_version !== 1 ||\n !Array.isArray(value.nodes) ||\n value.nodes.length === 0\n ) {\n return null\n }\n\n return value as BlocksClip\n } catch {\n return null\n }\n}\n\nfunction read(): BlocksClip | null {\n try {\n return parseClip(storage()?.getItem(CLIPBOARD_KEY) ?? null)\n } catch {\n return null\n }\n}\n\n/* One listener for the whole page, never removed: the clip is one value for every field on it. */\nfunction listen(): void {\n if (listening || typeof window === 'undefined') return\n\n listening = true\n clip.value = read()\n window.addEventListener('storage', (event) => {\n if (event.key === CLIPBOARD_KEY || event.key === null) clip.value = read()\n })\n}\n\nexport function useBlocksClipboard(): {\n clip: Readonly<Ref<BlocksClip | null>>\n copy: (nodes: BlockNode[]) => void\n clear: () => void\n} {\n listen()\n\n return {\n clip: readonly(clip) as Readonly<Ref<BlocksClip | null>>,\n copy(nodes) {\n const next: BlocksClip = {\n format: 'webx-blocks-clip',\n format_version: 1,\n copied_at: new Date().toISOString(),\n nodes: JSON.parse(JSON.stringify(nodes)) as BlockNode[],\n }\n\n clip.value = next\n\n try {\n storage()?.setItem(CLIPBOARD_KEY, JSON.stringify(next))\n } catch {\n // Full or refused: the clip still works in this tab, which is most of what it is for.\n }\n },\n clear() {\n clip.value = null\n\n try {\n storage()?.removeItem(CLIPBOARD_KEY)\n } catch {\n // Nothing to do: there was nothing it could have kept either.\n }\n },\n }\n}\n\n/** Why a block of the clip did not go in. */\nexport type SkipReason = 'unknown' | 'place' | 'limit' | 'full'\n\n/** The list a paste goes into, and the rules that list stands under. */\nexport interface PasteTarget {\n /** The whole tree of the page, for the per-page limits of the types. */\n tree: BlockNode[]\n /** The list itself — the tree, or a container's field. */\n list: BlockNode[]\n /** The container's type, or the top level's owner (a block's sample form), or null. */\n parent: BlockType | null\n allow: string[] | null\n max: number | null\n /** What the list is called in `allowed_in`; only the top level is ever anything but `root`. */\n root: string\n}\n\nexport interface PastePlan {\n /** Fresh copies, keys renewed all the way down, in the clip's order. */\n accepted: BlockNode[]\n skipped: { node: BlockNode; reason: SkipReason }[]\n}\n\n/**\n * What of the clip may go into this list, judged by the same rules the picker and \"Move to\"\n * go by, so a paste never puts down what adding by hand would not.\n *\n * Block by block rather than all or nothing: a page copied whole into a region that takes half\n * of it gets that half, and the rest is named. A block whose type — or the type of anything\n * inside it — this site does not offer is left out whole: half a section is not that section.\n */\nexport function planPaste(\n nodes: BlockNode[],\n target: PasteTarget,\n catalog: BlockType[],\n): PastePlan {\n const accepted: BlockNode[] = []\n const skipped: PastePlan['skipped'] = []\n const offered = (slug: string) =>\n catalog.find(\n (type) =>\n type.slug === slug &&\n kindOf(type) !== 'component' &&\n type.is_enabled &&\n type.published !== null,\n ) ?? null\n\n for (const node of nodes) {\n const type = offered(node.type)\n let known = type !== null\n\n walk([node], (inner) => {\n if (!catalog.some((entry) => entry.slug === inner.type)) known = false\n })\n\n if (!type || !known) {\n skipped.push({ node, reason: 'unknown' })\n continue\n }\n\n if (!allows(type, target.parent, target.allow, target.root)) {\n skipped.push({ node, reason: 'place' })\n continue\n }\n\n if (target.max !== null && target.list.length + accepted.length >= target.max) {\n skipped.push({ node, reason: 'full' })\n continue\n }\n\n const page = [...target.tree, ...accepted]\n let over = false\n\n walk([node], (inner) => {\n const limit = catalog.find((entry) => entry.slug === inner.type)?.max_per_entity ?? null\n\n if (limit !== null && countType(page, inner.type) + countType([node], inner.type) > limit) {\n over = true\n }\n })\n\n if (over) {\n skipped.push({ node, reason: 'limit' })\n continue\n }\n\n accepted.push(cloneNode(node))\n }\n\n return { accepted, skipped }\n}\n\n/** A container field's own rules, read off its node in the type's schema. */\nexport function slotRules(slot: ScreenNode | null): { allow: string[] | null; max: number | null } {\n return {\n allow: (slot?.props?.allow as string[] | undefined) ?? null,\n max: (slot?.props?.max as number | undefined) ?? null,\n }\n}\n","<script setup lang=\"ts\">\nimport {\n computed,\n getCurrentInstance,\n inject,\n onBeforeUnmount,\n onMounted,\n provide,\n ref,\n shallowRef,\n watch,\n} from 'vue'\nimport {\n adminKey,\n loadShortcodes,\n useErrorText,\n useTranslate,\n WxRowMenu,\n type AdminContext,\n type RowAction,\n type ShortcodeToken,\n} 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 screenErrorsKey,\n WxScreenRenderer,\n type RenderContext,\n type ScreenNode,\n type TypeRegistry,\n type ValidationErrors,\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 { planPaste, slotRules, useBlocksClipboard, type PastePlan } from './clipboard'\nimport {\n cloneNode,\n countInside,\n insertNode,\n locate,\n makeNode,\n removeNode,\n replaceList,\n setHidden,\n swapNode,\n updateValues,\n walk,\n} from './content'\nimport { useBlocksMessages } from './i18n'\nimport {\n blocksFragmentKey,\n blocksOwnerKey,\n blocksPreviewKey,\n blocksRootKey,\n blocksTopKey,\n} from './preview'\nimport { destinations, type Destination } from './move'\nimport { formSchema, markupFields, startValues, withPlaceholders, withShortcodes } 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 * The site's shortcodes, offered in the text fields of a block. Fetched from the panel when\n * absent, like the catalog.\n */\n shortcodes?: ShortcodeToken[] | null\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 shortcodes: null,\n },\n)\n\nconst model = defineModel<BlockNode[]>({ default: () => [] })\n\nconst nested = inject(blocksRootKey, false)\n/* The refusal of the last save of the screen this field stands on: `blocks.<key>.<field>`. */\nconst refusal = inject(screenErrorsKey, null)\n/* Inside the block editor's sample form, the top level is that block rather than a page. */\nconst owner = inject(blocksOwnerKey, null)\n/* In a layout region's editor, the top level is that region rather than a page. */\nconst top = inject(blocksTopKey, null)\nprovide(blocksTopKey, ref(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\n/* The field's own props win: a screen that narrows the top level has said so on purpose. */\nconst topAllow = computed(() => props.allow ?? top?.value?.allow ?? null)\nconst topMax = computed(() => props.max ?? top?.value?.max ?? null)\nconst topRoot = computed(() => top?.value?.root ?? 'root')\n/* The region the preview frames, when the screen above says which. */\nconst framed = computed(() => top?.value?.frame ?? null)\n\nconst tree = computed<BlockNode[]>(() => (Array.isArray(model.value) ? model.value : []))\n\n/**\n * The refusal, by block: key → field → messages. The server names a value by the block's key and\n * the field (`blocks.k1.title`), and a block standing where it may not by the key alone\n * (`blocks.k1`, under `''`). A limit of the whole page names the type (`blocks.hero`) — kept\n * under that, for the list above the tree.\n */\nconst refused = computed<Record<string, Record<string, string[]>>>(() => {\n const errors: ValidationErrors | undefined = refusal?.value\n const prefix = `${props.name ?? 'blocks'}.`\n const out: Record<string, Record<string, string[]>> = {}\n\n for (const [path, messages] of Object.entries(errors ?? {})) {\n if (!path.startsWith(prefix)) continue\n\n const rest = path.slice(prefix.length)\n const dot = rest.indexOf('.')\n const key = dot === -1 ? rest : rest.slice(0, dot)\n const field = dot === -1 ? '' : rest.slice(dot + 1)\n\n out[key] = { ...(out[key] ?? {}), [field]: messages }\n }\n\n return out\n})\n\n/** What the tree marks: every message of a block, in one list. */\nconst refusedByKey = computed<Record<string, string[]>>(() => {\n const out: Record<string, string[]> = {}\n\n for (const [key, fields] of Object.entries(refused.value)) {\n out[key] = Object.values(fields).flat()\n }\n\n return out\n})\n\n/** A refusal that names no block on the page — a limit of the whole page, by type. */\nconst pageRefusals = computed(() =>\n Object.entries(refusedByKey.value)\n .filter(([key]) => locate(tree.value, key) === null)\n .flatMap(([, messages]) => messages),\n)\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 root: 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 ? topAllow.value : ((slot?.props?.allow as string[] | undefined) ?? null)\n const max = parentKey === null ? topMax.value : ((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 // Only the top level is the region; a container's field is named by its own type.\n root: parentKey === null ? topRoot.value : 'root',\n })\n\n if (!type) return\n\n const node = makeNode(\n type.slug,\n startValues(type.content?.schema ?? [], type.content?.sample ?? {}),\n )\n set(insertNode(tree.value, parentKey, field, index ?? list.length, node))\n selectedKey.value = node.key\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\n/*\n * What a «Shared block» form asks of the constructor: the copies of the shared block put where it\n * stood, the first of them opened — what was there a moment ago is still what is on screen. Nothing\n * else changes: the page's draft takes them the ordinary way, autosave and history included.\n */\nprovide(blocksFragmentKey, {\n selected: selectedKey,\n own: computed(() =>\n topRoot.value.startsWith('region:') ? topRoot.value.slice('region:'.length) : null,\n ),\n detach(key: string, nodes: BlockNode[]): boolean {\n if (!locate(tree.value, key)) return false\n\n set(swapNode(tree.value, key, nodes))\n selectedKey.value = nodes[0]?.key ?? null\n\n return true\n },\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: topAllow.value,\n max: topMax.value,\n root: topRoot.value,\n }),\n topLabel: owner?.value?.title ?? top?.value?.label ?? 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\nconst { clip, copy: putAside } = useBlocksClipboard()\n\n/** The clip's blocks, for the tree's paste lines. */\nconst clipNodes = computed(() => clip.value?.nodes ?? null)\n\n/** One block, or the whole page; the toast names what went, so a click is seen to have worked. */\nfunction copyNodes(nodes: BlockNode[]): void {\n if (nodes.length === 0) return\n\n putAside(nodes)\n toast.success(\n nodes.length === 1\n ? t('field.copied', { title: titleOf(nodes[0]!) })\n : t('field.copied-many', { count: nodes.length }),\n )\n}\n\nfunction copyBlock(key: string): void {\n const found = locate(tree.value, key)\n if (found) copyNodes([found.node])\n}\n\n/** What did not go in and why, one name to a reason. */\nfunction skippedText(skipped: PastePlan['skipped']): string {\n return skipped\n .map(({ node, reason }) => `${titleOf(node)} (${t(`field.skip-${reason}`)})`)\n .join(', ')\n}\n\n/**\n * The clip into a list: the page, or a container's field, at `index` or at the end.\n *\n * Fresh keys all the way down, as for a duplicate: the same block twice on one page would be one\n * block to the preview's markers and to the refusals of a save. Only what this list may hold\n * goes in, by the picker's rules; the rest is named rather than dropped in silence. Nothing is\n * opened afterwards — a paste is often several blocks, and the tree is where they are seen.\n */\nfunction paste(\n parentKey: string | null,\n field: string | null,\n slot: ScreenNode | null,\n index?: number,\n): void {\n const nodes = clip.value?.nodes\n if (!nodes?.length) return\n\n const parent = parentKey ? locate(tree.value, parentKey) : null\n const list =\n parentKey === null\n ? tree.value\n : parent && field\n ? ((parent.node.values[field] as BlockNode[] | undefined) ?? [])\n : []\n const rules = parentKey === null ? { allow: topAllow.value, max: topMax.value } : slotRules(slot)\n\n const plan = planPaste(\n nodes,\n {\n tree: tree.value,\n list,\n parent: parent\n ? (catalog.value.find((type) => type.slug === parent.node.type) ?? null)\n : (owner?.value ?? null),\n allow: rules.allow,\n max: rules.max,\n root: parentKey === null ? topRoot.value : 'root',\n },\n catalog.value,\n )\n\n let next = tree.value\n let at = index ?? list.length\n\n for (const node of plan.accepted) {\n next = insertNode(next, parentKey, field, at++, node)\n }\n\n if (plan.accepted.length) set(next)\n\n if (plan.skipped.length) {\n toast.warning(t('field.paste-skipped', { list: skippedText(plan.skipped) }))\n } else {\n toast.success(t('field.pasted', { count: plan.accepted.length }))\n }\n}\n\n/** The list's own lines: the whole page into the clip, and the clip onto the end of the page. */\nconst listActions = computed<RowAction[]>(() => {\n const actions: RowAction[] = [\n {\n key: 'copy-all',\n icon: 'clipboard',\n label: t('field.copy-all'),\n disabled: tree.value.length === 0,\n run: () => copyNodes(tree.value),\n },\n ]\n const nodes = clip.value?.nodes ?? []\n\n if (!props.disabled && nodes.length) {\n actions.push({\n key: 'paste',\n icon: 'clipboard-paste',\n label:\n nodes.length === 1\n ? t('field.paste', { title: titleOf(nodes[0]!) })\n : t('field.paste-many', { count: nodes.length }),\n disabled: topMax.value !== null && tree.value.length >= topMax.value,\n run: () => paste(null, null, null),\n })\n }\n\n return actions\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\n/*\n * A save refused for a block's value opens that block, so the field with the message is on\n * screen: the tree marks it, but a form that is not open shows nothing under any field.\n */\nwatch(refusedByKey, (now) => {\n const keys = Object.keys(now).filter((key) => locate(tree.value, key) !== null)\n\n if (keys.length === 0 || (selectedKey.value !== null && keys.includes(selectedKey.value))) return\n\n selectedKey.value = keys[0]!\n})\n\n/** The open block's refusal, under the names its form's fields answer to. */\nconst selectedErrors = computed<ValidationErrors | undefined>(() => {\n const fields = selectedKey.value ? refused.value[selectedKey.value] : undefined\n\n if (!fields) return undefined\n\n const out: ValidationErrors = {}\n\n for (const [field, messages] of Object.entries(fields)) {\n if (field !== '') out[field] = messages\n }\n\n return out\n})\n\n/** What the open block was refused for as a whole — where it stands, not a value. */\nconst selectedPlacement = computed(() =>\n selectedKey.value ? (refused.value[selectedKey.value]?.[''] ?? []) : [],\n)\n\n/** Keys of the blocks switched off, for the preview to mark until it reloads without them. */\nconst hiddenKeys = computed(() => {\n const keys: string[] = []\n\n walk(tree.value, (node) => {\n if (node.hidden === true) keys.push(node.key)\n })\n\n return keys\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\n/*\n * Plain fields whose value holds tags, read once per block opened rather than on every keystroke:\n * the help under a field coming and going while somebody types into it would rebuild the form\n * under their caret.\n */\nconst marked = ref<string[]>([])\n\nwatch(\n [selectedKey, selectedType],\n () => {\n const schema = selectedType.value?.content?.schema\n marked.value =\n schema && selected.value ? markupFields(schema, selected.value.node.values ?? {}) : []\n },\n { immediate: true },\n)\n\n/*\n * The shortcodes of the site, for the text fields of the open block. Asked of the panel only\n * when a block is drawn here at all — a nested instance is a note — and once per panel, however\n * many blocks and pages are opened. They come late, and the fields take them when they do.\n */\nconst fetchedShortcodes = shallowRef<ShortcodeToken[]>([])\n\nif (admin && !nested && props.shortcodes === null) {\n void loadShortcodes(admin).then((list) => (fetchedShortcodes.value = list))\n}\n\nconst shortcodes = computed(() => props.shortcodes ?? fetchedShortcodes.value)\n\nconst formRoot = computed(() =>\n selectedType.value?.content\n ? withShortcodes(\n withPlaceholders(\n formSchema(selectedType.value.content.schema),\n selectedType.value.content.sample ?? {},\n marked.value,\n t('field.markup-in-text'),\n ),\n shortcodes.value,\n { tokensTitle: t('field.shortcodes'), tokensLabel: t('field.shortcodes-insert') },\n )\n : [],\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 <span class=\"wx-blocks__panel-extra\">\n <wx-text size=\"sm\" tone=\"muted\">{{ tree.length }}</wx-text>\n <wx-row-menu :actions=\"listActions\" :label=\"t('field.blocks')\" />\n </span>\n </div>\n <div v-if=\"pageRefusals.length\" class=\"wx-blocks__refusals\" role=\"alert\">\n <wx-text v-for=\"(line, index) in pageRefusals\" :key=\"index\" size=\"sm\" tone=\"danger\">{{\n line\n }}</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 :errors=\"refusedByKey\"\n :clip=\"clipNodes\"\n @select=\"select\"\n @add=\"add\"\n @remove=\"remove\"\n @duplicate=\"duplicate\"\n @copy=\"copyBlock\"\n @paste=\"paste\"\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 <div v-if=\"selectedPlacement.length\" class=\"wx-blocks__refusals\" role=\"alert\">\n <wx-text\n v-for=\"(line, index) in selectedPlacement\"\n :key=\"index\"\n size=\"sm\"\n tone=\"danger\"\n >{{ line }}</wx-text\n >\n </div>\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 :errors=\"selectedErrors\"\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 :hidden=\"hiddenKeys\"\n :reload=\"preview.reload?.value ?? 0\"\n :compact=\"compact\"\n :region=\"framed\"\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/* What a save was refused for that is not one field's: a limit of the page, a block standing\n where it may not. Above the tree or the form, where the eye starts. */\n.wx-blocks__refusals {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-4);\n padding: var(--wx-space-6) var(--wx-space-8);\n border-radius: var(--wx-radius-control);\n background: var(--wx-color-danger-soft);\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, ref, watch } from 'vue'\nimport { useAdmin, useErrorText, useTranslate } from '@webx-ui/module-admin'\nimport {\n toast,\n useModal,\n WxAlert,\n WxBadge,\n WxButton,\n WxDialog,\n WxEmpty,\n WxSkeleton,\n WxSpace,\n WxSwitch,\n WxText,\n} from '@webx-ui/core'\nimport { createBlocksApi } from './api'\nimport { useBlocksMessages } from './i18n'\nimport type { BlockImportRow, BlockImportStatus } from './types'\n\n/**\n * \"Import\" (§17.1): a file in, asked about twice. First the server reads it without writing —\n * what each type would become: new, updated, unchanged or refused, and why — then, once the\n * person has seen that, for real. A type that is already here is not replaced: it gets a new\n * draft version, so the site keeps drawing what it drew until someone publishes, unless the\n * switch to publish is on.\n *\n * Resolves with the rows written, so the section can fetch its list again; a run where some\n * type stayed behind keeps the dialog open on the result, because a toast would be gone before\n * the reason was read.\n */\nconst { resolve, dismiss, open } = useModal<BlockImportRow[]>()\n\nconst context = useAdmin()\nconst api = createBlocksApi(context)\nuseBlocksMessages()\n\nconst t = useTranslate('webx-blocks')\nconst message = useErrorText()\n\nconst picker = ref<HTMLInputElement | null>(null)\nconst name = ref<string | null>(null)\n/** The text of the file, sent as it is: decoded here, its strings would be trimmed on the way. */\nconst file = ref<string | null>(null)\nconst rows = ref<BlockImportRow[] | null>(null)\n/** Why the file was refused as a whole: not JSON, not a pack, a circle among its types. */\nconst refusal = ref<string | null>(null)\nconst publish = ref(false)\nconst reading = ref(false)\nconst importing = ref(false)\n/** The rows are the outcome, not the plan: the import has run. */\nconst done = ref(false)\n\nconst STATUS: Record<BlockImportStatus, 'success' | 'primary' | 'default' | 'danger'> = {\n created: 'success',\n updated: 'primary',\n unchanged: 'default',\n failed: 'danger',\n}\n\nconst writable = computed(() => (rows.value ?? []).filter((row) => row.status !== 'failed'))\nconst changes = computed(() =>\n writable.value.filter((row) => row.status !== 'unchanged' || (publish.value && row.writes)),\n)\n\n/** Nothing to write and nothing to publish: the button would be a promise of nothing. */\nconst upToDate = computed(\n () => rows.value !== null && writable.value.length > 0 && changes.value.length === 0,\n)\n\nfunction choose(): void {\n picker.value?.click()\n}\n\nfunction refusalOf(error: unknown): string {\n const body = (error as { status?: number; body?: { errors?: { file?: string[] } } }).body\n\n return body?.errors?.file?.[0] ?? message(error, t('exchange.import-failed'))\n}\n\nasync function onFile(event: Event): Promise<void> {\n const input = event.target as HTMLInputElement\n const chosen = input.files?.[0]\n\n // The same file chosen again must still fire `change` — it is how a fixed file is re-read.\n input.value = ''\n\n if (!chosen) return\n\n name.value = chosen.name\n rows.value = null\n refusal.value = null\n done.value = false\n reading.value = true\n\n try {\n const text = await chosen.text()\n\n try {\n JSON.parse(text)\n } catch {\n file.value = null\n refusal.value = t('exchange.not-json')\n\n return\n }\n\n file.value = text\n await plan()\n } finally {\n reading.value = false\n }\n}\n\n/** The dry run — with the publish checks when publishing is asked, so the plan warns first. */\nasync function plan(): Promise<void> {\n if (file.value === null) return\n\n try {\n rows.value = await api.importPack(file.value, {\n name: name.value ?? undefined,\n dryRun: true,\n publish: publish.value,\n })\n } catch (error) {\n rows.value = null\n refusal.value = refusalOf(error)\n }\n}\n\nwatch(publish, () => {\n if (rows.value !== null && !done.value) void plan()\n})\n\nasync function run(): Promise<void> {\n importing.value = true\n\n try {\n const result = await api.importPack(file.value ?? '', {\n name: name.value ?? undefined,\n publish: publish.value,\n })\n const written = result.filter((row) => row.status !== 'failed' && row.status !== 'unchanged')\n\n toast.success(t('exchange.imported', { count: written.length }))\n\n if (result.some((row) => row.error !== null)) {\n rows.value = result\n done.value = true\n\n return\n }\n\n resolve(result)\n } catch (error) {\n refusal.value = refusalOf(error)\n } finally {\n importing.value = false\n }\n}\n\n/** Past the run, closing is the answer — with the rows, so the section knows to refresh. */\nfunction close(): void {\n if (done.value && rows.value) resolve(rows.value)\n else dismiss()\n}\n\nfunction statusLabel(row: BlockImportRow): string {\n return t(`exchange.status-${row.status}`)\n}\n</script>\n\n<template>\n <wx-dialog v-model:open=\"open\" :title=\"t('exchange.import-title')\" :width=\"600\">\n <div class=\"wx-block-import\">\n <wx-text tone=\"muted\" size=\"sm\">{{ t('exchange.import-help') }}</wx-text>\n\n <input ref=\"picker\" type=\"file\" accept=\".json,application/json\" hidden @change=\"onFile\" />\n\n <wx-empty\n v-if=\"name === null\"\n icon=\"upload\"\n :title=\"t('exchange.import-title')\"\n class=\"wx-block-import__pick\"\n >\n <template #actions>\n <wx-button type=\"primary\" icon=\"upload\" @click=\"choose\">\n {{ t('exchange.choose-file') }}\n </wx-button>\n </template>\n </wx-empty>\n\n <template v-else>\n <div class=\"wx-block-import__file\">\n <span class=\"wx-block-import__name\">{{ name }}</span>\n <wx-button v-if=\"!done\" size=\"sm\" variant=\"text\" @click=\"choose\">\n {{ t('exchange.other-file') }}\n </wx-button>\n </div>\n\n <wx-skeleton v-if=\"reading\" :rows=\"4\" />\n\n <wx-alert v-else-if=\"refusal\" type=\"danger\" variant=\"soft\" :description=\"refusal\" />\n\n <template v-else-if=\"rows\">\n <ul class=\"wx-block-import__list\">\n <li v-for=\"row in rows\" :key=\"row.slug\" class=\"wx-block-import__row\">\n <div class=\"wx-block-import__type\">\n <span class=\"wx-block-import__title\">{{ row.title ?? row.slug }}</span>\n <span class=\"wx-block-import__meta\">\n {{ row.slug }}\n <template v-if=\"row.kind === 'component'\">\n · {{ t('components.kind-component') }}</template\n >\n <template v-if=\"done && row.version !== null\"> · v{{ row.version }}</template>\n </span>\n <span\n v-if=\"row.error\"\n class=\"wx-block-import__error\"\n :class=\"{ 'is-warning': row.status !== 'failed' }\"\n >{{ row.error }}</span\n >\n </div>\n <wx-badge :type=\"STATUS[row.status]\" variant=\"soft\" size=\"sm\">\n {{ statusLabel(row) }}\n </wx-badge>\n </li>\n </ul>\n\n <wx-alert\n v-if=\"upToDate && !done\"\n type=\"info\"\n variant=\"soft\"\n :description=\"t('exchange.up-to-date')\"\n />\n\n <wx-switch\n v-if=\"!done && writable.length > 0\"\n v-model=\"publish\"\n :label=\"t('exchange.publish')\"\n />\n </template>\n </template>\n </div>\n\n <template #footer>\n <wx-space size=\"sm\">\n <wx-button variant=\"outline\" @click=\"close\">{{ t('page.cancel') }}</wx-button>\n <wx-button\n v-if=\"!done\"\n type=\"primary\"\n :loading=\"importing\"\n :disabled=\"rows === null || changes.length === 0\"\n @click=\"run\"\n >\n {{ t('exchange.run') }}\n </wx-button>\n </wx-space>\n </template>\n </wx-dialog>\n</template>\n\n<style scoped>\n.wx-block-import {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-12);\n}\n\n.wx-block-import__file {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--wx-space-8);\n min-width: 0;\n}\n\n.wx-block-import__name {\n overflow: hidden;\n font-weight: var(--wx-font-weight-medium);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.wx-block-import__list {\n display: flex;\n flex-direction: column;\n max-height: 340px;\n margin: 0;\n padding: 0;\n overflow-y: auto;\n list-style: none;\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n}\n\n.wx-block-import__row {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: var(--wx-space-12);\n padding: var(--wx-space-8) var(--wx-space-12);\n}\n\n.wx-block-import__row + .wx-block-import__row {\n border-top: 1px solid var(--wx-border-default);\n}\n\n.wx-block-import__type {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-2);\n min-width: 0;\n}\n\n.wx-block-import__meta {\n font-size: var(--wx-font-size-xs);\n color: var(--wx-text-muted);\n}\n\n.wx-block-import__error {\n font-size: var(--wx-font-size-xs);\n color: var(--wx-color-danger);\n overflow-wrap: anywhere;\n}\n\n.wx-block-import__error.is-warning {\n color: var(--wx-color-warning);\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 BlockExportDialog from './BlockExportDialog.vue'\nimport BlockImportDialog from './BlockImportDialog.vue'\nimport { useBlocksMessages } from './i18n'\nimport { groupLabel, kindOf } from './schema'\nimport type { BlockImportRow, 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)\nconst exportTypes = createModal<true, { selected?: string[] }>(BlockExportDialog)\nconst importTypes = createModal<BlockImportRow[], Record<string, never>>(BlockImportDialog)\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/** A file of types in: the list is fetched again, since new cards and new drafts came with it. */\nasync function importFile(): Promise<void> {\n if (await importTypes({})) await load()\n}\n\n/*\n * What the section offers. Declared, because on a phone the head folds it into the ···.\n * Export is reading, so whoever sees the section may take a file; import writes drafts, so it\n * stands with \"New block\" behind the right to make types.\n */\nconst actions = computed<ScreenAction[]>(() => [\n ...(types.value.length > 0\n ? [\n {\n key: 'export',\n label: t('exchange.export'),\n icon: 'download',\n run: () => void exportTypes({}),\n },\n ]\n : []),\n ...(canManage.value\n ? [\n {\n key: 'import',\n label: t('exchange.import'),\n icon: 'upload',\n run: () => void importFile(),\n },\n { key: 'new', label: t('page.new'), icon: 'plus', primary: true, run: () => void add() },\n ]\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","<script setup lang=\"ts\">\nimport { useTranslate } from '@webx-ui/module-admin'\nimport type { SiteBarRegion } from './types'\n\n/**\n * A region's unpublished draft in the panel on the site, with the buttons that publish it or\n * throw it away.\n *\n * Drawn over the region's map and over the form of one of its blocks alike: the head of the bar\n * speaks for the record only, so the form is where an editor who has just saved a block of the\n * footer is looking — and a notice that only the map carried was found after a reload.\n */\ndefineProps<{\n region: SiteBarRegion\n /** This region's publication or discard is under way. */\n busy?: boolean\n /** Another region's is: one at a time, since each reloads the page. */\n blocked?: boolean\n /** Why the publication was refused — the blocks of the draft that fail. */\n refusals?: string[]\n /** The region's draft drawn on this page: after a reload the page shows the site again. */\n preview?: string | null\n}>()\n\nconst emit = defineEmits<{ publish: []; discard: [] }>()\n\nconst t = useTranslate('webx-blocks')\n</script>\n\n<template>\n <wx-alert\n type=\"warning\"\n :title=\"t('site-bar.changes', { count: region.draft.changes })\"\n :description=\"\n !region.draft.mine && region.draft.by\n ? t('site-bar.draft-other', { name: region.draft.by })\n : undefined\n \"\n >\n <template #actions>\n <wx-button\n size=\"sm\"\n type=\"primary\"\n :loading=\"busy\"\n :disabled=\"blocked && !busy\"\n @click=\"emit('publish')\"\n >\n {{ t('site-bar.publish') }}\n </wx-button>\n <wx-button size=\"sm\" variant=\"outline\" :disabled=\"busy || blocked\" @click=\"emit('discard')\">\n {{ t('site-bar.discard') }}\n </wx-button>\n <wx-button\n v-if=\"preview\"\n size=\"sm\"\n variant=\"text\"\n :href=\"preview\"\n target=\"_blank\"\n rel=\"noopener\"\n >\n {{ t('site-bar.preview') }}\n </wx-button>\n </template>\n </wx-alert>\n\n <div v-if=\"refusals?.length\" class=\"wx-region-draft__refusals\" role=\"alert\">\n <wx-text v-for=\"(line, index) in refusals\" :key=\"index\" size=\"sm\" tone=\"danger\">{{\n line\n }}</wx-text>\n </div>\n</template>\n\n<style scoped>\n.wx-region-draft__refusals {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-4);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, provide, ref, shallowRef, watch } from 'vue'\nimport {\n HttpError,\n loadShortcodes,\n onSitePage,\n tellSitePage,\n useAdmin,\n useErrorText,\n useSiteBar,\n useTranslate,\n WxRowMenu,\n type EditingEditor,\n type RowAction,\n type ShortcodeToken,\n type SiteBarContext,\n} from '@webx-ui/module-admin'\nimport { confirm, createModal, toast } from '@webx-ui/core'\nimport {\n coreTypes,\n WxScreenRenderer,\n type TypeRegistry,\n type ValidationErrors,\n} from '@webx-ui/schema'\nimport { createBlocksApi, createRegionsApi, createSiteBarBlocksApi } from './api'\nimport BlockPicker from './BlockPicker.vue'\nimport { clone, countType, locate, nestedFields } from './content'\nimport { useBlocksMessages } from './i18n'\nimport { blocksFragmentKey, blocksRootKey } from './preview'\nimport RegionDraftNotice from './RegionDraftNotice.vue'\nimport { formSchema, markupFields, startValues, withPlaceholders, withShortcodes } from './schema'\nimport type {\n BlockNode,\n BlockOutlineLine,\n BlockType,\n SiteBarBlockEdited,\n SiteBarBlockOp,\n SiteBarBlocks,\n SiteBarRegion,\n} from './types'\n\n/**\n * The «Blocks» tab of the panel on the site (WEBX_UI_SITE_BAR.md, §8–§9, SB4).\n *\n * Two states, like the constructor's narrow column: maps of the blocks, or one block's fields.\n * The maps are the record's — the page behind the address — and the layout's regions', the\n * header and the footer, each under its own name; a row under the pointer frames its block on the\n * page. The pencil is the way from the page: with it on, a click on a block picks it there\n * instead of following its link, whichever tree it belongs to.\n *\n * The form is the constructor's own — the block's schema through the same steps, drawn by the\n * same renderer with the panel's field types — and its values are the draft's, never the\n * site's: an edit goes into the draft of whatever holds the block, and a form that showed what\n * is published would write over whatever a colleague prepared. «Save» writes the fields that\n * changed and puts the block, drawn from the draft, in place of the old one on the page.\n *\n * The record's draft is published from the head of the bar; a region's — with its own buttons\n * over its map and over the form of its block, since it is a draft of its own and goes on every\n * page at once.\n *\n * The structure too (SB5): a block added — below another, at the end of a tree, inside a\n * container — duplicated, moved up or down, hidden, shown or deleted, each one an operation of the\n * agent's dictionary into the same draft. The picker is the constructor's, held to the same rules\n * of the place; what cannot be done right now is greyed with the reason rather than missing.\n */\nconst props = defineProps<{ context: SiteBarContext }>()\n\nconst admin = useAdmin()\nuseBlocksMessages()\nconst t = useTranslate('webx-blocks')\nconst errorText = useErrorText()\nconst bar = useSiteBar()\nconst api = createSiteBarBlocksApi(admin)\nconst regionsApi = createRegionsApi(admin)\n\n/* A list of blocks inside a block's form is the constructor's to change, in the panel: the\n nested field draws its note instead of a second constructor. */\nprovide(blocksRootKey, true)\n\n/** One tree of blocks the tab edits: the record's, or a region's. */\ninterface Source {\n /** What the page knows the tree by: `page:12`, `region:header`. */\n scope: string\n /** The address of its blocks: the record's type and id, or `region` and the region's name. */\n type: string\n id: string | number\n title: string\n content: SiteBarBlocks\n region: SiteBarRegion | null\n /** A shared block: on the pages that place it, not on every page like the header. */\n fragment: boolean\n /** What its top level takes: a region's declaration, or anything for a record. */\n top: { allow: string[] | null; max: number | null; root: string }\n}\n\n/** One list of blocks: the top level of a tree, or a container's field. */\ninterface Place {\n parentKey: string | null\n field: string | null\n list: BlockNode[]\n parent: BlockType | null\n allow: string[] | null\n max: number | null\n root: string\n}\n\nconst sources = ref<Source[]>([])\nconst catalog = shallowRef<BlockType[]>([])\nconst loading = ref(true)\nconst failed = ref(false)\nconst selected = ref<{ scope: string; key: string } | null>(null)\nconst values = ref<Record<string, unknown>>({})\nconst held = ref('{}')\nconst errors = ref<ValidationErrors | undefined>(undefined)\n/* What a save was refused for that is not one of this form's fields: where a block stands — this\n one or another of the same tree — which the constructor in the panel is the place to change. */\nconst refusals = ref<string[]>([])\nconst saving = ref(false)\nconst picking = ref(false)\nconst others = ref<string[]>([])\n/* A region's publication refused — a block of its draft fails — said over that region's map. */\nconst regionRefusals = ref<Record<string, string[]>>({})\nconst busy = ref<string | null>(null)\n/* A change of structure under way: one at a time, since each answers with the page's steps. */\nconst shaping = ref(false)\n/* The sets of block styles and scripts the page has, as the page reported them. */\nconst pageBundles = ref<string[] | null>(null)\n/* The regions the page prints, as it reported them; null from a page of the release before. */\nconst pageRegions = ref<string[] | null>(null)\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 | null\n root: string\n }\n>(BlockPicker)\n\nconst groupsOrder = computed<string[]>(\n () =>\n (admin.state.manifest?.modules.find((m) => m.id === 'blocks')?.meta?.groups as\n string[] | undefined) ?? [],\n)\n\nconst entity = computed(() => props.context.entity)\nconst offersRecord = computed(() => props.context.sections.includes('blocks') && !!entity.value)\nconst offersRegions = computed(() => props.context.sections.includes('regions'))\n\nfunction typeOf(slug: string): BlockType | null {\n return catalog.value.find((type) => type.slug === slug) ?? null\n}\n\nfunction titleOf(slug: string): string {\n return typeOf(slug)?.title ?? slug\n}\n\nfunction rowsOf(source: Source) {\n return (source.content.outline ?? []).map((line: BlockOutlineLine, index) => ({\n id: line.key ?? `~${index}`,\n key: line.key ?? null,\n depth: line.depth,\n title: titleOf(line.type),\n label: line.label && line.label !== titleOf(line.type) ? line.label : '',\n hidden: line.hidden === true,\n }))\n}\n\n/* A region that is not on the site shows the markup from code: there is nothing of it on the\n page to pick, and its draft is the panel's to set up. */\nfunction onSite(source: Source): boolean {\n return source.region === null || source.region.published\n}\n\n/*\n * A shared block is listed on a page that holds it and on no other: on the rest its map is blocks\n * nobody can point at here, and its draft notice an invitation to publish what this page does not\n * show. Every one is listed by a page that cannot say what it holds.\n */\nfunction onPage(source: Source): boolean {\n return (\n !source.fragment || pageRegions.value === null || pageRegions.value.includes(String(source.id))\n )\n}\n\nconst groups = computed(() =>\n sources.value\n .filter(onPage)\n .map((source) => ({ source, rows: onSite(source) ? rowsOf(source) : [] })),\n)\n\nconst current = computed(() =>\n selected.value\n ? (sources.value.find((one) => one.scope === selected.value!.scope) ?? null)\n : null,\n)\nconst tree = computed(() => current.value?.content.tree ?? [])\nconst found = computed(() => (selected.value ? locate(tree.value, selected.value.key) : null))\nconst selectedType = computed(() => (found.value ? typeOf(found.value.node.type) : null))\n\n/* The blocks the open one is inside, outermost first — the way back up to its parent. */\nconst trail = computed(() => {\n const steps: { key: string; title: string }[] = []\n let at = found.value?.parent ?? null\n\n while (at) {\n steps.unshift({ key: at.key, title: titleOf(at.type) })\n at = locate(tree.value, at.key)?.parent ?? null\n }\n\n return steps\n})\n\nconst types = computed<TypeRegistry>(() => ({ ...coreTypes, ...(admin.types ?? {}) }))\nconst translate = computed(() => admin.i18n.t)\nconst can = computed(() => admin.can)\n\nconst shortcodes = shallowRef<ShortcodeToken[]>([])\nconst marked = ref<string[]>([])\n\nconst formRoot = computed(() =>\n selectedType.value?.content\n ? withShortcodes(\n withPlaceholders(\n formSchema(selectedType.value.content.schema),\n selectedType.value.content.sample ?? {},\n marked.value,\n t('field.markup-in-text'),\n ),\n shortcodes.value,\n { tokensTitle: t('field.shortcodes'), tokensLabel: t('field.shortcodes-insert') },\n )\n : [],\n)\n\n/* What «Save» sends: the fields that differ from what the form was opened with. A list of\n blocks is left out — it is not this form's to change. */\nconst changed = computed<Record<string, unknown>>(() => {\n const before = JSON.parse(held.value) as Record<string, unknown>\n const nested = new Set(selectedType.value?.content?.schema ? nestedIds() : [])\n const out: Record<string, unknown> = {}\n\n for (const [name, value] of Object.entries(values.value)) {\n if (nested.has(name)) continue\n if (JSON.stringify(value ?? null) !== JSON.stringify(before[name] ?? null)) out[name] = value\n }\n\n return out\n})\n\nconst dirty = computed(() => Object.keys(changed.value).length > 0)\n\nfunction nestedIds(): string[] {\n const ids: string[] = []\n const visit = (nodes: { id?: string; type: string; children?: unknown }[]): void => {\n for (const node of nodes) {\n if (node.type === 'wx-blocks' && node.id) ids.push(node.id)\n if (Array.isArray(node.children)) visit(node.children as typeof nodes)\n }\n }\n\n visit(selectedType.value?.content?.schema ?? [])\n\n return ids\n}\n\n/* Where the panel edits what holds the block: the record's screen, or the region's editor. */\nfunction panelHref(source: Source | null): string | null {\n const base = admin.basePath.replace(/\\/$/, '')\n\n if (source?.region) {\n const path = (admin.modules ?? []).find((module) => module.id === 'regions')?.path ?? '/regions'\n\n return `${base}${path}/${encodeURIComponent(source.region.name)}`\n }\n\n return entity.value?.edit ? `${base}${entity.value.edit}` : null\n}\n\n/** The page is told which trees it may pick from, and what each block is called on hover. */\nfunction announce(): void {\n tellSitePage({\n type: 'blocks',\n sources: sources.value.filter(onSite).map((source) => ({\n scope: source.scope,\n // The page's own blocks go by their type alone; a region's say whose they are.\n ...(source.region ? { title: source.title } : {}),\n items: (source.content.outline ?? []).flatMap((line) =>\n line.key ? [{ key: line.key, label: titleOf(line.type) }] : [],\n ),\n })),\n })\n}\n\nasync function readRecord(): Promise<Source[]> {\n const record = entity.value\n\n if (!offersRecord.value || !record) return []\n\n return [\n {\n scope: `${record.type}:${record.id}`,\n type: record.type,\n id: record.id,\n title: record.kind,\n content: await api.read(record.type, record.id),\n region: null,\n fragment: false,\n top: { allow: null, max: null, root: 'root' },\n },\n ]\n}\n\nasync function readRegions(): Promise<Source[]> {\n if (!offersRegions.value) return []\n\n const rows = await regionsApi.list()\n\n return Promise.all(\n rows.map(async (row): Promise<Source> => {\n const read = await api.read('region', row.name)\n\n return {\n scope: `region:${row.name}`,\n type: 'region',\n id: row.name,\n title: read.region?.title ?? row.title,\n content: read,\n region: read.region ?? null,\n fragment: row.fragment === true,\n top: { allow: row.allow, max: row.max, root: `region:${row.name}` },\n }\n }),\n )\n}\n\nasync function load(): Promise<void> {\n loading.value = sources.value.length === 0\n failed.value = false\n\n try {\n const [record, regions, types] = await Promise.all([\n readRecord(),\n readRegions(),\n catalog.value.length ? Promise.resolve(catalog.value) : createBlocksApi(admin).catalog(),\n ])\n\n catalog.value = types\n sources.value = [...record, ...regions]\n announce()\n\n if (selected.value && !found.value) back()\n } catch {\n failed.value = true\n } finally {\n loading.value = false\n }\n}\n\nfunction open(scope: string, key: string): void {\n const source = sources.value.find((one) => one.scope === scope)\n const hit = source ? locate(source.content.tree, key) : null\n\n if (!source || !hit) return\n\n if (selected.value && selected.value.scope !== scope) stopPresence()\n\n selected.value = { scope, key }\n values.value = clone(hit.node.values ?? {})\n held.value = JSON.stringify(values.value)\n errors.value = undefined\n refusals.value = []\n marked.value = typeOf(hit.node.type)?.content\n ? markupFields(typeOf(hit.node.type)!.content!.schema, hit.node.values ?? {})\n : []\n tellSitePage({ type: 'select', key, scope })\n startPresence()\n}\n\nfunction back(): void {\n const was = selected.value\n\n stopPresence()\n selected.value = null\n errors.value = undefined\n refusals.value = []\n tellSitePage({ type: 'select', key: null, ...(was ? { scope: was.scope } : {}) })\n}\n\nfunction highlight(scope: string, key: string | null): void {\n tellSitePage({ type: 'highlight', key, scope })\n}\n\nfunction togglePicking(): void {\n picking.value = !picking.value\n tellSitePage({ type: 'mode', on: picking.value })\n}\n\n/**\n * The refusal of a value under the field it names (`blocks.<key>.<field>`); everything else the\n * server said — a block that stands where its container does not take it, a region holding more\n * than it may — as lines above, under a sentence that says it is not this form's doing.\n */\nfunction refuse(error: HttpError, key: string): void {\n const prefix = `blocks.${key}.`\n const fields: ValidationErrors = {}\n const lines: string[] = []\n\n for (const [path, messages] of Object.entries(error.errors)) {\n if (path.startsWith(prefix)) fields[path.slice(prefix.length)] = messages\n else lines.push(...messages)\n }\n\n errors.value = Object.keys(fields).length ? fields : undefined\n refusals.value = [...new Set(lines)]\n}\n\nasync function save(): Promise<void> {\n const source = current.value\n const key = selected.value?.key\n\n if (!source || !key || !dirty.value || saving.value) return\n\n saving.value = true\n errors.value = undefined\n refusals.value = []\n\n try {\n const done = await api.edit(source.type, source.id, {\n revision: source.content.revision,\n locale: props.context.locale,\n url: props.context.url,\n bundles: pageBundles.value ?? undefined,\n ops: [{ op: 'set', key, values: changed.value }],\n })\n\n // The block from the draft in place of the old one, framed as a draft on the page.\n showOnPage(source, done, key)\n\n held.value = JSON.stringify(values.value)\n toast.success(t('site-bar.saved'))\n\n await load()\n // The head counts the record's changes; it reads them again. A region counts its own.\n if (!source.region) void bar?.refresh()\n } catch (caught) {\n if (caught instanceof HttpError && caught.status === 409) {\n // Somebody wrote the tree since the form read it: read again and say who.\n conflicted(caught)\n await load()\n open(source.scope, key)\n\n return\n }\n\n if (caught instanceof HttpError && caught.isValidation && Object.keys(caught.errors).length) {\n refuse(caught, key)\n\n return\n }\n\n toast.danger(errorText(caught))\n } finally {\n saving.value = false\n }\n}\n\n/*\n * What the page does to show the draft: the steps the server worked out, after the styles and\n * script of a type the page did not have — so that a new block arrives dressed.\n */\nfunction showOnPage(source: Source, done: SiteBarBlockEdited, edited?: string): void {\n const scope = source.scope\n\n if (done.assets) tellSitePage({ type: 'assets', ...done.assets })\n\n // An answer of the release before: the one block drawn.\n if (!done.steps) {\n const key = edited ?? done.key\n\n if (key && done.html !== '') tellSitePage({ type: 'replace', key, scope, html: done.html })\n\n return\n }\n\n for (const step of done.steps) {\n if (step.do === 'reload') {\n tellSitePage({ type: 'reload' })\n } else if (step.do === 'remove') {\n tellSitePage({ type: 'remove', key: step.key, scope })\n } else {\n tellSitePage({\n type: step.do === 'move' ? 'move' : 'insert',\n key: step.key,\n scope,\n html: step.html ?? '',\n after: step.after ?? [],\n before: step.before ?? [],\n top: step.top === true,\n })\n }\n }\n}\n\n/* Somebody wrote the tree since the tab read it: say who. */\nfunction conflicted(caught: HttpError): void {\n const body = caught.body as { changed?: { author?: string | null } | null } | null\n const name = body?.changed?.author\n\n toast.warning(name ? t('site-bar.conflict-by', { name }) : t('site-bar.conflict'))\n}\n\n/** One list of blocks of a tree: the top level, or the field of a container. */\nfunction placeOf(source: Source, parentKey: string | null, field: string | null): Place {\n if (parentKey === null) {\n return {\n parentKey: null,\n field: null,\n list: source.content.tree,\n parent: null,\n allow: source.top.allow,\n max: source.top.max,\n root: source.top.root,\n }\n }\n\n const holder = locate(source.content.tree, parentKey)\n const parent = holder ? typeOf(holder.node.type) : null\n const slot = parent?.content\n ? nestedFields(parent.content.schema).find((one) => one.id === field)\n : undefined\n const value = field !== null ? holder?.node.values[field] : undefined\n\n return {\n parentKey,\n field,\n list: Array.isArray(value) ? (value as BlockNode[]) : [],\n parent,\n allow: (slot?.props?.allow as string[] | undefined) ?? null,\n max: (slot?.props?.max as number | undefined) ?? null,\n // A container's field is named by its own type in `allowed_in`, not by the tree's root.\n root: 'root',\n }\n}\n\n/** The list a block is in. */\nfunction placeAround(source: Source, key: string): Place | null {\n const hit = locate(source.content.tree, key)\n\n return hit ? placeOf(source, hit.parent?.key ?? null, hit.field) : null\n}\n\nfunction isFull(place: Place): boolean {\n return place.max !== null && place.list.length >= place.max\n}\n\n/** Why nothing more goes into a list, or null when something does. */\nfunction fullness(place: Place): string | null {\n return isFull(place) ? t('site-bar.full', { count: place.max! }) : null\n}\n\n/**\n * A change of structure into the draft, and the page brought in step. One at a time: each answer\n * names what the page has to do, and two of them crossing would leave it guessing.\n */\nasync function shape(\n source: Source,\n ops: SiteBarBlockOp[],\n options: { forgetBundles?: boolean; quiet?: boolean } = {},\n): Promise<SiteBarBlockEdited | null> {\n if (shaping.value) return null\n\n shaping.value = true\n\n try {\n const done = await api.edit(source.type, source.id, {\n revision: source.content.revision,\n locale: props.context.locale,\n url: props.context.url,\n bundles: options.forgetBundles ? undefined : (pageBundles.value ?? undefined),\n ops,\n })\n\n showOnPage(source, done)\n // Quiet where the caller says what was done in its own words.\n if (!options.quiet) toast.success(t('site-bar.saved'))\n\n await load()\n if (!source.region) void bar?.refresh()\n\n return done\n } catch (caught) {\n if (caught instanceof HttpError && caught.status === 409) {\n conflicted(caught)\n await load()\n } else if (caught instanceof HttpError && caught.isValidation) {\n // Where a block may stand, how many a page takes — the server's words, as they are.\n const lines = [...new Set(Object.values(caught.errors).flat())]\n\n toast.danger(lines.length ? lines.join(' ') : errorText(caught))\n } else {\n toast.danger(errorText(caught))\n }\n\n return null\n } finally {\n shaping.value = false\n }\n}\n\n/**\n * A new block in a list — after `after`, or at its end — of a type chosen in the constructor's\n * own picker, held to the same rules of the place. Its form opens at once.\n */\nasync function addTo(source: Source, place: Place, after: string | null): Promise<void> {\n if (isFull(place) || shaping.value) return\n\n const type = await pick({\n catalog: catalog.value,\n parent: place.parent,\n allow: place.allow,\n tree: source.content.tree,\n groups: groupsOrder.value,\n blocksPath: null,\n root: place.root,\n })\n\n if (!type) return\n\n const done = await shape(source, [\n {\n op: 'add',\n type: type.slug,\n values: startValues(type.content?.schema ?? [], type.content?.sample ?? {}),\n ...(place.parentKey !== null ? { parent: place.parentKey, field: place.field ?? '' } : {}),\n ...(after !== null ? { after } : {}),\n },\n ])\n\n if (done?.key) open(source.scope, done.key)\n}\n\nasync function duplicate(source: Source, key: string): Promise<void> {\n const done = await shape(source, [{ op: 'duplicate', key }])\n\n if (done?.key) open(source.scope, done.key)\n}\n\n/** One step up or down its own list, past the neighbour. */\nasync function moveBy(source: Source, key: string, by: -1 | 1): Promise<void> {\n const hit = locate(source.content.tree, key)\n const next = hit?.list[hit.index + by]\n\n if (!hit || !next?.key) return\n\n await shape(source, [\n {\n op: 'move',\n key,\n ...(hit.parent ? { parent: hit.parent.key, field: hit.field ?? '' } : {}),\n ...(by < 0 ? { before: next.key } : { after: next.key }),\n },\n ])\n}\n\nasync function removeBlock(source: Source, key: string): Promise<void> {\n const hit = locate(source.content.tree, key)\n\n if (!hit) return\n\n const agreed = await confirm({\n title: t('site-bar.delete-title', { title: titleOf(hit.node.type) }),\n message: t('site-bar.delete-text'),\n confirmText: t('site-bar.delete'),\n cancelText: t('site-bar.cancel'),\n tone: 'danger',\n })\n\n if (agreed) await shape(source, [{ op: 'remove', key }])\n}\n\n/**\n * What a block offers, on its row of the map and over its form: the panel's own `···`. What\n * cannot be done right now — the first block up, a full list — is greyed with the reason.\n */\nfunction actionsFor(source: Source, key: string): RowAction[] {\n const hit = locate(source.content.tree, key)\n\n if (!hit) return []\n\n const place = placeOf(source, hit.parent?.key ?? null, hit.field)\n const full = fullness(place)\n const type = typeOf(hit.node.type)\n const limit = type?.max_per_entity ?? null\n const limited =\n limit !== null && countType(source.content.tree, hit.node.type) >= limit\n ? t('site-bar.limit', { count: limit })\n : null\n const slots = type?.content ? nestedFields(type.content.schema) : []\n const hidden = hit.node.hidden === true\n // A neighbour of old content without a key cannot be named: nothing moves past it from here.\n const above = hit.list[hit.index - 1]\n const below = hit.list[hit.index + 1]\n const up = !above ? t('site-bar.at-top') : !above.key ? t('site-bar.temporary') : null\n const down = !below ? t('site-bar.at-bottom') : !below.key ? t('site-bar.temporary') : null\n\n return [\n {\n key: 'add-below',\n icon: 'plus',\n label: t('site-bar.add-below'),\n disabled: full !== null,\n hint: full ?? undefined,\n run: () => void addTo(source, place, key),\n },\n ...slots.map((slot): RowAction => {\n const inside = placeOf(source, key, slot.id)\n const why = fullness(inside)\n\n return {\n key: `add-inside-${slot.id}`,\n icon: 'plus',\n label:\n slots.length > 1\n ? `${t('site-bar.add-inside')} · ${String(slot.label ?? slot.id)}`\n : t('site-bar.add-inside'),\n disabled: why !== null,\n hint: why ?? undefined,\n run: () => void addTo(source, inside, null),\n }\n }),\n {\n key: 'duplicate',\n icon: 'copy',\n label: t('site-bar.duplicate'),\n disabled: full !== null || limited !== null,\n hint: full ?? limited ?? undefined,\n run: () => void duplicate(source, key),\n },\n {\n key: 'move-up',\n icon: 'arrow-up',\n label: t('site-bar.move-up'),\n disabled: up !== null,\n hint: up ?? undefined,\n run: () => void moveBy(source, key, -1),\n },\n {\n key: 'move-down',\n icon: 'arrow-down',\n label: t('site-bar.move-down'),\n disabled: down !== null,\n hint: down ?? undefined,\n run: () => void moveBy(source, key, 1),\n },\n {\n key: 'visibility',\n icon: hidden ? 'eye' : 'eye-off',\n label: hidden ? t('site-bar.show') : t('site-bar.hide'),\n run: () => void shape(source, [{ op: hidden ? 'show' : 'hide', key }]),\n },\n {\n key: 'delete',\n icon: 'trash',\n label: t('site-bar.delete'),\n danger: true,\n run: () => void removeBlock(source, key),\n },\n ]\n}\n\n/* The whole draft on a page, for after a reload: the region's preview drawn on this page. */\nfunction regionPreview(source: Source): string | null {\n const url = source.region?.preview\n\n return url ? `${url}&at=${encodeURIComponent(props.context.url)}` : null\n}\n\n/*\n * A region's draft on the site, or thrown away — the same calls its editor in the panel makes.\n * Every page that prints it changes at once, so the page in front reloads to show it.\n */\nasync function publishRegion(source: Source): Promise<void> {\n if (!source.region || busy.value) return\n\n busy.value = source.scope\n regionRefusals.value = { ...regionRefusals.value, [source.scope]: [] }\n\n try {\n await regionsApi.publish(source.region.name, source.content.revision)\n tellSitePage({ type: 'reload' })\n } catch (caught) {\n // A block of the draft fails: the region would print its fallback, so it is not published,\n // and the lines say which block and why.\n const lines = caught instanceof HttpError ? Object.values(caught.errors).flat() : []\n\n regionRefusals.value = { ...regionRefusals.value, [source.scope]: lines }\n toast.danger(errorText(caught))\n // A 409 is somebody's edit the tab had not seen: the map shows it now.\n void load()\n } finally {\n busy.value = null\n }\n}\n\nasync function discardRegion(source: Source): Promise<void> {\n if (!source.region || busy.value) return\n\n const agreed = await confirm({\n title: t('site-bar.discard-title', { name: source.title }),\n message: t('site-bar.discard-text'),\n confirmText: t('site-bar.discard'),\n cancelText: t('site-bar.cancel'),\n tone: 'danger',\n })\n\n if (!agreed) return\n\n busy.value = source.scope\n\n try {\n await regionsApi.discardDraft(source.region.name)\n tellSitePage({ type: 'reload' })\n } catch (caught) {\n toast.danger(errorText(caught))\n } finally {\n busy.value = null\n }\n}\n\n/*\n * Presence (§9): while a block's form is open the bar knocks where the editor in the panel does\n * — the record's, or the region's — so an editor open there at the same time sees that it is\n * being edited.\n */\nlet beat: ReturnType<typeof setInterval> | undefined\nlet knocking: string | null = null\n\nfunction presenceUrl(): string | null {\n const source = current.value\n\n if (source?.region)\n return `${admin.apiPath}/editing/regions/${encodeURIComponent(source.region.name)}`\n\n const record = entity.value\n\n return source && record?.editing\n ? `${admin.apiPath}/editing/${record.editing}/${encodeURIComponent(String(record.id))}`\n : null\n}\n\nasync function knock(): Promise<void> {\n if (!knocking) return\n\n try {\n const ping = (await admin.http.post<{ data: { editors?: EditingEditor[] } }>(knocking)).data\n\n others.value = (ping.editors ?? []).map((one) => one.name).filter((name) => name !== '')\n } catch {\n // A courtesy: its absence is not worth a word on screen.\n }\n}\n\nfunction startPresence(): void {\n const url = presenceUrl()\n\n if (beat !== undefined || !url) return\n\n knocking = url\n void knock()\n beat = setInterval(() => void knock(), 20_000)\n}\n\nfunction stopPresence(): void {\n if (beat === undefined) return\n\n clearInterval(beat)\n beat = undefined\n others.value = []\n\n if (knocking) void admin.http.delete(knocking).catch(() => {})\n knocking = null\n}\n\n/* The page's half: a block picked there, picking switched off there with Esc, «Add below» on the\n picked block, and the sets of styles the page has. A message without a tree is from a page of\n the release before, where the record's was the only one. */\nconst stopListening = onSitePage((message) => {\n if (message.type === 'mode') {\n picking.value = message.on\n } else if (message.type === 'select') {\n const scope = message.scope ?? sources.value[0]?.scope\n const source = sources.value.find((one) => one.scope === scope)\n\n if (source && locate(source.content.tree, message.key)) {\n bar?.show('blocks')\n open(source.scope, message.key)\n }\n } else if (message.type === 'add') {\n const scope = message.scope ?? sources.value[0]?.scope\n const source = sources.value.find((one) => one.scope === scope)\n const place = source ? placeAround(source, message.key) : null\n\n if (source && place) {\n bar?.show('blocks')\n void addTo(source, place, message.key)\n }\n } else if (message.type === 'bundles') {\n pageBundles.value = message.hashes\n } else if (message.type === 'regions') {\n pageRegions.value = message.names\n }\n})\n\n/*\n * «Make it this page's own» of a «Shared block» open here (§5.2 of the shared blocks spec): the\n * shared block's published blocks put after it, then it taken out — one edit of the draft of\n * whatever holds it, so the page is brought in step by the answer, as after any other. Added in\n * reverse, each right after the shared block: the server makes their keys, and the first of them\n * — the last one made — is the one opened.\n */\nprovide(blocksFragmentKey, {\n selected: computed(() => selected.value?.key ?? null),\n own: computed(() => (current.value?.fragment ? String(current.value.id) : null)),\n async detach(key: string, nodes: BlockNode[]): Promise<boolean> {\n const source = current.value\n const hit = source ? locate(source.content.tree, key) : null\n\n if (!source || !hit) return false\n\n const where = hit.parent ? { parent: hit.parent.key, field: hit.field ?? '' } : {}\n const done = await shape(\n source,\n [\n ...[...nodes].reverse().map((node): SiteBarBlockOp => ({\n op: 'add',\n type: node.type,\n values: node.values,\n after: key,\n ...where,\n })),\n { op: 'remove', key },\n // The page is not told which sets it has: the shared block printed its own in place, and\n // that `<link>` goes with its range — the copies would come in without their styles.\n ],\n { forgetBundles: true, quiet: true },\n )\n\n if (done?.key) open(source.scope, done.key)\n\n return done !== null\n },\n})\n\n/* Esc in the frame ends picking first; the screen closes the drawer on the next one. */\nfunction onKeydown(event: KeyboardEvent): void {\n if (event.key !== 'Escape' || !picking.value) return\n\n event.preventDefault()\n togglePicking()\n}\n\n/* Another record — the bar was pointed at another address. The context is read again after every\n save, and the same record in a new object is not a reason to read the blocks twice. */\nwatch(\n () => (entity.value ? `${entity.value.type}:${entity.value.id}` : null),\n () => void load(),\n)\n\nonMounted(() => {\n window.addEventListener('keydown', onKeydown)\n void load()\n void loadShortcodes(admin).then((list) => (shortcodes.value = list))\n})\n\nonBeforeUnmount(() => {\n window.removeEventListener('keydown', onKeydown)\n stopListening()\n stopPresence()\n\n if (picking.value) tellSitePage({ type: 'mode', on: false })\n})\n</script>\n\n<template>\n <div class=\"wx-blocks-bar\">\n <!-- One row: the way back to the list on the left, picking on the page on the right — two\n rows of one button each took the height the form needs. -->\n <div class=\"wx-blocks-bar__tools\">\n <nav v-if=\"found && current\" class=\"wx-blocks-bar__trail\" :aria-label=\"t('site-bar.all')\">\n <wx-button size=\"sm\" variant=\"text\" icon=\"arrow-left\" @click=\"back\">\n {{ t('site-bar.all') }}\n </wx-button>\n <template v-for=\"step in trail\" :key=\"step.key\">\n <span class=\"wx-blocks-bar__slash\" aria-hidden=\"true\">/</span>\n <wx-button size=\"sm\" variant=\"text\" @click=\"open(current.scope, step.key)\">\n {{ step.title }}\n </wx-button>\n </template>\n </nav>\n <wx-button\n size=\"sm\"\n icon=\"edit\"\n :variant=\"picking ? 'solid' : 'outline'\"\n :type=\"picking ? 'primary' : 'default'\"\n :aria-pressed=\"picking\"\n @click=\"togglePicking\"\n >\n {{ picking ? t('site-bar.pick-off') : t('site-bar.pick') }}\n </wx-button>\n </div>\n\n <wx-text v-if=\"picking\" size=\"sm\" tone=\"muted\">{{ t('site-bar.picking') }}</wx-text>\n\n <wx-loading v-if=\"loading\" />\n\n <wx-result v-else-if=\"failed\" status=\"info\" :title=\"t('site-bar.error')\">\n <wx-button @click=\"load\">{{ t('site-bar.retry') }}</wx-button>\n </wx-result>\n\n <template v-else-if=\"found && current\">\n <div class=\"wx-blocks-bar__name\">\n <wx-text weight=\"semibold\">\n {{ selectedType?.title ?? found.node.type }}\n <span v-if=\"current.region\" class=\"wx-blocks-bar__where\">· {{ current.title }}</span>\n <span v-if=\"found.node.hidden\" class=\"wx-blocks-bar__where\"\n >· {{ t('site-bar.hidden') }}</span\n >\n </wx-text>\n <wx-row-menu\n :actions=\"actionsFor(current, found.node.key)\"\n :label=\"t('site-bar.actions')\"\n />\n </div>\n\n <wx-text v-if=\"current.region\" size=\"sm\" tone=\"muted\">\n {{ current.fragment ? t('site-bar.fragment-everywhere') : t('site-bar.region-everywhere') }}\n </wx-text>\n\n <!-- Here too, not only over the map: the form is where the editor is after saving. -->\n <region-draft-notice\n v-if=\"current.region?.draft.differs\"\n :region=\"current.region\"\n :busy=\"busy === current.scope\"\n :blocked=\"busy !== null\"\n :refusals=\"regionRefusals[current.scope]\"\n :preview=\"regionPreview(current)\"\n @publish=\"publishRegion(current)\"\n @discard=\"discardRegion(current)\"\n />\n\n <wx-text v-if=\"others.length\" size=\"sm\" tone=\"muted\">\n {{ t('site-bar.others', { names: others.join(', ') }) }}\n </wx-text>\n\n <wx-alert\n v-if=\"refusals.length\"\n type=\"danger\"\n role=\"alert\"\n class=\"wx-blocks-bar__refused\"\n :title=\"t('site-bar.refused')\"\n >\n <ul class=\"wx-blocks-bar__lines\">\n <li v-for=\"(line, index) in refusals\" :key=\"index\">{{ line }}</li>\n </ul>\n <template v-if=\"panelHref(current)\" #actions>\n <wx-button\n size=\"sm\"\n variant=\"outline\"\n :href=\"panelHref(current)!\"\n target=\"_blank\"\n rel=\"noopener\"\n >\n {{ t('site-bar.open-in-panel') }}\n </wx-button>\n </template>\n </wx-alert>\n\n <div class=\"wx-blocks-bar__form\">\n <wx-screen-renderer\n v-if=\"selectedType?.content\"\n :key=\"`${current.scope}|${found.node.key}`\"\n v-model=\"values\"\n :root=\"formRoot\"\n :types=\"types\"\n :translate=\"translate\"\n :can=\"can\"\n :errors=\"errors\"\n />\n <wx-text v-else size=\"sm\" tone=\"danger\">{{ t('site-bar.unknown-type') }}</wx-text>\n </div>\n\n <div class=\"wx-blocks-bar__actions\">\n <wx-button type=\"primary\" :disabled=\"!dirty\" :loading=\"saving\" @click=\"save\">\n {{ t('site-bar.save') }}\n </wx-button>\n </div>\n </template>\n\n <template v-else>\n <wx-text size=\"sm\" tone=\"muted\">{{ t('site-bar.hint') }}</wx-text>\n\n <section\n v-for=\"{ source, rows } in groups\"\n :key=\"source.scope\"\n class=\"wx-blocks-bar__group\"\n :aria-label=\"source.title\"\n >\n <header class=\"wx-blocks-bar__head\">\n <wx-text weight=\"semibold\">{{ source.title }}</wx-text>\n <wx-text v-if=\"source.region\" size=\"xs\" tone=\"muted\">\n {{ source.fragment ? t('site-bar.fragment-where') : t('site-bar.region-everywhere') }}\n </wx-text>\n </header>\n\n <!-- A region's own draft: published from here, since the head of the bar is the record's. -->\n <region-draft-notice\n v-if=\"source.region?.draft.differs && onSite(source)\"\n :region=\"source.region\"\n :busy=\"busy === source.scope\"\n :blocked=\"busy !== null\"\n :refusals=\"regionRefusals[source.scope]\"\n :preview=\"regionPreview(source)\"\n @publish=\"publishRegion(source)\"\n @discard=\"discardRegion(source)\"\n />\n\n <template v-if=\"!onSite(source)\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('site-bar.region-fallback') }}</wx-text>\n <div>\n <wx-button\n size=\"sm\"\n variant=\"outline\"\n :href=\"panelHref(source)!\"\n target=\"_blank\"\n rel=\"noopener\"\n >\n {{ t('site-bar.open-in-panel') }}\n </wx-button>\n </div>\n </template>\n\n <wx-text v-else-if=\"rows.length === 0\" size=\"sm\" tone=\"muted\">{{\n t('site-bar.empty')\n }}</wx-text>\n\n <ul v-else class=\"wx-blocks-bar__map\">\n <li v-for=\"row in rows\" :key=\"row.id\" class=\"wx-blocks-bar__item\">\n <button\n type=\"button\"\n class=\"wx-blocks-bar__row\"\n :data-key=\"row.key ?? undefined\"\n :data-scope=\"source.scope\"\n :class=\"{ 'is-hidden': row.hidden, 'is-temporary': row.key === null }\"\n :style=\"{ '--wx-blocks-bar-depth': row.depth }\"\n :disabled=\"row.key === null\"\n :title=\"row.key === null ? t('site-bar.temporary') : undefined\"\n @mouseenter=\"highlight(source.scope, row.key)\"\n @mouseleave=\"highlight(source.scope, null)\"\n @focus=\"highlight(source.scope, row.key)\"\n @blur=\"highlight(source.scope, null)\"\n @click=\"row.key && open(source.scope, row.key)\"\n >\n <span class=\"wx-blocks-bar__title\">{{ row.title }}</span>\n <span v-if=\"row.label\" class=\"wx-blocks-bar__label\">{{ row.label }}</span>\n <span v-if=\"row.hidden\" class=\"wx-blocks-bar__flag\">{{ t('site-bar.hidden') }}</span>\n <span v-if=\"row.key === null\" class=\"wx-blocks-bar__flag\">{{\n t('site-bar.temporary')\n }}</span>\n </button>\n <wx-row-menu v-if=\"row.key\" :actions=\"actionsFor(source, row.key)\" :label=\"row.title\" />\n </li>\n </ul>\n\n <!-- At the end of the tree, whatever its blocks are: a page with none needs it most. -->\n <div v-if=\"onSite(source)\" class=\"wx-blocks-bar__add\">\n <wx-button\n size=\"sm\"\n variant=\"outline\"\n icon=\"plus\"\n :disabled=\"fullness(placeOf(source, null, null)) !== null\"\n :loading=\"shaping\"\n @click=\"addTo(source, placeOf(source, null, null), null)\"\n >\n {{ t('site-bar.add') }}\n </wx-button>\n <wx-text v-if=\"fullness(placeOf(source, null, null))\" size=\"xs\" tone=\"muted\">\n {{ fullness(placeOf(source, null, null)) }}\n </wx-text>\n </div>\n </section>\n </template>\n </div>\n</template>\n\n<style scoped>\n.wx-blocks-bar {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-12);\n min-width: 0;\n}\n\n.wx-blocks-bar__actions {\n display: flex;\n gap: var(--wx-space-8);\n}\n\n/* The way back on the left, picking on the right; alone, picking stays where it always was. A\n long trail to a nested block wraps, and picking goes under it rather than off the edge. */\n.wx-blocks-bar__tools {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: var(--wx-space-8);\n}\n\n.wx-blocks-bar__trail {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wx-space-2);\n min-width: 0;\n}\n\n.wx-blocks-bar__slash,\n.wx-blocks-bar__where {\n color: var(--wx-text-muted);\n font-weight: var(--wx-font-weight-regular);\n}\n\n/* One tree a group: the page's, then each region's, with what is said about it over its map. */\n.wx-blocks-bar__group {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n min-width: 0;\n padding-top: var(--wx-space-12);\n border-top: 1px solid var(--wx-border-default);\n}\n\n.wx-blocks-bar__head {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--wx-space-8);\n min-width: 0;\n}\n\n.wx-blocks-bar__map {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-2);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n/* A row and its `···`: the menu keeps its square at the end whatever the row says. */\n.wx-blocks-bar__item {\n display: flex;\n align-items: center;\n gap: var(--wx-space-4);\n min-width: 0;\n}\n\n.wx-blocks-bar__name {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: var(--wx-space-8);\n min-width: 0;\n}\n\n.wx-blocks-bar__add {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wx-space-8);\n}\n\n/* One line a block, indented by how deep it is nested: the map is read by its shape. */\n.wx-blocks-bar__row {\n display: flex;\n flex: 1 1 auto;\n align-items: baseline;\n gap: var(--wx-space-8);\n width: 100%;\n min-width: 0;\n padding: var(--wx-space-6) var(--wx-space-8);\n padding-left: calc(var(--wx-space-8) + var(--wx-blocks-bar-depth, 0) * var(--wx-space-16));\n border: 0;\n border-radius: var(--wx-radius-sm);\n background: transparent;\n color: var(--wx-text-default);\n font: inherit;\n text-align: left;\n cursor: pointer;\n}\n\n.wx-blocks-bar__row:hover:not(:disabled),\n.wx-blocks-bar__row:focus-visible {\n background: var(--wx-bg-fill);\n}\n\n.wx-blocks-bar__row:focus-visible {\n outline: 2px solid var(--wx-border-focus);\n outline-offset: -2px;\n}\n\n.wx-blocks-bar__row:disabled {\n cursor: default;\n}\n\n.wx-blocks-bar__title {\n flex: 0 0 auto;\n font-weight: var(--wx-font-weight-medium);\n}\n\n.wx-blocks-bar__label {\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-sm);\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n\n.wx-blocks-bar__flag {\n flex: 0 0 auto;\n margin-left: auto;\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n}\n\n.wx-blocks-bar__row.is-hidden .wx-blocks-bar__title,\n.wx-blocks-bar__row.is-temporary .wx-blocks-bar__title {\n color: var(--wx-text-muted);\n}\n\n.wx-blocks-bar__form {\n min-width: 0;\n}\n\n.wx-blocks-bar__lines {\n margin: 0;\n padding-left: var(--wx-space-16);\n overflow-wrap: anywhere;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, inject, onMounted, ref } from 'vue'\nimport { adminKey, useErrorText, useTranslate, type AdminContext } from '@webx-ui/module-admin'\nimport { confirm, toast, WxBadge, WxButton, WxSelect, WxSkeleton, WxText } from '@webx-ui/core'\nimport { createBlocksApi, createRegionsApi } from './api'\nimport { useBlocksMessages } from './i18n'\nimport { blocksFragmentKey } from './preview'\nimport type { RegionRow } from './types'\n\n/**\n * `wx-fragment` — the one field of «Shared block» (§4.1 of the shared blocks spec): which shared\n * block of the site this place on the page shows.\n *\n * The field says what it has chosen as well as letting it be chosen, because the block's own\n * content is not here: is it on the site, where is it edited, and that an edit there reaches\n * every page it stands on. And it offers the way out — the blocks of the shared one copied into\n * this page in its place, to follow it no more.\n */\ndefineOptions({ name: 'WxFragmentField', inheritAttrs: false })\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | null\n disabled?: boolean\n /** The shared blocks to choose from. Fetched from the panel when absent — a demo hands them in. */\n fragments?: RegionRow[] | null\n }>(),\n { modelValue: null, disabled: false, fragments: null },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string | null] }>()\n\nuseBlocksMessages()\nconst t = useTranslate('webx-blocks')\nconst message = useErrorText()\n\n/* `inject` and not `useAdmin()`: a field must draw outside a panel too, in a demo or a test. */\nconst admin: AdminContext | null = inject(adminKey, null)\nconst host = inject(blocksFragmentKey, null)\n\nconst loaded = ref<RegionRow[] | null>(null)\nconst list = computed(() => props.fragments ?? loaded.value)\nconst copying = ref(false)\n\n/* Not inside itself: the shared block being edited is not one of its own choices. */\nconst choices = computed(() =>\n (list.value ?? []).filter((row) => row.name !== (host?.own.value ?? null)),\n)\n\nconst options = computed(() => choices.value.map((row) => ({ label: row.title, value: row.name })))\n\nconst chosen = computed(() => list.value?.find((row) => row.name === props.modelValue) ?? null)\n\ntype Status = 'live' | 'edits' | 'fallback' | 'empty'\n\n/**\n * What the site shows in its place. Empty counts the tree being edited, so a published shared\n * block whose draft was emptied reads «with edits» first — that is the fact that will change.\n */\nconst status = computed<Status | null>(() => {\n const row = chosen.value\n\n if (!row) return null\n if (!row.published) return 'fallback'\n if (row.has_draft) return 'edits'\n\n return row.count === 0 ? 'empty' : 'live'\n})\n\nconst badge = computed(() =>\n status.value === 'live' ? 'success' : status.value === 'edits' ? 'warning' : 'default',\n)\n\n/**\n * Where the shared block is edited: its own editor, in a new tab — the page being edited here\n * keeps its draft and its place. Only for whoever may go there, and only where the panel has the\n * section. Built from the panel's address rather than asked of the router: the panel on the site\n * draws this form in a frame that has none.\n */\nconst editHref = computed<string | null>(() => {\n const name = chosen.value?.name\n const path = admin?.modules?.find((module) => module.id === 'regions')?.path\n\n if (!name || !path || !admin?.can('blocks.regions')) return null\n\n return `${admin.basePath.replace(/\\/$/, '')}${path}/${encodeURIComponent(name)}`\n})\n\n/** Only inside a constructor, which is what can put the copies in its place. */\nconst canDetach = computed(() => host !== null && admin !== null && chosen.value !== null)\n\nfunction choose(value: unknown): void {\n emit('update:modelValue', typeof value === 'string' && value !== '' ? value : null)\n}\n\n/**\n * The shared block's published blocks, with keys of their own, in place of this one. Asked first,\n * because what it gives up is not on screen: the edits the shared block will get from now on.\n */\nasync function detach(): Promise<void> {\n const row = chosen.value\n const key = host?.selected.value\n\n if (!row || !key || !admin || !host) return\n\n const agreed = await confirm({\n title: t('fragment.detach-title', { title: row.title }),\n message: t('fragment.detach-text'),\n confirmText: t('fragment.detach'),\n cancelText: t('page.cancel'),\n })\n\n if (!agreed) return\n\n copying.value = true\n\n try {\n // The host says how it went when it has more to say than this: the panel on the site saves.\n if (await host.detach(key, await createRegionsApi(admin).copy(row.name))) {\n toast.success(t('fragment.detached', { title: row.title }))\n }\n } catch (error) {\n toast.danger(message(error))\n } finally {\n copying.value = false\n }\n}\n\nonMounted(async () => {\n if (props.fragments !== null || !admin) return\n\n try {\n loaded.value = await createBlocksApi(admin).fragments()\n } catch (error) {\n loaded.value = []\n toast.danger(message(error))\n }\n})\n</script>\n\n<template>\n <div class=\"wx-fragment-field\">\n <wx-skeleton v-if=\"list === null\" :rows=\"1\" />\n\n <template v-else>\n <wx-select\n :model-value=\"modelValue ?? null\"\n :options=\"options\"\n :placeholder=\"t('fragment.choose')\"\n :disabled=\"disabled\"\n :aria-label=\"t('fragment.choose')\"\n teleport\n @update:model-value=\"choose\"\n />\n\n <wx-text v-if=\"choices.length === 0\" size=\"sm\" tone=\"muted\">{{ t('fragment.none') }}</wx-text>\n\n <!-- A name the site no longer declares: the page prints nothing there, and says so here. -->\n <wx-text v-else-if=\"modelValue && !chosen\" size=\"sm\" tone=\"danger\">{{\n t('fragment.missing', { name: modelValue })\n }}</wx-text>\n\n <div v-if=\"chosen\" class=\"wx-fragment-field__about\">\n <div class=\"wx-fragment-field__state\">\n <wx-badge :type=\"badge\" dot>{{ t(`fragment.status-${status}`) }}</wx-badge>\n <code>{{ chosen.name }}</code>\n </div>\n\n <wx-text size=\"sm\" tone=\"muted\">{{ t('fragment.explain') }}</wx-text>\n\n <div class=\"wx-fragment-field__actions\">\n <wx-button\n v-if=\"editHref\"\n size=\"sm\"\n variant=\"outline\"\n icon=\"external-link\"\n :href=\"editHref\"\n target=\"_blank\"\n >\n {{ t('fragment.edit') }}\n </wx-button>\n <wx-button\n v-if=\"canDetach\"\n size=\"sm\"\n variant=\"outline\"\n icon=\"copy\"\n :loading=\"copying\"\n :disabled=\"disabled || !chosen.published\"\n @click=\"detach\"\n >\n {{ t('fragment.detach') }}\n </wx-button>\n </div>\n\n <!-- Said beside the button rather than left for its disabled state to explain. -->\n <wx-text v-if=\"canDetach && !chosen.published\" size=\"sm\" tone=\"muted\">{{\n t('fragment.unpublished')\n }}</wx-text>\n </div>\n </template>\n </div>\n</template>\n\n<style scoped>\n.wx-fragment-field {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n min-width: 0;\n}\n\n.wx-fragment-field__about {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n padding: var(--wx-space-10) var(--wx-space-12);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n background: var(--wx-bg-subtle);\n}\n\n.wx-fragment-field__state {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: var(--wx-space-8);\n}\n\n.wx-fragment-field__state code {\n font-size: var(--wx-font-size-xs);\n color: var(--wx-text-muted);\n}\n\n.wx-fragment-field__actions {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wx-space-8);\n}\n</style>\n","import { inject, provide, type InjectionKey, type Ref } from 'vue'\nimport type { RegionDetail } from './types'\n\n/**\n * What the region editor knows and the nodes of its screen do not.\n *\n * The editor is a described screen (`regions.form`), so a site can add a tab to it with a patch;\n * the history is a node type of that screen, and it needs the region being edited — which a\n * description cannot hand it. The page hosting the screen provides it instead.\n */\nexport interface RegionEditorContext {\n /** The region as the server last answered it, or `null` while the first request is out. */\n region: Ref<RegionDetail | null>\n /** Whether this administrator may write. */\n canManage: boolean\n /** Ask the server for the region again — after a restore. */\n reload(): Promise<void>\n}\n\nexport const regionEditorKey: InjectionKey<RegionEditorContext> = Symbol('wx-region-editor')\n\nexport function provideRegionEditor(editor: RegionEditorContext): void {\n provide(regionEditorKey, editor)\n}\n\n/** The editor above this node, or `null` outside one: a node drawn in a demo draws nothing. */\nexport function useRegionEditor(): RegionEditorContext | null {\n return inject(regionEditorKey, null)\n}\n\n/**\n * The preview address for one page of the site.\n *\n * The server signs the region and nothing else, so the page is appended by the panel: a person\n * looking at the header on the contacts page is still looking at the same region.\n */\nexport function previewAt(url: string, path: string): string {\n return `${url}${url.includes('?') ? '&' : '?'}at=${encodeURIComponent(path)}`\n}\n\n/** A site path out of whatever the link picker holds: an address typed, or a page's URL. */\nexport function sitePath(address: string | null): string | null {\n if (address === null || address.trim() === '') return null\n\n const trimmed = address.trim()\n\n try {\n // Absolute or relative alike: the base only makes `/about` parse, and is thrown away.\n const url = new URL(trimmed, 'http://site.invalid')\n\n return url.pathname || '/'\n } catch {\n return trimmed.startsWith('/') ? trimmed : `/${trimmed}`\n }\n}\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport {\n createLinksApi,\n emptyLink,\n useAdmin,\n useI18n,\n useTranslate,\n WxLinkPicker,\n type LinkValue,\n} from '@webx-ui/module-admin'\nimport { WxButton, WxIcon, WxPopover } from '@webx-ui/core'\nimport { useBlocksMessages } from './i18n'\nimport { sitePath } from './region'\n\n/**\n * Which page of the site the region is looked at on.\n *\n * A header is judged against the page under it, so the preview is a real address of the site\n * and this picks which one. The choice goes through the panel's own link picker — the same\n * \"what can be pointed at\" every link field uses — and what comes out is a path: the preview\n * needs where the page is, not which entity it is.\n */\ndefineOptions({ name: 'WxRegionPagePicker' })\n\nexport interface RegionPlace {\n /** The site path the preview draws, `/` for the home page. */\n path: string\n /** What was chosen, so reopening the picker shows it chosen. `null` — the home page. */\n link: LinkValue | null\n}\n\nconst place = defineModel<RegionPlace>({ required: true })\n\nconst admin = useAdmin()\nconst i18n = useI18n()\nconst links = createLinksApi(admin)\nuseBlocksMessages()\n\nconst t = useTranslate('webx-blocks')\n\nconst open = ref(false)\n\n/** Starts on an address rather than a section: \"/\" is the one place worth typing. */\nconst link = computed<LinkValue>(() => place.value.link ?? { ...emptyLink(), target: 'url' })\n\nconst label = computed(() => (place.value.path === '/' ? t('region.home') : place.value.path))\n\n/**\n * The link as the picker changes it, turned into a path once there is one.\n *\n * Half-made values are kept but not applied — a section picked and nothing searched yet — so\n * the preview does not jump to nowhere while somebody is still choosing.\n */\nasync function change(value: LinkValue | null): Promise<void> {\n if (value === null) return\n\n if (value.target === 'url') {\n place.value = { path: sitePath(value.url) ?? place.value.path, link: value }\n\n return\n }\n\n if (value.target === 'entity' && value.entity_type !== null && value.entity_id !== null) {\n const [resolved] = await links.resolve(\n [{ type: value.entity_type, id: value.entity_id }],\n i18n.state.locale,\n )\n\n place.value = { path: sitePath(resolved?.url ?? null) ?? place.value.path, link: value }\n\n return\n }\n\n place.value = { ...place.value, link: value }\n}\n\nfunction home(): void {\n place.value = { path: '/', link: null }\n open.value = false\n}\n</script>\n\n<template>\n <wx-popover\n v-model:open=\"open\"\n :title=\"t('region.choose-page')\"\n :width=\"380\"\n side=\"bottom\"\n align=\"end\"\n teleport\n >\n <template #trigger>\n <wx-button size=\"sm\" variant=\"outline\" class=\"wx-region-page-picker__trigger\">\n <wx-icon name=\"eye\" />\n <span class=\"wx-region-page-picker__words\">\n {{ t('region.shown-on') }}:\n <strong>{{ label }}</strong>\n </span>\n <wx-icon name=\"chevron-down\" />\n </wx-button>\n </template>\n\n <div class=\"wx-region-page-picker\">\n <wx-link-picker\n :model-value=\"link\"\n :allow-none=\"false\"\n :attributes=\"false\"\n @update:model-value=\"change\"\n />\n <wx-button size=\"sm\" variant=\"text\" :disabled=\"place.path === '/'\" @click=\"home\">\n <wx-icon name=\"home\" />\n {{ t('region.back-home') }}\n </wx-button>\n </div>\n </wx-popover>\n</template>\n\n<style scoped>\n.wx-region-page-picker {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n gap: var(--wx-space-12);\n}\n\n.wx-region-page-picker > :deep(.wx-button) {\n align-self: flex-start;\n}\n\n/* The path can be long; the button stays one line and the path is what gets cut. */\n.wx-region-page-picker__words {\n max-width: 260px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'\nimport { onBeforeRouteLeave, useRoute, useRouter } from 'vue-router'\nimport {\n useAdmin,\n useEditing,\n useErrorText,\n useTranslate,\n WxEditingAlerts,\n WxSaveState,\n WxScreen,\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 WxSkeleton,\n WxText,\n} from '@webx-ui/core'\nimport type { ScreenModel } from '@webx-ui/schema'\nimport { createRegionsApi } from './api'\nimport { useBlocksMessages } from './i18n'\nimport { provideBlocksPreview, provideBlocksTop, type BlocksTop } from './preview'\nimport { previewAt, provideRegionEditor, sitePath } from './region'\nimport RegionPagePicker, { type RegionPlace } from './RegionPagePicker.vue'\nimport type { BlockNode, FragmentUse, RegionConflict, RegionDetail } from './types'\n\n/**\n * The editor of one layout region: the page editor without what a region does not have — no\n * address, no SEO, no template of its own.\n *\n * Between the head and the bar is `regions.form`, a described screen, so a site adds a tab with\n * a patch as it would to a page. What the screen cannot know is which region it is — its name in\n * `allowed_in`, its `allow` and `max` from the config — and where to preview it; this page\n * provides both.\n *\n * Saving is by autosave, as on a page; publishing, taking off and discarding are asked about,\n * because each of them changes what every page of the site shows.\n */\ndefineOptions({ name: 'WxRegionEditorPage' })\n\nconst props = withDefaults(defineProps<{ base?: string }>(), { base: '/regions' })\n\nconst context = useAdmin()\nconst api = createRegionsApi(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\n/** How long after the last change the draft goes to the server. */\nconst PAUSE = 1200\n\nconst name = computed(() => String(route.params.name ?? ''))\n\nconst region = ref<RegionDetail | null>(null)\nconst values = ref<ScreenModel>({ blocks: [] })\nconst revision = ref('')\n\nconst loading = ref(true)\nconst saving = ref(false)\nconst working = ref(false)\nconst errors = ref<Record<string, string[]>>({})\n\nconst snapshot = ref('')\nconst reloadToken = ref(0)\nconst screenKey = ref(0)\n\n/* `can()` answers a plain boolean; wrapped here so the template and the guards read one thing. */\nconst canManage = computed(() => context.can('blocks.regions'))\n\n/*\n * Other people on the same region: a refused save is merged with theirs block by block and saved\n * again, and only a block both sides changed is asked about. The form is `{ blocks }` — the shape\n * the screen edits — so the merge walks the tree the same way it walks a page's.\n */\nconst editing = useEditing<ScreenModel>({\n entity: 'regions',\n id: () => region.value?.name,\n values,\n revision,\n read: async () => {\n const detail = await api.get(name.value)\n\n return { values: { blocks: detail.blocks }, revision: detail.revision }\n },\n adopt: (theirs) => {\n snapshot.value = JSON.stringify(theirs.values)\n reloadToken.value += 1\n },\n // Published or taken off by somebody else: the badge follows, and the form stays as it is.\n // No `restore`: a region is declared by the code, so there is no bin to take it out of.\n refresh: () => refresh(),\n canWrite: () => canManage.value,\n busy: () => saving.value || flight !== undefined,\n screen: 'regions.form',\n})\n\nconst conflict = editing.conflict\n\nconst current = computed(() => JSON.stringify(values.value))\nconst dirty = computed(() => snapshot.value !== '' && current.value !== snapshot.value)\n\nconst tree = computed<BlockNode[]>(() =>\n Array.isArray(values.value.blocks) ? (values.value.blocks as BlockNode[]) : [],\n)\n\nconst state = computed<'saving' | 'unsaved' | 'saved'>(() => {\n if (saving.value) return 'saving'\n\n return dirty.value ? 'unsaved' : 'saved'\n})\n\n/* Which page of the site the region is looked at on, remembered per region in this browser. */\nconst place = ref<RegionPlace>({ path: '/', link: null })\n\n/* Whether somebody chose the page here, or it is the one the editor started on. */\nconst chosenPlace = ref(false)\n\nconst storageKey = computed(() => `webx.regions.at.${name.value}`)\n\nfunction readPlace(): RegionPlace | null {\n try {\n const stored = JSON.parse(\n localStorage.getItem(storageKey.value) ?? 'null',\n ) as RegionPlace | null\n\n if (stored && typeof stored.path === 'string' && stored.path.startsWith('/')) return stored\n } catch {\n // Private windows and blocked storage throw on the accessor itself: the home page it is.\n }\n\n return null\n}\n\n/**\n * A page picked — in the picker, or from where the shared block stands — and remembered. Only a\n * pick is: the page the editor starts on by itself is a guess, and a stored guess would outlive\n * the page it guessed.\n */\nfunction pickPlace(next: RegionPlace): void {\n place.value = next\n chosenPlace.value = true\n\n try {\n localStorage.setItem(storageKey.value, JSON.stringify(next))\n } catch {\n // Not remembered, which is all that is lost.\n }\n}\n\n/**\n * Where a shared block is looked at before anybody chose: the first page that places it, what the\n * site shows before a draft — not the home page, which more often than not does not hold it, and\n * then the preview is the stage with a notice instead of the block among its neighbours.\n */\nfunction firstPlace(detail: RegionDetail): RegionPlace | null {\n const uses = (detail.used_on ?? []).filter((use) => use.url)\n const use = uses.find((one) => one.live !== false) ?? uses[0]\n const path = sitePath(use?.url ?? null)\n\n return path ? { path, link: null } : null\n}\n\n/** The records that place this shared block; nothing for a region of the layout. */\nconst usedOn = computed<FragmentUse[]>(() => region.value?.used_on ?? [])\n\nfunction showOn(use: FragmentUse): void {\n const path = sitePath(use.url ?? null)\n\n if (path) pickPlace({ path, link: null })\n}\n\nconst previewUrl = computed(() =>\n region.value ? previewAt(region.value.preview_url, place.value.path) : null,\n)\n\nprovideBlocksPreview({ url: previewUrl, reload: reloadToken })\n\nprovideBlocksTop(\n computed<BlocksTop | null>(() =>\n region.value\n ? {\n root: `region:${region.value.name}`,\n label: region.value.title,\n allow: region.value.allow,\n max: region.value.max,\n // A shared block is wherever the page put it: the preview frames it and goes there.\n frame: region.value.fragment ? region.value.name : null,\n }\n : null,\n ),\n)\n\nprovideRegionEditor({ region, canManage: canManage.value, reload: () => load(true) })\n\nfunction take(detail: RegionDetail): void {\n region.value = detail\n values.value = { blocks: detail.blocks }\n revision.value = detail.revision\n snapshot.value = JSON.stringify(values.value)\n editing.opened(values.value)\n conflict.value = null\n}\n\nasync function load(silent = false): Promise<void> {\n if (!silent) loading.value = true\n\n try {\n const detail = await api.get(name.value)\n\n take(detail)\n\n if (!chosenPlace.value && detail.fragment) place.value = firstPlace(detail) ?? place.value\n\n reloadToken.value += 1\n } catch (error) {\n toast.danger(message(error))\n void router.push(props.base)\n } finally {\n loading.value = false\n }\n}\n\n/**\n * What surrounds the form, read again: the region with its status. Not the blocks — the form is\n * somebody's work in progress, and a change of its content is the notice's to offer.\n */\nasync function refresh(): Promise<void> {\n try {\n region.value = await api.get(name.value)\n } catch {\n // The heartbeat says what happened; a region that could not be read again stays as it was.\n }\n}\n\n/* One pending save at a time, and one pending pause. */\nlet timer: ReturnType<typeof setTimeout> | undefined\n\nfunction schedule(): void {\n if (!canManage.value || conflict.value || !dirty.value || editing.stopped.value) return\n\n clearTimeout(timer)\n timer = setTimeout(() => void save(), PAUSE)\n}\n\nfunction onFocusOut(): void {\n if (!canManage.value || conflict.value || !dirty.value || saving.value || editing.stopped.value)\n return\n\n clearTimeout(timer)\n void save()\n}\n\n/* The save on its way, and what it carries. */\nlet flight: { carried: string; done: Promise<void> } | undefined\n\n/** A save asked for while another is out waits for it rather than being dropped (as pages). */\nasync function save(): Promise<void> {\n while (flight) {\n const { carried, done } = flight\n\n await done\n\n if (!dirty.value || conflict.value || current.value === carried) return\n }\n\n const carried = current.value\n const done = write()\n\n flight = { carried, done }\n\n try {\n await done\n } finally {\n if (flight?.done === done) flight = undefined\n }\n}\n\nasync function write(): Promise<void> {\n if (!region.value || !canManage.value) return\n\n clearTimeout(timer)\n\n // What is being sent, so that anything changed while the request is out stays dirty.\n const sending = current.value\n const sent = values.value\n const blocks = tree.value\n\n saving.value = true\n errors.value = {}\n\n try {\n const detail = await api.save(region.value.name, { blocks, revision: revision.value })\n\n region.value = detail\n revision.value = detail.revision\n conflict.value = null\n\n if (current.value === sending) snapshot.value = sending\n\n // What the server holds now is what was sent: the base of the next merge.\n editing.opened(sent)\n\n // The preview draws the draft, and the draft is what was just written.\n reloadToken.value += 1\n } catch (error) {\n const failure = error as {\n status?: number\n body?: Partial<RegionConflict> & { errors?: Record<string, string[]> }\n }\n\n if (failure.status === 409 && failure.body?.data) {\n const theirs = failure.body.data\n const merged = editing.refused({\n values: { blocks: theirs.blocks },\n revision: theirs.revision,\n changed: failure.body.changed,\n })\n\n // Nothing overlapping: both edits are in the form now, and they go to the server again.\n if (merged) {\n region.value = theirs\n void save()\n }\n } else if (failure.body?.errors) {\n errors.value = failure.body.errors\n toast.danger(t('region.save-failed'))\n } else if (!(await editing.failed(error))) {\n toast.danger(message(error))\n }\n } finally {\n saving.value = false\n }\n}\n\n/** Give up what was written and take the region as it now is; the component asked first. */\nasync function takeTheirs(): Promise<void> {\n await load(true)\n}\n\n/**\n * Run one of the three actions that change the site, after the question and a save.\n *\n * Saving first, because each of them works on the draft the server holds: publishing a region\n * with the last second of edits still in the pause would publish without them.\n */\nasync function act(\n words: {\n title: string\n text: string\n confirm: string\n done: string\n danger?: boolean\n publishing?: boolean\n },\n call: (name: string, revision?: string) => Promise<RegionDetail>,\n): Promise<void> {\n if (!region.value) return\n\n // Publishing saves before the question rather than after: the draft on the server may hold\n // somebody else's edit this editor never pulled in, and that is said before it goes on the\n // site — with whose it is and where — rather than published unseen.\n let held: { revision: string; asked: boolean } | null = null\n\n if (words.publishing) {\n if (dirty.value) await save()\n if (conflict.value || dirty.value) return\n\n held = await editing.beforePublish()\n\n if (!held) return\n }\n\n // One question is enough: whoever just agreed to publish somebody else's changes has said yes.\n const agreed =\n held?.asked ||\n (await confirm({\n title: words.title,\n message: words.text,\n confirmText: words.confirm,\n cancelText: t('region.cancel'),\n tone: words.danger ? 'danger' : undefined,\n }))\n\n if (!agreed) return\n\n if (dirty.value) await save()\n if (conflict.value || dirty.value || !region.value) return\n\n working.value = true\n\n try {\n take(await call(region.value.name, held?.revision))\n reloadToken.value += 1\n toast.success(words.done)\n } catch (error) {\n // A block that cannot be drawn refuses the publication by name; that sentence is the\n // server's to say, since only it rendered the region.\n const refused = (error as { body?: { errors?: Record<string, string[]> } }).body?.errors\n ?.blocks?.[0]\n\n if (refused) toast.danger(refused)\n else if (!(await editing.failed(error))) toast.danger(message(error))\n } finally {\n working.value = false\n }\n}\n\nfunction publish(): Promise<void> {\n const title = region.value?.title ?? ''\n\n return act(\n {\n title: t('region.publish-title', { title }),\n text: region.value?.fragment ? t('fragment.publish-text') : t('region.publish-text'),\n confirm: t('region.publish'),\n done: t('region.published'),\n publishing: true,\n },\n (region, revision) => api.publish(region, revision),\n )\n}\n\nfunction unpublish(): Promise<void> {\n const title = region.value?.title ?? ''\n\n return act(\n {\n title: t('region.unpublish-title', { title }),\n text: t('region.unpublish-text'),\n confirm: t('region.unpublish'),\n done: t('region.unpublished'),\n danger: true,\n },\n (region) => api.unpublish(region),\n )\n}\n\nfunction discard(): Promise<void> {\n const title = region.value?.title ?? ''\n\n return act(\n {\n title: t('region.discard-title', { title }),\n text: t('region.discard-text'),\n confirm: t('region.discard'),\n done: t('region.discarded'),\n danger: true,\n },\n (region) => api.discardDraft(region),\n )\n}\n\n/** The code's view made into a block type, with one of it put in the draft (§7.3). */\nasync function adopt(): Promise<void> {\n if (!region.value) return\n\n if (dirty.value) await save()\n\n working.value = true\n\n try {\n const adopted = await api.adopt(region.value.name)\n\n take(adopted.region)\n reloadToken.value += 1\n // The constructor reads the catalogue once, when it mounts, and the type that was just made\n // is not in it: drawn again, the new block gets its title and its form rather than a slug.\n screenKey.value += 1\n toast.success(t('region.adopted', { slug: adopted.block.slug }))\n } catch (error) {\n toast.danger(message(error))\n } finally {\n working.value = false\n }\n}\n\ntype Status = 'live' | 'modified' | 'fallback'\n\nconst status = computed<Status>(() => {\n if (!region.value?.published) return 'fallback'\n\n return region.value.has_draft || dirty.value ? 'modified' : 'live'\n})\n\nconst badge = computed(() =>\n status.value === 'live' ? 'success' : status.value === 'modified' ? 'warning' : 'default',\n)\n\nconst actions = computed<ScreenAction[]>(() =>\n previewUrl.value\n ? [\n {\n key: 'preview',\n label: t('region.preview'),\n icon: 'external-link',\n href: previewUrl.value,\n },\n ]\n : [],\n)\n\nfunction leaveGuard(event: BeforeUnloadEvent): void {\n if (dirty.value) event.preventDefault()\n}\n\nwatch(current, schedule)\n\nwatch(\n name,\n () => {\n const stored = readPlace()\n\n place.value = stored ?? { path: '/', link: null }\n chosenPlace.value = stored !== null\n void load()\n },\n { immediate: true },\n)\n\nonMounted(() => {\n window.addEventListener('beforeunload', leaveGuard)\n})\n\nonBeforeUnmount(() => {\n clearTimeout(timer)\n window.removeEventListener('beforeunload', leaveGuard)\n})\n\n/* Leaving flushes the pause rather than asking, and asks only when the save did not go through. */\nonBeforeRouteLeave(async () => {\n if (!dirty.value || !canManage.value) return true\n\n await save()\n\n if (!dirty.value) return true\n\n return await confirm({\n title: t('region.leave-title'),\n message: t('region.leave-text'),\n confirmText: t('region.leave'),\n cancelText: t('region.cancel'),\n tone: 'danger',\n })\n})\n</script>\n\n<template>\n <div class=\"wx-region-editor\" @focusout=\"onFocusOut\">\n <template v-if=\"loading || !region\">\n <wx-skeleton class=\"wx-region-editor__ghost\" title :rows=\"1\" />\n <wx-card><wx-skeleton :rows=\"8\" /></wx-card>\n </template>\n\n <template v-else>\n <wx-screen-head\n divider\n :back=\"base\"\n :back-label=\"t('region.title')\"\n :title=\"region.title\"\n :subtitle=\"region.description ?? undefined\"\n :actions=\"actions\"\n >\n <template #title-after>\n <wx-badge :type=\"badge\" dot>{{ t(`region.status-${status}`) }}</wx-badge>\n </template>\n\n <template #extra>\n <region-page-picker :model-value=\"place\" @update:model-value=\"pickPlace\" />\n </template>\n </wx-screen-head>\n\n <!-- Somebody else wrote while this editor was open. What does not overlap is merged\n without a word; what does is listed block by block. -->\n <wx-editing-alerts :editing=\"editing\" @save=\"save\" @theirs=\"takeTheirs\" />\n\n <!--\n While the tree is empty the site prints the view from the code, and the preview shows\n exactly that — so the page says which view it is and how to replace it, rather than\n leaving a header that is plainly there beside a constructor that says \"no blocks\".\n -->\n <wx-alert\n v-if=\"tree.length === 0\"\n class=\"wx-region-editor__empty\"\n type=\"info\"\n variant=\"soft\"\n :title=\"t('region.empty-title')\"\n :description=\"\n region.fallback\n ? t('region.empty-text', { view: region.fallback })\n : t('region.empty-text-none')\n \"\n >\n <template v-if=\"region.can_adopt && canManage\" #actions>\n <wx-button size=\"sm\" variant=\"outline\" :loading=\"working\" @click=\"adopt\">\n {{ t('region.adopt') }}\n </wx-button>\n </template>\n </wx-alert>\n\n <!--\n Where a shared block stands — the records whose content places it. Each one is a page to\n look at it on, which is what a list of places is for in front of a preview; a shared block\n inside another one leads to that one's editor. Templates that print the tag are not\n content, and the line under the list says they are not counted rather than leaving the\n list to look complete.\n -->\n <div v-if=\"region.fragment\" class=\"wx-region-editor__where\">\n <span class=\"wx-region-editor__where-label\">{{ t('fragment.used-on') }}</span>\n <template v-if=\"usedOn.length\">\n <template v-for=\"use in usedOn\" :key=\"`${use.model}:${use.id}`\">\n <router-link\n v-if=\"use.region\"\n :to=\"`${base}/${encodeURIComponent(use.region)}`\"\n class=\"wx-region-editor__use\"\n >\n {{ use.title ?? use.region }}\n </router-link>\n <button\n v-else-if=\"use.url\"\n type=\"button\"\n class=\"wx-region-editor__use\"\n :class=\"{ 'is-active': sitePath(use.url) === place.path }\"\n :aria-pressed=\"sitePath(use.url) === place.path\"\n :title=\"t('fragment.show-here')\"\n @click=\"showOn(use)\"\n >\n {{ use.title ?? `#${use.id}` }}\n <wx-badge v-if=\"use.live === false\" type=\"warning\" size=\"sm\">{{\n t('fragment.draft-only')\n }}</wx-badge>\n </button>\n <span v-else class=\"wx-region-editor__use is-plain\">{{\n use.title ?? `#${use.id}`\n }}</span>\n </template>\n </template>\n <wx-text v-else size=\"sm\" tone=\"muted\">{{ t('fragment.used-nowhere') }}</wx-text>\n <wx-text size=\"sm\" tone=\"muted\" class=\"wx-region-editor__where-note\">{{\n t('fragment.templates')\n }}</wx-text>\n </div>\n\n <div class=\"wx-region-editor__screen\">\n <wx-screen\n :key=\"screenKey\"\n v-model=\"values\"\n name=\"regions.form\"\n :errors=\"errors\"\n :disabled=\"!canManage || working\"\n />\n </div>\n\n <wx-action-bar v-if=\"canManage\">\n <template #state>\n <wx-save-state v-if=\"!editing.stopped.value\" :state=\"state\" />\n </template>\n\n <wx-button v-if=\"region.published\" variant=\"text\" :disabled=\"working\" @click=\"unpublish\">\n {{ t('region.unpublish') }}\n </wx-button>\n\n <wx-button\n v-if=\"region.has_draft && region.published\"\n variant=\"text\"\n :disabled=\"working\"\n @click=\"discard\"\n >\n {{ t('region.discard') }}\n </wx-button>\n\n <wx-button\n variant=\"outline\"\n :loading=\"saving\"\n :disabled=\"!dirty || editing.stopped.value\"\n :title=\"editing.blocked.value\"\n @click=\"save\"\n >\n {{ t('region.save') }}\n </wx-button>\n\n <wx-button\n type=\"primary\"\n :loading=\"working\"\n :disabled=\"editing.stopped.value || (region.published && !region.has_draft && !dirty)\"\n :title=\"editing.blocked.value\"\n @click=\"publish\"\n >\n {{ t('region.publish') }}\n </wx-button>\n </wx-action-bar>\n </template>\n </div>\n</template>\n\n<style scoped>\n.wx-region-editor {\n display: flex;\n flex-direction: column;\n gap: var(--wx-gap, var(--wx-space-16));\n height: 100%;\n min-height: 0;\n container-type: inline-size;\n}\n\n.wx-region-editor__ghost {\n max-width: 420px;\n}\n\n.wx-region-editor__where {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wx-space-6) var(--wx-space-8);\n min-width: 0;\n}\n\n.wx-region-editor__where-label {\n font-size: var(--wx-font-size-sm);\n font-weight: var(--wx-font-weight-semibold);\n color: var(--wx-text-strong);\n}\n\n/* A row of pages, each a press away from the preview: chips rather than links, since they stay. */\n.wx-region-editor__use {\n display: inline-flex;\n align-items: center;\n gap: var(--wx-space-6);\n min-width: 0;\n max-width: 100%;\n padding: var(--wx-space-2) var(--wx-space-10);\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-text-default);\n font: inherit;\n font-size: var(--wx-font-size-sm);\n text-decoration: none;\n overflow-wrap: anywhere;\n cursor: pointer;\n}\n\n.wx-region-editor__use:hover {\n border-color: var(--wx-border-strong);\n}\n\n.wx-region-editor__use:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n.wx-region-editor__use.is-active {\n border-color: var(--wx-color-primary);\n color: var(--wx-text-link);\n}\n\n.wx-region-editor__use.is-plain {\n cursor: default;\n}\n\n/* Its own line: a note about the list, not one more place in it. */\n.wx-region-editor__where-note {\n flex-basis: 100%;\n}\n\n.wx-region-editor__screen {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n}\n\n/*\n * The height travels through the screen's own boxes, as on the page editor: each is a flex\n * column that may shrink — and only the tab on screen, since `display: flex` on a kept-alive\n * hidden tab would override its `[hidden]` and split the height between all of them (§4).\n */\n.wx-region-editor__screen :deep(.wx-screen-host),\n.wx-region-editor__screen :deep(.wx-screen),\n.wx-region-editor__screen :deep(.wx-tabs),\n.wx-region-editor__screen :deep(.wx-tabs__layout),\n.wx-region-editor__screen :deep(.wx-tabs__panels),\n.wx-region-editor__screen :deep(.wx-tab:not([hidden])) {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport { useAdmin, useErrorText, useTranslate, WxDate, WxDrafts } from '@webx-ui/module-admin'\nimport { confirm, toast, WxBadge, WxButton, WxEmpty, WxSkeleton, WxText } from '@webx-ui/core'\nimport { createRegionsApi } from './api'\nimport { useBlocksMessages } from './i18n'\nimport { useRegionEditor } from './region'\nimport type { RegionVersion } from './types'\n\n/**\n * What was published in the region, when and by whom — the `wx-region-history` node of\n * `regions.form`.\n *\n * Publications first, and the copies of the draft — autosaves, a draft somebody else's save wrote\n * over — in a list of their own under them, as with pages. Restoring makes an old version the\n * draft, and publishing it is the usual separate step — so nothing here changes the site by\n * itself, and a header cannot be swapped by one slip in a list.\n */\ndefineOptions({ name: 'WxRegionHistory' })\n\nconst context = useAdmin()\nconst api = createRegionsApi(context)\nconst editor = useRegionEditor()\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 versions = ref<RegionVersion[] | null>(null)\nconst working = ref(false)\n\nconst region = computed(() => editor?.region.value ?? null)\nconst canManage = computed(() => editor?.canManage ?? false)\n\n/** The newest publication is the site — while the region is on it at all. */\nconst live = computed(() =>\n region.value?.published ? (versions.value?.[0]?.number ?? null) : null,\n)\n\nasync function load(): Promise<void> {\n const current = region.value\n\n // Never saved: no row, so no history to ask for.\n if (!current || current.id === null) {\n versions.value = current ? [] : null\n\n return\n }\n\n try {\n versions.value = await api.versions(current.name)\n } catch (error) {\n versions.value = []\n toast.danger(message(error))\n }\n}\n\nasync function restore(version: RegionVersion): Promise<void> {\n const current = region.value\n\n if (!current) return\n\n const agreed = await confirm({\n title: t('region.restore-title', { number: version.number }),\n message: t('region.restore-text'),\n confirmText: t('region.restore'),\n cancelText: t('region.cancel'),\n })\n\n if (!agreed) return\n\n working.value = true\n\n try {\n await api.restoreVersion(current.name, version.number)\n // Through the editor rather than with the answer: its values are what the constructor is\n // bound to, and a version restored underneath it has to reach the tree.\n await editor?.reload()\n toast.success(t('region.restored-version', { number: version.number }))\n } catch (error) {\n toast.danger(message(error))\n } finally {\n working.value = false\n }\n}\n\n// The region is read again after every publication and restore; its stamps say when to list.\nwatch(\n () => [region.value?.name, region.value?.published_at, region.value?.updated_at],\n () => void load(),\n { immediate: true },\n)\n</script>\n\n<template>\n <div class=\"wx-region-history-tab\">\n <div class=\"wx-region-history\">\n <wx-skeleton v-if=\"versions === null\" class=\"wx-region-history__ghost\" :rows=\"3\" />\n <wx-empty v-else-if=\"versions.length === 0\" :description=\"t('region.history-empty')\" />\n <div\n v-for=\"version in versions\"\n v-else\n :key=\"version.number\"\n class=\"wx-region-history__row\"\n :class=\"{ 'is-live': version.number === live }\"\n >\n <code class=\"wx-region-history__number\">{{\n t('region.version', { number: version.number })\n }}</code>\n <div class=\"wx-region-history__who\">\n <wx-date v-if=\"version.created_at\" :value=\"version.created_at\" size=\"md\" tone=\"default\" />\n <wx-text size=\"sm\" tone=\"muted\">\n {{ version.author?.name ?? t(`region.source-${version.source}`) }}\n <template v-if=\"version.comment\"> · {{ version.comment }}</template>\n </wx-text>\n </div>\n <wx-badge v-if=\"version.number === live\" type=\"success\" dot>{{\n t('region.version-live')\n }}</wx-badge>\n <wx-button\n v-if=\"canManage && version.number !== live\"\n size=\"sm\"\n variant=\"outline\"\n :loading=\"working\"\n @click=\"restore(version)\"\n >\n {{ t('region.restore') }}\n </wx-button>\n </div>\n </div>\n\n <wx-drafts\n :id=\"region?.name\"\n entity=\"regions\"\n screen=\"regions.form\"\n :can-restore=\"canManage\"\n :stamp=\"[region?.published_at, region?.updated_at]\"\n @restored=\"editor?.reload()\"\n />\n </div>\n</template>\n\n<style scoped>\n.wx-region-history-tab {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-24);\n}\n\n.wx-region-history {\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 /* Clip, not hidden: rounding the rows' corners needs no scroll container (§4). */\n overflow: clip;\n}\n\n.wx-region-history__ghost {\n padding: var(--wx-space-10) var(--wx-space-12);\n}\n\n.wx-region-history__row {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\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-default);\n}\n\n.wx-region-history__row:last-child {\n border-block-end: 0;\n}\n\n.wx-region-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-region-history__who {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-width: 160px;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onMounted, ref } from 'vue'\nimport { useAdmin, useErrorText, useTranslate, WxDate, WxScreenHead } from '@webx-ui/module-admin'\nimport { toast, WxBadge, WxEmpty, WxIcon, WxSkeleton, WxText } from '@webx-ui/core'\nimport { createRegionsApi } from './api'\nimport { useBlocksMessages } from './i18n'\nimport type { RegionRow } from './types'\n\n/**\n * The layout regions of the site: one card each.\n *\n * Not a table. A site declares two regions, the header and the footer, and a table of two rows\n * is a heading row and a lot of empty width — while what a reader wants from each is a sentence:\n * is the site showing the blocks or the code, and which view of the code.\n */\ndefineOptions({ name: 'WxRegionsPage' })\n\nconst props = withDefaults(defineProps<{ base?: string }>(), { base: '/regions' })\n\nconst context = useAdmin()\nconst api = createRegionsApi(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 regions = ref<RegionRow[] | null>(null)\n\n/**\n * The regions of the layout, then the shared blocks (§4.3 of the shared blocks spec): the first are\n * on every page, the second wherever somebody put them, and one list of both read as if the\n * request form stood on every page like the header. A site without shared blocks gets the one\n * list it always had, without a heading over it.\n */\nconst sections = computed(() => {\n const rows = regions.value ?? []\n const shared = rows.filter((row) => row.fragment === true)\n\n if (shared.length === 0) return [{ key: 'all', title: null, help: null, rows }]\n\n return [\n {\n key: 'layout',\n title: t('fragment.group-layout'),\n help: null,\n rows: rows.filter((row) => row.fragment !== true),\n },\n {\n key: 'shared',\n title: t('fragment.group-shared'),\n help: t('fragment.group-shared-help'),\n rows: shared,\n },\n ].filter((section) => section.rows.length > 0)\n})\n\n/**\n * The state as one chip, and a second one only when it adds something: a region on the site with\n * edits waiting is two facts, and folding them into one word would hide either.\n */\nfunction chips(region: RegionRow): { label: string; type: 'success' | 'warning' | 'default' }[] {\n if (region.published) {\n const live = { label: t('region.state-live'), type: 'success' as const }\n\n return region.has_draft ? [live, { label: t('region.state-edits'), type: 'warning' }] : [live]\n }\n\n // Never saved, or taken off the site: either way the site prints the code's view. A draft\n // that exists is said beside it, because it is what the next \"Publish\" would put there.\n const fallback = { label: t('region.state-fallback'), type: 'default' as const }\n\n return region.has_draft\n ? [fallback, { label: t('region.state-draft'), type: 'warning' }]\n : [fallback]\n}\n\nonMounted(async () => {\n try {\n regions.value = await api.list()\n } catch (error) {\n regions.value = []\n toast.danger(message(error))\n }\n})\n</script>\n\n<template>\n <div class=\"wx-regions\">\n <wx-screen-head :title=\"t('region.title')\" :subtitle=\"t('region.intro')\" />\n\n <div v-if=\"regions === null\" class=\"wx-regions__grid\">\n <div v-for=\"index in 2\" :key=\"index\" class=\"wx-regions__card\">\n <wx-skeleton title :rows=\"2\" />\n </div>\n </div>\n\n <wx-empty\n v-else-if=\"regions.length === 0\"\n :title=\"t('region.empty')\"\n :description=\"t('region.empty-help')\"\n />\n\n <template v-else>\n <section\n v-for=\"section in sections\"\n :key=\"section.key\"\n class=\"wx-regions__section\"\n :aria-label=\"section.title ?? undefined\"\n >\n <div v-if=\"section.title\" class=\"wx-regions__head\">\n <h2 class=\"wx-regions__heading\">{{ section.title }}</h2>\n <wx-text v-if=\"section.help\" size=\"sm\" tone=\"muted\">{{ section.help }}</wx-text>\n </div>\n\n <div class=\"wx-regions__grid\">\n <router-link\n v-for=\"region in section.rows\"\n :key=\"region.name\"\n :to=\"`${props.base}/${encodeURIComponent(region.name)}`\"\n class=\"wx-regions__card is-link\"\n >\n <div class=\"wx-regions__top\">\n <span class=\"wx-regions__title\">{{ region.title }}</span>\n <code class=\"wx-regions__name\">{{ region.name }}</code>\n </div>\n\n <wx-text\n v-if=\"region.description\"\n size=\"sm\"\n tone=\"muted\"\n class=\"wx-regions__description\"\n >\n {{ region.description }}\n </wx-text>\n\n <div class=\"wx-regions__chips\">\n <wx-badge v-for=\"chip in chips(region)\" :key=\"chip.label\" :type=\"chip.type\" dot>\n {{ chip.label }}\n </wx-badge>\n </div>\n\n <div class=\"wx-regions__meta\">\n <wx-text size=\"sm\" tone=\"muted\">{{\n t('region.count', { count: region.count })\n }}</wx-text>\n <!-- Where it stands, for a shared block: a header is on every page and says nothing. -->\n <wx-text v-if=\"region.fragment && region.used_on\" size=\"sm\" tone=\"muted\">\n {{\n region.used_on.length\n ? t('fragment.count', { count: region.used_on.length })\n : t('fragment.used-nowhere')\n }}\n </wx-text>\n <wx-text size=\"sm\" tone=\"muted\">\n {{\n region.fallback\n ? t('region.fallback-view', { view: region.fallback })\n : t('region.fallback-none')\n }}\n </wx-text>\n <wx-date v-if=\"region.updated_at\" :value=\"region.updated_at\" size=\"sm\" tone=\"muted\" />\n </div>\n\n <wx-icon name=\"chevron-right\" class=\"wx-regions__go\" aria-hidden=\"true\" />\n </router-link>\n </div>\n </section>\n </template>\n </div>\n</template>\n\n<style scoped>\n.wx-regions {\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-regions__section {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n}\n\n.wx-regions__head {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-2);\n}\n\n.wx-regions__heading {\n margin: 0;\n font-size: var(--wx-font-size-md);\n font-weight: var(--wx-font-weight-semibold);\n color: var(--wx-text-strong);\n}\n\n/* Side by side while each card keeps room for its sentence; one above the other on a phone. */\n.wx-regions__grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n gap: var(--wx-gap, var(--wx-space-16));\n}\n\n.wx-regions__card {\n position: relative;\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n min-width: 0;\n padding: var(--wx-space-16);\n padding-inline-end: var(--wx-space-40);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n background: var(--wx-bg-surface);\n box-shadow: var(--wx-shadow-card);\n color: var(--wx-text-default);\n text-decoration: none;\n}\n\n.wx-regions__card.is-link {\n transition: border-color var(--wx-duration-fast);\n}\n\n.wx-regions__card.is-link:hover {\n border-color: var(--wx-border-strong);\n}\n\n.wx-regions__card.is-link:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n.wx-regions__top {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--wx-space-8);\n}\n\n.wx-regions__title {\n font-size: var(--wx-font-size-lg);\n font-weight: var(--wx-font-weight-semibold);\n color: var(--wx-text-strong);\n}\n\n.wx-regions__name {\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-regions__chips {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wx-space-6);\n}\n\n.wx-regions__meta {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wx-space-4) var(--wx-space-12);\n /* A view name is one long word; without this it pushes the card wider than its column. */\n overflow-wrap: anywhere;\n}\n\n.wx-regions__go {\n position: absolute;\n inset-block-start: 50%;\n inset-inline-end: var(--wx-space-12);\n translate: 0 -50%;\n color: var(--wx-text-muted);\n}\n</style>\n","import {\n screenLabels,\n type AdminContext,\n type AdminModule,\n type BlockLabels,\n} from '@webx-ui/module-admin'\nimport { markRaw } from 'vue'\nimport { createBlocksApi } from './api'\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'\nimport BlocksSiteBarTab from './BlocksSiteBarTab.vue'\nimport FragmentField from './FragmentField.vue'\nimport { seedBlocksMessages } from './i18n'\nimport RegionEditorPage from './RegionEditorPage.vue'\nimport RegionHistory from './RegionHistory.vue'\nimport RegionsPage from './RegionsPage.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 blockLabels,\n // «Blocks» in the panel on the site (§8 of WEBX_UI_SITE_BAR.md): where the server offers it\n // — a record with blocks, for somebody who may edit it, and the layout's regions, for\n // somebody who edits those. One tab for both: the page has one picker, and a click on the\n // header should not have to know which tab it belongs to.\n siteBarTabs: [\n {\n name: 'blocks',\n sections: ['regions'],\n label: (admin) => {\n seedBlocksMessages(admin.i18n)\n\n return admin.i18n.scope('webx-blocks')('site-bar.tab')\n },\n component: markRaw(BlocksSiteBarTab),\n },\n ],\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 // «Shared block»: which shared block of the site this place on a page shows — a region\n // declared with `fragment`, edited once in «Site regions» (§4.1 of the shared blocks spec).\n 'wx-fragment': { component: FragmentField, kind: 'field' },\n },\n }\n}\n\nexport interface RegionsOptions {\n /** Where the section lives inside the panel. */\n path?: string\n}\n\n/**\n * The layout regions — the header and the footer made of blocks — as a section of their own.\n *\n * A second module rather than two more routes of `blocks()`: the navigation is one entry per\n * module, and this one stands in a different place for a different person. Blocks is the\n * developer's section, closed by `blocks.manage` because a template is code; the header is\n * edited by whoever edits the pages, under `blocks.regions`. The id matches the module the\n * server reports, which is what puts the entry in the menu.\n */\nexport function regions(options: RegionsOptions = {}): AdminModule {\n const path = options.path ?? '/regions'\n\n return {\n id: 'regions',\n blockLabels,\n path,\n routes: [\n { path, name: 'webx.regions', component: RegionsPage, props: { base: path } },\n {\n path: `${path}/:name`,\n name: 'webx.regions.edit',\n component: RegionEditorPage,\n props: { base: path },\n },\n ],\n // The part of `regions.form` that is not a field: it reads the region from the editor.\n types: {\n 'wx-region-history': { component: RegionHistory, kind: 'display' },\n },\n }\n}\n\n/**\n * What the published block types and their fields are called, for the panel's notices about\n * somebody else's edit: «Hero › Text below the button», as the constructor names it.\n */\nasync function blockLabels(admin: AdminContext): Promise<BlockLabels> {\n const types = await createBlocksApi(admin).catalog()\n const names = new Map(types.map((type) => [type.slug, type.title]))\n const fields = new Map(\n types.map((type) => [type.slug, screenLabels(type.content?.schema ?? [])] as const),\n )\n\n return {\n type: (slug) => names.get(slug) || undefined,\n field: (slug, name) => fields.get(slug)?.get(name),\n }\n}\n"],"names":["createBlocksApi","admin","base","data","body","id","input","slug","options","number","ids","slugs","query","search","file","createSiteBarBlocksApi","at","type","createRegionsApi","name","revision","blocksMessages","seeded","seedBlocksMessages","i18n","useBlocksMessages","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","mine","computed","lint","passed","codes","lines","_hoisted_2","WxIcon","_createElementVNode","_Fragment","_createTextVNode","_toDisplayString","_renderList","line","formSchema","schema","node","usageWords","count","groupLabel","key","words","kindOf","callerWords","LAYOUT","WORDS","startValues","sample","values","schemaFields","PLAIN","TAG","holdsMarkup","one","markupFields","withPlaceholders","nodes","marked","markupHelp","inline","helped","sampleWords","takesShortcodes","withShortcodes","tokens","children","strip","found","callTag","fallback","fields","attributes","variableOf","slots","head","_match","letter","resolve","dismiss","open","useModal","context","api","message","useErrorText","types","chosen","drafts","loading","exporting","ordered","all","some","toggleAll","on","toggle","versionOf","version","fileName","download","pack","url","link","run","skipped","missing","toast","onMounted","WxDialog","$event","WxSpace","WxButton","WxSkeleton","WxCheckbox","_cache","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","_hoisted_7","WxSwitch","versions","load","state","restore","confirm","block","WxDate","WxBadge","SELECTED_CLASS","HOVER_CLASS","STYLE_ID","findRange","root","findPair","findRegion","opener","walker","start","replaceBlock","doc","html","range","parent","template","anchor","done","fragment","inserted","runtime","child","UNDRAWN","blockElement","drawnElements","drawn","empty","element","rect","regionRect","top","left","right","bottom","REGION_FRAME_ID","frameRegion","box","view","highlightBlock","ensureStyle","HIDDEN_CLASS","markHidden","keys","hoverBlock","keyAt","depth","sibling","bindFrame","handlers","hovered","onClick","event","inert","onMove","onLeave","swallow","target","freezeFrame","listeners","listener","STAGE_KEY","STAGE_STYLES","fillStage","style","mountScript","script","stageDocument","escapeAttribute","frame","SHELL_PLACE","siteShell","findMarker","absolute","tag","rel","copy","inner","attribute","thumbDocument","shell","widths","width","boxWidth","useElementWidth","contentHeight","picked","fits","option","pick","scale","srcdoc","generation","loadedScript","measure","margin","binding","observer","release","fill","onLoad","Observer","now","before","onBeforeUnmount","frameStyle","clipStyle","WxSegmented","isNode","isNodeList","newKey","makeNode","locate","tree","find","list","field","index","walk","visit","countType","countInside","typesIn","seen","nestedFields","cloneNode","clone","setHidden","hidden","swapNode","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","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","declared","answer","bound","detail","info","boost","label","snippetCompletion","stack","printable","loopVariables","space","closer","escape","tail","keysOf","q","part","helper","origin","own","outer","styleClasses","blocks","stylesCompletions","statement","styled","used","templateClasses","names","prelude","char","parents","selectors","selector","NODE_KEYS","schemaCompletions","jsonContext","quoted","applyJson","entry","pos","snapshot","string","escaped","i","NAMED","GENERIC_FONTS","WIDE","FONT_KEYWORDS","NOT_PAINT","cssFindings","css","vocabulary","comment","findings","offset","declarations","colon","property","problem","subject","declaration","lineAt","reference","paint","color","whole","named","family","families","a","b","bare","allowed","item","parens","raw","p","lintBlock","content","lints","marker","undeclared","stringOnText","stray","prefix","few","withoutComments","media","tokenLints","grouped","finding","code","param","subjects","fieldIds","closure","STRING_CALLS","references","textFields","inItem","call","expression","pattern","use","joined","kind","trimmed","blocksPreviewKey","provideBlocksPreview","preview","provide","useBlocksPreview","inject","blocksTopKey","provideBlocksTop","blocksRootKey","blocksOwnerKey","blocksFragmentKey","route","useRoute","router","useRouter","usage","saving","publishing","tab","meta","module","canManage","settings","reactive","schemaText","schemaError","errors","refusal","stage","current","dirty","typeIds","schemas","loadTargets","place","assist","coreTypes","groupOptions","group","sampleModel","fieldSnippets","insertable","pill","containerFields","allowHelp","settingsOf","take","loaded","stored","onSchemaText","timer","pending","redraw","render","ticket","templateEditor","insertField","editor","save","settingsBefore","saved","publish","declaredModule","callers","isComponent","publishAsking","blockId","remove","reset","languageNotice","changes","flip","refusalError","withStage","examples","shownUsage","whereWords","hasWhere","deleteBlocked","dataInputs","shape","copyCall","errorOf","leaveGuard","kindOptions","exportType","createModal","BlockExportDialog","actions","WxCard","WxScreenHead","WxRenameButton","WxPopover","_component_router_link","entity","WxAlert","_normalizeClass","WxTabs","WxTab","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","_hoisted_20","BlockHistory","BlockStage","WxActionBar","WxEmpty","step","shells","loadShell","response","useSiteShell","adminKey","watchEffect","TALL","watcher","entries","blank","widthScale","fitted","fit","allows","allow","parentAllows","typeAllows","destinations","catalog","moving","here","trail","container","slot","title","max","allowedHere","exhausted","shown","needle","sections","order","o","section","emptyText","BlockThumb","REGION","bar","fullscreen","ready","grown","pin","page","margins","height","nextTick","bring","watch_","reveal","forget","scroller","overflow","room","band","foot","above","tall","delta","replace","refresh","onKey","__expose","WxAction","typeOf","titleOf","fieldsOf","childrenIn","flagsOf","flags","refused","limitOf","isFull","limit","actionsFor","pasteActions","clipLabel","clip","WxSortableList","_withCtx","flag","WxTooltip","WxRowMenu","_component_blocks_tree","f","n","CLIPBOARD_KEY","listening","storage","parseClip","read","listen","useBlocksClipboard","readonly","planPaste","accepted","offered","known","over","slotRules","model","_useModel","nested","screenErrorsKey","owner","topAllow","topMax","topRoot","framed","out","path","messages","dot","refusedByKey","pageRefusals","selectedKey","selected","selectedType","steps","previewEl","host","hostWidth","hasPreview","compact","sheet","sheetTitle","sideProps","groups","m","self","getCurrentInstance","translate","can","BlockPicker","set","add","parentType","duplicate","chooseDestination","BlockMoveDialog","move","without","putAside","clipNodes","copyNodes","copyBlock","skippedText","reason","paste","rules","plan","listActions","visibility","reorder","select","selectFromPreview","onValues","typeId","selectedErrors","selectedPlacement","hiddenKeys","fetchedShortcodes","shallowRef","loadShortcodes","shortcodes","formRoot","_resolveDynamicComponent","WxDrawer","_mergeProps","BlocksTree","_hoisted_8","BlocksPreview","form","slugTouched","slugify","WxRadioGroup","WxRadio","picker","rows","reading","importing","STATUS","writable","row","upToDate","choose","refusalOf","onFile","result","written","close","statusLabel","COMPONENTS","customising","create","BlockCreateDialog","exportTypes","importTypes","BlockImportDialog","components","hasComponents","moduleName","declaredBy","matches","shownComponents","shownPending","views","groupViews","componentView","componentsLabel","nothing","canDrag","droppedAt","dropped","customise","importFile","WxListScreen","WxSkeletonItem","VueDraggable","BlockCard","BlockDeclaredCard","_component_wx_alert","_component_wx_button","_component_wx_text","errorText","useSiteBar","regionsApi","sources","failed","held","refusals","picking","others","regionRefusals","busy","shaping","pageBundles","pageRegions","groupsOrder","offersRecord","offersRegions","rowsOf","onSite","onPage","changed","nestedIds","panelHref","announce","tellSitePage","readRecord","record","readRegions","regions","back","scope","hit","stopPresence","startPresence","was","highlight","togglePicking","refuse","showOnPage","caught","HttpError","conflicted","edited","placeOf","holder","placeAround","fullness","ops","addTo","after","moveBy","by","removeBlock","full","limited","below","up","down","why","regionPreview","publishRegion","discardRegion","beat","knocking","presenceUrl","knock","ping","stopListening","onSitePage","where","onKeydown","_component_wx_loading","_component_wx_result","RegionDraftNotice","_normalizeStyle","copying","choices","status","badge","editHref","canDetach","detach","regionEditorKey","provideRegionEditor","useRegionEditor","previewAt","sitePath","address","useI18n","links","createLinksApi","emptyLink","change","resolved","home","WxLinkPicker","PAUSE","region","working","reloadToken","screenKey","editing","useEditing","theirs","flight","conflict","chosenPlace","storageKey","readPlace","pickPlace","firstPlace","uses","usedOn","showOn","previewUrl","silent","schedule","onFocusOut","carried","write","sending","sent","takeTheirs","act","unpublish","discard","adopt","adopted","onBeforeRouteLeave","RegionPagePicker","WxEditingAlerts","WxScreen","WxSaveState","live","WxDrafts","shared","chips","chip","blockLabels","markRaw","BlocksSiteBarTab","BlocksPage","BlockEditorPage","BlocksField","BlockDataField","FragmentField","RegionsPage","RegionEditorPage","RegionHistory","screenLabels"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/api.ts","../src/messages.ts","../src/i18n.ts","../src/BlockDataField.vue","../src/BlockChecks.vue","../src/schema.ts","../src/BlockExportDialog.vue","../src/BlockHistory.vue","../src/frame.ts","../src/BlockStage.vue","../src/content.ts","../src/completions.ts","../src/css-tokens.ts","../src/lint.ts","../src/preview.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/clipboard.ts","../src/BlocksField.vue","../src/BlockCard.vue","../src/BlockCreateDialog.vue","../src/BlockDeclaredCard.vue","../src/BlockImportDialog.vue","../src/BlocksPage.vue","../src/RegionDraftNotice.vue","../src/BlocksSiteBarTab.vue","../src/FragmentField.vue","../src/region.ts","../src/RegionPagePicker.vue","../src/RegionEditorPage.vue","../src/RegionHistory.vue","../src/RegionsPage.vue","../src/module.ts"],"sourcesContent":["import type { AdminContext } from '@webx-ui/module-admin'\nimport type {\n BlockExport,\n BlockImportRow,\n BlockInput,\n BlockPack,\n BlockList,\n BlockType,\n BlockUsage,\n BlockVersion,\n BlockNode,\n BlockVersionMeta,\n DeclaredComponent,\n RegionAdopted,\n RegionDetail,\n RegionRow,\n RegionVersion,\n RenderInput,\n RenderResult,\n SiteBarBlockEdit,\n SiteBarBlockEdited,\n SiteBarBlocks,\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 /** `dropTranslations` agrees to keep one language where a field stops being localized. */\n publish(id: number, options?: { dropTranslations?: boolean }): Promise<BlockType>\n render(id: number, input?: RenderInput): Promise<RenderResult>\n usage(id: number): Promise<BlockUsage[]>\n /** The shared blocks a page may place, with their state; open to whoever reads the catalog. */\n fragments(): Promise<RegionRow[]>\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 /** A pack of the types named — every type when none is — and the components they call. */\n exportPack(slugs: string[], options?: { draft?: boolean }): Promise<BlockExport>\n /**\n * What the file would do (`dryRun`), or what it did. Drafts, unless `publish` is asked for.\n * The file goes as its text: the server compares it with what is stored, whitespace included.\n */\n importPack(\n file: string,\n options?: { name?: string; dryRun?: boolean; publish?: boolean },\n ): Promise<BlockImportRow[]>\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, options = {}) =>\n admin.http\n .post<{ data: BlockType }>(\n `${base}/${id}/publish`,\n options.dropTranslations ? { drop_translations: true } : {},\n )\n .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 fragments: () => admin.http.get<{ data: RegionRow[] }>(`${base}/fragments`).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 exportPack: (slugs, options = {}) => {\n const query = new URLSearchParams()\n\n for (const slug of slugs) query.append('slugs[]', slug)\n if (options.draft) query.set('draft', '1')\n\n const search = query.toString()\n\n return admin.http\n .get<{\n data: BlockPack\n skipped?: string[]\n missing?: string[]\n }>(`${base}/export${search === '' ? '' : `?${search}`}`)\n .then((body) => ({\n pack: body.data,\n skipped: body.skipped ?? [],\n missing: body.missing ?? [],\n }))\n },\n importPack: (file, options = {}) =>\n admin.http\n .post<{ data: BlockImportRow[] }>(`${base}/import`, {\n file,\n name: options.name,\n dry_run: options.dryRun === true,\n publish: options.publish === true,\n })\n .then(data),\n }\n}\n\nexport interface SiteBarBlocksApi {\n /** A record's blocks: the draft's, or the site's when there is no draft. */\n read(type: string, id: number | string): Promise<SiteBarBlocks>\n /**\n * One block's fields into the record's draft. A revision that moved is answered 409 — the\n * error's body names who moved it.\n */\n edit(type: string, id: number | string, input: SiteBarBlockEdit): Promise<SiteBarBlockEdited>\n}\n\n/** The two addresses of the «Blocks» tab of the panel on the site, by the record's address type. */\nexport function createSiteBarBlocksApi(admin: AdminContext): SiteBarBlocksApi {\n const at = (type: string, id: number | string) =>\n `${admin.apiPath}/blocks/content/${encodeURIComponent(type)}/${encodeURIComponent(String(id))}`\n\n return {\n read: (type, id) =>\n admin.http.get<{ data: SiteBarBlocks }>(at(type, id)).then((body) => body.data),\n edit: (type, id, input) =>\n admin.http\n .post<{ data: SiteBarBlockEdited }>(`${at(type, id)}/edit`, input)\n .then((body) => body.data),\n }\n}\n\nexport interface RegionsApi {\n /** Every region the site's config declares, saved or not. */\n list(): Promise<RegionRow[]>\n get(name: string): Promise<RegionDetail>\n /**\n * Save the draft. Refused with a 409 when the revision is not the current one — the error's\n * body is a {@link RegionConflict}: the region as it now is, to merge with.\n */\n save(name: string, input: { blocks: BlockNode[]; revision?: string }): Promise<RegionDetail>\n /** `revision` is what the editor held: a draft that moved on since is answered 409, not published. */\n publish(name: string, revision?: string): Promise<RegionDetail>\n /** Off the site: the code's view comes back, the blocks stay as the draft. */\n unpublish(name: string): Promise<RegionDetail>\n discardDraft(name: string): Promise<RegionDetail>\n versions(name: string): Promise<RegionVersion[]>\n /** An old publication becomes the draft; putting it on the site is a separate step. */\n restoreVersion(name: string, number: number): Promise<RegionDetail>\n /** The fallback view made into a block type, and one of it put into the draft. */\n adopt(name: string): Promise<RegionAdopted>\n /**\n * A shared block's published tree with fresh keys, to put in a page in its place. Writes nothing;\n * 409 while the shared block is not published.\n */\n copy(name: string): Promise<BlockNode[]>\n}\n\n/** Everything under `/regions`, below the panel's API path. */\nexport function createRegionsApi(admin: AdminContext): RegionsApi {\n const base = `${admin.apiPath}/regions`\n const data = <T>(body: { data: T }): T => body.data\n const at = (name: string) => `${base}/${encodeURIComponent(name)}`\n\n return {\n list: () => admin.http.get<{ data: RegionRow[] }>(base).then(data),\n get: (name) => admin.http.get<{ data: RegionDetail }>(at(name)).then(data),\n save: (name, input) => admin.http.put<{ data: RegionDetail }>(at(name), input).then(data),\n publish: (name, revision) =>\n admin.http\n .post<{ data: RegionDetail }>(`${at(name)}/publish`, revision ? { revision } : {})\n .then(data),\n unpublish: (name) =>\n admin.http.post<{ data: RegionDetail }>(`${at(name)}/unpublish`, {}).then(data),\n discardDraft: (name) =>\n admin.http.delete<{ data: RegionDetail }>(`${at(name)}/draft`).then(data),\n versions: (name) =>\n admin.http.get<{ data: RegionVersion[] }>(`${at(name)}/versions`).then(data),\n restoreVersion: (name, number) =>\n admin.http\n .post<{ data: RegionDetail }>(`${at(name)}/versions/${number}/restore`, {})\n .then(data),\n adopt: (name) =>\n admin.http\n .post<{ data: RegionDetail; block: { id: number; slug: string } }>(`${at(name)}/adopt`, {})\n .then((body) => ({ region: body.data, block: body.block })),\n copy: (name) =>\n admin.http\n .post<{ data: { blocks: BlockNode[] } }>(`${at(name)}/copy`, {})\n .then((body) => body.data.blocks),\n }\n}\n","import type { Messages } from '@webx-ui/module-admin'\n\n/**\n * The English this package speaks on its own, before the server's dictionary arrives, or\n * without one. The server ships the same lines in ten languages under `webx-blocks::` and\n * overrides these; `messages.test.ts` keeps the two sets of keys equal.\n */\nexport const blocksMessages: Record<string, Messages> = {\n module: {\n title: 'Blocks',\n regions: 'Site regions',\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 rewrites every page and region it stands on; it is refused while another template calls it.',\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':\n 'Types that can be put inside a field holding blocks that names none of its own. Empty — any type.',\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 'source-theme': 'theme',\n 'allow-help-none':\n 'The schema has no field of type wx-blocks, so the block holds nothing; this list applies once it has one.',\n 'allow-from-fields':\n 'The fields holding blocks name what they take — :fields — and that wins. This list applies to a field that names nothing.',\n renamed: 'Renamed to :slug. Pages and regions rewritten: :pages; other types: :types.',\n 'settings-saved': 'Settings saved.',\n 'drop-translations-title': 'Keep only the main language?',\n 'drop-translations-confirm': 'Keep the main language and publish',\n 'thumb-empty': 'Prints nothing on its sample: it draws only when there is data to show.',\n 'drops-translations':\n 'This version makes :fields hold one language. :count page(s) hold text in several languages there, and only the main one would be kept: :pages. Publish again agreeing to drop the other languages, or move the text first.',\n 'localized-changes':\n 'Publishing this version changes the language shape of :fields: the values already on :count page(s) will be converted.',\n 'rename-called':\n 'Other types call this one by its identifier: :types. Change their templates first, then rename it.',\n 'rename-declared': 'A module calls this component by its identifier, so it cannot be renamed.',\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 copy: 'Copy',\n 'copy-all': 'Copy all blocks',\n copied: 'Copied: :title',\n 'copied-many': 'Copied, blocks: :count',\n paste: 'Paste: :title',\n 'paste-many': 'Paste (blocks: :count)',\n 'paste-after': 'Paste after: :title',\n 'paste-after-many': 'Paste after (blocks: :count)',\n 'paste-inside': 'Paste inside: :title',\n 'paste-inside-many': 'Paste inside (blocks: :count)',\n pasted: 'Pasted, blocks: :count',\n 'paste-skipped': 'Not pasted: :list',\n 'skip-unknown': 'not available on this site',\n 'skip-place': 'not allowed here',\n 'skip-limit': 'the limit for this block is reached',\n 'skip-full': 'the list is full',\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 'markup-in-text': 'This text holds HTML tags. Change the words and leave the tags as they are.',\n shortcodes: 'Shortcodes',\n 'shortcodes-insert': 'Insert a shortcode',\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 'add-inside-full': 'Full: takes :max',\n invalid: 'Some values were not accepted',\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 region: {\n title: 'Site regions',\n intro:\n \"The parts of the layout every page shares. While a region is empty, the site shows what the site's code draws there.\",\n empty: 'No regions are declared on this site.',\n 'empty-help':\n 'A region is declared under regions in config/webx-blocks.php and printed by the layout with <x-webx-blocks::region>.',\n 'state-live': 'On the site',\n 'state-edits': 'Edits waiting',\n 'state-draft': 'Draft',\n 'state-fallback': 'Fallback from code',\n count: 'Blocks: :count',\n 'fallback-view': 'From code: :view',\n 'fallback-none': 'Nothing from code',\n 'tab-content': 'Content',\n 'tab-history': 'History',\n 'shown-on': 'Shown on',\n home: 'Home page',\n 'choose-page': 'Choose the page to look at the region on',\n 'back-home': 'Back to the home page',\n preview: 'Open the preview',\n 'empty-title': 'The site draws this region from its code',\n 'empty-text':\n 'Right now the site prints the view :view here. Add blocks and publish to replace it.',\n 'empty-text-none':\n 'Right now the site prints nothing here. Add blocks and publish to fill the region.',\n adopt: 'Move the markup into a block',\n adopted: 'Block type :slug made from the view and put into the draft.',\n save: 'Save draft',\n 'save-failed': 'The draft was not saved.',\n publish: 'Publish',\n 'publish-title': 'Put \":title\" on the site?',\n 'publish-text': \"Every page of the site shows these blocks instead of the code's view.\",\n published: 'Published.',\n unpublish: 'Take off the site',\n 'unpublish-title': 'Take \":title\" off the site?',\n 'unpublish-text':\n \"The site goes back to the code's view. The blocks stay here as a draft, and publishing brings them back.\",\n unpublished: \"Taken off the site. It shows the code's view again.\",\n discard: 'Discard draft',\n 'discard-title': 'Discard the draft of \":title\"?',\n 'discard-text': 'The edits go, and the region is again what the site shows now.',\n discarded: 'Draft discarded.',\n 'status-live': 'On the site',\n 'status-modified': 'Edits waiting',\n 'status-fallback': 'Fallback from code',\n 'conflict-title': 'The region changed while you were editing',\n 'conflict-theirs': 'Take the newer version',\n 'conflict-theirs-title': 'Give up what you wrote?',\n 'conflict-theirs-text':\n 'Your edits since the last save go, and the region is loaded as somebody else left it.',\n 'conflict-mine': 'Keep mine',\n 'leave-title': 'Leave without saving?',\n 'leave-text': 'The last edits did not reach the server and will be lost.',\n leave: 'Leave',\n cancel: 'Cancel',\n 'history-empty': 'Nothing published yet.',\n version: 'v:number',\n 'version-live': 'On the site',\n restore: 'Restore',\n 'restore-title': 'Make v:number the draft?',\n 'restore-text':\n 'The draft becomes this version. The site keeps what it shows until you publish.',\n 'restored-version': 'v:number is the draft now.',\n 'source-panel': 'From the panel',\n 'source-mcp': 'By an agent',\n 'source-import': 'Imported',\n },\n fragment: {\n choose: 'Choose a shared block',\n none: 'The site has no shared blocks yet. A developer declares one under regions in config/webx-blocks.php, with fragment set to true.',\n missing: '“:name” is not a shared block of the site any more: nothing is shown here.',\n 'status-live': 'On the site',\n 'status-edits': 'On the site, edits waiting',\n 'status-fallback': 'Not published: the site shows its fallback',\n 'status-empty': 'Empty',\n explain:\n 'This block shows a shared block of the site. Editing it changes it on every page where it stands.',\n edit: 'Edit for all pages',\n detach: 'Make it this page’s own',\n 'detach-title': 'Make “:title” this page’s own?',\n 'detach-text':\n 'Its blocks are copied into this page in its place, as they are on the site. They stop following the shared block: its edits will not reach this page any more.',\n detached: 'The blocks of “:title” are this page’s own now.',\n unpublished: 'The shared block is not published yet: there is nothing to copy.',\n 'group-layout': 'Header and footer',\n 'group-shared': 'Shared blocks',\n 'group-shared-help':\n 'Edited once here and shown wherever a page or a template of the site places them.',\n count: 'Pages: :count',\n 'used-on': 'Where it stands',\n 'used-nowhere': 'No page places it yet.',\n templates: 'Templates of the site that print it with a tag are not listed.',\n 'draft-only': 'In a draft',\n 'show-here': 'Preview on this page',\n 'publish-text': 'Every page that places it shows these blocks instead of the code’s view.',\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 'string-on-text':\n 'With a shortcode in it, :field is HTML: a string function or a cast hands that HTML to {{ }}, which escapes it a second time. Change it through wx_text(): {{ wx_text(:field)->trimEnd(\".\") }} — trim, trimStart, stripPrefix, stripSuffix and map() keep it HTML.',\n 'variables-missing':\n 'The template uses :variables, which the schema does not declare. Publishing will be refused.',\n 'marker-slug':\n 'The root is marked data-wx-block=\":marker\", but the identifier is «:slug»: the script and the panel find the block by the exact identifier. 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 syntax: 'The template does not compile: :reason. Publishing will be refused.',\n 'unknown-field-type':\n 'Fields of a type this site does not know: :fields. The form draws a warning in their place and nothing checks their values.',\n 'field-id': 'Field ids must be letters, digits, _ and -, starting with a letter: :ids.',\n 'literal-colors':\n 'Literal colours: :values. No preset and no change in tokens.json repaints them: use a colour role, var(--site-color-…).',\n 'literal-fonts':\n 'Literal font families: :values. The owner’s font never reaches them: use var(--site-font-body) or var(--site-font-heading), or a generic family.',\n 'unknown-tokens':\n 'Not among the theme’s tokens: :tokens. A variable nobody declares is an empty value — no colour, no border, no error.',\n 'token-fallbacks':\n 'A fallback inside :tokens is a literal value no preset repaints. Every token of the theme has a value: write var() without one.',\n },\n exchange: {\n export: 'Export',\n import: 'Import',\n 'export-title': 'Export blocks',\n 'import-title': 'Import blocks',\n 'export-help':\n 'Choose the types to take. The components they call come along, so the file works on another site as it is.',\n 'select-all': 'Select all',\n drafts: 'Take drafts where there are any',\n 'drafts-help':\n 'Otherwise the published version goes, and a type that was never published is left out.',\n download: 'Download',\n exported: 'Types in the file: :count',\n skipped: 'Never published, left out: :list',\n missing: 'Called, but not on this site: :list',\n nothing: 'Nothing to export: none of the chosen types is published.',\n 'export-failed': 'The export did not go through.',\n 'import-help':\n 'A file exported from this section or by the webx:blocks:export command. Types come in as drafts; a type that is already here gets a new draft version.',\n 'choose-file': 'Choose a file',\n 'other-file': 'Another file',\n publish: 'Publish what passes the checks',\n 'status-created': 'New',\n 'status-updated': 'Updated',\n 'status-unchanged': 'Unchanged',\n 'status-failed': 'Refused',\n run: 'Import',\n imported: 'Types written: :count',\n 'up-to-date': 'Everything in the file is already here; there is nothing to write.',\n 'not-json': 'This file is not JSON.',\n 'not-a-pack': 'This file is not a block type or a pack of them.',\n cycle: 'The types in the file call each other in a circle: :path.',\n 'import-failed': 'The import did not go through.',\n },\n 'site-bar': {\n tab: 'Blocks',\n pick: 'Pick a block',\n 'pick-off': 'Stop picking',\n picking: 'Click a block on the page. Esc stops.',\n hint: 'Pick a block on the page or in the list to change its fields. Changes go into the draft.',\n empty: 'This page has no blocks.',\n temporary: 'Open in panel to edit',\n hidden: 'Hidden',\n all: 'All blocks',\n save: 'Save to draft',\n saved: 'Saved to the draft',\n 'unknown-type': 'There is no form for this block: its type is not published.',\n error: 'Could not read the blocks of this page.',\n retry: 'Try again',\n conflict: 'The page changed after the form read it; the form shows what is there now.',\n 'conflict-by':\n ':name changed the page after the form read it; the form shows what is there now.',\n 'bad-op': 'This change cannot be made from the site.',\n gone: 'This block is not on the page any more.',\n others: 'Also open in the panel: :names',\n 'region-everywhere': 'On every page',\n 'fragment-where': 'Shared block: on every page where it stands',\n 'fragment-everywhere': 'A shared block: an edit here changes it on every page where it stands.',\n 'region-fallback':\n 'The site shows the markup from code here. Set the region up in the panel to edit it from the site.',\n 'open-in-panel': 'Open in panel',\n changes: 'Unpublished changes: :count',\n publish: 'Publish',\n discard: 'Discard',\n 'discard-title': 'Discard the draft of :name?',\n 'discard-text':\n 'Changes nobody has published yet are thrown away; the site keeps what it shows now.',\n cancel: 'Cancel',\n 'draft-other': ':name has a draft here; your edits go into it',\n refused: 'Not saved: what stands around this block has to be put right in the panel first.',\n 'bad-type': 'Blocks of this type cannot be added from the site.',\n 'too-deep': 'Blocks nest no deeper than this on the site. Levels at most: :max',\n add: 'Add block',\n 'add-below': 'Add below',\n 'add-inside': 'Add inside',\n duplicate: 'Duplicate',\n 'move-up': 'Move up',\n 'move-down': 'Move down',\n hide: 'Hide',\n show: 'Show',\n delete: 'Delete',\n actions: 'Block actions',\n 'at-top': 'Already first',\n 'at-bottom': 'Already last',\n full: 'No room for more blocks here. Most it takes: :count',\n limit: 'A page takes no more blocks of this type. Most: :count',\n 'delete-title': 'Delete «:title»?',\n 'delete-text':\n 'It goes from the draft with everything inside it. Visitors see it until the draft is published.',\n preview: 'Preview draft',\n },\n}\n","import { useAdmin, type I18n } from '@webx-ui/module-admin'\nimport { blocksMessages } from './messages'\n\nconst seeded = new WeakSet<object>()\n\n/**\n * Puts this package's English under a panel's dictionary, once per panel. For what runs outside\n * a component's setup — the label of a tab on the panel on the site is asked for by the frame.\n */\nexport function seedBlocksMessages(i18n: I18n): void {\n if (!seeded.has(i18n)) {\n i18n.defaults('webx-blocks', blocksMessages)\n seeded.add(i18n)\n }\n}\n\n/** Puts this package's English under the panel's dictionary, once per panel. */\nexport function useBlocksMessages(): void {\n try {\n seedBlocksMessages(useAdmin().i18n)\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","<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') && !codes.has('marker-slug')) 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","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/**\n * Fields whose sample is words somebody wrote — a heading, a caption, a picture. A block added to\n * a page starts without them: the sample is the author's example, and copied in as the block's own\n * content it went onto the site under the next autosave (\"Quote text sample\", \"John Doe\"). What\n * the other fields hold — a number, a switch, a choice from a list — is a setting, and the sample's\n * setting is as good a start as any. A chosen record is the author's too: the form of the Inbox a\n * sample names is one on the author's site, and on another one the save would refuse it.\n */\nconst WORDS = new Set([\n 'wx-input',\n 'wx-textarea',\n 'wx-rich-text',\n 'wx-tags-input',\n 'wx-autocomplete',\n 'wx-code-editor',\n 'wx-media',\n 'wx-gallery',\n 'wx-file',\n 'wx-files',\n 'wx-link',\n 'wx-repeater',\n 'wx-relations',\n 'wx-inbox-form',\n 'wx-blocks',\n])\n\n/**\n * What a block added from the picker starts with: the sample's settings, none of its words.\n *\n * @see WORDS\n */\nexport function startValues(\n schema: ScreenNode[],\n sample: Record<string, unknown>,\n): Record<string, unknown> {\n const values: Record<string, unknown> = {}\n\n for (const node of schemaFields(schema)) {\n if (WORDS.has(node.type) || !(node.id in sample)) continue\n\n const value = sample[node.id]\n\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') continue\n\n values[node.id] = value\n }\n\n return values\n}\n\n/** Plain text fields — what shows a value as it is stored, tags and all. */\nconst PLAIN = new Set(['wx-input', 'wx-textarea'])\n\n/** A tag, opening or closing: `<span>`, `</em>`, `<br/>`. A lone `<` in a sentence is not one. */\nconst TAG = /<\\/?[a-z][a-z0-9-]*(\\s[^<>]*)?\\/?>/i\n\n/**\n * Whether a value — or any language of a translated one — holds markup.\n *\n * A heading written with an accent in it (`Deeply heard<span>.</span>`) still sits in a plain\n * input in types that came before the inline rich field, and the input shows it raw: the editor\n * sees the tags and is one stray keystroke away from printing them on the site.\n */\nexport function holdsMarkup(value: unknown): boolean {\n if (typeof value === 'string') return TAG.test(value)\n\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n return Object.values(value as Record<string, unknown>).some(\n (one) => typeof one === 'string' && TAG.test(one),\n )\n }\n\n return false\n}\n\n/** The plain text fields of a block whose values hold markup, by id. */\nexport function markupFields(schema: ScreenNode[], values: Record<string, unknown>): string[] {\n return schemaFields(schema)\n .filter((node) => PLAIN.has(node.type) && holdsMarkup(values[node.id]))\n .map((node) => node.id)\n}\n\n/**\n * The form of a block, with the sample's words shown as placeholders in the empty fields that\n * take words: the editor sees what goes where without the example becoming the content.\n *\n * `marked` are plain fields whose value holds tags ({@see markupFields}); each gets `markupHelp`\n * under it unless the type already says something there. Nothing is changed in the value — the\n * tags are the author's, and the type moving the field to `wx-rich-text` with `inline` is what\n * takes them out of sight.\n */\nexport function withPlaceholders(\n nodes: ScreenNode[],\n sample: Record<string, unknown>,\n marked: string[] = [],\n markupHelp = '',\n): ScreenNode[] {\n return nodes.map((node) => {\n if (LAYOUT.has(node.type)) {\n return node.children\n ? { ...node, children: withPlaceholders(node.children, sample, marked, markupHelp) }\n : node\n }\n\n const inline = node.type === 'wx-rich-text' && node.props?.inline === true\n if (!PLAIN.has(node.type) && !inline) return node\n\n const helped =\n markupHelp !== '' && marked.includes(node.id) && node.help === undefined\n ? { ...node, help: markupHelp }\n : node\n\n if (helped.props?.placeholder !== undefined) return helped\n\n // An inline field's sample is markup itself; its placeholder is the words without it.\n const words = sampleWords(sample[node.id], inline)\n\n return words === null\n ? helped\n : { ...helped, props: { ...(helped.props ?? {}), placeholder: words } }\n })\n}\n\n/**\n * Whether the site reads shortcodes in a field's value: words a person wrote — a line, a\n * paragraph, a rich text. An input typed as an e-mail, an address or a phone is a value the site\n * prints into an attribute, and a `[phone]` there would be a broken link rather than a number.\n */\nfunction takesShortcodes(node: ScreenNode): boolean {\n if (node.type === 'wx-textarea' || node.type === 'wx-rich-text') return true\n if (node.type !== 'wx-input') return false\n\n const type = node.props?.type\n\n return type === undefined || type === 'text'\n}\n\n/**\n * The form of a block, with the site's shortcodes handed to every field the site reads them in —\n * through layout and into a repeater's items, whose children are the fields of one item. A field\n * whose type already set `tokens` keeps its own.\n *\n * Here and not in the panel's field types: the same `wx-input` is a slug or a search box on\n * other screens, and only block content is printed through the shortcodes. `words` are the\n * field's own words for them — core's defaults speak of placeholders, the panel of shortcodes.\n */\nexport function withShortcodes<T>(\n nodes: ScreenNode[],\n tokens: readonly T[],\n words: { tokensTitle?: string; tokensLabel?: string } = {},\n): ScreenNode[] {\n if (tokens.length === 0) return nodes\n\n return nodes.map((node) => {\n const children = node.children ? withShortcodes(node.children, tokens, words) : node.children\n const next = children === node.children ? node : { ...node, children }\n\n return takesShortcodes(node) && next.props?.tokens === undefined\n ? { ...next, props: { ...words, ...(next.props ?? {}), tokens } }\n : next\n })\n}\n\n/** A sample's text: itself, or the first language of a translated one. */\nfunction sampleWords(value: unknown, strip = false): string | null {\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n value = Object.values(value as Record<string, unknown>).find(\n (one) => typeof one === 'string' && one.trim() !== '',\n )\n }\n\n if (typeof value !== 'string') return null\n\n const words = strip ? value.replace(new RegExp(TAG.source, 'gi'), '') : value\n\n return words.trim() === '' ? null : words.slice(0, 160)\n}\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, '"')}\"`\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, onMounted, ref } from 'vue'\nimport { useAdmin, useErrorText, useTranslate } from '@webx-ui/module-admin'\nimport {\n toast,\n useModal,\n WxButton,\n WxCheckbox,\n WxDialog,\n WxSkeleton,\n WxSpace,\n WxSwitch,\n WxText,\n} from '@webx-ui/core'\nimport { createBlocksApi } from './api'\nimport { useBlocksMessages } from './i18n'\nimport { kindOf } from './schema'\nimport type { BlockPack, BlockType } from './types'\n\n/**\n * \"Export\" (§17.1): the types to take, ticked, and one file out — the command's documents in a\n * pack. The components the chosen types call are not offered as a choice: the server adds them,\n * because a block without them draws nothing on the site it lands on, and a person exporting a\n * block for another site would only find that out there.\n *\n * Opened from a type's editor, it comes with that type ticked: a block for the catalogue of\n * ready blocks is made one at a time.\n */\nconst props = defineProps<{ selected?: string[] }>()\n\nconst { resolve, dismiss, open } = useModal<true>()\n\nconst context = useAdmin()\nconst api = createBlocksApi(context)\nuseBlocksMessages()\n\nconst t = useTranslate('webx-blocks')\nconst message = useErrorText()\n\nconst types = ref<BlockType[]>([])\nconst chosen = ref<string[]>([...(props.selected ?? [])])\nconst drafts = ref(false)\nconst loading = ref(true)\nconst exporting = ref(false)\n\n/** Blocks first, then components, each in the list's order — the order the section shows. */\nconst ordered = computed(() => [\n ...types.value.filter((type) => kindOf(type) === 'block'),\n ...types.value.filter((type) => kindOf(type) === 'component'),\n])\n\nconst all = computed(\n () => ordered.value.length > 0 && ordered.value.every((type) => chosen.value.includes(type.slug)),\n)\nconst some = computed(() => chosen.value.length > 0 && !all.value)\n\nfunction toggleAll(on: boolean): void {\n chosen.value = on ? ordered.value.map((type) => type.slug) : []\n}\n\nfunction toggle(slug: string, on: boolean): void {\n chosen.value = on ? [...chosen.value, slug] : chosen.value.filter((one) => one !== slug)\n}\n\n/** What a type would give: the published version, or the draft only when drafts are asked for. */\nfunction versionOf(type: BlockType): string {\n const version = drafts.value ? (type.draft ?? type.published) : type.published\n\n return version === null ? t('page.never-published') : `v${version.number}`\n}\n\n/** One type's file is named after it; several are named after the day they left. */\nfunction fileName(): string {\n if (chosen.value.length === 1) return `${chosen.value[0]}.blocks.json`\n\n return `blocks-${new Date().toISOString().slice(0, 10)}.json`\n}\n\nfunction download(pack: BlockPack, name: string): void {\n const url = URL.createObjectURL(\n new Blob([`${JSON.stringify(pack, null, 2)}\\n`], { type: 'application/json' }),\n )\n const link = document.createElement('a')\n\n link.href = url\n link.download = name\n link.click()\n // After the click has been handled: revoking first would hand the browser a dead address.\n setTimeout(() => URL.revokeObjectURL(url), 0)\n}\n\nasync function run(): Promise<void> {\n exporting.value = true\n\n try {\n const { pack, skipped, missing } = await api.exportPack(chosen.value, { draft: drafts.value })\n\n if (pack.blocks.length === 0) {\n toast.warning(t('exchange.nothing'))\n\n return\n }\n\n download(pack, fileName())\n toast.success(t('exchange.exported', { count: pack.blocks.length }))\n\n if (skipped.length > 0) toast.warning(t('exchange.skipped', { list: skipped.join(', ') }))\n if (missing.length > 0) toast.warning(t('exchange.missing', { list: missing.join(', ') }))\n\n resolve(true)\n } catch (error) {\n toast.danger(message(error, t('exchange.export-failed')))\n } finally {\n exporting.value = false\n }\n}\n\nonMounted(async () => {\n try {\n types.value = await api.list()\n // A type that was never published has nothing to give but its draft: opened on one, the\n // switch starts on, or the file would come out empty.\n drafts.value = types.value.some(\n (type) => chosen.value.includes(type.slug) && type.published === null,\n )\n } catch (error) {\n toast.danger(message(error))\n } finally {\n loading.value = false\n }\n})\n</script>\n\n<template>\n <wx-dialog v-model:open=\"open\" :title=\"t('exchange.export-title')\" :width=\"560\">\n <div class=\"wx-block-export\">\n <wx-text tone=\"muted\" size=\"sm\">{{ t('exchange.export-help') }}</wx-text>\n\n <wx-skeleton v-if=\"loading\" :rows=\"5\" />\n\n <template v-else>\n <wx-checkbox\n :model-value=\"all\"\n :indeterminate=\"some\"\n :label=\"t('exchange.select-all')\"\n class=\"wx-block-export__all\"\n @update:model-value=\"toggleAll(Boolean($event))\"\n />\n\n <ul class=\"wx-block-export__list\">\n <li v-for=\"type in ordered\" :key=\"type.id\" class=\"wx-block-export__row\">\n <!-- The checkbox is the row: its own label stretches across it, the version included,\n so a click anywhere ticks it — a label around the checkbox's label would not. -->\n <wx-checkbox\n :model-value=\"chosen.includes(type.slug)\"\n class=\"wx-block-export__check\"\n @update:model-value=\"toggle(type.slug, Boolean($event))\"\n >\n <span class=\"wx-block-export__type\">\n <span class=\"wx-block-export__title\">{{ type.title }}</span>\n <span class=\"wx-block-export__meta\">\n {{ type.slug }}\n <template v-if=\"kindOf(type) === 'component'\">\n · {{ t('components.kind-component') }}</template\n >\n </span>\n </span>\n <span class=\"wx-block-export__version\">{{ versionOf(type) }}</span>\n </wx-checkbox>\n </li>\n </ul>\n\n <div class=\"wx-block-export__drafts\">\n <wx-switch v-model=\"drafts\" :label=\"t('exchange.drafts')\" />\n <wx-text tone=\"muted\" size=\"sm\">{{ t('exchange.drafts-help') }}</wx-text>\n </div>\n </template>\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\n type=\"primary\"\n icon=\"download\"\n :loading=\"exporting\"\n :disabled=\"chosen.length === 0\"\n @click=\"run\"\n >\n {{ t('exchange.download') }}\n </wx-button>\n </wx-space>\n </template>\n </wx-dialog>\n</template>\n\n<style scoped>\n.wx-block-export {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-12);\n}\n\n.wx-block-export__list {\n display: flex;\n flex-direction: column;\n max-height: 320px;\n margin: 0;\n padding: 0;\n overflow-y: auto;\n list-style: none;\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n}\n\n.wx-block-export__check {\n display: flex;\n width: 100%;\n box-sizing: border-box;\n padding: var(--wx-space-8) var(--wx-space-12);\n}\n\n.wx-block-export__check :deep(.wx-checkbox__label) {\n display: flex;\n flex: 1;\n align-items: center;\n justify-content: space-between;\n gap: var(--wx-space-12);\n min-width: 0;\n}\n\n.wx-block-export__row + .wx-block-export__row {\n border-top: 1px solid var(--wx-border-default);\n}\n\n.wx-block-export__title {\n margin-right: var(--wx-space-6);\n}\n\n.wx-block-export__meta,\n.wx-block-export__version {\n font-size: var(--wx-font-size-xs);\n color: var(--wx-text-muted);\n}\n\n.wx-block-export__version {\n flex-shrink: 0;\n}\n\n.wx-block-export__drafts {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-4);\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 return findPair(root, `wx:${key}`)\n}\n\n/**\n * The pair around a region — `<!--wx-region:name-->` — which the region's own preview prints\n * whatever the region holds, its fallback included.\n */\nexport function findRegion(root: Node, name: string): MarkerRange | null {\n return findPair(root, `wx-region:${name}`)\n}\n\nfunction findPair(root: Node, opener: 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 === opener) {\n start = node as Comment\n } else if (start !== null && text === `/${opener}`) {\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/**\n * What a block prints that is never drawn. A block holding a shared block starts with the\n * region's stylesheet, printed in place — and a `<link>` taken for the block was a box of nothing\n * at the top of the page: the outline went nowhere and the preview never scrolled to it.\n */\nconst UNDRAWN = new Set(['link', 'style', 'script', 'template', 'meta', 'noscript'])\n\n/**\n * The element a block is pointed at by — the outline, the scroll: the first one it prints that\n * takes room on the page. One that draws nothing at all, or where the layout cannot be measured,\n * gives the first it prints that could.\n */\nexport function blockElement(root: Node, key: string): Element | null {\n const range = findRange(root, key)\n\n return range ? (drawnElements(range)[0] ?? null) : null\n}\n\n/** Elements between a pair of markers that could be drawn, the ones that are drawn first. */\nfunction drawnElements(range: MarkerRange): Element[] {\n const drawn: Element[] = []\n const empty: Element[] = []\n\n for (let node = range.start.nextSibling; node && node !== range.end; node = node.nextSibling) {\n if (node.nodeType !== 1) continue\n\n const element = node as Element\n\n if (UNDRAWN.has(element.tagName.toLowerCase())) continue\n\n const rect = element.getBoundingClientRect()\n\n ;(rect.width > 0 || rect.height > 0 ? drawn : empty).push(element)\n }\n\n return [...drawn, ...empty]\n}\n\n/**\n * Where a region stands on the page: one box around everything it printed, in the page's own\n * coordinates. Null when the page does not print it, or it printed nothing that takes room.\n */\nexport function regionRect(\n doc: Document,\n name: string,\n): { top: number; left: number; width: number; height: number } | null {\n const range = findRegion(doc, name)\n\n if (!range) return null\n\n let top = Infinity\n let left = Infinity\n let right = -Infinity\n let bottom = -Infinity\n\n for (const element of drawnElements(range)) {\n const rect = element.getBoundingClientRect()\n\n if (rect.width === 0 && rect.height === 0) continue\n\n top = Math.min(top, rect.top)\n left = Math.min(left, rect.left)\n right = Math.max(right, rect.right)\n bottom = Math.max(bottom, rect.bottom)\n }\n\n return top === Infinity ? null : { top, left, width: right - left, height: bottom - top }\n}\n\nexport const REGION_FRAME_ID = 'wx-preview-region'\n\n/**\n * Draw a frame around a region of the page, or take it away (null).\n *\n * A box laid over the page rather than a class on an element, as a block has: a region is any\n * number of blocks side by side, and wrapping them in an element of ours would break the site's\n * own rules — `.site-main > section` stops matching the moment there is a `div` in between.\n * Hangs off the root element and not the body, which a site may have positioned: there its top\n * is the page's top, whatever the body's margins.\n */\nexport function frameRegion(doc: Document, name: string | null): void {\n const rect = name === null ? null : regionRect(doc, name)\n let box = doc.getElementById(REGION_FRAME_ID)\n\n if (rect === null) {\n box?.remove()\n\n return\n }\n\n if (box === null) {\n box = doc.createElement('div')\n box.id = REGION_FRAME_ID\n box.setAttribute('aria-hidden', 'true')\n doc.documentElement.appendChild(box)\n }\n\n const view = doc.defaultView\n const top = rect.top + (view?.scrollY ?? 0)\n const left = rect.left + (view?.scrollX ?? 0)\n\n box.style.cssText =\n `position:absolute;top:${top}px;left:${left}px;width:${rect.width}px;height:${rect.height}px;` +\n // The selected block's outline, so the two read as one family: what is being edited.\n 'outline:2px solid #427edd;outline-offset:-2px;pointer-events:none;z-index:2147483646;margin:0;'\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\nexport const HIDDEN_CLASS = 'wx-preview-hidden'\n\n/**\n * Mark the blocks switched off. The page drawn under the preview token leaves a hidden block out,\n * but one hidden after the page was drawn is still in the frame until it reloads — and it looked\n * exactly like the blocks that will be on the site.\n */\nexport function markHidden(doc: Document, keys: string[]): void {\n ensureStyle(doc)\n\n for (const element of Array.from(doc.querySelectorAll(`.${HIDDEN_CLASS}`))) {\n element.classList.remove(HIDDEN_CLASS)\n }\n\n for (const key of keys) {\n blockElement(doc, key)?.classList.add(HIDDEN_CLASS)\n }\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/** What the widgets of a drawn block load: tags for `<head>` and for the end of `<body>`. */\nexport interface BlockAssets {\n head: string[]\n body: string[]\n}\n\n/**\n * Put what a block's widgets load into a page printed before the block was there — the\n * stylesheet and the script of a map, the dialog of a form it opens. The server gathers them\n * as it does for a whole page; a page gets each of them once, so what the page already has\n * (the same address, the same id, the same inline style) is skipped.\n *\n * A stylesheet goes beside the widgets' stylesheets the page has, where the server puts them:\n * under every theme layer, which restyles a widget by coming later. A script is made anew,\n * since one parsed from markup never runs.\n */\nexport function addAssets(doc: Document, assets: BlockAssets | null | undefined): void {\n if (!assets) return\n\n for (const element of assets.head.flatMap((tag) => parseTags(doc, tag))) {\n if (!present(doc, element)) addToHead(doc, element)\n }\n\n for (const element of assets.body.flatMap((tag) => parseTags(doc, tag))) {\n if (!present(doc, element)) doc.body.appendChild(live(doc, element))\n }\n}\n\nfunction parseTags(doc: Document, tag: string): Element[] {\n const template = doc.createElement('template')\n template.innerHTML = tag\n\n return Array.from(template.content.children)\n}\n\nfunction absolute(doc: Document, value: string): string {\n try {\n return new URL(value, doc.baseURI).href\n } catch {\n return value\n }\n}\n\nfunction present(doc: Document, element: Element): boolean {\n if (element.id && doc.getElementById(element.id)) return true\n\n const tag = element.tagName.toLowerCase()\n const address = element.getAttribute(tag === 'link' ? 'href' : 'src')\n\n if ((tag === 'link' || tag === 'script') && address) {\n const href = absolute(doc, address)\n const attribute = tag === 'link' ? 'href' : 'src'\n\n return Array.from(doc.querySelectorAll(`${tag}[${attribute}]`)).some(\n (other) => absolute(doc, other.getAttribute(attribute) ?? '') === href,\n )\n }\n\n if (tag === 'style') {\n return Array.from(doc.querySelectorAll('style')).some(\n (other) => other.textContent === element.textContent,\n )\n }\n\n return false\n}\n\nfunction addToHead(doc: Document, element: Element): void {\n const head = doc.head ?? doc.documentElement\n const href = element.getAttribute('href')\n\n if (element.tagName.toLowerCase() === 'link' && href) {\n const folder = absolute(doc, href).replace(/[^/]*$/, '')\n const siblings = Array.from(head.querySelectorAll('link[rel=\"stylesheet\"][href]')).filter(\n (other) => absolute(doc, other.getAttribute('href') ?? '').startsWith(folder),\n )\n const last = siblings[siblings.length - 1]\n\n if (last) {\n last.after(live(doc, element))\n\n return\n }\n\n // No widget's stylesheet on the page: the first in the cascade, as the server would put it.\n const first = head.querySelector('link[rel=\"stylesheet\"], style')\n\n if (first) {\n head.insertBefore(live(doc, element), first)\n\n return\n }\n }\n\n head.appendChild(live(doc, element))\n}\n\nfunction live(doc: Document, element: Element): Element {\n if (element.tagName.toLowerCase() !== 'script') return doc.importNode(element, true)\n\n const script = doc.createElement('script')\n\n for (const attribute of Array.from(element.attributes)) {\n script.setAttribute(attribute.name, attribute.value)\n }\n\n script.textContent = element.textContent\n\n return script\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 // Dimmed and greyed, not removed: it is still the block an editor clicks to switch back on.\n `.${HIDDEN_CLASS}{opacity:.35;filter:grayscale(1);outline:1px dashed #8a8f98;outline-offset:-1px;}`\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 /** What the block's widgets load. */\n assets?: BlockAssets | 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 const head = input.assets?.head.join('') ?? ''\n const tail = input.assets?.body.join('') ?? ''\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>${head}${frame}<style>${input.styles}</style></head>` +\n `<body>${input.html}${runtime}${tail}</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, '&').replace(/\"/g, '"').replace(/</g, '<')\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 {\n addAssets,\n fillStage,\n freezeFrame,\n mountScript,\n stageDocument,\n type BlockAssets,\n type FrameBinding,\n} 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 /** What the widgets in the block load: a map's stylesheet and script. */\n assets?: BlockAssets | 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, assets: 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 assets: props.assets,\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 addAssets(doc, props.assets)\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, props.assets] 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/**\n * One block taken out and others put where it stood, in its list — what «Make it this page's own»\n * does to a shared block. The tree as it was when the key is not in it.\n */\nexport function swapNode(tree: BlockNode[], key: string, nodes: BlockNode[]): 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, ...clone(nodes))\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 tariffs: [\n 'name',\n 'badge',\n 'price',\n 'amount',\n 'currency',\n 'symbol',\n 'period',\n 'price_text',\n 'features',\n 'description',\n 'button',\n 'featured',\n 'service_links',\n 'fields',\n ],\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: 'default', value: '', info: 'Shown and read until the field is set.' },\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","/**\n * CSS knows only tokens (THEMES §8) — the theme engine's `Checks\\CssCheck`, rule for rule, for\n * the editor's live lints. Not a parser: a walk over braces and semicolons that knows strings,\n * comments and parentheses.\n *\n * Unlike the engine it has no `media-width`: the editor's `media-query` says it of any `@media`.\n */\n\nexport type CssProblem = 'literal-color' | 'literal-font' | 'unknown-token' | 'token-fallback'\n\nexport interface CssFinding {\n problem: CssProblem\n line: number\n subject: string\n}\n\n/** CSS Color 4 — every named colour a browser paints. */\nconst NAMED = [\n 'aliceblue',\n 'antiquewhite',\n 'aqua',\n 'aquamarine',\n 'azure',\n 'beige',\n 'bisque',\n 'black',\n 'blanchedalmond',\n 'blue',\n 'blueviolet',\n 'brown',\n 'burlywood',\n 'cadetblue',\n 'chartreuse',\n 'chocolate',\n 'coral',\n 'cornflowerblue',\n 'cornsilk',\n 'crimson',\n 'cyan',\n 'darkblue',\n 'darkcyan',\n 'darkgoldenrod',\n 'darkgray',\n 'darkgreen',\n 'darkgrey',\n 'darkkhaki',\n 'darkmagenta',\n 'darkolivegreen',\n 'darkorange',\n 'darkorchid',\n 'darkred',\n 'darksalmon',\n 'darkseagreen',\n 'darkslateblue',\n 'darkslategray',\n 'darkslategrey',\n 'darkturquoise',\n 'darkviolet',\n 'deeppink',\n 'deepskyblue',\n 'dimgray',\n 'dimgrey',\n 'dodgerblue',\n 'firebrick',\n 'floralwhite',\n 'forestgreen',\n 'fuchsia',\n 'gainsboro',\n 'ghostwhite',\n 'gold',\n 'goldenrod',\n 'gray',\n 'green',\n 'greenyellow',\n 'grey',\n 'honeydew',\n 'hotpink',\n 'indianred',\n 'indigo',\n 'ivory',\n 'khaki',\n 'lavender',\n 'lavenderblush',\n 'lawngreen',\n 'lemonchiffon',\n 'lightblue',\n 'lightcoral',\n 'lightcyan',\n 'lightgoldenrodyellow',\n 'lightgray',\n 'lightgreen',\n 'lightgrey',\n 'lightpink',\n 'lightsalmon',\n 'lightseagreen',\n 'lightskyblue',\n 'lightslategray',\n 'lightslategrey',\n 'lightsteelblue',\n 'lightyellow',\n 'lime',\n 'limegreen',\n 'linen',\n 'magenta',\n 'maroon',\n 'mediumaquamarine',\n 'mediumblue',\n 'mediumorchid',\n 'mediumpurple',\n 'mediumseagreen',\n 'mediumslateblue',\n 'mediumspringgreen',\n 'mediumturquoise',\n 'mediumvioletred',\n 'midnightblue',\n 'mintcream',\n 'mistyrose',\n 'moccasin',\n 'navajowhite',\n 'navy',\n 'oldlace',\n 'olive',\n 'olivedrab',\n 'orange',\n 'orangered',\n 'orchid',\n 'palegoldenrod',\n 'palegreen',\n 'paleturquoise',\n 'palevioletred',\n 'papayawhip',\n 'peachpuff',\n 'peru',\n 'pink',\n 'plum',\n 'powderblue',\n 'purple',\n 'rebeccapurple',\n 'red',\n 'rosybrown',\n 'royalblue',\n 'saddlebrown',\n 'salmon',\n 'sandybrown',\n 'seagreen',\n 'seashell',\n 'sienna',\n 'silver',\n 'skyblue',\n 'slateblue',\n 'slategray',\n 'slategrey',\n 'snow',\n 'springgreen',\n 'steelblue',\n 'tan',\n 'teal',\n 'thistle',\n 'tomato',\n 'turquoise',\n 'violet',\n 'wheat',\n 'white',\n 'whitesmoke',\n 'yellow',\n 'yellowgreen',\n].join('|')\n\nconst GENERIC_FONTS = [\n 'serif',\n 'sans-serif',\n 'monospace',\n 'cursive',\n 'fantasy',\n 'system-ui',\n 'ui-serif',\n 'ui-sans-serif',\n 'ui-monospace',\n 'ui-rounded',\n 'math',\n 'emoji',\n 'fangsong',\n]\n\nconst WIDE = ['inherit', 'initial', 'unset', 'revert', 'revert-layer']\n\nconst FONT_KEYWORDS = [\n 'normal',\n 'italic',\n 'oblique',\n 'bold',\n 'bolder',\n 'lighter',\n 'small-caps',\n 'ultra-condensed',\n 'extra-condensed',\n 'condensed',\n 'semi-condensed',\n 'semi-expanded',\n 'expanded',\n 'extra-expanded',\n 'ultra-expanded',\n 'xx-small',\n 'x-small',\n 'small',\n 'medium',\n 'large',\n 'x-large',\n 'xx-large',\n 'xxx-large',\n 'smaller',\n 'larger',\n 'caption',\n 'icon',\n 'menu',\n 'message-box',\n 'small-caption',\n 'status-bar',\n]\n\n/** Properties whose values are names, not paint: an animation called `fade`, a grid area `aside`. */\nconst NOT_PAINT =\n /^(?:font|font-[a-z-]+|transition(?:-[a-z-]+)?|animation(?:-[a-z-]+)?|grid(?:-[a-z-]+)?|will-change|content|counter-[a-z-]+|quotes|container(?:-[a-z-]+)?|view-transition-name|list-style-type)$/\n\n/**\n * @param tokens The chain's vocabulary, names without `--site-`.\n */\nexport function cssFindings(css: string, tokens: Iterable<string>): CssFinding[] {\n const vocabulary = new Set(tokens)\n const source = css.replace(/\\/\\*[\\s\\S]*?\\*\\//g, (comment) => comment.replace(/[^\\n]/g, ' '))\n const findings: CssFinding[] = []\n\n for (const [text, offset, inside] of declarations(source)) {\n if (/^@(?:font-face|property)\\b/i.test(inside)) continue\n\n const colon = text.indexOf(':')\n const property = text.slice(0, colon).trim().toLowerCase()\n const start = offset + colon + 1\n\n for (const [problem, at, subject] of declaration(property, text.slice(colon + 1), vocabulary)) {\n findings.push({ problem, line: lineAt(source, start + at), subject })\n }\n }\n\n return findings\n}\n\nfunction declaration(\n property: string,\n value: string,\n vocabulary: Set<string>,\n): [CssProblem, number, string][] {\n const found: [CssProblem, number, string][] = []\n\n for (const reference of value.matchAll(/var\\(\\s*--([A-Za-z0-9_-]+)\\s*([,)])/g)) {\n const name = reference[1]!\n\n // A block's own variable — `var(--team-columns, 3)` — keeps its default.\n if (!name.startsWith('site-')) continue\n\n if (!vocabulary.has(name.slice(5))) found.push(['unknown-token', reference.index, `--${name}`])\n if (reference[2] === ',') found.push(['token-fallback', reference.index, `var(--${name}, …)`])\n }\n\n const paint = value.replace(\n /\"(?:[^\"\\\\]|\\\\.)*\"|'(?:[^'\\\\]|\\\\.)*'|url\\([^)]*\\)|--[A-Za-z0-9_-]+/gi,\n (match) => ' '.repeat(match.length),\n )\n\n for (const color of paint.matchAll(\n /(?<![\\w&-])#[0-9a-f]{3,8}(?![\\w-])|(?<![\\w-])(?:rgba?|hsla?|hwb|lab|lch|oklab|oklch|color)\\(/gi,\n )) {\n found.push(['literal-color', color.index, color[0].endsWith('(') ? `${color[0]}…)` : color[0]])\n }\n\n if (property.startsWith('--')) {\n const whole = new RegExp(`^(\\\\s*)(${NAMED})\\\\s*(?:!important\\\\s*)?$`, 'i').exec(paint)\n if (whole) found.push(['literal-color', whole[1]!.length, whole[2]!])\n } else if (!NOT_PAINT.test(property)) {\n for (const named of paint.matchAll(new RegExp(`(?<![\\\\w-])(${NAMED})(?![\\\\w-])`, 'gi'))) {\n found.push(['literal-color', named.index, named[1]!])\n }\n }\n\n if (property === 'font-family' || property === 'font') {\n for (const [family, at] of families(property, value)) found.push(['literal-font', at, family])\n }\n\n return found.sort((a, b) => a[1] - b[1])\n}\n\nfunction families(property: string, value: string): [string, number][] {\n const bare = value.replace(/var\\([^()]*(?:\\([^()]*\\)[^()]*)*\\)|!important/gi, (match) =>\n ' '.repeat(match.length),\n )\n let allowed = [...GENERIC_FONTS, ...WIDE]\n const found: [string, number][] = []\n\n if (property === 'font-family') {\n for (const item of bare.matchAll(/[^,]+/g)) {\n const family = item[0].trim()\n\n if (family !== '' && !allowed.includes(family.toLowerCase())) {\n found.push([family, item.index + item[0].indexOf(family[0]!)])\n }\n }\n\n return found\n }\n\n // The shorthand: keywords and families share the line; `Open Sans` is two unknown words in a row.\n allowed = [...allowed, ...FONT_KEYWORDS]\n let end: number | null = null\n\n for (const word of bare.matchAll(/\"[^\"]*\"|'[^']*'|(?<![\\w.%#-])[A-Za-z_-][A-Za-z0-9_-]*/g)) {\n const quoted = word[0][0] === '\"' || word[0][0] === \"'\"\n\n if (!quoted && allowed.includes(word[0].toLowerCase())) {\n end = null\n continue\n }\n\n if (!quoted && end !== null && bare.slice(end, word.index).trim() === '') {\n found[found.length - 1]![0] += ` ${word[0]}`\n } else {\n found.push([word[0], word.index])\n }\n\n end = quoted ? null : word.index + word[0].length\n }\n\n return found\n}\n\n/** Declarations — what a `;` or a `}` closes inside a block — with their offset and the at-rule they stand in. */\nfunction declarations(source: string): [string, number, string][] {\n const found: [string, number, string][] = []\n const stack: string[] = []\n let start = 0\n let quote: string | null = null\n let parens = 0\n\n for (let i = 0; i < source.length; i++) {\n const char = source[i]!\n\n if (quote !== null) {\n if (char === '\\\\') i++\n else if (char === quote) quote = null\n continue\n }\n\n if (char === '\"' || char === \"'\") quote = char\n else if (char === '(') parens++\n else if (char === ')') parens = Math.max(0, parens - 1)\n else if (parens === 0 && (char === '{' || char === ';' || char === '}')) {\n const raw = source.slice(start, i)\n const text = raw.trim()\n const offset = start + (raw.length - raw.trimStart().length)\n\n if (char === '{') {\n stack.push(text)\n } else if (stack.length > 0 && text !== '' && !text.startsWith('@') && text.includes(':')) {\n found.push([text, offset, [...stack].reverse().find((p) => p.startsWith('@')) ?? ''])\n }\n\n if (char === '}') stack.pop()\n\n start = i + 1\n }\n }\n\n return found\n}\n\nfunction lineAt(source: string, offset: number): number {\n return source.slice(0, Math.max(0, offset)).split('\\n').length\n}\n","import type { ScreenNode } from '@webx-ui/schema'\nimport { cssFindings, type CssProblem } from './css-tokens'\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 * On a site with a theme, the styles also know only its tokens (`tokenLints`).\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 tokens: string[] | null = null,\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 // The runtime and the panel match the marker to the slug exactly; «Quote» on `quote` never ran.\n const marker = /data-wx-block\\s*=\\s*([\"'])([^\"']*)\\1/.exec(content.template)?.[2]\n\n if (marker !== undefined && !marker.includes('{{') && marker !== slug) {\n lints.push({\n file: 'template',\n code: 'marker-slug',\n line: null,\n message: t('checks.marker-slug', { marker, slug }),\n })\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 for (const [field, line] of stringOnText(content.template, content.schema)) {\n lints.push({\n file: 'template',\n code: 'string-on-text',\n line,\n message: t('checks.string-on-text', { field }),\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, ...tokenLints(content.styles, tokens, t)]\n}\n\n/**\n * CSS knows only tokens (THEMES §8), as warnings: a literal colour or font, a `--site-*` the\n * theme does not have, a fallback inside one — one line per kind, on the first place it stands.\n * Only on a site with a theme (`tokens` is its vocabulary, null without one). `Lints::tokens()`.\n */\nexport function tokenLints(styles: string, tokens: string[] | null, t: Translate): Lint[] {\n if (tokens === null || styles.trim() === '') return []\n\n const codes: Record<CssProblem, [string, 'values' | 'tokens']> = {\n 'literal-color': ['literal-colors', 'values'],\n 'literal-font': ['literal-fonts', 'values'],\n 'unknown-token': ['unknown-tokens', 'tokens'],\n 'token-fallback': ['token-fallbacks', 'tokens'],\n }\n const grouped = new Map<CssProblem, [string, number][]>()\n\n for (const finding of cssFindings(styles, tokens)) {\n grouped.set(finding.problem, [\n ...(grouped.get(finding.problem) ?? []),\n [finding.subject, finding.line],\n ])\n }\n\n const lints: Lint[] = []\n\n for (const [problem, [code, param]] of Object.entries(codes) as [\n CssProblem,\n [string, 'values' | 'tokens'],\n ][]) {\n const subjects = grouped.get(problem)\n\n if (subjects) {\n lints.push({\n file: 'styles',\n code,\n line: subjects[0]![1],\n message: t(`checks.${code}`, { [param]: few(subjects) }),\n })\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 // A closure's parameters and what it `use`s are its own: `wx_text($lead)->map(fn ($text) => …)`.\n for (const closure of template.matchAll(/(?:fn|function)\\s*\\(([^)]*)\\)/g)) {\n for (const name of closure[1]!.matchAll(/\\$([a-zA-Z_]\\w*)/g)) declared.add(name[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\n/**\n * Calls that make a string of what they are given — a field with a shortcode becomes its HTML,\n * which `{{ }}` then escapes again. `STRING_CALLS` in `Panel\\Lints`.\n */\nconst STRING_CALLS =\n 'trim|rtrim|ltrim|chop|strtoupper|strtolower|ucfirst|lcfirst|ucwords|mb_strtoupper|mb_strtolower|mb_convert_case|mb_substr|mb_strimwidth|substr|str_replace|str_ireplace|preg_replace|preg_replace_callback|sprintf|vsprintf|strip_tags|nl2br|wordwrap|str_pad|strrev|html_entity_decode|htmlspecialchars|e|str|Str::\\\\w+'\n\n/**\n * Text fields a template turns into a string and prints with `{{ }}`: `{{ rtrim($heading, '.') }}`\n * prints `Call <a href=…` once the heading holds `[phone]`. `wx_text()` is the fix, and an\n * echo that goes through it is not counted; nor is `$heading->plain()`, which is text.\n */\nexport function stringOnText(template: string, schema: ScreenNode[]): [string, number][] {\n const references = textFields(schema).map(([name, inItem]) => {\n const quoted = name.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n\n return inItem\n ? new RegExp(`\\\\$\\\\w+\\\\[\\\\s*['\"]${quoted}['\"]\\\\s*\\\\](?!\\\\s*->)`, 'g')\n : new RegExp(`\\\\$${quoted}\\\\b(?!\\\\s*(?:->|\\\\[|\\\\())`, 'g')\n })\n\n if (references.length === 0) return []\n\n const found = new Map<string, number>()\n const call = new RegExp(`(?<![\\\\w$>:])(?:${STRING_CALLS})\\\\s*\\\\(|\\\\(\\\\s*string\\\\s*\\\\)`, 'i')\n\n for (const echo of template.matchAll(/(?<!@)\\{\\{(?!--)([\\s\\S]*?)\\}\\}/g)) {\n const expression = echo[1]!\n const offset = echo.index + 2\n\n if (expression.includes('wx_text(')) continue\n\n const start = call.exec(expression)?.index ?? null\n\n for (const pattern of references) {\n for (const use of expression.matchAll(pattern)) {\n const at = use.index\n // Joined with `.` is the same string as a cast.\n const joined =\n /(?<!\\.)\\.\\s*$/.test(expression.slice(0, at)) ||\n /^\\s*\\.(?![.=\\d])/.test(expression.slice(at + use[0].length))\n\n if (((start !== null && at > start) || joined) && !found.has(use[0])) {\n found.set(use[0], lineAt(template, offset + at))\n }\n }\n }\n }\n\n return [...found]\n}\n\n/** The text fields the renderer resolves shortcodes in, and whether each is a repeater item's. */\nfunction textFields(nodes: ScreenNode[], inItem = false): [string, boolean][] {\n const fields: [string, boolean][] = []\n\n for (const node of nodes) {\n const key = node.id ?? node.name\n const kind = node.props?.type ?? 'text'\n const text =\n node.type === 'wx-textarea' ||\n (node.type === 'wx-input' && (kind === 'text' || kind === 'search'))\n\n if (text && typeof key === 'string' && /^[A-Za-z_]\\w*$/.test(key)) {\n fields.push([key, inItem])\n continue\n }\n\n if (node.children) {\n fields.push(...textFields(node.children, inItem || node.type === 'wx-repeater'))\n }\n }\n\n return fields\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 { BlockNode, 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 * What the top level of the constructor is, when it is not a page.\n *\n * A layout region is edited with the same `wx-blocks` field as a page, from a screen described\n * once for every region — so what differs between `header` and `footer` (the name types list in\n * `allowed_in`, and the region's own `allow` and `max` from the site's config) cannot be written\n * into the description. The editor hosting the screen provides it instead, the way it provides\n * the preview.\n */\nexport interface BlocksTop {\n /** The name of the top level in `allowed_in` — `region:header`. */\n root: string\n /** What \"Move to\" calls the top level — the region's title rather than \"The page\". */\n label?: string\n /** What may stand 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 region the preview frames and scrolls to: a shared block, which stands wherever a page\n * put it. A header needs neither — it is at the top of every page.\n */\n frame?: string | null\n}\n\nexport const blocksTopKey: InjectionKey<Readonly<Ref<BlocksTop | null>>> = Symbol('wx-blocks-top')\n\n/** Called by the hosting screen, above the `wx-blocks` field. */\nexport function provideBlocksTop(top: Readonly<Ref<BlocksTop | null>>): void {\n provide(blocksTopKey, top)\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\n/**\n * What a «Shared block» form needs of the constructor it is open in, and a field drawn by the\n * renderer cannot reach otherwise: which block it is, and the way to put others in its place.\n */\nexport interface BlocksFragmentHost {\n /** The key of the block whose form is open — the one a field in that form belongs to. */\n selected: Readonly<Ref<string | null>>\n /** The shared block this constructor edits, when it edits one: never offered inside itself. */\n own: Readonly<Ref<string | null>>\n /**\n * Put these blocks where the block with this key stands, and open the first of them. Whether it\n * was done — the panel on the site writes it to the draft first, and the draft may refuse.\n */\n detach(key: string, nodes: BlockNode[]): boolean | Promise<boolean>\n}\n\nexport const blocksFragmentKey: InjectionKey<BlocksFragmentHost> = Symbol('wx-blocks-fragment')\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 createModal,\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 BlockExportDialog from './BlockExportDialog.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 RenderResult,\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 assets: null as RenderResult['assets'],\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, block.value?.tokens ?? null))\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\n/**\n * What \"Insert a field\" offers: the fields a template can read, as the snippet that reads them.\n *\n * Through layout (cards, tabs, rows) and not into a field: a repeater's children are keys of its\n * rows, not variables, so the repeater is offered as a loop over them; a container is offered as\n * `@blocks('…')`, which is how its blocks are printed. A heading, a note or a divider in the form\n * holds no value and is not offered at all.\n */\nconst fieldSnippets = computed(() => insertable(content.schema))\n\nfunction insertable(nodes: BlockContent['schema']): { id: string; label: string; text: string }[] {\n const found: { id: string; label: string; text: string }[] = []\n\n for (const node of nodes) {\n if (LAYOUT.includes(node.type)) {\n found.push(...insertable(node.children ?? []))\n continue\n }\n\n if (!node.id) continue\n\n if (node.type === 'wx-blocks') {\n found.push({ id: node.id, label: `@blocks('${node.id}')`, text: `@blocks('${node.id}')` })\n } else if (node.type === 'wx-repeater') {\n const keys = (node.children ?? []).filter((child) => child.id && !LAYOUT.includes(child.type))\n const inner = keys.map((child) => `{{ $item['${child.id}'] }}`).join(' ')\n\n found.push({\n id: node.id,\n label: `@foreach ($${node.id} …)`,\n text: `@foreach ($${node.id} ?? [] as $item)\\n ${inner}\\n@endforeach`,\n })\n } else {\n found.push({ id: node.id, label: pill(node.id), text: pill(node.id) })\n }\n }\n\n return found\n}\n\n/** The schema types that arrange or explain fields and hold no value — `Schema::LAYOUT` on the server. */\nconst LAYOUT = [\n 'wx-card',\n 'wx-tabs',\n 'wx-tab',\n 'wx-row',\n 'wx-col',\n 'wx-divider',\n 'wx-heading',\n 'wx-text',\n 'wx-alert',\n]\n\n/**\n * The containers of the schema and what each takes of its own: the settings' \"May hold\" applies\n * to a field that names nothing, and says so when every field names its own.\n */\nconst containerFields = computed(() =>\n schemaFields(content.schema)\n .filter((node) => node.type === 'wx-blocks')\n .map((node) => ({\n id: node.id,\n allow: Array.isArray(node.props?.allow) ? (node.props.allow as string[]) : null,\n })),\n)\n\nconst allowHelp = computed(() => {\n const fields = containerFields.value\n\n if (fields.length === 0) return t('page.allow-help-none')\n\n const own = fields.filter((field) => field.allow !== null)\n\n if (own.length === 0) return t('page.allow-help')\n\n return t('page.allow-from-fields', {\n fields: own.map((field) => `${field.id}: ${field.allow!.join(', ') || '—'}`).join('; '),\n })\n})\n\n/** The row's own settings as a type carries them — what decides whether a save changed any. */\nfunction settingsOf(type: BlockType): Record<string, unknown> {\n return {\n kind: kindOf(type),\n slug: type.slug,\n title: type.title,\n description: type.description,\n icon: type.icon,\n group: type.group,\n sort: type.sort,\n allow: type.allow,\n allowed_in: type.allowed_in,\n max_per_entity: type.max_per_entity,\n is_enabled: type.is_enabled,\n }\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.assets = drawn.assets ?? null\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/** A field's snippet at the caret of the template editor. */\nfunction insertField(text: 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 += text\n\n return\n }\n\n editor.dispatch(editor.state.replaceSelection(text))\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 const settingsBefore = JSON.stringify(settingsOf(block.value))\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 // Three different outcomes, three different sentences: a rename (and what it rewrote), a new\n // version, settings alone. \"Nothing changed\" was said after a rename that rewrote every page.\n if (saved.renamed) {\n toast.success(\n t('page.renamed', {\n slug: saved.renamed.to,\n pages: saved.renamed.entities,\n types: saved.renamed.types,\n }),\n )\n } else if (saved.draft && saved.draft.number !== before) {\n toast.success(t('page.saved', { number: saved.draft.number }))\n } else if (JSON.stringify(settingsOf(saved)) !== settingsBefore) {\n toast.success(t('page.settings-saved'))\n } else {\n toast.success(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 publishAsking(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?.translations) {\n // Asked and declined: nothing was published, and nothing more to say.\n return\n }\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\n/**\n * Publish, and when the draft takes `localized` off a field over pages holding several languages,\n * ask whether to keep only the main one — the server refuses with 409 and the pages, and the same\n * request goes again with the answer.\n */\nasync function publishAsking(blockId: number): Promise<BlockType> {\n try {\n return await api.publish(blockId)\n } catch (error) {\n const body = (error as { status?: number; body?: PublishRefusal }).body\n\n if (!body?.translations) throw error\n\n const agreed = await confirm({\n title: t('page.drop-translations-title'),\n message: body.message,\n confirmText: t('page.drop-translations-confirm'),\n cancelText: t('page.cancel'),\n tone: 'danger',\n })\n\n if (!agreed) throw error\n\n return api.publish(blockId, { dropTranslations: true })\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 languageNotice = computed(() => {\n const changes = block.value?.language_changes\n\n if (!changes || changes.flips.length === 0) return null\n\n return t('page.localized-changes', {\n fields: changes.flips\n .map((flip) => (flip.child ? `${flip.field}.*.${flip.child}` : flip.field))\n .join(', '),\n count: changes.entities.length,\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 exportType = createModal<true, { selected?: string[] }>(BlockExportDialog)\n\n/*\n * Export stands here as well as on the list: a block for the catalogue of ready blocks is made\n * and taken one at a time, from the screen it was made on. What is saved goes, not the edits.\n */\nconst actions = computed<ScreenAction[]>(() => [\n ...(block.value\n ? [\n {\n key: 'export',\n label: t('exchange.export'),\n icon: 'download',\n run: () => void exportType({ selected: [block.value!.slug] }),\n },\n ]\n : []),\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 <!-- Said before anybody presses Publish: the draft changes the shape of values already on\n pages, and publishing converts them. -->\n <wx-alert v-if=\"languageNotice\" type=\"warning\" variant=\"soft\" :description=\"languageNotice\" />\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=\"fieldSnippets.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 fieldSnippets\"\n :key=\"field.id\"\n type=\"button\"\n class=\"wx-block-editor__pill\"\n :disabled=\"!canManage\"\n @click=\"insertField(field.text)\"\n v-text=\"field.label\"\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=\"allowHelp\"\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 :assets=\"stage.assets\"\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, onMounted, ref } from 'vue'\nimport { useTranslate } from '@webx-ui/module-admin'\nimport { useElementWidth, WxIcon, WxText } 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 t = useTranslate('webx-blocks')\n\nconst box = ref<HTMLElement | null>(null)\nconst boxWidth = useElementWidth(box)\n\n/*\n * Drawn once it is near the screen, and never taken down again. Every frame loads the site's\n * stylesheet and its fonts, and the list of a site with forty types built forty of them at once —\n * most of them below the fold, all of them competing with the one being looked at.\n */\nconst seen = ref(typeof IntersectionObserver === 'undefined')\nlet watcher: IntersectionObserver | null = null\n\nonMounted(() => {\n if (seen.value || !box.value) return\n\n watcher = new IntersectionObserver(\n (entries) => {\n if (entries.some((entry) => entry.isIntersecting)) {\n seen.value = true\n watcher?.disconnect()\n watcher = null\n }\n },\n { rootMargin: '200px' },\n )\n watcher.observe(box.value)\n})\n\n/** Drawn, and nothing came out: a block that prints only with data to print. */\nconst blank = computed(() => props.thumbnail?.empty === true)\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(() => {\n observer?.disconnect()\n watcher?.disconnect()\n})\n</script>\n\n<template>\n <div ref=\"box\" class=\"wx-block-thumb\" :style=\"{ height: `${height}px` }\">\n <div v-if=\"blank\" class=\"wx-block-thumb__empty is-blank\">\n <wx-icon name=\"grid\" />\n <wx-text size=\"xs\" tone=\"muted\">{{ t('page.thumb-empty') }}</wx-text>\n </div>\n <iframe\n v-else-if=\"thumbnail && seen\"\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-if=\"!thumbnail\" 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\n.wx-block-thumb__empty.is-blank {\n place-content: center;\n gap: var(--wx-space-4);\n padding: var(--wx-space-8);\n text-align: center;\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(\n type: BlockType,\n parent: BlockType | null,\n allow: string[] | null,\n root = 'root',\n): 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 * What the top level is called in `allowed_in`: `root` for a page, `region:<name>` for a\n * layout region — a type made for the header must not be offered in the middle of an article.\n */\n root?: string\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, top.root)) {\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 /** What the top level is called in `allowed_in`: a page, or a layout region. */\n root?: string\n }>(),\n {\n parent: null,\n allow: null,\n tree: () => [],\n groups: () => [],\n blocksPath: null,\n root: 'root',\n },\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, props.root)\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 {\n addAssets,\n bindFrame,\n blockElement,\n frameRegion,\n highlightBlock,\n markHidden,\n regionRect,\n replaceBlock,\n type BlockAssets,\n type FrameBinding,\n} 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 /** Keys of the blocks switched off: marked in the page until it reloads without them. */\n hidden?: string[]\n /**\n * A region to frame and scroll to: a shared block, which is wherever the page placed it and\n * not where a header always is — down the page under the content, more often than not.\n */\n region?: string | null\n }>(),\n { selected: null, reload: 0, compact: false, hidden: () => [], region: null },\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 /* The page moved under the frame drawn around the region — laid over it, not inside it — and\n a width that changed moves it as surely as a height. */\n if (props.region) frameRegion(page, props.region)\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 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 markHidden(page, props.hidden)\n frameRegion(page, props.region)\n reveal(props.selected ?? (props.region ? REGION : null))\n\n /* Measured after the ask, not before: the frame grows to its page on the next tick, and only an\n ask already pending is asked again then. Before, a block or a region further down than the\n window-high frame reached scrolled only as far as that frame let it — and stayed there. */\n watch_(page)\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/* What `pending` holds for the region rather than a block: no key of a block looks like it. */\nconst REGION = '\\u0000region'\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(rect: { top: number; height: number }): { top: number; height: number } | null {\n const box = frame.value?.getBoundingClientRect()\n\n if (!box) return null\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 target =\n pending === REGION\n ? props.region\n ? regionRect(page, props.region)\n : null\n : (blockElement(page, pending)?.getBoundingClientRect() ?? null)\n const at = target ? place(target) : 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/**\n * Swap one block's markup in place, with what its widgets load; false when the page has to be\n * reloaded instead.\n */\nfunction replace(key: string, html: string, assets?: BlockAssets | null): boolean {\n const page = doc()\n\n if (!page || !ready.value) return false\n\n const done = replaceBlock(page, key, html)\n if (done) {\n addAssets(page, assets)\n highlightBlock(page, props.selected ?? null)\n markHidden(page, props.hidden)\n frameRegion(page, props.region)\n }\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.hidden,\n (keys) => {\n const page = doc()\n\n if (page && ready.value) markHidden(page, keys)\n },\n)\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, WxTooltip } 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 /** What the last save was refused for, by block key. */\n errors?: Record<string, string[]>\n /** What \"Copy\" put aside, for the paste lines; null while there is nothing. */\n clip?: BlockNode[] | null\n }>(),\n {\n parentKey: null,\n field: null,\n fieldNode: null,\n max: null,\n selected: null,\n disabled: false,\n depth: 0,\n errors: () => ({}),\n clip: null,\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 copy: [key: string]\n /** The clip into this list or a container's field, at `index` or at the end. */\n paste: [parentKey: string | null, field: string | null, node: ScreenNode | null, index?: number]\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\ninterface Flag {\n key: string\n icon: string\n tone: 'danger' | 'warning' | null\n text: string\n}\n\n/**\n * The marks beside a block's name, each with the words it stands for: refused on the last save,\n * a type nobody has, a type with an unpublished version or hidden from editors, a block switched\n * off. The hidden one is always there, not only on hover: the actions beside it are invisible at\n * rest, and a row that is merely dimmer than its neighbours is not a statement.\n */\nfunction flagsOf(node: BlockNode): Flag[] {\n const flags: Flag[] = []\n const refused = props.errors[node.key]\n const type = typeOf(node)\n\n if (refused?.length) {\n flags.push({ key: 'invalid', icon: 'warning', tone: 'danger', text: refused.join(' ') })\n }\n\n if (!type) {\n flags.push({\n key: 'unknown',\n icon: 'close-circle',\n tone: 'danger',\n text: t('field.unknown-type', { type: node.type }),\n })\n } else if (type.draft) {\n flags.push({ key: 'draft', icon: 'warning', tone: 'warning', text: t('field.draft-type') })\n } else if (type.is_enabled === false) {\n // Not the eye: that one means this block is off, which is a different thing from its type\n // being withdrawn from the catalogue.\n flags.push({ key: 'disabled', icon: 'lock', tone: null, text: t('field.disabled-type') })\n }\n\n if (node.hidden === true) {\n flags.push({ key: 'hidden', icon: 'eye-off', tone: null, text: t('field.hidden-note') })\n }\n\n return flags\n}\n\n/** How many blocks a container's field takes, or null for no limit. */\nfunction limitOf(field: ScreenNode): number | null {\n const max = field.props?.max\n\n return typeof max === 'number' ? max : null\n}\n\n/** A field that holds as many blocks as it takes: \"Add inside\" says so instead of doing nothing. */\nfunction isFull(node: BlockNode, field: ScreenNode): boolean {\n const limit = limitOf(field)\n\n return limit !== null && childrenIn(node, field).length >= limit\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 /* Copy is for another page or section; duplicate stays for this one, being one click. */\n {\n key: 'copy',\n icon: 'clipboard',\n label: t('field.copy'),\n run: () => emit('copy', node.key),\n },\n ...pasteActions(node, index, limit),\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\n/** What the clip is, in the words of a menu line: the block's name, or how many. */\nfunction clipLabel(prefix: 'paste-after' | 'paste-inside'): string {\n const clip = props.clip ?? []\n\n return clip.length === 1\n ? t(`field.${prefix}`, { title: titleOf(clip[0]!) })\n : t(`field.${prefix}-many`, { count: clip.length })\n}\n\n/**\n * Paste after this row, and — on a container — into each of its fields, which is the only way\n * into one that is still empty. Only while there is something to paste: a line that can only\n * say \"nothing copied\" is a line to read past every time.\n */\nfunction pasteActions(node: BlockNode, index: number, limit: number | null): RowAction[] {\n if (!props.clip?.length) return []\n\n const slots = fieldsOf(node)\n\n return [\n {\n key: 'paste-after',\n icon: 'clipboard-paste',\n label: clipLabel('paste-after'),\n disabled: limit !== null && props.nodes.length >= limit,\n run: () => emit('paste', props.parentKey, props.field, props.fieldNode, index + 1),\n },\n ...slots.map((slot) => ({\n key: `paste-inside-${slot.id}`,\n icon: 'clipboard-paste',\n label:\n slots.length > 1\n ? `${clipLabel('paste-inside')} · ${slot.label ?? slot.id}`\n : clipLabel('paste-inside'),\n disabled: isFull(node, slot),\n run: () => emit('paste', node.key, slot.id, slot),\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=\"{\n 'is-selected': selected === item.key,\n 'is-hidden': item.hidden === true,\n 'is-invalid': (errors[item.key]?.length ?? 0) > 0,\n }\"\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 <!-- The panel's own tooltip, not the browser's `title`: the same tip, delay and look as\n every other icon of the panel, and one a finger on a phone can open. -->\n <wx-tooltip v-for=\"flag in flagsOf(item)\" :key=\"flag.key\" :content=\"flag.text\">\n <span\n class=\"wx-blocks-tree__flag\"\n :class=\"flag.tone ? `is-${flag.tone}` : undefined\"\n role=\"img\"\n tabindex=\"0\"\n :aria-label=\"flag.text\"\n >\n <wx-icon :name=\"flag.icon\" />\n </span>\n </wx-tooltip>\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 :errors=\"errors\"\n :clip=\"clip\"\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 @copy=\"emit('copy', $event)\"\n @paste=\"(p, f, n, i) => emit('paste', p, f, n, i)\"\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 <!-- A full container says so, the way \"Move to\" marks one: a button that did nothing\n on a click was a button that looked broken. -->\n <button\n v-if=\"!disabled\"\n type=\"button\"\n class=\"wx-blocks-tree__add is-inner\"\n :disabled=\"isFull(item, slot)\"\n @click=\"emit('add', item.key, slot.id, slot)\"\n >\n <template v-if=\"isFull(item, slot)\">{{\n t('field.add-inside-full', { max: limitOf(slot)! })\n }}</template>\n <template v-else>+ {{ t('field.add-inside') }}</template>\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:not(:disabled) {\n color: var(--wx-color-primary);\n border-color: var(--wx-color-primary);\n background: var(--wx-color-primary-soft);\n}\n\n.wx-blocks-tree__add:disabled {\n cursor: not-allowed;\n border-style: solid;\n border-color: var(--wx-border-default);\n}\n\n/* A block a save was refused for: the row says so before anybody opens it. */\n.wx-blocks-tree__row.is-invalid {\n border-color: var(--wx-color-danger);\n}\n</style>\n","import { readonly, ref, type Ref } from 'vue'\nimport type { ScreenNode } from '@webx-ui/schema'\nimport { cloneNode, countType, walk } from './content'\nimport { allows } from './move'\nimport { kindOf } from './schema'\nimport type { BlockNode, BlockType } from './types'\n\n/**\n * Copy and paste of blocks, across pages and across modules of the same panel.\n *\n * The clipboard is the browser's storage rather than the system one: a block is not text, the\n * system clipboard asks for permission to be read, and what is copied here is only ever pasted\n * into a constructor of the same site — every module stores the same `{ key, type, values }`.\n * One entry, kept after a paste, so the same block can go onto several pages; every tab sees\n * what another one copied.\n */\n\nexport const CLIPBOARD_KEY = 'wx-blocks-clipboard'\n\nexport interface BlocksClip {\n format: 'webx-blocks-clip'\n /** Bumped when the shape changes; a clip of another version is treated as empty. */\n format_version: 1\n copied_at: string\n nodes: BlockNode[]\n}\n\nconst clip = ref<BlocksClip | null>(null)\nlet listening = false\n\n/** Storage that may be missing or refuse: a private window, blocked site data, a test. */\nfunction storage(): Storage | null {\n try {\n return typeof window === 'undefined' ? null : window.localStorage\n } catch {\n return null\n }\n}\n\n/** What is stored, if it is a clip this code understands — anything else is no clip at all. */\nexport function parseClip(raw: string | null): BlocksClip | null {\n if (!raw) return null\n\n try {\n const value = JSON.parse(raw) as Partial<BlocksClip> | null\n\n if (\n value?.format !== 'webx-blocks-clip' ||\n value.format_version !== 1 ||\n !Array.isArray(value.nodes) ||\n value.nodes.length === 0\n ) {\n return null\n }\n\n return value as BlocksClip\n } catch {\n return null\n }\n}\n\nfunction read(): BlocksClip | null {\n try {\n return parseClip(storage()?.getItem(CLIPBOARD_KEY) ?? null)\n } catch {\n return null\n }\n}\n\n/* One listener for the whole page, never removed: the clip is one value for every field on it. */\nfunction listen(): void {\n if (listening || typeof window === 'undefined') return\n\n listening = true\n clip.value = read()\n window.addEventListener('storage', (event) => {\n if (event.key === CLIPBOARD_KEY || event.key === null) clip.value = read()\n })\n}\n\nexport function useBlocksClipboard(): {\n clip: Readonly<Ref<BlocksClip | null>>\n copy: (nodes: BlockNode[]) => void\n clear: () => void\n} {\n listen()\n\n return {\n clip: readonly(clip) as Readonly<Ref<BlocksClip | null>>,\n copy(nodes) {\n const next: BlocksClip = {\n format: 'webx-blocks-clip',\n format_version: 1,\n copied_at: new Date().toISOString(),\n nodes: JSON.parse(JSON.stringify(nodes)) as BlockNode[],\n }\n\n clip.value = next\n\n try {\n storage()?.setItem(CLIPBOARD_KEY, JSON.stringify(next))\n } catch {\n // Full or refused: the clip still works in this tab, which is most of what it is for.\n }\n },\n clear() {\n clip.value = null\n\n try {\n storage()?.removeItem(CLIPBOARD_KEY)\n } catch {\n // Nothing to do: there was nothing it could have kept either.\n }\n },\n }\n}\n\n/** Why a block of the clip did not go in. */\nexport type SkipReason = 'unknown' | 'place' | 'limit' | 'full'\n\n/** The list a paste goes into, and the rules that list stands under. */\nexport interface PasteTarget {\n /** The whole tree of the page, for the per-page limits of the types. */\n tree: BlockNode[]\n /** The list itself — the tree, or a container's field. */\n list: BlockNode[]\n /** The container's type, or the top level's owner (a block's sample form), or null. */\n parent: BlockType | null\n allow: string[] | null\n max: number | null\n /** What the list is called in `allowed_in`; only the top level is ever anything but `root`. */\n root: string\n}\n\nexport interface PastePlan {\n /** Fresh copies, keys renewed all the way down, in the clip's order. */\n accepted: BlockNode[]\n skipped: { node: BlockNode; reason: SkipReason }[]\n}\n\n/**\n * What of the clip may go into this list, judged by the same rules the picker and \"Move to\"\n * go by, so a paste never puts down what adding by hand would not.\n *\n * Block by block rather than all or nothing: a page copied whole into a region that takes half\n * of it gets that half, and the rest is named. A block whose type — or the type of anything\n * inside it — this site does not offer is left out whole: half a section is not that section.\n */\nexport function planPaste(\n nodes: BlockNode[],\n target: PasteTarget,\n catalog: BlockType[],\n): PastePlan {\n const accepted: BlockNode[] = []\n const skipped: PastePlan['skipped'] = []\n const offered = (slug: string) =>\n catalog.find(\n (type) =>\n type.slug === slug &&\n kindOf(type) !== 'component' &&\n type.is_enabled &&\n type.published !== null,\n ) ?? null\n\n for (const node of nodes) {\n const type = offered(node.type)\n let known = type !== null\n\n walk([node], (inner) => {\n if (!catalog.some((entry) => entry.slug === inner.type)) known = false\n })\n\n if (!type || !known) {\n skipped.push({ node, reason: 'unknown' })\n continue\n }\n\n if (!allows(type, target.parent, target.allow, target.root)) {\n skipped.push({ node, reason: 'place' })\n continue\n }\n\n if (target.max !== null && target.list.length + accepted.length >= target.max) {\n skipped.push({ node, reason: 'full' })\n continue\n }\n\n const page = [...target.tree, ...accepted]\n let over = false\n\n walk([node], (inner) => {\n const limit = catalog.find((entry) => entry.slug === inner.type)?.max_per_entity ?? null\n\n if (limit !== null && countType(page, inner.type) + countType([node], inner.type) > limit) {\n over = true\n }\n })\n\n if (over) {\n skipped.push({ node, reason: 'limit' })\n continue\n }\n\n accepted.push(cloneNode(node))\n }\n\n return { accepted, skipped }\n}\n\n/** A container field's own rules, read off its node in the type's schema. */\nexport function slotRules(slot: ScreenNode | null): { allow: string[] | null; max: number | null } {\n return {\n allow: (slot?.props?.allow as string[] | undefined) ?? null,\n max: (slot?.props?.max as number | undefined) ?? null,\n }\n}\n","<script setup lang=\"ts\">\nimport {\n computed,\n getCurrentInstance,\n inject,\n onBeforeUnmount,\n onMounted,\n provide,\n ref,\n shallowRef,\n watch,\n} from 'vue'\nimport {\n adminKey,\n loadShortcodes,\n useErrorText,\n useTranslate,\n WxRowMenu,\n type AdminContext,\n type RowAction,\n type ShortcodeToken,\n} 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 screenErrorsKey,\n WxScreenRenderer,\n type RenderContext,\n type ScreenNode,\n type TypeRegistry,\n type ValidationErrors,\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 { planPaste, slotRules, useBlocksClipboard, type PastePlan } from './clipboard'\nimport {\n cloneNode,\n countInside,\n insertNode,\n locate,\n makeNode,\n removeNode,\n replaceList,\n setHidden,\n swapNode,\n updateValues,\n walk,\n} from './content'\nimport { useBlocksMessages } from './i18n'\nimport {\n blocksFragmentKey,\n blocksOwnerKey,\n blocksPreviewKey,\n blocksRootKey,\n blocksTopKey,\n} from './preview'\nimport { destinations, type Destination } from './move'\nimport { formSchema, markupFields, startValues, withPlaceholders, withShortcodes } 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 * The site's shortcodes, offered in the text fields of a block. Fetched from the panel when\n * absent, like the catalog.\n */\n shortcodes?: ShortcodeToken[] | null\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 shortcodes: null,\n },\n)\n\nconst model = defineModel<BlockNode[]>({ default: () => [] })\n\nconst nested = inject(blocksRootKey, false)\n/* The refusal of the last save of the screen this field stands on: `blocks.<key>.<field>`. */\nconst refusal = inject(screenErrorsKey, null)\n/* Inside the block editor's sample form, the top level is that block rather than a page. */\nconst owner = inject(blocksOwnerKey, null)\n/* In a layout region's editor, the top level is that region rather than a page. */\nconst top = inject(blocksTopKey, null)\nprovide(blocksTopKey, ref(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\n/* The field's own props win: a screen that narrows the top level has said so on purpose. */\nconst topAllow = computed(() => props.allow ?? top?.value?.allow ?? null)\nconst topMax = computed(() => props.max ?? top?.value?.max ?? null)\nconst topRoot = computed(() => top?.value?.root ?? 'root')\n/* The region the preview frames, when the screen above says which. */\nconst framed = computed(() => top?.value?.frame ?? null)\n\nconst tree = computed<BlockNode[]>(() => (Array.isArray(model.value) ? model.value : []))\n\n/**\n * The refusal, by block: key → field → messages. The server names a value by the block's key and\n * the field (`blocks.k1.title`), and a block standing where it may not by the key alone\n * (`blocks.k1`, under `''`). A limit of the whole page names the type (`blocks.hero`) — kept\n * under that, for the list above the tree.\n */\nconst refused = computed<Record<string, Record<string, string[]>>>(() => {\n const errors: ValidationErrors | undefined = refusal?.value\n const prefix = `${props.name ?? 'blocks'}.`\n const out: Record<string, Record<string, string[]>> = {}\n\n for (const [path, messages] of Object.entries(errors ?? {})) {\n if (!path.startsWith(prefix)) continue\n\n const rest = path.slice(prefix.length)\n const dot = rest.indexOf('.')\n const key = dot === -1 ? rest : rest.slice(0, dot)\n const field = dot === -1 ? '' : rest.slice(dot + 1)\n\n out[key] = { ...(out[key] ?? {}), [field]: messages }\n }\n\n return out\n})\n\n/** What the tree marks: every message of a block, in one list. */\nconst refusedByKey = computed<Record<string, string[]>>(() => {\n const out: Record<string, string[]> = {}\n\n for (const [key, fields] of Object.entries(refused.value)) {\n out[key] = Object.values(fields).flat()\n }\n\n return out\n})\n\n/** A refusal that names no block on the page — a limit of the whole page, by type. */\nconst pageRefusals = computed(() =>\n Object.entries(refusedByKey.value)\n .filter(([key]) => locate(tree.value, key) === null)\n .flatMap(([, messages]) => messages),\n)\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 root: 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 ? topAllow.value : ((slot?.props?.allow as string[] | undefined) ?? null)\n const max = parentKey === null ? topMax.value : ((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 // Only the top level is the region; a container's field is named by its own type.\n root: parentKey === null ? topRoot.value : 'root',\n })\n\n if (!type) return\n\n const node = makeNode(\n type.slug,\n startValues(type.content?.schema ?? [], type.content?.sample ?? {}),\n )\n set(insertNode(tree.value, parentKey, field, index ?? list.length, node))\n selectedKey.value = node.key\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\n/*\n * What a «Shared block» form asks of the constructor: the copies of the shared block put where it\n * stood, the first of them opened — what was there a moment ago is still what is on screen. Nothing\n * else changes: the page's draft takes them the ordinary way, autosave and history included.\n */\nprovide(blocksFragmentKey, {\n selected: selectedKey,\n own: computed(() =>\n topRoot.value.startsWith('region:') ? topRoot.value.slice('region:'.length) : null,\n ),\n detach(key: string, nodes: BlockNode[]): boolean {\n if (!locate(tree.value, key)) return false\n\n set(swapNode(tree.value, key, nodes))\n selectedKey.value = nodes[0]?.key ?? null\n\n return true\n },\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: topAllow.value,\n max: topMax.value,\n root: topRoot.value,\n }),\n topLabel: owner?.value?.title ?? top?.value?.label ?? 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\nconst { clip, copy: putAside } = useBlocksClipboard()\n\n/** The clip's blocks, for the tree's paste lines. */\nconst clipNodes = computed(() => clip.value?.nodes ?? null)\n\n/** One block, or the whole page; the toast names what went, so a click is seen to have worked. */\nfunction copyNodes(nodes: BlockNode[]): void {\n if (nodes.length === 0) return\n\n putAside(nodes)\n toast.success(\n nodes.length === 1\n ? t('field.copied', { title: titleOf(nodes[0]!) })\n : t('field.copied-many', { count: nodes.length }),\n )\n}\n\nfunction copyBlock(key: string): void {\n const found = locate(tree.value, key)\n if (found) copyNodes([found.node])\n}\n\n/** What did not go in and why, one name to a reason. */\nfunction skippedText(skipped: PastePlan['skipped']): string {\n return skipped\n .map(({ node, reason }) => `${titleOf(node)} (${t(`field.skip-${reason}`)})`)\n .join(', ')\n}\n\n/**\n * The clip into a list: the page, or a container's field, at `index` or at the end.\n *\n * Fresh keys all the way down, as for a duplicate: the same block twice on one page would be one\n * block to the preview's markers and to the refusals of a save. Only what this list may hold\n * goes in, by the picker's rules; the rest is named rather than dropped in silence. Nothing is\n * opened afterwards — a paste is often several blocks, and the tree is where they are seen.\n */\nfunction paste(\n parentKey: string | null,\n field: string | null,\n slot: ScreenNode | null,\n index?: number,\n): void {\n const nodes = clip.value?.nodes\n if (!nodes?.length) return\n\n const parent = parentKey ? locate(tree.value, parentKey) : null\n const list =\n parentKey === null\n ? tree.value\n : parent && field\n ? ((parent.node.values[field] as BlockNode[] | undefined) ?? [])\n : []\n const rules = parentKey === null ? { allow: topAllow.value, max: topMax.value } : slotRules(slot)\n\n const plan = planPaste(\n nodes,\n {\n tree: tree.value,\n list,\n parent: parent\n ? (catalog.value.find((type) => type.slug === parent.node.type) ?? null)\n : (owner?.value ?? null),\n allow: rules.allow,\n max: rules.max,\n root: parentKey === null ? topRoot.value : 'root',\n },\n catalog.value,\n )\n\n let next = tree.value\n let at = index ?? list.length\n\n for (const node of plan.accepted) {\n next = insertNode(next, parentKey, field, at++, node)\n }\n\n if (plan.accepted.length) set(next)\n\n if (plan.skipped.length) {\n toast.warning(t('field.paste-skipped', { list: skippedText(plan.skipped) }))\n } else {\n toast.success(t('field.pasted', { count: plan.accepted.length }))\n }\n}\n\n/** The list's own lines: the whole page into the clip, and the clip onto the end of the page. */\nconst listActions = computed<RowAction[]>(() => {\n const actions: RowAction[] = [\n {\n key: 'copy-all',\n icon: 'clipboard',\n label: t('field.copy-all'),\n disabled: tree.value.length === 0,\n run: () => copyNodes(tree.value),\n },\n ]\n const nodes = clip.value?.nodes ?? []\n\n if (!props.disabled && nodes.length) {\n actions.push({\n key: 'paste',\n icon: 'clipboard-paste',\n label:\n nodes.length === 1\n ? t('field.paste', { title: titleOf(nodes[0]!) })\n : t('field.paste-many', { count: nodes.length }),\n disabled: topMax.value !== null && tree.value.length >= topMax.value,\n run: () => paste(null, null, null),\n })\n }\n\n return actions\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, drawn.assets)) previewEl.value?.refresh()\n })\n .catch(() => {})\n }, 300)\n },\n { deep: true },\n)\n\n/*\n * A save refused for a block's value opens that block, so the field with the message is on\n * screen: the tree marks it, but a form that is not open shows nothing under any field.\n */\nwatch(refusedByKey, (now) => {\n const keys = Object.keys(now).filter((key) => locate(tree.value, key) !== null)\n\n if (keys.length === 0 || (selectedKey.value !== null && keys.includes(selectedKey.value))) return\n\n selectedKey.value = keys[0]!\n})\n\n/** The open block's refusal, under the names its form's fields answer to. */\nconst selectedErrors = computed<ValidationErrors | undefined>(() => {\n const fields = selectedKey.value ? refused.value[selectedKey.value] : undefined\n\n if (!fields) return undefined\n\n const out: ValidationErrors = {}\n\n for (const [field, messages] of Object.entries(fields)) {\n if (field !== '') out[field] = messages\n }\n\n return out\n})\n\n/** What the open block was refused for as a whole — where it stands, not a value. */\nconst selectedPlacement = computed(() =>\n selectedKey.value ? (refused.value[selectedKey.value]?.[''] ?? []) : [],\n)\n\n/** Keys of the blocks switched off, for the preview to mark until it reloads without them. */\nconst hiddenKeys = computed(() => {\n const keys: string[] = []\n\n walk(tree.value, (node) => {\n if (node.hidden === true) keys.push(node.key)\n })\n\n return keys\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\n/*\n * Plain fields whose value holds tags, read once per block opened rather than on every keystroke:\n * the help under a field coming and going while somebody types into it would rebuild the form\n * under their caret.\n */\nconst marked = ref<string[]>([])\n\nwatch(\n [selectedKey, selectedType],\n () => {\n const schema = selectedType.value?.content?.schema\n marked.value =\n schema && selected.value ? markupFields(schema, selected.value.node.values ?? {}) : []\n },\n { immediate: true },\n)\n\n/*\n * The shortcodes of the site, for the text fields of the open block. Asked of the panel only\n * when a block is drawn here at all — a nested instance is a note — and once per panel, however\n * many blocks and pages are opened. They come late, and the fields take them when they do.\n */\nconst fetchedShortcodes = shallowRef<ShortcodeToken[]>([])\n\nif (admin && !nested && props.shortcodes === null) {\n void loadShortcodes(admin).then((list) => (fetchedShortcodes.value = list))\n}\n\nconst shortcodes = computed(() => props.shortcodes ?? fetchedShortcodes.value)\n\nconst formRoot = computed(() =>\n selectedType.value?.content\n ? withShortcodes(\n withPlaceholders(\n formSchema(selectedType.value.content.schema),\n selectedType.value.content.sample ?? {},\n marked.value,\n t('field.markup-in-text'),\n ),\n shortcodes.value,\n { tokensTitle: t('field.shortcodes'), tokensLabel: t('field.shortcodes-insert') },\n )\n : [],\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 <span class=\"wx-blocks__panel-extra\">\n <wx-text size=\"sm\" tone=\"muted\">{{ tree.length }}</wx-text>\n <wx-row-menu :actions=\"listActions\" :label=\"t('field.blocks')\" />\n </span>\n </div>\n <div v-if=\"pageRefusals.length\" class=\"wx-blocks__refusals\" role=\"alert\">\n <wx-text v-for=\"(line, index) in pageRefusals\" :key=\"index\" size=\"sm\" tone=\"danger\">{{\n line\n }}</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 :errors=\"refusedByKey\"\n :clip=\"clipNodes\"\n @select=\"select\"\n @add=\"add\"\n @remove=\"remove\"\n @duplicate=\"duplicate\"\n @copy=\"copyBlock\"\n @paste=\"paste\"\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 <div v-if=\"selectedPlacement.length\" class=\"wx-blocks__refusals\" role=\"alert\">\n <wx-text\n v-for=\"(line, index) in selectedPlacement\"\n :key=\"index\"\n size=\"sm\"\n tone=\"danger\"\n >{{ line }}</wx-text\n >\n </div>\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 :errors=\"selectedErrors\"\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 :hidden=\"hiddenKeys\"\n :reload=\"preview.reload?.value ?? 0\"\n :compact=\"compact\"\n :region=\"framed\"\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/* What a save was refused for that is not one field's: a limit of the page, a block standing\n where it may not. Above the tree or the form, where the eye starts. */\n.wx-blocks__refusals {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-4);\n padding: var(--wx-space-6) var(--wx-space-8);\n border-radius: var(--wx-radius-control);\n background: var(--wx-color-danger-soft);\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, ref, watch } from 'vue'\nimport { useAdmin, useErrorText, useTranslate } from '@webx-ui/module-admin'\nimport {\n toast,\n useModal,\n WxAlert,\n WxBadge,\n WxButton,\n WxDialog,\n WxEmpty,\n WxSkeleton,\n WxSpace,\n WxSwitch,\n WxText,\n} from '@webx-ui/core'\nimport { createBlocksApi } from './api'\nimport { useBlocksMessages } from './i18n'\nimport type { BlockImportRow, BlockImportStatus } from './types'\n\n/**\n * \"Import\" (§17.1): a file in, asked about twice. First the server reads it without writing —\n * what each type would become: new, updated, unchanged or refused, and why — then, once the\n * person has seen that, for real. A type that is already here is not replaced: it gets a new\n * draft version, so the site keeps drawing what it drew until someone publishes, unless the\n * switch to publish is on.\n *\n * Resolves with the rows written, so the section can fetch its list again; a run where some\n * type stayed behind keeps the dialog open on the result, because a toast would be gone before\n * the reason was read.\n */\nconst { resolve, dismiss, open } = useModal<BlockImportRow[]>()\n\nconst context = useAdmin()\nconst api = createBlocksApi(context)\nuseBlocksMessages()\n\nconst t = useTranslate('webx-blocks')\nconst message = useErrorText()\n\nconst picker = ref<HTMLInputElement | null>(null)\nconst name = ref<string | null>(null)\n/** The text of the file, sent as it is: decoded here, its strings would be trimmed on the way. */\nconst file = ref<string | null>(null)\nconst rows = ref<BlockImportRow[] | null>(null)\n/** Why the file was refused as a whole: not JSON, not a pack, a circle among its types. */\nconst refusal = ref<string | null>(null)\nconst publish = ref(false)\nconst reading = ref(false)\nconst importing = ref(false)\n/** The rows are the outcome, not the plan: the import has run. */\nconst done = ref(false)\n\nconst STATUS: Record<BlockImportStatus, 'success' | 'primary' | 'default' | 'danger'> = {\n created: 'success',\n updated: 'primary',\n unchanged: 'default',\n failed: 'danger',\n}\n\nconst writable = computed(() => (rows.value ?? []).filter((row) => row.status !== 'failed'))\nconst changes = computed(() =>\n writable.value.filter((row) => row.status !== 'unchanged' || (publish.value && row.writes)),\n)\n\n/** Nothing to write and nothing to publish: the button would be a promise of nothing. */\nconst upToDate = computed(\n () => rows.value !== null && writable.value.length > 0 && changes.value.length === 0,\n)\n\nfunction choose(): void {\n picker.value?.click()\n}\n\nfunction refusalOf(error: unknown): string {\n const body = (error as { status?: number; body?: { errors?: { file?: string[] } } }).body\n\n return body?.errors?.file?.[0] ?? message(error, t('exchange.import-failed'))\n}\n\nasync function onFile(event: Event): Promise<void> {\n const input = event.target as HTMLInputElement\n const chosen = input.files?.[0]\n\n // The same file chosen again must still fire `change` — it is how a fixed file is re-read.\n input.value = ''\n\n if (!chosen) return\n\n name.value = chosen.name\n rows.value = null\n refusal.value = null\n done.value = false\n reading.value = true\n\n try {\n const text = await chosen.text()\n\n try {\n JSON.parse(text)\n } catch {\n file.value = null\n refusal.value = t('exchange.not-json')\n\n return\n }\n\n file.value = text\n await plan()\n } finally {\n reading.value = false\n }\n}\n\n/** The dry run — with the publish checks when publishing is asked, so the plan warns first. */\nasync function plan(): Promise<void> {\n if (file.value === null) return\n\n try {\n rows.value = await api.importPack(file.value, {\n name: name.value ?? undefined,\n dryRun: true,\n publish: publish.value,\n })\n } catch (error) {\n rows.value = null\n refusal.value = refusalOf(error)\n }\n}\n\nwatch(publish, () => {\n if (rows.value !== null && !done.value) void plan()\n})\n\nasync function run(): Promise<void> {\n importing.value = true\n\n try {\n const result = await api.importPack(file.value ?? '', {\n name: name.value ?? undefined,\n publish: publish.value,\n })\n const written = result.filter((row) => row.status !== 'failed' && row.status !== 'unchanged')\n\n toast.success(t('exchange.imported', { count: written.length }))\n\n if (result.some((row) => row.error !== null)) {\n rows.value = result\n done.value = true\n\n return\n }\n\n resolve(result)\n } catch (error) {\n refusal.value = refusalOf(error)\n } finally {\n importing.value = false\n }\n}\n\n/** Past the run, closing is the answer — with the rows, so the section knows to refresh. */\nfunction close(): void {\n if (done.value && rows.value) resolve(rows.value)\n else dismiss()\n}\n\nfunction statusLabel(row: BlockImportRow): string {\n return t(`exchange.status-${row.status}`)\n}\n</script>\n\n<template>\n <wx-dialog v-model:open=\"open\" :title=\"t('exchange.import-title')\" :width=\"600\">\n <div class=\"wx-block-import\">\n <wx-text tone=\"muted\" size=\"sm\">{{ t('exchange.import-help') }}</wx-text>\n\n <input ref=\"picker\" type=\"file\" accept=\".json,application/json\" hidden @change=\"onFile\" />\n\n <wx-empty\n v-if=\"name === null\"\n icon=\"upload\"\n :title=\"t('exchange.import-title')\"\n class=\"wx-block-import__pick\"\n >\n <template #actions>\n <wx-button type=\"primary\" icon=\"upload\" @click=\"choose\">\n {{ t('exchange.choose-file') }}\n </wx-button>\n </template>\n </wx-empty>\n\n <template v-else>\n <div class=\"wx-block-import__file\">\n <span class=\"wx-block-import__name\">{{ name }}</span>\n <wx-button v-if=\"!done\" size=\"sm\" variant=\"text\" @click=\"choose\">\n {{ t('exchange.other-file') }}\n </wx-button>\n </div>\n\n <wx-skeleton v-if=\"reading\" :rows=\"4\" />\n\n <wx-alert v-else-if=\"refusal\" type=\"danger\" variant=\"soft\" :description=\"refusal\" />\n\n <template v-else-if=\"rows\">\n <ul class=\"wx-block-import__list\">\n <li v-for=\"row in rows\" :key=\"row.slug\" class=\"wx-block-import__row\">\n <div class=\"wx-block-import__type\">\n <span class=\"wx-block-import__title\">{{ row.title ?? row.slug }}</span>\n <span class=\"wx-block-import__meta\">\n {{ row.slug }}\n <template v-if=\"row.kind === 'component'\">\n · {{ t('components.kind-component') }}</template\n >\n <template v-if=\"done && row.version !== null\"> · v{{ row.version }}</template>\n </span>\n <span\n v-if=\"row.error\"\n class=\"wx-block-import__error\"\n :class=\"{ 'is-warning': row.status !== 'failed' }\"\n >{{ row.error }}</span\n >\n </div>\n <wx-badge :type=\"STATUS[row.status]\" variant=\"soft\" size=\"sm\">\n {{ statusLabel(row) }}\n </wx-badge>\n </li>\n </ul>\n\n <wx-alert\n v-if=\"upToDate && !done\"\n type=\"info\"\n variant=\"soft\"\n :description=\"t('exchange.up-to-date')\"\n />\n\n <wx-switch\n v-if=\"!done && writable.length > 0\"\n v-model=\"publish\"\n :label=\"t('exchange.publish')\"\n />\n </template>\n </template>\n </div>\n\n <template #footer>\n <wx-space size=\"sm\">\n <wx-button variant=\"outline\" @click=\"close\">{{ t('page.cancel') }}</wx-button>\n <wx-button\n v-if=\"!done\"\n type=\"primary\"\n :loading=\"importing\"\n :disabled=\"rows === null || changes.length === 0\"\n @click=\"run\"\n >\n {{ t('exchange.run') }}\n </wx-button>\n </wx-space>\n </template>\n </wx-dialog>\n</template>\n\n<style scoped>\n.wx-block-import {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-12);\n}\n\n.wx-block-import__file {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--wx-space-8);\n min-width: 0;\n}\n\n.wx-block-import__name {\n overflow: hidden;\n font-weight: var(--wx-font-weight-medium);\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.wx-block-import__list {\n display: flex;\n flex-direction: column;\n max-height: 340px;\n margin: 0;\n padding: 0;\n overflow-y: auto;\n list-style: none;\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n}\n\n.wx-block-import__row {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: var(--wx-space-12);\n padding: var(--wx-space-8) var(--wx-space-12);\n}\n\n.wx-block-import__row + .wx-block-import__row {\n border-top: 1px solid var(--wx-border-default);\n}\n\n.wx-block-import__type {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-2);\n min-width: 0;\n}\n\n.wx-block-import__meta {\n font-size: var(--wx-font-size-xs);\n color: var(--wx-text-muted);\n}\n\n.wx-block-import__error {\n font-size: var(--wx-font-size-xs);\n color: var(--wx-color-danger);\n overflow-wrap: anywhere;\n}\n\n.wx-block-import__error.is-warning {\n color: var(--wx-color-warning);\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 BlockExportDialog from './BlockExportDialog.vue'\nimport BlockImportDialog from './BlockImportDialog.vue'\nimport { useBlocksMessages } from './i18n'\nimport { groupLabel, kindOf } from './schema'\nimport type { BlockImportRow, 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)\nconst exportTypes = createModal<true, { selected?: string[] }>(BlockExportDialog)\nconst importTypes = createModal<BlockImportRow[], Record<string, never>>(BlockImportDialog)\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/** A file of types in: the list is fetched again, since new cards and new drafts came with it. */\nasync function importFile(): Promise<void> {\n if (await importTypes({})) await load()\n}\n\n/*\n * What the section offers. Declared, because on a phone the head folds it into the ···.\n * Export is reading, so whoever sees the section may take a file; import writes drafts, so it\n * stands with \"New block\" behind the right to make types.\n */\nconst actions = computed<ScreenAction[]>(() => [\n ...(types.value.length > 0\n ? [\n {\n key: 'export',\n label: t('exchange.export'),\n icon: 'download',\n run: () => void exportTypes({}),\n },\n ]\n : []),\n ...(canManage.value\n ? [\n {\n key: 'import',\n label: t('exchange.import'),\n icon: 'upload',\n run: () => void importFile(),\n },\n { key: 'new', label: t('page.new'), icon: 'plus', primary: true, run: () => void add() },\n ]\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","<script setup lang=\"ts\">\nimport { useTranslate } from '@webx-ui/module-admin'\nimport type { SiteBarRegion } from './types'\n\n/**\n * A region's unpublished draft in the panel on the site, with the buttons that publish it or\n * throw it away.\n *\n * Drawn over the region's map and over the form of one of its blocks alike: the head of the bar\n * speaks for the record only, so the form is where an editor who has just saved a block of the\n * footer is looking — and a notice that only the map carried was found after a reload.\n */\ndefineProps<{\n region: SiteBarRegion\n /** This region's publication or discard is under way. */\n busy?: boolean\n /** Another region's is: one at a time, since each reloads the page. */\n blocked?: boolean\n /** Why the publication was refused — the blocks of the draft that fail. */\n refusals?: string[]\n /** The region's draft drawn on this page: after a reload the page shows the site again. */\n preview?: string | null\n}>()\n\nconst emit = defineEmits<{ publish: []; discard: [] }>()\n\nconst t = useTranslate('webx-blocks')\n</script>\n\n<template>\n <wx-alert\n type=\"warning\"\n :title=\"t('site-bar.changes', { count: region.draft.changes })\"\n :description=\"\n !region.draft.mine && region.draft.by\n ? t('site-bar.draft-other', { name: region.draft.by })\n : undefined\n \"\n >\n <template #actions>\n <wx-button\n size=\"sm\"\n type=\"primary\"\n :loading=\"busy\"\n :disabled=\"blocked && !busy\"\n @click=\"emit('publish')\"\n >\n {{ t('site-bar.publish') }}\n </wx-button>\n <wx-button size=\"sm\" variant=\"outline\" :disabled=\"busy || blocked\" @click=\"emit('discard')\">\n {{ t('site-bar.discard') }}\n </wx-button>\n <wx-button\n v-if=\"preview\"\n size=\"sm\"\n variant=\"text\"\n :href=\"preview\"\n target=\"_blank\"\n rel=\"noopener\"\n >\n {{ t('site-bar.preview') }}\n </wx-button>\n </template>\n </wx-alert>\n\n <div v-if=\"refusals?.length\" class=\"wx-region-draft__refusals\" role=\"alert\">\n <wx-text v-for=\"(line, index) in refusals\" :key=\"index\" size=\"sm\" tone=\"danger\">{{\n line\n }}</wx-text>\n </div>\n</template>\n\n<style scoped>\n.wx-region-draft__refusals {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-4);\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, provide, ref, shallowRef, watch } from 'vue'\nimport {\n HttpError,\n loadShortcodes,\n onSitePage,\n tellSitePage,\n useAdmin,\n useErrorText,\n useSiteBar,\n useTranslate,\n WxRowMenu,\n type EditingEditor,\n type RowAction,\n type ShortcodeToken,\n type SiteBarContext,\n} from '@webx-ui/module-admin'\nimport { confirm, createModal, toast } from '@webx-ui/core'\nimport {\n coreTypes,\n WxScreenRenderer,\n type TypeRegistry,\n type ValidationErrors,\n} from '@webx-ui/schema'\nimport { createBlocksApi, createRegionsApi, createSiteBarBlocksApi } from './api'\nimport BlockPicker from './BlockPicker.vue'\nimport { clone, countType, locate, nestedFields } from './content'\nimport { useBlocksMessages } from './i18n'\nimport { blocksFragmentKey, blocksRootKey } from './preview'\nimport RegionDraftNotice from './RegionDraftNotice.vue'\nimport { formSchema, markupFields, startValues, withPlaceholders, withShortcodes } from './schema'\nimport type {\n BlockNode,\n BlockOutlineLine,\n BlockType,\n SiteBarBlockEdited,\n SiteBarBlockOp,\n SiteBarBlocks,\n SiteBarRegion,\n} from './types'\n\n/**\n * The «Blocks» tab of the panel on the site (WEBX_UI_SITE_BAR.md, §8–§9, SB4).\n *\n * Two states, like the constructor's narrow column: maps of the blocks, or one block's fields.\n * The maps are the record's — the page behind the address — and the layout's regions', the\n * header and the footer, each under its own name; a row under the pointer frames its block on the\n * page. The pencil is the way from the page: with it on, a click on a block picks it there\n * instead of following its link, whichever tree it belongs to.\n *\n * The form is the constructor's own — the block's schema through the same steps, drawn by the\n * same renderer with the panel's field types — and its values are the draft's, never the\n * site's: an edit goes into the draft of whatever holds the block, and a form that showed what\n * is published would write over whatever a colleague prepared. «Save» writes the fields that\n * changed and puts the block, drawn from the draft, in place of the old one on the page.\n *\n * The record's draft is published from the head of the bar; a region's — with its own buttons\n * over its map and over the form of its block, since it is a draft of its own and goes on every\n * page at once.\n *\n * The structure too (SB5): a block added — below another, at the end of a tree, inside a\n * container — duplicated, moved up or down, hidden, shown or deleted, each one an operation of the\n * agent's dictionary into the same draft. The picker is the constructor's, held to the same rules\n * of the place; what cannot be done right now is greyed with the reason rather than missing.\n */\nconst props = defineProps<{ context: SiteBarContext }>()\n\nconst admin = useAdmin()\nuseBlocksMessages()\nconst t = useTranslate('webx-blocks')\nconst errorText = useErrorText()\nconst bar = useSiteBar()\nconst api = createSiteBarBlocksApi(admin)\nconst regionsApi = createRegionsApi(admin)\n\n/* A list of blocks inside a block's form is the constructor's to change, in the panel: the\n nested field draws its note instead of a second constructor. */\nprovide(blocksRootKey, true)\n\n/** One tree of blocks the tab edits: the record's, or a region's. */\ninterface Source {\n /** What the page knows the tree by: `page:12`, `region:header`. */\n scope: string\n /** The address of its blocks: the record's type and id, or `region` and the region's name. */\n type: string\n id: string | number\n title: string\n content: SiteBarBlocks\n region: SiteBarRegion | null\n /** A shared block: on the pages that place it, not on every page like the header. */\n fragment: boolean\n /** What its top level takes: a region's declaration, or anything for a record. */\n top: { allow: string[] | null; max: number | null; root: string }\n}\n\n/** One list of blocks: the top level of a tree, or a container's field. */\ninterface Place {\n parentKey: string | null\n field: string | null\n list: BlockNode[]\n parent: BlockType | null\n allow: string[] | null\n max: number | null\n root: string\n}\n\nconst sources = ref<Source[]>([])\nconst catalog = shallowRef<BlockType[]>([])\nconst loading = ref(true)\nconst failed = ref(false)\nconst selected = ref<{ scope: string; key: string } | null>(null)\nconst values = ref<Record<string, unknown>>({})\nconst held = ref('{}')\nconst errors = ref<ValidationErrors | undefined>(undefined)\n/* What a save was refused for that is not one of this form's fields: where a block stands — this\n one or another of the same tree — which the constructor in the panel is the place to change. */\nconst refusals = ref<string[]>([])\nconst saving = ref(false)\nconst picking = ref(false)\nconst others = ref<string[]>([])\n/* A region's publication refused — a block of its draft fails — said over that region's map. */\nconst regionRefusals = ref<Record<string, string[]>>({})\nconst busy = ref<string | null>(null)\n/* A change of structure under way: one at a time, since each answers with the page's steps. */\nconst shaping = ref(false)\n/* The sets of block styles and scripts the page has, as the page reported them. */\nconst pageBundles = ref<string[] | null>(null)\n/* The regions the page prints, as it reported them; null from a page of the release before. */\nconst pageRegions = ref<string[] | null>(null)\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 | null\n root: string\n }\n>(BlockPicker)\n\nconst groupsOrder = computed<string[]>(\n () =>\n (admin.state.manifest?.modules.find((m) => m.id === 'blocks')?.meta?.groups as\n string[] | undefined) ?? [],\n)\n\nconst entity = computed(() => props.context.entity)\nconst offersRecord = computed(() => props.context.sections.includes('blocks') && !!entity.value)\nconst offersRegions = computed(() => props.context.sections.includes('regions'))\n\nfunction typeOf(slug: string): BlockType | null {\n return catalog.value.find((type) => type.slug === slug) ?? null\n}\n\nfunction titleOf(slug: string): string {\n return typeOf(slug)?.title ?? slug\n}\n\nfunction rowsOf(source: Source) {\n return (source.content.outline ?? []).map((line: BlockOutlineLine, index) => ({\n id: line.key ?? `~${index}`,\n key: line.key ?? null,\n depth: line.depth,\n title: titleOf(line.type),\n label: line.label && line.label !== titleOf(line.type) ? line.label : '',\n hidden: line.hidden === true,\n }))\n}\n\n/* A region that is not on the site shows the markup from code: there is nothing of it on the\n page to pick, and its draft is the panel's to set up. */\nfunction onSite(source: Source): boolean {\n return source.region === null || source.region.published\n}\n\n/*\n * A shared block is listed on a page that holds it and on no other: on the rest its map is blocks\n * nobody can point at here, and its draft notice an invitation to publish what this page does not\n * show. Every one is listed by a page that cannot say what it holds.\n */\nfunction onPage(source: Source): boolean {\n return (\n !source.fragment || pageRegions.value === null || pageRegions.value.includes(String(source.id))\n )\n}\n\nconst groups = computed(() =>\n sources.value\n .filter(onPage)\n .map((source) => ({ source, rows: onSite(source) ? rowsOf(source) : [] })),\n)\n\nconst current = computed(() =>\n selected.value\n ? (sources.value.find((one) => one.scope === selected.value!.scope) ?? null)\n : null,\n)\nconst tree = computed(() => current.value?.content.tree ?? [])\nconst found = computed(() => (selected.value ? locate(tree.value, selected.value.key) : null))\nconst selectedType = computed(() => (found.value ? typeOf(found.value.node.type) : null))\n\n/* The blocks the open one is inside, outermost first — the way back up to its parent. */\nconst trail = computed(() => {\n const steps: { key: string; title: string }[] = []\n let at = found.value?.parent ?? null\n\n while (at) {\n steps.unshift({ key: at.key, title: titleOf(at.type) })\n at = locate(tree.value, at.key)?.parent ?? null\n }\n\n return steps\n})\n\nconst types = computed<TypeRegistry>(() => ({ ...coreTypes, ...(admin.types ?? {}) }))\nconst translate = computed(() => admin.i18n.t)\nconst can = computed(() => admin.can)\n\nconst shortcodes = shallowRef<ShortcodeToken[]>([])\nconst marked = ref<string[]>([])\n\nconst formRoot = computed(() =>\n selectedType.value?.content\n ? withShortcodes(\n withPlaceholders(\n formSchema(selectedType.value.content.schema),\n selectedType.value.content.sample ?? {},\n marked.value,\n t('field.markup-in-text'),\n ),\n shortcodes.value,\n { tokensTitle: t('field.shortcodes'), tokensLabel: t('field.shortcodes-insert') },\n )\n : [],\n)\n\n/* What «Save» sends: the fields that differ from what the form was opened with. A list of\n blocks is left out — it is not this form's to change. */\nconst changed = computed<Record<string, unknown>>(() => {\n const before = JSON.parse(held.value) as Record<string, unknown>\n const nested = new Set(selectedType.value?.content?.schema ? nestedIds() : [])\n const out: Record<string, unknown> = {}\n\n for (const [name, value] of Object.entries(values.value)) {\n if (nested.has(name)) continue\n if (JSON.stringify(value ?? null) !== JSON.stringify(before[name] ?? null)) out[name] = value\n }\n\n return out\n})\n\nconst dirty = computed(() => Object.keys(changed.value).length > 0)\n\nfunction nestedIds(): string[] {\n const ids: string[] = []\n const visit = (nodes: { id?: string; type: string; children?: unknown }[]): void => {\n for (const node of nodes) {\n if (node.type === 'wx-blocks' && node.id) ids.push(node.id)\n if (Array.isArray(node.children)) visit(node.children as typeof nodes)\n }\n }\n\n visit(selectedType.value?.content?.schema ?? [])\n\n return ids\n}\n\n/* Where the panel edits what holds the block: the record's screen, or the region's editor. */\nfunction panelHref(source: Source | null): string | null {\n const base = admin.basePath.replace(/\\/$/, '')\n\n if (source?.region) {\n const path = (admin.modules ?? []).find((module) => module.id === 'regions')?.path ?? '/regions'\n\n return `${base}${path}/${encodeURIComponent(source.region.name)}`\n }\n\n return entity.value?.edit ? `${base}${entity.value.edit}` : null\n}\n\n/** The page is told which trees it may pick from, and what each block is called on hover. */\nfunction announce(): void {\n tellSitePage({\n type: 'blocks',\n sources: sources.value.filter(onSite).map((source) => ({\n scope: source.scope,\n // The page's own blocks go by their type alone; a region's say whose they are.\n ...(source.region ? { title: source.title } : {}),\n items: (source.content.outline ?? []).flatMap((line) =>\n line.key ? [{ key: line.key, label: titleOf(line.type) }] : [],\n ),\n })),\n })\n}\n\nasync function readRecord(): Promise<Source[]> {\n const record = entity.value\n\n if (!offersRecord.value || !record) return []\n\n return [\n {\n scope: `${record.type}:${record.id}`,\n type: record.type,\n id: record.id,\n title: record.kind,\n content: await api.read(record.type, record.id),\n region: null,\n fragment: false,\n top: { allow: null, max: null, root: 'root' },\n },\n ]\n}\n\nasync function readRegions(): Promise<Source[]> {\n if (!offersRegions.value) return []\n\n const rows = await regionsApi.list()\n\n return Promise.all(\n rows.map(async (row): Promise<Source> => {\n const read = await api.read('region', row.name)\n\n return {\n scope: `region:${row.name}`,\n type: 'region',\n id: row.name,\n title: read.region?.title ?? row.title,\n content: read,\n region: read.region ?? null,\n fragment: row.fragment === true,\n top: { allow: row.allow, max: row.max, root: `region:${row.name}` },\n }\n }),\n )\n}\n\nasync function load(): Promise<void> {\n loading.value = sources.value.length === 0\n failed.value = false\n\n try {\n const [record, regions, types] = await Promise.all([\n readRecord(),\n readRegions(),\n catalog.value.length ? Promise.resolve(catalog.value) : createBlocksApi(admin).catalog(),\n ])\n\n catalog.value = types\n sources.value = [...record, ...regions]\n announce()\n\n if (selected.value && !found.value) back()\n } catch {\n failed.value = true\n } finally {\n loading.value = false\n }\n}\n\nfunction open(scope: string, key: string): void {\n const source = sources.value.find((one) => one.scope === scope)\n const hit = source ? locate(source.content.tree, key) : null\n\n if (!source || !hit) return\n\n if (selected.value && selected.value.scope !== scope) stopPresence()\n\n selected.value = { scope, key }\n values.value = clone(hit.node.values ?? {})\n held.value = JSON.stringify(values.value)\n errors.value = undefined\n refusals.value = []\n marked.value = typeOf(hit.node.type)?.content\n ? markupFields(typeOf(hit.node.type)!.content!.schema, hit.node.values ?? {})\n : []\n tellSitePage({ type: 'select', key, scope })\n startPresence()\n}\n\nfunction back(): void {\n const was = selected.value\n\n stopPresence()\n selected.value = null\n errors.value = undefined\n refusals.value = []\n tellSitePage({ type: 'select', key: null, ...(was ? { scope: was.scope } : {}) })\n}\n\nfunction highlight(scope: string, key: string | null): void {\n tellSitePage({ type: 'highlight', key, scope })\n}\n\nfunction togglePicking(): void {\n picking.value = !picking.value\n tellSitePage({ type: 'mode', on: picking.value })\n}\n\n/**\n * The refusal of a value under the field it names (`blocks.<key>.<field>`); everything else the\n * server said — a block that stands where its container does not take it, a region holding more\n * than it may — as lines above, under a sentence that says it is not this form's doing.\n */\nfunction refuse(error: HttpError, key: string): void {\n const prefix = `blocks.${key}.`\n const fields: ValidationErrors = {}\n const lines: string[] = []\n\n for (const [path, messages] of Object.entries(error.errors)) {\n if (path.startsWith(prefix)) fields[path.slice(prefix.length)] = messages\n else lines.push(...messages)\n }\n\n errors.value = Object.keys(fields).length ? fields : undefined\n refusals.value = [...new Set(lines)]\n}\n\nasync function save(): Promise<void> {\n const source = current.value\n const key = selected.value?.key\n\n if (!source || !key || !dirty.value || saving.value) return\n\n saving.value = true\n errors.value = undefined\n refusals.value = []\n\n try {\n const done = await api.edit(source.type, source.id, {\n revision: source.content.revision,\n locale: props.context.locale,\n url: props.context.url,\n bundles: pageBundles.value ?? undefined,\n ops: [{ op: 'set', key, values: changed.value }],\n })\n\n // The block from the draft in place of the old one, framed as a draft on the page.\n showOnPage(source, done, key)\n\n held.value = JSON.stringify(values.value)\n toast.success(t('site-bar.saved'))\n\n await load()\n // The head counts the record's changes; it reads them again. A region counts its own.\n if (!source.region) void bar?.refresh()\n } catch (caught) {\n if (caught instanceof HttpError && caught.status === 409) {\n // Somebody wrote the tree since the form read it: read again and say who.\n conflicted(caught)\n await load()\n open(source.scope, key)\n\n return\n }\n\n if (caught instanceof HttpError && caught.isValidation && Object.keys(caught.errors).length) {\n refuse(caught, key)\n\n return\n }\n\n toast.danger(errorText(caught))\n } finally {\n saving.value = false\n }\n}\n\n/*\n * What the page does to show the draft: the steps the server worked out, after the styles and\n * script of a type the page did not have — so that a new block arrives dressed.\n */\nfunction showOnPage(source: Source, done: SiteBarBlockEdited, edited?: string): void {\n const scope = source.scope\n\n if (done.assets) tellSitePage({ type: 'assets', ...done.assets })\n\n // An answer of the release before: the one block drawn.\n if (!done.steps) {\n const key = edited ?? done.key\n\n if (key && done.html !== '') tellSitePage({ type: 'replace', key, scope, html: done.html })\n\n return\n }\n\n for (const step of done.steps) {\n if (step.do === 'reload') {\n tellSitePage({ type: 'reload' })\n } else if (step.do === 'remove') {\n tellSitePage({ type: 'remove', key: step.key, scope })\n } else {\n tellSitePage({\n type: step.do === 'move' ? 'move' : 'insert',\n key: step.key,\n scope,\n html: step.html ?? '',\n after: step.after ?? [],\n before: step.before ?? [],\n top: step.top === true,\n })\n }\n }\n}\n\n/* Somebody wrote the tree since the tab read it: say who. */\nfunction conflicted(caught: HttpError): void {\n const body = caught.body as { changed?: { author?: string | null } | null } | null\n const name = body?.changed?.author\n\n toast.warning(name ? t('site-bar.conflict-by', { name }) : t('site-bar.conflict'))\n}\n\n/** One list of blocks of a tree: the top level, or the field of a container. */\nfunction placeOf(source: Source, parentKey: string | null, field: string | null): Place {\n if (parentKey === null) {\n return {\n parentKey: null,\n field: null,\n list: source.content.tree,\n parent: null,\n allow: source.top.allow,\n max: source.top.max,\n root: source.top.root,\n }\n }\n\n const holder = locate(source.content.tree, parentKey)\n const parent = holder ? typeOf(holder.node.type) : null\n const slot = parent?.content\n ? nestedFields(parent.content.schema).find((one) => one.id === field)\n : undefined\n const value = field !== null ? holder?.node.values[field] : undefined\n\n return {\n parentKey,\n field,\n list: Array.isArray(value) ? (value as BlockNode[]) : [],\n parent,\n allow: (slot?.props?.allow as string[] | undefined) ?? null,\n max: (slot?.props?.max as number | undefined) ?? null,\n // A container's field is named by its own type in `allowed_in`, not by the tree's root.\n root: 'root',\n }\n}\n\n/** The list a block is in. */\nfunction placeAround(source: Source, key: string): Place | null {\n const hit = locate(source.content.tree, key)\n\n return hit ? placeOf(source, hit.parent?.key ?? null, hit.field) : null\n}\n\nfunction isFull(place: Place): boolean {\n return place.max !== null && place.list.length >= place.max\n}\n\n/** Why nothing more goes into a list, or null when something does. */\nfunction fullness(place: Place): string | null {\n return isFull(place) ? t('site-bar.full', { count: place.max! }) : null\n}\n\n/**\n * A change of structure into the draft, and the page brought in step. One at a time: each answer\n * names what the page has to do, and two of them crossing would leave it guessing.\n */\nasync function shape(\n source: Source,\n ops: SiteBarBlockOp[],\n options: { forgetBundles?: boolean; quiet?: boolean } = {},\n): Promise<SiteBarBlockEdited | null> {\n if (shaping.value) return null\n\n shaping.value = true\n\n try {\n const done = await api.edit(source.type, source.id, {\n revision: source.content.revision,\n locale: props.context.locale,\n url: props.context.url,\n bundles: options.forgetBundles ? undefined : (pageBundles.value ?? undefined),\n ops,\n })\n\n showOnPage(source, done)\n // Quiet where the caller says what was done in its own words.\n if (!options.quiet) toast.success(t('site-bar.saved'))\n\n await load()\n if (!source.region) void bar?.refresh()\n\n return done\n } catch (caught) {\n if (caught instanceof HttpError && caught.status === 409) {\n conflicted(caught)\n await load()\n } else if (caught instanceof HttpError && caught.isValidation) {\n // Where a block may stand, how many a page takes — the server's words, as they are.\n const lines = [...new Set(Object.values(caught.errors).flat())]\n\n toast.danger(lines.length ? lines.join(' ') : errorText(caught))\n } else {\n toast.danger(errorText(caught))\n }\n\n return null\n } finally {\n shaping.value = false\n }\n}\n\n/**\n * A new block in a list — after `after`, or at its end — of a type chosen in the constructor's\n * own picker, held to the same rules of the place. Its form opens at once.\n */\nasync function addTo(source: Source, place: Place, after: string | null): Promise<void> {\n if (isFull(place) || shaping.value) return\n\n const type = await pick({\n catalog: catalog.value,\n parent: place.parent,\n allow: place.allow,\n tree: source.content.tree,\n groups: groupsOrder.value,\n blocksPath: null,\n root: place.root,\n })\n\n if (!type) return\n\n const done = await shape(source, [\n {\n op: 'add',\n type: type.slug,\n values: startValues(type.content?.schema ?? [], type.content?.sample ?? {}),\n ...(place.parentKey !== null ? { parent: place.parentKey, field: place.field ?? '' } : {}),\n ...(after !== null ? { after } : {}),\n },\n ])\n\n if (done?.key) open(source.scope, done.key)\n}\n\nasync function duplicate(source: Source, key: string): Promise<void> {\n const done = await shape(source, [{ op: 'duplicate', key }])\n\n if (done?.key) open(source.scope, done.key)\n}\n\n/** One step up or down its own list, past the neighbour. */\nasync function moveBy(source: Source, key: string, by: -1 | 1): Promise<void> {\n const hit = locate(source.content.tree, key)\n const next = hit?.list[hit.index + by]\n\n if (!hit || !next?.key) return\n\n await shape(source, [\n {\n op: 'move',\n key,\n ...(hit.parent ? { parent: hit.parent.key, field: hit.field ?? '' } : {}),\n ...(by < 0 ? { before: next.key } : { after: next.key }),\n },\n ])\n}\n\nasync function removeBlock(source: Source, key: string): Promise<void> {\n const hit = locate(source.content.tree, key)\n\n if (!hit) return\n\n const agreed = await confirm({\n title: t('site-bar.delete-title', { title: titleOf(hit.node.type) }),\n message: t('site-bar.delete-text'),\n confirmText: t('site-bar.delete'),\n cancelText: t('site-bar.cancel'),\n tone: 'danger',\n })\n\n if (agreed) await shape(source, [{ op: 'remove', key }])\n}\n\n/**\n * What a block offers, on its row of the map and over its form: the panel's own `···`. What\n * cannot be done right now — the first block up, a full list — is greyed with the reason.\n */\nfunction actionsFor(source: Source, key: string): RowAction[] {\n const hit = locate(source.content.tree, key)\n\n if (!hit) return []\n\n const place = placeOf(source, hit.parent?.key ?? null, hit.field)\n const full = fullness(place)\n const type = typeOf(hit.node.type)\n const limit = type?.max_per_entity ?? null\n const limited =\n limit !== null && countType(source.content.tree, hit.node.type) >= limit\n ? t('site-bar.limit', { count: limit })\n : null\n const slots = type?.content ? nestedFields(type.content.schema) : []\n const hidden = hit.node.hidden === true\n // A neighbour of old content without a key cannot be named: nothing moves past it from here.\n const above = hit.list[hit.index - 1]\n const below = hit.list[hit.index + 1]\n const up = !above ? t('site-bar.at-top') : !above.key ? t('site-bar.temporary') : null\n const down = !below ? t('site-bar.at-bottom') : !below.key ? t('site-bar.temporary') : null\n\n return [\n {\n key: 'add-below',\n icon: 'plus',\n label: t('site-bar.add-below'),\n disabled: full !== null,\n hint: full ?? undefined,\n run: () => void addTo(source, place, key),\n },\n ...slots.map((slot): RowAction => {\n const inside = placeOf(source, key, slot.id)\n const why = fullness(inside)\n\n return {\n key: `add-inside-${slot.id}`,\n icon: 'plus',\n label:\n slots.length > 1\n ? `${t('site-bar.add-inside')} · ${String(slot.label ?? slot.id)}`\n : t('site-bar.add-inside'),\n disabled: why !== null,\n hint: why ?? undefined,\n run: () => void addTo(source, inside, null),\n }\n }),\n {\n key: 'duplicate',\n icon: 'copy',\n label: t('site-bar.duplicate'),\n disabled: full !== null || limited !== null,\n hint: full ?? limited ?? undefined,\n run: () => void duplicate(source, key),\n },\n {\n key: 'move-up',\n icon: 'arrow-up',\n label: t('site-bar.move-up'),\n disabled: up !== null,\n hint: up ?? undefined,\n run: () => void moveBy(source, key, -1),\n },\n {\n key: 'move-down',\n icon: 'arrow-down',\n label: t('site-bar.move-down'),\n disabled: down !== null,\n hint: down ?? undefined,\n run: () => void moveBy(source, key, 1),\n },\n {\n key: 'visibility',\n icon: hidden ? 'eye' : 'eye-off',\n label: hidden ? t('site-bar.show') : t('site-bar.hide'),\n run: () => void shape(source, [{ op: hidden ? 'show' : 'hide', key }]),\n },\n {\n key: 'delete',\n icon: 'trash',\n label: t('site-bar.delete'),\n danger: true,\n run: () => void removeBlock(source, key),\n },\n ]\n}\n\n/* The whole draft on a page, for after a reload: the region's preview drawn on this page. */\nfunction regionPreview(source: Source): string | null {\n const url = source.region?.preview\n\n return url ? `${url}&at=${encodeURIComponent(props.context.url)}` : null\n}\n\n/*\n * A region's draft on the site, or thrown away — the same calls its editor in the panel makes.\n * Every page that prints it changes at once, so the page in front reloads to show it.\n */\nasync function publishRegion(source: Source): Promise<void> {\n if (!source.region || busy.value) return\n\n busy.value = source.scope\n regionRefusals.value = { ...regionRefusals.value, [source.scope]: [] }\n\n try {\n await regionsApi.publish(source.region.name, source.content.revision)\n tellSitePage({ type: 'reload' })\n } catch (caught) {\n // A block of the draft fails: the region would print its fallback, so it is not published,\n // and the lines say which block and why.\n const lines = caught instanceof HttpError ? Object.values(caught.errors).flat() : []\n\n regionRefusals.value = { ...regionRefusals.value, [source.scope]: lines }\n toast.danger(errorText(caught))\n // A 409 is somebody's edit the tab had not seen: the map shows it now.\n void load()\n } finally {\n busy.value = null\n }\n}\n\nasync function discardRegion(source: Source): Promise<void> {\n if (!source.region || busy.value) return\n\n const agreed = await confirm({\n title: t('site-bar.discard-title', { name: source.title }),\n message: t('site-bar.discard-text'),\n confirmText: t('site-bar.discard'),\n cancelText: t('site-bar.cancel'),\n tone: 'danger',\n })\n\n if (!agreed) return\n\n busy.value = source.scope\n\n try {\n await regionsApi.discardDraft(source.region.name)\n tellSitePage({ type: 'reload' })\n } catch (caught) {\n toast.danger(errorText(caught))\n } finally {\n busy.value = null\n }\n}\n\n/*\n * Presence (§9): while a block's form is open the bar knocks where the editor in the panel does\n * — the record's, or the region's — so an editor open there at the same time sees that it is\n * being edited.\n */\nlet beat: ReturnType<typeof setInterval> | undefined\nlet knocking: string | null = null\n\nfunction presenceUrl(): string | null {\n const source = current.value\n\n if (source?.region)\n return `${admin.apiPath}/editing/regions/${encodeURIComponent(source.region.name)}`\n\n const record = entity.value\n\n return source && record?.editing\n ? `${admin.apiPath}/editing/${record.editing}/${encodeURIComponent(String(record.id))}`\n : null\n}\n\nasync function knock(): Promise<void> {\n if (!knocking) return\n\n try {\n const ping = (await admin.http.post<{ data: { editors?: EditingEditor[] } }>(knocking)).data\n\n others.value = (ping.editors ?? []).map((one) => one.name).filter((name) => name !== '')\n } catch {\n // A courtesy: its absence is not worth a word on screen.\n }\n}\n\nfunction startPresence(): void {\n const url = presenceUrl()\n\n if (beat !== undefined || !url) return\n\n knocking = url\n void knock()\n beat = setInterval(() => void knock(), 20_000)\n}\n\nfunction stopPresence(): void {\n if (beat === undefined) return\n\n clearInterval(beat)\n beat = undefined\n others.value = []\n\n if (knocking) void admin.http.delete(knocking).catch(() => {})\n knocking = null\n}\n\n/* The page's half: a block picked there, picking switched off there with Esc, «Add below» on the\n picked block, and the sets of styles the page has. A message without a tree is from a page of\n the release before, where the record's was the only one. */\nconst stopListening = onSitePage((message) => {\n if (message.type === 'mode') {\n picking.value = message.on\n } else if (message.type === 'select') {\n const scope = message.scope ?? sources.value[0]?.scope\n const source = sources.value.find((one) => one.scope === scope)\n\n if (source && locate(source.content.tree, message.key)) {\n bar?.show('blocks')\n open(source.scope, message.key)\n }\n } else if (message.type === 'add') {\n const scope = message.scope ?? sources.value[0]?.scope\n const source = sources.value.find((one) => one.scope === scope)\n const place = source ? placeAround(source, message.key) : null\n\n if (source && place) {\n bar?.show('blocks')\n void addTo(source, place, message.key)\n }\n } else if (message.type === 'bundles') {\n pageBundles.value = message.hashes\n } else if (message.type === 'regions') {\n pageRegions.value = message.names\n }\n})\n\n/*\n * «Make it this page's own» of a «Shared block» open here (§5.2 of the shared blocks spec): the\n * shared block's published blocks put after it, then it taken out — one edit of the draft of\n * whatever holds it, so the page is brought in step by the answer, as after any other. Added in\n * reverse, each right after the shared block: the server makes their keys, and the first of them\n * — the last one made — is the one opened.\n */\nprovide(blocksFragmentKey, {\n selected: computed(() => selected.value?.key ?? null),\n own: computed(() => (current.value?.fragment ? String(current.value.id) : null)),\n async detach(key: string, nodes: BlockNode[]): Promise<boolean> {\n const source = current.value\n const hit = source ? locate(source.content.tree, key) : null\n\n if (!source || !hit) return false\n\n const where = hit.parent ? { parent: hit.parent.key, field: hit.field ?? '' } : {}\n const done = await shape(\n source,\n [\n ...[...nodes].reverse().map((node): SiteBarBlockOp => ({\n op: 'add',\n type: node.type,\n values: node.values,\n after: key,\n ...where,\n })),\n { op: 'remove', key },\n // The page is not told which sets it has: the shared block printed its own in place, and\n // that `<link>` goes with its range — the copies would come in without their styles.\n ],\n { forgetBundles: true, quiet: true },\n )\n\n if (done?.key) open(source.scope, done.key)\n\n return done !== null\n },\n})\n\n/* Esc in the frame ends picking first; the screen closes the drawer on the next one. */\nfunction onKeydown(event: KeyboardEvent): void {\n if (event.key !== 'Escape' || !picking.value) return\n\n event.preventDefault()\n togglePicking()\n}\n\n/* Another record — the bar was pointed at another address. The context is read again after every\n save, and the same record in a new object is not a reason to read the blocks twice. */\nwatch(\n () => (entity.value ? `${entity.value.type}:${entity.value.id}` : null),\n () => void load(),\n)\n\nonMounted(() => {\n window.addEventListener('keydown', onKeydown)\n void load()\n void loadShortcodes(admin).then((list) => (shortcodes.value = list))\n})\n\nonBeforeUnmount(() => {\n window.removeEventListener('keydown', onKeydown)\n stopListening()\n stopPresence()\n\n if (picking.value) tellSitePage({ type: 'mode', on: false })\n})\n</script>\n\n<template>\n <div class=\"wx-blocks-bar\">\n <!-- One row: the way back to the list on the left, picking on the page on the right — two\n rows of one button each took the height the form needs. -->\n <div class=\"wx-blocks-bar__tools\">\n <nav v-if=\"found && current\" class=\"wx-blocks-bar__trail\" :aria-label=\"t('site-bar.all')\">\n <wx-button size=\"sm\" variant=\"text\" icon=\"arrow-left\" @click=\"back\">\n {{ t('site-bar.all') }}\n </wx-button>\n <template v-for=\"step in trail\" :key=\"step.key\">\n <span class=\"wx-blocks-bar__slash\" aria-hidden=\"true\">/</span>\n <wx-button size=\"sm\" variant=\"text\" @click=\"open(current.scope, step.key)\">\n {{ step.title }}\n </wx-button>\n </template>\n </nav>\n <wx-button\n size=\"sm\"\n icon=\"edit\"\n :variant=\"picking ? 'solid' : 'outline'\"\n :type=\"picking ? 'primary' : 'default'\"\n :aria-pressed=\"picking\"\n @click=\"togglePicking\"\n >\n {{ picking ? t('site-bar.pick-off') : t('site-bar.pick') }}\n </wx-button>\n </div>\n\n <wx-text v-if=\"picking\" size=\"sm\" tone=\"muted\">{{ t('site-bar.picking') }}</wx-text>\n\n <wx-loading v-if=\"loading\" />\n\n <wx-result v-else-if=\"failed\" status=\"info\" :title=\"t('site-bar.error')\">\n <wx-button @click=\"load\">{{ t('site-bar.retry') }}</wx-button>\n </wx-result>\n\n <template v-else-if=\"found && current\">\n <div class=\"wx-blocks-bar__name\">\n <wx-text weight=\"semibold\">\n {{ selectedType?.title ?? found.node.type }}\n <span v-if=\"current.region\" class=\"wx-blocks-bar__where\">· {{ current.title }}</span>\n <span v-if=\"found.node.hidden\" class=\"wx-blocks-bar__where\"\n >· {{ t('site-bar.hidden') }}</span\n >\n </wx-text>\n <wx-row-menu\n :actions=\"actionsFor(current, found.node.key)\"\n :label=\"t('site-bar.actions')\"\n />\n </div>\n\n <wx-text v-if=\"current.region\" size=\"sm\" tone=\"muted\">\n {{ current.fragment ? t('site-bar.fragment-everywhere') : t('site-bar.region-everywhere') }}\n </wx-text>\n\n <!-- Here too, not only over the map: the form is where the editor is after saving. -->\n <region-draft-notice\n v-if=\"current.region?.draft.differs\"\n :region=\"current.region\"\n :busy=\"busy === current.scope\"\n :blocked=\"busy !== null\"\n :refusals=\"regionRefusals[current.scope]\"\n :preview=\"regionPreview(current)\"\n @publish=\"publishRegion(current)\"\n @discard=\"discardRegion(current)\"\n />\n\n <wx-text v-if=\"others.length\" size=\"sm\" tone=\"muted\">\n {{ t('site-bar.others', { names: others.join(', ') }) }}\n </wx-text>\n\n <wx-alert\n v-if=\"refusals.length\"\n type=\"danger\"\n role=\"alert\"\n class=\"wx-blocks-bar__refused\"\n :title=\"t('site-bar.refused')\"\n >\n <ul class=\"wx-blocks-bar__lines\">\n <li v-for=\"(line, index) in refusals\" :key=\"index\">{{ line }}</li>\n </ul>\n <template v-if=\"panelHref(current)\" #actions>\n <wx-button\n size=\"sm\"\n variant=\"outline\"\n :href=\"panelHref(current)!\"\n target=\"_blank\"\n rel=\"noopener\"\n >\n {{ t('site-bar.open-in-panel') }}\n </wx-button>\n </template>\n </wx-alert>\n\n <div class=\"wx-blocks-bar__form\">\n <wx-screen-renderer\n v-if=\"selectedType?.content\"\n :key=\"`${current.scope}|${found.node.key}`\"\n v-model=\"values\"\n :root=\"formRoot\"\n :types=\"types\"\n :translate=\"translate\"\n :can=\"can\"\n :errors=\"errors\"\n />\n <wx-text v-else size=\"sm\" tone=\"danger\">{{ t('site-bar.unknown-type') }}</wx-text>\n </div>\n\n <div class=\"wx-blocks-bar__actions\">\n <wx-button type=\"primary\" :disabled=\"!dirty\" :loading=\"saving\" @click=\"save\">\n {{ t('site-bar.save') }}\n </wx-button>\n </div>\n </template>\n\n <template v-else>\n <wx-text size=\"sm\" tone=\"muted\">{{ t('site-bar.hint') }}</wx-text>\n\n <section\n v-for=\"{ source, rows } in groups\"\n :key=\"source.scope\"\n class=\"wx-blocks-bar__group\"\n :aria-label=\"source.title\"\n >\n <header class=\"wx-blocks-bar__head\">\n <wx-text weight=\"semibold\">{{ source.title }}</wx-text>\n <wx-text v-if=\"source.region\" size=\"xs\" tone=\"muted\">\n {{ source.fragment ? t('site-bar.fragment-where') : t('site-bar.region-everywhere') }}\n </wx-text>\n </header>\n\n <!-- A region's own draft: published from here, since the head of the bar is the record's. -->\n <region-draft-notice\n v-if=\"source.region?.draft.differs && onSite(source)\"\n :region=\"source.region\"\n :busy=\"busy === source.scope\"\n :blocked=\"busy !== null\"\n :refusals=\"regionRefusals[source.scope]\"\n :preview=\"regionPreview(source)\"\n @publish=\"publishRegion(source)\"\n @discard=\"discardRegion(source)\"\n />\n\n <template v-if=\"!onSite(source)\">\n <wx-text size=\"sm\" tone=\"muted\">{{ t('site-bar.region-fallback') }}</wx-text>\n <div>\n <wx-button\n size=\"sm\"\n variant=\"outline\"\n :href=\"panelHref(source)!\"\n target=\"_blank\"\n rel=\"noopener\"\n >\n {{ t('site-bar.open-in-panel') }}\n </wx-button>\n </div>\n </template>\n\n <wx-text v-else-if=\"rows.length === 0\" size=\"sm\" tone=\"muted\">{{\n t('site-bar.empty')\n }}</wx-text>\n\n <ul v-else class=\"wx-blocks-bar__map\">\n <li v-for=\"row in rows\" :key=\"row.id\" class=\"wx-blocks-bar__item\">\n <button\n type=\"button\"\n class=\"wx-blocks-bar__row\"\n :data-key=\"row.key ?? undefined\"\n :data-scope=\"source.scope\"\n :class=\"{ 'is-hidden': row.hidden, 'is-temporary': row.key === null }\"\n :style=\"{ '--wx-blocks-bar-depth': row.depth }\"\n :disabled=\"row.key === null\"\n :title=\"row.key === null ? t('site-bar.temporary') : undefined\"\n @mouseenter=\"highlight(source.scope, row.key)\"\n @mouseleave=\"highlight(source.scope, null)\"\n @focus=\"highlight(source.scope, row.key)\"\n @blur=\"highlight(source.scope, null)\"\n @click=\"row.key && open(source.scope, row.key)\"\n >\n <span class=\"wx-blocks-bar__title\">{{ row.title }}</span>\n <span v-if=\"row.label\" class=\"wx-blocks-bar__label\">{{ row.label }}</span>\n <span v-if=\"row.hidden\" class=\"wx-blocks-bar__flag\">{{ t('site-bar.hidden') }}</span>\n <span v-if=\"row.key === null\" class=\"wx-blocks-bar__flag\">{{\n t('site-bar.temporary')\n }}</span>\n </button>\n <wx-row-menu v-if=\"row.key\" :actions=\"actionsFor(source, row.key)\" :label=\"row.title\" />\n </li>\n </ul>\n\n <!-- At the end of the tree, whatever its blocks are: a page with none needs it most. -->\n <div v-if=\"onSite(source)\" class=\"wx-blocks-bar__add\">\n <wx-button\n size=\"sm\"\n variant=\"outline\"\n icon=\"plus\"\n :disabled=\"fullness(placeOf(source, null, null)) !== null\"\n :loading=\"shaping\"\n @click=\"addTo(source, placeOf(source, null, null), null)\"\n >\n {{ t('site-bar.add') }}\n </wx-button>\n <wx-text v-if=\"fullness(placeOf(source, null, null))\" size=\"xs\" tone=\"muted\">\n {{ fullness(placeOf(source, null, null)) }}\n </wx-text>\n </div>\n </section>\n </template>\n </div>\n</template>\n\n<style scoped>\n.wx-blocks-bar {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-12);\n min-width: 0;\n}\n\n.wx-blocks-bar__actions {\n display: flex;\n gap: var(--wx-space-8);\n}\n\n/* The way back on the left, picking on the right; alone, picking stays where it always was. A\n long trail to a nested block wraps, and picking goes under it rather than off the edge. */\n.wx-blocks-bar__tools {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: space-between;\n gap: var(--wx-space-8);\n}\n\n.wx-blocks-bar__trail {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wx-space-2);\n min-width: 0;\n}\n\n.wx-blocks-bar__slash,\n.wx-blocks-bar__where {\n color: var(--wx-text-muted);\n font-weight: var(--wx-font-weight-regular);\n}\n\n/* One tree a group: the page's, then each region's, with what is said about it over its map. */\n.wx-blocks-bar__group {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n min-width: 0;\n padding-top: var(--wx-space-12);\n border-top: 1px solid var(--wx-border-default);\n}\n\n.wx-blocks-bar__head {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n justify-content: space-between;\n gap: var(--wx-space-8);\n min-width: 0;\n}\n\n.wx-blocks-bar__map {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-2);\n margin: 0;\n padding: 0;\n list-style: none;\n}\n\n/* A row and its `···`: the menu keeps its square at the end whatever the row says. */\n.wx-blocks-bar__item {\n display: flex;\n align-items: center;\n gap: var(--wx-space-4);\n min-width: 0;\n}\n\n.wx-blocks-bar__name {\n display: flex;\n align-items: flex-start;\n justify-content: space-between;\n gap: var(--wx-space-8);\n min-width: 0;\n}\n\n.wx-blocks-bar__add {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wx-space-8);\n}\n\n/* One line a block, indented by how deep it is nested: the map is read by its shape. */\n.wx-blocks-bar__row {\n display: flex;\n flex: 1 1 auto;\n align-items: baseline;\n gap: var(--wx-space-8);\n width: 100%;\n min-width: 0;\n padding: var(--wx-space-6) var(--wx-space-8);\n padding-left: calc(var(--wx-space-8) + var(--wx-blocks-bar-depth, 0) * var(--wx-space-16));\n border: 0;\n border-radius: var(--wx-radius-sm);\n background: transparent;\n color: var(--wx-text-default);\n font: inherit;\n text-align: left;\n cursor: pointer;\n}\n\n.wx-blocks-bar__row:hover:not(:disabled),\n.wx-blocks-bar__row:focus-visible {\n background: var(--wx-bg-fill);\n}\n\n.wx-blocks-bar__row:focus-visible {\n outline: 2px solid var(--wx-border-focus);\n outline-offset: -2px;\n}\n\n.wx-blocks-bar__row:disabled {\n cursor: default;\n}\n\n.wx-blocks-bar__title {\n flex: 0 0 auto;\n font-weight: var(--wx-font-weight-medium);\n}\n\n.wx-blocks-bar__label {\n flex: 1 1 auto;\n min-width: 0;\n overflow: hidden;\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-sm);\n white-space: nowrap;\n text-overflow: ellipsis;\n}\n\n.wx-blocks-bar__flag {\n flex: 0 0 auto;\n margin-left: auto;\n color: var(--wx-text-muted);\n font-size: var(--wx-font-size-xs);\n}\n\n.wx-blocks-bar__row.is-hidden .wx-blocks-bar__title,\n.wx-blocks-bar__row.is-temporary .wx-blocks-bar__title {\n color: var(--wx-text-muted);\n}\n\n.wx-blocks-bar__form {\n min-width: 0;\n}\n\n.wx-blocks-bar__lines {\n margin: 0;\n padding-left: var(--wx-space-16);\n overflow-wrap: anywhere;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, inject, onMounted, ref } from 'vue'\nimport { adminKey, useErrorText, useTranslate, type AdminContext } from '@webx-ui/module-admin'\nimport { confirm, toast, WxBadge, WxButton, WxSelect, WxSkeleton, WxText } from '@webx-ui/core'\nimport { createBlocksApi, createRegionsApi } from './api'\nimport { useBlocksMessages } from './i18n'\nimport { blocksFragmentKey } from './preview'\nimport type { RegionRow } from './types'\n\n/**\n * `wx-fragment` — the one field of «Shared block» (§4.1 of the shared blocks spec): which shared\n * block of the site this place on the page shows.\n *\n * The field says what it has chosen as well as letting it be chosen, because the block's own\n * content is not here: is it on the site, where is it edited, and that an edit there reaches\n * every page it stands on. And it offers the way out — the blocks of the shared one copied into\n * this page in its place, to follow it no more.\n */\ndefineOptions({ name: 'WxFragmentField', inheritAttrs: false })\n\nconst props = withDefaults(\n defineProps<{\n modelValue?: string | null\n disabled?: boolean\n /** The shared blocks to choose from. Fetched from the panel when absent — a demo hands them in. */\n fragments?: RegionRow[] | null\n }>(),\n { modelValue: null, disabled: false, fragments: null },\n)\n\nconst emit = defineEmits<{ 'update:modelValue': [value: string | null] }>()\n\nuseBlocksMessages()\nconst t = useTranslate('webx-blocks')\nconst message = useErrorText()\n\n/* `inject` and not `useAdmin()`: a field must draw outside a panel too, in a demo or a test. */\nconst admin: AdminContext | null = inject(adminKey, null)\nconst host = inject(blocksFragmentKey, null)\n\nconst loaded = ref<RegionRow[] | null>(null)\nconst list = computed(() => props.fragments ?? loaded.value)\nconst copying = ref(false)\n\n/* Not inside itself: the shared block being edited is not one of its own choices. */\nconst choices = computed(() =>\n (list.value ?? []).filter((row) => row.name !== (host?.own.value ?? null)),\n)\n\nconst options = computed(() => choices.value.map((row) => ({ label: row.title, value: row.name })))\n\nconst chosen = computed(() => list.value?.find((row) => row.name === props.modelValue) ?? null)\n\ntype Status = 'live' | 'edits' | 'fallback' | 'empty'\n\n/**\n * What the site shows in its place. Empty counts the tree being edited, so a published shared\n * block whose draft was emptied reads «with edits» first — that is the fact that will change.\n */\nconst status = computed<Status | null>(() => {\n const row = chosen.value\n\n if (!row) return null\n if (!row.published) return 'fallback'\n if (row.has_draft) return 'edits'\n\n return row.count === 0 ? 'empty' : 'live'\n})\n\nconst badge = computed(() =>\n status.value === 'live' ? 'success' : status.value === 'edits' ? 'warning' : 'default',\n)\n\n/**\n * Where the shared block is edited: its own editor, in a new tab — the page being edited here\n * keeps its draft and its place. Only for whoever may go there, and only where the panel has the\n * section. Built from the panel's address rather than asked of the router: the panel on the site\n * draws this form in a frame that has none.\n */\nconst editHref = computed<string | null>(() => {\n const name = chosen.value?.name\n const path = admin?.modules?.find((module) => module.id === 'regions')?.path\n\n if (!name || !path || !admin?.can('blocks.regions')) return null\n\n return `${admin.basePath.replace(/\\/$/, '')}${path}/${encodeURIComponent(name)}`\n})\n\n/** Only inside a constructor, which is what can put the copies in its place. */\nconst canDetach = computed(() => host !== null && admin !== null && chosen.value !== null)\n\nfunction choose(value: unknown): void {\n emit('update:modelValue', typeof value === 'string' && value !== '' ? value : null)\n}\n\n/**\n * The shared block's published blocks, with keys of their own, in place of this one. Asked first,\n * because what it gives up is not on screen: the edits the shared block will get from now on.\n */\nasync function detach(): Promise<void> {\n const row = chosen.value\n const key = host?.selected.value\n\n if (!row || !key || !admin || !host) return\n\n const agreed = await confirm({\n title: t('fragment.detach-title', { title: row.title }),\n message: t('fragment.detach-text'),\n confirmText: t('fragment.detach'),\n cancelText: t('page.cancel'),\n })\n\n if (!agreed) return\n\n copying.value = true\n\n try {\n // The host says how it went when it has more to say than this: the panel on the site saves.\n if (await host.detach(key, await createRegionsApi(admin).copy(row.name))) {\n toast.success(t('fragment.detached', { title: row.title }))\n }\n } catch (error) {\n toast.danger(message(error))\n } finally {\n copying.value = false\n }\n}\n\nonMounted(async () => {\n if (props.fragments !== null || !admin) return\n\n try {\n loaded.value = await createBlocksApi(admin).fragments()\n } catch (error) {\n loaded.value = []\n toast.danger(message(error))\n }\n})\n</script>\n\n<template>\n <div class=\"wx-fragment-field\">\n <wx-skeleton v-if=\"list === null\" :rows=\"1\" />\n\n <template v-else>\n <wx-select\n :model-value=\"modelValue ?? null\"\n :options=\"options\"\n :placeholder=\"t('fragment.choose')\"\n :disabled=\"disabled\"\n :aria-label=\"t('fragment.choose')\"\n teleport\n @update:model-value=\"choose\"\n />\n\n <wx-text v-if=\"choices.length === 0\" size=\"sm\" tone=\"muted\">{{ t('fragment.none') }}</wx-text>\n\n <!-- A name the site no longer declares: the page prints nothing there, and says so here. -->\n <wx-text v-else-if=\"modelValue && !chosen\" size=\"sm\" tone=\"danger\">{{\n t('fragment.missing', { name: modelValue })\n }}</wx-text>\n\n <div v-if=\"chosen\" class=\"wx-fragment-field__about\">\n <div class=\"wx-fragment-field__state\">\n <wx-badge :type=\"badge\" dot>{{ t(`fragment.status-${status}`) }}</wx-badge>\n <code>{{ chosen.name }}</code>\n </div>\n\n <wx-text size=\"sm\" tone=\"muted\">{{ t('fragment.explain') }}</wx-text>\n\n <div class=\"wx-fragment-field__actions\">\n <wx-button\n v-if=\"editHref\"\n size=\"sm\"\n variant=\"outline\"\n icon=\"external-link\"\n :href=\"editHref\"\n target=\"_blank\"\n >\n {{ t('fragment.edit') }}\n </wx-button>\n <wx-button\n v-if=\"canDetach\"\n size=\"sm\"\n variant=\"outline\"\n icon=\"copy\"\n :loading=\"copying\"\n :disabled=\"disabled || !chosen.published\"\n @click=\"detach\"\n >\n {{ t('fragment.detach') }}\n </wx-button>\n </div>\n\n <!-- Said beside the button rather than left for its disabled state to explain. -->\n <wx-text v-if=\"canDetach && !chosen.published\" size=\"sm\" tone=\"muted\">{{\n t('fragment.unpublished')\n }}</wx-text>\n </div>\n </template>\n </div>\n</template>\n\n<style scoped>\n.wx-fragment-field {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n min-width: 0;\n}\n\n.wx-fragment-field__about {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n padding: var(--wx-space-10) var(--wx-space-12);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n background: var(--wx-bg-subtle);\n}\n\n.wx-fragment-field__state {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: var(--wx-space-8);\n}\n\n.wx-fragment-field__state code {\n font-size: var(--wx-font-size-xs);\n color: var(--wx-text-muted);\n}\n\n.wx-fragment-field__actions {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wx-space-8);\n}\n</style>\n","import { inject, provide, type InjectionKey, type Ref } from 'vue'\nimport type { RegionDetail } from './types'\n\n/**\n * What the region editor knows and the nodes of its screen do not.\n *\n * The editor is a described screen (`regions.form`), so a site can add a tab to it with a patch;\n * the history is a node type of that screen, and it needs the region being edited — which a\n * description cannot hand it. The page hosting the screen provides it instead.\n */\nexport interface RegionEditorContext {\n /** The region as the server last answered it, or `null` while the first request is out. */\n region: Ref<RegionDetail | null>\n /** Whether this administrator may write. */\n canManage: boolean\n /** Ask the server for the region again — after a restore. */\n reload(): Promise<void>\n}\n\nexport const regionEditorKey: InjectionKey<RegionEditorContext> = Symbol('wx-region-editor')\n\nexport function provideRegionEditor(editor: RegionEditorContext): void {\n provide(regionEditorKey, editor)\n}\n\n/** The editor above this node, or `null` outside one: a node drawn in a demo draws nothing. */\nexport function useRegionEditor(): RegionEditorContext | null {\n return inject(regionEditorKey, null)\n}\n\n/**\n * The preview address for one page of the site.\n *\n * The server signs the region and nothing else, so the page is appended by the panel: a person\n * looking at the header on the contacts page is still looking at the same region.\n */\nexport function previewAt(url: string, path: string): string {\n return `${url}${url.includes('?') ? '&' : '?'}at=${encodeURIComponent(path)}`\n}\n\n/** A site path out of whatever the link picker holds: an address typed, or a page's URL. */\nexport function sitePath(address: string | null): string | null {\n if (address === null || address.trim() === '') return null\n\n const trimmed = address.trim()\n\n try {\n // Absolute or relative alike: the base only makes `/about` parse, and is thrown away.\n const url = new URL(trimmed, 'http://site.invalid')\n\n return url.pathname || '/'\n } catch {\n return trimmed.startsWith('/') ? trimmed : `/${trimmed}`\n }\n}\n","<script setup lang=\"ts\">\nimport { computed, ref } from 'vue'\nimport {\n createLinksApi,\n emptyLink,\n useAdmin,\n useI18n,\n useTranslate,\n WxLinkPicker,\n type LinkValue,\n} from '@webx-ui/module-admin'\nimport { WxButton, WxIcon, WxPopover } from '@webx-ui/core'\nimport { useBlocksMessages } from './i18n'\nimport { sitePath } from './region'\n\n/**\n * Which page of the site the region is looked at on.\n *\n * A header is judged against the page under it, so the preview is a real address of the site\n * and this picks which one. The choice goes through the panel's own link picker — the same\n * \"what can be pointed at\" every link field uses — and what comes out is a path: the preview\n * needs where the page is, not which entity it is.\n */\ndefineOptions({ name: 'WxRegionPagePicker' })\n\nexport interface RegionPlace {\n /** The site path the preview draws, `/` for the home page. */\n path: string\n /** What was chosen, so reopening the picker shows it chosen. `null` — the home page. */\n link: LinkValue | null\n}\n\nconst place = defineModel<RegionPlace>({ required: true })\n\nconst admin = useAdmin()\nconst i18n = useI18n()\nconst links = createLinksApi(admin)\nuseBlocksMessages()\n\nconst t = useTranslate('webx-blocks')\n\nconst open = ref(false)\n\n/** Starts on an address rather than a section: \"/\" is the one place worth typing. */\nconst link = computed<LinkValue>(() => place.value.link ?? { ...emptyLink(), target: 'url' })\n\nconst label = computed(() => (place.value.path === '/' ? t('region.home') : place.value.path))\n\n/**\n * The link as the picker changes it, turned into a path once there is one.\n *\n * Half-made values are kept but not applied — a section picked and nothing searched yet — so\n * the preview does not jump to nowhere while somebody is still choosing.\n */\nasync function change(value: LinkValue | null): Promise<void> {\n if (value === null) return\n\n if (value.target === 'url') {\n place.value = { path: sitePath(value.url) ?? place.value.path, link: value }\n\n return\n }\n\n if (value.target === 'entity' && value.entity_type !== null && value.entity_id !== null) {\n const [resolved] = await links.resolve(\n [{ type: value.entity_type, id: value.entity_id }],\n i18n.state.locale,\n )\n\n place.value = { path: sitePath(resolved?.url ?? null) ?? place.value.path, link: value }\n\n return\n }\n\n place.value = { ...place.value, link: value }\n}\n\nfunction home(): void {\n place.value = { path: '/', link: null }\n open.value = false\n}\n</script>\n\n<template>\n <wx-popover\n v-model:open=\"open\"\n :title=\"t('region.choose-page')\"\n :width=\"380\"\n side=\"bottom\"\n align=\"end\"\n teleport\n >\n <template #trigger>\n <wx-button size=\"sm\" variant=\"outline\" class=\"wx-region-page-picker__trigger\">\n <wx-icon name=\"eye\" />\n <span class=\"wx-region-page-picker__words\">\n {{ t('region.shown-on') }}:\n <strong>{{ label }}</strong>\n </span>\n <wx-icon name=\"chevron-down\" />\n </wx-button>\n </template>\n\n <div class=\"wx-region-page-picker\">\n <wx-link-picker\n :model-value=\"link\"\n :allow-none=\"false\"\n :attributes=\"false\"\n @update:model-value=\"change\"\n />\n <wx-button size=\"sm\" variant=\"text\" :disabled=\"place.path === '/'\" @click=\"home\">\n <wx-icon name=\"home\" />\n {{ t('region.back-home') }}\n </wx-button>\n </div>\n </wx-popover>\n</template>\n\n<style scoped>\n.wx-region-page-picker {\n display: flex;\n flex-direction: column;\n align-items: stretch;\n gap: var(--wx-space-12);\n}\n\n.wx-region-page-picker > :deep(.wx-button) {\n align-self: flex-start;\n}\n\n/* The path can be long; the button stays one line and the path is what gets cut. */\n.wx-region-page-picker__words {\n max-width: 260px;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, ref, watch } from 'vue'\nimport { onBeforeRouteLeave, useRoute, useRouter } from 'vue-router'\nimport {\n useAdmin,\n useEditing,\n useErrorText,\n useTranslate,\n WxEditingAlerts,\n WxSaveState,\n WxScreen,\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 WxSkeleton,\n WxText,\n} from '@webx-ui/core'\nimport type { ScreenModel } from '@webx-ui/schema'\nimport { createRegionsApi } from './api'\nimport { useBlocksMessages } from './i18n'\nimport { provideBlocksPreview, provideBlocksTop, type BlocksTop } from './preview'\nimport { previewAt, provideRegionEditor, sitePath } from './region'\nimport RegionPagePicker, { type RegionPlace } from './RegionPagePicker.vue'\nimport type { BlockNode, FragmentUse, RegionConflict, RegionDetail } from './types'\n\n/**\n * The editor of one layout region: the page editor without what a region does not have — no\n * address, no SEO, no template of its own.\n *\n * Between the head and the bar is `regions.form`, a described screen, so a site adds a tab with\n * a patch as it would to a page. What the screen cannot know is which region it is — its name in\n * `allowed_in`, its `allow` and `max` from the config — and where to preview it; this page\n * provides both.\n *\n * Saving is by autosave, as on a page; publishing, taking off and discarding are asked about,\n * because each of them changes what every page of the site shows.\n */\ndefineOptions({ name: 'WxRegionEditorPage' })\n\nconst props = withDefaults(defineProps<{ base?: string }>(), { base: '/regions' })\n\nconst context = useAdmin()\nconst api = createRegionsApi(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\n/** How long after the last change the draft goes to the server. */\nconst PAUSE = 1200\n\nconst name = computed(() => String(route.params.name ?? ''))\n\nconst region = ref<RegionDetail | null>(null)\nconst values = ref<ScreenModel>({ blocks: [] })\nconst revision = ref('')\n\nconst loading = ref(true)\nconst saving = ref(false)\nconst working = ref(false)\nconst errors = ref<Record<string, string[]>>({})\n\nconst snapshot = ref('')\nconst reloadToken = ref(0)\nconst screenKey = ref(0)\n\n/* `can()` answers a plain boolean; wrapped here so the template and the guards read one thing. */\nconst canManage = computed(() => context.can('blocks.regions'))\n\n/*\n * Other people on the same region: a refused save is merged with theirs block by block and saved\n * again, and only a block both sides changed is asked about. The form is `{ blocks }` — the shape\n * the screen edits — so the merge walks the tree the same way it walks a page's.\n */\nconst editing = useEditing<ScreenModel>({\n entity: 'regions',\n id: () => region.value?.name,\n values,\n revision,\n read: async () => {\n const detail = await api.get(name.value)\n\n return { values: { blocks: detail.blocks }, revision: detail.revision }\n },\n adopt: (theirs) => {\n snapshot.value = JSON.stringify(theirs.values)\n reloadToken.value += 1\n },\n // Published or taken off by somebody else: the badge follows, and the form stays as it is.\n // No `restore`: a region is declared by the code, so there is no bin to take it out of.\n refresh: () => refresh(),\n canWrite: () => canManage.value,\n busy: () => saving.value || flight !== undefined,\n screen: 'regions.form',\n})\n\nconst conflict = editing.conflict\n\nconst current = computed(() => JSON.stringify(values.value))\nconst dirty = computed(() => snapshot.value !== '' && current.value !== snapshot.value)\n\nconst tree = computed<BlockNode[]>(() =>\n Array.isArray(values.value.blocks) ? (values.value.blocks as BlockNode[]) : [],\n)\n\nconst state = computed<'saving' | 'unsaved' | 'saved'>(() => {\n if (saving.value) return 'saving'\n\n return dirty.value ? 'unsaved' : 'saved'\n})\n\n/* Which page of the site the region is looked at on, remembered per region in this browser. */\nconst place = ref<RegionPlace>({ path: '/', link: null })\n\n/* Whether somebody chose the page here, or it is the one the editor started on. */\nconst chosenPlace = ref(false)\n\nconst storageKey = computed(() => `webx.regions.at.${name.value}`)\n\nfunction readPlace(): RegionPlace | null {\n try {\n const stored = JSON.parse(\n localStorage.getItem(storageKey.value) ?? 'null',\n ) as RegionPlace | null\n\n if (stored && typeof stored.path === 'string' && stored.path.startsWith('/')) return stored\n } catch {\n // Private windows and blocked storage throw on the accessor itself: the home page it is.\n }\n\n return null\n}\n\n/**\n * A page picked — in the picker, or from where the shared block stands — and remembered. Only a\n * pick is: the page the editor starts on by itself is a guess, and a stored guess would outlive\n * the page it guessed.\n */\nfunction pickPlace(next: RegionPlace): void {\n place.value = next\n chosenPlace.value = true\n\n try {\n localStorage.setItem(storageKey.value, JSON.stringify(next))\n } catch {\n // Not remembered, which is all that is lost.\n }\n}\n\n/**\n * Where a shared block is looked at before anybody chose: the first page that places it, what the\n * site shows before a draft — not the home page, which more often than not does not hold it, and\n * then the preview is the stage with a notice instead of the block among its neighbours.\n */\nfunction firstPlace(detail: RegionDetail): RegionPlace | null {\n const uses = (detail.used_on ?? []).filter((use) => use.url)\n const use = uses.find((one) => one.live !== false) ?? uses[0]\n const path = sitePath(use?.url ?? null)\n\n return path ? { path, link: null } : null\n}\n\n/** The records that place this shared block; nothing for a region of the layout. */\nconst usedOn = computed<FragmentUse[]>(() => region.value?.used_on ?? [])\n\nfunction showOn(use: FragmentUse): void {\n const path = sitePath(use.url ?? null)\n\n if (path) pickPlace({ path, link: null })\n}\n\nconst previewUrl = computed(() =>\n region.value ? previewAt(region.value.preview_url, place.value.path) : null,\n)\n\nprovideBlocksPreview({ url: previewUrl, reload: reloadToken })\n\nprovideBlocksTop(\n computed<BlocksTop | null>(() =>\n region.value\n ? {\n root: `region:${region.value.name}`,\n label: region.value.title,\n allow: region.value.allow,\n max: region.value.max,\n // A shared block is wherever the page put it: the preview frames it and goes there.\n frame: region.value.fragment ? region.value.name : null,\n }\n : null,\n ),\n)\n\nprovideRegionEditor({ region, canManage: canManage.value, reload: () => load(true) })\n\nfunction take(detail: RegionDetail): void {\n region.value = detail\n values.value = { blocks: detail.blocks }\n revision.value = detail.revision\n snapshot.value = JSON.stringify(values.value)\n editing.opened(values.value)\n conflict.value = null\n}\n\nasync function load(silent = false): Promise<void> {\n if (!silent) loading.value = true\n\n try {\n const detail = await api.get(name.value)\n\n take(detail)\n\n if (!chosenPlace.value && detail.fragment) place.value = firstPlace(detail) ?? place.value\n\n reloadToken.value += 1\n } catch (error) {\n toast.danger(message(error))\n void router.push(props.base)\n } finally {\n loading.value = false\n }\n}\n\n/**\n * What surrounds the form, read again: the region with its status. Not the blocks — the form is\n * somebody's work in progress, and a change of its content is the notice's to offer.\n */\nasync function refresh(): Promise<void> {\n try {\n region.value = await api.get(name.value)\n } catch {\n // The heartbeat says what happened; a region that could not be read again stays as it was.\n }\n}\n\n/* One pending save at a time, and one pending pause. */\nlet timer: ReturnType<typeof setTimeout> | undefined\n\nfunction schedule(): void {\n if (!canManage.value || conflict.value || !dirty.value || editing.stopped.value) return\n\n clearTimeout(timer)\n timer = setTimeout(() => void save(), PAUSE)\n}\n\nfunction onFocusOut(): void {\n if (!canManage.value || conflict.value || !dirty.value || saving.value || editing.stopped.value)\n return\n\n clearTimeout(timer)\n void save()\n}\n\n/* The save on its way, and what it carries. */\nlet flight: { carried: string; done: Promise<void> } | undefined\n\n/** A save asked for while another is out waits for it rather than being dropped (as pages). */\nasync function save(): Promise<void> {\n while (flight) {\n const { carried, done } = flight\n\n await done\n\n if (!dirty.value || conflict.value || current.value === carried) return\n }\n\n const carried = current.value\n const done = write()\n\n flight = { carried, done }\n\n try {\n await done\n } finally {\n if (flight?.done === done) flight = undefined\n }\n}\n\nasync function write(): Promise<void> {\n if (!region.value || !canManage.value) return\n\n clearTimeout(timer)\n\n // What is being sent, so that anything changed while the request is out stays dirty.\n const sending = current.value\n const sent = values.value\n const blocks = tree.value\n\n saving.value = true\n errors.value = {}\n\n try {\n const detail = await api.save(region.value.name, { blocks, revision: revision.value })\n\n region.value = detail\n revision.value = detail.revision\n conflict.value = null\n\n if (current.value === sending) snapshot.value = sending\n\n // What the server holds now is what was sent: the base of the next merge.\n editing.opened(sent)\n\n // The preview draws the draft, and the draft is what was just written.\n reloadToken.value += 1\n } catch (error) {\n const failure = error as {\n status?: number\n body?: Partial<RegionConflict> & { errors?: Record<string, string[]> }\n }\n\n if (failure.status === 409 && failure.body?.data) {\n const theirs = failure.body.data\n const merged = editing.refused({\n values: { blocks: theirs.blocks },\n revision: theirs.revision,\n changed: failure.body.changed,\n })\n\n // Nothing overlapping: both edits are in the form now, and they go to the server again.\n if (merged) {\n region.value = theirs\n void save()\n }\n } else if (failure.body?.errors) {\n errors.value = failure.body.errors\n toast.danger(t('region.save-failed'))\n } else if (!(await editing.failed(error))) {\n toast.danger(message(error))\n }\n } finally {\n saving.value = false\n }\n}\n\n/** Give up what was written and take the region as it now is; the component asked first. */\nasync function takeTheirs(): Promise<void> {\n await load(true)\n}\n\n/**\n * Run one of the three actions that change the site, after the question and a save.\n *\n * Saving first, because each of them works on the draft the server holds: publishing a region\n * with the last second of edits still in the pause would publish without them.\n */\nasync function act(\n words: {\n title: string\n text: string\n confirm: string\n done: string\n danger?: boolean\n publishing?: boolean\n },\n call: (name: string, revision?: string) => Promise<RegionDetail>,\n): Promise<void> {\n if (!region.value) return\n\n // Publishing saves before the question rather than after: the draft on the server may hold\n // somebody else's edit this editor never pulled in, and that is said before it goes on the\n // site — with whose it is and where — rather than published unseen.\n let held: { revision: string; asked: boolean } | null = null\n\n if (words.publishing) {\n if (dirty.value) await save()\n if (conflict.value || dirty.value) return\n\n held = await editing.beforePublish()\n\n if (!held) return\n }\n\n // One question is enough: whoever just agreed to publish somebody else's changes has said yes.\n const agreed =\n held?.asked ||\n (await confirm({\n title: words.title,\n message: words.text,\n confirmText: words.confirm,\n cancelText: t('region.cancel'),\n tone: words.danger ? 'danger' : undefined,\n }))\n\n if (!agreed) return\n\n if (dirty.value) await save()\n if (conflict.value || dirty.value || !region.value) return\n\n working.value = true\n\n try {\n take(await call(region.value.name, held?.revision))\n reloadToken.value += 1\n toast.success(words.done)\n } catch (error) {\n // A block that cannot be drawn refuses the publication by name; that sentence is the\n // server's to say, since only it rendered the region.\n const refused = (error as { body?: { errors?: Record<string, string[]> } }).body?.errors\n ?.blocks?.[0]\n\n if (refused) toast.danger(refused)\n else if (!(await editing.failed(error))) toast.danger(message(error))\n } finally {\n working.value = false\n }\n}\n\nfunction publish(): Promise<void> {\n const title = region.value?.title ?? ''\n\n return act(\n {\n title: t('region.publish-title', { title }),\n text: region.value?.fragment ? t('fragment.publish-text') : t('region.publish-text'),\n confirm: t('region.publish'),\n done: t('region.published'),\n publishing: true,\n },\n (region, revision) => api.publish(region, revision),\n )\n}\n\nfunction unpublish(): Promise<void> {\n const title = region.value?.title ?? ''\n\n return act(\n {\n title: t('region.unpublish-title', { title }),\n text: t('region.unpublish-text'),\n confirm: t('region.unpublish'),\n done: t('region.unpublished'),\n danger: true,\n },\n (region) => api.unpublish(region),\n )\n}\n\nfunction discard(): Promise<void> {\n const title = region.value?.title ?? ''\n\n return act(\n {\n title: t('region.discard-title', { title }),\n text: t('region.discard-text'),\n confirm: t('region.discard'),\n done: t('region.discarded'),\n danger: true,\n },\n (region) => api.discardDraft(region),\n )\n}\n\n/** The code's view made into a block type, with one of it put in the draft (§7.3). */\nasync function adopt(): Promise<void> {\n if (!region.value) return\n\n if (dirty.value) await save()\n\n working.value = true\n\n try {\n const adopted = await api.adopt(region.value.name)\n\n take(adopted.region)\n reloadToken.value += 1\n // The constructor reads the catalogue once, when it mounts, and the type that was just made\n // is not in it: drawn again, the new block gets its title and its form rather than a slug.\n screenKey.value += 1\n toast.success(t('region.adopted', { slug: adopted.block.slug }))\n } catch (error) {\n toast.danger(message(error))\n } finally {\n working.value = false\n }\n}\n\ntype Status = 'live' | 'modified' | 'fallback'\n\nconst status = computed<Status>(() => {\n if (!region.value?.published) return 'fallback'\n\n return region.value.has_draft || dirty.value ? 'modified' : 'live'\n})\n\nconst badge = computed(() =>\n status.value === 'live' ? 'success' : status.value === 'modified' ? 'warning' : 'default',\n)\n\nconst actions = computed<ScreenAction[]>(() =>\n previewUrl.value\n ? [\n {\n key: 'preview',\n label: t('region.preview'),\n icon: 'external-link',\n href: previewUrl.value,\n },\n ]\n : [],\n)\n\nfunction leaveGuard(event: BeforeUnloadEvent): void {\n if (dirty.value) event.preventDefault()\n}\n\nwatch(current, schedule)\n\nwatch(\n name,\n () => {\n const stored = readPlace()\n\n place.value = stored ?? { path: '/', link: null }\n chosenPlace.value = stored !== null\n void load()\n },\n { immediate: true },\n)\n\nonMounted(() => {\n window.addEventListener('beforeunload', leaveGuard)\n})\n\nonBeforeUnmount(() => {\n clearTimeout(timer)\n window.removeEventListener('beforeunload', leaveGuard)\n})\n\n/* Leaving flushes the pause rather than asking, and asks only when the save did not go through. */\nonBeforeRouteLeave(async () => {\n if (!dirty.value || !canManage.value) return true\n\n await save()\n\n if (!dirty.value) return true\n\n return await confirm({\n title: t('region.leave-title'),\n message: t('region.leave-text'),\n confirmText: t('region.leave'),\n cancelText: t('region.cancel'),\n tone: 'danger',\n })\n})\n</script>\n\n<template>\n <div class=\"wx-region-editor\" @focusout=\"onFocusOut\">\n <template v-if=\"loading || !region\">\n <wx-skeleton class=\"wx-region-editor__ghost\" title :rows=\"1\" />\n <wx-card><wx-skeleton :rows=\"8\" /></wx-card>\n </template>\n\n <template v-else>\n <wx-screen-head\n divider\n :back=\"base\"\n :back-label=\"t('region.title')\"\n :title=\"region.title\"\n :subtitle=\"region.description ?? undefined\"\n :actions=\"actions\"\n >\n <template #title-after>\n <wx-badge :type=\"badge\" dot>{{ t(`region.status-${status}`) }}</wx-badge>\n </template>\n\n <template #extra>\n <region-page-picker :model-value=\"place\" @update:model-value=\"pickPlace\" />\n </template>\n </wx-screen-head>\n\n <!-- Somebody else wrote while this editor was open. What does not overlap is merged\n without a word; what does is listed block by block. -->\n <wx-editing-alerts :editing=\"editing\" @save=\"save\" @theirs=\"takeTheirs\" />\n\n <!--\n While the tree is empty the site prints the view from the code, and the preview shows\n exactly that — so the page says which view it is and how to replace it, rather than\n leaving a header that is plainly there beside a constructor that says \"no blocks\".\n -->\n <wx-alert\n v-if=\"tree.length === 0\"\n class=\"wx-region-editor__empty\"\n type=\"info\"\n variant=\"soft\"\n :title=\"t('region.empty-title')\"\n :description=\"\n region.fallback\n ? t('region.empty-text', { view: region.fallback })\n : t('region.empty-text-none')\n \"\n >\n <template v-if=\"region.can_adopt && canManage\" #actions>\n <wx-button size=\"sm\" variant=\"outline\" :loading=\"working\" @click=\"adopt\">\n {{ t('region.adopt') }}\n </wx-button>\n </template>\n </wx-alert>\n\n <!--\n Where a shared block stands — the records whose content places it. Each one is a page to\n look at it on, which is what a list of places is for in front of a preview; a shared block\n inside another one leads to that one's editor. Templates that print the tag are not\n content, and the line under the list says they are not counted rather than leaving the\n list to look complete.\n -->\n <div v-if=\"region.fragment\" class=\"wx-region-editor__where\">\n <span class=\"wx-region-editor__where-label\">{{ t('fragment.used-on') }}</span>\n <template v-if=\"usedOn.length\">\n <template v-for=\"use in usedOn\" :key=\"`${use.model}:${use.id}`\">\n <router-link\n v-if=\"use.region\"\n :to=\"`${base}/${encodeURIComponent(use.region)}`\"\n class=\"wx-region-editor__use\"\n >\n {{ use.title ?? use.region }}\n </router-link>\n <button\n v-else-if=\"use.url\"\n type=\"button\"\n class=\"wx-region-editor__use\"\n :class=\"{ 'is-active': sitePath(use.url) === place.path }\"\n :aria-pressed=\"sitePath(use.url) === place.path\"\n :title=\"t('fragment.show-here')\"\n @click=\"showOn(use)\"\n >\n {{ use.title ?? `#${use.id}` }}\n <wx-badge v-if=\"use.live === false\" type=\"warning\" size=\"sm\">{{\n t('fragment.draft-only')\n }}</wx-badge>\n </button>\n <span v-else class=\"wx-region-editor__use is-plain\">{{\n use.title ?? `#${use.id}`\n }}</span>\n </template>\n </template>\n <wx-text v-else size=\"sm\" tone=\"muted\">{{ t('fragment.used-nowhere') }}</wx-text>\n <wx-text size=\"sm\" tone=\"muted\" class=\"wx-region-editor__where-note\">{{\n t('fragment.templates')\n }}</wx-text>\n </div>\n\n <div class=\"wx-region-editor__screen\">\n <wx-screen\n :key=\"screenKey\"\n v-model=\"values\"\n name=\"regions.form\"\n :errors=\"errors\"\n :disabled=\"!canManage || working\"\n />\n </div>\n\n <wx-action-bar v-if=\"canManage\">\n <template #state>\n <wx-save-state v-if=\"!editing.stopped.value\" :state=\"state\" />\n </template>\n\n <wx-button v-if=\"region.published\" variant=\"text\" :disabled=\"working\" @click=\"unpublish\">\n {{ t('region.unpublish') }}\n </wx-button>\n\n <wx-button\n v-if=\"region.has_draft && region.published\"\n variant=\"text\"\n :disabled=\"working\"\n @click=\"discard\"\n >\n {{ t('region.discard') }}\n </wx-button>\n\n <wx-button\n variant=\"outline\"\n :loading=\"saving\"\n :disabled=\"!dirty || editing.stopped.value\"\n :title=\"editing.blocked.value\"\n @click=\"save\"\n >\n {{ t('region.save') }}\n </wx-button>\n\n <wx-button\n type=\"primary\"\n :loading=\"working\"\n :disabled=\"editing.stopped.value || (region.published && !region.has_draft && !dirty)\"\n :title=\"editing.blocked.value\"\n @click=\"publish\"\n >\n {{ t('region.publish') }}\n </wx-button>\n </wx-action-bar>\n </template>\n </div>\n</template>\n\n<style scoped>\n.wx-region-editor {\n display: flex;\n flex-direction: column;\n gap: var(--wx-gap, var(--wx-space-16));\n height: 100%;\n min-height: 0;\n container-type: inline-size;\n}\n\n.wx-region-editor__ghost {\n max-width: 420px;\n}\n\n.wx-region-editor__where {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wx-space-6) var(--wx-space-8);\n min-width: 0;\n}\n\n.wx-region-editor__where-label {\n font-size: var(--wx-font-size-sm);\n font-weight: var(--wx-font-weight-semibold);\n color: var(--wx-text-strong);\n}\n\n/* A row of pages, each a press away from the preview: chips rather than links, since they stay. */\n.wx-region-editor__use {\n display: inline-flex;\n align-items: center;\n gap: var(--wx-space-6);\n min-width: 0;\n max-width: 100%;\n padding: var(--wx-space-2) var(--wx-space-10);\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-text-default);\n font: inherit;\n font-size: var(--wx-font-size-sm);\n text-decoration: none;\n overflow-wrap: anywhere;\n cursor: pointer;\n}\n\n.wx-region-editor__use:hover {\n border-color: var(--wx-border-strong);\n}\n\n.wx-region-editor__use:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n.wx-region-editor__use.is-active {\n border-color: var(--wx-color-primary);\n color: var(--wx-text-link);\n}\n\n.wx-region-editor__use.is-plain {\n cursor: default;\n}\n\n/* Its own line: a note about the list, not one more place in it. */\n.wx-region-editor__where-note {\n flex-basis: 100%;\n}\n\n.wx-region-editor__screen {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n}\n\n/*\n * The height travels through the screen's own boxes, as on the page editor: each is a flex\n * column that may shrink — and only the tab on screen, since `display: flex` on a kept-alive\n * hidden tab would override its `[hidden]` and split the height between all of them (§4).\n */\n.wx-region-editor__screen :deep(.wx-screen-host),\n.wx-region-editor__screen :deep(.wx-screen),\n.wx-region-editor__screen :deep(.wx-tabs),\n.wx-region-editor__screen :deep(.wx-tabs__layout),\n.wx-region-editor__screen :deep(.wx-tabs__panels),\n.wx-region-editor__screen :deep(.wx-tab:not([hidden])) {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-height: 0;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, ref, watch } from 'vue'\nimport { useAdmin, useErrorText, useTranslate, WxDate, WxDrafts } from '@webx-ui/module-admin'\nimport { confirm, toast, WxBadge, WxButton, WxEmpty, WxSkeleton, WxText } from '@webx-ui/core'\nimport { createRegionsApi } from './api'\nimport { useBlocksMessages } from './i18n'\nimport { useRegionEditor } from './region'\nimport type { RegionVersion } from './types'\n\n/**\n * What was published in the region, when and by whom — the `wx-region-history` node of\n * `regions.form`.\n *\n * Publications first, and the copies of the draft — autosaves, a draft somebody else's save wrote\n * over — in a list of their own under them, as with pages. Restoring makes an old version the\n * draft, and publishing it is the usual separate step — so nothing here changes the site by\n * itself, and a header cannot be swapped by one slip in a list.\n */\ndefineOptions({ name: 'WxRegionHistory' })\n\nconst context = useAdmin()\nconst api = createRegionsApi(context)\nconst editor = useRegionEditor()\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 versions = ref<RegionVersion[] | null>(null)\nconst working = ref(false)\n\nconst region = computed(() => editor?.region.value ?? null)\nconst canManage = computed(() => editor?.canManage ?? false)\n\n/** The newest publication is the site — while the region is on it at all. */\nconst live = computed(() =>\n region.value?.published ? (versions.value?.[0]?.number ?? null) : null,\n)\n\nasync function load(): Promise<void> {\n const current = region.value\n\n // Never saved: no row, so no history to ask for.\n if (!current || current.id === null) {\n versions.value = current ? [] : null\n\n return\n }\n\n try {\n versions.value = await api.versions(current.name)\n } catch (error) {\n versions.value = []\n toast.danger(message(error))\n }\n}\n\nasync function restore(version: RegionVersion): Promise<void> {\n const current = region.value\n\n if (!current) return\n\n const agreed = await confirm({\n title: t('region.restore-title', { number: version.number }),\n message: t('region.restore-text'),\n confirmText: t('region.restore'),\n cancelText: t('region.cancel'),\n })\n\n if (!agreed) return\n\n working.value = true\n\n try {\n await api.restoreVersion(current.name, version.number)\n // Through the editor rather than with the answer: its values are what the constructor is\n // bound to, and a version restored underneath it has to reach the tree.\n await editor?.reload()\n toast.success(t('region.restored-version', { number: version.number }))\n } catch (error) {\n toast.danger(message(error))\n } finally {\n working.value = false\n }\n}\n\n// The region is read again after every publication and restore; its stamps say when to list.\nwatch(\n () => [region.value?.name, region.value?.published_at, region.value?.updated_at],\n () => void load(),\n { immediate: true },\n)\n</script>\n\n<template>\n <div class=\"wx-region-history-tab\">\n <div class=\"wx-region-history\">\n <wx-skeleton v-if=\"versions === null\" class=\"wx-region-history__ghost\" :rows=\"3\" />\n <wx-empty v-else-if=\"versions.length === 0\" :description=\"t('region.history-empty')\" />\n <div\n v-for=\"version in versions\"\n v-else\n :key=\"version.number\"\n class=\"wx-region-history__row\"\n :class=\"{ 'is-live': version.number === live }\"\n >\n <code class=\"wx-region-history__number\">{{\n t('region.version', { number: version.number })\n }}</code>\n <div class=\"wx-region-history__who\">\n <wx-date v-if=\"version.created_at\" :value=\"version.created_at\" size=\"md\" tone=\"default\" />\n <wx-text size=\"sm\" tone=\"muted\">\n {{ version.author?.name ?? t(`region.source-${version.source}`) }}\n <template v-if=\"version.comment\"> · {{ version.comment }}</template>\n </wx-text>\n </div>\n <wx-badge v-if=\"version.number === live\" type=\"success\" dot>{{\n t('region.version-live')\n }}</wx-badge>\n <wx-button\n v-if=\"canManage && version.number !== live\"\n size=\"sm\"\n variant=\"outline\"\n :loading=\"working\"\n @click=\"restore(version)\"\n >\n {{ t('region.restore') }}\n </wx-button>\n </div>\n </div>\n\n <wx-drafts\n :id=\"region?.name\"\n entity=\"regions\"\n screen=\"regions.form\"\n :can-restore=\"canManage\"\n :stamp=\"[region?.published_at, region?.updated_at]\"\n @restored=\"editor?.reload()\"\n />\n </div>\n</template>\n\n<style scoped>\n.wx-region-history-tab {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-24);\n}\n\n.wx-region-history {\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 /* Clip, not hidden: rounding the rows' corners needs no scroll container (§4). */\n overflow: clip;\n}\n\n.wx-region-history__ghost {\n padding: var(--wx-space-10) var(--wx-space-12);\n}\n\n.wx-region-history__row {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\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-default);\n}\n\n.wx-region-history__row:last-child {\n border-block-end: 0;\n}\n\n.wx-region-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-region-history__who {\n display: flex;\n flex-direction: column;\n flex: 1;\n min-width: 160px;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onMounted, ref } from 'vue'\nimport { useAdmin, useErrorText, useTranslate, WxDate, WxScreenHead } from '@webx-ui/module-admin'\nimport { toast, WxBadge, WxEmpty, WxIcon, WxSkeleton, WxText } from '@webx-ui/core'\nimport { createRegionsApi } from './api'\nimport { useBlocksMessages } from './i18n'\nimport type { RegionRow } from './types'\n\n/**\n * The layout regions of the site: one card each.\n *\n * Not a table. A site declares two regions, the header and the footer, and a table of two rows\n * is a heading row and a lot of empty width — while what a reader wants from each is a sentence:\n * is the site showing the blocks or the code, and which view of the code.\n */\ndefineOptions({ name: 'WxRegionsPage' })\n\nconst props = withDefaults(defineProps<{ base?: string }>(), { base: '/regions' })\n\nconst context = useAdmin()\nconst api = createRegionsApi(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 regions = ref<RegionRow[] | null>(null)\n\n/**\n * The regions of the layout, then the shared blocks (§4.3 of the shared blocks spec): the first are\n * on every page, the second wherever somebody put them, and one list of both read as if the\n * request form stood on every page like the header. A site without shared blocks gets the one\n * list it always had, without a heading over it.\n */\nconst sections = computed(() => {\n const rows = regions.value ?? []\n const shared = rows.filter((row) => row.fragment === true)\n\n if (shared.length === 0) return [{ key: 'all', title: null, help: null, rows }]\n\n return [\n {\n key: 'layout',\n title: t('fragment.group-layout'),\n help: null,\n rows: rows.filter((row) => row.fragment !== true),\n },\n {\n key: 'shared',\n title: t('fragment.group-shared'),\n help: t('fragment.group-shared-help'),\n rows: shared,\n },\n ].filter((section) => section.rows.length > 0)\n})\n\n/**\n * The state as one chip, and a second one only when it adds something: a region on the site with\n * edits waiting is two facts, and folding them into one word would hide either.\n */\nfunction chips(region: RegionRow): { label: string; type: 'success' | 'warning' | 'default' }[] {\n if (region.published) {\n const live = { label: t('region.state-live'), type: 'success' as const }\n\n return region.has_draft ? [live, { label: t('region.state-edits'), type: 'warning' }] : [live]\n }\n\n // Never saved, or taken off the site: either way the site prints the code's view. A draft\n // that exists is said beside it, because it is what the next \"Publish\" would put there.\n const fallback = { label: t('region.state-fallback'), type: 'default' as const }\n\n return region.has_draft\n ? [fallback, { label: t('region.state-draft'), type: 'warning' }]\n : [fallback]\n}\n\nonMounted(async () => {\n try {\n regions.value = await api.list()\n } catch (error) {\n regions.value = []\n toast.danger(message(error))\n }\n})\n</script>\n\n<template>\n <div class=\"wx-regions\">\n <wx-screen-head :title=\"t('region.title')\" :subtitle=\"t('region.intro')\" />\n\n <div v-if=\"regions === null\" class=\"wx-regions__grid\">\n <div v-for=\"index in 2\" :key=\"index\" class=\"wx-regions__card\">\n <wx-skeleton title :rows=\"2\" />\n </div>\n </div>\n\n <wx-empty\n v-else-if=\"regions.length === 0\"\n :title=\"t('region.empty')\"\n :description=\"t('region.empty-help')\"\n />\n\n <template v-else>\n <section\n v-for=\"section in sections\"\n :key=\"section.key\"\n class=\"wx-regions__section\"\n :aria-label=\"section.title ?? undefined\"\n >\n <div v-if=\"section.title\" class=\"wx-regions__head\">\n <h2 class=\"wx-regions__heading\">{{ section.title }}</h2>\n <wx-text v-if=\"section.help\" size=\"sm\" tone=\"muted\">{{ section.help }}</wx-text>\n </div>\n\n <div class=\"wx-regions__grid\">\n <router-link\n v-for=\"region in section.rows\"\n :key=\"region.name\"\n :to=\"`${props.base}/${encodeURIComponent(region.name)}`\"\n class=\"wx-regions__card is-link\"\n >\n <div class=\"wx-regions__top\">\n <span class=\"wx-regions__title\">{{ region.title }}</span>\n <code class=\"wx-regions__name\">{{ region.name }}</code>\n </div>\n\n <wx-text\n v-if=\"region.description\"\n size=\"sm\"\n tone=\"muted\"\n class=\"wx-regions__description\"\n >\n {{ region.description }}\n </wx-text>\n\n <div class=\"wx-regions__chips\">\n <wx-badge v-for=\"chip in chips(region)\" :key=\"chip.label\" :type=\"chip.type\" dot>\n {{ chip.label }}\n </wx-badge>\n </div>\n\n <div class=\"wx-regions__meta\">\n <wx-text size=\"sm\" tone=\"muted\">{{\n t('region.count', { count: region.count })\n }}</wx-text>\n <!-- Where it stands, for a shared block: a header is on every page and says nothing. -->\n <wx-text v-if=\"region.fragment && region.used_on\" size=\"sm\" tone=\"muted\">\n {{\n region.used_on.length\n ? t('fragment.count', { count: region.used_on.length })\n : t('fragment.used-nowhere')\n }}\n </wx-text>\n <wx-text size=\"sm\" tone=\"muted\">\n {{\n region.fallback\n ? t('region.fallback-view', { view: region.fallback })\n : t('region.fallback-none')\n }}\n </wx-text>\n <wx-date v-if=\"region.updated_at\" :value=\"region.updated_at\" size=\"sm\" tone=\"muted\" />\n </div>\n\n <wx-icon name=\"chevron-right\" class=\"wx-regions__go\" aria-hidden=\"true\" />\n </router-link>\n </div>\n </section>\n </template>\n </div>\n</template>\n\n<style scoped>\n.wx-regions {\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-regions__section {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n}\n\n.wx-regions__head {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-2);\n}\n\n.wx-regions__heading {\n margin: 0;\n font-size: var(--wx-font-size-md);\n font-weight: var(--wx-font-weight-semibold);\n color: var(--wx-text-strong);\n}\n\n/* Side by side while each card keeps room for its sentence; one above the other on a phone. */\n.wx-regions__grid {\n display: grid;\n grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));\n gap: var(--wx-gap, var(--wx-space-16));\n}\n\n.wx-regions__card {\n position: relative;\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n min-width: 0;\n padding: var(--wx-space-16);\n padding-inline-end: var(--wx-space-40);\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-md);\n background: var(--wx-bg-surface);\n box-shadow: var(--wx-shadow-card);\n color: var(--wx-text-default);\n text-decoration: none;\n}\n\n.wx-regions__card.is-link {\n transition: border-color var(--wx-duration-fast);\n}\n\n.wx-regions__card.is-link:hover {\n border-color: var(--wx-border-strong);\n}\n\n.wx-regions__card.is-link:focus-visible {\n outline: none;\n box-shadow: var(--wx-ring-focus);\n}\n\n.wx-regions__top {\n display: flex;\n flex-wrap: wrap;\n align-items: baseline;\n gap: var(--wx-space-8);\n}\n\n.wx-regions__title {\n font-size: var(--wx-font-size-lg);\n font-weight: var(--wx-font-weight-semibold);\n color: var(--wx-text-strong);\n}\n\n.wx-regions__name {\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-regions__chips {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wx-space-6);\n}\n\n.wx-regions__meta {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wx-space-4) var(--wx-space-12);\n /* A view name is one long word; without this it pushes the card wider than its column. */\n overflow-wrap: anywhere;\n}\n\n.wx-regions__go {\n position: absolute;\n inset-block-start: 50%;\n inset-inline-end: var(--wx-space-12);\n translate: 0 -50%;\n color: var(--wx-text-muted);\n}\n</style>\n","import {\n screenLabels,\n type AdminContext,\n type AdminModule,\n type BlockLabels,\n} from '@webx-ui/module-admin'\nimport { markRaw } from 'vue'\nimport { createBlocksApi } from './api'\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'\nimport BlocksSiteBarTab from './BlocksSiteBarTab.vue'\nimport FragmentField from './FragmentField.vue'\nimport { seedBlocksMessages } from './i18n'\nimport RegionEditorPage from './RegionEditorPage.vue'\nimport RegionHistory from './RegionHistory.vue'\nimport RegionsPage from './RegionsPage.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 blockLabels,\n // «Blocks» in the panel on the site (§8 of WEBX_UI_SITE_BAR.md): where the server offers it\n // — a record with blocks, for somebody who may edit it, and the layout's regions, for\n // somebody who edits those. One tab for both: the page has one picker, and a click on the\n // header should not have to know which tab it belongs to.\n siteBarTabs: [\n {\n name: 'blocks',\n sections: ['regions'],\n label: (admin) => {\n seedBlocksMessages(admin.i18n)\n\n return admin.i18n.scope('webx-blocks')('site-bar.tab')\n },\n component: markRaw(BlocksSiteBarTab),\n },\n ],\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 // «Shared block»: which shared block of the site this place on a page shows — a region\n // declared with `fragment`, edited once in «Site regions» (§4.1 of the shared blocks spec).\n 'wx-fragment': { component: FragmentField, kind: 'field' },\n },\n }\n}\n\nexport interface RegionsOptions {\n /** Where the section lives inside the panel. */\n path?: string\n}\n\n/**\n * The layout regions — the header and the footer made of blocks — as a section of their own.\n *\n * A second module rather than two more routes of `blocks()`: the navigation is one entry per\n * module, and this one stands in a different place for a different person. Blocks is the\n * developer's section, closed by `blocks.manage` because a template is code; the header is\n * edited by whoever edits the pages, under `blocks.regions`. The id matches the module the\n * server reports, which is what puts the entry in the menu.\n */\nexport function regions(options: RegionsOptions = {}): AdminModule {\n const path = options.path ?? '/regions'\n\n return {\n id: 'regions',\n blockLabels,\n path,\n routes: [\n { path, name: 'webx.regions', component: RegionsPage, props: { base: path } },\n {\n path: `${path}/:name`,\n name: 'webx.regions.edit',\n component: RegionEditorPage,\n props: { base: path },\n },\n ],\n // The part of `regions.form` that is not a field: it reads the region from the editor.\n types: {\n 'wx-region-history': { component: RegionHistory, kind: 'display' },\n },\n }\n}\n\n/**\n * What the published block types and their fields are called, for the panel's notices about\n * somebody else's edit: «Hero › Text below the button», as the constructor names it.\n */\nasync function blockLabels(admin: AdminContext): Promise<BlockLabels> {\n const types = await createBlocksApi(admin).catalog()\n const names = new Map(types.map((type) => [type.slug, type.title]))\n const fields = new Map(\n types.map((type) => [type.slug, screenLabels(type.content?.schema ?? [])] as const),\n )\n\n return {\n type: (slug) => names.get(slug) || undefined,\n field: (slug, name) => fields.get(slug)?.get(name),\n }\n}\n"],"names":["createBlocksApi","admin","base","data","body","id","input","slug","options","number","ids","slugs","query","search","file","createSiteBarBlocksApi","at","type","createRegionsApi","name","revision","blocksMessages","seeded","seedBlocksMessages","i18n","useBlocksMessages","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","mine","computed","lint","passed","codes","lines","_hoisted_2","WxIcon","_createElementVNode","_Fragment","_createTextVNode","_toDisplayString","_renderList","line","formSchema","schema","node","usageWords","count","groupLabel","key","words","kindOf","callerWords","LAYOUT","WORDS","startValues","sample","values","schemaFields","PLAIN","TAG","holdsMarkup","one","markupFields","withPlaceholders","nodes","marked","markupHelp","inline","helped","sampleWords","takesShortcodes","withShortcodes","tokens","children","strip","found","callTag","fallback","fields","attributes","variableOf","slots","head","_match","letter","resolve","dismiss","open","useModal","context","api","message","useErrorText","types","chosen","drafts","loading","exporting","ordered","all","some","toggleAll","on","toggle","versionOf","version","fileName","download","pack","url","link","run","skipped","missing","toast","onMounted","WxDialog","$event","WxSpace","WxButton","WxSkeleton","WxCheckbox","_cache","_hoisted_3","_hoisted_4","_hoisted_5","_hoisted_6","_hoisted_7","WxSwitch","versions","load","state","restore","confirm","block","WxDate","WxBadge","SELECTED_CLASS","HOVER_CLASS","STYLE_ID","findRange","root","findPair","findRegion","opener","walker","start","replaceBlock","doc","html","range","parent","template","anchor","done","fragment","inserted","runtime","child","UNDRAWN","blockElement","drawnElements","drawn","empty","element","rect","regionRect","top","left","right","bottom","REGION_FRAME_ID","frameRegion","box","view","highlightBlock","ensureStyle","HIDDEN_CLASS","markHidden","keys","hoverBlock","keyAt","depth","sibling","bindFrame","handlers","hovered","onClick","event","inert","onMove","onLeave","swallow","target","freezeFrame","listeners","listener","STAGE_KEY","STAGE_STYLES","fillStage","style","mountScript","script","addAssets","assets","tag","parseTags","present","addToHead","live","absolute","address","href","attribute","other","folder","siblings","last","first","stageDocument","escapeAttribute","frame","tail","SHELL_PLACE","siteShell","findMarker","rel","copy","inner","thumbDocument","shell","widths","width","boxWidth","useElementWidth","contentHeight","picked","fits","option","pick","scale","srcdoc","generation","loadedScript","measure","margin","binding","observer","release","fill","onLoad","Observer","now","before","onBeforeUnmount","frameStyle","clipStyle","WxSegmented","isNode","isNodeList","newKey","makeNode","locate","tree","find","list","field","index","walk","visit","countType","countInside","typesIn","seen","nestedFields","cloneNode","clone","setHidden","hidden","swapNode","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","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","match","reserved","declared","answer","bound","detail","info","boost","label","snippetCompletion","stack","printable","loopVariables","space","closer","escape","keysOf","q","part","helper","origin","own","outer","styleClasses","blocks","stylesCompletions","statement","styled","used","templateClasses","names","prelude","char","parents","selectors","selector","NODE_KEYS","schemaCompletions","jsonContext","quoted","applyJson","entry","pos","snapshot","string","escaped","i","NAMED","GENERIC_FONTS","WIDE","FONT_KEYWORDS","NOT_PAINT","cssFindings","css","vocabulary","comment","findings","offset","declarations","colon","property","problem","subject","declaration","lineAt","reference","paint","color","whole","named","family","families","a","b","bare","allowed","item","parens","raw","p","lintBlock","content","lints","marker","undeclared","stringOnText","stray","prefix","few","withoutComments","media","tokenLints","grouped","finding","code","param","subjects","fieldIds","closure","STRING_CALLS","references","textFields","inItem","call","expression","pattern","use","joined","kind","trimmed","blocksPreviewKey","provideBlocksPreview","preview","provide","useBlocksPreview","inject","blocksTopKey","provideBlocksTop","blocksRootKey","blocksOwnerKey","blocksFragmentKey","route","useRoute","router","useRouter","usage","saving","publishing","tab","meta","module","canManage","settings","reactive","schemaText","schemaError","errors","refusal","stage","current","dirty","typeIds","schemas","loadTargets","place","assist","coreTypes","groupOptions","group","sampleModel","fieldSnippets","insertable","pill","containerFields","allowHelp","settingsOf","take","loaded","stored","onSchemaText","timer","pending","redraw","render","ticket","templateEditor","insertField","editor","save","settingsBefore","saved","publish","declaredModule","callers","isComponent","publishAsking","blockId","remove","reset","languageNotice","changes","flip","refusalError","withStage","examples","shownUsage","whereWords","hasWhere","deleteBlocked","dataInputs","shape","copyCall","errorOf","leaveGuard","kindOptions","exportType","createModal","BlockExportDialog","actions","WxCard","WxScreenHead","WxRenameButton","WxPopover","_component_router_link","entity","WxAlert","_normalizeClass","WxTabs","WxTab","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","_hoisted_20","BlockHistory","BlockStage","WxActionBar","WxEmpty","step","shells","loadShell","response","useSiteShell","adminKey","watchEffect","TALL","watcher","entries","blank","widthScale","fitted","fit","allows","allow","parentAllows","typeAllows","destinations","catalog","moving","here","trail","container","slot","title","max","allowedHere","exhausted","shown","needle","sections","order","o","section","emptyText","BlockThumb","REGION","bar","fullscreen","ready","grown","pin","page","margins","height","nextTick","bring","watch_","reveal","forget","scroller","overflow","room","band","foot","above","tall","delta","replace","refresh","onKey","__expose","WxAction","typeOf","titleOf","fieldsOf","childrenIn","flagsOf","flags","refused","limitOf","isFull","limit","actionsFor","pasteActions","clipLabel","clip","WxSortableList","_withCtx","flag","WxTooltip","WxRowMenu","_component_blocks_tree","f","n","CLIPBOARD_KEY","listening","storage","parseClip","read","listen","useBlocksClipboard","readonly","planPaste","accepted","offered","known","over","slotRules","model","_useModel","nested","screenErrorsKey","owner","topAllow","topMax","topRoot","framed","out","path","messages","dot","refusedByKey","pageRefusals","selectedKey","selected","selectedType","steps","previewEl","host","hostWidth","hasPreview","compact","sheet","sheetTitle","sideProps","groups","m","self","getCurrentInstance","translate","can","BlockPicker","set","add","parentType","duplicate","chooseDestination","BlockMoveDialog","move","without","putAside","clipNodes","copyNodes","copyBlock","skippedText","reason","paste","rules","plan","listActions","visibility","reorder","select","selectFromPreview","onValues","typeId","selectedErrors","selectedPlacement","hiddenKeys","fetchedShortcodes","shallowRef","loadShortcodes","shortcodes","formRoot","_resolveDynamicComponent","WxDrawer","_mergeProps","BlocksTree","_hoisted_8","BlocksPreview","form","slugTouched","slugify","WxRadioGroup","WxRadio","picker","rows","reading","importing","STATUS","writable","row","upToDate","choose","refusalOf","onFile","result","written","close","statusLabel","COMPONENTS","customising","create","BlockCreateDialog","exportTypes","importTypes","BlockImportDialog","components","hasComponents","moduleName","declaredBy","matches","shownComponents","shownPending","views","groupViews","componentView","componentsLabel","nothing","canDrag","droppedAt","dropped","customise","importFile","WxListScreen","WxSkeletonItem","VueDraggable","BlockCard","BlockDeclaredCard","_component_wx_alert","_component_wx_button","_component_wx_text","errorText","useSiteBar","regionsApi","sources","failed","held","refusals","picking","others","regionRefusals","busy","shaping","pageBundles","pageRegions","groupsOrder","offersRecord","offersRegions","rowsOf","onSite","onPage","changed","nestedIds","panelHref","announce","tellSitePage","readRecord","record","readRegions","regions","back","scope","hit","stopPresence","startPresence","was","highlight","togglePicking","refuse","showOnPage","caught","HttpError","conflicted","edited","placeOf","holder","placeAround","fullness","ops","addTo","after","moveBy","by","removeBlock","full","limited","below","up","down","why","regionPreview","publishRegion","discardRegion","beat","knocking","presenceUrl","knock","ping","stopListening","onSitePage","where","onKeydown","_component_wx_loading","_component_wx_result","RegionDraftNotice","_normalizeStyle","copying","choices","status","badge","editHref","canDetach","detach","regionEditorKey","provideRegionEditor","useRegionEditor","previewAt","sitePath","useI18n","links","createLinksApi","emptyLink","change","resolved","home","WxLinkPicker","PAUSE","region","working","reloadToken","screenKey","editing","useEditing","theirs","flight","conflict","chosenPlace","storageKey","readPlace","pickPlace","firstPlace","uses","usedOn","showOn","previewUrl","silent","schedule","onFocusOut","carried","write","sending","sent","takeTheirs","act","unpublish","discard","adopt","adopted","onBeforeRouteLeave","RegionPagePicker","WxEditingAlerts","WxScreen","WxSaveState","WxDrafts","shared","chips","chip","blockLabels","markRaw","BlocksSiteBarTab","BlocksPage","BlockEditorPage","BlocksField","BlockDataField","FragmentField","RegionsPage","RegionEditorPage","RegionHistory","screenLabels"],"mappings":"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QAAQ,wBAAwB,MAAM;AACpD;AC5+BA,MAAMuX,KAAQ;AAAA,EACZ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAC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"}
|