@operato/layout 10.29.59 → 10.29.60

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.
@@ -103,6 +103,12 @@ export declare function closeEntity360(): void;
103
103
  * they are. A subject no longer shown is only remembered.
104
104
  */
105
105
  export declare function setEntity360Value(subject: Pick<Entity360Subject, 'kind' | 'id'>, value: Record<string, any>): void;
106
+ /**
107
+ * Reads the shown 360 again when what changed is about it - the header's refresh, asked by whatever wrote the records
108
+ * (an applied AI card). Every section reads its door again and keeps what it holds (ADR-0098); another 360, or none,
109
+ * is left alone. Returns whether one was read again.
110
+ */
111
+ export declare function refreshEntity360(about: (subject: Pick<Entity360Subject, 'kind' | 'id'>) => boolean): boolean;
106
112
  type Entity360Listener = (subject: Entity360Subject | undefined) => void;
107
113
  /**
108
114
  * Hear which subject the registry's 360 shows - on open, on back or forward, and `undefined` on close.
@@ -181,6 +181,17 @@ export function setEntity360Value(subject, value) {
181
181
  draw(shown);
182
182
  }
183
183
  }
184
+ /**
185
+ * Reads the shown 360 again when what changed is about it - the header's refresh, asked by whatever wrote the records
186
+ * (an applied AI card). Every section reads its door again and keeps what it holds (ADR-0098); another 360, or none,
187
+ * is left alone. Returns whether one was read again.
188
+ */
189
+ export function refreshEntity360(about) {
190
+ if (!shown || !isEntity360Shown(OWNER) || !about({ kind: shown.kind, id: shown.id }))
191
+ return false;
192
+ draw({ ...shown });
193
+ return true;
194
+ }
184
195
  const listeners = new Set();
