@webx-ui/module-banners 0.2.4 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-3RALKrkh.js","sources":["../src/api.ts","../src/editor.ts","../src/messages.ts","../src/i18n.ts","../src/layers.ts","../src/LayerInspector.vue","../src/LayersField.vue","../src/module.ts","../src/index.ts"],"sourcesContent":["import type { AdminContext } from '@webx-ui/module-admin'\nimport type { ScreenModel } from '@webx-ui/schema'\nimport type { BannerDetail, BannerRow, BannersTheme, PlaceInput, PlaceRow } from './types'\n\nexport interface BannersApi {\n /** Every place: the declared ones in the config's order, then the own ones by name. */\n places(): Promise<PlaceRow[]>\n createPlace(input: PlaceInput): Promise<PlaceRow>\n /** Only a place of somebody's own, and only its name: the key is what a template asks for. */\n renamePlace(key: string, title: PlaceInput['title']): Promise<PlaceRow>\n /** Only an own place with nothing in it, the bin included — a 422 with the count otherwise. */\n removePlace(key: string): Promise<void>\n\n /** The banners of a place in their order, or its bin. A declared place without a row: `[]`. */\n list(place: string, trashed?: boolean): Promise<BannerRow[]>\n get(id: number): Promise<BannerDetail>\n /**\n * A new banner out of the values of its form, in one request: the form is filled in first and\n * the record made on the first save, so nobody leaves an empty banner in a place.\n */\n create(place: string, values: ScreenModel): Promise<BannerDetail>\n /**\n * Refused with a 422 under the name of the field — `buttons.<n>.link` for a button's row. A\n * `place` other than the one it stands in moves it to the end of that one (decision 14).\n */\n save(id: number, values: ScreenModel, place?: string): Promise<BannerDetail>\n remove(id: number): Promise<void>\n restore(id: number): Promise<BannerRow>\n /** The order of one place, written whole. */\n reorder(place: string, ids: number[]): Promise<void>\n /** The site's theme as the layer editor shows it; empty on a site without one. */\n theme(): Promise<BannersTheme>\n}\n\n/** Everything under `/banners`, below the panel's API path (§5.6). */\nexport function createBannersApi(admin: AdminContext): BannersApi {\n const base = `${admin.apiPath}/banners`\n const place = (key: string) => `${base}/places/${encodeURIComponent(key)}`\n const data = <T>(body: { data: T }): T => body.data\n\n return {\n places: () => admin.http.get<{ data: PlaceRow[] }>(`${base}/places`).then(data),\n createPlace: (input) => admin.http.post<{ data: PlaceRow }>(`${base}/places`, input).then(data),\n renamePlace: (key, title) =>\n admin.http.put<{ data: PlaceRow }>(place(key), { title }).then(data),\n removePlace: (key) => admin.http.delete<void>(place(key)).then(() => undefined),\n\n list: (key, trashed = false) =>\n admin.http\n .get<{ data: BannerRow[] }>(`${place(key)}/banners${trashed ? '?trashed=1' : ''}`)\n .then(data),\n get: (id) => admin.http.get<{ data: BannerDetail }>(`${base}/${id}`).then(data),\n create: (key, values) =>\n admin.http.post<{ data: BannerDetail }>(`${place(key)}/banners`, { values }).then(data),\n save: (id, values, key) =>\n admin.http\n .put<{ data: BannerDetail }>(\n `${base}/${id}`,\n key === undefined ? { values } : { values, place: key },\n )\n .then(data),\n remove: (id) => admin.http.delete<void>(`${base}/${id}`).then(() => undefined),\n // The resource of the list line, and not the form's pair: a restored banner stays closed.\n restore: (id) => admin.http.post<{ data: BannerRow }>(`${base}/${id}/restore`, {}).then(data),\n reorder: (key, ids) =>\n admin.http.post<void>(`${place(key)}/reorder`, { ids }).then(() => undefined),\n theme: () => admin.http.get<{ data: BannersTheme }>(`${base}/theme`).then(data),\n }\n}\n","import { inject, provide, type ComputedRef, type InjectionKey, type Ref } from 'vue'\nimport type { ScreenModel } from '@webx-ui/schema'\nimport type { PlaceRow } from './types'\n\n/**\n * What the banner's page tells the fields of its screen that need more than their own value: the\n * layer editor draws the banner's picture, puts in its title and text, and lays out its buttons,\n * in the frame of the place the banner stands in.\n */\nexport interface BannerEditorContext {\n values: Ref<ScreenModel>\n place: ComputedRef<PlaceRow | null>\n}\n\nconst key: InjectionKey<BannerEditorContext> = Symbol('wx-banner-editor')\n\nexport function provideBannerEditor(context: BannerEditorContext): void {\n provide(key, context)\n}\n\nexport function useBannerEditor(): BannerEditorContext | null {\n return inject(key, null)\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 without\n * one. The server ships the same lines in ten languages under `webx-banners::` and overrides\n * these; `messages.test.ts` keeps the two sets of keys equal. The server's refusals (`errors`)\n * are not here: the panel only ever shows them as they come.\n */\nexport const bannersMessages: Record<string, Messages> = {\n module: {\n banners: 'Banners',\n },\n places: {\n hero: 'Home page slider',\n promo: 'Promo strip',\n notice: 'Announcement bar',\n list: 'Places',\n new: 'New place',\n title: 'Name',\n key: 'Key',\n 'key-help':\n 'What the site’s template asks for: lowercase Latin letters, digits and dashes, starting with a letter. It cannot be changed later.',\n declared: 'Declared in the configuration',\n 'in-template': \"In a template: banners(':key')\",\n count: 'Banners',\n rename: 'Rename',\n delete: 'Delete',\n 'delete-confirm': 'Delete the place “:title”?',\n 'delete-not-empty': 'Only an empty place can be deleted — the bin counts too.',\n empty: 'No places yet',\n choose: 'Choose a place on the left',\n create: 'Create',\n save: 'Save',\n cancel: 'Cancel',\n created: 'Place created',\n renamed: 'Place renamed',\n deleted: 'Place deleted',\n places: 'Places',\n 'new-title': 'New place',\n 'rename-title': 'Rename the place',\n 'delete-title': 'Delete the place “:place”?',\n 'delete-text':\n 'There is nothing in it. A template that still asks for it gets an empty list, not an error.',\n 'delete-empty-first': 'Delete: empty it first',\n 'delete-blocked': 'Banners in this place, the bin included: :count. Take them out first.',\n 'field-title': 'Name',\n 'field-key': 'Key',\n 'declared-help': 'Cannot be renamed or deleted here: a template asks for it by its key.',\n usage: 'In a template:',\n 'layout-single': 'One banner',\n 'layout-random': 'A random one',\n 'layout-slider': 'Slider',\n 'empty-help': 'The site’s config declares the places its templates ask for.',\n 'choose-help': 'Its banners open beside the list.',\n },\n banner: {\n new: 'New banner',\n trash: 'Bin',\n 'to-trash': 'Move to the bin',\n restore: 'Restore',\n open: 'Open',\n enable: 'Turn on',\n disable: 'Turn off',\n disabled: 'Off',\n video: 'Video',\n empty: 'No banners in this place yet',\n 'trash-empty': 'The bin is empty',\n place: 'Place',\n 'place-help': 'Moving the banner puts it at the end of the new place.',\n back: 'Back to the place',\n save: 'Save',\n saved: 'Banner saved',\n trashed: 'Bin',\n restored: 'Banner restored',\n 'leave-title': 'Leave without saving?',\n 'leave-text': 'The changes to this banner will be lost.',\n leave: 'Leave',\n stay: 'Stay',\n reorder: 'Reorder',\n untitled: 'Untitled banner',\n all: 'Banners',\n 'empty-help': 'The site shows them wherever a template asks for this place.',\n 'empty-bin': 'The bin is empty.',\n 'no-picture': 'No picture',\n order: 'Drag to change the order on the site.',\n 'switched-on': 'Switched on.',\n 'switched-off': 'Switched off.',\n delete: 'Delete',\n 'delete-title': 'Delete “:name”?',\n 'delete-text': 'It goes to the bin and leaves the site. Restored, it comes back to its place.',\n deleted: 'Moved to the bin.',\n 'reorder-failed': 'The new order was not saved.',\n 'save-failed': 'Not saved.',\n cancel: 'Cancel',\n previous: 'Previous banner',\n next: 'Next banner',\n },\n screen: {\n media: 'Pictures and video',\n image: 'Picture',\n 'image-help': 'Required. Shown on wide screens, and as the poster of the video.',\n 'image-mobile': 'Picture for phones',\n 'image-mobile-help': 'Optional. Narrow screens show it instead of the picture above.',\n video: 'Video',\n 'video-help':\n 'Optional. Plays silently over the picture; the picture becomes its poster and what is seen without it.',\n words: 'Words',\n title: 'Title',\n 'title-help':\n 'A banner with words is shown only in the languages they are written in; one without words is shown everywhere.',\n text: 'Text',\n 'text-help': 'Plain text; line breaks are kept.',\n buttons: 'Buttons',\n 'buttons-help': 'Up to three. A button without a label in a language is not shown in it.',\n 'buttons-add': 'Add a button',\n 'buttons-empty': 'No buttons',\n label: 'Label',\n link: 'Link',\n variant: 'Look',\n 'variant-placeholder': 'The first one',\n settings: 'Settings',\n enabled: 'On',\n 'enabled-help': 'Only a banner that is on is shown on the site. A new one starts off.',\n layers: 'Layers',\n 'layers-help':\n 'Texts, pictures and buttons placed on the picture. Every size is a percent of the picture’s width, so the banner scales as a whole.',\n },\n layers: {\n text: 'Text',\n image: 'Picture',\n button: 'Button',\n 'title-layer': 'Banner title',\n 'text-layer': 'Banner text',\n 'buttons-layer': 'Banner buttons',\n desktop: 'Computer',\n mobile: 'Phone',\n layout: 'Layout',\n undo: 'Undo (Ctrl+Z)',\n redo: 'Redo (Ctrl+Shift+Z)',\n 'not-here': 'This place does not print layers: they are kept, but the site does not show them.',\n canvas: 'Banner canvas',\n 'no-picture': 'Choose a picture above',\n hint: 'Click to select, drag to move, the handles resize. Arrows move by 0.05 (with Shift by 0.5), Delete removes, Ctrl+D duplicates, Ctrl+Z undoes. Alt while dragging: no snapping. The shade is what the frame of the place crops away.',\n empty: 'No layers yet',\n list: 'Layers',\n outside: 'Outside the frame: not seen on the site',\n show: 'Show on this layout',\n hide: 'Hide on this layout',\n delete: 'Delete',\n choose: 'Select a layer on the picture or in the list.',\n name: 'Name in the list',\n label: 'Label',\n words: 'Words',\n 'falls-back': 'Empty here: the site shows the words in :code.',\n 'words-help':\n 'Empty in a language — the default language is shown. {title} and {text} put in the banner’s fields.',\n 'unknown-field': 'Not a field of the banner: :fields. Fields are {title} and {text}.',\n tag: 'Tag',\n link: 'Link',\n variant: 'Look',\n 'buttons-help': 'The buttons of the banner, in a row. Edit them in “Buttons” below.',\n 'geometry-desktop': 'Position on a computer',\n 'geometry-mobile-own': 'Position on a phone',\n 'geometry-mobile-same': 'Position on a phone — as on a computer',\n 'same-as-desktop': 'As on a computer',\n unit: 'In percent of the picture’s width.',\n x: 'x (from the left)',\n y: 'y (from the top)',\n w: 'Width',\n size: 'Font size',\n pad: 'Padding',\n radius: 'Rounding',\n tracking: 'Letter spacing, em',\n rotate: 'Rotation, °',\n gap: 'Gap',\n origin: 'Anchor',\n 'origin-help': 'Which point of the layer stands at x and y: longer words grow away from it.',\n 'hidden-here': 'Hidden on this layout',\n look: 'Look',\n font: 'Font',\n 'font-site': 'As on the site',\n 'font-heading': 'Headings',\n 'font-body': 'Body text',\n weight: 'Weight',\n 'line-height': 'Line height',\n opacity: 'Opacity',\n align: 'Alignment',\n 'align-start': 'Start',\n 'align-center': 'Centre',\n 'align-end': 'End',\n italic: 'Italic',\n uppercase: 'Capitals',\n shadow: 'Shadow',\n color: 'Colour',\n background: 'Background',\n motion: 'Motion',\n entrance: 'Entrance',\n loop: 'Loop',\n delay: 'Delay, ms',\n duration: 'Duration, ms',\n 'motion-none': 'None',\n 'in-fade': 'Fade in',\n 'in-rise': 'Rise',\n 'in-slide-start': 'From the start',\n 'in-slide-end': 'From the end',\n 'in-zoom': 'Zoom',\n 'loop-spin': 'Spin',\n 'loop-float': 'Float',\n },\n}\n","import { useAdmin } from '@webx-ui/module-admin'\nimport { bannersMessages } from './messages'\n\nconst seeded = new WeakSet<object>()\n\n/** Puts this package's English under the panel's dictionary, once per panel. */\nexport function useBannersMessages(): void {\n try {\n const { i18n } = useAdmin()\n\n if (!seeded.has(i18n)) {\n i18n.defaults('webx-banners', bannersMessages)\n seeded.add(i18n)\n }\n } catch {\n // Outside a panel there is no dictionary to seed, and `useTranslate` falls back on its own.\n }\n}\n","import type { LocalizedValue } from '@webx-ui/core'\nimport type { LinkValue } from '@webx-ui/module-admin'\n\n/**\n * The layers of a banner on the panel's side (the layers spec, §3.2): their shape, the ones a\n * banner starts with, and the custom properties `layers.css` reads — the same numbers the server\n * prints (`Rendering\\Layers`), so the canvas is the site.\n */\n\nexport type LayerType = 'text' | 'image' | 'button' | 'buttons'\n\nexport type LayerOrigin = 'tl' | 't' | 'tr' | 'l' | 'c' | 'r' | 'bl' | 'b' | 'br'\n\nexport type LayerView = 'desktop' | 'mobile'\n\n/** One layout's geometry, every length in percent of the picture's width (decision 1). */\nexport interface LayerFrame {\n x: number\n y: number\n w: number\n size: number\n pad: number\n radius: number\n /** In em: letter spacing follows the type, not the picture. */\n tracking: number\n rotate: number\n gap: number\n origin: LayerOrigin\n hidden: boolean\n}\n\nexport interface LayerStyle {\n font: 'heading' | 'body' | null\n weight: number\n italic: boolean\n uppercase: boolean\n align: 'start' | 'center' | 'end'\n line_height: number\n /** `#rrggbb`, `token:<name of the palette>` or `null` — the site's. */\n color: string | null\n background: string | null\n opacity: number\n shadow: boolean\n}\n\nexport interface LayerMotion {\n in: 'fade' | 'rise' | 'slide-start' | 'slide-end' | 'zoom' | null\n loop: 'spin' | 'float' | null\n delay: number\n duration: number\n}\n\nexport interface MediaRef {\n path: string\n url?: string\n alt?: LocalizedValue | string\n}\n\nexport interface BannerLayer {\n id: string\n type: LayerType\n name?: string\n text?: LocalizedValue\n tag?: string\n image?: MediaRef | null\n link?: LinkValue | null\n variant?: string | null\n style: LayerStyle\n frames: { desktop: LayerFrame; mobile: LayerFrame | null }\n motion: LayerMotion\n}\n\n/** Range, step and default of each number of a layout — as `LayerRules::FRAME` has them. */\nexport const FRAME_LIMITS: Record<\n Exclude<keyof LayerFrame, 'origin' | 'hidden'>,\n [number, number, number]\n> = {\n x: [-50, 150, 5],\n y: [-50, 150, 5],\n w: [1, 150, 40],\n size: [0.3, 20, 3],\n pad: [0, 10, 0],\n radius: [0, 50, 0],\n tracking: [-0.2, 1, 0],\n rotate: [-180, 180, 0],\n gap: [0, 10, 1],\n}\n\nexport const ORIGINS: LayerOrigin[] = ['tl', 't', 'tr', 'l', 'c', 'r', 'bl', 'b', 'br']\n\nconst ORIGIN_SHIFT: Record<LayerOrigin, [number, number]> = {\n tl: [0, 0],\n t: [-50, 0],\n tr: [-100, 0],\n l: [0, -50],\n c: [-50, -50],\n r: [-100, -50],\n bl: [0, -100],\n b: [-50, -100],\n br: [-100, -100],\n}\n\nexport const ENTRANCES = ['fade', 'rise', 'slide-start', 'slide-end', 'zoom'] as const\n\nexport const LOOPS = ['spin', 'float'] as const\n\n/** The two fields of a banner a layer's words may put in. */\nexport const FIELDS = ['title', 'text'] as const\n\nexport function frame(over: Partial<LayerFrame> = {}): LayerFrame {\n return {\n x: 5,\n y: 5,\n w: 40,\n size: 3,\n pad: 0,\n radius: 0,\n tracking: 0,\n rotate: 0,\n gap: 1,\n origin: 'tl',\n hidden: false,\n ...over,\n }\n}\n\nexport function style(over: Partial<LayerStyle> = {}): LayerStyle {\n return {\n font: null,\n weight: 400,\n italic: false,\n uppercase: false,\n align: 'start',\n line_height: 1.2,\n color: null,\n background: null,\n opacity: 1,\n shadow: false,\n ...over,\n }\n}\n\nexport function motion(over: Partial<LayerMotion> = {}): LayerMotion {\n return { in: null, loop: null, delay: 0, duration: 600, ...over }\n}\n\n/**\n * A deep copy of a layer. Not `structuredClone`: what the form holds is a reactive proxy, and the\n * browser refuses to clone one.\n */\nexport function clone<T>(value: T): T {\n return JSON.parse(JSON.stringify(value)) as T\n}\n\n/** A short id, unique among the layers it joins. */\nexport function layerId(taken: Iterable<string> = []): string {\n const used = new Set(taken)\n let id = ''\n\n do {\n id = Math.random().toString(36).slice(2, 8).padEnd(6, '0')\n } while (used.has(id) || !/^[a-z0-9]{4,12}$/.test(id))\n\n return id\n}\n\n/** A new layer of a kind, where a new layer of that kind usually goes. */\nexport function newLayer(type: LayerType, taken: Iterable<string>, locale: string): BannerLayer {\n const base = { id: layerId(taken), type, style: style(), motion: motion() }\n\n switch (type) {\n case 'text':\n return {\n ...base,\n text: { [locale]: 'Text' },\n tag: 'p',\n frames: { desktop: frame({ x: 10, y: 10, size: 2.4 }), mobile: null },\n }\n case 'image':\n return {\n ...base,\n image: null,\n frames: { desktop: frame({ x: 60, y: 10, w: 20 }), mobile: null },\n }\n case 'button':\n return {\n ...base,\n text: { [locale]: 'Button' },\n link: null,\n variant: null,\n frames: { desktop: frame({ x: 10, y: 25, w: 30, size: 1.2 }), mobile: null },\n }\n case 'buttons':\n return {\n ...base,\n frames: { desktop: frame({ x: 6, y: 27, w: 50, size: 1.2 }), mobile: null },\n }\n }\n}\n\n/**\n * What a banner of a place with layers starts with (decision 5): its title, its text and its\n * buttons, in a column on the left. The words are written once, in the default language — the\n * others take them from there (decision 6) — and the fields are put in in the page's language.\n */\nexport function defaultLayers(defaultLocale: string): BannerLayer[] {\n const taken: string[] = []\n const next = (layer: Omit<BannerLayer, 'id'>): BannerLayer => {\n const made = { ...layer, id: layerId(taken) } as BannerLayer\n\n taken.push(made.id)\n\n return made\n }\n\n return [\n next({\n type: 'text',\n text: { [defaultLocale]: '{title}' },\n tag: 'h2',\n style: style({ weight: 700, line_height: 1.05, color: '#ffffff', shadow: true }),\n frames: { desktop: frame({ x: 6, y: 6, w: 45, size: 4.2 }), mobile: null },\n motion: motion({ in: 'rise' }),\n }),\n next({\n type: 'text',\n text: { [defaultLocale]: '{text}' },\n tag: 'p',\n style: style({ line_height: 1.4, color: '#ffffff', shadow: true }),\n frames: { desktop: frame({ x: 6, y: 18, w: 40, size: 1.4 }), mobile: null },\n motion: motion({ in: 'rise', delay: 150 }),\n }),\n next({\n type: 'buttons',\n style: style(),\n frames: { desktop: frame({ x: 6, y: 28, w: 50, size: 1.2 }), mobile: null },\n motion: motion({ in: 'rise', delay: 300 }),\n }),\n ]\n}\n\n/**\n * A layer's words in this language: the page's, else the site's default, else the first one\n * written in the order of the site's languages (decision 6) — then the banner's fields put in,\n * in the page's language. The same as `Rendering\\Layers::words()`.\n */\nexport function layerWords(\n text: LocalizedValue | undefined,\n locale: string,\n order: string[],\n fields: Partial<Record<(typeof FIELDS)[number], string>>,\n): string {\n const map = text ?? {}\n const codes = [...new Set([locale, ...order, ...Object.keys(map)])]\n const words = codes.map((code) => map[code]).find((one) => (one ?? '').trim() !== '') ?? ''\n\n return words\n .replaceAll('{title}', fields.title ?? '')\n .replaceAll('{text}', fields.text ?? '')\n .trim()\n}\n\n/** `{title}` and `{text}` are fields; any other `{…}` in a layer's words is very likely a typo. */\nexport function unknownFields(text: string): string[] {\n return [...text.matchAll(/\\{([a-z_.]+)\\}/g)]\n .map((match) => match[1] ?? '')\n .filter((name) => !(FIELDS as readonly string[]).includes(name))\n}\n\n/** A colour of the theme's palette, or one of its own; anything else is no colour at all. */\nexport function cssColor(color: string | null | undefined): string | null {\n if (typeof color !== 'string') return null\n if (/^#[0-9a-f]{6}([0-9a-f]{2})?$/.test(color)) return color\n\n const token = /^token:([a-z][a-z0-9-]{0,40})$/.exec(color)\n\n return token ? `var(--site-color-${token[1]})` : null\n}\n\nconst round = (value: number): number => Math.round(value * 100) / 100\n\n/** The custom properties of a layer, as the server prints them, for both layouts. */\nexport function layerVars(layer: BannerLayer, z: number): Record<string, string> {\n const vars: Record<string, string> = {}\n const desktop = layer.frames.desktop\n const mobile = layer.frames.mobile ?? desktop\n\n for (const [prefix, one] of [\n ['', desktop],\n ['m-', mobile],\n ] as const) {\n for (const key of Object.keys(FRAME_LIMITS) as (keyof typeof FRAME_LIMITS)[]) {\n vars[`--${prefix}${key}`] = String(round(one[key]))\n }\n\n const [ox, oy] = ORIGIN_SHIFT[one.origin] ?? [0, 0]\n\n vars[`--${prefix}ox`] = `${ox}%`\n vars[`--${prefix}oy`] = `${oy}%`\n vars[`--${prefix}display`] = one.hidden ? 'none' : 'block'\n }\n\n vars['--weight'] = String(layer.style.weight)\n vars['--leading'] = String(layer.style.line_height)\n vars['--opacity'] = String(layer.style.opacity)\n vars['--align'] = layer.style.align\n\n const color = cssColor(layer.style.color)\n const background = cssColor(layer.style.background)\n\n if (color) vars['--color'] = color\n if (background) vars['--background'] = background\n if (layer.style.font) vars['--font'] = `var(--site-font-${layer.style.font})`\n\n vars['z-index'] = String(z)\n\n return vars\n}\n\n/** The classes of a layer's element, as the server prints them (motion is the site's, not the canvas's). */\nexport function layerClasses(layer: BannerLayer): string[] {\n const classes = ['webx-banner__layer', `webx-banner__layer--${layer.type}`]\n\n if (layer.style.italic) classes.push('is-italic')\n if (layer.style.uppercase) classes.push('is-uppercase')\n if (layer.style.shadow) classes.push('is-shadow')\n if (layer.style.background) classes.push('has-background')\n\n return classes\n}\n\n/** `16/6`, `16 / 6`, `2.4` → width over height; anything else is `fallback`. */\nexport function ratioOf(value: string | number | null | undefined, fallback: number): number {\n if (typeof value === 'number') return value > 0 ? value : fallback\n\n const match = /^\\s*(\\d+(?:\\.\\d+)?)\\s*(?:\\/\\s*(\\d+(?:\\.\\d+)?))?\\s*$/.exec(value ?? '')\n\n if (!match) return fallback\n\n const ratio = Number(match[1]) / Number(match[2] ?? 1)\n\n return Number.isFinite(ratio) && ratio > 0 ? ratio : fallback\n}\n\n/**\n * Where the frame of the place falls on the picture — what the site shows of it — as percent of\n * the picture's width and height. `cover` crops the longer side, centred.\n */\nexport function cropBox(\n image: number,\n frameRatio: number,\n): { left: number; top: number; width: number; height: number } {\n if (image > frameRatio) {\n const width = (frameRatio / image) * 100\n\n return { left: (100 - width) / 2, top: 0, width, height: 100 }\n }\n\n const height = (image / frameRatio) * 100\n\n return { left: 0, top: (100 - height) / 2, width: 100, height }\n}\n\n/** A layer as it is stored: the phone's layout, when it differs, or `null`. */\nexport function clampFrame(one: LayerFrame): LayerFrame {\n const next = { ...one }\n\n for (const key of Object.keys(FRAME_LIMITS) as (keyof typeof FRAME_LIMITS)[]) {\n const [min, max] = FRAME_LIMITS[key]\n\n next[key] = round(Math.min(max, Math.max(min, Number(next[key]) || 0)))\n }\n\n return next\n}\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport {\n useLocales,\n WxButton,\n WxColorPicker,\n WxFormItem,\n WxIcon,\n WxInput,\n WxInputNumber,\n WxSegmented,\n WxSelect,\n WxSwitch,\n WxText,\n WxTextarea,\n type LocalizedValue,\n} from '@webx-ui/core'\nimport { useTranslate, WxLinkField, type LinkValue } from '@webx-ui/module-admin'\nimport { WxMediaField } from '@webx-ui/module-media'\nimport {\n clone,\n ENTRANCES,\n FRAME_LIMITS,\n LOOPS,\n ORIGINS,\n unknownFields,\n type BannerLayer,\n type LayerFrame,\n type LayerOrigin,\n type LayerStyle,\n type LayerView,\n type MediaRef,\n} from './layers'\n\n/**\n * What the selected layer is, in fields (§5.4 of the layers spec): its words, its geometry on the\n * layout being edited, its look and its motion. Every length is a percent of the picture's width.\n *\n * It never writes the layer itself: a changed layer goes up whole (`update`), a changed number of\n * the geometry as a patch of the layout on screen (`frame`) — the canvas decides which layout\n * that is, and copies the computer's to the phone on the phone's first change.\n */\ndefineOptions({ name: 'WxBannerLayerInspector' })\n\nconst props = defineProps<{\n layer: BannerLayer\n view: LayerView\n tags: { value: string; label: string }[]\n variants: { value: string; label: string }[]\n palette: { key: string; value: string }[]\n disabled?: boolean\n}>()\n\nconst emit = defineEmits<{\n update: [layer: BannerLayer]\n frame: [patch: Partial<LayerFrame>]\n 'same-as-desktop': []\n delete: []\n}>()\n\nconst t = useTranslate('webx-banners')\nconst locales = useLocales()\n\nconst current = computed<LayerFrame>(() =>\n props.view === 'mobile'\n ? (props.layer.frames.mobile ?? props.layer.frames.desktop)\n : props.layer.frames.desktop,\n)\n\nconst ownPhone = computed(() => props.view === 'mobile' && props.layer.frames.mobile !== null)\n\nfunction change(mutate: (layer: BannerLayer) => void): void {\n const next = clone(props.layer)\n\n mutate(next)\n emit('update', next)\n}\n\nfunction setStyle<K extends keyof LayerStyle>(key: K, value: LayerStyle[K]): void {\n change((layer) => {\n layer.style[key] = value\n })\n}\n\nconst hasWords = computed(() => props.layer.type === 'text' || props.layer.type === 'button')\n\nconst text = computed<LocalizedValue>({\n get: () => props.layer.text ?? {},\n set: (value) =>\n change((layer) => {\n layer.text = value\n }),\n})\n\nconst name = computed<string>({\n get: () => props.layer.name ?? '',\n set: (value) =>\n change((layer) => {\n layer.name = value\n }),\n})\n\n/** What is on screen in the active language — and which `{…}` in it is not a field. */\nconst typos = computed(() => unknownFields(text.value[locales.active.value] ?? ''))\nconst typoList = computed(() => typos.value.map((one) => `{${one}}`).join(', '))\n\n/**\n * The language whose words a reader of the active one sees when it is empty (decision 6), for\n * the field's hint.\n */\nconst fallsBackTo = computed(() => {\n const map = text.value\n const active = locales.active.value\n\n if ((map[active] ?? '').trim() !== '') return null\n\n return (\n [...locales.list.value.map((one) => one.code), ...Object.keys(map)].find(\n (code) => (map[code] ?? '').trim() !== '',\n ) ?? null\n )\n})\n\nfunction insert(field: 'title' | 'text'): void {\n const code = locales.active.value\n const words = text.value[code] ?? ''\n\n text.value = { ...text.value, [code]: `${words}${words === '' ? '' : ' '}{${field}}` }\n}\n\nconst image = computed<MediaRef | null>({\n get: () => props.layer.image ?? null,\n set: (value) =>\n change((layer) => {\n layer.image = value\n }),\n})\n\nconst link = computed<LinkValue | null>({\n get: () => props.layer.link ?? null,\n set: (value) =>\n change((layer) => {\n layer.link = value\n }),\n})\n\nconst choice = <T,>(get: () => T, set: (value: T) => void) =>\n computed<string | number | null>({\n get: () => get() as unknown as string | number | null,\n set: (value) => set(value as unknown as T),\n })\n\nconst tag = choice(\n () => props.layer.tag ?? 'p',\n (value: string) =>\n change((layer) => {\n layer.tag = value\n }),\n)\n\nconst variant = choice(\n () => props.layer.variant ?? props.variants[0]?.value ?? null,\n (value: string | null) =>\n change((layer) => {\n layer.variant = value\n }),\n)\n\nconst font = choice(\n () => props.layer.style.font ?? 'site',\n (value: string) => setStyle('font', value === 'heading' || value === 'body' ? value : null),\n)\n\nconst weight = choice(\n () => props.layer.style.weight,\n (value: number) => setStyle('weight', Number(value)),\n)\n\nconst align = computed<string | number>({\n get: () => props.layer.style.align,\n set: (value) => setStyle('align', value as LayerStyle['align']),\n})\n\nconst entrance = choice(\n () => props.layer.motion.in ?? 'none',\n (value: string) =>\n change((layer) => {\n layer.motion.in = (ENTRANCES as readonly string[]).includes(value)\n ? (value as BannerLayer['motion']['in'])\n : null\n }),\n)\n\nconst loop = choice(\n () => props.layer.motion.loop ?? 'none',\n (value: string) =>\n change((layer) => {\n layer.motion.loop = (LOOPS as readonly string[]).includes(value)\n ? (value as BannerLayer['motion']['loop'])\n : null\n }),\n)\n\ntype FrameNumber = keyof typeof FRAME_LIMITS\n\n/** The numbers of the geometry this kind of layer has. */\nconst numbers = computed<FrameNumber[]>(() => {\n switch (props.layer.type) {\n case 'image':\n return ['x', 'y', 'w', 'radius', 'rotate']\n case 'buttons':\n return ['x', 'y', 'w', 'size', 'gap', 'rotate']\n default:\n return ['x', 'y', 'w', 'size', 'pad', 'radius', 'tracking', 'rotate']\n }\n})\n\nconst steps: Record<FrameNumber, number> = {\n x: 0.05,\n y: 0.05,\n w: 0.5,\n size: 0.05,\n pad: 0.05,\n radius: 0.1,\n tracking: 0.01,\n rotate: 1,\n gap: 0.1,\n}\n\nfunction setNumber(key: FrameNumber, value: number | null): void {\n if (value === null || Number.isNaN(value)) return\n\n emit('frame', { [key]: value })\n}\n\nfunction setOrigin(origin: LayerOrigin): void {\n emit('frame', { origin })\n}\n\nconst fontOptions = computed(() => [\n { value: 'site', label: t('layers.font-site') },\n { value: 'heading', label: t('layers.font-heading') },\n { value: 'body', label: t('layers.font-body') },\n])\n\nconst weightOptions = [100, 200, 300, 400, 500, 600, 700, 800, 900].map((value) => ({\n value,\n label: String(value),\n}))\n\nconst alignOptions = computed(() => [\n { value: 'start', label: t('layers.align-start') },\n { value: 'center', label: t('layers.align-center') },\n { value: 'end', label: t('layers.align-end') },\n])\n\nconst entranceOptions = computed(() => [\n { value: 'none', label: t('layers.motion-none') },\n ...ENTRANCES.map((value) => ({ value, label: t(`layers.in-${value}`) })),\n])\n\nconst loopOptions = computed(() => [\n { value: 'none', label: t('layers.motion-none') },\n ...LOOPS.map((value) => ({ value, label: t(`layers.loop-${value}`) })),\n])\n\n/* A colour is a swatch of the theme's palette (it follows the theme) or one of its own. */\nfunction colorOf(key: 'color' | 'background'): string | null {\n const value = props.layer.style[key]\n\n if (value === null) return null\n if (value.startsWith('token:')) {\n return props.palette.find((one) => `token:${one.key}` === value)?.value ?? null\n }\n\n return value\n}\n\nfunction pickColor(key: 'color' | 'background', value: string | null): void {\n const hex =\n typeof value === 'string' && /^#[0-9a-f]{6}([0-9a-f]{2})?$/i.test(value)\n ? value.toLowerCase()\n : null\n\n setStyle(key, hex)\n}\n</script>\n\n<template>\n <div class=\"wx-banner-layer-inspector\">\n <div class=\"wx-banner-layer-inspector__head\">\n <wx-input\n v-model=\"name\"\n size=\"sm\"\n :placeholder=\"t('layers.name')\"\n :aria-label=\"t('layers.name')\"\n :disabled=\"disabled\"\n />\n <wx-button size=\"sm\" variant=\"outline\" danger :disabled=\"disabled\" @click=\"emit('delete')\">\n <template #icon><wx-icon name=\"trash\" /></template>\n {{ t('layers.delete') }}\n </wx-button>\n </div>\n\n <template v-if=\"hasWords\">\n <wx-form-item\n :label=\"layer.type === 'button' ? t('layers.label') : t('layers.words')\"\n :help=\"\n fallsBackTo\n ? t('layers.falls-back', { code: fallsBackTo.toUpperCase() })\n : t('layers.words-help')\n \"\n >\n <wx-textarea\n v-if=\"layer.type === 'text'\"\n v-model=\"text\"\n localized\n :rows=\"2\"\n :disabled=\"disabled\"\n />\n <wx-input v-else v-model=\"text\" localized :disabled=\"disabled\" />\n </wx-form-item>\n <div class=\"wx-banner-layer-inspector__fields\">\n <wx-button size=\"sm\" variant=\"text\" :disabled=\"disabled\" @click=\"insert('title')\"\n >+ {title}</wx-button\n >\n <wx-button size=\"sm\" variant=\"text\" :disabled=\"disabled\" @click=\"insert('text')\"\n >+ {text}</wx-button\n >\n </div>\n <wx-text v-if=\"typos.length > 0\" size=\"sm\" tone=\"warning\">\n {{ t('layers.unknown-field', { fields: typoList }) }}\n </wx-text>\n </template>\n\n <wx-form-item v-if=\"layer.type === 'text'\" :label=\"t('layers.tag')\">\n <wx-select v-model=\"tag\" :options=\"tags\" size=\"sm\" :disabled=\"disabled\" />\n </wx-form-item>\n\n <wx-form-item v-if=\"layer.type === 'image'\" :label=\"t('layers.image')\">\n <wx-media-field\n v-model=\"image\"\n accept=\"image\"\n :aspect=\"null\"\n :height=\"120\"\n :disabled=\"disabled\"\n />\n </wx-form-item>\n\n <template v-if=\"layer.type === 'button'\">\n <wx-form-item :label=\"t('layers.link')\">\n <wx-link-field v-model=\"link\" :allow-none=\"false\" :disabled=\"disabled\" />\n </wx-form-item>\n <wx-form-item :label=\"t('layers.variant')\">\n <wx-select v-model=\"variant\" :options=\"variants\" size=\"sm\" :disabled=\"disabled\" />\n </wx-form-item>\n </template>\n\n <wx-text v-if=\"layer.type === 'buttons'\" size=\"sm\" tone=\"muted\">{{\n t('layers.buttons-help')\n }}</wx-text>\n\n <section class=\"wx-banner-layer-inspector__group\">\n <div class=\"wx-banner-layer-inspector__title\">\n <wx-text size=\"sm\" strong>\n {{\n view === 'mobile'\n ? ownPhone\n ? t('layers.geometry-mobile-own')\n : t('layers.geometry-mobile-same')\n : t('layers.geometry-desktop')\n }}\n </wx-text>\n <wx-button\n v-if=\"ownPhone\"\n size=\"sm\"\n variant=\"text\"\n :disabled=\"disabled\"\n @click=\"emit('same-as-desktop')\"\n >\n {{ t('layers.same-as-desktop') }}\n </wx-button>\n </div>\n <wx-text size=\"sm\" tone=\"muted\">{{ t('layers.unit') }}</wx-text>\n\n <div class=\"wx-banner-layer-inspector__grid\">\n <wx-form-item v-for=\"key in numbers\" :key=\"key\" :label=\"t(`layers.${key}`)\">\n <wx-input-number\n :model-value=\"current[key]\"\n :min=\"FRAME_LIMITS[key][0]\"\n :max=\"FRAME_LIMITS[key][1]\"\n :step=\"steps[key]\"\n :precision=\"2\"\n size=\"sm\"\n :disabled=\"disabled\"\n @update:model-value=\"\n (value: number | null | undefined) => setNumber(key, value ?? null)\n \"\n />\n </wx-form-item>\n </div>\n\n <wx-form-item :label=\"t('layers.origin')\" :help=\"t('layers.origin-help')\">\n <div\n class=\"wx-banner-layer-inspector__origins\"\n role=\"radiogroup\"\n :aria-label=\"t('layers.origin')\"\n >\n <button\n v-for=\"origin in ORIGINS\"\n :key=\"origin\"\n type=\"button\"\n role=\"radio\"\n :aria-checked=\"current.origin === origin\"\n :aria-label=\"origin\"\n :disabled=\"disabled\"\n :class=\"[\n 'wx-banner-layer-inspector__origin',\n { 'is-active': current.origin === origin },\n ]\"\n @click=\"setOrigin(origin)\"\n />\n </div>\n </wx-form-item>\n\n <wx-switch\n :model-value=\"current.hidden\"\n :label=\"t('layers.hidden-here')\"\n :disabled=\"disabled\"\n @update:model-value=\"(value) => emit('frame', { hidden: value === true })\"\n />\n </section>\n\n <section v-if=\"layer.type !== 'image'\" class=\"wx-banner-layer-inspector__group\">\n <wx-text size=\"sm\" strong>{{ t('layers.look') }}</wx-text>\n\n <div class=\"wx-banner-layer-inspector__grid\">\n <wx-form-item :label=\"t('layers.font')\">\n <wx-select v-model=\"font\" :options=\"fontOptions\" size=\"sm\" :disabled=\"disabled\" />\n </wx-form-item>\n <wx-form-item :label=\"t('layers.weight')\">\n <wx-select v-model=\"weight\" :options=\"weightOptions\" size=\"sm\" :disabled=\"disabled\" />\n </wx-form-item>\n <wx-form-item :label=\"t('layers.line-height')\">\n <wx-input-number\n :model-value=\"layer.style.line_height\"\n :min=\"0.8\"\n :max=\"3\"\n :step=\"0.05\"\n :precision=\"2\"\n size=\"sm\"\n :disabled=\"disabled\"\n @update:model-value=\"\n (value: number | null | undefined) => value != null && setStyle('line_height', value)\n \"\n />\n </wx-form-item>\n <wx-form-item :label=\"t('layers.opacity')\">\n <wx-input-number\n :model-value=\"layer.style.opacity\"\n :min=\"0\"\n :max=\"1\"\n :step=\"0.05\"\n :precision=\"2\"\n size=\"sm\"\n :disabled=\"disabled\"\n @update:model-value=\"\n (value: number | null | undefined) => value != null && setStyle('opacity', value)\n \"\n />\n </wx-form-item>\n </div>\n\n <wx-form-item :label=\"t('layers.align')\">\n <wx-segmented v-model=\"align\" :options=\"alignOptions\" size=\"sm\" :disabled=\"disabled\" />\n </wx-form-item>\n\n <div class=\"wx-banner-layer-inspector__switches\">\n <wx-switch\n :model-value=\"layer.style.italic\"\n :label=\"t('layers.italic')\"\n :disabled=\"disabled\"\n @update:model-value=\"(value) => setStyle('italic', value === true)\"\n />\n <wx-switch\n :model-value=\"layer.style.uppercase\"\n :label=\"t('layers.uppercase')\"\n :disabled=\"disabled\"\n @update:model-value=\"(value) => setStyle('uppercase', value === true)\"\n />\n <wx-switch\n :model-value=\"layer.style.shadow\"\n :label=\"t('layers.shadow')\"\n :disabled=\"disabled\"\n @update:model-value=\"(value) => setStyle('shadow', value === true)\"\n />\n </div>\n\n <wx-form-item\n v-for=\"key in ['color', 'background'] as const\"\n :key=\"key\"\n :label=\"t(`layers.${key}`)\"\n >\n <div class=\"wx-banner-layer-inspector__color\">\n <button\n v-for=\"swatch in palette\"\n :key=\"swatch.key\"\n type=\"button\"\n :title=\"swatch.key\"\n :aria-label=\"swatch.key\"\n :disabled=\"disabled\"\n :class=\"[\n 'wx-banner-layer-inspector__swatch',\n { 'is-active': layer.style[key] === `token:${swatch.key}` },\n ]\"\n :style=\"{ background: swatch.value }\"\n @click=\"setStyle(key, `token:${swatch.key}`)\"\n />\n <wx-color-picker\n :model-value=\"colorOf(key)\"\n clearable\n size=\"sm\"\n :disabled=\"disabled\"\n @update:model-value=\"(value: string | null) => pickColor(key, value)\"\n />\n </div>\n </wx-form-item>\n </section>\n\n <section class=\"wx-banner-layer-inspector__group\">\n <wx-text size=\"sm\" strong>{{ t('layers.motion') }}</wx-text>\n <div class=\"wx-banner-layer-inspector__grid\">\n <wx-form-item :label=\"t('layers.entrance')\">\n <wx-select v-model=\"entrance\" :options=\"entranceOptions\" size=\"sm\" :disabled=\"disabled\" />\n </wx-form-item>\n <wx-form-item :label=\"t('layers.loop')\">\n <wx-select v-model=\"loop\" :options=\"loopOptions\" size=\"sm\" :disabled=\"disabled\" />\n </wx-form-item>\n <wx-form-item :label=\"t('layers.delay')\">\n <wx-input-number\n :model-value=\"layer.motion.delay\"\n :min=\"0\"\n :max=\"10000\"\n :step=\"50\"\n size=\"sm\"\n :disabled=\"disabled || layer.motion.in === null\"\n @update:model-value=\"\n (value: number | null | undefined) =>\n value != null && change((one) => (one.motion.delay = value))\n \"\n />\n </wx-form-item>\n <wx-form-item :label=\"t('layers.duration')\">\n <wx-input-number\n :model-value=\"layer.motion.duration\"\n :min=\"100\"\n :max=\"5000\"\n :step=\"50\"\n size=\"sm\"\n :disabled=\"disabled || layer.motion.in === null\"\n @update:model-value=\"\n (value: number | null | undefined) =>\n value != null && change((one) => (one.motion.duration = value))\n \"\n />\n </wx-form-item>\n </div>\n </section>\n </div>\n</template>\n\n<style scoped>\n.wx-banner-layer-inspector {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-12);\n min-width: 0;\n}\n\n.wx-banner-layer-inspector__head {\n display: flex;\n gap: var(--wx-space-8);\n}\n\n.wx-banner-layer-inspector__fields {\n display: flex;\n gap: var(--wx-space-4);\n margin-top: calc(-1 * var(--wx-space-8));\n}\n\n.wx-banner-layer-inspector__group {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n padding-top: var(--wx-space-12);\n border-top: 1px solid var(--wx-border-default);\n}\n\n.wx-banner-layer-inspector__title {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: var(--wx-space-8);\n}\n\n.wx-banner-layer-inspector__grid {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 0 var(--wx-space-8);\n}\n\n.wx-banner-layer-inspector__grid :deep(.wx-form-item),\n.wx-banner-layer-inspector :deep(.wx-form-item) {\n margin-bottom: var(--wx-space-4);\n}\n\n.wx-banner-layer-inspector__switches {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wx-space-12);\n}\n\n.wx-banner-layer-inspector__origins {\n display: grid;\n grid-template-columns: repeat(3, 18px);\n gap: var(--wx-space-4);\n}\n\n.wx-banner-layer-inspector__origin {\n width: 18px;\n height: 18px;\n padding: 0;\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-xs);\n background: var(--wx-bg-surface);\n cursor: pointer;\n}\n\n.wx-banner-layer-inspector__origin.is-active {\n border-color: var(--wx-color-primary);\n background: var(--wx-color-primary);\n}\n\n.wx-banner-layer-inspector__color {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--wx-space-4);\n}\n\n.wx-banner-layer-inspector__swatch {\n width: 22px;\n height: 22px;\n padding: 0;\n border: 1px solid var(--wx-border-default);\n border-radius: var(--wx-radius-full);\n cursor: pointer;\n}\n\n.wx-banner-layer-inspector__swatch.is-active {\n outline: 2px solid var(--wx-color-primary);\n outline-offset: 1px;\n}\n</style>\n","<script setup lang=\"ts\">\nimport { computed, onBeforeUnmount, onMounted, reactive, ref, watch } from 'vue'\nimport {\n useLocales,\n WxButton,\n WxIcon,\n WxSegmented,\n WxSortableList,\n WxText,\n WxTooltip,\n} from '@webx-ui/core'\nimport { useAdmin, useTranslate } from '@webx-ui/module-admin'\nimport { createMediaApi } from '@webx-ui/module-media'\nimport { createBannersApi } from './api'\nimport { useBannerEditor } from './editor'\nimport { useBannersMessages } from './i18n'\nimport LayerInspector from './LayerInspector.vue'\nimport {\n clampFrame,\n clone,\n cropBox,\n layerClasses,\n layerVars,\n layerWords,\n newLayer,\n ratioOf,\n type BannerLayer,\n type LayerFrame,\n type LayerType,\n type LayerView,\n} from './layers'\nimport type { BannerButton, BannersTheme } from './types'\nimport '../../../php/packages/module-banners/resources/css/layers.css'\n\n/**\n * The layers of a banner, edited on its picture (§5 of the layers spec).\n *\n * The canvas is the site: the same `layers.css`, the same custom properties the server prints,\n * every length a percent of the picture's width — so the width of this column changes the scale\n * and nothing else. It shows the whole picture and darkens what the frame of the place crops\n * away; a layer under the shade is not seen on the site.\n *\n * A field of `banners.form` like any other: the value is the list of layers, and every change is\n * a new list. Undo is this field's own — Ctrl+Z on the canvas — because a text input keeps its\n * own and the two must not fight.\n */\ndefineOptions({ name: 'WxBannerLayers' })\n\nconst props = defineProps<{\n modelValue?: BannerLayer[] | null\n disabled?: boolean\n}>()\n\nconst emit = defineEmits<{ 'update:modelValue': [value: BannerLayer[]] }>()\n\nconst admin = useAdmin()\nconst editor = useBannerEditor()\nconst locales = useLocales()\nconst media = createMediaApi(admin)\nconst api = createBannersApi(admin)\nuseBannersMessages()\n\nconst t = useTranslate('webx-banners')\n\nconst layers = computed<BannerLayer[]>(() => props.modelValue ?? [])\nconst place = computed(() => editor?.place.value?.layers ?? null)\n\nconst view = ref<LayerView>('desktop')\nconst selectedId = ref<string | null>(null)\nconst selected = computed(() => layers.value.find((layer) => layer.id === selectedId.value) ?? null)\n\nconst locale = computed(() => {\n const active = locales.active.value\n\n return locales.list.value.some((one) => one.code === active)\n ? active\n : (locales.list.value[0]?.code ?? 'en')\n})\nconst order = computed(() => locales.list.value.map((one) => one.code))\n\n/* --- History ---------------------------------------------------------------------------- */\n\nconst past = ref<string[]>([])\nconst future = ref<string[]>([])\n\nfunction remember(): void {\n past.value = [...past.value.slice(-99), JSON.stringify(layers.value)]\n future.value = []\n}\n\nfunction commit(next: BannerLayer[], record = true): void {\n if (record) remember()\n\n emit('update:modelValue', next)\n}\n\nfunction undo(): void {\n const last = past.value.at(-1)\n\n if (last === undefined) return\n\n future.value = [...future.value, JSON.stringify(layers.value)]\n past.value = past.value.slice(0, -1)\n emit('update:modelValue', JSON.parse(last) as BannerLayer[])\n}\n\nfunction redo(): void {\n const next = future.value.at(-1)\n\n if (next === undefined) return\n\n past.value = [...past.value, JSON.stringify(layers.value)]\n future.value = future.value.slice(0, -1)\n emit('update:modelValue', JSON.parse(next) as BannerLayer[])\n}\n\n/* --- Changing layers --------------------------------------------------------------------- */\n\nfunction replace(id: string, change: (layer: BannerLayer) => BannerLayer, record = true): void {\n commit(\n layers.value.map((layer) => (layer.id === id ? change(clone(layer)) : layer)),\n record,\n )\n}\n\n/** The layout being edited; the phone's is the computer's until it is changed (decision 3). */\nfunction frameOf(layer: BannerLayer, which: LayerView = view.value): LayerFrame {\n return which === 'mobile' ? (layer.frames.mobile ?? layer.frames.desktop) : layer.frames.desktop\n}\n\nfunction setFrame(id: string, patch: Partial<LayerFrame>, record = true): void {\n replace(\n id,\n (layer) => {\n const next = clampFrame({ ...frameOf(layer), ...patch })\n\n if (view.value === 'mobile') layer.frames.mobile = next\n else layer.frames.desktop = next\n\n return layer\n },\n record,\n )\n}\n\n/* Inspector edits typed in a row are one step of history, not one per key. */\nlet lastEdit = { id: '', at: 0 }\n\nfunction edit(next: BannerLayer): void {\n const now = Date.now()\n const merge = lastEdit.id === next.id && now - lastEdit.at < 800\n\n lastEdit = { id: next.id, at: now }\n replace(next.id, () => next, !merge)\n}\n\nfunction add(type: LayerType): void {\n const layer = newLayer(\n type,\n layers.value.map((one) => one.id),\n locale.value,\n )\n\n commit([layer, ...layers.value])\n selectedId.value = layer.id\n}\n\nfunction remove(id: string): void {\n commit(layers.value.filter((layer) => layer.id !== id))\n\n if (selectedId.value === id) selectedId.value = null\n}\n\nfunction duplicate(id: string): void {\n const index = layers.value.findIndex((layer) => layer.id === id)\n const source = layers.value[index]\n\n if (!source || source.type === 'buttons') return\n\n const copy = clone(source)\n\n copy.id = newLayer(\n 'text',\n layers.value.map((one) => one.id),\n locale.value,\n ).id\n copy.frames.desktop = {\n ...copy.frames.desktop,\n x: copy.frames.desktop.x + 2,\n y: copy.frames.desktop.y + 2,\n }\n\n const next = [...layers.value]\n\n next.splice(index, 0, copy)\n commit(next)\n selectedId.value = copy.id\n}\n\nfunction toggleHidden(layer: BannerLayer): void {\n setFrame(layer.id, { hidden: !frameOf(layer).hidden })\n}\n\nconst hasButtonsLayer = computed(() => layers.value.some((layer) => layer.type === 'buttons'))\n\nconst listModel = computed<BannerLayer[]>({\n get: () => layers.value,\n set: (next) => commit(next),\n})\n\n/* --- The pictures ------------------------------------------------------------------------ */\n\ninterface Picture {\n url: string\n ratio: number | null\n}\n\nconst pictures = reactive<Record<string, Picture | null>>({})\n\nfunction pathOf(value: unknown): string | null {\n const path = (value as { path?: unknown } | null)?.path\n\n return typeof path === 'string' && path !== '' ? path : null\n}\n\nasync function resolve(path: string | null): Promise<void> {\n if (path === null || path in pictures) return\n\n pictures[path] = null\n\n try {\n const file = await media.fileByPath(path)\n\n pictures[path] = file\n ? { url: file.url, ratio: file.width && file.height ? file.width / file.height : null }\n : null\n } catch {\n pictures[path] = null\n }\n}\n\nconst desktopPath = computed(() => pathOf(editor?.values.value.image))\nconst mobilePath = computed(() => pathOf(editor?.values.value.image_mobile))\n\nwatch(\n () => [desktopPath.value, mobilePath.value, ...layers.value.map((layer) => pathOf(layer.image))],\n (paths) => paths.forEach((path) => void resolve(path)),\n { immediate: true },\n)\n\nconst frameRatio = computed(() =>\n view.value === 'mobile'\n ? ratioOf(place.value?.ratio_mobile, 0.8)\n : ratioOf(place.value?.ratio, 16 / 6),\n)\n\nconst background = computed<Picture | null>(() => {\n const mobile = mobilePath.value === null ? null : (pictures[mobilePath.value] ?? null)\n const desktop = desktopPath.value === null ? null : (pictures[desktopPath.value] ?? null)\n\n return view.value === 'mobile' ? (mobile ?? desktop) : desktop\n})\n\n/* The canvas shows the whole picture: its own proportions, the frame's crop drawn over it. */\nconst imageRatio = computed(() => background.value?.ratio ?? frameRatio.value)\nconst crop = computed(() => cropBox(imageRatio.value, frameRatio.value))\n\nconst frameStyle = computed(() => {\n const ratio = String(imageRatio.value)\n\n return { '--ratio': ratio, '--ratio-mobile': ratio, '--img': ratio, '--img-m': ratio }\n})\n\n/* --- What a layer shows ------------------------------------------------------------------ */\n\n/* Exactly the language asked for: a field with no words in it puts in nothing, as on the site. */\nconst ownFields = computed(() => {\n const own = (field: 'title' | 'text'): string => {\n const value = editor?.values.value[field] as Record<string, string> | undefined\n\n return (value?.[locale.value] ?? '').trim()\n }\n\n return { title: own('title'), text: own('text') }\n})\n\nfunction wordsOf(layer: BannerLayer): string {\n return layerWords(layer.text, locale.value, order.value, ownFields.value)\n}\n\nconst bannerButtons = computed(() =>\n ((editor?.values.value.buttons as BannerButton[] | undefined) ?? [])\n .map((button) => ({\n label: (button.label?.[locale.value] ?? '').trim(),\n variant: button.variant ?? place.value?.variants[0]?.value ?? 'primary',\n }))\n .filter((button) => button.label !== ''),\n)\n\nfunction tagOf(layer: BannerLayer): string {\n return layer.type === 'text' && /^(p|span|h[1-6])$/.test(layer.tag ?? '')\n ? (layer.tag as string)\n : 'div'\n}\n\nfunction labelOf(layer: BannerLayer): string {\n if (layer.name) return layer.name\n\n const own = layer.text?.[locale.value] ?? Object.values(layer.text ?? {})[0] ?? ''\n\n if (own.trim() === '{title}') return t('layers.title-layer')\n if (own.trim() === '{text}') return t('layers.text-layer')\n if (layer.type === 'buttons') return t('layers.buttons-layer')\n if (layer.type === 'image') return t('layers.image')\n\n return own.trim() || t(`layers.${layer.type}`)\n}\n\nconst icons: Record<LayerType, string> = {\n text: 'file-text',\n image: 'image',\n button: 'link',\n buttons: 'grid',\n}\n\n/** A layer the frame hides on this layout: wholly under the shade. */\nfunction outside(layer: BannerLayer): boolean {\n const one = frameOf(layer)\n const height = 100 / imageRatio.value\n const box = crop.value\n const left = box.left\n const right = box.left + box.width\n const top = (box.top / 100) * height\n const bottom = ((box.top + box.height) / 100) * height\n\n // The box itself, not its anchor: a layer anchored on the right reaches left of its x.\n const x = one.x + (originShift(one.origin)[0] / 100) * one.w\n\n return x > right || x + one.w < left || one.y > bottom || one.y < top - 50\n}\n\n/* --- Pointer: move and resize ------------------------------------------------------------ */\n\nconst stage = ref<HTMLElement | null>(null)\nconst canvas = ref<HTMLElement | null>(null)\nconst guides = ref<{ axis: 'x' | 'y'; at: number }[]>([])\n\n/** How far the pointer must go before a press becomes a drag, in px. */\nconst SLOP = 3\n/** How close an edge must come to a guide to stick to it, in px. */\nconst SNAP = 6\n\nfunction snapTargets(axis: 'x' | 'y', skip: string): number[] {\n const height = 100 / imageRatio.value\n const box = crop.value\n const targets =\n axis === 'x'\n ? [0, 50, 100, box.left, box.left + box.width]\n : [0, height / 2, height, (box.top / 100) * height, ((box.top + box.height) / 100) * height]\n\n for (const layer of layers.value) {\n if (layer.id === skip) continue\n\n const one = frameOf(layer)\n\n if (axis === 'x') targets.push(one.x, one.x + one.w)\n else targets.push(one.y)\n }\n\n return targets\n}\n\nfunction snap(\n axis: 'x' | 'y',\n value: number,\n size: number,\n unit: number,\n skip: string,\n free: boolean,\n): number {\n if (free) return value\n\n const edges = [0, size / 2, size]\n let best: { delta: number; at: number } | null = null\n\n for (const target of snapTargets(axis, skip)) {\n for (const edge of edges) {\n const delta = target - (value + edge)\n\n if (\n Math.abs(delta) * unit <= SNAP &&\n (best === null || Math.abs(delta) < Math.abs(best.delta))\n ) {\n best = { delta, at: target }\n }\n }\n }\n\n if (best === null) return value\n\n guides.value = [...guides.value.filter((one) => one.axis !== axis), { axis, at: best.at }]\n\n return value + best.delta\n}\n\nfunction select(layer: BannerLayer): void {\n selectedId.value = layer.id\n canvas.value?.focus({ preventScroll: true })\n}\n\nfunction press(event: PointerEvent, layer: BannerLayer, mode: 'move' | 'width' | 'scale'): void {\n select(layer)\n\n if (props.disabled || event.button !== 0 || !stage.value) return\n\n event.preventDefault()\n\n const rect = stage.value.getBoundingClientRect()\n const unit = rect.width / 100\n const element = (event.target as HTMLElement).closest('.webx-banner__layer') as HTMLElement | null\n const box = element?.getBoundingClientRect()\n const height = box ? box.height / unit : 0\n const from = { ...frameOf(layer) }\n const start = { x: event.clientX, y: event.clientY }\n let moving = false\n\n const move = (next: PointerEvent): void => {\n const dx = (next.clientX - start.x) / unit\n const dy = (next.clientY - start.y) / unit\n\n if (!moving) {\n if (Math.hypot(next.clientX - start.x, next.clientY - start.y) < SLOP) return\n\n moving = true\n remember()\n }\n\n guides.value = []\n\n if (mode === 'move') {\n // The box's own left and top, so its edges and its middle are what sticks.\n const shift = {\n x: (originShift(from.origin)[0] / 100) * from.w,\n y: (originShift(from.origin)[1] / 100) * height,\n }\n const left = snap('x', from.x + dx + shift.x, from.w, unit, layer.id, next.altKey)\n const top = snap('y', from.y + dy + shift.y, height, unit, layer.id, next.altKey)\n\n setFrame(layer.id, { x: left - shift.x, y: top - shift.y }, false)\n } else if (mode === 'width') {\n setFrame(layer.id, { w: Math.max(1, from.w + dx) }, false)\n } else {\n const factor = Math.max(0.05, (from.w + dx) / from.w)\n\n setFrame(layer.id, { w: from.w * factor, size: from.size * factor }, false)\n }\n }\n\n const up = (): void => {\n window.removeEventListener('pointermove', move)\n window.removeEventListener('pointerup', up)\n window.removeEventListener('pointercancel', up)\n guides.value = []\n }\n\n window.addEventListener('pointermove', move)\n window.addEventListener('pointerup', up)\n window.addEventListener('pointercancel', up)\n}\n\nfunction originShift(origin: LayerFrame['origin']): [number, number] {\n const x = origin.endsWith('r')\n ? -100\n : origin === 't' || origin === 'c' || origin === 'b'\n ? -50\n : 0\n const y = origin.startsWith('b')\n ? -100\n : origin === 'l' || origin === 'c' || origin === 'r'\n ? -50\n : 0\n\n return [x, y]\n}\n\nfunction pressCanvas(event: PointerEvent): void {\n if (!(event.target as HTMLElement).closest('.webx-banner__layer')) selectedId.value = null\n}\n\n/* --- Keyboard ---------------------------------------------------------------------------- */\n\nfunction onKeydown(event: KeyboardEvent): void {\n const mod = event.ctrlKey || event.metaKey\n const key = event.key.toLowerCase()\n\n if (mod && key === 'z') {\n event.preventDefault()\n\n if (event.shiftKey) redo()\n else undo()\n\n return\n }\n\n if (mod && key === 'y') {\n event.preventDefault()\n redo()\n\n return\n }\n\n const layer = selected.value\n\n if (!layer || props.disabled) return\n\n if (mod && key === 'd') {\n event.preventDefault()\n duplicate(layer.id)\n\n return\n }\n\n if (key === 'delete' || key === 'backspace') {\n event.preventDefault()\n remove(layer.id)\n\n return\n }\n\n if (key === 'escape') {\n selectedId.value = null\n\n return\n }\n\n const step = event.shiftKey ? 0.5 : 0.05\n const arrows: Record<string, [number, number]> = {\n arrowleft: [-step, 0],\n arrowright: [step, 0],\n arrowup: [0, -step],\n arrowdown: [0, step],\n }\n const by = arrows[key]\n\n if (!by) return\n\n event.preventDefault()\n\n const one = frameOf(layer)\n const now = Date.now()\n // A key held down is one step of history.\n const merge = lastEdit.id === `arrows:${layer.id}` && now - lastEdit.at < 800\n\n lastEdit = { id: `arrows:${layer.id}`, at: now }\n setFrame(layer.id, { x: one.x + by[0], y: one.y + by[1] }, !merge)\n}\n\n/* --- The theme --------------------------------------------------------------------------- */\n\nconst theme = ref<BannersTheme | null>(null)\nlet themeStyle: HTMLStyleElement | null = null\n\nonMounted(async () => {\n try {\n theme.value = await api.theme()\n } catch {\n theme.value = null\n }\n\n const css = `${theme.value?.tokens_css ?? ''}\\n${theme.value?.fonts_css ?? ''}`.trim()\n\n if (css !== '' && !document.getElementById('wx-banners-theme')) {\n themeStyle = document.createElement('style')\n themeStyle.id = 'wx-banners-theme'\n themeStyle.textContent = css\n document.head.append(themeStyle)\n }\n})\n\nonBeforeUnmount(() => {\n themeStyle?.remove()\n})\n\nconst viewOptions = computed(() => [\n { value: 'desktop', label: t('layers.desktop'), icon: 'monitor' as const },\n { value: 'mobile', label: t('layers.mobile'), icon: 'smartphone' as const },\n])\n\nconst viewModel = computed<string | number>({\n get: () => view.value,\n set: (value) => {\n view.value = value === 'mobile' ? 'mobile' : 'desktop'\n },\n})\n</script>\n\n<template>\n <div class=\"wx-banner-layers\" :class=\"{ 'is-disabled': disabled }\">\n <div class=\"wx-banner-layers__bar\">\n <wx-segmented\n v-model=\"viewModel\"\n :options=\"viewOptions\"\n size=\"sm\"\n :aria-label=\"t('layers.layout')\"\n />\n\n <div class=\"wx-banner-layers__tools\">\n <wx-tooltip :content=\"t('layers.undo')\">\n <wx-button\n size=\"sm\"\n variant=\"text\"\n :disabled=\"disabled || past.length === 0\"\n :aria-label=\"t('layers.undo')\"\n @click=\"undo\"\n >\n <template #icon><wx-icon name=\"rotate-left\" /></template>\n </wx-button>\n </wx-tooltip>\n <wx-tooltip :content=\"t('layers.redo')\">\n <wx-button\n size=\"sm\"\n variant=\"text\"\n :disabled=\"disabled || future.length === 0\"\n :aria-label=\"t('layers.redo')\"\n @click=\"redo\"\n >\n <template #icon><wx-icon name=\"rotate-right\" /></template>\n </wx-button>\n </wx-tooltip>\n <wx-button size=\"sm\" variant=\"outline\" :disabled=\"disabled\" @click=\"add('text')\">\n <template #icon><wx-icon name=\"plus\" /></template>\n {{ t('layers.text') }}\n </wx-button>\n <wx-button size=\"sm\" variant=\"outline\" :disabled=\"disabled\" @click=\"add('image')\">\n <template #icon><wx-icon name=\"plus\" /></template>\n {{ t('layers.image') }}\n </wx-button>\n <wx-button size=\"sm\" variant=\"outline\" :disabled=\"disabled\" @click=\"add('button')\">\n <template #icon><wx-icon name=\"plus\" /></template>\n {{ t('layers.button') }}\n </wx-button>\n <wx-button\n v-if=\"!hasButtonsLayer\"\n size=\"sm\"\n variant=\"outline\"\n :disabled=\"disabled\"\n @click=\"add('buttons')\"\n >\n <template #icon><wx-icon name=\"plus\" /></template>\n {{ t('layers.buttons-layer') }}\n </wx-button>\n </div>\n </div>\n\n <wx-text v-if=\"!place\" size=\"sm\" tone=\"muted\">{{ t('layers.not-here') }}</wx-text>\n\n <div class=\"wx-banner-layers__body\">\n <div class=\"wx-banner-layers__main\">\n <div\n ref=\"canvas\"\n class=\"wx-banner-layers__canvas\"\n :class=\"{ 'is-overflow': place?.overflow }\"\n tabindex=\"0\"\n :aria-label=\"t('layers.canvas')\"\n @pointerdown=\"pressCanvas\"\n @keydown=\"onKeydown\"\n >\n <div\n class=\"webx-banner wx-banner-layers__frame\"\n :class=\"{ 'is-mobile': view === 'mobile' }\"\n :style=\"frameStyle\"\n >\n <div class=\"webx-banner__picture\">\n <img v-if=\"background\" class=\"webx-banner__image\" :src=\"background.url\" alt=\"\" />\n <div v-else class=\"wx-banner-layers__empty\">{{ t('layers.no-picture') }}</div>\n </div>\n\n <div ref=\"stage\" class=\"webx-banner__stage\">\n <component\n :is=\"tagOf(layer)\"\n v-for=\"(layer, index) in layers\"\n :key=\"layer.id\"\n :class=\"[\n ...layerClasses(layer),\n { 'is-selected': layer.id === selectedId, 'is-outside': outside(layer) },\n ]\"\n :style=\"layerVars(layer, layers.length - index)\"\n @pointerdown.stop=\"press($event, layer, 'move')\"\n >\n <span\n v-if=\"layer.type === 'text'\"\n class=\"webx-banner__inner wx-banner-layers__words\"\n >{{ wordsOf(layer) || '…' }}</span\n >\n <img\n v-else-if=\"layer.type === 'image'\"\n class=\"webx-banner__inner\"\n :src=\"pictures[pathOf(layer.image) ?? '']?.url ?? ''\"\n alt=\"\"\n draggable=\"false\"\n />\n <span\n v-else-if=\"layer.type === 'button'\"\n class=\"webx-banner__inner webx-banner__buttons\"\n >\n <span\n :class=\"[\n 'webx-banner__button',\n `webx-banner__button--${layer.variant ?? place?.variants[0]?.value ?? 'primary'}`,\n ]\"\n >\n {{ wordsOf(layer) || '…' }}\n </span>\n </span>\n <span v-else class=\"webx-banner__inner webx-banner__buttons\">\n <span\n v-for=\"(button, at) in bannerButtons\"\n :key=\"at\"\n :class=\"['webx-banner__button', `webx-banner__button--${button.variant}`]\"\n >{{ button.label }}</span\n >\n <span v-if=\"bannerButtons.length === 0\" class=\"webx-banner__button\">{{\n t('layers.buttons-layer')\n }}</span>\n </span>\n\n <template v-if=\"layer.id === selectedId && !disabled\">\n <span\n class=\"wx-banner-layers__handle wx-banner-layers__handle--width\"\n @pointerdown.stop=\"press($event, layer, 'width')\"\n />\n <span\n class=\"wx-banner-layers__handle wx-banner-layers__handle--scale\"\n @pointerdown.stop=\"press($event, layer, 'scale')\"\n />\n </template>\n </component>\n </div>\n\n <div\n class=\"wx-banner-layers__crop\"\n :style=\"{\n left: `${crop.left}%`,\n top: `${crop.top}%`,\n width: `${crop.width}%`,\n height: `${crop.height}%`,\n }\"\n />\n\n <div\n v-for=\"guide in guides\"\n :key=\"guide.axis\"\n :class=\"['wx-banner-layers__guide', `wx-banner-layers__guide--${guide.axis}`]\"\n :style=\"\n guide.axis === 'x' ? { left: `${guide.at}%` } : { top: `calc(${guide.at} * 1cqw)` }\n \"\n />\n </div>\n </div>\n\n <wx-text size=\"sm\" tone=\"muted\">{{ t('layers.hint') }}</wx-text>\n\n <wx-sortable-list\n v-model=\"listModel\"\n class=\"wx-banner-layers__list\"\n item-key=\"id\"\n size=\"sm\"\n :disabled=\"disabled\"\n :empty-text=\"t('layers.empty')\"\n :aria-label=\"t('layers.list')\"\n >\n <template #default=\"{ item }\">\n <button\n type=\"button\"\n class=\"wx-banner-layers__row\"\n :class=\"{ 'is-selected': (item as BannerLayer).id === selectedId }\"\n @click=\"select(item as BannerLayer)\"\n >\n <wx-icon :name=\"icons[(item as BannerLayer).type] as 'image'\" />\n <span class=\"wx-banner-layers__name\">{{ labelOf(item as BannerLayer) }}</span>\n <wx-icon\n v-if=\"outside(item as BannerLayer)\"\n name=\"warning\"\n class=\"wx-banner-layers__warn\"\n :aria-label=\"t('layers.outside')\"\n />\n </button>\n </template>\n <template #actions=\"{ item }\">\n <wx-button\n size=\"sm\"\n variant=\"text\"\n :disabled=\"disabled\"\n :aria-label=\"\n frameOf(item as BannerLayer).hidden ? t('layers.show') : t('layers.hide')\n \"\n @click=\"toggleHidden(item as BannerLayer)\"\n >\n <template #icon>\n <wx-icon :name=\"frameOf(item as BannerLayer).hidden ? 'eye-off' : 'eye'\" />\n </template>\n </wx-button>\n <wx-button\n size=\"sm\"\n variant=\"text\"\n :disabled=\"disabled\"\n :aria-label=\"t('layers.delete')\"\n @click=\"remove((item as BannerLayer).id)\"\n >\n <template #icon><wx-icon name=\"trash\" /></template>\n </wx-button>\n </template>\n </wx-sortable-list>\n </div>\n\n <layer-inspector\n v-if=\"selected\"\n class=\"wx-banner-layers__inspector\"\n :layer=\"selected\"\n :view=\"view\"\n :tags=\"place?.tags ?? []\"\n :variants=\"place?.variants ?? []\"\n :palette=\"theme?.palette ?? []\"\n :disabled=\"disabled\"\n @update=\"edit\"\n @frame=\"(patch: Partial<LayerFrame>) => setFrame(selected!.id, patch)\"\n @same-as-desktop=\"\n replace(selected!.id, (layer) => ({\n ...layer,\n frames: { ...layer.frames, mobile: null },\n }))\n \"\n @delete=\"remove(selected!.id)\"\n />\n <wx-text v-else class=\"wx-banner-layers__inspector\" size=\"sm\" tone=\"muted\">\n {{ t('layers.choose') }}\n </wx-text>\n </div>\n </div>\n</template>\n\n<style scoped>\n.wx-banner-layers {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-12);\n container-type: inline-size;\n min-width: 0;\n}\n\n.wx-banner-layers__bar {\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-banner-layers__tools {\n display: flex;\n flex-wrap: wrap;\n gap: var(--wx-space-4);\n}\n\n.wx-banner-layers__body {\n display: grid;\n grid-template-columns: minmax(0, 1fr);\n gap: var(--wx-space-16);\n}\n\n@container (min-width: 900px) {\n .wx-banner-layers__body {\n grid-template-columns: minmax(0, 1fr) 320px;\n align-items: start;\n }\n}\n\n.wx-banner-layers__main {\n display: flex;\n flex-direction: column;\n gap: var(--wx-space-8);\n min-width: 0;\n}\n\n.wx-banner-layers__canvas {\n position: relative;\n /* The layers, the shade and the guides stack inside the canvas, never over the sticky bar. */\n isolation: isolate;\n overflow: hidden;\n border-radius: var(--wx-radius-sm);\n background: var(--wx-bg-muted, var(--wx-bg-surface));\n outline-offset: 2px;\n user-select: none;\n touch-action: none;\n}\n\n/* Room below the picture for a layer that steps out of the frame (decision 13). */\n.wx-banner-layers__canvas.is-overflow {\n padding-bottom: 24%;\n background-image: repeating-linear-gradient(\n 45deg,\n transparent 0 8px,\n color-mix(in srgb, var(--wx-text-muted) 12%, transparent) 8px 9px\n );\n}\n\n.wx-banner-layers__canvas:focus-visible {\n outline: 2px solid var(--wx-color-primary);\n}\n\n.wx-banner-layers__frame {\n overflow: visible;\n}\n\n.wx-banner-layers__frame :deep(.webx-banner__stage) {\n pointer-events: auto;\n}\n\n/* The site's motion is the site's: the canvas stands still, so a layer is where it ends up. */\n.wx-banner-layers__frame :deep(.webx-banner__layer),\n.wx-banner-layers__frame :deep(.webx-banner__inner) {\n animation: none !important;\n cursor: move;\n pointer-events: auto;\n}\n\n.wx-banner-layers__words {\n white-space: pre-line;\n}\n\n.wx-banner-layers__frame :deep(.webx-banner__layer.is-selected) {\n outline: 2px solid var(--wx-color-primary);\n outline-offset: 1px;\n}\n\n.wx-banner-layers__frame :deep(.webx-banner__layer:hover:not(.is-selected)) {\n outline: 1px dashed var(--wx-color-primary);\n}\n\n.wx-banner-layers__frame :deep(.webx-banner__layer.is-outside) {\n opacity: 0.5;\n}\n\n.wx-banner-layers__handle {\n position: absolute;\n width: 10px;\n height: 10px;\n border: 2px solid var(--wx-color-primary);\n border-radius: 2px;\n background: var(--wx-bg-surface);\n translate: 50% -50%;\n}\n\n.wx-banner-layers__handle--width {\n top: 50%;\n right: 0;\n cursor: ew-resize;\n}\n\n.wx-banner-layers__handle--scale {\n right: 0;\n bottom: 0;\n translate: 50% 50%;\n cursor: nwse-resize;\n}\n\n/* What the frame of the place crops away is shaded: the site never shows it. */\n.wx-banner-layers__crop {\n position: absolute;\n z-index: 1000;\n box-shadow: 0 0 0 100vmax rgb(0 0 0 / 0.45);\n outline: 1px dashed rgb(255 255 255 / 0.8);\n pointer-events: none;\n}\n\n.wx-banner-layers__guide {\n position: absolute;\n z-index: 1001;\n background: var(--wx-color-primary);\n pointer-events: none;\n}\n\n.wx-banner-layers__guide--x {\n top: 0;\n bottom: 0;\n width: 1px;\n}\n\n.wx-banner-layers__guide--y {\n left: 0;\n right: 0;\n height: 1px;\n}\n\n.wx-banner-layers__empty {\n display: grid;\n place-items: center;\n height: 100%;\n color: var(--wx-text-muted);\n}\n\n.wx-banner-layers__row {\n display: flex;\n align-items: center;\n gap: var(--wx-space-8);\n width: 100%;\n min-width: 0;\n padding: 0;\n border: 0;\n background: none;\n color: inherit;\n font: inherit;\n text-align: start;\n cursor: pointer;\n}\n\n.wx-banner-layers__row.is-selected {\n color: var(--wx-color-primary);\n font-weight: 600;\n}\n\n.wx-banner-layers__name {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.wx-banner-layers__warn {\n color: var(--wx-color-warning);\n}\n</style>\n","import type { AdminModule } from '@webx-ui/module-admin'\nimport LayersField from './LayersField.vue'\n\nexport interface BannersOptions {\n /** Where the banners live inside the panel. */\n path?: string\n}\n\n/**\n * Banners as a section of the panel (§5.4): one module and one entry, without a group.\n *\n * Two screens. The places and the banners of one of them are a list and its detail, the way the\n * menus are; a banner is a page of its own, because its form is long — three pictures, the words\n * and up to three buttons — and a pane beside a list is no room for it. A section whose server\n * half is not installed never appears — the entry is built from the manifest.\n */\nexport function banners(options: BannersOptions = {}): AdminModule {\n const path = options.path ?? '/banners'\n\n return {\n id: 'banners',\n path,\n routes: [\n // The open place is in the address (`?place=`), so a link to it is a link to its banners.\n {\n path,\n name: 'webx.banners',\n component: () => import('./BannersPage.vue'),\n props: { base: path },\n },\n // A banner not written yet: the place it goes to rides in the query (`?place=hero`).\n {\n path: `${path}/new`,\n name: 'webx.banners.new',\n component: () => import('./BannerEditorPage.vue'),\n props: { base: path },\n },\n {\n path: `${path}/:id(\\\\d+)`,\n name: 'webx.banners.edit',\n component: () => import('./BannerEditorPage.vue'),\n props: { base: path },\n },\n ],\n /*\n * The one node of `banners.form` only this module can draw: the layers, on the banner's\n * picture. A field like any other — its value is the list of layers.\n */\n types: {\n 'wx-banner-layers': { component: LayersField, kind: 'field', wide: true },\n },\n }\n}\n","import { defineAsyncComponent } from 'vue'\nexport { banners, type BannersOptions } from './module'\nexport { createBannersApi, type BannersApi } from './api'\nexport { bannersMessages } from './messages'\nexport const WxBannersPage = defineAsyncComponent(() => import('./BannersPage.vue'))\nexport const WxBannerEditorPage = defineAsyncComponent(() => import('./BannerEditorPage.vue'))\nexport { default as WxBannerLayers } from './LayersField.vue'\nexport * from './layers'\nexport type {\n BannerButton,\n BannerDetail,\n BannerRow,\n BannerSummary,\n PlaceInput,\n PlaceLayers,\n PlaceRow,\n BannersTheme,\n} from './types'\n"],"names":["createBannersApi","admin","base","place","key","data","body","input","title","trashed","id","values","ids","provideBannerEditor","context","provide","useBannerEditor","inject","bannersMessages","seeded","useBannersMessages","i18n","useAdmin","FRAME_LIMITS","ORIGINS","ORIGIN_SHIFT","ENTRANCES","LOOPS","FIELDS","frame","over","style","motion","clone","value","layerId","taken","used","newLayer","type","locale","defaultLayers","defaultLocale","next","layer","made","layerWords","text","order","fields","map","code","one","unknownFields","match","name","cssColor","color","token","round","layerVars","z","vars","desktop","mobile","prefix","ox","oy","background","layerClasses","classes","ratioOf","fallback","ratio","cropBox","image","frameRatio","width","height","clampFrame","min","max","props","__props","emit","__emit","t","useTranslate","locales","useLocales","current","computed","ownPhone","change","mutate","setStyle","hasWords","typos","typoList","fallsBackTo","active","insert","field","words","link","choice","get","set","tag","variant","font","weight","align","entrance","loop","numbers","steps","setNumber","setOrigin","origin","fontOptions","weightOptions","alignOptions","entranceOptions","loopOptions","colorOf","pickColor","hex","_openBlock","_createElementBlock","_hoisted_1","_createElementVNode","_hoisted_2","_createVNode","_unref","WxInput","$event","WxButton","WxIcon","_createTextVNode","_Fragment","WxFormItem","_createBlock","WxTextarea","_hoisted_3","_cache","WxText","_toDisplayString","WxSelect","WxMediaField","WxLinkField","_hoisted_4","_hoisted_5","_hoisted_6","_renderList","WxInputNumber","_normalizeClass","WxSwitch","_hoisted_9","_hoisted_10","WxSegmented","_hoisted_11","_hoisted_12","swatch","_normalizeStyle","WxColorPicker","_hoisted_14","_hoisted_15","SLOP","SNAP","editor","media","createMediaApi","api","layers","view","ref","selectedId","selected","past","future","remember","commit","record","undo","last","redo","replace","frameOf","which","setFrame","patch","lastEdit","edit","now","merge","add","remove","duplicate","index","source","copy","toggleHidden","hasButtonsLayer","listModel","pictures","reactive","pathOf","path","resolve","file","desktopPath","mobilePath","watch","paths","imageRatio","crop","frameStyle","ownFields","own","wordsOf","bannerButtons","button","tagOf","labelOf","icons","outside","box","left","right","top","bottom","x","originShift","stage","canvas","guides","snapTargets","axis","skip","targets","snap","size","unit","free","edges","best","target","edge","delta","select","press","event","mode","from","start","moving","move","dx","dy","shift","factor","up","y","pressCanvas","onKeydown","mod","step","by","theme","themeStyle","onMounted","css","onBeforeUnmount","viewOptions","viewModel","WxTooltip","_hoisted_8","_resolveDynamicComponent","_withModifiers","at","_hoisted_13","guide","WxSortableList","_withCtx","item","_hoisted_17","LayerInspector","banners","options","LayersField","WxBannersPage","defineAsyncComponent","WxBannerEditorPage"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,8 +1,20 @@
1
1
  export { banners, type BannersOptions } from './module';
2
2
  export { createBannersApi, type BannersApi } from './api';
3
3
  export { bannersMessages } from './messages';
4
- export { default as WxBannersPage } from './BannersPage';
5
- export { default as WxBannerEditorPage } from './BannerEditorPage';
4
+ export declare const WxBannersPage: import('vue').DefineComponent<{
5
+ base?: string;
6
+ }, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{
7
+ base?: string;
8
+ }> & Readonly<{}>, {
9
+ base: string;
10
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
11
+ export declare const WxBannerEditorPage: import('vue').DefineComponent<{
12
+ base?: string;
13
+ }, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<{
14
+ base?: string;
15
+ }> & Readonly<{}>, {
16
+ base: string;
17
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
6
18
  export { default as WxBannerLayers } from './LayersField';
7
19
  export * from './layers';
8
20
  export type { BannerButton, BannerDetail, BannerRow, BannerSummary, PlaceInput, PlaceLayers, PlaceRow, BannersTheme, } from './types';