@baack-software/baack-ts-editor 0.1.1 → 0.1.2
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/editor.js +6 -6
- package/dist/editor.js.map +3 -3
- package/package.json +1 -1
package/dist/editor.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../node_modules/@baack-software/baack-ts-components/src/core/vnode.ts", "../src/core/registry.ts", "../src/core/discovery.ts", "../src/core/pending.ts", "../src/core/stash.ts", "../node_modules/@baack-software/baack-ts-client/src/entity-view.ts", "../src/core/store.ts", "../src/core/scoped-views.ts", "../src/targets.ts", "../src/ui/marker.ts", "../node_modules/@baack-software/baack-ts-components/src/core/format.ts", "../node_modules/@baack-software/baack-ts-components/src/core/components.ts", "../src/types/values.ts", "../src/images.ts", "../node_modules/@baack-software/baack-ts-components/src/core/live.ts", "../src/live.ts", "../src/ui/inline.ts", "../src/editing.ts", "../src/ui/messages.ts", "../src/feedback.ts", "../src/core/diff.ts", "../src/core/events.ts", "../src/ui/form.ts", "../src/saving.ts", "../src/ui/change.ts", "../src/ui/history-view.ts", "../src/ui/tooltip.ts", "../src/ui/stack.ts", "../src/history.ts", "../src/core/ordering.ts", "../src/templates.ts", "../src/ui/reorder-panel.ts", "../src/moves.ts", "../src/ui/order-tags.ts", "../src/core/groups.ts", "../src/core/entity-directory.ts", "../src/page-entity.ts", "../src/onboarding.ts", "../src/ui/review-view.ts", "../src/publishing.ts", "../src/ui/outline.ts", "../src/outline-model.ts", "../src/after-publish.ts", "../src/ui/entity-picker.ts", "../src/ui/menu.ts", "../src/ui/popover.ts", "../src/ui/toolbar.ts", "../src/ui/transition.ts", "../src/view.ts", "../src/controller.ts", "../src/types/text.ts", "../src/types/index.ts", "../src/editor.ts"],
|
|
4
|
-
"sourcesContent": [null, "// The type registry: one entry per item type. Everything type-specific lives\n// in an entry; the rest of the editor works on any entry through the generic\n// helpers below.\n\nimport type { Entity, EntityView } from '@baack-software/baack-ts-client';\nimport type { ComponentSpec } from '@baack-software/baack-ts-components/components';\nimport { patch } from '@baack-software/baack-ts-components/vnode';\n\n/** The keys of Entity that hold item arrays. */\nexport type ItemArrayKey =\n | 'texts'\n | 'markdowns'\n | 'templates'\n | 'jsons'\n | 'booleans'\n | 'longs'\n | 'doubles'\n | 'dateTimes'\n | 'latLongs'\n | 'money'\n | 'images'\n | 'links'\n | 'references';\n\nexport type ContentItem = NonNullable<Entity[ItemArrayKey]>[number];\n\nexport type ItemType =\n | 'text'\n | 'markdown'\n | 'template'\n | 'json'\n | 'boolean'\n | 'long'\n | 'double'\n | 'dateTime'\n | 'latLong'\n | 'money'\n | 'image'\n | 'link'\n | 'reference';\n\n/** Fields every item carries that are not part of its value. */\ntype ItemMeta = 'urn' | 'url' | 'name' | 'sortOrder' | 'entity' | 'isPublished' | 'createdTimestamp' | 'history';\n\n/** The value fields of an item, for example `{value}` or `{latitude, longitude}`. */\nexport type ItemValue<I extends ContentItem> = Omit<I, ItemMeta>;\n\n/** What is sent on a create or update: JSON types as the API expects, entity by URN only. */\nexport type ItemRepresentation<I extends ContentItem> = ItemValue<I> & {\n urn?: string;\n name: string;\n sortOrder: number;\n entity: { urn: string };\n};\n\nexport interface Issue {\n level: 'warning' | 'error';\n message: string;\n}\n\n/** `entity`: an entity URN, chosen by path and language. */\nexport type FieldKind = 'text' | 'textarea' | 'code' | 'integer' | 'decimal' | 'checkbox' | 'datetime' | 'currency' | 'url' | 'file' | 'entity';\n\nexport interface FieldSpec {\n key: string;\n label: string;\n kind: FieldKind;\n}\n\nexport type FormValues = Record<string, string | boolean>;\n\n/** A form editor for the popover or panel. */\nexport interface FormSpec<I extends ContentItem> {\n fields: readonly FieldSpec[];\n toForm(value: ItemValue<I>): FormValues;\n /** The value the form describes, or an error message. */\n fromForm(values: FormValues): ItemValue<I> | string;\n /** A line shown under the form, e.g. what will be stored. */\n describe?(values: FormValues): string;\n}\n\nexport interface TypeEntry<I extends ContentItem = ContentItem> {\n readonly type: ItemType;\n readonly label: string;\n /** The `<attribute>` in `data-<attribute>-name`, `-sort-order` and `-urn`. */\n readonly attribute: string;\n readonly entityArray: ItemArrayKey;\n readonly endpoint: string;\n readonly historyEndpoint: string;\n /** Where the value is edited: in place, in a popover, or in the wider panel. */\n readonly surface: 'inline' | 'popover' | 'panel';\n /** The value fields a write sends. */\n readonly valueKeys: readonly string[];\n /** Fields the API derives (money's formattedValue); never sent, and dropped from previews. */\n readonly derived?: readonly string[];\n /**\n * Fields kept from the current version unless the edit replaces them: an\n * image's file addresses, which the API keeps only when an update passes\n * them back unchanged.\n */\n readonly carried?: readonly string[];\n /**\n * The page shows the entity view's rendering (markdown, templates). A write\n * returns the source, which must never be rendered; the editor re-reads the view.\n */\n readonly renderedByView?: boolean;\n /** The component that rendered an element. Absent for types with nothing to show (JSON, references). */\n component?(element: Element): ComponentSpec<I, unknown>;\n /** The item at a name and stored sort order in an entity view. */\n find(view: EntityView, name: string, sortOrder: number): I | undefined;\n defaults(): ItemValue<I>;\n /** In-place editing only: the value an element shows while being edited. */\n read?(element: HTMLElement): ItemValue<I>;\n /** Popover and panel editing. */\n form?: FormSpec<I>;\n /**\n * The value a new item starts from, read from the placeholder an element\n * shows. Undefined when the placeholder is not a value (for example\n * \"Contact us\" in a price); the type's defaults are used instead.\n */\n fromPlaceholder?(element: HTMLElement): ItemValue<I> | undefined;\n validate(value: ItemValue<I>): Issue[];\n}\n\n/** An edit's value with the carried fields of the version it is based on filled in. */\nexport function withCarried<I extends ContentItem>(entry: TypeEntry<I>, base: ItemValue<I> | I | undefined, value: ItemValue<I>): ItemValue<I> {\n if (!entry.carried || !base) return value;\n const merged: Record<string, unknown> = { ...value };\n for (const key of entry.carried) {\n const kept = (base as Record<string, unknown>)[key];\n if (!(key in merged) && kept !== undefined) merged[key] = kept;\n }\n return merged as ItemValue<I>;\n}\n\n/** The value fields of an item. */\nexport function valueOf<I extends ContentItem>(entry: TypeEntry<I>, item: ItemValue<I> | I): ItemValue<I> {\n const value: Record<string, unknown> = {};\n for (const key of entry.valueKeys) {\n const field = (item as Record<string, unknown>)[key];\n if (field !== undefined) value[key] = field;\n }\n return value as ItemValue<I>;\n}\n\nexport function sameValue<I extends ContentItem>(entry: TypeEntry<I>, a: ItemValue<I> | I, b: ItemValue<I> | I): boolean {\n return JSON.stringify(valueOf(entry, a)) === JSON.stringify(valueOf(entry, b));\n}\n\n/** An item showing a pending value, without the fields the API would derive from the old one. */\nexport function preview<I extends ContentItem>(entry: TypeEntry<I>, item: I, value: ItemValue<I>): I {\n const merged: Record<string, unknown> = { ...item, ...value };\n for (const key of entry.derived ?? []) delete merged[key];\n return merged as I;\n}\n\n/** Re-renders an element exactly as its component would, for an item (or its placeholder). */\nexport function renderInto<I extends ContentItem>(\n entry: TypeEntry<I>,\n element: HTMLElement,\n slot: { name: string; sortOrder: number },\n item: I | undefined,\n): void {\n const spec = entry.component?.(element);\n if (!spec) return;\n const props = spec.propsFrom(element);\n patch(element, spec.render({ name: slot.name, sortOrder: slot.sortOrder, item }, props), spec.volatile, spec.ownsChildren);\n}\n\n/** Builds the body for a create or update of `item` with a new value. */\nexport function toRepresentation<I extends ContentItem>(\n entry: TypeEntry<I>,\n item: I,\n value: ItemValue<I>,\n entityUrn: string,\n): ItemRepresentation<I> {\n const representation = {\n ...valueOf(entry, value),\n name: item.name,\n sortOrder: item.sortOrder,\n entity: { urn: entityUrn },\n } as ItemRepresentation<I>;\n if (item.urn !== undefined) representation.urn = item.urn;\n return representation;\n}\n\nexport function nameAttribute(entry: TypeEntry): string {\n return `data-${entry.attribute}-name`;\n}\n\nexport function sortOrderAttribute(entry: TypeEntry): string {\n return `data-${entry.attribute}-sort-order`;\n}\n\nexport function urnAttribute(entry: TypeEntry): string {\n return `data-${entry.attribute}-urn`;\n}\n", "// Finds item elements on the page, continuously. Islands and client-rendered\n// content can add elements at any time, so a MutationObserver keeps the set of\n// bindings current.\n\nimport { nameAttribute, sortOrderAttribute, type TypeEntry } from './registry.ts';\n\nexport const SCOPE_ATTRIBUTE = 'data-entity-urn';\n\n/** One element showing one item slot. */\nexport interface Binding {\n readonly element: HTMLElement;\n readonly entry: TypeEntry;\n /** The `data-entity-urn` of the nearest ancestor scope. */\n readonly scope: string;\n readonly name: string;\n /** The stored sort order to match. A bare name means 0. */\n readonly sortOrder: number;\n}\n\n/** An element naming an item but outside any `data-entity-urn` scope: the page has no entity yet. */\nexport interface UnscopedSlot {\n readonly element: HTMLElement;\n readonly entry: TypeEntry;\n readonly name: string;\n readonly sortOrder: number;\n}\n\nexport interface DiscoveryListener {\n added(bindings: Binding[]): void;\n removed(bindings: Binding[]): void;\n}\n\nexport class Discovery {\n private readonly entries: readonly TypeEntry[];\n private readonly listener: DiscoveryListener;\n private readonly selector: string;\n private readonly byElement = new Map<HTMLElement, Binding[]>();\n private readonly unscopedByElement = new Map<HTMLElement, UnscopedSlot[]>();\n private readonly observer: MutationObserver;\n private readonly warned = new WeakSet<Element>();\n\n constructor(entries: readonly TypeEntry[], listener: DiscoveryListener) {\n this.entries = entries;\n this.listener = listener;\n this.selector = entries.map((entry) => `[${nameAttribute(entry)}]`).join(',');\n this.observer = new MutationObserver((records) => this.onMutations(records));\n }\n\n start(root: Element = document.documentElement): void {\n this.scan(root);\n this.observer.observe(root, {\n subtree: true,\n childList: true,\n attributes: true,\n attributeFilter: [\n SCOPE_ATTRIBUTE,\n ...this.entries.flatMap((entry) => [nameAttribute(entry), sortOrderAttribute(entry)]),\n ],\n });\n }\n\n stop(): void {\n this.observer.disconnect();\n }\n\n all(): Binding[] {\n return [...this.byElement.values()].flat();\n }\n\n unscoped(): UnscopedSlot[] {\n for (const element of this.unscopedByElement.keys()) {\n if (!element.isConnected) this.unscopedByElement.delete(element);\n }\n return [...this.unscopedByElement.values()].flat();\n }\n\n of(element: HTMLElement): Binding[] {\n return this.byElement.get(element) ?? [];\n }\n\n /** The nearest bound element at or above `target`. */\n closest(target: EventTarget | null): HTMLElement | undefined {\n if (!(target instanceof Element)) return undefined;\n const element = target.closest(this.selector);\n return element instanceof HTMLElement && this.byElement.has(element) ? element : undefined;\n }\n\n /** Applies changes the observer has not delivered yet, so bindings match the page now. */\n flush(): void {\n const records = this.observer.takeRecords();\n if (records.length > 0) this.onMutations(records);\n }\n\n private onMutations(records: MutationRecord[]): void {\n const rescan = new Set<Element>();\n let removedSome = false;\n for (const record of records) {\n if (record.type === 'attributes' && record.target instanceof Element) {\n rescan.add(record.target);\n }\n for (const node of record.addedNodes) {\n if (node instanceof Element) rescan.add(node);\n }\n if (record.removedNodes.length > 0) removedSome = true;\n }\n\n if (removedSome) this.sweep();\n for (const element of rescan) {\n if (element.isConnected) this.scan(element);\n }\n }\n\n /** Binds `root` and its descendants, replacing bindings whose attributes changed. */\n private scan(root: Element): void {\n const candidates = [...root.querySelectorAll<HTMLElement>(this.selector)];\n if (root instanceof HTMLElement && root.matches(this.selector)) candidates.unshift(root);\n // A scope change on root also changes the scope of bound descendants.\n const added: Binding[] = [];\n const removed: Binding[] = [];\n\n for (const element of candidates) {\n const next = this.bind(element);\n const unscoped = this.unscopedSlots(element);\n if (unscoped.length > 0) {\n this.unscopedByElement.set(element, unscoped);\n } else {\n this.unscopedByElement.delete(element);\n }\n const previous = this.byElement.get(element) ?? [];\n if (sameBindings(previous, next)) continue;\n removed.push(...previous);\n added.push(...next);\n if (next.length > 0) {\n this.byElement.set(element, next);\n } else {\n this.byElement.delete(element);\n }\n }\n\n // Elements that no longer match (a name attribute was removed).\n if (root instanceof HTMLElement && !root.matches(this.selector) && this.byElement.has(root)) {\n removed.push(...this.byElement.get(root)!);\n this.byElement.delete(root);\n }\n\n if (removed.length > 0) this.listener.removed(removed);\n if (added.length > 0) this.listener.added(added);\n }\n\n private sweep(): void {\n const removed: Binding[] = [];\n for (const [element, bindings] of this.byElement) {\n if (!element.isConnected) {\n removed.push(...bindings);\n this.byElement.delete(element);\n }\n }\n if (removed.length > 0) this.listener.removed(removed);\n }\n\n private bind(element: HTMLElement): Binding[] {\n const scope = element.closest(`[${SCOPE_ATTRIBUTE}]`)?.getAttribute(SCOPE_ATTRIBUTE);\n const bindings: Binding[] = [];\n for (const entry of this.entries) {\n const name = element.getAttribute(nameAttribute(entry));\n if (!name) continue;\n if (!scope) continue; // Kept as an unscoped slot, for onboarding.\n const sortOrder = this.sortOrder(element, entry);\n if (sortOrder !== undefined) bindings.push({ element, entry, scope, name, sortOrder });\n }\n return bindings;\n }\n\n private unscopedSlots(element: HTMLElement): UnscopedSlot[] {\n if (element.closest(`[${SCOPE_ATTRIBUTE}]`)) return [];\n const slots: UnscopedSlot[] = [];\n for (const entry of this.entries) {\n const name = element.getAttribute(nameAttribute(entry));\n const sortOrder = name ? this.sortOrder(element, entry) : undefined;\n if (name && sortOrder !== undefined) slots.push({ element, entry, name, sortOrder });\n }\n return slots;\n }\n\n private sortOrder(element: HTMLElement, entry: TypeEntry): number | undefined {\n const rawOrder = element.getAttribute(sortOrderAttribute(entry));\n const sortOrder = rawOrder === null || rawOrder.trim() === '' ? 0 : Number(rawOrder);\n if (Number.isInteger(sortOrder)) return sortOrder;\n this.warn(element, `has ${sortOrderAttribute(entry)}=\"${rawOrder}\", which is not an integer`);\n return undefined;\n }\n\n private warn(element: Element, problem: string): void {\n if (this.warned.has(element)) return;\n this.warned.add(element);\n console.warn(`Baack editor: element ${problem}; it will not be editable.`, element);\n }\n}\n\nfunction sameBindings(a: Binding[], b: Binding[]): boolean {\n return (\n a.length === b.length &&\n a.every(\n (binding, i) =>\n binding.entry === b[i]!.entry &&\n binding.scope === b[i]!.scope &&\n binding.name === b[i]!.name &&\n binding.sortOrder === b[i]!.sortOrder,\n )\n );\n}\n", "// Unsent work: edits to existing versions (keyed by URN) and creates of new\n// items (keyed by entity, type, name and sort order, since they have no URN\n// until the POST returns). Plain data, so it can be stashed.\n\nimport type { ContentItem, ItemType, ItemValue } from './registry.ts';\n\ntype Value = ItemValue<ContentItem>;\n\nexport interface PendingEdit {\n kind: 'edit';\n type: ItemType;\n urn: string;\n entityUrn: string;\n name: string;\n sortOrder: number;\n value: Value;\n /** Restored from the stash, but the item has a newer version now. Not sendable until resolved. */\n stale?: boolean;\n /** Deliberately based on an older version (\"edit from this version\"): no conflict check. */\n fromVersion?: boolean;\n}\n\nexport interface PendingCreate {\n kind: 'create';\n type: ItemType;\n entityUrn: string;\n name: string;\n sortOrder: number;\n value: Value;\n}\n\n/**\n * One step of a planned move (a reorder, swap, shift, row move or rename):\n * the item `urn` gets `to`. Steps of one plan share `planId` and run in the\n * order they were queued; a step whose target is already in place is\n * skipped, so a plan can be replayed safely.\n */\nexport interface PendingMove {\n kind: 'move';\n planId: string;\n /** What the plan does, for people: \"Reorder feature\", \"Swap price #0 and #1\". */\n label: string;\n type: ItemType;\n urn: string;\n entityUrn: string;\n /** Where the item is now. */\n name: string;\n sortOrder: number;\n to: { name: string; sortOrder: number };\n}\n\nexport type Pending = PendingEdit | PendingCreate | PendingMove;\n\nexport function createKey(slot: { entityUrn: string; type: ItemType; name: string; sortOrder: number }): string {\n return `${slot.entityUrn}|${slot.type}|${slot.name}|${slot.sortOrder}`;\n}\n\nexport function pendingKey(pending: Pending): string {\n if (pending.kind === 'move') return `move|${pending.planId}|${pending.urn}`;\n return pending.kind === 'edit' ? pending.urn : createKey(pending);\n}\n\nexport class PendingEdits {\n private readonly items = new Map<string, Pending>();\n private readonly onChange: () => void;\n\n constructor(onChange: () => void) {\n this.onChange = onChange;\n }\n\n getEdit(urn: string): PendingEdit | undefined {\n const pending = this.items.get(urn);\n return pending?.kind === 'edit' ? pending : undefined;\n }\n\n getCreate(key: string): PendingCreate | undefined {\n const pending = this.items.get(key);\n return pending?.kind === 'create' ? pending : undefined;\n }\n\n set(pending: Pending): void {\n this.items.set(pendingKey(pending), pending);\n this.onChange();\n }\n\n clear(key: string): void {\n if (this.items.delete(key)) this.onChange();\n }\n\n clearAll(entityUrn?: string): Pending[] {\n const removed = this.all().filter((pending) => entityUrn === undefined || pending.entityUrn === entityUrn);\n for (const pending of removed) this.items.delete(pendingKey(pending));\n if (removed.length > 0) this.onChange();\n return removed;\n }\n\n /** Replaces everything, for a restore. */\n load(items: Pending[]): void {\n this.items.clear();\n for (const pending of items) this.items.set(pendingKey(pending), pending);\n this.onChange();\n }\n\n all(): Pending[] {\n return [...this.items.values()];\n }\n\n /** The queued steps of a plan, in order. */\n plan(planId: string): PendingMove[] {\n return this.all().filter((p): p is PendingMove => p.kind === 'move' && p.planId === planId);\n }\n\n count(): number {\n return this.items.size;\n }\n\n byEntity(): Map<string, Pending[]> {\n const groups = new Map<string, Pending[]>();\n for (const pending of this.items.values()) {\n groups.set(pending.entityUrn, [...(groups.get(pending.entityUrn) ?? []), pending]);\n }\n return groups;\n }\n}\n", "// Unsent work survives a reload in localStorage, keyed by user, so it is never\n// restored for someone else. Stashes older than a week are dropped. Storage\n// can be missing or full (private windows, quotas), so every access is\n// guarded; losing the stash must never break editing.\n\nimport type { Pending } from './pending.ts';\n\nconst PREFIX = 'baack-editor:stash:';\nconst MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;\n\ninterface StashData {\n version: 1;\n savedAt: number;\n items: Pending[];\n}\n\nexport class Stash {\n private readonly key: string;\n\n constructor(userUrn: string) {\n this.key = PREFIX + userUrn;\n }\n\n load(now = Date.now()): Pending[] {\n dropExpired(now);\n try {\n const raw = window.localStorage.getItem(this.key);\n if (!raw) return [];\n const data = JSON.parse(raw) as Partial<StashData>;\n if (data.version !== 1 || !Array.isArray(data.items)) return [];\n return data.items;\n } catch (error) {\n console.warn('Baack editor: could not read unsaved changes from this browser.', error);\n return [];\n }\n }\n\n save(items: Pending[], now = Date.now()): void {\n try {\n if (items.length === 0) {\n window.localStorage.removeItem(this.key);\n } else {\n const data: StashData = { version: 1, savedAt: now, items };\n window.localStorage.setItem(this.key, JSON.stringify(data));\n }\n } catch (error) {\n console.warn('Baack editor: could not keep unsaved changes in this browser.', error);\n }\n }\n}\n\nfunction dropExpired(now: number): void {\n try {\n for (let index = window.localStorage.length - 1; index >= 0; index -= 1) {\n const key = window.localStorage.key(index);\n if (!key?.startsWith(PREFIX)) continue;\n const savedAt = (JSON.parse(window.localStorage.getItem(key) ?? '{}') as Partial<StashData>).savedAt;\n if (typeof savedAt !== 'number' || now - savedAt > MAX_AGE_MS) window.localStorage.removeItem(key);\n }\n } catch {\n // Storage unavailable: nothing to tidy.\n }\n}\n", "/**\n * EntityView\n * ----------\n * A thin, read-only wrapper around a raw `Entity` returned from the\n * ENTITY_VIEW endpoint. The raw Entity models content as parallel\n * collections (`texts`, `markdowns`, `images`, `booleans`, `doubles`,\n * `longs`, `money`, `dateTimes`, `latLongs`, `jsons`, `templates`), each\n * entry identified by a `name` and ordered by `sortOrder`.\n *\n * EntityView hides that navigation and gives you name-based accessors that\n * return the underlying item (not just its scalar value), so you still have\n * access to metadata like `isPublished`, `history`, etc. Each single-item\n * accessor also takes an optional `sortOrder`, which defaults to 0, so you\n * can reach a specific entry in a repeated field:\n *\n * const view = new EntityView(entity);\n * view.text('headline'); // TextItem | undefined (sortOrder 0)\n * view.text('gallery-captions', 2); // TextItem | undefined (sortOrder 2)\n * view.markdown('body'); // MarkdownItem | undefined\n * view.image('hero'); // ImageItem | undefined\n * view.texts('gallery-captions'); // TextItem[] (all entries, sortOrder-ordered)\n */\n\nimport type {\n Entity,\n TextItem,\n MarkdownItem,\n TemplateItem,\n BooleanItem,\n DoubleItem,\n LongItem,\n MoneyItem,\n DateTimeItem,\n ImageItem,\n LatLongItem,\n JsonItem,\n LinkItem,\n ReferenceItem\n} from './types/index.ts';\nimport { BaackClient, type QueryParams } from './client.ts';\nimport { Endpoint } from './endpoints.ts';\n\n/** Anything shaped like an Entity content item (has a name + sortOrder). */\ninterface NamedItem {\n name: string;\n sortOrder: number;\n}\n\nexport class EntityView {\n constructor(private readonly entity: Entity) {}\n\n // ---------------------------------------------------------------------\n // Metadata\n // ---------------------------------------------------------------------\n\n get urn(): string {\n return this.entity.urn;\n }\n\n get name(): string {\n return this.entity.name;\n }\n\n get status(): Entity['status'] {\n return this.entity.status;\n }\n\n get language(): string {\n return this.entity.language;\n }\n\n get variant(): string | undefined {\n return this.entity.variant;\n }\n\n get publishedAt(): Date | undefined {\n return this.entity.publishTimestamp ? new Date(this.entity.publishTimestamp) : undefined;\n }\n\n get updatedAt(): Date | undefined {\n return this.entity.updatedTimestamp ? new Date(this.entity.updatedTimestamp) : undefined;\n }\n\n /** Escape hatch back to the untouched Entity, for anything not yet covered. */\n get raw(): Entity {\n return this.entity;\n }\n\n // ---------------------------------------------------------------------\n // Generic helpers\n // ---------------------------------------------------------------------\n\n /**\n * Returns every item in a collection matching `name`, ordered by sortOrder.\n * Collections legitimately support multiple items sharing a name (e.g. a\n * repeated \"gallery-image\" field), so this is the base primitive that all\n * single-value accessors build on.\n */\n private allByName<T extends NamedItem>(\n items: T[] | undefined,\n name: string,\n ): T[] {\n if (!items) return [];\n return items\n .filter((item) => item.name === name)\n .sort((a, b) => a.sortOrder - b.sortOrder);\n }\n\n /**\n * Returns the item matching both `name` and `sortOrder`. Most fields only\n * ever have a single item at `sortOrder` 0, so that's the default \u2014 pass\n * an explicit `sortOrder` to reach a specific entry in a repeated field.\n */\n private byNameAndSortOrder<T extends NamedItem>(\n items: T[] | undefined,\n name: string,\n sortOrder = 0,\n ): T | undefined {\n return items?.find((item) => item.name === name && item.sortOrder === sortOrder);\n }\n\n /**\n * True if any content collection on the entity has an item with this name.\n * Useful for conditionally rendering optional sections.\n */\n has(name: string): boolean {\n const {\n texts, markdowns, templates, booleans, doubles, longs, money, dateTimes, images, latLongs, jsons, links, references,\n } = this.entity;\n return [\n texts, markdowns, templates, booleans, doubles, longs, money, dateTimes, images, latLongs, jsons, links, references,\n ].some(\n (collection) => (collection as NamedItem[] | undefined)?.some((item) => item.name === name),\n );\n }\n\n private hasByNameAndSortOrder<T extends NamedItem>(\n items: T[] | undefined,\n name: string,\n sortOrder = 0,\n ): boolean {\n return this.byNameAndSortOrder(items, name, sortOrder) !== undefined;\n }\n\n hasText(name: string, sortOrder = 0): boolean {\n return this.hasByNameAndSortOrder(this.entity.texts, name, sortOrder);\n }\n\n hasMarkdown(name: string, sortOrder = 0): boolean {\n return this.hasByNameAndSortOrder(this.entity.markdowns, name, sortOrder);\n }\n\n hasTemplate(name: string, sortOrder = 0): boolean {\n return this.hasByNameAndSortOrder(this.entity.templates, name, sortOrder);\n }\n\n hasBoolean(name: string, sortOrder = 0): boolean {\n return this.hasByNameAndSortOrder(this.entity.booleans, name, sortOrder);\n }\n\n hasDouble(name: string, sortOrder = 0): boolean {\n return this.hasByNameAndSortOrder(this.entity.doubles, name, sortOrder);\n }\n\n hasLong(name: string, sortOrder = 0): boolean {\n return this.hasByNameAndSortOrder(this.entity.longs, name, sortOrder);\n }\n\n /** True if either a double or a long item exists with this name/sortOrder. */\n hasNumber(name: string, sortOrder = 0): boolean {\n return this.hasDouble(name, sortOrder) || this.hasLong(name, sortOrder);\n }\n\n hasMoney(name: string, sortOrder = 0): boolean {\n return this.hasByNameAndSortOrder(this.entity.money, name, sortOrder);\n }\n\n hasDate(name: string, sortOrder = 0): boolean {\n return this.hasByNameAndSortOrder(this.entity.dateTimes, name, sortOrder);\n }\n\n hasImage(name: string, sortOrder = 0): boolean {\n return this.hasByNameAndSortOrder(this.entity.images, name, sortOrder);\n }\n\n hasLatLong(name: string, sortOrder = 0): boolean {\n return this.hasByNameAndSortOrder(this.entity.latLongs, name, sortOrder);\n }\n\n hasJson(name: string, sortOrder = 0): boolean {\n return this.hasByNameAndSortOrder(this.entity.jsons, name, sortOrder);\n }\n\n hasLink(name: string, sortOrder = 0): boolean {\n return this.hasByNameAndSortOrder(this.entity.links, name, sortOrder);\n }\n\n hasReference(name: string, sortOrder = 0): boolean {\n return this.hasByNameAndSortOrder(this.entity.references, name, sortOrder);\n }\n\n // ---------------------------------------------------------------------\n // Text\n // ---------------------------------------------------------------------\n\n text(name: string, sortOrder = 0): TextItem | undefined {\n return this.byNameAndSortOrder<TextItem>(this.entity.texts, name, sortOrder);\n }\n\n texts(name: string): TextItem[] {\n return this.allByName<TextItem>(this.entity.texts, name);\n }\n\n /** Like `text`, but throws if the field is missing \u2014 for required content. */\n requireText(name: string, sortOrder = 0): TextItem {\n const item = this.text(name, sortOrder);\n if (item === undefined) {\n throw new Error(`EntityView: missing required text item \"${name}\" on entity ${this.entity.urn}`);\n }\n return item;\n }\n\n // ---------------------------------------------------------------------\n // Markdown\n // ---------------------------------------------------------------------\n\n markdown(name: string, sortOrder = 0): MarkdownItem | undefined {\n return this.byNameAndSortOrder<MarkdownItem>(this.entity.markdowns, name, sortOrder);\n }\n\n markdowns(name: string): MarkdownItem[] {\n return this.allByName<MarkdownItem>(this.entity.markdowns, name);\n }\n\n // ---------------------------------------------------------------------\n // Template\n // ---------------------------------------------------------------------\n\n template(name: string, sortOrder = 0): TemplateItem | undefined {\n return this.byNameAndSortOrder<TemplateItem>(this.entity.templates, name, sortOrder);\n }\n\n templates(name: string): TemplateItem[] {\n return this.allByName<TemplateItem>(this.entity.templates, name);\n }\n\n // ---------------------------------------------------------------------\n // Boolean\n // ---------------------------------------------------------------------\n\n boolean(name: string, sortOrder = 0): BooleanItem | undefined {\n return this.byNameAndSortOrder<BooleanItem>(this.entity.booleans, name, sortOrder);\n }\n\n booleans(name: string): BooleanItem[] {\n return this.allByName<BooleanItem>(this.entity.booleans, name);\n }\n\n // ---------------------------------------------------------------------\n // Numbers (double / long kept distinct to match the underlying API)\n // ---------------------------------------------------------------------\n\n double(name: string, sortOrder = 0): DoubleItem | undefined {\n return this.byNameAndSortOrder<DoubleItem>(this.entity.doubles, name, sortOrder);\n }\n\n doubles(name: string): DoubleItem[] {\n return this.allByName<DoubleItem>(this.entity.doubles, name);\n }\n\n long(name: string, sortOrder = 0): LongItem | undefined {\n return this.byNameAndSortOrder<LongItem>(this.entity.longs, name, sortOrder);\n }\n\n longs(name: string): LongItem[] {\n return this.allByName<LongItem>(this.entity.longs, name);\n }\n\n /** Convenience: checks doubles first, falls back to longs, for callers who don't care which. */\n number(name: string, sortOrder = 0): DoubleItem | LongItem | undefined {\n return this.double(name, sortOrder) ?? this.long(name, sortOrder);\n }\n\n // ---------------------------------------------------------------------\n // Money\n // ---------------------------------------------------------------------\n\n money(name: string, sortOrder = 0): MoneyItem | undefined {\n return this.byNameAndSortOrder<MoneyItem>(this.entity.money, name, sortOrder);\n }\n\n moneys(name: string): MoneyItem[] {\n return this.allByName<MoneyItem>(this.entity.money, name);\n }\n\n // ---------------------------------------------------------------------\n // DateTime\n // ---------------------------------------------------------------------\n\n date(name: string, sortOrder = 0): DateTimeItem | undefined {\n return this.byNameAndSortOrder<DateTimeItem>(this.entity.dateTimes, name, sortOrder);\n }\n\n dates(name: string): DateTimeItem[] {\n return this.allByName<DateTimeItem>(this.entity.dateTimes, name);\n }\n\n // ---------------------------------------------------------------------\n // Images\n // ---------------------------------------------------------------------\n\n image(name: string, sortOrder = 0): ImageItem | undefined {\n return this.byNameAndSortOrder<ImageItem>(this.entity.images, name, sortOrder);\n }\n\n images(name: string): ImageItem[] {\n return this.allByName<ImageItem>(this.entity.images, name);\n }\n\n // ---------------------------------------------------------------------\n // LatLong\n // ---------------------------------------------------------------------\n\n latLong(name: string, sortOrder = 0): LatLongItem | undefined {\n return this.byNameAndSortOrder<LatLongItem>(this.entity.latLongs, name, sortOrder);\n }\n\n latLongs(name: string): LatLongItem[] {\n return this.allByName<LatLongItem>(this.entity.latLongs, name);\n }\n\n // ---------------------------------------------------------------------\n // JSON\n // ---------------------------------------------------------------------\n\n json(name: string, sortOrder = 0): JsonItem | undefined {\n return this.byNameAndSortOrder<JsonItem>(this.entity.jsons, name, sortOrder);\n }\n\n jsons(name: string): JsonItem[] {\n return this.allByName<JsonItem>(this.entity.jsons, name);\n }\n\n // ---------------------------------------------------------------------\n // Links\n // ---------------------------------------------------------------------\n\n link(name: string, sortOrder = 0): LinkItem | undefined {\n return this.byNameAndSortOrder<LinkItem>(this.entity.links, name, sortOrder);\n }\n\n links(name: string): LinkItem[] {\n return this.allByName<LinkItem>(this.entity.links, name);\n }\n\n // ---------------------------------------------------------------------\n // References to other entities\n // ---------------------------------------------------------------------\n\n reference(name: string, sortOrder = 0): ReferenceItem | undefined {\n return this.byNameAndSortOrder<ReferenceItem>(this.entity.references, name, sortOrder);\n }\n\n references(name: string): ReferenceItem[] {\n return this.allByName<ReferenceItem>(this.entity.references, name);\n }\n\n // ---------------------------------------------------------------------\n // Static helpers\n // ---------------------------------------------------------------------\n\n /**\n * Fetches an entity view from the API and wraps it directly, so callers\n * never have to touch the raw Entity at all:\n *\n * const view = await EntityView.fetch(client, '/home', { language: 'en-GB', variant: '' });\n *\n * `params` and `headers` are passed to `client.read`, for example to\n * forward a visitor's `Accept-Language`.\n */\n static async fetch(\n client: BaackClient,\n path: string,\n params?: QueryParams,\n headers?: Record<string, string>,\n ): Promise<EntityView> {\n const entity = await client.read<Entity>(Endpoint.ENTITY_VIEW, path, params, headers);\n return new EntityView(entity);\n }\n\n /** Wrap an Entity you already fetched some other way. */\n static from(entity: Entity): EntityView {\n return new EntityView(entity);\n }\n}\n", "// The editor's model of the content: entities as read, and items by version\n// URN. Items hold only the URN of their entity, so nothing here is circular.\n// Unsent work lives in PendingEdits.\n\nimport { EntityView, type Entity } from '@baack-software/baack-ts-client';\nimport type { Binding } from './discovery.ts';\nimport type { ContentItem, TypeEntry } from './registry.ts';\n\nexport interface StoredItem<I extends ContentItem = ContentItem> {\n readonly entry: TypeEntry<I>;\n readonly item: I;\n /** The entity the item belongs to, as returned by the API. */\n readonly entityUrn: string;\n}\n\nexport class Store {\n /** Scope on the page (or an entity URN read directly) \u2192 URN of the entity the API returned for it. */\n private readonly scopes = new Map<string, string>();\n private readonly views = new Map<string, EntityView>();\n private readonly items = new Map<string, StoredItem>();\n\n hasScope(scope: string): boolean {\n return this.scopes.has(scope);\n }\n\n /**\n * Records an entity read for a scope. The API can return a different entity\n * from the one addressed (another language version), so items are keyed by\n * what came back.\n */\n loadEntity(scope: string, entity: Entity): void {\n this.scopes.set(scope, entity.urn);\n this.views.set(entity.urn, EntityView.from(entity));\n }\n\n entityFor(scope: string): string | undefined {\n return this.scopes.get(scope);\n }\n\n view(entityUrn: string): EntityView | undefined {\n return this.views.get(entityUrn);\n }\n\n /** Entity URNs read so far, in the order they were first read. */\n entities(): string[] {\n return [...this.views.keys()];\n }\n\n /** The page scopes whose reads returned this entity. */\n scopesFor(entityUrn: string): string[] {\n return [...this.scopes].filter(([, urn]) => urn === entityUrn).map(([scope]) => scope);\n }\n\n /** The current item for a binding, or undefined when its slot is empty. */\n itemFor(binding: Binding): StoredItem | undefined {\n const entityUrn = this.scopes.get(binding.scope);\n return entityUrn === undefined ? undefined : this.itemAt(entityUrn, binding.entry, binding.name, binding.sortOrder);\n }\n\n /** The item in an entity's latest view at a name and stored sort order. */\n itemAt(entityUrn: string, entry: TypeEntry, name: string, sortOrder: number): StoredItem | undefined {\n const view = this.views.get(entityUrn);\n const found = view ? entry.find(view, name, sortOrder) : undefined;\n if (!found?.urn) return undefined;\n // Always the view's copy: a template's rendering can change while its URN does not.\n const stored: StoredItem = { entry, item: found, entityUrn };\n this.items.set(found.urn, stored);\n return stored;\n }\n\n /** Remembers a version that is not in the view, such as an older one from history. */\n remember(entityUrn: string, entry: TypeEntry, item: ContentItem): StoredItem {\n const stored: StoredItem = { entry, item, entityUrn };\n if (item.urn) this.items.set(item.urn, stored);\n return stored;\n }\n\n get(urn: string): StoredItem | undefined {\n return this.items.get(urn);\n }\n\n /**\n * Swaps a version for the one a write returned. The view is patched too,\n * unless the type's view value is a rendering (markdown, templates): a write\n * returns source, and the next view read brings the rendering.\n */\n replace(oldUrn: string, item: ContentItem): StoredItem {\n const previous = this.items.get(oldUrn);\n if (!previous || !item.urn) throw new Error(`Cannot replace unknown item ${oldUrn}`);\n const next: StoredItem = { entry: previous.entry, item, entityUrn: previous.entityUrn };\n this.items.delete(oldUrn);\n this.items.set(item.urn, next);\n\n if (previous.entry.renderedByView) return next;\n const items = this.views.get(previous.entityUrn)?.raw[previous.entry.entityArray] as ContentItem[] | undefined;\n const index = items?.findIndex((candidate) => candidate.urn === oldUrn) ?? -1;\n if (items && index >= 0) items[index] = item;\n return next;\n }\n\n /** Forgets entities and items so the next edit session reads them fresh. */\n clearEntities(): void {\n this.scopes.clear();\n this.views.clear();\n this.items.clear();\n }\n}\n", "// Reads the entity view for an entity in scope on the page. The view treats a\n// URN as a locator (api-model.md section 8), but addressed with the entity's\n// own language and variant it always returns that entity. So each read sends\n// the language and variant of the entity in scope, learnt from the admin\n// endpoint (which addresses the URN exactly). A response for any other entity\n// breaks that contract: it is an error, never something to edit.\n\nimport { isBaackApiError, type Entity } from '@baack-software/baack-ts-client';\nimport type { EntityViewOptions, Transport } from './transport.ts';\n\n/** The view answered with a different entity from the one in scope. */\nexport class EntityMismatchError extends Error {\n readonly expectedUrn: string;\n readonly received: Entity;\n\n constructor(expectedUrn: string, received: Entity) {\n super(`The entity view returned ${received.urn} (${received.language}) for ${expectedUrn}`);\n this.name = 'EntityMismatchError';\n this.expectedUrn = expectedUrn;\n this.received = received;\n }\n}\n\n/**\n * A live read of an entity that exists but is not published: the view answers\n * 404 for it, which is its safe behaviour when rendering for visitors.\n */\nexport class NotLiveError extends Error {\n readonly entityUrn: string;\n\n constructor(entityUrn: string) {\n super(`${entityUrn} has no live view: it is not published`);\n this.name = 'NotLiveError';\n this.entityUrn = entityUrn;\n }\n}\n\n/** The entity is visible on the site: published, possibly with newer drafts. */\nexport function isLive(status: Entity['status'] | undefined): boolean {\n return status === 'PUBLISHED' || status === 'PUBLISHED_WITH_DRAFTS';\n}\n\ninterface Locator {\n language: string;\n variant: string;\n}\n\nexport class ScopedViews {\n private readonly transport: Transport;\n /** Language and variant per entity URN, read once from the admin endpoint. */\n private readonly locators = new Map<string, Promise<Locator>>();\n\n constructor(transport: Transport) {\n this.transport = transport;\n }\n\n /** The view of exactly this entity, in the given read mode. */\n async read(entityUrn: string, options: Pick<EntityViewOptions, 'version'> = {}): Promise<Entity> {\n const locator = await this.locator(entityUrn);\n let entity: Entity;\n try {\n entity = await this.transport.entityView(entityUrn, { ...options, ...locator });\n } catch (error) {\n // The admin read just found the entity, and a live read needs no session: a 404 means it is not published.\n if (options.version === undefined && isBaackApiError(error) && error.isNotFound) throw new NotLiveError(entityUrn);\n throw error;\n }\n if (entity.urn !== entityUrn) throw new EntityMismatchError(entityUrn, entity);\n return entity;\n }\n\n /**\n * The page as visitors see it: the live view of a published entity, or the\n * latest drafts of one in an earlier state, which has no live view. The\n * status is read fresh, since publishing can change it during a visit.\n */\n async readAsLive(entityUrn: string): Promise<{ entity: Entity; live: boolean }> {\n const fields = await this.transport.readEntity(entityUrn);\n this.locators.set(entityUrn, Promise.resolve({ language: fields.language, variant: fields.variant ?? '' }));\n if (isLive(fields.status)) return { entity: await this.read(entityUrn), live: true };\n // While publishing (or stuck publishing), an entity that was already public still has a live view.\n if (fields.status === 'PUBLISH' || fields.status === 'PUBLISH_PENDING') {\n try {\n return { entity: await this.read(entityUrn), live: true };\n } catch (error) {\n if (!(error instanceof NotLiveError)) throw error;\n }\n }\n return { entity: await this.read(entityUrn, { version: 'LATEST' }), live: false };\n }\n\n private locator(entityUrn: string): Promise<Locator> {\n let locator = this.locators.get(entityUrn);\n if (!locator) {\n locator = this.transport.readEntity(entityUrn).then((entity) => ({ language: entity.language, variant: entity.variant ?? '' }));\n // A failed read is not remembered, so a retry asks again.\n locator.catch(() => this.locators.delete(entityUrn));\n this.locators.set(entityUrn, locator);\n }\n return locator;\n }\n}\n", "// Types shared by the editor's modules, and small helpers about lifecycle.\n\nimport type { LiveIslands } from './live.ts';\nimport type { Entity } from '@baack-software/baack-ts-client';\nimport { SCOPE_ATTRIBUTE, type Discovery, type Binding } from './core/discovery.ts';\nimport type { PendingEdits } from './core/pending.ts';\nimport type { ContentItem, ItemType, ItemValue, TypeEntry } from './core/registry.ts';\nimport type { Store } from './core/store.ts';\nimport type { Transport } from './core/transport.ts';\nimport type { Feedback } from './feedback.ts';\nimport type { GroupLog } from './core/groups.ts';\nimport type { EditorHost } from './ui/host.ts';\nimport type { Popover } from './ui/popover.ts';\nimport type { MessageAction, Toolbar } from './ui/toolbar.ts';\nimport type { ScopedViews } from './core/scoped-views.ts';\n\nexport type Value = ItemValue<ContentItem>;\n\n/** One cell of an entity's content matrix. */\nexport interface Slot {\n entityUrn: string;\n entry: TypeEntry;\n name: string;\n sortOrder: number;\n}\n\n/** What is being edited: an existing version (`urn`) or an empty slot to create. */\nexport interface EditTarget extends Slot {\n urn?: string | undefined;\n /** Where the popover opens: the element, or an outline row. */\n anchor: HTMLElement;\n /** The element, when editing on the page. */\n binding?: Binding | undefined;\n /** \"Edit from this version\": deliberately based on an older version, so no conflict check. */\n fromVersion?: boolean;\n}\n\n/** Late-bound actions between modules. */\nexport interface EditorHooks {\n openHistory(slot: Slot & { urn: string }): void;\n publishEntity(entityUrn: string): void;\n /** The element is an entry in a list or a table's rows. */\n canReorder(binding: Binding): boolean;\n reorder(binding: Binding): void;\n moveBy(binding: Binding, delta: -1 | 1): void;\n /** Opens Items with an item selected (highlighted and scrolled to). */\n showItem(slot: Slot): void;\n /** Move or rename: opens Items on the item's slots. */\n relocate(target: EditTarget): void;\n /** The rename form for an item. */\n rename(slot: Slot, item: ContentItem): void;\n /** Moves an item to a sort order, swapping with any item there. True when done. */\n moveSlot(slot: Slot, item: ContentItem, sortOrder: number): Promise<boolean>;\n /** Runs (or replays) a queued plan of moves. */\n runPlan(planId: string): Promise<boolean>;\n /** Saves an image with new files for some slots. */\n saveImage(target: EditTarget, files: Map<'DEFAULT' | 'MEDIUM' | 'LARGE', File>): Promise<void>;\n}\n\nexport interface PanelOptions {\n /** Shown above this entity's level, so Back leads to it. */\n entityUrn?: string;\n /** The level's title; by default the content's own `.title` child, which is then removed. */\n title?: string;\n /** False for progress shown while the user works elsewhere. */\n focus?: boolean;\n /** Runs when the level leaves the sidebar by any route (Back, Escape, another panel, Close of a task). */\n onLeave?(): void;\n}\n\nexport interface PanelHandle {\n /** Goes back from the panel, if it is still in the sidebar. */\n close(): void;\n readonly isOpen: boolean;\n}\n\n/**\n * A task as a sidebar level (a form, a confirm, progress): the deepest level,\n * so it never covers what it is about, and Back cancels it. Each is closed\n * through its own handle, never \"whatever is on screen\". A form's Cancel\n * (a `cancel` event on the content) goes back too. Showing one while another\n * is on screen replaces it.\n */\nexport interface Panels {\n show(content: HTMLElement, options?: PanelOptions): PanelHandle;\n}\n\n/** What every module shares. Built once by `Editor`. */\nexport interface EditorContext {\n readonly transport: Transport;\n readonly host: EditorHost;\n readonly registry: readonly TypeEntry[];\n readonly store: Store;\n readonly pending: PendingEdits;\n readonly toolbar: Toolbar;\n readonly popover: Popover;\n /** Tasks shown as sidebar levels. */\n readonly panels: Panels;\n readonly feedback: Feedback;\n /** Entity view reads for entities in scope, held to their language and variant. */\n readonly views: ScopedViews;\n /** Source loaded for types whose view value is a rendering, by URN. */\n readonly sources: Map<string, Value>;\n readonly discovery: Discovery;\n /** The user's role allows publishing (PUBLISHER or above). */\n readonly canPublish: boolean;\n /** Image slots a version needs before publishing (site setting). */\n readonly requiredImageSlots: readonly ('DEFAULT' | 'MEDIUM' | 'LARGE')[];\n readonly hooks: EditorHooks;\n /** Versions created together by one operation, kept in this browser. */\n readonly groups: GroupLog | undefined;\n /** Shows items in content the page's framework renders (`data-content-live`) through events. */\n readonly live: LiveIslands;\n entry(type: ItemType): TypeEntry;\n entityTitle(entityUrn: string): string;\n /** Says `done` after a publish, with the site's `afterPublish` message or callback. */\n announcePublished(entityUrn: string, done: string, options?: { itemUrn?: string; info?: boolean }): void;\n}\n\n/** The next step after saving drafts to an entity: its review, as the entity's own label offers it. */\nexport function reviewAction(ctx: EditorContext, entityUrn: string): MessageAction {\n return { label: ctx.canPublish ? 'Review and publish\u2026' : 'Request approval\u2026', run: () => ctx.hooks.publishEntity(entityUrn) };\n}\n\n/** The entity is visible on the site: new items there are published as soon as they are created. */\nexport { isLive } from './core/scoped-views.ts';\n\n/** The page's own entity: the one read for the root scope. */\nexport function pageEntity(store: Store): string | undefined {\n const root = document.documentElement.getAttribute(SCOPE_ATTRIBUTE);\n return root ? store.entityFor(root) : undefined;\n}\n\n/** The page's own entity first, then the others in the order given. */\nexport function pageFirst(store: Store, entityUrns: string[]): string[] {\n const page = pageEntity(store);\n return [...entityUrns].sort((a, b) => (a === page ? -1 : b === page ? 1 : 0));\n}\n\n/** The entity's lifecycle state as the server reports it (CLAUDE.md rule 7). */\nexport function lifecycleLabel(status: Entity['status'] | undefined): string {\n switch (status) {\n case 'DRAFT_UNPUBLISHED':\n return 'Draft, not published yet';\n case 'PUBLISH':\n return 'Publishing\u2026';\n case 'PUBLISH_PENDING':\n return 'Scheduled to publish';\n case 'PUBLISHED':\n return 'Published';\n case 'PUBLISHED_WITH_DRAFTS':\n return 'Published, with unpublished changes';\n default:\n return '';\n }\n}\n", "// Marks item elements on the host page while in edit mode. Uses inline\n// outline styles, which need no host CSS and are restored exactly on exit.\n// An empty element is held open at one character by one line, so its outline\n// (and the caret, while editing) stays visible.\n\nimport { PAGE_COLOURS } from './theme.ts';\n\n/** `published`: on the live page, content published since the page was built, which visitors may not see yet. */\nexport type MarkState = 'editable' | 'changed' | 'editing' | 'unresolved' | 'previewing' | 'published';\n\nexport const STATE_ATTRIBUTE = 'data-baack-state';\n\ntype Colour = keyof typeof PAGE_COLOURS;\n\n/** Width, style, colour and its opacity: the outline each state draws on the page. */\nconst OUTLINES: Record<MarkState, [string, Colour, number]> = {\n editable: ['1px dashed', 'primary', 70],\n editing: ['2px solid', 'primary', 100],\n changed: ['2px solid', 'warning', 100],\n unresolved: ['1px dotted', 'muted', 80],\n previewing: ['2px dashed', 'preview', 100],\n published: ['2px solid', 'success', 100],\n};\n\n/** The outline in the light colour, then (where the browser has light-dark()) following the page's color-scheme. */\nfunction drawOutline(element: HTMLElement, state: MarkState): void {\n const [line, colour, opacity] = OUTLINES[state];\n const [light, dark] = PAGE_COLOURS[colour];\n const faded = (value: string) => (opacity === 100 ? value : `color-mix(in srgb, ${value} ${opacity}%, transparent)`);\n element.style.outline = `${line} ${faded(light)}`;\n // Ignored, leaving the light colour, where light-dark() is not supported.\n element.style.outline = `${line} ${faded(`light-dark(${light}, ${dark})`)}`;\n}\n\ninterface Saved {\n outline: string;\n outlineOffset: string;\n display: string;\n minWidth: string;\n minHeight: string;\n}\n\nconst saved = new WeakMap<HTMLElement, Saved>();\n\nexport function mark(element: HTMLElement, state: MarkState): void {\n if (!saved.has(element)) {\n const { outline, outlineOffset, display, minWidth, minHeight } = element.style;\n saved.set(element, { outline, outlineOffset, display, minWidth, minHeight });\n }\n drawOutline(element, state);\n element.style.outlineOffset = '2px';\n element.setAttribute(STATE_ATTRIBUTE, state);\n fitEmpty(element);\n}\n\n/**\n * Holds a marked element open while it has no text: one character wide and\n * one line high. An inline element becomes inline-block to take the size.\n * Called again as its content changes (typing), and undone once it has text.\n */\nexport function fitEmpty(element: HTMLElement): void {\n const original = saved.get(element);\n if (!original) return;\n element.style.display = original.display;\n element.style.minWidth = original.minWidth;\n element.style.minHeight = original.minHeight;\n if (element.textContent !== '' || element.querySelector('img, picture, svg, video, iframe')) return;\n if (getComputedStyle(element).display === 'inline') element.style.display = 'inline-block';\n element.style.minWidth = '1ch';\n element.style.minHeight = '1lh';\n}\n\nexport function unmark(element: HTMLElement): void {\n const original = saved.get(element);\n if (original) {\n element.style.outline = original.outline;\n element.style.outlineOffset = original.outlineOffset;\n element.style.display = original.display;\n element.style.minWidth = original.minWidth;\n element.style.minHeight = original.minHeight;\n if (!element.getAttribute('style')) element.removeAttribute('style');\n saved.delete(element);\n }\n element.removeAttribute(STATE_ATTRIBUTE);\n}\n", null, null, "// Registry entries for every type except text. One entry per type.\n\nimport {\n Endpoint,\n type BooleanItem,\n type DateTimeItem,\n type DoubleItem,\n type ImageItem,\n type JsonItem,\n type LatLongItem,\n type LinkItem,\n type LongItem,\n type MarkdownItem,\n type MoneyItem,\n type ReferenceItem,\n type TemplateItem,\n} from '@baack-software/baack-ts-client';\nimport * as components from '@baack-software/baack-ts-components/components';\nimport { currencyDigits, majorToMinor, minorToMajor, parseTimestamp } from '@baack-software/baack-ts-components/format';\nimport type { TypeEntry } from '../core/registry.ts';\n\nconst str = (v: unknown) => (typeof v === 'string' ? v : '');\n\nfunction sourceEntry<I extends MarkdownItem | TemplateItem>(\n type: 'markdown' | 'template',\n label: string,\n endpoint: string,\n historyEndpoint: string,\n spec: typeof components.markdown,\n find: TypeEntry<I>['find'],\n): TypeEntry<I> {\n return {\n type,\n label,\n attribute: type,\n entityArray: type === 'markdown' ? 'markdowns' : 'templates',\n endpoint,\n historyEndpoint,\n surface: 'panel',\n valueKeys: ['value'],\n renderedByView: true,\n component: () => spec as never,\n // The placeholder renders as <p>text</p>.\n fromPlaceholder: (element) => ({ value: (element.textContent ?? '').trim() }) as never,\n find,\n defaults: () => ({ value: '' }) as never,\n form: {\n fields: [{ key: 'value', label: type === 'markdown' ? 'Markdown source' : 'Velocity template source', kind: 'code' }],\n toForm: (value) => ({ value: value.value }),\n fromForm: (values) => ({ value: str(values['value']) }) as never,\n describe: () =>\n type === 'markdown'\n ? 'The page shows the rendered result after you send.'\n : 'Templates can show other items. The page shows the result after you send.',\n },\n validate: () => [],\n };\n}\n\nexport const markdown = sourceEntry<MarkdownItem>(\n 'markdown',\n 'Markdown',\n Endpoint.MARKDOWN,\n Endpoint.MARKDOWN_HISTORY,\n components.markdown,\n (view, name, sortOrder) => view.markdown(name, sortOrder),\n);\n\nexport const template = sourceEntry<TemplateItem>(\n 'template',\n 'Template',\n Endpoint.TEMPLATE,\n Endpoint.TEMPLATE_HISTORY,\n components.template as typeof components.markdown,\n (view, name, sortOrder) => view.template(name, sortOrder),\n);\n\nexport const json: TypeEntry<JsonItem> = {\n type: 'json',\n label: 'JSON',\n attribute: 'json',\n entityArray: 'jsons',\n endpoint: Endpoint.JSON,\n historyEndpoint: Endpoint.JSON_HISTORY,\n surface: 'panel',\n valueKeys: ['value'],\n find: (view, name, sortOrder) => view.json(name, sortOrder),\n defaults: () => ({ value: {} }),\n form: {\n fields: [{ key: 'value', label: 'JSON object', kind: 'code' }],\n toForm: (value) => ({ value: JSON.stringify(value.value ?? {}, null, 2) }),\n fromForm: (values) => {\n try {\n const parsed: unknown = JSON.parse(str(values['value']));\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) return 'The value must be a JSON object, like {\"key\": \"value\"}.';\n return { value: parsed };\n } catch (error) {\n return `This is not valid JSON: ${error instanceof Error ? error.message : String(error)}`;\n }\n },\n },\n validate: () => [],\n};\n\nexport const boolean: TypeEntry<BooleanItem> = {\n type: 'boolean',\n label: 'Switch',\n attribute: 'boolean',\n entityArray: 'booleans',\n endpoint: Endpoint.BOOLEAN,\n historyEndpoint: Endpoint.BOOLEAN_HISTORY,\n surface: 'popover',\n valueKeys: ['value'],\n component: () => components.boolean as never,\n fromPlaceholder: (element) => ({ value: element.getAttribute('data-boolean-value') === 'true' }),\n find: (view, name, sortOrder) => view.boolean(name, sortOrder),\n defaults: () => ({ value: false }),\n form: {\n fields: [{ key: 'value', label: 'On', kind: 'checkbox' }],\n toForm: (value) => ({ value: value.value }),\n fromForm: (values) => ({ value: values['value'] === true }),\n },\n validate: () => [],\n};\n\nfunction wholeNumber(text: string): number | undefined {\n if (!/^\\s*-?\\d+\\s*$/.test(text)) return undefined;\n const value = Number(text);\n return Number.isSafeInteger(value) ? value : undefined;\n}\n\nexport const long: TypeEntry<LongItem> = {\n type: 'long',\n label: 'Whole number',\n attribute: 'long',\n entityArray: 'longs',\n endpoint: Endpoint.LONG,\n historyEndpoint: Endpoint.LONG_HISTORY,\n surface: 'popover',\n valueKeys: ['value'],\n component: () => components.long as never,\n find: (view, name, sortOrder) => view.long(name, sortOrder),\n defaults: () => ({ value: 0 }),\n form: {\n fields: [{ key: 'value', label: 'Value', kind: 'integer' }],\n toForm: (value) => ({ value: String(value.value) }),\n fromForm: (values) => {\n const value = wholeNumber(str(values['value']));\n return value === undefined ? 'Enter a whole number.' : { value };\n },\n },\n validate: () => [],\n};\n\nfunction decimal(text: string): number | undefined {\n if (!/^\\s*-?(\\d+\\.?\\d*|\\.\\d+)(e[+-]?\\d+)?\\s*$/i.test(text)) return undefined;\n const value = Number(text);\n return Number.isFinite(value) ? value : undefined;\n}\n\nexport const double: TypeEntry<DoubleItem> = {\n type: 'double',\n label: 'Number',\n attribute: 'double',\n entityArray: 'doubles',\n endpoint: Endpoint.DOUBLE,\n historyEndpoint: Endpoint.DOUBLE_HISTORY,\n surface: 'popover',\n valueKeys: ['value'],\n component: () => components.double as never,\n find: (view, name, sortOrder) => view.double(name, sortOrder),\n defaults: () => ({ value: 0 }),\n form: {\n fields: [{ key: 'value', label: 'Value', kind: 'decimal' }],\n toForm: (value) => ({ value: String(value.value) }),\n fromForm: (values) => {\n const value = decimal(str(values['value']));\n return value === undefined ? 'Enter a number.' : { value };\n },\n },\n validate: () => [],\n};\n\n/** \"2026-11-01T09:00:00.000\" (UTC, as the API writes it) \u2192 \"2026-11-01T09:00\" in the browser's local time. */\nfunction toLocalInput(value: string): string {\n const time = parseTimestamp(value);\n if (Number.isNaN(time)) return '';\n const local = new Date(time - new Date(time).getTimezoneOffset() * 60_000);\n return local.toISOString().slice(0, 16);\n}\n\n/** \"2026-11-01T09:00\" in local time \u2192 the API's UTC timestamp. */\nfunction fromLocalInput(text: string): string | undefined {\n if (!/^\\d{4}-\\d\\d-\\d\\dT\\d\\d:\\d\\d(:\\d\\d)?$/.test(text)) return undefined;\n const time = new Date(text).getTime(); // A date-time without a zone is local time.\n return Number.isNaN(time) ? undefined : new Date(time).toISOString().replace('Z', '');\n}\n\nexport const dateTime: TypeEntry<DateTimeItem> = {\n type: 'dateTime',\n label: 'Date and time',\n attribute: 'datetime',\n entityArray: 'dateTimes',\n endpoint: Endpoint.DATE_TIME,\n historyEndpoint: Endpoint.DATE_TIME_HISTORY,\n surface: 'popover',\n valueKeys: ['value'],\n component: () => components.dateTime as never,\n find: (view, name, sortOrder) => view.date(name, sortOrder),\n defaults: () => ({ value: new Date().toISOString().replace('Z', '') }),\n form: {\n fields: [{ key: 'value', label: 'Date and time (your local time)', kind: 'datetime' }],\n toForm: (value) => ({ value: toLocalInput(value.value) }),\n fromForm: (values) => {\n const value = fromLocalInput(str(values['value']));\n return value === undefined ? 'Enter a date and time.' : { value };\n },\n describe: (values) => {\n const value = fromLocalInput(str(values['value']));\n return value ? `Stored as ${value.slice(0, 16).replace('T', ' ')} UTC.` : '';\n },\n },\n validate: () => [],\n};\n\nexport const latLong: TypeEntry<LatLongItem> = {\n type: 'latLong',\n label: 'Location',\n attribute: 'latlong',\n entityArray: 'latLongs',\n endpoint: Endpoint.LAT_LONG,\n historyEndpoint: Endpoint.LAT_LONG_HISTORY,\n surface: 'popover',\n valueKeys: ['latitude', 'longitude'],\n component: () => components.latLong as never,\n find: (view, name, sortOrder) => view.latLong(name, sortOrder),\n defaults: () => ({ latitude: 0, longitude: 0 }),\n form: {\n fields: [\n { key: 'latitude', label: 'Latitude', kind: 'decimal' },\n { key: 'longitude', label: 'Longitude', kind: 'decimal' },\n ],\n toForm: (value) => ({ latitude: String(value.latitude), longitude: String(value.longitude) }),\n fromForm: (values) => {\n const latitude = decimal(str(values['latitude']));\n const longitude = decimal(str(values['longitude']));\n if (latitude === undefined || Math.abs(latitude) > 90) return 'Latitude must be a number from -90 to 90.';\n if (longitude === undefined || Math.abs(longitude) > 180) return 'Longitude must be a number from -180 to 180.';\n return { latitude, longitude };\n },\n },\n validate: () => [],\n};\n\nfunction validCurrency(code: string): boolean {\n if (!/^[A-Z]{3}$/.test(code)) return false;\n try {\n new Intl.NumberFormat('en', { style: 'currency', currency: code });\n return true;\n } catch {\n return false;\n }\n}\n\nexport const money: TypeEntry<MoneyItem> = {\n type: 'money',\n label: 'Money',\n attribute: 'money',\n entityArray: 'money',\n endpoint: Endpoint.MONEY,\n historyEndpoint: Endpoint.MONEY_HISTORY,\n surface: 'popover',\n valueKeys: ['currencyCode', 'unitValue'],\n derived: ['formattedValue', 'currencySymbol'],\n component: () => components.money as never,\n find: (view, name, sortOrder) => view.money(name, sortOrder),\n defaults: () => ({ currencyCode: 'GBP', unitValue: 0 }),\n form: {\n fields: [\n { key: 'currencyCode', label: 'Currency', kind: 'currency' },\n { key: 'amount', label: 'Amount', kind: 'text' },\n ],\n toForm: (value) => ({\n currencyCode: value.currencyCode,\n amount: minorToMajor(value.unitValue, currencyDigits(value.currencyCode)),\n }),\n fromForm: (values) => {\n const currencyCode = str(values['currencyCode']).trim().toUpperCase();\n if (!validCurrency(currencyCode)) return 'Enter a three-letter currency code, like GBP or JPY.';\n const digits = currencyDigits(currencyCode);\n const unitValue = majorToMinor(str(values['amount']), digits);\n if (unitValue === undefined) {\n return digits === 0\n ? `${currencyCode} has no minor units. Enter a whole amount.`\n : `Enter an amount with at most ${digits} decimal places, like ${minorToMajor(1250, digits)}.`;\n }\n return { currencyCode, unitValue };\n },\n describe: (values) => {\n const currencyCode = str(values['currencyCode']).trim().toUpperCase();\n if (!validCurrency(currencyCode)) return '';\n const unitValue = majorToMinor(str(values['amount']), currencyDigits(currencyCode));\n return unitValue === undefined ? '' : `Stored as ${unitValue} in the smallest unit of ${currencyCode}.`;\n },\n },\n validate: () => [],\n};\n\n/** The image's file slots: the upload's size name and the item field that holds its address. */\nexport const IMAGE_SLOTS = [\n { size: 'DEFAULT', field: 'src', label: 'Default file' },\n { size: 'MEDIUM', field: 'mediumSrc', label: 'Medium file (from 768px wide)' },\n { size: 'LARGE', field: 'largeSrc', label: 'Large file (from 1024px wide)' },\n] as const;\n\nexport const image: TypeEntry<ImageItem> = {\n type: 'image',\n label: 'Image',\n attribute: 'image',\n entityArray: 'images',\n endpoint: Endpoint.IMAGE,\n historyEndpoint: Endpoint.IMAGE_HISTORY,\n surface: 'popover',\n valueKeys: ['altText', 'src', 'mediumSrc', 'largeSrc'],\n // The API keeps a version's files only when an update passes their addresses back unchanged.\n carried: ['src', 'mediumSrc', 'largeSrc'],\n component: () => components.image as never,\n fromPlaceholder: (element) => ({ altText: element.querySelector('img')?.alt ?? '' }),\n find: (view, name, sortOrder) => view.image(name, sortOrder),\n defaults: () => ({ altText: '' }),\n form: {\n fields: [{ key: 'altText', label: 'Alt text', kind: 'text' }, ...IMAGE_SLOTS.map((slot) => ({ key: slot.size, label: slot.label, kind: 'file' as const }))],\n // Each slot field shows the current file; the chosen file itself is read from the popover.\n toForm: (value) => ({\n altText: value.altText ?? '',\n ...Object.fromEntries(IMAGE_SLOTS.flatMap((slot) => [[slot.size, ''], [`${slot.size}:current`, String(value[slot.field] ?? '')]])),\n }),\n fromForm: (values) => ({ altText: str(values['altText']) }),\n describe: (values) => {\n const replacing = IMAGE_SLOTS.filter((slot) => str(values[slot.size]) !== '');\n if (replacing.length === 0) return 'Saving keeps the current files.';\n const kept = IMAGE_SLOTS.filter((slot) => !replacing.includes(slot) && str(values[`${slot.size}:current`]) !== '');\n const note = `Saving creates a new version, then uploads ${replacing.map((slot) => slot.label.toLowerCase().split(' (')[0]).join(', ')}.`;\n return replacing.some((slot) => slot.size === 'DEFAULT') && kept.length > 0\n ? `${note} The ${kept.map((slot) => slot.size.toLowerCase()).join(' and ')} file still shows the previous picture; choose new ones too if it changed.`\n : note;\n },\n },\n validate: ({ altText }) => (altText ? [] : [{ level: 'warning', message: 'Images need alt text unless they are decorative.' }]),\n};\n\nexport const link: TypeEntry<LinkItem> = {\n type: 'link',\n label: 'Link',\n attribute: 'link',\n entityArray: 'links',\n endpoint: Endpoint.LINK,\n historyEndpoint: Endpoint.LINK_HISTORY,\n surface: 'popover',\n valueKeys: ['href', 'text', 'rel', 'lang'],\n component: () => components.link as never,\n fromPlaceholder: (element) => {\n const href = element.getAttribute('href');\n const text = (element.textContent ?? '').trim();\n return { href: href && href !== '#' ? href : '', ...(text ? { text } : {}) };\n },\n find: (view, name, sortOrder) => view.link(name, sortOrder),\n defaults: () => ({ href: '', text: '' }),\n form: {\n fields: [\n { key: 'text', label: 'Text', kind: 'text' },\n { key: 'href', label: 'Address', kind: 'url' },\n { key: 'rel', label: 'Relationship (rel), e.g. nofollow', kind: 'text' },\n { key: 'lang', label: 'Language of the target, e.g. en', kind: 'text' },\n ],\n toForm: (value) => ({ text: value.text ?? '', href: value.href, rel: value.rel ?? '', lang: value.lang ?? '' }),\n fromForm: (values) => {\n const href = str(values['href']).trim();\n if (!href) return 'Enter the address the link goes to.';\n if (href.length > 2048) return 'The address can be at most 2048 characters.';\n const value: { href: string; text?: string; rel?: string; lang?: string } = { href };\n for (const key of ['text', 'rel', 'lang'] as const) {\n const field = str(values[key]).trim();\n if (field) value[key] = field;\n }\n return value;\n },\n },\n validate: ({ href }) =>\n /^\\s*javascript:/i.test(href) ? [{ level: 'error', message: 'Links cannot run scripts.' }] : [],\n};\n\nexport const reference: TypeEntry<ReferenceItem> = {\n type: 'reference',\n label: 'Reference',\n attribute: 'reference',\n entityArray: 'references',\n endpoint: Endpoint.REFERENCE,\n historyEndpoint: Endpoint.REFERENCE_HISTORY,\n surface: 'popover',\n valueKeys: ['entityReference'],\n find: (view, name, sortOrder) => view.reference(name, sortOrder),\n defaults: () => ({ entityReference: { urn: '' } as ReferenceItem['entityReference'] }),\n form: {\n // Chosen by path and language; the reference stores the URN.\n fields: [{ key: 'urn', label: 'Entity referred to', kind: 'entity' }],\n toForm: (value) => ({ urn: value.entityReference?.urn ?? '' }),\n fromForm: (values) => {\n const urn = str(values['urn']).trim();\n if (!/^[0-9a-f-]{36}$/i.test(urn)) return 'Choose the entity this refers to.';\n return { entityReference: { urn } as ReferenceItem['entityReference'] };\n },\n },\n validate: () => [],\n};\n", "// Replacing an image's files. Never upload to a version whose slot already\n// has a file (CLAUDE.md rule 5): save a new version first, with the slots\n// being replaced left empty (the API keeps a slot's address only when the\n// update passes it back), then upload each file to that new version, in\n// parallel, and wait for the CDN to place them.\n\nimport type { ImageItem } from '@baack-software/baack-ts-client';\nimport { createKey } from './core/pending.ts';\nimport { urnAttribute, withCarried, type ContentItem } from './core/registry.ts';\nimport type { Editing } from './editing.ts';\nimport type { Saving } from './saving.ts';\nimport type { EditTarget, EditorContext, Value } from './targets.ts';\nimport { el } from './ui/host.ts';\nimport { mark } from './ui/marker.ts';\nimport { IMAGE_SLOTS } from './types/values.ts';\nimport type { PageView } from './view.ts';\nimport './config.ts'; // Declares window.baackEditorConfig.\n\ntype Size = (typeof IMAGE_SLOTS)[number]['size'];\n\n/** Reads between polls: quick at first, never slower than every 4 seconds; give up after about 30 seconds. */\nconst POLL_MS = [250, 500, 1000, 2000, 4000];\nconst POLL_LIMIT_MS = 30_000;\n\nexport class Images {\n private readonly ctx: EditorContext;\n private readonly view: PageView;\n private readonly saving: () => Saving;\n private readonly editing: () => Editing;\n\n constructor(ctx: EditorContext, view: PageView, saving: () => Saving, editing: () => Editing) {\n this.ctx = ctx;\n this.view = view;\n this.saving = saving;\n this.editing = editing;\n }\n\n /** Saves the image's alt text with new files for the chosen slots. */\n async save(target: EditTarget, chosen: Map<Size, File>): Promise<void> {\n const problem = imageFileIssues(chosen).find((issue) => issue.level === 'error');\n if (problem) return this.ctx.popover.setError(problem.message);\n const files = await withSizes(chosen, window.baackEditorConfig?.imageWidths);\n const { pending, popover, store, feedback } = this.ctx;\n const entry = target.entry;\n const form = entry.form!.fromForm(popover.values());\n if (typeof form === 'string') return popover.setError(form);\n\n // The new version keeps the files not being replaced, and leaves the replaced slots empty for the upload.\n const base = target.urn ? (store.get(target.urn)?.item as ImageItem | undefined) : undefined;\n const value = withCarried(entry, base, form) as Record<string, unknown>;\n for (const size of files.keys()) delete value[IMAGE_SLOTS.find((slot) => slot.size === size)!.field];\n if (target.urn) {\n pending.set({ kind: 'edit', type: entry.type, urn: target.urn, entityUrn: target.entityUrn, name: target.name, sortOrder: target.sortOrder, value: value as Value });\n } else {\n pending.set({ kind: 'create', type: entry.type, entityUrn: target.entityUrn, name: target.name, sortOrder: target.sortOrder, value: value as Value });\n }\n const change = target.urn ? pending.getEdit(target.urn)! : pending.getCreate(createKey({ ...target, type: entry.type }))!;\n\n popover.setSending(true);\n popover.setError('');\n let version: ContentItem;\n try {\n version = await this.saving().commit(change);\n } catch (error) {\n popover.setSending(false);\n const failure = await feedback.describe(error, 'save this image');\n popover.setError(failure.message, failure.debug);\n return;\n }\n\n popover.setSending(false);\n // Show the chosen files at once, marked as changed, while the CDN places them.\n const previews = new Map<Size, string>([...files].map(([size, file]) => [size, URL.createObjectURL(file)]));\n this.preview(target.entityUrn, version, previews);\n await this.upload(target, version, files, previews);\n }\n\n /** Uploads files to a version's empty slots in parallel, then waits for their addresses. Progress shows in the toolbar. */\n private async upload(target: EditTarget, version: ContentItem, files: Map<Size, File>, previews: Map<Size, string>): Promise<void> {\n const { transport, feedback, toolbar } = this.ctx;\n this.editing().close();\n const panel = el('div', 'simple-form');\n panel.setAttribute('aria-label', 'Image upload');\n const lines = new Map<Size, HTMLElement>();\n panel.append(el('div', 'title', `Uploading to a new version of ${target.name}`));\n for (const [size, file] of files) {\n const line = el('p', 'hint', `${label(size)}: ${file.name}: uploading\u2026`);\n lines.set(size, line);\n panel.append(line);\n }\n // Progress, shown above the item's entity without taking focus from the page.\n const progress = this.ctx.panels.show(panel, { entityUrn: target.entityUrn, focus: false });\n const say = (size: Size, text: string, problem = false) => {\n const line = lines.get(size)!;\n line.textContent = `${label(size)}: ${files.get(size)!.name}: ${text}`;\n line.className = problem ? 'error' : 'hint';\n };\n\n // Synchronous uploads: each answers with the image item, its slot's address already set.\n const results = await Promise.allSettled([...files].map(([size, file]) => transport.uploadImageFile(version.urn!, size, file)));\n const answered = results.flatMap((result) => (result.status === 'fulfilled' ? [result.value as Record<string, unknown>] : []));\n const failed = new Map<Size, File>();\n for (const [index, result] of results.entries()) {\n const [size, file] = [...files][index]!;\n if (result.status === 'rejected') {\n failed.set(size, file);\n say(size, (await feedback.describe(result.reason, 'upload this file')).message, true);\n } else {\n say(size, 'uploaded; waiting for the CDN\u2026');\n }\n }\n\n const uploaded = [...files.keys()].filter((size) => !failed.has(size));\n const fieldOf = (size: Size) => IMAGE_SLOTS.find((slot) => slot.size === size)!.field;\n const inResponses = uploaded.every((size) => answered.some((item) => item[fieldOf(size)]));\n // Only if a response lacked an address (not expected), read the version until it appears.\n const placed = inResponses || (await this.waitForAddresses(target.entry, version.urn!, uploaded));\n for (const size of uploaded) say(size, placed ? 'done' : 'still processing; it appears when the CDN has placed it.');\n await this.view.refresh(target.entityUrn); // Shows the real addresses.\n\n if (failed.size > 0) {\n // The failed slots of this version are still empty, so they can be retried safely.\n this.preview(target.entityUrn, version, new Map([...previews].filter(([size]) => failed.has(size))));\n const retry = el('button', 'primary', 'Retry failed uploads');\n retry.type = 'button';\n retry.addEventListener('click', () => void this.retry(target, version, failed, previews));\n const actions = el('div', 'actions');\n actions.append(retry);\n panel.append(el('p', 'message', 'Some files were not uploaded. The new version keeps the others.'), actions);\n return;\n }\n for (const url of previews.values()) URL.revokeObjectURL(url);\n progress.close();\n toolbar.showMessage(`Uploaded ${files.size} ${files.size === 1 ? 'file' : 'files'} to a new version of ${target.name}.`, true);\n }\n\n /** Retries only slots of the same version that are still empty: never uploads over a file. */\n private async retry(target: EditTarget, version: ContentItem, failed: Map<Size, File>, previews: Map<Size, string>): Promise<void> {\n const current = (await this.ctx.transport.read(target.entry, version.urn!)) as unknown as Record<string, unknown>;\n const stillEmpty = new Map([...failed].filter(([size]) => !current[IMAGE_SLOTS.find((slot) => slot.size === size)!.field]));\n await this.upload(target, version, stillEmpty, previews);\n }\n\n /** Reads the version until every uploaded slot has its address. */\n private async waitForAddresses(entry: EditTarget['entry'], urn: string, sizes: Size[]): Promise<boolean> {\n if (sizes.length === 0) return true;\n const start = Date.now();\n for (let attempt = 0; Date.now() - start < POLL_LIMIT_MS; attempt += 1) {\n const item = (await this.ctx.transport.read(entry, urn)) as unknown as Record<string, unknown>;\n if (sizes.every((size) => item[IMAGE_SLOTS.find((slot) => slot.size === size)!.field])) {\n this.ctx.store.remember(this.ctx.store.get(urn)?.entityUrn ?? '', entry, item as unknown as ContentItem);\n return true;\n }\n await new Promise((resolve) => setTimeout(resolve, POLL_MS[Math.min(attempt, POLL_MS.length - 1)]));\n }\n return false;\n }\n\n /** Renders the chosen files (object URLs) wherever the new version shows. */\n private preview(entityUrn: string, version: ContentItem, previews: Map<Size, string>): void {\n // Start from the newest copy of the version: slots already placed keep their addresses.\n const item: Record<string, unknown> = { ...(this.ctx.store.get(version.urn!)?.item ?? version) };\n for (const [size, url] of previews) item[IMAGE_SLOTS.find((slot) => slot.size === size)!.field] = url;\n const entry = this.ctx.entry('image');\n for (const binding of this.ctx.discovery.all()) {\n if (binding.entry !== entry || this.ctx.store.entityFor(binding.scope) !== entityUrn) continue;\n if (binding.element.getAttribute(urnAttribute(entry)) !== version.urn && !(binding.name === version.name && binding.sortOrder === version.sortOrder)) continue;\n this.ctx.live.render(binding, item as unknown as ImageItem);\n mark(binding.element, 'changed');\n }\n }\n}\n\nfunction label(size: Size): string {\n return IMAGE_SLOTS.find((slot) => slot.size === size)!.label.split(' (')[0]!;\n}\n\n/**\n * Off by default: when the site sets `imageWidths` and only a default file\n * is chosen, scale it in the browser to those widths for the medium and\n * large slots. Never scales up; a file the browser cannot scale is used as is.\n */\nasync function withSizes(files: Map<Size, File>, widths: { MEDIUM?: number; LARGE?: number } | undefined): Promise<Map<Size, File>> {\n const original = files.get('DEFAULT');\n if (!widths || !original || files.size > 1) return files;\n const result = new Map(files);\n for (const size of ['MEDIUM', 'LARGE'] as const) {\n const width = widths[size];\n if (width) result.set(size, await scaled(original, width, size));\n }\n return result;\n}\n\nasync function scaled(file: File, width: number, size: Size): Promise<File> {\n try {\n const bitmap = await createImageBitmap(file);\n if (bitmap.width <= width) return file;\n const height = Math.round((bitmap.height * width) / bitmap.width);\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n canvas.getContext('2d')!.drawImage(bitmap, 0, 0, width, height);\n const type = file.type === 'image/png' || file.type === 'image/webp' ? file.type : 'image/jpeg';\n const blob = await new Promise<Blob>((resolve, reject) =>\n canvas.toBlob((b) => (b ? resolve(b) : reject(new Error('Could not scale the image'))), type, 0.9),\n );\n const name = file.name.replace(/(\\.[^.]+)?$/, `-${size.toLowerCase()}$1`);\n return new File([blob], name, { type });\n } catch {\n return file;\n }\n}\n\n/**\n * Image types the upload accepts (confirmed against the API). SVG is shown\n * through <img>, where its scripts do not run; the CDN should still serve it\n * with `Content-Security-Policy: script-src 'none'` for anyone opening it directly.\n */\nexport const IMAGE_TYPES = ['image/apng', 'image/avif', 'image/gif', 'image/jpeg', 'image/png', 'image/svg+xml', 'image/webp'];\n\nconst MB = 1024 * 1024;\n\n/** Problems with chosen files, checked before anything is saved: type, the size limit, and a size warning. */\nexport function imageFileIssues(files: Map<string, File>): { level: 'warning' | 'error'; message: string }[] {\n const max = window.baackEditorConfig?.maxImageBytes ?? 10 * MB;\n const warn = window.baackEditorConfig?.warnImageBytes ?? 2 * MB;\n const size = (bytes: number) => `${(bytes / MB).toFixed(1)} MB`;\n const issues: { level: 'warning' | 'error'; message: string }[] = [];\n for (const file of files.values()) {\n if (!IMAGE_TYPES.includes(file.type)) {\n issues.push({ level: 'error', message: `${file.name} is not an image type Baack accepts: JPEG, PNG, APNG, GIF, WebP, AVIF or SVG.` });\n } else if (file.size > max) {\n issues.push({ level: 'error', message: `${file.name} is ${size(file.size)}; the limit is ${size(max)}. Use a smaller file.` });\n } else if (file.size > warn) {\n issues.push({ level: 'warning', message: `${file.name} is ${size(file.size)}, large for the web. Compressing it will make the page faster.` });\n }\n }\n return issues;\n}\n", null, "// Content inside a `data-content-live` element is rendered by the page's\n// framework (a hydrated island, a client-rendered app), which would undo or\n// trip over a direct DOM change. There the editor announces what each item\n// should show (`baack:item-shown`), and the page re-renders from its entity\n// (`useLiveEntity` in the components). Everywhere else it renders in place.\n\nimport {\n ITEM_SHOWN_EVENT,\n LIVE_ATTRIBUTE,\n LIVE_REQUEST_EVENT,\n type ItemShownDetail,\n type LiveRequestDetail,\n} from '@baack-software/baack-ts-components/live';\nimport type { Binding } from './core/discovery.ts';\nimport { renderInto, urnAttribute, type ContentItem } from './core/registry.ts';\nimport type { Store } from './core/store.ts';\n\n/** True when the page's framework renders this element. */\nexport function inLiveContent(element: Element): boolean {\n return element.closest(`[${LIVE_ATTRIBUTE}]`) !== null;\n}\n\nexport class LiveIslands {\n private readonly store: Store;\n /** What the editor shows in live content, by slot: sent again to content that renders later. */\n private readonly shown = new Map<string, ItemShownDetail>();\n /** Slots holding a reorder preview: the page re-renders its elements there, which must not end the preview. */\n private readonly previews = new Set<string>();\n\n constructor(store: Store) {\n this.store = store;\n document.addEventListener(LIVE_REQUEST_EVENT, this.onRequest);\n }\n\n /** Shows `item` in a binding's element: through an event for live content, in place otherwise. */\n render(binding: Binding, item: ContentItem): void {\n if (!inLiveContent(binding.element)) {\n renderInto(binding.entry, binding.element, binding, item);\n return;\n }\n const detail: ItemShownDetail = { ...this.slot(binding), item };\n // A reorder preview holds this slot until it is saved or reverted.\n if (this.previews.has(key(detail))) return;\n this.shown.set(key(detail), detail);\n dispatch(detail);\n // The framework renders asynchronously; the editor finds the element by its URN straight away.\n if (item.urn) binding.element.setAttribute(urnAttribute(binding.entry), item.urn);\n }\n\n /** For live content, asks the page to show its own value again and returns true; false for other content. */\n restore(binding: Binding): boolean {\n if (!inLiveContent(binding.element)) return false;\n const detail: ItemShownDetail = { ...this.slot(binding), restore: true };\n if (this.previews.has(key(detail))) return true;\n this.shown.delete(key(detail));\n dispatch(detail);\n return true;\n }\n\n /**\n * For live content: shows `item` at another slot of the binding's name (a\n * reorder preview), or with no item, asks the page to show its own again.\n */\n showAt(binding: Binding, sortOrder: number, item: ContentItem | undefined): void {\n const detail: ItemShownDetail = item ? { ...this.slot(binding), sortOrder, item } : { ...this.slot(binding), sortOrder, restore: true };\n if (item) {\n this.shown.set(key(detail), detail);\n this.previews.add(key(detail));\n } else {\n this.shown.delete(key(detail));\n this.previews.delete(key(detail));\n }\n dispatch(detail);\n }\n\n /** A reorder preview was saved, or edit mode is ending: its slots show what the editor renders again. */\n endPreviews(): void {\n this.previews.clear();\n }\n\n private slot(binding: Binding) {\n return {\n entityUrn: this.store.entityFor(binding.scope) ?? binding.scope,\n type: binding.entry.type,\n name: binding.name,\n sortOrder: binding.sortOrder,\n };\n }\n\n private readonly onRequest = (event: CustomEvent<LiveRequestDetail>) => {\n for (const detail of this.shown.values()) if (detail.entityUrn === event.detail.entityUrn) dispatch(detail);\n };\n}\n\nfunction key(detail: ItemShownDetail): string {\n return `${detail.entityUrn}\\u0000${detail.type}\\u0000${detail.name}\\u0000${detail.sortOrder}`;\n}\n\nfunction dispatch(detail: ItemShownDetail): void {\n document.dispatchEvent(new CustomEvent(ITEM_SHOWN_EVENT, { detail }));\n}\n", "// Editing in place on the host page's own element. Handles only the DOM side:\n// making the element editable, keys, focus, and putting everything back.\n\nimport type { EditorHost } from './host.ts';\nimport { fitEmpty } from './marker.ts';\nimport { inLiveContent } from '../live.ts';\n\nexport interface InlineCallbacks {\n input(): void;\n send(): void;\n revert(): void;\n /** Focus left the element and the editor UI. The edit is kept. */\n blurred(): void;\n}\n\nconst IS_MAC = /Mac|iPhone|iPad/.test(navigator.userAgent);\n\nexport class InlineEdit {\n readonly element: HTMLElement;\n /** Inline elements (a span) send on Enter; block elements and paragraph layouts take a newline. */\n readonly sendsOnEnter: boolean;\n private readonly host: EditorHost;\n private readonly callbacks: InlineCallbacks;\n private readonly savedEditable: string | null;\n private readonly savedWhiteSpace: string;\n /** In live content, the framework's own nodes, put back on close so it can render the saved value over them. */\n private readonly savedChildren: Node[] | undefined;\n\n /** `raw` is the value to edit, shown as plain text in place of the component's rendering. */\n constructor(element: HTMLElement, raw: string, host: EditorHost, callbacks: InlineCallbacks) {\n this.element = element;\n this.host = host;\n this.callbacks = callbacks;\n this.sendsOnEnter =\n getComputedStyle(element).display.startsWith('inline') && element.getAttribute('data-text-layout') !== 'paragraphs';\n this.savedEditable = element.getAttribute('contenteditable');\n this.savedWhiteSpace = element.style.whiteSpace;\n this.savedChildren = inLiveContent(element) ? [...element.childNodes] : undefined;\n\n element.textContent = raw;\n fitEmpty(element);\n // plaintext-only: the browser inserts no markup, and pastes arrive as text.\n element.setAttribute('contenteditable', 'plaintext-only');\n // Show newlines and repeated spaces exactly as they will be stored.\n element.style.whiteSpace = 'pre-wrap';\n element.addEventListener('input', this.onInput);\n element.addEventListener('keydown', this.onKeyDown);\n element.addEventListener('blur', this.onBlur);\n element.focus();\n placeCaret(element);\n }\n\n get hint(): string {\n const modifier = IS_MAC ? '\u2318' : 'Ctrl';\n return this.sendsOnEnter ? 'Enter to save \u00B7 Esc to revert' : `${modifier}+Enter to save \u00B7 Esc to revert`;\n }\n\n close(): void {\n this.element.removeEventListener('input', this.onInput);\n this.element.removeEventListener('keydown', this.onKeyDown);\n this.element.removeEventListener('blur', this.onBlur);\n if (this.savedEditable === null) {\n this.element.removeAttribute('contenteditable');\n } else {\n this.element.setAttribute('contenteditable', this.savedEditable);\n }\n this.element.style.whiteSpace = this.savedWhiteSpace;\n if (!this.element.getAttribute('style')) this.element.removeAttribute('style');\n if (this.savedChildren) this.element.replaceChildren(...this.savedChildren);\n }\n\n private readonly onInput = () => {\n // Emptied by typing: keep the element (and the caret) visible.\n fitEmpty(this.element);\n this.callbacks.input();\n };\n\n private readonly onKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n event.preventDefault();\n this.callbacks.revert();\n } else if (event.key === 'Enter' && (event.metaKey || event.ctrlKey || (this.sendsOnEnter && !event.shiftKey))) {\n event.preventDefault();\n this.callbacks.send();\n }\n };\n\n private readonly onBlur = (event: FocusEvent) => {\n // Focus moving into the editor's own UI is not leaving the edit.\n if (event.relatedTarget === this.host.element) return;\n this.callbacks.blurred();\n };\n}\n\n/** Keeps a selection the double-click made inside the element; otherwise puts the caret at the end. */\nfunction placeCaret(element: HTMLElement): void {\n const selection = window.getSelection();\n if (!selection) return;\n if (selection.rangeCount > 0 && element.contains(selection.getRangeAt(0).commonAncestorContainer)) return;\n const range = document.createRange();\n range.selectNodeContents(element);\n range.collapse(false);\n selection.removeAllRanges();\n selection.addRange(range);\n}\n", "// Opening an editor for an element or an outline row: in place for text, a\n// form otherwise; recording unsaved values and previewing them.\n\nimport type { Binding } from './core/discovery.ts';\nimport { createKey } from './core/pending.ts';\nimport { sameValue, urnAttribute, valueOf, withCarried, type FormValues } from './core/registry.ts';\nimport { isLive, type EditTarget, type EditorContext, type Value } from './targets.ts';\nimport { imageFileIssues } from './images.ts';\nimport { InlineEdit } from './ui/inline.ts';\nimport { mark } from './ui/marker.ts';\nimport type { ExtraAction } from './ui/popover.ts';\nimport type { PageView } from './view.ts';\n\ninterface ActiveEdit {\n target: EditTarget;\n /** In-place editing; absent for a form. */\n session: InlineEdit | undefined;\n}\n\nexport class Editing {\n private readonly ctx: EditorContext;\n private readonly view: PageView;\n private readonly save: (target: EditTarget) => Promise<void>;\n private active: ActiveEdit | undefined;\n\n constructor(ctx: EditorContext, view: PageView, save: (target: EditTarget) => Promise<void>) {\n this.ctx = ctx;\n this.view = view;\n this.save = save;\n }\n\n /** The edit in progress, if any. */\n get current(): ActiveEdit | undefined {\n return this.active;\n }\n\n attach(): void {\n document.addEventListener('dblclick', this.onDoubleClick, true);\n document.addEventListener('click', this.onClick, true);\n }\n\n detach(): void {\n document.removeEventListener('dblclick', this.onDoubleClick, true);\n document.removeEventListener('click', this.onClick, true);\n }\n\n private readonly onDoubleClick = (event: MouseEvent) => {\n const { discovery, toolbar } = this.ctx;\n const element = discovery.closest(event.target);\n if (!element || this.active?.target.binding?.element === element) return;\n const binding = discovery.of(element)[0];\n if (!binding) return;\n event.preventDefault();\n const target = this.targetFor(binding);\n if (!target) {\n toolbar.showMessage(`The content for \"${binding.name}\" has not loaded.`);\n return;\n }\n this.open(target);\n };\n\n /** In edit mode a click on an item must not follow a link around it. */\n private readonly onClick = (event: MouseEvent) => {\n if (this.ctx.discovery.closest(event.target)) event.preventDefault();\n };\n\n /** Clicking elsewhere closes a form; the edit is kept. */\n private readonly onPointerDown = (event: PointerEvent) => {\n const path = event.composedPath();\n const anchor = this.active?.target.binding?.element ?? this.active?.target.anchor;\n if (!this.active || path.includes(this.ctx.host.element) || (anchor && path.includes(anchor))) return;\n this.close();\n };\n\n targetFor(binding: Binding): EditTarget | undefined {\n const { store } = this.ctx;\n const entityUrn = store.entityFor(binding.scope);\n if (!entityUrn) return undefined;\n const urn = binding.element.getAttribute(urnAttribute(binding.entry)) ?? undefined;\n return {\n entityUrn,\n entry: binding.entry,\n name: binding.name,\n sortOrder: binding.sortOrder,\n urn: urn && store.get(urn) ? urn : undefined,\n anchor: binding.element,\n binding,\n };\n }\n\n open(target: EditTarget): void {\n // Editing starts from the latest, so a preview of an older version of this item ends.\n this.view.stopPreview(target);\n const visible = target.binding && target.binding.element.getClientRects().length > 0;\n // In place only where the item's component renders the element's content (not a section or switch).\n const ownsChildren = target.binding ? target.entry.component?.(target.binding.element).ownsChildren !== false : false;\n if (target.urn && target.entry.surface === 'inline' && target.binding && visible && ownsChildren) {\n this.openInline(target);\n } else {\n // A create starts from the page's placeholder, even when its element is not visible (such as the head).\n const placeholder = !target.urn && target.binding ? target.entry.fromPlaceholder?.(target.binding.element) : undefined;\n void this.openForm(visible ? target : { ...target, binding: undefined, anchor: target.anchor }, placeholder);\n }\n }\n\n private openInline(target: EditTarget): void {\n this.close();\n const { store, pending, host, popover } = this.ctx;\n const { entry } = target;\n const element = target.binding!.element;\n const stored = store.get(target.urn!)!;\n const value = (pending.getEdit(target.urn!)?.value ?? valueOf(entry, stored.item)) as { value?: unknown };\n const session = new InlineEdit(element, String(value.value ?? ''), host, {\n input: () => this.setPending(target, entry.read!(element)),\n send: () => void this.save(target),\n revert: () => this.revert(target),\n blurred: () => this.close(),\n });\n this.active = { target, session };\n mark(element, 'editing');\n popover.show(element, entry.label, `${target.name} #${target.sortOrder}`, session.hint, {\n send: () => void this.save(target),\n revert: () => this.revert(target),\n });\n popover.setIssues(entry.validate(entry.read!(element)));\n this.offerHistory(target);\n }\n\n /** Secondary actions for an existing item: history, moving it, and reordering its list. */\n private offerHistory(target: EditTarget): void {\n const { hooks } = this.ctx;\n this.ctx.popover.setNameAction(() => hooks.showItem(target));\n const urn = target.urn;\n if (!urn || target.fromVersion) {\n this.ctx.popover.setExtras([]);\n return;\n }\n const binding = target.binding;\n const actions: ExtraAction[] = [\n {\n label: 'History',\n icon: 'history',\n run: () => {\n this.close();\n hooks.openHistory({ entityUrn: target.entityUrn, entry: target.entry, name: target.name, sortOrder: target.sortOrder, urn });\n },\n },\n ];\n if (binding && hooks.canReorder(binding)) {\n actions.push(\n { label: 'Move up', icon: 'arrow-up', menu: true, run: () => hooks.moveBy(binding, -1) },\n { label: 'Move down', icon: 'arrow-down', menu: true, run: () => hooks.moveBy(binding, 1) },\n { label: 'Reorder\u2026', icon: 'list-ordered', menu: true, run: () => hooks.reorder(binding) },\n );\n }\n actions.push({ label: 'Move or rename\u2026', icon: 'pencil-line', menu: true, run: () => hooks.relocate(target) });\n this.ctx.popover.setExtras(actions);\n }\n\n /** `placeholder`: the starting value of a create, read from its page element. */\n async openForm(target: EditTarget, placeholder?: Value): Promise<void> {\n this.close();\n const { store, pending, popover, toolbar } = this.ctx;\n const { entry } = target;\n const form = entry.form;\n if (!form) return;\n\n let value: Value;\n if (target.urn) {\n const base = await this.baseValue(target);\n if (!base) return;\n value = (target.fromVersion ? undefined : pending.getEdit(target.urn)?.value) ?? base;\n } else {\n if (store.itemAt(target.entityUrn, entry, target.name, target.sortOrder)) {\n toolbar.showMessage(`An item already exists at ${target.name} #${target.sortOrder}.`);\n return;\n }\n value =\n pending.getCreate(createKey({ ...target, type: entry.type }))?.value ??\n placeholder ??\n (target.binding ? entry.fromPlaceholder?.(target.binding.element) : undefined) ??\n entry.defaults();\n }\n\n this.active = { target, session: undefined };\n if (target.binding) mark(target.binding.element, 'editing');\n const values = form.toForm(value);\n popover.showForm(\n target.anchor,\n target.fromVersion ? `${entry.label}, from an older version` : target.urn ? entry.label : `New ${entry.label.toLowerCase()}`,\n `${target.name} #${target.sortOrder}`,\n form.fields,\n values,\n {\n input: (current) => this.onFormInput(target, current),\n send: () => void this.save(target),\n revert: () => this.revert(target),\n },\n entry.surface === 'panel',\n );\n popover.setDescription(this.describeForm(target, values));\n popover.setIssues(entry.validate(value));\n this.offerHistory(target);\n // The older version is the edit, before anything is typed.\n if (target.fromVersion) this.setPending(target, value);\n document.addEventListener('pointerdown', this.onPointerDown, true);\n }\n\n /** The form's own note, plus a warning when a new item would go live immediately. */\n private describeForm(target: EditTarget, values: FormValues): string {\n const notes = [target.entry.form?.describe?.(values) ?? ''];\n if (!target.urn && isLive(this.ctx.store.view(target.entityUrn)?.status)) {\n notes.push('This content is published, so a new item is live as soon as it is saved.');\n }\n return notes.filter(Boolean).join(' ');\n }\n\n /** The value an edit starts from: the item's, or its source for a view-rendered type. */\n private async baseValue(target: EditTarget): Promise<Value | undefined> {\n const { store, sources, transport, feedback } = this.ctx;\n const urn = target.urn!;\n // Items with no element (head, JSON, outline rows) are found through the view.\n const stored = store.get(urn) ?? store.itemAt(target.entityUrn, target.entry, target.name, target.sortOrder);\n if (!stored || stored.item.urn !== urn) return undefined;\n if (!target.entry.renderedByView) return valueOf(target.entry, stored.item);\n try {\n const source = sources.get(urn) ?? valueOf(target.entry, await transport.read(target.entry, urn));\n sources.set(urn, source);\n return source;\n } catch (error) {\n void feedback.report(error, 'load the source', () => void this.openForm(target));\n return undefined;\n }\n }\n\n close(): void {\n const active = this.active;\n if (!active) return;\n this.active = undefined;\n document.removeEventListener('pointerdown', this.onPointerDown, true);\n active.session?.close();\n this.ctx.popover.hide();\n // Re-render: in-place editing left raw text in the element.\n const binding = active.target.binding;\n if (this.view.isEditing && binding?.element.isConnected) this.view.show(binding);\n }\n\n private onFormInput(target: EditTarget, values: FormValues): void {\n const { popover } = this.ctx;\n const form = target.entry.form;\n if (!form) return;\n popover.setDescription(this.describeForm(target, values));\n const value = form.fromForm(values);\n if (typeof value === 'string') {\n popover.setError(value);\n popover.setIssues([]);\n return;\n }\n popover.setError('');\n // Chosen image files are checked as soon as they are picked.\n const fileIssues = target.entry.type === 'image' ? imageFileIssues(popover.files()) : [];\n popover.setIssues([...target.entry.validate(value), ...fileIssues]);\n this.setPending(target, value);\n }\n\n /** Records an unsaved value and previews it everywhere the item is shown. */\n setPending(target: EditTarget, input: Value): void {\n const { store, sources, pending, popover } = this.ctx;\n const { entry } = target;\n let value = input;\n if (target.urn) {\n const stored = store.get(target.urn) ?? store.itemAt(target.entityUrn, entry, target.name, target.sortOrder);\n // Fields the form does not edit (an image's files) carry over from the version.\n value = withCarried(entry, stored?.item, input);\n // From an older version, the change is against the item as it is now: saving that version unchanged restores it.\n const current = target.fromVersion ? store.itemAt(target.entityUrn, entry, target.name, target.sortOrder) : stored;\n const base = entry.renderedByView ? sources.get(current?.item.urn ?? target.urn) : current?.item;\n if (base && sameValue(entry, value, base)) {\n pending.clear(target.urn);\n } else {\n pending.set({\n kind: 'edit',\n type: entry.type,\n urn: target.urn,\n entityUrn: target.entityUrn,\n name: target.name,\n sortOrder: target.sortOrder,\n value,\n ...(target.fromVersion ? { fromVersion: true } : {}),\n });\n }\n } else {\n pending.set({ kind: 'create', type: entry.type, entityUrn: target.entityUrn, name: target.name, sortOrder: target.sortOrder, value });\n }\n this.view.reshow(target);\n if (target.entry.surface === 'inline' && this.active?.session) popover.setIssues(entry.validate(value));\n }\n\n revert(target: EditTarget): void {\n this.ctx.pending.clear(target.urn ?? createKey({ ...target, type: target.entry.type }));\n this.close();\n this.view.reshow(target);\n }\n}\n", "// Turns a failure into something the user can act on. Each kind needs a\n// different response, so they must stay distinguishable.\n\nimport { isBaackApiError, type BaackApiError } from '@baack-software/baack-ts-client';\nimport { EntityMismatchError, NotLiveError } from '../core/scoped-views.ts';\n\nexport type FailureKind = 'unauthorized' | 'forbidden' | 'not-found' | 'not-live' | 'conflict' | 'mismatch' | 'network' | 'failed';\n\nexport interface Failure {\n kind: FailureKind;\n message: string;\n /** The API's JSON error body, pretty-printed, for a collapsed \"Debug\" section. */\n debug?: string;\n}\n\n/**\n * The API answers 404, not 401 or 403, when the session or a permission is\n * missing. So for a 404, pass `hasSession` from a fresh client context read:\n * without a session it is treated as an ended session.\n */\nexport function describeFailure(error: unknown, action: string, hasSession?: boolean): Failure {\n if (isBaackApiError(error)) {\n const debug = debugText(error);\n return debug === undefined ? describeApiError(error, action, hasSession) : { ...describeApiError(error, action, hasSession), debug };\n }\n return describeOther(error, action);\n}\n\nfunction describeApiError(error: BaackApiError, action: string, hasSession: boolean | undefined): Failure {\n if (error.isUnauthorized || (error.isNotFound && hasSession === false)) {\n return { kind: 'unauthorized', message: `Your session has ended. Log in again to ${action}. Your changes are kept.` };\n }\n if (error.isForbidden) {\n return { kind: 'forbidden', message: `You don't have permission to ${action}.` };\n }\n if (error.isNotFound) {\n return { kind: 'not-found', message: `This item no longer exists, or you don't have permission to ${action}.` };\n }\n if (error.isConflict) {\n return { kind: 'conflict', message: `Someone else changed this since you opened it. Reload to see their version.` };\n }\n const { detail } = error;\n return {\n kind: 'failed',\n message: `Couldn't ${action} (HTTP ${error.status})${detail ? `: ${detail.replace(/\\.$/, '')}` : ''}. Try again.`,\n };\n}\n\nfunction describeOther(error: unknown, action: string): Failure {\n if (error instanceof NotLiveError) {\n return { kind: 'not-live', message: 'This content is not published yet, so it has no live version to show. Show the latest drafts to edit it.' };\n }\n if (error instanceof EntityMismatchError) {\n const { language } = error.received;\n return {\n kind: 'mismatch',\n message: `Couldn't ${action}: Baack returned a different language version (${language}) instead of the content on this page, so it can't be edited here. Reload the page and try again.`,\n };\n }\n if (error instanceof TypeError) {\n return { kind: 'network', message: `Couldn't reach Baack to ${action}. Check your connection and try again.` };\n }\n return { kind: 'failed', message: `Couldn't ${action}: ${error instanceof Error ? error.message : String(error)}` };\n}\n\n/**\n * What was sent and what came back, for the \"Debug\" section: the request's\n * method, path and JSON body, then the API's JSON error body. Undefined when\n * the response had no JSON body.\n */\nfunction debugText(error: BaackApiError): string | undefined {\n const body = error.json();\n if (body === undefined) return undefined;\n const pretty = (text: string) => {\n try {\n return JSON.stringify(JSON.parse(text), null, 2);\n } catch {\n return text;\n }\n };\n const path = (() => {\n try {\n return new URL(error.url).pathname;\n } catch {\n return error.url;\n }\n })();\n const request = `Request: ${error.method} ${path}${error.requestBody ? `\\n${pretty(error.requestBody)}` : ''}`;\n return `${request}\\n\\nResponse: ${error.status}\\n${JSON.stringify(body, null, 2)}`;\n}\n", "// Turning failures into messages, and the login prompt. A 404 can mean the\n// session ended, so the client context is asked which it is.\n\nimport { isBaackApiError } from '@baack-software/baack-ts-client';\nimport type { Transport } from './core/transport.ts';\nimport { describeFailure, type Failure } from './ui/messages.ts';\nimport type { Toolbar } from './ui/toolbar.ts';\n\nexport class Feedback {\n private readonly transport: Transport;\n private readonly toolbar: () => Toolbar;\n private retry: (() => void) | undefined;\n\n /** `toolbar` is read lazily: the toolbar is built with this object's retry. */\n constructor(transport: Transport, toolbar: () => Toolbar) {\n this.transport = transport;\n this.toolbar = toolbar;\n }\n\n /** Called by the login prompt's \"try again\". */\n retryAfterLogin(): void {\n this.retry?.();\n }\n\n async report(error: unknown, action: string, retry: () => void): Promise<void> {\n const failure = await this.describe(error, action);\n this.toolbar().showMessage(failure.message, false, failure.debug);\n if (failure.kind === 'unauthorized') void this.promptLogin(failure.message, retry);\n }\n\n async describe(error: unknown, action: string): Promise<Failure> {\n let hasSession: boolean | undefined;\n if (isBaackApiError(error) && error.isNotFound) {\n try {\n hasSession = (await this.transport.clientContext()).hasSession === true;\n } catch (contextError) {\n console.warn('Baack editor: could not read the client context to explain a 404', contextError);\n }\n }\n return describeFailure(error, action, hasSession);\n }\n\n async promptLogin(message: string, retry: () => void): Promise<void> {\n this.retry = retry;\n let iframeSrc: string | null | undefined;\n try {\n iframeSrc = (await this.transport.clientContext()).loginIframeSrc;\n } catch (error) {\n console.warn('Baack editor: could not read the client context for the login prompt', error);\n }\n this.toolbar().showLogin(message, iframeSrc);\n }\n}\n", "// A word diff for showing what changed between two versions. Text only: the\n// result is rendered as text nodes, never markup.\n\nexport interface DiffPart {\n /** `increase` and `decrease` mark a summary's percentage change, for values that cannot be diffed as words. */\n kind: 'same' | 'added' | 'removed' | 'increase' | 'decrease' | 'arrow';\n text: string;\n}\n\n/**\n * The change from `before` to `after` as a percentage of `before`'s size.\n * From zero, any rise is +100% and any fall -100%. Crossing zero counts the\n * whole distance against the starting value: 20 to -20 is -200%.\n */\nexport function percentChange(before: number, after: number): number {\n if (before === after) return 0;\n if (before === 0) return after > 0 ? 100 : -100;\n return ((after - before) / Math.abs(before)) * 100;\n}\n\n/** \"+96%\" or \"\u2212200%\", at most one decimal place. */\nexport function formatPercent(percent: number): string {\n const size = new Intl.NumberFormat('en-GB', { maximumFractionDigits: 1 }).format(Math.abs(percent));\n return `${percent > 0 ? '+' : percent < 0 ? '\u2212' : ''}${size}%`;\n}\n\nconst MAX_TOKENS = 2000;\n\nexport function diffWords(before: string, after: string): DiffPart[] {\n if (before === after) return [{ kind: 'same', text: after }];\n const a = before.split(/(\\s+)/).filter(Boolean);\n const b = after.split(/(\\s+)/).filter(Boolean);\n // Long values: show a plain replacement rather than spend time on the table.\n if (a.length * b.length > MAX_TOKENS * MAX_TOKENS) {\n return [\n { kind: 'removed', text: before },\n { kind: 'added', text: after },\n ];\n }\n // Longest common subsequence, from the end.\n const table: number[][] = Array.from({ length: a.length + 1 }, () => new Array<number>(b.length + 1).fill(0));\n for (let i = a.length - 1; i >= 0; i -= 1) {\n for (let j = b.length - 1; j >= 0; j -= 1) {\n table[i]![j] = a[i] === b[j] ? table[i + 1]![j + 1]! + 1 : Math.max(table[i + 1]![j]!, table[i]![j + 1]!);\n }\n }\n const parts: DiffPart[] = [];\n const push = (kind: DiffPart['kind'], text: string) => {\n const last = parts.at(-1);\n if (last?.kind === kind) last.text += text;\n else parts.push({ kind, text });\n };\n let i = 0;\n let j = 0;\n while (i < a.length && j < b.length) {\n if (a[i] === b[j]) {\n push('same', a[i]!);\n i += 1;\n j += 1;\n } else if (table[i + 1]![j]! >= table[i]![j + 1]!) {\n push('removed', a[i]!);\n i += 1;\n } else {\n push('added', b[j]!);\n j += 1;\n }\n }\n while (i < a.length) push('removed', a[i++]!);\n while (j < b.length) push('added', b[j++]!);\n return parts;\n}\n", "// DOM events for host code and framework islands. Dispatched on `document`.\n\nimport type { ItemType } from './registry.ts';\n\nexport interface ItemUpdatedDetail {\n entityUrn: string;\n /** Absent when the item was just created. */\n oldUrn?: string;\n newUrn: string;\n type: ItemType;\n /** The item as the API returned it. */\n value: unknown;\n}\n\nexport interface ItemPublishedDetail {\n entityUrn: string;\n /** The version now live. */\n urn: string;\n type: ItemType;\n}\n\nexport interface EntityStateDetail {\n entityUrn: string;\n status: string;\n previous: string | undefined;\n}\n\ndeclare global {\n interface DocumentEventMap {\n 'baack:item-updated': CustomEvent<ItemUpdatedDetail>;\n 'baack:item-published': CustomEvent<ItemPublishedDetail>;\n 'baack:entity-state': CustomEvent<EntityStateDetail>;\n 'baack:entity-published': CustomEvent<{ entityUrn: string }>;\n }\n}\n\nexport function dispatchItemUpdated(detail: ItemUpdatedDetail): void {\n document.dispatchEvent(new CustomEvent('baack:item-updated', { detail }));\n}\n\nexport function dispatchItemPublished(detail: ItemPublishedDetail): void {\n document.dispatchEvent(new CustomEvent('baack:item-published', { detail }));\n}\n\nexport function dispatchEntityState(detail: EntityStateDetail): void {\n document.dispatchEvent(new CustomEvent('baack:entity-state', { detail }));\n}\n\nexport function dispatchEntityPublished(entityUrn: string): void {\n document.dispatchEvent(new CustomEvent('baack:entity-published', { detail: { entityUrn } }));\n}\n", "// A small form for the editor's own panels (creating an entity, adding an\n// item). Item values use the popover's form; this is for everything else.\n\nimport { el, selectBox } from './host.ts';\n\nexport interface SimpleField {\n key: string;\n label: string;\n value: string;\n /** Offer a choice instead of free text. */\n options?: { value: string; label: string }[];\n}\n\nexport class SimpleForm {\n readonly element: HTMLFormElement;\n private readonly inputs = new Map<string, HTMLInputElement | HTMLSelectElement>();\n private readonly submit: HTMLButtonElement;\n private readonly error: HTMLElement;\n private readonly submitLabel: string;\n private readonly onCancel: (() => void) | undefined;\n\n /** `onCancel` runs after Cancel closes the form. */\n constructor(\n title: string,\n fields: SimpleField[],\n submitLabel: string,\n onSubmit: (values: Record<string, string>) => void,\n onCancel?: () => void,\n ) {\n this.submitLabel = submitLabel;\n this.onCancel = onCancel;\n this.element = el('form', 'simple-form');\n this.element.append(el('div', 'title', title));\n for (const field of fields) {\n const label = el('label', 'field');\n let input: HTMLInputElement | HTMLSelectElement;\n if (field.options) {\n input = el('select');\n for (const option of field.options) input.append(Object.assign(el('option', '', option.label), { value: option.value }));\n } else {\n input = el('input');\n input.type = 'text';\n }\n input.name = field.key;\n input.value = field.value;\n label.append(el('span', 'caption', field.label), input instanceof HTMLSelectElement ? selectBox(input) : input);\n this.inputs.set(field.key, input);\n this.element.append(label);\n }\n this.error = el('p', 'error');\n this.error.setAttribute('role', 'alert');\n this.submit = el('button', 'primary', submitLabel);\n this.submit.type = 'submit';\n const cancel = el('button', '', 'Cancel');\n cancel.type = 'button';\n cancel.addEventListener('click', () => this.cancel());\n const actions = el('div', 'actions');\n actions.append(cancel, this.submit);\n this.element.append(this.error, actions);\n this.element.addEventListener('submit', (event) => {\n event.preventDefault();\n if (!this.submit.disabled) onSubmit(this.values());\n });\n }\n\n /** Removes the form, as its Cancel button does, and tells its container (a `cancel` event). */\n cancel(): void {\n this.element.dispatchEvent(new Event('cancel'));\n this.element.remove();\n this.onCancel?.();\n }\n\n values(): Record<string, string> {\n return Object.fromEntries([...this.inputs].map(([key, input]) => [key, input.value.trim()]));\n }\n\n /** Disables the button while a request is in flight, so it cannot be sent twice. */\n setBusy(busy: boolean, label = 'Working\u2026'): void {\n this.submit.disabled = busy;\n this.submit.textContent = busy ? label : this.submitLabel;\n }\n\n setError(message: string): void {\n this.error.textContent = message;\n }\n}\n", "// Saving unsaved work: one change, all of an entity's changes, or every empty\n// slot. Each save creates a version; the latest view is re-read afterwards so\n// templates and renderings update.\n\nimport { dispatchItemUpdated } from './core/events.ts';\nimport { createKey, pendingKey, type Pending, type PendingEdit } from './core/pending.ts';\nimport { toRepresentation, urnAttribute, type ContentItem, type TypeEntry } from './core/registry.ts';\nimport type { Editing } from './editing.ts';\nimport { parseTimestamp as parseUtc } from '@baack-software/baack-ts-components/format';\nimport { isLive, reviewAction, type EditTarget, type EditorContext } from './targets.ts';\nimport { SimpleForm } from './ui/form.ts';\nimport { mark } from './ui/marker.ts';\nimport type { PageView } from './view.ts';\nimport { formatPercent, percentChange, type DiffPart } from './core/diff.ts';\n\n/** Someone saved a newer draft of the item since this edit began. Nothing was saved. */\nexport class ConflictError extends Error {\n readonly change: PendingEdit;\n readonly newest: ContentItem;\n\n constructor(change: PendingEdit, newest: ContentItem) {\n super('a newer draft of this item has been saved');\n this.change = change;\n this.newest = newest;\n }\n}\n\n/** A value as a short line, for comparing two versions. */\nexport function summarise(entry: TypeEntry, value: object): string {\n if (!entry.form) return JSON.stringify(value);\n return Object.values(entry.form.toForm(value as never))\n .map((field) => (typeof field === 'boolean' ? (field ? 'on' : 'off') : field))\n .filter((field) => field !== '')\n .join(' \u00B7 ');\n}\n\n/**\n * A change between values that cannot be diffed as words: \"was \u2192 now\", with\n * a money change in one currency as a percentage, up or down.\n */\nexport function summariseChange(entry: TypeEntry, before: ContentItem, after: ContentItem): DiffPart[] {\n const parts: DiffPart[] = [\n { kind: 'same', text: summarise(entry, before) },\n { kind: 'arrow', text: '\u2192' },\n { kind: 'same', text: summarise(entry, after) },\n ];\n const delta = moneyDelta(before, after);\n return delta ? [...parts, { kind: 'same', text: ' ' }, delta] : parts;\n}\n\n/** Amounts are integer minor units, compared only in the same currency. */\nfunction moneyDelta(before: ContentItem, after: ContentItem): DiffPart | undefined {\n const was = before as { unitValue?: unknown; currencyCode?: unknown };\n const now = after as { unitValue?: unknown; currencyCode?: unknown };\n if (typeof was.unitValue !== 'number' || typeof now.unitValue !== 'number' || was.currencyCode !== now.currencyCode) return undefined;\n const percent = percentChange(was.unitValue, now.unitValue);\n if (percent === 0) return undefined;\n return { kind: percent > 0 ? 'increase' : 'decrease', text: formatPercent(percent) };\n}\n\nexport class Saving {\n private readonly ctx: EditorContext;\n private readonly view: PageView;\n private readonly editing: () => Editing;\n private readonly inFlight = new Set<string>();\n\n /** `editing` is read lazily: it is built with this object's save. */\n constructor(ctx: EditorContext, view: PageView, editing: () => Editing) {\n this.ctx = ctx;\n this.view = view;\n this.editing = editing;\n }\n\n /** Saves the change for a target, from its open form or its unsaved value. */\n async save(target: EditTarget): Promise<void> {\n const { pending, popover, feedback } = this.ctx;\n const editing = this.editing();\n const key = target.urn ?? createKey({ ...target, type: target.entry.type });\n if (this.inFlight.has(key)) return;\n const isActive = () => editing.current?.target === target;\n\n // New image files: a new version first, then uploads (rule 5).\n if (isActive() && target.entry.type === 'image') {\n const files = popover.files() as Map<'DEFAULT' | 'MEDIUM' | 'LARGE', File>;\n if (files.size > 0) {\n this.inFlight.add(key);\n try {\n await this.ctx.hooks.saveImage(target, files);\n } finally {\n this.inFlight.delete(key);\n }\n return;\n }\n }\n\n // A form showing an invalid value must not save an older valid one.\n if (isActive() && !editing.current!.session && target.entry.form) {\n const current = target.entry.form.fromForm(popover.values());\n if (typeof current === 'string') {\n popover.setError(current);\n return;\n }\n // A create opened from a placeholder can be saved unchanged.\n if (!target.urn || !pending.getEdit(target.urn)) editing.setPending(target, current);\n }\n const change = target.urn ? pending.getEdit(target.urn) : pending.getCreate(key);\n if (!change) {\n if (isActive()) editing.close();\n return;\n }\n if (target.entry.validate(change.value).some((issue) => issue.level === 'error')) return;\n\n this.inFlight.add(key);\n popover.setSending(true);\n popover.setError('');\n try {\n await this.commit(change);\n if (isActive()) editing.close();\n await this.view.refresh(target.entityUrn);\n } catch (error) {\n if (error instanceof ConflictError) {\n this.showConflict(error, isActive() ? target.anchor : this.ctx.toolbar.modeButton);\n return;\n }\n if (error instanceof StoredElsewhereError) {\n // Saved all the same: nothing is left to send, and the page and Items show what the API stored.\n if (isActive()) editing.close();\n this.ctx.toolbar.showMessage(error.message);\n await this.view.refresh(target.entityUrn);\n return;\n }\n const retry = () => void this.save(target);\n if (isActive()) {\n const failure = await feedback.describe(error, target.urn ? 'save this change' : 'create this item');\n popover.setError(failure.message, failure.debug);\n if (failure.kind === 'unauthorized') void feedback.promptLogin(failure.message, retry);\n } else {\n void feedback.report(error, 'save this change', retry);\n }\n } finally {\n this.inFlight.delete(key);\n popover.setSending(false);\n }\n }\n\n /** Saves one unsaved change. Throws on failure, leaving it unsaved. */\n async commit(change: Exclude<Pending, { kind: 'move' }>): Promise<ContentItem> {\n const { store, transport, pending } = this.ctx;\n const entry = this.ctx.entry(change.type);\n if (change.kind === 'edit') {\n // Never draft from an old version by accident: if someone saved a newer one, stop and show both.\n if (!change.fromVersion) {\n const newest = (await transport.history(entry, change.urn)).history[0];\n if (newest?.urn && newest.urn !== change.urn) throw new ConflictError(change, newest);\n }\n const stored = store.get(change.urn) ?? store.itemAt(change.entityUrn, entry, change.name, change.sortOrder);\n if (!stored || stored.item.urn !== change.urn) throw new Error('the item has changed since this edit was made');\n const saved = await transport.update(entry, change.urn, toRepresentation(entry, stored.item, change.value, change.entityUrn));\n if (!saved?.urn) throw new Error('the API returned no URN for the new version');\n this.applySaved(entry, change.urn, saved);\n dispatchItemUpdated({ entityUrn: change.entityUrn, oldUrn: change.urn, newUrn: saved.urn, type: entry.type, value: saved });\n checkSlot(saved, stored.item);\n return saved;\n }\n // Check occupancy first: a create at an occupied slot would draft over the item there.\n if (store.itemAt(change.entityUrn, entry, change.name, change.sortOrder)) {\n pending.clear(pendingKey(change));\n throw new Error(`an item already exists at ${change.name} #${change.sortOrder}`);\n }\n const slot = { name: change.name, sortOrder: change.sortOrder } as ContentItem;\n const saved = await transport.create(entry, toRepresentation(entry, slot, change.value, change.entityUrn));\n if (!saved?.urn) throw new Error('the API returned no URN for the new item');\n pending.clear(pendingKey(change));\n dispatchItemUpdated({ entityUrn: change.entityUrn, newUrn: saved.urn, type: entry.type, value: saved });\n checkSlot(saved, slot);\n return saved;\n }\n\n /** Every element showing the old version now shows the new one, URN included. */\n private applySaved(entry: TypeEntry, oldUrn: string, saved: ContentItem): void {\n const { discovery, store, pending, sources, toolbar } = this.ctx;\n const editing = this.editing();\n const elements = discovery\n .all()\n .filter((binding) => binding.entry === entry && binding.element.getAttribute(urnAttribute(entry)) === oldUrn);\n store.replace(oldUrn, saved);\n pending.clear(oldUrn);\n sources.delete(oldUrn);\n const editingBinding = editing.current?.target.binding;\n if (editingBinding && elements.includes(editingBinding)) editing.close();\n for (const binding of elements) {\n if (entry.renderedByView) {\n // The response is source; the rendering arrives with the re-read.\n binding.element.setAttribute(urnAttribute(entry), saved.urn!);\n } else {\n this.ctx.live.render(binding, saved);\n }\n mark(binding.element, 'editable');\n }\n toolbar.showMessage('');\n }\n\n /** Saves unsaved changes in order, for one entity or all. Stops when the session has ended. */\n async saveAll(entityUrn?: string): Promise<void> {\n const { pending, feedback, toolbar } = this.ctx;\n const queue = pending\n .all()\n .filter((p) => (entityUrn === undefined || p.entityUrn === entityUrn) && !(p.kind === 'edit' && p.stale));\n // Queued moves run as their plans, in order.\n for (const planId of new Set(queue.flatMap((p) => (p.kind === 'move' ? [p.planId] : [])))) {\n await this.ctx.hooks.runPlan(planId);\n }\n await Promise.all([...new Set(queue.map((p) => p.entityUrn))].map((urn) => this.view.loadScope(urn)));\n const failures: string[] = [];\n const debug: string[] = [];\n const touched = new Set<string>();\n let saved = 0;\n for (const change of queue) {\n if (change.kind === 'move') continue;\n try {\n await this.commit(change);\n saved += 1;\n touched.add(change.entityUrn);\n } catch (error) {\n if (error instanceof StoredElsewhereError) {\n saved += 1;\n touched.add(change.entityUrn);\n failures.push(`${change.name} #${change.sortOrder}: ${error.message}`);\n continue;\n }\n if (error instanceof ConflictError) {\n // Held until someone chooses which value wins.\n this.ctx.pending.set({ ...error.change, stale: true });\n failures.push(`${change.name} #${change.sortOrder}: a newer draft was saved; use Resolve.`);\n continue;\n }\n const failure = await feedback.describe(error, 'save this change');\n if (failure.kind === 'unauthorized') {\n void feedback.promptLogin(failure.message, () => void this.saveAll(entityUrn));\n break;\n }\n failures.push(`${change.name} #${change.sortOrder}: ${failure.message}`);\n if (failure.debug) debug.push(`${change.name} #${change.sortOrder}:\\n${failure.debug}`);\n }\n }\n for (const urn of touched) await this.view.refresh(urn);\n // Saved to one entity: its review is the next step.\n const [only] = touched;\n toolbar.showMessage(\n failures.length > 0 ? `Saved ${saved}. Not saved: ${failures.join(' ')}` : `Saved ${saved} ${saved === 1 ? 'change' : 'changes'}.`,\n failures.length === 0,\n debug.join('\\n\\n') || undefined,\n failures.length === 0 && saved > 0 && touched.size === 1 && only ? reviewAction(this.ctx, only) : undefined,\n );\n }\n\n /** For an edit held as \"based on an older version\": compare it with the newest draft and choose. */\n async resolve(change: PendingEdit, anchor: HTMLElement): Promise<void> {\n const entry = this.ctx.entry(change.type);\n try {\n const newest = (await this.ctx.transport.history(entry, change.urn)).history[0];\n if (newest?.urn && newest.urn !== change.urn) {\n this.showConflict(new ConflictError(change, newest), anchor);\n } else {\n // Nothing newer after all: it can be saved as it is.\n this.ctx.pending.set({ ...change, stale: false });\n }\n } catch (error) {\n void this.ctx.feedback.report(error, 'check this item', () => void this.resolve(change, anchor));\n }\n }\n\n /** Shows both values and lets the author choose; nothing is saved without a choice. */\n private showConflict(conflict: ConflictError, anchor: HTMLElement): void {\n const { popover } = this.ctx;\n const { change, newest } = conflict;\n const entry = this.ctx.entry(change.type);\n const when = newest.createdTimestamp ? new Date(parseUtc(newest.createdTimestamp)).toLocaleString() : 'recently';\n const done = () => {\n popover.hide();\n this.editing().close();\n };\n popover.showChoices(\n anchor,\n 'A newer draft was saved',\n `${change.name} #${change.sortOrder}`,\n [\n { label: 'Yours (not saved)', text: summarise(entry, change.value) },\n { label: `The newer draft, saved ${when}`, text: summarise(entry, newest) },\n ],\n 'Nothing has been saved. Choose which value to keep.',\n [\n { label: 'Cancel', run: done },\n {\n label: 'Keep theirs',\n run: () => {\n this.ctx.pending.clear(change.urn);\n done();\n void this.view.refresh(change.entityUrn);\n },\n },\n { label: 'Save yours on top', primary: true, run: () => void this.saveOnTop(conflict, done) },\n ],\n );\n }\n\n /** Saves the author's value as a new draft on top of the newest one. */\n private async saveOnTop(conflict: ConflictError, done: () => void): Promise<void> {\n const { transport, pending, sources, feedback } = this.ctx;\n const { change, newest } = conflict;\n const entry = this.ctx.entry(change.type);\n try {\n const saved = await transport.update(entry, newest.urn!, toRepresentation(entry, newest, change.value, change.entityUrn));\n pending.clear(change.urn);\n sources.delete(change.urn);\n dispatchItemUpdated({ entityUrn: change.entityUrn, oldUrn: newest.urn!, newUrn: saved.urn!, type: entry.type, value: saved });\n done();\n await this.view.refresh(change.entityUrn);\n } catch (error) {\n void feedback.report(error, 'save this change', () => void this.saveOnTop(conflict, done));\n }\n }\n\n discardAll(entityUrn?: string): void {\n this.editing().close();\n const removed = this.ctx.pending.clearAll(entityUrn);\n for (const change of removed) {\n this.view.reshow({\n entityUrn: change.entityUrn,\n entry: this.ctx.entry(change.type),\n name: change.name,\n sortOrder: change.sortOrder,\n urn: change.kind === 'edit' ? change.urn : undefined,\n });\n }\n this.ctx.toolbar.showMessage(`Discarded ${removed.length} unsaved ${removed.length === 1 ? 'change' : 'changes'}.`, true);\n }\n\n /** On a published entity a new item is live as soon as it is created, so ask first. */\n confirmCreateAll(entityUrn: string, count: number): void {\n const { store } = this.ctx;\n if (!isLive(store.view(entityUrn)?.status)) {\n void this.createAll(entityUrn);\n return;\n }\n const form = new SimpleForm(\n `${this.ctx.entityTitle(entityUrn)} is published`,\n [],\n `Create ${count} ${count === 1 ? 'item' : 'items'} on the live site`,\n () => {\n panel.close();\n void this.createAll(entityUrn);\n },\n );\n form.element.insertBefore(\n Object.assign(document.createElement('p'), {\n className: 'hint',\n textContent: 'New items on a published entity are live as soon as they are created. Check the placeholders first.',\n }),\n form.element.querySelector('.error'),\n );\n const panel = this.ctx.panels.show(form.element, { entityUrn });\n }\n\n /** Creates every empty slot of an entity shown on the page, from its placeholder. Safe to run again. */\n async createAll(entityUrn: string): Promise<void> {\n const { store, pending, feedback, toolbar } = this.ctx;\n await this.view.refresh(entityUrn); // Occupancy is checked against the latest read.\n let created = 0;\n const failures: string[] = [];\n const debug: string[] = [];\n for (const binding of this.view.missingBindings(entityUrn)) {\n const { entry } = binding;\n if (store.itemAt(entityUrn, entry, binding.name, binding.sortOrder)) continue;\n const key = createKey({ entityUrn, type: entry.type, name: binding.name, sortOrder: binding.sortOrder });\n const value = pending.getCreate(key)?.value ?? entry.fromPlaceholder?.(binding.element) ?? entry.defaults();\n if (entry.form && typeof entry.form.fromForm(entry.form.toForm(value)) === 'string') {\n failures.push(`${binding.name}: its placeholder is not a valid ${entry.label.toLowerCase()}`);\n continue;\n }\n try {\n await this.commit({ kind: 'create', type: entry.type, entityUrn, name: binding.name, sortOrder: binding.sortOrder, value });\n created += 1;\n await this.view.refresh(entityUrn);\n } catch (error) {\n const failure = await feedback.describe(error, 'create this item');\n if (failure.kind === 'unauthorized') {\n void feedback.promptLogin(failure.message, () => void this.createAll(entityUrn));\n break;\n }\n failures.push(`${binding.name}: ${failure.message}`);\n if (failure.debug) debug.push(`${binding.name}:\\n${failure.debug}`);\n }\n }\n toolbar.showMessage(\n `Created ${created} ${created === 1 ? 'item' : 'items'}.${failures.length > 0 ? ` Not created: ${failures.join(' ')}` : ''}`,\n failures.length === 0,\n debug.join('\\n\\n') || undefined,\n );\n }\n}\n\n/**\n * The API must store an item at the name and sort order sent. When it does\n * not (a create that dropped `name`), the write still happened, so this\n * reports it without leaving anything to send again.\n */\nfunction checkSlot(saved: ContentItem, sent: Pick<ContentItem, 'name' | 'sortOrder'>): void {\n if (saved.name === sent.name && saved.sortOrder === sent.sortOrder) return;\n throw new StoredElsewhereError(\n `Saved, but the API stored it as \"${saved.name ?? ''}\" #${saved.sortOrder ?? '?'} instead of ${sent.name} #${sent.sortOrder}. ` +\n 'Do not save it again; this needs fixing in the API.',\n );\n}\n\n/** The write happened, at another name or sort order than sent. */\nexport class StoredElsewhereError extends Error {}\n", "// A change between two versions: a word diff (<ins>, <del>), or a summary line\n// with a percentage change marked up or down. All of it is text, never markup.\n\nimport type { DiffPart } from '../core/diff.ts';\nimport { el } from './host.ts';\n\nconst ELEMENTS: Record<Exclude<DiffPart['kind'], 'same'>, [tag: 'ins' | 'del' | 'span', className: string]> = {\n added: ['ins', ''],\n removed: ['del', ''],\n increase: ['span', 'delta up'],\n decrease: ['span', 'delta down'],\n arrow: ['span', 'arrow'],\n};\n\nexport function renderChange(value: DiffPart[] | string): HTMLElement {\n const box = el('div', 'change');\n if (typeof value === 'string') {\n box.textContent = value;\n return box;\n }\n for (const part of value) {\n if (part.kind === 'same') {\n box.append(part.text);\n continue;\n }\n const [tag, className] = ELEMENTS[part.kind];\n const element = el(tag, className, part.text);\n if (part.kind === 'arrow') element.setAttribute('aria-label', 'to');\n if (part.kind === 'increase' || part.kind === 'decrease') element.title = `${part.text.replace(/^[+\u2212]/, '')} ${part.kind}`;\n box.append(element);\n }\n return box;\n}\n", "// An item's history as sidebar levels (docs/plans/single-sidebar.md): the\n// Item level lists its versions, newest first, each with its change and a\n// preview toggle; choosing one drills into its Version level, which shows\n// the change against the one before and against live, one above the other,\n// and the version's actions.\n\nimport type { DiffPart } from '../core/diff.ts';\nimport { renderChange } from './change.ts';\nimport { icon } from './icons.ts';\nimport { button as makeButton, el, selectBox, variantOf } from './host.ts';\n\nexport interface HistoryAction {\n label: string;\n /** A toggle, such as the preview: shown pressed. */\n pressed?: boolean;\n disabled?: string | undefined;\n primary?: boolean;\n /** Shown as a destructive button: it deletes or discards. */\n destructive?: boolean;\n run(anchor: HTMLElement): void;\n}\n\nexport interface HistoryRowModel {\n when: string;\n /** UTC, for the tooltip. */\n whenUtc: string;\n live: boolean;\n /** What changed against the comparison version. */\n change: DiffPart[] | string;\n /** \"moved from #0 to #1\", \"renamed from \u2026\". */\n notes: string[];\n /** Drills into the version's level. */\n open(): void;\n preview: HistoryAction;\n /** Earlier drafts collapsed into this row. */\n collapsed: HistoryRowModel[];\n}\n\nexport interface VersionModel {\n when: string;\n whenUtc: string;\n /** \"live\", \"latest\". */\n marks: string[];\n notes: string[];\n changes: { label: string; change: DiffPart[] | string }[];\n actions: HistoryAction[];\n}\n\n/** The Item level's body: what to compare with, the versions, and older ones on request. */\nexport class ItemHistoryView {\n readonly element: HTMLElement;\n private readonly status: HTMLElement;\n private readonly list: HTMLElement;\n private readonly more: HTMLButtonElement;\n private readonly compare: HTMLSelectElement;\n\n constructor(onMore: () => void, onCompare: (against: 'live' | 'previous') => void) {\n this.element = el('div', 'level-item');\n const compareLabel = el('label', 'field');\n this.compare = el('select');\n this.compare.append(\n Object.assign(el('option', '', 'Compare with the live version'), { value: 'live' }),\n Object.assign(el('option', '', 'Compare with the previous version'), { value: 'previous' }),\n );\n this.compare.addEventListener('change', () => onCompare(this.compare.value as 'live' | 'previous'));\n compareLabel.append(el('span', 'caption', 'Show changes'), selectBox(this.compare));\n\n this.status = el('p', 'hint');\n this.status.setAttribute('role', 'status');\n this.list = el('ol', 'rows history-rows');\n this.list.setAttribute('aria-label', 'Versions, newest first');\n this.more = el('button', '', 'Load older versions');\n this.more.type = 'button';\n this.more.hidden = true;\n this.more.addEventListener('click', onMore);\n this.element.append(compareLabel, this.status, this.list, this.more);\n }\n\n setStatus(text: string): void {\n this.status.textContent = text;\n }\n\n render(rows: HistoryRowModel[], hasMore: boolean): void {\n // Open groups of earlier drafts stay open across a refresh.\n const expanded = new Set(\n [...this.list.querySelectorAll<HTMLElement>('li.history-row:has(> button[aria-expanded=\"true\"])')].map((row) => row.dataset['when']),\n );\n this.list.replaceChildren(...rows.map((row) => this.row(row, expanded)));\n this.more.hidden = !hasMore;\n }\n\n private row(row: HistoryRowModel, expanded: Set<string | undefined>): HTMLElement {\n const item = el('li', 'row history-row');\n item.dataset['when'] = row.whenUtc;\n const head = el('button', 'row-main');\n head.type = 'button';\n head.dataset['row'] = '';\n const time = el('span', 'row-name', row.when);\n time.title = `${row.whenUtc} UTC`;\n head.append(time);\n if (row.live) head.append(el('span', 'status status-up-to-date', 'live'));\n for (const note of row.notes) head.append(el('span', 'status note', note));\n const chevron = el('span', 'stack-chevron');\n chevron.append(icon('chevron-right'));\n chevron.setAttribute('aria-hidden', 'true');\n head.append(chevron);\n head.addEventListener('click', () => row.open());\n const actions = el('div', 'actions');\n actions.append(actionButton(row.preview));\n item.append(head, renderChange(row.change), actions);\n if (row.collapsed.length > 0) {\n const toggle = makeButton(`${row.collapsed.length} earlier ${row.collapsed.length === 1 ? 'draft' : 'drafts'}`, 'ghost', 'xs');\n const open = expanded.has(row.whenUtc);\n toggle.setAttribute('aria-expanded', String(open));\n const nested = el('ol', 'rows');\n nested.hidden = !open;\n nested.append(...row.collapsed.map((inner) => this.row(inner, expanded)));\n toggle.addEventListener('click', () => {\n nested.hidden = !nested.hidden;\n toggle.setAttribute('aria-expanded', String(!nested.hidden));\n });\n item.append(toggle, nested);\n }\n return item;\n }\n}\n\n/** Fills a Version level's body, or says the version is gone. */\nexport function renderVersion(body: HTMLElement, model: VersionModel | undefined): void {\n if (!model) {\n body.replaceChildren(el('p', 'message', 'This version is no longer in the history. Go back to see the versions there are.'));\n return;\n }\n // The time is the level's title; the head adds its marks and notes.\n const head = el('p', 'version-head');\n head.title = `Saved ${model.whenUtc} UTC`;\n for (const mark of model.marks) head.append(el('span', `status ${mark === 'live' ? 'status-up-to-date' : 'note'}`, mark));\n for (const note of model.notes) head.append(el('span', 'status note', note));\n // The comparisons one above the other, not side by side, so the level keeps the sidebar's width.\n const changes = model.changes.map(({ label, change }) => {\n const section = el('div', 'field version-change');\n section.append(el('span', 'caption', label), renderChange(change));\n return section;\n });\n const actions = el('div', 'actions');\n actions.append(...model.actions.map(actionButton));\n body.replaceChildren(...(head.childElementCount > 0 ? [head] : []), ...changes, actions);\n}\n\nfunction actionButton(action: HistoryAction): HTMLButtonElement {\n const button = makeButton(action.label, variantOf(action), 'sm');\n if (action.pressed !== undefined) button.setAttribute('aria-pressed', String(action.pressed));\n if (action.disabled) {\n button.disabled = true;\n button.title = action.disabled;\n }\n button.addEventListener('click', () => action.run(button));\n return button;\n}\n", "// A tooltip: shadcn/ui's, shown above a control on hover (after a short\n// wait) and on keyboard focus, and hidden on leave, blur, a press or Escape.\n// Its text is also the control's description, so a screen reader hears it\n// without the tooltip. Not on touch, where there is no hover.\n//\n// A disabled button keeps its title for the reason it is disabled: it does\n// not take focus, and not every browser sends it pointer events.\n\nimport { el } from './host.ts';\n\nconst WAIT_MS = 400;\n\nlet count = 0;\nlet shown: { tip: HTMLElement; trigger: HTMLElement } | undefined;\nlet timer = 0;\n\n/**\n * `text` is shown and becomes the control's description. Without `text`, the tooltip shows the control's aria-label (an icon button's name).\n */\nexport function tooltip(trigger: HTMLElement, text?: string): void {\n trigger.removeAttribute('title');\n if (text !== undefined) {\n const description = el('span', 'visually-hidden', text);\n description.id = `baack-tooltip-${++count}`;\n // Beside the control: now, or once the code building it has put it on the page.\n const place = () => trigger.parentElement && !description.isConnected && trigger.after(description);\n place();\n queueMicrotask(place);\n trigger.setAttribute('aria-describedby', description.id);\n }\n const content = () => text ?? trigger.getAttribute('aria-label') ?? '';\n\n trigger.addEventListener('pointerenter', (event) => {\n if (event.pointerType === 'touch') return;\n clearTimeout(timer);\n timer = window.setTimeout(() => show(trigger, content()), shown ? 0 : WAIT_MS);\n });\n trigger.addEventListener('focus', () => {\n if (trigger.matches(':focus-visible')) show(trigger, content());\n });\n for (const type of ['pointerleave', 'blur', 'pointerdown'] as const) trigger.addEventListener(type, hide);\n trigger.addEventListener('keydown', (event) => {\n if (event.key === 'Escape' && shown?.trigger === trigger) hide();\n });\n}\n\nfunction show(trigger: HTMLElement, text: string): void {\n hide();\n if (!trigger.isConnected || trigger.getClientRects().length === 0) return;\n const tip = el('div', 'tooltip', text);\n tip.setAttribute('aria-hidden', 'true');\n (trigger.getRootNode() as ShadowRoot | Document).append(tip);\n const rect = trigger.getBoundingClientRect();\n const { width, height } = tip.getBoundingClientRect();\n const above = rect.top - height - 6;\n tip.style.top = `${above >= 8 ? above : rect.bottom + 6}px`;\n tip.style.left = `${Math.min(Math.max(8, rect.left + rect.width / 2 - width / 2), window.innerWidth - width - 8)}px`;\n shown = { tip, trigger };\n}\n\nfunction hide(): void {\n clearTimeout(timer);\n shown?.tip.remove();\n shown = undefined;\n}\n", "// One sidebar explored by drilling in (docs/plans/single-sidebar.md): a\n// navigation stack of levels. Choosing a row pushes a level, which slides in\n// from the side the sidebar is docked away from; Back pops it, returning to\n// the level above as it was (scroll and focus kept). A breadcrumb jumps up\n// several levels. Entry points can build the whole stack at once (`reset`),\n// so Back from a deep link goes to the parent.\n\nimport { button, el, type EditorHost, variantOf } from './host.ts';\nimport { icon } from './icons.ts';\nimport { tooltip } from './tooltip.ts';\n\nexport interface Level {\n /** Stable within the stack, for `popTo` and tests. */\n readonly id: string;\n readonly title: string;\n /** Built once, when the level is first shown; the level keeps it current itself. */\n render(): HTMLElement;\n /** Called each time the level becomes the one on screen (after pushing it, or coming back to it). */\n onShow?(): void;\n /** Called when the level leaves the stack. */\n dispose?(): void;\n}\n\nexport type Side = 'right' | 'left';\n\ninterface Entry {\n level: Level;\n section: HTMLElement;\n /** Where the level was scrolled to when a deeper level covered it. */\n scrollTop: number;\n /** The element that drilled in from this level, focused again on coming back. */\n origin: HTMLElement | undefined;\n}\n\nconst SIDE_KEY = 'baack-editor:side';\nconst SLIDE_MS = 150;\n/** Breadcrumbs beyond this many collapse to the root, an ellipsis and the last ones. */\nconst CRUMBS = 3;\n\nlet stacks = 0;\n\n/** Below this width the sidebar is a bottom sheet (`host.ts`). */\nconst NARROW = '(max-width: 640px)';\n\nexport class SidebarStack {\n readonly element: HTMLElement;\n private readonly back: HTMLButtonElement;\n private readonly heading: HTMLHeadingElement;\n private readonly crumbs: HTMLOListElement;\n private readonly body: HTMLElement;\n private readonly announcer: HTMLElement;\n private readonly dock: HTMLButtonElement;\n private readonly entries: Entry[] = [];\n private readonly id = `baack-stack-${(stacks += 1)}`;\n private readonly closeListeners: (() => void)[] = [];\n private toolbar: HTMLElement | undefined;\n\n constructor(host: EditorHost) {\n this.element = el('aside', 'panel side stack');\n this.element.setAttribute('aria-label', 'Editor');\n this.element.hidden = true;\n\n const bar = el('div', 'stack-bar');\n this.back = button('', 'ghost', 'sm', 'stack-back');\n this.back.addEventListener('click', () => this.pop());\n this.dock = button('', 'ghost', 'icon-sm', 'side-dock');\n this.dock.addEventListener('click', () => this.setSide(this.side === 'right' ? 'left' : 'right'));\n const close = button('', 'ghost', 'icon-sm', 'stack-close');\n close.setAttribute('aria-label', 'Close');\n close.append(icon('x'));\n close.addEventListener('click', () => this.close());\n bar.append(this.back, el('span', 'stack-spacer'), this.dock, close);\n tooltip(this.dock);\n tooltip(close);\n\n const nav = el('nav', 'stack-crumbs');\n nav.setAttribute('aria-label', 'Where you are');\n this.crumbs = el('ol');\n nav.append(this.crumbs);\n this.heading = el('h2', 'stack-title');\n this.heading.id = `${this.id}-title`;\n this.heading.tabIndex = -1;\n this.body = el('div', 'stack-body');\n this.announcer = el('p', 'visually-hidden');\n this.announcer.setAttribute('aria-live', 'polite');\n\n this.element.append(bar, nav, this.heading, this.body, this.announcer);\n this.element.addEventListener('keydown', this.onKeyDown);\n this.setSide(readSide());\n host.root.append(this.element);\n }\n\n /**\n * Keeps clear of the editor's toolbar (bottom right), whose height changes\n * with its messages: docked on its side, or as a bottom sheet, the sidebar\n * ends just above it.\n */\n avoid(toolbar: HTMLElement): void {\n this.toolbar = toolbar;\n new ResizeObserver(() => this.fit()).observe(toolbar);\n window.addEventListener('resize', () => this.fit());\n this.fit();\n }\n\n /** Runs when the sidebar is closed (its Close, Escape from the top level). */\n onClose(listener: () => void): void {\n this.closeListeners.push(listener);\n }\n\n private fit(): void {\n const top = this.toolbar?.getBoundingClientRect().top;\n const above = (this.side === 'right' || matchMedia(NARROW).matches) && top !== undefined;\n this.element.style.bottom = above ? `${Math.max(16, window.innerHeight - top + 8)}px` : '';\n }\n\n /** The level on screen. */\n get current(): Level | undefined {\n return this.entries.at(-1)?.level;\n }\n\n /** The ids of the levels, root first. */\n get path(): string[] {\n return this.entries.map((entry) => entry.level.id);\n }\n\n get isOpen(): boolean {\n return !this.element.hidden;\n }\n\n /** Drills into a level from the current one. `focus: false` leaves focus where it is (progress shown while working elsewhere). */\n push(level: Level, { focus = true } = {}): void {\n const from = this.entries.at(-1);\n if (from) {\n from.scrollTop = this.body.scrollTop;\n from.origin = this.focusedIn(from.section);\n }\n const entry = this.enter(level);\n this.entries.push(entry);\n this.show(entry, from, 'in', focus);\n }\n\n /** Back one level; from the root, closes the sidebar. */\n pop(): void {\n if (this.entries.length <= 1) {\n this.close();\n return;\n }\n this.popTo(this.entries.at(-2)!.level.id);\n }\n\n /** Back to the level with this id, leaving every level above it. */\n popTo(id: string): void {\n const index = this.entries.findIndex((entry) => entry.level.id === id);\n if (index < 0 || index === this.entries.length - 1) return;\n const from = this.entries.at(-1)!;\n for (const left of this.entries.splice(index + 1)) this.leave(left, left === from);\n this.show(this.entries[index]!, from, 'out');\n }\n\n /** Replaces the level on screen, as after finishing a task that changed what it showed. */\n replace(level: Level, { focus = true } = {}): void {\n const from = this.entries.pop();\n if (from) this.leave(from, false);\n const entry = this.enter(level);\n this.entries.push(entry);\n this.show(entry, undefined, 'none', focus);\n }\n\n /** Builds the whole stack at once (a deep link), showing the last level and opening the sidebar. */\n reset(levels: readonly Level[], { focus = true } = {}): void {\n for (const left of this.entries.splice(0)) this.leave(left, false);\n for (const level of levels) this.entries.push(this.enter(level));\n const top = this.entries.at(-1);\n if (top) this.show(top, undefined, 'none', focus);\n }\n\n open(): void {\n this.element.hidden = false;\n }\n\n /** Hides the sidebar, keeping its levels for next time. */\n close(): void {\n if (this.element.hidden) return;\n this.element.hidden = true;\n for (const listener of this.closeListeners) listener();\n }\n\n get side(): Side {\n return this.element.dataset['side'] === 'left' ? 'left' : 'right';\n }\n\n /** Docks the sidebar on one side of the page, remembered in this browser. */\n setSide(side: Side): void {\n this.element.dataset['side'] = side;\n this.dock.setAttribute('aria-label', side === 'right' ? 'Move to left' : 'Move to right');\n this.dock.replaceChildren(icon(side === 'right' ? 'panel-left' : 'panel-right'));\n this.fit();\n try {\n localStorage.setItem(SIDE_KEY, side);\n } catch {\n // Storage can be blocked; the sidebar still docks for this visit.\n }\n }\n\n private enter(level: Level): Entry {\n const section = el('section', 'stack-level');\n section.dataset['level'] = level.id;\n section.setAttribute('aria-labelledby', this.heading.id);\n section.hidden = true;\n section.append(level.render());\n this.body.append(section);\n return { level, section, scrollTop: 0, origin: undefined };\n }\n\n private leave(entry: Entry, animated: boolean): void {\n entry.level.dispose?.();\n // A level sliding out stays until its animation ends.\n if (!animated || !this.animates()) entry.section.remove();\n }\n\n private show(entry: Entry, from: Entry | undefined, direction: 'in' | 'out' | 'none', focus = true): void {\n this.element.hidden = false;\n for (const other of this.entries) other.section.hidden = other !== entry;\n entry.section.hidden = false;\n this.renderHeader();\n this.body.scrollTop = direction === 'out' ? entry.scrollTop : 0;\n if (from && direction !== 'none') this.slide(entry.section, from.section, direction);\n entry.level.onShow?.();\n this.announcer.textContent = entry.level.title;\n // Coming back: the row that drilled in. Going in: the new level's heading.\n const origin = direction === 'out' && entry.origin?.isConnected ? entry.origin : undefined;\n if (focus) (origin ?? this.heading).focus({ preventScroll: direction === 'out' });\n }\n\n private renderHeader(): void {\n const current = this.entries.at(-1)!.level;\n const parent = this.entries.at(-2)?.level;\n this.heading.textContent = current.title;\n this.back.hidden = !parent;\n this.back.replaceChildren(...(parent ? [icon('chevron-left'), el('span', 'stack-back-text', parent.title)] : []));\n this.back.setAttribute('aria-label', parent ? `Back to ${parent.title}` : 'Back');\n\n const items = this.entries.map((entry, index) => ({ entry, index }));\n const shown =\n items.length > CRUMBS + 1 ? [items[0]!, undefined, ...items.slice(items.length - (CRUMBS - 1))] : items;\n this.crumbs.replaceChildren(\n ...shown.flatMap((item, position) => {\n // Between crumbs, a chevron that is not read out.\n const separator = el('li', 'stack-crumb-separator');\n separator.setAttribute('role', 'presentation');\n separator.setAttribute('aria-hidden', 'true');\n separator.append(icon('chevron-right'));\n const li = el('li');\n const crumb = (content: HTMLElement) => {\n li.append(content);\n return position === 0 ? [li] : [separator, li];\n };\n if (!item) return crumb(el('span', 'meta', '\u2026'));\n if (item.index === this.entries.length - 1) {\n const here = el('span', '', item.entry.level.title);\n here.setAttribute('aria-current', 'page');\n return crumb(here);\n }\n const jump = el('button', 'stack-crumb', item.entry.level.title);\n jump.type = 'button';\n jump.addEventListener('click', () => this.popTo(item.entry.level.id));\n return crumb(jump);\n }),\n );\n // A single level has nowhere to go back to: no breadcrumb.\n (this.crumbs.parentElement as HTMLElement).hidden = this.entries.length < 2;\n }\n\n private animates(): boolean {\n return typeof Element.prototype.animate === 'function' && !matchMedia('(prefers-reduced-motion: reduce)').matches;\n }\n\n /** Slides `to` in over `from` (drilling in), or `from` out to reveal `to` (Back). */\n private slide(to: HTMLElement, from: HTMLElement, direction: 'in' | 'out'): void {\n if (!this.animates()) return;\n // Deeper levels come from the far side: the right when docked right, the left when docked left.\n const away = this.side === 'right' ? '100%' : '-100%';\n const options: KeyframeAnimationOptions = { duration: SLIDE_MS, easing: 'ease-out' };\n if (direction === 'in') {\n to.animate([{ transform: `translateX(${away})` }, { transform: 'none' }], options);\n return;\n }\n // The level going out is drawn over the one coming back until it has slid away.\n // Only drawn: out of the accessibility tree and unreachable, so it never reads as the level on screen.\n from.hidden = false;\n from.inert = true;\n from.setAttribute('aria-hidden', 'true');\n from.classList.add('leaving');\n from.style.top = `${this.body.scrollTop}px`;\n const animation = from.animate([{ transform: 'none' }, { transform: `translateX(${away})` }], options);\n animation.finished.then(\n () => from.remove(),\n () => from.remove(),\n );\n }\n\n private focusedIn(section: HTMLElement): HTMLElement | undefined {\n const active = (this.element.getRootNode() as ShadowRoot).activeElement;\n return active instanceof HTMLElement && section.contains(active) ? active : undefined;\n }\n\n private readonly onKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape' && !event.defaultPrevented) {\n event.preventDefault();\n event.stopPropagation();\n this.pop();\n return;\n }\n if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') return;\n // Rows (`[data-row]`) in the level on screen: arrows move between them.\n const section = this.entries.at(-1)?.section;\n const active = section && this.focusedIn(section);\n if (!section || !active?.matches('[data-row]')) return;\n const rows = [...section.querySelectorAll<HTMLElement>('[data-row]')].filter((row) => !row.closest('[hidden]'));\n const next = rows[rows.indexOf(active) + (event.key === 'ArrowDown' ? 1 : -1)];\n if (!next) return;\n event.preventDefault();\n next.focus();\n };\n}\n\nfunction readSide(): Side {\n try {\n return localStorage.getItem(SIDE_KEY) === 'left' ? 'left' : 'right';\n } catch {\n return 'right';\n }\n}\n\n/**\n * A row that drills into a level: a full-width button with a label, an\n * optional detail line, and a chevron. Arrow keys move between rows.\n */\nexport function drillRow(label: string, detail: string, open: () => void): HTMLButtonElement {\n const row = el('button', 'stack-row');\n row.type = 'button';\n row.dataset['row'] = '';\n const text = el('span', 'stack-row-text');\n text.append(el('span', 'stack-row-label', label));\n if (detail) text.append(el('span', 'meta', detail));\n const chevron = el('span', 'stack-chevron');\n chevron.append(icon('chevron-right'));\n row.append(text, chevron);\n row.addEventListener('click', open);\n return row;\n}\n\nexport interface Choice {\n label: string;\n primary?: boolean;\n /** Shown as a destructive button: it deletes or discards. */\n destructive?: boolean;\n /** Gets the button, to disable it while the choice runs. */\n run(button: HTMLButtonElement): void;\n}\n\n/**\n * A confirm as a level (forms and confirms are the deepest level, so they\n * never cover what they are about): what it is about, the values concerned,\n * what happens, then the choices. Cancel is a choice that goes Back.\n */\nexport function confirmLevel(options: {\n id: string;\n title: string;\n meta: string;\n blocks: { label: string; text: string }[];\n description: string;\n choices: Choice[];\n}): Level {\n const body = el('div', 'level-confirm');\n body.append(el('p', 'meta', options.meta));\n for (const block of options.blocks) {\n const box = el('div', 'field');\n box.append(el('span', 'caption', block.label), el('pre', 'snippet', block.text));\n body.append(box);\n }\n body.append(el('p', 'description', options.description));\n const actions = el('div', 'actions');\n for (const choice of options.choices) {\n const choiceButton = button(choice.label, variantOf(choice));\n choiceButton.addEventListener('click', () => choice.run(choiceButton));\n actions.append(choiceButton);\n }\n body.append(actions);\n return { id: options.id, title: options.title, render: () => body };\n}\n", "// An item's history: its versions, what each changed, and the actions on a\n// version. \"Publish this version\" moves the live pointer (no new version);\n// \"Edit from this version\" saves a new draft based on it; \"Preview on the\n// page\" only shows it in place, sending nothing.\n//\n// It is explored in the sidebar (docs/plans/single-sidebar.md): the Item\n// level lists the versions, a Version level shows one with its actions, and\n// deleting one confirms in a level above that.\n\nimport { parseTimestamp } from '@baack-software/baack-ts-components/format';\nimport { diffWords, type DiffPart } from './core/diff.ts';\nimport { dispatchItemPublished } from './core/events.ts';\nimport type { ContentItem, TypeEntry } from './core/registry.ts';\nimport type { Editing } from './editing.ts';\nimport { summarise, summariseChange } from './saving.ts';\nimport { isLive, type EditorContext, type Slot } from './targets.ts';\nimport { el } from './ui/host.ts';\nimport { ItemHistoryView, renderVersion, type HistoryAction, type HistoryRowModel, type VersionModel } from './ui/history-view.ts';\nimport { confirmLevel, type Level, type SidebarStack } from './ui/stack.ts';\nimport type { PageView } from './view.ts';\n\n/** Drafts saved within this long of each other collapse into one row. */\nconst COLLAPSE_MS = 10 * 60 * 1000;\n\ninterface Open extends Slot {\n urn: string;\n versions: ContentItem[];\n live: ContentItem | undefined;\n after: string | undefined;\n against: 'live' | 'previous';\n linked: boolean;\n level: Level;\n view: ItemHistoryView;\n /** The Version level on screen above the item's, if any. */\n version: { urn: string; body: HTMLElement } | undefined;\n}\n\nexport interface HistoryHooks {\n /** A linked version publishes with its entity: open the publish dialog. */\n publishEntity(entityUrn: string): void;\n /** After a version was published: re-read the entity and its status. */\n published(entityUrn: string): Promise<void>;\n /** Shows an item's level in the sidebar, above its entity's level. */\n show(level: Level, entityUrn: string): void;\n}\n\nexport class History {\n private readonly stack: SidebarStack;\n private readonly ctx: EditorContext;\n private readonly editing: Editing;\n private readonly view: PageView;\n private readonly hooks: HistoryHooks;\n private state: Open | undefined;\n\n constructor(ctx: EditorContext, editing: Editing, view: PageView, stack: SidebarStack, hooks: HistoryHooks) {\n this.ctx = ctx;\n this.editing = editing;\n this.view = view;\n this.stack = stack;\n this.hooks = hooks;\n view.onPreviewChange(() => this.render());\n }\n\n /** Opens the item's level in the sidebar (from the popover, or a row on its entity's level). */\n async open(slot: Slot & { urn: string }): Promise<void> {\n // Another item's history: its preview ends.\n if (this.state && !sameItem(this.state, slot)) this.stopPreview();\n const itemView = new ItemHistoryView(\n () => void this.loadMore(),\n (against) => {\n if (this.state !== state) return;\n state.against = against;\n this.render();\n },\n );\n const level: Level = {\n id: itemLevelId(slot),\n title: `${slot.name} #${slot.sortOrder}`,\n render: () => itemView.element,\n // The level left the stack (Back past it, or another deep link): its preview ends with it.\n dispose: () => {\n if (this.state !== state) return;\n this.stopPreview();\n this.state = undefined;\n },\n };\n const state: Open = { ...slot, versions: [], live: undefined, after: undefined, against: 'live', linked: false, level, view: itemView, version: undefined };\n // Set before showing, so the level it replaces does not end a preview of the same item.\n this.state = state;\n this.hooks.show(level, slot.entityUrn);\n itemView.setStatus('Loading\u2026');\n state.linked = await this.isLinked(slot);\n if (this.state === state) await this.loadMore();\n }\n\n /** Ends the preview and forgets the item (leaving a read mode). */\n close(): void {\n this.stopPreview();\n this.state = undefined;\n }\n\n /** Ends a preview of a version, if one is shown. */\n stopPreview(): void {\n if (this.state && this.view.previewedUrn) {\n this.view.stopPreview(this.state);\n this.ctx.toolbar.showMessage('');\n }\n }\n\n /** Shows a version on the page in place of the latest, or stops showing it. Sends nothing. */\n private togglePreview(state: Open, version: ContentItem): void {\n if (this.view.previewedUrn === version.urn) {\n this.stopPreview();\n return;\n }\n // The element may be open for editing (History opens from its popover): close it, keeping any unsaved edit.\n this.editing.close();\n this.view.previewVersion(state, version);\n // The selection from opening the editor would cover the previewed value.\n const selection = window.getSelection();\n const shown = this.view.bindingsAt(state).map((binding) => binding.element);\n if (selection?.anchorNode && shown.some((element) => element.contains(selection.anchorNode))) selection.removeAllRanges();\n this.view.bindingsAt(state)[0]?.element.scrollIntoView({ block: 'nearest', behavior: 'smooth' });\n const when = new Date(parseTimestamp(version.createdTimestamp ?? '')).toLocaleString();\n this.ctx.toolbar.showMessage(`Previewing the version of ${state.name} saved ${when}. Nothing is saved; stop the preview to see the latest again.`, true);\n }\n\n /** Content changed (a save, a publish): reload if this entity's history is open. */\n changed(entityUrn?: string): void {\n const state = this.state;\n if (!state || (entityUrn && entityUrn !== state.entityUrn)) return;\n // Follow the item to its newest version.\n const current = this.ctx.store.itemAt(state.entityUrn, state.entry, state.name, state.sortOrder);\n if (current?.item.urn) state.urn = current.item.urn;\n void this.reload(state);\n }\n\n /** Reads the history again from its newest page, keeping the levels on screen. */\n private async reload(state: Open): Promise<void> {\n try {\n const page = await this.ctx.transport.history(state.entry, state.urn);\n if (this.state !== state) return;\n state.live = page.item ?? undefined;\n state.versions = [...page.history];\n state.after = page.pagination?.isMorePages ? page.pagination.after ?? undefined : undefined;\n this.render();\n } catch (error) {\n void this.ctx.feedback.report(error, 'load the history', () => void this.reload(state));\n }\n }\n\n private async loadMore(): Promise<void> {\n const state = this.state;\n if (!state) return;\n try {\n const page = await this.ctx.transport.history(state.entry, state.urn, state.after);\n if (this.state !== state) return;\n state.live ??= page.item ?? undefined;\n state.versions.push(...page.history);\n state.after = page.pagination?.isMorePages ? page.pagination.after ?? undefined : undefined;\n state.view.setStatus('');\n this.render();\n } catch (error) {\n state.view.setStatus('');\n void this.ctx.feedback.report(error, 'load the history', () => void this.loadMore());\n }\n }\n\n private render(): void {\n const state = this.state;\n if (!state) return;\n const rows = state.versions.map((version, index) => this.row(state, version, state.versions[index + 1]));\n // Collapse a run of drafts saved close together into its newest; the live version always shows.\n const grouped: HistoryRowModel[] = [];\n let groupTime: number | undefined;\n state.versions.forEach((version, index) => {\n const time = parseTimestamp(version.createdTimestamp ?? '');\n const head = grouped.at(-1);\n const live = version.isPublished === true;\n if (head && !live && !head.live && groupTime !== undefined && groupTime - time <= COLLAPSE_MS) {\n head.collapsed.push(rows[index]!);\n } else {\n grouped.push(rows[index]!);\n }\n groupTime = time;\n });\n state.view.render(grouped, state.after !== undefined);\n if (state.version && this.stack.path.includes(versionLevelId(state.version.urn))) {\n renderVersion(state.version.body, this.versionModel(state, state.version.urn));\n }\n }\n\n private row(state: Open, version: ContentItem, previous: ContentItem | undefined): HistoryRowModel {\n const against = state.against === 'live' ? state.live : previous;\n return {\n when: when(version),\n whenUtc: version.createdTimestamp ?? '',\n live: version.isPublished === true,\n change: describe(state.entry, version, against, state.against),\n notes: this.notes(version, previous),\n open: () => this.openVersion(state, version),\n preview: this.previewAction(state, version),\n collapsed: [],\n };\n }\n\n private notes(version: ContentItem, previous: ContentItem | undefined): string[] {\n const notes: string[] = [];\n if (previous && previous.name !== version.name) notes.push(`renamed from ${previous.name}`);\n if (previous && previous.sortOrder !== version.sortOrder) notes.push(`moved from #${previous.sortOrder} to #${version.sortOrder}`);\n const group = version.urn ? this.ctx.groups?.of(version.urn) : undefined;\n if (group) notes.push(`part of: ${group.label}`);\n return notes;\n }\n\n /** Drills into one version: both comparisons, and what can be done with it. */\n private openVersion(state: Open, version: ContentItem): void {\n const urn = version.urn!;\n const body = el('div', 'level-version');\n state.version = { urn, body };\n renderVersion(body, this.versionModel(state, urn));\n this.stack.push({\n id: versionLevelId(urn),\n title: `Version saved ${when(version)}`,\n render: () => body,\n dispose: () => {\n if (state.version?.urn === urn) state.version = undefined;\n },\n });\n }\n\n /** The version's level, from the history as last read; undefined once it is gone. */\n private versionModel(state: Open, urn: string): VersionModel | undefined {\n const index = state.versions.findIndex((version) => version.urn === urn);\n const version = state.versions[index];\n if (!version) return undefined;\n const previous = state.versions[index + 1];\n const marks = [...(version.isPublished === true ? ['live'] : []), ...(index === 0 ? ['latest'] : [])];\n // One comparison when the one before is the live version; none against live for the live version itself.\n const beforeIsLive = previous !== undefined && previous.urn === state.live?.urn;\n const changes = [\n {\n label: beforeIsLive ? 'Against the one before, which is live' : 'Against the one before',\n change: describe(state.entry, version, previous, 'previous') || 'The same value as the one before.',\n },\n ];\n if (version.isPublished !== true && !beforeIsLive) changes.push({ label: 'Against live', change: describe(state.entry, version, state.live, 'live') });\n return { when: when(version), whenUtc: version.createdTimestamp ?? '', marks, notes: this.notes(version, previous), changes, actions: this.actions(state, version) };\n }\n\n private actions(state: Open, version: ContentItem): HistoryAction[] {\n const { ctx } = this;\n const actions: HistoryAction[] = [];\n const status = ctx.store.view(state.entityUrn)?.status;\n // Item publish only means something on a live entity, and needs the publish permission.\n if (ctx.canPublish && version.isPublished !== true && (isLive(status) || status === 'PUBLISH')) {\n const busy = status === 'PUBLISH' ? 'Publishing is in progress for this page.' : undefined;\n // Half of a swap or reorder must not go live alone.\n const grouped = ctx.groups?.of(version.urn!) !== undefined;\n actions.push(\n state.linked || grouped\n ? { label: 'Publish with the page\u2026', disabled: busy, run: () => this.hooks.publishEntity(state.entityUrn) }\n : { label: 'Publish this version', primary: true, disabled: busy, run: () => void this.publish(state, version) },\n );\n }\n actions.push(this.previewAction(state, version));\n if (version !== state.versions[0]) {\n actions.push({ label: 'Edit from this version', run: (anchor) => this.editFrom(state, version, anchor) });\n }\n // One revision at a time. Whether it is allowed (the delete permission on the item, its\n // entity, or admin on the owner) is the API's decision; the client cannot see it.\n // Deleting an item's only version deletes the item, live or not; deleting the live\n // version puts another live in its place (see `successor`).\n const onlyVersion = state.versions.length === 1 && state.after === undefined;\n actions.push({\n label: onlyVersion ? 'Delete this item\u2026' : 'Delete this version\u2026',\n destructive: true,\n run: () => this.confirmDelete(state, version, onlyVersion),\n });\n return actions;\n }\n\n private previewAction(state: Open, version: ContentItem): HistoryAction {\n const previewing = this.view.previewedUrn === version.urn;\n const current = this.ctx.store.itemAt(state.entityUrn, state.entry, state.name, state.sortOrder)?.item.urn;\n const disabled = state.entry.renderedByView\n ? 'The page shows the server\\'s rendering of this type, which history does not include.'\n : this.view.mode !== 'LATEST'\n ? 'Previews are shown on the latest drafts.'\n : this.view.bindingsAt(state).length === 0\n ? 'This item is not shown on this page.'\n : version.urn === current && !this.ctx.pending.getEdit(version.urn!)\n ? 'The page already shows this version.'\n : undefined;\n return {\n label: previewing ? 'Stop preview' : 'Preview on the page',\n pressed: previewing,\n disabled: previewing ? undefined : disabled,\n run: () => this.togglePreview(state, version),\n };\n }\n\n /** Deleting a revision (or, with its only version, the item) is permanent, so it asks first. */\n private confirmDelete(state: Open, version: ContentItem, wholeItem: boolean): void {\n const when = new Date(parseTimestamp(version.createdTimestamp ?? '')).toLocaleString();\n const where = version.isPublished === true ? 'from this page and from the live site' : 'from this page';\n const blocks = [{ label: `The version saved ${when}`, text: summarise(state.entry, version) }];\n let description = wholeItem\n ? `This is its only version, so deleting it deletes the item: it disappears ${where}, and cannot be restored.`\n : 'It is removed from the history for good and cannot be restored. Every version uses storage, which is billed.';\n const next = !wholeItem && version.isPublished === true ? successor(state, version) : undefined;\n if (next) {\n const nextWhen = new Date(parseTimestamp(next.version?.createdTimestamp ?? '')).toLocaleString();\n if (next.version) {\n blocks.push({ label: `Goes live in its place: the version saved ${nextWhen}`, text: summarise(state.entry, next.version) });\n }\n description =\n next.newer\n ? `This is the live version. The API puts the next newer version live in its place: a draft saved ${nextWhen}, which may never have been published. Publish the version you want first if that is not it. It cannot be restored.`\n : next.version\n ? `This is the live version. The API puts the version before it live in its place (saved ${nextWhen}). It cannot be restored.`\n : 'This is the live version. The API puts the version before it live in its place. It cannot be restored.';\n }\n this.stack.push(\n confirmLevel({\n id: 'confirm-delete',\n title: wholeItem ? 'Delete this item permanently?' : next ? 'Delete the live version permanently?' : 'Delete this version permanently?',\n meta: `${state.name} #${state.sortOrder}`,\n blocks,\n description,\n choices: [\n { label: 'Cancel', run: () => this.stack.pop() },\n {\n label: 'Delete permanently',\n destructive: true,\n run: (button) => {\n button.disabled = true;\n button.textContent = 'Deleting\u2026';\n void this.deleteVersion(state, version).finally(() => {\n button.disabled = false;\n button.textContent = 'Delete permanently';\n });\n },\n },\n ],\n }),\n );\n }\n\n private async deleteVersion(state: Open, version: ContentItem): Promise<void> {\n const { transport, pending, toolbar, feedback } = this.ctx;\n // Known before the delete: which version the API will put live in its place.\n const promoted = version.isPublished === true ? successor(state, version).version : undefined;\n try {\n await transport.remove(state.entry, version.urn!);\n if (promoted?.urn) dispatchItemPublished({ entityUrn: state.entityUrn, urn: promoted.urn, type: state.entry.type });\n const remaining = state.versions.find((other) => other.urn !== version.urn);\n const edit = pending.getEdit(version.urn!);\n if (!remaining?.urn) {\n // That was its only version: the item is gone, and so is anything to save against it.\n if (edit) pending.clear(version.urn!);\n this.close();\n this.stack.popTo(`entity:${state.entityUrn}`);\n toolbar.showMessage(`Deleted ${state.name} #${state.sortOrder}.`, true);\n await this.hooks.published(state.entityUrn);\n return;\n }\n // An unsaved edit based on the deleted version can no longer be saved as it was.\n if (edit) pending.set({ ...edit, stale: true });\n toolbar.showMessage(`Deleted the version of ${state.name} saved ${new Date(parseTimestamp(version.createdTimestamp ?? '')).toLocaleString()}.`, true);\n // Back to the versions there are. The page may have shown that version: re-read, and the history follows the item.\n if (this.state === state) this.stack.popTo(state.level.id);\n state.urn = remaining.urn;\n await this.hooks.published(state.entityUrn);\n if (this.state === state) await this.reload(state);\n } catch (error) {\n void feedback.report(error, 'delete this version', () => void this.deleteVersion(state, version));\n }\n }\n\n private async publish(state: Open, version: ContentItem): Promise<void> {\n try {\n await this.ctx.transport.publishVersion(state.entry, version);\n dispatchItemPublished({ entityUrn: state.entityUrn, urn: version.urn!, type: state.entry.type });\n this.ctx.announcePublished(state.entityUrn, `Published the version of ${state.name} saved ${new Date(parseTimestamp(version.createdTimestamp ?? '')).toLocaleString()}.`, { itemUrn: version.urn! });\n await this.hooks.published(state.entityUrn);\n } catch (error) {\n void this.ctx.feedback.report(error, 'publish this version', () => void this.publish(state, version));\n }\n }\n\n private editFrom(state: Open, version: ContentItem, anchor: HTMLElement): void {\n this.ctx.store.remember(state.entityUrn, state.entry, version);\n this.editing.open({\n entityUrn: state.entityUrn,\n entry: state.entry,\n name: version.name,\n sortOrder: version.sortOrder,\n urn: version.urn,\n anchor,\n binding: undefined,\n fromVersion: true,\n });\n }\n\n /**\n * Linked items publish with their entity: templates, and items a template\n * on the same entity uses (the view does not expose references, so the\n * template sources are scanned).\n */\n private async isLinked(slot: Slot): Promise<boolean> {\n if (slot.entry.type === 'template') return true;\n const { store, sources, transport } = this.ctx;\n const templates = (store.view(slot.entityUrn)?.raw.templates ?? []) as ContentItem[];\n const template = this.ctx.entry('template');\n const pattern = new RegExp(`\\\\$\\\\{?${slot.name.replace(/[^\\w-]/g, '')}\\\\b`);\n for (const item of templates) {\n if (!item.urn) continue;\n try {\n const source = sources.get(item.urn) ?? { value: (await transport.read(template, item.urn) as { value?: unknown }).value };\n sources.set(item.urn, source);\n if (pattern.test(String((source as { value?: unknown }).value ?? ''))) return true;\n } catch {\n // Unreadable template: assume not linked; the entity publish dialog remains available.\n }\n }\n return false;\n }\n}\n\nfunction describe(entry: TypeEntry, version: ContentItem, against: ContentItem | undefined, mode: 'live' | 'previous'): DiffPart[] | string {\n if (!against) return mode === 'live' ? 'Nothing is live yet.' : 'The first version.';\n if (against.urn === version.urn) return mode === 'live' ? 'This is the live version.' : '';\n const before = (against as { value?: unknown }).value;\n const after = (version as { value?: unknown }).value;\n if (typeof before === 'string' && typeof after === 'string') return diffWords(before, after);\n const was = summarise(entry, against);\n const now = summarise(entry, version);\n if (was === now) return 'No change to the value.';\n return summariseChange(entry, against, version);\n}\n\nfunction when(version: ContentItem): string {\n const time = parseTimestamp(version.createdTimestamp ?? '');\n return Number.isNaN(time) ? 'Unknown time' : new Date(time).toLocaleString();\n}\n\nfunction itemLevelId(slot: Slot): string {\n return `item:${slot.entityUrn}:${slot.entry.type}:${slot.name}:${slot.sortOrder}`;\n}\n\nfunction versionLevelId(urn: string): string {\n return `version:${urn}`;\n}\n\nfunction sameItem(a: Slot, b: Slot): boolean {\n return a.entityUrn === b.entityUrn && a.entry === b.entry && a.name === b.name && a.sortOrder === b.sortOrder;\n}\n\n/**\n * The version the API makes live when the live version is deleted: the next\n * newer version if there is one, otherwise the one before it. `version` is\n * undefined when the one before is on a page of history not loaded yet.\n */\nfunction successor(state: Open, live: ContentItem): { version: ContentItem | undefined; newer: boolean } {\n const index = state.versions.indexOf(live);\n // Newest first: the next newer version is the one above.\n if (index > 0) return { version: state.versions[index - 1], newer: true };\n return { version: state.versions[index + 1], newer: false };\n}\n", "// Sort order arithmetic for moves and inserts. Sort orders are stored values,\n// not positions: lists can be sparse, and values are never renumbered beyond\n// what a move needs (docs/editor-v2-plan.md section 10.1).\n\nexport interface Placed {\n /** Identifies the item (a version URN). */\n key: string;\n sortOrder: number;\n}\n\nexport interface SortChange {\n key: string;\n from: number;\n to: number;\n}\n\n/**\n * Applies a new order to a list by reusing its existing sort order values in\n * ascending order, so only items whose value must change are moved and the\n * list's spacing is kept. A swap of two neighbours is two changes.\n */\nexport function reorder(items: readonly Placed[], newOrder: readonly string[]): SortChange[] {\n const values = items.map((item) => item.sortOrder).sort((a, b) => a - b);\n const byKey = new Map(items.map((item) => [item.key, item]));\n if (newOrder.length !== items.length || newOrder.some((key) => !byKey.has(key))) {\n throw new Error('The new order must contain exactly the items of the list');\n }\n const changes: SortChange[] = [];\n newOrder.forEach((key, index) => {\n const item = byKey.get(key)!;\n const to = values[index]!;\n if (item.sortOrder !== to) changes.push({ key, from: item.sortOrder, to });\n });\n return changes;\n}\n\nexport type InsertAt = { position: 'head' } | { position: 'tail' } | { position: 'after'; key: string };\n\nexport interface InsertPlan {\n /** The sort order the new item takes. */\n sortOrder: number;\n /** Items that must move first to make room (one operation). */\n shifts: SortChange[];\n}\n\n/**\n * Picks a free sort order for a new item: below the head, above the tail,\n * or between two neighbours. When neighbours are adjacent integers, the\n * shorter side shifts by one to make room; nothing else moves.\n */\nexport function planInsert(items: readonly Placed[], at: InsertAt): InsertPlan {\n const sorted = [...items].sort((a, b) => a.sortOrder - b.sortOrder);\n if (sorted.length === 0) return { sortOrder: 0, shifts: [] };\n if (at.position === 'head') return { sortOrder: sorted[0]!.sortOrder - 1, shifts: [] };\n if (at.position === 'tail') return { sortOrder: sorted.at(-1)!.sortOrder + 1, shifts: [] };\n\n const index = sorted.findIndex((item) => item.key === at.key);\n if (index < 0) throw new Error('The item to insert after is not in the list');\n const before = sorted[index]!;\n const after = sorted[index + 1];\n if (!after) return { sortOrder: before.sortOrder + 1, shifts: [] };\n if (after.sortOrder - before.sortOrder > 1) {\n return { sortOrder: Math.floor((before.sortOrder + after.sortOrder) / 2), shifts: [] };\n }\n\n // Adjacent: shift the shorter side outwards by one, starting from the far end so no value is shared longer than needed.\n const left = sorted.slice(0, index + 1);\n const right = sorted.slice(index + 1);\n if (right.length <= left.length) {\n return {\n sortOrder: after.sortOrder,\n shifts: [...shiftRun(right, +1)].reverse(),\n };\n }\n return {\n sortOrder: before.sortOrder,\n shifts: shiftRun([...left].reverse(), -1).reverse(),\n };\n}\n\n/**\n * Moves a run of items by one in a direction, but only as far as needed: the\n * run stops at the first gap. `run` starts next to the freed slot.\n */\nfunction shiftRun(run: readonly Placed[], step: 1 | -1): SortChange[] {\n const changes: SortChange[] = [];\n for (const [index, item] of run.entries()) {\n // Keep going only while the item sits where the previous one is moving to.\n if (index > 0 && item.sortOrder !== changes.at(-1)!.to) break; // A gap: the rest can stay.\n changes.push({ key: item.key, from: item.sortOrder, to: item.sortOrder + step });\n }\n return changes;\n}\n\n/** Exchanges two items' sort orders. */\nexport function swap(a: Placed, b: Placed): SortChange[] {\n return [\n { key: a.key, from: a.sortOrder, to: b.sortOrder },\n { key: b.key, from: b.sortOrder, to: a.sortOrder },\n ];\n}\n", "// Which templates on an entity use an item name. The entity view does not\n// expose template references (open question 18), so template sources are\n// read and scanned for `$name` and `${name}`.\n\nimport type { ContentItem } from './core/registry.ts';\nimport type { EditorContext } from './targets.ts';\n\nexport async function templatesUsing(ctx: EditorContext, entityUrn: string, name: string): Promise<string[]> {\n const { store, sources, transport } = ctx;\n const template = ctx.entry('template');\n const pattern = new RegExp(`\\\\$\\\\{?${name.replace(/[^\\w-]/g, '')}\\\\b`);\n const users: string[] = [];\n for (const item of (store.view(entityUrn)?.raw.templates ?? []) as ContentItem[]) {\n if (!item.urn) continue;\n try {\n const source = sources.get(item.urn) ?? { value: ((await transport.read(template, item.urn)) as { value?: unknown }).value };\n sources.set(item.urn, source);\n if (pattern.test(String((source as { value?: unknown }).value ?? ''))) users.push(`${item.name} #${item.sortOrder}`);\n } catch {\n // Unreadable template: not listed; publishing and moving still work.\n }\n }\n return users;\n}\n", "// The reorder dialog: the entries of a list (or a table's rows, or a page's\n// sections) with their values shown clearly, each with a handle to drag and\n// Move up / Move down buttons. The page previews the order as it changes.\n// It is a sidebar level above the list's entity: leaving it by any route\n// (Back, Escape, Cancel) puts the page's order back.\n\nimport type { PanelHandle, Panels } from '../targets.ts';\nimport { button, el } from './host.ts';\nimport { tooltip } from './tooltip.ts';\nimport { icon } from './icons.ts';\n\nexport interface ReorderEntry {\n key: string;\n /** The value, shown clearly: what is being ordered. */\n label: string;\n /** More context, such as the start of a section's content. */\n detail?: string;\n sortOrder: number;\n}\n\nexport interface ReorderActions {\n /** The order changed (a drag or a button); `keys` is the new order. */\n changed(keys: string[]): void;\n save(keys: string[]): void;\n cancel(): void;\n /** Adds an entry: at the start, at the end, or after a key. */\n add?(at: { position: 'head' } | { position: 'tail' } | { position: 'after'; key: string }, anchor: HTMLElement): void;\n}\n\nexport class ReorderPanel {\n readonly element: HTMLElement;\n private entries: ReorderEntry[] = [];\n private actions: ReorderActions | undefined;\n private readonly list: HTMLElement;\n private readonly status: HTMLElement;\n private readonly saveButton: HTMLButtonElement;\n private readonly addButtons: HTMLElement;\n private dragging: string | undefined;\n\n private readonly panels: Panels;\n private handle: PanelHandle | undefined;\n\n constructor(panels: Panels) {\n this.panels = panels;\n this.element = el('div', 'reorder');\n this.status = el('p', 'hint');\n this.status.setAttribute('role', 'status');\n this.list = el('ol', 'rows reorder-rows');\n this.list.setAttribute('aria-label', 'Entries, in order');\n this.addButtons = el('div', 'actions');\n const buttons = el('div', 'actions');\n const cancel = el('button', '', 'Cancel');\n cancel.type = 'button';\n cancel.addEventListener('click', () => this.actions?.cancel());\n this.saveButton = el('button', 'primary', 'Save order');\n this.saveButton.type = 'button';\n this.saveButton.addEventListener('click', () => this.actions?.save(this.keys()));\n buttons.append(cancel, this.saveButton);\n this.element.append(this.status, this.list, this.addButtons, buttons);\n }\n\n get isOpen(): boolean {\n return this.handle?.isOpen ?? false;\n }\n\n open(title: string, entityUrn: string, entries: ReorderEntry[], actions: ReorderActions): void {\n this.entries = [...entries];\n this.actions = actions;\n this.setStatus('');\n this.setBusy(false);\n this.addButtons.replaceChildren();\n if (actions.add) {\n const head = el('button', '', 'Add at the start');\n head.type = 'button';\n head.addEventListener('click', () => actions.add!({ position: 'head' }, head));\n const tail = el('button', '', 'Add at the end');\n tail.type = 'button';\n tail.addEventListener('click', () => actions.add!({ position: 'tail' }, tail));\n this.addButtons.append(head, tail);\n }\n this.render();\n this.handle = this.panels.show(this.element, {\n title,\n entityUrn,\n // Left without Save or Cancel (Back, Escape, another task): the same as Cancel.\n onLeave: () => {\n const left = this.actions;\n this.actions = undefined;\n left?.cancel();\n },\n });\n }\n\n close(): void {\n this.actions = undefined;\n this.handle?.close();\n }\n\n setStatus(text: string): void {\n this.status.textContent = text;\n }\n\n setBusy(busy: boolean, label = 'Saving\u2026'): void {\n this.saveButton.disabled = busy;\n this.saveButton.textContent = busy ? label : 'Save order';\n }\n\n private keys(): string[] {\n return this.entries.map((entry) => entry.key);\n }\n\n /** `button`: the Move button used, focused again in the moved entry (or its other one at the end), so the keyboard stays in the list. */\n private move(from: number, to: number, button?: 'up' | 'down'): void {\n if (to < 0 || to >= this.entries.length || from === to) return;\n const [entry] = this.entries.splice(from, 1);\n this.entries.splice(to, 0, entry!);\n this.render();\n if (button) {\n const row = [...this.list.children].find((child) => (child as HTMLElement).dataset['key'] === entry!.key);\n const buttons = [...(row?.querySelectorAll<HTMLButtonElement>('button[data-move]') ?? [])];\n (buttons.find((b) => b.dataset['move'] === button && !b.disabled) ?? buttons.find((b) => !b.disabled))?.focus();\n }\n this.actions?.changed(this.keys());\n }\n\n private render(): void {\n this.list.replaceChildren(\n ...this.entries.map((entry, index) => {\n const row = el('li', 'row reorder-row');\n row.draggable = true;\n row.dataset['key'] = entry.key;\n const handle = el('span', 'handle');\n handle.setAttribute('aria-hidden', 'true');\n handle.append(icon('grip-vertical'));\n const text = el('div', 'row-main');\n text.append(el('span', 'row-name', entry.label));\n if (entry.detail) text.append(el('span', 'meta', entry.detail));\n const up = el('button', '', 'Move up');\n up.type = 'button';\n up.disabled = index === 0;\n up.setAttribute('aria-label', `Move ${entry.label} up`);\n up.dataset['move'] = 'up';\n up.addEventListener('click', () => this.move(index, index - 1, 'up'));\n const down = el('button', '', 'Move down');\n down.type = 'button';\n down.disabled = index === this.entries.length - 1;\n down.setAttribute('aria-label', `Move ${entry.label} down`);\n down.dataset['move'] = 'down';\n down.addEventListener('click', () => this.move(index, index + 1, 'down'));\n row.append(handle, text, up, down);\n if (this.actions?.add) {\n const add = button('', 'ghost', 'icon-sm');\n add.setAttribute('aria-label', `Add after ${entry.label}`);\n add.append(icon('plus'));\n tooltip(add);\n add.addEventListener('click', () => this.actions?.add!({ position: 'after', key: entry.key }, add));\n row.append(add);\n }\n // Drag and drop within the list.\n row.addEventListener('dragstart', (event) => {\n this.dragging = entry.key;\n event.dataTransfer?.setData('text/plain', entry.key);\n row.classList.add('dragging');\n });\n row.addEventListener('dragend', () => {\n this.dragging = undefined;\n row.classList.remove('dragging');\n });\n row.addEventListener('dragover', (event) => event.preventDefault());\n row.addEventListener('drop', (event) => {\n event.preventDefault();\n const from = this.entries.findIndex((candidate) => candidate.key === this.dragging);\n if (from >= 0) this.move(from, index);\n });\n return row;\n }),\n );\n }\n}\n", "// Moving items: reordering a list, a table's rows or a page's sections,\n// swapping fixed slots, making room for an insert, and relocating or\n// renaming an item.\n//\n// The API has no atomic multi-item commit, so every move is planned first:\n// its steps are queued as unsaved changes (and stashed) before any call,\n// then run in order. A step whose target is already in place is skipped, so\n// a plan can be replayed after a failure or a reload. Moves are drafts: they\n// go live when published, and the versions of one plan publish together.\n\nimport type { Binding } from './core/discovery.ts';\nimport { dispatchItemUpdated } from './core/events.ts';\nimport type { GroupLog } from './core/groups.ts';\nimport { planInsert, reorder, swap, type InsertAt, type Placed, type SortChange } from './core/ordering.ts';\nimport { pendingKey, type PendingCreate, type PendingMove } from './core/pending.ts';\nimport { toRepresentation, valueOf, type ContentItem, type TypeEntry } from './core/registry.ts';\nimport type { Editing } from './editing.ts';\nimport { isLive, reviewAction, type EditorContext, type PanelHandle } from './targets.ts';\nimport { inLiveContent } from './live.ts';\nimport { templatesUsing } from './templates.ts';\nimport { SimpleForm } from './ui/form.ts';\nimport { debugDetails, el } from './ui/host.ts';\nimport { ReorderPanel } from './ui/reorder-panel.ts';\nimport type { PageView } from './view.ts';\n\n/** One reorderable entry: a direct child of the group's container, and the items it shows. */\ninterface Unit {\n key: string;\n element: HTMLElement;\n bindings: Binding[];\n sortOrder: number;\n label: string;\n detail?: string;\n /** A keyed member whose order item does not exist yet: its key, the value the item is created with. */\n missing?: string;\n}\n\n/** A list (every item of a name) or a table's rows. */\ninterface Group {\n kind: 'list' | 'rows';\n container: HTMLElement;\n entityUrn: string;\n entry: TypeEntry;\n /** The list's item name; for rows, the first column's. */\n name: string;\n units: Unit[];\n}\n\nexport class Moves {\n readonly panel: ReorderPanel;\n private readonly ctx: EditorContext;\n private readonly view: PageView;\n private readonly editing: () => Editing;\n private readonly groups: () => GroupLog | undefined;\n /** Steps already done per plan (for put-back), and the versions they made. */\n private readonly done = new Map<string, { step: PendingMove; urn: string }[]>();\n /** A plan's failure panel (Retry, Put back), by plan, closed when the plan finishes or is put back. */\n private readonly failures = new Map<string, PanelHandle>();\n\n /** Creates an item (through the same checks as any create), for an order list's first move. */\n private readonly create: (change: PendingCreate) => Promise<ContentItem>;\n\n constructor(\n ctx: EditorContext,\n view: PageView,\n editing: () => Editing,\n groups: () => GroupLog | undefined,\n create: (change: PendingCreate) => Promise<ContentItem>,\n ) {\n this.ctx = ctx;\n this.create = create;\n this.view = view;\n this.editing = editing;\n this.groups = groups;\n this.panel = new ReorderPanel(ctx.panels);\n }\n\n /** The group an element belongs to, if it is in a list or a table's rows. */\n groupOf(binding: Binding): Group | undefined {\n const entityUrn = this.ctx.store.entityFor(binding.scope);\n if (!entityUrn) return undefined;\n const rows = binding.element.closest<HTMLElement>('[data-content-rows]');\n const list = binding.element.closest<HTMLElement>(`[data-${binding.entry.attribute}-list=\"${CSS.escape(binding.name)}\"]`);\n // The nearest container wins: a list inside a table cell is a list.\n if (list && (!rows || rows.contains(list))) return this.listGroup(list, binding, entityUrn);\n if (rows) return this.rowsGroup(rows, binding, entityUrn);\n return undefined;\n }\n\n private listGroup(container: HTMLElement, binding: Binding, entityUrn: string): Group {\n const units: Unit[] = [];\n for (const child of container.children) {\n const member = this.ctx.discovery\n .all()\n .find((b) => b.entry === binding.entry && b.name === binding.name && child.contains(b.element) && this.ctx.store.entityFor(b.scope) === entityUrn);\n if (!member) continue;\n const stored = this.ctx.store.itemFor(member);\n // A keyed group (cards, sections) names its key on the element, so a member is ordered before its item exists.\n const key = member.element.getAttribute('data-section');\n if (!stored?.item.urn && key === null) continue; // A placeholder list entry has nothing to move yet.\n const value = stored?.item.urn ? String((stored.item as { value?: unknown }).value ?? stored.item.name) : key!;\n units.push({\n key: stored?.item.urn ?? `slot:${member.sortOrder}`,\n element: child as HTMLElement,\n bindings: [member],\n sortOrder: member.sortOrder,\n label: key === null ? value : groupLabel(child as HTMLElement, value),\n ...(key !== null ? { detail: ` \u00B7 ${(child.textContent ?? '').trim().replace(/\\s+/g, ' ').slice(0, 70)}\u2026` } : {}),\n ...(stored?.item.urn ? {} : { missing: key! }),\n });\n }\n return { kind: 'list', container, entityUrn, entry: binding.entry, name: binding.name, units };\n }\n\n private rowsGroup(container: HTMLElement, binding: Binding, entityUrn: string): Group {\n const units: Unit[] = [];\n for (const child of container.children) {\n const sortOrder = Number(child.getAttribute('data-content-row'));\n if (!Number.isInteger(sortOrder)) continue;\n const bindings = this.ctx.discovery.all().filter((b) => child.contains(b.element) && this.ctx.store.entityFor(b.scope) === entityUrn);\n const cells = bindings.map((b) => (b.element.textContent ?? '').trim()).filter(Boolean);\n units.push({\n key: `row:${sortOrder}`,\n element: child as HTMLElement,\n bindings,\n sortOrder,\n label: cells[0] ?? `Row ${sortOrder}`,\n detail: cells.length > 1 ? ` \u00B7 ${cells.slice(1).join(' \u00B7 ')}` : '',\n });\n }\n return { kind: 'rows', container, entityUrn, entry: binding.entry, name: binding.name, units };\n }\n\n // ---------------------------------------------------------------------\n // The reorder dialog, and Move up / Move down\n // ---------------------------------------------------------------------\n\n openReorder(binding: Binding): void {\n const group = this.groupOf(binding);\n if (!group || group.units.length === 0) return;\n this.editing().close();\n this.view.rememberOrder(group.container);\n const before = group.units.map((unit) => unit.key);\n const what = group.kind === 'rows' ? 'rows' : group.name === 'sections' ? 'sections' : `\"${group.name}\"`;\n this.panel.open(\n `Reorder ${what}`,\n group.entityUrn,\n group.units.map((unit) => ({ key: unit.key, label: unit.label, sortOrder: unit.sortOrder, ...(unit.detail ? { detail: unit.detail } : {}) })),\n {\n changed: (keys) => this.preview(group, keys),\n cancel: () => {\n this.preview(group, before);\n this.panel.close();\n },\n save: (keys) => void this.saveOrder(group, keys, () => this.panel.close()),\n ...(group.kind === 'list' ? { add: (at, anchor) => void this.insert(group, at, anchor) } : {}),\n },\n );\n }\n\n /** Moves an entry up or down by one, straight away. */\n moveBy(binding: Binding, delta: -1 | 1): void {\n const group = this.groupOf(binding);\n if (!group) return;\n const keys = group.units.map((unit) => unit.key);\n const index = group.units.findIndex((unit) => unit.bindings.includes(binding));\n const target = index + delta;\n if (index < 0 || target < 0 || target >= keys.length) return;\n [keys[index], keys[target]] = [keys[target]!, keys[index]!];\n this.editing().close();\n this.view.rememberOrder(group.container);\n this.preview(group, keys);\n void this.saveOrder(group, keys, () => undefined);\n }\n\n /** Shows an order on the page by moving the entries themselves, or, in live content, by telling the page. */\n private preview(group: Group, keys: string[]): void {\n const byKey = new Map(group.units.map((unit) => [unit.key, unit]));\n if (inLiveContent(group.container)) {\n this.previewLive(group, keys);\n return;\n }\n // The entries' places, in the order they are on the page now (an earlier preview may have moved them).\n const elements = new Set(group.units.map((unit) => unit.element));\n const inPage = [...group.container.children].filter((child) => elements.has(child as HTMLElement));\n const markers = inPage.map((element) => {\n const marker = document.createComment('');\n element.replaceWith(marker);\n return marker;\n });\n keys.forEach((key, index) => markers[index]?.replaceWith(byKey.get(key)!.element));\n }\n\n /**\n * Live content (an island) owns its DOM: each place in the order is sent the\n * item that moves there, and the page re-renders in that order. The original\n * order is sent as restores.\n */\n private previewLive(group: Group, keys: string[]): void {\n const byKey = new Map(group.units.map((unit) => [unit.key, unit]));\n const places = group.units.map((unit) => unit.sortOrder).sort((a, b) => a - b);\n const original = group.units.map((unit) => unit.key);\n const unchanged = keys.every((key, index) => key === original[index]);\n keys.forEach((key, index) => {\n const unit = byKey.get(key)!;\n const binding = unit.bindings[0]!;\n const stored = this.ctx.store.itemFor(binding);\n const item = (stored?.item ?? { name: group.name, value: unit.missing }) as ContentItem;\n this.ctx.live.showAt(binding, places[index]!, unchanged ? undefined : ({ ...item, sortOrder: places[index]! } as ContentItem));\n });\n }\n\n /** Plans the moves for a new order, runs them, and re-tags the entries so each shows its item. */\n private async saveOrder(group: Group, keys: string[], close: () => void): Promise<void> {\n const changes: SortChange[] = reorder(\n group.units.map((unit): Placed => ({ key: unit.key, sortOrder: unit.sortOrder })),\n keys,\n );\n const byKey = new Map(group.units.map((unit) => [unit.key, unit]));\n const missing = group.units.filter((unit) => unit.missing !== undefined);\n if (changes.length === 0 && missing.length === 0) {\n close();\n return;\n }\n const steps: Omit<PendingMove, 'planId' | 'label'>[] = [];\n for (const change of changes) {\n const unit = byKey.get(change.key)!;\n if (unit.missing !== undefined) continue; // Created at its new place below.\n for (const binding of unit.bindings) {\n const stored = this.ctx.store.itemFor(binding);\n if (!stored?.item.urn) continue; // An empty cell has nothing to move.\n steps.push(this.step(binding.entry, stored.item, group.entityUrn, { name: binding.name, sortOrder: change.to }));\n }\n }\n const label = group.kind === 'rows' ? 'Reorder rows' : `Reorder ${group.name}`;\n this.panel.setBusy(true);\n const ok = (await this.runSteps(steps, label)) && (await this.createMissing(group, missing, changes));\n this.panel.setBusy(false);\n if (!ok) {\n // The page shows what was actually saved; the remaining steps stay queued.\n this.preview(group, group.units.map((unit) => unit.key));\n await this.view.refresh(group.entityUrn);\n return;\n }\n // Keep the new order on the page: each moved entry now shows its item at its new sort order.\n if (inLiveContent(group.container)) this.ctx.live.endPreviews();\n else {\n for (const change of changes) {\n for (const binding of byKey.get(change.key)!.bindings) this.view.retag(binding, change.to);\n }\n }\n close();\n await this.view.refresh(group.entityUrn);\n }\n\n /**\n * The first move of a keyed group whose order items do not all exist yet:\n * creates each missing one, holding its key, at its place in the new order.\n * Checked against the latest read, so it never drafts over an item (rule 8).\n */\n private async createMissing(group: Group, missing: Unit[], changes: SortChange[]): Promise<boolean> {\n if (missing.length === 0) return true;\n const { feedback, toolbar } = this.ctx;\n await this.view.refresh(group.entityUrn);\n const to = new Map(changes.map((change) => [change.key, change.to]));\n for (const unit of missing) {\n const sortOrder = to.get(unit.key) ?? unit.sortOrder;\n try {\n await this.create({ kind: 'create', type: group.entry.type, entityUrn: group.entityUrn, name: group.name, sortOrder, value: { value: unit.missing } });\n } catch (error) {\n const failure = await feedback.describe(error, `add ${unit.missing} to ${group.name}`);\n toolbar.showMessage(`Reorder ${group.name}: ${failure.message}`, false, failure.debug);\n return false;\n }\n }\n return true;\n }\n\n // ---------------------------------------------------------------------\n // Keyed groups: the members' tags and their move menu\n // ---------------------------------------------------------------------\n\n /** Every member of a keyed group (cards, sections) on the page, with its place, for its tag. */\n keyedMembers(): { binding: Binding; name: string; index: number; count: number }[] {\n const seen = new Set<HTMLElement>();\n const members: { binding: Binding; name: string; index: number; count: number }[] = [];\n for (const binding of this.ctx.discovery.all()) {\n if (!binding.element.hasAttribute('data-section')) continue;\n const group = this.groupOf(binding);\n if (!group || group.kind !== 'list' || seen.has(group.container)) continue;\n seen.add(group.container);\n group.units.forEach((unit, index) => members.push({ binding: unit.bindings[0]!, name: group.name, index, count: group.units.length }));\n }\n return members;\n }\n\n /**\n * The member's menu: Move previous and Move next swap it with its neighbour\n * on the page, as a preview. Nothing is sent until Save; Revert, Escape, or\n * the popover closing for anything else puts the page back.\n */\n openOrderMenu(binding: Binding): void {\n const group = this.groupOf(binding);\n if (!group || group.units.length < 2) return;\n const { popover } = this.ctx;\n this.editing().close();\n this.view.rememberOrder(group.container);\n const original = group.units.map((unit) => unit.key);\n const unit = group.units.find((u) => u.bindings.includes(binding))!;\n let keys = [...original];\n const labelOf = new Map(group.units.map((u) => [u.key, u.label]));\n const revert = () => {\n this.preview(group, original);\n this.changedOrder();\n };\n const render = () => {\n const index = keys.indexOf(unit.key);\n const changed = keys.some((key, i) => key !== original[i]);\n const move = (delta: -1 | 1) => {\n const next = [...keys];\n [next[index], next[index + delta]] = [next[index + delta]!, next[index]!];\n keys = next;\n this.preview(group, keys);\n this.changedOrder();\n render();\n };\n const previous = keys[index - 1];\n const following = keys[index + 1];\n popover.whenEnded(undefined);\n popover.showChoices(\n unit.element,\n `Order of ${group.name}`,\n `${index + 1} of ${keys.length}`,\n [],\n [\n `${unit.label} is ${index + 1} of ${keys.length}.`,\n previous ? `Before it: ${labelOf.get(previous)}.` : '',\n following ? `After it: ${labelOf.get(following)}.` : '',\n changed ? 'Not saved yet.' : '',\n // Creating the order list on a published entity: new items are live as soon as they are created.\n changed && group.units.some((u) => u.missing !== undefined) && isLive(this.ctx.store.view(group.entityUrn)?.status)\n ? 'This content is published, and this order is new, so it is live as soon as it is saved.'\n : '',\n ]\n .filter(Boolean)\n .join(' '),\n [\n ...(previous ? [{ label: 'Move previous', run: () => move(-1) }] : []),\n ...(following ? [{ label: 'Move next', run: () => move(1) }] : []),\n {\n label: 'Reorder all\u2026',\n run: () => {\n popover.whenEnded(undefined);\n popover.hide();\n revert();\n this.openReorder(binding);\n },\n },\n ...(changed\n ? [\n {\n label: 'Save',\n primary: true,\n run: () => {\n popover.whenEnded(undefined);\n popover.hide();\n void this.saveOrder(group, keys, () => undefined).then(() => this.changedOrder());\n },\n },\n ]\n : []),\n // Last: Escape runs it.\n { label: changed ? 'Revert' : 'Close', run: () => popover.hide() },\n ],\n );\n popover.whenEnded(revert);\n };\n render();\n }\n\n /** Listeners told when a group's order on the page changes (a preview, a revert, a save). */\n private readonly orderListeners = new Set<() => void>();\n\n onOrderChange(listener: () => void): void {\n this.orderListeners.add(listener);\n }\n\n private changedOrder(): void {\n for (const listener of this.orderListeners) listener();\n }\n\n // ---------------------------------------------------------------------\n // Inserting into a list\n // ---------------------------------------------------------------------\n\n /** Makes room if needed, adds a preview entry to the page, and opens the create form for it. */\n private async insert(group: Group, at: InsertAt, anchor: HTMLElement): Promise<void> {\n const items = group.units.map((unit): Placed => ({ key: unit.key, sortOrder: unit.sortOrder }));\n await this.view.refresh(group.entityUrn); // Check occupancy against the latest read.\n const plan = planInsert(items, at);\n const byKey = new Map(group.units.map((unit) => [unit.key, unit]));\n if (plan.shifts.length > 0) {\n const steps = plan.shifts.flatMap((shift) =>\n byKey.get(shift.key)!.bindings.flatMap((binding) => {\n const stored = this.ctx.store.itemFor(binding);\n return stored?.item.urn ? [this.step(binding.entry, stored.item, group.entityUrn, { name: binding.name, sortOrder: shift.to })] : [];\n }),\n );\n if (!(await this.runSteps(steps, `Make room in ${group.name}`))) return;\n for (const shift of plan.shifts) for (const binding of byKey.get(shift.key)!.bindings) this.view.retag(binding, shift.to);\n await this.view.refresh(group.entityUrn); // The new slot is checked against what was just saved.\n }\n if (this.ctx.store.itemAt(group.entityUrn, group.entry, group.name, plan.sortOrder)) {\n this.ctx.toolbar.showMessage(`${group.name} #${plan.sortOrder} is taken. Reopen the list and try again.`);\n return;\n }\n // Preview: a copy of an entry, emptied and pointed at the new slot.\n const model = group.units.at(at.position === 'head' ? 0 : -1)!;\n const reference = at.position === 'after' ? byKey.get(at.key)!.element : model.element;\n const copy = model.element.cloneNode(true) as HTMLElement;\n for (const element of [copy, ...copy.querySelectorAll<HTMLElement>('*')]) {\n element.removeAttribute('style');\n element.removeAttribute('data-baack-state');\n element.removeAttribute(`data-${group.entry.attribute}-urn`);\n if (element.hasAttribute(`data-${group.entry.attribute}-name`)) {\n element.setAttribute(`data-${group.entry.attribute}-sort-order`, String(plan.sortOrder));\n element.setAttribute('data-placeholder', '');\n }\n }\n if (at.position === 'head') group.container.insertBefore(copy, reference);\n else reference.after(copy);\n this.view.track(copy);\n this.panel.close();\n const bound = copy.matches(`[data-${group.entry.attribute}-name]`) ? copy : copy.querySelector<HTMLElement>(`[data-${group.entry.attribute}-name]`);\n void anchor;\n this.editing().open({\n entityUrn: group.entityUrn,\n entry: group.entry,\n name: group.name,\n sortOrder: plan.sortOrder,\n anchor: bound ?? copy,\n binding: undefined,\n });\n }\n\n // ---------------------------------------------------------------------\n // Move or rename (guided relocation)\n // ---------------------------------------------------------------------\n\n async relocate(binding: Binding | undefined, entityUrn: string, entry: TypeEntry, item: ContentItem): Promise<void> {\n const { store } = this.ctx;\n this.editing().close();\n const places = this.ctx.discovery.all().filter((b) => b.entry === entry && b.name === item.name && b.sortOrder === item.sortOrder).length;\n const templates = await templatesUsing(this.ctx, entityUrn, item.name);\n const info = el('div', 'simple-form');\n info.append(\n el('p', 'hint', `${item.name} #${item.sortOrder} is shown in ${places} ${places === 1 ? 'place' : 'places'} on this page. Those places will show the new item there, or a placeholder.`),\n );\n const form = new SimpleForm(\n `Move or rename ${item.name} #${item.sortOrder}`,\n [\n { key: 'name', label: 'Name', value: item.name },\n { key: 'sortOrder', label: 'Sort order', value: String(item.sortOrder) },\n ],\n 'Move',\n (values) => {\n const name = values['name'] ?? '';\n const sortOrder = Number(values['sortOrder']);\n if (!/^[A-Za-z0-9_-]+$/.test(name)) return form.setError('Use letters, numbers, - and _ in the name.');\n if (!Number.isInteger(sortOrder)) return form.setError('The sort order must be a whole number.');\n if (name === item.name && sortOrder === item.sortOrder) return form.setError('That is where it is now.');\n form.setBusy(true, 'Checking\u2026');\n void this.view.refresh(entityUrn).then(async () => {\n form.setBusy(false);\n if (store.itemAt(entityUrn, entry, name, sortOrder) && !swapping) {\n swapping = true;\n form.setError(`${name} #${sortOrder} is taken. Press Move again to swap the two.`);\n return;\n }\n panel.close();\n await this.moveTo(entityUrn, entry, item, { name, sortOrder });\n });\n },\n );\n let swapping = false;\n form.element.insertBefore(info, form.element.querySelector('.error'));\n if (templates.length > 0) {\n form.element.insertBefore(\n el('p', 'issues', `Templates use \"${item.name}\" and would stop showing it if it is renamed: ${templates.join(', ')}.`),\n form.element.querySelector('.error'),\n );\n }\n form.element.insertBefore(\n el('p', 'issues', 'Renaming changes the name every client looks this item up by, including apps this editor cannot see. They break when it is published.'),\n form.element.querySelector('.error'),\n );\n const panel = this.ctx.panels.show(form.element, { entityUrn });\n void binding;\n }\n\n // ---------------------------------------------------------------------\n // Plans: queue, run, retry, put back\n // ---------------------------------------------------------------------\n\n /**\n * Moves or renames an item to a slot, swapping with the item already there.\n * Occupancy is checked against a fresh read first (rule 8). True when done.\n */\n async moveTo(entityUrn: string, entry: TypeEntry, item: ContentItem, to: { name: string; sortOrder: number }): Promise<boolean> {\n await this.view.refresh(entityUrn);\n const occupant = this.ctx.store.itemAt(entityUrn, entry, to.name, to.sortOrder);\n if (occupant?.item.urn === item.urn) return true;\n const steps = occupant\n ? swap({ key: item.urn!, sortOrder: item.sortOrder }, { key: occupant.item.urn!, sortOrder: to.sortOrder }).map((change) =>\n this.step(entry, change.key === item.urn ? item : occupant.item, entityUrn, {\n name: change.key === item.urn ? to.name : item.name,\n sortOrder: change.to,\n }),\n )\n : [this.step(entry, item, entityUrn, to)];\n const label = occupant\n ? `Swap ${item.name} #${item.sortOrder} and ${to.name} #${to.sortOrder}`\n : to.name === item.name\n ? `Move ${item.name} #${item.sortOrder} to #${to.sortOrder}`\n : `Rename ${item.name} to ${to.name}`;\n if (!(await this.runSteps(steps, label))) return false;\n await this.view.refresh(entityUrn);\n return true;\n }\n\n private step(entry: TypeEntry, item: ContentItem, entityUrn: string, to: { name: string; sortOrder: number }): Omit<PendingMove, 'planId' | 'label'> {\n return { kind: 'move', type: entry.type, urn: item.urn!, entityUrn, name: item.name, sortOrder: item.sortOrder, to };\n }\n\n /** Queues the steps as one plan (stashed before any call) and runs it. True when every step is done. */\n private async runSteps(steps: Omit<PendingMove, 'planId' | 'label'>[], label: string): Promise<boolean> {\n if (steps.length === 0) return true;\n const planId = `plan-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 7)}`;\n for (const step of steps) this.ctx.pending.set({ ...step, planId, label });\n return this.run(planId);\n }\n\n /** Runs (or replays) a plan's queued steps in order. */\n async run(planId: string): Promise<boolean> {\n const { pending, transport, toolbar, feedback } = this.ctx;\n const steps = pending.plan(planId);\n if (steps.length === 0) return true;\n const label = steps[0]!.label;\n const entityUrn = steps[0]!.entityUrn;\n const done = this.done.get(planId) ?? [];\n this.done.set(planId, done);\n toolbar.showMessage(`${label}: moving\u2026`, true);\n for (const step of steps) {\n const entry = this.ctx.entry(step.type);\n try {\n const newest = (await transport.history(entry, step.urn)).history[0];\n if (!newest?.urn) throw new Error(`${step.name} #${step.sortOrder} no longer exists`);\n // Replay: already where it should be.\n if (newest.name === step.to.name && newest.sortOrder === step.to.sortOrder) {\n pending.clear(pendingKey(step));\n done.push({ step, urn: newest.urn });\n continue;\n }\n if (newest.urn !== step.urn) throw new Error(`${step.name} #${step.sortOrder} was changed by someone else after this move was planned`);\n const moved = { ...newest, name: step.to.name, sortOrder: step.to.sortOrder } as ContentItem;\n const saved = await transport.update(entry, newest.urn, toRepresentation(entry, moved, valueOf(entry, newest), step.entityUrn));\n if (!saved?.urn) throw new Error('the API returned no URN for the new version');\n pending.clear(pendingKey(step));\n done.push({ step, urn: saved.urn });\n dispatchItemUpdated({ entityUrn: step.entityUrn, oldUrn: step.urn, newUrn: saved.urn, type: entry.type, value: saved });\n } catch (error) {\n const failure = await feedback.describe(error, 'move this item');\n this.showFailure(planId, label, done.length, done.length + pending.plan(planId).length, failure.message, failure.debug, entityUrn);\n if (failure.kind === 'unauthorized') void feedback.promptLogin(failure.message, () => void this.run(planId));\n return false;\n }\n }\n this.groups()?.add({ id: planId, label, entityUrn, versions: done.map((d) => d.urn), at: Date.now() });\n this.done.delete(planId);\n this.closeFailure(planId);\n toolbar.showMessage(`${label}: done. Saved as drafts.`, true, undefined, reviewAction(this.ctx, entityUrn));\n return true;\n }\n\n /** A plan stopped part-way: say what moved, and offer to retry the rest or put the moved items back. */\n private showFailure(planId: string, label: string, moved: number, total: number, message: string, debug: string | undefined, entityUrn: string): void {\n const panel = el('div', 'simple-form');\n panel.append(\n el('div', 'title', `${label} stopped part-way`),\n el('p', 'message', `Moved ${moved} of ${total}. ${message}`),\n ...debugDetails(debug),\n el('p', 'hint', 'The rest is kept with your unsaved changes, in this browser, until you retry or put things back.'),\n );\n const retry = el('button', 'primary', 'Retry');\n retry.type = 'button';\n retry.addEventListener('click', () => void this.run(planId).then(async (ok) => {\n if (ok) await this.refreshAfter(planId);\n }));\n const back = el('button', '', moved > 0 ? 'Put back' : 'Discard this move');\n back.type = 'button';\n back.addEventListener('click', () => void this.putBack(planId));\n const actions = el('div', 'actions');\n actions.append(back, retry);\n panel.append(actions);\n this.closeFailure(planId);\n this.failures.set(planId, this.ctx.panels.show(panel, { entityUrn }));\n }\n\n private closeFailure(planId: string): void {\n this.failures.get(planId)?.close();\n this.failures.delete(planId);\n }\n\n private async refreshAfter(planId: string): Promise<void> {\n void planId;\n for (const urn of this.ctx.store.entities()) await this.view.refresh(urn);\n }\n\n /** Drops the plan's remaining steps and moves what had moved back where it was (each one more version). */\n private async putBack(planId: string): Promise<void> {\n const { pending } = this.ctx;\n const done = this.done.get(planId) ?? [];\n const remaining = pending.plan(planId);\n for (const step of remaining) pending.clear(pendingKey(step));\n const label = remaining[0]?.label ?? done[0]?.step.label ?? 'Move';\n const entityUrn = remaining[0]?.entityUrn ?? done[0]?.step.entityUrn;\n this.done.delete(planId);\n if (done.length === 0) {\n // Nothing had moved: dropping the plan is all there is to do.\n this.closeFailure(planId);\n this.ctx.toolbar.showMessage(`${label}: nothing had moved, so nothing changed. The move is discarded.`, true);\n return;\n }\n const steps = done.map(({ step, urn }) => ({\n kind: 'move' as const,\n type: step.type,\n urn,\n entityUrn: step.entityUrn,\n name: step.to.name,\n sortOrder: step.to.sortOrder,\n to: { name: step.name, sortOrder: step.sortOrder },\n }));\n if (await this.runSteps(steps, `Put back: ${label}`)) {\n this.ctx.toolbar.showMessage(`Put back: ${label}.`, true);\n if (entityUrn) await this.view.refresh(entityUrn);\n }\n }\n}\n\n/** A keyed member's label: its first heading, or else its key. */\nfunction groupLabel(element: HTMLElement, key: string): string {\n const heading = element.querySelector('h1, h2, h3, h4, h5, h6');\n const text = (heading?.textContent ?? '').trim().replace(/\\s+/g, ' ');\n return text || key;\n}\n", "// A small tag on each member of a keyed group (cards, sections) in edit\n// mode, saying it is in an ordered list and where (\"services \u00B7 2 of 3\"),\n// with a \u22EF that opens its move menu. Drawn in the editor's shadow root over\n// the member's top-right corner, so the page's own markup is untouched.\n\nimport type { Binding } from '../core/discovery.ts';\nimport { el, type EditorHost } from './host.ts';\n\nexport interface OrderTag {\n binding: Binding;\n name: string;\n index: number;\n count: number;\n}\n\nexport class OrderTags {\n private readonly layer: HTMLElement;\n private readonly onOpen: (binding: Binding) => void;\n private tags: { binding: Binding; element: HTMLElement; button: HTMLButtonElement }[] = [];\n private frame = 0;\n private readonly resizes = new ResizeObserver(() => this.schedule());\n\n constructor(host: EditorHost, onOpen: (binding: Binding) => void) {\n this.layer = el('div', 'order-tags');\n host.root.append(this.layer);\n this.onOpen = onOpen;\n }\n\n /** Shows a tag on every member, replacing the tags shown before (kept as they are when nothing changed). */\n show(members: OrderTag[]): void {\n const same =\n members.length === this.tags.length &&\n members.every((member, index) => this.tags[index]!.binding === member.binding && this.tags[index]!.button.textContent === text(member));\n if (same) {\n this.place();\n return;\n }\n const focused = this.tags.findIndex((tag) => tag.button.matches(':focus'));\n this.clear();\n for (const member of members) {\n const button = el('button', 'order-tag', text(member));\n button.type = 'button';\n button.setAttribute('aria-label', `Order of ${member.name}: ${member.index + 1} of ${member.count}`);\n button.addEventListener('click', () => this.onOpen(member.binding));\n this.layer.append(button);\n this.tags.push({ binding: member.binding, element: member.binding.element, button });\n this.resizes.observe(member.binding.element);\n }\n if (this.tags.length > 0) {\n window.addEventListener('scroll', this.schedule, true);\n window.addEventListener('resize', this.schedule);\n }\n this.place();\n this.tags[focused]?.button.focus();\n }\n\n clear(): void {\n cancelAnimationFrame(this.frame);\n this.resizes.disconnect();\n window.removeEventListener('scroll', this.schedule, true);\n window.removeEventListener('resize', this.schedule);\n this.layer.replaceChildren();\n this.tags = [];\n }\n\n private readonly schedule = () => {\n cancelAnimationFrame(this.frame);\n this.frame = requestAnimationFrame(() => this.place());\n };\n\n /** Each tag sits just inside its member's top-right corner, and is hidden with it. */\n private place(): void {\n for (const { element, button } of this.tags) {\n const rect = element.getBoundingClientRect();\n button.hidden = element.getClientRects().length === 0;\n button.style.top = `${rect.top + 4}px`;\n button.style.right = `${window.innerWidth - rect.right + 4}px`;\n }\n }\n}\n\nfunction text(member: OrderTag): string {\n return `${member.name} \u00B7 ${member.index + 1} of ${member.count} \u22EF`;\n}\n", "// Versions created together by one operation (a swap, a reorder, a row move)\n// belong together: shown as one in history, and published together. The API\n// has no operation identifier yet (api-changes.md item 4), so groups are kept\n// in this browser, per user.\n\nconst PREFIX = 'baack-editor:groups:';\nconst MAX_GROUPS = 200;\n\nexport interface Group {\n id: string;\n label: string;\n entityUrn: string;\n /** Version URNs the operation created. */\n versions: string[];\n at: number;\n}\n\nexport class GroupLog {\n private readonly key: string;\n\n constructor(userUrn: string) {\n this.key = PREFIX + userUrn;\n }\n\n all(): Group[] {\n try {\n const groups = JSON.parse(window.localStorage.getItem(this.key) ?? '[]') as unknown;\n return Array.isArray(groups) ? (groups as Group[]) : [];\n } catch {\n return [];\n }\n }\n\n /** The group a version belongs to, if any. */\n of(versionUrn: string): Group | undefined {\n return this.all().find((group) => group.versions.includes(versionUrn));\n }\n\n add(group: Group): void {\n try {\n const groups = [...this.all(), group].slice(-MAX_GROUPS);\n window.localStorage.setItem(this.key, JSON.stringify(groups));\n } catch (error) {\n console.warn('Baack editor: could not record which versions belong together.', error);\n }\n }\n}\n", "// The entities a user can pick from: every entity the search finds, used by\n// URN only (the search stays a list of references: it does not render the\n// entities, and typed results may carry no more), each described by its admin\n// read (name, language, variant). Those fields rarely change, so they are\n// cached per URN for a day, in memory and in this browser, and the picker\n// filters from the cache; the editor's own creates are added as they happen.\n\nimport { isBaackApiError, type Entity } from '@baack-software/baack-ts-client';\nimport type { Transport } from './transport.ts';\n\nexport interface EntitySummary {\n urn: string;\n /** The stored name, such as /<company>/content/menu. */\n name: string;\n /** The name as a page path, such as /menu. */\n path: string;\n language: string;\n variant: string;\n}\n\nexport interface EntityListing {\n entities: EntitySummary[];\n /** False when the search was still partial, so some entities may be missing. */\n complete: boolean;\n}\n\ninterface Cached extends EntitySummary {\n at: number;\n}\n\nconst CACHE_KEY = 'baack-editor:entities';\nconst CACHE_MS = 24 * 60 * 60 * 1000;\n/** The API is rate limited (10 requests a second): a few reads at a time leave room for the editor's other calls. */\nconst CONCURRENT_READS = 4;\n/** A read refused for the rate (429) is tried again after these waits. */\nconst RETRY_DELAYS_MS = [500, 2000];\n\n/** An entity name as a page path: names are scoped as /<company>/content<path>. */\nexport function displayPath(name: string): string {\n return name.replace(/^\\/[^/]+\\/content(?=\\/|$)/, '') || '/';\n}\n\nexport class EntityDirectory {\n private readonly transport: Transport;\n private readonly owners: () => Promise<string[]>;\n private readonly cache = new Map<string, Cached>();\n /** Per user, like the stash of unsent edits. */\n private readonly key: string;\n private search: Promise<{ urns: string[]; complete: boolean }> | undefined;\n\n constructor(transport: Transport, owners: () => Promise<string[]>, userUrn: string | undefined) {\n this.transport = transport;\n this.owners = owners;\n this.key = `${CACHE_KEY}:${userUrn ?? 'anonymous'}`;\n try {\n const stored = JSON.parse(localStorage.getItem(this.key) ?? '[]') as Cached[];\n for (const entry of stored) if (Date.now() - entry.at < CACHE_MS) this.cache.set(entry.urn, entry);\n } catch {\n // No browser storage (private window, blocked): the cache is per visit.\n }\n }\n\n /** A summary already known, without a request. */\n get(urn: string): EntitySummary | undefined {\n return this.cache.get(urn);\n }\n\n /** A summary from the cache, or from the admin read. */\n async describe(urn: string): Promise<EntitySummary> {\n return this.cache.get(urn) ?? this.remember(await this.transport.readEntity(urn));\n }\n\n /** Adds an entity read or created elsewhere, and includes it in the listing. */\n remember(entity: Entity): EntitySummary {\n const summary: Cached = {\n urn: entity.urn,\n name: entity.name,\n path: displayPath(entity.name),\n language: entity.language,\n variant: entity.variant ?? '',\n at: Date.now(),\n };\n this.cache.set(summary.urn, summary);\n this.search = this.search?.then((found) => ({ ...found, urns: found.urns.includes(summary.urn) ? found.urns : [...found.urns, summary.urn] }));\n this.save();\n return summary;\n }\n\n /**\n * Every entity, sorted by path then language. Cached summaries come at\n * once; the rest are read a few at a time, with `onUpdate` called as they\n * arrive. An entity that can no longer be read (deleted, or no access) is\n * left out; any other failure rejects once the rest are in.\n */\n async list(onUpdate?: (listing: EntityListing) => void): Promise<EntityListing> {\n this.search ??= this.searchAll().catch((error: unknown) => {\n this.search = undefined; // Searched again next time.\n throw error;\n });\n const { urns, complete } = await this.search;\n const listing = (): EntityListing => ({\n entities: urns.flatMap((urn) => this.cache.get(urn) ?? []).sort(compare),\n complete,\n });\n const missing = urns.filter((urn) => !this.fresh(urn));\n if (missing.length > 0) onUpdate?.(listing());\n let failure: unknown;\n const next = [...missing];\n const worker = async () => {\n for (let urn = next.shift(); urn; urn = next.shift()) {\n try {\n this.remember(await this.readWithRetry(urn));\n onUpdate?.(listing());\n } catch (error) {\n if (!(isBaackApiError(error) && error.isNotFound)) failure ??= error;\n }\n }\n };\n await Promise.all(Array.from({ length: Math.min(CONCURRENT_READS, missing.length) }, worker));\n if (failure) throw failure;\n const result = listing();\n onUpdate?.(result);\n return result;\n }\n\n private async readWithRetry(urn: string): Promise<Entity> {\n for (const delay of RETRY_DELAYS_MS) {\n try {\n return await this.transport.readEntity(urn);\n } catch (error) {\n if (!(isBaackApiError(error) && error.status === 429)) throw error;\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n return this.transport.readEntity(urn);\n }\n\n private async searchAll(): Promise<{ urns: string[]; complete: boolean }> {\n const results = await Promise.all((await this.owners()).map((owner) => this.transport.searchEntities(owner)));\n return { urns: [...new Set(results.flatMap((result) => result.urns))], complete: results.every((result) => result.complete) };\n }\n\n private fresh(urn: string): boolean {\n const cached = this.cache.get(urn);\n return cached !== undefined && Date.now() - cached.at < CACHE_MS;\n }\n\n private save(): void {\n try {\n localStorage.setItem(this.key, JSON.stringify([...this.cache.values()]));\n } catch {\n // No browser storage: the cache is per visit.\n }\n }\n}\n\nfunction compare(a: EntitySummary, b: EntitySummary): number {\n return a.path.localeCompare(b.path) || a.language.localeCompare(b.language) || a.variant.localeCompare(b.variant);\n}\n", "// Which entity name serves a page, when the page does not say\n// (`data-entity-urn`). Baack has no index concept: an entity has a name of its\n// own, and lists are separate entity lists. A page at a directory path (`/`,\n// implicitly `/index.html`, or `/docs/`) is served by an entity named for it in\n// the site's own stack, so the URL path is not always the entity name. Baack's\n// sites name the home page's entity `/home`. A suffix such as `/index` or\n// `/index.html` is allowed too, for routers that build straight from the page\n// path: entities are not HTML, so the name is the site's choice.\n\n/** The entity name for the home page by default. */\nexport const HOME_ENTITY_NAME = '/home';\n\n/** The site's own rule (`entityNameForPage` in the config), or the default. */\nexport type EntityNameForPage = (pathname: string) => string;\n\n/**\n * The default rule: `/` and `/index.html` are `/home`; otherwise the path\n * without `index.html` or a trailing slash (`/docs/` is `/docs`).\n */\nexport function defaultEntityName(pathname: string): string {\n const path = pathname.replace(/\\/index\\.html?$/, '/').replace(/\\/+$/, '');\n return path === '' ? HOME_ENTITY_NAME : path;\n}\n\n/** The site's own rule for the page an entity serves (`pagePathForEntity` in the config), or the default. */\nexport type PagePathForEntity = (name: string) => string;\n\n/**\n * The default page address for an entity (its name without the company\n * prefix): `/home` is `/`; any other name is its own path. Used where the\n * editor offers a page address, such as a link's suggestions and what\n * `afterPublish` is told.\n */\nexport function defaultPagePath(name: string): string {\n return name === HOME_ENTITY_NAME ? '/' : name;\n}\n\n/** An entity name may not end in `/`: there is no index entity to name that way. */\nexport function isIndexName(name: string): boolean {\n return name.endsWith('/');\n}\n", "// Getting content into Baack: finding or creating the entity for a page that\n// has none, creating any other entity (a shared menu), and starting a new page\n// from an existing one. The API is\n// micro-request: an entity is created first, then each item with\n// `entity: {urn}`. Entity creation is not idempotent, so every create button\n// is disabled while its request is in flight.\n\nimport { isBaackApiError, type ClientContext, type Company, type Entity } from '@baack-software/baack-ts-client';\nimport { displayPath } from './core/entity-directory.ts';\nimport { SCOPE_ATTRIBUTE } from './core/discovery.ts';\nimport { toRepresentation, valueOf, type ContentItem, type TypeEntry } from './core/registry.ts';\nimport type { Store } from './core/store.ts';\nimport type { Transport } from './core/transport.ts';\nimport { SimpleForm } from './ui/form.ts';\nimport { el } from './ui/host.ts';\nimport { describeFailure } from './ui/messages.ts';\nimport { defaultEntityName, isIndexName, type EntityNameForPage } from './page-entity.ts';\nimport type { Panels } from './targets.ts';\nimport type { Toolbar } from './ui/toolbar.ts';\n\nexport interface OnboardingDeps {\n transport: Transport;\n toolbar: Toolbar;\n context: ClientContext;\n registry: readonly TypeEntry[];\n store: Store;\n panels: Panels;\n /** The site's rule for the entity name serving a page (config), if it has one. */\n entityNameForPage?: EntityNameForPage | undefined;\n /** Opens an entity's level in the sidebar. */\n openEntity(entityUrn: string): void;\n report(error: unknown, action: string, retry: () => void): Promise<void>;\n /** An entity was created (for the entity picker's list). */\n created(entity: Entity): void;\n}\n\nexport interface NewEntityOptions {\n title: string;\n submitLabel: string;\n /** The starting path, such as /menu. */\n path: string;\n /** Default: \"Path, such as /menu\". */\n pathLabel?: string;\n /** A line above the fields. */\n hint?: string;\n language: string;\n variant?: string;\n onCreated(entity: Entity): void;\n onCancel?(): void;\n}\n\nexport class Onboarding {\n private readonly deps: OnboardingDeps;\n\n constructor(deps: OnboardingDeps) {\n this.deps = deps;\n }\n\n /** The page shows items but names no entity: find it by path, or offer to create it. */\n async offerEntityForPage(): Promise<void> {\n const { transport, panels } = this.deps;\n // Not the URL path itself: `/` has no entity of that name (see page-entity.ts).\n const path = (this.deps.entityNameForPage ?? defaultEntityName)(location.pathname);\n const language = document.documentElement.lang || 'en-GB';\n try {\n const entity = await transport.entityView(path, { version: 'LATEST', language });\n const panel = el('div', 'simple-form');\n panel.append(\n el('div', 'title', 'Content for this page exists'),\n el('p', 'hint', `Add this to the page's root element so the editor and the site can find it:`),\n snippet(entity.urn),\n );\n const use = el('button', 'primary', 'Use it for this visit');\n use.type = 'button';\n use.addEventListener('click', () => {\n document.documentElement.setAttribute(SCOPE_ATTRIBUTE, entity.urn);\n handle.close();\n });\n panel.append(actions(use));\n const handle = panels.show(panel);\n } catch (error) {\n if (isBaackApiError(error) && error.isNotFound) {\n await this.showCreateEntity(path, language);\n } else {\n void this.deps.report(error, 'look up this page', () => void this.offerEntityForPage());\n }\n }\n }\n\n private async showCreateEntity(path: string, language: string): Promise<void> {\n const { panels } = this.deps;\n const form = await this.newEntityForm({\n title: 'This page has no content in Baack yet',\n submitLabel: 'Create content for this page',\n path,\n pathLabel: 'Name of this page\\'s content',\n hint: `No content named ${path} (${language}) was found for ${location.pathname}.`,\n language,\n onCreated: (entity) => {\n const done = el('div', 'simple-form');\n done.append(\n el('div', 'title', 'Content created (in draft)'),\n el('p', 'hint', `Add this to the page's root element. Until then, the editor uses it for this visit:`),\n snippet(entity.urn),\n el('p', 'hint', 'Next: create the items this page shows, with \"Create all\" on its content.'),\n );\n const next = el('button', 'primary', 'Show its items');\n next.type = 'button';\n next.addEventListener('click', () => this.deps.openEntity(entity.urn));\n done.append(actions(next));\n panels.show(done);\n document.documentElement.setAttribute(SCOPE_ATTRIBUTE, entity.urn);\n },\n });\n panels.show(form.element);\n }\n\n /** \"New entity\u2026\": any entity, such as a menu shared by many pages, created empty in draft. */\n async offerNewEntity(language: string): Promise<void> {\n const { panels } = this.deps;\n const form = await this.newEntityForm({\n title: 'New entity',\n submitLabel: 'Create entity',\n path: '',\n language,\n onCreated: (entity) => {\n const done = el('div', 'simple-form');\n const urn = el('pre', 'snippet', entity.urn);\n const copy = el('button', '', 'Copy URN');\n copy.type = 'button';\n copy.addEventListener('click', () => {\n navigator.clipboard?.writeText(entity.urn).then(\n () => (copy.textContent = 'Copied'),\n () => (copy.textContent = 'Select and copy it'),\n );\n });\n // Back to where New entity was chosen; the sidebar's own Close hides the sidebar.\n const close = el('button', '', 'Done');\n close.type = 'button';\n close.addEventListener('click', () => shown.close());\n done.append(\n el('div', 'title', `Created ${displayPath(entity.name)} (${entity.language}) in draft`),\n el('p', 'hint', 'Choose it in a reference item, or use its URN in the site:'),\n urn,\n actions(copy, close),\n );\n const shown = panels.show(done);\n },\n });\n panels.show(form.element);\n }\n\n /**\n * The form for creating an entity: path, language, variant, and the owner\n * when there is a choice. It refuses a path, language and variant that\n * already has an entity, found by reading the view (a 404 means none).\n */\n async newEntityForm(options: NewEntityOptions): Promise<SimpleForm> {\n const { transport } = this.deps;\n const owners = await this.owners();\n const form = new SimpleForm(\n options.title,\n [\n { key: 'name', label: options.pathLabel ?? 'Path, such as /menu', value: options.path },\n { key: 'language', label: 'Language', value: options.language },\n { key: 'variant', label: 'Variant (optional)', value: options.variant ?? '' },\n ...(owners.length > 1\n ? [{ key: 'owner', label: 'Owner', value: owners[0]!.urn, options: owners.map((c) => ({ value: c.urn, label: c.name ?? c.urn })) }]\n : []),\n ],\n options.submitLabel,\n (values) => {\n const owner = values['owner'] ?? owners[0]?.urn;\n const name = values['name'] ?? '';\n const language = values['language'] ?? '';\n const variant = values['variant'] ?? '';\n if (!owner) return form.setError('No company was found to own the content.');\n if (!name.startsWith('/')) return form.setError('The path must start with /, like /menu.');\n if (isIndexName(name)) return form.setError(`Content has no index: give it a name of its own, without a trailing /, such as ${defaultEntityName(name)}.`);\n if (!language) return form.setError('Enter a language, such as en-GB.');\n form.setError('');\n form.setBusy(true, 'Creating\u2026');\n this.existing(name, language, variant)\n .then((found) => {\n if (found) {\n form.setBusy(false);\n form.setError(`${name} (${language}${variant ? ` \u00B7 ${variant}` : ''}) already exists.`);\n return;\n }\n return transport.createEntity({ owner: { urn: owner }, status: 'DRAFT_UNPUBLISHED', name, language, variant }).then((entity) => {\n this.deps.created(entity);\n options.onCreated(entity);\n });\n })\n .catch((error: unknown) => {\n // Not retried automatically: a retry could create a second entity.\n form.setBusy(false);\n form.setError(describeFailure(error, 'create the entity').message);\n });\n },\n options.onCancel,\n );\n if (options.hint) form.element.insertBefore(el('p', 'hint', options.hint), form.element.querySelector('label'));\n return form;\n }\n\n /** The entity already at a path, language and variant, if any. The view may answer another language's, which does not count. */\n private async existing(path: string, language: string, variant: string): Promise<Entity | undefined> {\n try {\n const entity = await this.deps.transport.entityView(path, { version: 'LATEST', language, variant });\n const same = displayPath(entity.name) === path && entity.language.toLowerCase() === language.toLowerCase() && (entity.variant ?? '') === variant;\n return same ? entity : undefined;\n } catch (error) {\n if (isBaackApiError(error) && error.isNotFound) return undefined;\n throw error;\n }\n }\n\n /** A new entity with the same owner, language and variant, filled with this one's items. */\n offerNewPageLike(entityUrn: string): void {\n const { transport, panels, store, context } = this.deps;\n const view = store.view(entityUrn);\n if (!view) return;\n const form = new SimpleForm(\n 'New page like this',\n [{ key: 'name', label: 'Path of the new page', value: '' }],\n 'Create page',\n (values) => {\n const name = values['name'] ?? '';\n const owner = view.raw.owner?.urn ?? context.company?.urn;\n if (!name.startsWith('/')) return form.setError('The path must start with /, like /blog/new-post.');\n if (isIndexName(name)) return form.setError(`Content has no index: give it a name of its own, without a trailing /, such as ${defaultEntityName(name)}.`);\n if (!owner) return form.setError('No company was found to own the content.');\n form.setError('');\n form.setBusy(true, 'Creating\u2026');\n transport\n .createEntity({ owner: { urn: owner }, status: 'DRAFT_UNPUBLISHED', name, language: view.language, variant: view.variant ?? '' })\n .then((created) => this.copyItems(entityUrn, created.urn, name, 0))\n .catch((error: unknown) => {\n form.setBusy(false);\n form.setError(describeFailure(error, 'create the page').message);\n });\n },\n );\n panels.show(form.element, { entityUrn });\n }\n\n /** Posts the source entity's items to the new one, one by one, from `start`. */\n private async copyItems(sourceUrn: string, targetUrn: string, path: string, start: number): Promise<void> {\n const { transport, panels, store, registry } = this.deps;\n const view = store.view(sourceUrn)!;\n const items: [TypeEntry, ContentItem][] = registry.flatMap((entry) =>\n ((view.raw[entry.entityArray] ?? []) as ContentItem[]).map((item): [TypeEntry, ContentItem] => [entry, item]),\n );\n const progress = el('p', 'hint');\n progress.setAttribute('role', 'status');\n const panel = el('div', 'simple-form');\n panel.append(el('div', 'title', `Creating ${path}`), progress);\n panels.show(panel, { entityUrn: sourceUrn });\n\n for (let index = start; index < items.length; index += 1) {\n const [entry, item] = items[index]!;\n progress.textContent = `Copying item ${index + 1} of ${items.length}\u2026`;\n try {\n // The view holds renderings of markdown and templates; copy their source.\n const value = entry.renderedByView ? valueOf(entry, await transport.read(entry, item.urn!)) : valueOf(entry, item);\n const slot = { name: item.name, sortOrder: item.sortOrder } as ContentItem;\n await transport.create(entry, toRepresentation(entry, slot, value, targetUrn));\n } catch (error) {\n progress.textContent = `Copied ${index} of ${items.length}. ${describeFailure(error, `copy ${item.name}`).message}`;\n const retry = el('button', 'primary', 'Copy the rest');\n retry.type = 'button';\n // Safe to repeat: a create at an existing name and sort order drafts over that item.\n retry.addEventListener('click', () => void this.copyItems(sourceUrn, targetUrn, path, index));\n panel.append(actions(retry));\n return;\n }\n }\n const link = el('a', '', `Open ${path}`);\n link.href = path;\n progress.textContent = `Created ${path} in draft with ${items.length} items. Images need their files uploaded again. A site built ahead of time shows the page after its next build.`;\n panel.append(actions(link));\n }\n\n private async owners(): Promise<Company[]> {\n const fallback = this.deps.context.company ? [this.deps.context.company] : [];\n try {\n const companies = await this.deps.transport.companies();\n const preferred = this.deps.context.company?.urn;\n return companies.length > 0\n ? [...companies].sort((a, b) => (a.urn === preferred ? -1 : b.urn === preferred ? 1 : 0))\n : fallback;\n } catch {\n return fallback;\n }\n }\n}\n\nfunction snippet(urn: string): HTMLElement {\n const wrapper = el('div', 'simple-form');\n const code = el('pre', 'snippet', `<html data-entity-urn=\"${urn}\">`);\n const copy = el('button', '', 'Copy');\n copy.type = 'button';\n copy.addEventListener('click', () => {\n navigator.clipboard?.writeText(`data-entity-urn=\"${urn}\"`).then(\n () => (copy.textContent = 'Copied'),\n () => (copy.textContent = 'Select and copy it'),\n );\n });\n wrapper.append(code, actions(copy));\n return wrapper;\n}\n\nfunction actions(...children: HTMLElement[]): HTMLElement {\n const row = el('div', 'actions');\n row.append(...children);\n return row;\n}\n", "// The Review level (docs/plans/single-sidebar.md): every change that will go\n// live, and the Schedule level it drills into.\n\nimport type { DiffPart } from '../core/diff.ts';\nimport { renderChange } from './change.ts';\nimport { el } from './host.ts';\nimport { tooltip } from './tooltip.ts';\n\nexport interface ReviewChange {\n name: string;\n sortOrder: number;\n type: string;\n /** `changed` includes a move or rename with the value unchanged: the move is then the `change`. */\n kind: 'changed' | 'new' | 'removed';\n change: DiffPart[] | string;\n /** Beside a changed value: \"moved #1 \u2192 #0 (\u22121)\", \"renamed from \u2026\". */\n notes?: string[];\n /** Opens the item's history. */\n select?(): void;\n}\n\nexport interface ReviewModel {\n changes: ReviewChange[];\n /** Problems that stop publishing. */\n blockers: string[];\n warnings: string[];\n /** Publish, or request approval when the user cannot publish. */\n confirmLabel: string;\n note?: string;\n}\n\nexport interface ReviewActions {\n confirm(button: HTMLButtonElement): void;\n /** Drills into the Schedule level; only when the content can be scheduled. */\n schedule?(): void;\n}\n\n/**\n * Fills the Review level's body: what blocks or warns, every change that\n * will go live, then Publish (or Request approval) and Schedule\u2026. Closing is\n * Back or the sidebar's Close: a Cancel beside the changes would read as\n * abandoning them, which is a different action.\n */\nexport function renderReview(body: HTMLElement, model: ReviewModel, actions: ReviewActions): void {\n const status = el('p', 'hint', model.note ?? '');\n status.setAttribute('role', 'status');\n const parts: HTMLElement[] = [status];\n for (const blocker of model.blockers) parts.push(el('p', 'error', blocker));\n for (const warning of model.warnings) parts.push(el('p', 'issues', warning));\n\n const list = el('ul', 'rows');\n list.setAttribute('aria-label', 'Changes that will go live');\n for (const change of model.changes) {\n const row = el('li', 'row history-row');\n const head = el('div', 'row-main');\n const name = change.select ? el('button', 'row-name link', change.name) : el('span', 'row-name', change.name);\n if (name instanceof HTMLButtonElement) {\n name.type = 'button';\n tooltip(name, 'Show its history');\n name.addEventListener('click', () => change.select?.());\n }\n head.append(\n name,\n el('span', 'meta', ` #${change.sortOrder} \u00B7 ${change.type}`),\n el('span', `status status-${change.kind === 'changed' ? 'unpublished-changes' : 'note'}`, change.kind),\n ...(change.notes ?? []).map((note) => el('span', 'status note move', note)),\n );\n row.append(head, renderChange(change.change));\n list.append(row);\n }\n if (model.changes.length === 0) parts.push(el('p', 'hint', 'Nothing has changed since the last publish.'));\n parts.push(list);\n\n const buttons = el('div', 'actions');\n if (actions.schedule) {\n const run = actions.schedule;\n const schedule = el('button', '', 'Schedule\u2026');\n schedule.type = 'button';\n tooltip(schedule, 'Publish at a later time');\n schedule.disabled = model.blockers.length > 0;\n schedule.addEventListener('click', () => run());\n buttons.append(schedule);\n }\n const confirm = el('button', 'primary', model.confirmLabel);\n confirm.type = 'button';\n confirm.disabled = model.blockers.length > 0;\n confirm.addEventListener('click', () => actions.confirm(confirm));\n buttons.append(confirm);\n parts.push(buttons);\n body.replaceChildren(...parts);\n}\n\n/**\n * Fills the Schedule level: when to publish, in the user's local time, and\n * the button that schedules it. Only content that has never been public can\n * be scheduled.\n */\nexport function renderSchedule(body: HTMLElement, label: string, schedule: (at: string, button: HTMLButtonElement) => void, cancel: () => void): void {\n const hint = el('p', 'hint', 'The content goes live by itself at this time. Until then it stays a draft, and you can cancel the schedule.');\n const field = el('label', 'field');\n const at = el('input');\n at.type = 'datetime-local';\n field.append(el('span', 'caption', 'Publish at (your local time)'), at);\n const buttons = el('div', 'actions');\n const back = el('button', '', 'Cancel');\n back.type = 'button';\n back.addEventListener('click', cancel);\n const confirm = el('button', 'primary', label);\n confirm.type = 'button';\n confirm.disabled = true;\n at.addEventListener('input', () => (confirm.disabled = !at.value));\n confirm.addEventListener('click', () => schedule(at.value, confirm));\n buttons.append(back, confirm);\n body.replaceChildren(hint, field, buttons);\n}\n", "// The entity lifecycle: the status the server reports (never one the editor\n// expects, CLAUDE.md rule 7), the verbs available from it, polling while a\n// publish is in flight, the review, and requests for approval. The review,\n// the schedule and going back to draft are sidebar levels above the entity's\n// (docs/plans/single-sidebar.md).\n\nimport type { Entity } from '@baack-software/baack-ts-client';\nimport { parseTimestamp } from '@baack-software/baack-ts-components/format';\nimport { diffWords, type DiffPart } from './core/diff.ts';\nimport { dispatchEntityPublished, dispatchEntityState } from './core/events.ts';\nimport { sameValue, valueOf, type ContentItem, type TypeEntry } from './core/registry.ts';\nimport { summarise, summariseChange } from './saving.ts';\nimport { isLive, lifecycleLabel, pageFirst, type EditorContext } from './targets.ts';\nimport { el } from './ui/host.ts';\nimport { renderReview, renderSchedule, type ReviewChange } from './ui/review-view.ts';\nimport { confirmLevel, type Level, type SidebarStack } from './ui/stack.ts';\nimport type { LifecycleRow } from './ui/toolbar.ts';\nimport type { PageView } from './view.ts';\n\n/** Seconds between status reads while publishing: quick at first, then every 15 seconds. */\nconst BACKOFF = [1, 2, 4, 8, 15];\n\ninterface Tracked {\n status: Entity['status'];\n /** When this entity was first seen in PUBLISH, to notice one that is stuck. */\n publishingSince?: number;\n timer?: ReturnType<typeof setTimeout>;\n attempt: number;\n}\n\nexport interface PublishingHooks {\n /** Shows a level in the sidebar above an entity's level. */\n show(level: Level, entityUrn: string): void;\n}\n\nexport class Publishing {\n private readonly ctx: EditorContext;\n private readonly stack: SidebarStack;\n private readonly hooks: PublishingHooks;\n /** The Review level in the stack, refreshed in place when the content changed under it. */\n private reviewing: { entityUrn: string; id: string; body: HTMLElement } | undefined;\n private readonly view: PageView;\n private readonly tracked = new Map<string, Tracked>();\n private readonly stuckAfterMs: number;\n private active = false;\n\n constructor(ctx: EditorContext, view: PageView, stuckAfterMs: number, stack: SidebarStack, hooks: PublishingHooks) {\n this.ctx = ctx;\n this.view = view;\n this.stuckAfterMs = stuckAfterMs;\n this.stack = stack;\n this.hooks = hooks;\n // A colleague may have started a transition: re-read when the tab comes back.\n window.addEventListener('focus', () => void this.refreshAll());\n document.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'visible') void this.refreshAll();\n });\n }\n\n start(): void {\n this.active = true;\n this.render();\n }\n\n stop(): void {\n this.active = false;\n for (const tracked of this.tracked.values()) clearTimeout(tracked.timer);\n this.tracked.clear();\n this.reviewing = undefined;\n this.ctx.toolbar.setLifecycle([]);\n }\n\n /** Content was read: take each entity's status from the view, as the server reported it. */\n changed(): void {\n if (!this.active) return;\n for (const urn of this.ctx.store.entities()) {\n const status = this.ctx.store.view(urn)?.status;\n if (status) this.observe(urn, status);\n }\n this.render();\n }\n\n async refreshAll(): Promise<void> {\n if (!this.active) return;\n await Promise.all(this.ctx.store.entities().map((urn) => this.refreshStatus(urn)));\n }\n\n /** Reads an entity's status from the API. */\n async refreshStatus(entityUrn: string): Promise<void> {\n try {\n const entity = await this.ctx.transport.readEntity(entityUrn);\n this.observe(entityUrn, entity.status, entity.publishTimestamp ?? undefined);\n this.render();\n } catch (error) {\n void this.ctx.feedback.report(error, 'check the publishing status', () => void this.refreshStatus(entityUrn));\n }\n }\n\n private observe(entityUrn: string, status: Entity['status'], publishTimestamp?: string): void {\n const view = this.ctx.store.view(entityUrn);\n if (view) {\n // Other modules read the status from the view; keep it current.\n const raw = view.raw as Entity;\n raw.status = status;\n if (publishTimestamp !== undefined) raw.publishTimestamp = publishTimestamp;\n }\n const tracked = this.tracked.get(entityUrn);\n const previous = tracked?.status;\n const next: Tracked = tracked ?? { status, attempt: 0 };\n next.status = status;\n if (status === 'PUBLISH') {\n next.publishingSince ??= Date.now();\n this.poll(entityUrn, next);\n } else {\n clearTimeout(next.timer);\n delete next.timer;\n delete next.publishingSince;\n next.attempt = 0;\n }\n this.tracked.set(entityUrn, next);\n if (previous !== undefined && previous !== status) {\n dispatchEntityState({ entityUrn, status, previous });\n if (previous === 'PUBLISH' && isLive(status)) this.published(entityUrn);\n }\n }\n\n /** A publish finished: say so, and re-read so the page, Items and history show the new live versions. */\n private published(entityUrn: string): void {\n dispatchEntityPublished(entityUrn);\n this.ctx.announcePublished(entityUrn, `${this.ctx.entityTitle(entityUrn)} is published.`);\n void this.view.refresh(entityUrn);\n }\n\n /** While publishing, read the status again with backoff until it settles. Scheduled entities are not polled. */\n private poll(entityUrn: string, tracked: Tracked): void {\n if (tracked.timer) return;\n const seconds = BACKOFF[Math.min(tracked.attempt, BACKOFF.length - 1)]!;\n tracked.attempt += 1;\n tracked.timer = setTimeout(() => {\n delete tracked.timer;\n if (this.active) void this.refreshStatus(entityUrn);\n }, seconds * 1000);\n }\n\n private render(): void {\n if (!this.active) return;\n const rows: LifecycleRow[] = pageFirst(this.ctx.store, this.ctx.store.entities()).map((urn) => this.row(urn));\n this.ctx.toolbar.setLifecycle(rows);\n }\n\n private row(entityUrn: string): LifecycleRow {\n const { canPublish } = this.ctx;\n const view = this.ctx.store.view(entityUrn);\n const status = this.tracked.get(entityUrn)?.status ?? view?.status;\n const title = this.ctx.entityTitle(entityUrn);\n const publish = canPublish ? 'Publish\u2026' : 'Request approval\u2026';\n const review = canPublish ? 'Review and publish\u2026' : 'Request approval\u2026';\n const row: LifecycleRow = { entityUrn, title, label: lifecycleLabel(status), verbs: [] };\n switch (status) {\n case 'DRAFT_UNPUBLISHED':\n row.verbs.push({ label: publish, primary: true, run: () => void this.openReview(entityUrn) });\n break;\n case 'PUBLISH_PENDING': {\n const at = view?.raw.publishTimestamp;\n if (at) row.label = `Scheduled for ${new Date(parseTimestamp(at)).toLocaleString()}`;\n if (canPublish) row.verbs.push({ label: 'Cancel schedule', run: () => this.confirmDraft(entityUrn, 'Cancel the schedule?') });\n break;\n }\n case 'PUBLISH': {\n const since = this.tracked.get(entityUrn)?.publishingSince ?? Date.now();\n if (Date.now() - since > this.stuckAfterMs) {\n row.note = 'Publishing is taking longer than expected. Publishing again is safe; if that does not help, contact support.';\n if (canPublish) row.verbs.push({ label: 'Publish again', run: () => void this.setStatus(entityUrn, 'PUBLISH', undefined) });\n }\n break;\n }\n case 'PUBLISHED_WITH_DRAFTS':\n row.verbs.push({ label: review, primary: true, run: () => void this.openReview(entityUrn) });\n if (canPublish) row.verbs.push({ label: 'Unpublish', run: () => this.confirmDraft(entityUrn, 'Unpublish this content?') });\n break;\n case 'PUBLISHED':\n if (canPublish) row.verbs.push({ label: 'Unpublish', run: () => this.confirmDraft(entityUrn, 'Unpublish this content?') });\n break;\n default:\n break;\n }\n return row;\n }\n\n /** Back to draft: not public, not deleted. Used for unpublishing and for cancelling a schedule. */\n private confirmDraft(entityUrn: string, question: string): void {\n this.hooks.show(\n confirmLevel({\n id: `draft:${entityUrn}`,\n title: question,\n meta: this.ctx.entityTitle(entityUrn),\n blocks: [],\n description: 'The content stays in Baack but is no longer public. You can publish it again, now or at a later time.',\n choices: [\n { label: 'Cancel', run: () => this.stack.pop() },\n {\n label: 'Back to draft',\n primary: true,\n run: (button) => {\n button.disabled = true;\n void this.setStatus(entityUrn, 'DRAFT_UNPUBLISHED', undefined).then((done) => {\n if (done) this.stack.popTo(`entity:${entityUrn}`);\n else button.disabled = false;\n });\n },\n },\n ],\n }),\n entityUrn,\n );\n }\n\n // ---------------------------------------------------------------------\n // The review\n // ---------------------------------------------------------------------\n\n /**\n * Opens the Review level for an entity: every change that will go live. A\n * review already in the stack is refreshed in place, with `note` saying why.\n */\n async openReview(entityUrn: string, note?: string): Promise<void> {\n const { store, views, canPublish } = this.ctx;\n const status = store.view(entityUrn)?.status;\n if (status === 'PUBLISH') return; // No verbs during a verb state.\n let live: Entity | undefined;\n try {\n live = await views.read(entityUrn);\n } catch {\n live = undefined; // Never published, or not public (in this language): everything is new.\n }\n const latest = store.view(entityUrn)!.raw;\n const shown = latestUrns(latest, this.ctx.registry);\n const changes = await this.changes(entityUrn, latest, live);\n const { blockers, warnings } = await this.checks(latest);\n const id = `review:${entityUrn}`;\n const count = `${changes.length} ${changes.length === 1 ? 'change' : 'changes'}`;\n const existing = this.reviewing?.id === id && this.stack.path.includes(id) ? this.reviewing : undefined;\n const body = existing?.body ?? el('div', 'level-review');\n renderReview(\n body,\n {\n changes,\n blockers,\n warnings,\n confirmLabel: canPublish ? `Publish ${count}` : 'Request approval',\n ...(note ? { note } : {}),\n },\n {\n confirm: (button) => void this.confirm(entityUrn, shown, changes, undefined, button),\n // Only content that has never been public can go live at a later time.\n ...(canPublish && status === 'DRAFT_UNPUBLISHED' ? { schedule: () => this.stack.push(this.scheduleLevel(entityUrn, shown, changes, `Schedule ${count}`)) } : {}),\n },\n );\n if (existing) {\n this.stack.popTo(id);\n return;\n }\n this.reviewing = { entityUrn, id, body };\n const path = this.ctx.entityTitle(entityUrn).replace(/^Content for /, '');\n this.hooks.show(\n {\n id,\n title: `${canPublish ? 'Review and publish' : 'Request approval for'} ${path}`,\n render: () => body,\n dispose: () => {\n if (this.reviewing?.body === body) this.reviewing = undefined;\n },\n },\n entityUrn,\n );\n }\n\n private scheduleLevel(entityUrn: string, shown: Set<string>, changes: ReviewChange[], label: string): Level {\n const body = el('div', 'level-schedule');\n renderSchedule(body, label, (at, button) => void this.confirm(entityUrn, shown, changes, at, button), () => this.stack.pop());\n return { id: `schedule:${entityUrn}`, title: 'Schedule the publish', render: () => body };\n }\n\n /** Re-checks before sending: if any version differs from the list shown, refresh the list instead. */\n private async confirm(entityUrn: string, shown: Set<string>, changes: ReviewChange[], at: string | undefined, button: HTMLButtonElement): Promise<void> {\n const { views, feedback, canPublish } = this.ctx;\n button.disabled = true;\n try {\n const fresh = await views.read(entityUrn, { version: 'LATEST' });\n const now = latestUrns(fresh, this.ctx.registry);\n if (now.size !== shown.size || [...now].some((urn) => !shown.has(urn))) {\n await this.view.refresh(entityUrn);\n await this.openReview(entityUrn, 'The content changed while you were reviewing. Check the list again before publishing.');\n return;\n }\n if (canPublish) {\n const when = at ? new Date(at).toISOString().replace('Z', '') : undefined;\n if (!(await this.setStatus(entityUrn, 'PUBLISH', when))) {\n button.disabled = false;\n return;\n }\n } else {\n await this.requestApproval(entityUrn, changes);\n }\n // Done: back to the entity, where the lifecycle shows what the server reports.\n this.stack.popTo(`entity:${entityUrn}`);\n } catch (error) {\n button.disabled = false;\n void feedback.report(error, canPublish ? 'publish' : 'request approval', () => void this.confirm(entityUrn, shown, changes, at, button));\n }\n }\n\n /** Sends a lifecycle verb with the entity's own fields: never the item arrays. False when it failed (and was reported). */\n private async setStatus(entityUrn: string, status: 'PUBLISH' | 'DRAFT_UNPUBLISHED', publishTimestamp: string | undefined): Promise<boolean> {\n const { transport, feedback } = this.ctx;\n try {\n const entity = await transport.readEntity(entityUrn);\n const updated = await transport.updateEntity(entityUrn, {\n owner: { urn: entity.owner!.urn },\n name: entity.name,\n language: entity.language,\n variant: entity.variant ?? '',\n status,\n ...(publishTimestamp ? { publishTimestamp } : {}),\n });\n const before = this.tracked.get(entityUrn)?.status;\n this.observe(entityUrn, updated.status, updated.publishTimestamp ?? undefined);\n // A publish that completes in the request answers a live status straight away, never PUBLISH.\n if (status === 'PUBLISH' && before !== 'PUBLISH' && isLive(updated.status)) {\n if (updated.status === 'PUBLISHED') {\n this.published(entityUrn);\n } else {\n // Still with drafts after publishing: show what the server reports, not what was expected (rule 7).\n this.ctx.announcePublished(entityUrn, `${this.ctx.entityTitle(entityUrn)} was published, but some changes are still not live.`, { info: false });\n void this.view.refresh(entityUrn);\n }\n }\n this.render();\n if (status === 'DRAFT_UNPUBLISHED') await this.view.refresh(entityUrn);\n return true;\n } catch (error) {\n void feedback.report(error, status === 'PUBLISH' ? 'publish' : 'move the content back to draft', () =>\n void this.setStatus(entityUrn, status, publishTimestamp),\n );\n return false;\n }\n }\n\n /** For users who cannot publish: a task linked to the entity, listing the changes. */\n private async requestApproval(entityUrn: string, changes: ReviewChange[]): Promise<void> {\n const { transport, store, toolbar } = this.ctx;\n const view = store.view(entityUrn)!;\n const owner = view.raw.owner?.urn;\n const path = this.ctx.entityTitle(entityUrn).replace(/^Content for /, '');\n const lines = changes.map((change) => `- ${change.name} #${change.sortOrder} (${change.type}): ${change.kind}`);\n const task = await transport.createTask({\n ...(owner ? { owner: { urn: owner } as never } : {}),\n title: `Review and publish ${path}`,\n description: [`Page: ${location.href}`, `Entity: ${entityUrn}`, '', 'Changes:', ...lines].join('\\n'),\n status: 'PENDING',\n priority: 'MEDIUM',\n associatedEntities: [{ urn: entityUrn } as never],\n });\n toolbar.showMessage(`Approval requested (task ${task.urn?.slice(0, 8) ?? ''}).`, true);\n }\n\n // ---------------------------------------------------------------------\n // Building the review list\n // ---------------------------------------------------------------------\n\n /**\n * Every change that will go live, item by item. A draft is compared with\n * its own live version, found through its history, so a moved or renamed\n * item reads as a move (\"#1 \u2192 #0 (\u22121)\") rather than as a different value\n * in the slot. Without a readable history, the live item in the same slot\n * stands in.\n */\n private async changes(entityUrn: string, latest: Entity, live: Entity | undefined): Promise<ReviewChange[]> {\n // A draft's name opens its history above the review, so Back returns to the review.\n const select = (entry: TypeEntry, item: ContentItem) => () =>\n item.urn ? this.ctx.hooks.openHistory({ entityUrn, entry, name: item.name, sortOrder: item.sortOrder, urn: item.urn }) : undefined;\n const changes: ReviewChange[] = [];\n for (const entry of this.ctx.registry) {\n const latestItems = (latest[entry.entityArray] ?? []) as ContentItem[];\n const liveItems = (live?.[entry.entityArray] ?? []) as ContentItem[];\n const liveByUrn = new Map(liveItems.map((item) => [item.urn, item]));\n const slot = (item: ContentItem) => `${item.name}#${item.sortOrder}`;\n const liveBySlot = new Map(liveItems.map((item) => [slot(item), item]));\n const drafts = latestItems.filter((item) => !liveByUrn.has(item.urn));\n const befores = await Promise.all(drafts.map((item) => this.liveVersionOf(entry, item, liveByUrn, liveBySlot.get(slot(item)))));\n const accounted = new Set<string | undefined>(latestItems.filter((item) => liveByUrn.has(item.urn)).map((item) => item.urn));\n drafts.forEach((item, index) => {\n const before = befores[index];\n if (before) accounted.add(before.urn);\n const notes = before ? moveNotes(before, item) : [];\n const valueChanged = !before || !sameValue(entry, valueOf(entry, before), valueOf(entry, item));\n changes.push({\n name: item.name,\n sortOrder: item.sortOrder,\n type: entry.label,\n kind: !before ? 'new' : 'changed',\n // A move or rename alone is the change itself (\"Moved #3 \u2192 #2 (\u22121)\"); beside a new value it is a note.\n change: valueChanged ? describe(entry, before, item) : sentence(notes.join('; ')),\n ...(valueChanged && notes.length > 0 ? { notes } : {}),\n select: select(entry, item),\n });\n });\n for (const item of liveItems) {\n if (!accounted.has(item.urn) && !latestItems.some((other) => slot(other) === slot(item))) {\n changes.push({ name: item.name, sortOrder: item.sortOrder, type: entry.label, kind: 'removed', change: describe(entry, item, undefined) });\n }\n }\n }\n return changes;\n }\n\n /** The live version of a draft's item: the newest version in its history that is live, else the live item in its slot. */\n private async liveVersionOf(\n entry: TypeEntry,\n draft: ContentItem,\n liveByUrn: Map<string | undefined, ContentItem>,\n inSlot: ContentItem | undefined,\n ): Promise<ContentItem | undefined> {\n try {\n const { history, pagination } = await this.ctx.transport.history(entry, draft.urn!);\n const found = history.find((version) => liveByUrn.has(version.urn));\n if (found) return liveByUrn.get(found.urn);\n // No live version in the history: the item is new, unless older pages could still hold one.\n return pagination?.isMorePages ? inSlot : undefined;\n } catch {\n return inSlot;\n }\n }\n\n /** Blockers (an image without its file) and warnings (referenced content that is not fully published). */\n private async checks(latest: Entity): Promise<{ blockers: string[]; warnings: string[] }> {\n const blockers = (latest.images ?? []).flatMap((image) =>\n missingSlots(image, this.ctx.requiredImageSlots).map(\n (slot) => `${image.name} #${image.sortOrder} has no ${slot === 'DEFAULT' ? 'image' : slot.toLowerCase()} file. Upload one before publishing.`,\n ),\n );\n const warnings: string[] = [];\n for (const reference of latest.references ?? []) {\n const urn = reference.entityReference?.urn;\n if (!urn) continue;\n try {\n const referenced = await this.ctx.transport.readEntity(urn);\n if (referenced.status === 'DRAFT_UNPUBLISHED' || referenced.status === 'PUBLISHED_WITH_DRAFTS') {\n warnings.push(`${reference.name} refers to content that ${referenced.status === 'DRAFT_UNPUBLISHED' ? 'is not published' : 'has unpublished changes'} (${referenced.name}).`);\n }\n } catch {\n warnings.push(`${reference.name} refers to content that could not be checked.`);\n }\n }\n return { blockers, warnings };\n }\n}\n\n/** The required slots an image version has no file for. */\nexport function missingSlots(image: object, required: readonly ('DEFAULT' | 'MEDIUM' | 'LARGE')[]): ('DEFAULT' | 'MEDIUM' | 'LARGE')[] {\n const fields = { DEFAULT: 'src', MEDIUM: 'mediumSrc', LARGE: 'largeSrc' } as const;\n return required.filter((slot) => !(image as Record<string, unknown>)[fields[slot]]);\n}\n\n/** Every version URN in an entity view. */\nfunction latestUrns(entity: Entity, registry: readonly TypeEntry[]): Set<string> {\n const urns = new Set<string>();\n for (const entry of registry) {\n for (const item of (entity[entry.entityArray] ?? []) as ContentItem[]) if (item.urn) urns.add(item.urn);\n }\n return urns;\n}\n\n/** What readers will see change: a word diff of text, or of the rendered text for markdown and templates. */\nfunction describe(entry: TypeEntry, before: ContentItem | undefined, after: ContentItem | undefined): DiffPart[] | string {\n const text = (item: ContentItem | undefined) => {\n const value = (item as { value?: unknown } | undefined)?.value;\n if (typeof value !== 'string') return undefined;\n return entry.renderedByView ? (new DOMParser().parseFromString(value, 'text/html').body.textContent ?? '') : value;\n };\n const was = text(before);\n const now = text(after);\n if (was !== undefined || now !== undefined) return diffWords(was ?? '', now ?? '');\n if (!before) return summarise(entry, after!);\n if (!after) return `Removed: ${summarise(entry, before)}`;\n return summariseChange(entry, before, after);\n}\n\n/** \"renamed from \u2026\" and \"moved #1 \u2192 #0 (\u22121)\", comparing a draft with its live version. */\nconst sentence = (text: string) => text.charAt(0).toUpperCase() + text.slice(1);\n\nfunction moveNotes(before: ContentItem, after: ContentItem): string[] {\n const notes: string[] = [];\n if (before.name !== after.name) notes.push(`renamed from ${before.name}`);\n const delta = after.sortOrder - before.sortOrder;\n if (delta !== 0) notes.push(`moved #${before.sortOrder} \u2192 #${after.sortOrder} (${delta > 0 ? '+' : '\u2212'}${Math.abs(delta)})`);\n return notes;\n}\n", "// The item outline: every item an entity holds, grouped by where it shows,\n// with status and flags. Built from the entity view, not the DOM, so it\n// reaches items with no element (head, JSON, references, hidden content).\n//\n// It is explored as a stack (docs/plans/single-sidebar.md): the page's\n// entities, then one entity (its lifecycle and items), and deeper levels on\n// top. The stack is the editor's one sidebar, the \"Editor\" landmark.\n\nimport { button as actionButton, el, type EditorHost, variantOf } from './host.ts';\nimport { SidebarStack } from './stack.ts';\n\nexport interface OutlineAction {\n label: string;\n run(anchor: HTMLElement): void;\n primary?: boolean;\n /** Shown as a destructive button: it deletes or discards. */\n destructive?: boolean;\n /** Why it cannot be used now; the button is disabled with this as its title. */\n disabled?: string;\n}\n\nexport interface OutlineRow {\n name: string;\n sortOrder: number;\n type: string;\n /** Publication status; empty when it would say nothing (the entity is not live). */\n status: string;\n /** Neutral notes, such as \"not used\". */\n notes?: string[];\n /** Problems worth fixing. */\n flags: string[];\n /** Opens the item: scroll to it and edit, or edit beside the row. */\n select?(anchor: HTMLElement): void;\n action?: OutlineAction;\n /** More actions, after `action`. */\n actions?: OutlineAction[];\n /** The row the view is about, highlighted (for example the item being moved). */\n current?: boolean;\n}\n\nexport interface OutlineGroup {\n label: string;\n /** One line explaining the group. */\n hint?: string;\n rows: OutlineRow[];\n action?: OutlineAction;\n}\n\nexport interface OutlineSection {\n /** The entity's lifecycle state, from the server. */\n subtitle?: string;\n /** More about the state, such as a publish taking too long. */\n note?: string;\n /** The lifecycle's verbs (publish, unpublish, schedule). */\n verbs?: OutlineAction[];\n groups: OutlineGroup[];\n actions: OutlineAction[];\n}\n\nexport class Outline {\n readonly stack: SidebarStack;\n private readonly onOpen: () => void;\n\n /** `onOpen` runs whenever the sidebar comes on screen; `onClose` when it is closed. */\n constructor(host: EditorHost, onOpen: () => void, onClose: () => void = () => {}) {\n this.onOpen = onOpen;\n this.stack = new SidebarStack(host);\n this.stack.element.classList.add('outline');\n this.stack.onClose(onClose);\n }\n\n get element(): HTMLElement {\n return this.stack.element;\n }\n\n /** The sidebar is on screen. */\n get isOpen(): boolean {\n return this.stack.isOpen;\n }\n\n open(): void {\n this.stack.open();\n this.onOpen();\n }\n\n close(): void {\n this.stack.close();\n }\n\n /** Focuses the filter of the level on screen, if it has one. */\n focusFilter(): void {\n this.element.querySelector<HTMLElement>('.stack-level:not([hidden]) input[type=\"search\"]')?.focus();\n }\n\n /**\n * Fills an entity level's body: its lifecycle, a filter, its groups of\n * items, then its actions. The filter's text is kept across refreshes.\n */\n renderSection(body: HTMLElement, section: OutlineSection): void {\n const filter = body.querySelector<HTMLInputElement>('input[type=\"search\"]')?.value ?? '';\n const parts: HTMLElement[] = [];\n if (section.subtitle || section.verbs?.length) {\n const lifecycle = el('div', 'level-lifecycle');\n lifecycle.setAttribute('role', 'group');\n lifecycle.setAttribute('aria-label', 'Lifecycle');\n if (section.subtitle) lifecycle.append(el('p', 'section-status lifecycle-status', section.subtitle));\n if (section.note) lifecycle.append(el('p', 'message', section.note));\n if (section.verbs?.length) {\n const verbs = el('div', 'actions');\n verbs.append(...section.verbs.map((verb) => this.button(verb)));\n lifecycle.append(verbs);\n }\n parts.push(lifecycle);\n }\n const input = el('input');\n input.type = 'search';\n input.placeholder = 'Filter by name or type';\n input.setAttribute('aria-label', 'Filter items');\n input.value = filter;\n input.addEventListener('input', () => applyFilter(body, input.value));\n parts.push(input);\n for (const group of section.groups) {\n if (group.rows.length === 0) continue;\n const groupElement = el('div', 'outline-group');\n const heading = el('div', 'group-heading');\n heading.append(el('span', 'group-label', `${group.label} (${group.rows.length})`));\n if (group.action) heading.append(this.button(group.action));\n groupElement.append(heading);\n if (group.hint) groupElement.append(el('p', 'group-hint', group.hint));\n const list = el('ul', 'rows');\n list.setAttribute('aria-label', group.label);\n list.append(...group.rows.map((row) => this.row(row)));\n groupElement.append(list);\n parts.push(groupElement);\n }\n if (section.actions.length > 0) {\n const actions = el('div', 'actions');\n actions.append(...section.actions.map((action) => this.button(action)));\n parts.push(actions);\n }\n body.replaceChildren(...parts);\n applyFilter(body, filter);\n body.querySelector('li.row.current')?.scrollIntoView({ block: 'nearest' });\n }\n\n private row(row: OutlineRow): HTMLElement {\n const item = el('li', row.current ? 'row current' : 'row');\n if (row.current) item.setAttribute('aria-current', 'true');\n item.dataset['filter'] = `${row.name} ${row.type}`.toLowerCase();\n const main = el(row.select ? 'button' : 'div', 'row-main');\n if (main instanceof HTMLButtonElement) {\n main.type = 'button';\n main.dataset['row'] = '';\n main.addEventListener('click', () => row.select?.(item));\n }\n main.append(\n el('span', 'row-name', row.name),\n el('span', 'meta', ` #${row.sortOrder} \u00B7 ${row.type}`),\n ...(row.status ? [el('span', `status status-${row.status.replace(/\\s+/g, '-')}`, row.status)] : []),\n ...(row.notes ?? []).map((note) => el('span', 'status note', note)),\n );\n item.append(main);\n for (const flag of row.flags) item.append(el('span', 'flag', flag));\n if (row.action) item.append(this.button(row.action));\n for (const action of row.actions ?? []) item.append(this.button(action));\n return item;\n }\n\n private button(action: OutlineAction): HTMLButtonElement {\n const button = actionButton(action.label, variantOf(action), 'sm');\n if (action.disabled) {\n button.disabled = true;\n button.title = action.disabled;\n }\n button.addEventListener('click', () => action.run(button));\n return button;\n }\n}\n\nfunction applyFilter(body: HTMLElement, value: string): void {\n const query = value.trim().toLowerCase();\n for (const row of body.querySelectorAll<HTMLElement>('li.row')) {\n row.hidden = query !== '' && !row.dataset['filter']!.includes(query);\n }\n}\n", "// Builds the item outline from the latest views, the page's elements, the\n// live views (for publication status) and unsaved work.\n\nimport { createKey } from './core/pending.ts';\nimport type { ContentItem, ItemType, TypeEntry } from './core/registry.ts';\nimport type { Editing } from './editing.ts';\nimport type { Onboarding } from './onboarding.ts';\nimport type { Saving } from './saving.ts';\nimport { isLive, lifecycleLabel, pageEntity, pageFirst, type EditTarget, type EditorContext, type PanelHandle, type PanelOptions, type Slot } from './targets.ts';\nimport { missingSlots } from './publishing.ts';\nimport { SimpleForm } from './ui/form.ts';\nimport { el } from './ui/host.ts';\nimport { Outline, type OutlineAction, type OutlineRow, type OutlineSection } from './ui/outline.ts';\nimport { drillRow, type Level } from './ui/stack.ts';\nimport type { PageView } from './view.ts';\nimport { tooltip } from './ui/tooltip.ts';\n\n// Something that looks like a tag, for the outline's flag.\nconst MARKUP = /<\\/?[a-z!][^>]*>/i;\n\nexport class OutlineModel {\n readonly outline: Outline;\n private readonly ctx: EditorContext;\n private readonly view: PageView;\n private readonly editing: Editing;\n private readonly saving: Saving;\n private readonly onboarding: Onboarding;\n /** Reads for publication status, by entity: see `counterpartUrns`. */\n private readonly live = new Map<string, Promise<{ urns: Set<string>; found: boolean }>>();\n /** Move or rename: the slots level shows one name's slots, with this sort order highlighted. */\n private focus: Slot | undefined;\n /** An item to highlight and scroll to in its entity's level. */\n private selected: Slot | undefined;\n /** The levels built for the stack, by id, each with the body it refreshes. */\n private readonly levels = new Map<string, { level: Level; body: HTMLElement; refresh(): Promise<void> | void }>();\n private closed: (() => void) | undefined;\n /** Panels shown so far, for their level ids. */\n private panels = 0;\n /** Offers \"New entity\u2026\" on the top level, while editing the latest drafts. */\n private newEntity: (() => void) | undefined;\n\n constructor(ctx: EditorContext, view: PageView, editing: Editing, saving: Saving, onboarding: Onboarding) {\n this.ctx = ctx;\n this.view = view;\n this.editing = editing;\n this.saving = saving;\n this.onboarding = onboarding;\n this.outline = new Outline(\n ctx.host,\n () => {\n if (this.outline.stack.path.length === 0) this.openAt(pageEntity(ctx.store), { focus: false });\n else void this.render();\n },\n () => {\n this.focus = undefined;\n this.selected = undefined;\n this.closed?.();\n },\n );\n }\n\n /** Runs when the sidebar closes (a preview shown from it ends). */\n onClose(listener: () => void): void {\n this.closed = listener;\n }\n\n /** Content changed; re-read live status for an entity that was re-read. */\n changed(entityUrn?: string): void {\n if (entityUrn) this.live.delete(entityUrn);\n if (this.outline.isOpen) void this.render();\n }\n\n clear(): void {\n this.outline.close();\n this.outline.stack.reset([]);\n this.levels.clear();\n this.live.clear();\n this.focus = undefined;\n }\n\n setNewEntity(run: (() => void) | undefined): void {\n this.newEntity = run;\n if (this.outline.isOpen) void this.render();\n }\n\n /** Shows Items at the page's entity (or where it was left), or closes it when it is on screen. */\n toggle(): void {\n if (this.outline.isOpen) this.outline.close();\n else this.outline.open();\n }\n\n /** Opens the stack at an entity's level, above the page's level. */\n openEntity(entityUrn: string): void {\n this.selected = undefined;\n this.focus = undefined;\n this.openAt(entityUrn);\n }\n\n /** Opens Items with an item highlighted and scrolled to. */\n selectItem(slot: Slot): void {\n this.focus = undefined;\n this.selected = { entityUrn: slot.entityUrn, entry: slot.entry, name: slot.name, sortOrder: slot.sortOrder };\n this.openAt(slot.entityUrn);\n }\n\n /** Opens Items on the slots of an item's name, to move it among them or rename it. */\n focusSlot(slot: Slot): void {\n this.focus = { entityUrn: slot.entityUrn, entry: slot.entry, name: slot.name, sortOrder: slot.sortOrder };\n this.openAt(slot.entityUrn, { slots: true });\n }\n\n /**\n * Shows a level above an entity's (an item's history, its review, a\n * confirm): drilled into from the entity's level or its review when one of\n * those is on screen, so Back returns there; otherwise the stack is built\n * to it.\n */\n showAbove(entityUrn: string, level: Level): void {\n const { stack } = this.outline;\n const from = [`entity:${entityUrn}`, `review:${entityUrn}`];\n if (this.outline.isOpen && from.includes(stack.current?.id ?? '')) {\n stack.push(level);\n return;\n }\n this.focus = undefined;\n this.selected = undefined;\n this.openAt(entityUrn, { above: level });\n }\n\n /** Shows a task as a level (see `Panels` in targets.ts). */\n showPanel(content: HTMLElement, options: PanelOptions = {}): PanelHandle {\n const { stack } = this.outline;\n const heading = content.querySelector(':scope > .title');\n const title = options.title ?? heading?.textContent ?? 'Editor';\n if (!options.title) heading?.remove();\n this.panels += 1;\n const id = `panel:${this.panels}`;\n let open = true;\n const level: Level = {\n id,\n title,\n render: () => content,\n dispose: () => {\n open = false;\n options.onLeave?.();\n },\n };\n const handle: PanelHandle = {\n get isOpen() {\n return open;\n },\n close: () => {\n const path = stack.path;\n const index = path.indexOf(id);\n if (index > 0) stack.popTo(path[index - 1]!);\n },\n };\n content.addEventListener('cancel', () => handle.close());\n const focus = options.focus ?? true;\n const showing = this.outline.isOpen && stack.path.length > 0;\n if (showing && stack.current?.id.startsWith('panel:')) {\n stack.replace(level, { focus });\n } else if (showing && (!options.entityUrn || stack.path.includes(`entity:${options.entityUrn}`))) {\n // From wherever the user is in that entity: Back returns there.\n stack.push(level, { focus });\n } else {\n this.focus = undefined;\n this.selected = undefined;\n this.openAt(options.entityUrn, { above: level, focus });\n }\n return handle;\n }\n\n private openAt(entityUrn: string | undefined, { slots = false, focus = true, above = undefined as Level | undefined } = {}): void {\n const path = [this.pageLevel()];\n if (entityUrn && this.ctx.store.view(entityUrn)) path.push(this.entityLevel(entityUrn));\n if (slots && this.focus) path.push(this.slotsLevel(this.focus));\n if (above) path.push(above);\n this.outline.stack.reset(path, { focus });\n this.outline.open();\n void this.render();\n }\n\n /** Refreshes the levels in the stack from the current state. */\n async render(): Promise<void> {\n if (!this.outline.isOpen) return;\n await Promise.all(this.outline.stack.path.map((id) => this.levels.get(id)?.refresh()));\n }\n\n private remember(level: Level, body: HTMLElement, refresh: () => Promise<void> | void): Level {\n this.levels.set(level.id, { level, body, refresh });\n return level;\n }\n\n /** The top level: the entities in this visit, page's first, with their state; New entity. */\n private pageLevel(): Level {\n const body = el('div', 'level-page');\n const level: Level = { id: 'page', title: 'This page', render: () => body };\n return this.remember(level, body, () => {\n const { store, toolbar } = this.ctx;\n const entities = pageFirst(store, store.entities());\n const parts: HTMLElement[] = entities.map((urn) =>\n drillRow(this.ctx.entityTitle(urn), toolbar.lifecycleOf(urn)?.label ?? lifecycleLabel(store.view(urn)?.status), () =>\n this.outline.stack.push(this.entityLevel(urn)),\n ),\n );\n if (entities.length === 0) parts.push(el('p', 'hint', 'No content has loaded for this page.'));\n if (this.newEntity) {\n const run = this.newEntity;\n const button = el('button', '', 'New entity\u2026');\n button.type = 'button';\n tooltip(button, 'Create an entity, such as a menu shared by many pages');\n button.addEventListener('click', () => run());\n const actions = el('div', 'actions');\n actions.append(button);\n parts.push(actions);\n }\n body.replaceChildren(...parts);\n });\n }\n\n /** One entity: its lifecycle and verbs, then its items. */\n private entityLevel(entityUrn: string): Level {\n const id = `entity:${entityUrn}`;\n const known = this.levels.get(id);\n if (known) return known.level;\n const body = el('div', 'level-entity');\n const level: Level = { id, title: this.ctx.entityTitle(entityUrn), render: () => body, onShow: () => void this.render() };\n return this.remember(level, body, async () => {\n if (!this.ctx.store.view(entityUrn)) return;\n const section = await this.section(entityUrn, entityUrn === pageEntity(this.ctx.store));\n if (this.outline.stack.path.includes(id)) this.outline.renderSection(body, section);\n });\n }\n\n /** Toggles the unsent changes, above the page's level: shown, or closed when already on screen. */\n togglePending(): void {\n if (this.outline.isOpen && this.outline.stack.current?.id === 'unsaved') {\n this.outline.close();\n return;\n }\n this.focus = undefined;\n this.selected = undefined;\n this.outline.stack.reset([this.pageLevel(), this.pendingLevel()]);\n this.outline.open();\n }\n\n /** Every entity's unsent changes, each with Save all and Discard all; kept current as they change. */\n private pendingLevel(): Level {\n const body = el('div', 'level-unsaved');\n const level: Level = { id: 'unsaved', title: 'Unsaved changes', render: () => body };\n return this.remember(level, body, () => body.replaceChildren(...this.ctx.toolbar.pendingSections()));\n }\n\n /** Move or rename: the slots of one name. */\n private slotsLevel(focus: Slot): Level {\n const body = el('div', 'level-slots');\n const level: Level = { id: 'slots', title: `Slots for ${focus.name}`, render: () => body };\n return this.remember(level, body, () => {\n if (!this.focus || !this.ctx.store.view(this.focus.entityUrn)) return;\n this.outline.renderSection(body, this.slotsSection(this.focus));\n });\n }\n\n /**\n * Every slot of one name in sort order: filled ones and free ones (the gaps,\n * when there are few, and the next after the last). The item being moved is\n * highlighted; it can swap with a filled slot, move to a free one, or be\n * renamed. Each move checks occupancy against a fresh read first.\n */\n private slotsSection(focus: Slot): OutlineSection {\n const { store, hooks } = this.ctx;\n const { entityUrn, entry, name } = focus;\n const items = ((store.view(entityUrn)!.raw[entry.entityArray] ?? []) as ContentItem[])\n .filter((item) => item.name === name && item.urn)\n .sort((a, b) => a.sortOrder - b.sortOrder);\n const moving = items.find((item) => item.sortOrder === focus.sortOrder);\n const move = async (sortOrder: number) => {\n if (!moving) return;\n if (await hooks.moveSlot(focus, moving, sortOrder)) {\n this.focus = { ...focus, sortOrder };\n void this.render();\n }\n };\n const rows: OutlineRow[] = items.map((item) =>\n item === moving\n ? {\n name,\n sortOrder: item.sortOrder,\n type: entry.label,\n status: 'moving',\n flags: [],\n current: true,\n actions: [{ label: 'Rename\u2026', run: () => hooks.rename(focus, item) }],\n }\n : {\n name,\n sortOrder: item.sortOrder,\n type: entry.label,\n status: '',\n flags: [],\n ...(moving ? { actions: [{ label: `Swap with #${moving.sortOrder}`, run: () => void move(item.sortOrder) }] } : {}),\n },\n );\n if (moving) {\n const used = new Set(items.map((item) => item.sortOrder));\n const first = items[0]?.sortOrder ?? 0;\n const last = items.at(-1)?.sortOrder ?? 0;\n const gaps = Array.from({ length: Math.max(0, last - first) }, (_, index) => first + index).filter((order) => !used.has(order));\n for (const sortOrder of [...(gaps.length <= 5 ? gaps : []), last + 1]) {\n rows.push({ name, sortOrder, type: entry.label, status: 'empty', flags: [], actions: [{ label: 'Move here', run: () => void move(sortOrder) }] });\n }\n rows.sort((a, b) => a.sortOrder - b.sortOrder);\n }\n return {\n subtitle: moving ? `Moving ${name} #${moving.sortOrder}. Swap it with another, move it to a free sort order, or rename it.` : `${name} #${focus.sortOrder} is no longer here.`,\n groups: [{ label: `Slots for ${name}`, rows }],\n actions: [\n {\n label: 'Show all items',\n run: () => {\n this.focus = undefined;\n this.outline.stack.popTo(`entity:${entityUrn}`);\n },\n },\n ],\n };\n }\n\n private async section(entityUrn: string, isRoot: boolean): Promise<OutlineSection> {\n const { store, pending, registry } = this.ctx;\n const view = store.view(entityUrn)!;\n const { urns: counterpart, found } = await this.counterpartUrns(entityUrn);\n // Live when the status says so, or a live view exists (an entity that is publishing, or stuck publishing, still has one).\n const published = this.view.mode === 'live' ? !this.view.draftsOnLivePage.has(entityUrn) : isLive(view.status) || found;\n const onPage: OutlineRow[] = [];\n const settings: OutlineRow[] = [];\n const unused: OutlineRow[] = [];\n\n for (const entry of registry) {\n const items = (view.raw[entry.entityArray] ?? []) as ContentItem[];\n for (const item of items) {\n if (!item.urn) continue;\n const slot: Slot = { entityUrn, entry, name: item.name, sortOrder: item.sortOrder };\n const bindings = this.view.bindingsAt(slot);\n const visible = bindings.filter((b) => !b.element.closest('head'));\n const duplicates = items.filter((other) => other.name === item.name && other.sortOrder === item.sortOrder).length;\n const urn = item.urn;\n const row: OutlineRow = {\n name: item.name,\n sortOrder: item.sortOrder,\n type: entry.label,\n // Lifecycle comes from the server: per-item status only means something once the entity is live.\n status: pending.getEdit(urn) ? 'unsaved' : !published ? '' : counterpart.has(urn) ? 'up to date' : 'unpublished changes',\n flags: [\n ...flags(entry, item, duplicates, this.ctx.requiredImageSlots),\n ...(bindings.some((b) => b.element.hasAttribute('data-text-unsafe-literal')) ? ['the site renders this as HTML'] : []),\n ],\n action: { label: 'History', run: () => this.ctx.hooks.openHistory({ ...slot, urn }) },\n ...this.referenceAction(item),\n current: isSlot(this.selected, slot),\n select: (anchor) => {\n const target: EditTarget = { ...slot, urn, anchor, binding: visible[0] };\n if (visible[0]) visible[0].element.scrollIntoView({ block: 'center' });\n this.editing.open(visible[0] && visible[0].element.getClientRects().length > 0 ? target : { ...target, binding: undefined });\n },\n };\n if (visible.length > 0) onPage.push(row);\n else if (bindings.length > 0 || !entry.component) settings.push(row);\n else unused.push({ ...row, notes: ['not used'] });\n }\n }\n\n const missing: OutlineRow[] = this.view.missingBindings(entityUrn).map((binding) => {\n const key = createKey({ entityUrn, type: binding.entry.type, name: binding.name, sortOrder: binding.sortOrder });\n return {\n name: binding.name,\n sortOrder: binding.sortOrder,\n type: binding.entry.label,\n status: pending.getCreate(key) ? 'unsaved' : 'not in content',\n flags: [],\n current: isSlot(this.selected, { entityUrn, entry: binding.entry, name: binding.name, sortOrder: binding.sortOrder }),\n action: {\n label: 'Create',\n // The page's element supplies the placeholder value; the form opens beside the row.\n run: (anchor) => {\n if (binding.element.getClientRects().length > 0) binding.element.scrollIntoView({ block: 'center' });\n this.editing.open({ entityUrn, entry: binding.entry, name: binding.name, sortOrder: binding.sortOrder, anchor, binding });\n },\n },\n };\n });\n\n const lifecycle = this.ctx.toolbar.lifecycleOf(entityUrn);\n return {\n subtitle: lifecycle?.label ?? lifecycleLabel(view.status),\n ...(lifecycle?.note ? { note: lifecycle.note } : {}),\n verbs: (lifecycle?.verbs ?? []).map((verb): OutlineAction => ({\n label: verb.label,\n run: () => verb.run(),\n ...(verb.primary ? { primary: true } : {}),\n ...(verb.disabled ? { disabled: verb.disabled } : {}),\n })),\n groups: [\n { label: 'On this page', rows: onPage },\n { label: 'Page settings', rows: settings },\n { label: 'Not used on this page', rows: unused, hint: 'In the content, but nothing on this page shows them.' },\n {\n label: 'In the page, not in the content',\n rows: missing,\n hint: 'Content items on the page that are not saved in the content yet. Each shows its placeholder until it is created.',\n action: { label: 'Create all', run: () => this.saving.confirmCreateAll(entityUrn, missing.length) },\n },\n ],\n actions: [\n { label: 'Add item', run: (anchor) => this.showAddItem(entityUrn, anchor) },\n ...(isRoot ? [{ label: 'New page like this', run: () => this.onboarding.offerNewPageLike(entityUrn) }] : []),\n ],\n };\n }\n\n /** A reference to an entity this page has loaded drills into that entity's level. */\n private referenceAction(item: ContentItem): Pick<OutlineRow, 'actions'> {\n const urn = (item as { entityReference?: { urn?: string } }).entityReference?.urn;\n if (!urn || !this.ctx.store.view(urn)) return {};\n const title = this.ctx.entityTitle(urn);\n return { actions: [{ label: `${title} \u203A`, run: () => this.outline.stack.push(this.entityLevel(urn)) }] };\n }\n\n /**\n * Version URNs to compare the shown items with: the live view's while the\n * latest drafts are shown, and the latest drafts' on the live page. An item\n * found in both is up to date; otherwise it has unpublished changes. Empty\n * when the entity has never been published.\n */\n private counterpartUrns(entityUrn: string): Promise<{ urns: Set<string>; found: boolean }> {\n let live = this.live.get(entityUrn);\n if (!live) {\n live = this.ctx.views\n .read(entityUrn, this.view.mode === 'live' ? { version: 'LATEST' } : {})\n .then((entity) => {\n const urns = new Set<string>();\n for (const entry of this.ctx.registry) {\n for (const item of (entity[entry.entityArray] ?? []) as ContentItem[]) if (item.urn) urns.add(item.urn);\n }\n return urns;\n })\n .then((urns) => ({ urns, found: true }))\n .catch(() => ({ urns: new Set<string>(), found: false }));\n this.live.set(entityUrn, live);\n }\n return live;\n }\n\n private showAddItem(entityUrn: string, anchor: HTMLElement): void {\n const { store, registry } = this.ctx;\n const form = new SimpleForm(\n `Add an item to ${this.ctx.entityTitle(entityUrn)}`,\n [\n { key: 'type', label: 'Type', value: 'text', options: registry.map((e) => ({ value: e.type, label: e.label })) },\n { key: 'name', label: 'Name', value: '' },\n { key: 'sortOrder', label: 'Sort order', value: '0' },\n ],\n 'Next',\n (values) => {\n const entry = this.ctx.entry(values['type'] as ItemType);\n const name = values['name'] ?? '';\n const sortOrder = Number(values['sortOrder']);\n if (!/^[A-Za-z0-9_-]+$/.test(name)) return form.setError('Use letters, numbers, - and _ in the name.');\n if (!Number.isInteger(sortOrder)) return form.setError('The sort order must be a whole number.');\n form.setBusy(true, 'Checking\u2026');\n void this.view.refresh(entityUrn).then(() => {\n form.setBusy(false);\n if (store.itemAt(entityUrn, entry, name, sortOrder)) {\n form.setError(`An item already exists at ${name} #${sortOrder}. Choose a free sort order.`);\n return;\n }\n panel.close();\n this.editing.open({ entityUrn, entry, name, sortOrder, anchor, binding: undefined });\n });\n },\n );\n const panel = this.ctx.panels.show(form.element, { entityUrn });\n }\n}\n\nfunction flags(entry: TypeEntry, item: ContentItem, duplicates: number, required: readonly ('DEFAULT' | 'MEDIUM' | 'LARGE')[]): string[] {\n const result: string[] = [];\n if (duplicates > 1) result.push(`${duplicates} items share this sort order`);\n const record = item as unknown as Record<string, unknown>;\n if (entry.type === 'text' && MARKUP.test(String(record['value'] ?? ''))) result.push('contains markup');\n if (entry.type === 'image') {\n if (!record['altText']) result.push('no alt text');\n for (const slot of missingSlots(item, required)) result.push(slot === 'DEFAULT' ? 'no image file' : `no ${slot.toLowerCase()} file`);\n }\n return result;\n}\n\nfunction isSlot(a: Slot | undefined, b: Slot): boolean {\n return a !== undefined && a.entityUrn === b.entityUrn && a.entry === b.entry && a.name === b.name && a.sortOrder === b.sortOrder;\n}\n", "// What the site wants said or done after a publish: the `afterPublish`\n// setting. A site built ahead of time can say when visitors will see the\n// change, or start its own rebuild. The editor's job ends here (plan \u00A715).\n\nimport type { Toolbar } from './ui/toolbar.ts';\n\nexport interface PublishedDetail {\n entityUrn: string;\n /** The entity's name as the API stores it. */\n name: string;\n /** The page path within the name, such as /menu: what a site maps to its routes. */\n path: string;\n /** The entity's language and variant ('' for none). */\n language: string;\n variant: string;\n /** For an item publish (from History), the version now live. Absent when the entity was published. */\n itemUrn?: string;\n}\n\n/**\n * A message shown after every publish, or a function called after every\n * publish. A function may return (or resolve to) a message to show.\n */\nexport type AfterPublish = string | ((detail: PublishedDetail) => string | void | Promise<string | void>);\n\n/** Said on leaving edit mode, when the page shows content published in the visit, unless the site's message replaces it. */\nexport const DEFAULT_LIVE_NOTE = 'A site that is built ahead of time shows it to visitors after its next build.';\n\n/** The site's message when it is fixed text, for places with no publish to call back about. */\nexport function fixedMessage(setting: AfterPublish | undefined): string | undefined {\n return typeof setting === 'string' ? setting : undefined;\n}\n\n/**\n * Shows `done`, then runs the site's setting and adds its message. A\n * callback that throws is shown and logged, never hidden.\n */\nexport async function announcePublished(toolbar: Toolbar, setting: AfterPublish | undefined, detail: PublishedDetail, done: string, info = true): Promise<void> {\n toolbar.showMessage(done, info);\n if (setting === undefined) return;\n try {\n const message = typeof setting === 'string' ? setting : await setting(detail);\n if (message) toolbar.showMessage(`${done} ${message}`, info);\n } catch (error) {\n console.error('Baack editor: the site\\'s afterPublish callback failed', error);\n const reason = error instanceof Error ? error.message : String(error);\n toolbar.showMessage(`${done} The site's after-publish step failed: ${reason}`, false);\n }\n}\n", "// A combo box for choosing an entity by its path and language instead of\n// typing a URN. Entities load as the list opens; typing filters them; the\n// last option creates a new entity. The chosen URN is kept in a hidden input\n// that the form reads like any other field.\n\nimport type { EntityListing, EntitySummary } from '../core/entity-directory.ts';\nimport { el } from './host.ts';\nimport { icon } from './icons.ts';\n\nexport interface EntityPickerSource {\n list(onUpdate: (listing: EntityListing) => void): Promise<EntityListing>;\n describe(urn: string): Promise<EntitySummary>;\n /** The page's language: within a path, its entity is listed first. */\n readonly language: string;\n /** Shows the new-entity form in `container`, starting from `path`. Resolves with the new entity, or undefined if cancelled. */\n create(container: HTMLElement, path: string): Promise<EntitySummary | undefined>;\n /** A line about the chosen entity, such as that a draft is not shown to visitors; '' for none. */\n note(urn: string): Promise<string>;\n /** The page address an entity serves, from its path (`/home` is `/`): a link's suggestions. */\n pagePath(path: string): string;\n /** Reports a failed load in the editor's usual way. */\n report(error: unknown, action: string, retry: () => void): void;\n}\n\n/** At most this many options are listed; typing narrows them. */\nconst SHOWN = 50;\n\nlet pickers = 0;\n\nexport function summaryLabel(entity: EntitySummary): string {\n return `${entity.path} (${entity.language}${entity.variant ? ` \u00B7 ${entity.variant}` : ''})`;\n}\n\nexport class EntityPicker {\n readonly element: HTMLElement;\n /** The visible combo box. */\n readonly input: HTMLInputElement;\n /** The chosen URN, read by the form. */\n readonly value: HTMLInputElement;\n private readonly source: EntityPickerSource;\n private readonly onChange: () => void;\n private readonly listbox: HTMLElement;\n private readonly status: HTMLElement;\n private readonly note: HTMLElement;\n private readonly createArea: HTMLElement;\n private readonly id = `baack-entity-picker-${(pickers += 1)}`;\n private listing: EntityListing | undefined;\n /** Entities created here: listed even if the list loaded (or finishes loading) without them. */\n private readonly created: EntitySummary[] = [];\n private loading: Promise<void> | undefined;\n private options: { element: HTMLElement; choose(): void }[] = [];\n private active = -1;\n /** The text shown for the chosen entity, put back if the user types and leaves without choosing. */\n private chosenLabel = '';\n\n constructor(source: EntityPickerSource, key: string, urn: string, onChange: () => void) {\n this.source = source;\n this.onChange = onChange;\n this.element = el('div', 'entity-picker');\n this.input = el('input');\n this.input.type = 'text';\n this.input.autocomplete = 'off';\n this.input.spellcheck = false;\n this.input.placeholder = 'Type a path, such as /menu';\n this.input.setAttribute('role', 'combobox');\n this.input.setAttribute('aria-autocomplete', 'list');\n this.input.setAttribute('aria-expanded', 'false');\n this.input.setAttribute('aria-controls', `${this.id}-list`);\n this.value = el('input');\n this.value.type = 'hidden';\n this.value.name = key;\n this.value.value = urn;\n this.listbox = el('ul', 'entity-options');\n this.listbox.id = `${this.id}-list`;\n this.listbox.setAttribute('role', 'listbox');\n this.listbox.setAttribute('aria-label', 'Entities');\n this.listbox.hidden = true;\n this.status = el('p', 'hint');\n this.status.setAttribute('role', 'status');\n this.note = el('p', 'hint');\n this.createArea = el('div', 'entity-create');\n // shadcn/ui's combobox: a search field over a list of options, the chosen one ticked.\n const field = el('div', 'combobox-field');\n field.append(icon('search'), this.input, icon('chevron-down'));\n this.element.append(field, this.listbox, this.status, this.note, this.createArea, this.value);\n\n this.input.addEventListener('focus', () => this.open());\n this.input.addEventListener('input', () => this.open());\n this.input.addEventListener('keydown', this.onKeyDown);\n this.input.addEventListener('blur', () => {\n // A click on an option keeps focus (mousedown is prevented), so a blur is leaving.\n this.close();\n if (this.input.value !== this.chosenLabel) this.input.value = this.chosenLabel;\n });\n if (urn) this.showChosen(urn);\n }\n\n private async showChosen(urn: string): Promise<void> {\n this.chosenLabel = urn;\n this.input.value = urn;\n try {\n const entity = await this.source.describe(urn);\n if (this.value.value !== urn) return;\n this.chosenLabel = summaryLabel(entity);\n if (this.input.value === urn) this.input.value = this.chosenLabel;\n } catch (error) {\n this.source.report(error, 'show the entity referred to', () => void this.showChosen(urn));\n }\n void this.showNote(urn);\n }\n\n private async showNote(urn: string): Promise<void> {\n try {\n const note = await this.source.note(urn);\n if (this.value.value === urn) this.note.textContent = note;\n } catch (error) {\n this.source.report(error, 'check the entity referred to', () => void this.showNote(urn));\n }\n }\n\n private open(): void {\n this.listbox.hidden = false;\n this.input.setAttribute('aria-expanded', 'true');\n this.loading ??= this.source\n .list((listing) => {\n this.listing = listing;\n this.render();\n })\n .then((listing) => {\n this.listing = listing;\n this.render();\n })\n .catch((error: unknown) => {\n this.loading = undefined; // Loaded again on the next open.\n this.status.textContent = 'The list of entities could not be loaded.';\n this.source.report(error, 'list the entities', () => this.open());\n });\n this.render();\n }\n\n private close(): void {\n this.listbox.hidden = true;\n this.input.setAttribute('aria-expanded', 'false');\n this.input.removeAttribute('aria-activedescendant');\n this.active = -1;\n }\n\n private render(): void {\n if (this.listbox.hidden) return;\n const query = this.input.value === this.chosenLabel ? '' : this.input.value.trim().toLowerCase();\n const loaded = this.listing?.entities ?? [];\n const entities = [...loaded, ...this.created.filter((entity) => !loaded.some((known) => known.urn === entity.urn))]\n .filter((entity) => !query || summaryLabel(entity).toLowerCase().includes(query))\n .sort((a, b) => (a.path === b.path ? Number(b.language === this.source.language) - Number(a.language === this.source.language) : 0));\n this.options = entities.slice(0, SHOWN).map((entity) => {\n const option = el('li', 'entity-option');\n option.append(el('span', '', entity.path), el('span', 'meta', ` ${entity.language}${entity.variant ? ` \u00B7 ${entity.variant}` : ''}`));\n const chosen = entity.urn === this.value.value;\n option.setAttribute('aria-selected', String(chosen));\n if (chosen) option.append(icon('check'));\n return { element: option, choose: () => this.choose(entity) };\n });\n const typed = this.input.value.trim();\n const path = query && typed.startsWith('/') ? typed : query ? `/${typed}` : '';\n const create = el('li', 'entity-option create', path ? `Create a new entity \"${path}\"\u2026` : 'Create a new entity\u2026');\n create.prepend(icon('plus'));\n this.options.push({ element: create, choose: () => void this.create(path) });\n this.options.forEach((option, index) => {\n option.element.id = `${this.id}-option-${index}`;\n option.element.setAttribute('role', 'option');\n option.element.addEventListener('mousedown', (event) => event.preventDefault());\n option.element.addEventListener('click', () => option.choose());\n });\n this.listbox.replaceChildren(...this.options.map((option) => option.element));\n this.setActive(Math.min(this.active, this.options.length - 1));\n\n const count = loaded.length + this.created.length;\n this.status.textContent = !this.listing\n ? 'Loading entities\u2026'\n : [\n entities.length > SHOWN ? `Showing ${SHOWN} of ${entities.length}; type to narrow.` : '',\n this.listing.complete ? '' : 'The search was still running, so some entities may be missing.',\n count === 0 ? 'No entities found.' : '',\n ]\n .filter(Boolean)\n .join(' ');\n }\n\n private setActive(index: number): void {\n this.active = index;\n this.options.forEach((option, i) => option.element.classList.toggle('active', i === index));\n const current = this.options[index];\n if (current) {\n this.input.setAttribute('aria-activedescendant', current.element.id);\n current.element.scrollIntoView({ block: 'nearest' });\n } else {\n this.input.removeAttribute('aria-activedescendant');\n }\n }\n\n private choose(entity: EntitySummary): void {\n this.value.value = entity.urn;\n this.chosenLabel = summaryLabel(entity);\n this.input.value = this.chosenLabel;\n this.note.textContent = '';\n this.close();\n this.onChange();\n void this.showNote(entity.urn);\n }\n\n private async create(path: string): Promise<void> {\n this.close();\n this.input.disabled = true;\n try {\n const entity = await this.source.create(this.createArea, path);\n if (entity) {\n this.created.push(entity);\n this.choose(entity);\n }\n } finally {\n this.createArea.replaceChildren();\n this.input.disabled = false;\n this.input.focus();\n }\n }\n\n private readonly onKeyDown = (event: KeyboardEvent) => {\n const open = !this.listbox.hidden;\n if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault();\n if (!open) this.open();\n const step = event.key === 'ArrowDown' ? 1 : -1;\n this.setActive((this.active + step + this.options.length) % this.options.length);\n } else if (event.key === 'Enter' && open && this.active >= 0 && !(event.metaKey || event.ctrlKey)) {\n event.preventDefault();\n event.stopPropagation();\n this.options[this.active]?.choose();\n } else if (event.key === 'Escape' && open) {\n // Closes the list only, not the whole form.\n event.preventDefault();\n event.stopPropagation();\n this.close();\n }\n };\n}\n", "// A dropdown menu: shadcn/ui's, with the WAI-ARIA menu button pattern. The\n// trigger opens a list of menu items below it (above, when there is no room).\n// Arrow keys, Home, End and the first letter move between items; Enter runs\n// one; Escape or Tab closes it and puts focus back on the trigger.\n//\n// Opened with the pointer, the menu takes no focus, so an inline edit the\n// trigger sits beside stays focused (and is not ended by a blur).\n\nimport { el } from './host.ts';\nimport { icon, type IconName } from './icons.ts';\n\nexport interface MenuItem {\n label: string;\n icon?: IconName;\n destructive?: boolean;\n run(): void;\n}\n\nlet count = 0;\n\nexport class Dropdown {\n readonly trigger: HTMLButtonElement;\n private readonly items: () => MenuItem[];\n private menu: HTMLElement | undefined;\n\n constructor(trigger: HTMLButtonElement, items: () => MenuItem[]) {\n this.trigger = trigger;\n this.items = items;\n trigger.id ||= `baack-menu-trigger-${++count}`;\n trigger.setAttribute('aria-haspopup', 'menu');\n trigger.setAttribute('aria-expanded', 'false');\n trigger.addEventListener('mousedown', (event) => event.preventDefault());\n // detail is 0 for a click made with the keyboard (Enter or Space).\n trigger.addEventListener('click', (event) => (this.menu ? this.close(true) : this.open(event.detail === 0 ? 'first' : undefined)));\n trigger.addEventListener('keydown', (event) => {\n if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault();\n this.open(event.key === 'ArrowDown' ? 'first' : 'last');\n }\n });\n }\n\n get isOpen(): boolean {\n return this.menu !== undefined;\n }\n\n open(focus?: 'first' | 'last'): void {\n this.close(false);\n const menu = el('div', 'menu');\n menu.setAttribute('role', 'menu');\n menu.setAttribute('aria-labelledby', this.trigger.id);\n for (const item of this.items()) {\n const entry = el('button', item.destructive ? 'menu-item destructive' : 'menu-item');\n entry.type = 'button';\n entry.setAttribute('role', 'menuitem');\n entry.tabIndex = -1;\n if (item.icon) entry.append(icon(item.icon));\n entry.append(item.label);\n entry.addEventListener('mousedown', (event) => event.preventDefault());\n entry.addEventListener('click', () => {\n this.close(entry.matches(':focus'));\n item.run();\n });\n menu.append(entry);\n }\n menu.addEventListener('keydown', this.onKey);\n // In the trigger's panel, so a popover's dialog contains its menu.\n (this.trigger.closest('.panel') ?? this.trigger.parentElement!).append(menu);\n this.menu = menu;\n this.trigger.setAttribute('aria-expanded', 'true');\n this.trigger.setAttribute('aria-controls', (menu.id = `${this.trigger.id}-list`));\n this.place();\n window.addEventListener('pointerdown', this.onOutside, true);\n window.addEventListener('scroll', this.onScroll, true);\n window.addEventListener('resize', this.onScroll);\n if (focus) this.focusAt(focus === 'first' ? 0 : -1);\n }\n\n /** `restoreFocus`: put focus back on the trigger, as after Escape. */\n close(restoreFocus: boolean): void {\n if (!this.menu) return;\n this.menu.remove();\n this.menu = undefined;\n this.trigger.setAttribute('aria-expanded', 'false');\n this.trigger.removeAttribute('aria-controls');\n window.removeEventListener('pointerdown', this.onOutside, true);\n window.removeEventListener('scroll', this.onScroll, true);\n window.removeEventListener('resize', this.onScroll);\n if (restoreFocus) this.trigger.focus();\n }\n\n private entries(): HTMLButtonElement[] {\n return [...(this.menu?.querySelectorAll<HTMLButtonElement>('[role=\"menuitem\"]') ?? [])];\n }\n\n private focusAt(index: number): void {\n const entries = this.entries();\n const entry = entries.at(index % entries.length);\n for (const other of entries) other.tabIndex = other === entry ? 0 : -1;\n entry?.focus();\n }\n\n private readonly onKey = (event: KeyboardEvent) => {\n const entries = this.entries();\n const current = entries.indexOf(event.target as HTMLButtonElement);\n if (event.key === 'Escape') {\n // Only the menu closes, not the popover or edit it sits in.\n event.preventDefault();\n event.stopPropagation();\n this.close(true);\n } else if (event.key === 'Tab') {\n event.preventDefault();\n this.close(true);\n } else if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault();\n this.focusAt((current + (event.key === 'ArrowDown' ? 1 : -1) + entries.length) % entries.length);\n } else if (event.key === 'Home' || event.key === 'End') {\n event.preventDefault();\n this.focusAt(event.key === 'Home' ? 0 : -1);\n } else if (event.key.length === 1 && /\\S/.test(event.key)) {\n // The next item starting with the letter typed.\n const letter = event.key.toLowerCase();\n for (let step = 1; step <= entries.length; step++) {\n const index = (current + step) % entries.length;\n if (entries[index]!.textContent!.trim().toLowerCase().startsWith(letter)) {\n this.focusAt(index);\n break;\n }\n }\n }\n };\n\n private readonly onOutside = (event: PointerEvent) => {\n const path = event.composedPath();\n if (!path.includes(this.menu!) && !path.includes(this.trigger)) this.close(false);\n };\n\n private readonly onScroll = (event: Event) => {\n if (event.type === 'scroll' && this.menu && event.composedPath().includes(this.menu)) return;\n this.close(false);\n };\n\n /** Below the trigger, its end edges aligned; above it when there is no room below. */\n private place(): void {\n const menu = this.menu!;\n const rect = this.trigger.getBoundingClientRect();\n menu.style.minWidth = `${Math.max(rect.width, 128)}px`;\n const { width, height } = menu.getBoundingClientRect();\n const below = rect.bottom + 4;\n const top = below + height <= window.innerHeight - 8 || rect.top - height - 4 < 8 ? below : rect.top - height - 4;\n menu.style.top = `${Math.max(8, top)}px`;\n menu.style.left = `${Math.min(Math.max(8, rect.right - width), window.innerWidth - width - 8)}px`;\n }\n}\n", "// The panel beside an element being edited: what it is, a form for non-text\n// types, warnings, errors, and the Send and Revert actions.\n\nimport type { FieldSpec, FormValues, Issue } from '../core/registry.ts';\nimport { button, type EditorHost, debugDetails, el, variantOf } from './host.ts';\nimport type { EntityListing } from '../core/entity-directory.ts';\nimport { EntityPicker, type EntityPickerSource } from './entity-picker.ts';\nimport { icon, type IconName } from './icons.ts';\nimport { Dropdown } from './menu.ts';\nimport { tooltip } from './tooltip.ts';\n\nexport interface PopoverActions {\n send(): void;\n revert(): void;\n}\n\n/** A secondary action for the item being edited. `menu`: listed in the \u22EF menu rather than shown as a button. */\nexport interface ExtraAction {\n label: string;\n icon?: IconName;\n menu?: boolean;\n run(): void;\n}\n\n/** A decision with its own buttons, such as resolving a conflict. */\nexport interface Choice {\n label: string;\n primary?: boolean;\n /** Shown as a destructive button: it deletes or discards. */\n destructive?: boolean;\n run(): void;\n}\n\nexport interface FormActions extends PopoverActions {\n /** Called on every change with the current form values. */\n input(values: FormValues): void;\n}\n\n// Offered as suggestions; any ISO 4217 code is accepted.\nconst COMMON_CURRENCIES = ['GBP', 'EUR', 'USD', 'JPY', 'CHF', 'CAD', 'AUD', 'NZD', 'SEK', 'NOK', 'DKK', 'PLN', 'INR', 'CNY', 'BRL'];\n\nconst IS_MAC = /Mac|iPhone|iPad/.test(navigator.userAgent);\n\nexport class Popover {\n readonly element: HTMLElement;\n private readonly title: HTMLElement;\n private readonly form: HTMLElement;\n private readonly description: HTMLElement;\n private readonly issues: HTMLElement;\n private readonly error: HTMLElement;\n private readonly errorDebug: HTMLElement;\n private readonly sendButton: HTMLButtonElement;\n private readonly extras: HTMLElement;\n private menu: Dropdown | undefined;\n private readonly buttons: HTMLElement;\n private readonly choices: HTMLElement;\n private readonly hint: HTMLElement;\n private anchor: HTMLElement | undefined;\n private actions: PopoverActions | undefined;\n private inputs = new Map<string, HTMLInputElement | HTMLTextAreaElement>();\n private readonly slotStatus = new Map<string, HTMLElement>();\n private readonly reposition = () => this.place();\n /** Which side of the element the popover sits on, chosen when it opens. */\n private side: 'below' | 'above' | 'within' | undefined;\n /** Called once when this opening ends: hidden, or replaced by another opening. */\n private onEnd: (() => void) | undefined;\n /** Follows the element being edited as its value makes it taller or shorter. */\n private readonly anchorObserver = new ResizeObserver(this.reposition);\n /** Where entity fields find entities, and link addresses their suggestions. */\n private entities: EntityPickerSource | undefined;\n /** The values the form opened with, for fields that show the current state (file slots). */\n private currentValues: FormValues = {};\n\n constructor(host: EditorHost) {\n this.element = el('div', 'panel popover');\n this.element.setAttribute('role', 'dialog');\n this.element.hidden = true;\n this.title = el('div', 'title');\n this.form = el('div', 'form');\n this.description = el('p', 'hint');\n this.issues = el('ul', 'issues');\n this.error = el('p', 'error');\n this.error.setAttribute('role', 'alert');\n this.errorDebug = el('div', 'error-debug');\n\n const revert = el('button', '', 'Revert');\n revert.type = 'button';\n this.sendButton = el('button', 'primary', 'Save');\n this.sendButton.type = 'button';\n // Keep focus in the element being edited, so pressing a button is not a blur.\n for (const button of [revert, this.sendButton]) {\n button.addEventListener('mousedown', (event) => event.preventDefault());\n }\n revert.addEventListener('click', () => this.actions?.revert());\n this.sendButton.addEventListener('click', () => this.actions?.send());\n this.element.addEventListener('keydown', (event) => {\n if (event.key === 'Escape') {\n event.preventDefault();\n this.actions?.revert();\n } else if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) {\n event.preventDefault();\n this.actions?.send();\n }\n });\n\n this.extras = el('div', 'extras');\n this.buttons = el('div', 'actions');\n this.buttons.append(revert, this.sendButton);\n this.choices = el('div', 'actions');\n this.choices.hidden = true;\n this.hint = el('p', 'hint');\n this.element.append(this.title, this.form, this.description, this.issues, this.error, this.errorDebug, this.extras, this.buttons, this.choices, this.hint);\n host.root.append(this.element);\n // Warnings, errors, a file preview or the entity list can make it taller: choose its side again, to keep it on\n // screen. Only the element growing keeps the side.\n new ResizeObserver(() => {\n if (this.element.hidden) return;\n this.side = undefined;\n this.place();\n }).observe(this.element);\n }\n\n setEntitySource(source: EntityPickerSource): void {\n this.entities = source;\n }\n\n get isOpen(): boolean {\n return !this.element.hidden;\n }\n\n /** For in-place editing: the element itself holds the value. */\n show(anchor: HTMLElement, label: string, meta: string, hint: string, actions: PopoverActions): void {\n this.open(anchor, label, meta, hint, actions, false);\n this.form.replaceChildren();\n this.inputs.clear();\n this.place();\n }\n\n /** For popover and panel editing: a form holds the value. */\n showForm(\n anchor: HTMLElement,\n label: string,\n meta: string,\n fields: readonly FieldSpec[],\n values: FormValues,\n actions: FormActions,\n wide: boolean,\n ): void {\n this.open(anchor, label, meta, `${IS_MAC ? '\u2318' : 'Ctrl'}+Enter to save \u00B7 Esc to revert`, actions, wide);\n this.inputs.clear();\n this.slotStatus.clear();\n this.currentValues = values;\n this.form.replaceChildren(...fields.map((field) => this.field(field, values[field.key], () => actions.input(this.values()))));\n this.place();\n this.form.querySelector<HTMLElement>('input:not([type=\"hidden\"]), textarea, select')?.focus();\n }\n\n /** Shows labelled values side by side and a set of choices instead of Save and Revert. */\n showChoices(anchor: HTMLElement, label: string, meta: string, blocks: { label: string; text: string }[], description: string, choices: Choice[]): void {\n this.open(anchor, label, meta, '', { send: () => undefined, revert: () => choices.at(-1)?.run() }, true);\n this.inputs.clear();\n this.form.replaceChildren(\n ...blocks.map((block) => {\n const box = el('div', 'field');\n box.append(el('span', 'caption', block.label), el('pre', 'snippet', block.text));\n return box;\n }),\n );\n this.setDescription(description);\n this.buttons.hidden = true;\n this.choices.hidden = false;\n this.choices.replaceChildren(\n ...choices.map((choice) => {\n const choiceButton = button(choice.label, variantOf(choice));\n choiceButton.addEventListener('click', () => choice.run());\n return choiceButton;\n }),\n );\n this.place();\n }\n\n /**\n * Runs `end` once when this opening ends, whether hidden or replaced by\n * another item's, so a preview on the page is never left behind.\n */\n whenEnded(end: (() => void) | undefined): void {\n this.onEnd = end;\n }\n\n private ended(): void {\n const end = this.onEnd;\n this.onEnd = undefined;\n end?.();\n }\n\n hide(): void {\n this.ended();\n this.menu?.close(false);\n this.element.hidden = true;\n this.anchor = undefined;\n this.side = undefined;\n this.anchorObserver.disconnect();\n this.actions = undefined;\n window.removeEventListener('scroll', this.reposition, true);\n window.removeEventListener('resize', this.reposition);\n window.removeEventListener('keydown', this.onWindowKey);\n }\n\n /**\n * Escape reverts wherever focus is while the popover is open, like the\n * Revert button. The popover and the in-place editor handle it first when\n * focus is theirs, and mark it handled.\n */\n private readonly onWindowKey = (event: KeyboardEvent) => {\n if (event.key !== 'Escape' || event.defaultPrevented || this.element.hidden) return;\n event.preventDefault();\n this.actions?.revert();\n };\n\n values(): FormValues {\n // Start from what the form opened with, so read-only state (a slot's current file) is included.\n const values: FormValues = { ...this.currentValues };\n for (const [key, input] of this.inputs) {\n if (input instanceof HTMLInputElement && input.type === 'file') values[key] = input.files?.[0]?.name ?? '';\n else values[key] = input instanceof HTMLInputElement && input.type === 'checkbox' ? input.checked : input.value;\n }\n return values;\n }\n\n /** Files chosen in file fields, by field key. */\n files(): Map<string, File> {\n const files = new Map<string, File>();\n for (const [key, input] of this.inputs) {\n const file = input instanceof HTMLInputElement && input.type === 'file' ? input.files?.[0] : undefined;\n if (file) files.set(key, file);\n }\n return files;\n }\n\n /** A status line under a file field: \"uploading\u2026\", \"done\", or the API's error. */\n setSlotStatus(key: string, text: string, problem = false): void {\n const status = this.slotStatus.get(key);\n if (!status) return;\n status.textContent = text;\n status.classList.toggle('error', problem);\n }\n\n setValues(values: FormValues): void {\n for (const [key, input] of this.inputs) {\n const value = values[key];\n if (input instanceof HTMLInputElement && input.type === 'checkbox') {\n input.checked = value === true;\n } else if (input.type !== 'file') {\n input.value = typeof value === 'string' ? value : '';\n }\n }\n }\n\n /** Makes the item's \"name #sort order\" in the title a link, for example to show it in Items. */\n setNameAction(run: (() => void) | undefined): void {\n const meta = this.title.querySelector('.meta');\n if (!meta || !run) return;\n const link = el('button', 'meta link', meta.textContent ?? '');\n link.type = 'button';\n tooltip(link, 'Show in Items');\n link.addEventListener('mousedown', (event) => event.preventDefault());\n link.addEventListener('click', run);\n meta.replaceWith(link);\n }\n\n /** Secondary actions for the item: History as a button, then the others (Reorder\u2026, Move up\u2026) in a \u22EF menu. */\n setExtras(actions: ExtraAction[]): void {\n this.menu?.close(false);\n this.menu = undefined;\n const shown = actions.filter((action) => !action.menu);\n const listed = actions.filter((action) => action.menu);\n this.extras.replaceChildren(\n ...shown.map((action) => {\n const extra = button(action.label, 'ghost', 'sm');\n if (action.icon) extra.prepend(icon(action.icon));\n extra.addEventListener('mousedown', (event) => event.preventDefault());\n extra.addEventListener('click', () => action.run());\n return extra;\n }),\n );\n if (listed.length > 0) {\n const more = button('', 'ghost', 'icon-sm');\n more.setAttribute('aria-label', 'More actions');\n more.append(icon('ellipsis'));\n this.extras.append(more);\n tooltip(more);\n this.menu = new Dropdown(more, () => listed);\n }\n }\n\n setDescription(text: string): void {\n this.description.textContent = text;\n }\n\n setIssues(issues: Issue[]): void {\n this.issues.replaceChildren(...issues.map((issue) => el('li', issue.level, issue.message)));\n }\n\n /** `debug`: an API error body, shown behind a collapsed \"Debug\" section. */\n setError(message: string, debug?: string): void {\n this.error.textContent = message;\n this.errorDebug.replaceChildren(...debugDetails(debug));\n }\n\n setSending(sending: boolean): void {\n this.sendButton.disabled = sending;\n this.sendButton.textContent = sending ? 'Saving\u2026' : 'Save';\n }\n\n private open(anchor: HTMLElement, label: string, meta: string, hint: string, actions: PopoverActions, wide: boolean) {\n this.ended();\n if (anchor !== this.anchor) this.side = undefined;\n this.anchor = anchor;\n this.anchorObserver.disconnect();\n this.anchorObserver.observe(anchor);\n this.actions = actions;\n this.title.textContent = `${label} `;\n this.title.append(el('span', 'meta', meta));\n this.element.setAttribute('aria-label', `Edit ${label.toLowerCase()} ${meta}`);\n this.element.classList.toggle('wide', wide);\n this.buttons.hidden = false;\n this.choices.hidden = true;\n this.setExtras([]);\n this.hint.textContent = hint;\n this.setDescription('');\n this.setIssues([]);\n this.setError('');\n this.setSending(false);\n this.element.hidden = false;\n window.addEventListener('scroll', this.reposition, true);\n window.addEventListener('resize', this.reposition);\n window.addEventListener('keydown', this.onWindowKey);\n }\n\n private field(field: FieldSpec, value: string | boolean | undefined, onInput: () => void): HTMLElement {\n const label = el('label', `field ${field.kind}`);\n const caption = el('span', 'caption', field.label);\n let input: HTMLInputElement | HTMLTextAreaElement;\n if (field.kind === 'file') {\n // A file slot: the current file, a chooser, and a status line.\n input = el('input');\n input.type = 'file';\n input.accept = 'image/apng,image/avif,image/gif,image/jpeg,image/png,image/svg+xml,image/webp';\n input.name = field.key;\n const current = typeof this.currentValues[`${field.key}:current`] === 'string' ? (this.currentValues[`${field.key}:current`] as string) : '';\n const preview = el('div', 'slot-preview');\n if (current) {\n const img = el('img');\n img.src = current;\n img.alt = '';\n preview.append(img, el('span', 'meta', current));\n } else {\n preview.append(el('span', 'meta', 'No file'));\n }\n const status = el('span', 'hint');\n status.setAttribute('role', 'status');\n this.slotStatus.set(field.key, status);\n input.addEventListener('change', onInput);\n this.inputs.set(field.key, input);\n label.append(caption, preview, input, status);\n return label;\n }\n if (field.kind === 'entity' && this.entities) {\n // Not a <label>: the picker holds a list and a form, which must not become part of its name.\n const wrapper = el('div', 'field entity');\n caption.id = `baack-field-${field.key}`;\n const picker = new EntityPicker(this.entities, field.key, typeof value === 'string' ? value : '', onInput);\n picker.input.setAttribute('aria-labelledby', caption.id);\n this.inputs.set(field.key, picker.value);\n wrapper.append(caption, picker.element);\n return wrapper;\n }\n if (field.kind === 'textarea' || field.kind === 'code') {\n input = el('textarea');\n input.rows = field.kind === 'code' ? 12 : 4;\n input.spellcheck = field.kind !== 'code';\n } else {\n input = el('input');\n input.type =\n field.kind === 'checkbox' ? 'checkbox' : field.kind === 'datetime' ? 'datetime-local' : field.kind === 'url' ? 'url' : 'text';\n if (field.kind === 'integer') input.inputMode = 'numeric';\n if (field.kind === 'decimal') input.inputMode = 'decimal';\n if (field.kind === 'currency') {\n input.maxLength = 3;\n input.autocapitalize = 'characters';\n const list = el('datalist');\n list.id = `baack-currencies-${field.key}`;\n list.append(...COMMON_CURRENCIES.map((code) => Object.assign(el('option'), { value: code })));\n input.setAttribute('list', list.id);\n label.append(list);\n }\n if (field.kind === 'url' && this.entities) label.append(this.pathSuggestions(input as HTMLInputElement, field.key));\n }\n if (input instanceof HTMLInputElement && input.type === 'checkbox') {\n // Drawn as a switch: an on/off value that takes effect when saved.\n input.setAttribute('role', 'switch');\n input.className = 'switch';\n input.checked = value === true;\n label.append(input, caption);\n } else {\n input.value = typeof value === 'string' ? value : '';\n label.append(caption, input);\n }\n input.name = field.key;\n input.addEventListener('input', onInput);\n input.addEventListener('change', onInput);\n this.inputs.set(field.key, input);\n return label;\n }\n\n /** Suggests the paths of entities for a link address, once the field is first used. */\n private pathSuggestions(input: HTMLInputElement, key: string): HTMLElement {\n const list = el('datalist');\n list.id = `baack-paths-${key}`;\n input.setAttribute('list', list.id);\n const fill = ({ entities }: EntityListing) =>\n list.replaceChildren(...[...new Set(entities.map((entity) => this.entities!.pagePath(entity.path)))].map((path) => Object.assign(el('option'), { value: path })));\n input.addEventListener(\n 'focus',\n () => {\n // Suggestions only: a failed listing leaves the field as a plain address.\n this.entities?.list(fill).then(fill, () => undefined);\n },\n { once: true },\n );\n return list;\n }\n\n private place(): void {\n if (!this.anchor) return;\n const rect = this.anchor.getBoundingClientRect();\n // An element with no box (a switch turned off hides its content) leaves the popover where it was.\n if (!this.anchor.getClientRects().length && this.side) return;\n const height = this.element.offsetHeight;\n const width = this.element.offsetWidth;\n // Opened from another editor panel (an outline row): sit beside that panel, not over it.\n const panel = this.anchor.closest('.panel');\n if (panel && panel !== this.element) {\n const panelRect = panel.getBoundingClientRect();\n this.element.style.left = `${Math.max(8, panelRect.left - width - 8)}px`;\n this.element.style.top = `${Math.max(8, Math.min(rect.top, window.innerHeight - height - 8))}px`;\n return;\n }\n // The side is chosen once per opening and then kept: pinned to that edge of the element, the popover moves\n // with it as the value grows, never over it, even when that takes it past the bottom of the window. An\n // element with room on neither side (a tall image) is covered anyway, so the popover stays in the window.\n this.side ??=\n rect.bottom + 8 + height <= window.innerHeight ? 'below' : rect.top - height - 8 >= 8 ? 'above' : 'within';\n const top =\n this.side === 'below'\n ? Math.max(8, rect.bottom + 8)\n : this.side === 'above'\n ? Math.min(rect.top - height - 8, window.innerHeight - height - 8)\n : Math.max(8, Math.min(rect.bottom + 8, window.innerHeight - height - 8));\n const left = Math.max(8, Math.min(rect.left, window.innerWidth - width - 8));\n this.element.style.top = `${top}px`;\n this.element.style.left = `${left}px`;\n }\n}\n", "// The persistent control: edit mode, the sidebar, read mode, the unsent\n// count (opening the unsent changes in the sidebar), a label for the page's\n// entity (its state and unsent count, opening it in the sidebar), page-level\n// messages, and the login prompt. Everything else is in the sidebar\n// (docs/plans/single-sidebar.md).\n\nimport { button, type EditorHost, debugDetails, el } from './host.ts';\nimport { createLauncher } from './launcher.ts';\nimport { tooltip } from './tooltip.ts';\n\nexport interface PendingRow {\n label: string;\n /** \"edit\", \"new item\", or a problem such as \"based on an older version\". */\n detail: string;\n problem?: boolean;\n /** For example \"Resolve\" on an edit made on an older version. */\n action?: { label: string; run(anchor: HTMLElement): void };\n}\n\nexport interface PendingGroup {\n entityUrn: string;\n title: string;\n rows: PendingRow[];\n}\n\n/** One entity's lifecycle: its status as the server reports it, and the verbs available. */\nexport interface LifecycleRow {\n entityUrn: string;\n title: string;\n label: string;\n note?: string;\n verbs: { label: string; primary?: boolean; disabled?: string; run(): void }[];\n}\n\nexport interface MessageAction {\n label: string;\n run(): void;\n}\n\nexport interface PendingActions {\n sendAll(entityUrn?: string): void;\n discardAll(entityUrn?: string): void;\n}\n\nexport class Toolbar {\n readonly modeButton: HTMLButtonElement;\n readonly itemsButton: HTMLButtonElement;\n /** Switches between the latest drafts and the live page. */\n readonly readButton: HTMLButtonElement;\n private readonly pendingButton: HTMLButtonElement;\n private readonly message: HTMLElement;\n /** What to do next, after a message such as \"Saved as drafts\": Review and publish\u2026. */\n private readonly messageAction: HTMLButtonElement;\n private runMessageAction: (() => void) | undefined;\n private readonly messageDebug: HTMLElement;\n /** The page entity's label. */\n private readonly entities: HTMLElement;\n private lifecycleRows: LifecycleRow[] = [];\n private pendingGroups: PendingGroup[] = [];\n /** Opens the unsent changes in the sidebar (the count's click). */\n private openPending: (() => void) | undefined;\n private readonly pendingListeners: (() => void)[] = [];\n /** Opens an entity's level in the sidebar (the label's click). */\n private openEntity: ((entityUrn: string) => void) | undefined;\n private readonly lifecycleListeners: (() => void)[] = [];\n private readonly login: HTMLElement;\n private readonly loginFrame: HTMLIFrameElement;\n private readonly loginText: HTMLElement;\n private readonly pendingActions: PendingActions;\n\n constructor(host: EditorHost, onRetryAfterLogin: () => void, pendingActions: PendingActions) {\n this.pendingActions = pendingActions;\n this.modeButton = createLauncher(host);\n const bar = this.modeButton.closest('.toolbar')!;\n const row = this.modeButton.parentElement!;\n\n this.itemsButton = el('button', '', 'Items');\n this.itemsButton.type = 'button';\n tooltip(this.itemsButton, 'Every item on this page (Alt+Shift+I)');\n this.itemsButton.hidden = true;\n\n this.pendingButton = el('button', 'pending');\n this.pendingButton.type = 'button';\n this.pendingButton.hidden = true;\n tooltip(this.pendingButton, 'Show them in the sidebar, with Save all and Discard all');\n this.pendingButton.addEventListener('click', () => this.openPending?.());\n this.readButton = el('button', '', 'Show live page');\n this.readButton.type = 'button';\n this.readButton.hidden = true;\n row.append(this.itemsButton, this.readButton, this.pendingButton);\n\n this.message = el('p', 'message');\n this.message.setAttribute('role', 'status');\n this.messageAction = button('', 'primary', 'sm', 'message-action');\n this.messageAction.hidden = true;\n this.messageAction.addEventListener('click', () => {\n const run = this.runMessageAction;\n this.showMessage('');\n run?.();\n });\n this.messageDebug = el('div', 'message-debug');\n this.entities = el('div', 'entities');\n\n this.login = el('div', 'login');\n this.login.hidden = true;\n this.loginText = el('p', 'message');\n this.loginText.setAttribute('role', 'alert');\n this.loginFrame = el('iframe');\n this.loginFrame.title = 'Log in to Baack';\n const retry = el('button', 'primary', 'I have logged in, try again');\n retry.type = 'button';\n retry.addEventListener('click', () => {\n this.hideLogin();\n onRetryAfterLogin();\n });\n this.login.append(this.loginText, this.loginFrame, retry);\n\n bar.append(this.entities, this.message, this.messageAction, this.messageDebug, this.login);\n }\n\n setEditMode(on: boolean): void {\n this.modeButton.disabled = false;\n this.modeButton.setAttribute('aria-pressed', String(on));\n this.itemsButton.hidden = !on;\n this.readButton.hidden = !on;\n }\n\n /** `latest` true while showing the editable latest drafts. */\n setReadMode(latest: boolean): void {\n this.readButton.textContent = latest ? 'Show live page' : 'Show latest drafts';\n }\n\n setPending(groups: PendingGroup[]): void {\n this.pendingGroups = groups;\n const count = groups.reduce((total, group) => total + group.rows.length, 0);\n this.pendingButton.hidden = count === 0;\n this.pendingButton.textContent = count === 1 ? '1 unsaved change' : `${count} unsaved changes`;\n this.renderEntities();\n for (const listener of this.pendingListeners) listener();\n }\n\n /** What the unsent count opens. */\n setOpenPending(open: () => void): void {\n this.openPending = open;\n }\n\n /** Called whenever the unsent changes change. */\n onPending(listener: () => void): void {\n this.pendingListeners.push(listener);\n }\n\n /** The unsent changes, one section per entity with Save all and Discard all, for the sidebar's level. */\n pendingSections(): HTMLElement[] {\n if (this.pendingGroups.length === 0) return [el('p', 'hint', 'Nothing is unsaved.')];\n return [\n ...this.pendingGroups.map((group) => this.pendingSection(group)),\n ...(this.pendingGroups.length > 1 ? [this.actions(undefined, 'everywhere')] : []),\n ];\n }\n\n /** What the page entity's label opens. */\n setOpenEntity(open: (entityUrn: string) => void): void {\n this.openEntity = open;\n }\n\n /** In display order: the page's entity first, then the others. */\n setLifecycle(rows: LifecycleRow[]): void {\n this.lifecycleRows = rows;\n this.renderEntities();\n for (const listener of this.lifecycleListeners) listener();\n }\n\n /** An entity's lifecycle row, while editing. */\n lifecycleOf(entityUrn: string): LifecycleRow | undefined {\n return this.lifecycleRows.find((row) => row.entityUrn === entityUrn);\n }\n\n /** Called whenever the lifecycle rows change. */\n onLifecycle(listener: () => void): void {\n this.lifecycleListeners.push(listener);\n }\n\n /** The page's entity as a label (its title, state and unsent count) that opens it in the sidebar. */\n private renderEntities(): void {\n const page = this.lifecycleRows[0];\n this.entities.replaceChildren(...(page ? [this.entityLabel(page)] : []));\n }\n\n private entityLabel(row: LifecycleRow): HTMLElement {\n const unsent = this.pendingGroups.find((group) => group.entityUrn === row.entityUrn)?.rows.length ?? 0;\n const label = el('button', 'entity-label');\n label.type = 'button';\n tooltip(label, 'Open in the sidebar');\n label.append(el('span', 'title', row.title), el('span', 'meta', ` \u00B7 ${row.label}`));\n if (unsent > 0) label.append(el('span', 'meta unsent', ` \u00B7 ${unsent} unsaved`));\n label.addEventListener('click', () => this.openEntity?.(row.entityUrn));\n if (row.note) {\n const section = el('div', 'entity');\n section.append(label, el('p', 'message', row.note));\n return section;\n }\n return label;\n }\n\n private pendingSection(group: PendingGroup): HTMLElement {\n const title = group.title;\n const section = el('section', 'entity');\n section.setAttribute('aria-label', `Unsaved in ${title}`);\n section.append(el('div', 'meta', `${title}: ${group.rows.length} unsaved`));\n const list = el('ul', 'rows');\n for (const pendingRow of group.rows) {\n const item = el('li', pendingRow.problem ? 'row problem' : 'row', pendingRow.label);\n item.append(el('span', 'meta', ` \u00B7 ${pendingRow.detail}`));\n if (pendingRow.action) {\n const button = el('button', '', pendingRow.action.label);\n button.type = 'button';\n const run = pendingRow.action.run;\n button.addEventListener('click', () => run(button));\n item.append(' ', button);\n }\n list.append(item);\n }\n section.append(list, this.actions(group.entityUrn, `in ${title}`));\n return section;\n }\n\n /**\n * `debug`: an API error body, shown behind a collapsed \"Debug\" section. `action`: the next step, as a button after\n * the message; using it clears the message.\n */\n showMessage(text: string, info = false, debug?: string, action?: MessageAction): void {\n this.message.textContent = text;\n this.message.classList.toggle('info', info);\n this.messageDebug.replaceChildren(...debugDetails(debug));\n this.runMessageAction = action?.run;\n this.messageAction.textContent = action?.label ?? '';\n this.messageAction.hidden = !action;\n }\n\n showLogin(text: string, iframeSrc: string | null | undefined): void {\n this.loginText.textContent = text;\n if (iframeSrc) {\n this.loginFrame.src = iframeSrc;\n this.loginFrame.hidden = false;\n } else {\n this.loginFrame.removeAttribute('src');\n this.loginFrame.hidden = true;\n }\n this.login.hidden = false;\n }\n\n hideLogin(): void {\n this.login.hidden = true;\n }\n\n private actions(entityUrn: string | undefined, scope: string): HTMLElement {\n const actions = el('div', 'actions');\n const send = el('button', 'primary', entityUrn ? 'Save all' : 'Save everything');\n send.type = 'button';\n send.setAttribute('aria-label', `Save all unsaved changes ${scope}`);\n send.addEventListener('click', () => this.pendingActions.sendAll(entityUrn));\n const discard = button(entityUrn ? 'Discard all' : 'Discard everything', 'destructive');\n discard.setAttribute('aria-label', `Discard all unsaved changes ${scope}`);\n discard.addEventListener('click', () => this.pendingActions.discardAll(entityUrn));\n actions.append(discard, send);\n return actions;\n }\n}\n", "// Changing what the page shows (live, drafts, back to as built) in one step,\n// crossfaded with the browser's View Transitions API where it has one. No\n// styles on the host page: the browser's default crossfade is used as is.\n\n/**\n * Runs `update` (synchronous DOM changes only: read everything first) as one\n * change to the page. Resolves once the page shows it; the fade may still be\n * running. Without the API, with reduced motion asked for, or in a hidden\n * tab, the page changes at once.\n */\nexport function swapContent(update: () => void): Promise<void> {\n const reduced = window.matchMedia?.('(prefers-reduced-motion: reduce)').matches ?? false;\n if (typeof document.startViewTransition !== 'function' || reduced || document.visibilityState !== 'visible') {\n update();\n return Promise.resolve();\n }\n const transition = document.startViewTransition(update);\n // Only the animation: skipped when another transition (an Astro navigation) starts.\n transition.ready.catch(() => undefined);\n transition.finished.catch(() => undefined);\n // An error in `update` itself is passed on.\n return transition.updateCallbackDone;\n}\n", "// The page in edit mode: which elements show which items, reading the latest\n// content, rendering it (with unsaved previews), and putting the page back\n// as it was when edit mode ends: as built, or with the live content of\n// entities changed in this visit, since a built page lags until a rebuild.\n\nimport type { Entity } from '@baack-software/baack-ts-client';\nimport type { Binding } from './core/discovery.ts';\nimport { createKey } from './core/pending.ts';\nimport { inLiveContent } from './live.ts';\nimport { preview, sortOrderAttribute, urnAttribute, valueOf, type ContentItem, type TypeEntry } from './core/registry.ts';\nimport { isLive, type EditorContext, type Slot } from './targets.ts';\nimport { mark, STATE_ATTRIBUTE, unmark } from './ui/marker.ts';\nimport { swapContent } from './ui/transition.ts';\n\n/** An element exactly as the page rendered it, before edit mode. */\ninterface Snapshot {\n attributes: [string, string][];\n /** Only when the component owns the children; a boolean's children are the page's. */\n children: Node[] | undefined;\n}\n\nexport interface ViewHooks {\n /** The element being edited in place, which must not be re-rendered under the cursor. */\n editingElement(): HTMLElement | undefined;\n /** The binding being edited, in any way. */\n editingBinding(): Binding | undefined;\n closeEditor(): void;\n /** Content changed: the outline may need to redraw. */\n changed(entityUrn?: string): void;\n}\n\n/** What the page shows: the latest drafts (editable), the live page, or drafts as of a time (epoch ms). */\nexport type ReadMode = 'LATEST' | 'live' | number;\n\n/** A scope read ahead of showing it. `draft`: shown by its latest drafts on the live page, as it is not published. */\nexport interface ScopeRead {\n entity: Entity;\n draft: boolean;\n}\n\nexport class PageView {\n private readonly ctx: EditorContext;\n private readonly hooks: ViewHooks;\n private readonly snapshots = new Map<Binding, Snapshot>();\n /** Snapshots carried over when the editor itself re-tags an element (a move), by element and type. */\n private readonly carried = new Map<HTMLElement, Map<TypeEntry, Snapshot>>();\n /** Containers whose children the editor reordered, with their original order. */\n private readonly orders = new Map<Element, Node[]>();\n /** Elements the editor added to preview a new list entry. */\n private readonly added = new Set<Element>();\n private readonly loading = new Map<string, Promise<void>>();\n private editMode = false;\n private readMode: ReadMode = 'LATEST';\n /** Increments on every edit mode change, so late responses from an old session are dropped. */\n private session = 0;\n /** A version from History shown in place of the latest, on every element showing its slot. Nothing is saved. */\n private previewing: { slot: Slot; version: ContentItem } | undefined;\n private readonly previewListeners = new Set<() => void>();\n /** Entities re-read after a change in this visit (a save, a move, a publish). */\n private readonly changedThisVisit = new Set<string>();\n /**\n * The URN each element showed as the page was built, by type (none for a placeholder). Kept across edit\n * sessions: leaving edit mode after a publish leaves newer content on the page, which is not what was built.\n */\n private readonly built = new WeakMap<HTMLElement, Map<TypeEntry, string | undefined>>();\n\n constructor(ctx: EditorContext, hooks: ViewHooks) {\n this.ctx = ctx;\n this.hooks = hooks;\n }\n\n get isEditing(): boolean {\n return this.editMode;\n }\n\n get mode(): ReadMode {\n return this.readMode;\n }\n\n begin(mode: ReadMode = 'LATEST'): void {\n this.editMode = true;\n this.readMode = mode;\n this.session += 1;\n }\n\n /** The read for a mode. Draft reads need a session (rule 6); the loader only starts the editor with one. */\n private readOptions(mode: ReadMode): { version?: string } {\n if (mode === 'live') return {};\n return { version: mode === 'LATEST' ? 'LATEST' : String(mode) };\n }\n\n /**\n * Before edit mode ends: the live views of the entities changed in this\n * visit that are live now, by scope. Read first, so the page changes once.\n */\n readLiveChanges(): Promise<[string, Entity][]> {\n const { store } = this.ctx;\n const scopes = [...this.changedThisVisit]\n .filter((urn) => isLive(store.view(urn)?.status))\n .flatMap((urn) => store.scopesFor(urn));\n return this.readLive(scopes);\n }\n\n private async readLive(scopes: string[]): Promise<[string, Entity][]> {\n try {\n return await Promise.all(scopes.map(async (scope): Promise<[string, Entity]> => [scope, await this.ctx.views.read(scope)]));\n } catch (error) {\n // The page stays as built; a retry outside edit mode shows the published content.\n void this.ctx.feedback.report(error, 'show the published content', () => {\n void this.readLive(scopes).then((reads) => {\n if (!this.editMode) this.showLive(reads);\n });\n });\n return [];\n }\n }\n\n /**\n * Outside edit mode, shows live views read by `readLiveChanges`: the page\n * as visitors see it once the site is rebuilt (or at once, if it renders\n * per request). Items with no live version keep what the page rendered.\n * True when anything differed from the page as rendered.\n */\n showLive(reads: [string, Entity][]): boolean {\n const { store, discovery } = this.ctx;\n for (const [scope, entity] of reads) store.loadEntity(scope, entity);\n const scopes = new Set(reads.map(([scope]) => scope));\n let changed = false;\n // Restoring put back the sort orders the editor changed (moves): bind as the page is now.\n discovery.flush();\n for (const binding of discovery.all()) {\n if (!scopes.has(binding.scope)) continue;\n const stored = store.itemFor(binding);\n if (!stored?.item.urn || binding.element.getAttribute(urnAttribute(binding.entry)) === stored.item.urn) continue;\n this.recordBuilt(binding);\n this.ctx.live.render(binding, stored.item);\n changed = true;\n }\n store.clearEntities();\n return changed;\n }\n\n /**\n * Leaves edit mode in one change to the page: puts it back as built, then\n * shows the live reads from `readLiveChanges`. True when those differed.\n */\n async leave(reads: [string, Entity][]): Promise<boolean> {\n let changed = false;\n await swapContent(() => {\n this.end();\n changed = this.showLive(reads);\n });\n return changed;\n }\n\n /** Reads every scope in a mode without changing what the page shows, so a switch can change it once. */\n async prefetch(mode: ReadMode, scopes: string[]): Promise<Map<string, ScopeRead>> {\n const reads = await Promise.all(scopes.map(async (scope) => [scope, await this.readIn(scope, mode)] as const));\n return new Map(reads);\n }\n\n /** Switches the read mode in one change to the page, from reads made by `prefetch`. */\n async switchTo(mode: ReadMode, reads: Map<string, ScopeRead>): Promise<void> {\n const { store, discovery } = this.ctx;\n await swapContent(() => {\n this.end();\n this.begin(mode);\n for (const [scope, read] of reads) {\n store.loadEntity(scope, read.entity);\n if (read.draft) this.draftsOnLivePage.add(read.entity.urn);\n }\n // Ending put back the sort orders the editor changed: bind as the page is now.\n discovery.flush();\n for (const binding of discovery.all()) this.show(binding);\n });\n this.hooks.changed();\n }\n\n /** The URN of the version being previewed, if any. */\n get previewedUrn(): string | undefined {\n return this.previewing?.version.urn;\n }\n\n /** Called when a preview starts or stops. */\n onPreviewChange(listener: () => void): void {\n this.previewListeners.add(listener);\n }\n\n /**\n * Shows a version's value on every element showing its slot, in place of\n * the latest. The element keeps the latest version's URN, so editing still\n * starts from the latest. Nothing is sent. Not for view-rendered types.\n */\n previewVersion(slot: Slot, version: ContentItem): void {\n const previous = this.previewing?.slot;\n this.previewing = { slot, version };\n if (previous && !sameSlot(previous, slot)) this.reshow(previous);\n this.reshow(slot);\n this.notifyPreview();\n }\n\n /** Ends a preview (only one of `slot`, when given), showing the latest again. */\n stopPreview(slot?: Slot): void {\n const previewing = this.previewing;\n if (!previewing || (slot && !sameSlot(previewing.slot, slot))) return;\n this.previewing = undefined;\n this.reshow(previewing.slot);\n this.notifyPreview();\n }\n\n private notifyPreview(): void {\n for (const listener of this.previewListeners) listener();\n }\n\n /** Puts every element back as the page rendered it and forgets what was read. */\n end(): void {\n if (this.previewing) {\n this.previewing = undefined;\n this.notifyPreview();\n }\n this.editMode = false;\n this.session += 1;\n this.ctx.live.endPreviews();\n for (const element of this.added) element.remove();\n this.added.clear();\n this.restoreOrders();\n for (const binding of [...this.snapshots.keys()]) this.restore(binding);\n for (const [element, byEntry] of this.carried) {\n // Moves inside live content are not supported yet: its framework owns the order.\n for (const saved of byEntry.values()) if (element.isConnected && !inLiveContent(element)) restoreSnapshot(element, saved);\n }\n this.carried.clear();\n this.ctx.store.clearEntities();\n this.loading.clear();\n this.draftsOnLivePage.clear();\n this.ctx.sources.clear();\n }\n\n async hydrate(bindings: Binding[]): Promise<void> {\n const session = this.session;\n const scopes = new Set(bindings.map((binding) => binding.scope));\n await Promise.all([...scopes].map((scope) => this.loadScope(scope)));\n if (session !== this.session) return;\n await swapContent(() => {\n if (session !== this.session) return;\n for (const binding of bindings) {\n if (this.ctx.discovery.of(binding.element).includes(binding)) this.show(binding);\n }\n });\n if (session !== this.session) return;\n this.hooks.changed();\n }\n\n /** Entities shown by their latest drafts on the live page, because they are not published. */\n readonly draftsOnLivePage = new Set<string>();\n\n /** Reads a scope in the current mode. On the live page, an entity that is not published shows its latest drafts. */\n private async readScope(scope: string): Promise<Entity> {\n const { entity, draft } = await this.readIn(scope, this.readMode);\n if (draft) this.draftsOnLivePage.add(entity.urn);\n else this.draftsOnLivePage.delete(entity.urn);\n return entity;\n }\n\n private async readIn(scope: string, mode: ReadMode): Promise<ScopeRead> {\n const { views } = this.ctx;\n if (mode !== 'live') return { entity: await views.read(scope, this.readOptions(mode)), draft: false };\n const { entity, live } = await views.readAsLive(scope);\n return { entity, draft: !live };\n }\n\n /** Reads a scope (or an entity URN) in the current mode, once per edit session. */\n loadScope(scope: string): Promise<void> {\n const { store, feedback, discovery } = this.ctx;\n if (store.hasScope(scope)) return Promise.resolve();\n let loading = this.loading.get(scope);\n if (!loading) {\n const session = this.session;\n loading = this.readScope(scope)\n .then((entity) => {\n if (session === this.session) store.loadEntity(scope, entity);\n })\n .catch((error: unknown) => {\n this.loading.delete(scope);\n const action = this.readMode === 'live' ? 'load the live content' : 'load the latest content';\n void feedback.report(error, action, () => void this.hydrate(discovery.all()));\n });\n this.loading.set(scope, loading);\n }\n return loading;\n }\n\n /** Renders a binding from the latest view, previewing any unsaved value. */\n show(binding: Binding): void {\n const { store, pending } = this.ctx;\n const { element, entry } = binding;\n if (!this.snapshots.has(binding)) this.snapshots.set(binding, this.carriedSnapshot(element, entry) ?? snapshot(element, entry));\n this.recordBuilt(binding);\n const stored = store.itemFor(binding);\n const previewing = this.previewing;\n if (stored?.item.urn && previewing && sameSlot(previewing.slot, { ...binding, entityUrn: store.entityFor(binding.scope)! })) {\n this.ctx.live.render(binding, preview(entry, stored.item, valueOf(entry, previewing.version)));\n mark(element, 'previewing');\n return;\n }\n if (stored?.item.urn) {\n const edit = pending.getEdit(stored.item.urn);\n const usable = edit && !edit.stale;\n // A view-rendered type cannot preview: the page would need the server's rendering.\n const item = usable && !entry.renderedByView ? preview(entry, stored.item, edit.value) : stored.item;\n this.ctx.live.render(binding, item);\n mark(element, usable ? 'changed' : this.publishedSinceBuilt(binding, stored.item.urn) ? 'published' : 'editable');\n return;\n }\n const entityUrn = store.entityFor(binding.scope);\n const create = entityUrn\n ? pending.getCreate(createKey({ entityUrn, type: entry.type, name: binding.name, sortOrder: binding.sortOrder }))\n : undefined;\n if (create && !entry.renderedByView) {\n this.ctx.live.render(binding, { name: binding.name, sortOrder: binding.sortOrder, ...create.value } as ContentItem);\n mark(element, 'changed');\n } else {\n mark(element, create ? 'changed' : 'unresolved');\n }\n }\n\n /** Notes what an element showed as built, the first time the editor is about to change it. */\n private recordBuilt({ element, entry }: Binding): void {\n const byEntry = this.built.get(element) ?? new Map<TypeEntry, string | undefined>();\n if (!byEntry.has(entry)) byEntry.set(entry, element.getAttribute(urnAttribute(entry)) ?? undefined);\n this.built.set(element, byEntry);\n }\n\n /** On the live page: the element shows a version published since the page was built (not a draft shown instead). */\n private publishedSinceBuilt(binding: Binding, urn: string): boolean {\n if (this.readMode !== 'live') return false;\n const entityUrn = this.ctx.store.entityFor(binding.scope);\n if (!entityUrn || this.draftsOnLivePage.has(entityUrn)) return false;\n return this.built.get(binding.element)?.get(binding.entry) !== urn;\n }\n\n /** How many elements on the live page show content published since the page was built. */\n countPublishedSinceBuilt(): number {\n return new Set(\n this.ctx.discovery\n .all()\n .filter((binding) => binding.element.getAttribute(STATE_ATTRIBUTE) === 'published')\n .map((binding) => binding.element),\n ).size;\n }\n\n showAll(): void {\n for (const binding of this.ctx.discovery.all()) this.show(binding);\n }\n\n /** Re-renders every element showing a slot or version, except one being edited in place. */\n reshow(target: Slot & { urn?: string | undefined }): void {\n const { discovery, store } = this.ctx;\n for (const binding of discovery.all()) {\n if (binding.entry !== target.entry || store.entityFor(binding.scope) !== target.entityUrn) continue;\n const showsUrn = target.urn && binding.element.getAttribute(urnAttribute(binding.entry)) === target.urn;\n const showsSlot = binding.name === target.name && binding.sortOrder === target.sortOrder;\n if (!showsUrn && !showsSlot) continue;\n if (this.hooks.editingElement() === binding.element) continue;\n this.show(binding);\n }\n }\n\n forget(bindings: Binding[]): void {\n for (const binding of bindings) {\n if (this.hooks.editingBinding() === binding) this.hooks.closeEditor();\n // Re-tagged by the editor: its snapshot travels with it to the new binding.\n if (this.carried.get(binding.element)?.has(binding.entry)) {\n this.snapshots.delete(binding);\n continue;\n }\n this.restore(binding);\n }\n }\n\n /**\n * Gives an element a new sort order (after a move), keeping the snapshot of\n * how the page rendered it, so leaving edit mode still restores it exactly.\n */\n retag(binding: Binding, sortOrder: number, name = binding.name): void {\n const { element, entry } = binding;\n const saved = this.snapshots.get(binding) ?? snapshot(element, entry);\n const byEntry = this.carried.get(element) ?? new Map<TypeEntry, Snapshot>();\n byEntry.set(entry, saved);\n this.carried.set(element, byEntry);\n element.setAttribute(sortOrderAttribute(entry), String(sortOrder));\n element.setAttribute(`data-${entry.attribute}-name`, name);\n }\n\n private carriedSnapshot(element: HTMLElement, entry: TypeEntry): Snapshot | undefined {\n const byEntry = this.carried.get(element);\n const saved = byEntry?.get(entry);\n if (saved) byEntry!.delete(entry);\n if (byEntry && byEntry.size === 0) this.carried.delete(element);\n return saved;\n }\n\n /** Remembers a container's child order before the editor first reorders it. */\n rememberOrder(container: Element): void {\n // The page's framework owns the order of live content: the editor never moves it, so has nothing to put back.\n if (inLiveContent(container)) return;\n if (!this.orders.has(container)) this.orders.set(container, [...container.childNodes]);\n }\n\n /** Puts a container's children back in the order the page rendered them. */\n restoreOrder(container: Element): void {\n const nodes = this.orders.get(container);\n if (!nodes) return;\n container.append(...nodes.filter((node) => node.parentNode === container || !node.parentNode));\n this.orders.delete(container);\n }\n\n private restoreOrders(): void {\n for (const container of [...this.orders.keys()]) this.restoreOrder(container);\n }\n\n /** Tracks an element the editor added to preview a new entry; removed when edit mode ends. */\n track(element: Element): void {\n this.added.add(element);\n }\n\n /** Re-reads the latest view of an entity and re-renders what it shows, so templates and renderings update. */\n async refresh(entityUrn: string): Promise<void> {\n const { store, feedback, discovery } = this.ctx;\n const session = this.session;\n const scopes = store.scopesFor(entityUrn);\n if (this.readMode === 'LATEST') this.changedThisVisit.add(entityUrn);\n try {\n for (const scope of scopes) {\n const entity = await this.readScope(scope);\n if (session !== this.session) return;\n store.loadEntity(scope, entity);\n }\n } catch (error) {\n void feedback.report(error, 'show the latest content', () => void this.refresh(entityUrn));\n return;\n }\n for (const binding of discovery.all()) {\n if (scopes.includes(binding.scope) && this.hooks.editingBinding() !== binding) this.show(binding);\n }\n this.hooks.changed(entityUrn);\n }\n\n /** Elements showing a slot of an entity. */\n bindingsAt(slot: Slot): Binding[] {\n return this.ctx.discovery\n .all()\n .filter(\n (b) =>\n b.entry === slot.entry &&\n b.name === slot.name &&\n b.sortOrder === slot.sortOrder &&\n this.ctx.store.entityFor(b.scope) === slot.entityUrn,\n );\n }\n\n /** Elements of an entity's scopes whose slot has no item, one per slot. */\n missingBindings(entityUrn: string): Binding[] {\n const { store, discovery } = this.ctx;\n const seen = new Set<string>();\n return discovery.all().filter((binding) => {\n if (store.entityFor(binding.scope) !== entityUrn) return false;\n if (store.itemAt(entityUrn, binding.entry, binding.name, binding.sortOrder)) return false;\n const key = createKey({ entityUrn, type: binding.entry.type, name: binding.name, sortOrder: binding.sortOrder });\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n }\n\n private restore(binding: Binding): void {\n const saved = this.snapshots.get(binding);\n this.snapshots.delete(binding);\n unmark(binding.element);\n if (this.ctx.live.restore(binding)) {\n // The page re-renders its own value later; until then the element carries the URN it had, as a later read compares it.\n const urn = urnAttribute(binding.entry);\n const own = saved?.attributes.find(([name]) => name === urn)?.[1];\n if (own) binding.element.setAttribute(urn, own);\n else binding.element.removeAttribute(urn);\n return;\n }\n if (saved && binding.element.isConnected) restoreSnapshot(binding.element, saved);\n }\n}\n\nfunction snapshot(element: HTMLElement, entry: TypeEntry): Snapshot {\n const ownsChildren = entry.component?.(element).ownsChildren ?? true;\n return {\n attributes: [...element.attributes].map((attribute) => [attribute.name, attribute.value]),\n children: ownsChildren ? [...element.childNodes].map((node) => node.cloneNode(true)) : undefined,\n };\n}\n\nfunction restoreSnapshot(element: HTMLElement, saved: Snapshot): void {\n const names = new Set(saved.attributes.map(([name]) => name));\n for (const attribute of [...element.attributes]) {\n if (!names.has(attribute.name)) element.removeAttribute(attribute.name);\n }\n for (const [name, value] of saved.attributes) element.setAttribute(name, value);\n if (saved.children) element.replaceChildren(...saved.children);\n}\n\nfunction sameSlot(a: Slot, b: Slot): boolean {\n return a.entityUrn === b.entityUrn && a.entry === b.entry && a.name === b.name && a.sortOrder === b.sortOrder;\n}\n", "// The editor's composition root: builds the shared context and the modules,\n// and owns edit mode, the unsaved-changes list, and the stash.\n//\n// view.ts the page in edit mode: reading, rendering, restoring\n// editing.ts opening editors and recording unsaved values\n// saving.ts saving, save all, create all\n// outline-model.ts the item outline\n// onboarding.ts entities for pages that have none, new pages\n\nimport type { ClientContext } from '@baack-software/baack-ts-client';\nimport { Discovery, SCOPE_ATTRIBUTE } from './core/discovery.ts';\nimport { PendingEdits, type Pending } from './core/pending.ts';\nimport type { ItemType, TypeEntry } from './core/registry.ts';\nimport { Stash } from './core/stash.ts';\nimport { Store } from './core/store.ts';\nimport type { Transport } from './core/transport.ts';\nimport { Editing } from './editing.ts';\nimport { Feedback } from './feedback.ts';\nimport { History } from './history.ts';\nimport { Moves } from './moves.ts';\nimport { OrderTags } from './ui/order-tags.ts';\nimport { Images } from './images.ts';\nimport { GroupLog } from './core/groups.ts';\nimport { Onboarding } from './onboarding.ts';\nimport { OutlineModel } from './outline-model.ts';\nimport { Publishing } from './publishing.ts';\nimport { LiveIslands } from './live.ts';\nimport { Saving } from './saving.ts';\nimport { isLive, pageEntity, pageFirst, type EditorContext, type EditorHooks, type Value } from './targets.ts';\nimport { displayPath, EntityDirectory } from './core/entity-directory.ts';\nimport { defaultPagePath } from './page-entity.ts';\nimport type { EntityPickerSource } from './ui/entity-picker.ts';\nimport { announcePublished, DEFAULT_LIVE_NOTE, fixedMessage, type PublishedDetail } from './after-publish.ts';\nimport './config.ts'; // Declares window.baackEditorConfig.\nimport type { EditorHost } from './ui/host.ts';\nimport { Popover } from './ui/popover.ts';\nimport { Toolbar, type PendingGroup } from './ui/toolbar.ts';\nimport { PageView, type ReadMode, type ScopeRead } from './view.ts';\nimport { ScopedViews } from './core/scoped-views.ts';\n\nexport class Editor {\n private readonly ctx: EditorContext;\n private readonly view: PageView;\n private readonly editing: Editing;\n private readonly saving: Saving;\n private readonly outline: OutlineModel;\n private readonly onboarding: Onboarding;\n private readonly history: History;\n private readonly publishing: Publishing;\n private readonly moves: Moves;\n /** The tags on the members of keyed groups (cards, sections), with their move menus. */\n private readonly tags: OrderTags;\n private readonly images: Images;\n private readonly stash: Stash | undefined;\n private restored = false;\n\n constructor(\n transport: Transport,\n host: EditorHost,\n entries: readonly TypeEntry[],\n registry: readonly TypeEntry[],\n context: ClientContext,\n ) {\n const store = new Store();\n let toolbar: Toolbar | undefined;\n const feedback = new Feedback(transport, () => toolbar!);\n toolbar = new Toolbar(host, () => feedback.retryAfterLogin(), {\n sendAll: (entityUrn) => void this.saving.saveAll(entityUrn),\n discardAll: (entityUrn) => this.saving.discardAll(entityUrn),\n });\n const discovery = new Discovery(entries, {\n added: (bindings) => {\n if (this.view.isEditing) void this.view.hydrate(bindings);\n },\n removed: (bindings) => this.view.forget(bindings),\n });\n\n const directory = new EntityDirectory(\n transport,\n async () => {\n // Every company the user may administer; the context's own when that cannot be listed.\n const companies = await transport.companies().catch(() => []);\n const urns = companies.map((company) => company.urn);\n return urns.length > 0 ? urns : context.company?.urn ? [context.company.urn] : [];\n },\n context.user?.urn,\n );\n\n this.ctx = {\n transport,\n host,\n registry,\n store,\n pending: new PendingEdits(() => this.pendingChanged()),\n toolbar,\n popover: new Popover(host),\n panels: {\n show: (content, options) => this.outline.showPanel(content, options),\n },\n feedback,\n views: new ScopedViews(transport),\n sources: new Map<string, Value>(),\n discovery,\n canPublish: ['PUBLISHER', 'ADMIN', 'SUPER'].includes(context.user?.role ?? ''),\n requiredImageSlots: window.baackEditorConfig?.requiredImageSlots ?? ['DEFAULT'],\n live: new LiveIslands(store),\n hooks: {\n openHistory: (slot) => void this.history.open(slot),\n publishEntity: (entityUrn) => void this.publishing.openReview(entityUrn),\n canReorder: (binding) => (this.moves.groupOf(binding)?.units.length ?? 0) > 1,\n reorder: (binding) => this.moves.openReorder(binding),\n moveBy: (binding, delta) => this.moves.moveBy(binding, delta),\n relocate: (target) => {\n this.editing.close();\n this.outline.focusSlot(target);\n },\n showItem: (slot) => this.outline.selectItem(slot),\n rename: (slot, item) => void this.moves.relocate(undefined, slot.entityUrn, slot.entry, item),\n moveSlot: (slot, item, sortOrder) => this.moves.moveTo(slot.entityUrn, slot.entry, item, { name: slot.name, sortOrder }),\n runPlan: (planId) => this.moves.run(planId),\n saveImage: (target, files) => this.images.save(target, files),\n } satisfies EditorHooks,\n groups: context.user?.urn ? new GroupLog(context.user.urn) : undefined,\n entry: (type: ItemType) => registry.find((entry) => entry.type === type)!,\n entityTitle: (entityUrn: string) => {\n const name = store.view(entityUrn)?.name;\n return name ? `Content for ${displayPath(name)}` : `Entity ${entityUrn.slice(0, 8)}`;\n },\n announcePublished: (entityUrn, done, options = {}) => {\n const view = store.view(entityUrn);\n const name = view?.name ?? '';\n const detail: PublishedDetail = { entityUrn, name, path: name && pagePath(displayPath(name)), language: view?.language ?? '', variant: view?.variant ?? '' };\n if (options.itemUrn) detail.itemUrn = options.itemUrn;\n void announcePublished(toolbar, window.baackEditorConfig?.afterPublish, detail, done, options.info);\n },\n };\n\n this.stash = context.user?.urn ? new Stash(context.user.urn) : undefined;\n this.view = new PageView(this.ctx, {\n editingElement: () => (this.editing.current?.session ? this.editing.current.target.binding?.element : undefined),\n editingBinding: () => this.editing.current?.target.binding,\n closeEditor: () => this.editing.close(),\n changed: (entityUrn) => {\n this.refreshTags();\n this.outline.changed(entityUrn);\n this.history?.changed(entityUrn);\n this.publishing?.changed();\n },\n });\n this.saving = new Saving(this.ctx, this.view, () => this.editing);\n this.editing = new Editing(this.ctx, this.view, (target) => this.saving.save(target));\n this.onboarding = new Onboarding({\n transport,\n toolbar,\n context,\n registry,\n store,\n panels: this.ctx.panels,\n openEntity: (entityUrn) => this.outline.openEntity(entityUrn),\n entityNameForPage: window.baackEditorConfig?.entityNameForPage,\n report: (error, action, retry) => feedback.report(error, action, retry),\n created: (entity) => directory.remember(entity),\n });\n this.ctx.popover.setEntitySource(this.entitySource(directory));\n this.outline = new OutlineModel(this.ctx, this.view, this.editing, this.saving, this.onboarding);\n const sidebar = this.outline.outline.stack;\n sidebar.avoid(toolbar.modeButton.closest<HTMLElement>('.toolbar')!);\n // A bottom sheet on narrow screens steps aside while an item is edited, so only the popover shows (host.ts).\n const popover = this.ctx.popover.element;\n new MutationObserver(() => sidebar.element.classList.toggle('item-editing', !popover.hidden)).observe(popover, {\n attributes: true,\n attributeFilter: ['hidden'],\n });\n this.moves = new Moves(this.ctx, this.view, () => this.editing, () => this.ctx.groups, (change) => this.saving.commit(change));\n this.tags = new OrderTags(this.ctx.host, (binding) => this.moves.openOrderMenu(binding));\n this.moves.onOrderChange(() => this.refreshTags());\n this.images = new Images(this.ctx, this.view, () => this.saving, () => this.editing);\n this.publishing = new Publishing(this.ctx, this.view, window.baackEditorConfig?.publishTimeoutMs ?? 5 * 60 * 1000, this.outline.outline.stack, {\n show: (level, entityUrn) => this.outline.showAbove(entityUrn, level),\n });\n this.history = new History(this.ctx, this.editing, this.view, this.outline.outline.stack, {\n show: (level, entityUrn) => this.outline.showAbove(entityUrn, level),\n publishEntity: (entityUrn) => this.ctx.hooks.publishEntity(entityUrn),\n published: async (entityUrn) => {\n await this.view.refresh(entityUrn);\n await this.publishing.refreshStatus(entityUrn);\n },\n });\n\n toolbar.modeButton.addEventListener('click', () => void this.setEditMode(!this.view.isEditing));\n toolbar.itemsButton.addEventListener('click', () => this.outline.toggle());\n toolbar.setOpenEntity((entityUrn) => this.outline.openEntity(entityUrn));\n toolbar.onLifecycle(() => this.outline.changed());\n toolbar.setOpenPending(() => this.outline.togglePending());\n toolbar.onPending(() => this.outline.changed());\n this.outline.onClose(() => this.history.stopPreview());\n toolbar.readButton.addEventListener('click', () => void this.setReadMode(this.view.mode === 'LATEST' ? 'live' : 'LATEST'));\n document.addEventListener('keydown', (event) => {\n if (this.view.isEditing && event.altKey && event.shiftKey && event.code === 'KeyI') {\n event.preventDefault();\n this.outline.toggle();\n if (this.outline.outline.isOpen) this.outline.outline.focusFilter();\n }\n });\n discovery.start();\n }\n\n private leaving: Promise<void> | undefined;\n\n get isEditing(): boolean {\n return this.view.isEditing;\n }\n\n /** `showLive`: on leaving, show content published in this visit (not when only switching the read mode). */\n async setEditMode(on: boolean, mode: ReadMode = 'LATEST', showLive = true): Promise<void> {\n // Leaving reads the live content first; a click meanwhile waits for it.\n await this.leaving;\n if (on === this.view.isEditing) return;\n const { toolbar, discovery } = this.ctx;\n toolbar.setEditMode(on);\n if (on) {\n this.view.begin(mode);\n this.startMode(mode);\n await this.view.hydrate(discovery.all());\n await this.afterRead(mode);\n } else {\n this.stopMode();\n // Content published in this visit is shown live, not as the (older) built page.\n const reading = showLive && this.view.mode === 'LATEST' ? this.view.readLiveChanges() : Promise.resolve([]);\n this.leaving = reading.then(() => undefined);\n const live = await reading;\n this.leaving = undefined;\n if (await this.view.leave(live)) {\n toolbar.showMessage(`Showing the published content. ${fixedMessage(window.baackEditorConfig?.afterPublish) ?? DEFAULT_LIVE_NOTE}`, true);\n }\n }\n }\n\n /** The toolbar and editing for a read mode, before its content shows. */\n private startMode(mode: ReadMode): void {\n this.showReadMode(mode);\n if (mode === 'LATEST') {\n this.editing.attach();\n this.publishing.start();\n this.outline.setNewEntity(() => void this.onboarding.offerNewEntity(this.pageLanguage()));\n }\n }\n\n /** The language of the page's entity: the default for a new entity. */\n private pageLanguage(): string {\n const { store } = this.ctx;\n const page = pageEntity(store);\n return (page && store.view(page)?.language) || document.documentElement.lang || 'en-GB';\n }\n\n /** Where entity fields (references) find entities, and how they create one. */\n private entitySource(directory: EntityDirectory): EntityPickerSource {\n const { transport, feedback } = this.ctx;\n const onboarding = () => this.onboarding;\n const pageLanguage = () => this.pageLanguage();\n return {\n list: (onUpdate) => directory.list(onUpdate),\n describe: (urn) => directory.describe(urn),\n get language() {\n return pageLanguage();\n },\n create(container, path) {\n return new Promise((resolve) => {\n void onboarding()\n .newEntityForm({\n title: 'New entity',\n submitLabel: 'Create and choose it',\n path,\n language: this.language,\n onCreated: (entity) => resolve(directory.remember(entity)),\n onCancel: () => resolve(undefined),\n })\n .then((form) => {\n // Escape cancels this form only, not the item's.\n form.element.addEventListener('keydown', (event) => {\n if (event.key !== 'Escape') return;\n event.preventDefault();\n event.stopPropagation();\n form.cancel();\n });\n container.replaceChildren(form.element);\n form.element.querySelector('input')?.focus();\n });\n });\n },\n note: async (urn) => {\n const entity = await transport.readEntity(urn);\n directory.remember(entity);\n return isLive(entity.status) || entity.status === 'PUBLISH'\n ? ''\n : `${displayPath(entity.name)} is not published yet, so pages show it only once it is.`;\n },\n pagePath,\n report: (error, action, retry) => void feedback.report(error, action, retry),\n };\n }\n\n /** Tags every member of a keyed group while the editable drafts show. */\n private refreshTags(): void {\n if (!this.tags) return;\n if (this.view.isEditing && this.view.mode === 'LATEST') this.tags.show(this.moves.keyedMembers());\n else this.tags.clear();\n }\n\n /** Closes everything that belongs to the current read mode. */\n private stopMode(): void {\n const { toolbar } = this.ctx;\n this.tags.clear();\n this.editing.detach();\n this.editing.close();\n this.outline.clear();\n this.history.close();\n this.publishing.stop();\n this.moves.panel.close();\n this.outline.setNewEntity(undefined);\n toolbar.showMessage('');\n toolbar.hideLogin();\n }\n\n /** Once a mode's content shows: its notices, then unsaved work and onboarding for the editable drafts. */\n private async afterRead(mode: ReadMode): Promise<void> {\n const { toolbar, discovery } = this.ctx;\n if (mode === 'live') {\n // Content published since the page was built is live, but a built site shows it only after its next build.\n const newer = this.view.countPublishedSinceBuilt();\n const parts = [\n newer > 0\n ? `Showing the live content. ${newer === 1 ? '1 item was' : `${newer} items were`} published since this page was built, outlined in green. ${fixedMessage(window.baackEditorConfig?.afterPublish) ?? DEFAULT_LIVE_NOTE}`\n : 'Showing the live page, as visitors see it.',\n ];\n if (this.view.draftsOnLivePage.size > 0) {\n const titles = [...this.view.draftsOnLivePage].map((urn) => this.ctx.entityTitle(urn)).join(', ');\n parts.push(`Not published yet, so shown as the latest drafts: ${titles}.`);\n }\n toolbar.showMessage(`${parts.join(' ')} Editing is off.`, true);\n }\n if (mode !== 'LATEST') return;\n await this.restoreStash();\n if (discovery.unscoped().length > 0 && !document.documentElement.hasAttribute(SCOPE_ATTRIBUTE)) {\n void this.onboarding.offerEntityForPage();\n }\n }\n\n /**\n * Shows the page as the live site does, or as the latest drafts were at a\n * time (read-only), or back to the editable latest drafts.\n */\n async setReadMode(mode: ReadMode): Promise<void> {\n if (!this.view.isEditing) {\n await this.setEditMode(true, mode);\n return;\n }\n if (mode === this.view.mode) return;\n // Read the new mode first, so the page changes once instead of showing the built page in between.\n const scopes = [...new Set(this.ctx.discovery.all().map((binding) => binding.scope))];\n let reads: Map<string, ScopeRead>;\n try {\n reads = await this.view.prefetch(mode, scopes);\n } catch (error) {\n const action = mode === 'live' ? 'load the live content' : 'load the latest content';\n void this.ctx.feedback.report(error, action, () => void this.setReadMode(mode));\n return;\n }\n if (!this.view.isEditing || mode === this.view.mode) return;\n this.stopMode();\n this.startMode(mode);\n await this.view.switchTo(mode, reads);\n await this.afterRead(mode);\n }\n\n private showReadMode(mode: ReadMode): void {\n const { toolbar } = this.ctx;\n toolbar.setReadMode(mode === 'LATEST');\n if (mode === 'live') toolbar.showMessage('Showing the live page, as visitors see it. Editing is off.', true);\n if (typeof mode === 'number') {\n toolbar.showMessage(`Showing the latest drafts as of ${new Date(mode).toLocaleString()}. Read-only.`, true);\n }\n }\n\n // ---------------------------------------------------------------------\n // Unsaved work: the toolbar list, the stash, and leaving the page\n // ---------------------------------------------------------------------\n\n private pendingChanged(): void {\n const { pending, toolbar } = this.ctx;\n const all = pending.all();\n this.stash?.save(all);\n const byEntity = pending.byEntity();\n const groups: PendingGroup[] = pageFirst(this.ctx.store, [...byEntity.keys()]).map((entityUrn) => ({\n entityUrn,\n title: this.ctx.entityTitle(entityUrn),\n rows: byEntity.get(entityUrn)!.map((p) => ({\n label: `${p.name} #${p.sortOrder}`,\n detail:\n p.kind === 'create'\n ? 'new item'\n : p.kind === 'move'\n ? `${p.label}: to ${p.to.name === p.name ? '' : p.to.name}#${p.to.sortOrder}`\n : p.stale\n ? 'based on an older version'\n : 'edit',\n problem: p.kind === 'edit' && p.stale === true,\n ...(p.kind === 'edit' && p.stale ? { action: { label: 'Resolve', run: (anchor: HTMLElement) => void this.saving.resolve(p, anchor) } } : {}),\n })),\n }));\n toolbar.setPending(groups);\n if (all.length > 0) {\n window.addEventListener('beforeunload', onBeforeUnload);\n } else {\n window.removeEventListener('beforeunload', onBeforeUnload);\n }\n // Built lazily: the first restore runs before the outline exists.\n this.outline?.changed();\n }\n\n /** Restores unsaved work from this browser, once per page load. */\n private async restoreStash(): Promise<void> {\n if (this.restored || !this.stash) return;\n this.restored = true;\n const items = this.stash.load();\n if (items.length === 0) return;\n await Promise.all([...new Set(items.map((p) => p.entityUrn))].map((urn) => this.view.loadScope(urn)));\n const restored = items.map((p): Pending => {\n if (p.kind !== 'edit') return p;\n const current = this.ctx.store.itemAt(p.entityUrn, this.ctx.entry(p.type), p.name, p.sortOrder);\n return current?.item.urn === p.urn ? { ...p, stale: false } : { ...p, stale: true };\n });\n this.ctx.pending.load(restored);\n this.view.showAll();\n this.ctx.toolbar.showMessage(\n `Restored ${restored.length} unsaved ${restored.length === 1 ? 'change' : 'changes'} from this browser.`,\n true,\n );\n }\n}\n\nfunction onBeforeUnload(event: BeforeUnloadEvent): void {\n event.preventDefault();\n}\n\n/** The page address an entity serves, by the site's rule or the default (`/home` is `/`). */\nfunction pagePath(path: string): string {\n return (window.baackEditorConfig?.pagePathForEntity ?? defaultPagePath)(path);\n}\n", "import { Endpoint, type TextItem } from '@baack-software/baack-ts-client';\nimport * as components from '@baack-software/baack-ts-components/components';\nimport type { TypeEntry } from '../core/registry.ts';\n\n// Something that looks like a tag: <p>, </p>, <br/>, <!-- -->, <script ...>.\nconst MARKUP = /<\\/?[a-z!][^>]*>/i;\n\nexport const text: TypeEntry<TextItem> = {\n type: 'text',\n label: 'Text',\n attribute: 'text',\n entityArray: 'texts',\n endpoint: Endpoint.TEXT,\n historyEndpoint: Endpoint.TEXT_HISTORY,\n surface: 'inline',\n valueKeys: ['value'],\n\n component: (element) =>\n element.localName === 'meta'\n ? components.meta\n : element.hasAttribute('data-section')\n ? components.section\n : escaped(element.getAttribute('data-text-layout') === 'paragraphs' ? components.textBlock : components.text),\n\n find: (view, name, sortOrder) => view.text(name, sortOrder),\n\n defaults: () => ({ value: '' }),\n\n // While editing, the element holds the raw value as text (see InlineEdit).\n read: (element) => ({ value: plainText(element) }),\n\n // Away from its element: head items, the outline, and creates.\n form: {\n fields: [{ key: 'value', label: 'Text', kind: 'textarea' }],\n toForm: (value) => ({ value: value.value }),\n fromForm: (values) => ({ value: typeof values['value'] === 'string' ? values['value'] : '' }),\n },\n\n fromPlaceholder: (element) => {\n if (element.localName === 'meta') return { value: element.getAttribute('content') ?? '' };\n // A section's (or card's) order item holds its key, never the content it wraps.\n if (element.hasAttribute('data-section')) return { value: element.getAttribute('data-section') ?? '' };\n if (element.getAttribute('data-text-layout') === 'paragraphs') {\n return { value: [...element.querySelectorAll(':scope > p')].map((p) => plainText(p)).join('\\n\\n') };\n }\n return { value: plainText(element) };\n },\n\n validate: ({ value }) =>\n MARKUP.test(value)\n ? [{ level: 'warning', message: 'This looks like HTML. Text items are plain text, so the page shows the tags as typed, and apps on other platforms will too.' }]\n : [],\n};\n\n/**\n * The editor never inserts a text value as HTML (CLAUDE.md rule 1), even where\n * the page opted into `unsafeLiteral`: in edit mode it shows drafts written by\n * other people. Such an element shows its text escaped while editing, keeps\n * its marker, and gets its HTML back from the page's own rendering on exit.\n */\nfunction escaped<P extends components.TextProps>(\n spec: components.ComponentSpec<TextItem, P>,\n): components.ComponentSpec<TextItem, P> {\n return {\n ...spec,\n render(ref, props) {\n const node = spec.render(ref, { ...props, unsafeLiteral: false });\n if (props.unsafeLiteral) node.attrs['data-text-unsafe-literal'] = '';\n return node;\n },\n };\n}\n\n/** The element's text with line breaks kept; the browser may insert <br> while editing. */\nfunction plainText(element: Node): string {\n let result = '';\n for (const node of element.childNodes) {\n if (node.nodeType === Node.TEXT_NODE) {\n result += node.nodeValue ?? '';\n } else if (node.nodeName === 'BR') {\n result += '\\n';\n } else {\n result += plainText(node);\n }\n }\n return result;\n}\n", "// The registry: one entry for each of the thirteen item types.\n\nimport type { TypeEntry } from '../core/registry.ts';\nimport { text } from './text.ts';\nimport {\n boolean,\n dateTime,\n double,\n image,\n json,\n latLong,\n link,\n long,\n markdown,\n money,\n reference,\n template,\n} from './values.ts';\n\nexport const registry: readonly TypeEntry[] = [\n text,\n markdown,\n template,\n json,\n boolean,\n long,\n double,\n dateTime,\n latLong,\n money,\n image,\n link,\n reference,\n] as readonly TypeEntry[];\n\n/** The types a page can show, so discovery looks for their elements. */\nexport const onPage = registry.filter((entry) => entry.component !== undefined);\n", "// The lazily loaded editor. Started by the loader once the user asks to edit.\n\nimport { Editor } from './controller.ts';\nimport type { Transport } from './core/transport.ts';\nimport type { EditorHost } from './ui/host.ts';\nimport type { ClientContext } from '@baack-software/baack-ts-client';\nimport { onPage, registry } from './types/index.ts';\n\nimport type { ReadMode } from './view.ts';\n\nexport function start(options: { transport: Transport; host: EditorHost; context: ClientContext; mode?: ReadMode }): Editor {\n const editor = new Editor(options.transport, options.host, onPage, registry, options.context);\n void editor.setReadMode(options.mode ?? 'LATEST');\n return editor;\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["h", "tag", "attrs", "children", "toDom", "node", "doc", "element", "name", "value", "child", "patch", "volatile", "ownsChildren", "withCarried", "entry", "base", "value", "merged", "key", "kept", "valueOf", "item", "field", "sameValue", "a", "b", "preview", "renderInto", "element", "slot", "spec", "props", "patch", "toRepresentation", "entityUrn", "representation", "nameAttribute", "sortOrderAttribute", "urnAttribute", "SCOPE_ATTRIBUTE", "Discovery", "entries", "listener", "entry", "nameAttribute", "records", "root", "sortOrderAttribute", "element", "target", "rescan", "removedSome", "record", "node", "candidates", "added", "removed", "next", "unscoped", "previous", "sameBindings", "bindings", "scope", "name", "sortOrder", "slots", "rawOrder", "problem", "a", "b", "binding", "i", "createKey", "slot", "pendingKey", "pending", "PendingEdits", "onChange", "urn", "key", "entityUrn", "removed", "items", "planId", "p", "groups", "PREFIX", "Stash", "userUrn", "PREFIX", "now", "dropExpired", "raw", "data", "error", "items", "index", "key", "savedAt", "EntityView", "_EntityView", "entity", "items", "name", "item", "a", "b", "sortOrder", "texts", "markdowns", "templates", "booleans", "doubles", "longs", "money", "dateTimes", "images", "latLongs", "jsons", "links", "references", "collection", "client", "path", "params", "headers", "Endpoint", "Store", "scope", "entity", "EntityView", "entityUrn", "urn", "binding", "entry", "name", "sortOrder", "view", "found", "stored", "item", "oldUrn", "previous", "next", "items", "index", "candidate", "EntityMismatchError", "expectedUrn", "received", "NotLiveError", "entityUrn", "isLive", "status", "ScopedViews", "transport", "options", "locator", "entity", "error", "isBaackApiError", "fields", "reviewAction", "ctx", "entityUrn", "pageEntity", "store", "root", "SCOPE_ATTRIBUTE", "pageFirst", "entityUrns", "page", "a", "b", "lifecycleLabel", "status", "STATE_ATTRIBUTE", "OUTLINES", "drawOutline", "element", "state", "line", "colour", "opacity", "light", "dark", "PAGE_COLOURS", "faded", "value", "saved", "mark", "outline", "outlineOffset", "display", "minWidth", "minHeight", "fitEmpty", "original", "unmark", "textParagraphs", "value", "paragraph", "line", "lines", "textLines", "LINKABLE", "linkSegments", "text", "part", "index", "segment", "currencyDigits", "currencyCode", "moneyAmount", "item", "minorToMajor", "moneySymbol", "units", "digits", "negative", "whole", "padded", "majorToMinor", "match", "sign", "fraction", "parseTimestamp", "formatDate", "format", "time", "options", "formatNumber", "locale", "PASS_THROUGH_NAMES", "CONTRACT_ATTRIBUTE", "isPassThrough", "name", "passThrough", "attributes", "allowed", "value", "contentAttributes", "type", "ref", "placeholder", "volatileFor", "more", "common", "element", "lines", "texts", "render", "joinWithBreaks", "line", "index", "h", "linked", "text", "linkify", "linkSegments", "segment", "props", "fromItem", "textLines", "tag", "content", "textBlock", "textParagraphs", "paragraphs", "paragraph", "meta", "rendered", "html", "markdown", "template", "money", "item", "recorded", "amount", "moneyAmount", "moneySymbol", "numeric", "formatNumber", "long", "double", "dateTime", "instant", "parseTimestamp", "formatDate", "boolean", "shown", "latLong", "attrs", "link", "label", "MEDIUM_MIN_WIDTH", "LARGE_MIN_WIDTH", "image", "section", "volatileFor", "ref", "props", "value", "h", "passThrough", "contentAttributes", "element", "str", "v", "sourceEntry", "type", "label", "endpoint", "historyEndpoint", "spec", "find", "element", "value", "values", "markdown", "Endpoint", "view", "name", "sortOrder", "template", "json", "parsed", "error", "boolean", "wholeNumber", "text", "long", "decimal", "double", "toLocalInput", "time", "parseTimestamp", "fromLocalInput", "dateTime", "latLong", "latitude", "longitude", "validCurrency", "code", "money", "minorToMajor", "currencyDigits", "currencyCode", "digits", "unitValue", "majorToMinor", "IMAGE_SLOTS", "image", "slot", "replacing", "kept", "note", "altText", "link", "href", "key", "field", "reference", "urn", "POLL_MS", "POLL_LIMIT_MS", "Images", "ctx", "view", "saving", "editing", "target", "chosen", "problem", "imageFileIssues", "issue", "files", "withSizes", "pending", "popover", "store", "feedback", "entry", "form", "base", "value", "withCarried", "size", "IMAGE_SLOTS", "slot", "change", "createKey", "version", "error", "failure", "previews", "file", "transport", "toolbar", "panel", "el", "lines", "line", "label", "progress", "say", "text", "results", "answered", "result", "failed", "index", "uploaded", "fieldOf", "placed", "item", "retry", "actions", "url", "current", "stillEmpty", "urn", "sizes", "start", "attempt", "resolve", "entityUrn", "binding", "urnAttribute", "mark", "widths", "original", "width", "scaled", "bitmap", "height", "canvas", "type", "blob", "reject", "b", "name", "IMAGE_TYPES", "MB", "max", "warn", "bytes", "issues", "LIVE_ATTRIBUTE", "ITEM_SHOWN_EVENT", "LIVE_REQUEST_EVENT", "inLiveContent", "element", "LIVE_ATTRIBUTE", "LiveIslands", "store", "LIVE_REQUEST_EVENT", "binding", "item", "renderInto", "detail", "key", "dispatch", "urnAttribute", "sortOrder", "event", "ITEM_SHOWN_EVENT", "IS_MAC", "InlineEdit", "element", "raw", "host", "callbacks", "inLiveContent", "fitEmpty", "placeCaret", "modifier", "event", "selection", "range", "Editing", "ctx", "view", "save", "event", "discovery", "toolbar", "element", "binding", "target", "path", "anchor", "store", "entityUrn", "urn", "urnAttribute", "visible", "ownsChildren", "placeholder", "pending", "host", "popover", "entry", "stored", "value", "valueOf", "session", "InlineEdit", "mark", "hooks", "actions", "form", "base", "createKey", "values", "current", "notes", "isLive", "sources", "transport", "feedback", "source", "error", "active", "fileIssues", "imageFileIssues", "input", "withCarried", "sameValue", "describeFailure", "error", "action", "hasSession", "isBaackApiError", "debug", "debugText", "describeApiError", "describeOther", "detail", "NotLiveError", "EntityMismatchError", "language", "body", "pretty", "text", "path", "Feedback", "transport", "toolbar", "error", "action", "retry", "failure", "hasSession", "isBaackApiError", "contextError", "describeFailure", "message", "iframeSrc", "percentChange", "before", "after", "formatPercent", "percent", "size", "MAX_TOKENS", "diffWords", "a", "b", "table", "i", "j", "parts", "push", "kind", "text", "last", "dispatchItemUpdated", "detail", "dispatchItemPublished", "dispatchEntityState", "dispatchEntityPublished", "entityUrn", "SimpleForm", "title", "fields", "submitLabel", "onSubmit", "onCancel", "el", "field", "label", "input", "option", "selectBox", "cancel", "actions", "event", "key", "busy", "message", "ConflictError", "change", "newest", "summarise", "entry", "value", "field", "summariseChange", "before", "after", "parts", "delta", "moneyDelta", "was", "now", "percent", "percentChange", "formatPercent", "Saving", "ctx", "view", "editing", "target", "pending", "popover", "feedback", "key", "createKey", "isActive", "files", "current", "issue", "error", "StoredElsewhereError", "retry", "failure", "store", "transport", "stored", "saved", "toRepresentation", "dispatchItemUpdated", "checkSlot", "pendingKey", "slot", "oldUrn", "discovery", "sources", "toolbar", "elements", "binding", "urnAttribute", "editingBinding", "mark", "entityUrn", "queue", "p", "planId", "urn", "failures", "debug", "touched", "only", "reviewAction", "anchor", "conflict", "when", "parseTimestamp", "done", "removed", "count", "isLive", "form", "SimpleForm", "panel", "created", "sent", "ELEMENTS", "renderChange", "value", "box", "el", "part", "tag", "className", "element", "ItemHistoryView", "onMore", "onCompare", "el", "compareLabel", "selectBox", "text", "rows", "hasMore", "expanded", "row", "item", "head", "time", "note", "chevron", "icon", "actions", "actionButton", "renderChange", "toggle", "button", "open", "nested", "inner", "renderVersion", "body", "model", "mark", "changes", "label", "change", "section", "action", "variantOf", "WAIT_MS", "count", "shown", "timer", "tooltip", "trigger", "text", "description", "el", "place", "content", "event", "show", "type", "hide", "tip", "rect", "width", "height", "above", "SIDE_KEY", "SLIDE_MS", "CRUMBS", "stacks", "NARROW", "SidebarStack", "host", "el", "bar", "button", "close", "icon", "tooltip", "nav", "readSide", "toolbar", "listener", "top", "above", "entry", "level", "focus", "from", "id", "index", "left", "levels", "side", "section", "animated", "direction", "other", "origin", "current", "parent", "items", "shown", "item", "position", "separator", "li", "crumb", "content", "here", "jump", "to", "away", "options", "active", "event", "rows", "row", "next", "drillRow", "label", "detail", "open", "text", "chevron", "confirmLevel", "body", "block", "box", "actions", "choice", "choiceButton", "variantOf", "COLLAPSE_MS", "History", "ctx", "editing", "view", "stack", "hooks", "slot", "sameItem", "itemView", "ItemHistoryView", "against", "state", "level", "itemLevelId", "version", "selection", "shown", "binding", "element", "when", "parseTimestamp", "entityUrn", "current", "page", "error", "rows", "index", "grouped", "groupTime", "time", "head", "live", "versionLevelId", "renderVersion", "previous", "describe", "notes", "group", "urn", "body", "el", "marks", "beforeIsLive", "changes", "actions", "status", "isLive", "busy", "anchor", "onlyVersion", "previewing", "disabled", "wholeItem", "where", "blocks", "summarise", "description", "next", "successor", "nextWhen", "confirmLevel", "button", "transport", "pending", "toolbar", "feedback", "promoted", "dispatchItemPublished", "remaining", "other", "edit", "store", "sources", "templates", "template", "pattern", "item", "source", "entry", "mode", "before", "after", "diffWords", "was", "now", "summariseChange", "a", "b", "reorder", "items", "newOrder", "values", "item", "a", "b", "byKey", "key", "changes", "index", "to", "planInsert", "at", "sorted", "before", "after", "left", "right", "shiftRun", "run", "step", "swap", "templatesUsing", "ctx", "entityUrn", "name", "store", "sources", "transport", "template", "pattern", "users", "item", "source", "ReorderPanel", "panels", "el", "buttons", "cancel", "title", "entityUrn", "entries", "actions", "head", "tail", "left", "text", "busy", "label", "entry", "from", "to", "button", "child", "b", "index", "row", "handle", "icon", "up", "down", "add", "tooltip", "event", "candidate", "Moves", "ctx", "view", "editing", "groups", "create", "ReorderPanel", "binding", "entityUrn", "rows", "list", "container", "units", "child", "member", "b", "stored", "key", "value", "groupLabel", "sortOrder", "bindings", "cells", "group", "before", "unit", "what", "keys", "at", "anchor", "delta", "index", "target", "byKey", "inLiveContent", "elements", "markers", "element", "marker", "places", "original", "unchanged", "item", "close", "changes", "reorder", "missing", "steps", "change", "label", "ok", "feedback", "toolbar", "to", "error", "failure", "seen", "members", "popover", "labelOf", "revert", "render", "changed", "i", "move", "next", "previous", "following", "u", "isLive", "listener", "items", "plan", "planInsert", "shift", "model", "reference", "copy", "bound", "entry", "store", "templates", "templatesUsing", "info", "el", "form", "SimpleForm", "values", "name", "swapping", "panel", "occupant", "swap", "planId", "step", "pending", "transport", "done", "newest", "pendingKey", "moved", "saved", "toRepresentation", "valueOf", "dispatchItemUpdated", "d", "reviewAction", "total", "message", "debug", "debugDetails", "retry", "back", "actions", "urn", "remaining", "OrderTags", "host", "onOpen", "el", "members", "member", "index", "text", "focused", "tag", "button", "element", "rect", "PREFIX", "GroupLog", "userUrn", "PREFIX", "groups", "versionUrn", "group", "error", "CACHE_KEY", "CACHE_MS", "CONCURRENT_READS", "RETRY_DELAYS_MS", "displayPath", "name", "EntityDirectory", "transport", "owners", "userUrn", "stored", "entry", "urn", "entity", "summary", "found", "onUpdate", "error", "urns", "complete", "listing", "compare", "missing", "failure", "next", "worker", "isBaackApiError", "result", "delay", "resolve", "results", "owner", "cached", "a", "b", "HOME_ENTITY_NAME", "defaultEntityName", "pathname", "path", "defaultPagePath", "name", "isIndexName", "Onboarding", "deps", "transport", "panels", "path", "defaultEntityName", "language", "entity", "panel", "el", "snippet", "use", "SCOPE_ATTRIBUTE", "handle", "actions", "error", "isBaackApiError", "form", "done", "next", "urn", "copy", "close", "shown", "displayPath", "options", "owners", "SimpleForm", "c", "values", "owner", "name", "variant", "isIndexName", "found", "describeFailure", "entityUrn", "store", "context", "view", "created", "sourceUrn", "targetUrn", "start", "registry", "items", "entry", "item", "progress", "index", "value", "valueOf", "slot", "toRepresentation", "retry", "link", "fallback", "companies", "preferred", "a", "b", "wrapper", "code", "children", "row", "renderReview", "body", "model", "actions", "status", "el", "parts", "blocker", "warning", "list", "change", "row", "head", "name", "tooltip", "note", "renderChange", "buttons", "run", "schedule", "confirm", "renderSchedule", "label", "cancel", "hint", "field", "at", "back", "BACKOFF", "Publishing", "ctx", "view", "stuckAfterMs", "stack", "hooks", "tracked", "urn", "status", "entityUrn", "entity", "error", "publishTimestamp", "raw", "previous", "next", "dispatchEntityState", "isLive", "dispatchEntityPublished", "seconds", "rows", "pageFirst", "canPublish", "title", "publish", "review", "row", "lifecycleLabel", "at", "parseTimestamp", "since", "question", "confirmLevel", "button", "done", "note", "store", "views", "live", "latest", "shown", "latestUrns", "changes", "blockers", "warnings", "id", "count", "existing", "body", "el", "renderReview", "path", "label", "renderSchedule", "feedback", "fresh", "now", "when", "transport", "updated", "before", "toolbar", "owner", "lines", "change", "task", "select", "entry", "item", "latestItems", "liveItems", "liveByUrn", "slot", "liveBySlot", "drafts", "befores", "accounted", "index", "notes", "moveNotes", "valueChanged", "sameValue", "valueOf", "describe", "sentence", "other", "draft", "inSlot", "history", "pagination", "found", "version", "image", "missingSlots", "reference", "referenced", "required", "fields", "registry", "urns", "after", "text", "value", "was", "diffWords", "summariseChange", "summarise", "delta", "Outline", "host", "onOpen", "onClose", "SidebarStack", "body", "section", "filter", "parts", "lifecycle", "el", "verbs", "verb", "input", "applyFilter", "group", "groupElement", "heading", "list", "row", "actions", "action", "item", "main", "note", "flag", "button", "variantOf", "value", "query", "MARKUP", "OutlineModel", "ctx", "view", "editing", "saving", "onboarding", "Outline", "pageEntity", "listener", "entityUrn", "run", "slot", "level", "stack", "from", "content", "options", "heading", "title", "id", "open", "handle", "path", "index", "focus", "showing", "slots", "above", "body", "refresh", "el", "store", "toolbar", "entities", "pageFirst", "parts", "urn", "drillRow", "lifecycleLabel", "button", "tooltip", "actions", "known", "section", "hooks", "entry", "name", "items", "item", "a", "b", "moving", "move", "sortOrder", "rows", "used", "first", "last", "gaps", "_", "order", "isRoot", "pending", "registry", "counterpart", "found", "published", "isLive", "onPage", "settings", "unused", "bindings", "visible", "duplicates", "other", "row", "flags", "isSlot", "anchor", "target", "missing", "binding", "key", "createKey", "lifecycle", "verb", "live", "entity", "urns", "form", "SimpleForm", "e", "values", "panel", "required", "result", "record", "missingSlots", "DEFAULT_LIVE_NOTE", "fixedMessage", "setting", "announcePublished", "toolbar", "detail", "done", "info", "message", "error", "reason", "SHOWN", "pickers", "summaryLabel", "entity", "EntityPicker", "source", "key", "urn", "onChange", "el", "field", "icon", "error", "note", "listing", "query", "loaded", "entities", "known", "a", "b", "option", "chosen", "typed", "path", "create", "index", "event", "count", "current", "open", "step", "count", "Dropdown", "trigger", "items", "event", "focus", "menu", "el", "item", "entry", "icon", "restoreFocus", "index", "entries", "other", "current", "letter", "step", "path", "rect", "width", "height", "below", "top", "COMMON_CURRENCIES", "IS_MAC", "Popover", "host", "el", "revert", "button", "event", "source", "anchor", "label", "meta", "hint", "actions", "fields", "values", "wide", "field", "blocks", "description", "choices", "block", "box", "choice", "choiceButton", "variantOf", "end", "key", "input", "files", "file", "text", "problem", "status", "value", "run", "link", "tooltip", "shown", "action", "listed", "extra", "icon", "more", "Dropdown", "issues", "issue", "message", "debug", "debugDetails", "sending", "onInput", "caption", "current", "preview", "img", "wrapper", "picker", "EntityPicker", "list", "code", "fill", "entities", "entity", "path", "rect", "height", "width", "panel", "panelRect", "top", "left", "Toolbar", "host", "onRetryAfterLogin", "pendingActions", "createLauncher", "bar", "row", "el", "tooltip", "button", "run", "retry", "on", "latest", "groups", "count", "total", "group", "listener", "open", "rows", "entityUrn", "page", "unsent", "label", "section", "title", "list", "pendingRow", "item", "text", "info", "debug", "action", "debugDetails", "iframeSrc", "scope", "actions", "send", "discard", "swapContent", "update", "reduced", "transition", "PageView", "ctx", "hooks", "mode", "store", "scopes", "urn", "isLive", "scope", "error", "reads", "discovery", "entity", "changed", "binding", "stored", "urnAttribute", "swapContent", "read", "listener", "slot", "version", "previous", "sameSlot", "previewing", "element", "byEntry", "saved", "inLiveContent", "restoreSnapshot", "bindings", "session", "draft", "views", "live", "feedback", "loading", "action", "pending", "entry", "snapshot", "preview", "valueOf", "mark", "edit", "usable", "item", "entityUrn", "create", "createKey", "STATE_ATTRIBUTE", "target", "showsUrn", "showsSlot", "sortOrder", "name", "sortOrderAttribute", "container", "nodes", "node", "b", "seen", "key", "unmark", "own", "ownsChildren", "attribute", "names", "value", "a", "Editor", "transport", "host", "entries", "registry", "context", "store", "Store", "toolbar", "feedback", "Feedback", "Toolbar", "entityUrn", "discovery", "Discovery", "bindings", "directory", "EntityDirectory", "urns", "company", "PendingEdits", "Popover", "content", "options", "ScopedViews", "LiveIslands", "slot", "binding", "delta", "target", "item", "sortOrder", "planId", "files", "GroupLog", "type", "entry", "name", "displayPath", "done", "view", "detail", "pagePath", "announcePublished", "Stash", "PageView", "Saving", "Editing", "Onboarding", "error", "action", "retry", "entity", "OutlineModel", "sidebar", "popover", "Moves", "change", "OrderTags", "Images", "Publishing", "level", "History", "event", "on", "mode", "showLive", "reading", "live", "fixedMessage", "DEFAULT_LIVE_NOTE", "page", "pageEntity", "onboarding", "pageLanguage", "onUpdate", "urn", "container", "path", "resolve", "form", "isLive", "newer", "parts", "titles", "SCOPE_ATTRIBUTE", "scopes", "reads", "pending", "all", "byEntity", "groups", "pageFirst", "p", "anchor", "onBeforeUnload", "items", "restored", "defaultPagePath", "MARKUP", "text", "Endpoint", "element", "meta", "section", "escaped", "textBlock", "view", "name", "sortOrder", "plainText", "value", "values", "p", "spec", "ref", "props", "node", "result", "registry", "text", "markdown", "template", "json", "boolean", "long", "double", "dateTime", "latLong", "money", "image", "link", "reference", "onPage", "entry", "start", "options", "editor", "Editor", "onPage", "registry"]
|
|
4
|
+
"sourcesContent": [null, "// The type registry: one entry per item type. Everything type-specific lives\n// in an entry; the rest of the editor works on any entry through the generic\n// helpers below.\n\nimport type { Entity, EntityView } from '@baack-software/baack-ts-client';\nimport type { ComponentSpec } from '@baack-software/baack-ts-components/components';\nimport { patch } from '@baack-software/baack-ts-components/vnode';\n\n/** The keys of Entity that hold item arrays. */\nexport type ItemArrayKey =\n | 'texts'\n | 'markdowns'\n | 'templates'\n | 'jsons'\n | 'booleans'\n | 'longs'\n | 'doubles'\n | 'dateTimes'\n | 'latLongs'\n | 'money'\n | 'images'\n | 'links'\n | 'references';\n\nexport type ContentItem = NonNullable<Entity[ItemArrayKey]>[number];\n\nexport type ItemType =\n | 'text'\n | 'markdown'\n | 'template'\n | 'json'\n | 'boolean'\n | 'long'\n | 'double'\n | 'dateTime'\n | 'latLong'\n | 'money'\n | 'image'\n | 'link'\n | 'reference';\n\n/** Fields every item carries that are not part of its value. */\ntype ItemMeta = 'urn' | 'url' | 'name' | 'sortOrder' | 'entity' | 'isPublished' | 'createdTimestamp' | 'history';\n\n/** The value fields of an item, for example `{value}` or `{latitude, longitude}`. */\nexport type ItemValue<I extends ContentItem> = Omit<I, ItemMeta>;\n\n/** What is sent on a create or update: JSON types as the API expects, entity by URN only. */\nexport type ItemRepresentation<I extends ContentItem> = ItemValue<I> & {\n urn?: string;\n name: string;\n sortOrder: number;\n entity: { urn: string };\n};\n\nexport interface Issue {\n level: 'warning' | 'error';\n message: string;\n}\n\n/** `entity`: an entity URN, chosen by path and language. */\nexport type FieldKind = 'text' | 'textarea' | 'code' | 'integer' | 'decimal' | 'checkbox' | 'datetime' | 'currency' | 'url' | 'file' | 'entity';\n\nexport interface FieldSpec {\n key: string;\n label: string;\n kind: FieldKind;\n}\n\nexport type FormValues = Record<string, string | boolean>;\n\n/** A form editor for the popover or panel. */\nexport interface FormSpec<I extends ContentItem> {\n fields: readonly FieldSpec[];\n toForm(value: ItemValue<I>): FormValues;\n /** The value the form describes, or an error message. */\n fromForm(values: FormValues): ItemValue<I> | string;\n /** A line shown under the form, e.g. what will be stored. */\n describe?(values: FormValues): string;\n}\n\nexport interface TypeEntry<I extends ContentItem = ContentItem> {\n readonly type: ItemType;\n readonly label: string;\n /** The `<attribute>` in `data-<attribute>-name`, `-sort-order` and `-urn`. */\n readonly attribute: string;\n readonly entityArray: ItemArrayKey;\n readonly endpoint: string;\n readonly historyEndpoint: string;\n /** Where the value is edited: in place, in a popover, or in the wider panel. */\n readonly surface: 'inline' | 'popover' | 'panel';\n /** The value fields a write sends. */\n readonly valueKeys: readonly string[];\n /** Fields the API derives (money's formattedValue); never sent, and dropped from previews. */\n readonly derived?: readonly string[];\n /**\n * Fields kept from the current version unless the edit replaces them: an\n * image's file addresses, which the API keeps only when an update passes\n * them back unchanged.\n */\n readonly carried?: readonly string[];\n /**\n * The page shows the entity view's rendering (markdown, templates). A write\n * returns the source, which must never be rendered; the editor re-reads the view.\n */\n readonly renderedByView?: boolean;\n /** The component that rendered an element. Absent for types with nothing to show (JSON, references). */\n component?(element: Element): ComponentSpec<I, unknown>;\n /** The item at a name and stored sort order in an entity view. */\n find(view: EntityView, name: string, sortOrder: number): I | undefined;\n defaults(): ItemValue<I>;\n /** In-place editing only: the value an element shows while being edited. */\n read?(element: HTMLElement): ItemValue<I>;\n /** Popover and panel editing. */\n form?: FormSpec<I>;\n /**\n * The value a new item starts from, read from the placeholder an element\n * shows. Undefined when the placeholder is not a value (for example\n * \"Contact us\" in a price); the type's defaults are used instead.\n */\n fromPlaceholder?(element: HTMLElement): ItemValue<I> | undefined;\n validate(value: ItemValue<I>): Issue[];\n}\n\n/** An edit's value with the carried fields of the version it is based on filled in. */\nexport function withCarried<I extends ContentItem>(entry: TypeEntry<I>, base: ItemValue<I> | I | undefined, value: ItemValue<I>): ItemValue<I> {\n if (!entry.carried || !base) return value;\n const merged: Record<string, unknown> = { ...value };\n for (const key of entry.carried) {\n const kept = (base as Record<string, unknown>)[key];\n if (!(key in merged) && kept !== undefined) merged[key] = kept;\n }\n return merged as ItemValue<I>;\n}\n\n/** The value fields of an item. */\nexport function valueOf<I extends ContentItem>(entry: TypeEntry<I>, item: ItemValue<I> | I): ItemValue<I> {\n const value: Record<string, unknown> = {};\n for (const key of entry.valueKeys) {\n const field = (item as Record<string, unknown>)[key];\n if (field !== undefined) value[key] = field;\n }\n return value as ItemValue<I>;\n}\n\nexport function sameValue<I extends ContentItem>(entry: TypeEntry<I>, a: ItemValue<I> | I, b: ItemValue<I> | I): boolean {\n return JSON.stringify(valueOf(entry, a)) === JSON.stringify(valueOf(entry, b));\n}\n\n/** An item showing a pending value, without the fields the API would derive from the old one. */\nexport function preview<I extends ContentItem>(entry: TypeEntry<I>, item: I, value: ItemValue<I>): I {\n const merged: Record<string, unknown> = { ...item, ...value };\n for (const key of entry.derived ?? []) delete merged[key];\n return merged as I;\n}\n\n/** Re-renders an element exactly as its component would, for an item (or its placeholder). */\nexport function renderInto<I extends ContentItem>(\n entry: TypeEntry<I>,\n element: HTMLElement,\n slot: { name: string; sortOrder: number },\n item: I | undefined,\n): void {\n const spec = entry.component?.(element);\n if (!spec) return;\n const props = spec.propsFrom(element);\n patch(element, spec.render({ name: slot.name, sortOrder: slot.sortOrder, item }, props), spec.volatile, spec.ownsChildren);\n}\n\n/** Builds the body for a create or update of `item` with a new value. */\nexport function toRepresentation<I extends ContentItem>(\n entry: TypeEntry<I>,\n item: I,\n value: ItemValue<I>,\n entityUrn: string,\n): ItemRepresentation<I> {\n const representation = {\n ...valueOf(entry, value),\n name: item.name,\n sortOrder: item.sortOrder,\n entity: { urn: entityUrn },\n } as ItemRepresentation<I>;\n if (item.urn !== undefined) representation.urn = item.urn;\n return representation;\n}\n\nexport function nameAttribute(entry: TypeEntry): string {\n return `data-${entry.attribute}-name`;\n}\n\nexport function sortOrderAttribute(entry: TypeEntry): string {\n return `data-${entry.attribute}-sort-order`;\n}\n\nexport function urnAttribute(entry: TypeEntry): string {\n return `data-${entry.attribute}-urn`;\n}\n", "// Finds item elements on the page, continuously. Islands and client-rendered\n// content can add elements at any time, so a MutationObserver keeps the set of\n// bindings current.\n\nimport { nameAttribute, sortOrderAttribute, type TypeEntry } from './registry.ts';\n\nexport const SCOPE_ATTRIBUTE = 'data-entity-urn';\n\n/** One element showing one item slot. */\nexport interface Binding {\n readonly element: HTMLElement;\n readonly entry: TypeEntry;\n /** The `data-entity-urn` of the nearest ancestor scope. */\n readonly scope: string;\n readonly name: string;\n /** The stored sort order to match. A bare name means 0. */\n readonly sortOrder: number;\n}\n\n/** An element naming an item but outside any `data-entity-urn` scope: the page has no entity yet. */\nexport interface UnscopedSlot {\n readonly element: HTMLElement;\n readonly entry: TypeEntry;\n readonly name: string;\n readonly sortOrder: number;\n}\n\nexport interface DiscoveryListener {\n added(bindings: Binding[]): void;\n removed(bindings: Binding[]): void;\n}\n\nexport class Discovery {\n private readonly entries: readonly TypeEntry[];\n private readonly listener: DiscoveryListener;\n private readonly selector: string;\n private readonly byElement = new Map<HTMLElement, Binding[]>();\n private readonly unscopedByElement = new Map<HTMLElement, UnscopedSlot[]>();\n private readonly observer: MutationObserver;\n private readonly warned = new WeakSet<Element>();\n\n constructor(entries: readonly TypeEntry[], listener: DiscoveryListener) {\n this.entries = entries;\n this.listener = listener;\n this.selector = entries.map((entry) => `[${nameAttribute(entry)}]`).join(',');\n this.observer = new MutationObserver((records) => this.onMutations(records));\n }\n\n start(root: Element = document.documentElement): void {\n this.scan(root);\n this.observer.observe(root, {\n subtree: true,\n childList: true,\n attributes: true,\n attributeFilter: [\n SCOPE_ATTRIBUTE,\n ...this.entries.flatMap((entry) => [nameAttribute(entry), sortOrderAttribute(entry)]),\n ],\n });\n }\n\n stop(): void {\n this.observer.disconnect();\n }\n\n all(): Binding[] {\n return [...this.byElement.values()].flat();\n }\n\n unscoped(): UnscopedSlot[] {\n for (const element of this.unscopedByElement.keys()) {\n if (!element.isConnected) this.unscopedByElement.delete(element);\n }\n return [...this.unscopedByElement.values()].flat();\n }\n\n of(element: HTMLElement): Binding[] {\n return this.byElement.get(element) ?? [];\n }\n\n /** The nearest bound element at or above `target`. */\n closest(target: EventTarget | null): HTMLElement | undefined {\n if (!(target instanceof Element)) return undefined;\n const element = target.closest(this.selector);\n return element instanceof HTMLElement && this.byElement.has(element) ? element : undefined;\n }\n\n /** Applies changes the observer has not delivered yet, so bindings match the page now. */\n flush(): void {\n const records = this.observer.takeRecords();\n if (records.length > 0) this.onMutations(records);\n }\n\n private onMutations(records: MutationRecord[]): void {\n const rescan = new Set<Element>();\n let removedSome = false;\n for (const record of records) {\n if (record.type === 'attributes' && record.target instanceof Element) {\n rescan.add(record.target);\n }\n for (const node of record.addedNodes) {\n if (node instanceof Element) rescan.add(node);\n }\n if (record.removedNodes.length > 0) removedSome = true;\n }\n\n if (removedSome) this.sweep();\n for (const element of rescan) {\n if (element.isConnected) this.scan(element);\n }\n }\n\n /** Binds `root` and its descendants, replacing bindings whose attributes changed. */\n private scan(root: Element): void {\n const candidates = [...root.querySelectorAll<HTMLElement>(this.selector)];\n if (root instanceof HTMLElement && root.matches(this.selector)) candidates.unshift(root);\n // A scope change on root also changes the scope of bound descendants.\n const added: Binding[] = [];\n const removed: Binding[] = [];\n\n for (const element of candidates) {\n const next = this.bind(element);\n const unscoped = this.unscopedSlots(element);\n if (unscoped.length > 0) {\n this.unscopedByElement.set(element, unscoped);\n } else {\n this.unscopedByElement.delete(element);\n }\n const previous = this.byElement.get(element) ?? [];\n if (sameBindings(previous, next)) continue;\n removed.push(...previous);\n added.push(...next);\n if (next.length > 0) {\n this.byElement.set(element, next);\n } else {\n this.byElement.delete(element);\n }\n }\n\n // Elements that no longer match (a name attribute was removed).\n if (root instanceof HTMLElement && !root.matches(this.selector) && this.byElement.has(root)) {\n removed.push(...this.byElement.get(root)!);\n this.byElement.delete(root);\n }\n\n if (removed.length > 0) this.listener.removed(removed);\n if (added.length > 0) this.listener.added(added);\n }\n\n private sweep(): void {\n const removed: Binding[] = [];\n for (const [element, bindings] of this.byElement) {\n if (!element.isConnected) {\n removed.push(...bindings);\n this.byElement.delete(element);\n }\n }\n if (removed.length > 0) this.listener.removed(removed);\n }\n\n private bind(element: HTMLElement): Binding[] {\n const scope = element.closest(`[${SCOPE_ATTRIBUTE}]`)?.getAttribute(SCOPE_ATTRIBUTE);\n const bindings: Binding[] = [];\n for (const entry of this.entries) {\n const name = element.getAttribute(nameAttribute(entry));\n if (!name) continue;\n if (!scope) continue; // Kept as an unscoped slot, for onboarding.\n const sortOrder = this.sortOrder(element, entry);\n if (sortOrder !== undefined) bindings.push({ element, entry, scope, name, sortOrder });\n }\n return bindings;\n }\n\n private unscopedSlots(element: HTMLElement): UnscopedSlot[] {\n if (element.closest(`[${SCOPE_ATTRIBUTE}]`)) return [];\n const slots: UnscopedSlot[] = [];\n for (const entry of this.entries) {\n const name = element.getAttribute(nameAttribute(entry));\n const sortOrder = name ? this.sortOrder(element, entry) : undefined;\n if (name && sortOrder !== undefined) slots.push({ element, entry, name, sortOrder });\n }\n return slots;\n }\n\n private sortOrder(element: HTMLElement, entry: TypeEntry): number | undefined {\n const rawOrder = element.getAttribute(sortOrderAttribute(entry));\n const sortOrder = rawOrder === null || rawOrder.trim() === '' ? 0 : Number(rawOrder);\n if (Number.isInteger(sortOrder)) return sortOrder;\n this.warn(element, `has ${sortOrderAttribute(entry)}=\"${rawOrder}\", which is not an integer`);\n return undefined;\n }\n\n private warn(element: Element, problem: string): void {\n if (this.warned.has(element)) return;\n this.warned.add(element);\n console.warn(`Baack editor: element ${problem}; it will not be editable.`, element);\n }\n}\n\nfunction sameBindings(a: Binding[], b: Binding[]): boolean {\n return (\n a.length === b.length &&\n a.every(\n (binding, i) =>\n binding.entry === b[i]!.entry &&\n binding.scope === b[i]!.scope &&\n binding.name === b[i]!.name &&\n binding.sortOrder === b[i]!.sortOrder,\n )\n );\n}\n", "// Unsent work: edits to existing versions (keyed by URN) and creates of new\n// items (keyed by entity, type, name and sort order, since they have no URN\n// until the POST returns). Plain data, so it can be stashed.\n\nimport type { ContentItem, ItemType, ItemValue } from './registry.ts';\n\ntype Value = ItemValue<ContentItem>;\n\nexport interface PendingEdit {\n kind: 'edit';\n type: ItemType;\n urn: string;\n entityUrn: string;\n name: string;\n sortOrder: number;\n value: Value;\n /** Restored from the stash, but the item has a newer version now. Not sendable until resolved. */\n stale?: boolean;\n /** Deliberately based on an older version (\"edit from this version\"): no conflict check. */\n fromVersion?: boolean;\n}\n\nexport interface PendingCreate {\n kind: 'create';\n type: ItemType;\n entityUrn: string;\n name: string;\n sortOrder: number;\n value: Value;\n}\n\n/**\n * One step of a planned move (a reorder, swap, shift, row move or rename):\n * the item `urn` gets `to`. Steps of one plan share `planId` and run in the\n * order they were queued; a step whose target is already in place is\n * skipped, so a plan can be replayed safely.\n */\nexport interface PendingMove {\n kind: 'move';\n planId: string;\n /** What the plan does, for people: \"Reorder feature\", \"Swap price #0 and #1\". */\n label: string;\n type: ItemType;\n urn: string;\n entityUrn: string;\n /** Where the item is now. */\n name: string;\n sortOrder: number;\n to: { name: string; sortOrder: number };\n}\n\nexport type Pending = PendingEdit | PendingCreate | PendingMove;\n\nexport function createKey(slot: { entityUrn: string; type: ItemType; name: string; sortOrder: number }): string {\n return `${slot.entityUrn}|${slot.type}|${slot.name}|${slot.sortOrder}`;\n}\n\nexport function pendingKey(pending: Pending): string {\n if (pending.kind === 'move') return `move|${pending.planId}|${pending.urn}`;\n return pending.kind === 'edit' ? pending.urn : createKey(pending);\n}\n\nexport class PendingEdits {\n private readonly items = new Map<string, Pending>();\n private readonly onChange: () => void;\n\n constructor(onChange: () => void) {\n this.onChange = onChange;\n }\n\n getEdit(urn: string): PendingEdit | undefined {\n const pending = this.items.get(urn);\n return pending?.kind === 'edit' ? pending : undefined;\n }\n\n getCreate(key: string): PendingCreate | undefined {\n const pending = this.items.get(key);\n return pending?.kind === 'create' ? pending : undefined;\n }\n\n set(pending: Pending): void {\n this.items.set(pendingKey(pending), pending);\n this.onChange();\n }\n\n clear(key: string): void {\n if (this.items.delete(key)) this.onChange();\n }\n\n clearAll(entityUrn?: string): Pending[] {\n const removed = this.all().filter((pending) => entityUrn === undefined || pending.entityUrn === entityUrn);\n for (const pending of removed) this.items.delete(pendingKey(pending));\n if (removed.length > 0) this.onChange();\n return removed;\n }\n\n /** Replaces everything, for a restore. */\n load(items: Pending[]): void {\n this.items.clear();\n for (const pending of items) this.items.set(pendingKey(pending), pending);\n this.onChange();\n }\n\n all(): Pending[] {\n return [...this.items.values()];\n }\n\n /** The queued steps of a plan, in order. */\n plan(planId: string): PendingMove[] {\n return this.all().filter((p): p is PendingMove => p.kind === 'move' && p.planId === planId);\n }\n\n count(): number {\n return this.items.size;\n }\n\n byEntity(): Map<string, Pending[]> {\n const groups = new Map<string, Pending[]>();\n for (const pending of this.items.values()) {\n groups.set(pending.entityUrn, [...(groups.get(pending.entityUrn) ?? []), pending]);\n }\n return groups;\n }\n}\n", "// Unsent work survives a reload in localStorage, keyed by user, so it is never\n// restored for someone else. Stashes older than a week are dropped. Storage\n// can be missing or full (private windows, quotas), so every access is\n// guarded; losing the stash must never break editing.\n\nimport type { Pending } from './pending.ts';\n\nconst PREFIX = 'baack-editor:stash:';\nconst MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;\n\ninterface StashData {\n version: 1;\n savedAt: number;\n items: Pending[];\n}\n\nexport class Stash {\n private readonly key: string;\n\n constructor(userUrn: string) {\n this.key = PREFIX + userUrn;\n }\n\n load(now = Date.now()): Pending[] {\n dropExpired(now);\n try {\n const raw = window.localStorage.getItem(this.key);\n if (!raw) return [];\n const data = JSON.parse(raw) as Partial<StashData>;\n if (data.version !== 1 || !Array.isArray(data.items)) return [];\n return data.items;\n } catch (error) {\n console.warn('Baack editor: could not read unsaved changes from this browser.', error);\n return [];\n }\n }\n\n save(items: Pending[], now = Date.now()): void {\n try {\n if (items.length === 0) {\n window.localStorage.removeItem(this.key);\n } else {\n const data: StashData = { version: 1, savedAt: now, items };\n window.localStorage.setItem(this.key, JSON.stringify(data));\n }\n } catch (error) {\n console.warn('Baack editor: could not keep unsaved changes in this browser.', error);\n }\n }\n}\n\nfunction dropExpired(now: number): void {\n try {\n for (let index = window.localStorage.length - 1; index >= 0; index -= 1) {\n const key = window.localStorage.key(index);\n if (!key?.startsWith(PREFIX)) continue;\n const savedAt = (JSON.parse(window.localStorage.getItem(key) ?? '{}') as Partial<StashData>).savedAt;\n if (typeof savedAt !== 'number' || now - savedAt > MAX_AGE_MS) window.localStorage.removeItem(key);\n }\n } catch {\n // Storage unavailable: nothing to tidy.\n }\n}\n", "/**\n * EntityView\n * ----------\n * A thin, read-only wrapper around a raw `Entity` returned from the\n * ENTITY_VIEW endpoint. The raw Entity models content as parallel\n * collections (`texts`, `markdowns`, `images`, `booleans`, `doubles`,\n * `longs`, `money`, `dateTimes`, `latLongs`, `jsons`, `templates`), each\n * entry identified by a `name` and ordered by `sortOrder`.\n *\n * EntityView hides that navigation and gives you name-based accessors that\n * return the underlying item (not just its scalar value), so you still have\n * access to metadata like `isPublished`, `history`, etc. Each single-item\n * accessor also takes an optional `sortOrder`, which defaults to 0, so you\n * can reach a specific entry in a repeated field:\n *\n * const view = new EntityView(entity);\n * view.text('headline'); // TextItem | undefined (sortOrder 0)\n * view.text('gallery-captions', 2); // TextItem | undefined (sortOrder 2)\n * view.markdown('body'); // MarkdownItem | undefined\n * view.image('hero'); // ImageItem | undefined\n * view.texts('gallery-captions'); // TextItem[] (all entries, sortOrder-ordered)\n */\n\nimport type {\n Entity,\n TextItem,\n MarkdownItem,\n TemplateItem,\n BooleanItem,\n DoubleItem,\n LongItem,\n MoneyItem,\n DateTimeItem,\n ImageItem,\n LatLongItem,\n JsonItem,\n LinkItem,\n ReferenceItem\n} from './types/index.ts';\nimport { BaackClient, type QueryParams } from './client.ts';\nimport { Endpoint } from './endpoints.ts';\n\n/** Anything shaped like an Entity content item (has a name + sortOrder). */\ninterface NamedItem {\n name: string;\n sortOrder: number;\n}\n\nexport class EntityView {\n constructor(private readonly entity: Entity) {}\n\n // ---------------------------------------------------------------------\n // Metadata\n // ---------------------------------------------------------------------\n\n get urn(): string {\n return this.entity.urn;\n }\n\n get name(): string {\n return this.entity.name;\n }\n\n get status(): Entity['status'] {\n return this.entity.status;\n }\n\n get language(): string {\n return this.entity.language;\n }\n\n get variant(): string | undefined {\n return this.entity.variant;\n }\n\n get publishedAt(): Date | undefined {\n return this.entity.publishTimestamp ? new Date(this.entity.publishTimestamp) : undefined;\n }\n\n get updatedAt(): Date | undefined {\n return this.entity.updatedTimestamp ? new Date(this.entity.updatedTimestamp) : undefined;\n }\n\n /** Escape hatch back to the untouched Entity, for anything not yet covered. */\n get raw(): Entity {\n return this.entity;\n }\n\n // ---------------------------------------------------------------------\n // Generic helpers\n // ---------------------------------------------------------------------\n\n /**\n * Returns every item in a collection matching `name`, ordered by sortOrder.\n * Collections legitimately support multiple items sharing a name (e.g. a\n * repeated \"gallery-image\" field), so this is the base primitive that all\n * single-value accessors build on.\n */\n private allByName<T extends NamedItem>(\n items: T[] | undefined,\n name: string,\n ): T[] {\n if (!items) return [];\n return items\n .filter((item) => item.name === name)\n .sort((a, b) => a.sortOrder - b.sortOrder);\n }\n\n /**\n * Returns the item matching both `name` and `sortOrder`. Most fields only\n * ever have a single item at `sortOrder` 0, so that's the default \u2014 pass\n * an explicit `sortOrder` to reach a specific entry in a repeated field.\n */\n private byNameAndSortOrder<T extends NamedItem>(\n items: T[] | undefined,\n name: string,\n sortOrder = 0,\n ): T | undefined {\n return items?.find((item) => item.name === name && item.sortOrder === sortOrder);\n }\n\n /**\n * True if any content collection on the entity has an item with this name.\n * Useful for conditionally rendering optional sections.\n */\n has(name: string): boolean {\n const {\n texts, markdowns, templates, booleans, doubles, longs, money, dateTimes, images, latLongs, jsons, links, references,\n } = this.entity;\n return [\n texts, markdowns, templates, booleans, doubles, longs, money, dateTimes, images, latLongs, jsons, links, references,\n ].some(\n (collection) => (collection as NamedItem[] | undefined)?.some((item) => item.name === name),\n );\n }\n\n private hasByNameAndSortOrder<T extends NamedItem>(\n items: T[] | undefined,\n name: string,\n sortOrder = 0,\n ): boolean {\n return this.byNameAndSortOrder(items, name, sortOrder) !== undefined;\n }\n\n hasText(name: string, sortOrder = 0): boolean {\n return this.hasByNameAndSortOrder(this.entity.texts, name, sortOrder);\n }\n\n hasMarkdown(name: string, sortOrder = 0): boolean {\n return this.hasByNameAndSortOrder(this.entity.markdowns, name, sortOrder);\n }\n\n hasTemplate(name: string, sortOrder = 0): boolean {\n return this.hasByNameAndSortOrder(this.entity.templates, name, sortOrder);\n }\n\n hasBoolean(name: string, sortOrder = 0): boolean {\n return this.hasByNameAndSortOrder(this.entity.booleans, name, sortOrder);\n }\n\n hasDouble(name: string, sortOrder = 0): boolean {\n return this.hasByNameAndSortOrder(this.entity.doubles, name, sortOrder);\n }\n\n hasLong(name: string, sortOrder = 0): boolean {\n return this.hasByNameAndSortOrder(this.entity.longs, name, sortOrder);\n }\n\n /** True if either a double or a long item exists with this name/sortOrder. */\n hasNumber(name: string, sortOrder = 0): boolean {\n return this.hasDouble(name, sortOrder) || this.hasLong(name, sortOrder);\n }\n\n hasMoney(name: string, sortOrder = 0): boolean {\n return this.hasByNameAndSortOrder(this.entity.money, name, sortOrder);\n }\n\n hasDate(name: string, sortOrder = 0): boolean {\n return this.hasByNameAndSortOrder(this.entity.dateTimes, name, sortOrder);\n }\n\n hasImage(name: string, sortOrder = 0): boolean {\n return this.hasByNameAndSortOrder(this.entity.images, name, sortOrder);\n }\n\n hasLatLong(name: string, sortOrder = 0): boolean {\n return this.hasByNameAndSortOrder(this.entity.latLongs, name, sortOrder);\n }\n\n hasJson(name: string, sortOrder = 0): boolean {\n return this.hasByNameAndSortOrder(this.entity.jsons, name, sortOrder);\n }\n\n hasLink(name: string, sortOrder = 0): boolean {\n return this.hasByNameAndSortOrder(this.entity.links, name, sortOrder);\n }\n\n hasReference(name: string, sortOrder = 0): boolean {\n return this.hasByNameAndSortOrder(this.entity.references, name, sortOrder);\n }\n\n // ---------------------------------------------------------------------\n // Text\n // ---------------------------------------------------------------------\n\n text(name: string, sortOrder = 0): TextItem | undefined {\n return this.byNameAndSortOrder<TextItem>(this.entity.texts, name, sortOrder);\n }\n\n texts(name: string): TextItem[] {\n return this.allByName<TextItem>(this.entity.texts, name);\n }\n\n /** Like `text`, but throws if the field is missing \u2014 for required content. */\n requireText(name: string, sortOrder = 0): TextItem {\n const item = this.text(name, sortOrder);\n if (item === undefined) {\n throw new Error(`EntityView: missing required text item \"${name}\" on entity ${this.entity.urn}`);\n }\n return item;\n }\n\n // ---------------------------------------------------------------------\n // Markdown\n // ---------------------------------------------------------------------\n\n markdown(name: string, sortOrder = 0): MarkdownItem | undefined {\n return this.byNameAndSortOrder<MarkdownItem>(this.entity.markdowns, name, sortOrder);\n }\n\n markdowns(name: string): MarkdownItem[] {\n return this.allByName<MarkdownItem>(this.entity.markdowns, name);\n }\n\n // ---------------------------------------------------------------------\n // Template\n // ---------------------------------------------------------------------\n\n template(name: string, sortOrder = 0): TemplateItem | undefined {\n return this.byNameAndSortOrder<TemplateItem>(this.entity.templates, name, sortOrder);\n }\n\n templates(name: string): TemplateItem[] {\n return this.allByName<TemplateItem>(this.entity.templates, name);\n }\n\n // ---------------------------------------------------------------------\n // Boolean\n // ---------------------------------------------------------------------\n\n boolean(name: string, sortOrder = 0): BooleanItem | undefined {\n return this.byNameAndSortOrder<BooleanItem>(this.entity.booleans, name, sortOrder);\n }\n\n booleans(name: string): BooleanItem[] {\n return this.allByName<BooleanItem>(this.entity.booleans, name);\n }\n\n // ---------------------------------------------------------------------\n // Numbers (double / long kept distinct to match the underlying API)\n // ---------------------------------------------------------------------\n\n double(name: string, sortOrder = 0): DoubleItem | undefined {\n return this.byNameAndSortOrder<DoubleItem>(this.entity.doubles, name, sortOrder);\n }\n\n doubles(name: string): DoubleItem[] {\n return this.allByName<DoubleItem>(this.entity.doubles, name);\n }\n\n long(name: string, sortOrder = 0): LongItem | undefined {\n return this.byNameAndSortOrder<LongItem>(this.entity.longs, name, sortOrder);\n }\n\n longs(name: string): LongItem[] {\n return this.allByName<LongItem>(this.entity.longs, name);\n }\n\n /** Convenience: checks doubles first, falls back to longs, for callers who don't care which. */\n number(name: string, sortOrder = 0): DoubleItem | LongItem | undefined {\n return this.double(name, sortOrder) ?? this.long(name, sortOrder);\n }\n\n // ---------------------------------------------------------------------\n // Money\n // ---------------------------------------------------------------------\n\n money(name: string, sortOrder = 0): MoneyItem | undefined {\n return this.byNameAndSortOrder<MoneyItem>(this.entity.money, name, sortOrder);\n }\n\n moneys(name: string): MoneyItem[] {\n return this.allByName<MoneyItem>(this.entity.money, name);\n }\n\n // ---------------------------------------------------------------------\n // DateTime\n // ---------------------------------------------------------------------\n\n date(name: string, sortOrder = 0): DateTimeItem | undefined {\n return this.byNameAndSortOrder<DateTimeItem>(this.entity.dateTimes, name, sortOrder);\n }\n\n dates(name: string): DateTimeItem[] {\n return this.allByName<DateTimeItem>(this.entity.dateTimes, name);\n }\n\n // ---------------------------------------------------------------------\n // Images\n // ---------------------------------------------------------------------\n\n image(name: string, sortOrder = 0): ImageItem | undefined {\n return this.byNameAndSortOrder<ImageItem>(this.entity.images, name, sortOrder);\n }\n\n images(name: string): ImageItem[] {\n return this.allByName<ImageItem>(this.entity.images, name);\n }\n\n // ---------------------------------------------------------------------\n // LatLong\n // ---------------------------------------------------------------------\n\n latLong(name: string, sortOrder = 0): LatLongItem | undefined {\n return this.byNameAndSortOrder<LatLongItem>(this.entity.latLongs, name, sortOrder);\n }\n\n latLongs(name: string): LatLongItem[] {\n return this.allByName<LatLongItem>(this.entity.latLongs, name);\n }\n\n // ---------------------------------------------------------------------\n // JSON\n // ---------------------------------------------------------------------\n\n json(name: string, sortOrder = 0): JsonItem | undefined {\n return this.byNameAndSortOrder<JsonItem>(this.entity.jsons, name, sortOrder);\n }\n\n jsons(name: string): JsonItem[] {\n return this.allByName<JsonItem>(this.entity.jsons, name);\n }\n\n // ---------------------------------------------------------------------\n // Links\n // ---------------------------------------------------------------------\n\n link(name: string, sortOrder = 0): LinkItem | undefined {\n return this.byNameAndSortOrder<LinkItem>(this.entity.links, name, sortOrder);\n }\n\n links(name: string): LinkItem[] {\n return this.allByName<LinkItem>(this.entity.links, name);\n }\n\n // ---------------------------------------------------------------------\n // References to other entities\n // ---------------------------------------------------------------------\n\n reference(name: string, sortOrder = 0): ReferenceItem | undefined {\n return this.byNameAndSortOrder<ReferenceItem>(this.entity.references, name, sortOrder);\n }\n\n references(name: string): ReferenceItem[] {\n return this.allByName<ReferenceItem>(this.entity.references, name);\n }\n\n // ---------------------------------------------------------------------\n // Static helpers\n // ---------------------------------------------------------------------\n\n /**\n * Fetches an entity view from the API and wraps it directly, so callers\n * never have to touch the raw Entity at all:\n *\n * const view = await EntityView.fetch(client, '/home', { language: 'en-GB', variant: '' });\n *\n * `params` and `headers` are passed to `client.read`, for example to\n * forward a visitor's `Accept-Language`.\n */\n static async fetch(\n client: BaackClient,\n path: string,\n params?: QueryParams,\n headers?: Record<string, string>,\n ): Promise<EntityView> {\n const entity = await client.read<Entity>(Endpoint.ENTITY_VIEW, path, params, headers);\n return new EntityView(entity);\n }\n\n /** Wrap an Entity you already fetched some other way. */\n static from(entity: Entity): EntityView {\n return new EntityView(entity);\n }\n}\n", "// The editor's model of the content: entities as read, and items by version\n// URN. Items hold only the URN of their entity, so nothing here is circular.\n// Unsent work lives in PendingEdits.\n\nimport { EntityView, type Entity } from '@baack-software/baack-ts-client';\nimport type { Binding } from './discovery.ts';\nimport type { ContentItem, TypeEntry } from './registry.ts';\n\nexport interface StoredItem<I extends ContentItem = ContentItem> {\n readonly entry: TypeEntry<I>;\n readonly item: I;\n /** The entity the item belongs to, as returned by the API. */\n readonly entityUrn: string;\n}\n\nexport class Store {\n /** Scope on the page (or an entity URN read directly) \u2192 URN of the entity the API returned for it. */\n private readonly scopes = new Map<string, string>();\n private readonly views = new Map<string, EntityView>();\n private readonly items = new Map<string, StoredItem>();\n\n hasScope(scope: string): boolean {\n return this.scopes.has(scope);\n }\n\n /**\n * Records an entity read for a scope. The API can return a different entity\n * from the one addressed (another language version), so items are keyed by\n * what came back.\n */\n loadEntity(scope: string, entity: Entity): void {\n this.scopes.set(scope, entity.urn);\n this.views.set(entity.urn, EntityView.from(entity));\n }\n\n entityFor(scope: string): string | undefined {\n return this.scopes.get(scope);\n }\n\n view(entityUrn: string): EntityView | undefined {\n return this.views.get(entityUrn);\n }\n\n /** Entity URNs read so far, in the order they were first read. */\n entities(): string[] {\n return [...this.views.keys()];\n }\n\n /** The page scopes whose reads returned this entity. */\n scopesFor(entityUrn: string): string[] {\n return [...this.scopes].filter(([, urn]) => urn === entityUrn).map(([scope]) => scope);\n }\n\n /** The current item for a binding, or undefined when its slot is empty. */\n itemFor(binding: Binding): StoredItem | undefined {\n const entityUrn = this.scopes.get(binding.scope);\n return entityUrn === undefined ? undefined : this.itemAt(entityUrn, binding.entry, binding.name, binding.sortOrder);\n }\n\n /** The item in an entity's latest view at a name and stored sort order. */\n itemAt(entityUrn: string, entry: TypeEntry, name: string, sortOrder: number): StoredItem | undefined {\n const view = this.views.get(entityUrn);\n const found = view ? entry.find(view, name, sortOrder) : undefined;\n if (!found?.urn) return undefined;\n // Always the view's copy: a template's rendering can change while its URN does not.\n const stored: StoredItem = { entry, item: found, entityUrn };\n this.items.set(found.urn, stored);\n return stored;\n }\n\n /** Remembers a version that is not in the view, such as an older one from history. */\n remember(entityUrn: string, entry: TypeEntry, item: ContentItem): StoredItem {\n const stored: StoredItem = { entry, item, entityUrn };\n if (item.urn) this.items.set(item.urn, stored);\n return stored;\n }\n\n get(urn: string): StoredItem | undefined {\n return this.items.get(urn);\n }\n\n /**\n * Swaps a version for the one a write returned. The view is patched too,\n * unless the type's view value is a rendering (markdown, templates): a write\n * returns source, and the next view read brings the rendering.\n */\n replace(oldUrn: string, item: ContentItem): StoredItem {\n const previous = this.items.get(oldUrn);\n if (!previous || !item.urn) throw new Error(`Cannot replace unknown item ${oldUrn}`);\n const next: StoredItem = { entry: previous.entry, item, entityUrn: previous.entityUrn };\n this.items.delete(oldUrn);\n this.items.set(item.urn, next);\n\n if (previous.entry.renderedByView) return next;\n const items = this.views.get(previous.entityUrn)?.raw[previous.entry.entityArray] as ContentItem[] | undefined;\n const index = items?.findIndex((candidate) => candidate.urn === oldUrn) ?? -1;\n if (items && index >= 0) items[index] = item;\n return next;\n }\n\n /** Forgets entities and items so the next edit session reads them fresh. */\n clearEntities(): void {\n this.scopes.clear();\n this.views.clear();\n this.items.clear();\n }\n}\n", "// Reads the entity view for an entity in scope on the page. The view treats a\n// URN as a locator (api-model.md section 8), but addressed with the entity's\n// own language and variant it always returns that entity. So each read sends\n// the language and variant of the entity in scope, learnt from the admin\n// endpoint (which addresses the URN exactly). A response for any other entity\n// breaks that contract: it is an error, never something to edit.\n\nimport { isBaackApiError, type Entity } from '@baack-software/baack-ts-client';\nimport type { EntityViewOptions, Transport } from './transport.ts';\n\n/** The view answered with a different entity from the one in scope. */\nexport class EntityMismatchError extends Error {\n readonly expectedUrn: string;\n readonly received: Entity;\n\n constructor(expectedUrn: string, received: Entity) {\n super(`The entity view returned ${received.urn} (${received.language}) for ${expectedUrn}`);\n this.name = 'EntityMismatchError';\n this.expectedUrn = expectedUrn;\n this.received = received;\n }\n}\n\n/**\n * A live read of an entity that exists but is not published: the view answers\n * 404 for it, which is its safe behaviour when rendering for visitors.\n */\nexport class NotLiveError extends Error {\n readonly entityUrn: string;\n\n constructor(entityUrn: string) {\n super(`${entityUrn} has no live view: it is not published`);\n this.name = 'NotLiveError';\n this.entityUrn = entityUrn;\n }\n}\n\n/** The entity is visible on the site: published, possibly with newer drafts. */\nexport function isLive(status: Entity['status'] | undefined): boolean {\n return status === 'PUBLISHED' || status === 'PUBLISHED_WITH_DRAFTS';\n}\n\ninterface Locator {\n language: string;\n variant: string;\n}\n\nexport class ScopedViews {\n private readonly transport: Transport;\n /** Language and variant per entity URN, read once from the admin endpoint. */\n private readonly locators = new Map<string, Promise<Locator>>();\n\n constructor(transport: Transport) {\n this.transport = transport;\n }\n\n /** The view of exactly this entity, in the given read mode. */\n async read(entityUrn: string, options: Pick<EntityViewOptions, 'version'> = {}): Promise<Entity> {\n const locator = await this.locator(entityUrn);\n let entity: Entity;\n try {\n entity = await this.transport.entityView(entityUrn, { ...options, ...locator });\n } catch (error) {\n // The admin read just found the entity, and a live read needs no session: a 404 means it is not published.\n if (options.version === undefined && isBaackApiError(error) && error.isNotFound) throw new NotLiveError(entityUrn);\n throw error;\n }\n if (entity.urn !== entityUrn) throw new EntityMismatchError(entityUrn, entity);\n return entity;\n }\n\n /**\n * The page as visitors see it: the live view of a published entity, or the\n * latest drafts of one in an earlier state, which has no live view. The\n * status is read fresh, since publishing can change it during a visit.\n */\n async readAsLive(entityUrn: string): Promise<{ entity: Entity; live: boolean }> {\n const fields = await this.transport.readEntity(entityUrn);\n this.locators.set(entityUrn, Promise.resolve({ language: fields.language, variant: fields.variant ?? '' }));\n if (isLive(fields.status)) return { entity: await this.read(entityUrn), live: true };\n // While publishing (or stuck publishing), an entity that was already public still has a live view.\n if (fields.status === 'PUBLISH' || fields.status === 'PUBLISH_PENDING') {\n try {\n return { entity: await this.read(entityUrn), live: true };\n } catch (error) {\n if (!(error instanceof NotLiveError)) throw error;\n }\n }\n return { entity: await this.read(entityUrn, { version: 'LATEST' }), live: false };\n }\n\n private locator(entityUrn: string): Promise<Locator> {\n let locator = this.locators.get(entityUrn);\n if (!locator) {\n locator = this.transport.readEntity(entityUrn).then((entity) => ({ language: entity.language, variant: entity.variant ?? '' }));\n // A failed read is not remembered, so a retry asks again.\n locator.catch(() => this.locators.delete(entityUrn));\n this.locators.set(entityUrn, locator);\n }\n return locator;\n }\n}\n", "// Types shared by the editor's modules, and small helpers about lifecycle.\n\nimport type { LiveIslands } from './live.ts';\nimport type { Entity } from '@baack-software/baack-ts-client';\nimport { SCOPE_ATTRIBUTE, type Discovery, type Binding } from './core/discovery.ts';\nimport type { PendingEdits } from './core/pending.ts';\nimport type { ContentItem, ItemType, ItemValue, TypeEntry } from './core/registry.ts';\nimport type { Store } from './core/store.ts';\nimport type { Transport } from './core/transport.ts';\nimport type { Feedback } from './feedback.ts';\nimport type { GroupLog } from './core/groups.ts';\nimport type { EditorHost } from './ui/host.ts';\nimport type { Popover } from './ui/popover.ts';\nimport type { MessageAction, Toolbar } from './ui/toolbar.ts';\nimport type { ScopedViews } from './core/scoped-views.ts';\n\nexport type Value = ItemValue<ContentItem>;\n\n/** One cell of an entity's content matrix. */\nexport interface Slot {\n entityUrn: string;\n entry: TypeEntry;\n name: string;\n sortOrder: number;\n}\n\n/** What is being edited: an existing version (`urn`) or an empty slot to create. */\nexport interface EditTarget extends Slot {\n urn?: string | undefined;\n /** Where the popover opens: the element, or an outline row. */\n anchor: HTMLElement;\n /** The element, when editing on the page. */\n binding?: Binding | undefined;\n /** \"Edit from this version\": deliberately based on an older version, so no conflict check. */\n fromVersion?: boolean;\n}\n\n/** Late-bound actions between modules. */\nexport interface EditorHooks {\n openHistory(slot: Slot & { urn: string }): void;\n publishEntity(entityUrn: string): void;\n /** The element is an entry in a list or a table's rows. */\n canReorder(binding: Binding): boolean;\n reorder(binding: Binding): void;\n moveBy(binding: Binding, delta: -1 | 1): void;\n /** Opens Items with an item selected (highlighted and scrolled to). */\n showItem(slot: Slot): void;\n /** Move or rename: opens Items on the item's slots. */\n relocate(target: EditTarget): void;\n /** The rename form for an item. */\n rename(slot: Slot, item: ContentItem): void;\n /** Moves an item to a sort order, swapping with any item there. True when done. */\n moveSlot(slot: Slot, item: ContentItem, sortOrder: number): Promise<boolean>;\n /** Runs (or replays) a queued plan of moves. */\n runPlan(planId: string): Promise<boolean>;\n /** Saves an image with new files for some slots. */\n saveImage(target: EditTarget, files: Map<'DEFAULT' | 'MEDIUM' | 'LARGE', File>): Promise<void>;\n}\n\nexport interface PanelOptions {\n /** Shown above this entity's level, so Back leads to it. */\n entityUrn?: string;\n /** The level's title; by default the content's own `.title` child, which is then removed. */\n title?: string;\n /** False for progress shown while the user works elsewhere. */\n focus?: boolean;\n /** Runs when the level leaves the sidebar by any route (Back, Escape, another panel, Close of a task). */\n onLeave?(): void;\n}\n\nexport interface PanelHandle {\n /** Goes back from the panel, if it is still in the sidebar. */\n close(): void;\n readonly isOpen: boolean;\n}\n\n/**\n * A task as a sidebar level (a form, a confirm, progress): the deepest level,\n * so it never covers what it is about, and Back cancels it. Each is closed\n * through its own handle, never \"whatever is on screen\". A form's Cancel\n * (a `cancel` event on the content) goes back too. Showing one while another\n * is on screen replaces it.\n */\nexport interface Panels {\n show(content: HTMLElement, options?: PanelOptions): PanelHandle;\n}\n\n/** What every module shares. Built once by `Editor`. */\nexport interface EditorContext {\n readonly transport: Transport;\n readonly host: EditorHost;\n readonly registry: readonly TypeEntry[];\n readonly store: Store;\n readonly pending: PendingEdits;\n readonly toolbar: Toolbar;\n readonly popover: Popover;\n /** Tasks shown as sidebar levels. */\n readonly panels: Panels;\n readonly feedback: Feedback;\n /** Entity view reads for entities in scope, held to their language and variant. */\n readonly views: ScopedViews;\n /** Source loaded for types whose view value is a rendering, by URN. */\n readonly sources: Map<string, Value>;\n readonly discovery: Discovery;\n /** The user's role allows publishing (PUBLISHER or above). */\n readonly canPublish: boolean;\n /** Image slots a version needs before publishing (site setting). */\n readonly requiredImageSlots: readonly ('DEFAULT' | 'MEDIUM' | 'LARGE')[];\n readonly hooks: EditorHooks;\n /** Versions created together by one operation, kept in this browser. */\n readonly groups: GroupLog | undefined;\n /** Shows items in content the page's framework renders (`data-content-live`) through events. */\n readonly live: LiveIslands;\n entry(type: ItemType): TypeEntry;\n entityTitle(entityUrn: string): string;\n /**\n * Says `done` after a publish, with the site's `afterPublish` message or callback. `quiet`: `done` is news of the\n * entity's state, so where the toolbar's card already shows it, it is only spoken.\n */\n announcePublished(entityUrn: string, done: string, options?: { itemUrn?: string; info?: boolean; quiet?: boolean }): void;\n}\n\n/** The next step after saving drafts to an entity: its review, as the entity's own label offers it. */\nexport function reviewAction(ctx: EditorContext, entityUrn: string): MessageAction {\n return { label: ctx.canPublish ? 'Review and publish\u2026' : 'Request approval\u2026', run: () => ctx.hooks.publishEntity(entityUrn) };\n}\n\n/** The entity is visible on the site: new items there are published as soon as they are created. */\nexport { isLive } from './core/scoped-views.ts';\n\n/** The page's own entity: the one read for the root scope. */\nexport function pageEntity(store: Store): string | undefined {\n const root = document.documentElement.getAttribute(SCOPE_ATTRIBUTE);\n return root ? store.entityFor(root) : undefined;\n}\n\n/** The page's own entity first, then the others in the order given. */\nexport function pageFirst(store: Store, entityUrns: string[]): string[] {\n const page = pageEntity(store);\n return [...entityUrns].sort((a, b) => (a === page ? -1 : b === page ? 1 : 0));\n}\n\n/** The entity's lifecycle state as the server reports it (CLAUDE.md rule 7). */\nexport function lifecycleLabel(status: Entity['status'] | undefined): string {\n switch (status) {\n case 'DRAFT_UNPUBLISHED':\n return 'Draft, not published yet';\n case 'PUBLISH':\n return 'Publishing\u2026';\n case 'PUBLISH_PENDING':\n return 'Scheduled to publish';\n case 'PUBLISHED':\n return 'Published';\n case 'PUBLISHED_WITH_DRAFTS':\n return 'Published, with unpublished changes';\n default:\n return '';\n }\n}\n", "// Marks item elements on the host page while in edit mode. Uses inline\n// outline styles, which need no host CSS and are restored exactly on exit.\n// An empty element is held open at one character by one line, so its outline\n// (and the caret, while editing) stays visible.\n\nimport { PAGE_COLOURS } from './theme.ts';\n\n/** `published`: on the live page, content published since the page was built, which visitors may not see yet. */\nexport type MarkState = 'editable' | 'changed' | 'editing' | 'unresolved' | 'previewing' | 'published';\n\nexport const STATE_ATTRIBUTE = 'data-baack-state';\n\ntype Colour = keyof typeof PAGE_COLOURS;\n\n/** Width, style, colour and its opacity: the outline each state draws on the page. */\nconst OUTLINES: Record<MarkState, [string, Colour, number]> = {\n editable: ['1px dashed', 'primary', 70],\n editing: ['2px solid', 'primary', 100],\n changed: ['2px solid', 'warning', 100],\n unresolved: ['1px dotted', 'muted', 80],\n previewing: ['2px dashed', 'preview', 100],\n published: ['2px solid', 'success', 100],\n};\n\n/** The outline in the light colour, then (where the browser has light-dark()) following the page's color-scheme. */\nfunction drawOutline(element: HTMLElement, state: MarkState): void {\n const [line, colour, opacity] = OUTLINES[state];\n const [light, dark] = PAGE_COLOURS[colour];\n const faded = (value: string) => (opacity === 100 ? value : `color-mix(in srgb, ${value} ${opacity}%, transparent)`);\n element.style.outline = `${line} ${faded(light)}`;\n // Ignored, leaving the light colour, where light-dark() is not supported.\n element.style.outline = `${line} ${faded(`light-dark(${light}, ${dark})`)}`;\n}\n\ninterface Saved {\n outline: string;\n outlineOffset: string;\n display: string;\n minWidth: string;\n minHeight: string;\n}\n\nconst saved = new WeakMap<HTMLElement, Saved>();\n\nexport function mark(element: HTMLElement, state: MarkState): void {\n if (!saved.has(element)) {\n const { outline, outlineOffset, display, minWidth, minHeight } = element.style;\n saved.set(element, { outline, outlineOffset, display, minWidth, minHeight });\n }\n drawOutline(element, state);\n element.style.outlineOffset = '2px';\n element.setAttribute(STATE_ATTRIBUTE, state);\n fitEmpty(element);\n}\n\n/**\n * Holds a marked element open while it has no text: one character wide and\n * one line high. An inline element becomes inline-block to take the size.\n * Called again as its content changes (typing), and undone once it has text.\n */\nexport function fitEmpty(element: HTMLElement): void {\n const original = saved.get(element);\n if (!original) return;\n element.style.display = original.display;\n element.style.minWidth = original.minWidth;\n element.style.minHeight = original.minHeight;\n if (element.textContent !== '' || element.querySelector('img, picture, svg, video, iframe')) return;\n if (getComputedStyle(element).display === 'inline') element.style.display = 'inline-block';\n element.style.minWidth = '1ch';\n element.style.minHeight = '1lh';\n}\n\nexport function unmark(element: HTMLElement): void {\n const original = saved.get(element);\n if (original) {\n element.style.outline = original.outline;\n element.style.outlineOffset = original.outlineOffset;\n element.style.display = original.display;\n element.style.minWidth = original.minWidth;\n element.style.minHeight = original.minHeight;\n if (!element.getAttribute('style')) element.removeAttribute('style');\n saved.delete(element);\n }\n element.removeAttribute(STATE_ATTRIBUTE);\n}\n", null, null, "// Registry entries for every type except text. One entry per type.\n\nimport {\n Endpoint,\n type BooleanItem,\n type DateTimeItem,\n type DoubleItem,\n type ImageItem,\n type JsonItem,\n type LatLongItem,\n type LinkItem,\n type LongItem,\n type MarkdownItem,\n type MoneyItem,\n type ReferenceItem,\n type TemplateItem,\n} from '@baack-software/baack-ts-client';\nimport * as components from '@baack-software/baack-ts-components/components';\nimport { currencyDigits, majorToMinor, minorToMajor, parseTimestamp } from '@baack-software/baack-ts-components/format';\nimport type { TypeEntry } from '../core/registry.ts';\n\nconst str = (v: unknown) => (typeof v === 'string' ? v : '');\n\nfunction sourceEntry<I extends MarkdownItem | TemplateItem>(\n type: 'markdown' | 'template',\n label: string,\n endpoint: string,\n historyEndpoint: string,\n spec: typeof components.markdown,\n find: TypeEntry<I>['find'],\n): TypeEntry<I> {\n return {\n type,\n label,\n attribute: type,\n entityArray: type === 'markdown' ? 'markdowns' : 'templates',\n endpoint,\n historyEndpoint,\n surface: 'panel',\n valueKeys: ['value'],\n renderedByView: true,\n component: () => spec as never,\n // The placeholder renders as <p>text</p>.\n fromPlaceholder: (element) => ({ value: (element.textContent ?? '').trim() }) as never,\n find,\n defaults: () => ({ value: '' }) as never,\n form: {\n fields: [{ key: 'value', label: type === 'markdown' ? 'Markdown source' : 'Velocity template source', kind: 'code' }],\n toForm: (value) => ({ value: value.value }),\n fromForm: (values) => ({ value: str(values['value']) }) as never,\n describe: () =>\n type === 'markdown'\n ? 'The page shows the rendered result after you send.'\n : 'Templates can show other items. The page shows the result after you send.',\n },\n validate: () => [],\n };\n}\n\nexport const markdown = sourceEntry<MarkdownItem>(\n 'markdown',\n 'Markdown',\n Endpoint.MARKDOWN,\n Endpoint.MARKDOWN_HISTORY,\n components.markdown,\n (view, name, sortOrder) => view.markdown(name, sortOrder),\n);\n\nexport const template = sourceEntry<TemplateItem>(\n 'template',\n 'Template',\n Endpoint.TEMPLATE,\n Endpoint.TEMPLATE_HISTORY,\n components.template as typeof components.markdown,\n (view, name, sortOrder) => view.template(name, sortOrder),\n);\n\nexport const json: TypeEntry<JsonItem> = {\n type: 'json',\n label: 'JSON',\n attribute: 'json',\n entityArray: 'jsons',\n endpoint: Endpoint.JSON,\n historyEndpoint: Endpoint.JSON_HISTORY,\n surface: 'panel',\n valueKeys: ['value'],\n find: (view, name, sortOrder) => view.json(name, sortOrder),\n defaults: () => ({ value: {} }),\n form: {\n fields: [{ key: 'value', label: 'JSON object', kind: 'code' }],\n toForm: (value) => ({ value: JSON.stringify(value.value ?? {}, null, 2) }),\n fromForm: (values) => {\n try {\n const parsed: unknown = JSON.parse(str(values['value']));\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) return 'The value must be a JSON object, like {\"key\": \"value\"}.';\n return { value: parsed };\n } catch (error) {\n return `This is not valid JSON: ${error instanceof Error ? error.message : String(error)}`;\n }\n },\n },\n validate: () => [],\n};\n\nexport const boolean: TypeEntry<BooleanItem> = {\n type: 'boolean',\n label: 'Switch',\n attribute: 'boolean',\n entityArray: 'booleans',\n endpoint: Endpoint.BOOLEAN,\n historyEndpoint: Endpoint.BOOLEAN_HISTORY,\n surface: 'popover',\n valueKeys: ['value'],\n component: () => components.boolean as never,\n fromPlaceholder: (element) => ({ value: element.getAttribute('data-boolean-value') === 'true' }),\n find: (view, name, sortOrder) => view.boolean(name, sortOrder),\n defaults: () => ({ value: false }),\n form: {\n fields: [{ key: 'value', label: 'On', kind: 'checkbox' }],\n toForm: (value) => ({ value: value.value }),\n fromForm: (values) => ({ value: values['value'] === true }),\n },\n validate: () => [],\n};\n\nfunction wholeNumber(text: string): number | undefined {\n if (!/^\\s*-?\\d+\\s*$/.test(text)) return undefined;\n const value = Number(text);\n return Number.isSafeInteger(value) ? value : undefined;\n}\n\nexport const long: TypeEntry<LongItem> = {\n type: 'long',\n label: 'Whole number',\n attribute: 'long',\n entityArray: 'longs',\n endpoint: Endpoint.LONG,\n historyEndpoint: Endpoint.LONG_HISTORY,\n surface: 'popover',\n valueKeys: ['value'],\n component: () => components.long as never,\n find: (view, name, sortOrder) => view.long(name, sortOrder),\n defaults: () => ({ value: 0 }),\n form: {\n fields: [{ key: 'value', label: 'Value', kind: 'integer' }],\n toForm: (value) => ({ value: String(value.value) }),\n fromForm: (values) => {\n const value = wholeNumber(str(values['value']));\n return value === undefined ? 'Enter a whole number.' : { value };\n },\n },\n validate: () => [],\n};\n\nfunction decimal(text: string): number | undefined {\n if (!/^\\s*-?(\\d+\\.?\\d*|\\.\\d+)(e[+-]?\\d+)?\\s*$/i.test(text)) return undefined;\n const value = Number(text);\n return Number.isFinite(value) ? value : undefined;\n}\n\nexport const double: TypeEntry<DoubleItem> = {\n type: 'double',\n label: 'Number',\n attribute: 'double',\n entityArray: 'doubles',\n endpoint: Endpoint.DOUBLE,\n historyEndpoint: Endpoint.DOUBLE_HISTORY,\n surface: 'popover',\n valueKeys: ['value'],\n component: () => components.double as never,\n find: (view, name, sortOrder) => view.double(name, sortOrder),\n defaults: () => ({ value: 0 }),\n form: {\n fields: [{ key: 'value', label: 'Value', kind: 'decimal' }],\n toForm: (value) => ({ value: String(value.value) }),\n fromForm: (values) => {\n const value = decimal(str(values['value']));\n return value === undefined ? 'Enter a number.' : { value };\n },\n },\n validate: () => [],\n};\n\n/** \"2026-11-01T09:00:00.000\" (UTC, as the API writes it) \u2192 \"2026-11-01T09:00\" in the browser's local time. */\nfunction toLocalInput(value: string): string {\n const time = parseTimestamp(value);\n if (Number.isNaN(time)) return '';\n const local = new Date(time - new Date(time).getTimezoneOffset() * 60_000);\n return local.toISOString().slice(0, 16);\n}\n\n/** \"2026-11-01T09:00\" in local time \u2192 the API's UTC timestamp. */\nfunction fromLocalInput(text: string): string | undefined {\n if (!/^\\d{4}-\\d\\d-\\d\\dT\\d\\d:\\d\\d(:\\d\\d)?$/.test(text)) return undefined;\n const time = new Date(text).getTime(); // A date-time without a zone is local time.\n return Number.isNaN(time) ? undefined : new Date(time).toISOString().replace('Z', '');\n}\n\nexport const dateTime: TypeEntry<DateTimeItem> = {\n type: 'dateTime',\n label: 'Date and time',\n attribute: 'datetime',\n entityArray: 'dateTimes',\n endpoint: Endpoint.DATE_TIME,\n historyEndpoint: Endpoint.DATE_TIME_HISTORY,\n surface: 'popover',\n valueKeys: ['value'],\n component: () => components.dateTime as never,\n find: (view, name, sortOrder) => view.date(name, sortOrder),\n defaults: () => ({ value: new Date().toISOString().replace('Z', '') }),\n form: {\n fields: [{ key: 'value', label: 'Date and time (your local time)', kind: 'datetime' }],\n toForm: (value) => ({ value: toLocalInput(value.value) }),\n fromForm: (values) => {\n const value = fromLocalInput(str(values['value']));\n return value === undefined ? 'Enter a date and time.' : { value };\n },\n describe: (values) => {\n const value = fromLocalInput(str(values['value']));\n return value ? `Stored as ${value.slice(0, 16).replace('T', ' ')} UTC.` : '';\n },\n },\n validate: () => [],\n};\n\nexport const latLong: TypeEntry<LatLongItem> = {\n type: 'latLong',\n label: 'Location',\n attribute: 'latlong',\n entityArray: 'latLongs',\n endpoint: Endpoint.LAT_LONG,\n historyEndpoint: Endpoint.LAT_LONG_HISTORY,\n surface: 'popover',\n valueKeys: ['latitude', 'longitude'],\n component: () => components.latLong as never,\n find: (view, name, sortOrder) => view.latLong(name, sortOrder),\n defaults: () => ({ latitude: 0, longitude: 0 }),\n form: {\n fields: [\n { key: 'latitude', label: 'Latitude', kind: 'decimal' },\n { key: 'longitude', label: 'Longitude', kind: 'decimal' },\n ],\n toForm: (value) => ({ latitude: String(value.latitude), longitude: String(value.longitude) }),\n fromForm: (values) => {\n const latitude = decimal(str(values['latitude']));\n const longitude = decimal(str(values['longitude']));\n if (latitude === undefined || Math.abs(latitude) > 90) return 'Latitude must be a number from -90 to 90.';\n if (longitude === undefined || Math.abs(longitude) > 180) return 'Longitude must be a number from -180 to 180.';\n return { latitude, longitude };\n },\n },\n validate: () => [],\n};\n\nfunction validCurrency(code: string): boolean {\n if (!/^[A-Z]{3}$/.test(code)) return false;\n try {\n new Intl.NumberFormat('en', { style: 'currency', currency: code });\n return true;\n } catch {\n return false;\n }\n}\n\nexport const money: TypeEntry<MoneyItem> = {\n type: 'money',\n label: 'Money',\n attribute: 'money',\n entityArray: 'money',\n endpoint: Endpoint.MONEY,\n historyEndpoint: Endpoint.MONEY_HISTORY,\n surface: 'popover',\n valueKeys: ['currencyCode', 'unitValue'],\n derived: ['formattedValue', 'currencySymbol'],\n component: () => components.money as never,\n find: (view, name, sortOrder) => view.money(name, sortOrder),\n defaults: () => ({ currencyCode: 'GBP', unitValue: 0 }),\n form: {\n fields: [\n { key: 'currencyCode', label: 'Currency', kind: 'currency' },\n { key: 'amount', label: 'Amount', kind: 'text' },\n ],\n toForm: (value) => ({\n currencyCode: value.currencyCode,\n amount: minorToMajor(value.unitValue, currencyDigits(value.currencyCode)),\n }),\n fromForm: (values) => {\n const currencyCode = str(values['currencyCode']).trim().toUpperCase();\n if (!validCurrency(currencyCode)) return 'Enter a three-letter currency code, like GBP or JPY.';\n const digits = currencyDigits(currencyCode);\n const unitValue = majorToMinor(str(values['amount']), digits);\n if (unitValue === undefined) {\n return digits === 0\n ? `${currencyCode} has no minor units. Enter a whole amount.`\n : `Enter an amount with at most ${digits} decimal places, like ${minorToMajor(1250, digits)}.`;\n }\n return { currencyCode, unitValue };\n },\n describe: (values) => {\n const currencyCode = str(values['currencyCode']).trim().toUpperCase();\n if (!validCurrency(currencyCode)) return '';\n const unitValue = majorToMinor(str(values['amount']), currencyDigits(currencyCode));\n return unitValue === undefined ? '' : `Stored as ${unitValue} in the smallest unit of ${currencyCode}.`;\n },\n },\n validate: () => [],\n};\n\n/** The image's file slots: the upload's size name and the item field that holds its address. */\nexport const IMAGE_SLOTS = [\n { size: 'DEFAULT', field: 'src', label: 'Default file' },\n { size: 'MEDIUM', field: 'mediumSrc', label: 'Medium file (from 768px wide)' },\n { size: 'LARGE', field: 'largeSrc', label: 'Large file (from 1024px wide)' },\n] as const;\n\nexport const image: TypeEntry<ImageItem> = {\n type: 'image',\n label: 'Image',\n attribute: 'image',\n entityArray: 'images',\n endpoint: Endpoint.IMAGE,\n historyEndpoint: Endpoint.IMAGE_HISTORY,\n surface: 'popover',\n valueKeys: ['altText', 'src', 'mediumSrc', 'largeSrc'],\n // The API keeps a version's files only when an update passes their addresses back unchanged.\n carried: ['src', 'mediumSrc', 'largeSrc'],\n component: () => components.image as never,\n fromPlaceholder: (element) => ({ altText: element.querySelector('img')?.alt ?? '' }),\n find: (view, name, sortOrder) => view.image(name, sortOrder),\n defaults: () => ({ altText: '' }),\n form: {\n fields: [{ key: 'altText', label: 'Alt text', kind: 'text' }, ...IMAGE_SLOTS.map((slot) => ({ key: slot.size, label: slot.label, kind: 'file' as const }))],\n // Each slot field shows the current file; the chosen file itself is read from the popover.\n toForm: (value) => ({\n altText: value.altText ?? '',\n ...Object.fromEntries(IMAGE_SLOTS.flatMap((slot) => [[slot.size, ''], [`${slot.size}:current`, String(value[slot.field] ?? '')]])),\n }),\n fromForm: (values) => ({ altText: str(values['altText']) }),\n describe: (values) => {\n const replacing = IMAGE_SLOTS.filter((slot) => str(values[slot.size]) !== '');\n if (replacing.length === 0) return 'Saving keeps the current files.';\n const kept = IMAGE_SLOTS.filter((slot) => !replacing.includes(slot) && str(values[`${slot.size}:current`]) !== '');\n const note = `Saving creates a new version, then uploads ${replacing.map((slot) => slot.label.toLowerCase().split(' (')[0]).join(', ')}.`;\n return replacing.some((slot) => slot.size === 'DEFAULT') && kept.length > 0\n ? `${note} The ${kept.map((slot) => slot.size.toLowerCase()).join(' and ')} file still shows the previous picture; choose new ones too if it changed.`\n : note;\n },\n },\n validate: ({ altText }) => (altText ? [] : [{ level: 'warning', message: 'Images need alt text unless they are decorative.' }]),\n};\n\nexport const link: TypeEntry<LinkItem> = {\n type: 'link',\n label: 'Link',\n attribute: 'link',\n entityArray: 'links',\n endpoint: Endpoint.LINK,\n historyEndpoint: Endpoint.LINK_HISTORY,\n surface: 'popover',\n valueKeys: ['href', 'text', 'rel', 'lang'],\n component: () => components.link as never,\n fromPlaceholder: (element) => {\n const href = element.getAttribute('href');\n const text = (element.textContent ?? '').trim();\n return { href: href && href !== '#' ? href : '', ...(text ? { text } : {}) };\n },\n find: (view, name, sortOrder) => view.link(name, sortOrder),\n defaults: () => ({ href: '', text: '' }),\n form: {\n fields: [\n { key: 'text', label: 'Text', kind: 'text' },\n { key: 'href', label: 'Address', kind: 'url' },\n { key: 'rel', label: 'Relationship (rel), e.g. nofollow', kind: 'text' },\n { key: 'lang', label: 'Language of the target, e.g. en', kind: 'text' },\n ],\n toForm: (value) => ({ text: value.text ?? '', href: value.href, rel: value.rel ?? '', lang: value.lang ?? '' }),\n fromForm: (values) => {\n const href = str(values['href']).trim();\n if (!href) return 'Enter the address the link goes to.';\n if (href.length > 2048) return 'The address can be at most 2048 characters.';\n const value: { href: string; text?: string; rel?: string; lang?: string } = { href };\n for (const key of ['text', 'rel', 'lang'] as const) {\n const field = str(values[key]).trim();\n if (field) value[key] = field;\n }\n return value;\n },\n },\n validate: ({ href }) =>\n /^\\s*javascript:/i.test(href) ? [{ level: 'error', message: 'Links cannot run scripts.' }] : [],\n};\n\nexport const reference: TypeEntry<ReferenceItem> = {\n type: 'reference',\n label: 'Reference',\n attribute: 'reference',\n entityArray: 'references',\n endpoint: Endpoint.REFERENCE,\n historyEndpoint: Endpoint.REFERENCE_HISTORY,\n surface: 'popover',\n valueKeys: ['entityReference'],\n find: (view, name, sortOrder) => view.reference(name, sortOrder),\n defaults: () => ({ entityReference: { urn: '' } as ReferenceItem['entityReference'] }),\n form: {\n // Chosen by path and language; the reference stores the URN.\n fields: [{ key: 'urn', label: 'Entity referred to', kind: 'entity' }],\n toForm: (value) => ({ urn: value.entityReference?.urn ?? '' }),\n fromForm: (values) => {\n const urn = str(values['urn']).trim();\n if (!/^[0-9a-f-]{36}$/i.test(urn)) return 'Choose the entity this refers to.';\n return { entityReference: { urn } as ReferenceItem['entityReference'] };\n },\n },\n validate: () => [],\n};\n", "// Replacing an image's files. Never upload to a version whose slot already\n// has a file (CLAUDE.md rule 5): save a new version first, with the slots\n// being replaced left empty (the API keeps a slot's address only when the\n// update passes it back), then upload each file to that new version, in\n// parallel, and wait for the CDN to place them.\n\nimport type { ImageItem } from '@baack-software/baack-ts-client';\nimport { createKey } from './core/pending.ts';\nimport { urnAttribute, withCarried, type ContentItem } from './core/registry.ts';\nimport type { Editing } from './editing.ts';\nimport type { Saving } from './saving.ts';\nimport type { EditTarget, EditorContext, Value } from './targets.ts';\nimport { el } from './ui/host.ts';\nimport { mark } from './ui/marker.ts';\nimport { IMAGE_SLOTS } from './types/values.ts';\nimport type { PageView } from './view.ts';\nimport './config.ts'; // Declares window.baackEditorConfig.\n\ntype Size = (typeof IMAGE_SLOTS)[number]['size'];\n\n/** Reads between polls: quick at first, never slower than every 4 seconds; give up after about 30 seconds. */\nconst POLL_MS = [250, 500, 1000, 2000, 4000];\nconst POLL_LIMIT_MS = 30_000;\n\nexport class Images {\n private readonly ctx: EditorContext;\n private readonly view: PageView;\n private readonly saving: () => Saving;\n private readonly editing: () => Editing;\n\n constructor(ctx: EditorContext, view: PageView, saving: () => Saving, editing: () => Editing) {\n this.ctx = ctx;\n this.view = view;\n this.saving = saving;\n this.editing = editing;\n }\n\n /** Saves the image's alt text with new files for the chosen slots. */\n async save(target: EditTarget, chosen: Map<Size, File>): Promise<void> {\n const problem = imageFileIssues(chosen).find((issue) => issue.level === 'error');\n if (problem) return this.ctx.popover.setError(problem.message);\n const files = await withSizes(chosen, window.baackEditorConfig?.imageWidths);\n const { pending, popover, store, feedback } = this.ctx;\n const entry = target.entry;\n const form = entry.form!.fromForm(popover.values());\n if (typeof form === 'string') return popover.setError(form);\n\n // The new version keeps the files not being replaced, and leaves the replaced slots empty for the upload.\n const base = target.urn ? (store.get(target.urn)?.item as ImageItem | undefined) : undefined;\n const value = withCarried(entry, base, form) as Record<string, unknown>;\n for (const size of files.keys()) delete value[IMAGE_SLOTS.find((slot) => slot.size === size)!.field];\n if (target.urn) {\n pending.set({ kind: 'edit', type: entry.type, urn: target.urn, entityUrn: target.entityUrn, name: target.name, sortOrder: target.sortOrder, value: value as Value });\n } else {\n pending.set({ kind: 'create', type: entry.type, entityUrn: target.entityUrn, name: target.name, sortOrder: target.sortOrder, value: value as Value });\n }\n const change = target.urn ? pending.getEdit(target.urn)! : pending.getCreate(createKey({ ...target, type: entry.type }))!;\n\n popover.setSending(true);\n popover.setError('');\n let version: ContentItem;\n try {\n version = await this.saving().commit(change);\n } catch (error) {\n popover.setSending(false);\n const failure = await feedback.describe(error, 'save this image');\n popover.setError(failure.message, failure.debug);\n return;\n }\n\n popover.setSending(false);\n // Show the chosen files at once, marked as changed, while the CDN places them.\n const previews = new Map<Size, string>([...files].map(([size, file]) => [size, URL.createObjectURL(file)]));\n this.preview(target.entityUrn, version, previews);\n await this.upload(target, version, files, previews);\n }\n\n /** Uploads files to a version's empty slots in parallel, then waits for their addresses. Progress shows in the toolbar. */\n private async upload(target: EditTarget, version: ContentItem, files: Map<Size, File>, previews: Map<Size, string>): Promise<void> {\n const { transport, feedback, toolbar } = this.ctx;\n this.editing().close();\n const panel = el('div', 'simple-form');\n panel.setAttribute('aria-label', 'Image upload');\n const lines = new Map<Size, HTMLElement>();\n panel.append(el('div', 'title', `Uploading to a new version of ${target.name}`));\n for (const [size, file] of files) {\n const line = el('p', 'hint', `${label(size)}: ${file.name}: uploading\u2026`);\n lines.set(size, line);\n panel.append(line);\n }\n // Progress, shown above the item's entity without taking focus from the page.\n const progress = this.ctx.panels.show(panel, { entityUrn: target.entityUrn, focus: false });\n const say = (size: Size, text: string, problem = false) => {\n const line = lines.get(size)!;\n line.textContent = `${label(size)}: ${files.get(size)!.name}: ${text}`;\n line.className = problem ? 'error' : 'hint';\n };\n\n // Synchronous uploads: each answers with the image item, its slot's address already set.\n const results = await Promise.allSettled([...files].map(([size, file]) => transport.uploadImageFile(version.urn!, size, file)));\n const answered = results.flatMap((result) => (result.status === 'fulfilled' ? [result.value as Record<string, unknown>] : []));\n const failed = new Map<Size, File>();\n for (const [index, result] of results.entries()) {\n const [size, file] = [...files][index]!;\n if (result.status === 'rejected') {\n failed.set(size, file);\n say(size, (await feedback.describe(result.reason, 'upload this file')).message, true);\n } else {\n say(size, 'uploaded; waiting for the CDN\u2026');\n }\n }\n\n const uploaded = [...files.keys()].filter((size) => !failed.has(size));\n const fieldOf = (size: Size) => IMAGE_SLOTS.find((slot) => slot.size === size)!.field;\n const inResponses = uploaded.every((size) => answered.some((item) => item[fieldOf(size)]));\n // Only if a response lacked an address (not expected), read the version until it appears.\n const placed = inResponses || (await this.waitForAddresses(target.entry, version.urn!, uploaded));\n for (const size of uploaded) say(size, placed ? 'done' : 'still processing; it appears when the CDN has placed it.');\n await this.view.refresh(target.entityUrn); // Shows the real addresses.\n\n if (failed.size > 0) {\n // The failed slots of this version are still empty, so they can be retried safely.\n this.preview(target.entityUrn, version, new Map([...previews].filter(([size]) => failed.has(size))));\n const retry = el('button', 'primary', 'Retry failed uploads');\n retry.type = 'button';\n retry.addEventListener('click', () => void this.retry(target, version, failed, previews));\n const actions = el('div', 'actions');\n actions.append(retry);\n panel.append(el('p', 'message', 'Some files were not uploaded. The new version keeps the others.'), actions);\n return;\n }\n for (const url of previews.values()) URL.revokeObjectURL(url);\n progress.close();\n toolbar.showMessage(`Uploaded ${files.size} ${files.size === 1 ? 'file' : 'files'} to a new version of ${target.name}.`, true);\n }\n\n /** Retries only slots of the same version that are still empty: never uploads over a file. */\n private async retry(target: EditTarget, version: ContentItem, failed: Map<Size, File>, previews: Map<Size, string>): Promise<void> {\n const current = (await this.ctx.transport.read(target.entry, version.urn!)) as unknown as Record<string, unknown>;\n const stillEmpty = new Map([...failed].filter(([size]) => !current[IMAGE_SLOTS.find((slot) => slot.size === size)!.field]));\n await this.upload(target, version, stillEmpty, previews);\n }\n\n /** Reads the version until every uploaded slot has its address. */\n private async waitForAddresses(entry: EditTarget['entry'], urn: string, sizes: Size[]): Promise<boolean> {\n if (sizes.length === 0) return true;\n const start = Date.now();\n for (let attempt = 0; Date.now() - start < POLL_LIMIT_MS; attempt += 1) {\n const item = (await this.ctx.transport.read(entry, urn)) as unknown as Record<string, unknown>;\n if (sizes.every((size) => item[IMAGE_SLOTS.find((slot) => slot.size === size)!.field])) {\n this.ctx.store.remember(this.ctx.store.get(urn)?.entityUrn ?? '', entry, item as unknown as ContentItem);\n return true;\n }\n await new Promise((resolve) => setTimeout(resolve, POLL_MS[Math.min(attempt, POLL_MS.length - 1)]));\n }\n return false;\n }\n\n /** Renders the chosen files (object URLs) wherever the new version shows. */\n private preview(entityUrn: string, version: ContentItem, previews: Map<Size, string>): void {\n // Start from the newest copy of the version: slots already placed keep their addresses.\n const item: Record<string, unknown> = { ...(this.ctx.store.get(version.urn!)?.item ?? version) };\n for (const [size, url] of previews) item[IMAGE_SLOTS.find((slot) => slot.size === size)!.field] = url;\n const entry = this.ctx.entry('image');\n for (const binding of this.ctx.discovery.all()) {\n if (binding.entry !== entry || this.ctx.store.entityFor(binding.scope) !== entityUrn) continue;\n if (binding.element.getAttribute(urnAttribute(entry)) !== version.urn && !(binding.name === version.name && binding.sortOrder === version.sortOrder)) continue;\n this.ctx.live.render(binding, item as unknown as ImageItem);\n mark(binding.element, 'changed');\n }\n }\n}\n\nfunction label(size: Size): string {\n return IMAGE_SLOTS.find((slot) => slot.size === size)!.label.split(' (')[0]!;\n}\n\n/**\n * Off by default: when the site sets `imageWidths` and only a default file\n * is chosen, scale it in the browser to those widths for the medium and\n * large slots. Never scales up; a file the browser cannot scale is used as is.\n */\nasync function withSizes(files: Map<Size, File>, widths: { MEDIUM?: number; LARGE?: number } | undefined): Promise<Map<Size, File>> {\n const original = files.get('DEFAULT');\n if (!widths || !original || files.size > 1) return files;\n const result = new Map(files);\n for (const size of ['MEDIUM', 'LARGE'] as const) {\n const width = widths[size];\n if (width) result.set(size, await scaled(original, width, size));\n }\n return result;\n}\n\nasync function scaled(file: File, width: number, size: Size): Promise<File> {\n try {\n const bitmap = await createImageBitmap(file);\n if (bitmap.width <= width) return file;\n const height = Math.round((bitmap.height * width) / bitmap.width);\n const canvas = document.createElement('canvas');\n canvas.width = width;\n canvas.height = height;\n canvas.getContext('2d')!.drawImage(bitmap, 0, 0, width, height);\n const type = file.type === 'image/png' || file.type === 'image/webp' ? file.type : 'image/jpeg';\n const blob = await new Promise<Blob>((resolve, reject) =>\n canvas.toBlob((b) => (b ? resolve(b) : reject(new Error('Could not scale the image'))), type, 0.9),\n );\n const name = file.name.replace(/(\\.[^.]+)?$/, `-${size.toLowerCase()}$1`);\n return new File([blob], name, { type });\n } catch {\n return file;\n }\n}\n\n/**\n * Image types the upload accepts (confirmed against the API). SVG is shown\n * through <img>, where its scripts do not run; the CDN should still serve it\n * with `Content-Security-Policy: script-src 'none'` for anyone opening it directly.\n */\nexport const IMAGE_TYPES = ['image/apng', 'image/avif', 'image/gif', 'image/jpeg', 'image/png', 'image/svg+xml', 'image/webp'];\n\nconst MB = 1024 * 1024;\n\n/** Problems with chosen files, checked before anything is saved: type, the size limit, and a size warning. */\nexport function imageFileIssues(files: Map<string, File>): { level: 'warning' | 'error'; message: string }[] {\n const max = window.baackEditorConfig?.maxImageBytes ?? 10 * MB;\n const warn = window.baackEditorConfig?.warnImageBytes ?? 2 * MB;\n const size = (bytes: number) => `${(bytes / MB).toFixed(1)} MB`;\n const issues: { level: 'warning' | 'error'; message: string }[] = [];\n for (const file of files.values()) {\n if (!IMAGE_TYPES.includes(file.type)) {\n issues.push({ level: 'error', message: `${file.name} is not an image type Baack accepts: JPEG, PNG, APNG, GIF, WebP, AVIF or SVG.` });\n } else if (file.size > max) {\n issues.push({ level: 'error', message: `${file.name} is ${size(file.size)}; the limit is ${size(max)}. Use a smaller file.` });\n } else if (file.size > warn) {\n issues.push({ level: 'warning', message: `${file.name} is ${size(file.size)}, large for the web. Compressing it will make the page faster.` });\n }\n }\n return issues;\n}\n", null, "// Content inside a `data-content-live` element is rendered by the page's\n// framework (a hydrated island, a client-rendered app), which would undo or\n// trip over a direct DOM change. There the editor announces what each item\n// should show (`baack:item-shown`), and the page re-renders from its entity\n// (`useLiveEntity` in the components). Everywhere else it renders in place.\n\nimport {\n ITEM_SHOWN_EVENT,\n LIVE_ATTRIBUTE,\n LIVE_REQUEST_EVENT,\n type ItemShownDetail,\n type LiveRequestDetail,\n} from '@baack-software/baack-ts-components/live';\nimport type { Binding } from './core/discovery.ts';\nimport { renderInto, urnAttribute, type ContentItem } from './core/registry.ts';\nimport type { Store } from './core/store.ts';\n\n/** True when the page's framework renders this element. */\nexport function inLiveContent(element: Element): boolean {\n return element.closest(`[${LIVE_ATTRIBUTE}]`) !== null;\n}\n\nexport class LiveIslands {\n private readonly store: Store;\n /** What the editor shows in live content, by slot: sent again to content that renders later. */\n private readonly shown = new Map<string, ItemShownDetail>();\n /** Slots holding a reorder preview: the page re-renders its elements there, which must not end the preview. */\n private readonly previews = new Set<string>();\n\n constructor(store: Store) {\n this.store = store;\n document.addEventListener(LIVE_REQUEST_EVENT, this.onRequest);\n }\n\n /** Shows `item` in a binding's element: through an event for live content, in place otherwise. */\n render(binding: Binding, item: ContentItem): void {\n if (!inLiveContent(binding.element)) {\n renderInto(binding.entry, binding.element, binding, item);\n return;\n }\n const detail: ItemShownDetail = { ...this.slot(binding), item };\n // A reorder preview holds this slot until it is saved or reverted.\n if (this.previews.has(key(detail))) return;\n this.shown.set(key(detail), detail);\n dispatch(detail);\n // The framework renders asynchronously; the editor finds the element by its URN straight away.\n if (item.urn) binding.element.setAttribute(urnAttribute(binding.entry), item.urn);\n }\n\n /** For live content, asks the page to show its own value again and returns true; false for other content. */\n restore(binding: Binding): boolean {\n if (!inLiveContent(binding.element)) return false;\n const detail: ItemShownDetail = { ...this.slot(binding), restore: true };\n if (this.previews.has(key(detail))) return true;\n this.shown.delete(key(detail));\n dispatch(detail);\n return true;\n }\n\n /**\n * For live content: shows `item` at another slot of the binding's name (a\n * reorder preview), or with no item, asks the page to show its own again.\n */\n showAt(binding: Binding, sortOrder: number, item: ContentItem | undefined): void {\n const detail: ItemShownDetail = item ? { ...this.slot(binding), sortOrder, item } : { ...this.slot(binding), sortOrder, restore: true };\n if (item) {\n this.shown.set(key(detail), detail);\n this.previews.add(key(detail));\n } else {\n this.shown.delete(key(detail));\n this.previews.delete(key(detail));\n }\n dispatch(detail);\n }\n\n /** A reorder preview was saved, or edit mode is ending: its slots show what the editor renders again. */\n endPreviews(): void {\n this.previews.clear();\n }\n\n private slot(binding: Binding) {\n return {\n entityUrn: this.store.entityFor(binding.scope) ?? binding.scope,\n type: binding.entry.type,\n name: binding.name,\n sortOrder: binding.sortOrder,\n };\n }\n\n private readonly onRequest = (event: CustomEvent<LiveRequestDetail>) => {\n for (const detail of this.shown.values()) if (detail.entityUrn === event.detail.entityUrn) dispatch(detail);\n };\n}\n\nfunction key(detail: ItemShownDetail): string {\n return `${detail.entityUrn}\\u0000${detail.type}\\u0000${detail.name}\\u0000${detail.sortOrder}`;\n}\n\nfunction dispatch(detail: ItemShownDetail): void {\n document.dispatchEvent(new CustomEvent(ITEM_SHOWN_EVENT, { detail }));\n}\n", "// Editing in place on the host page's own element. Handles only the DOM side:\n// making the element editable, keys, focus, and putting everything back.\n\nimport type { EditorHost } from './host.ts';\nimport { fitEmpty } from './marker.ts';\nimport { inLiveContent } from '../live.ts';\n\nexport interface InlineCallbacks {\n input(): void;\n send(): void;\n revert(): void;\n /** Focus left the element and the editor UI. The edit is kept. */\n blurred(): void;\n}\n\nconst IS_MAC = /Mac|iPhone|iPad/.test(navigator.userAgent);\n\nexport class InlineEdit {\n readonly element: HTMLElement;\n /** Inline elements (a span) send on Enter; block elements and paragraph layouts take a newline. */\n readonly sendsOnEnter: boolean;\n private readonly host: EditorHost;\n private readonly callbacks: InlineCallbacks;\n private readonly savedEditable: string | null;\n private readonly savedWhiteSpace: string;\n /** In live content, the framework's own nodes, put back on close so it can render the saved value over them. */\n private readonly savedChildren: Node[] | undefined;\n\n /** `raw` is the value to edit, shown as plain text in place of the component's rendering. */\n constructor(element: HTMLElement, raw: string, host: EditorHost, callbacks: InlineCallbacks) {\n this.element = element;\n this.host = host;\n this.callbacks = callbacks;\n this.sendsOnEnter =\n getComputedStyle(element).display.startsWith('inline') && element.getAttribute('data-text-layout') !== 'paragraphs';\n this.savedEditable = element.getAttribute('contenteditable');\n this.savedWhiteSpace = element.style.whiteSpace;\n this.savedChildren = inLiveContent(element) ? [...element.childNodes] : undefined;\n\n element.textContent = raw;\n fitEmpty(element);\n // plaintext-only: the browser inserts no markup, and pastes arrive as text.\n element.setAttribute('contenteditable', 'plaintext-only');\n // Show newlines and repeated spaces exactly as they will be stored.\n element.style.whiteSpace = 'pre-wrap';\n element.addEventListener('input', this.onInput);\n element.addEventListener('keydown', this.onKeyDown);\n element.addEventListener('blur', this.onBlur);\n element.focus();\n placeCaret(element);\n }\n\n get hint(): string {\n const modifier = IS_MAC ? '\u2318' : 'Ctrl';\n return this.sendsOnEnter ? 'Enter to save \u00B7 Esc to revert' : `${modifier}+Enter to save \u00B7 Esc to revert`;\n }\n\n close(): void {\n this.element.removeEventListener('input', this.onInput);\n this.element.removeEventListener('keydown', this.onKeyDown);\n this.element.removeEventListener('blur', this.onBlur);\n if (this.savedEditable === null) {\n this.element.removeAttribute('contenteditable');\n } else {\n this.element.setAttribute('contenteditable', this.savedEditable);\n }\n this.element.style.whiteSpace = this.savedWhiteSpace;\n if (!this.element.getAttribute('style')) this.element.removeAttribute('style');\n if (this.savedChildren) this.element.replaceChildren(...this.savedChildren);\n }\n\n private readonly onInput = () => {\n // Emptied by typing: keep the element (and the caret) visible.\n fitEmpty(this.element);\n this.callbacks.input();\n };\n\n private readonly onKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n event.preventDefault();\n this.callbacks.revert();\n } else if (event.key === 'Enter' && (event.metaKey || event.ctrlKey || (this.sendsOnEnter && !event.shiftKey))) {\n event.preventDefault();\n this.callbacks.send();\n }\n };\n\n private readonly onBlur = (event: FocusEvent) => {\n // Focus moving into the editor's own UI is not leaving the edit.\n if (event.relatedTarget === this.host.element) return;\n this.callbacks.blurred();\n };\n}\n\n/** Keeps a selection the double-click made inside the element; otherwise puts the caret at the end. */\nfunction placeCaret(element: HTMLElement): void {\n const selection = window.getSelection();\n if (!selection) return;\n if (selection.rangeCount > 0 && element.contains(selection.getRangeAt(0).commonAncestorContainer)) return;\n const range = document.createRange();\n range.selectNodeContents(element);\n range.collapse(false);\n selection.removeAllRanges();\n selection.addRange(range);\n}\n", "// Opening an editor for an element or an outline row: in place for text, a\n// form otherwise; recording unsaved values and previewing them.\n\nimport type { Binding } from './core/discovery.ts';\nimport { createKey } from './core/pending.ts';\nimport { sameValue, urnAttribute, valueOf, withCarried, type FormValues } from './core/registry.ts';\nimport { isLive, type EditTarget, type EditorContext, type Value } from './targets.ts';\nimport { imageFileIssues } from './images.ts';\nimport { InlineEdit } from './ui/inline.ts';\nimport { mark } from './ui/marker.ts';\nimport type { ExtraAction } from './ui/popover.ts';\nimport type { PageView } from './view.ts';\n\ninterface ActiveEdit {\n target: EditTarget;\n /** In-place editing; absent for a form. */\n session: InlineEdit | undefined;\n}\n\nexport class Editing {\n private readonly ctx: EditorContext;\n private readonly view: PageView;\n private readonly save: (target: EditTarget) => Promise<void>;\n private active: ActiveEdit | undefined;\n\n constructor(ctx: EditorContext, view: PageView, save: (target: EditTarget) => Promise<void>) {\n this.ctx = ctx;\n this.view = view;\n this.save = save;\n }\n\n /** The edit in progress, if any. */\n get current(): ActiveEdit | undefined {\n return this.active;\n }\n\n attach(): void {\n document.addEventListener('dblclick', this.onDoubleClick, true);\n document.addEventListener('click', this.onClick, true);\n }\n\n detach(): void {\n document.removeEventListener('dblclick', this.onDoubleClick, true);\n document.removeEventListener('click', this.onClick, true);\n }\n\n private readonly onDoubleClick = (event: MouseEvent) => {\n const { discovery, toolbar } = this.ctx;\n const element = discovery.closest(event.target);\n if (!element || this.active?.target.binding?.element === element) return;\n const binding = discovery.of(element)[0];\n if (!binding) return;\n event.preventDefault();\n const target = this.targetFor(binding);\n if (!target) {\n toolbar.showMessage(`The content for \"${binding.name}\" has not loaded.`);\n return;\n }\n this.open(target);\n };\n\n /** In edit mode a click on an item must not follow a link around it. */\n private readonly onClick = (event: MouseEvent) => {\n if (this.ctx.discovery.closest(event.target)) event.preventDefault();\n };\n\n /** Clicking elsewhere closes a form; the edit is kept. */\n private readonly onPointerDown = (event: PointerEvent) => {\n const path = event.composedPath();\n const anchor = this.active?.target.binding?.element ?? this.active?.target.anchor;\n if (!this.active || path.includes(this.ctx.host.element) || (anchor && path.includes(anchor))) return;\n this.close();\n };\n\n targetFor(binding: Binding): EditTarget | undefined {\n const { store } = this.ctx;\n const entityUrn = store.entityFor(binding.scope);\n if (!entityUrn) return undefined;\n const urn = binding.element.getAttribute(urnAttribute(binding.entry)) ?? undefined;\n return {\n entityUrn,\n entry: binding.entry,\n name: binding.name,\n sortOrder: binding.sortOrder,\n urn: urn && store.get(urn) ? urn : undefined,\n anchor: binding.element,\n binding,\n };\n }\n\n open(target: EditTarget): void {\n // Editing starts from the latest, so a preview of an older version of this item ends.\n this.view.stopPreview(target);\n const visible = target.binding && target.binding.element.getClientRects().length > 0;\n // In place only where the item's component renders the element's content (not a section or switch).\n const ownsChildren = target.binding ? target.entry.component?.(target.binding.element).ownsChildren !== false : false;\n if (target.urn && target.entry.surface === 'inline' && target.binding && visible && ownsChildren) {\n this.openInline(target);\n } else {\n // A create starts from the page's placeholder, even when its element is not visible (such as the head).\n const placeholder = !target.urn && target.binding ? target.entry.fromPlaceholder?.(target.binding.element) : undefined;\n void this.openForm(visible ? target : { ...target, binding: undefined, anchor: target.anchor }, placeholder);\n }\n }\n\n private openInline(target: EditTarget): void {\n this.close();\n const { store, pending, host, popover } = this.ctx;\n const { entry } = target;\n const element = target.binding!.element;\n const stored = store.get(target.urn!)!;\n const value = (pending.getEdit(target.urn!)?.value ?? valueOf(entry, stored.item)) as { value?: unknown };\n const session = new InlineEdit(element, String(value.value ?? ''), host, {\n input: () => this.setPending(target, entry.read!(element)),\n send: () => void this.save(target),\n revert: () => this.revert(target),\n blurred: () => this.close(),\n });\n this.active = { target, session };\n mark(element, 'editing');\n popover.show(element, entry.label, `${target.name} #${target.sortOrder}`, session.hint, {\n send: () => void this.save(target),\n revert: () => this.revert(target),\n });\n popover.setIssues(entry.validate(entry.read!(element)));\n this.offerHistory(target);\n }\n\n /** Secondary actions for an existing item: history, moving it, and reordering its list. */\n private offerHistory(target: EditTarget): void {\n const { hooks } = this.ctx;\n this.ctx.popover.setNameAction(() => hooks.showItem(target));\n const urn = target.urn;\n if (!urn || target.fromVersion) {\n this.ctx.popover.setExtras([]);\n return;\n }\n const binding = target.binding;\n const actions: ExtraAction[] = [\n {\n label: 'History',\n icon: 'history',\n run: () => {\n this.close();\n hooks.openHistory({ entityUrn: target.entityUrn, entry: target.entry, name: target.name, sortOrder: target.sortOrder, urn });\n },\n },\n ];\n if (binding && hooks.canReorder(binding)) {\n actions.push(\n { label: 'Move up', icon: 'arrow-up', menu: true, run: () => hooks.moveBy(binding, -1) },\n { label: 'Move down', icon: 'arrow-down', menu: true, run: () => hooks.moveBy(binding, 1) },\n { label: 'Reorder\u2026', icon: 'list-ordered', menu: true, run: () => hooks.reorder(binding) },\n );\n }\n actions.push({ label: 'Move or rename\u2026', icon: 'pencil-line', menu: true, run: () => hooks.relocate(target) });\n this.ctx.popover.setExtras(actions);\n }\n\n /** `placeholder`: the starting value of a create, read from its page element. */\n async openForm(target: EditTarget, placeholder?: Value): Promise<void> {\n this.close();\n const { store, pending, popover, toolbar } = this.ctx;\n const { entry } = target;\n const form = entry.form;\n if (!form) return;\n\n let value: Value;\n if (target.urn) {\n const base = await this.baseValue(target);\n if (!base) return;\n value = (target.fromVersion ? undefined : pending.getEdit(target.urn)?.value) ?? base;\n } else {\n if (store.itemAt(target.entityUrn, entry, target.name, target.sortOrder)) {\n toolbar.showMessage(`An item already exists at ${target.name} #${target.sortOrder}.`);\n return;\n }\n value =\n pending.getCreate(createKey({ ...target, type: entry.type }))?.value ??\n placeholder ??\n (target.binding ? entry.fromPlaceholder?.(target.binding.element) : undefined) ??\n entry.defaults();\n }\n\n this.active = { target, session: undefined };\n if (target.binding) mark(target.binding.element, 'editing');\n const values = form.toForm(value);\n popover.showForm(\n target.anchor,\n target.fromVersion ? `${entry.label}, from an older version` : target.urn ? entry.label : `New ${entry.label.toLowerCase()}`,\n `${target.name} #${target.sortOrder}`,\n form.fields,\n values,\n {\n input: (current) => this.onFormInput(target, current),\n send: () => void this.save(target),\n revert: () => this.revert(target),\n },\n entry.surface === 'panel',\n );\n popover.setDescription(this.describeForm(target, values));\n popover.setIssues(entry.validate(value));\n this.offerHistory(target);\n // The older version is the edit, before anything is typed.\n if (target.fromVersion) this.setPending(target, value);\n document.addEventListener('pointerdown', this.onPointerDown, true);\n }\n\n /** The form's own note, plus a warning when a new item would go live immediately. */\n private describeForm(target: EditTarget, values: FormValues): string {\n const notes = [target.entry.form?.describe?.(values) ?? ''];\n if (!target.urn && isLive(this.ctx.store.view(target.entityUrn)?.status)) {\n notes.push('This content is published, so a new item is live as soon as it is saved.');\n }\n return notes.filter(Boolean).join(' ');\n }\n\n /** The value an edit starts from: the item's, or its source for a view-rendered type. */\n private async baseValue(target: EditTarget): Promise<Value | undefined> {\n const { store, sources, transport, feedback } = this.ctx;\n const urn = target.urn!;\n // Items with no element (head, JSON, outline rows) are found through the view.\n const stored = store.get(urn) ?? store.itemAt(target.entityUrn, target.entry, target.name, target.sortOrder);\n if (!stored || stored.item.urn !== urn) return undefined;\n if (!target.entry.renderedByView) return valueOf(target.entry, stored.item);\n try {\n const source = sources.get(urn) ?? valueOf(target.entry, await transport.read(target.entry, urn));\n sources.set(urn, source);\n return source;\n } catch (error) {\n void feedback.report(error, 'load the source', () => void this.openForm(target));\n return undefined;\n }\n }\n\n close(): void {\n const active = this.active;\n if (!active) return;\n this.active = undefined;\n document.removeEventListener('pointerdown', this.onPointerDown, true);\n active.session?.close();\n this.ctx.popover.hide();\n // Re-render: in-place editing left raw text in the element.\n const binding = active.target.binding;\n if (this.view.isEditing && binding?.element.isConnected) this.view.show(binding);\n }\n\n private onFormInput(target: EditTarget, values: FormValues): void {\n const { popover } = this.ctx;\n const form = target.entry.form;\n if (!form) return;\n popover.setDescription(this.describeForm(target, values));\n const value = form.fromForm(values);\n if (typeof value === 'string') {\n popover.setError(value);\n popover.setIssues([]);\n return;\n }\n popover.setError('');\n // Chosen image files are checked as soon as they are picked.\n const fileIssues = target.entry.type === 'image' ? imageFileIssues(popover.files()) : [];\n popover.setIssues([...target.entry.validate(value), ...fileIssues]);\n this.setPending(target, value);\n }\n\n /** Records an unsaved value and previews it everywhere the item is shown. */\n setPending(target: EditTarget, input: Value): void {\n const { store, sources, pending, popover } = this.ctx;\n const { entry } = target;\n let value = input;\n if (target.urn) {\n const stored = store.get(target.urn) ?? store.itemAt(target.entityUrn, entry, target.name, target.sortOrder);\n // Fields the form does not edit (an image's files) carry over from the version.\n value = withCarried(entry, stored?.item, input);\n // From an older version, the change is against the item as it is now: saving that version unchanged restores it.\n const current = target.fromVersion ? store.itemAt(target.entityUrn, entry, target.name, target.sortOrder) : stored;\n const base = entry.renderedByView ? sources.get(current?.item.urn ?? target.urn) : current?.item;\n if (base && sameValue(entry, value, base)) {\n pending.clear(target.urn);\n } else {\n pending.set({\n kind: 'edit',\n type: entry.type,\n urn: target.urn,\n entityUrn: target.entityUrn,\n name: target.name,\n sortOrder: target.sortOrder,\n value,\n ...(target.fromVersion ? { fromVersion: true } : {}),\n });\n }\n } else {\n pending.set({ kind: 'create', type: entry.type, entityUrn: target.entityUrn, name: target.name, sortOrder: target.sortOrder, value });\n }\n this.view.reshow(target);\n if (target.entry.surface === 'inline' && this.active?.session) popover.setIssues(entry.validate(value));\n }\n\n revert(target: EditTarget): void {\n this.ctx.pending.clear(target.urn ?? createKey({ ...target, type: target.entry.type }));\n this.close();\n this.view.reshow(target);\n }\n}\n", "// Turns a failure into something the user can act on. Each kind needs a\n// different response, so they must stay distinguishable.\n\nimport { isBaackApiError, type BaackApiError } from '@baack-software/baack-ts-client';\nimport { EntityMismatchError, NotLiveError } from '../core/scoped-views.ts';\n\nexport type FailureKind = 'unauthorized' | 'forbidden' | 'not-found' | 'not-live' | 'conflict' | 'mismatch' | 'network' | 'failed';\n\nexport interface Failure {\n kind: FailureKind;\n message: string;\n /** The API's JSON error body, pretty-printed, for a collapsed \"Debug\" section. */\n debug?: string;\n}\n\n/**\n * The API answers 404, not 401 or 403, when the session or a permission is\n * missing. So for a 404, pass `hasSession` from a fresh client context read:\n * without a session it is treated as an ended session.\n */\nexport function describeFailure(error: unknown, action: string, hasSession?: boolean): Failure {\n if (isBaackApiError(error)) {\n const debug = debugText(error);\n return debug === undefined ? describeApiError(error, action, hasSession) : { ...describeApiError(error, action, hasSession), debug };\n }\n return describeOther(error, action);\n}\n\nfunction describeApiError(error: BaackApiError, action: string, hasSession: boolean | undefined): Failure {\n if (error.isUnauthorized || (error.isNotFound && hasSession === false)) {\n return { kind: 'unauthorized', message: `Your session has ended. Log in again to ${action}. Your changes are kept.` };\n }\n if (error.isForbidden) {\n return { kind: 'forbidden', message: `You don't have permission to ${action}.` };\n }\n if (error.isNotFound) {\n return { kind: 'not-found', message: `This item no longer exists, or you don't have permission to ${action}.` };\n }\n if (error.isConflict) {\n return { kind: 'conflict', message: `Someone else changed this since you opened it. Reload to see their version.` };\n }\n const { detail } = error;\n return {\n kind: 'failed',\n message: `Couldn't ${action} (HTTP ${error.status})${detail ? `: ${detail.replace(/\\.$/, '')}` : ''}. Try again.`,\n };\n}\n\nfunction describeOther(error: unknown, action: string): Failure {\n if (error instanceof NotLiveError) {\n return { kind: 'not-live', message: 'This content is not published yet, so it has no live version to show. Show the latest drafts to edit it.' };\n }\n if (error instanceof EntityMismatchError) {\n const { language } = error.received;\n return {\n kind: 'mismatch',\n message: `Couldn't ${action}: Baack returned a different language version (${language}) instead of the content on this page, so it can't be edited here. Reload the page and try again.`,\n };\n }\n if (error instanceof TypeError) {\n return { kind: 'network', message: `Couldn't reach Baack to ${action}. Check your connection and try again.` };\n }\n return { kind: 'failed', message: `Couldn't ${action}: ${error instanceof Error ? error.message : String(error)}` };\n}\n\n/**\n * What was sent and what came back, for the \"Debug\" section: the request's\n * method, path and JSON body, then the API's JSON error body. Undefined when\n * the response had no JSON body.\n */\nfunction debugText(error: BaackApiError): string | undefined {\n const body = error.json();\n if (body === undefined) return undefined;\n const pretty = (text: string) => {\n try {\n return JSON.stringify(JSON.parse(text), null, 2);\n } catch {\n return text;\n }\n };\n const path = (() => {\n try {\n return new URL(error.url).pathname;\n } catch {\n return error.url;\n }\n })();\n const request = `Request: ${error.method} ${path}${error.requestBody ? `\\n${pretty(error.requestBody)}` : ''}`;\n return `${request}\\n\\nResponse: ${error.status}\\n${JSON.stringify(body, null, 2)}`;\n}\n", "// Turning failures into messages, and the login prompt. A 404 can mean the\n// session ended, so the client context is asked which it is.\n\nimport { isBaackApiError } from '@baack-software/baack-ts-client';\nimport type { Transport } from './core/transport.ts';\nimport { describeFailure, type Failure } from './ui/messages.ts';\nimport type { Toolbar } from './ui/toolbar.ts';\n\nexport class Feedback {\n private readonly transport: Transport;\n private readonly toolbar: () => Toolbar;\n private retry: (() => void) | undefined;\n\n /** `toolbar` is read lazily: the toolbar is built with this object's retry. */\n constructor(transport: Transport, toolbar: () => Toolbar) {\n this.transport = transport;\n this.toolbar = toolbar;\n }\n\n /** Called by the login prompt's \"try again\". */\n retryAfterLogin(): void {\n this.retry?.();\n }\n\n async report(error: unknown, action: string, retry: () => void): Promise<void> {\n const failure = await this.describe(error, action);\n this.toolbar().showMessage(failure.message, false, failure.debug);\n if (failure.kind === 'unauthorized') void this.promptLogin(failure.message, retry);\n }\n\n async describe(error: unknown, action: string): Promise<Failure> {\n let hasSession: boolean | undefined;\n if (isBaackApiError(error) && error.isNotFound) {\n try {\n hasSession = (await this.transport.clientContext()).hasSession === true;\n } catch (contextError) {\n console.warn('Baack editor: could not read the client context to explain a 404', contextError);\n }\n }\n return describeFailure(error, action, hasSession);\n }\n\n async promptLogin(message: string, retry: () => void): Promise<void> {\n this.retry = retry;\n let iframeSrc: string | null | undefined;\n try {\n iframeSrc = (await this.transport.clientContext()).loginIframeSrc;\n } catch (error) {\n console.warn('Baack editor: could not read the client context for the login prompt', error);\n }\n this.toolbar().showLogin(message, iframeSrc);\n }\n}\n", "// A word diff for showing what changed between two versions. Text only: the\n// result is rendered as text nodes, never markup.\n\nexport interface DiffPart {\n /** `increase` and `decrease` mark a summary's percentage change, for values that cannot be diffed as words. */\n kind: 'same' | 'added' | 'removed' | 'increase' | 'decrease' | 'arrow';\n text: string;\n}\n\n/**\n * The change from `before` to `after` as a percentage of `before`'s size.\n * From zero, any rise is +100% and any fall -100%. Crossing zero counts the\n * whole distance against the starting value: 20 to -20 is -200%.\n */\nexport function percentChange(before: number, after: number): number {\n if (before === after) return 0;\n if (before === 0) return after > 0 ? 100 : -100;\n return ((after - before) / Math.abs(before)) * 100;\n}\n\n/** \"+96%\" or \"\u2212200%\", at most one decimal place. */\nexport function formatPercent(percent: number): string {\n const size = new Intl.NumberFormat('en-GB', { maximumFractionDigits: 1 }).format(Math.abs(percent));\n return `${percent > 0 ? '+' : percent < 0 ? '\u2212' : ''}${size}%`;\n}\n\nconst MAX_TOKENS = 2000;\n\nexport function diffWords(before: string, after: string): DiffPart[] {\n if (before === after) return [{ kind: 'same', text: after }];\n const a = before.split(/(\\s+)/).filter(Boolean);\n const b = after.split(/(\\s+)/).filter(Boolean);\n // Long values: show a plain replacement rather than spend time on the table.\n if (a.length * b.length > MAX_TOKENS * MAX_TOKENS) {\n return [\n { kind: 'removed', text: before },\n { kind: 'added', text: after },\n ];\n }\n // Longest common subsequence, from the end.\n const table: number[][] = Array.from({ length: a.length + 1 }, () => new Array<number>(b.length + 1).fill(0));\n for (let i = a.length - 1; i >= 0; i -= 1) {\n for (let j = b.length - 1; j >= 0; j -= 1) {\n table[i]![j] = a[i] === b[j] ? table[i + 1]![j + 1]! + 1 : Math.max(table[i + 1]![j]!, table[i]![j + 1]!);\n }\n }\n const parts: DiffPart[] = [];\n const push = (kind: DiffPart['kind'], text: string) => {\n const last = parts.at(-1);\n if (last?.kind === kind) last.text += text;\n else parts.push({ kind, text });\n };\n let i = 0;\n let j = 0;\n while (i < a.length && j < b.length) {\n if (a[i] === b[j]) {\n push('same', a[i]!);\n i += 1;\n j += 1;\n } else if (table[i + 1]![j]! >= table[i]![j + 1]!) {\n push('removed', a[i]!);\n i += 1;\n } else {\n push('added', b[j]!);\n j += 1;\n }\n }\n while (i < a.length) push('removed', a[i++]!);\n while (j < b.length) push('added', b[j++]!);\n return parts;\n}\n", "// DOM events for host code and framework islands. Dispatched on `document`.\n\nimport type { ItemType } from './registry.ts';\n\nexport interface ItemUpdatedDetail {\n entityUrn: string;\n /** Absent when the item was just created. */\n oldUrn?: string;\n newUrn: string;\n type: ItemType;\n /** The item as the API returned it. */\n value: unknown;\n}\n\nexport interface ItemPublishedDetail {\n entityUrn: string;\n /** The version now live. */\n urn: string;\n type: ItemType;\n}\n\nexport interface EntityStateDetail {\n entityUrn: string;\n status: string;\n previous: string | undefined;\n}\n\ndeclare global {\n interface DocumentEventMap {\n 'baack:item-updated': CustomEvent<ItemUpdatedDetail>;\n 'baack:item-published': CustomEvent<ItemPublishedDetail>;\n 'baack:entity-state': CustomEvent<EntityStateDetail>;\n 'baack:entity-published': CustomEvent<{ entityUrn: string }>;\n }\n}\n\nexport function dispatchItemUpdated(detail: ItemUpdatedDetail): void {\n document.dispatchEvent(new CustomEvent('baack:item-updated', { detail }));\n}\n\nexport function dispatchItemPublished(detail: ItemPublishedDetail): void {\n document.dispatchEvent(new CustomEvent('baack:item-published', { detail }));\n}\n\nexport function dispatchEntityState(detail: EntityStateDetail): void {\n document.dispatchEvent(new CustomEvent('baack:entity-state', { detail }));\n}\n\nexport function dispatchEntityPublished(entityUrn: string): void {\n document.dispatchEvent(new CustomEvent('baack:entity-published', { detail: { entityUrn } }));\n}\n", "// A small form for the editor's own panels (creating an entity, adding an\n// item). Item values use the popover's form; this is for everything else.\n\nimport { el, selectBox } from './host.ts';\n\nexport interface SimpleField {\n key: string;\n label: string;\n value: string;\n /** Offer a choice instead of free text. */\n options?: { value: string; label: string }[];\n}\n\nexport class SimpleForm {\n readonly element: HTMLFormElement;\n private readonly inputs = new Map<string, HTMLInputElement | HTMLSelectElement>();\n private readonly submit: HTMLButtonElement;\n private readonly error: HTMLElement;\n private readonly submitLabel: string;\n private readonly onCancel: (() => void) | undefined;\n\n /** `onCancel` runs after Cancel closes the form. */\n constructor(\n title: string,\n fields: SimpleField[],\n submitLabel: string,\n onSubmit: (values: Record<string, string>) => void,\n onCancel?: () => void,\n ) {\n this.submitLabel = submitLabel;\n this.onCancel = onCancel;\n this.element = el('form', 'simple-form');\n this.element.append(el('div', 'title', title));\n for (const field of fields) {\n const label = el('label', 'field');\n let input: HTMLInputElement | HTMLSelectElement;\n if (field.options) {\n input = el('select');\n for (const option of field.options) input.append(Object.assign(el('option', '', option.label), { value: option.value }));\n } else {\n input = el('input');\n input.type = 'text';\n }\n input.name = field.key;\n input.value = field.value;\n label.append(el('span', 'caption', field.label), input instanceof HTMLSelectElement ? selectBox(input) : input);\n this.inputs.set(field.key, input);\n this.element.append(label);\n }\n this.error = el('p', 'error');\n this.error.setAttribute('role', 'alert');\n this.submit = el('button', 'primary', submitLabel);\n this.submit.type = 'submit';\n const cancel = el('button', '', 'Cancel');\n cancel.type = 'button';\n cancel.addEventListener('click', () => this.cancel());\n const actions = el('div', 'actions');\n actions.append(cancel, this.submit);\n this.element.append(this.error, actions);\n this.element.addEventListener('submit', (event) => {\n event.preventDefault();\n if (!this.submit.disabled) onSubmit(this.values());\n });\n }\n\n /** Removes the form, as its Cancel button does, and tells its container (a `cancel` event). */\n cancel(): void {\n this.element.dispatchEvent(new Event('cancel'));\n this.element.remove();\n this.onCancel?.();\n }\n\n values(): Record<string, string> {\n return Object.fromEntries([...this.inputs].map(([key, input]) => [key, input.value.trim()]));\n }\n\n /** Disables the button while a request is in flight, so it cannot be sent twice. */\n setBusy(busy: boolean, label = 'Working\u2026'): void {\n this.submit.disabled = busy;\n this.submit.textContent = busy ? label : this.submitLabel;\n }\n\n setError(message: string): void {\n this.error.textContent = message;\n }\n}\n", "// Saving unsaved work: one change, all of an entity's changes, or every empty\n// slot. Each save creates a version; the latest view is re-read afterwards so\n// templates and renderings update.\n\nimport { dispatchItemUpdated } from './core/events.ts';\nimport { createKey, pendingKey, type Pending, type PendingEdit } from './core/pending.ts';\nimport { toRepresentation, urnAttribute, type ContentItem, type TypeEntry } from './core/registry.ts';\nimport type { Editing } from './editing.ts';\nimport { parseTimestamp as parseUtc } from '@baack-software/baack-ts-components/format';\nimport { isLive, reviewAction, type EditTarget, type EditorContext } from './targets.ts';\nimport { SimpleForm } from './ui/form.ts';\nimport { mark } from './ui/marker.ts';\nimport type { PageView } from './view.ts';\nimport { formatPercent, percentChange, type DiffPart } from './core/diff.ts';\n\n/** Someone saved a newer draft of the item since this edit began. Nothing was saved. */\nexport class ConflictError extends Error {\n readonly change: PendingEdit;\n readonly newest: ContentItem;\n\n constructor(change: PendingEdit, newest: ContentItem) {\n super('a newer draft of this item has been saved');\n this.change = change;\n this.newest = newest;\n }\n}\n\n/** A value as a short line, for comparing two versions. */\nexport function summarise(entry: TypeEntry, value: object): string {\n if (!entry.form) return JSON.stringify(value);\n return Object.values(entry.form.toForm(value as never))\n .map((field) => (typeof field === 'boolean' ? (field ? 'on' : 'off') : field))\n .filter((field) => field !== '')\n .join(' \u00B7 ');\n}\n\n/**\n * A change between values that cannot be diffed as words: \"was \u2192 now\", with\n * a money change in one currency as a percentage, up or down.\n */\nexport function summariseChange(entry: TypeEntry, before: ContentItem, after: ContentItem): DiffPart[] {\n const parts: DiffPart[] = [\n { kind: 'same', text: summarise(entry, before) },\n { kind: 'arrow', text: '\u2192' },\n { kind: 'same', text: summarise(entry, after) },\n ];\n const delta = moneyDelta(before, after);\n return delta ? [...parts, { kind: 'same', text: ' ' }, delta] : parts;\n}\n\n/** Amounts are integer minor units, compared only in the same currency. */\nfunction moneyDelta(before: ContentItem, after: ContentItem): DiffPart | undefined {\n const was = before as { unitValue?: unknown; currencyCode?: unknown };\n const now = after as { unitValue?: unknown; currencyCode?: unknown };\n if (typeof was.unitValue !== 'number' || typeof now.unitValue !== 'number' || was.currencyCode !== now.currencyCode) return undefined;\n const percent = percentChange(was.unitValue, now.unitValue);\n if (percent === 0) return undefined;\n return { kind: percent > 0 ? 'increase' : 'decrease', text: formatPercent(percent) };\n}\n\nexport class Saving {\n private readonly ctx: EditorContext;\n private readonly view: PageView;\n private readonly editing: () => Editing;\n private readonly inFlight = new Set<string>();\n\n /** `editing` is read lazily: it is built with this object's save. */\n constructor(ctx: EditorContext, view: PageView, editing: () => Editing) {\n this.ctx = ctx;\n this.view = view;\n this.editing = editing;\n }\n\n /** Saves the change for a target, from its open form or its unsaved value. */\n async save(target: EditTarget): Promise<void> {\n const { pending, popover, feedback } = this.ctx;\n const editing = this.editing();\n const key = target.urn ?? createKey({ ...target, type: target.entry.type });\n if (this.inFlight.has(key)) return;\n const isActive = () => editing.current?.target === target;\n\n // New image files: a new version first, then uploads (rule 5).\n if (isActive() && target.entry.type === 'image') {\n const files = popover.files() as Map<'DEFAULT' | 'MEDIUM' | 'LARGE', File>;\n if (files.size > 0) {\n this.inFlight.add(key);\n try {\n await this.ctx.hooks.saveImage(target, files);\n } finally {\n this.inFlight.delete(key);\n }\n return;\n }\n }\n\n // A form showing an invalid value must not save an older valid one.\n if (isActive() && !editing.current!.session && target.entry.form) {\n const current = target.entry.form.fromForm(popover.values());\n if (typeof current === 'string') {\n popover.setError(current);\n return;\n }\n // A create opened from a placeholder can be saved unchanged.\n if (!target.urn || !pending.getEdit(target.urn)) editing.setPending(target, current);\n }\n const change = target.urn ? pending.getEdit(target.urn) : pending.getCreate(key);\n if (!change) {\n if (isActive()) editing.close();\n return;\n }\n if (target.entry.validate(change.value).some((issue) => issue.level === 'error')) return;\n\n this.inFlight.add(key);\n popover.setSending(true);\n popover.setError('');\n try {\n await this.commit(change);\n if (isActive()) editing.close();\n await this.view.refresh(target.entityUrn);\n } catch (error) {\n if (error instanceof ConflictError) {\n this.showConflict(error, isActive() ? target.anchor : this.ctx.toolbar.modeButton);\n return;\n }\n if (error instanceof StoredElsewhereError) {\n // Saved all the same: nothing is left to send, and the page and Items show what the API stored.\n if (isActive()) editing.close();\n this.ctx.toolbar.showMessage(error.message);\n await this.view.refresh(target.entityUrn);\n return;\n }\n const retry = () => void this.save(target);\n if (isActive()) {\n const failure = await feedback.describe(error, target.urn ? 'save this change' : 'create this item');\n popover.setError(failure.message, failure.debug);\n if (failure.kind === 'unauthorized') void feedback.promptLogin(failure.message, retry);\n } else {\n void feedback.report(error, 'save this change', retry);\n }\n } finally {\n this.inFlight.delete(key);\n popover.setSending(false);\n }\n }\n\n /** Saves one unsaved change. Throws on failure, leaving it unsaved. */\n async commit(change: Exclude<Pending, { kind: 'move' }>): Promise<ContentItem> {\n const { store, transport, pending } = this.ctx;\n const entry = this.ctx.entry(change.type);\n if (change.kind === 'edit') {\n // Never draft from an old version by accident: if someone saved a newer one, stop and show both.\n if (!change.fromVersion) {\n const newest = (await transport.history(entry, change.urn)).history[0];\n if (newest?.urn && newest.urn !== change.urn) throw new ConflictError(change, newest);\n }\n const stored = store.get(change.urn) ?? store.itemAt(change.entityUrn, entry, change.name, change.sortOrder);\n if (!stored || stored.item.urn !== change.urn) throw new Error('the item has changed since this edit was made');\n const saved = await transport.update(entry, change.urn, toRepresentation(entry, stored.item, change.value, change.entityUrn));\n if (!saved?.urn) throw new Error('the API returned no URN for the new version');\n this.applySaved(entry, change.urn, saved);\n dispatchItemUpdated({ entityUrn: change.entityUrn, oldUrn: change.urn, newUrn: saved.urn, type: entry.type, value: saved });\n checkSlot(saved, stored.item);\n return saved;\n }\n // Check occupancy first: a create at an occupied slot would draft over the item there.\n if (store.itemAt(change.entityUrn, entry, change.name, change.sortOrder)) {\n pending.clear(pendingKey(change));\n throw new Error(`an item already exists at ${change.name} #${change.sortOrder}`);\n }\n const slot = { name: change.name, sortOrder: change.sortOrder } as ContentItem;\n const saved = await transport.create(entry, toRepresentation(entry, slot, change.value, change.entityUrn));\n if (!saved?.urn) throw new Error('the API returned no URN for the new item');\n pending.clear(pendingKey(change));\n dispatchItemUpdated({ entityUrn: change.entityUrn, newUrn: saved.urn, type: entry.type, value: saved });\n checkSlot(saved, slot);\n return saved;\n }\n\n /** Every element showing the old version now shows the new one, URN included. */\n private applySaved(entry: TypeEntry, oldUrn: string, saved: ContentItem): void {\n const { discovery, store, pending, sources, toolbar } = this.ctx;\n const editing = this.editing();\n const elements = discovery\n .all()\n .filter((binding) => binding.entry === entry && binding.element.getAttribute(urnAttribute(entry)) === oldUrn);\n store.replace(oldUrn, saved);\n pending.clear(oldUrn);\n sources.delete(oldUrn);\n const editingBinding = editing.current?.target.binding;\n if (editingBinding && elements.includes(editingBinding)) editing.close();\n for (const binding of elements) {\n if (entry.renderedByView) {\n // The response is source; the rendering arrives with the re-read.\n binding.element.setAttribute(urnAttribute(entry), saved.urn!);\n } else {\n this.ctx.live.render(binding, saved);\n }\n mark(binding.element, 'editable');\n }\n toolbar.showMessage('');\n }\n\n /** Saves unsaved changes in order, for one entity or all. Stops when the session has ended. */\n async saveAll(entityUrn?: string): Promise<void> {\n const { pending, feedback, toolbar } = this.ctx;\n const queue = pending\n .all()\n .filter((p) => (entityUrn === undefined || p.entityUrn === entityUrn) && !(p.kind === 'edit' && p.stale));\n // Queued moves run as their plans, in order.\n for (const planId of new Set(queue.flatMap((p) => (p.kind === 'move' ? [p.planId] : [])))) {\n await this.ctx.hooks.runPlan(planId);\n }\n await Promise.all([...new Set(queue.map((p) => p.entityUrn))].map((urn) => this.view.loadScope(urn)));\n const failures: string[] = [];\n const debug: string[] = [];\n const touched = new Set<string>();\n let saved = 0;\n for (const change of queue) {\n if (change.kind === 'move') continue;\n try {\n await this.commit(change);\n saved += 1;\n touched.add(change.entityUrn);\n } catch (error) {\n if (error instanceof StoredElsewhereError) {\n saved += 1;\n touched.add(change.entityUrn);\n failures.push(`${change.name} #${change.sortOrder}: ${error.message}`);\n continue;\n }\n if (error instanceof ConflictError) {\n // Held until someone chooses which value wins.\n this.ctx.pending.set({ ...error.change, stale: true });\n failures.push(`${change.name} #${change.sortOrder}: a newer draft was saved; use Resolve.`);\n continue;\n }\n const failure = await feedback.describe(error, 'save this change');\n if (failure.kind === 'unauthorized') {\n void feedback.promptLogin(failure.message, () => void this.saveAll(entityUrn));\n break;\n }\n failures.push(`${change.name} #${change.sortOrder}: ${failure.message}`);\n if (failure.debug) debug.push(`${change.name} #${change.sortOrder}:\\n${failure.debug}`);\n }\n }\n for (const urn of touched) await this.view.refresh(urn);\n // Saved to one entity: its review is the next step.\n const [only] = touched;\n toolbar.showMessage(\n failures.length > 0 ? `Saved ${saved}. Not saved: ${failures.join(' ')}` : `Saved ${saved} ${saved === 1 ? 'change' : 'changes'}.`,\n failures.length === 0,\n debug.join('\\n\\n') || undefined,\n failures.length === 0 && saved > 0 && touched.size === 1 && only ? reviewAction(this.ctx, only) : undefined,\n );\n }\n\n /** For an edit held as \"based on an older version\": compare it with the newest draft and choose. */\n async resolve(change: PendingEdit, anchor: HTMLElement): Promise<void> {\n const entry = this.ctx.entry(change.type);\n try {\n const newest = (await this.ctx.transport.history(entry, change.urn)).history[0];\n if (newest?.urn && newest.urn !== change.urn) {\n this.showConflict(new ConflictError(change, newest), anchor);\n } else {\n // Nothing newer after all: it can be saved as it is.\n this.ctx.pending.set({ ...change, stale: false });\n }\n } catch (error) {\n void this.ctx.feedback.report(error, 'check this item', () => void this.resolve(change, anchor));\n }\n }\n\n /** Shows both values and lets the author choose; nothing is saved without a choice. */\n private showConflict(conflict: ConflictError, anchor: HTMLElement): void {\n const { popover } = this.ctx;\n const { change, newest } = conflict;\n const entry = this.ctx.entry(change.type);\n const when = newest.createdTimestamp ? new Date(parseUtc(newest.createdTimestamp)).toLocaleString() : 'recently';\n const done = () => {\n popover.hide();\n this.editing().close();\n };\n popover.showChoices(\n anchor,\n 'A newer draft was saved',\n `${change.name} #${change.sortOrder}`,\n [\n { label: 'Yours (not saved)', text: summarise(entry, change.value) },\n { label: `The newer draft, saved ${when}`, text: summarise(entry, newest) },\n ],\n 'Nothing has been saved. Choose which value to keep.',\n [\n { label: 'Cancel', run: done },\n {\n label: 'Keep theirs',\n run: () => {\n this.ctx.pending.clear(change.urn);\n done();\n void this.view.refresh(change.entityUrn);\n },\n },\n { label: 'Save yours on top', primary: true, run: () => void this.saveOnTop(conflict, done) },\n ],\n );\n }\n\n /** Saves the author's value as a new draft on top of the newest one. */\n private async saveOnTop(conflict: ConflictError, done: () => void): Promise<void> {\n const { transport, pending, sources, feedback } = this.ctx;\n const { change, newest } = conflict;\n const entry = this.ctx.entry(change.type);\n try {\n const saved = await transport.update(entry, newest.urn!, toRepresentation(entry, newest, change.value, change.entityUrn));\n pending.clear(change.urn);\n sources.delete(change.urn);\n dispatchItemUpdated({ entityUrn: change.entityUrn, oldUrn: newest.urn!, newUrn: saved.urn!, type: entry.type, value: saved });\n done();\n await this.view.refresh(change.entityUrn);\n } catch (error) {\n void feedback.report(error, 'save this change', () => void this.saveOnTop(conflict, done));\n }\n }\n\n discardAll(entityUrn?: string): void {\n this.editing().close();\n const removed = this.ctx.pending.clearAll(entityUrn);\n for (const change of removed) {\n this.view.reshow({\n entityUrn: change.entityUrn,\n entry: this.ctx.entry(change.type),\n name: change.name,\n sortOrder: change.sortOrder,\n urn: change.kind === 'edit' ? change.urn : undefined,\n });\n }\n this.ctx.toolbar.showMessage(`Discarded ${removed.length} unsaved ${removed.length === 1 ? 'change' : 'changes'}.`, true);\n }\n\n /** On a published entity a new item is live as soon as it is created, so ask first. */\n confirmCreateAll(entityUrn: string, count: number): void {\n const { store } = this.ctx;\n if (!isLive(store.view(entityUrn)?.status)) {\n void this.createAll(entityUrn);\n return;\n }\n const form = new SimpleForm(\n `${this.ctx.entityTitle(entityUrn)} is published`,\n [],\n `Create ${count} ${count === 1 ? 'item' : 'items'} on the live site`,\n () => {\n panel.close();\n void this.createAll(entityUrn);\n },\n );\n form.element.insertBefore(\n Object.assign(document.createElement('p'), {\n className: 'hint',\n textContent: 'New items on a published entity are live as soon as they are created. Check the placeholders first.',\n }),\n form.element.querySelector('.error'),\n );\n const panel = this.ctx.panels.show(form.element, { entityUrn });\n }\n\n /** Creates every empty slot of an entity shown on the page, from its placeholder. Safe to run again. */\n async createAll(entityUrn: string): Promise<void> {\n const { store, pending, feedback, toolbar } = this.ctx;\n await this.view.refresh(entityUrn); // Occupancy is checked against the latest read.\n let created = 0;\n const failures: string[] = [];\n const debug: string[] = [];\n for (const binding of this.view.missingBindings(entityUrn)) {\n const { entry } = binding;\n if (store.itemAt(entityUrn, entry, binding.name, binding.sortOrder)) continue;\n const key = createKey({ entityUrn, type: entry.type, name: binding.name, sortOrder: binding.sortOrder });\n const value = pending.getCreate(key)?.value ?? entry.fromPlaceholder?.(binding.element) ?? entry.defaults();\n if (entry.form && typeof entry.form.fromForm(entry.form.toForm(value)) === 'string') {\n failures.push(`${binding.name}: its placeholder is not a valid ${entry.label.toLowerCase()}`);\n continue;\n }\n try {\n await this.commit({ kind: 'create', type: entry.type, entityUrn, name: binding.name, sortOrder: binding.sortOrder, value });\n created += 1;\n await this.view.refresh(entityUrn);\n } catch (error) {\n const failure = await feedback.describe(error, 'create this item');\n if (failure.kind === 'unauthorized') {\n void feedback.promptLogin(failure.message, () => void this.createAll(entityUrn));\n break;\n }\n failures.push(`${binding.name}: ${failure.message}`);\n if (failure.debug) debug.push(`${binding.name}:\\n${failure.debug}`);\n }\n }\n toolbar.showMessage(\n `Created ${created} ${created === 1 ? 'item' : 'items'}.${failures.length > 0 ? ` Not created: ${failures.join(' ')}` : ''}`,\n failures.length === 0,\n debug.join('\\n\\n') || undefined,\n );\n }\n}\n\n/**\n * The API must store an item at the name and sort order sent. When it does\n * not (a create that dropped `name`), the write still happened, so this\n * reports it without leaving anything to send again.\n */\nfunction checkSlot(saved: ContentItem, sent: Pick<ContentItem, 'name' | 'sortOrder'>): void {\n if (saved.name === sent.name && saved.sortOrder === sent.sortOrder) return;\n throw new StoredElsewhereError(\n `Saved, but the API stored it as \"${saved.name ?? ''}\" #${saved.sortOrder ?? '?'} instead of ${sent.name} #${sent.sortOrder}. ` +\n 'Do not save it again; this needs fixing in the API.',\n );\n}\n\n/** The write happened, at another name or sort order than sent. */\nexport class StoredElsewhereError extends Error {}\n", "// A change between two versions: a word diff (<ins>, <del>), or a summary line\n// with a percentage change marked up or down. All of it is text, never markup.\n\nimport type { DiffPart } from '../core/diff.ts';\nimport { el } from './host.ts';\n\nconst ELEMENTS: Record<Exclude<DiffPart['kind'], 'same'>, [tag: 'ins' | 'del' | 'span', className: string]> = {\n added: ['ins', ''],\n removed: ['del', ''],\n increase: ['span', 'delta up'],\n decrease: ['span', 'delta down'],\n arrow: ['span', 'arrow'],\n};\n\nexport function renderChange(value: DiffPart[] | string): HTMLElement {\n const box = el('div', 'change');\n if (typeof value === 'string') {\n box.textContent = value;\n return box;\n }\n for (const part of value) {\n if (part.kind === 'same') {\n box.append(part.text);\n continue;\n }\n const [tag, className] = ELEMENTS[part.kind];\n const element = el(tag, className, part.text);\n if (part.kind === 'arrow') element.setAttribute('aria-label', 'to');\n if (part.kind === 'increase' || part.kind === 'decrease') element.title = `${part.text.replace(/^[+\u2212]/, '')} ${part.kind}`;\n box.append(element);\n }\n return box;\n}\n", "// An item's history as sidebar levels (docs/plans/single-sidebar.md): the\n// Item level lists its versions, newest first, each with its change and a\n// preview toggle; choosing one drills into its Version level, which shows\n// the change against the one before and against live, one above the other,\n// and the version's actions.\n\nimport type { DiffPart } from '../core/diff.ts';\nimport { renderChange } from './change.ts';\nimport { icon } from './icons.ts';\nimport { button as makeButton, el, selectBox, variantOf } from './host.ts';\n\nexport interface HistoryAction {\n label: string;\n /** A toggle, such as the preview: shown pressed. */\n pressed?: boolean;\n disabled?: string | undefined;\n primary?: boolean;\n /** Shown as a destructive button: it deletes or discards. */\n destructive?: boolean;\n run(anchor: HTMLElement): void;\n}\n\nexport interface HistoryRowModel {\n when: string;\n /** UTC, for the tooltip. */\n whenUtc: string;\n live: boolean;\n /** What changed against the comparison version. */\n change: DiffPart[] | string;\n /** \"moved from #0 to #1\", \"renamed from \u2026\". */\n notes: string[];\n /** Drills into the version's level. */\n open(): void;\n preview: HistoryAction;\n /** Earlier drafts collapsed into this row. */\n collapsed: HistoryRowModel[];\n}\n\nexport interface VersionModel {\n when: string;\n whenUtc: string;\n /** \"live\", \"latest\". */\n marks: string[];\n notes: string[];\n changes: { label: string; change: DiffPart[] | string }[];\n actions: HistoryAction[];\n}\n\n/** The Item level's body: what to compare with, the versions, and older ones on request. */\nexport class ItemHistoryView {\n readonly element: HTMLElement;\n private readonly status: HTMLElement;\n private readonly list: HTMLElement;\n private readonly more: HTMLButtonElement;\n private readonly compare: HTMLSelectElement;\n\n constructor(onMore: () => void, onCompare: (against: 'live' | 'previous') => void) {\n this.element = el('div', 'level-item');\n const compareLabel = el('label', 'field');\n this.compare = el('select');\n this.compare.append(\n Object.assign(el('option', '', 'Compare with the live version'), { value: 'live' }),\n Object.assign(el('option', '', 'Compare with the previous version'), { value: 'previous' }),\n );\n this.compare.addEventListener('change', () => onCompare(this.compare.value as 'live' | 'previous'));\n compareLabel.append(el('span', 'caption', 'Show changes'), selectBox(this.compare));\n\n this.status = el('p', 'hint');\n this.status.setAttribute('role', 'status');\n this.list = el('ol', 'rows history-rows');\n this.list.setAttribute('aria-label', 'Versions, newest first');\n this.more = el('button', '', 'Load older versions');\n this.more.type = 'button';\n this.more.hidden = true;\n this.more.addEventListener('click', onMore);\n this.element.append(compareLabel, this.status, this.list, this.more);\n }\n\n setStatus(text: string): void {\n this.status.textContent = text;\n }\n\n render(rows: HistoryRowModel[], hasMore: boolean): void {\n // Open groups of earlier drafts stay open across a refresh.\n const expanded = new Set(\n [...this.list.querySelectorAll<HTMLElement>('li.history-row:has(> button[aria-expanded=\"true\"])')].map((row) => row.dataset['when']),\n );\n this.list.replaceChildren(...rows.map((row) => this.row(row, expanded)));\n this.more.hidden = !hasMore;\n }\n\n private row(row: HistoryRowModel, expanded: Set<string | undefined>): HTMLElement {\n const item = el('li', 'row history-row');\n item.dataset['when'] = row.whenUtc;\n const head = el('button', 'row-main');\n head.type = 'button';\n head.dataset['row'] = '';\n const time = el('span', 'row-name', row.when);\n time.title = `${row.whenUtc} UTC`;\n head.append(time);\n if (row.live) head.append(el('span', 'status status-up-to-date', 'live'));\n for (const note of row.notes) head.append(el('span', 'status note', note));\n const chevron = el('span', 'stack-chevron');\n chevron.append(icon('chevron-right'));\n chevron.setAttribute('aria-hidden', 'true');\n head.append(chevron);\n head.addEventListener('click', () => row.open());\n const actions = el('div', 'actions');\n actions.append(actionButton(row.preview));\n item.append(head, renderChange(row.change), actions);\n if (row.collapsed.length > 0) {\n const toggle = makeButton(`${row.collapsed.length} earlier ${row.collapsed.length === 1 ? 'draft' : 'drafts'}`, 'ghost', 'xs');\n const open = expanded.has(row.whenUtc);\n toggle.setAttribute('aria-expanded', String(open));\n const nested = el('ol', 'rows');\n nested.hidden = !open;\n nested.append(...row.collapsed.map((inner) => this.row(inner, expanded)));\n toggle.addEventListener('click', () => {\n nested.hidden = !nested.hidden;\n toggle.setAttribute('aria-expanded', String(!nested.hidden));\n });\n item.append(toggle, nested);\n }\n return item;\n }\n}\n\n/** Fills a Version level's body, or says the version is gone. */\nexport function renderVersion(body: HTMLElement, model: VersionModel | undefined): void {\n if (!model) {\n body.replaceChildren(el('p', 'message', 'This version is no longer in the history. Go back to see the versions there are.'));\n return;\n }\n // The time is the level's title; the head adds its marks and notes.\n const head = el('p', 'version-head');\n head.title = `Saved ${model.whenUtc} UTC`;\n for (const mark of model.marks) head.append(el('span', `status ${mark === 'live' ? 'status-up-to-date' : 'note'}`, mark));\n for (const note of model.notes) head.append(el('span', 'status note', note));\n // The comparisons one above the other, not side by side, so the level keeps the sidebar's width.\n const changes = model.changes.map(({ label, change }) => {\n const section = el('div', 'field version-change');\n section.append(el('span', 'caption', label), renderChange(change));\n return section;\n });\n const actions = el('div', 'actions');\n actions.append(...model.actions.map(actionButton));\n body.replaceChildren(...(head.childElementCount > 0 ? [head] : []), ...changes, actions);\n}\n\nfunction actionButton(action: HistoryAction): HTMLButtonElement {\n const button = makeButton(action.label, variantOf(action), 'sm');\n if (action.pressed !== undefined) button.setAttribute('aria-pressed', String(action.pressed));\n if (action.disabled) {\n button.disabled = true;\n button.title = action.disabled;\n }\n button.addEventListener('click', () => action.run(button));\n return button;\n}\n", "// A tooltip: shadcn/ui's, shown above a control on hover (after a short\n// wait) and on keyboard focus, and hidden on leave, blur, a press or Escape.\n// Its text is also the control's description, so a screen reader hears it\n// without the tooltip. Not on touch, where there is no hover.\n//\n// A disabled button keeps its title for the reason it is disabled: it does\n// not take focus, and not every browser sends it pointer events.\n\nimport { el } from './host.ts';\n\nconst WAIT_MS = 400;\n\nlet count = 0;\nlet shown: { tip: HTMLElement; trigger: HTMLElement } | undefined;\nlet timer = 0;\n\n/**\n * `text` is shown and becomes the control's description. Without `text`, the tooltip shows the control's aria-label (an icon button's name).\n */\nexport function tooltip(trigger: HTMLElement, text?: string): void {\n trigger.removeAttribute('title');\n if (text !== undefined) {\n const description = el('span', 'visually-hidden', text);\n description.id = `baack-tooltip-${++count}`;\n // Beside the control: now, or once the code building it has put it on the page.\n const place = () => trigger.parentElement && !description.isConnected && trigger.after(description);\n place();\n queueMicrotask(place);\n trigger.setAttribute('aria-describedby', description.id);\n }\n const content = () => text ?? trigger.getAttribute('aria-label') ?? '';\n\n trigger.addEventListener('pointerenter', (event) => {\n if (event.pointerType === 'touch') return;\n clearTimeout(timer);\n timer = window.setTimeout(() => show(trigger, content()), shown ? 0 : WAIT_MS);\n });\n trigger.addEventListener('focus', () => {\n if (trigger.matches(':focus-visible')) show(trigger, content());\n });\n for (const type of ['pointerleave', 'blur', 'pointerdown'] as const) trigger.addEventListener(type, hide);\n trigger.addEventListener('keydown', (event) => {\n if (event.key === 'Escape' && shown?.trigger === trigger) hide();\n });\n}\n\nfunction show(trigger: HTMLElement, text: string): void {\n hide();\n if (!trigger.isConnected || trigger.getClientRects().length === 0) return;\n const tip = el('div', 'tooltip', text);\n tip.setAttribute('aria-hidden', 'true');\n (trigger.getRootNode() as ShadowRoot | Document).append(tip);\n const rect = trigger.getBoundingClientRect();\n const { width, height } = tip.getBoundingClientRect();\n const above = rect.top - height - 6;\n tip.style.top = `${above >= 8 ? above : rect.bottom + 6}px`;\n tip.style.left = `${Math.min(Math.max(8, rect.left + rect.width / 2 - width / 2), window.innerWidth - width - 8)}px`;\n shown = { tip, trigger };\n}\n\nfunction hide(): void {\n clearTimeout(timer);\n shown?.tip.remove();\n shown = undefined;\n}\n", "// One sidebar explored by drilling in (docs/plans/single-sidebar.md): a\n// navigation stack of levels. Choosing a row pushes a level, which slides in\n// from the side the sidebar is docked away from; Back pops it, returning to\n// the level above as it was (scroll and focus kept). A breadcrumb jumps up\n// several levels. Entry points can build the whole stack at once (`reset`),\n// so Back from a deep link goes to the parent.\n\nimport { button, el, type EditorHost, variantOf } from './host.ts';\nimport { icon } from './icons.ts';\nimport { tooltip } from './tooltip.ts';\n\nexport interface Level {\n /** Stable within the stack, for `popTo` and tests. */\n readonly id: string;\n readonly title: string;\n /** Built once, when the level is first shown; the level keeps it current itself. */\n render(): HTMLElement;\n /** Called each time the level becomes the one on screen (after pushing it, or coming back to it). */\n onShow?(): void;\n /** Called when the level leaves the stack. */\n dispose?(): void;\n}\n\nexport type Side = 'right' | 'left';\n\ninterface Entry {\n level: Level;\n section: HTMLElement;\n /** Where the level was scrolled to when a deeper level covered it. */\n scrollTop: number;\n /** The element that drilled in from this level, focused again on coming back. */\n origin: HTMLElement | undefined;\n}\n\nconst SIDE_KEY = 'baack-editor:side';\nconst SLIDE_MS = 150;\n/** Breadcrumbs beyond this many collapse to the root, an ellipsis and the last ones. */\nconst CRUMBS = 3;\n\nlet stacks = 0;\n\n/** Below this width the sidebar is a bottom sheet (`host.ts`). */\nconst NARROW = '(max-width: 640px)';\n\nexport class SidebarStack {\n readonly element: HTMLElement;\n private readonly back: HTMLButtonElement;\n private readonly heading: HTMLHeadingElement;\n private readonly crumbs: HTMLOListElement;\n private readonly body: HTMLElement;\n private readonly announcer: HTMLElement;\n private readonly dock: HTMLButtonElement;\n private readonly entries: Entry[] = [];\n private readonly id = `baack-stack-${(stacks += 1)}`;\n private readonly closeListeners: (() => void)[] = [];\n private toolbar: HTMLElement | undefined;\n\n constructor(host: EditorHost) {\n this.element = el('aside', 'panel side stack');\n this.element.setAttribute('aria-label', 'Editor');\n this.element.hidden = true;\n\n const bar = el('div', 'stack-bar');\n this.back = button('', 'ghost', 'sm', 'stack-back');\n this.back.addEventListener('click', () => this.pop());\n this.dock = button('', 'ghost', 'icon-sm', 'side-dock');\n this.dock.addEventListener('click', () => this.setSide(this.side === 'right' ? 'left' : 'right'));\n const close = button('', 'ghost', 'icon-sm', 'stack-close');\n close.setAttribute('aria-label', 'Close');\n close.append(icon('x'));\n close.addEventListener('click', () => this.close());\n bar.append(this.back, el('span', 'stack-spacer'), this.dock, close);\n tooltip(this.dock);\n tooltip(close);\n\n const nav = el('nav', 'stack-crumbs');\n nav.setAttribute('aria-label', 'Where you are');\n this.crumbs = el('ol');\n nav.append(this.crumbs);\n this.heading = el('h2', 'stack-title');\n this.heading.id = `${this.id}-title`;\n this.heading.tabIndex = -1;\n this.body = el('div', 'stack-body');\n this.announcer = el('p', 'visually-hidden');\n this.announcer.setAttribute('aria-live', 'polite');\n\n this.element.append(bar, nav, this.heading, this.body, this.announcer);\n this.element.addEventListener('keydown', this.onKeyDown);\n this.setSide(readSide());\n host.root.append(this.element);\n }\n\n /**\n * Keeps clear of the editor's toolbar (bottom right), whose height changes\n * with its messages: docked on its side, or as a bottom sheet, the sidebar\n * ends just above it.\n */\n avoid(toolbar: HTMLElement): void {\n this.toolbar = toolbar;\n new ResizeObserver(() => this.fit()).observe(toolbar);\n window.addEventListener('resize', () => this.fit());\n this.fit();\n }\n\n /** Runs when the sidebar is closed (its Close, Escape from the top level). */\n onClose(listener: () => void): void {\n this.closeListeners.push(listener);\n }\n\n private fit(): void {\n const top = this.toolbar?.getBoundingClientRect().top;\n const above = (this.side === 'right' || matchMedia(NARROW).matches) && top !== undefined;\n this.element.style.bottom = above ? `${Math.max(16, window.innerHeight - top + 8)}px` : '';\n }\n\n /** The level on screen. */\n get current(): Level | undefined {\n return this.entries.at(-1)?.level;\n }\n\n /** The ids of the levels, root first. */\n get path(): string[] {\n return this.entries.map((entry) => entry.level.id);\n }\n\n get isOpen(): boolean {\n return !this.element.hidden;\n }\n\n /** Drills into a level from the current one. `focus: false` leaves focus where it is (progress shown while working elsewhere). */\n push(level: Level, { focus = true } = {}): void {\n const from = this.entries.at(-1);\n if (from) {\n from.scrollTop = this.body.scrollTop;\n from.origin = this.focusedIn(from.section);\n }\n const entry = this.enter(level);\n this.entries.push(entry);\n this.show(entry, from, 'in', focus);\n }\n\n /** Back one level; from the root, closes the sidebar. */\n pop(): void {\n if (this.entries.length <= 1) {\n this.close();\n return;\n }\n this.popTo(this.entries.at(-2)!.level.id);\n }\n\n /** Back to the level with this id, leaving every level above it. */\n popTo(id: string): void {\n const index = this.entries.findIndex((entry) => entry.level.id === id);\n if (index < 0 || index === this.entries.length - 1) return;\n const from = this.entries.at(-1)!;\n for (const left of this.entries.splice(index + 1)) this.leave(left, left === from);\n this.show(this.entries[index]!, from, 'out');\n }\n\n /** Replaces the level on screen, as after finishing a task that changed what it showed. */\n replace(level: Level, { focus = true } = {}): void {\n const from = this.entries.pop();\n if (from) this.leave(from, false);\n const entry = this.enter(level);\n this.entries.push(entry);\n this.show(entry, undefined, 'none', focus);\n }\n\n /** Builds the whole stack at once (a deep link), showing the last level and opening the sidebar. */\n reset(levels: readonly Level[], { focus = true } = {}): void {\n for (const left of this.entries.splice(0)) this.leave(left, false);\n for (const level of levels) this.entries.push(this.enter(level));\n const top = this.entries.at(-1);\n if (top) this.show(top, undefined, 'none', focus);\n }\n\n open(): void {\n this.element.hidden = false;\n }\n\n /** Hides the sidebar, keeping its levels for next time. */\n close(): void {\n if (this.element.hidden) return;\n this.element.hidden = true;\n for (const listener of this.closeListeners) listener();\n }\n\n get side(): Side {\n return this.element.dataset['side'] === 'left' ? 'left' : 'right';\n }\n\n /** Docks the sidebar on one side of the page, remembered in this browser. */\n setSide(side: Side): void {\n this.element.dataset['side'] = side;\n this.dock.setAttribute('aria-label', side === 'right' ? 'Move to left' : 'Move to right');\n this.dock.replaceChildren(icon(side === 'right' ? 'panel-left' : 'panel-right'));\n this.fit();\n try {\n localStorage.setItem(SIDE_KEY, side);\n } catch {\n // Storage can be blocked; the sidebar still docks for this visit.\n }\n }\n\n private enter(level: Level): Entry {\n const section = el('section', 'stack-level');\n section.dataset['level'] = level.id;\n section.setAttribute('aria-labelledby', this.heading.id);\n section.hidden = true;\n section.append(level.render());\n this.body.append(section);\n return { level, section, scrollTop: 0, origin: undefined };\n }\n\n private leave(entry: Entry, animated: boolean): void {\n entry.level.dispose?.();\n // A level sliding out stays until its animation ends.\n if (!animated || !this.animates()) entry.section.remove();\n }\n\n private show(entry: Entry, from: Entry | undefined, direction: 'in' | 'out' | 'none', focus = true): void {\n this.element.hidden = false;\n for (const other of this.entries) other.section.hidden = other !== entry;\n entry.section.hidden = false;\n this.renderHeader();\n this.body.scrollTop = direction === 'out' ? entry.scrollTop : 0;\n if (from && direction !== 'none') this.slide(entry.section, from.section, direction);\n entry.level.onShow?.();\n this.announcer.textContent = entry.level.title;\n // Coming back: the row that drilled in. Going in: the new level's heading.\n const origin = direction === 'out' && entry.origin?.isConnected ? entry.origin : undefined;\n if (focus) (origin ?? this.heading).focus({ preventScroll: direction === 'out' });\n }\n\n private renderHeader(): void {\n const current = this.entries.at(-1)!.level;\n const parent = this.entries.at(-2)?.level;\n this.heading.textContent = current.title;\n this.back.hidden = !parent;\n this.back.replaceChildren(...(parent ? [icon('chevron-left'), el('span', 'stack-back-text', parent.title)] : []));\n this.back.setAttribute('aria-label', parent ? `Back to ${parent.title}` : 'Back');\n\n const items = this.entries.map((entry, index) => ({ entry, index }));\n const shown =\n items.length > CRUMBS + 1 ? [items[0]!, undefined, ...items.slice(items.length - (CRUMBS - 1))] : items;\n this.crumbs.replaceChildren(\n ...shown.flatMap((item, position) => {\n // Between crumbs, a chevron that is not read out.\n const separator = el('li', 'stack-crumb-separator');\n separator.setAttribute('role', 'presentation');\n separator.setAttribute('aria-hidden', 'true');\n separator.append(icon('chevron-right'));\n const li = el('li');\n const crumb = (content: HTMLElement) => {\n li.append(content);\n return position === 0 ? [li] : [separator, li];\n };\n if (!item) return crumb(el('span', 'meta', '\u2026'));\n if (item.index === this.entries.length - 1) {\n const here = el('span', '', item.entry.level.title);\n here.setAttribute('aria-current', 'page');\n return crumb(here);\n }\n const jump = el('button', 'stack-crumb', item.entry.level.title);\n jump.type = 'button';\n jump.addEventListener('click', () => this.popTo(item.entry.level.id));\n return crumb(jump);\n }),\n );\n // A single level has nowhere to go back to: no breadcrumb.\n (this.crumbs.parentElement as HTMLElement).hidden = this.entries.length < 2;\n }\n\n private animates(): boolean {\n return typeof Element.prototype.animate === 'function' && !matchMedia('(prefers-reduced-motion: reduce)').matches;\n }\n\n /** Slides `to` in over `from` (drilling in), or `from` out to reveal `to` (Back). */\n private slide(to: HTMLElement, from: HTMLElement, direction: 'in' | 'out'): void {\n if (!this.animates()) return;\n // Deeper levels come from the far side: the right when docked right, the left when docked left.\n const away = this.side === 'right' ? '100%' : '-100%';\n const options: KeyframeAnimationOptions = { duration: SLIDE_MS, easing: 'ease-out' };\n if (direction === 'in') {\n to.animate([{ transform: `translateX(${away})` }, { transform: 'none' }], options);\n return;\n }\n // The level going out is drawn over the one coming back until it has slid away.\n // Only drawn: out of the accessibility tree and unreachable, so it never reads as the level on screen.\n from.hidden = false;\n from.inert = true;\n from.setAttribute('aria-hidden', 'true');\n from.classList.add('leaving');\n from.style.top = `${this.body.scrollTop}px`;\n const animation = from.animate([{ transform: 'none' }, { transform: `translateX(${away})` }], options);\n animation.finished.then(\n () => from.remove(),\n () => from.remove(),\n );\n }\n\n private focusedIn(section: HTMLElement): HTMLElement | undefined {\n const active = (this.element.getRootNode() as ShadowRoot).activeElement;\n return active instanceof HTMLElement && section.contains(active) ? active : undefined;\n }\n\n private readonly onKeyDown = (event: KeyboardEvent) => {\n if (event.key === 'Escape' && !event.defaultPrevented) {\n event.preventDefault();\n event.stopPropagation();\n this.pop();\n return;\n }\n if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') return;\n // Rows (`[data-row]`) in the level on screen: arrows move between them.\n const section = this.entries.at(-1)?.section;\n const active = section && this.focusedIn(section);\n if (!section || !active?.matches('[data-row]')) return;\n const rows = [...section.querySelectorAll<HTMLElement>('[data-row]')].filter((row) => !row.closest('[hidden]'));\n const next = rows[rows.indexOf(active) + (event.key === 'ArrowDown' ? 1 : -1)];\n if (!next) return;\n event.preventDefault();\n next.focus();\n };\n}\n\nfunction readSide(): Side {\n try {\n return localStorage.getItem(SIDE_KEY) === 'left' ? 'left' : 'right';\n } catch {\n return 'right';\n }\n}\n\n/**\n * A row that drills into a level: a full-width button with a label, an\n * optional detail line, and a chevron. Arrow keys move between rows.\n */\nexport function drillRow(label: string, detail: string, open: () => void): HTMLButtonElement {\n const row = el('button', 'stack-row');\n row.type = 'button';\n row.dataset['row'] = '';\n const text = el('span', 'stack-row-text');\n text.append(el('span', 'stack-row-label', label));\n if (detail) text.append(el('span', 'meta', detail));\n const chevron = el('span', 'stack-chevron');\n chevron.append(icon('chevron-right'));\n row.append(text, chevron);\n row.addEventListener('click', open);\n return row;\n}\n\nexport interface Choice {\n label: string;\n primary?: boolean;\n /** Shown as a destructive button: it deletes or discards. */\n destructive?: boolean;\n /** Gets the button, to disable it while the choice runs. */\n run(button: HTMLButtonElement): void;\n}\n\n/**\n * A confirm as a level (forms and confirms are the deepest level, so they\n * never cover what they are about): what it is about, the values concerned,\n * what happens, then the choices. Cancel is a choice that goes Back.\n */\nexport function confirmLevel(options: {\n id: string;\n title: string;\n meta: string;\n blocks: { label: string; text: string }[];\n description: string;\n choices: Choice[];\n}): Level {\n const body = el('div', 'level-confirm');\n body.append(el('p', 'meta', options.meta));\n for (const block of options.blocks) {\n const box = el('div', 'field');\n box.append(el('span', 'caption', block.label), el('pre', 'snippet', block.text));\n body.append(box);\n }\n body.append(el('p', 'description', options.description));\n const actions = el('div', 'actions');\n for (const choice of options.choices) {\n const choiceButton = button(choice.label, variantOf(choice));\n choiceButton.addEventListener('click', () => choice.run(choiceButton));\n actions.append(choiceButton);\n }\n body.append(actions);\n return { id: options.id, title: options.title, render: () => body };\n}\n", "// An item's history: its versions, what each changed, and the actions on a\n// version. \"Publish this version\" moves the live pointer (no new version);\n// \"Edit from this version\" saves a new draft based on it; \"Preview on the\n// page\" only shows it in place, sending nothing.\n//\n// It is explored in the sidebar (docs/plans/single-sidebar.md): the Item\n// level lists the versions, a Version level shows one with its actions, and\n// deleting one confirms in a level above that.\n\nimport { parseTimestamp } from '@baack-software/baack-ts-components/format';\nimport { diffWords, type DiffPart } from './core/diff.ts';\nimport { dispatchItemPublished } from './core/events.ts';\nimport type { ContentItem, TypeEntry } from './core/registry.ts';\nimport type { Editing } from './editing.ts';\nimport { summarise, summariseChange } from './saving.ts';\nimport { isLive, type EditorContext, type Slot } from './targets.ts';\nimport { el } from './ui/host.ts';\nimport { ItemHistoryView, renderVersion, type HistoryAction, type HistoryRowModel, type VersionModel } from './ui/history-view.ts';\nimport { confirmLevel, type Level, type SidebarStack } from './ui/stack.ts';\nimport type { PageView } from './view.ts';\n\n/** Drafts saved within this long of each other collapse into one row. */\nconst COLLAPSE_MS = 10 * 60 * 1000;\n\ninterface Open extends Slot {\n urn: string;\n versions: ContentItem[];\n live: ContentItem | undefined;\n after: string | undefined;\n against: 'live' | 'previous';\n linked: boolean;\n level: Level;\n view: ItemHistoryView;\n /** The Version level on screen above the item's, if any. */\n version: { urn: string; body: HTMLElement } | undefined;\n}\n\nexport interface HistoryHooks {\n /** A linked version publishes with its entity: open the publish dialog. */\n publishEntity(entityUrn: string): void;\n /** After a version was published: re-read the entity and its status. */\n published(entityUrn: string): Promise<void>;\n /** Shows an item's level in the sidebar, above its entity's level. */\n show(level: Level, entityUrn: string): void;\n}\n\nexport class History {\n private readonly stack: SidebarStack;\n private readonly ctx: EditorContext;\n private readonly editing: Editing;\n private readonly view: PageView;\n private readonly hooks: HistoryHooks;\n private state: Open | undefined;\n\n constructor(ctx: EditorContext, editing: Editing, view: PageView, stack: SidebarStack, hooks: HistoryHooks) {\n this.ctx = ctx;\n this.editing = editing;\n this.view = view;\n this.stack = stack;\n this.hooks = hooks;\n view.onPreviewChange(() => this.render());\n }\n\n /** Opens the item's level in the sidebar (from the popover, or a row on its entity's level). */\n async open(slot: Slot & { urn: string }): Promise<void> {\n // Another item's history: its preview ends.\n if (this.state && !sameItem(this.state, slot)) this.stopPreview();\n const itemView = new ItemHistoryView(\n () => void this.loadMore(),\n (against) => {\n if (this.state !== state) return;\n state.against = against;\n this.render();\n },\n );\n const level: Level = {\n id: itemLevelId(slot),\n title: `${slot.name} #${slot.sortOrder}`,\n render: () => itemView.element,\n // The level left the stack (Back past it, or another deep link): its preview ends with it.\n dispose: () => {\n if (this.state !== state) return;\n this.stopPreview();\n this.state = undefined;\n },\n };\n const state: Open = { ...slot, versions: [], live: undefined, after: undefined, against: 'live', linked: false, level, view: itemView, version: undefined };\n // Set before showing, so the level it replaces does not end a preview of the same item.\n this.state = state;\n this.hooks.show(level, slot.entityUrn);\n itemView.setStatus('Loading\u2026');\n state.linked = await this.isLinked(slot);\n if (this.state === state) await this.loadMore();\n }\n\n /** Ends the preview and forgets the item (leaving a read mode). */\n close(): void {\n this.stopPreview();\n this.state = undefined;\n }\n\n /** Ends a preview of a version, if one is shown. */\n stopPreview(): void {\n if (this.state && this.view.previewedUrn) {\n this.view.stopPreview(this.state);\n this.ctx.toolbar.showMessage('');\n }\n }\n\n /** Shows a version on the page in place of the latest, or stops showing it. Sends nothing. */\n private togglePreview(state: Open, version: ContentItem): void {\n if (this.view.previewedUrn === version.urn) {\n this.stopPreview();\n return;\n }\n // The element may be open for editing (History opens from its popover): close it, keeping any unsaved edit.\n this.editing.close();\n this.view.previewVersion(state, version);\n // The selection from opening the editor would cover the previewed value.\n const selection = window.getSelection();\n const shown = this.view.bindingsAt(state).map((binding) => binding.element);\n if (selection?.anchorNode && shown.some((element) => element.contains(selection.anchorNode))) selection.removeAllRanges();\n this.view.bindingsAt(state)[0]?.element.scrollIntoView({ block: 'nearest', behavior: 'smooth' });\n const when = new Date(parseTimestamp(version.createdTimestamp ?? '')).toLocaleString();\n this.ctx.toolbar.showMessage(`Previewing the version of ${state.name} saved ${when}. Nothing is saved; stop the preview to see the latest again.`, true);\n }\n\n /** Content changed (a save, a publish): reload if this entity's history is open. */\n changed(entityUrn?: string): void {\n const state = this.state;\n if (!state || (entityUrn && entityUrn !== state.entityUrn)) return;\n // Follow the item to its newest version.\n const current = this.ctx.store.itemAt(state.entityUrn, state.entry, state.name, state.sortOrder);\n if (current?.item.urn) state.urn = current.item.urn;\n void this.reload(state);\n }\n\n /** Reads the history again from its newest page, keeping the levels on screen. */\n private async reload(state: Open): Promise<void> {\n try {\n const page = await this.ctx.transport.history(state.entry, state.urn);\n if (this.state !== state) return;\n state.live = page.item ?? undefined;\n state.versions = [...page.history];\n state.after = page.pagination?.isMorePages ? page.pagination.after ?? undefined : undefined;\n this.render();\n } catch (error) {\n void this.ctx.feedback.report(error, 'load the history', () => void this.reload(state));\n }\n }\n\n private async loadMore(): Promise<void> {\n const state = this.state;\n if (!state) return;\n try {\n const page = await this.ctx.transport.history(state.entry, state.urn, state.after);\n if (this.state !== state) return;\n state.live ??= page.item ?? undefined;\n state.versions.push(...page.history);\n state.after = page.pagination?.isMorePages ? page.pagination.after ?? undefined : undefined;\n state.view.setStatus('');\n this.render();\n } catch (error) {\n state.view.setStatus('');\n void this.ctx.feedback.report(error, 'load the history', () => void this.loadMore());\n }\n }\n\n private render(): void {\n const state = this.state;\n if (!state) return;\n const rows = state.versions.map((version, index) => this.row(state, version, state.versions[index + 1]));\n // Collapse a run of drafts saved close together into its newest; the live version always shows.\n const grouped: HistoryRowModel[] = [];\n let groupTime: number | undefined;\n state.versions.forEach((version, index) => {\n const time = parseTimestamp(version.createdTimestamp ?? '');\n const head = grouped.at(-1);\n const live = version.isPublished === true;\n if (head && !live && !head.live && groupTime !== undefined && groupTime - time <= COLLAPSE_MS) {\n head.collapsed.push(rows[index]!);\n } else {\n grouped.push(rows[index]!);\n }\n groupTime = time;\n });\n state.view.render(grouped, state.after !== undefined);\n if (state.version && this.stack.path.includes(versionLevelId(state.version.urn))) {\n renderVersion(state.version.body, this.versionModel(state, state.version.urn));\n }\n }\n\n private row(state: Open, version: ContentItem, previous: ContentItem | undefined): HistoryRowModel {\n const against = state.against === 'live' ? state.live : previous;\n return {\n when: when(version),\n whenUtc: version.createdTimestamp ?? '',\n live: version.isPublished === true,\n change: describe(state.entry, version, against, state.against),\n notes: this.notes(version, previous),\n open: () => this.openVersion(state, version),\n preview: this.previewAction(state, version),\n collapsed: [],\n };\n }\n\n private notes(version: ContentItem, previous: ContentItem | undefined): string[] {\n const notes: string[] = [];\n if (previous && previous.name !== version.name) notes.push(`renamed from ${previous.name}`);\n if (previous && previous.sortOrder !== version.sortOrder) notes.push(`moved from #${previous.sortOrder} to #${version.sortOrder}`);\n const group = version.urn ? this.ctx.groups?.of(version.urn) : undefined;\n if (group) notes.push(`part of: ${group.label}`);\n return notes;\n }\n\n /** Drills into one version: both comparisons, and what can be done with it. */\n private openVersion(state: Open, version: ContentItem): void {\n const urn = version.urn!;\n const body = el('div', 'level-version');\n state.version = { urn, body };\n renderVersion(body, this.versionModel(state, urn));\n this.stack.push({\n id: versionLevelId(urn),\n title: `Version saved ${when(version)}`,\n render: () => body,\n dispose: () => {\n if (state.version?.urn === urn) state.version = undefined;\n },\n });\n }\n\n /** The version's level, from the history as last read; undefined once it is gone. */\n private versionModel(state: Open, urn: string): VersionModel | undefined {\n const index = state.versions.findIndex((version) => version.urn === urn);\n const version = state.versions[index];\n if (!version) return undefined;\n const previous = state.versions[index + 1];\n const marks = [...(version.isPublished === true ? ['live'] : []), ...(index === 0 ? ['latest'] : [])];\n // One comparison when the one before is the live version; none against live for the live version itself.\n const beforeIsLive = previous !== undefined && previous.urn === state.live?.urn;\n const changes = [\n {\n label: beforeIsLive ? 'Against the one before, which is live' : 'Against the one before',\n change: describe(state.entry, version, previous, 'previous') || 'The same value as the one before.',\n },\n ];\n if (version.isPublished !== true && !beforeIsLive) changes.push({ label: 'Against live', change: describe(state.entry, version, state.live, 'live') });\n return { when: when(version), whenUtc: version.createdTimestamp ?? '', marks, notes: this.notes(version, previous), changes, actions: this.actions(state, version) };\n }\n\n private actions(state: Open, version: ContentItem): HistoryAction[] {\n const { ctx } = this;\n const actions: HistoryAction[] = [];\n const status = ctx.store.view(state.entityUrn)?.status;\n // Item publish only means something on a live entity, and needs the publish permission.\n if (ctx.canPublish && version.isPublished !== true && (isLive(status) || status === 'PUBLISH')) {\n const busy = status === 'PUBLISH' ? 'Publishing is in progress for this page.' : undefined;\n // Half of a swap or reorder must not go live alone.\n const grouped = ctx.groups?.of(version.urn!) !== undefined;\n actions.push(\n state.linked || grouped\n ? { label: 'Publish with the page\u2026', disabled: busy, run: () => this.hooks.publishEntity(state.entityUrn) }\n : { label: 'Publish this version', primary: true, disabled: busy, run: () => void this.publish(state, version) },\n );\n }\n actions.push(this.previewAction(state, version));\n if (version !== state.versions[0]) {\n actions.push({ label: 'Edit from this version', run: (anchor) => this.editFrom(state, version, anchor) });\n }\n // One revision at a time. Whether it is allowed (the delete permission on the item, its\n // entity, or admin on the owner) is the API's decision; the client cannot see it.\n // Deleting an item's only version deletes the item, live or not; deleting the live\n // version puts another live in its place (see `successor`).\n const onlyVersion = state.versions.length === 1 && state.after === undefined;\n actions.push({\n label: onlyVersion ? 'Delete this item\u2026' : 'Delete this version\u2026',\n destructive: true,\n run: () => this.confirmDelete(state, version, onlyVersion),\n });\n return actions;\n }\n\n private previewAction(state: Open, version: ContentItem): HistoryAction {\n const previewing = this.view.previewedUrn === version.urn;\n const current = this.ctx.store.itemAt(state.entityUrn, state.entry, state.name, state.sortOrder)?.item.urn;\n const disabled = state.entry.renderedByView\n ? 'The page shows the server\\'s rendering of this type, which history does not include.'\n : this.view.mode !== 'LATEST'\n ? 'Previews are shown on the latest drafts.'\n : this.view.bindingsAt(state).length === 0\n ? 'This item is not shown on this page.'\n : version.urn === current && !this.ctx.pending.getEdit(version.urn!)\n ? 'The page already shows this version.'\n : undefined;\n return {\n label: previewing ? 'Stop preview' : 'Preview on the page',\n pressed: previewing,\n disabled: previewing ? undefined : disabled,\n run: () => this.togglePreview(state, version),\n };\n }\n\n /** Deleting a revision (or, with its only version, the item) is permanent, so it asks first. */\n private confirmDelete(state: Open, version: ContentItem, wholeItem: boolean): void {\n const when = new Date(parseTimestamp(version.createdTimestamp ?? '')).toLocaleString();\n const where = version.isPublished === true ? 'from this page and from the live site' : 'from this page';\n const blocks = [{ label: `The version saved ${when}`, text: summarise(state.entry, version) }];\n let description = wholeItem\n ? `This is its only version, so deleting it deletes the item: it disappears ${where}, and cannot be restored.`\n : 'It is removed from the history for good and cannot be restored. Every version uses storage, which is billed.';\n const next = !wholeItem && version.isPublished === true ? successor(state, version) : undefined;\n if (next) {\n const nextWhen = new Date(parseTimestamp(next.version?.createdTimestamp ?? '')).toLocaleString();\n if (next.version) {\n blocks.push({ label: `Goes live in its place: the version saved ${nextWhen}`, text: summarise(state.entry, next.version) });\n }\n description =\n next.newer\n ? `This is the live version. The API puts the next newer version live in its place: a draft saved ${nextWhen}, which may never have been published. Publish the version you want first if that is not it. It cannot be restored.`\n : next.version\n ? `This is the live version. The API puts the version before it live in its place (saved ${nextWhen}). It cannot be restored.`\n : 'This is the live version. The API puts the version before it live in its place. It cannot be restored.';\n }\n this.stack.push(\n confirmLevel({\n id: 'confirm-delete',\n title: wholeItem ? 'Delete this item permanently?' : next ? 'Delete the live version permanently?' : 'Delete this version permanently?',\n meta: `${state.name} #${state.sortOrder}`,\n blocks,\n description,\n choices: [\n { label: 'Cancel', run: () => this.stack.pop() },\n {\n label: 'Delete permanently',\n destructive: true,\n run: (button) => {\n button.disabled = true;\n button.textContent = 'Deleting\u2026';\n void this.deleteVersion(state, version).finally(() => {\n button.disabled = false;\n button.textContent = 'Delete permanently';\n });\n },\n },\n ],\n }),\n );\n }\n\n private async deleteVersion(state: Open, version: ContentItem): Promise<void> {\n const { transport, pending, toolbar, feedback } = this.ctx;\n // Known before the delete: which version the API will put live in its place.\n const promoted = version.isPublished === true ? successor(state, version).version : undefined;\n try {\n await transport.remove(state.entry, version.urn!);\n if (promoted?.urn) dispatchItemPublished({ entityUrn: state.entityUrn, urn: promoted.urn, type: state.entry.type });\n const remaining = state.versions.find((other) => other.urn !== version.urn);\n const edit = pending.getEdit(version.urn!);\n if (!remaining?.urn) {\n // That was its only version: the item is gone, and so is anything to save against it.\n if (edit) pending.clear(version.urn!);\n this.close();\n this.stack.popTo(`entity:${state.entityUrn}`);\n toolbar.showMessage(`Deleted ${state.name} #${state.sortOrder}.`, true);\n await this.hooks.published(state.entityUrn);\n return;\n }\n // An unsaved edit based on the deleted version can no longer be saved as it was.\n if (edit) pending.set({ ...edit, stale: true });\n toolbar.showMessage(`Deleted the version of ${state.name} saved ${new Date(parseTimestamp(version.createdTimestamp ?? '')).toLocaleString()}.`, true);\n // Back to the versions there are. The page may have shown that version: re-read, and the history follows the item.\n if (this.state === state) this.stack.popTo(state.level.id);\n state.urn = remaining.urn;\n await this.hooks.published(state.entityUrn);\n if (this.state === state) await this.reload(state);\n } catch (error) {\n void feedback.report(error, 'delete this version', () => void this.deleteVersion(state, version));\n }\n }\n\n private async publish(state: Open, version: ContentItem): Promise<void> {\n try {\n await this.ctx.transport.publishVersion(state.entry, version);\n dispatchItemPublished({ entityUrn: state.entityUrn, urn: version.urn!, type: state.entry.type });\n this.ctx.announcePublished(state.entityUrn, `Published the version of ${state.name} saved ${new Date(parseTimestamp(version.createdTimestamp ?? '')).toLocaleString()}.`, { itemUrn: version.urn! });\n await this.hooks.published(state.entityUrn);\n } catch (error) {\n void this.ctx.feedback.report(error, 'publish this version', () => void this.publish(state, version));\n }\n }\n\n private editFrom(state: Open, version: ContentItem, anchor: HTMLElement): void {\n this.ctx.store.remember(state.entityUrn, state.entry, version);\n this.editing.open({\n entityUrn: state.entityUrn,\n entry: state.entry,\n name: version.name,\n sortOrder: version.sortOrder,\n urn: version.urn,\n anchor,\n binding: undefined,\n fromVersion: true,\n });\n }\n\n /**\n * Linked items publish with their entity: templates, and items a template\n * on the same entity uses (the view does not expose references, so the\n * template sources are scanned).\n */\n private async isLinked(slot: Slot): Promise<boolean> {\n if (slot.entry.type === 'template') return true;\n const { store, sources, transport } = this.ctx;\n const templates = (store.view(slot.entityUrn)?.raw.templates ?? []) as ContentItem[];\n const template = this.ctx.entry('template');\n const pattern = new RegExp(`\\\\$\\\\{?${slot.name.replace(/[^\\w-]/g, '')}\\\\b`);\n for (const item of templates) {\n if (!item.urn) continue;\n try {\n const source = sources.get(item.urn) ?? { value: (await transport.read(template, item.urn) as { value?: unknown }).value };\n sources.set(item.urn, source);\n if (pattern.test(String((source as { value?: unknown }).value ?? ''))) return true;\n } catch {\n // Unreadable template: assume not linked; the entity publish dialog remains available.\n }\n }\n return false;\n }\n}\n\nfunction describe(entry: TypeEntry, version: ContentItem, against: ContentItem | undefined, mode: 'live' | 'previous'): DiffPart[] | string {\n if (!against) return mode === 'live' ? 'Nothing is live yet.' : 'The first version.';\n if (against.urn === version.urn) return mode === 'live' ? 'This is the live version.' : '';\n const before = (against as { value?: unknown }).value;\n const after = (version as { value?: unknown }).value;\n if (typeof before === 'string' && typeof after === 'string') return diffWords(before, after);\n const was = summarise(entry, against);\n const now = summarise(entry, version);\n if (was === now) return 'No change to the value.';\n return summariseChange(entry, against, version);\n}\n\nfunction when(version: ContentItem): string {\n const time = parseTimestamp(version.createdTimestamp ?? '');\n return Number.isNaN(time) ? 'Unknown time' : new Date(time).toLocaleString();\n}\n\nfunction itemLevelId(slot: Slot): string {\n return `item:${slot.entityUrn}:${slot.entry.type}:${slot.name}:${slot.sortOrder}`;\n}\n\nfunction versionLevelId(urn: string): string {\n return `version:${urn}`;\n}\n\nfunction sameItem(a: Slot, b: Slot): boolean {\n return a.entityUrn === b.entityUrn && a.entry === b.entry && a.name === b.name && a.sortOrder === b.sortOrder;\n}\n\n/**\n * The version the API makes live when the live version is deleted: the next\n * newer version if there is one, otherwise the one before it. `version` is\n * undefined when the one before is on a page of history not loaded yet.\n */\nfunction successor(state: Open, live: ContentItem): { version: ContentItem | undefined; newer: boolean } {\n const index = state.versions.indexOf(live);\n // Newest first: the next newer version is the one above.\n if (index > 0) return { version: state.versions[index - 1], newer: true };\n return { version: state.versions[index + 1], newer: false };\n}\n", "// Sort order arithmetic for moves and inserts. Sort orders are stored values,\n// not positions: lists can be sparse, and values are never renumbered beyond\n// what a move needs (docs/editor-v2-plan.md section 10.1).\n\nexport interface Placed {\n /** Identifies the item (a version URN). */\n key: string;\n sortOrder: number;\n}\n\nexport interface SortChange {\n key: string;\n from: number;\n to: number;\n}\n\n/**\n * Applies a new order to a list by reusing its existing sort order values in\n * ascending order, so only items whose value must change are moved and the\n * list's spacing is kept. A swap of two neighbours is two changes.\n */\nexport function reorder(items: readonly Placed[], newOrder: readonly string[]): SortChange[] {\n const values = items.map((item) => item.sortOrder).sort((a, b) => a - b);\n const byKey = new Map(items.map((item) => [item.key, item]));\n if (newOrder.length !== items.length || newOrder.some((key) => !byKey.has(key))) {\n throw new Error('The new order must contain exactly the items of the list');\n }\n const changes: SortChange[] = [];\n newOrder.forEach((key, index) => {\n const item = byKey.get(key)!;\n const to = values[index]!;\n if (item.sortOrder !== to) changes.push({ key, from: item.sortOrder, to });\n });\n return changes;\n}\n\nexport type InsertAt = { position: 'head' } | { position: 'tail' } | { position: 'after'; key: string };\n\nexport interface InsertPlan {\n /** The sort order the new item takes. */\n sortOrder: number;\n /** Items that must move first to make room (one operation). */\n shifts: SortChange[];\n}\n\n/**\n * Picks a free sort order for a new item: below the head, above the tail,\n * or between two neighbours. When neighbours are adjacent integers, the\n * shorter side shifts by one to make room; nothing else moves.\n */\nexport function planInsert(items: readonly Placed[], at: InsertAt): InsertPlan {\n const sorted = [...items].sort((a, b) => a.sortOrder - b.sortOrder);\n if (sorted.length === 0) return { sortOrder: 0, shifts: [] };\n if (at.position === 'head') return { sortOrder: sorted[0]!.sortOrder - 1, shifts: [] };\n if (at.position === 'tail') return { sortOrder: sorted.at(-1)!.sortOrder + 1, shifts: [] };\n\n const index = sorted.findIndex((item) => item.key === at.key);\n if (index < 0) throw new Error('The item to insert after is not in the list');\n const before = sorted[index]!;\n const after = sorted[index + 1];\n if (!after) return { sortOrder: before.sortOrder + 1, shifts: [] };\n if (after.sortOrder - before.sortOrder > 1) {\n return { sortOrder: Math.floor((before.sortOrder + after.sortOrder) / 2), shifts: [] };\n }\n\n // Adjacent: shift the shorter side outwards by one, starting from the far end so no value is shared longer than needed.\n const left = sorted.slice(0, index + 1);\n const right = sorted.slice(index + 1);\n if (right.length <= left.length) {\n return {\n sortOrder: after.sortOrder,\n shifts: [...shiftRun(right, +1)].reverse(),\n };\n }\n return {\n sortOrder: before.sortOrder,\n shifts: shiftRun([...left].reverse(), -1).reverse(),\n };\n}\n\n/**\n * Moves a run of items by one in a direction, but only as far as needed: the\n * run stops at the first gap. `run` starts next to the freed slot.\n */\nfunction shiftRun(run: readonly Placed[], step: 1 | -1): SortChange[] {\n const changes: SortChange[] = [];\n for (const [index, item] of run.entries()) {\n // Keep going only while the item sits where the previous one is moving to.\n if (index > 0 && item.sortOrder !== changes.at(-1)!.to) break; // A gap: the rest can stay.\n changes.push({ key: item.key, from: item.sortOrder, to: item.sortOrder + step });\n }\n return changes;\n}\n\n/** Exchanges two items' sort orders. */\nexport function swap(a: Placed, b: Placed): SortChange[] {\n return [\n { key: a.key, from: a.sortOrder, to: b.sortOrder },\n { key: b.key, from: b.sortOrder, to: a.sortOrder },\n ];\n}\n", "// Which templates on an entity use an item name. The entity view does not\n// expose template references (open question 18), so template sources are\n// read and scanned for `$name` and `${name}`.\n\nimport type { ContentItem } from './core/registry.ts';\nimport type { EditorContext } from './targets.ts';\n\nexport async function templatesUsing(ctx: EditorContext, entityUrn: string, name: string): Promise<string[]> {\n const { store, sources, transport } = ctx;\n const template = ctx.entry('template');\n const pattern = new RegExp(`\\\\$\\\\{?${name.replace(/[^\\w-]/g, '')}\\\\b`);\n const users: string[] = [];\n for (const item of (store.view(entityUrn)?.raw.templates ?? []) as ContentItem[]) {\n if (!item.urn) continue;\n try {\n const source = sources.get(item.urn) ?? { value: ((await transport.read(template, item.urn)) as { value?: unknown }).value };\n sources.set(item.urn, source);\n if (pattern.test(String((source as { value?: unknown }).value ?? ''))) users.push(`${item.name} #${item.sortOrder}`);\n } catch {\n // Unreadable template: not listed; publishing and moving still work.\n }\n }\n return users;\n}\n", "// The reorder dialog: the entries of a list (or a table's rows, or a page's\n// sections) with their values shown clearly, each with a handle to drag and\n// Move up / Move down buttons. The page previews the order as it changes.\n// It is a sidebar level above the list's entity: leaving it by any route\n// (Back, Escape, Cancel) puts the page's order back.\n\nimport type { PanelHandle, Panels } from '../targets.ts';\nimport { button, el } from './host.ts';\nimport { tooltip } from './tooltip.ts';\nimport { icon } from './icons.ts';\n\nexport interface ReorderEntry {\n key: string;\n /** The value, shown clearly: what is being ordered. */\n label: string;\n /** More context, such as the start of a section's content. */\n detail?: string;\n sortOrder: number;\n}\n\nexport interface ReorderActions {\n /** The order changed (a drag or a button); `keys` is the new order. */\n changed(keys: string[]): void;\n save(keys: string[]): void;\n cancel(): void;\n /** Adds an entry: at the start, at the end, or after a key. */\n add?(at: { position: 'head' } | { position: 'tail' } | { position: 'after'; key: string }, anchor: HTMLElement): void;\n}\n\nexport class ReorderPanel {\n readonly element: HTMLElement;\n private entries: ReorderEntry[] = [];\n private actions: ReorderActions | undefined;\n private readonly list: HTMLElement;\n private readonly status: HTMLElement;\n private readonly saveButton: HTMLButtonElement;\n private readonly addButtons: HTMLElement;\n private dragging: string | undefined;\n\n private readonly panels: Panels;\n private handle: PanelHandle | undefined;\n\n constructor(panels: Panels) {\n this.panels = panels;\n this.element = el('div', 'reorder');\n this.status = el('p', 'hint');\n this.status.setAttribute('role', 'status');\n this.list = el('ol', 'rows reorder-rows');\n this.list.setAttribute('aria-label', 'Entries, in order');\n this.addButtons = el('div', 'actions');\n const buttons = el('div', 'actions');\n const cancel = el('button', '', 'Cancel');\n cancel.type = 'button';\n cancel.addEventListener('click', () => this.actions?.cancel());\n this.saveButton = el('button', 'primary', 'Save order');\n this.saveButton.type = 'button';\n this.saveButton.addEventListener('click', () => this.actions?.save(this.keys()));\n buttons.append(cancel, this.saveButton);\n this.element.append(this.status, this.list, this.addButtons, buttons);\n }\n\n get isOpen(): boolean {\n return this.handle?.isOpen ?? false;\n }\n\n open(title: string, entityUrn: string, entries: ReorderEntry[], actions: ReorderActions): void {\n this.entries = [...entries];\n this.actions = actions;\n this.setStatus('');\n this.setBusy(false);\n this.addButtons.replaceChildren();\n if (actions.add) {\n const head = el('button', '', 'Add at the start');\n head.type = 'button';\n head.addEventListener('click', () => actions.add!({ position: 'head' }, head));\n const tail = el('button', '', 'Add at the end');\n tail.type = 'button';\n tail.addEventListener('click', () => actions.add!({ position: 'tail' }, tail));\n this.addButtons.append(head, tail);\n }\n this.render();\n this.handle = this.panels.show(this.element, {\n title,\n entityUrn,\n // Left without Save or Cancel (Back, Escape, another task): the same as Cancel.\n onLeave: () => {\n const left = this.actions;\n this.actions = undefined;\n left?.cancel();\n },\n });\n }\n\n close(): void {\n this.actions = undefined;\n this.handle?.close();\n }\n\n setStatus(text: string): void {\n this.status.textContent = text;\n }\n\n setBusy(busy: boolean, label = 'Saving\u2026'): void {\n this.saveButton.disabled = busy;\n this.saveButton.textContent = busy ? label : 'Save order';\n }\n\n private keys(): string[] {\n return this.entries.map((entry) => entry.key);\n }\n\n /** `button`: the Move button used, focused again in the moved entry (or its other one at the end), so the keyboard stays in the list. */\n private move(from: number, to: number, button?: 'up' | 'down'): void {\n if (to < 0 || to >= this.entries.length || from === to) return;\n const [entry] = this.entries.splice(from, 1);\n this.entries.splice(to, 0, entry!);\n this.render();\n if (button) {\n const row = [...this.list.children].find((child) => (child as HTMLElement).dataset['key'] === entry!.key);\n const buttons = [...(row?.querySelectorAll<HTMLButtonElement>('button[data-move]') ?? [])];\n (buttons.find((b) => b.dataset['move'] === button && !b.disabled) ?? buttons.find((b) => !b.disabled))?.focus();\n }\n this.actions?.changed(this.keys());\n }\n\n private render(): void {\n this.list.replaceChildren(\n ...this.entries.map((entry, index) => {\n const row = el('li', 'row reorder-row');\n row.draggable = true;\n row.dataset['key'] = entry.key;\n const handle = el('span', 'handle');\n handle.setAttribute('aria-hidden', 'true');\n handle.append(icon('grip-vertical'));\n const text = el('div', 'row-main');\n text.append(el('span', 'row-name', entry.label));\n if (entry.detail) text.append(el('span', 'meta', entry.detail));\n const up = el('button', '', 'Move up');\n up.type = 'button';\n up.disabled = index === 0;\n up.setAttribute('aria-label', `Move ${entry.label} up`);\n up.dataset['move'] = 'up';\n up.addEventListener('click', () => this.move(index, index - 1, 'up'));\n const down = el('button', '', 'Move down');\n down.type = 'button';\n down.disabled = index === this.entries.length - 1;\n down.setAttribute('aria-label', `Move ${entry.label} down`);\n down.dataset['move'] = 'down';\n down.addEventListener('click', () => this.move(index, index + 1, 'down'));\n row.append(handle, text, up, down);\n if (this.actions?.add) {\n const add = button('', 'ghost', 'icon-sm');\n add.setAttribute('aria-label', `Add after ${entry.label}`);\n add.append(icon('plus'));\n tooltip(add);\n add.addEventListener('click', () => this.actions?.add!({ position: 'after', key: entry.key }, add));\n row.append(add);\n }\n // Drag and drop within the list.\n row.addEventListener('dragstart', (event) => {\n this.dragging = entry.key;\n event.dataTransfer?.setData('text/plain', entry.key);\n row.classList.add('dragging');\n });\n row.addEventListener('dragend', () => {\n this.dragging = undefined;\n row.classList.remove('dragging');\n });\n row.addEventListener('dragover', (event) => event.preventDefault());\n row.addEventListener('drop', (event) => {\n event.preventDefault();\n const from = this.entries.findIndex((candidate) => candidate.key === this.dragging);\n if (from >= 0) this.move(from, index);\n });\n return row;\n }),\n );\n }\n}\n", "// Moving items: reordering a list, a table's rows or a page's sections,\n// swapping fixed slots, making room for an insert, and relocating or\n// renaming an item.\n//\n// The API has no atomic multi-item commit, so every move is planned first:\n// its steps are queued as unsaved changes (and stashed) before any call,\n// then run in order. A step whose target is already in place is skipped, so\n// a plan can be replayed after a failure or a reload. Moves are drafts: they\n// go live when published, and the versions of one plan publish together.\n\nimport type { Binding } from './core/discovery.ts';\nimport { dispatchItemUpdated } from './core/events.ts';\nimport type { GroupLog } from './core/groups.ts';\nimport { planInsert, reorder, swap, type InsertAt, type Placed, type SortChange } from './core/ordering.ts';\nimport { pendingKey, type PendingCreate, type PendingMove } from './core/pending.ts';\nimport { toRepresentation, valueOf, type ContentItem, type TypeEntry } from './core/registry.ts';\nimport type { Editing } from './editing.ts';\nimport { isLive, reviewAction, type EditorContext, type PanelHandle } from './targets.ts';\nimport { inLiveContent } from './live.ts';\nimport { templatesUsing } from './templates.ts';\nimport { SimpleForm } from './ui/form.ts';\nimport { debugDetails, el } from './ui/host.ts';\nimport { ReorderPanel } from './ui/reorder-panel.ts';\nimport type { PageView } from './view.ts';\n\n/** One reorderable entry: a direct child of the group's container, and the items it shows. */\ninterface Unit {\n key: string;\n element: HTMLElement;\n bindings: Binding[];\n sortOrder: number;\n label: string;\n detail?: string;\n /** A keyed member whose order item does not exist yet: its key, the value the item is created with. */\n missing?: string;\n}\n\n/** A list (every item of a name) or a table's rows. */\ninterface Group {\n kind: 'list' | 'rows';\n container: HTMLElement;\n entityUrn: string;\n entry: TypeEntry;\n /** The list's item name; for rows, the first column's. */\n name: string;\n units: Unit[];\n}\n\nexport class Moves {\n readonly panel: ReorderPanel;\n private readonly ctx: EditorContext;\n private readonly view: PageView;\n private readonly editing: () => Editing;\n private readonly groups: () => GroupLog | undefined;\n /** Steps already done per plan (for put-back), and the versions they made. */\n private readonly done = new Map<string, { step: PendingMove; urn: string }[]>();\n /** A plan's failure panel (Retry, Put back), by plan, closed when the plan finishes or is put back. */\n private readonly failures = new Map<string, PanelHandle>();\n\n /** Creates an item (through the same checks as any create), for an order list's first move. */\n private readonly create: (change: PendingCreate) => Promise<ContentItem>;\n\n constructor(\n ctx: EditorContext,\n view: PageView,\n editing: () => Editing,\n groups: () => GroupLog | undefined,\n create: (change: PendingCreate) => Promise<ContentItem>,\n ) {\n this.ctx = ctx;\n this.create = create;\n this.view = view;\n this.editing = editing;\n this.groups = groups;\n this.panel = new ReorderPanel(ctx.panels);\n }\n\n /** The group an element belongs to, if it is in a list or a table's rows. */\n groupOf(binding: Binding): Group | undefined {\n const entityUrn = this.ctx.store.entityFor(binding.scope);\n if (!entityUrn) return undefined;\n const rows = binding.element.closest<HTMLElement>('[data-content-rows]');\n const list = binding.element.closest<HTMLElement>(`[data-${binding.entry.attribute}-list=\"${CSS.escape(binding.name)}\"]`);\n // The nearest container wins: a list inside a table cell is a list.\n if (list && (!rows || rows.contains(list))) return this.listGroup(list, binding, entityUrn);\n if (rows) return this.rowsGroup(rows, binding, entityUrn);\n return undefined;\n }\n\n private listGroup(container: HTMLElement, binding: Binding, entityUrn: string): Group {\n const units: Unit[] = [];\n for (const child of container.children) {\n const member = this.ctx.discovery\n .all()\n .find((b) => b.entry === binding.entry && b.name === binding.name && child.contains(b.element) && this.ctx.store.entityFor(b.scope) === entityUrn);\n if (!member) continue;\n const stored = this.ctx.store.itemFor(member);\n // A keyed group (cards, sections) names its key on the element, so a member is ordered before its item exists.\n const key = member.element.getAttribute('data-section');\n if (!stored?.item.urn && key === null) continue; // A placeholder list entry has nothing to move yet.\n const value = stored?.item.urn ? String((stored.item as { value?: unknown }).value ?? stored.item.name) : key!;\n units.push({\n key: stored?.item.urn ?? `slot:${member.sortOrder}`,\n element: child as HTMLElement,\n bindings: [member],\n sortOrder: member.sortOrder,\n label: key === null ? value : groupLabel(child as HTMLElement, value),\n ...(key !== null ? { detail: ` \u00B7 ${(child.textContent ?? '').trim().replace(/\\s+/g, ' ').slice(0, 70)}\u2026` } : {}),\n ...(stored?.item.urn ? {} : { missing: key! }),\n });\n }\n return { kind: 'list', container, entityUrn, entry: binding.entry, name: binding.name, units };\n }\n\n private rowsGroup(container: HTMLElement, binding: Binding, entityUrn: string): Group {\n const units: Unit[] = [];\n for (const child of container.children) {\n const sortOrder = Number(child.getAttribute('data-content-row'));\n if (!Number.isInteger(sortOrder)) continue;\n const bindings = this.ctx.discovery.all().filter((b) => child.contains(b.element) && this.ctx.store.entityFor(b.scope) === entityUrn);\n const cells = bindings.map((b) => (b.element.textContent ?? '').trim()).filter(Boolean);\n units.push({\n key: `row:${sortOrder}`,\n element: child as HTMLElement,\n bindings,\n sortOrder,\n label: cells[0] ?? `Row ${sortOrder}`,\n detail: cells.length > 1 ? ` \u00B7 ${cells.slice(1).join(' \u00B7 ')}` : '',\n });\n }\n return { kind: 'rows', container, entityUrn, entry: binding.entry, name: binding.name, units };\n }\n\n // ---------------------------------------------------------------------\n // The reorder dialog, and Move up / Move down\n // ---------------------------------------------------------------------\n\n openReorder(binding: Binding): void {\n const group = this.groupOf(binding);\n if (!group || group.units.length === 0) return;\n this.editing().close();\n this.view.rememberOrder(group.container);\n const before = group.units.map((unit) => unit.key);\n const what = group.kind === 'rows' ? 'rows' : group.name === 'sections' ? 'sections' : `\"${group.name}\"`;\n this.panel.open(\n `Reorder ${what}`,\n group.entityUrn,\n group.units.map((unit) => ({ key: unit.key, label: unit.label, sortOrder: unit.sortOrder, ...(unit.detail ? { detail: unit.detail } : {}) })),\n {\n changed: (keys) => this.preview(group, keys),\n cancel: () => {\n this.preview(group, before);\n this.panel.close();\n },\n save: (keys) => void this.saveOrder(group, keys, () => this.panel.close()),\n ...(group.kind === 'list' ? { add: (at, anchor) => void this.insert(group, at, anchor) } : {}),\n },\n );\n }\n\n /** Moves an entry up or down by one, straight away. */\n moveBy(binding: Binding, delta: -1 | 1): void {\n const group = this.groupOf(binding);\n if (!group) return;\n const keys = group.units.map((unit) => unit.key);\n const index = group.units.findIndex((unit) => unit.bindings.includes(binding));\n const target = index + delta;\n if (index < 0 || target < 0 || target >= keys.length) return;\n [keys[index], keys[target]] = [keys[target]!, keys[index]!];\n this.editing().close();\n this.view.rememberOrder(group.container);\n this.preview(group, keys);\n void this.saveOrder(group, keys, () => undefined);\n }\n\n /** Shows an order on the page by moving the entries themselves, or, in live content, by telling the page. */\n private preview(group: Group, keys: string[]): void {\n const byKey = new Map(group.units.map((unit) => [unit.key, unit]));\n if (inLiveContent(group.container)) {\n this.previewLive(group, keys);\n return;\n }\n // The entries' places, in the order they are on the page now (an earlier preview may have moved them).\n const elements = new Set(group.units.map((unit) => unit.element));\n const inPage = [...group.container.children].filter((child) => elements.has(child as HTMLElement));\n const markers = inPage.map((element) => {\n const marker = document.createComment('');\n element.replaceWith(marker);\n return marker;\n });\n keys.forEach((key, index) => markers[index]?.replaceWith(byKey.get(key)!.element));\n }\n\n /**\n * Live content (an island) owns its DOM: each place in the order is sent the\n * item that moves there, and the page re-renders in that order. The original\n * order is sent as restores.\n */\n private previewLive(group: Group, keys: string[]): void {\n const byKey = new Map(group.units.map((unit) => [unit.key, unit]));\n const places = group.units.map((unit) => unit.sortOrder).sort((a, b) => a - b);\n const original = group.units.map((unit) => unit.key);\n const unchanged = keys.every((key, index) => key === original[index]);\n keys.forEach((key, index) => {\n const unit = byKey.get(key)!;\n const binding = unit.bindings[0]!;\n const stored = this.ctx.store.itemFor(binding);\n const item = (stored?.item ?? { name: group.name, value: unit.missing }) as ContentItem;\n this.ctx.live.showAt(binding, places[index]!, unchanged ? undefined : ({ ...item, sortOrder: places[index]! } as ContentItem));\n });\n }\n\n /** Plans the moves for a new order, runs them, and re-tags the entries so each shows its item. */\n private async saveOrder(group: Group, keys: string[], close: () => void): Promise<void> {\n const changes: SortChange[] = reorder(\n group.units.map((unit): Placed => ({ key: unit.key, sortOrder: unit.sortOrder })),\n keys,\n );\n const byKey = new Map(group.units.map((unit) => [unit.key, unit]));\n const missing = group.units.filter((unit) => unit.missing !== undefined);\n if (changes.length === 0 && missing.length === 0) {\n close();\n return;\n }\n const steps: Omit<PendingMove, 'planId' | 'label'>[] = [];\n for (const change of changes) {\n const unit = byKey.get(change.key)!;\n if (unit.missing !== undefined) continue; // Created at its new place below.\n for (const binding of unit.bindings) {\n const stored = this.ctx.store.itemFor(binding);\n if (!stored?.item.urn) continue; // An empty cell has nothing to move.\n steps.push(this.step(binding.entry, stored.item, group.entityUrn, { name: binding.name, sortOrder: change.to }));\n }\n }\n const label = group.kind === 'rows' ? 'Reorder rows' : `Reorder ${group.name}`;\n this.panel.setBusy(true);\n const ok = (await this.runSteps(steps, label)) && (await this.createMissing(group, missing, changes));\n this.panel.setBusy(false);\n if (!ok) {\n // The page shows what was actually saved; the remaining steps stay queued.\n this.preview(group, group.units.map((unit) => unit.key));\n await this.view.refresh(group.entityUrn);\n return;\n }\n // Keep the new order on the page: each moved entry now shows its item at its new sort order.\n if (inLiveContent(group.container)) this.ctx.live.endPreviews();\n else {\n for (const change of changes) {\n for (const binding of byKey.get(change.key)!.bindings) this.view.retag(binding, change.to);\n }\n }\n close();\n await this.view.refresh(group.entityUrn);\n }\n\n /**\n * The first move of a keyed group whose order items do not all exist yet:\n * creates each missing one, holding its key, at its place in the new order.\n * Checked against the latest read, so it never drafts over an item (rule 8).\n */\n private async createMissing(group: Group, missing: Unit[], changes: SortChange[]): Promise<boolean> {\n if (missing.length === 0) return true;\n const { feedback, toolbar } = this.ctx;\n await this.view.refresh(group.entityUrn);\n const to = new Map(changes.map((change) => [change.key, change.to]));\n for (const unit of missing) {\n const sortOrder = to.get(unit.key) ?? unit.sortOrder;\n try {\n await this.create({ kind: 'create', type: group.entry.type, entityUrn: group.entityUrn, name: group.name, sortOrder, value: { value: unit.missing } });\n } catch (error) {\n const failure = await feedback.describe(error, `add ${unit.missing} to ${group.name}`);\n toolbar.showMessage(`Reorder ${group.name}: ${failure.message}`, false, failure.debug);\n return false;\n }\n }\n return true;\n }\n\n // ---------------------------------------------------------------------\n // Keyed groups: the members' tags and their move menu\n // ---------------------------------------------------------------------\n\n /** Every member of a keyed group (cards, sections) on the page, with its place, for its tag. */\n keyedMembers(): { binding: Binding; name: string; index: number; count: number }[] {\n const seen = new Set<HTMLElement>();\n const members: { binding: Binding; name: string; index: number; count: number }[] = [];\n for (const binding of this.ctx.discovery.all()) {\n if (!binding.element.hasAttribute('data-section')) continue;\n const group = this.groupOf(binding);\n if (!group || group.kind !== 'list' || seen.has(group.container)) continue;\n seen.add(group.container);\n group.units.forEach((unit, index) => members.push({ binding: unit.bindings[0]!, name: group.name, index, count: group.units.length }));\n }\n return members;\n }\n\n /**\n * The member's menu: Move previous and Move next swap it with its neighbour\n * on the page, as a preview. Nothing is sent until Save; Revert, Escape, or\n * the popover closing for anything else puts the page back.\n */\n openOrderMenu(binding: Binding): void {\n const group = this.groupOf(binding);\n if (!group || group.units.length < 2) return;\n const { popover } = this.ctx;\n this.editing().close();\n this.view.rememberOrder(group.container);\n const original = group.units.map((unit) => unit.key);\n const unit = group.units.find((u) => u.bindings.includes(binding))!;\n let keys = [...original];\n const labelOf = new Map(group.units.map((u) => [u.key, u.label]));\n const revert = () => {\n this.preview(group, original);\n this.changedOrder();\n };\n const render = () => {\n const index = keys.indexOf(unit.key);\n const changed = keys.some((key, i) => key !== original[i]);\n const move = (delta: -1 | 1) => {\n const next = [...keys];\n [next[index], next[index + delta]] = [next[index + delta]!, next[index]!];\n keys = next;\n this.preview(group, keys);\n this.changedOrder();\n render();\n };\n const previous = keys[index - 1];\n const following = keys[index + 1];\n popover.whenEnded(undefined);\n popover.showChoices(\n unit.element,\n `Order of ${group.name}`,\n `${index + 1} of ${keys.length}`,\n [],\n [\n `${unit.label} is ${index + 1} of ${keys.length}.`,\n previous ? `Before it: ${labelOf.get(previous)}.` : '',\n following ? `After it: ${labelOf.get(following)}.` : '',\n changed ? 'Not saved yet.' : '',\n // Creating the order list on a published entity: new items are live as soon as they are created.\n changed && group.units.some((u) => u.missing !== undefined) && isLive(this.ctx.store.view(group.entityUrn)?.status)\n ? 'This content is published, and this order is new, so it is live as soon as it is saved.'\n : '',\n ]\n .filter(Boolean)\n .join(' '),\n [\n ...(previous ? [{ label: 'Move previous', run: () => move(-1) }] : []),\n ...(following ? [{ label: 'Move next', run: () => move(1) }] : []),\n {\n label: 'Reorder all\u2026',\n run: () => {\n popover.whenEnded(undefined);\n popover.hide();\n revert();\n this.openReorder(binding);\n },\n },\n ...(changed\n ? [\n {\n label: 'Save',\n primary: true,\n run: () => {\n popover.whenEnded(undefined);\n popover.hide();\n void this.saveOrder(group, keys, () => undefined).then(() => this.changedOrder());\n },\n },\n ]\n : []),\n // Last: Escape runs it.\n { label: changed ? 'Revert' : 'Close', run: () => popover.hide() },\n ],\n );\n popover.whenEnded(revert);\n };\n render();\n }\n\n /** Listeners told when a group's order on the page changes (a preview, a revert, a save). */\n private readonly orderListeners = new Set<() => void>();\n\n onOrderChange(listener: () => void): void {\n this.orderListeners.add(listener);\n }\n\n private changedOrder(): void {\n for (const listener of this.orderListeners) listener();\n }\n\n // ---------------------------------------------------------------------\n // Inserting into a list\n // ---------------------------------------------------------------------\n\n /** Makes room if needed, adds a preview entry to the page, and opens the create form for it. */\n private async insert(group: Group, at: InsertAt, anchor: HTMLElement): Promise<void> {\n const items = group.units.map((unit): Placed => ({ key: unit.key, sortOrder: unit.sortOrder }));\n await this.view.refresh(group.entityUrn); // Check occupancy against the latest read.\n const plan = planInsert(items, at);\n const byKey = new Map(group.units.map((unit) => [unit.key, unit]));\n if (plan.shifts.length > 0) {\n const steps = plan.shifts.flatMap((shift) =>\n byKey.get(shift.key)!.bindings.flatMap((binding) => {\n const stored = this.ctx.store.itemFor(binding);\n return stored?.item.urn ? [this.step(binding.entry, stored.item, group.entityUrn, { name: binding.name, sortOrder: shift.to })] : [];\n }),\n );\n if (!(await this.runSteps(steps, `Make room in ${group.name}`))) return;\n for (const shift of plan.shifts) for (const binding of byKey.get(shift.key)!.bindings) this.view.retag(binding, shift.to);\n await this.view.refresh(group.entityUrn); // The new slot is checked against what was just saved.\n }\n if (this.ctx.store.itemAt(group.entityUrn, group.entry, group.name, plan.sortOrder)) {\n this.ctx.toolbar.showMessage(`${group.name} #${plan.sortOrder} is taken. Reopen the list and try again.`);\n return;\n }\n // Preview: a copy of an entry, emptied and pointed at the new slot.\n const model = group.units.at(at.position === 'head' ? 0 : -1)!;\n const reference = at.position === 'after' ? byKey.get(at.key)!.element : model.element;\n const copy = model.element.cloneNode(true) as HTMLElement;\n for (const element of [copy, ...copy.querySelectorAll<HTMLElement>('*')]) {\n element.removeAttribute('style');\n element.removeAttribute('data-baack-state');\n element.removeAttribute(`data-${group.entry.attribute}-urn`);\n if (element.hasAttribute(`data-${group.entry.attribute}-name`)) {\n element.setAttribute(`data-${group.entry.attribute}-sort-order`, String(plan.sortOrder));\n element.setAttribute('data-placeholder', '');\n }\n }\n if (at.position === 'head') group.container.insertBefore(copy, reference);\n else reference.after(copy);\n this.view.track(copy);\n this.panel.close();\n const bound = copy.matches(`[data-${group.entry.attribute}-name]`) ? copy : copy.querySelector<HTMLElement>(`[data-${group.entry.attribute}-name]`);\n void anchor;\n this.editing().open({\n entityUrn: group.entityUrn,\n entry: group.entry,\n name: group.name,\n sortOrder: plan.sortOrder,\n anchor: bound ?? copy,\n binding: undefined,\n });\n }\n\n // ---------------------------------------------------------------------\n // Move or rename (guided relocation)\n // ---------------------------------------------------------------------\n\n async relocate(binding: Binding | undefined, entityUrn: string, entry: TypeEntry, item: ContentItem): Promise<void> {\n const { store } = this.ctx;\n this.editing().close();\n const places = this.ctx.discovery.all().filter((b) => b.entry === entry && b.name === item.name && b.sortOrder === item.sortOrder).length;\n const templates = await templatesUsing(this.ctx, entityUrn, item.name);\n const info = el('div', 'simple-form');\n info.append(\n el('p', 'hint', `${item.name} #${item.sortOrder} is shown in ${places} ${places === 1 ? 'place' : 'places'} on this page. Those places will show the new item there, or a placeholder.`),\n );\n const form = new SimpleForm(\n `Move or rename ${item.name} #${item.sortOrder}`,\n [\n { key: 'name', label: 'Name', value: item.name },\n { key: 'sortOrder', label: 'Sort order', value: String(item.sortOrder) },\n ],\n 'Move',\n (values) => {\n const name = values['name'] ?? '';\n const sortOrder = Number(values['sortOrder']);\n if (!/^[A-Za-z0-9_-]+$/.test(name)) return form.setError('Use letters, numbers, - and _ in the name.');\n if (!Number.isInteger(sortOrder)) return form.setError('The sort order must be a whole number.');\n if (name === item.name && sortOrder === item.sortOrder) return form.setError('That is where it is now.');\n form.setBusy(true, 'Checking\u2026');\n void this.view.refresh(entityUrn).then(async () => {\n form.setBusy(false);\n if (store.itemAt(entityUrn, entry, name, sortOrder) && !swapping) {\n swapping = true;\n form.setError(`${name} #${sortOrder} is taken. Press Move again to swap the two.`);\n return;\n }\n panel.close();\n await this.moveTo(entityUrn, entry, item, { name, sortOrder });\n });\n },\n );\n let swapping = false;\n form.element.insertBefore(info, form.element.querySelector('.error'));\n if (templates.length > 0) {\n form.element.insertBefore(\n el('p', 'issues', `Templates use \"${item.name}\" and would stop showing it if it is renamed: ${templates.join(', ')}.`),\n form.element.querySelector('.error'),\n );\n }\n form.element.insertBefore(\n el('p', 'issues', 'Renaming changes the name every client looks this item up by, including apps this editor cannot see. They break when it is published.'),\n form.element.querySelector('.error'),\n );\n const panel = this.ctx.panels.show(form.element, { entityUrn });\n void binding;\n }\n\n // ---------------------------------------------------------------------\n // Plans: queue, run, retry, put back\n // ---------------------------------------------------------------------\n\n /**\n * Moves or renames an item to a slot, swapping with the item already there.\n * Occupancy is checked against a fresh read first (rule 8). True when done.\n */\n async moveTo(entityUrn: string, entry: TypeEntry, item: ContentItem, to: { name: string; sortOrder: number }): Promise<boolean> {\n await this.view.refresh(entityUrn);\n const occupant = this.ctx.store.itemAt(entityUrn, entry, to.name, to.sortOrder);\n if (occupant?.item.urn === item.urn) return true;\n const steps = occupant\n ? swap({ key: item.urn!, sortOrder: item.sortOrder }, { key: occupant.item.urn!, sortOrder: to.sortOrder }).map((change) =>\n this.step(entry, change.key === item.urn ? item : occupant.item, entityUrn, {\n name: change.key === item.urn ? to.name : item.name,\n sortOrder: change.to,\n }),\n )\n : [this.step(entry, item, entityUrn, to)];\n const label = occupant\n ? `Swap ${item.name} #${item.sortOrder} and ${to.name} #${to.sortOrder}`\n : to.name === item.name\n ? `Move ${item.name} #${item.sortOrder} to #${to.sortOrder}`\n : `Rename ${item.name} to ${to.name}`;\n if (!(await this.runSteps(steps, label))) return false;\n await this.view.refresh(entityUrn);\n return true;\n }\n\n private step(entry: TypeEntry, item: ContentItem, entityUrn: string, to: { name: string; sortOrder: number }): Omit<PendingMove, 'planId' | 'label'> {\n return { kind: 'move', type: entry.type, urn: item.urn!, entityUrn, name: item.name, sortOrder: item.sortOrder, to };\n }\n\n /** Queues the steps as one plan (stashed before any call) and runs it. True when every step is done. */\n private async runSteps(steps: Omit<PendingMove, 'planId' | 'label'>[], label: string): Promise<boolean> {\n if (steps.length === 0) return true;\n const planId = `plan-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 7)}`;\n for (const step of steps) this.ctx.pending.set({ ...step, planId, label });\n return this.run(planId);\n }\n\n /** Runs (or replays) a plan's queued steps in order. */\n async run(planId: string): Promise<boolean> {\n const { pending, transport, toolbar, feedback } = this.ctx;\n const steps = pending.plan(planId);\n if (steps.length === 0) return true;\n const label = steps[0]!.label;\n const entityUrn = steps[0]!.entityUrn;\n const done = this.done.get(planId) ?? [];\n this.done.set(planId, done);\n toolbar.showMessage(`${label}: moving\u2026`, true);\n for (const step of steps) {\n const entry = this.ctx.entry(step.type);\n try {\n const newest = (await transport.history(entry, step.urn)).history[0];\n if (!newest?.urn) throw new Error(`${step.name} #${step.sortOrder} no longer exists`);\n // Replay: already where it should be.\n if (newest.name === step.to.name && newest.sortOrder === step.to.sortOrder) {\n pending.clear(pendingKey(step));\n done.push({ step, urn: newest.urn });\n continue;\n }\n if (newest.urn !== step.urn) throw new Error(`${step.name} #${step.sortOrder} was changed by someone else after this move was planned`);\n const moved = { ...newest, name: step.to.name, sortOrder: step.to.sortOrder } as ContentItem;\n const saved = await transport.update(entry, newest.urn, toRepresentation(entry, moved, valueOf(entry, newest), step.entityUrn));\n if (!saved?.urn) throw new Error('the API returned no URN for the new version');\n pending.clear(pendingKey(step));\n done.push({ step, urn: saved.urn });\n dispatchItemUpdated({ entityUrn: step.entityUrn, oldUrn: step.urn, newUrn: saved.urn, type: entry.type, value: saved });\n } catch (error) {\n const failure = await feedback.describe(error, 'move this item');\n this.showFailure(planId, label, done.length, done.length + pending.plan(planId).length, failure.message, failure.debug, entityUrn);\n if (failure.kind === 'unauthorized') void feedback.promptLogin(failure.message, () => void this.run(planId));\n return false;\n }\n }\n this.groups()?.add({ id: planId, label, entityUrn, versions: done.map((d) => d.urn), at: Date.now() });\n this.done.delete(planId);\n this.closeFailure(planId);\n toolbar.showMessage(`${label}: done. Saved as drafts.`, true, undefined, reviewAction(this.ctx, entityUrn));\n return true;\n }\n\n /** A plan stopped part-way: say what moved, and offer to retry the rest or put the moved items back. */\n private showFailure(planId: string, label: string, moved: number, total: number, message: string, debug: string | undefined, entityUrn: string): void {\n const panel = el('div', 'simple-form');\n panel.append(\n el('div', 'title', `${label} stopped part-way`),\n el('p', 'message', `Moved ${moved} of ${total}. ${message}`),\n ...debugDetails(debug),\n el('p', 'hint', 'The rest is kept with your unsaved changes, in this browser, until you retry or put things back.'),\n );\n const retry = el('button', 'primary', 'Retry');\n retry.type = 'button';\n retry.addEventListener('click', () => void this.run(planId).then(async (ok) => {\n if (ok) await this.refreshAfter(planId);\n }));\n const back = el('button', '', moved > 0 ? 'Put back' : 'Discard this move');\n back.type = 'button';\n back.addEventListener('click', () => void this.putBack(planId));\n const actions = el('div', 'actions');\n actions.append(back, retry);\n panel.append(actions);\n this.closeFailure(planId);\n this.failures.set(planId, this.ctx.panels.show(panel, { entityUrn }));\n }\n\n private closeFailure(planId: string): void {\n this.failures.get(planId)?.close();\n this.failures.delete(planId);\n }\n\n private async refreshAfter(planId: string): Promise<void> {\n void planId;\n for (const urn of this.ctx.store.entities()) await this.view.refresh(urn);\n }\n\n /** Drops the plan's remaining steps and moves what had moved back where it was (each one more version). */\n private async putBack(planId: string): Promise<void> {\n const { pending } = this.ctx;\n const done = this.done.get(planId) ?? [];\n const remaining = pending.plan(planId);\n for (const step of remaining) pending.clear(pendingKey(step));\n const label = remaining[0]?.label ?? done[0]?.step.label ?? 'Move';\n const entityUrn = remaining[0]?.entityUrn ?? done[0]?.step.entityUrn;\n this.done.delete(planId);\n if (done.length === 0) {\n // Nothing had moved: dropping the plan is all there is to do.\n this.closeFailure(planId);\n this.ctx.toolbar.showMessage(`${label}: nothing had moved, so nothing changed. The move is discarded.`, true);\n return;\n }\n const steps = done.map(({ step, urn }) => ({\n kind: 'move' as const,\n type: step.type,\n urn,\n entityUrn: step.entityUrn,\n name: step.to.name,\n sortOrder: step.to.sortOrder,\n to: { name: step.name, sortOrder: step.sortOrder },\n }));\n if (await this.runSteps(steps, `Put back: ${label}`)) {\n this.ctx.toolbar.showMessage(`Put back: ${label}.`, true);\n if (entityUrn) await this.view.refresh(entityUrn);\n }\n }\n}\n\n/** A keyed member's label: its first heading, or else its key. */\nfunction groupLabel(element: HTMLElement, key: string): string {\n const heading = element.querySelector('h1, h2, h3, h4, h5, h6');\n const text = (heading?.textContent ?? '').trim().replace(/\\s+/g, ' ');\n return text || key;\n}\n", "// A small tag on each member of a keyed group (cards, sections) in edit\n// mode, saying it is in an ordered list and where (\"services \u00B7 2 of 3\"),\n// with a \u22EF that opens its move menu. Drawn in the editor's shadow root over\n// the member's top-right corner, so the page's own markup is untouched.\n\nimport type { Binding } from '../core/discovery.ts';\nimport { el, type EditorHost } from './host.ts';\n\nexport interface OrderTag {\n binding: Binding;\n name: string;\n index: number;\n count: number;\n}\n\nexport class OrderTags {\n private readonly layer: HTMLElement;\n private readonly onOpen: (binding: Binding) => void;\n private tags: { binding: Binding; element: HTMLElement; button: HTMLButtonElement }[] = [];\n private frame = 0;\n private readonly resizes = new ResizeObserver(() => this.schedule());\n\n constructor(host: EditorHost, onOpen: (binding: Binding) => void) {\n this.layer = el('div', 'order-tags');\n host.root.append(this.layer);\n this.onOpen = onOpen;\n }\n\n /** Shows a tag on every member, replacing the tags shown before (kept as they are when nothing changed). */\n show(members: OrderTag[]): void {\n const same =\n members.length === this.tags.length &&\n members.every((member, index) => this.tags[index]!.binding === member.binding && this.tags[index]!.button.textContent === text(member));\n if (same) {\n this.place();\n return;\n }\n const focused = this.tags.findIndex((tag) => tag.button.matches(':focus'));\n this.clear();\n for (const member of members) {\n const button = el('button', 'order-tag', text(member));\n button.type = 'button';\n button.setAttribute('aria-label', `Order of ${member.name}: ${member.index + 1} of ${member.count}`);\n button.addEventListener('click', () => this.onOpen(member.binding));\n this.layer.append(button);\n this.tags.push({ binding: member.binding, element: member.binding.element, button });\n this.resizes.observe(member.binding.element);\n }\n if (this.tags.length > 0) {\n window.addEventListener('scroll', this.schedule, true);\n window.addEventListener('resize', this.schedule);\n }\n this.place();\n this.tags[focused]?.button.focus();\n }\n\n clear(): void {\n cancelAnimationFrame(this.frame);\n this.resizes.disconnect();\n window.removeEventListener('scroll', this.schedule, true);\n window.removeEventListener('resize', this.schedule);\n this.layer.replaceChildren();\n this.tags = [];\n }\n\n private readonly schedule = () => {\n cancelAnimationFrame(this.frame);\n this.frame = requestAnimationFrame(() => this.place());\n };\n\n /** Each tag sits just inside its member's top-right corner, and is hidden with it. */\n private place(): void {\n for (const { element, button } of this.tags) {\n const rect = element.getBoundingClientRect();\n button.hidden = element.getClientRects().length === 0;\n button.style.top = `${rect.top + 4}px`;\n button.style.right = `${window.innerWidth - rect.right + 4}px`;\n }\n }\n}\n\nfunction text(member: OrderTag): string {\n return `${member.name} \u00B7 ${member.index + 1} of ${member.count} \u22EF`;\n}\n", "// Versions created together by one operation (a swap, a reorder, a row move)\n// belong together: shown as one in history, and published together. The API\n// has no operation identifier yet (api-changes.md item 4), so groups are kept\n// in this browser, per user.\n\nconst PREFIX = 'baack-editor:groups:';\nconst MAX_GROUPS = 200;\n\nexport interface Group {\n id: string;\n label: string;\n entityUrn: string;\n /** Version URNs the operation created. */\n versions: string[];\n at: number;\n}\n\nexport class GroupLog {\n private readonly key: string;\n\n constructor(userUrn: string) {\n this.key = PREFIX + userUrn;\n }\n\n all(): Group[] {\n try {\n const groups = JSON.parse(window.localStorage.getItem(this.key) ?? '[]') as unknown;\n return Array.isArray(groups) ? (groups as Group[]) : [];\n } catch {\n return [];\n }\n }\n\n /** The group a version belongs to, if any. */\n of(versionUrn: string): Group | undefined {\n return this.all().find((group) => group.versions.includes(versionUrn));\n }\n\n add(group: Group): void {\n try {\n const groups = [...this.all(), group].slice(-MAX_GROUPS);\n window.localStorage.setItem(this.key, JSON.stringify(groups));\n } catch (error) {\n console.warn('Baack editor: could not record which versions belong together.', error);\n }\n }\n}\n", "// The entities a user can pick from: every entity the search finds, used by\n// URN only (the search stays a list of references: it does not render the\n// entities, and typed results may carry no more), each described by its admin\n// read (name, language, variant). Those fields rarely change, so they are\n// cached per URN for a day, in memory and in this browser, and the picker\n// filters from the cache; the editor's own creates are added as they happen.\n\nimport { isBaackApiError, type Entity } from '@baack-software/baack-ts-client';\nimport type { Transport } from './transport.ts';\n\nexport interface EntitySummary {\n urn: string;\n /** The stored name, such as /<company>/content/menu. */\n name: string;\n /** The name as a page path, such as /menu. */\n path: string;\n language: string;\n variant: string;\n}\n\nexport interface EntityListing {\n entities: EntitySummary[];\n /** False when the search was still partial, so some entities may be missing. */\n complete: boolean;\n}\n\ninterface Cached extends EntitySummary {\n at: number;\n}\n\nconst CACHE_KEY = 'baack-editor:entities';\nconst CACHE_MS = 24 * 60 * 60 * 1000;\n/** The API is rate limited (10 requests a second): a few reads at a time leave room for the editor's other calls. */\nconst CONCURRENT_READS = 4;\n/** A read refused for the rate (429) is tried again after these waits. */\nconst RETRY_DELAYS_MS = [500, 2000];\n\n/** An entity name as a page path: names are scoped as /<company>/content<path>. */\nexport function displayPath(name: string): string {\n return name.replace(/^\\/[^/]+\\/content(?=\\/|$)/, '') || '/';\n}\n\nexport class EntityDirectory {\n private readonly transport: Transport;\n private readonly owners: () => Promise<string[]>;\n private readonly cache = new Map<string, Cached>();\n /** Per user, like the stash of unsent edits. */\n private readonly key: string;\n private search: Promise<{ urns: string[]; complete: boolean }> | undefined;\n\n constructor(transport: Transport, owners: () => Promise<string[]>, userUrn: string | undefined) {\n this.transport = transport;\n this.owners = owners;\n this.key = `${CACHE_KEY}:${userUrn ?? 'anonymous'}`;\n try {\n const stored = JSON.parse(localStorage.getItem(this.key) ?? '[]') as Cached[];\n for (const entry of stored) if (Date.now() - entry.at < CACHE_MS) this.cache.set(entry.urn, entry);\n } catch {\n // No browser storage (private window, blocked): the cache is per visit.\n }\n }\n\n /** A summary already known, without a request. */\n get(urn: string): EntitySummary | undefined {\n return this.cache.get(urn);\n }\n\n /** A summary from the cache, or from the admin read. */\n async describe(urn: string): Promise<EntitySummary> {\n return this.cache.get(urn) ?? this.remember(await this.transport.readEntity(urn));\n }\n\n /** Adds an entity read or created elsewhere, and includes it in the listing. */\n remember(entity: Entity): EntitySummary {\n const summary: Cached = {\n urn: entity.urn,\n name: entity.name,\n path: displayPath(entity.name),\n language: entity.language,\n variant: entity.variant ?? '',\n at: Date.now(),\n };\n this.cache.set(summary.urn, summary);\n this.search = this.search?.then((found) => ({ ...found, urns: found.urns.includes(summary.urn) ? found.urns : [...found.urns, summary.urn] }));\n this.save();\n return summary;\n }\n\n /**\n * Every entity, sorted by path then language. Cached summaries come at\n * once; the rest are read a few at a time, with `onUpdate` called as they\n * arrive. An entity that can no longer be read (deleted, or no access) is\n * left out; any other failure rejects once the rest are in.\n */\n async list(onUpdate?: (listing: EntityListing) => void): Promise<EntityListing> {\n this.search ??= this.searchAll().catch((error: unknown) => {\n this.search = undefined; // Searched again next time.\n throw error;\n });\n const { urns, complete } = await this.search;\n const listing = (): EntityListing => ({\n entities: urns.flatMap((urn) => this.cache.get(urn) ?? []).sort(compare),\n complete,\n });\n const missing = urns.filter((urn) => !this.fresh(urn));\n if (missing.length > 0) onUpdate?.(listing());\n let failure: unknown;\n const next = [...missing];\n const worker = async () => {\n for (let urn = next.shift(); urn; urn = next.shift()) {\n try {\n this.remember(await this.readWithRetry(urn));\n onUpdate?.(listing());\n } catch (error) {\n if (!(isBaackApiError(error) && error.isNotFound)) failure ??= error;\n }\n }\n };\n await Promise.all(Array.from({ length: Math.min(CONCURRENT_READS, missing.length) }, worker));\n if (failure) throw failure;\n const result = listing();\n onUpdate?.(result);\n return result;\n }\n\n private async readWithRetry(urn: string): Promise<Entity> {\n for (const delay of RETRY_DELAYS_MS) {\n try {\n return await this.transport.readEntity(urn);\n } catch (error) {\n if (!(isBaackApiError(error) && error.status === 429)) throw error;\n await new Promise((resolve) => setTimeout(resolve, delay));\n }\n }\n return this.transport.readEntity(urn);\n }\n\n private async searchAll(): Promise<{ urns: string[]; complete: boolean }> {\n const results = await Promise.all((await this.owners()).map((owner) => this.transport.searchEntities(owner)));\n return { urns: [...new Set(results.flatMap((result) => result.urns))], complete: results.every((result) => result.complete) };\n }\n\n private fresh(urn: string): boolean {\n const cached = this.cache.get(urn);\n return cached !== undefined && Date.now() - cached.at < CACHE_MS;\n }\n\n private save(): void {\n try {\n localStorage.setItem(this.key, JSON.stringify([...this.cache.values()]));\n } catch {\n // No browser storage: the cache is per visit.\n }\n }\n}\n\nfunction compare(a: EntitySummary, b: EntitySummary): number {\n return a.path.localeCompare(b.path) || a.language.localeCompare(b.language) || a.variant.localeCompare(b.variant);\n}\n", "// Which entity name serves a page, when the page does not say\n// (`data-entity-urn`). Baack has no index concept: an entity has a name of its\n// own, and lists are separate entity lists. A page at a directory path (`/`,\n// implicitly `/index.html`, or `/docs/`) is served by an entity named for it in\n// the site's own stack, so the URL path is not always the entity name. Baack's\n// sites name the home page's entity `/home`. A suffix such as `/index` or\n// `/index.html` is allowed too, for routers that build straight from the page\n// path: entities are not HTML, so the name is the site's choice.\n\n/** The entity name for the home page by default. */\nexport const HOME_ENTITY_NAME = '/home';\n\n/** The site's own rule (`entityNameForPage` in the config), or the default. */\nexport type EntityNameForPage = (pathname: string) => string;\n\n/**\n * The default rule: `/` and `/index.html` are `/home`; otherwise the path\n * without `index.html` or a trailing slash (`/docs/` is `/docs`).\n */\nexport function defaultEntityName(pathname: string): string {\n const path = pathname.replace(/\\/index\\.html?$/, '/').replace(/\\/+$/, '');\n return path === '' ? HOME_ENTITY_NAME : path;\n}\n\n/** The site's own rule for the page an entity serves (`pagePathForEntity` in the config), or the default. */\nexport type PagePathForEntity = (name: string) => string;\n\n/**\n * The default page address for an entity (its name without the company\n * prefix): `/home` is `/`; any other name is its own path. Used where the\n * editor offers a page address, such as a link's suggestions and what\n * `afterPublish` is told.\n */\nexport function defaultPagePath(name: string): string {\n return name === HOME_ENTITY_NAME ? '/' : name;\n}\n\n/** An entity name may not end in `/`: there is no index entity to name that way. */\nexport function isIndexName(name: string): boolean {\n return name.endsWith('/');\n}\n", "// Getting content into Baack: finding or creating the entity for a page that\n// has none, creating any other entity (a shared menu), and starting a new page\n// from an existing one. The API is\n// micro-request: an entity is created first, then each item with\n// `entity: {urn}`. Entity creation is not idempotent, so every create button\n// is disabled while its request is in flight.\n\nimport { isBaackApiError, type ClientContext, type Company, type Entity } from '@baack-software/baack-ts-client';\nimport { displayPath } from './core/entity-directory.ts';\nimport { SCOPE_ATTRIBUTE } from './core/discovery.ts';\nimport { toRepresentation, valueOf, type ContentItem, type TypeEntry } from './core/registry.ts';\nimport type { Store } from './core/store.ts';\nimport type { Transport } from './core/transport.ts';\nimport { SimpleForm } from './ui/form.ts';\nimport { el } from './ui/host.ts';\nimport { describeFailure } from './ui/messages.ts';\nimport { defaultEntityName, isIndexName, type EntityNameForPage } from './page-entity.ts';\nimport type { Panels } from './targets.ts';\nimport type { Toolbar } from './ui/toolbar.ts';\n\nexport interface OnboardingDeps {\n transport: Transport;\n toolbar: Toolbar;\n context: ClientContext;\n registry: readonly TypeEntry[];\n store: Store;\n panels: Panels;\n /** The site's rule for the entity name serving a page (config), if it has one. */\n entityNameForPage?: EntityNameForPage | undefined;\n /** Opens an entity's level in the sidebar. */\n openEntity(entityUrn: string): void;\n report(error: unknown, action: string, retry: () => void): Promise<void>;\n /** An entity was created (for the entity picker's list). */\n created(entity: Entity): void;\n}\n\nexport interface NewEntityOptions {\n title: string;\n submitLabel: string;\n /** The starting path, such as /menu. */\n path: string;\n /** Default: \"Path, such as /menu\". */\n pathLabel?: string;\n /** A line above the fields. */\n hint?: string;\n language: string;\n variant?: string;\n onCreated(entity: Entity): void;\n onCancel?(): void;\n}\n\nexport class Onboarding {\n private readonly deps: OnboardingDeps;\n\n constructor(deps: OnboardingDeps) {\n this.deps = deps;\n }\n\n /** The page shows items but names no entity: find it by path, or offer to create it. */\n async offerEntityForPage(): Promise<void> {\n const { transport, panels } = this.deps;\n // Not the URL path itself: `/` has no entity of that name (see page-entity.ts).\n const path = (this.deps.entityNameForPage ?? defaultEntityName)(location.pathname);\n const language = document.documentElement.lang || 'en-GB';\n try {\n const entity = await transport.entityView(path, { version: 'LATEST', language });\n const panel = el('div', 'simple-form');\n panel.append(\n el('div', 'title', 'Content for this page exists'),\n el('p', 'hint', `Add this to the page's root element so the editor and the site can find it:`),\n snippet(entity.urn),\n );\n const use = el('button', 'primary', 'Use it for this visit');\n use.type = 'button';\n use.addEventListener('click', () => {\n document.documentElement.setAttribute(SCOPE_ATTRIBUTE, entity.urn);\n handle.close();\n });\n panel.append(actions(use));\n const handle = panels.show(panel);\n } catch (error) {\n if (isBaackApiError(error) && error.isNotFound) {\n await this.showCreateEntity(path, language);\n } else {\n void this.deps.report(error, 'look up this page', () => void this.offerEntityForPage());\n }\n }\n }\n\n private async showCreateEntity(path: string, language: string): Promise<void> {\n const { panels } = this.deps;\n const form = await this.newEntityForm({\n title: 'This page has no content in Baack yet',\n submitLabel: 'Create content for this page',\n path,\n pathLabel: 'Name of this page\\'s content',\n hint: `No content named ${path} (${language}) was found for ${location.pathname}.`,\n language,\n onCreated: (entity) => {\n const done = el('div', 'simple-form');\n done.append(\n el('div', 'title', 'Content created (in draft)'),\n el('p', 'hint', `Add this to the page's root element. Until then, the editor uses it for this visit:`),\n snippet(entity.urn),\n el('p', 'hint', 'Next: create the items this page shows, with \"Create all\" on its content.'),\n );\n const next = el('button', 'primary', 'Show its items');\n next.type = 'button';\n next.addEventListener('click', () => this.deps.openEntity(entity.urn));\n done.append(actions(next));\n panels.show(done);\n document.documentElement.setAttribute(SCOPE_ATTRIBUTE, entity.urn);\n },\n });\n panels.show(form.element);\n }\n\n /** \"New entity\u2026\": any entity, such as a menu shared by many pages, created empty in draft. */\n async offerNewEntity(language: string): Promise<void> {\n const { panels } = this.deps;\n const form = await this.newEntityForm({\n title: 'New entity',\n submitLabel: 'Create entity',\n path: '',\n language,\n onCreated: (entity) => {\n const done = el('div', 'simple-form');\n const urn = el('pre', 'snippet', entity.urn);\n const copy = el('button', '', 'Copy URN');\n copy.type = 'button';\n copy.addEventListener('click', () => {\n navigator.clipboard?.writeText(entity.urn).then(\n () => (copy.textContent = 'Copied'),\n () => (copy.textContent = 'Select and copy it'),\n );\n });\n // Back to where New entity was chosen; the sidebar's own Close hides the sidebar.\n const close = el('button', '', 'Done');\n close.type = 'button';\n close.addEventListener('click', () => shown.close());\n done.append(\n el('div', 'title', `Created ${displayPath(entity.name)} (${entity.language}) in draft`),\n el('p', 'hint', 'Choose it in a reference item, or use its URN in the site:'),\n urn,\n actions(copy, close),\n );\n const shown = panels.show(done);\n },\n });\n panels.show(form.element);\n }\n\n /**\n * The form for creating an entity: path, language, variant, and the owner\n * when there is a choice. It refuses a path, language and variant that\n * already has an entity, found by reading the view (a 404 means none).\n */\n async newEntityForm(options: NewEntityOptions): Promise<SimpleForm> {\n const { transport } = this.deps;\n const owners = await this.owners();\n const form = new SimpleForm(\n options.title,\n [\n { key: 'name', label: options.pathLabel ?? 'Path, such as /menu', value: options.path },\n { key: 'language', label: 'Language', value: options.language },\n { key: 'variant', label: 'Variant (optional)', value: options.variant ?? '' },\n ...(owners.length > 1\n ? [{ key: 'owner', label: 'Owner', value: owners[0]!.urn, options: owners.map((c) => ({ value: c.urn, label: c.name ?? c.urn })) }]\n : []),\n ],\n options.submitLabel,\n (values) => {\n const owner = values['owner'] ?? owners[0]?.urn;\n const name = values['name'] ?? '';\n const language = values['language'] ?? '';\n const variant = values['variant'] ?? '';\n if (!owner) return form.setError('No company was found to own the content.');\n if (!name.startsWith('/')) return form.setError('The path must start with /, like /menu.');\n if (isIndexName(name)) return form.setError(`Content has no index: give it a name of its own, without a trailing /, such as ${defaultEntityName(name)}.`);\n if (!language) return form.setError('Enter a language, such as en-GB.');\n form.setError('');\n form.setBusy(true, 'Creating\u2026');\n this.existing(name, language, variant)\n .then((found) => {\n if (found) {\n form.setBusy(false);\n form.setError(`${name} (${language}${variant ? ` \u00B7 ${variant}` : ''}) already exists.`);\n return;\n }\n return transport.createEntity({ owner: { urn: owner }, status: 'DRAFT_UNPUBLISHED', name, language, variant }).then((entity) => {\n this.deps.created(entity);\n options.onCreated(entity);\n });\n })\n .catch((error: unknown) => {\n // Not retried automatically: a retry could create a second entity.\n form.setBusy(false);\n form.setError(describeFailure(error, 'create the entity').message);\n });\n },\n options.onCancel,\n );\n if (options.hint) form.element.insertBefore(el('p', 'hint', options.hint), form.element.querySelector('label'));\n return form;\n }\n\n /** The entity already at a path, language and variant, if any. The view may answer another language's, which does not count. */\n private async existing(path: string, language: string, variant: string): Promise<Entity | undefined> {\n try {\n const entity = await this.deps.transport.entityView(path, { version: 'LATEST', language, variant });\n const same = displayPath(entity.name) === path && entity.language.toLowerCase() === language.toLowerCase() && (entity.variant ?? '') === variant;\n return same ? entity : undefined;\n } catch (error) {\n if (isBaackApiError(error) && error.isNotFound) return undefined;\n throw error;\n }\n }\n\n /** A new entity with the same owner, language and variant, filled with this one's items. */\n offerNewPageLike(entityUrn: string): void {\n const { transport, panels, store, context } = this.deps;\n const view = store.view(entityUrn);\n if (!view) return;\n const form = new SimpleForm(\n 'New page like this',\n [{ key: 'name', label: 'Path of the new page', value: '' }],\n 'Create page',\n (values) => {\n const name = values['name'] ?? '';\n const owner = view.raw.owner?.urn ?? context.company?.urn;\n if (!name.startsWith('/')) return form.setError('The path must start with /, like /blog/new-post.');\n if (isIndexName(name)) return form.setError(`Content has no index: give it a name of its own, without a trailing /, such as ${defaultEntityName(name)}.`);\n if (!owner) return form.setError('No company was found to own the content.');\n form.setError('');\n form.setBusy(true, 'Creating\u2026');\n transport\n .createEntity({ owner: { urn: owner }, status: 'DRAFT_UNPUBLISHED', name, language: view.language, variant: view.variant ?? '' })\n .then((created) => this.copyItems(entityUrn, created.urn, name, 0))\n .catch((error: unknown) => {\n form.setBusy(false);\n form.setError(describeFailure(error, 'create the page').message);\n });\n },\n );\n panels.show(form.element, { entityUrn });\n }\n\n /** Posts the source entity's items to the new one, one by one, from `start`. */\n private async copyItems(sourceUrn: string, targetUrn: string, path: string, start: number): Promise<void> {\n const { transport, panels, store, registry } = this.deps;\n const view = store.view(sourceUrn)!;\n const items: [TypeEntry, ContentItem][] = registry.flatMap((entry) =>\n ((view.raw[entry.entityArray] ?? []) as ContentItem[]).map((item): [TypeEntry, ContentItem] => [entry, item]),\n );\n const progress = el('p', 'hint');\n progress.setAttribute('role', 'status');\n const panel = el('div', 'simple-form');\n panel.append(el('div', 'title', `Creating ${path}`), progress);\n panels.show(panel, { entityUrn: sourceUrn });\n\n for (let index = start; index < items.length; index += 1) {\n const [entry, item] = items[index]!;\n progress.textContent = `Copying item ${index + 1} of ${items.length}\u2026`;\n try {\n // The view holds renderings of markdown and templates; copy their source.\n const value = entry.renderedByView ? valueOf(entry, await transport.read(entry, item.urn!)) : valueOf(entry, item);\n const slot = { name: item.name, sortOrder: item.sortOrder } as ContentItem;\n await transport.create(entry, toRepresentation(entry, slot, value, targetUrn));\n } catch (error) {\n progress.textContent = `Copied ${index} of ${items.length}. ${describeFailure(error, `copy ${item.name}`).message}`;\n const retry = el('button', 'primary', 'Copy the rest');\n retry.type = 'button';\n // Safe to repeat: a create at an existing name and sort order drafts over that item.\n retry.addEventListener('click', () => void this.copyItems(sourceUrn, targetUrn, path, index));\n panel.append(actions(retry));\n return;\n }\n }\n const link = el('a', '', `Open ${path}`);\n link.href = path;\n progress.textContent = `Created ${path} in draft with ${items.length} items. Images need their files uploaded again. A site built ahead of time shows the page after its next build.`;\n panel.append(actions(link));\n }\n\n private async owners(): Promise<Company[]> {\n const fallback = this.deps.context.company ? [this.deps.context.company] : [];\n try {\n const companies = await this.deps.transport.companies();\n const preferred = this.deps.context.company?.urn;\n return companies.length > 0\n ? [...companies].sort((a, b) => (a.urn === preferred ? -1 : b.urn === preferred ? 1 : 0))\n : fallback;\n } catch {\n return fallback;\n }\n }\n}\n\nfunction snippet(urn: string): HTMLElement {\n const wrapper = el('div', 'simple-form');\n const code = el('pre', 'snippet', `<html data-entity-urn=\"${urn}\">`);\n const copy = el('button', '', 'Copy');\n copy.type = 'button';\n copy.addEventListener('click', () => {\n navigator.clipboard?.writeText(`data-entity-urn=\"${urn}\"`).then(\n () => (copy.textContent = 'Copied'),\n () => (copy.textContent = 'Select and copy it'),\n );\n });\n wrapper.append(code, actions(copy));\n return wrapper;\n}\n\nfunction actions(...children: HTMLElement[]): HTMLElement {\n const row = el('div', 'actions');\n row.append(...children);\n return row;\n}\n", "// The Review level (docs/plans/single-sidebar.md): every change that will go\n// live, and the Schedule level it drills into.\n\nimport type { DiffPart } from '../core/diff.ts';\nimport { renderChange } from './change.ts';\nimport { el } from './host.ts';\nimport { tooltip } from './tooltip.ts';\n\nexport interface ReviewChange {\n name: string;\n sortOrder: number;\n type: string;\n /** `changed` includes a move or rename with the value unchanged: the move is then the `change`. */\n kind: 'changed' | 'new' | 'removed';\n change: DiffPart[] | string;\n /** Beside a changed value: \"moved #1 \u2192 #0 (\u22121)\", \"renamed from \u2026\". */\n notes?: string[];\n /** Opens the item's history. */\n select?(): void;\n}\n\nexport interface ReviewModel {\n changes: ReviewChange[];\n /** Problems that stop publishing. */\n blockers: string[];\n warnings: string[];\n /** Publish, or request approval when the user cannot publish. */\n confirmLabel: string;\n note?: string;\n}\n\nexport interface ReviewActions {\n confirm(button: HTMLButtonElement): void;\n /** Drills into the Schedule level; only when the content can be scheduled. */\n schedule?(): void;\n}\n\n/**\n * Fills the Review level's body: what blocks or warns, every change that\n * will go live, then Publish (or Request approval) and Schedule\u2026. Closing is\n * Back or the sidebar's Close: a Cancel beside the changes would read as\n * abandoning them, which is a different action.\n */\nexport function renderReview(body: HTMLElement, model: ReviewModel, actions: ReviewActions): void {\n const status = el('p', 'hint', model.note ?? '');\n status.setAttribute('role', 'status');\n const parts: HTMLElement[] = [status];\n for (const blocker of model.blockers) parts.push(el('p', 'error', blocker));\n for (const warning of model.warnings) parts.push(el('p', 'issues', warning));\n\n const list = el('ul', 'rows');\n list.setAttribute('aria-label', 'Changes that will go live');\n for (const change of model.changes) {\n const row = el('li', 'row history-row');\n const head = el('div', 'row-main');\n const name = change.select ? el('button', 'row-name link', change.name) : el('span', 'row-name', change.name);\n if (name instanceof HTMLButtonElement) {\n name.type = 'button';\n tooltip(name, 'Show its history');\n name.addEventListener('click', () => change.select?.());\n }\n head.append(\n name,\n el('span', 'meta', ` #${change.sortOrder} \u00B7 ${change.type}`),\n el('span', `status status-${change.kind === 'changed' ? 'unpublished-changes' : 'note'}`, change.kind),\n ...(change.notes ?? []).map((note) => el('span', 'status note move', note)),\n );\n row.append(head, renderChange(change.change));\n list.append(row);\n }\n if (model.changes.length === 0) parts.push(el('p', 'hint', 'Nothing has changed since the last publish.'));\n parts.push(list);\n\n const buttons = el('div', 'actions');\n if (actions.schedule) {\n const run = actions.schedule;\n const schedule = el('button', '', 'Schedule\u2026');\n schedule.type = 'button';\n tooltip(schedule, 'Publish at a later time');\n schedule.disabled = model.blockers.length > 0;\n schedule.addEventListener('click', () => run());\n buttons.append(schedule);\n }\n const confirm = el('button', 'primary', model.confirmLabel);\n confirm.type = 'button';\n confirm.disabled = model.blockers.length > 0;\n confirm.addEventListener('click', () => actions.confirm(confirm));\n buttons.append(confirm);\n parts.push(buttons);\n body.replaceChildren(...parts);\n}\n\n/**\n * Fills the Schedule level: when to publish, in the user's local time, and\n * the button that schedules it. Only content that has never been public can\n * be scheduled.\n */\nexport function renderSchedule(body: HTMLElement, label: string, schedule: (at: string, button: HTMLButtonElement) => void, cancel: () => void): void {\n const hint = el('p', 'hint', 'The content goes live by itself at this time. Until then it stays a draft, and you can cancel the schedule.');\n const field = el('label', 'field');\n const at = el('input');\n at.type = 'datetime-local';\n field.append(el('span', 'caption', 'Publish at (your local time)'), at);\n const buttons = el('div', 'actions');\n const back = el('button', '', 'Cancel');\n back.type = 'button';\n back.addEventListener('click', cancel);\n const confirm = el('button', 'primary', label);\n confirm.type = 'button';\n confirm.disabled = true;\n at.addEventListener('input', () => (confirm.disabled = !at.value));\n confirm.addEventListener('click', () => schedule(at.value, confirm));\n buttons.append(back, confirm);\n body.replaceChildren(hint, field, buttons);\n}\n", "// The entity lifecycle: the status the server reports (never one the editor\n// expects, CLAUDE.md rule 7), the verbs available from it, polling while a\n// publish is in flight, the review, and requests for approval. The review,\n// the schedule and going back to draft are sidebar levels above the entity's\n// (docs/plans/single-sidebar.md).\n\nimport type { Entity } from '@baack-software/baack-ts-client';\nimport { parseTimestamp } from '@baack-software/baack-ts-components/format';\nimport { diffWords, type DiffPart } from './core/diff.ts';\nimport { dispatchEntityPublished, dispatchEntityState } from './core/events.ts';\nimport { sameValue, valueOf, type ContentItem, type TypeEntry } from './core/registry.ts';\nimport { summarise, summariseChange } from './saving.ts';\nimport { isLive, lifecycleLabel, pageFirst, type EditorContext } from './targets.ts';\nimport { el } from './ui/host.ts';\nimport { renderReview, renderSchedule, type ReviewChange } from './ui/review-view.ts';\nimport { confirmLevel, type Level, type SidebarStack } from './ui/stack.ts';\nimport type { LifecycleRow } from './ui/toolbar.ts';\nimport type { PageView } from './view.ts';\n\n/** Seconds between status reads while publishing: quick at first, then every 15 seconds. */\nconst BACKOFF = [1, 2, 4, 8, 15];\n\ninterface Tracked {\n status: Entity['status'];\n /** When this entity was first seen in PUBLISH, to notice one that is stuck. */\n publishingSince?: number;\n timer?: ReturnType<typeof setTimeout>;\n attempt: number;\n}\n\nexport interface PublishingHooks {\n /** Shows a level in the sidebar above an entity's level. */\n show(level: Level, entityUrn: string): void;\n}\n\nexport class Publishing {\n private readonly ctx: EditorContext;\n private readonly stack: SidebarStack;\n private readonly hooks: PublishingHooks;\n /** The Review level in the stack, refreshed in place when the content changed under it. */\n private reviewing: { entityUrn: string; id: string; body: HTMLElement } | undefined;\n private readonly view: PageView;\n private readonly tracked = new Map<string, Tracked>();\n private readonly stuckAfterMs: number;\n private active = false;\n\n constructor(ctx: EditorContext, view: PageView, stuckAfterMs: number, stack: SidebarStack, hooks: PublishingHooks) {\n this.ctx = ctx;\n this.view = view;\n this.stuckAfterMs = stuckAfterMs;\n this.stack = stack;\n this.hooks = hooks;\n // A colleague may have started a transition: re-read when the tab comes back.\n window.addEventListener('focus', () => void this.refreshAll());\n document.addEventListener('visibilitychange', () => {\n if (document.visibilityState === 'visible') void this.refreshAll();\n });\n }\n\n start(): void {\n this.active = true;\n this.render();\n }\n\n stop(): void {\n this.active = false;\n for (const tracked of this.tracked.values()) clearTimeout(tracked.timer);\n this.tracked.clear();\n this.reviewing = undefined;\n this.ctx.toolbar.setLifecycle([]);\n }\n\n /** Content was read: take each entity's status from the view, as the server reported it. */\n changed(): void {\n if (!this.active) return;\n for (const urn of this.ctx.store.entities()) {\n const status = this.ctx.store.view(urn)?.status;\n if (status) this.observe(urn, status);\n }\n this.render();\n }\n\n async refreshAll(): Promise<void> {\n if (!this.active) return;\n await Promise.all(this.ctx.store.entities().map((urn) => this.refreshStatus(urn)));\n }\n\n /** Reads an entity's status from the API. */\n async refreshStatus(entityUrn: string): Promise<void> {\n try {\n const entity = await this.ctx.transport.readEntity(entityUrn);\n this.observe(entityUrn, entity.status, entity.publishTimestamp ?? undefined);\n this.render();\n } catch (error) {\n void this.ctx.feedback.report(error, 'check the publishing status', () => void this.refreshStatus(entityUrn));\n }\n }\n\n private observe(entityUrn: string, status: Entity['status'], publishTimestamp?: string): void {\n const view = this.ctx.store.view(entityUrn);\n if (view) {\n // Other modules read the status from the view; keep it current.\n const raw = view.raw as Entity;\n raw.status = status;\n if (publishTimestamp !== undefined) raw.publishTimestamp = publishTimestamp;\n }\n const tracked = this.tracked.get(entityUrn);\n const previous = tracked?.status;\n const next: Tracked = tracked ?? { status, attempt: 0 };\n next.status = status;\n if (status === 'PUBLISH') {\n next.publishingSince ??= Date.now();\n this.poll(entityUrn, next);\n } else {\n clearTimeout(next.timer);\n delete next.timer;\n delete next.publishingSince;\n next.attempt = 0;\n }\n this.tracked.set(entityUrn, next);\n if (previous !== undefined && previous !== status) {\n dispatchEntityState({ entityUrn, status, previous });\n if (previous === 'PUBLISH' && isLive(status)) this.published(entityUrn);\n }\n }\n\n /** A publish finished: say so, and re-read so the page, Items and history show the new live versions. */\n private published(entityUrn: string): void {\n dispatchEntityPublished(entityUrn);\n this.ctx.announcePublished(entityUrn, `${this.ctx.entityTitle(entityUrn)} is published.`, { quiet: true });\n void this.view.refresh(entityUrn);\n }\n\n /** While publishing, read the status again with backoff until it settles. Scheduled entities are not polled. */\n private poll(entityUrn: string, tracked: Tracked): void {\n if (tracked.timer) return;\n const seconds = BACKOFF[Math.min(tracked.attempt, BACKOFF.length - 1)]!;\n tracked.attempt += 1;\n tracked.timer = setTimeout(() => {\n delete tracked.timer;\n if (this.active) void this.refreshStatus(entityUrn);\n }, seconds * 1000);\n }\n\n private render(): void {\n if (!this.active) return;\n const rows: LifecycleRow[] = pageFirst(this.ctx.store, this.ctx.store.entities()).map((urn) => this.row(urn));\n this.ctx.toolbar.setLifecycle(rows);\n }\n\n private row(entityUrn: string): LifecycleRow {\n const { canPublish } = this.ctx;\n const view = this.ctx.store.view(entityUrn);\n const status = this.tracked.get(entityUrn)?.status ?? view?.status;\n const title = this.ctx.entityTitle(entityUrn);\n const publish = canPublish ? 'Publish\u2026' : 'Request approval\u2026';\n const review = canPublish ? 'Review and publish\u2026' : 'Request approval\u2026';\n const row: LifecycleRow = { entityUrn, title, label: lifecycleLabel(status), verbs: [] };\n switch (status) {\n case 'DRAFT_UNPUBLISHED':\n row.verbs.push({ label: publish, primary: true, run: () => void this.openReview(entityUrn) });\n break;\n case 'PUBLISH_PENDING': {\n const at = view?.raw.publishTimestamp;\n if (at) row.label = `Scheduled for ${new Date(parseTimestamp(at)).toLocaleString()}`;\n if (canPublish) row.verbs.push({ label: 'Cancel schedule', run: () => this.confirmDraft(entityUrn, 'Cancel the schedule?') });\n break;\n }\n case 'PUBLISH': {\n const since = this.tracked.get(entityUrn)?.publishingSince ?? Date.now();\n if (Date.now() - since > this.stuckAfterMs) {\n row.note = 'Publishing is taking longer than expected. Publishing again is safe; if that does not help, contact support.';\n if (canPublish) row.verbs.push({ label: 'Publish again', run: () => void this.setStatus(entityUrn, 'PUBLISH', undefined) });\n }\n break;\n }\n case 'PUBLISHED_WITH_DRAFTS':\n row.verbs.push({ label: review, primary: true, run: () => void this.openReview(entityUrn) });\n if (canPublish) row.verbs.push({ label: 'Unpublish', run: () => this.confirmDraft(entityUrn, 'Unpublish this content?') });\n break;\n case 'PUBLISHED':\n if (canPublish) row.verbs.push({ label: 'Unpublish', run: () => this.confirmDraft(entityUrn, 'Unpublish this content?') });\n break;\n default:\n break;\n }\n return row;\n }\n\n /** Back to draft: not public, not deleted. Used for unpublishing and for cancelling a schedule. */\n private confirmDraft(entityUrn: string, question: string): void {\n this.hooks.show(\n confirmLevel({\n id: `draft:${entityUrn}`,\n title: question,\n meta: this.ctx.entityTitle(entityUrn),\n blocks: [],\n description: 'The content stays in Baack but is no longer public. You can publish it again, now or at a later time.',\n choices: [\n { label: 'Cancel', run: () => this.stack.pop() },\n {\n label: 'Back to draft',\n primary: true,\n run: (button) => {\n button.disabled = true;\n void this.setStatus(entityUrn, 'DRAFT_UNPUBLISHED', undefined).then((done) => {\n if (done) this.stack.popTo(`entity:${entityUrn}`);\n else button.disabled = false;\n });\n },\n },\n ],\n }),\n entityUrn,\n );\n }\n\n // ---------------------------------------------------------------------\n // The review\n // ---------------------------------------------------------------------\n\n /**\n * Opens the Review level for an entity: every change that will go live. A\n * review already in the stack is refreshed in place, with `note` saying why.\n */\n async openReview(entityUrn: string, note?: string): Promise<void> {\n const { store, views, canPublish } = this.ctx;\n const status = store.view(entityUrn)?.status;\n if (status === 'PUBLISH') return; // No verbs during a verb state.\n let live: Entity | undefined;\n try {\n live = await views.read(entityUrn);\n } catch {\n live = undefined; // Never published, or not public (in this language): everything is new.\n }\n const latest = store.view(entityUrn)!.raw;\n const shown = latestUrns(latest, this.ctx.registry);\n const changes = await this.changes(entityUrn, latest, live);\n const { blockers, warnings } = await this.checks(latest);\n const id = `review:${entityUrn}`;\n const count = `${changes.length} ${changes.length === 1 ? 'change' : 'changes'}`;\n const existing = this.reviewing?.id === id && this.stack.path.includes(id) ? this.reviewing : undefined;\n const body = existing?.body ?? el('div', 'level-review');\n renderReview(\n body,\n {\n changes,\n blockers,\n warnings,\n confirmLabel: canPublish ? `Publish ${count}` : 'Request approval',\n ...(note ? { note } : {}),\n },\n {\n confirm: (button) => void this.confirm(entityUrn, shown, changes, undefined, button),\n // Only content that has never been public can go live at a later time.\n ...(canPublish && status === 'DRAFT_UNPUBLISHED' ? { schedule: () => this.stack.push(this.scheduleLevel(entityUrn, shown, changes, `Schedule ${count}`)) } : {}),\n },\n );\n if (existing) {\n this.stack.popTo(id);\n return;\n }\n this.reviewing = { entityUrn, id, body };\n const path = this.ctx.entityTitle(entityUrn).replace(/^Content for /, '');\n this.hooks.show(\n {\n id,\n title: `${canPublish ? 'Review and publish' : 'Request approval for'} ${path}`,\n render: () => body,\n dispose: () => {\n if (this.reviewing?.body === body) this.reviewing = undefined;\n },\n },\n entityUrn,\n );\n }\n\n private scheduleLevel(entityUrn: string, shown: Set<string>, changes: ReviewChange[], label: string): Level {\n const body = el('div', 'level-schedule');\n renderSchedule(body, label, (at, button) => void this.confirm(entityUrn, shown, changes, at, button), () => this.stack.pop());\n return { id: `schedule:${entityUrn}`, title: 'Schedule the publish', render: () => body };\n }\n\n /** Re-checks before sending: if any version differs from the list shown, refresh the list instead. */\n private async confirm(entityUrn: string, shown: Set<string>, changes: ReviewChange[], at: string | undefined, button: HTMLButtonElement): Promise<void> {\n const { views, feedback, canPublish } = this.ctx;\n button.disabled = true;\n try {\n const fresh = await views.read(entityUrn, { version: 'LATEST' });\n const now = latestUrns(fresh, this.ctx.registry);\n if (now.size !== shown.size || [...now].some((urn) => !shown.has(urn))) {\n await this.view.refresh(entityUrn);\n await this.openReview(entityUrn, 'The content changed while you were reviewing. Check the list again before publishing.');\n return;\n }\n if (canPublish) {\n const when = at ? new Date(at).toISOString().replace('Z', '') : undefined;\n if (!(await this.setStatus(entityUrn, 'PUBLISH', when))) {\n button.disabled = false;\n return;\n }\n } else {\n await this.requestApproval(entityUrn, changes);\n }\n // Done: back to the entity, where the lifecycle shows what the server reports.\n this.stack.popTo(`entity:${entityUrn}`);\n } catch (error) {\n button.disabled = false;\n void feedback.report(error, canPublish ? 'publish' : 'request approval', () => void this.confirm(entityUrn, shown, changes, at, button));\n }\n }\n\n /** Sends a lifecycle verb with the entity's own fields: never the item arrays. False when it failed (and was reported). */\n private async setStatus(entityUrn: string, status: 'PUBLISH' | 'DRAFT_UNPUBLISHED', publishTimestamp: string | undefined): Promise<boolean> {\n const { transport, feedback } = this.ctx;\n try {\n const entity = await transport.readEntity(entityUrn);\n const updated = await transport.updateEntity(entityUrn, {\n owner: { urn: entity.owner!.urn },\n name: entity.name,\n language: entity.language,\n variant: entity.variant ?? '',\n status,\n ...(publishTimestamp ? { publishTimestamp } : {}),\n });\n const before = this.tracked.get(entityUrn)?.status;\n this.observe(entityUrn, updated.status, updated.publishTimestamp ?? undefined);\n // A publish that completes in the request answers a live status straight away, never PUBLISH.\n if (status === 'PUBLISH' && before !== 'PUBLISH' && isLive(updated.status)) {\n if (updated.status === 'PUBLISHED') {\n this.published(entityUrn);\n } else {\n // Still with drafts after publishing: show what the server reports, not what was expected (rule 7).\n this.ctx.announcePublished(entityUrn, `${this.ctx.entityTitle(entityUrn)} was published, but some changes are still not live.`, { info: false });\n void this.view.refresh(entityUrn);\n }\n }\n this.render();\n if (status === 'DRAFT_UNPUBLISHED') await this.view.refresh(entityUrn);\n return true;\n } catch (error) {\n void feedback.report(error, status === 'PUBLISH' ? 'publish' : 'move the content back to draft', () =>\n void this.setStatus(entityUrn, status, publishTimestamp),\n );\n return false;\n }\n }\n\n /** For users who cannot publish: a task linked to the entity, listing the changes. */\n private async requestApproval(entityUrn: string, changes: ReviewChange[]): Promise<void> {\n const { transport, store, toolbar } = this.ctx;\n const view = store.view(entityUrn)!;\n const owner = view.raw.owner?.urn;\n const path = this.ctx.entityTitle(entityUrn).replace(/^Content for /, '');\n const lines = changes.map((change) => `- ${change.name} #${change.sortOrder} (${change.type}): ${change.kind}`);\n const task = await transport.createTask({\n ...(owner ? { owner: { urn: owner } as never } : {}),\n title: `Review and publish ${path}`,\n description: [`Page: ${location.href}`, `Entity: ${entityUrn}`, '', 'Changes:', ...lines].join('\\n'),\n status: 'PENDING',\n priority: 'MEDIUM',\n associatedEntities: [{ urn: entityUrn } as never],\n });\n toolbar.showMessage(`Approval requested (task ${task.urn?.slice(0, 8) ?? ''}).`, true);\n }\n\n // ---------------------------------------------------------------------\n // Building the review list\n // ---------------------------------------------------------------------\n\n /**\n * Every change that will go live, item by item. A draft is compared with\n * its own live version, found through its history, so a moved or renamed\n * item reads as a move (\"#1 \u2192 #0 (\u22121)\") rather than as a different value\n * in the slot. Without a readable history, the live item in the same slot\n * stands in.\n */\n private async changes(entityUrn: string, latest: Entity, live: Entity | undefined): Promise<ReviewChange[]> {\n // A draft's name opens its history above the review, so Back returns to the review.\n const select = (entry: TypeEntry, item: ContentItem) => () =>\n item.urn ? this.ctx.hooks.openHistory({ entityUrn, entry, name: item.name, sortOrder: item.sortOrder, urn: item.urn }) : undefined;\n const changes: ReviewChange[] = [];\n for (const entry of this.ctx.registry) {\n const latestItems = (latest[entry.entityArray] ?? []) as ContentItem[];\n const liveItems = (live?.[entry.entityArray] ?? []) as ContentItem[];\n const liveByUrn = new Map(liveItems.map((item) => [item.urn, item]));\n const slot = (item: ContentItem) => `${item.name}#${item.sortOrder}`;\n const liveBySlot = new Map(liveItems.map((item) => [slot(item), item]));\n const drafts = latestItems.filter((item) => !liveByUrn.has(item.urn));\n const befores = await Promise.all(drafts.map((item) => this.liveVersionOf(entry, item, liveByUrn, liveBySlot.get(slot(item)))));\n const accounted = new Set<string | undefined>(latestItems.filter((item) => liveByUrn.has(item.urn)).map((item) => item.urn));\n drafts.forEach((item, index) => {\n const before = befores[index];\n if (before) accounted.add(before.urn);\n const notes = before ? moveNotes(before, item) : [];\n const valueChanged = !before || !sameValue(entry, valueOf(entry, before), valueOf(entry, item));\n changes.push({\n name: item.name,\n sortOrder: item.sortOrder,\n type: entry.label,\n kind: !before ? 'new' : 'changed',\n // A move or rename alone is the change itself (\"Moved #3 \u2192 #2 (\u22121)\"); beside a new value it is a note.\n change: valueChanged ? describe(entry, before, item) : sentence(notes.join('; ')),\n ...(valueChanged && notes.length > 0 ? { notes } : {}),\n select: select(entry, item),\n });\n });\n for (const item of liveItems) {\n if (!accounted.has(item.urn) && !latestItems.some((other) => slot(other) === slot(item))) {\n changes.push({ name: item.name, sortOrder: item.sortOrder, type: entry.label, kind: 'removed', change: describe(entry, item, undefined) });\n }\n }\n }\n return changes;\n }\n\n /** The live version of a draft's item: the newest version in its history that is live, else the live item in its slot. */\n private async liveVersionOf(\n entry: TypeEntry,\n draft: ContentItem,\n liveByUrn: Map<string | undefined, ContentItem>,\n inSlot: ContentItem | undefined,\n ): Promise<ContentItem | undefined> {\n try {\n const { history, pagination } = await this.ctx.transport.history(entry, draft.urn!);\n const found = history.find((version) => liveByUrn.has(version.urn));\n if (found) return liveByUrn.get(found.urn);\n // No live version in the history: the item is new, unless older pages could still hold one.\n return pagination?.isMorePages ? inSlot : undefined;\n } catch {\n return inSlot;\n }\n }\n\n /** Blockers (an image without its file) and warnings (referenced content that is not fully published). */\n private async checks(latest: Entity): Promise<{ blockers: string[]; warnings: string[] }> {\n const blockers = (latest.images ?? []).flatMap((image) =>\n missingSlots(image, this.ctx.requiredImageSlots).map(\n (slot) => `${image.name} #${image.sortOrder} has no ${slot === 'DEFAULT' ? 'image' : slot.toLowerCase()} file. Upload one before publishing.`,\n ),\n );\n const warnings: string[] = [];\n for (const reference of latest.references ?? []) {\n const urn = reference.entityReference?.urn;\n if (!urn) continue;\n try {\n const referenced = await this.ctx.transport.readEntity(urn);\n if (referenced.status === 'DRAFT_UNPUBLISHED' || referenced.status === 'PUBLISHED_WITH_DRAFTS') {\n warnings.push(`${reference.name} refers to content that ${referenced.status === 'DRAFT_UNPUBLISHED' ? 'is not published' : 'has unpublished changes'} (${referenced.name}).`);\n }\n } catch {\n warnings.push(`${reference.name} refers to content that could not be checked.`);\n }\n }\n return { blockers, warnings };\n }\n}\n\n/** The required slots an image version has no file for. */\nexport function missingSlots(image: object, required: readonly ('DEFAULT' | 'MEDIUM' | 'LARGE')[]): ('DEFAULT' | 'MEDIUM' | 'LARGE')[] {\n const fields = { DEFAULT: 'src', MEDIUM: 'mediumSrc', LARGE: 'largeSrc' } as const;\n return required.filter((slot) => !(image as Record<string, unknown>)[fields[slot]]);\n}\n\n/** Every version URN in an entity view. */\nfunction latestUrns(entity: Entity, registry: readonly TypeEntry[]): Set<string> {\n const urns = new Set<string>();\n for (const entry of registry) {\n for (const item of (entity[entry.entityArray] ?? []) as ContentItem[]) if (item.urn) urns.add(item.urn);\n }\n return urns;\n}\n\n/** What readers will see change: a word diff of text, or of the rendered text for markdown and templates. */\nfunction describe(entry: TypeEntry, before: ContentItem | undefined, after: ContentItem | undefined): DiffPart[] | string {\n const text = (item: ContentItem | undefined) => {\n const value = (item as { value?: unknown } | undefined)?.value;\n if (typeof value !== 'string') return undefined;\n return entry.renderedByView ? (new DOMParser().parseFromString(value, 'text/html').body.textContent ?? '') : value;\n };\n const was = text(before);\n const now = text(after);\n if (was !== undefined || now !== undefined) return diffWords(was ?? '', now ?? '');\n if (!before) return summarise(entry, after!);\n if (!after) return `Removed: ${summarise(entry, before)}`;\n return summariseChange(entry, before, after);\n}\n\n/** \"renamed from \u2026\" and \"moved #1 \u2192 #0 (\u22121)\", comparing a draft with its live version. */\nconst sentence = (text: string) => text.charAt(0).toUpperCase() + text.slice(1);\n\nfunction moveNotes(before: ContentItem, after: ContentItem): string[] {\n const notes: string[] = [];\n if (before.name !== after.name) notes.push(`renamed from ${before.name}`);\n const delta = after.sortOrder - before.sortOrder;\n if (delta !== 0) notes.push(`moved #${before.sortOrder} \u2192 #${after.sortOrder} (${delta > 0 ? '+' : '\u2212'}${Math.abs(delta)})`);\n return notes;\n}\n", "// The item outline: every item an entity holds, grouped by where it shows,\n// with status and flags. Built from the entity view, not the DOM, so it\n// reaches items with no element (head, JSON, references, hidden content).\n//\n// It is explored as a stack (docs/plans/single-sidebar.md): the page's\n// entities, then one entity (its lifecycle and items), and deeper levels on\n// top. The stack is the editor's one sidebar, the \"Editor\" landmark.\n\nimport { button as actionButton, el, type EditorHost, variantOf } from './host.ts';\nimport { SidebarStack } from './stack.ts';\n\nexport interface OutlineAction {\n label: string;\n run(anchor: HTMLElement): void;\n primary?: boolean;\n /** Shown as a destructive button: it deletes or discards. */\n destructive?: boolean;\n /** Why it cannot be used now; the button is disabled with this as its title. */\n disabled?: string;\n}\n\nexport interface OutlineRow {\n name: string;\n sortOrder: number;\n type: string;\n /** Publication status; empty when it would say nothing (the entity is not live). */\n status: string;\n /** Neutral notes, such as \"not used\". */\n notes?: string[];\n /** Problems worth fixing. */\n flags: string[];\n /** Opens the item: scroll to it and edit, or edit beside the row. */\n select?(anchor: HTMLElement): void;\n action?: OutlineAction;\n /** More actions, after `action`. */\n actions?: OutlineAction[];\n /** The row the view is about, highlighted (for example the item being moved). */\n current?: boolean;\n}\n\nexport interface OutlineGroup {\n label: string;\n /** One line explaining the group. */\n hint?: string;\n rows: OutlineRow[];\n action?: OutlineAction;\n}\n\nexport interface OutlineSection {\n /** The entity's lifecycle state, from the server. */\n subtitle?: string;\n /** More about the state, such as a publish taking too long. */\n note?: string;\n /** The lifecycle's verbs (publish, unpublish, schedule). */\n verbs?: OutlineAction[];\n groups: OutlineGroup[];\n actions: OutlineAction[];\n}\n\nexport class Outline {\n readonly stack: SidebarStack;\n private readonly onOpen: () => void;\n\n /** `onOpen` runs whenever the sidebar comes on screen; `onClose` when it is closed. */\n constructor(host: EditorHost, onOpen: () => void, onClose: () => void = () => {}) {\n this.onOpen = onOpen;\n this.stack = new SidebarStack(host);\n this.stack.element.classList.add('outline');\n this.stack.onClose(onClose);\n }\n\n get element(): HTMLElement {\n return this.stack.element;\n }\n\n /** The sidebar is on screen. */\n get isOpen(): boolean {\n return this.stack.isOpen;\n }\n\n open(): void {\n this.stack.open();\n this.onOpen();\n }\n\n close(): void {\n this.stack.close();\n }\n\n /** Focuses the filter of the level on screen, if it has one. */\n focusFilter(): void {\n this.element.querySelector<HTMLElement>('.stack-level:not([hidden]) input[type=\"search\"]')?.focus();\n }\n\n /**\n * Fills an entity level's body: its lifecycle, a filter, its groups of\n * items, then its actions. The filter's text is kept across refreshes.\n */\n renderSection(body: HTMLElement, section: OutlineSection): void {\n const filter = body.querySelector<HTMLInputElement>('input[type=\"search\"]')?.value ?? '';\n const parts: HTMLElement[] = [];\n if (section.subtitle || section.verbs?.length) {\n const lifecycle = el('div', 'level-lifecycle');\n lifecycle.setAttribute('role', 'group');\n lifecycle.setAttribute('aria-label', 'Lifecycle');\n if (section.subtitle) lifecycle.append(el('p', 'section-status lifecycle-status', section.subtitle));\n if (section.note) lifecycle.append(el('p', 'message', section.note));\n if (section.verbs?.length) {\n const verbs = el('div', 'actions');\n verbs.append(...section.verbs.map((verb) => this.button(verb)));\n lifecycle.append(verbs);\n }\n parts.push(lifecycle);\n }\n const input = el('input');\n input.type = 'search';\n input.placeholder = 'Filter by name or type';\n input.setAttribute('aria-label', 'Filter items');\n input.value = filter;\n input.addEventListener('input', () => applyFilter(body, input.value));\n parts.push(input);\n for (const group of section.groups) {\n if (group.rows.length === 0) continue;\n const groupElement = el('div', 'outline-group');\n const heading = el('div', 'group-heading');\n heading.append(el('span', 'group-label', `${group.label} (${group.rows.length})`));\n if (group.action) heading.append(this.button(group.action));\n groupElement.append(heading);\n if (group.hint) groupElement.append(el('p', 'group-hint', group.hint));\n const list = el('ul', 'rows');\n list.setAttribute('aria-label', group.label);\n list.append(...group.rows.map((row) => this.row(row)));\n groupElement.append(list);\n parts.push(groupElement);\n }\n if (section.actions.length > 0) {\n const actions = el('div', 'actions');\n actions.append(...section.actions.map((action) => this.button(action)));\n parts.push(actions);\n }\n body.replaceChildren(...parts);\n applyFilter(body, filter);\n body.querySelector('li.row.current')?.scrollIntoView({ block: 'nearest' });\n }\n\n private row(row: OutlineRow): HTMLElement {\n const item = el('li', row.current ? 'row current' : 'row');\n if (row.current) item.setAttribute('aria-current', 'true');\n item.dataset['filter'] = `${row.name} ${row.type}`.toLowerCase();\n const main = el(row.select ? 'button' : 'div', 'row-main');\n if (main instanceof HTMLButtonElement) {\n main.type = 'button';\n main.dataset['row'] = '';\n main.addEventListener('click', () => row.select?.(item));\n }\n main.append(\n el('span', 'row-name', row.name),\n el('span', 'meta', ` #${row.sortOrder} \u00B7 ${row.type}`),\n ...(row.status ? [el('span', `status status-${row.status.replace(/\\s+/g, '-')}`, row.status)] : []),\n ...(row.notes ?? []).map((note) => el('span', 'status note', note)),\n );\n item.append(main);\n for (const flag of row.flags) item.append(el('span', 'flag', flag));\n if (row.action) item.append(this.button(row.action));\n for (const action of row.actions ?? []) item.append(this.button(action));\n return item;\n }\n\n private button(action: OutlineAction): HTMLButtonElement {\n const button = actionButton(action.label, variantOf(action), 'sm');\n if (action.disabled) {\n button.disabled = true;\n button.title = action.disabled;\n }\n button.addEventListener('click', () => action.run(button));\n return button;\n }\n}\n\nfunction applyFilter(body: HTMLElement, value: string): void {\n const query = value.trim().toLowerCase();\n for (const row of body.querySelectorAll<HTMLElement>('li.row')) {\n row.hidden = query !== '' && !row.dataset['filter']!.includes(query);\n }\n}\n", "// Builds the item outline from the latest views, the page's elements, the\n// live views (for publication status) and unsaved work.\n\nimport { createKey } from './core/pending.ts';\nimport type { ContentItem, ItemType, TypeEntry } from './core/registry.ts';\nimport type { Editing } from './editing.ts';\nimport type { Onboarding } from './onboarding.ts';\nimport type { Saving } from './saving.ts';\nimport { isLive, lifecycleLabel, pageEntity, pageFirst, type EditTarget, type EditorContext, type PanelHandle, type PanelOptions, type Slot } from './targets.ts';\nimport { missingSlots } from './publishing.ts';\nimport { SimpleForm } from './ui/form.ts';\nimport { el } from './ui/host.ts';\nimport { Outline, type OutlineAction, type OutlineRow, type OutlineSection } from './ui/outline.ts';\nimport { drillRow, type Level } from './ui/stack.ts';\nimport type { PageView } from './view.ts';\nimport { tooltip } from './ui/tooltip.ts';\n\n// Something that looks like a tag, for the outline's flag.\nconst MARKUP = /<\\/?[a-z!][^>]*>/i;\n\nexport class OutlineModel {\n readonly outline: Outline;\n private readonly ctx: EditorContext;\n private readonly view: PageView;\n private readonly editing: Editing;\n private readonly saving: Saving;\n private readonly onboarding: Onboarding;\n /** Reads for publication status, by entity: see `counterpartUrns`. */\n private readonly live = new Map<string, Promise<{ urns: Set<string>; found: boolean }>>();\n /** Move or rename: the slots level shows one name's slots, with this sort order highlighted. */\n private focus: Slot | undefined;\n /** An item to highlight and scroll to in its entity's level. */\n private selected: Slot | undefined;\n /** The levels built for the stack, by id, each with the body it refreshes. */\n private readonly levels = new Map<string, { level: Level; body: HTMLElement; refresh(): Promise<void> | void }>();\n private closed: (() => void) | undefined;\n /** Panels shown so far, for their level ids. */\n private panels = 0;\n /** Offers \"New entity\u2026\" on the top level, while editing the latest drafts. */\n private newEntity: (() => void) | undefined;\n\n constructor(ctx: EditorContext, view: PageView, editing: Editing, saving: Saving, onboarding: Onboarding) {\n this.ctx = ctx;\n this.view = view;\n this.editing = editing;\n this.saving = saving;\n this.onboarding = onboarding;\n this.outline = new Outline(\n ctx.host,\n () => {\n if (this.outline.stack.path.length === 0) this.openAt(pageEntity(ctx.store), { focus: false });\n else void this.render();\n },\n () => {\n this.focus = undefined;\n this.selected = undefined;\n this.closed?.();\n },\n );\n }\n\n /** Runs when the sidebar closes (a preview shown from it ends). */\n onClose(listener: () => void): void {\n this.closed = listener;\n }\n\n /** Content changed; re-read live status for an entity that was re-read. */\n changed(entityUrn?: string): void {\n if (entityUrn) this.live.delete(entityUrn);\n if (this.outline.isOpen) void this.render();\n }\n\n clear(): void {\n this.outline.close();\n this.outline.stack.reset([]);\n this.levels.clear();\n this.live.clear();\n this.focus = undefined;\n }\n\n setNewEntity(run: (() => void) | undefined): void {\n this.newEntity = run;\n if (this.outline.isOpen) void this.render();\n }\n\n /** Shows Items at the page's entity (or where it was left), or closes it when it is on screen. */\n toggle(): void {\n if (this.outline.isOpen) this.outline.close();\n else this.outline.open();\n }\n\n /** Opens the stack at an entity's level, above the page's level. */\n openEntity(entityUrn: string): void {\n this.selected = undefined;\n this.focus = undefined;\n this.openAt(entityUrn);\n }\n\n /** Opens Items with an item highlighted and scrolled to. */\n selectItem(slot: Slot): void {\n this.focus = undefined;\n this.selected = { entityUrn: slot.entityUrn, entry: slot.entry, name: slot.name, sortOrder: slot.sortOrder };\n this.openAt(slot.entityUrn);\n }\n\n /** Opens Items on the slots of an item's name, to move it among them or rename it. */\n focusSlot(slot: Slot): void {\n this.focus = { entityUrn: slot.entityUrn, entry: slot.entry, name: slot.name, sortOrder: slot.sortOrder };\n this.openAt(slot.entityUrn, { slots: true });\n }\n\n /**\n * Shows a level above an entity's (an item's history, its review, a\n * confirm): drilled into from the entity's level or its review when one of\n * those is on screen, so Back returns there; otherwise the stack is built\n * to it.\n */\n showAbove(entityUrn: string, level: Level): void {\n const { stack } = this.outline;\n const from = [`entity:${entityUrn}`, `review:${entityUrn}`];\n if (this.outline.isOpen && from.includes(stack.current?.id ?? '')) {\n stack.push(level);\n return;\n }\n this.focus = undefined;\n this.selected = undefined;\n this.openAt(entityUrn, { above: level });\n }\n\n /** Shows a task as a level (see `Panels` in targets.ts). */\n showPanel(content: HTMLElement, options: PanelOptions = {}): PanelHandle {\n const { stack } = this.outline;\n const heading = content.querySelector(':scope > .title');\n const title = options.title ?? heading?.textContent ?? 'Editor';\n if (!options.title) heading?.remove();\n this.panels += 1;\n const id = `panel:${this.panels}`;\n let open = true;\n const level: Level = {\n id,\n title,\n render: () => content,\n dispose: () => {\n open = false;\n options.onLeave?.();\n },\n };\n const handle: PanelHandle = {\n get isOpen() {\n return open;\n },\n close: () => {\n const path = stack.path;\n const index = path.indexOf(id);\n if (index > 0) stack.popTo(path[index - 1]!);\n },\n };\n content.addEventListener('cancel', () => handle.close());\n const focus = options.focus ?? true;\n const showing = this.outline.isOpen && stack.path.length > 0;\n if (showing && stack.current?.id.startsWith('panel:')) {\n stack.replace(level, { focus });\n } else if (showing && (!options.entityUrn || stack.path.includes(`entity:${options.entityUrn}`))) {\n // From wherever the user is in that entity: Back returns there.\n stack.push(level, { focus });\n } else {\n this.focus = undefined;\n this.selected = undefined;\n this.openAt(options.entityUrn, { above: level, focus });\n }\n return handle;\n }\n\n private openAt(entityUrn: string | undefined, { slots = false, focus = true, above = undefined as Level | undefined } = {}): void {\n const path = [this.pageLevel()];\n if (entityUrn && this.ctx.store.view(entityUrn)) path.push(this.entityLevel(entityUrn));\n if (slots && this.focus) path.push(this.slotsLevel(this.focus));\n if (above) path.push(above);\n this.outline.stack.reset(path, { focus });\n this.outline.open();\n void this.render();\n }\n\n /** Refreshes the levels in the stack from the current state. */\n async render(): Promise<void> {\n if (!this.outline.isOpen) return;\n await Promise.all(this.outline.stack.path.map((id) => this.levels.get(id)?.refresh()));\n }\n\n private remember(level: Level, body: HTMLElement, refresh: () => Promise<void> | void): Level {\n this.levels.set(level.id, { level, body, refresh });\n return level;\n }\n\n /** The top level: the entities in this visit, page's first, with their state; New entity. */\n private pageLevel(): Level {\n const body = el('div', 'level-page');\n const level: Level = { id: 'page', title: 'This page', render: () => body };\n return this.remember(level, body, () => {\n const { store, toolbar } = this.ctx;\n const entities = pageFirst(store, store.entities());\n const parts: HTMLElement[] = entities.map((urn) =>\n drillRow(this.ctx.entityTitle(urn), toolbar.lifecycleOf(urn)?.label ?? lifecycleLabel(store.view(urn)?.status), () =>\n this.outline.stack.push(this.entityLevel(urn)),\n ),\n );\n if (entities.length === 0) parts.push(el('p', 'hint', 'No content has loaded for this page.'));\n if (this.newEntity) {\n const run = this.newEntity;\n const button = el('button', '', 'New entity\u2026');\n button.type = 'button';\n tooltip(button, 'Create an entity, such as a menu shared by many pages');\n button.addEventListener('click', () => run());\n const actions = el('div', 'actions');\n actions.append(button);\n parts.push(actions);\n }\n body.replaceChildren(...parts);\n });\n }\n\n /** One entity: its lifecycle and verbs, then its items. */\n private entityLevel(entityUrn: string): Level {\n const id = `entity:${entityUrn}`;\n const known = this.levels.get(id);\n if (known) return known.level;\n const body = el('div', 'level-entity');\n const level: Level = { id, title: this.ctx.entityTitle(entityUrn), render: () => body, onShow: () => void this.render() };\n return this.remember(level, body, async () => {\n if (!this.ctx.store.view(entityUrn)) return;\n const section = await this.section(entityUrn, entityUrn === pageEntity(this.ctx.store));\n if (this.outline.stack.path.includes(id)) this.outline.renderSection(body, section);\n });\n }\n\n /** Toggles the unsent changes, above the page's level: shown, or closed when already on screen. */\n togglePending(): void {\n if (this.outline.isOpen && this.outline.stack.current?.id === 'unsaved') {\n this.outline.close();\n return;\n }\n this.focus = undefined;\n this.selected = undefined;\n this.outline.stack.reset([this.pageLevel(), this.pendingLevel()]);\n this.outline.open();\n }\n\n /** Every entity's unsent changes, each with Save all and Discard all; kept current as they change. */\n private pendingLevel(): Level {\n const body = el('div', 'level-unsaved');\n const level: Level = { id: 'unsaved', title: 'Unsaved changes', render: () => body };\n return this.remember(level, body, () => body.replaceChildren(...this.ctx.toolbar.pendingSections()));\n }\n\n /** Move or rename: the slots of one name. */\n private slotsLevel(focus: Slot): Level {\n const body = el('div', 'level-slots');\n const level: Level = { id: 'slots', title: `Slots for ${focus.name}`, render: () => body };\n return this.remember(level, body, () => {\n if (!this.focus || !this.ctx.store.view(this.focus.entityUrn)) return;\n this.outline.renderSection(body, this.slotsSection(this.focus));\n });\n }\n\n /**\n * Every slot of one name in sort order: filled ones and free ones (the gaps,\n * when there are few, and the next after the last). The item being moved is\n * highlighted; it can swap with a filled slot, move to a free one, or be\n * renamed. Each move checks occupancy against a fresh read first.\n */\n private slotsSection(focus: Slot): OutlineSection {\n const { store, hooks } = this.ctx;\n const { entityUrn, entry, name } = focus;\n const items = ((store.view(entityUrn)!.raw[entry.entityArray] ?? []) as ContentItem[])\n .filter((item) => item.name === name && item.urn)\n .sort((a, b) => a.sortOrder - b.sortOrder);\n const moving = items.find((item) => item.sortOrder === focus.sortOrder);\n const move = async (sortOrder: number) => {\n if (!moving) return;\n if (await hooks.moveSlot(focus, moving, sortOrder)) {\n this.focus = { ...focus, sortOrder };\n void this.render();\n }\n };\n const rows: OutlineRow[] = items.map((item) =>\n item === moving\n ? {\n name,\n sortOrder: item.sortOrder,\n type: entry.label,\n status: 'moving',\n flags: [],\n current: true,\n actions: [{ label: 'Rename\u2026', run: () => hooks.rename(focus, item) }],\n }\n : {\n name,\n sortOrder: item.sortOrder,\n type: entry.label,\n status: '',\n flags: [],\n ...(moving ? { actions: [{ label: `Swap with #${moving.sortOrder}`, run: () => void move(item.sortOrder) }] } : {}),\n },\n );\n if (moving) {\n const used = new Set(items.map((item) => item.sortOrder));\n const first = items[0]?.sortOrder ?? 0;\n const last = items.at(-1)?.sortOrder ?? 0;\n const gaps = Array.from({ length: Math.max(0, last - first) }, (_, index) => first + index).filter((order) => !used.has(order));\n for (const sortOrder of [...(gaps.length <= 5 ? gaps : []), last + 1]) {\n rows.push({ name, sortOrder, type: entry.label, status: 'empty', flags: [], actions: [{ label: 'Move here', run: () => void move(sortOrder) }] });\n }\n rows.sort((a, b) => a.sortOrder - b.sortOrder);\n }\n return {\n subtitle: moving ? `Moving ${name} #${moving.sortOrder}. Swap it with another, move it to a free sort order, or rename it.` : `${name} #${focus.sortOrder} is no longer here.`,\n groups: [{ label: `Slots for ${name}`, rows }],\n actions: [\n {\n label: 'Show all items',\n run: () => {\n this.focus = undefined;\n this.outline.stack.popTo(`entity:${entityUrn}`);\n },\n },\n ],\n };\n }\n\n private async section(entityUrn: string, isRoot: boolean): Promise<OutlineSection> {\n const { store, pending, registry } = this.ctx;\n const view = store.view(entityUrn)!;\n const { urns: counterpart, found } = await this.counterpartUrns(entityUrn);\n // Live when the status says so, or a live view exists (an entity that is publishing, or stuck publishing, still has one).\n const published = this.view.mode === 'live' ? !this.view.draftsOnLivePage.has(entityUrn) : isLive(view.status) || found;\n const onPage: OutlineRow[] = [];\n const settings: OutlineRow[] = [];\n const unused: OutlineRow[] = [];\n\n for (const entry of registry) {\n const items = (view.raw[entry.entityArray] ?? []) as ContentItem[];\n for (const item of items) {\n if (!item.urn) continue;\n const slot: Slot = { entityUrn, entry, name: item.name, sortOrder: item.sortOrder };\n const bindings = this.view.bindingsAt(slot);\n const visible = bindings.filter((b) => !b.element.closest('head'));\n const duplicates = items.filter((other) => other.name === item.name && other.sortOrder === item.sortOrder).length;\n const urn = item.urn;\n const row: OutlineRow = {\n name: item.name,\n sortOrder: item.sortOrder,\n type: entry.label,\n // Lifecycle comes from the server: per-item status only means something once the entity is live.\n status: pending.getEdit(urn) ? 'unsaved' : !published ? '' : counterpart.has(urn) ? 'up to date' : 'unpublished changes',\n flags: [\n ...flags(entry, item, duplicates, this.ctx.requiredImageSlots),\n ...(bindings.some((b) => b.element.hasAttribute('data-text-unsafe-literal')) ? ['the site renders this as HTML'] : []),\n ],\n action: { label: 'History', run: () => this.ctx.hooks.openHistory({ ...slot, urn }) },\n ...this.referenceAction(item),\n current: isSlot(this.selected, slot),\n select: (anchor) => {\n const target: EditTarget = { ...slot, urn, anchor, binding: visible[0] };\n if (visible[0]) visible[0].element.scrollIntoView({ block: 'center' });\n this.editing.open(visible[0] && visible[0].element.getClientRects().length > 0 ? target : { ...target, binding: undefined });\n },\n };\n if (visible.length > 0) onPage.push(row);\n else if (bindings.length > 0 || !entry.component) settings.push(row);\n else unused.push({ ...row, notes: ['not used'] });\n }\n }\n\n const missing: OutlineRow[] = this.view.missingBindings(entityUrn).map((binding) => {\n const key = createKey({ entityUrn, type: binding.entry.type, name: binding.name, sortOrder: binding.sortOrder });\n return {\n name: binding.name,\n sortOrder: binding.sortOrder,\n type: binding.entry.label,\n status: pending.getCreate(key) ? 'unsaved' : 'not in content',\n flags: [],\n current: isSlot(this.selected, { entityUrn, entry: binding.entry, name: binding.name, sortOrder: binding.sortOrder }),\n action: {\n label: 'Create',\n // The page's element supplies the placeholder value; the form opens beside the row.\n run: (anchor) => {\n if (binding.element.getClientRects().length > 0) binding.element.scrollIntoView({ block: 'center' });\n this.editing.open({ entityUrn, entry: binding.entry, name: binding.name, sortOrder: binding.sortOrder, anchor, binding });\n },\n },\n };\n });\n\n const lifecycle = this.ctx.toolbar.lifecycleOf(entityUrn);\n return {\n subtitle: lifecycle?.label ?? lifecycleLabel(view.status),\n ...(lifecycle?.note ? { note: lifecycle.note } : {}),\n verbs: (lifecycle?.verbs ?? []).map((verb): OutlineAction => ({\n label: verb.label,\n run: () => verb.run(),\n ...(verb.primary ? { primary: true } : {}),\n ...(verb.disabled ? { disabled: verb.disabled } : {}),\n })),\n groups: [\n { label: 'On this page', rows: onPage },\n { label: 'Page settings', rows: settings },\n { label: 'Not used on this page', rows: unused, hint: 'In the content, but nothing on this page shows them.' },\n {\n label: 'In the page, not in the content',\n rows: missing,\n hint: 'Content items on the page that are not saved in the content yet. Each shows its placeholder until it is created.',\n action: { label: 'Create all', run: () => this.saving.confirmCreateAll(entityUrn, missing.length) },\n },\n ],\n actions: [\n { label: 'Add item', run: (anchor) => this.showAddItem(entityUrn, anchor) },\n ...(isRoot ? [{ label: 'New page like this', run: () => this.onboarding.offerNewPageLike(entityUrn) }] : []),\n ],\n };\n }\n\n /** A reference to an entity this page has loaded drills into that entity's level. */\n private referenceAction(item: ContentItem): Pick<OutlineRow, 'actions'> {\n const urn = (item as { entityReference?: { urn?: string } }).entityReference?.urn;\n if (!urn || !this.ctx.store.view(urn)) return {};\n const title = this.ctx.entityTitle(urn);\n return { actions: [{ label: `${title} \u203A`, run: () => this.outline.stack.push(this.entityLevel(urn)) }] };\n }\n\n /**\n * Version URNs to compare the shown items with: the live view's while the\n * latest drafts are shown, and the latest drafts' on the live page. An item\n * found in both is up to date; otherwise it has unpublished changes. Empty\n * when the entity has never been published.\n */\n private counterpartUrns(entityUrn: string): Promise<{ urns: Set<string>; found: boolean }> {\n let live = this.live.get(entityUrn);\n if (!live) {\n live = this.ctx.views\n .read(entityUrn, this.view.mode === 'live' ? { version: 'LATEST' } : {})\n .then((entity) => {\n const urns = new Set<string>();\n for (const entry of this.ctx.registry) {\n for (const item of (entity[entry.entityArray] ?? []) as ContentItem[]) if (item.urn) urns.add(item.urn);\n }\n return urns;\n })\n .then((urns) => ({ urns, found: true }))\n .catch(() => ({ urns: new Set<string>(), found: false }));\n this.live.set(entityUrn, live);\n }\n return live;\n }\n\n private showAddItem(entityUrn: string, anchor: HTMLElement): void {\n const { store, registry } = this.ctx;\n const form = new SimpleForm(\n `Add an item to ${this.ctx.entityTitle(entityUrn)}`,\n [\n { key: 'type', label: 'Type', value: 'text', options: registry.map((e) => ({ value: e.type, label: e.label })) },\n { key: 'name', label: 'Name', value: '' },\n { key: 'sortOrder', label: 'Sort order', value: '0' },\n ],\n 'Next',\n (values) => {\n const entry = this.ctx.entry(values['type'] as ItemType);\n const name = values['name'] ?? '';\n const sortOrder = Number(values['sortOrder']);\n if (!/^[A-Za-z0-9_-]+$/.test(name)) return form.setError('Use letters, numbers, - and _ in the name.');\n if (!Number.isInteger(sortOrder)) return form.setError('The sort order must be a whole number.');\n form.setBusy(true, 'Checking\u2026');\n void this.view.refresh(entityUrn).then(() => {\n form.setBusy(false);\n if (store.itemAt(entityUrn, entry, name, sortOrder)) {\n form.setError(`An item already exists at ${name} #${sortOrder}. Choose a free sort order.`);\n return;\n }\n panel.close();\n this.editing.open({ entityUrn, entry, name, sortOrder, anchor, binding: undefined });\n });\n },\n );\n const panel = this.ctx.panels.show(form.element, { entityUrn });\n }\n}\n\nfunction flags(entry: TypeEntry, item: ContentItem, duplicates: number, required: readonly ('DEFAULT' | 'MEDIUM' | 'LARGE')[]): string[] {\n const result: string[] = [];\n if (duplicates > 1) result.push(`${duplicates} items share this sort order`);\n const record = item as unknown as Record<string, unknown>;\n if (entry.type === 'text' && MARKUP.test(String(record['value'] ?? ''))) result.push('contains markup');\n if (entry.type === 'image') {\n if (!record['altText']) result.push('no alt text');\n for (const slot of missingSlots(item, required)) result.push(slot === 'DEFAULT' ? 'no image file' : `no ${slot.toLowerCase()} file`);\n }\n return result;\n}\n\nfunction isSlot(a: Slot | undefined, b: Slot): boolean {\n return a !== undefined && a.entityUrn === b.entityUrn && a.entry === b.entry && a.name === b.name && a.sortOrder === b.sortOrder;\n}\n", "// What the site wants said or done after a publish: the `afterPublish`\n// setting. A site built ahead of time can say when visitors will see the\n// change, or start its own rebuild. The editor's job ends here (plan \u00A715).\n\nimport type { Toolbar } from './ui/toolbar.ts';\n\nexport interface PublishedDetail {\n entityUrn: string;\n /** The entity's name as the API stores it. */\n name: string;\n /** The page path within the name, such as /menu: what a site maps to its routes. */\n path: string;\n /** The entity's language and variant ('' for none). */\n language: string;\n variant: string;\n /** For an item publish (from History), the version now live. Absent when the entity was published. */\n itemUrn?: string;\n}\n\n/**\n * A message shown after every publish, or a function called after every\n * publish. A function may return (or resolve to) a message to show.\n */\nexport type AfterPublish = string | ((detail: PublishedDetail) => string | void | Promise<string | void>);\n\n/** Said on leaving edit mode, when the page shows content published in the visit, unless the site's message replaces it. */\nexport const DEFAULT_LIVE_NOTE = 'A site that is built ahead of time shows it to visitors after its next build.';\n\n/** The site's message when it is fixed text, for places with no publish to call back about. */\nexport function fixedMessage(setting: AfterPublish | undefined): string | undefined {\n return typeof setting === 'string' ? setting : undefined;\n}\n\n/**\n * Shows `done`, then runs the site's setting and adds its message. A\n * callback that throws is shown and logged, never hidden. `quiet`: the\n * toolbar already shows `done` (the entity's card says Published), so it is\n * only spoken, and only the site's message is shown.\n */\nexport async function announcePublished(\n toolbar: Toolbar,\n setting: AfterPublish | undefined,\n detail: PublishedDetail,\n done: string,\n { info = true, quiet = false }: { info?: boolean; quiet?: boolean } = {},\n): Promise<void> {\n const say = (message: string, isInfo: boolean) => (quiet ? toolbar.announce(done, message, isInfo) : toolbar.showMessage(message ? `${done} ${message}` : done, isInfo));\n say('', info);\n if (setting === undefined) return;\n try {\n const message = typeof setting === 'string' ? setting : await setting(detail);\n if (message) say(message, info);\n } catch (error) {\n console.error('Baack editor: the site\\'s afterPublish callback failed', error);\n const reason = error instanceof Error ? error.message : String(error);\n say(`The site's after-publish step failed: ${reason}`, false);\n }\n}\n", "// A combo box for choosing an entity by its path and language instead of\n// typing a URN. Entities load as the list opens; typing filters them; the\n// last option creates a new entity. The chosen URN is kept in a hidden input\n// that the form reads like any other field.\n\nimport type { EntityListing, EntitySummary } from '../core/entity-directory.ts';\nimport { el } from './host.ts';\nimport { icon } from './icons.ts';\n\nexport interface EntityPickerSource {\n list(onUpdate: (listing: EntityListing) => void): Promise<EntityListing>;\n describe(urn: string): Promise<EntitySummary>;\n /** The page's language: within a path, its entity is listed first. */\n readonly language: string;\n /** Shows the new-entity form in `container`, starting from `path`. Resolves with the new entity, or undefined if cancelled. */\n create(container: HTMLElement, path: string): Promise<EntitySummary | undefined>;\n /** A line about the chosen entity, such as that a draft is not shown to visitors; '' for none. */\n note(urn: string): Promise<string>;\n /** The page address an entity serves, from its path (`/home` is `/`): a link's suggestions. */\n pagePath(path: string): string;\n /** Reports a failed load in the editor's usual way. */\n report(error: unknown, action: string, retry: () => void): void;\n}\n\n/** At most this many options are listed; typing narrows them. */\nconst SHOWN = 50;\n\nlet pickers = 0;\n\nexport function summaryLabel(entity: EntitySummary): string {\n return `${entity.path} (${entity.language}${entity.variant ? ` \u00B7 ${entity.variant}` : ''})`;\n}\n\nexport class EntityPicker {\n readonly element: HTMLElement;\n /** The visible combo box. */\n readonly input: HTMLInputElement;\n /** The chosen URN, read by the form. */\n readonly value: HTMLInputElement;\n private readonly source: EntityPickerSource;\n private readonly onChange: () => void;\n private readonly listbox: HTMLElement;\n private readonly status: HTMLElement;\n private readonly note: HTMLElement;\n private readonly createArea: HTMLElement;\n private readonly id = `baack-entity-picker-${(pickers += 1)}`;\n private listing: EntityListing | undefined;\n /** Entities created here: listed even if the list loaded (or finishes loading) without them. */\n private readonly created: EntitySummary[] = [];\n private loading: Promise<void> | undefined;\n private options: { element: HTMLElement; choose(): void }[] = [];\n private active = -1;\n /** The text shown for the chosen entity, put back if the user types and leaves without choosing. */\n private chosenLabel = '';\n\n constructor(source: EntityPickerSource, key: string, urn: string, onChange: () => void) {\n this.source = source;\n this.onChange = onChange;\n this.element = el('div', 'entity-picker');\n this.input = el('input');\n this.input.type = 'text';\n this.input.autocomplete = 'off';\n this.input.spellcheck = false;\n this.input.placeholder = 'Type a path, such as /menu';\n this.input.setAttribute('role', 'combobox');\n this.input.setAttribute('aria-autocomplete', 'list');\n this.input.setAttribute('aria-expanded', 'false');\n this.input.setAttribute('aria-controls', `${this.id}-list`);\n this.value = el('input');\n this.value.type = 'hidden';\n this.value.name = key;\n this.value.value = urn;\n this.listbox = el('ul', 'entity-options');\n this.listbox.id = `${this.id}-list`;\n this.listbox.setAttribute('role', 'listbox');\n this.listbox.setAttribute('aria-label', 'Entities');\n this.listbox.hidden = true;\n this.status = el('p', 'hint');\n this.status.setAttribute('role', 'status');\n this.note = el('p', 'hint');\n this.createArea = el('div', 'entity-create');\n // shadcn/ui's combobox: a search field over a list of options, the chosen one ticked.\n const field = el('div', 'combobox-field');\n field.append(icon('search'), this.input, icon('chevron-down'));\n this.element.append(field, this.listbox, this.status, this.note, this.createArea, this.value);\n\n this.input.addEventListener('focus', () => this.open());\n this.input.addEventListener('input', () => this.open());\n this.input.addEventListener('keydown', this.onKeyDown);\n this.input.addEventListener('blur', () => {\n // A click on an option keeps focus (mousedown is prevented), so a blur is leaving.\n this.close();\n if (this.input.value !== this.chosenLabel) this.input.value = this.chosenLabel;\n });\n if (urn) this.showChosen(urn);\n }\n\n private async showChosen(urn: string): Promise<void> {\n this.chosenLabel = urn;\n this.input.value = urn;\n try {\n const entity = await this.source.describe(urn);\n if (this.value.value !== urn) return;\n this.chosenLabel = summaryLabel(entity);\n if (this.input.value === urn) this.input.value = this.chosenLabel;\n } catch (error) {\n this.source.report(error, 'show the entity referred to', () => void this.showChosen(urn));\n }\n void this.showNote(urn);\n }\n\n private async showNote(urn: string): Promise<void> {\n try {\n const note = await this.source.note(urn);\n if (this.value.value === urn) this.note.textContent = note;\n } catch (error) {\n this.source.report(error, 'check the entity referred to', () => void this.showNote(urn));\n }\n }\n\n private open(): void {\n this.listbox.hidden = false;\n this.input.setAttribute('aria-expanded', 'true');\n this.loading ??= this.source\n .list((listing) => {\n this.listing = listing;\n this.render();\n })\n .then((listing) => {\n this.listing = listing;\n this.render();\n })\n .catch((error: unknown) => {\n this.loading = undefined; // Loaded again on the next open.\n this.status.textContent = 'The list of entities could not be loaded.';\n this.source.report(error, 'list the entities', () => this.open());\n });\n this.render();\n }\n\n private close(): void {\n this.listbox.hidden = true;\n this.input.setAttribute('aria-expanded', 'false');\n this.input.removeAttribute('aria-activedescendant');\n this.active = -1;\n }\n\n private render(): void {\n if (this.listbox.hidden) return;\n const query = this.input.value === this.chosenLabel ? '' : this.input.value.trim().toLowerCase();\n const loaded = this.listing?.entities ?? [];\n const entities = [...loaded, ...this.created.filter((entity) => !loaded.some((known) => known.urn === entity.urn))]\n .filter((entity) => !query || summaryLabel(entity).toLowerCase().includes(query))\n .sort((a, b) => (a.path === b.path ? Number(b.language === this.source.language) - Number(a.language === this.source.language) : 0));\n this.options = entities.slice(0, SHOWN).map((entity) => {\n const option = el('li', 'entity-option');\n option.append(el('span', '', entity.path), el('span', 'meta', ` ${entity.language}${entity.variant ? ` \u00B7 ${entity.variant}` : ''}`));\n const chosen = entity.urn === this.value.value;\n option.setAttribute('aria-selected', String(chosen));\n if (chosen) option.append(icon('check'));\n return { element: option, choose: () => this.choose(entity) };\n });\n const typed = this.input.value.trim();\n const path = query && typed.startsWith('/') ? typed : query ? `/${typed}` : '';\n const create = el('li', 'entity-option create', path ? `Create a new entity \"${path}\"\u2026` : 'Create a new entity\u2026');\n create.prepend(icon('plus'));\n this.options.push({ element: create, choose: () => void this.create(path) });\n this.options.forEach((option, index) => {\n option.element.id = `${this.id}-option-${index}`;\n option.element.setAttribute('role', 'option');\n option.element.addEventListener('mousedown', (event) => event.preventDefault());\n option.element.addEventListener('click', () => option.choose());\n });\n this.listbox.replaceChildren(...this.options.map((option) => option.element));\n this.setActive(Math.min(this.active, this.options.length - 1));\n\n const count = loaded.length + this.created.length;\n this.status.textContent = !this.listing\n ? 'Loading entities\u2026'\n : [\n entities.length > SHOWN ? `Showing ${SHOWN} of ${entities.length}; type to narrow.` : '',\n this.listing.complete ? '' : 'The search was still running, so some entities may be missing.',\n count === 0 ? 'No entities found.' : '',\n ]\n .filter(Boolean)\n .join(' ');\n }\n\n private setActive(index: number): void {\n this.active = index;\n this.options.forEach((option, i) => option.element.classList.toggle('active', i === index));\n const current = this.options[index];\n if (current) {\n this.input.setAttribute('aria-activedescendant', current.element.id);\n current.element.scrollIntoView({ block: 'nearest' });\n } else {\n this.input.removeAttribute('aria-activedescendant');\n }\n }\n\n private choose(entity: EntitySummary): void {\n this.value.value = entity.urn;\n this.chosenLabel = summaryLabel(entity);\n this.input.value = this.chosenLabel;\n this.note.textContent = '';\n this.close();\n this.onChange();\n void this.showNote(entity.urn);\n }\n\n private async create(path: string): Promise<void> {\n this.close();\n this.input.disabled = true;\n try {\n const entity = await this.source.create(this.createArea, path);\n if (entity) {\n this.created.push(entity);\n this.choose(entity);\n }\n } finally {\n this.createArea.replaceChildren();\n this.input.disabled = false;\n this.input.focus();\n }\n }\n\n private readonly onKeyDown = (event: KeyboardEvent) => {\n const open = !this.listbox.hidden;\n if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault();\n if (!open) this.open();\n const step = event.key === 'ArrowDown' ? 1 : -1;\n this.setActive((this.active + step + this.options.length) % this.options.length);\n } else if (event.key === 'Enter' && open && this.active >= 0 && !(event.metaKey || event.ctrlKey)) {\n event.preventDefault();\n event.stopPropagation();\n this.options[this.active]?.choose();\n } else if (event.key === 'Escape' && open) {\n // Closes the list only, not the whole form.\n event.preventDefault();\n event.stopPropagation();\n this.close();\n }\n };\n}\n", "// A dropdown menu: shadcn/ui's, with the WAI-ARIA menu button pattern. The\n// trigger opens a list of menu items below it (above, when there is no room).\n// Arrow keys, Home, End and the first letter move between items; Enter runs\n// one; Escape or Tab closes it and puts focus back on the trigger.\n//\n// Opened with the pointer, the menu takes no focus, so an inline edit the\n// trigger sits beside stays focused (and is not ended by a blur).\n\nimport { el } from './host.ts';\nimport { icon, type IconName } from './icons.ts';\n\nexport interface MenuItem {\n label: string;\n icon?: IconName;\n destructive?: boolean;\n run(): void;\n}\n\nlet count = 0;\n\nexport class Dropdown {\n readonly trigger: HTMLButtonElement;\n private readonly items: () => MenuItem[];\n private menu: HTMLElement | undefined;\n\n constructor(trigger: HTMLButtonElement, items: () => MenuItem[]) {\n this.trigger = trigger;\n this.items = items;\n trigger.id ||= `baack-menu-trigger-${++count}`;\n trigger.setAttribute('aria-haspopup', 'menu');\n trigger.setAttribute('aria-expanded', 'false');\n trigger.addEventListener('mousedown', (event) => event.preventDefault());\n // detail is 0 for a click made with the keyboard (Enter or Space).\n trigger.addEventListener('click', (event) => (this.menu ? this.close(true) : this.open(event.detail === 0 ? 'first' : undefined)));\n trigger.addEventListener('keydown', (event) => {\n if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault();\n this.open(event.key === 'ArrowDown' ? 'first' : 'last');\n }\n });\n }\n\n get isOpen(): boolean {\n return this.menu !== undefined;\n }\n\n open(focus?: 'first' | 'last'): void {\n this.close(false);\n const menu = el('div', 'menu');\n menu.setAttribute('role', 'menu');\n menu.setAttribute('aria-labelledby', this.trigger.id);\n for (const item of this.items()) {\n const entry = el('button', item.destructive ? 'menu-item destructive' : 'menu-item');\n entry.type = 'button';\n entry.setAttribute('role', 'menuitem');\n entry.tabIndex = -1;\n if (item.icon) entry.append(icon(item.icon));\n entry.append(item.label);\n entry.addEventListener('mousedown', (event) => event.preventDefault());\n entry.addEventListener('click', () => {\n this.close(entry.matches(':focus'));\n item.run();\n });\n menu.append(entry);\n }\n menu.addEventListener('keydown', this.onKey);\n // In the trigger's panel, so a popover's dialog contains its menu.\n (this.trigger.closest('.panel') ?? this.trigger.parentElement!).append(menu);\n this.menu = menu;\n this.trigger.setAttribute('aria-expanded', 'true');\n this.trigger.setAttribute('aria-controls', (menu.id = `${this.trigger.id}-list`));\n this.place();\n window.addEventListener('pointerdown', this.onOutside, true);\n window.addEventListener('scroll', this.onScroll, true);\n window.addEventListener('resize', this.onScroll);\n if (focus) this.focusAt(focus === 'first' ? 0 : -1);\n }\n\n /** `restoreFocus`: put focus back on the trigger, as after Escape. */\n close(restoreFocus: boolean): void {\n if (!this.menu) return;\n this.menu.remove();\n this.menu = undefined;\n this.trigger.setAttribute('aria-expanded', 'false');\n this.trigger.removeAttribute('aria-controls');\n window.removeEventListener('pointerdown', this.onOutside, true);\n window.removeEventListener('scroll', this.onScroll, true);\n window.removeEventListener('resize', this.onScroll);\n if (restoreFocus) this.trigger.focus();\n }\n\n private entries(): HTMLButtonElement[] {\n return [...(this.menu?.querySelectorAll<HTMLButtonElement>('[role=\"menuitem\"]') ?? [])];\n }\n\n private focusAt(index: number): void {\n const entries = this.entries();\n const entry = entries.at(index % entries.length);\n for (const other of entries) other.tabIndex = other === entry ? 0 : -1;\n entry?.focus();\n }\n\n private readonly onKey = (event: KeyboardEvent) => {\n const entries = this.entries();\n const current = entries.indexOf(event.target as HTMLButtonElement);\n if (event.key === 'Escape') {\n // Only the menu closes, not the popover or edit it sits in.\n event.preventDefault();\n event.stopPropagation();\n this.close(true);\n } else if (event.key === 'Tab') {\n event.preventDefault();\n this.close(true);\n } else if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {\n event.preventDefault();\n this.focusAt((current + (event.key === 'ArrowDown' ? 1 : -1) + entries.length) % entries.length);\n } else if (event.key === 'Home' || event.key === 'End') {\n event.preventDefault();\n this.focusAt(event.key === 'Home' ? 0 : -1);\n } else if (event.key.length === 1 && /\\S/.test(event.key)) {\n // The next item starting with the letter typed.\n const letter = event.key.toLowerCase();\n for (let step = 1; step <= entries.length; step++) {\n const index = (current + step) % entries.length;\n if (entries[index]!.textContent!.trim().toLowerCase().startsWith(letter)) {\n this.focusAt(index);\n break;\n }\n }\n }\n };\n\n private readonly onOutside = (event: PointerEvent) => {\n const path = event.composedPath();\n if (!path.includes(this.menu!) && !path.includes(this.trigger)) this.close(false);\n };\n\n private readonly onScroll = (event: Event) => {\n if (event.type === 'scroll' && this.menu && event.composedPath().includes(this.menu)) return;\n this.close(false);\n };\n\n /** Below the trigger, its end edges aligned; above it when there is no room below. */\n private place(): void {\n const menu = this.menu!;\n const rect = this.trigger.getBoundingClientRect();\n menu.style.minWidth = `${Math.max(rect.width, 128)}px`;\n const { width, height } = menu.getBoundingClientRect();\n const below = rect.bottom + 4;\n const top = below + height <= window.innerHeight - 8 || rect.top - height - 4 < 8 ? below : rect.top - height - 4;\n menu.style.top = `${Math.max(8, top)}px`;\n menu.style.left = `${Math.min(Math.max(8, rect.right - width), window.innerWidth - width - 8)}px`;\n }\n}\n", "// The panel beside an element being edited: what it is, a form for non-text\n// types, warnings, errors, and the Send and Revert actions.\n\nimport type { FieldSpec, FormValues, Issue } from '../core/registry.ts';\nimport { button, type EditorHost, debugDetails, el, variantOf } from './host.ts';\nimport type { EntityListing } from '../core/entity-directory.ts';\nimport { EntityPicker, type EntityPickerSource } from './entity-picker.ts';\nimport { icon, type IconName } from './icons.ts';\nimport { Dropdown } from './menu.ts';\nimport { tooltip } from './tooltip.ts';\n\nexport interface PopoverActions {\n send(): void;\n revert(): void;\n}\n\n/** A secondary action for the item being edited. `menu`: listed in the \u22EF menu rather than shown as a button. */\nexport interface ExtraAction {\n label: string;\n icon?: IconName;\n menu?: boolean;\n run(): void;\n}\n\n/** A decision with its own buttons, such as resolving a conflict. */\nexport interface Choice {\n label: string;\n primary?: boolean;\n /** Shown as a destructive button: it deletes or discards. */\n destructive?: boolean;\n run(): void;\n}\n\nexport interface FormActions extends PopoverActions {\n /** Called on every change with the current form values. */\n input(values: FormValues): void;\n}\n\n// Offered as suggestions; any ISO 4217 code is accepted.\nconst COMMON_CURRENCIES = ['GBP', 'EUR', 'USD', 'JPY', 'CHF', 'CAD', 'AUD', 'NZD', 'SEK', 'NOK', 'DKK', 'PLN', 'INR', 'CNY', 'BRL'];\n\nconst IS_MAC = /Mac|iPhone|iPad/.test(navigator.userAgent);\n\nexport class Popover {\n readonly element: HTMLElement;\n private readonly title: HTMLElement;\n private readonly form: HTMLElement;\n private readonly description: HTMLElement;\n private readonly issues: HTMLElement;\n private readonly error: HTMLElement;\n private readonly errorDebug: HTMLElement;\n private readonly sendButton: HTMLButtonElement;\n private readonly extras: HTMLElement;\n private menu: Dropdown | undefined;\n private readonly buttons: HTMLElement;\n private readonly choices: HTMLElement;\n private readonly hint: HTMLElement;\n private anchor: HTMLElement | undefined;\n private actions: PopoverActions | undefined;\n private inputs = new Map<string, HTMLInputElement | HTMLTextAreaElement>();\n private readonly slotStatus = new Map<string, HTMLElement>();\n private readonly reposition = () => this.place();\n /** Which side of the element the popover sits on, chosen when it opens. */\n private side: 'below' | 'above' | 'within' | undefined;\n /** Called once when this opening ends: hidden, or replaced by another opening. */\n private onEnd: (() => void) | undefined;\n /** Follows the element being edited as its value makes it taller or shorter. */\n private readonly anchorObserver = new ResizeObserver(this.reposition);\n /** Where entity fields find entities, and link addresses their suggestions. */\n private entities: EntityPickerSource | undefined;\n /** The values the form opened with, for fields that show the current state (file slots). */\n private currentValues: FormValues = {};\n\n constructor(host: EditorHost) {\n this.element = el('div', 'panel popover');\n this.element.setAttribute('role', 'dialog');\n this.element.hidden = true;\n this.title = el('div', 'title');\n this.form = el('div', 'form');\n this.description = el('p', 'hint');\n this.issues = el('ul', 'issues');\n this.error = el('p', 'error');\n this.error.setAttribute('role', 'alert');\n this.errorDebug = el('div', 'error-debug');\n\n const revert = el('button', '', 'Revert');\n revert.type = 'button';\n this.sendButton = el('button', 'primary', 'Save');\n this.sendButton.type = 'button';\n // Keep focus in the element being edited, so pressing a button is not a blur.\n for (const button of [revert, this.sendButton]) {\n button.addEventListener('mousedown', (event) => event.preventDefault());\n }\n revert.addEventListener('click', () => this.actions?.revert());\n this.sendButton.addEventListener('click', () => this.actions?.send());\n this.element.addEventListener('keydown', (event) => {\n if (event.key === 'Escape') {\n event.preventDefault();\n this.actions?.revert();\n } else if (event.key === 'Enter' && (event.metaKey || event.ctrlKey)) {\n event.preventDefault();\n this.actions?.send();\n }\n });\n\n this.extras = el('div', 'extras');\n this.buttons = el('div', 'actions');\n this.buttons.append(revert, this.sendButton);\n this.choices = el('div', 'actions');\n this.choices.hidden = true;\n this.hint = el('p', 'hint');\n this.element.append(this.title, this.form, this.description, this.issues, this.error, this.errorDebug, this.extras, this.buttons, this.choices, this.hint);\n host.root.append(this.element);\n // Warnings, errors, a file preview or the entity list can make it taller: choose its side again, to keep it on\n // screen. Only the element growing keeps the side.\n new ResizeObserver(() => {\n if (this.element.hidden) return;\n this.side = undefined;\n this.place();\n }).observe(this.element);\n }\n\n setEntitySource(source: EntityPickerSource): void {\n this.entities = source;\n }\n\n get isOpen(): boolean {\n return !this.element.hidden;\n }\n\n /** For in-place editing: the element itself holds the value. */\n show(anchor: HTMLElement, label: string, meta: string, hint: string, actions: PopoverActions): void {\n this.open(anchor, label, meta, hint, actions, false);\n this.form.replaceChildren();\n this.inputs.clear();\n this.place();\n }\n\n /** For popover and panel editing: a form holds the value. */\n showForm(\n anchor: HTMLElement,\n label: string,\n meta: string,\n fields: readonly FieldSpec[],\n values: FormValues,\n actions: FormActions,\n wide: boolean,\n ): void {\n this.open(anchor, label, meta, `${IS_MAC ? '\u2318' : 'Ctrl'}+Enter to save \u00B7 Esc to revert`, actions, wide);\n this.inputs.clear();\n this.slotStatus.clear();\n this.currentValues = values;\n this.form.replaceChildren(...fields.map((field) => this.field(field, values[field.key], () => actions.input(this.values()))));\n this.place();\n this.form.querySelector<HTMLElement>('input:not([type=\"hidden\"]), textarea, select')?.focus();\n }\n\n /** Shows labelled values side by side and a set of choices instead of Save and Revert. */\n showChoices(anchor: HTMLElement, label: string, meta: string, blocks: { label: string; text: string }[], description: string, choices: Choice[]): void {\n this.open(anchor, label, meta, '', { send: () => undefined, revert: () => choices.at(-1)?.run() }, true);\n this.inputs.clear();\n this.form.replaceChildren(\n ...blocks.map((block) => {\n const box = el('div', 'field');\n box.append(el('span', 'caption', block.label), el('pre', 'snippet', block.text));\n return box;\n }),\n );\n this.setDescription(description);\n this.buttons.hidden = true;\n this.choices.hidden = false;\n this.choices.replaceChildren(\n ...choices.map((choice) => {\n const choiceButton = button(choice.label, variantOf(choice));\n choiceButton.addEventListener('click', () => choice.run());\n return choiceButton;\n }),\n );\n this.place();\n }\n\n /**\n * Runs `end` once when this opening ends, whether hidden or replaced by\n * another item's, so a preview on the page is never left behind.\n */\n whenEnded(end: (() => void) | undefined): void {\n this.onEnd = end;\n }\n\n private ended(): void {\n const end = this.onEnd;\n this.onEnd = undefined;\n end?.();\n }\n\n hide(): void {\n this.ended();\n this.menu?.close(false);\n this.element.hidden = true;\n this.anchor = undefined;\n this.side = undefined;\n this.anchorObserver.disconnect();\n this.actions = undefined;\n window.removeEventListener('scroll', this.reposition, true);\n window.removeEventListener('resize', this.reposition);\n window.removeEventListener('keydown', this.onWindowKey);\n }\n\n /**\n * Escape reverts wherever focus is while the popover is open, like the\n * Revert button. The popover and the in-place editor handle it first when\n * focus is theirs, and mark it handled.\n */\n private readonly onWindowKey = (event: KeyboardEvent) => {\n if (event.key !== 'Escape' || event.defaultPrevented || this.element.hidden) return;\n event.preventDefault();\n this.actions?.revert();\n };\n\n values(): FormValues {\n // Start from what the form opened with, so read-only state (a slot's current file) is included.\n const values: FormValues = { ...this.currentValues };\n for (const [key, input] of this.inputs) {\n if (input instanceof HTMLInputElement && input.type === 'file') values[key] = input.files?.[0]?.name ?? '';\n else values[key] = input instanceof HTMLInputElement && input.type === 'checkbox' ? input.checked : input.value;\n }\n return values;\n }\n\n /** Files chosen in file fields, by field key. */\n files(): Map<string, File> {\n const files = new Map<string, File>();\n for (const [key, input] of this.inputs) {\n const file = input instanceof HTMLInputElement && input.type === 'file' ? input.files?.[0] : undefined;\n if (file) files.set(key, file);\n }\n return files;\n }\n\n /** A status line under a file field: \"uploading\u2026\", \"done\", or the API's error. */\n setSlotStatus(key: string, text: string, problem = false): void {\n const status = this.slotStatus.get(key);\n if (!status) return;\n status.textContent = text;\n status.classList.toggle('error', problem);\n }\n\n setValues(values: FormValues): void {\n for (const [key, input] of this.inputs) {\n const value = values[key];\n if (input instanceof HTMLInputElement && input.type === 'checkbox') {\n input.checked = value === true;\n } else if (input.type !== 'file') {\n input.value = typeof value === 'string' ? value : '';\n }\n }\n }\n\n /** Makes the item's \"name #sort order\" in the title a link, for example to show it in Items. */\n setNameAction(run: (() => void) | undefined): void {\n const meta = this.title.querySelector('.meta');\n if (!meta || !run) return;\n const link = el('button', 'meta link', meta.textContent ?? '');\n link.type = 'button';\n tooltip(link, 'Show in Items');\n link.addEventListener('mousedown', (event) => event.preventDefault());\n link.addEventListener('click', run);\n meta.replaceWith(link);\n }\n\n /** Secondary actions for the item: History as a button, then the others (Reorder\u2026, Move up\u2026) in a \u22EF menu. */\n setExtras(actions: ExtraAction[]): void {\n this.menu?.close(false);\n this.menu = undefined;\n const shown = actions.filter((action) => !action.menu);\n const listed = actions.filter((action) => action.menu);\n this.extras.replaceChildren(\n ...shown.map((action) => {\n const extra = button(action.label, 'ghost', 'sm');\n if (action.icon) extra.prepend(icon(action.icon));\n extra.addEventListener('mousedown', (event) => event.preventDefault());\n extra.addEventListener('click', () => action.run());\n return extra;\n }),\n );\n if (listed.length > 0) {\n const more = button('', 'ghost', 'icon-sm');\n more.setAttribute('aria-label', 'More actions');\n more.append(icon('ellipsis'));\n this.extras.append(more);\n tooltip(more);\n this.menu = new Dropdown(more, () => listed);\n }\n }\n\n setDescription(text: string): void {\n this.description.textContent = text;\n }\n\n setIssues(issues: Issue[]): void {\n this.issues.replaceChildren(...issues.map((issue) => el('li', issue.level, issue.message)));\n }\n\n /** `debug`: an API error body, shown behind a collapsed \"Debug\" section. */\n setError(message: string, debug?: string): void {\n this.error.textContent = message;\n this.errorDebug.replaceChildren(...debugDetails(debug));\n }\n\n setSending(sending: boolean): void {\n this.sendButton.disabled = sending;\n this.sendButton.textContent = sending ? 'Saving\u2026' : 'Save';\n }\n\n private open(anchor: HTMLElement, label: string, meta: string, hint: string, actions: PopoverActions, wide: boolean) {\n this.ended();\n if (anchor !== this.anchor) this.side = undefined;\n this.anchor = anchor;\n this.anchorObserver.disconnect();\n this.anchorObserver.observe(anchor);\n this.actions = actions;\n this.title.textContent = `${label} `;\n this.title.append(el('span', 'meta', meta));\n this.element.setAttribute('aria-label', `Edit ${label.toLowerCase()} ${meta}`);\n this.element.classList.toggle('wide', wide);\n this.buttons.hidden = false;\n this.choices.hidden = true;\n this.setExtras([]);\n this.hint.textContent = hint;\n this.setDescription('');\n this.setIssues([]);\n this.setError('');\n this.setSending(false);\n this.element.hidden = false;\n window.addEventListener('scroll', this.reposition, true);\n window.addEventListener('resize', this.reposition);\n window.addEventListener('keydown', this.onWindowKey);\n }\n\n private field(field: FieldSpec, value: string | boolean | undefined, onInput: () => void): HTMLElement {\n const label = el('label', `field ${field.kind}`);\n const caption = el('span', 'caption', field.label);\n let input: HTMLInputElement | HTMLTextAreaElement;\n if (field.kind === 'file') {\n // A file slot: the current file, a chooser, and a status line.\n input = el('input');\n input.type = 'file';\n input.accept = 'image/apng,image/avif,image/gif,image/jpeg,image/png,image/svg+xml,image/webp';\n input.name = field.key;\n const current = typeof this.currentValues[`${field.key}:current`] === 'string' ? (this.currentValues[`${field.key}:current`] as string) : '';\n const preview = el('div', 'slot-preview');\n if (current) {\n const img = el('img');\n img.src = current;\n img.alt = '';\n preview.append(img, el('span', 'meta', current));\n } else {\n preview.append(el('span', 'meta', 'No file'));\n }\n const status = el('span', 'hint');\n status.setAttribute('role', 'status');\n this.slotStatus.set(field.key, status);\n input.addEventListener('change', onInput);\n this.inputs.set(field.key, input);\n label.append(caption, preview, input, status);\n return label;\n }\n if (field.kind === 'entity' && this.entities) {\n // Not a <label>: the picker holds a list and a form, which must not become part of its name.\n const wrapper = el('div', 'field entity');\n caption.id = `baack-field-${field.key}`;\n const picker = new EntityPicker(this.entities, field.key, typeof value === 'string' ? value : '', onInput);\n picker.input.setAttribute('aria-labelledby', caption.id);\n this.inputs.set(field.key, picker.value);\n wrapper.append(caption, picker.element);\n return wrapper;\n }\n if (field.kind === 'textarea' || field.kind === 'code') {\n input = el('textarea');\n input.rows = field.kind === 'code' ? 12 : 4;\n input.spellcheck = field.kind !== 'code';\n } else {\n input = el('input');\n input.type =\n field.kind === 'checkbox' ? 'checkbox' : field.kind === 'datetime' ? 'datetime-local' : field.kind === 'url' ? 'url' : 'text';\n if (field.kind === 'integer') input.inputMode = 'numeric';\n if (field.kind === 'decimal') input.inputMode = 'decimal';\n if (field.kind === 'currency') {\n input.maxLength = 3;\n input.autocapitalize = 'characters';\n const list = el('datalist');\n list.id = `baack-currencies-${field.key}`;\n list.append(...COMMON_CURRENCIES.map((code) => Object.assign(el('option'), { value: code })));\n input.setAttribute('list', list.id);\n label.append(list);\n }\n if (field.kind === 'url' && this.entities) label.append(this.pathSuggestions(input as HTMLInputElement, field.key));\n }\n if (input instanceof HTMLInputElement && input.type === 'checkbox') {\n // Drawn as a switch: an on/off value that takes effect when saved.\n input.setAttribute('role', 'switch');\n input.className = 'switch';\n input.checked = value === true;\n label.append(input, caption);\n } else {\n input.value = typeof value === 'string' ? value : '';\n label.append(caption, input);\n }\n input.name = field.key;\n input.addEventListener('input', onInput);\n input.addEventListener('change', onInput);\n this.inputs.set(field.key, input);\n return label;\n }\n\n /** Suggests the paths of entities for a link address, once the field is first used. */\n private pathSuggestions(input: HTMLInputElement, key: string): HTMLElement {\n const list = el('datalist');\n list.id = `baack-paths-${key}`;\n input.setAttribute('list', list.id);\n const fill = ({ entities }: EntityListing) =>\n list.replaceChildren(...[...new Set(entities.map((entity) => this.entities!.pagePath(entity.path)))].map((path) => Object.assign(el('option'), { value: path })));\n input.addEventListener(\n 'focus',\n () => {\n // Suggestions only: a failed listing leaves the field as a plain address.\n this.entities?.list(fill).then(fill, () => undefined);\n },\n { once: true },\n );\n return list;\n }\n\n private place(): void {\n if (!this.anchor) return;\n const rect = this.anchor.getBoundingClientRect();\n // An element with no box (a switch turned off hides its content) leaves the popover where it was.\n if (!this.anchor.getClientRects().length && this.side) return;\n const height = this.element.offsetHeight;\n const width = this.element.offsetWidth;\n // Opened from another editor panel (an outline row): sit beside that panel, not over it.\n const panel = this.anchor.closest('.panel');\n if (panel && panel !== this.element) {\n const panelRect = panel.getBoundingClientRect();\n this.element.style.left = `${Math.max(8, panelRect.left - width - 8)}px`;\n this.element.style.top = `${Math.max(8, Math.min(rect.top, window.innerHeight - height - 8))}px`;\n return;\n }\n // The side is chosen once per opening and then kept: pinned to that edge of the element, the popover moves\n // with it as the value grows, never over it, even when that takes it past the bottom of the window. An\n // element with room on neither side (a tall image) is covered anyway, so the popover stays in the window.\n this.side ??=\n rect.bottom + 8 + height <= window.innerHeight ? 'below' : rect.top - height - 8 >= 8 ? 'above' : 'within';\n const top =\n this.side === 'below'\n ? Math.max(8, rect.bottom + 8)\n : this.side === 'above'\n ? Math.min(rect.top - height - 8, window.innerHeight - height - 8)\n : Math.max(8, Math.min(rect.bottom + 8, window.innerHeight - height - 8));\n const left = Math.max(8, Math.min(rect.left, window.innerWidth - width - 8));\n this.element.style.top = `${top}px`;\n this.element.style.left = `${left}px`;\n }\n}\n", "// The persistent control: edit mode, the sidebar, read mode, the unsent\n// count (opening the unsent changes in the sidebar), a label for the page's\n// entity (its state and unsent count, opening it in the sidebar), page-level\n// messages, and the login prompt. Everything else is in the sidebar\n// (docs/plans/single-sidebar.md).\n\nimport { button, type EditorHost, debugDetails, el } from './host.ts';\nimport { createLauncher } from './launcher.ts';\nimport { tooltip } from './tooltip.ts';\n\nexport interface PendingRow {\n label: string;\n /** \"edit\", \"new item\", or a problem such as \"based on an older version\". */\n detail: string;\n problem?: boolean;\n /** For example \"Resolve\" on an edit made on an older version. */\n action?: { label: string; run(anchor: HTMLElement): void };\n}\n\nexport interface PendingGroup {\n entityUrn: string;\n title: string;\n rows: PendingRow[];\n}\n\n/** One entity's lifecycle: its status as the server reports it, and the verbs available. */\nexport interface LifecycleRow {\n entityUrn: string;\n title: string;\n label: string;\n note?: string;\n verbs: { label: string; primary?: boolean; disabled?: string; run(): void }[];\n}\n\nexport interface MessageAction {\n label: string;\n run(): void;\n}\n\nexport interface PendingActions {\n sendAll(entityUrn?: string): void;\n discardAll(entityUrn?: string): void;\n}\n\nexport class Toolbar {\n readonly modeButton: HTMLButtonElement;\n readonly itemsButton: HTMLButtonElement;\n /** Switches between the latest drafts and the live page. */\n readonly readButton: HTMLButtonElement;\n private readonly pendingButton: HTMLButtonElement;\n private readonly message: HTMLElement;\n /** What to do next, after a message such as \"Saved as drafts\": Review and publish\u2026. */\n private readonly messageAction: HTMLButtonElement;\n private runMessageAction: (() => void) | undefined;\n private readonly messageDebug: HTMLElement;\n /** The page entity's label. */\n private readonly entities: HTMLElement;\n private lifecycleRows: LifecycleRow[] = [];\n private pendingGroups: PendingGroup[] = [];\n /** Opens the unsent changes in the sidebar (the count's click). */\n private openPending: (() => void) | undefined;\n private readonly pendingListeners: (() => void)[] = [];\n /** Opens an entity's level in the sidebar (the label's click). */\n private openEntity: ((entityUrn: string) => void) | undefined;\n private readonly lifecycleListeners: (() => void)[] = [];\n private readonly login: HTMLElement;\n private readonly loginFrame: HTMLIFrameElement;\n private readonly loginText: HTMLElement;\n private readonly pendingActions: PendingActions;\n\n constructor(host: EditorHost, onRetryAfterLogin: () => void, pendingActions: PendingActions) {\n this.pendingActions = pendingActions;\n this.modeButton = createLauncher(host);\n const bar = this.modeButton.closest('.toolbar')!;\n const row = this.modeButton.parentElement!;\n\n this.itemsButton = el('button', '', 'Items');\n this.itemsButton.type = 'button';\n tooltip(this.itemsButton, 'Every item on this page (Alt+Shift+I)');\n this.itemsButton.hidden = true;\n\n this.pendingButton = el('button', 'pending');\n this.pendingButton.type = 'button';\n this.pendingButton.hidden = true;\n tooltip(this.pendingButton, 'Show them in the sidebar, with Save all and Discard all');\n this.pendingButton.addEventListener('click', () => this.openPending?.());\n this.readButton = el('button', '', 'Show live page');\n this.readButton.type = 'button';\n this.readButton.hidden = true;\n row.append(this.itemsButton, this.readButton, this.pendingButton);\n\n this.message = el('p', 'message');\n this.message.setAttribute('role', 'status');\n this.messageAction = button('', 'primary', 'sm', 'message-action');\n this.messageAction.hidden = true;\n this.messageAction.addEventListener('click', () => {\n const run = this.runMessageAction;\n this.showMessage('');\n run?.();\n });\n this.messageDebug = el('div', 'message-debug');\n this.entities = el('div', 'entities');\n\n this.login = el('div', 'login');\n this.login.hidden = true;\n this.loginText = el('p', 'message');\n this.loginText.setAttribute('role', 'alert');\n this.loginFrame = el('iframe');\n this.loginFrame.title = 'Log in to Baack';\n const retry = el('button', 'primary', 'I have logged in, try again');\n retry.type = 'button';\n retry.addEventListener('click', () => {\n this.hideLogin();\n onRetryAfterLogin();\n });\n this.login.append(this.loginText, this.loginFrame, retry);\n\n bar.append(this.entities, this.message, this.messageAction, this.messageDebug, this.login);\n }\n\n setEditMode(on: boolean): void {\n this.modeButton.disabled = false;\n this.modeButton.setAttribute('aria-pressed', String(on));\n this.itemsButton.hidden = !on;\n this.readButton.hidden = !on;\n }\n\n /** `latest` true while showing the editable latest drafts. */\n setReadMode(latest: boolean): void {\n this.readButton.textContent = latest ? 'Show live page' : 'Show latest drafts';\n }\n\n setPending(groups: PendingGroup[]): void {\n this.pendingGroups = groups;\n const count = groups.reduce((total, group) => total + group.rows.length, 0);\n this.pendingButton.hidden = count === 0;\n this.pendingButton.textContent = count === 1 ? '1 unsaved change' : `${count} unsaved changes`;\n this.renderEntities();\n for (const listener of this.pendingListeners) listener();\n }\n\n /** What the unsent count opens. */\n setOpenPending(open: () => void): void {\n this.openPending = open;\n }\n\n /** Called whenever the unsent changes change. */\n onPending(listener: () => void): void {\n this.pendingListeners.push(listener);\n }\n\n /** The unsent changes, one section per entity with Save all and Discard all, for the sidebar's level. */\n pendingSections(): HTMLElement[] {\n if (this.pendingGroups.length === 0) return [el('p', 'hint', 'Nothing is unsaved.')];\n return [\n ...this.pendingGroups.map((group) => this.pendingSection(group)),\n ...(this.pendingGroups.length > 1 ? [this.actions(undefined, 'everywhere')] : []),\n ];\n }\n\n /** What the page entity's label opens. */\n setOpenEntity(open: (entityUrn: string) => void): void {\n this.openEntity = open;\n }\n\n /** In display order: the page's entity first, then the others. */\n setLifecycle(rows: LifecycleRow[]): void {\n this.lifecycleRows = rows;\n this.renderEntities();\n for (const listener of this.lifecycleListeners) listener();\n }\n\n /** An entity's lifecycle row, while editing. */\n lifecycleOf(entityUrn: string): LifecycleRow | undefined {\n return this.lifecycleRows.find((row) => row.entityUrn === entityUrn);\n }\n\n /** Whether the toolbar's card is this entity's, showing its state. */\n showsEntity(entityUrn: string): boolean {\n return this.lifecycleRows[0]?.entityUrn === entityUrn;\n }\n\n /** Called whenever the lifecycle rows change. */\n onLifecycle(listener: () => void): void {\n this.lifecycleListeners.push(listener);\n }\n\n /** The page's entity as a label (its title, state and unsent count) that opens it in the sidebar. */\n private renderEntities(): void {\n const page = this.lifecycleRows[0];\n this.entities.replaceChildren(...(page ? [this.entityLabel(page)] : []));\n }\n\n private entityLabel(row: LifecycleRow): HTMLElement {\n const unsent = this.pendingGroups.find((group) => group.entityUrn === row.entityUrn)?.rows.length ?? 0;\n const label = el('button', 'entity-label');\n label.type = 'button';\n tooltip(label, 'Open in the sidebar');\n label.append(el('span', 'title', row.title), el('span', 'meta', ` \u00B7 ${row.label}`));\n if (unsent > 0) label.append(el('span', 'meta unsent', ` \u00B7 ${unsent} unsaved`));\n label.addEventListener('click', () => this.openEntity?.(row.entityUrn));\n if (row.note) {\n const section = el('div', 'entity');\n section.append(label, el('p', 'message', row.note));\n return section;\n }\n return label;\n }\n\n private pendingSection(group: PendingGroup): HTMLElement {\n const title = group.title;\n const section = el('section', 'entity');\n section.setAttribute('aria-label', `Unsaved in ${title}`);\n section.append(el('div', 'meta', `${title}: ${group.rows.length} unsaved`));\n const list = el('ul', 'rows');\n for (const pendingRow of group.rows) {\n const item = el('li', pendingRow.problem ? 'row problem' : 'row', pendingRow.label);\n item.append(el('span', 'meta', ` \u00B7 ${pendingRow.detail}`));\n if (pendingRow.action) {\n const button = el('button', '', pendingRow.action.label);\n button.type = 'button';\n const run = pendingRow.action.run;\n button.addEventListener('click', () => run(button));\n item.append(' ', button);\n }\n list.append(item);\n }\n section.append(list, this.actions(group.entityUrn, `in ${title}`));\n return section;\n }\n\n /**\n * `debug`: an API error body, shown behind a collapsed \"Debug\" section. `action`: the next step, as a button after\n * the message; using it clears the message.\n */\n showMessage(text: string, info = false, debug?: string, action?: MessageAction): void {\n this.message.textContent = text;\n this.message.classList.remove('visually-hidden');\n this.message.classList.toggle('info', info);\n this.messageDebug.replaceChildren(...debugDetails(debug));\n this.runMessageAction = action?.run;\n this.messageAction.textContent = action?.label ?? '';\n this.messageAction.hidden = !action;\n }\n\n /**\n * Says `spoken` to screen readers without showing it, for news the toolbar already shows (an entity's status on its\n * card). `shown` follows it, on screen and spoken; without it, nothing is shown.\n */\n announce(spoken: string, shown = '', info = true): void {\n this.showMessage(shown, info);\n this.message.prepend(el('span', 'visually-hidden', shown ? `${spoken} ` : spoken));\n this.message.classList.toggle('visually-hidden', !shown);\n }\n\n showLogin(text: string, iframeSrc: string | null | undefined): void {\n this.loginText.textContent = text;\n if (iframeSrc) {\n this.loginFrame.src = iframeSrc;\n this.loginFrame.hidden = false;\n } else {\n this.loginFrame.removeAttribute('src');\n this.loginFrame.hidden = true;\n }\n this.login.hidden = false;\n }\n\n hideLogin(): void {\n this.login.hidden = true;\n }\n\n private actions(entityUrn: string | undefined, scope: string): HTMLElement {\n const actions = el('div', 'actions');\n const send = el('button', 'primary', entityUrn ? 'Save all' : 'Save everything');\n send.type = 'button';\n send.setAttribute('aria-label', `Save all unsaved changes ${scope}`);\n send.addEventListener('click', () => this.pendingActions.sendAll(entityUrn));\n const discard = button(entityUrn ? 'Discard all' : 'Discard everything', 'destructive');\n discard.setAttribute('aria-label', `Discard all unsaved changes ${scope}`);\n discard.addEventListener('click', () => this.pendingActions.discardAll(entityUrn));\n actions.append(discard, send);\n return actions;\n }\n}\n", "// Changing what the page shows (live, drafts, back to as built) in one step,\n// crossfaded with the browser's View Transitions API where it has one. No\n// styles on the host page: the browser's default crossfade is used as is.\n\n/**\n * Runs `update` (synchronous DOM changes only: read everything first) as one\n * change to the page. Resolves once the page shows it; the fade may still be\n * running. Without the API, with reduced motion asked for, or in a hidden\n * tab, the page changes at once.\n */\nexport function swapContent(update: () => void): Promise<void> {\n const reduced = window.matchMedia?.('(prefers-reduced-motion: reduce)').matches ?? false;\n if (typeof document.startViewTransition !== 'function' || reduced || document.visibilityState !== 'visible') {\n update();\n return Promise.resolve();\n }\n const transition = document.startViewTransition(update);\n // Only the animation: skipped when another transition (an Astro navigation) starts.\n transition.ready.catch(() => undefined);\n transition.finished.catch(() => undefined);\n // An error in `update` itself is passed on.\n return transition.updateCallbackDone;\n}\n", "// The page in edit mode: which elements show which items, reading the latest\n// content, rendering it (with unsaved previews), and putting the page back\n// as it was when edit mode ends: as built, or with the live content of\n// entities changed in this visit, since a built page lags until a rebuild.\n\nimport type { Entity } from '@baack-software/baack-ts-client';\nimport type { Binding } from './core/discovery.ts';\nimport { createKey } from './core/pending.ts';\nimport { inLiveContent } from './live.ts';\nimport { preview, sortOrderAttribute, urnAttribute, valueOf, type ContentItem, type TypeEntry } from './core/registry.ts';\nimport { isLive, type EditorContext, type Slot } from './targets.ts';\nimport { mark, STATE_ATTRIBUTE, unmark } from './ui/marker.ts';\nimport { swapContent } from './ui/transition.ts';\n\n/** An element exactly as the page rendered it, before edit mode. */\ninterface Snapshot {\n attributes: [string, string][];\n /** Only when the component owns the children; a boolean's children are the page's. */\n children: Node[] | undefined;\n}\n\nexport interface ViewHooks {\n /** The element being edited in place, which must not be re-rendered under the cursor. */\n editingElement(): HTMLElement | undefined;\n /** The binding being edited, in any way. */\n editingBinding(): Binding | undefined;\n closeEditor(): void;\n /** Content changed: the outline may need to redraw. */\n changed(entityUrn?: string): void;\n}\n\n/** What the page shows: the latest drafts (editable), the live page, or drafts as of a time (epoch ms). */\nexport type ReadMode = 'LATEST' | 'live' | number;\n\n/** A scope read ahead of showing it. `draft`: shown by its latest drafts on the live page, as it is not published. */\nexport interface ScopeRead {\n entity: Entity;\n draft: boolean;\n}\n\nexport class PageView {\n private readonly ctx: EditorContext;\n private readonly hooks: ViewHooks;\n private readonly snapshots = new Map<Binding, Snapshot>();\n /** Snapshots carried over when the editor itself re-tags an element (a move), by element and type. */\n private readonly carried = new Map<HTMLElement, Map<TypeEntry, Snapshot>>();\n /** Containers whose children the editor reordered, with their original order. */\n private readonly orders = new Map<Element, Node[]>();\n /** Elements the editor added to preview a new list entry. */\n private readonly added = new Set<Element>();\n private readonly loading = new Map<string, Promise<void>>();\n private editMode = false;\n private readMode: ReadMode = 'LATEST';\n /** Increments on every edit mode change, so late responses from an old session are dropped. */\n private session = 0;\n /** A version from History shown in place of the latest, on every element showing its slot. Nothing is saved. */\n private previewing: { slot: Slot; version: ContentItem } | undefined;\n private readonly previewListeners = new Set<() => void>();\n /** Entities re-read after a change in this visit (a save, a move, a publish). */\n private readonly changedThisVisit = new Set<string>();\n /**\n * The URN each element showed as the page was built, by type (none for a placeholder). Kept across edit\n * sessions: leaving edit mode after a publish leaves newer content on the page, which is not what was built.\n */\n private readonly built = new WeakMap<HTMLElement, Map<TypeEntry, string | undefined>>();\n\n constructor(ctx: EditorContext, hooks: ViewHooks) {\n this.ctx = ctx;\n this.hooks = hooks;\n }\n\n get isEditing(): boolean {\n return this.editMode;\n }\n\n get mode(): ReadMode {\n return this.readMode;\n }\n\n begin(mode: ReadMode = 'LATEST'): void {\n this.editMode = true;\n this.readMode = mode;\n this.session += 1;\n }\n\n /** The read for a mode. Draft reads need a session (rule 6); the loader only starts the editor with one. */\n private readOptions(mode: ReadMode): { version?: string } {\n if (mode === 'live') return {};\n return { version: mode === 'LATEST' ? 'LATEST' : String(mode) };\n }\n\n /**\n * Before edit mode ends: the live views of the entities changed in this\n * visit that are live now, by scope. Read first, so the page changes once.\n */\n readLiveChanges(): Promise<[string, Entity][]> {\n const { store } = this.ctx;\n const scopes = [...this.changedThisVisit]\n .filter((urn) => isLive(store.view(urn)?.status))\n .flatMap((urn) => store.scopesFor(urn));\n return this.readLive(scopes);\n }\n\n private async readLive(scopes: string[]): Promise<[string, Entity][]> {\n try {\n return await Promise.all(scopes.map(async (scope): Promise<[string, Entity]> => [scope, await this.ctx.views.read(scope)]));\n } catch (error) {\n // The page stays as built; a retry outside edit mode shows the published content.\n void this.ctx.feedback.report(error, 'show the published content', () => {\n void this.readLive(scopes).then((reads) => {\n if (!this.editMode) this.showLive(reads);\n });\n });\n return [];\n }\n }\n\n /**\n * Outside edit mode, shows live views read by `readLiveChanges`: the page\n * as visitors see it once the site is rebuilt (or at once, if it renders\n * per request). Items with no live version keep what the page rendered.\n * True when anything differed from the page as rendered.\n */\n showLive(reads: [string, Entity][]): boolean {\n const { store, discovery } = this.ctx;\n for (const [scope, entity] of reads) store.loadEntity(scope, entity);\n const scopes = new Set(reads.map(([scope]) => scope));\n let changed = false;\n // Restoring put back the sort orders the editor changed (moves): bind as the page is now.\n discovery.flush();\n for (const binding of discovery.all()) {\n if (!scopes.has(binding.scope)) continue;\n const stored = store.itemFor(binding);\n if (!stored?.item.urn || binding.element.getAttribute(urnAttribute(binding.entry)) === stored.item.urn) continue;\n this.recordBuilt(binding);\n this.ctx.live.render(binding, stored.item);\n changed = true;\n }\n store.clearEntities();\n return changed;\n }\n\n /**\n * Leaves edit mode in one change to the page: puts it back as built, then\n * shows the live reads from `readLiveChanges`. True when those differed.\n */\n async leave(reads: [string, Entity][]): Promise<boolean> {\n let changed = false;\n await swapContent(() => {\n this.end();\n changed = this.showLive(reads);\n });\n return changed;\n }\n\n /** Reads every scope in a mode without changing what the page shows, so a switch can change it once. */\n async prefetch(mode: ReadMode, scopes: string[]): Promise<Map<string, ScopeRead>> {\n const reads = await Promise.all(scopes.map(async (scope) => [scope, await this.readIn(scope, mode)] as const));\n return new Map(reads);\n }\n\n /** Switches the read mode in one change to the page, from reads made by `prefetch`. */\n async switchTo(mode: ReadMode, reads: Map<string, ScopeRead>): Promise<void> {\n const { store, discovery } = this.ctx;\n await swapContent(() => {\n this.end();\n this.begin(mode);\n for (const [scope, read] of reads) {\n store.loadEntity(scope, read.entity);\n if (read.draft) this.draftsOnLivePage.add(read.entity.urn);\n }\n // Ending put back the sort orders the editor changed: bind as the page is now.\n discovery.flush();\n for (const binding of discovery.all()) this.show(binding);\n });\n this.hooks.changed();\n }\n\n /** The URN of the version being previewed, if any. */\n get previewedUrn(): string | undefined {\n return this.previewing?.version.urn;\n }\n\n /** Called when a preview starts or stops. */\n onPreviewChange(listener: () => void): void {\n this.previewListeners.add(listener);\n }\n\n /**\n * Shows a version's value on every element showing its slot, in place of\n * the latest. The element keeps the latest version's URN, so editing still\n * starts from the latest. Nothing is sent. Not for view-rendered types.\n */\n previewVersion(slot: Slot, version: ContentItem): void {\n const previous = this.previewing?.slot;\n this.previewing = { slot, version };\n if (previous && !sameSlot(previous, slot)) this.reshow(previous);\n this.reshow(slot);\n this.notifyPreview();\n }\n\n /** Ends a preview (only one of `slot`, when given), showing the latest again. */\n stopPreview(slot?: Slot): void {\n const previewing = this.previewing;\n if (!previewing || (slot && !sameSlot(previewing.slot, slot))) return;\n this.previewing = undefined;\n this.reshow(previewing.slot);\n this.notifyPreview();\n }\n\n private notifyPreview(): void {\n for (const listener of this.previewListeners) listener();\n }\n\n /** Puts every element back as the page rendered it and forgets what was read. */\n end(): void {\n if (this.previewing) {\n this.previewing = undefined;\n this.notifyPreview();\n }\n this.editMode = false;\n this.session += 1;\n this.ctx.live.endPreviews();\n for (const element of this.added) element.remove();\n this.added.clear();\n this.restoreOrders();\n for (const binding of [...this.snapshots.keys()]) this.restore(binding);\n for (const [element, byEntry] of this.carried) {\n // Moves inside live content are not supported yet: its framework owns the order.\n for (const saved of byEntry.values()) if (element.isConnected && !inLiveContent(element)) restoreSnapshot(element, saved);\n }\n this.carried.clear();\n this.ctx.store.clearEntities();\n this.loading.clear();\n this.draftsOnLivePage.clear();\n this.ctx.sources.clear();\n }\n\n async hydrate(bindings: Binding[]): Promise<void> {\n const session = this.session;\n const scopes = new Set(bindings.map((binding) => binding.scope));\n await Promise.all([...scopes].map((scope) => this.loadScope(scope)));\n if (session !== this.session) return;\n await swapContent(() => {\n if (session !== this.session) return;\n for (const binding of bindings) {\n if (this.ctx.discovery.of(binding.element).includes(binding)) this.show(binding);\n }\n });\n if (session !== this.session) return;\n this.hooks.changed();\n }\n\n /** Entities shown by their latest drafts on the live page, because they are not published. */\n readonly draftsOnLivePage = new Set<string>();\n\n /** Reads a scope in the current mode. On the live page, an entity that is not published shows its latest drafts. */\n private async readScope(scope: string): Promise<Entity> {\n const { entity, draft } = await this.readIn(scope, this.readMode);\n if (draft) this.draftsOnLivePage.add(entity.urn);\n else this.draftsOnLivePage.delete(entity.urn);\n return entity;\n }\n\n private async readIn(scope: string, mode: ReadMode): Promise<ScopeRead> {\n const { views } = this.ctx;\n if (mode !== 'live') return { entity: await views.read(scope, this.readOptions(mode)), draft: false };\n const { entity, live } = await views.readAsLive(scope);\n return { entity, draft: !live };\n }\n\n /** Reads a scope (or an entity URN) in the current mode, once per edit session. */\n loadScope(scope: string): Promise<void> {\n const { store, feedback, discovery } = this.ctx;\n if (store.hasScope(scope)) return Promise.resolve();\n let loading = this.loading.get(scope);\n if (!loading) {\n const session = this.session;\n loading = this.readScope(scope)\n .then((entity) => {\n if (session === this.session) store.loadEntity(scope, entity);\n })\n .catch((error: unknown) => {\n this.loading.delete(scope);\n const action = this.readMode === 'live' ? 'load the live content' : 'load the latest content';\n void feedback.report(error, action, () => void this.hydrate(discovery.all()));\n });\n this.loading.set(scope, loading);\n }\n return loading;\n }\n\n /** Renders a binding from the latest view, previewing any unsaved value. */\n show(binding: Binding): void {\n const { store, pending } = this.ctx;\n const { element, entry } = binding;\n if (!this.snapshots.has(binding)) this.snapshots.set(binding, this.carriedSnapshot(element, entry) ?? snapshot(element, entry));\n this.recordBuilt(binding);\n const stored = store.itemFor(binding);\n const previewing = this.previewing;\n if (stored?.item.urn && previewing && sameSlot(previewing.slot, { ...binding, entityUrn: store.entityFor(binding.scope)! })) {\n this.ctx.live.render(binding, preview(entry, stored.item, valueOf(entry, previewing.version)));\n mark(element, 'previewing');\n return;\n }\n if (stored?.item.urn) {\n const edit = pending.getEdit(stored.item.urn);\n const usable = edit && !edit.stale;\n // A view-rendered type cannot preview: the page would need the server's rendering.\n const item = usable && !entry.renderedByView ? preview(entry, stored.item, edit.value) : stored.item;\n this.ctx.live.render(binding, item);\n mark(element, usable ? 'changed' : this.publishedSinceBuilt(binding, stored.item.urn) ? 'published' : 'editable');\n return;\n }\n const entityUrn = store.entityFor(binding.scope);\n const create = entityUrn\n ? pending.getCreate(createKey({ entityUrn, type: entry.type, name: binding.name, sortOrder: binding.sortOrder }))\n : undefined;\n if (create && !entry.renderedByView) {\n this.ctx.live.render(binding, { name: binding.name, sortOrder: binding.sortOrder, ...create.value } as ContentItem);\n mark(element, 'changed');\n } else {\n mark(element, create ? 'changed' : 'unresolved');\n }\n }\n\n /** Notes what an element showed as built, the first time the editor is about to change it. */\n private recordBuilt({ element, entry }: Binding): void {\n const byEntry = this.built.get(element) ?? new Map<TypeEntry, string | undefined>();\n if (!byEntry.has(entry)) byEntry.set(entry, element.getAttribute(urnAttribute(entry)) ?? undefined);\n this.built.set(element, byEntry);\n }\n\n /** On the live page: the element shows a version published since the page was built (not a draft shown instead). */\n private publishedSinceBuilt(binding: Binding, urn: string): boolean {\n if (this.readMode !== 'live') return false;\n const entityUrn = this.ctx.store.entityFor(binding.scope);\n if (!entityUrn || this.draftsOnLivePage.has(entityUrn)) return false;\n return this.built.get(binding.element)?.get(binding.entry) !== urn;\n }\n\n /** How many elements on the live page show content published since the page was built. */\n countPublishedSinceBuilt(): number {\n return new Set(\n this.ctx.discovery\n .all()\n .filter((binding) => binding.element.getAttribute(STATE_ATTRIBUTE) === 'published')\n .map((binding) => binding.element),\n ).size;\n }\n\n showAll(): void {\n for (const binding of this.ctx.discovery.all()) this.show(binding);\n }\n\n /** Re-renders every element showing a slot or version, except one being edited in place. */\n reshow(target: Slot & { urn?: string | undefined }): void {\n const { discovery, store } = this.ctx;\n for (const binding of discovery.all()) {\n if (binding.entry !== target.entry || store.entityFor(binding.scope) !== target.entityUrn) continue;\n const showsUrn = target.urn && binding.element.getAttribute(urnAttribute(binding.entry)) === target.urn;\n const showsSlot = binding.name === target.name && binding.sortOrder === target.sortOrder;\n if (!showsUrn && !showsSlot) continue;\n if (this.hooks.editingElement() === binding.element) continue;\n this.show(binding);\n }\n }\n\n forget(bindings: Binding[]): void {\n for (const binding of bindings) {\n if (this.hooks.editingBinding() === binding) this.hooks.closeEditor();\n // Re-tagged by the editor: its snapshot travels with it to the new binding.\n if (this.carried.get(binding.element)?.has(binding.entry)) {\n this.snapshots.delete(binding);\n continue;\n }\n this.restore(binding);\n }\n }\n\n /**\n * Gives an element a new sort order (after a move), keeping the snapshot of\n * how the page rendered it, so leaving edit mode still restores it exactly.\n */\n retag(binding: Binding, sortOrder: number, name = binding.name): void {\n const { element, entry } = binding;\n const saved = this.snapshots.get(binding) ?? snapshot(element, entry);\n const byEntry = this.carried.get(element) ?? new Map<TypeEntry, Snapshot>();\n byEntry.set(entry, saved);\n this.carried.set(element, byEntry);\n element.setAttribute(sortOrderAttribute(entry), String(sortOrder));\n element.setAttribute(`data-${entry.attribute}-name`, name);\n }\n\n private carriedSnapshot(element: HTMLElement, entry: TypeEntry): Snapshot | undefined {\n const byEntry = this.carried.get(element);\n const saved = byEntry?.get(entry);\n if (saved) byEntry!.delete(entry);\n if (byEntry && byEntry.size === 0) this.carried.delete(element);\n return saved;\n }\n\n /** Remembers a container's child order before the editor first reorders it. */\n rememberOrder(container: Element): void {\n // The page's framework owns the order of live content: the editor never moves it, so has nothing to put back.\n if (inLiveContent(container)) return;\n if (!this.orders.has(container)) this.orders.set(container, [...container.childNodes]);\n }\n\n /** Puts a container's children back in the order the page rendered them. */\n restoreOrder(container: Element): void {\n const nodes = this.orders.get(container);\n if (!nodes) return;\n container.append(...nodes.filter((node) => node.parentNode === container || !node.parentNode));\n this.orders.delete(container);\n }\n\n private restoreOrders(): void {\n for (const container of [...this.orders.keys()]) this.restoreOrder(container);\n }\n\n /** Tracks an element the editor added to preview a new entry; removed when edit mode ends. */\n track(element: Element): void {\n this.added.add(element);\n }\n\n /** Re-reads the latest view of an entity and re-renders what it shows, so templates and renderings update. */\n async refresh(entityUrn: string): Promise<void> {\n const { store, feedback, discovery } = this.ctx;\n const session = this.session;\n const scopes = store.scopesFor(entityUrn);\n if (this.readMode === 'LATEST') this.changedThisVisit.add(entityUrn);\n try {\n for (const scope of scopes) {\n const entity = await this.readScope(scope);\n if (session !== this.session) return;\n store.loadEntity(scope, entity);\n }\n } catch (error) {\n void feedback.report(error, 'show the latest content', () => void this.refresh(entityUrn));\n return;\n }\n for (const binding of discovery.all()) {\n if (scopes.includes(binding.scope) && this.hooks.editingBinding() !== binding) this.show(binding);\n }\n this.hooks.changed(entityUrn);\n }\n\n /** Elements showing a slot of an entity. */\n bindingsAt(slot: Slot): Binding[] {\n return this.ctx.discovery\n .all()\n .filter(\n (b) =>\n b.entry === slot.entry &&\n b.name === slot.name &&\n b.sortOrder === slot.sortOrder &&\n this.ctx.store.entityFor(b.scope) === slot.entityUrn,\n );\n }\n\n /** Elements of an entity's scopes whose slot has no item, one per slot. */\n missingBindings(entityUrn: string): Binding[] {\n const { store, discovery } = this.ctx;\n const seen = new Set<string>();\n return discovery.all().filter((binding) => {\n if (store.entityFor(binding.scope) !== entityUrn) return false;\n if (store.itemAt(entityUrn, binding.entry, binding.name, binding.sortOrder)) return false;\n const key = createKey({ entityUrn, type: binding.entry.type, name: binding.name, sortOrder: binding.sortOrder });\n if (seen.has(key)) return false;\n seen.add(key);\n return true;\n });\n }\n\n private restore(binding: Binding): void {\n const saved = this.snapshots.get(binding);\n this.snapshots.delete(binding);\n unmark(binding.element);\n if (this.ctx.live.restore(binding)) {\n // The page re-renders its own value later; until then the element carries the URN it had, as a later read compares it.\n const urn = urnAttribute(binding.entry);\n const own = saved?.attributes.find(([name]) => name === urn)?.[1];\n if (own) binding.element.setAttribute(urn, own);\n else binding.element.removeAttribute(urn);\n return;\n }\n if (saved && binding.element.isConnected) restoreSnapshot(binding.element, saved);\n }\n}\n\nfunction snapshot(element: HTMLElement, entry: TypeEntry): Snapshot {\n const ownsChildren = entry.component?.(element).ownsChildren ?? true;\n return {\n attributes: [...element.attributes].map((attribute) => [attribute.name, attribute.value]),\n children: ownsChildren ? [...element.childNodes].map((node) => node.cloneNode(true)) : undefined,\n };\n}\n\nfunction restoreSnapshot(element: HTMLElement, saved: Snapshot): void {\n const names = new Set(saved.attributes.map(([name]) => name));\n for (const attribute of [...element.attributes]) {\n if (!names.has(attribute.name)) element.removeAttribute(attribute.name);\n }\n for (const [name, value] of saved.attributes) element.setAttribute(name, value);\n if (saved.children) element.replaceChildren(...saved.children);\n}\n\nfunction sameSlot(a: Slot, b: Slot): boolean {\n return a.entityUrn === b.entityUrn && a.entry === b.entry && a.name === b.name && a.sortOrder === b.sortOrder;\n}\n", "// The editor's composition root: builds the shared context and the modules,\n// and owns edit mode, the unsaved-changes list, and the stash.\n//\n// view.ts the page in edit mode: reading, rendering, restoring\n// editing.ts opening editors and recording unsaved values\n// saving.ts saving, save all, create all\n// outline-model.ts the item outline\n// onboarding.ts entities for pages that have none, new pages\n\nimport type { ClientContext } from '@baack-software/baack-ts-client';\nimport { Discovery, SCOPE_ATTRIBUTE } from './core/discovery.ts';\nimport { PendingEdits, type Pending } from './core/pending.ts';\nimport type { ItemType, TypeEntry } from './core/registry.ts';\nimport { Stash } from './core/stash.ts';\nimport { Store } from './core/store.ts';\nimport type { Transport } from './core/transport.ts';\nimport { Editing } from './editing.ts';\nimport { Feedback } from './feedback.ts';\nimport { History } from './history.ts';\nimport { Moves } from './moves.ts';\nimport { OrderTags } from './ui/order-tags.ts';\nimport { Images } from './images.ts';\nimport { GroupLog } from './core/groups.ts';\nimport { Onboarding } from './onboarding.ts';\nimport { OutlineModel } from './outline-model.ts';\nimport { Publishing } from './publishing.ts';\nimport { LiveIslands } from './live.ts';\nimport { Saving } from './saving.ts';\nimport { isLive, pageEntity, pageFirst, type EditorContext, type EditorHooks, type Value } from './targets.ts';\nimport { displayPath, EntityDirectory } from './core/entity-directory.ts';\nimport { defaultPagePath } from './page-entity.ts';\nimport type { EntityPickerSource } from './ui/entity-picker.ts';\nimport { announcePublished, DEFAULT_LIVE_NOTE, fixedMessage, type PublishedDetail } from './after-publish.ts';\nimport './config.ts'; // Declares window.baackEditorConfig.\nimport type { EditorHost } from './ui/host.ts';\nimport { Popover } from './ui/popover.ts';\nimport { Toolbar, type PendingGroup } from './ui/toolbar.ts';\nimport { PageView, type ReadMode, type ScopeRead } from './view.ts';\nimport { ScopedViews } from './core/scoped-views.ts';\n\nexport class Editor {\n private readonly ctx: EditorContext;\n private readonly view: PageView;\n private readonly editing: Editing;\n private readonly saving: Saving;\n private readonly outline: OutlineModel;\n private readonly onboarding: Onboarding;\n private readonly history: History;\n private readonly publishing: Publishing;\n private readonly moves: Moves;\n /** The tags on the members of keyed groups (cards, sections), with their move menus. */\n private readonly tags: OrderTags;\n private readonly images: Images;\n private readonly stash: Stash | undefined;\n private restored = false;\n\n constructor(\n transport: Transport,\n host: EditorHost,\n entries: readonly TypeEntry[],\n registry: readonly TypeEntry[],\n context: ClientContext,\n ) {\n const store = new Store();\n let toolbar: Toolbar | undefined;\n const feedback = new Feedback(transport, () => toolbar!);\n toolbar = new Toolbar(host, () => feedback.retryAfterLogin(), {\n sendAll: (entityUrn) => void this.saving.saveAll(entityUrn),\n discardAll: (entityUrn) => this.saving.discardAll(entityUrn),\n });\n const discovery = new Discovery(entries, {\n added: (bindings) => {\n if (this.view.isEditing) void this.view.hydrate(bindings);\n },\n removed: (bindings) => this.view.forget(bindings),\n });\n\n const directory = new EntityDirectory(\n transport,\n async () => {\n // Every company the user may administer; the context's own when that cannot be listed.\n const companies = await transport.companies().catch(() => []);\n const urns = companies.map((company) => company.urn);\n return urns.length > 0 ? urns : context.company?.urn ? [context.company.urn] : [];\n },\n context.user?.urn,\n );\n\n this.ctx = {\n transport,\n host,\n registry,\n store,\n pending: new PendingEdits(() => this.pendingChanged()),\n toolbar,\n popover: new Popover(host),\n panels: {\n show: (content, options) => this.outline.showPanel(content, options),\n },\n feedback,\n views: new ScopedViews(transport),\n sources: new Map<string, Value>(),\n discovery,\n canPublish: ['PUBLISHER', 'ADMIN', 'SUPER'].includes(context.user?.role ?? ''),\n requiredImageSlots: window.baackEditorConfig?.requiredImageSlots ?? ['DEFAULT'],\n live: new LiveIslands(store),\n hooks: {\n openHistory: (slot) => void this.history.open(slot),\n publishEntity: (entityUrn) => void this.publishing.openReview(entityUrn),\n canReorder: (binding) => (this.moves.groupOf(binding)?.units.length ?? 0) > 1,\n reorder: (binding) => this.moves.openReorder(binding),\n moveBy: (binding, delta) => this.moves.moveBy(binding, delta),\n relocate: (target) => {\n this.editing.close();\n this.outline.focusSlot(target);\n },\n showItem: (slot) => this.outline.selectItem(slot),\n rename: (slot, item) => void this.moves.relocate(undefined, slot.entityUrn, slot.entry, item),\n moveSlot: (slot, item, sortOrder) => this.moves.moveTo(slot.entityUrn, slot.entry, item, { name: slot.name, sortOrder }),\n runPlan: (planId) => this.moves.run(planId),\n saveImage: (target, files) => this.images.save(target, files),\n } satisfies EditorHooks,\n groups: context.user?.urn ? new GroupLog(context.user.urn) : undefined,\n entry: (type: ItemType) => registry.find((entry) => entry.type === type)!,\n entityTitle: (entityUrn: string) => {\n const name = store.view(entityUrn)?.name;\n return name ? `Content for ${displayPath(name)}` : `Entity ${entityUrn.slice(0, 8)}`;\n },\n announcePublished: (entityUrn, done, options = {}) => {\n const view = store.view(entityUrn);\n const name = view?.name ?? '';\n const detail: PublishedDetail = { entityUrn, name, path: name && pagePath(displayPath(name)), language: view?.language ?? '', variant: view?.variant ?? '' };\n if (options.itemUrn) detail.itemUrn = options.itemUrn;\n const quiet = options.quiet === true && toolbar.showsEntity(entityUrn);\n void announcePublished(toolbar, window.baackEditorConfig?.afterPublish, detail, done, { ...(options.info !== undefined ? { info: options.info } : {}), quiet });\n },\n };\n\n this.stash = context.user?.urn ? new Stash(context.user.urn) : undefined;\n this.view = new PageView(this.ctx, {\n editingElement: () => (this.editing.current?.session ? this.editing.current.target.binding?.element : undefined),\n editingBinding: () => this.editing.current?.target.binding,\n closeEditor: () => this.editing.close(),\n changed: (entityUrn) => {\n this.refreshTags();\n this.outline.changed(entityUrn);\n this.history?.changed(entityUrn);\n this.publishing?.changed();\n },\n });\n this.saving = new Saving(this.ctx, this.view, () => this.editing);\n this.editing = new Editing(this.ctx, this.view, (target) => this.saving.save(target));\n this.onboarding = new Onboarding({\n transport,\n toolbar,\n context,\n registry,\n store,\n panels: this.ctx.panels,\n openEntity: (entityUrn) => this.outline.openEntity(entityUrn),\n entityNameForPage: window.baackEditorConfig?.entityNameForPage,\n report: (error, action, retry) => feedback.report(error, action, retry),\n created: (entity) => directory.remember(entity),\n });\n this.ctx.popover.setEntitySource(this.entitySource(directory));\n this.outline = new OutlineModel(this.ctx, this.view, this.editing, this.saving, this.onboarding);\n const sidebar = this.outline.outline.stack;\n sidebar.avoid(toolbar.modeButton.closest<HTMLElement>('.toolbar')!);\n // A bottom sheet on narrow screens steps aside while an item is edited, so only the popover shows (host.ts).\n const popover = this.ctx.popover.element;\n new MutationObserver(() => sidebar.element.classList.toggle('item-editing', !popover.hidden)).observe(popover, {\n attributes: true,\n attributeFilter: ['hidden'],\n });\n this.moves = new Moves(this.ctx, this.view, () => this.editing, () => this.ctx.groups, (change) => this.saving.commit(change));\n this.tags = new OrderTags(this.ctx.host, (binding) => this.moves.openOrderMenu(binding));\n this.moves.onOrderChange(() => this.refreshTags());\n this.images = new Images(this.ctx, this.view, () => this.saving, () => this.editing);\n this.publishing = new Publishing(this.ctx, this.view, window.baackEditorConfig?.publishTimeoutMs ?? 5 * 60 * 1000, this.outline.outline.stack, {\n show: (level, entityUrn) => this.outline.showAbove(entityUrn, level),\n });\n this.history = new History(this.ctx, this.editing, this.view, this.outline.outline.stack, {\n show: (level, entityUrn) => this.outline.showAbove(entityUrn, level),\n publishEntity: (entityUrn) => this.ctx.hooks.publishEntity(entityUrn),\n published: async (entityUrn) => {\n await this.view.refresh(entityUrn);\n await this.publishing.refreshStatus(entityUrn);\n },\n });\n\n toolbar.modeButton.addEventListener('click', () => void this.setEditMode(!this.view.isEditing));\n toolbar.itemsButton.addEventListener('click', () => this.outline.toggle());\n toolbar.setOpenEntity((entityUrn) => this.outline.openEntity(entityUrn));\n toolbar.onLifecycle(() => this.outline.changed());\n toolbar.setOpenPending(() => this.outline.togglePending());\n toolbar.onPending(() => this.outline.changed());\n this.outline.onClose(() => this.history.stopPreview());\n toolbar.readButton.addEventListener('click', () => void this.setReadMode(this.view.mode === 'LATEST' ? 'live' : 'LATEST'));\n document.addEventListener('keydown', (event) => {\n if (this.view.isEditing && event.altKey && event.shiftKey && event.code === 'KeyI') {\n event.preventDefault();\n this.outline.toggle();\n if (this.outline.outline.isOpen) this.outline.outline.focusFilter();\n }\n });\n discovery.start();\n }\n\n private leaving: Promise<void> | undefined;\n\n get isEditing(): boolean {\n return this.view.isEditing;\n }\n\n /** `showLive`: on leaving, show content published in this visit (not when only switching the read mode). */\n async setEditMode(on: boolean, mode: ReadMode = 'LATEST', showLive = true): Promise<void> {\n // Leaving reads the live content first; a click meanwhile waits for it.\n await this.leaving;\n if (on === this.view.isEditing) return;\n const { toolbar, discovery } = this.ctx;\n toolbar.setEditMode(on);\n if (on) {\n this.view.begin(mode);\n this.startMode(mode);\n await this.view.hydrate(discovery.all());\n await this.afterRead(mode);\n } else {\n this.stopMode();\n // Content published in this visit is shown live, not as the (older) built page.\n const reading = showLive && this.view.mode === 'LATEST' ? this.view.readLiveChanges() : Promise.resolve([]);\n this.leaving = reading.then(() => undefined);\n const live = await reading;\n this.leaving = undefined;\n if (await this.view.leave(live)) {\n toolbar.showMessage(`Showing the published content. ${fixedMessage(window.baackEditorConfig?.afterPublish) ?? DEFAULT_LIVE_NOTE}`, true);\n }\n }\n }\n\n /** The toolbar and editing for a read mode, before its content shows. */\n private startMode(mode: ReadMode): void {\n this.showReadMode(mode);\n if (mode === 'LATEST') {\n this.editing.attach();\n this.publishing.start();\n this.outline.setNewEntity(() => void this.onboarding.offerNewEntity(this.pageLanguage()));\n }\n }\n\n /** The language of the page's entity: the default for a new entity. */\n private pageLanguage(): string {\n const { store } = this.ctx;\n const page = pageEntity(store);\n return (page && store.view(page)?.language) || document.documentElement.lang || 'en-GB';\n }\n\n /** Where entity fields (references) find entities, and how they create one. */\n private entitySource(directory: EntityDirectory): EntityPickerSource {\n const { transport, feedback } = this.ctx;\n const onboarding = () => this.onboarding;\n const pageLanguage = () => this.pageLanguage();\n return {\n list: (onUpdate) => directory.list(onUpdate),\n describe: (urn) => directory.describe(urn),\n get language() {\n return pageLanguage();\n },\n create(container, path) {\n return new Promise((resolve) => {\n void onboarding()\n .newEntityForm({\n title: 'New entity',\n submitLabel: 'Create and choose it',\n path,\n language: this.language,\n onCreated: (entity) => resolve(directory.remember(entity)),\n onCancel: () => resolve(undefined),\n })\n .then((form) => {\n // Escape cancels this form only, not the item's.\n form.element.addEventListener('keydown', (event) => {\n if (event.key !== 'Escape') return;\n event.preventDefault();\n event.stopPropagation();\n form.cancel();\n });\n container.replaceChildren(form.element);\n form.element.querySelector('input')?.focus();\n });\n });\n },\n note: async (urn) => {\n const entity = await transport.readEntity(urn);\n directory.remember(entity);\n return isLive(entity.status) || entity.status === 'PUBLISH'\n ? ''\n : `${displayPath(entity.name)} is not published yet, so pages show it only once it is.`;\n },\n pagePath,\n report: (error, action, retry) => void feedback.report(error, action, retry),\n };\n }\n\n /** Tags every member of a keyed group while the editable drafts show. */\n private refreshTags(): void {\n if (!this.tags) return;\n if (this.view.isEditing && this.view.mode === 'LATEST') this.tags.show(this.moves.keyedMembers());\n else this.tags.clear();\n }\n\n /** Closes everything that belongs to the current read mode. */\n private stopMode(): void {\n const { toolbar } = this.ctx;\n this.tags.clear();\n this.editing.detach();\n this.editing.close();\n this.outline.clear();\n this.history.close();\n this.publishing.stop();\n this.moves.panel.close();\n this.outline.setNewEntity(undefined);\n toolbar.showMessage('');\n toolbar.hideLogin();\n }\n\n /** Once a mode's content shows: its notices, then unsaved work and onboarding for the editable drafts. */\n private async afterRead(mode: ReadMode): Promise<void> {\n const { toolbar, discovery } = this.ctx;\n if (mode === 'live') {\n // Content published since the page was built is live, but a built site shows it only after its next build.\n const newer = this.view.countPublishedSinceBuilt();\n const parts = [\n newer > 0\n ? `Showing the live content. ${newer === 1 ? '1 item was' : `${newer} items were`} published since this page was built, outlined in green. ${fixedMessage(window.baackEditorConfig?.afterPublish) ?? DEFAULT_LIVE_NOTE}`\n : 'Showing the live page, as visitors see it.',\n ];\n if (this.view.draftsOnLivePage.size > 0) {\n const titles = [...this.view.draftsOnLivePage].map((urn) => this.ctx.entityTitle(urn)).join(', ');\n parts.push(`Not published yet, so shown as the latest drafts: ${titles}.`);\n }\n toolbar.showMessage(`${parts.join(' ')} Editing is off.`, true);\n }\n if (mode !== 'LATEST') return;\n await this.restoreStash();\n if (discovery.unscoped().length > 0 && !document.documentElement.hasAttribute(SCOPE_ATTRIBUTE)) {\n void this.onboarding.offerEntityForPage();\n }\n }\n\n /**\n * Shows the page as the live site does, or as the latest drafts were at a\n * time (read-only), or back to the editable latest drafts.\n */\n async setReadMode(mode: ReadMode): Promise<void> {\n if (!this.view.isEditing) {\n await this.setEditMode(true, mode);\n return;\n }\n if (mode === this.view.mode) return;\n // Read the new mode first, so the page changes once instead of showing the built page in between.\n const scopes = [...new Set(this.ctx.discovery.all().map((binding) => binding.scope))];\n let reads: Map<string, ScopeRead>;\n try {\n reads = await this.view.prefetch(mode, scopes);\n } catch (error) {\n const action = mode === 'live' ? 'load the live content' : 'load the latest content';\n void this.ctx.feedback.report(error, action, () => void this.setReadMode(mode));\n return;\n }\n if (!this.view.isEditing || mode === this.view.mode) return;\n this.stopMode();\n this.startMode(mode);\n await this.view.switchTo(mode, reads);\n await this.afterRead(mode);\n }\n\n private showReadMode(mode: ReadMode): void {\n const { toolbar } = this.ctx;\n toolbar.setReadMode(mode === 'LATEST');\n if (mode === 'live') toolbar.showMessage('Showing the live page, as visitors see it. Editing is off.', true);\n if (typeof mode === 'number') {\n toolbar.showMessage(`Showing the latest drafts as of ${new Date(mode).toLocaleString()}. Read-only.`, true);\n }\n }\n\n // ---------------------------------------------------------------------\n // Unsaved work: the toolbar list, the stash, and leaving the page\n // ---------------------------------------------------------------------\n\n private pendingChanged(): void {\n const { pending, toolbar } = this.ctx;\n const all = pending.all();\n this.stash?.save(all);\n const byEntity = pending.byEntity();\n const groups: PendingGroup[] = pageFirst(this.ctx.store, [...byEntity.keys()]).map((entityUrn) => ({\n entityUrn,\n title: this.ctx.entityTitle(entityUrn),\n rows: byEntity.get(entityUrn)!.map((p) => ({\n label: `${p.name} #${p.sortOrder}`,\n detail:\n p.kind === 'create'\n ? 'new item'\n : p.kind === 'move'\n ? `${p.label}: to ${p.to.name === p.name ? '' : p.to.name}#${p.to.sortOrder}`\n : p.stale\n ? 'based on an older version'\n : 'edit',\n problem: p.kind === 'edit' && p.stale === true,\n ...(p.kind === 'edit' && p.stale ? { action: { label: 'Resolve', run: (anchor: HTMLElement) => void this.saving.resolve(p, anchor) } } : {}),\n })),\n }));\n toolbar.setPending(groups);\n if (all.length > 0) {\n window.addEventListener('beforeunload', onBeforeUnload);\n } else {\n window.removeEventListener('beforeunload', onBeforeUnload);\n }\n // Built lazily: the first restore runs before the outline exists.\n this.outline?.changed();\n }\n\n /** Restores unsaved work from this browser, once per page load. */\n private async restoreStash(): Promise<void> {\n if (this.restored || !this.stash) return;\n this.restored = true;\n const items = this.stash.load();\n if (items.length === 0) return;\n await Promise.all([...new Set(items.map((p) => p.entityUrn))].map((urn) => this.view.loadScope(urn)));\n const restored = items.map((p): Pending => {\n if (p.kind !== 'edit') return p;\n const current = this.ctx.store.itemAt(p.entityUrn, this.ctx.entry(p.type), p.name, p.sortOrder);\n return current?.item.urn === p.urn ? { ...p, stale: false } : { ...p, stale: true };\n });\n this.ctx.pending.load(restored);\n this.view.showAll();\n this.ctx.toolbar.showMessage(\n `Restored ${restored.length} unsaved ${restored.length === 1 ? 'change' : 'changes'} from this browser.`,\n true,\n );\n }\n}\n\nfunction onBeforeUnload(event: BeforeUnloadEvent): void {\n event.preventDefault();\n}\n\n/** The page address an entity serves, by the site's rule or the default (`/home` is `/`). */\nfunction pagePath(path: string): string {\n return (window.baackEditorConfig?.pagePathForEntity ?? defaultPagePath)(path);\n}\n", "import { Endpoint, type TextItem } from '@baack-software/baack-ts-client';\nimport * as components from '@baack-software/baack-ts-components/components';\nimport type { TypeEntry } from '../core/registry.ts';\n\n// Something that looks like a tag: <p>, </p>, <br/>, <!-- -->, <script ...>.\nconst MARKUP = /<\\/?[a-z!][^>]*>/i;\n\nexport const text: TypeEntry<TextItem> = {\n type: 'text',\n label: 'Text',\n attribute: 'text',\n entityArray: 'texts',\n endpoint: Endpoint.TEXT,\n historyEndpoint: Endpoint.TEXT_HISTORY,\n surface: 'inline',\n valueKeys: ['value'],\n\n component: (element) =>\n element.localName === 'meta'\n ? components.meta\n : element.hasAttribute('data-section')\n ? components.section\n : escaped(element.getAttribute('data-text-layout') === 'paragraphs' ? components.textBlock : components.text),\n\n find: (view, name, sortOrder) => view.text(name, sortOrder),\n\n defaults: () => ({ value: '' }),\n\n // While editing, the element holds the raw value as text (see InlineEdit).\n read: (element) => ({ value: plainText(element) }),\n\n // Away from its element: head items, the outline, and creates.\n form: {\n fields: [{ key: 'value', label: 'Text', kind: 'textarea' }],\n toForm: (value) => ({ value: value.value }),\n fromForm: (values) => ({ value: typeof values['value'] === 'string' ? values['value'] : '' }),\n },\n\n fromPlaceholder: (element) => {\n if (element.localName === 'meta') return { value: element.getAttribute('content') ?? '' };\n // A section's (or card's) order item holds its key, never the content it wraps.\n if (element.hasAttribute('data-section')) return { value: element.getAttribute('data-section') ?? '' };\n if (element.getAttribute('data-text-layout') === 'paragraphs') {\n return { value: [...element.querySelectorAll(':scope > p')].map((p) => plainText(p)).join('\\n\\n') };\n }\n return { value: plainText(element) };\n },\n\n validate: ({ value }) =>\n MARKUP.test(value)\n ? [{ level: 'warning', message: 'This looks like HTML. Text items are plain text, so the page shows the tags as typed, and apps on other platforms will too.' }]\n : [],\n};\n\n/**\n * The editor never inserts a text value as HTML (CLAUDE.md rule 1), even where\n * the page opted into `unsafeLiteral`: in edit mode it shows drafts written by\n * other people. Such an element shows its text escaped while editing, keeps\n * its marker, and gets its HTML back from the page's own rendering on exit.\n */\nfunction escaped<P extends components.TextProps>(\n spec: components.ComponentSpec<TextItem, P>,\n): components.ComponentSpec<TextItem, P> {\n return {\n ...spec,\n render(ref, props) {\n const node = spec.render(ref, { ...props, unsafeLiteral: false });\n if (props.unsafeLiteral) node.attrs['data-text-unsafe-literal'] = '';\n return node;\n },\n };\n}\n\n/** The element's text with line breaks kept; the browser may insert <br> while editing. */\nfunction plainText(element: Node): string {\n let result = '';\n for (const node of element.childNodes) {\n if (node.nodeType === Node.TEXT_NODE) {\n result += node.nodeValue ?? '';\n } else if (node.nodeName === 'BR') {\n result += '\\n';\n } else {\n result += plainText(node);\n }\n }\n return result;\n}\n", "// The registry: one entry for each of the thirteen item types.\n\nimport type { TypeEntry } from '../core/registry.ts';\nimport { text } from './text.ts';\nimport {\n boolean,\n dateTime,\n double,\n image,\n json,\n latLong,\n link,\n long,\n markdown,\n money,\n reference,\n template,\n} from './values.ts';\n\nexport const registry: readonly TypeEntry[] = [\n text,\n markdown,\n template,\n json,\n boolean,\n long,\n double,\n dateTime,\n latLong,\n money,\n image,\n link,\n reference,\n] as readonly TypeEntry[];\n\n/** The types a page can show, so discovery looks for their elements. */\nexport const onPage = registry.filter((entry) => entry.component !== undefined);\n", "// The lazily loaded editor. Started by the loader once the user asks to edit.\n\nimport { Editor } from './controller.ts';\nimport type { Transport } from './core/transport.ts';\nimport type { EditorHost } from './ui/host.ts';\nimport type { ClientContext } from '@baack-software/baack-ts-client';\nimport { onPage, registry } from './types/index.ts';\n\nimport type { ReadMode } from './view.ts';\n\nexport function start(options: { transport: Transport; host: EditorHost; context: ClientContext; mode?: ReadMode }): Editor {\n const editor = new Editor(options.transport, options.host, onPage, registry, options.context);\n void editor.setReadMode(options.mode ?? 'LATEST');\n return editor;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["h", "tag", "attrs", "children", "toDom", "node", "doc", "element", "name", "value", "child", "patch", "volatile", "ownsChildren", "withCarried", "entry", "base", "value", "merged", "key", "kept", "valueOf", "item", "field", "sameValue", "a", "b", "preview", "renderInto", "element", "slot", "spec", "props", "patch", "toRepresentation", "entityUrn", "representation", "nameAttribute", "sortOrderAttribute", "urnAttribute", "SCOPE_ATTRIBUTE", "Discovery", "entries", "listener", "entry", "nameAttribute", "records", "root", "sortOrderAttribute", "element", "target", "rescan", "removedSome", "record", "node", "candidates", "added", "removed", "next", "unscoped", "previous", "sameBindings", "bindings", "scope", "name", "sortOrder", "slots", "rawOrder", "problem", "a", "b", "binding", "i", "createKey", "slot", "pendingKey", "pending", "PendingEdits", "onChange", "urn", "key", "entityUrn", "removed", "items", "planId", "p", "groups", "PREFIX", "Stash", "userUrn", "PREFIX", "now", "dropExpired", "raw", "data", "error", "items", "index", "key", "savedAt", "EntityView", "_EntityView", "entity", "items", "name", "item", "a", "b", "sortOrder", "texts", "markdowns", "templates", "booleans", "doubles", "longs", "money", "dateTimes", "images", "latLongs", "jsons", "links", "references", "collection", "client", "path", "params", "headers", "Endpoint", "Store", "scope", "entity", "EntityView", "entityUrn", "urn", "binding", "entry", "name", "sortOrder", "view", "found", "stored", "item", "oldUrn", "previous", "next", "items", "index", "candidate", "EntityMismatchError", "expectedUrn", "received", "NotLiveError", "entityUrn", "isLive", "status", "ScopedViews", "transport", "options", "locator", "entity", "error", "isBaackApiError", "fields", "reviewAction", "ctx", "entityUrn", "pageEntity", "store", "root", "SCOPE_ATTRIBUTE", "pageFirst", "entityUrns", "page", "a", "b", "lifecycleLabel", "status", "STATE_ATTRIBUTE", "OUTLINES", "drawOutline", "element", "state", "line", "colour", "opacity", "light", "dark", "PAGE_COLOURS", "faded", "value", "saved", "mark", "outline", "outlineOffset", "display", "minWidth", "minHeight", "fitEmpty", "original", "unmark", "textParagraphs", "value", "paragraph", "line", "lines", "textLines", "LINKABLE", "linkSegments", "text", "part", "index", "segment", "currencyDigits", "currencyCode", "moneyAmount", "item", "minorToMajor", "moneySymbol", "units", "digits", "negative", "whole", "padded", "majorToMinor", "match", "sign", "fraction", "parseTimestamp", "formatDate", "format", "time", "options", "formatNumber", "locale", "PASS_THROUGH_NAMES", "CONTRACT_ATTRIBUTE", "isPassThrough", "name", "passThrough", "attributes", "allowed", "value", "contentAttributes", "type", "ref", "placeholder", "volatileFor", "more", "common", "element", "lines", "texts", "render", "joinWithBreaks", "line", "index", "h", "linked", "text", "linkify", "linkSegments", "segment", "props", "fromItem", "textLines", "tag", "content", "textBlock", "textParagraphs", "paragraphs", "paragraph", "meta", "rendered", "html", "markdown", "template", "money", "item", "recorded", "amount", "moneyAmount", "moneySymbol", "numeric", "formatNumber", "long", "double", "dateTime", "instant", "parseTimestamp", "formatDate", "boolean", "shown", "latLong", "attrs", "link", "label", "MEDIUM_MIN_WIDTH", "LARGE_MIN_WIDTH", "image", "section", "volatileFor", "ref", "props", "value", "h", "passThrough", "contentAttributes", "element", "str", "v", "sourceEntry", "type", "label", "endpoint", "historyEndpoint", "spec", "find", "element", "value", "values", "markdown", "Endpoint", "view", "name", "sortOrder", "template", "json", "parsed", "error", "boolean", "wholeNumber", "text", "long", "decimal", "double", "toLocalInput", "time", "parseTimestamp", "fromLocalInput", "dateTime", "latLong", "latitude", "longitude", "validCurrency", "code", "money", "minorToMajor", "currencyDigits", "currencyCode", "digits", "unitValue", "majorToMinor", "IMAGE_SLOTS", "image", "slot", "replacing", "kept", "note", "altText", "link", "href", "key", "field", "reference", "urn", "POLL_MS", "POLL_LIMIT_MS", "Images", "ctx", "view", "saving", "editing", "target", "chosen", "problem", "imageFileIssues", "issue", "files", "withSizes", "pending", "popover", "store", "feedback", "entry", "form", "base", "value", "withCarried", "size", "IMAGE_SLOTS", "slot", "change", "createKey", "version", "error", "failure", "previews", "file", "transport", "toolbar", "panel", "el", "lines", "line", "label", "progress", "say", "text", "results", "answered", "result", "failed", "index", "uploaded", "fieldOf", "placed", "item", "retry", "actions", "url", "current", "stillEmpty", "urn", "sizes", "start", "attempt", "resolve", "entityUrn", "binding", "urnAttribute", "mark", "widths", "original", "width", "scaled", "bitmap", "height", "canvas", "type", "blob", "reject", "b", "name", "IMAGE_TYPES", "MB", "max", "warn", "bytes", "issues", "LIVE_ATTRIBUTE", "ITEM_SHOWN_EVENT", "LIVE_REQUEST_EVENT", "inLiveContent", "element", "LIVE_ATTRIBUTE", "LiveIslands", "store", "LIVE_REQUEST_EVENT", "binding", "item", "renderInto", "detail", "key", "dispatch", "urnAttribute", "sortOrder", "event", "ITEM_SHOWN_EVENT", "IS_MAC", "InlineEdit", "element", "raw", "host", "callbacks", "inLiveContent", "fitEmpty", "placeCaret", "modifier", "event", "selection", "range", "Editing", "ctx", "view", "save", "event", "discovery", "toolbar", "element", "binding", "target", "path", "anchor", "store", "entityUrn", "urn", "urnAttribute", "visible", "ownsChildren", "placeholder", "pending", "host", "popover", "entry", "stored", "value", "valueOf", "session", "InlineEdit", "mark", "hooks", "actions", "form", "base", "createKey", "values", "current", "notes", "isLive", "sources", "transport", "feedback", "source", "error", "active", "fileIssues", "imageFileIssues", "input", "withCarried", "sameValue", "describeFailure", "error", "action", "hasSession", "isBaackApiError", "debug", "debugText", "describeApiError", "describeOther", "detail", "NotLiveError", "EntityMismatchError", "language", "body", "pretty", "text", "path", "Feedback", "transport", "toolbar", "error", "action", "retry", "failure", "hasSession", "isBaackApiError", "contextError", "describeFailure", "message", "iframeSrc", "percentChange", "before", "after", "formatPercent", "percent", "size", "MAX_TOKENS", "diffWords", "a", "b", "table", "i", "j", "parts", "push", "kind", "text", "last", "dispatchItemUpdated", "detail", "dispatchItemPublished", "dispatchEntityState", "dispatchEntityPublished", "entityUrn", "SimpleForm", "title", "fields", "submitLabel", "onSubmit", "onCancel", "el", "field", "label", "input", "option", "selectBox", "cancel", "actions", "event", "key", "busy", "message", "ConflictError", "change", "newest", "summarise", "entry", "value", "field", "summariseChange", "before", "after", "parts", "delta", "moneyDelta", "was", "now", "percent", "percentChange", "formatPercent", "Saving", "ctx", "view", "editing", "target", "pending", "popover", "feedback", "key", "createKey", "isActive", "files", "current", "issue", "error", "StoredElsewhereError", "retry", "failure", "store", "transport", "stored", "saved", "toRepresentation", "dispatchItemUpdated", "checkSlot", "pendingKey", "slot", "oldUrn", "discovery", "sources", "toolbar", "elements", "binding", "urnAttribute", "editingBinding", "mark", "entityUrn", "queue", "p", "planId", "urn", "failures", "debug", "touched", "only", "reviewAction", "anchor", "conflict", "when", "parseTimestamp", "done", "removed", "count", "isLive", "form", "SimpleForm", "panel", "created", "sent", "ELEMENTS", "renderChange", "value", "box", "el", "part", "tag", "className", "element", "ItemHistoryView", "onMore", "onCompare", "el", "compareLabel", "selectBox", "text", "rows", "hasMore", "expanded", "row", "item", "head", "time", "note", "chevron", "icon", "actions", "actionButton", "renderChange", "toggle", "button", "open", "nested", "inner", "renderVersion", "body", "model", "mark", "changes", "label", "change", "section", "action", "variantOf", "WAIT_MS", "count", "shown", "timer", "tooltip", "trigger", "text", "description", "el", "place", "content", "event", "show", "type", "hide", "tip", "rect", "width", "height", "above", "SIDE_KEY", "SLIDE_MS", "CRUMBS", "stacks", "NARROW", "SidebarStack", "host", "el", "bar", "button", "close", "icon", "tooltip", "nav", "readSide", "toolbar", "listener", "top", "above", "entry", "level", "focus", "from", "id", "index", "left", "levels", "side", "section", "animated", "direction", "other", "origin", "current", "parent", "items", "shown", "item", "position", "separator", "li", "crumb", "content", "here", "jump", "to", "away", "options", "active", "event", "rows", "row", "next", "drillRow", "label", "detail", "open", "text", "chevron", "confirmLevel", "body", "block", "box", "actions", "choice", "choiceButton", "variantOf", "COLLAPSE_MS", "History", "ctx", "editing", "view", "stack", "hooks", "slot", "sameItem", "itemView", "ItemHistoryView", "against", "state", "level", "itemLevelId", "version", "selection", "shown", "binding", "element", "when", "parseTimestamp", "entityUrn", "current", "page", "error", "rows", "index", "grouped", "groupTime", "time", "head", "live", "versionLevelId", "renderVersion", "previous", "describe", "notes", "group", "urn", "body", "el", "marks", "beforeIsLive", "changes", "actions", "status", "isLive", "busy", "anchor", "onlyVersion", "previewing", "disabled", "wholeItem", "where", "blocks", "summarise", "description", "next", "successor", "nextWhen", "confirmLevel", "button", "transport", "pending", "toolbar", "feedback", "promoted", "dispatchItemPublished", "remaining", "other", "edit", "store", "sources", "templates", "template", "pattern", "item", "source", "entry", "mode", "before", "after", "diffWords", "was", "now", "summariseChange", "a", "b", "reorder", "items", "newOrder", "values", "item", "a", "b", "byKey", "key", "changes", "index", "to", "planInsert", "at", "sorted", "before", "after", "left", "right", "shiftRun", "run", "step", "swap", "templatesUsing", "ctx", "entityUrn", "name", "store", "sources", "transport", "template", "pattern", "users", "item", "source", "ReorderPanel", "panels", "el", "buttons", "cancel", "title", "entityUrn", "entries", "actions", "head", "tail", "left", "text", "busy", "label", "entry", "from", "to", "button", "child", "b", "index", "row", "handle", "icon", "up", "down", "add", "tooltip", "event", "candidate", "Moves", "ctx", "view", "editing", "groups", "create", "ReorderPanel", "binding", "entityUrn", "rows", "list", "container", "units", "child", "member", "b", "stored", "key", "value", "groupLabel", "sortOrder", "bindings", "cells", "group", "before", "unit", "what", "keys", "at", "anchor", "delta", "index", "target", "byKey", "inLiveContent", "elements", "markers", "element", "marker", "places", "original", "unchanged", "item", "close", "changes", "reorder", "missing", "steps", "change", "label", "ok", "feedback", "toolbar", "to", "error", "failure", "seen", "members", "popover", "labelOf", "revert", "render", "changed", "i", "move", "next", "previous", "following", "u", "isLive", "listener", "items", "plan", "planInsert", "shift", "model", "reference", "copy", "bound", "entry", "store", "templates", "templatesUsing", "info", "el", "form", "SimpleForm", "values", "name", "swapping", "panel", "occupant", "swap", "planId", "step", "pending", "transport", "done", "newest", "pendingKey", "moved", "saved", "toRepresentation", "valueOf", "dispatchItemUpdated", "d", "reviewAction", "total", "message", "debug", "debugDetails", "retry", "back", "actions", "urn", "remaining", "OrderTags", "host", "onOpen", "el", "members", "member", "index", "text", "focused", "tag", "button", "element", "rect", "PREFIX", "GroupLog", "userUrn", "PREFIX", "groups", "versionUrn", "group", "error", "CACHE_KEY", "CACHE_MS", "CONCURRENT_READS", "RETRY_DELAYS_MS", "displayPath", "name", "EntityDirectory", "transport", "owners", "userUrn", "stored", "entry", "urn", "entity", "summary", "found", "onUpdate", "error", "urns", "complete", "listing", "compare", "missing", "failure", "next", "worker", "isBaackApiError", "result", "delay", "resolve", "results", "owner", "cached", "a", "b", "HOME_ENTITY_NAME", "defaultEntityName", "pathname", "path", "defaultPagePath", "name", "isIndexName", "Onboarding", "deps", "transport", "panels", "path", "defaultEntityName", "language", "entity", "panel", "el", "snippet", "use", "SCOPE_ATTRIBUTE", "handle", "actions", "error", "isBaackApiError", "form", "done", "next", "urn", "copy", "close", "shown", "displayPath", "options", "owners", "SimpleForm", "c", "values", "owner", "name", "variant", "isIndexName", "found", "describeFailure", "entityUrn", "store", "context", "view", "created", "sourceUrn", "targetUrn", "start", "registry", "items", "entry", "item", "progress", "index", "value", "valueOf", "slot", "toRepresentation", "retry", "link", "fallback", "companies", "preferred", "a", "b", "wrapper", "code", "children", "row", "renderReview", "body", "model", "actions", "status", "el", "parts", "blocker", "warning", "list", "change", "row", "head", "name", "tooltip", "note", "renderChange", "buttons", "run", "schedule", "confirm", "renderSchedule", "label", "cancel", "hint", "field", "at", "back", "BACKOFF", "Publishing", "ctx", "view", "stuckAfterMs", "stack", "hooks", "tracked", "urn", "status", "entityUrn", "entity", "error", "publishTimestamp", "raw", "previous", "next", "dispatchEntityState", "isLive", "dispatchEntityPublished", "seconds", "rows", "pageFirst", "canPublish", "title", "publish", "review", "row", "lifecycleLabel", "at", "parseTimestamp", "since", "question", "confirmLevel", "button", "done", "note", "store", "views", "live", "latest", "shown", "latestUrns", "changes", "blockers", "warnings", "id", "count", "existing", "body", "el", "renderReview", "path", "label", "renderSchedule", "feedback", "fresh", "now", "when", "transport", "updated", "before", "toolbar", "owner", "lines", "change", "task", "select", "entry", "item", "latestItems", "liveItems", "liveByUrn", "slot", "liveBySlot", "drafts", "befores", "accounted", "index", "notes", "moveNotes", "valueChanged", "sameValue", "valueOf", "describe", "sentence", "other", "draft", "inSlot", "history", "pagination", "found", "version", "image", "missingSlots", "reference", "referenced", "required", "fields", "registry", "urns", "after", "text", "value", "was", "diffWords", "summariseChange", "summarise", "delta", "Outline", "host", "onOpen", "onClose", "SidebarStack", "body", "section", "filter", "parts", "lifecycle", "el", "verbs", "verb", "input", "applyFilter", "group", "groupElement", "heading", "list", "row", "actions", "action", "item", "main", "note", "flag", "button", "variantOf", "value", "query", "MARKUP", "OutlineModel", "ctx", "view", "editing", "saving", "onboarding", "Outline", "pageEntity", "listener", "entityUrn", "run", "slot", "level", "stack", "from", "content", "options", "heading", "title", "id", "open", "handle", "path", "index", "focus", "showing", "slots", "above", "body", "refresh", "el", "store", "toolbar", "entities", "pageFirst", "parts", "urn", "drillRow", "lifecycleLabel", "button", "tooltip", "actions", "known", "section", "hooks", "entry", "name", "items", "item", "a", "b", "moving", "move", "sortOrder", "rows", "used", "first", "last", "gaps", "_", "order", "isRoot", "pending", "registry", "counterpart", "found", "published", "isLive", "onPage", "settings", "unused", "bindings", "visible", "duplicates", "other", "row", "flags", "isSlot", "anchor", "target", "missing", "binding", "key", "createKey", "lifecycle", "verb", "live", "entity", "urns", "form", "SimpleForm", "e", "values", "panel", "required", "result", "record", "missingSlots", "DEFAULT_LIVE_NOTE", "fixedMessage", "setting", "announcePublished", "toolbar", "detail", "done", "info", "quiet", "say", "message", "isInfo", "error", "reason", "SHOWN", "pickers", "summaryLabel", "entity", "EntityPicker", "source", "key", "urn", "onChange", "el", "field", "icon", "error", "note", "listing", "query", "loaded", "entities", "known", "a", "b", "option", "chosen", "typed", "path", "create", "index", "event", "count", "current", "open", "step", "count", "Dropdown", "trigger", "items", "event", "focus", "menu", "el", "item", "entry", "icon", "restoreFocus", "index", "entries", "other", "current", "letter", "step", "path", "rect", "width", "height", "below", "top", "COMMON_CURRENCIES", "IS_MAC", "Popover", "host", "el", "revert", "button", "event", "source", "anchor", "label", "meta", "hint", "actions", "fields", "values", "wide", "field", "blocks", "description", "choices", "block", "box", "choice", "choiceButton", "variantOf", "end", "key", "input", "files", "file", "text", "problem", "status", "value", "run", "link", "tooltip", "shown", "action", "listed", "extra", "icon", "more", "Dropdown", "issues", "issue", "message", "debug", "debugDetails", "sending", "onInput", "caption", "current", "preview", "img", "wrapper", "picker", "EntityPicker", "list", "code", "fill", "entities", "entity", "path", "rect", "height", "width", "panel", "panelRect", "top", "left", "Toolbar", "host", "onRetryAfterLogin", "pendingActions", "createLauncher", "bar", "row", "el", "tooltip", "button", "run", "retry", "on", "latest", "groups", "count", "total", "group", "listener", "open", "rows", "entityUrn", "page", "unsent", "label", "section", "title", "list", "pendingRow", "item", "text", "info", "debug", "action", "debugDetails", "spoken", "shown", "iframeSrc", "scope", "actions", "send", "discard", "swapContent", "update", "reduced", "transition", "PageView", "ctx", "hooks", "mode", "store", "scopes", "urn", "isLive", "scope", "error", "reads", "discovery", "entity", "changed", "binding", "stored", "urnAttribute", "swapContent", "read", "listener", "slot", "version", "previous", "sameSlot", "previewing", "element", "byEntry", "saved", "inLiveContent", "restoreSnapshot", "bindings", "session", "draft", "views", "live", "feedback", "loading", "action", "pending", "entry", "snapshot", "preview", "valueOf", "mark", "edit", "usable", "item", "entityUrn", "create", "createKey", "STATE_ATTRIBUTE", "target", "showsUrn", "showsSlot", "sortOrder", "name", "sortOrderAttribute", "container", "nodes", "node", "b", "seen", "key", "unmark", "own", "ownsChildren", "attribute", "names", "value", "a", "Editor", "transport", "host", "entries", "registry", "context", "store", "Store", "toolbar", "feedback", "Feedback", "Toolbar", "entityUrn", "discovery", "Discovery", "bindings", "directory", "EntityDirectory", "urns", "company", "PendingEdits", "Popover", "content", "options", "ScopedViews", "LiveIslands", "slot", "binding", "delta", "target", "item", "sortOrder", "planId", "files", "GroupLog", "type", "entry", "name", "displayPath", "done", "view", "detail", "pagePath", "quiet", "announcePublished", "Stash", "PageView", "Saving", "Editing", "Onboarding", "error", "action", "retry", "entity", "OutlineModel", "sidebar", "popover", "Moves", "change", "OrderTags", "Images", "Publishing", "level", "History", "event", "on", "mode", "showLive", "reading", "live", "fixedMessage", "DEFAULT_LIVE_NOTE", "page", "pageEntity", "onboarding", "pageLanguage", "onUpdate", "urn", "container", "path", "resolve", "form", "isLive", "newer", "parts", "titles", "SCOPE_ATTRIBUTE", "scopes", "reads", "pending", "all", "byEntity", "groups", "pageFirst", "p", "anchor", "onBeforeUnload", "items", "restored", "defaultPagePath", "MARKUP", "text", "Endpoint", "element", "meta", "section", "escaped", "textBlock", "view", "name", "sortOrder", "plainText", "value", "values", "p", "spec", "ref", "props", "node", "result", "registry", "text", "markdown", "template", "json", "boolean", "long", "double", "dateTime", "latLong", "money", "image", "link", "reference", "onPage", "entry", "start", "options", "editor", "Editor", "onPage", "registry"]
|
|
7
7
|
}
|