185
196
  /**
186
197
  * Hear which subject the registry's 360 shows - on open, on back or forward, and `undefined` on close.
@@ -1 +1 @@
1
- {"version":3,"file":"entity360-registry.js","sourceRoot":"","sources":["../../../src/actions/entity360-registry.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, type TemplateResult } from 'lit'\nimport { i18next } from '@operato/i18n'\nimport { OxPrompt } from '@operato/popup/ox-prompt.js'\nimport { addressController, writeAddress } from '@operato/utils/address.js'\n\nimport { store, UPDATE_CONTEXT } from '@operato/shell'\n\nimport { showEntity360, hideEntity360, canGoBackEntity360, isEntity360Shown, isEntity360Unkept, navigateEntity360 } from './entity360.js'\n\nconst returnFocusByAddress = new Map<string, () => void>()\n\n/**\n * Which kinds of thing open a 360, and what each module puts in it (ADR-0067, the person 360 ruling).\n *\n * An entity's name is a link to its 360 (ADR-0067 decision 1), and a grid shows names by the dozen -\n * `updater` alone is a person column on 65 framework screens. Writing an opener into every column\n * would never finish. Instead a kind is declared once with the GraphQL `__typename`s it claims, and\n * whatever draws a value can ask `entity360KindOf(value)`: registered, it is a link; not, it stays\n * text, exactly as before.\n *\n * This file knows no product words and imports no product module. A kind brings its own title; each\n * module hangs its own section with its own read door (`registerEntity360Section`), the way activity\n * panels hang on the activity detail. Opening a kind with no section says so in one line - never a\n * blank dock.\n */\n\n/** The thing a 360 is about: its kind, its id, and the value it was opened from. */\nexport interface Entity360Subject {\n kind: string\n id: string\n value: Record<string, any>\n}\n\nexport interface Entity360KindDeclaration {\n /** The name sections register under - 'person', 'role', … */\n kind: string\n /** The GraphQL `__typename`s whose values open this kind. A typename belongs to one kind. */\n typenames: string[]\n /**\n * The kind's one identifier for a value - what the address, the links and `subject.id` all carry (ADR-0067\n * decision 6). A section reads its door by `subject.id` alone: a reload or a shared link brings nothing else.\n * Without it, `value.id`.\n */\n id?(value: Record<string, any>): string | null | undefined\n /** The dock's title for a subject - what a person recognises it by. */\n title(subject: Entity360Subject): string\n /** A line under the title, if the kind has one. */\n context?(subject: Entity360Subject): string\n /**\n * The open 360 is what the page talks about: while it is open the page context's `subject` is\n * `{ type: kind, id }`, so the AI dock follows it (ai-assistant registerSubjectSurface). Closing\n * gives the page its own subject back. Off by default - a kind the assistant has no surface for\n * would only take the page's subject away.\n */\n assistantSubject?: boolean\n}\n\nexport interface Entity360Section {\n /** Unique within its kind. */\n name: string\n /** Lower comes first; equal orders keep the order they were registered in. */\n order?: number\n /** The section's content - usually the module's own element, which reads its own door. */\n render(subject: Entity360Subject): TemplateResult\n}\n\nexport type Entity360Rejection = { kind: string; name?: string; reason: string }\n\nconst kinds = new Map<string, Entity360KindDeclaration>()\nconst kindOfTypename = new Map<string, string>()\nconst sections = new Map<string, (Entity360Section & { at: number })[]>()\nconst rejected: Entity360Rejection[] = []\nlet registered = 0\n\n/** The dock has one owner for everything opened through this registry. */\nconst OWNER = {}\n\n/**\n * Declare a kind. A kind named twice, or a typename another kind already claims, is refused and\n * kept in `entity360Rejections()` - silently taking the second would reroute links nobody asked to move.\n */\nexport function registerEntity360Kind(declaration: Entity360KindDeclaration): void {\n const kind = String(declaration?.kind ?? '').trim()\n\n if (!kind) return void rejected.push({ kind: '(no kind)', reason: 'no-kind' })\n if (kinds.has(kind)) return void rejected.push({ kind, reason: 'duplicate-kind' })\n if (typeof declaration.title !== 'function') return void rejected.push({ kind, reason: 'no-title' })\n\n const taken = (declaration.typenames || []).find(typename => kindOfTypename.has(typename))\n if (taken) return void rejected.push({ kind, name: taken, reason: 'typename-claimed' })\n\n kinds.set(kind, { ...declaration, kind })\n for (const typename of declaration.typenames || []) kindOfTypename.set(typename, kind)\n}\n\n/** Hang a section on a kind. A name already on that kind is refused. */\nexport function registerEntity360Section(kind: string, section: Entity360Section): void {\n const name = String(section?.name ?? '').trim()\n\n if (!name) return void rejected.push({ kind, reason: 'no-name' })\n if (typeof section.render !== 'function') return void rejected.push({ kind, name, reason: 'no-render' })\n\n const list = sections.get(kind) ?? []\n if (list.some(one => one.name === name)) return void rejected.push({ kind, name, reason: 'duplicate-name' })\n\n list.push({ ...section, name, at: registered++ })\n list.sort((a, b) => (a.order ?? 0) - (b.order ?? 0) || a.at - b.at)\n sections.set(kind, list)\n}\n\n/**\n * The kind a value opens, or `undefined`.\n *\n * `undefined` for anything not registered and for a value without `__typename` (a call that turned\n * the cache off) - the caller draws it as it always has.\n */\nexport function entity360KindOf(value: unknown): string | undefined {\n const typename = (value as any)?.__typename\n return typeof typename === 'string' ? kindOfTypename.get(typename) : undefined\n}\n\n/** The identifier a kind gives a value (its declaration's `id`, else `value.id`); '' when there is none. */\nexport function entity360IdOf(kind: string, value: Record<string, any> | null | undefined): string {\n const declared = kinds.get(kind)?.id\n return String((declared ? declared(value ?? {}) : value?.id) ?? '')\n}\n\n/** Whether a kind was declared - an identifier of an undeclared kind stays text. */\nexport function entity360KindRegistered(kind: string): boolean {\n return kinds.has(kind)\n}\n\n/** The sections hung on a kind, in order. */\nexport function entity360Sections(kind: string): Entity360Section[] {\n return [...(sections.get(kind) ?? [])]\n}\n\n/** What was refused, and why - for a test or a boot check to read. */\nexport function entity360Rejections(): Entity360Rejection[] {\n return [...rejected]\n}\n\nlet shown: Entity360Subject | undefined\n/** Values opened in this page, by address - going back to one gives its section the value it was opened with. */\nconst opened = new Map<string, Record<string, any>>()\n/** The page's own subject while a 360 stands in for it, and the page it belongs to. */\nlet pageSubject: { path: string; subject: unknown; ours?: unknown } | undefined\n\n/** The address of a subject: `f=kind:id`. The id may hold colons (an EPC URN); the kind does not. */\nconst FOCUS = 'f'\nconst addressOf = (kind: string, id: string) => `${kind}:${id}`\n\nfunction subjectInAddress(): { kind: string; id: string } | undefined {\n const value = new URLSearchParams(location.search).get(FOCUS)\n const at = value ? value.indexOf(':') : -1\n return at > 0 ? { kind: value!.slice(0, at), id: value!.slice(at + 1) } : undefined\n}\n\n/**\n * Open the 360 of a value.\n *\n * A kind with sections shows them in order. A kind with none - or a value that opens no kind -\n * shows one line saying there is no 360 for it yet. The dock is never blank.\n */\nexport function openEntity360For(value: Record<string, any>, returnFocus?: () => void, source?: Element): void {\n openEntity360Kind(entity360KindOf(value) ?? '', value, returnFocus, source)\n}\n\n/**\n * Open the 360 of a kind directly - for a value known by its kind and id rather than by a GraphQL\n * typename: an identifier inside a row, or a relation inside another 360.\n *\n * Opening is a step in the address (`f=kind:id`, the same step twin's focus takes), so the dock's back\n * button and the browser's go to the 360 before, and a reload or a shared link opens the same one.\n */\nexport function openEntity360Kind(\n kind: string,\n value: Record<string, any>,\n returnFocus?: () => void,\n /** The element the request comes from; a link inside a popup names that popup as its origin. */\n source?: Element\n): void {\n const subject: Entity360Subject = { kind, id: entity360IdOf(kind, value), value: value ?? {} }\n const address = addressOf(kind, subject.id)\n opened.set(address, subject.value)\n if (returnFocus) returnFocusByAddress.set(address, returnFocus)\n\n if (kind && subject.id) {\n const url = new URL(location.href)\n if (url.searchParams.get(FOCUS) !== address) {\n url.searchParams.set(FOCUS, address)\n void navigateEntity360(url.pathname + url.search + url.hash, source)\n return\n }\n }\n\n /*\n * Already shown - an app that wrote the address itself (twin's focus) opens it again right after the address drew\n * it. Drawing again would hand the sections a new subject, which is how a refresh asks them to read.\n */\n if (shown?.kind === kind && shown.id === subject.id && isEntity360Shown(OWNER)) return\n\n draw(subject, returnFocus)\n}\n\n/*\n * What a 360 section holds unsaved goes when its subject does. A draft keeps it (ADR-0098) - only an entry this\n * browser cannot keep is asked about, with the page's own question, by the address layer's one guard.\n */\naddressController().guard({\n discards: change => (change.focus || change.route) && isEntity360Unkept(OWNER),\n kept: () => false,\n approve: change =>\n !((change.focus || change.route) && isEntity360Unkept(OWNER)) ||\n OxPrompt.open({\n type: 'warning',\n title: i18next.t('title.unsaved-draft', { defaultValue: 'there is an unsaved edit' }),\n text: i18next.t('text.unsaved-may-be-lost', { defaultValue: 'anything not saved is lost.' }),\n confirmButton: { text: i18next.t('button.discard', { defaultValue: 'discard' }), destructive: true },\n cancelButton: { text: i18next.t('button.cancel', { defaultValue: 'cancel' }) },\n signal: change.signal\n })\n})\n\n/* Back and forward walk the address; the dock follows it and adds no step of its own. */\naddressController().subscribe(() => {\n const inAddress = subjectInAddress()\n\n if (inAddress && kinds.has(inAddress.kind)) {\n if (shown?.kind === inAddress.kind && shown.id === inAddress.id && isEntity360Shown(OWNER)) return\n const value = opened.get(addressOf(inAddress.kind, inAddress.id)) ?? { id: inAddress.id }\n draw({ ...inAddress, value }, returnFocusByAddress.get(addressOf(inAddress.kind, inAddress.id)))\n } else if (isEntity360Shown(OWNER)) {\n close(false)\n }\n}, false)\n\n/** Close the registry's 360 and take its step out of the address - for an app whose own state let go of it. */\nexport function closeEntity360(): void {\n if (isEntity360Shown(OWNER)) close(true)\n}\n\n/**\n * What a section has read about its subject - its name, what the title and context are drawn from (ADR-0067\n * decision 6). Opened from an address alone the value is `{ id }`; the section that reads who the subject is gives\n * the rest here, the value is kept for going back to it, and the heading is drawn anew. The sections are left as\n * they are. A subject no longer shown is only remembered.\n */\nexport function setEntity360Value(subject: Pick<Entity360Subject, 'kind' | 'id'>, value: Record<string, any>): void {\n const address = addressOf(subject.kind, subject.id)\n const merged = { ...opened.get(address), ...value, id: subject.id }\n opened.set(address, merged)\n if (shown?.kind === subject.kind && shown.id === subject.id && isEntity360Shown(OWNER)) {\n shown.value = merged\n draw(shown)\n }\n}\n\ntype Entity360Listener = (subject: Entity360Subject | undefined) => void\nconst listeners = new Set<Entity360Listener>()\n\n/**\n * Hear which subject the registry's 360 shows - on open, on back or forward, and `undefined` on close.\n * An app with its own selection (twin's focus) follows the dock through this. Returns the unsubscribe.\n */\nexport function onEntity360Change(listener: Entity360Listener): () => void {\n listeners.add(listener)\n return () => listeners.delete(listener)\n}\n\nfunction tell(subject: Entity360Subject | undefined): void {\n listeners.forEach(listener => listener(subject))\n}\n\nfunction close(clearAddress: boolean): void {\n if (clearAddress && subjectInAddress()) {\n const url = new URL(location.href)\n url.searchParams.delete(FOCUS)\n void writeAddress(url, { replace: true, state: history.state })\n return\n }\n hideEntity360(OWNER)\n shown = undefined\n giveSubjectBack()\n tell(undefined)\n}\n\nfunction draw(subject: Entity360Subject, returnFocus?: () => void): void {\n const { kind, value } = subject\n const declaration = kinds.get(kind)\n const hung = entity360Sections(kind)\n shown = subject\n\n const content = hung.length\n ? html`${hung.map(section => section.render(subject))}`\n : html`<p data-not-yet>${i18next.t('text.entity360-not-yet', { defaultValue: 'there is no 360 for this kind yet.' })}</p>`\n\n showEntity360(\n OWNER,\n {\n key: addressOf(kind, subject.id),\n title: declaration ? declaration.title(subject) : String(value?.name ?? value?.id ?? ''),\n context: declaration?.context ? declaration.context(subject) : '',\n content,\n labels: {\n close: i18next.t('button.close', { defaultValue: 'close' }),\n expand: i18next.t('button.expand', { defaultValue: 'expand' }),\n collapse: i18next.t('button.collapse', { defaultValue: 'collapse' }),\n resize: i18next.t('label.resize', { defaultValue: 'resize' }),\n back: i18next.t('button.back', { defaultValue: 'back' })\n },\n onClose: () => close(true),\n onBack: canGoBackEntity360() ? () => history.back() : undefined,\n /* A new subject of the same kind and id: every section reads its door again and keeps what it holds. */\n onRefresh: () => {\n if (shown === subject) draw({ ...subject })\n }\n },\n returnFocus\n )\n\n if (declaration?.assistantSubject) takeSubject({ type: kind, id: subject.id })\n else giveSubjectBack()\n\n tell(subject)\n}\n\nfunction routeContext(): any {\n return (store.getState() as any)?.route?.context ?? {}\n}\n\nfunction takeSubject(ours: { type: string; id: string }): void {\n const context = routeContext()\n if (!pageSubject || pageSubject.path !== location.pathname) pageSubject = { path: location.pathname, subject: context.subject }\n pageSubject.ours = ours\n store.dispatch({ type: UPDATE_CONTEXT, context: { ...context, subject: ours } })\n}\n\n/** Only on the same page, and only while the subject is still the one the 360 put there. */\nfunction giveSubjectBack(): void {\n const taken = pageSubject\n pageSubject = undefined\n if (!taken || taken.path !== location.pathname) return\n\n const context = routeContext()\n if (context.subject === taken.ours) store.dispatch({ type: UPDATE_CONTEXT, context: { ...context, subject: taken.subject } })\n}\n"]}
1
+ {"version":3,"file":"entity360-registry.js","sourceRoot":"","sources":["../../../src/actions/entity360-registry.ts"],"names":[],"mappings":"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","sourcesContent":["import { html, type TemplateResult } from 'lit'\nimport { i18next } from '@operato/i18n'\nimport { OxPrompt } from '@operato/popup/ox-prompt.js'\nimport { addressController, writeAddress } from '@operato/utils/address.js'\n\nimport { store, UPDATE_CONTEXT } from '@operato/shell'\n\nimport { showEntity360, hideEntity360, canGoBackEntity360, isEntity360Shown, isEntity360Unkept, navigateEntity360 } from './entity360.js'\n\nconst returnFocusByAddress = new Map<string, () => void>()\n\n/**\n * Which kinds of thing open a 360, and what each module puts in it (ADR-0067, the person 360 ruling).\n *\n * An entity's name is a link to its 360 (ADR-0067 decision 1), and a grid shows names by the dozen -\n * `updater` alone is a person column on 65 framework screens. Writing an opener into every column\n * would never finish. Instead a kind is declared once with the GraphQL `__typename`s it claims, and\n * whatever draws a value can ask `entity360KindOf(value)`: registered, it is a link; not, it stays\n * text, exactly as before.\n *\n * This file knows no product words and imports no product module. A kind brings its own title; each\n * module hangs its own section with its own read door (`registerEntity360Section`), the way activity\n * panels hang on the activity detail. Opening a kind with no section says so in one line - never a\n * blank dock.\n */\n\n/** The thing a 360 is about: its kind, its id, and the value it was opened from. */\nexport interface Entity360Subject {\n kind: string\n id: string\n value: Record<string, any>\n}\n\nexport interface Entity360KindDeclaration {\n /** The name sections register under - 'person', 'role', … */\n kind: string\n /** The GraphQL `__typename`s whose values open this kind. A typename belongs to one kind. */\n typenames: string[]\n /**\n * The kind's one identifier for a value - what the address, the links and `subject.id` all carry (ADR-0067\n * decision 6). A section reads its door by `subject.id` alone: a reload or a shared link brings nothing else.\n * Without it, `value.id`.\n */\n id?(value: Record<string, any>): string | null | undefined\n /** The dock's title for a subject - what a person recognises it by. */\n title(subject: Entity360Subject): string\n /** A line under the title, if the kind has one. */\n context?(subject: Entity360Subject): string\n /**\n * The open 360 is what the page talks about: while it is open the page context's `subject` is\n * `{ type: kind, id }`, so the AI dock follows it (ai-assistant registerSubjectSurface). Closing\n * gives the page its own subject back. Off by default - a kind the assistant has no surface for\n * would only take the page's subject away.\n */\n assistantSubject?: boolean\n}\n\nexport interface Entity360Section {\n /** Unique within its kind. */\n name: string\n /** Lower comes first; equal orders keep the order they were registered in. */\n order?: number\n /** The section's content - usually the module's own element, which reads its own door. */\n render(subject: Entity360Subject): TemplateResult\n}\n\nexport type Entity360Rejection = { kind: string; name?: string; reason: string }\n\nconst kinds = new Map<string, Entity360KindDeclaration>()\nconst kindOfTypename = new Map<string, string>()\nconst sections = new Map<string, (Entity360Section & { at: number })[]>()\nconst rejected: Entity360Rejection[] = []\nlet registered = 0\n\n/** The dock has one owner for everything opened through this registry. */\nconst OWNER = {}\n\n/**\n * Declare a kind. A kind named twice, or a typename another kind already claims, is refused and\n * kept in `entity360Rejections()` - silently taking the second would reroute links nobody asked to move.\n */\nexport function registerEntity360Kind(declaration: Entity360KindDeclaration): void {\n const kind = String(declaration?.kind ?? '').trim()\n\n if (!kind) return void rejected.push({ kind: '(no kind)', reason: 'no-kind' })\n if (kinds.has(kind)) return void rejected.push({ kind, reason: 'duplicate-kind' })\n if (typeof declaration.title !== 'function') return void rejected.push({ kind, reason: 'no-title' })\n\n const taken = (declaration.typenames || []).find(typename => kindOfTypename.has(typename))\n if (taken) return void rejected.push({ kind, name: taken, reason: 'typename-claimed' })\n\n kinds.set(kind, { ...declaration, kind })\n for (const typename of declaration.typenames || []) kindOfTypename.set(typename, kind)\n}\n\n/** Hang a section on a kind. A name already on that kind is refused. */\nexport function registerEntity360Section(kind: string, section: Entity360Section): void {\n const name = String(section?.name ?? '').trim()\n\n if (!name) return void rejected.push({ kind, reason: 'no-name' })\n if (typeof section.render !== 'function') return void rejected.push({ kind, name, reason: 'no-render' })\n\n const list = sections.get(kind) ?? []\n if (list.some(one => one.name === name)) return void rejected.push({ kind, name, reason: 'duplicate-name' })\n\n list.push({ ...section, name, at: registered++ })\n list.sort((a, b) => (a.order ?? 0) - (b.order ?? 0) || a.at - b.at)\n sections.set(kind, list)\n}\n\n/**\n * The kind a value opens, or `undefined`.\n *\n * `undefined` for anything not registered and for a value without `__typename` (a call that turned\n * the cache off) - the caller draws it as it always has.\n */\nexport function entity360KindOf(value: unknown): string | undefined {\n const typename = (value as any)?.__typename\n return typeof typename === 'string' ? kindOfTypename.get(typename) : undefined\n}\n\n/** The identifier a kind gives a value (its declaration's `id`, else `value.id`); '' when there is none. */\nexport function entity360IdOf(kind: string, value: Record<string, any> | null | undefined): string {\n const declared = kinds.get(kind)?.id\n return String((declared ? declared(value ?? {}) : value?.id) ?? '')\n}\n\n/** Whether a kind was declared - an identifier of an undeclared kind stays text. */\nexport function entity360KindRegistered(kind: string): boolean {\n return kinds.has(kind)\n}\n\n/** The sections hung on a kind, in order. */\nexport function entity360Sections(kind: string): Entity360Section[] {\n return [...(sections.get(kind) ?? [])]\n}\n\n/** What was refused, and why - for a test or a boot check to read. */\nexport function entity360Rejections(): Entity360Rejection[] {\n return [...rejected]\n}\n\nlet shown: Entity360Subject | undefined\n/** Values opened in this page, by address - going back to one gives its section the value it was opened with. */\nconst opened = new Map<string, Record<string, any>>()\n/** The page's own subject while a 360 stands in for it, and the page it belongs to. */\nlet pageSubject: { path: string; subject: unknown; ours?: unknown } | undefined\n\n/** The address of a subject: `f=kind:id`. The id may hold colons (an EPC URN); the kind does not. */\nconst FOCUS = 'f'\nconst addressOf = (kind: string, id: string) => `${kind}:${id}`\n\nfunction subjectInAddress(): { kind: string; id: string } | undefined {\n const value = new URLSearchParams(location.search).get(FOCUS)\n const at = value ? value.indexOf(':') : -1\n return at > 0 ? { kind: value!.slice(0, at), id: value!.slice(at + 1) } : undefined\n}\n\n/**\n * Open the 360 of a value.\n *\n * A kind with sections shows them in order. A kind with none - or a value that opens no kind -\n * shows one line saying there is no 360 for it yet. The dock is never blank.\n */\nexport function openEntity360For(value: Record<string, any>, returnFocus?: () => void, source?: Element): void {\n openEntity360Kind(entity360KindOf(value) ?? '', value, returnFocus, source)\n}\n\n/**\n * Open the 360 of a kind directly - for a value known by its kind and id rather than by a GraphQL\n * typename: an identifier inside a row, or a relation inside another 360.\n *\n * Opening is a step in the address (`f=kind:id`, the same step twin's focus takes), so the dock's back\n * button and the browser's go to the 360 before, and a reload or a shared link opens the same one.\n */\nexport function openEntity360Kind(\n kind: string,\n value: Record<string, any>,\n returnFocus?: () => void,\n /** The element the request comes from; a link inside a popup names that popup as its origin. */\n source?: Element\n): void {\n const subject: Entity360Subject = { kind, id: entity360IdOf(kind, value), value: value ?? {} }\n const address = addressOf(kind, subject.id)\n opened.set(address, subject.value)\n if (returnFocus) returnFocusByAddress.set(address, returnFocus)\n\n if (kind && subject.id) {\n const url = new URL(location.href)\n if (url.searchParams.get(FOCUS) !== address) {\n url.searchParams.set(FOCUS, address)\n void navigateEntity360(url.pathname + url.search + url.hash, source)\n return\n }\n }\n\n /*\n * Already shown - an app that wrote the address itself (twin's focus) opens it again right after the address drew\n * it. Drawing again would hand the sections a new subject, which is how a refresh asks them to read.\n */\n if (shown?.kind === kind && shown.id === subject.id && isEntity360Shown(OWNER)) return\n\n draw(subject, returnFocus)\n}\n\n/*\n * What a 360 section holds unsaved goes when its subject does. A draft keeps it (ADR-0098) - only an entry this\n * browser cannot keep is asked about, with the page's own question, by the address layer's one guard.\n */\naddressController().guard({\n discards: change => (change.focus || change.route) && isEntity360Unkept(OWNER),\n kept: () => false,\n approve: change =>\n !((change.focus || change.route) && isEntity360Unkept(OWNER)) ||\n OxPrompt.open({\n type: 'warning',\n title: i18next.t('title.unsaved-draft', { defaultValue: 'there is an unsaved edit' }),\n text: i18next.t('text.unsaved-may-be-lost', { defaultValue: 'anything not saved is lost.' }),\n confirmButton: { text: i18next.t('button.discard', { defaultValue: 'discard' }), destructive: true },\n cancelButton: { text: i18next.t('button.cancel', { defaultValue: 'cancel' }) },\n signal: change.signal\n })\n})\n\n/* Back and forward walk the address; the dock follows it and adds no step of its own. */\naddressController().subscribe(() => {\n const inAddress = subjectInAddress()\n\n if (inAddress && kinds.has(inAddress.kind)) {\n if (shown?.kind === inAddress.kind && shown.id === inAddress.id && isEntity360Shown(OWNER)) return\n const value = opened.get(addressOf(inAddress.kind, inAddress.id)) ?? { id: inAddress.id }\n draw({ ...inAddress, value }, returnFocusByAddress.get(addressOf(inAddress.kind, inAddress.id)))\n } else if (isEntity360Shown(OWNER)) {\n close(false)\n }\n}, false)\n\n/** Close the registry's 360 and take its step out of the address - for an app whose own state let go of it. */\nexport function closeEntity360(): void {\n if (isEntity360Shown(OWNER)) close(true)\n}\n\n/**\n * What a section has read about its subject - its name, what the title and context are drawn from (ADR-0067\n * decision 6). Opened from an address alone the value is `{ id }`; the section that reads who the subject is gives\n * the rest here, the value is kept for going back to it, and the heading is drawn anew. The sections are left as\n * they are. A subject no longer shown is only remembered.\n */\nexport function setEntity360Value(subject: Pick<Entity360Subject, 'kind' | 'id'>, value: Record<string, any>): void {\n const address = addressOf(subject.kind, subject.id)\n const merged = { ...opened.get(address), ...value, id: subject.id }\n opened.set(address, merged)\n if (shown?.kind === subject.kind && shown.id === subject.id && isEntity360Shown(OWNER)) {\n shown.value = merged\n draw(shown)\n }\n}\n\n/**\n * Reads the shown 360 again when what changed is about it - the header's refresh, asked by whatever wrote the records\n * (an applied AI card). Every section reads its door again and keeps what it holds (ADR-0098); another 360, or none,\n * is left alone. Returns whether one was read again.\n */\nexport function refreshEntity360(about: (subject: Pick<Entity360Subject, 'kind' | 'id'>) => boolean): boolean {\n if (!shown || !isEntity360Shown(OWNER) || !about({ kind: shown.kind, id: shown.id })) return false\n draw({ ...shown })\n return true\n}\n\ntype Entity360Listener = (subject: Entity360Subject | undefined) => void\nconst listeners = new Set<Entity360Listener>()\n\n/**\n * Hear which subject the registry's 360 shows - on open, on back or forward, and `undefined` on close.\n * An app with its own selection (twin's focus) follows the dock through this. Returns the unsubscribe.\n */\nexport function onEntity360Change(listener: Entity360Listener): () => void {\n listeners.add(listener)\n return () => listeners.delete(listener)\n}\n\nfunction tell(subject: Entity360Subject | undefined): void {\n listeners.forEach(listener => listener(subject))\n}\n\nfunction close(clearAddress: boolean): void {\n if (clearAddress && subjectInAddress()) {\n const url = new URL(location.href)\n url.searchParams.delete(FOCUS)\n void writeAddress(url, { replace: true, state: history.state })\n return\n }\n hideEntity360(OWNER)\n shown = undefined\n giveSubjectBack()\n tell(undefined)\n}\n\nfunction draw(subject: Entity360Subject, returnFocus?: () => void): void {\n const { kind, value } = subject\n const declaration = kinds.get(kind)\n const hung = entity360Sections(kind)\n shown = subject\n\n const content = hung.length\n ? html`${hung.map(section => section.render(subject))}`\n : html`<p data-not-yet>${i18next.t('text.entity360-not-yet', { defaultValue: 'there is no 360 for this kind yet.' })}</p>`\n\n showEntity360(\n OWNER,\n {\n key: addressOf(kind, subject.id),\n title: declaration ? declaration.title(subject) : String(value?.name ?? value?.id ?? ''),\n context: declaration?.context ? declaration.context(subject) : '',\n content,\n labels: {\n close: i18next.t('button.close', { defaultValue: 'close' }),\n expand: i18next.t('button.expand', { defaultValue: 'expand' }),\n collapse: i18next.t('button.collapse', { defaultValue: 'collapse' }),\n resize: i18next.t('label.resize', { defaultValue: 'resize' }),\n back: i18next.t('button.back', { defaultValue: 'back' })\n },\n onClose: () => close(true),\n onBack: canGoBackEntity360() ? () => history.back() : undefined,\n /* A new subject of the same kind and id: every section reads its door again and keeps what it holds. */\n onRefresh: () => {\n if (shown === subject) draw({ ...subject })\n }\n },\n returnFocus\n )\n\n if (declaration?.assistantSubject) takeSubject({ type: kind, id: subject.id })\n else giveSubjectBack()\n\n tell(subject)\n}\n\nfunction routeContext(): any {\n return (store.getState() as any)?.route?.context ?? {}\n}\n\nfunction takeSubject(ours: { type: string; id: string }): void {\n const context = routeContext()\n if (!pageSubject || pageSubject.path !== location.pathname) pageSubject = { path: location.pathname, subject: context.subject }\n pageSubject.ours = ours\n store.dispatch({ type: UPDATE_CONTEXT, context: { ...context, subject: ours } })\n}\n\n/** Only on the same page, and only while the subject is still the one the 360 put there. */\nfunction giveSubjectBack(): void {\n const taken = pageSubject\n pageSubject = undefined\n if (!taken || taken.path !== location.pathname) return\n\n const context = routeContext()\n if (context.subject === taken.ours) store.dispatch({ type: UPDATE_CONTEXT, context: { ...context, subject: taken.subject } })\n}\n"]}