@ai-matrx/summon 0.1.17 → 0.1.19
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/CHANGELOG.md +26 -1
- package/dist/chunk-server-C4KQZFIN.js +411 -0
- package/dist/chunk-server-C4KQZFIN.js.map +1 -0
- package/dist/chunk-server-H7NUWPEM.js +94 -0
- package/dist/chunk-server-H7NUWPEM.js.map +1 -0
- package/dist/chunk-server-WP7NOTZQ.js +208 -0
- package/dist/chunk-server-WP7NOTZQ.js.map +1 -0
- package/dist/dock.cjs +41 -112
- package/dist/dock.cjs.map +1 -1
- package/dist/dock.js +42 -113
- package/dist/dock.js.map +1 -1
- package/dist/handles.js +9 -272
- package/dist/handles.js.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +350 -810
- package/dist/index.js.map +1 -1
- package/dist/lite.cjs +16 -76
- package/dist/lite.cjs.map +1 -1
- package/dist/lite.js +17 -77
- package/dist/lite.js.map +1 -1
- package/dist/open.js +74 -439
- package/dist/open.js.map +1 -1
- package/dist/react.cjs +2 -2
- package/dist/react.cjs.map +1 -1
- package/dist/react.js +2 -2
- package/dist/react.js.map +1 -1
- package/dist/window.cjs +192 -287
- package/dist/window.cjs.map +1 -1
- package/dist/window.d.cts +3 -1
- package/dist/window.d.ts +3 -1
- package/dist/window.js +70 -165
- package/dist/window.js.map +1 -1
- package/package.json +4 -4
package/dist/open.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/types.ts","../src/core/ports.ts","../src/core/registry.ts","../src/open/actions.ts","../src/open/renderAcks.ts","../src/open/selectors.ts","../src/open/gate.ts","../src/handles/slot.ts","../src/open/peek.ts","../src/open/ids.ts","../src/open/handleEntries.ts","../src/open/lazyOpener.ts","../src/open/channels.ts","../src/open/grammar.ts"],"sourcesContent":["/**\n * The shared vocabulary of @ai-matrx/summon. Framework-free: no React, no Redux imports.\n *\n * An OVERLAY is any component rendered on top of the app by dispatch — a window, dialog, sheet,\n * light floating window, toast-like card, anything. It is identified by an `OverlayId` and opened\n * as one or more INSTANCES (`instanceId`, \"default\" for single-instance overlays).\n */\n\n/**\n * The host's overlay registry: overlay id → the data its opener accepts. Hosts extend it by\n * module augmentation so every open call is type-checked:\n *\n * declare module \"@ai-matrx/summon\" {\n * interface OverlayRegistry { notesWindow: { noteId?: string } }\n * }\n *\n * `defineOverlay` emits nothing at runtime for this; the augmentation is the host's one-line\n * declaration per overlay (the converter writes it next to each definition).\n */\n// Declared in ./augment (bundled only into the core's declarations, so `declare module\n// \"@ai-matrx/summon\"` merges into it); every section reads it through the package name.\nimport type { OverlayRegistry, OverlayHostTypes } from \"@ai-matrx/summon\";\nexport type { OverlayRegistry, OverlayHostTypes };\n\n/** Every registered overlay id; plain `string` until the host augments the registry. */\nexport type OverlayId = [keyof OverlayRegistry] extends [never]\n ? string\n : Extract<keyof OverlayRegistry, string>;\n\n/** The open-data type declared for an overlay id. */\nexport type OverlayDataOf<Id extends string> = Id extends keyof OverlayRegistry\n ? OverlayRegistry[Id]\n : Record<string, unknown>;\n\n/**\n * Data as it arrives at render time. It crossed Redux, a URL or storage, so it is NOT trusted to\n * match the opener's type: render code narrows it (or the definition supplies `parse`).\n */\nexport type OverlayRawData = Readonly<Record<string, unknown>> | null;\n\nexport const DEFAULT_INSTANCE_ID = \"default\";\n\n/** `single`: one instance (\"default\"). `multi`: any number, each with its own instanceId. */\nexport type InstanceMode = \"single\" | \"multi\";\n\n/**\n * What closing does to a mounted overlay (Arman, 2026-10-16, C38 R3):\n * none — unmount (default).\n * hidden — stay mounted but hidden; reopening shows the same live component (LRU-capped).\n * restore — unmount, but values saved with `useOverlayState` come back on reopen.\n * Minimizing a window always keeps its component mounted, whatever this says.\n */\nexport type KeepAlive = \"none\" | \"hidden\" | \"restore\";\n\n/** `overlayId:instanceId` — the one key every subsystem uses for an open instance. */\nexport type InstanceKey = `${string}:${string}`;\n\nexport function instanceKey(overlayId: string, instanceId: string = DEFAULT_INSTANCE_ID): InstanceKey {\n return `${overlayId}:${instanceId}`;\n}\n\nexport function parseInstanceKey(key: string): { overlayId: string; instanceId: string } | null {\n const at = key.indexOf(\":\");\n if (at <= 0 || at === key.length - 1) return null;\n return { overlayId: key.slice(0, at), instanceId: key.slice(at + 1) };\n}\n\n// ── Window options (consumed by the window surface; inert for other surfaces) ──────────────────\n\nexport type MobilePresentation = \"fullscreen\" | \"drawer\" | \"card\" | \"hidden\";\n\n/**\n * Default-deny allowlist of the open data a window may save and restore. A window with no\n * preservation entry restores geometry only.\n */\nexport interface WindowPreservation {\n readonly dataKeys: readonly string[];\n readonly requiredDataKeys?: readonly string[];\n readonly allowedDataValues?: Readonly<Record<string, readonly (string | number | boolean | null)[]>>;\n /** Default 32 KiB. */\n readonly maxDataBytes?: number;\n}\n\n/** One declared home for an unbidden (system-raised) window: a route prefix, or one exact page. */\nexport type UnbiddenHomeRoute = string | { readonly route: string; readonly exact: true };\n\nexport interface OverlayWindowOptions {\n readonly mobile?: MobilePresentation;\n readonly mobileSidebarAs?: \"drawer\" | \"inline\";\n /** Never saved or restored (debug panels, one-shot tools, callback-bound editors). */\n readonly ephemeral?: boolean;\n readonly preservation?: WindowPreservation;\n /**\n * Values merged under saved data when a window is RESTORED (reload, another device). Unlike the\n * definition's `defaults`, never applied to a normal open.\n */\n readonly restoreDefaults?: Readonly<Record<string, unknown>>;\n /**\n * The window-manager id the WindowPanel registers under for the default instance. Default: the\n * overlay id. The render watchdog reveals and inspects this id until the panel acks its own.\n */\n readonly windowId?: string;\n readonly deprecated?: { readonly replacement?: string; readonly reason?: string };\n /**\n * Where a window nobody opened (system-raised) may raise itself. Default deny: no home → it may\n * not raise itself anywhere (`mayRaiseUnbidden` in the window section).\n */\n readonly unbiddenHome?: readonly UnbiddenHomeRoute[];\n}\n\n// ── Host types (augmentable) ────────────────────────────────────────────────────────────────\n\n/**\n * Host-specific types the package passes through untouched. A Redux host augments `dispatch`\n * with its thunk-aware dispatch so link hydrators can dispatch its thunks without casts:\n *\n * declare module \"@ai-matrx/summon\" { interface OverlayHostTypes { dispatch: AppDispatch } }\n */\nexport type OverlayHostDispatch = OverlayHostTypes extends { dispatch: infer D } ? D : (action: unknown) => unknown;\n\n// ── Links (address-bar references) ──────────────────────────────────────────────────────────\n\nexport interface LinkHydrateContext<Data> {\n /** The id segment of the link token (`notes:<id>`). */\n readonly id: string;\n /** Decoded `k-v` arguments of the token. */\n readonly args: Readonly<Record<string, string>>;\n /** Open this overlay. */\n open(options?: { readonly instanceId?: string; readonly data?: Data }): void;\n /** The host store's dispatch, for thunks a hydrator needs (loading a record first). Typed by\n * augmenting `OverlayHostTypes` with the host's dispatch type. */\n readonly dispatch: OverlayHostDispatch;\n}\n\nexport interface OverlayLinkSpec<Data> {\n /** The token type key in `?panels=key:id`. Unique across the host. */\n readonly key: string;\n /** Older keys that still resolve to this overlay. */\n readonly aliases?: readonly string[];\n /** Turn a link token into an open overlay (and its data). `\"refused\"` keeps the token and says why. */\n hydrate(context: LinkHydrateContext<Data>): void | \"refused\" | Promise<void | \"refused\">;\n}\n\n// ── Definitions (framework-free half; the React half adds `render`) ─────────────────────────\n\nexport interface OverlayDefinitionMeta<Id extends string = string, Data = Record<string, unknown>> {\n readonly id: Id;\n /** Human label: tray, menus, diagnostics. */\n readonly label: string;\n readonly instance?: InstanceMode;\n readonly keepAlive?: KeepAlive;\n /** Close when the route changes — the overlay shows a piece of the page that opened it. */\n readonly closesOnNavigation?: boolean;\n /** Present only for overlays that render a WindowPanel. */\n readonly window?: OverlayWindowOptions;\n readonly link?: OverlayLinkSpec<Data>;\n /** Defaults merged under open data (replaces the old per-overlay schema registry). */\n readonly defaults?: Partial<Data>;\n}\n\n/** The window-manager id a singleton window overlay registers under (`window.windowId ?? id`). */\nexport function defaultWindowIdFor(meta: Pick<OverlayDefinitionMeta, \"id\" | \"window\">): string {\n return meta.window?.windowId ?? meta.id;\n}\n","/**\n * Everything the overlays system needs from its host, as ports. Every port ships a working\n * default, so a bare host gets a working system with zero wiring (package standard rule 8); a\n * host overrides only what it has: identity, navigation, notifications, error sink, debug flag,\n * persistence. Framework-free.\n */\n\nexport type Unsubscribe = () => void;\n\n/** Who the person is, for isolating saved state. `key` changes → everything saved is swapped. */\nexport interface IdentityPort {\n current(): { readonly key: string; readonly ready: boolean };\n subscribe(listener: () => void): Unsubscribe;\n}\n\n/** The address bar: route changes (close-on-navigation) and the `?panels=` link channel. */\nexport interface RouterPort {\n pathname(): string;\n search(): string;\n /** Replace the query string without navigating or remounting the page. */\n replaceSearch(nextSearch: string): void;\n subscribe(listener: () => void): Unsubscribe;\n}\n\nexport interface NotifyOptions {\n readonly id?: string;\n readonly description?: string;\n /** How long the notice stays up (ms). Hosts without timed notices ignore it. */\n readonly duration?: number;\n /** One action button (e.g. the render watchdog's \"Show it\"). Hosts without actions ignore it. */\n readonly action?: { readonly label: string; readonly onClick: () => void };\n}\n\nexport interface NotifyPort {\n info(message: string, options?: NotifyOptions): void;\n warn(message: string, options?: NotifyOptions): void;\n error(message: string, options?: NotifyOptions): void;\n /** Withdraw a notice by id (optional). */\n dismiss?(id: string): void;\n}\n\nexport interface ErrorSinkPort {\n capture(error: unknown, context: Readonly<Record<string, unknown>>): void;\n}\n\nexport interface DebugPort {\n enabled(): boolean;\n subscribe?(listener: () => void): Unsubscribe;\n}\n\n/** A stored value with its optimistic-concurrency version (0 when the store has none). */\nexport interface StoredValue<T = unknown> {\n readonly value: T;\n readonly version: number;\n}\n\n/**\n * Where saved overlay state lives when persistence is on. Keys are already scoped to the\n * identity by the caller (`<identityKey>/<key>`) for stores that are not per-person themselves.\n * Implementations: the browser-local store (`./persistence`), `@ai-matrx/data` over\n * `users.user_surface_state` (`./persistence/data`), or any host database.\n */\nexport interface OverlayPersistencePort {\n /**\n * True when the store is per-person itself (rows scoped to the signed-in person, e.g. the\n * `@ai-matrx/data` adapter): the persistence section then passes plain keys (`workspace`,\n * `state:<instanceKey>`) instead of `<identityKey>/<key>`, and defaults to `scope: \"person\"`.\n */\n readonly perPerson?: boolean;\n load<T = unknown>(key: string): Promise<StoredValue<T> | null>;\n save<T = unknown>(key: string, value: T, options?: { readonly expectedVersion?: number }): Promise<{ readonly version: number }>;\n remove(key: string): Promise<void>;\n list?(prefix: string): Promise<readonly string[]>;\n /**\n * Every saved value at once (key → value), for stores where one read is cheaper than several.\n * When present, restoring an identity costs exactly this one call: the workspace and every\n * saved component state come out of it, and `load`/`list` are not called on boot.\n */\n loadAll?(): Promise<ReadonlyMap<string, StoredValue>>;\n}\n\nexport interface SummonPorts {\n readonly identity: IdentityPort;\n readonly router: RouterPort;\n readonly notify: NotifyPort;\n readonly errors: ErrorSinkPort;\n readonly debug: DebugPort;\n /** `null` = persistence off (R6). */\n readonly persistence: OverlayPersistencePort | null;\n}\n\nconst noop = (): void => {};\n\nexport const anonymousIdentity: IdentityPort = {\n current: () => ({ key: \"anonymous\", ready: true }),\n subscribe: () => noop,\n};\n\n/** `window.location` + `history.replaceState`; inert on the server. */\nexport const locationRouter: RouterPort = {\n pathname: () => (typeof window === \"undefined\" ? \"/\" : window.location.pathname),\n search: () => (typeof window === \"undefined\" ? \"\" : window.location.search),\n replaceSearch: (nextSearch) => {\n if (typeof window === \"undefined\") return;\n const query = nextSearch && !nextSearch.startsWith(\"?\") ? `?${nextSearch}` : nextSearch;\n const url = `${window.location.pathname}${query}${window.location.hash}`;\n window.history.replaceState(window.history.state, \"\", url);\n },\n subscribe: (listener) => {\n if (typeof window === \"undefined\") return noop;\n window.addEventListener(\"popstate\", listener);\n return () => window.removeEventListener(\"popstate\", listener);\n },\n};\n\n/* eslint-disable no-console */\nexport const consoleNotify: NotifyPort = {\n info: (message) => console.info(`[summon] ${message}`),\n warn: (message) => console.warn(`[summon] ${message}`),\n error: (message) => console.error(`[summon] ${message}`),\n};\n\nexport const consoleErrorSink: ErrorSinkPort = {\n capture: (error, context) => console.error(\"[summon]\", error, context),\n};\n/* eslint-enable no-console */\n\nexport const debugOff: DebugPort = { enabled: () => false };\n\nexport const DEFAULT_PORTS: SummonPorts = {\n identity: anonymousIdentity,\n router: locationRouter,\n notify: consoleNotify,\n errors: consoleErrorSink,\n debug: debugOff,\n persistence: null,\n};\n\nexport function resolvePorts(overrides: Partial<SummonPorts> | undefined): SummonPorts {\n return { ...DEFAULT_PORTS, ...overrides };\n}\n","/**\n * The process-wide registry of overlay definition metadata (the framework-free half of each\n * definition). The host registers its definitions once (`<SummonHost definitions>` does it);\n * reducers stay pure — middleware and hooks read this registry and put what reducers need in the\n * action payload (e.g. the ids bound to the page).\n *\n * State lives in a global slot so a duplicated module graph (ESM + CJS, unsplit bundles) sees one\n * registry (kit `globalSlot`, architecture D9).\n */\nimport { globalSlot } from \"@ai-matrx/kit/global-slot\";\nimport type { OverlayDefinitionMeta } from \"./types\";\n\n/**\n * A definition's meta with its data type erased, so definitions of every data shape share one\n * registry without casts. (`never` erasure made `defaults` unassignable.)\n */\nexport interface AnyOverlayMeta extends Omit<OverlayDefinitionMeta<string, unknown>, \"defaults\"> {\n readonly defaults?: object | undefined;\n}\n\ntype AnyMeta = AnyOverlayMeta;\n\ninterface RegistryState {\n readonly byId: Map<string, AnyMeta>;\n readonly byLinkKey: Map<string, AnyMeta>;\n readonly listeners: Set<() => void>;\n}\n\nconst state = (): RegistryState =>\n globalSlot<RegistryState>(\"ai-matrx.summon.registry\", () => ({\n byId: new Map(),\n byLinkKey: new Map(),\n listeners: new Set(),\n }));\n\n/**\n * Register (or re-register) definitions. Re-registering an id replaces it (hot reload). A link\n * key claimed by two different ids is a host bug and throws, naming both.\n */\nexport function registerOverlayMeta(definitions: readonly AnyOverlayMeta[]): void {\n const s = state();\n for (const def of definitions) {\n s.byId.set(def.id, def);\n const keys = def.link ? [def.link.key, ...(def.link.aliases ?? [])] : [];\n for (const key of keys) {\n const holder = s.byLinkKey.get(key);\n if (holder && holder.id !== def.id) {\n throw new Error(`[summon] link key \"${key}\" is claimed by both \"${holder.id}\" and \"${def.id}\"`);\n }\n s.byLinkKey.set(key, def);\n }\n }\n for (const listener of s.listeners) listener();\n}\n\nexport function getOverlayMeta(overlayId: string): AnyMeta | undefined {\n return state().byId.get(overlayId);\n}\n\nexport function getOverlayMetaByLinkKey(linkKey: string): AnyMeta | undefined {\n return state().byLinkKey.get(linkKey);\n}\n\nexport function allOverlayMeta(): readonly AnyMeta[] {\n return [...state().byId.values()];\n}\n\nexport function isRegisteredOverlay(overlayId: string): boolean {\n return state().byId.has(overlayId);\n}\n\nexport function subscribeToOverlayRegistry(listener: () => void): () => void {\n const s = state();\n s.listeners.add(listener);\n return () => s.listeners.delete(listener);\n}\n\n/** Test-only. */\nexport function resetOverlayRegistry(): void {\n const s = state();\n s.byId.clear();\n s.byLinkKey.clear();\n}\n","// The public action creators, light: plain objects with the slices' own type strings, so a file\n// that only opens or closes something never loads a slice. The slices (core) handle these exact\n// types; `actions.parity.test.ts` proves every creator here equals its slice twin.\n//\n// `openOverlay`/`toggleOverlay` keep the two guarantees the slice creators had: functions are\n// stripped from open data (they can never travel through Redux — the D33 dead-button class) and\n// the definition's registered `defaults` ride the payload, so the reducer stays pure.\nimport { getOverlayMeta, allOverlayMeta } from \"../core/registry\";\nimport { DEFAULT_INSTANCE_ID, type InstanceKey, type OverlayDataOf, type OverlayId } from \"../core/types\";\n\nexport interface OpenOverlayPayload<Id extends OverlayId = OverlayId> {\n overlayId: Id;\n instanceId?: string;\n data?: OverlayDataOf<Id> | null;\n}\n\nexport interface CloseOverlayPayload<Id extends OverlayId = OverlayId> {\n overlayId: Id;\n instanceId?: string;\n}\n\nexport type ToggleOverlayPayload<Id extends OverlayId = OverlayId> = OpenOverlayPayload<Id>;\n\nexport interface CloseAllInstancesPayload<Id extends OverlayId = OverlayId> {\n overlayId: Id;\n}\n\nexport interface CloseOverlaysBoundToPagePayload {\n /** Overlay ids whose definitions say `closesOnNavigation`. */\n overlayIds: readonly string[];\n}\n\nexport interface PruneStaleInstancesPayload {\n olderThanMs: number;\n}\n\n/** Raw reducer payload: untyped ids + the registry defaults the creator resolved. */\nexport interface RawOpenPayload {\n overlayId: string;\n instanceId?: string;\n data?: unknown;\n defaults?: Readonly<Record<string, unknown>>;\n}\n\nexport interface SummonAction<P> {\n type: string;\n payload: P;\n /** Structurally a Redux `UnknownAction`. */\n [extra: string]: unknown;\n}\n\ntype Creator<Args extends unknown[], P> = ((...args: Args) => SummonAction<P>) & {\n readonly type: string;\n match(action: unknown): action is SummonAction<P>;\n};\n\nfunction creator<Args extends unknown[], P>(type: string, build: (...args: Args) => P): Creator<Args, P> {\n const create = (...args: Args): SummonAction<P> => ({ type, payload: build(...args) });\n return Object.assign(create, {\n type,\n toString: () => type,\n match: (action: unknown): action is SummonAction<P> =>\n typeof action === \"object\" && action !== null && (action as { type?: unknown }).type === type,\n });\n}\n\n/** A creator whose call signature stays generic (the inferred `creator` form erases `Id`). */\ntype Generic<F> = F & { readonly type: string; match(action: unknown): action is SummonAction<unknown> };\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction stripFunctions(overlayId: string, data: unknown): unknown {\n if (!isPlainRecord(data)) return data;\n const offenders = Object.keys(data).filter((key) => typeof data[key] === \"function\");\n if (offenders.length === 0) return data;\n // eslint-disable-next-line no-console\n console.error(\n `[summon] BUG: function value(s) in openOverlay data for \"${overlayId}\" (keys: ${offenders.join(\", \")}). ` +\n `Functions cannot travel through Redux — the handler would NEVER fire. Register a handle ` +\n `(@ai-matrx/summon/handles) and pass its id string instead. The offending key(s) were stripped from state.`,\n );\n const cleaned = { ...data };\n for (const key of offenders) delete cleaned[key];\n return cleaned;\n}\n\nfunction rawOpen(payload: { overlayId: string; instanceId?: string; data?: unknown }): RawOpenPayload {\n const raw: RawOpenPayload = { overlayId: payload.overlayId };\n if (payload.instanceId !== undefined) raw.instanceId = payload.instanceId;\n if (payload.data !== undefined) raw.data = stripFunctions(payload.overlayId, payload.data);\n const defaults: unknown = getOverlayMeta(payload.overlayId)?.defaults;\n if (isPlainRecord(defaults)) raw.defaults = stripFunctions(payload.overlayId, defaults) as Record<string, unknown>;\n return raw;\n}\n\nconst O = \"overlays/\";\n\nexport const openOverlay = creator(O + \"openOverlay\", (payload: OpenOverlayPayload) => rawOpen(payload)) as Generic<\n <Id extends OverlayId>(payload: OpenOverlayPayload<Id>) => SummonAction<RawOpenPayload>\n>;\n\nexport const closeOverlay = creator(O + \"closeOverlay\", (payload: CloseOverlayPayload): { overlayId: string; instanceId?: string } =>\n payload.instanceId === undefined ? { overlayId: payload.overlayId } : { overlayId: payload.overlayId, instanceId: payload.instanceId },\n) as Generic<<Id extends OverlayId>(payload: CloseOverlayPayload<Id>) => SummonAction<{ overlayId: string; instanceId?: string }>>;\n\nexport const toggleOverlay = creator(O + \"toggleOverlay\", (payload: ToggleOverlayPayload) => rawOpen(payload)) as Generic<\n <Id extends OverlayId>(payload: ToggleOverlayPayload<Id>) => SummonAction<RawOpenPayload>\n>;\n\nexport const closeAllInstancesOfOverlay = creator(O + \"closeAllInstancesOfOverlay\", (payload: CloseAllInstancesPayload) => ({\n overlayId: payload.overlayId as string,\n})) as Generic<<Id extends OverlayId>(payload: CloseAllInstancesPayload<Id>) => SummonAction<{ overlayId: string }>>;\n\n/** Ids of every registered overlay whose definition says `closesOnNavigation`. */\nexport function overlayIdsBoundToPage(): string[] {\n return allOverlayMeta()\n .filter((meta) => meta.closesOnNavigation === true)\n .map((meta) => meta.id);\n}\n\n/** Close page-bound overlays. Omit the ids to use the registry's `closesOnNavigation` list. */\nexport const closeOverlaysBoundToPage = creator(\n O + \"closeOverlaysBoundToPage\",\n (payload?: Partial<CloseOverlaysBoundToPagePayload>): CloseOverlaysBoundToPagePayload => ({\n overlayIds: [...(payload?.overlayIds ?? overlayIdsBoundToPage())],\n }),\n);\n\nexport const closeAllOverlays = creator(O + \"closeAllOverlays\", () => undefined);\nexport const pruneStaleInstances = creator(O + \"pruneStaleInstances\", (payload: PruneStaleInstancesPayload) => payload);\n\n// ── Window manager: the ones callers outside a window dispatch (menus, shortcuts, settings) ──\n\nconst W = \"windowManager/\";\nconst pass = <P>() => (payload: P) => payload;\n\nexport const focusWindow = creator(W + \"focusWindow\", pass<string>());\nexport const restoreWindow = creator(W + \"restoreWindow\", pass<string>());\nexport const toggleWindowsHidden = creator(W + \"toggleWindowsHidden\", () => undefined);\nexport const restoreAll = creator(W + \"restoreAll\", () => undefined);\nexport const minimizeAll = creator(W + \"minimizeAll\", pass<{ viewportWidth: number; viewportHeight: number }>());\n\nexport interface ArrangeActiveWindowsPayload {\n layout: import(\"../core/geometry/windowArrangements\").GlobalLayoutType;\n viewportWidth: number;\n viewportHeight: number;\n dirX?: \"ltr\" | \"rtl\";\n dirY?: \"ttb\" | \"btt\";\n primary?: \"horizontal\" | \"vertical\";\n}\nexport const arrangeActiveWindows = creator(W + \"arrangeActiveWindows\", pass<ArrangeActiveWindowsPayload>());\n\nexport const revealWindow = creator(W + \"revealWindow\", pass<{ id: string; viewportWidth: number; viewportHeight: number }>());\nexport const updateWindowRect = creator(\n W + \"updateWindowRect\",\n pass<{ id: string; rect: Partial<import(\"../core/geometry/types\").WindowRect> }>(),\n);\n\n// ── Saved component state ──\n\nexport const setOverlayStateValue = creator(\"overlayState/setOverlayStateValue\", pass<{ key: InstanceKey; name: string; value: unknown }>());\n\n// ── Links ────────────────────────────────────────────────────────────────────────────────────\n\nexport interface UrlSyncEntryPayload {\n typeKey: string;\n instanceId: string;\n args?: Readonly<Record<string, string>>;\n}\nexport const registerSyncEntry = creator(\"urlSync/registerSyncEntry\", pass<UrlSyncEntryPayload>());\nexport const unregisterSyncEntry = creator(\"urlSync/unregisterSyncEntry\", pass<{ typeKey: string; instanceId: string }>());\n\n/** Every slice key the summon reducers own; an action under one of them needs the runtime. */\nexport const SUMMON_SLICE_KEYS = [\"overlays\", \"windowManager\", \"urlSync\", \"overlayState\"] as const;\n\nexport function isSummonAction(action: unknown): action is { type: string } {\n if (typeof action !== \"object\" || action === null) return false;\n const type = (action as { type?: unknown }).type;\n if (typeof type !== \"string\") return false;\n const slash = type.indexOf(\"/\");\n return slash > 0 && (SUMMON_SLICE_KEYS as readonly string[]).includes(type.slice(0, slash));\n}\n\nexport { DEFAULT_INSTANCE_ID };\n","// Render acknowledgements a mobile surface reports (it renders instead of a WindowPanel). Light:\n// the same slot the render watchdog (core) reads, so a boot-graph hook can report without the core.\nimport { globalSlot } from \"@ai-matrx/kit/global-slot\";\n\ninterface AckSlot {\n readonly renderAcks: Map<string, { kind: \"window\"; windowId: string } | { kind: \"surface\" }>;\n readonly ackWaiters: Map<string, () => void>;\n readonly watches: Map<string, unknown>;\n}\n\n// Same key and shape as core/middleware/renderWatchdog.ts (RENDER_WATCHDOG_SLOT).\nconst slot = (): AckSlot =>\n globalSlot<AckSlot>(\"ai-matrx.summon.renderWatchdog\", () => ({ renderAcks: new Map(), ackWaiters: new Map(), watches: new Map() }));\n\nexport function ackOverlaySurfaceRender(overlayId: string): void {\n const s = slot();\n s.renderAcks.set(overlayId, { kind: \"surface\" });\n const notify = s.ackWaiters.get(overlayId);\n if (notify) {\n s.ackWaiters.delete(overlayId);\n notify();\n }\n}\n\nexport function clearOverlaySurfaceRender(overlayId: string): void {\n const s = slot();\n if (s.renderAcks.get(overlayId)?.kind === \"surface\") s.renderAcks.delete(overlayId);\n}\n","// The public overlay selectors, light and safe before the runtime: a host that loads the summon\n// slices on first use (the gate) has no `overlays` key until then, and every overlay reads closed.\nimport { DEFAULT_INSTANCE_ID } from \"../core/types\";\nimport { globalSlot } from \"@ai-matrx/kit/global-slot\";\n\nexport interface OverlayInstance {\n isOpen: boolean;\n data: unknown;\n /** Unix ms of the last open (pruneStaleInstances reads it). */\n lastUsedAt?: number;\n}\n\nexport interface OverlayState {\n overlays: Record<string, Record<string, OverlayInstance>>;\n}\n\n/** The slice of any store these selectors need (absent until the summon runtime is installed). */\n// `| object`: an all-optional type is \"weak\", and a host state sharing no key with it (before the\n// slices are injected, or typed without them) would be refused by TypeScript.\nexport type StateWithOverlays = { overlays?: OverlayState } | object;\nconst overlaysOf = (state: StateWithOverlays): OverlayState | undefined => (state as { overlays?: OverlayState }).overlays;\n\nexport interface OpenInstanceView {\n instanceId: string;\n data: unknown;\n}\n\nconst CLOSED: OverlayInstance = Object.freeze({ isOpen: false, data: null });\nconst EMPTY: readonly OpenInstanceView[] = Object.freeze([]);\n\nexport const selectOverlay = (state: StateWithOverlays, overlayId: string, instanceId: string = DEFAULT_INSTANCE_ID): OverlayInstance =>\n overlaysOf(state)?.overlays[overlayId]?.[instanceId] ?? CLOSED;\n\nexport const selectIsOverlayOpen = (state: StateWithOverlays, overlayId: string, instanceId: string = DEFAULT_INSTANCE_ID): boolean =>\n selectOverlay(state, overlayId, instanceId).isOpen;\n\nexport const selectOverlayData = (state: StateWithOverlays, overlayId: string, instanceId: string = DEFAULT_INSTANCE_ID): unknown =>\n selectOverlay(state, overlayId, instanceId).data;\n\ninterface CachedOpen {\n bucket: Record<string, OverlayInstance> | undefined;\n result: readonly OpenInstanceView[];\n}\nconst openCache = (): Map<string, CachedOpen> => globalSlot(\"ai-matrx.summon.openInstances\", () => new Map<string, CachedOpen>());\n\n/** All open instances of an overlay id; the array reference is stable while the open set is unchanged. */\nexport const selectOpenInstances = (state: StateWithOverlays, overlayId: string): readonly OpenInstanceView[] => {\n const bucket = overlaysOf(state)?.overlays[overlayId];\n const cache = openCache();\n const hit = cache.get(overlayId);\n if (hit && hit.bucket === bucket) return hit.result;\n let result: readonly OpenInstanceView[] = EMPTY;\n if (bucket) {\n const open: OpenInstanceView[] = [];\n for (const [instanceId, inst] of Object.entries(bucket)) if (inst.isOpen) open.push({ instanceId, data: inst.data });\n if (open.length > 0) result = open;\n }\n cache.set(overlayId, { bucket, result });\n return result;\n};\n\n/** Every open instance key (`overlayId:instanceId`). */\nexport function listOpenInstanceKeys(state: StateWithOverlays): string[] {\n const keys: string[] = [];\n for (const [overlayId, bucket] of Object.entries(overlaysOf(state)?.overlays ?? {})) {\n for (const [instanceId, inst] of Object.entries(bucket)) if (inst.isOpen) keys.push(`${overlayId}:${instanceId}`);\n }\n return keys;\n}\n\n/** True once anything has ever been opened in this store (a key exists in the slice). */\nexport function selectAnyOverlayTouched(state: StateWithOverlays): boolean {\n for (const _ in overlaysOf(state)?.overlays ?? {}) return true;\n return false;\n}\n\n/** The global hide-all flag (false before the runtime is installed). */\nexport const selectWindowsHidden = (state: object): boolean =>\n (state as { windowManager?: { windowsHidden: boolean } }).windowManager?.windowsHidden ?? false;\n\ntype WindowLike = import(\"../core/windowManagerSlice\").WindowEntry;\nconst EMPTY_WINDOWS: readonly never[] = Object.freeze([]);\nlet lastWindowsMap: unknown = null;\nlet lastWindows: readonly WindowLike[] = EMPTY_WINDOWS;\n\n/** Every registered window, topmost first (empty before the runtime is installed). Memoized on the map. */\nexport function selectAllWindows<W extends WindowLike = WindowLike>(state: object): readonly W[] {\n const map = (state as { windowManager?: { windows: Record<string, W> } }).windowManager?.windows;\n if (!map) return EMPTY_WINDOWS;\n if (map !== lastWindowsMap) {\n lastWindowsMap = map;\n lastWindows = Object.values(map).sort((a, b) => b.zIndex - a.zIndex);\n }\n return lastWindows as readonly W[];\n}\n\n/** True when windows exist and every one is minimized (false before the runtime is installed). */\nexport function selectAllMinimized(state: object): boolean {\n const map = (state as { windowManager?: { windows: Record<string, { state: string }> } }).windowManager?.windows;\n if (!map) return false;\n const wins = Object.values(map);\n return wins.length > 0 && wins.every((w) => w.state === \"minimized\");\n}\n","// The summon gate: a host store carries NONE of the summon slices or middleware until something\n// needs them. The gate is one middleware in the host chain. Before the core is loaded, every\n// summon action (open, close, a window action…) is queued and the first one starts ONE import()\n// of the core; when the core module evaluates it installs itself into every gate — the slices are\n// injected into the host's root reducer, the real middleware (close lifecycle, render watchdog)\n// joins the chain, and the queue replays in order. A host may also start the import early\n// (`prefetchSummonRuntime` on idle or pointer intent) so the first click opens at once.\n//\n// A module that needs the slices synchronously (the window section, links, persistence) imports\n// the core statically; the core installs at evaluation, so its state exists before it renders.\nimport type { Dispatch, Middleware, MiddlewareAPI, Reducer, UnknownAction } from \"@reduxjs/toolkit\";\nimport { globalSlot } from \"@ai-matrx/kit/global-slot\";\nimport type { SummonPorts } from \"../core/ports\";\nimport { isSummonAction } from \"./actions\";\n\n/** What the core hands the gate when it loads. */\nexport interface SummonCore {\n readonly reducers: Readonly<Record<string, Reducer>>;\n createMiddleware(ports?: Partial<SummonPorts>): Middleware[];\n}\n\n/** Dispatched once after the slices are injected into a live store, so they hold their initial state. */\nexport const SUMMON_INSTALLED_ACTION = \"@@summon/installed\";\n\ninterface GateInternals {\n install(core: SummonCore): void;\n}\n\ninterface GateSlot {\n core: SummonCore | null;\n loading: Promise<void> | null;\n readonly gates: Set<GateInternals>;\n readonly listeners: Set<() => void>;\n}\n\nconst slot = (): GateSlot =>\n globalSlot<GateSlot>(\"ai-matrx.summon.gate\", () => ({ core: null, loading: null, gates: new Set(), listeners: new Set() }));\n\n/** Called by the core module when it evaluates (idempotent). */\nexport function installSummonCore(core: SummonCore): void {\n const s = slot();\n if (s.core) return;\n s.core = core;\n const gates = [...s.gates];\n s.gates.clear();\n for (const gate of gates) gate.install(core);\n for (const listener of [...s.listeners]) listener();\n}\n\nexport function isSummonInstalled(): boolean {\n return slot().core !== null;\n}\n\nexport function subscribeSummonInstalled(listener: () => void): () => void {\n const s = slot();\n s.listeners.add(listener);\n return () => s.listeners.delete(listener);\n}\n\n/** Load the summon core (one import(), shared by every caller). Resolves once it is installed. */\nexport function ensureSummonRuntime(): Promise<void> {\n const s = slot();\n if (s.core) return Promise.resolve();\n s.loading ??= import(\"@ai-matrx/summon\").then(\n (core) => installSummonCore(core.summonCore),\n (error: unknown) => {\n s.loading = null; // a failed chunk may be retried by the next request\n throw error;\n },\n );\n return s.loading;\n}\n\n/** Start loading the core without waiting (idle, pointer intent). Errors surface on the next real request. */\nexport function prefetchSummonRuntime(): void {\n ensureSummonRuntime().catch(() => undefined);\n}\n\nexport interface SummonGate {\n /** Put this in the host store's middleware chain. */\n readonly middleware: Middleware;\n /**\n * Give the gate the host root reducer's inject function — before `configureStore`, so a core\n * that is already loaded (a page that imported the window section) is injected before the\n * store's first state exists.\n */\n attachReducer(inject: (reducers: Readonly<Record<string, Reducer>>) => void): void;\n}\n\nexport interface CreateSummonGateOptions {\n /** Ports for the summon middleware (render watchdog: notify, errors, debug). */\n readonly ports?: Partial<SummonPorts>;\n}\n\nexport function createSummonGate(options: CreateSummonGateOptions = {}): SummonGate {\n let inject: ((reducers: Readonly<Record<string, Reducer>>) => void) | null = null;\n let injected = false;\n let api: MiddlewareAPI<Dispatch<UnknownAction>, unknown> | null = null;\n let next: ((action: unknown) => unknown) | null = null;\n let chain: ((action: unknown) => unknown) | null = null;\n const queue: unknown[] = [];\n\n const settle = (core: SummonCore, live: boolean) => {\n if (inject && !injected) {\n inject(core.reducers);\n injected = true;\n }\n if (!api || !next || chain) return;\n const store = api;\n let composed: (action: unknown) => unknown = next;\n for (const middleware of [...core.createMiddleware(options.ports)].reverse()) {\n composed = middleware(store)(composed) as (action: unknown) => unknown;\n }\n chain = composed;\n const flush = () => {\n if (live) store.dispatch({ type: SUMMON_INSTALLED_ACTION });\n for (const action of queue.splice(0)) store.dispatch(action as UnknownAction);\n };\n // Redux forbids dispatching while the middleware chain is being built.\n if (live) flush();\n else if (queue.length > 0) queueMicrotask(flush);\n };\n\n const internals: GateInternals = { install: (core) => settle(core, true) };\n const core = () => slot().core;\n\n const middleware: Middleware = (storeApi) => {\n api = storeApi as MiddlewareAPI<Dispatch<UnknownAction>, unknown>;\n return (nextDispatch) => {\n next = nextDispatch as (action: unknown) => unknown;\n const loaded = core();\n if (loaded) settle(loaded, false);\n else slot().gates.add(internals);\n return (action) => {\n if (chain) return chain(action);\n if (!isSummonAction(action)) return nextDispatch(action);\n queue.push(action);\n void ensureSummonRuntime().catch((error: unknown) => {\n // eslint-disable-next-line no-console\n console.error(\"[summon] the overlay runtime failed to load; queued requests are kept for the next try\", error);\n });\n return action;\n };\n };\n };\n\n return {\n middleware,\n attachReducer(fn) {\n inject = fn;\n const loaded = core();\n if (loaded) {\n inject(loaded.reducers);\n injected = true;\n }\n },\n };\n}\n","/** The global slot that holds the handles registry (one registry per realm, whatever the bundling). */\nexport const HANDLES_SLOT = \"ai-matrx.summon.handles\";\n","// Read a registered handle WITHOUT loading the handles registry. A handle exists only after its\n// registrant loaded `@ai-matrx/summon/handles` and called `register*`; until then the registry's\n// global slot is empty and every id resolves to nothing — exactly what `callbackManager.get` would\n// say. So a boot-time caller that only resolves ids (a stream processor, a store middleware) reads\n// through here and never puts the registry in first load.\nimport { HANDLES_SLOT } from \"../handles/slot\";\n\ninterface PeekableSlot {\n readonly callbacks: Map<string, { readonly callback: unknown }>;\n}\n\n/** `callbackManager.get(id)` without loading the registry: `undefined` until something registers. */\nexport function peekHandle<T = unknown>(id: string): T | undefined {\n const slot = (globalThis as unknown as Record<symbol, PeekableSlot | undefined>)[Symbol.for(HANDLES_SLOT)];\n return slot?.callbacks.get(id)?.callback as T | undefined;\n}\n","/** A fresh handle id: `crypto.randomUUID` when present, else a v4 UUID from `getRandomValues`. */\nexport function newHandleId(): string {\n const c: Crypto | undefined = typeof globalThis.crypto === \"undefined\" ? undefined : globalThis.crypto;\n if (c && typeof c.randomUUID === \"function\") return c.randomUUID();\n const bytes = new Uint8Array(16);\n if (c && typeof c.getRandomValues === \"function\") {\n c.getRandomValues(bytes);\n } else {\n for (let i = 0; i < 16; i += 1) bytes[i] = Math.floor(Math.random() * 256);\n }\n bytes[6] = ((bytes[6] ?? 0) & 0x0f) | 0x40;\n bytes[8] = ((bytes[8] ?? 0) & 0x3f) | 0x80;\n const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, \"0\")).join(\"\");\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n","// The handles registry's STATE and its insert/remove path, without the registry's verbs (trigger,\n// subscribe, requests, channels). A boot-time opener that only needs an id NOW — register a\n// callback, a payload group, an object handle; drop it on close — writes through here and never\n// puts `@ai-matrx/summon/handles` in first load; whoever later triggers or reads loads the full\n// registry, which works on the same global slot through these same functions (one removal path).\nimport { globalSlot } from \"@ai-matrx/kit/global-slot\";\nimport { HANDLES_SLOT } from \"../handles/slot\";\nimport { newHandleId } from \"./ids\";\n\n/** A registry slot: a callback (invoked by triggers) or an object handle (only ever read). */\nexport type HandleEntrySlot = ((...args: never[]) => unknown) | object;\n\n/** @internal A registry entry (the handles section adds `listeners`). */\nexport interface HandleEntry {\n callback: HandleEntrySlot;\n context?: Record<string, unknown>;\n groupId?: string;\n owner?: string;\n listeners?: Array<(...args: never[]) => unknown>;\n /** Runs once when the entry leaves the registry for any reason (requests reject here). */\n onRemove?: () => void;\n}\n\n/** @internal The registry state in its global slot (one per realm, whatever the bundling). */\nexport interface HandlesState {\n readonly callbacks: Map<string, HandleEntry>;\n readonly groups: Map<string, Set<string>>;\n readonly owners: Map<string, Set<string>>;\n readonly registryListeners: Set<() => void>;\n}\n\nexport interface HandleEntryOptions {\n /** A fixed id (default: a fresh `newHandleId()`); an existing entry with it is replaced. */\n id?: string;\n context?: Record<string, unknown>;\n /** Join (or start) this group; `removeHandleGroup` drops every member. */\n groupId?: string;\n /** The InstanceKey (`overlayId:instanceId`) that owns this entry; disposed when it closes. */\n owner?: string;\n onRemove?: () => void;\n}\n\n/** @internal */\nexport const handlesState = (): HandlesState =>\n globalSlot<HandlesState>(HANDLES_SLOT, () => ({\n callbacks: new Map(),\n groups: new Map(),\n owners: new Map(),\n registryListeners: new Set(),\n }));\n\n/** @internal */\nexport function notifyHandlesRegistry(): void {\n for (const listener of [...handlesState().registryListeners]) listener();\n}\n\n/**\n * The one removal path. Reads the entry BEFORE deleting it so group and owner membership shrink,\n * then runs the entry's removal hook.\n */\nexport function deleteHandleEntry(id: string, notify = true): void {\n const s = handlesState();\n const entry = s.callbacks.get(id);\n if (!entry) return;\n s.callbacks.delete(id);\n if (entry.groupId !== undefined) {\n const group = s.groups.get(entry.groupId);\n group?.delete(id);\n if (group?.size === 0) s.groups.delete(entry.groupId);\n }\n if (entry.owner !== undefined) {\n const owned = s.owners.get(entry.owner);\n owned?.delete(id);\n if (owned?.size === 0) s.owners.delete(entry.owner);\n }\n if (notify) notifyHandlesRegistry();\n entry.onRemove?.();\n}\n\n/** Register a callback or object handle NOW (no registry load); returns its id. */\nexport function registerHandleEntry(slot: HandleEntrySlot, options: HandleEntryOptions = {}): string {\n const s = handlesState();\n const id = options.id ?? newHandleId();\n if (s.callbacks.has(id)) deleteHandleEntry(id, false);\n const entry: HandleEntry = { callback: slot };\n if (options.context !== undefined) entry.context = options.context;\n if (options.groupId !== undefined) entry.groupId = options.groupId;\n if (options.owner !== undefined) entry.owner = options.owner;\n if (options.onRemove !== undefined) entry.onRemove = options.onRemove;\n s.callbacks.set(id, entry);\n if (options.groupId !== undefined) {\n const group = s.groups.get(options.groupId) ?? new Set<string>();\n group.add(id);\n s.groups.set(options.groupId, group);\n }\n if (options.owner !== undefined) {\n const owned = s.owners.get(options.owner) ?? new Set<string>();\n owned.add(id);\n s.owners.set(options.owner, owned);\n }\n notifyHandlesRegistry();\n return id;\n}\n\n/** `callbackManager.unregister(id)` without loading the registry. */\nexport function unregisterHandleEntry(id: string): void {\n deleteHandleEntry(id, true);\n}\n\n/** `callbackManager.removeGroup(groupId)` without loading the registry. */\nexport function removeHandleGroup(groupId: string): void {\n const s = handlesState();\n const group = s.groups.get(groupId);\n if (!group) return;\n s.groups.delete(groupId);\n for (const id of [...group]) deleteHandleEntry(id, false);\n notifyHandlesRegistry();\n}\n","// A window opener whose code loads on its first call. Openers return a handle synchronously\n// (`{ instanceId, close }`, sometimes `update`), so a host cannot simply `import()` them: the\n// caller already holds the handle before the chunk arrives. `lazyOpener` returns a function with\n// the real opener's exact signature that knows the handle's instance id up front (minted, or\n// derived the way the real opener derives it), hands back a stand-in handle at once, and starts\n// `load()` — which a host shares across a whole set of openers (one import(), never one per id).\n// When the real opener arrives it opens with the same arguments; calls made on the stand-in in\n// the meantime (`update`, `close`) replay on the real handle in order. Once loaded, every call is\n// the real opener, synchronously, returning the real handle.\n//\n// Framework-free and tiny on purpose: it rides the first-load `./open` entry.\n\n/** How the stand-in handle learns its `instanceId` before the opener loads. */\nexport type LazyOpenerInstanceId<A extends readonly unknown[]> =\n /** `args[0].instanceId` when given, else a fresh `<overlayId>-<time>-<rand>`; written back into `args[0]`. */\n | \"mint\"\n /** Derived from the arguments exactly as the real opener derives it (a per-subject window). */\n | ((...args: A) => string);\n\nexport interface LazyOpenerOptions<A extends readonly unknown[]> {\n /** Absent: the opener's handle carries no `instanceId` (a single-instance window). */\n readonly instanceId?: LazyOpenerInstanceId<A>;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- any opener signature\ntype AnyOpener = (...args: any[]) => any;\n\ninterface RealHandle {\n readonly instanceId?: string;\n readonly callbackGroupId?: string | null;\n close?: () => void;\n update?: (patch: unknown) => void;\n}\n\n/** A fresh instance id in the shape hand-written openers mint: `<overlayId>-<time>-<rand>`. */\nexport function mintInstanceId(overlayId: string): string {\n return `${overlayId}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n}\n\nfunction withInstanceId(args: unknown[], instanceId: string): unknown[] {\n const first = args[0];\n const options = first && typeof first === \"object\" ? (first as Record<string, unknown>) : {};\n return [{ ...options, instanceId }, ...args.slice(1)];\n}\n\n/**\n * Wrap an opener so its module loads on the first call. `load` resolves to the real opener (a\n * plain function, never a hook); share one loader across a set so the set costs one import().\n */\nexport function lazyOpener<F extends AnyOpener>(\n overlayId: string,\n load: () => Promise<F>,\n options: LazyOpenerOptions<Parameters<F>> = {},\n): F {\n let real: F | null = null;\n let loading: Promise<F> | null = null;\n const ensure = (): Promise<F> => {\n loading ??= load().then(\n (opener) => {\n real = opener;\n return opener;\n },\n (error: unknown) => {\n loading = null; // a failed chunk may be retried by the next call\n throw error;\n },\n );\n return loading;\n };\n\n const lazy = (...callArgs: unknown[]): unknown => {\n let args = callArgs;\n let instanceId: string | undefined;\n const rule = options.instanceId;\n if (rule === \"mint\") {\n const given = (args[0] as { instanceId?: unknown } | undefined)?.instanceId;\n instanceId = typeof given === \"string\" && given ? given : mintInstanceId(overlayId);\n args = withInstanceId(args, instanceId);\n } else if (typeof rule === \"function\") {\n instanceId = rule(...(args as Parameters<F>));\n }\n if (real) return real(...args);\n\n let target: RealHandle | null = null;\n let closed = false;\n const pending: unknown[] = [];\n const standIn = {\n instanceId: instanceId ?? \"\",\n get callbackGroupId(): string | null {\n return target?.callbackGroupId ?? null;\n },\n update(patch: unknown) {\n if (target) target.update?.(patch);\n else if (!closed) pending.push(patch);\n },\n close() {\n if (target) target.close?.();\n else closed = true;\n },\n };\n ensure().then(\n (opener) => {\n if (closed) return; // closed before the chunk arrived: never open it\n const handle = opener(...args) as RealHandle | undefined;\n target = handle ?? {};\n for (const patch of pending.splice(0)) target.update?.(patch);\n },\n (error: unknown) => {\n // eslint-disable-next-line no-console\n console.error(`[summon] the \"${overlayId}\" opener failed to load; nothing opened`, error);\n },\n );\n return standIn;\n };\n return lazy as F;\n}\n","// Callback-aware opening without loading the handles registry up front. The opener needs a\n// channel id synchronously (it rides open data); the channel itself is created when the handles\n// section arrives — one import() started by the first such open — or at once by whoever emits\n// first (the render tree has handles statically). Closing the owner before then drops it.\nimport { globalSlot } from \"@ai-matrx/kit/global-slot\";\nimport type { EventChannel } from \"../handles/helpers\";\n\ntype Handlers = Readonly<Record<string, ((payload: unknown) => void) | undefined>> | undefined;\n\ninterface PendingChannel {\n readonly owner: string;\n readonly getHandlers: () => Handlers;\n}\n\n/** The one message shape on an overlay's channel. */\nexport interface OverlayEventMessage {\n readonly type: string;\n readonly payload: unknown;\n}\n\ntype CreateChannel = (options: { owner?: string; id?: string }) => EventChannel<OverlayEventMessage>;\n\nconst pending = (): Map<string, PendingChannel> => globalSlot(\"ai-matrx.summon.pendingChannels\", () => new Map<string, PendingChannel>());\n\n/** Create every pending channel now (idempotent per id). */\nexport function materializePendingChannels(createEventChannel: CreateChannel): void {\n const map = pending();\n for (const [id, entry] of [...map]) {\n map.delete(id);\n const channel = createEventChannel({ owner: entry.owner, id });\n channel.subscribe((message) => entry.getHandlers()?.[message.type]?.(message.payload));\n }\n}\n\n/** Reserve a channel owned by `owner` whose events go to the handlers `getHandlers` returns at emit time. */\nexport function openPendingEventChannel(owner: string, getHandlers: () => Handlers): string {\n const id = `ch-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;\n pending().set(id, { owner, getHandlers });\n void import(\"@ai-matrx/summon/handles\").then(({ createEventChannel }) => materializePendingChannels(createEventChannel));\n return id;\n}\n\n/** The owner closed before its channel was created: forget it. */\nexport function dropPendingChannelsOf(owner: string): void {\n const map = pending();\n for (const [id, entry] of [...map]) if (entry.owner === owner) map.delete(id);\n}\n","/**\n * The `?panels=` link grammar.\n *\n * panels = token (\",\" token)*\n * token = key [\":\" id [\":\" args]]\n * args = k \"-\" v (\"_\" k \"-\" v)*\n *\n * GRAMMAR v2 (this file): on WRITE, ids are percent-encoded for `% , :` and arg keys and values\n * for `% , : _ -`, so any value — a uuid, a date, a path, a list — survives the round trip.\n * Keys and ids keep `-` and `_` unencoded: they are not separators inside an id, and leaving them means a\n * uuid id writes byte-identically to v1. On READ, v1 tokens (unencoded) parse unchanged: an arg\n * pair splits on its FIRST hyphen, and decoding only touches well-formed `%XX` escapes.\n *\n * Framework-free; this is the one grammar every door (address bar, notifications, extension)\n * shares. This half (the WRITE side) is on `./open` because link builders run at boot (chat's\n * agent-variable href); the READ side (`parseLinkParam`, `readPanelsParam`, `withPanelsParam`, …)\n * lives in `../url/linkParse.ts` and ships on `./url`, which only the lazy link runtime loads —\n * a bundler keeps every used export of an entry, so parsers here rode into every first load (W4).\n */\n\nexport interface LinkToken {\n /** The token exactly as it appeared (the verbatim form written back while unresolved). */\n readonly raw: string;\n readonly key: string;\n /** `undefined` for a bare-key token (`keyword_research`). */\n readonly id: string | undefined;\n /** `undefined` when the token carries no args segment. */\n readonly args: Readonly<Record<string, string>> | undefined;\n}\n\nexport interface LinkEntry {\n readonly key: string;\n readonly id: string;\n readonly args?: Readonly<Record<string, string>> | undefined;\n}\n\nconst hex = (ch: string): string => `%${ch.charCodeAt(0).toString(16).toUpperCase().padStart(2, \"0\")}`;\n\n/** Encode a token id (`% , :`). */\nexport function encodeLinkId(id: string): string {\n return id.replace(/[%,:]/g, hex);\n}\n\n/** Encode an arg key or value (`% , : _ -`). */\nexport function encodeLinkArg(value: string): string {\n return value.replace(/[%,:_-]/g, hex);\n}\n\n/** Write one entry as a v2 token. Args are written in key order so equal entries write equal tokens. */\nexport function formatLinkToken(entry: LinkEntry): string {\n let token = `${encodeLinkId(entry.key)}:${encodeLinkId(entry.id)}`;\n const args = entry.args;\n if (args) {\n const keys = Object.keys(args).sort();\n if (keys.length > 0) {\n token += `:${keys.map((k) => `${encodeLinkArg(k)}-${encodeLinkArg(args[k] ?? \"\")}`).join(\"_\")}`;\n }\n }\n return token;\n}\n"],"mappings":"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","names":["globalSlot","globalSlot","state","globalSlot","slot","globalSlot","core","middleware","slot","hex","globalSlot","globalSlot","slot","pending","globalSlot"]}
|
|
1
|
+
{"version":3,"sources":["../src/open/renderAcks.ts","../src/open/peek.ts","../src/open/lazyOpener.ts","../src/open/grammar.ts"],"sourcesContent":["// Render acknowledgements a mobile surface reports (it renders instead of a WindowPanel). Light:\n// the same slot the render watchdog (core) reads, so a boot-graph hook can report without the core.\nimport { globalSlot } from \"@ai-matrx/kit/global-slot\";\n\ninterface AckSlot {\n readonly renderAcks: Map<string, { kind: \"window\"; windowId: string } | { kind: \"surface\" }>;\n readonly ackWaiters: Map<string, () => void>;\n readonly watches: Map<string, unknown>;\n}\n\n// Same key and shape as core/middleware/renderWatchdog.ts (RENDER_WATCHDOG_SLOT).\nconst slot = (): AckSlot =>\n globalSlot<AckSlot>(\"ai-matrx.summon.renderWatchdog\", () => ({ renderAcks: new Map(), ackWaiters: new Map(), watches: new Map() }));\n\nexport function ackOverlaySurfaceRender(overlayId: string): void {\n const s = slot();\n s.renderAcks.set(overlayId, { kind: \"surface\" });\n const notify = s.ackWaiters.get(overlayId);\n if (notify) {\n s.ackWaiters.delete(overlayId);\n notify();\n }\n}\n\nexport function clearOverlaySurfaceRender(overlayId: string): void {\n const s = slot();\n if (s.renderAcks.get(overlayId)?.kind === \"surface\") s.renderAcks.delete(overlayId);\n}\n","// Read a registered handle WITHOUT loading the handles registry. A handle exists only after its\n// registrant loaded `@ai-matrx/summon/handles` and called `register*`; until then the registry's\n// global slot is empty and every id resolves to nothing — exactly what `callbackManager.get` would\n// say. So a boot-time caller that only resolves ids (a stream processor, a store middleware) reads\n// through here and never puts the registry in first load.\nimport { HANDLES_SLOT } from \"../handles/slot\";\n\ninterface PeekableSlot {\n readonly callbacks: Map<string, { readonly callback: unknown }>;\n}\n\n/** `callbackManager.get(id)` without loading the registry: `undefined` until something registers. */\nexport function peekHandle<T = unknown>(id: string): T | undefined {\n const slot = (globalThis as unknown as Record<symbol, PeekableSlot | undefined>)[Symbol.for(HANDLES_SLOT)];\n return slot?.callbacks.get(id)?.callback as T | undefined;\n}\n","// A window opener whose code loads on its first call. Openers return a handle synchronously\n// (`{ instanceId, close }`, sometimes `update`), so a host cannot simply `import()` them: the\n// caller already holds the handle before the chunk arrives. `lazyOpener` returns a function with\n// the real opener's exact signature that knows the handle's instance id up front (minted, or\n// derived the way the real opener derives it), hands back a stand-in handle at once, and starts\n// `load()` — which a host shares across a whole set of openers (one import(), never one per id).\n// When the real opener arrives it opens with the same arguments; calls made on the stand-in in\n// the meantime (`update`, `close`) replay on the real handle in order. Once loaded, every call is\n// the real opener, synchronously, returning the real handle.\n//\n// Framework-free and tiny on purpose: it rides the first-load `./open` entry.\n\n/** How the stand-in handle learns its `instanceId` before the opener loads. */\nexport type LazyOpenerInstanceId<A extends readonly unknown[]> =\n /** `args[0].instanceId` when given, else a fresh `<overlayId>-<time>-<rand>`; written back into `args[0]`. */\n | \"mint\"\n /** Derived from the arguments exactly as the real opener derives it (a per-subject window). */\n | ((...args: A) => string);\n\nexport interface LazyOpenerOptions<A extends readonly unknown[]> {\n /** Absent: the opener's handle carries no `instanceId` (a single-instance window). */\n readonly instanceId?: LazyOpenerInstanceId<A>;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any -- any opener signature\ntype AnyOpener = (...args: any[]) => any;\n\ninterface RealHandle {\n readonly instanceId?: string;\n readonly callbackGroupId?: string | null;\n close?: () => void;\n update?: (patch: unknown) => void;\n}\n\n/** A fresh instance id in the shape hand-written openers mint: `<overlayId>-<time>-<rand>`. */\nexport function mintInstanceId(overlayId: string): string {\n return `${overlayId}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n}\n\nfunction withInstanceId(args: unknown[], instanceId: string): unknown[] {\n const first = args[0];\n const options = first && typeof first === \"object\" ? (first as Record<string, unknown>) : {};\n return [{ ...options, instanceId }, ...args.slice(1)];\n}\n\n/**\n * Wrap an opener so its module loads on the first call. `load` resolves to the real opener (a\n * plain function, never a hook); share one loader across a set so the set costs one import().\n */\nexport function lazyOpener<F extends AnyOpener>(\n overlayId: string,\n load: () => Promise<F>,\n options: LazyOpenerOptions<Parameters<F>> = {},\n): F {\n let real: F | null = null;\n let loading: Promise<F> | null = null;\n const ensure = (): Promise<F> => {\n loading ??= load().then(\n (opener) => {\n real = opener;\n return opener;\n },\n (error: unknown) => {\n loading = null; // a failed chunk may be retried by the next call\n throw error;\n },\n );\n return loading;\n };\n\n const lazy = (...callArgs: unknown[]): unknown => {\n let args = callArgs;\n let instanceId: string | undefined;\n const rule = options.instanceId;\n if (rule === \"mint\") {\n const given = (args[0] as { instanceId?: unknown } | undefined)?.instanceId;\n instanceId = typeof given === \"string\" && given ? given : mintInstanceId(overlayId);\n args = withInstanceId(args, instanceId);\n } else if (typeof rule === \"function\") {\n instanceId = rule(...(args as Parameters<F>));\n }\n if (real) return real(...args);\n\n let target: RealHandle | null = null;\n let closed = false;\n const pending: unknown[] = [];\n const standIn = {\n instanceId: instanceId ?? \"\",\n get callbackGroupId(): string | null {\n return target?.callbackGroupId ?? null;\n },\n update(patch: unknown) {\n if (target) target.update?.(patch);\n else if (!closed) pending.push(patch);\n },\n close() {\n if (target) target.close?.();\n else closed = true;\n },\n };\n ensure().then(\n (opener) => {\n if (closed) return; // closed before the chunk arrived: never open it\n const handle = opener(...args) as RealHandle | undefined;\n target = handle ?? {};\n for (const patch of pending.splice(0)) target.update?.(patch);\n },\n (error: unknown) => {\n // eslint-disable-next-line no-console\n console.error(`[summon] the \"${overlayId}\" opener failed to load; nothing opened`, error);\n },\n );\n return standIn;\n };\n return lazy as F;\n}\n","/**\n * The `?panels=` link grammar.\n *\n * panels = token (\",\" token)*\n * token = key [\":\" id [\":\" args]]\n * args = k \"-\" v (\"_\" k \"-\" v)*\n *\n * GRAMMAR v2 (this file): on WRITE, ids are percent-encoded for `% , :` and arg keys and values\n * for `% , : _ -`, so any value — a uuid, a date, a path, a list — survives the round trip.\n * Keys and ids keep `-` and `_` unencoded: they are not separators inside an id, and leaving them means a\n * uuid id writes byte-identically to v1. On READ, v1 tokens (unencoded) parse unchanged: an arg\n * pair splits on its FIRST hyphen, and decoding only touches well-formed `%XX` escapes.\n *\n * Framework-free; this is the one grammar every door (address bar, notifications, extension)\n * shares. This half (the WRITE side) is on `./open` because link builders run at boot (chat's\n * agent-variable href); the READ side (`parseLinkParam`, `readPanelsParam`, `withPanelsParam`, …)\n * lives in `../url/linkParse.ts` and ships on `./url`, which only the lazy link runtime loads —\n * a bundler keeps every used export of an entry, so parsers here rode into every first load (W4).\n */\n\nexport interface LinkToken {\n /** The token exactly as it appeared (the verbatim form written back while unresolved). */\n readonly raw: string;\n readonly key: string;\n /** `undefined` for a bare-key token (`keyword_research`). */\n readonly id: string | undefined;\n /** `undefined` when the token carries no args segment. */\n readonly args: Readonly<Record<string, string>> | undefined;\n}\n\nexport interface LinkEntry {\n readonly key: string;\n readonly id: string;\n readonly args?: Readonly<Record<string, string>> | undefined;\n}\n\nconst hex = (ch: string): string => `%${ch.charCodeAt(0).toString(16).toUpperCase().padStart(2, \"0\")}`;\n\n/** Encode a token id (`% , :`). */\nexport function encodeLinkId(id: string): string {\n return id.replace(/[%,:]/g, hex);\n}\n\n/** Encode an arg key or value (`% , : _ -`). */\nexport function encodeLinkArg(value: string): string {\n return value.replace(/[%,:_-]/g, hex);\n}\n\n/** Write one entry as a v2 token. Args are written in key order so equal entries write equal tokens. */\nexport function formatLinkToken(entry: LinkEntry): string {\n let token = `${encodeLinkId(entry.key)}:${encodeLinkId(entry.id)}`;\n const args = entry.args;\n if (args) {\n const keys = Object.keys(args).sort();\n if (keys.length > 0) {\n token += `:${keys.map((k) => `${encodeLinkArg(k)}-${encodeLinkArg(args[k] ?? \"\")}`).join(\"_\")}`;\n }\n }\n return token;\n}\n"],"mappings":"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","names":["slot"]}
|
package/dist/react.cjs
CHANGED
|
@@ -226,7 +226,7 @@ function OverlayLoadingFallback({ overlayId, label }) {
|
|
|
226
226
|
{
|
|
227
227
|
role: "status",
|
|
228
228
|
"aria-label": `Loading ${label}`,
|
|
229
|
-
className: "pointer-events-auto flex items-center gap-3 rounded-xl border border-border bg-card px-5 py-4 text-sm text-muted-foreground shadow-
|
|
229
|
+
className: "pointer-events-auto flex items-center gap-3 rounded-xl border border-border bg-card px-5 py-4 text-sm text-muted-foreground shadow-md",
|
|
230
230
|
children: [
|
|
231
231
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { "aria-hidden": true, className: "size-4 animate-spin rounded-full border-2 border-border border-t-primary" }),
|
|
232
232
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { children: "Loading\u2026" })
|
|
@@ -241,7 +241,7 @@ function OverlayErrorFallback({ label, error, retry, close, extras }) {
|
|
|
241
241
|
{
|
|
242
242
|
role: "alertdialog",
|
|
243
243
|
"aria-label": `${label} failed to load`,
|
|
244
|
-
className: "pointer-events-auto flex max-h-[85dvh] w-full max-w-lg flex-col overflow-hidden rounded-xl border border-destructive bg-card shadow-
|
|
244
|
+
className: "pointer-events-auto flex max-h-[85dvh] w-full max-w-lg flex-col overflow-hidden rounded-xl border border-destructive bg-card shadow-lg",
|
|
245
245
|
children: [
|
|
246
246
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "border-b border-border px-5 py-4", children: [
|
|
247
247
|
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("h2", { className: "text-sm font-semibold text-foreground", children: [
|
package/dist/react.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react.ts","../src/react/SummonProvider.tsx","../src/react/context.ts","../src/react/fallbacks.tsx","../src/react/storeHooks.ts","../src/react/keepAlive.ts","../src/react/loaderCache.ts","../src/react/events.ts","../src/react/SummonHost.tsx","../src/react/hostRenders.ts","../src/react/instanceBody.tsx","../src/react/OverlayErrorBoundary.tsx","../src/react/instance.tsx","../src/react/hooks.ts"],"sourcesContent":["// @ai-matrx/summon/react — the render layer: provider (own store context), declare-once\n// definitions, the host, the lazy loader with its boundary and fallbacks, and the hooks.\nexport { SummonProvider, DEFAULT_IMPORT_TIMEOUT_MS, DEFAULT_KEEP_ALIVE_LIMIT, DEFAULT_STALL_WARN_MS, type SummonProviderProps } from \"./react/SummonProvider\";\nexport {\n SummonStoreContext,\n type OverlayRenderContext,\n type OverlayLoadingFallbackProps,\n type OverlayErrorFallbackProps,\n type OverlayErrorExtrasContext,\n} from \"./react/context\";\nexport {\n useSummonSelector,\n useSummonDispatch,\n useSummonStore,\n useSummonPorts,\n useOptionalSummonPorts,\n useOptionalSummonStore,\n type SummonReactDispatch,\n type SummonReactStore,\n} from \"./react/storeHooks\";\nexport {\n defineOverlay,\n CALLBACK_GROUP_KEY,\n type OverlayDefinition,\n type OverlaySpec,\n type HostableOverlay,\n type OverlayHandle,\n type OverlayOpener,\n type OverlayOpenOptions,\n type OverlayControllerProps,\n type OverlayEmitter,\n} from \"@ai-matrx/summon/define\";\nexport type { OverlayRenderProps } from \"./react/instanceBody\";\nexport { emitOverlayEvent, type OverlayEventMap, type OverlayHandlers } from \"./react/events\";\nexport type { RenderModule, RenderLoader } from \"./react/loaderCache\";\nexport { SummonHost, useCloseOnNavigation, type SummonHostProps } from \"./react/SummonHost\";\nexport { MISSING_RENDER_ERROR, type ErasedRenderLoader, type OverlayRenderMap } from \"./react/hostRenders\";\nexport { SummonRoot, type SummonRootProps, configureSummonHost, type SummonHostConfig } from \"@ai-matrx/summon/root\";\nexport {\n useOverlayInstance,\n useOptionalOverlayInstance,\n useOverlayState,\n type OverlayInstanceContextValue,\n type OverlayStateSetter,\n} from \"./react/instance\";\nexport { useIsOverlayOpen, useOpenOverlay, useCloseOverlay, type OpenOverlayOptions } from \"./react/hooks\";\n// Also on `./url`; lives here so a render module can publish its link without loading the link section.\nexport { useOverlayLink } from \"@ai-matrx/summon/root\";\nexport { OverlayErrorBoundary, type OverlayErrorBoundaryProps } from \"./react/OverlayErrorBoundary\";\nexport { OverlayErrorFallback, OverlayLoadingFallback, normalizeOverlayError, type NormalizedOverlayError } from \"./react/fallbacks\";\nexport { chunkTimeoutError } from \"./react/loaderCache\";\n","// `<SummonProvider>` — mounts the overlays store on the package's own context (the host's store\n// when passed — AI Matrx mounts `summonReducers` into its one store — else a private store made\n// once), the resolved ports, and the render-layer knobs (fallbacks, error extras, wrapper,\n// keep-alive cap, import timeout).\n\nimport { useEffect, useMemo, useRef, useState, type ComponentType, type ReactNode } from \"react\";\nimport { Provider } from \"react-redux\";\nimport type { Store } from \"@reduxjs/toolkit\";\nimport { resolvePorts, type SummonPorts } from \"@ai-matrx/summon\";\nimport { createSummonStore } from \"@ai-matrx/summon\";\nimport {\n SummonConfigContext,\n SummonPortsContext,\n SummonStoreContext,\n type OverlayErrorExtrasContext,\n type OverlayErrorFallbackProps,\n type OverlayLoadingFallbackProps,\n type OverlayRenderContext,\n type SummonReactConfig,\n} from \"./context\";\nimport { OverlayErrorFallback, OverlayLoadingFallback } from \"./fallbacks\";\nimport { KeepAliveRegistry } from \"./keepAlive\";\nimport { LoaderCache } from \"./loaderCache\";\n\nimport { DEFAULT_IMPORT_TIMEOUT_MS, DEFAULT_KEEP_ALIVE_LIMIT, DEFAULT_STALL_WARN_MS } from \"./storeHooks\";\nexport { DEFAULT_IMPORT_TIMEOUT_MS, DEFAULT_KEEP_ALIVE_LIMIT, DEFAULT_STALL_WARN_MS };\n\nexport interface SummonProviderProps {\n /** The host's Redux store with `summonReducers` mounted at their root keys. Omit for a private store. */\n readonly store?: Store<unknown>;\n /** Host ports; anything omitted uses the working default. */\n readonly ports?: Partial<SummonPorts>;\n readonly fallbacks?: {\n readonly loading?: ComponentType<OverlayLoadingFallbackProps>;\n readonly error?: ComponentType<OverlayErrorFallbackProps>;\n };\n /** Extra controls in the default error card's footer (AI Matrx: \"Copy for AI\"). */\n readonly errorReportExtras?: (context: OverlayErrorExtrasContext) => ReactNode;\n /** Wrap every rendered overlay (AI Matrx: its surface layer boundary). */\n readonly renderWrapper?: (node: ReactNode, context: OverlayRenderContext) => ReactNode;\n /** Most closed-but-alive (`keepAlive: \"hidden\"`) instances kept mounted. Default 8. */\n readonly keepAliveLimit?: number;\n /** A render-module import that has not settled by then becomes a ChunkLoadError. Default 12 s. */\n readonly importTimeoutMs?: number;\n /** When the loading fallback reports a stall to the error port. Default 10 s. */\n readonly stallWarnMs?: number;\n readonly children?: ReactNode;\n}\n\nexport function SummonProvider({\n store,\n ports,\n fallbacks,\n errorReportExtras,\n renderWrapper,\n keepAliveLimit = DEFAULT_KEEP_ALIVE_LIMIT,\n importTimeoutMs = DEFAULT_IMPORT_TIMEOUT_MS,\n stallWarnMs = DEFAULT_STALL_WARN_MS,\n children,\n}: SummonProviderProps) {\n const resolvedPorts = useMemo(() => resolvePorts(ports), [ports]);\n const [privateStore] = useState(() => (store ? null : createSummonStore({ ports: resolvedPorts })));\n const activeStore: Store<unknown> = store ?? (privateStore as Store<unknown>);\n\n const timeoutRef = useRef(importTimeoutMs);\n timeoutRef.current = importTimeoutMs;\n const [keepAlive] = useState(() => new KeepAliveRegistry(keepAliveLimit));\n const [loaders] = useState(() => new LoaderCache({ timeoutMs: () => timeoutRef.current }));\n useEffect(() => keepAlive.setLimit(keepAliveLimit), [keepAlive, keepAliveLimit]);\n\n const loading = fallbacks?.loading ?? OverlayLoadingFallback;\n const error = fallbacks?.error ?? OverlayErrorFallback;\n const config = useMemo<SummonReactConfig>(\n () => ({\n loadingFallback: loading,\n errorFallback: error,\n errorReportExtras: errorReportExtras ?? null,\n renderWrapper: renderWrapper ?? null,\n importTimeoutMs,\n stallWarnMs,\n keepAlive,\n loaders,\n }),\n [loading, error, errorReportExtras, renderWrapper, importTimeoutMs, stallWarnMs, keepAlive, loaders],\n );\n\n return (\n <Provider store={activeStore} context={SummonStoreContext}>\n <SummonPortsContext.Provider value={resolvedPorts}>\n <SummonConfigContext.Provider value={config}>{children}</SummonConfigContext.Provider>\n </SummonPortsContext.Provider>\n </Provider>\n );\n}\n","// The React section's own contexts. The overlays store rides its OWN react-redux context\n// (chat-package pattern), so a private overlays store never collides with a host's store and a\n// host that mounts `summonReducers` into its one store simply passes it in.\n\nimport { createContext, type ComponentType, type ReactNode } from \"react\";\nimport type { KeepAliveRegistry } from \"./keepAlive\";\nimport type { LoaderCache } from \"./loaderCache\";\nimport type { OverlayRenderContext, OverlayErrorExtrasContext } from \"@ai-matrx/summon/root\";\n\n// One identity: the store and ports contexts live in the light root section.\nexport { SummonStoreContext, SummonPortsContext } from \"@ai-matrx/summon/root\";\nexport type { OverlayRenderContext, OverlayErrorExtrasContext };\n\nexport interface OverlayLoadingFallbackProps {\n readonly overlayId: string;\n readonly label: string;\n}\n\nexport interface OverlayErrorFallbackProps {\n readonly overlayId: string;\n readonly instanceId: string;\n readonly label: string;\n readonly error: unknown;\n readonly componentStack: string | null;\n /** Re-import the render module and mount again. */\n readonly retry: () => void;\n /** Close this instance (no reload). */\n readonly close: () => void;\n /** Host-provided extras (AI Matrx: \"Copy for AI\"), already rendered for this error. */\n readonly extras: ReactNode;\n}\n\nexport interface SummonReactConfig {\n readonly loadingFallback: ComponentType<OverlayLoadingFallbackProps>;\n readonly errorFallback: ComponentType<OverlayErrorFallbackProps>;\n readonly errorReportExtras: ((context: OverlayErrorExtrasContext) => ReactNode) | null;\n readonly renderWrapper: ((node: ReactNode, context: OverlayRenderContext) => ReactNode) | null;\n readonly importTimeoutMs: number;\n readonly stallWarnMs: number;\n readonly keepAlive: KeepAliveRegistry;\n readonly loaders: LoaderCache;\n}\n\nexport const SummonConfigContext = createContext<SummonReactConfig | null>(null);\nSummonConfigContext.displayName = \"SummonConfigContext\";\n","// The default loading and error fallbacks every overlay renders through. A host replaces either\n// with `<SummonProvider fallbacks>`; AI Matrx adds its \"Copy for AI\" through `errorReportExtras`.\n// Design-system components and tokens only — no app imports.\n\nimport { useEffect } from \"react\";\nimport { Button } from \"@ai-matrx/design-system\";\nimport type { OverlayErrorFallbackProps, OverlayLoadingFallbackProps } from \"./context\";\nimport { useSummonConfig, useSummonPorts } from \"./storeHooks\";\n\nexport interface NormalizedOverlayError {\n readonly name: string;\n readonly message: string;\n readonly stack: string | null;\n readonly isChunkLoadError: boolean;\n}\n\nexport function normalizeOverlayError(error: unknown): NormalizedOverlayError {\n if (error instanceof Error) {\n const isChunkLoadError =\n error.name === \"ChunkLoadError\" ||\n /Loading chunk [\\w-]+ failed|Failed to fetch dynamically imported module|Importing a module script failed/i.test(\n error.message,\n );\n return { name: error.name, message: error.message, stack: error.stack ?? null, isChunkLoadError };\n }\n return { name: \"Error\", message: typeof error === \"string\" ? error : String(error), stack: null, isChunkLoadError: false };\n}\n\n/**\n * Spinner while the render module is in flight. Never blank. At the stall threshold it reports\n * once through the error port; the loader's import timeout (later) turns a hung import into a\n * real error so the error fallback takes over.\n */\nexport function OverlayLoadingFallback({ overlayId, label }: OverlayLoadingFallbackProps) {\n const ports = useSummonPorts();\n const { stallWarnMs } = useSummonConfig();\n useEffect(() => {\n const timer = setTimeout(() => {\n ports.errors.capture(new Error(`Overlay \"${overlayId}\" still loading after ${stallWarnMs}ms`), {\n stage: \"overlay-load-stall\",\n overlayId,\n level: \"warning\",\n });\n }, stallWarnMs);\n return () => clearTimeout(timer);\n }, [ports, overlayId, stallWarnMs]);\n\n return (\n <div className=\"pointer-events-none fixed inset-0 z-[2147483000] flex items-center justify-center p-4\">\n <div\n role=\"status\"\n aria-label={`Loading ${label}`}\n className=\"pointer-events-auto flex items-center gap-3 rounded-xl border border-border bg-card px-5 py-4 text-sm text-muted-foreground shadow-[var(--elevation-2)]\"\n >\n <span aria-hidden className=\"size-4 animate-spin rounded-full border-2 border-border border-t-primary\" />\n <span>Loading…</span>\n </div>\n </div>\n );\n}\n\n/** The error card: what failed, and a way out that never needs a page reload. */\nexport function OverlayErrorFallback({ label, error, retry, close, extras }: OverlayErrorFallbackProps) {\n const e = normalizeOverlayError(error);\n return (\n <div className=\"pointer-events-none fixed inset-0 z-[2147483001] flex items-center justify-center p-4\">\n <div\n role=\"alertdialog\"\n aria-label={`${label} failed to load`}\n className=\"pointer-events-auto flex max-h-[85dvh] w-full max-w-lg flex-col overflow-hidden rounded-xl border border-destructive bg-card shadow-[var(--elevation-3)]\"\n >\n <div className=\"border-b border-border px-5 py-4\">\n <h2 className=\"text-sm font-semibold text-foreground\">{label} failed to load</h2>\n <p className=\"mt-1 text-xs text-muted-foreground\">\n {e.isChunkLoadError ? \"Part of it did not finish loading.\" : \"It hit an error while rendering.\"}\n </p>\n </div>\n <div className=\"min-h-0 flex-1 overflow-auto px-5 py-4\">\n <div className=\"rounded-lg bg-muted px-3 py-2 font-mono text-xs text-foreground\">\n <span className=\"text-destructive\">{e.name}</span>: {e.message}\n </div>\n </div>\n <div className=\"flex items-center justify-between gap-2 border-t border-border px-5 py-3\">\n <div>{extras}</div>\n <div className=\"flex items-center gap-2\">\n <Button variant=\"ghost\" size=\"sm\" onClick={close}>\n Close\n </Button>\n <Button variant=\"primary\" size=\"sm\" onClick={retry}>\n Try again\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => {\n if (typeof window !== \"undefined\") window.location.reload();\n }}\n >\n Reload page\n </Button>\n </div>\n </div>\n </div>\n </div>\n );\n}\n","// The store hooks live in the light root section (one context identity); the render-layer config\n// hook stays here: the nearest SummonProvider's config, else one built from the root's settings.\nimport { useContext } from \"react\";\nimport { getSummonHostConfig, getSummonHostVersion } from \"@ai-matrx/summon/root\";\nimport { globalSlot } from \"@ai-matrx/kit/global-slot\";\nimport { SummonConfigContext, type SummonReactConfig } from \"./context\";\nimport { OverlayErrorFallback, OverlayLoadingFallback } from \"./fallbacks\";\nimport { KeepAliveRegistry } from \"./keepAlive\";\nimport { LoaderCache } from \"./loaderCache\";\n\nexport {\n useSummonSelector,\n useSummonDispatch,\n useSummonStore,\n useSummonPorts,\n useOptionalSummonPorts,\n useOptionalSummonStore,\n type SummonReactDispatch,\n type SummonReactStore,\n} from \"@ai-matrx/summon/root\";\n\nexport const DEFAULT_KEEP_ALIVE_LIMIT = 8;\nexport const DEFAULT_IMPORT_TIMEOUT_MS = 12_000;\nexport const DEFAULT_STALL_WARN_MS = 10_000;\n\ninterface HostConfigSlot {\n version: number;\n config: SummonReactConfig | null;\n keepAlive: KeepAliveRegistry | null;\n loaders: LoaderCache | null;\n}\n\nconst hostConfigSlot = (): HostConfigSlot =>\n globalSlot<HostConfigSlot>(\"ai-matrx.summon.hostReactConfig\", () => ({ version: -1, config: null, keepAlive: null, loaders: null }));\n\n/** The render config when no SummonProvider is above: the root's settings, one keep-alive and loader cache per page. */\nexport function hostReactConfig(): SummonReactConfig {\n const s = hostConfigSlot();\n const version = getSummonHostVersion();\n if (s.config && s.version === version) return s.config;\n const host = getSummonHostConfig();\n s.keepAlive ??= new KeepAliveRegistry(DEFAULT_KEEP_ALIVE_LIMIT);\n s.loaders ??= new LoaderCache({ timeoutMs: () => DEFAULT_IMPORT_TIMEOUT_MS });\n s.config = {\n loadingFallback: OverlayLoadingFallback,\n errorFallback: OverlayErrorFallback,\n errorReportExtras: host.errorReportExtras ?? null,\n renderWrapper: host.renderWrapper ?? null,\n importTimeoutMs: DEFAULT_IMPORT_TIMEOUT_MS,\n stallWarnMs: DEFAULT_STALL_WARN_MS,\n keepAlive: s.keepAlive,\n loaders: s.loaders,\n };\n s.version = version;\n return s.config;\n}\n\nexport function useSummonConfig(): SummonReactConfig {\n return useContext(SummonConfigContext) ?? hostReactConfig();\n}\n","// The provider's LRU of closed-but-alive instances (`keepAlive: \"hidden\"`, C38 R3). Each slot\n// retains its own hidden instances; this registry only keeps the global order and tells the\n// owning slot when one falls off the end, so at most `limit` hidden components stay mounted.\n\nexport class KeepAliveRegistry {\n private readonly order: string[] = [];\n private readonly evictors = new Map<string, () => void>();\n\n private limit: number;\n\n constructor(limit: number) {\n this.limit = limit;\n }\n\n setLimit(limit: number): void {\n this.limit = Math.max(0, Math.floor(limit));\n this.trim();\n }\n\n /** Mark `key` as hidden-alive (most recent). `evict` unmounts it when the cap is exceeded. */\n retain(key: string, evict: () => void): void {\n this.drop(key);\n this.order.push(key);\n this.evictors.set(key, evict);\n this.trim();\n }\n\n /** `key` reopened or its slot went away: no longer counted. */\n release(key: string): void {\n this.drop(key);\n }\n\n size(): number {\n return this.order.length;\n }\n\n private drop(key: string): void {\n const at = this.order.indexOf(key);\n if (at >= 0) this.order.splice(at, 1);\n this.evictors.delete(key);\n }\n\n private trim(): void {\n while (this.order.length > this.limit) {\n const oldest = this.order.shift();\n if (oldest === undefined) return;\n const evict = this.evictors.get(oldest);\n this.evictors.delete(oldest);\n evict?.();\n }\n }\n}\n","// Per-provider cache of each definition's lazily loaded render component. Lives in the provider\n// (React state), never at module level. A definition's render module is fetched the first time\n// one of its instances mounts — never before — and a retry swaps in a FRESH lazy so the import is\n// genuinely attempted again (a React.lazy caches its first rejection forever).\n\nimport { lazy, type ComponentType, type LazyExoticComponent } from \"react\";\n\nexport interface RenderModule<P> {\n readonly default: ComponentType<P>;\n}\n\nexport type RenderLoader<P> = () => Promise<RenderModule<P>>;\n\nexport interface LoaderEntry<P> {\n readonly attempt: number;\n readonly Component: LazyExoticComponent<ComponentType<P>>;\n}\n\nexport interface LoaderCacheOptions {\n readonly timeoutMs: () => number;\n readonly onImportStart?: (key: string, attempt: number) => void;\n}\n\n/** The error a stalled import becomes, so the error boundary always fires. */\nexport function chunkTimeoutError(key: string, timeoutMs: number): Error {\n const error = new Error(\n `Overlay \"${key}\" render module did not load within ${timeoutMs}ms. The import() did not resolve before the recovery timeout.`,\n );\n error.name = \"ChunkLoadError\";\n return error;\n}\n\nfunction raceTimeout<T>(key: string, real: Promise<T>, timeoutMs: number): Promise<T> {\n // A late rejection after the timeout won must not surface as unhandled.\n real.catch(() => undefined);\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(chunkTimeoutError(key, timeoutMs)), timeoutMs);\n });\n return Promise.race([real, timeout]).finally(() => {\n if (timer !== undefined) clearTimeout(timer);\n });\n}\n\nexport class LoaderCache {\n private readonly entries = new Map<string, LoaderEntry<unknown>>();\n\n private readonly options: LoaderCacheOptions;\n\n constructor(options: LoaderCacheOptions) {\n this.options = options;\n }\n\n private create<P>(key: string, loader: RenderLoader<P>, attempt: number): LoaderEntry<P> {\n const Component = lazy(() => {\n this.options.onImportStart?.(key, attempt);\n return raceTimeout(key, loader(), this.options.timeoutMs());\n });\n return { attempt, Component };\n }\n\n /** The current lazy component for `key`, created on first request. */\n get<P>(key: string, loader: RenderLoader<P>): LoaderEntry<P> {\n const existing = this.entries.get(key);\n // Sound by construction: an entry under `key` is only ever created from that key's loader.\n if (existing) return existing as LoaderEntry<P>;\n const created = this.create(key, loader, 0);\n this.entries.set(key, created as LoaderEntry<unknown>);\n return created;\n }\n\n /** Replace `key`'s lazy with a fresh one so the next render re-imports. */\n retry<P>(key: string, loader: RenderLoader<P>, failedAttempt: number): void {\n const existing = this.entries.get(key);\n // Another instance already retried past the failed attempt: share its fresh lazy.\n if (existing && existing.attempt > failedAttempt) return;\n const next = this.create(key, loader, failedAttempt + 1);\n this.entries.set(key, next as LoaderEntry<unknown>);\n }\n}\n","// Overlay events on the render side. Opening (the channel id that rides open data) is light and\n// lives in the root section; here, with the handles registry loaded, an emit first creates any\n// channel still pending and then delivers synchronously. Registered on evaluation so a\n// definition's `useEmit` (light) emits synchronously inside the render tree.\n\nimport { createEventChannel, getEventChannel } from \"@ai-matrx/summon/handles\";\nimport { materializePendingChannels, type OverlayEventMessage } from \"@ai-matrx/summon/open\";\nimport { registerOverlayEmitter } from \"@ai-matrx/summon/root\";\n\nexport type { OverlayEventMap, OverlayHandlers } from \"@ai-matrx/summon/root\";\nexport type { OverlayEventMessage };\n\n/** Deliver one event on a channel; a disposed or unknown channel is a silent no-op by contract. */\nexport function emitOverlayEvent(channelId: string, type: string, payload: unknown): void {\n materializePendingChannels(createEventChannel);\n getEventChannel<OverlayEventMessage>(channelId)?.emit({ type, payload });\n}\n\nregisterOverlayEmitter(emitOverlayEvent);\n","// `<SummonHost definitions>` — registers each definition's metadata and renders every definition\n// through its OWN subscriber (`DefinitionSlot`), so opening overlay A never re-renders B (the old\n// controller held ~440 subscriptions in one component). A closed overlay puts nothing in the tree\n// and fetches no chunk. `keepAlive: \"hidden\"` keeps closed instances mounted inside\n// `<Activity mode=\"hidden\">`, LRU-capped per provider.\n\nimport { Activity, memo, useCallback, useEffect, useRef, useState, type ComponentType, type ReactNode } from \"react\";\nimport { releaseOverlayInstance } from \"@ai-matrx/summon\";\nimport { registerOverlayMeta } from \"@ai-matrx/summon\";\nimport { closeOverlaysBoundToPage, overlayIdsBoundToPage, selectOpenInstances, type OpenInstanceView } from \"@ai-matrx/summon\";\nimport { instanceKey as toInstanceKey, type OverlayRawData } from \"@ai-matrx/summon\";\nimport { dispatchClose, type HostableOverlay } from \"@ai-matrx/summon/root\";\nimport { HostRendersContext, type OverlayRenderMap } from \"./hostRenders\";\nimport { createInstanceBody, type InstanceBodyProps, type OverlayRenderProps } from \"./instanceBody\";\nimport type { RenderLoader } from \"./loaderCache\";\nimport { useSummonConfig, useSummonDispatch, useSummonPorts, useSummonSelector } from \"./storeHooks\";\n\nexport interface SummonHostProps {\n /** Every overlay this host can render — the app's definition list, passed once. */\n readonly definitions: readonly HostableOverlay[];\n /**\n * id → `() => import(\"./<id>.render\")` for definitions declared without `render`. Large apps\n * use it so opener importers never reach a window subtree; a definition's own `render` wins.\n */\n readonly renders?: OverlayRenderMap;\n}\n\nfunction asRawData(data: unknown): OverlayRawData {\n return typeof data === \"object\" && data !== null && !Array.isArray(data) ? (data as OverlayRawData) : null;\n}\n\n/** Equal when the same instances are open with the same data references. */\nfunction sameInstances(a: readonly OpenInstanceView[], b: readonly OpenInstanceView[]): boolean {\n if (a === b) return true;\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i += 1) {\n const x = a[i];\n const y = b[i];\n if (!x || !y || x.instanceId !== y.instanceId || x.data !== y.data) return false;\n }\n return true;\n}\n\n// A definition is light (it carries no render code); the host builds each one's instance body on\n// first render and keeps it for the definition's lifetime.\nconst bodies = new WeakMap<HostableOverlay, ComponentType<InstanceBodyProps>>();\nfunction bodyOf(definition: HostableOverlay): ComponentType<InstanceBodyProps> {\n let body = bodies.get(definition);\n if (!body) {\n const parse = definition.parse ?? ((raw: OverlayRawData) => raw);\n // The definition's loader returns its own render module; erased here like the host map's entries.\n const render = definition.render as RenderLoader<OverlayRenderProps<unknown>> | undefined;\n body = createInstanceBody<unknown>(definition.id, definition.label, render, parse, definition.parse !== undefined);\n bodies.set(definition, body);\n }\n return body;\n}\n\nconst NO_RETAINED: ReadonlyMap<string, OverlayRawData> = new Map();\n\n/** Close-on-navigation: on a pathname change, close every overlay bound to the page. */\nexport function useCloseOnNavigation(): void {\n const ports = useSummonPorts();\n const dispatch = useSummonDispatch();\n useEffect(() => {\n const router = ports.router;\n let previous = router.pathname();\n return router.subscribe(() => {\n const next = router.pathname();\n if (next === previous) return;\n previous = next;\n const overlayIds = overlayIdsBoundToPage();\n if (overlayIds.length > 0) dispatch(closeOverlaysBoundToPage({ overlayIds }));\n });\n }, [ports, dispatch]);\n}\n\ninterface InstanceSlotProps {\n readonly definition: HostableOverlay;\n readonly instanceId: string;\n readonly data: OverlayRawData;\n readonly hidden: boolean;\n}\n\n// Memoized: a slot re-renders only when its own instance changes, never because the host did.\nconst InstanceSlot = memo(function InstanceSlot({ definition, instanceId, data, hidden }: InstanceSlotProps) {\n const dispatch = useSummonDispatch();\n const close = useCallback(() => dispatchClose(dispatch, definition.id, instanceId), [dispatch, definition.id, instanceId]);\n const Body = bodyOf(definition);\n return <Body instanceId={instanceId} instanceKey={toInstanceKey(definition.id, instanceId)} data={data} hidden={hidden} close={close} />;\n});\n\n// Memoized on the definition: the slot re-renders from its own store subscription (one overlay's\n// open instances) and nothing else. Unmemoized, every re-render of the host's parent re-rendered\n// every open overlay's render module (the ~425-renders-in-2-s storm the runtime sweep measured).\nconst DefinitionSlot = memo(function DefinitionSlot({ definition }: { readonly definition: HostableOverlay }) {\n const { keepAlive } = useSummonConfig();\n const dispatch = useSummonDispatch();\n const open = useSummonSelector((state) => selectOpenInstances(state, definition.id), sameInstances);\n const keepHidden = definition.keepAlive === \"hidden\";\n\n // Closed-but-alive instances, derived during render (no unmount/remount flash on close).\n const [retained, setRetained] = useState(NO_RETAINED);\n const [previousOpen, setPreviousOpen] = useState(open);\n if (previousOpen !== open) {\n setPreviousOpen(open);\n if (keepHidden) {\n const openIds = new Set(open.map((instance) => instance.instanceId));\n const next = new Map(retained);\n for (const instance of previousOpen) {\n if (!openIds.has(instance.instanceId)) next.set(instance.instanceId, asRawData(instance.data));\n }\n for (const id of openIds) next.delete(id);\n setRetained(next);\n }\n }\n\n // Mirror the retained set into the provider LRU; eviction unmounts here.\n const registered = useRef(new Set<string>());\n useEffect(() => {\n const seen = registered.current;\n for (const instanceId of retained.keys()) {\n if (seen.has(instanceId)) continue;\n seen.add(instanceId);\n const key = toInstanceKey(definition.id, instanceId);\n keepAlive.retain(key, () => {\n seen.delete(instanceId);\n // Evicted: its handles and saved state go now, as a plain close would have done.\n releaseOverlayInstance(dispatch, key);\n setRetained((current) => {\n if (!current.has(instanceId)) return current;\n const next = new Map(current);\n next.delete(instanceId);\n return next;\n });\n });\n }\n for (const instanceId of [...seen]) {\n if (retained.has(instanceId)) continue;\n seen.delete(instanceId);\n keepAlive.release(toInstanceKey(definition.id, instanceId));\n }\n }, [retained, keepAlive, definition.id, dispatch]);\n useEffect(() => {\n const seen = registered.current;\n return () => {\n for (const instanceId of seen) {\n const key = toInstanceKey(definition.id, instanceId);\n keepAlive.release(key);\n releaseOverlayInstance(dispatch, key);\n }\n seen.clear();\n };\n }, [keepAlive, definition.id, dispatch]);\n\n if (open.length === 0 && retained.size === 0) return null;\n\n const nodes: ReactNode[] = [];\n for (const instance of open) {\n const node = (\n <InstanceSlot key={instance.instanceId} definition={definition} instanceId={instance.instanceId} data={asRawData(instance.data)} hidden={false} />\n );\n nodes.push(\n keepHidden ? (\n <Activity key={instance.instanceId} mode=\"visible\">\n {node}\n </Activity>\n ) : (\n node\n ),\n );\n }\n if (keepHidden) {\n for (const [instanceId, data] of retained) {\n nodes.push(\n <Activity key={instanceId} mode=\"hidden\">\n <InstanceSlot key={instanceId} definition={definition} instanceId={instanceId} data={data} hidden />\n </Activity>,\n );\n }\n }\n return <>{nodes}</>;\n});\n\nexport function SummonHost({ definitions, renders }: SummonHostProps) {\n // Register before any slot renders: links, the close middleware and defaults read the registry.\n const registeredFor = useRef<readonly HostableOverlay[] | null>(null);\n if (registeredFor.current !== definitions) {\n registerOverlayMeta(definitions.map((definition) => definition.meta));\n registeredFor.current = definitions;\n }\n useCloseOnNavigation();\n return (\n <HostRendersContext.Provider value={renders ?? null}>\n {definitions.map((definition) => (\n <DefinitionSlot key={definition.id} definition={definition} />\n ))}\n </HostRendersContext.Provider>\n );\n}\n","// The host-side render map. A definition may omit `render`; the host then resolves the overlay's\n// render module from `<SummonHost renders={…}>`. This keeps import() edges out of every file\n// that imports a definition only to open it: in a large app, ~450 opener importers each gaining\n// an edge to a window subtree multiplied the build graph (the host-build law). One generated map\n// imported by the host alone keeps every import() behind the host's own lazy boundary.\n\nimport { createContext, type JSXElementConstructor } from \"react\";\nimport type { OverlayRenderProps } from \"./instanceBody\";\nimport type { RenderLoader } from \"./loaderCache\";\n\n/**\n * One overlay's loader with its data type erased. `never` data accepts every render component\n * typed `OverlayRenderProps<Data>`, so a map of differently typed render modules type-checks\n * without `any` (JSXElementConstructor, not ComponentType: `defaultProps` would make a class\n * component's props covariant and refuse the erasure).\n */\nexport type ErasedRenderLoader = () => Promise<{ readonly default: JSXElementConstructor<OverlayRenderProps<never>> }>;\n\n/** id → lazy render module, for definitions declared without `render`. */\nexport type OverlayRenderMap = Readonly<Record<string, ErasedRenderLoader>>;\n\nexport const HostRendersContext = createContext<OverlayRenderMap | null>(null);\n\n/** The name of the error an overlay with no render source raises into its error card. */\nexport const MISSING_RENDER_ERROR = \"OverlayRenderMissingError\";\n\nconst missing = new Map<string, () => Promise<never>>();\n\n/**\n * A loader for an overlay that is open but has no render module anywhere (no `render` on the\n * definition and no entry in the host's `renders`). It rejects, so the instance shows the error\n * card; in development it also logs once. Never a silent blank.\n */\nexport function missingRenderLoader<P>(overlayId: string): RenderLoader<P> {\n let loader = missing.get(overlayId);\n if (!loader) {\n const message = `Overlay \"${overlayId}\" is open but has no render module: its definition has no \\`render\\` and <SummonHost renders> has no \"${overlayId}\" entry.`;\n loader = () => {\n if (process.env.NODE_ENV !== \"production\") console.error(`[summon] ${message}`);\n const error = new Error(message);\n error.name = MISSING_RENDER_ERROR;\n return Promise.reject(error);\n };\n missing.set(overlayId, loader);\n }\n return loader;\n}\n","// One open instance, rendered: instance context → host wrapper → error boundary → Suspense →\n// the lazily loaded render module with its typed props. Created per definition (inside\n// `defineOverlay`) so the parsed-data type stays inside the closure and the host deals only in\n// untyped instances — no casts at the host.\n\nimport { Suspense, memo, useContext, useEffect, useMemo, useRef, type ComponentType, type ReactNode } from \"react\";\nimport type { InstanceKey, OverlayRawData } from \"@ai-matrx/summon\";\nimport type { OverlayRenderContext } from \"./context\";\nimport { OverlayErrorBoundary } from \"./OverlayErrorBoundary\";\nimport { OverlayInstanceContext, type OverlayInstanceContextValue } from \"./instance\";\nimport { HostRendersContext, missingRenderLoader } from \"./hostRenders\";\nimport type { RenderLoader } from \"./loaderCache\";\nimport { useSummonConfig, useSummonPorts } from \"./storeHooks\";\n\n/** The props every overlay's render module receives. */\nexport interface OverlayRenderProps<Data = OverlayRawData> {\n readonly overlayId: string;\n readonly instanceId: string;\n /** The open data: raw (narrow it yourself) unless the definition declares `parse`. */\n readonly data: Data;\n readonly isOpen: true;\n readonly close: () => void;\n /** True while kept alive behind a close (`keepAlive: \"hidden\"`). */\n readonly hidden: boolean;\n}\n\n/** What the host hands each instance — no data type, by design. */\nexport interface InstanceBodyProps {\n readonly instanceId: string;\n readonly instanceKey: InstanceKey;\n readonly data: OverlayRawData;\n readonly hidden: boolean;\n readonly close: () => void;\n}\n\ninterface LazyRenderProps<Parsed> {\n readonly overlayId: string;\n readonly instanceId: string;\n readonly data: Parsed;\n readonly hidden: boolean;\n readonly close: () => void;\n readonly render: RenderLoader<OverlayRenderProps<Parsed>>;\n readonly attemptRef: { current: number };\n}\n\nfunction LazyRender<Parsed>({ overlayId, instanceId, data, hidden, close, render, attemptRef }: LazyRenderProps<Parsed>) {\n const { loaders } = useSummonConfig();\n const entry = loaders.get(overlayId, render);\n attemptRef.current = entry.attempt;\n const Render = entry.Component;\n return <Render overlayId={overlayId} instanceId={instanceId} data={data} isOpen close={close} hidden={hidden} />;\n}\n\nexport function createInstanceBody<Parsed>(\n overlayId: string,\n label: string,\n /** The definition's own loader; when absent the host's `renders` map supplies it. */\n ownRender: RenderLoader<OverlayRenderProps<Parsed>> | undefined,\n parse: (raw: OverlayRawData) => Parsed | null,\n /** False when the definition has no `parse`: a null result is then just empty data. */\n refusable: boolean,\n): ComponentType<InstanceBodyProps> {\n function OverlayInstanceBody({ instanceId, instanceKey, data, hidden, close }: InstanceBodyProps) {\n const config = useSummonConfig();\n const ports = useSummonPorts();\n const hostRenders = useContext(HostRendersContext);\n const hostRender = ownRender ? undefined : hostRenders?.[overlayId];\n // The host map is erased (it holds every overlay's loader); the entry under this id was\n // generated from this definition's own render file, so narrowing it to Parsed is sound.\n const render: RenderLoader<OverlayRenderProps<Parsed>> =\n ownRender ?? (hostRender as RenderLoader<OverlayRenderProps<Parsed>> | undefined) ?? missingRenderLoader(overlayId);\n const attemptRef = useRef(0);\n const parsed = useMemo(() => parse(data), [data]);\n const refused = refusable && parsed === null;\n\n useEffect(() => {\n if (!refused) return;\n if (process.env.NODE_ENV !== \"production\") {\n ports.notify.warn(`Overlay \"${overlayId}\" was opened with data its parse() refused; closing it.`, {\n id: `overlays-parse-${instanceKey}`,\n });\n }\n close();\n }, [refused, ports, instanceKey, close]);\n\n const instance = useMemo<OverlayInstanceContextValue>(\n () => ({ overlayId, instanceId, instanceKey, close, hidden, rawData: data }),\n [instanceId, instanceKey, close, hidden, data],\n );\n\n if (refused) return null;\n\n const context: OverlayRenderContext = { overlayId, instanceId, instanceKey, label };\n const body: ReactNode = (\n <OverlayErrorBoundary\n overlayId={overlayId}\n instanceId={instanceId}\n instanceKey={instanceKey}\n label={label}\n errors={ports.errors}\n fallback={config.errorFallback}\n extras={config.errorReportExtras}\n onRetry={() => config.loaders.retry(overlayId, render, attemptRef.current)}\n onClose={close}\n >\n <Suspense fallback={<config.loadingFallback overlayId={overlayId} label={label} />}>\n <LazyRender\n overlayId={overlayId}\n instanceId={instanceId}\n data={parsed as Parsed}\n hidden={hidden}\n close={close}\n render={render}\n attemptRef={attemptRef}\n />\n </Suspense>\n </OverlayErrorBoundary>\n );\n\n return (\n <OverlayInstanceContext.Provider value={instance}>\n {config.renderWrapper ? config.renderWrapper(body, context) : body}\n </OverlayInstanceContext.Provider>\n );\n }\n OverlayInstanceBody.displayName = `Overlay(${overlayId})`;\n // Memoized: props are the instance's own (ids, data reference, hidden, a stable close).\n return memo(OverlayInstanceBody);\n}\n","// A per-instance error boundary. React.lazy + Suspense give a loading state but no error state,\n// so a rejected import (or a render throw) would otherwise unmount the whole host. Outcomes are\n// exactly: the overlay, its loading fallback, or a meaningful error with Close and Try again.\n\nimport { Component, type ComponentType, type ErrorInfo, type ReactNode } from \"react\";\nimport type { ErrorSinkPort } from \"@ai-matrx/summon\";\nimport type { OverlayErrorExtrasContext, OverlayErrorFallbackProps } from \"./context\";\nimport { normalizeOverlayError } from \"./fallbacks\";\n\nexport interface OverlayErrorBoundaryProps {\n readonly overlayId: string;\n readonly instanceId: string;\n readonly instanceKey: string;\n readonly label: string;\n readonly errors: ErrorSinkPort;\n readonly fallback: ComponentType<OverlayErrorFallbackProps>;\n readonly extras: ((context: OverlayErrorExtrasContext) => ReactNode) | null;\n /** Swap in a fresh loader BEFORE the boundary clears, so the remount re-imports. */\n readonly onRetry: () => void;\n readonly onClose: () => void;\n readonly children: ReactNode;\n}\n\ninterface OverlayErrorBoundaryState {\n readonly error: unknown;\n readonly hasError: boolean;\n readonly componentStack: string | null;\n}\n\nconst CLEAR: OverlayErrorBoundaryState = { error: null, hasError: false, componentStack: null };\n\nexport class OverlayErrorBoundary extends Component<OverlayErrorBoundaryProps, OverlayErrorBoundaryState> {\n override state: OverlayErrorBoundaryState = CLEAR;\n\n static getDerivedStateFromError(error: unknown): Partial<OverlayErrorBoundaryState> {\n return { error, hasError: true };\n }\n\n override componentDidCatch(error: unknown, info: ErrorInfo): void {\n const componentStack = info.componentStack ?? null;\n this.setState({ componentStack });\n const e = normalizeOverlayError(error);\n // Loud recovery: a caught overlay error is a real bug or a broken chunk graph.\n this.props.errors.capture(error, {\n boundary: \"OverlayErrorBoundary\",\n overlayId: this.props.overlayId,\n instanceId: this.props.instanceId,\n errorName: e.name,\n isChunkLoadError: e.isChunkLoadError,\n componentStack,\n });\n }\n\n private readonly retry = (): void => {\n this.props.onRetry();\n this.setState(CLEAR);\n };\n\n override render(): ReactNode {\n const { hasError, error, componentStack } = this.state;\n if (!hasError) return this.props.children;\n const { overlayId, instanceId, instanceKey, label, extras, onClose } = this.props;\n const Fallback = this.props.fallback;\n const renderedExtras = extras ? extras({ overlayId, instanceId, instanceKey, label, error, componentStack }) : null;\n return (\n <Fallback\n overlayId={overlayId}\n instanceId={instanceId}\n label={label}\n error={error}\n componentStack={componentStack}\n retry={this.retry}\n close={onClose}\n extras={renderedExtras}\n />\n );\n }\n}\n","// The context every rendered overlay instance provides to its subtree, and the hooks that read\n// it: who am I, close me, am I hidden, and `useOverlayState` — saved component state scoped to\n// the open instance that survives `keepAlive: \"restore\"` (and persistence, when on).\n\nimport { useCallback } from \"react\";\nimport { selectOverlayStateValue, setOverlayStateValue } from \"@ai-matrx/summon\";\nimport { useOverlayInstance } from \"@ai-matrx/summon/root\";\nimport { useSummonDispatch, useSummonSelector, useSummonStore } from \"./storeHooks\";\n\nexport {\n OverlayInstanceContext,\n useOverlayInstance,\n useOptionalOverlayInstance,\n type OverlayInstanceContextValue,\n} from \"@ai-matrx/summon/root\";\n\nexport type OverlayStateSetter<T> = (next: T | ((previous: T) => T)) => void;\n\n/**\n * Saved state for the current overlay instance — `useState`, but kept in the overlays store under\n * `overlayId:instanceId` so it survives `keepAlive: \"restore\"` close/reopen and is persisted when\n * persistence is on. Any descendant of the overlay may call it; the same `name` reads the same\n * value. Values must be serialisable.\n */\nexport function useOverlayState<T>(name: string, initial: T): [T, OverlayStateSetter<T>] {\n const { instanceKey } = useOverlayInstance();\n const dispatch = useSummonDispatch();\n const store = useSummonStore();\n const stored = useSummonSelector((state) => selectOverlayStateValue(state, instanceKey, name));\n const value = stored === undefined ? initial : (stored as T);\n const setValue = useCallback<OverlayStateSetter<T>>(\n (next) => {\n const current = selectOverlayStateValue(store.getState(), instanceKey, name);\n const previous = current === undefined ? initial : (current as T);\n const resolved = typeof next === \"function\" ? (next as (previous: T) => T)(previous) : next;\n dispatch(setOverlayStateValue({ key: instanceKey, name, value: resolved }));\n },\n // `initial` is the first-render default, like useState's; its identity never re-binds.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [dispatch, store, instanceKey, name],\n );\n return [value, setValue];\n}\n","// Id-addressed hooks — the escape hatch when a caller has an overlay id rather than its\n// definition. Typed through the host's `OverlayRegistry` augmentation.\n\nimport { useCallback } from \"react\";\nimport { getOverlayMeta } from \"@ai-matrx/summon\";\nimport { selectIsOverlayOpen } from \"@ai-matrx/summon\";\nimport { DEFAULT_INSTANCE_ID, type OverlayDataOf, type OverlayId } from \"@ai-matrx/summon\";\nimport { dispatchClose, dispatchOpen, newInstanceId, type OverlayHandle } from \"@ai-matrx/summon/root\";\nimport { useSummonDispatch, useSummonSelector } from \"./storeHooks\";\n\n/** True while the instance is open. */\nexport function useIsOverlayOpen(overlayId: OverlayId, instanceId: string = DEFAULT_INSTANCE_ID): boolean {\n return useSummonSelector((state) => selectIsOverlayOpen(state, overlayId, instanceId));\n}\n\nexport interface OpenOverlayOptions<Id extends OverlayId> {\n readonly data?: OverlayDataOf<Id>;\n readonly instanceId?: string;\n}\n\n/**\n * Open an overlay by id. A multi-instance overlay (per its registered definition) gets a fresh\n * instance id when none is given; a single-instance one opens \"default\".\n */\nexport function useOpenOverlay<Id extends OverlayId>(overlayId: Id): (options?: OpenOverlayOptions<Id>) => OverlayHandle {\n const dispatch = useSummonDispatch();\n return useCallback(\n (options?: OpenOverlayOptions<Id>) => {\n const multi = getOverlayMeta(overlayId)?.instance === \"multi\";\n const instanceId = options?.instanceId ?? (multi ? newInstanceId(overlayId) : DEFAULT_INSTANCE_ID);\n dispatchOpen(dispatch, overlayId, instanceId, options?.data ?? null);\n return { overlayId, instanceId, close: () => dispatchClose(dispatch, overlayId, instanceId) };\n },\n [dispatch, overlayId],\n );\n}\n\n/** A stable close function for one instance (pass straight to an `onClose` prop). */\nexport function useCloseOverlay(overlayId: OverlayId, instanceId: string = DEFAULT_INSTANCE_ID): () => void {\n const dispatch = useSummonDispatch();\n return useCallback(() => dispatchClose(dispatch, overlayId, instanceId), [dispatch, overlayId, instanceId]);\n}\n"],"mappings":"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","names":["import_react","import_summon","import_react","import_react","import_root","import_react","Component","import_root","import_jsx_runtime","import_root","import_react","import_summon","import_root","import_react","import_react","import_react","import_jsx_runtime","import_react","import_summon","import_root","import_root","import_jsx_runtime","import_jsx_runtime","InstanceSlot","toInstanceKey","DefinitionSlot","import_root","import_react","import_summon","import_root","import_root"]}
|
|
1
|
+
{"version":3,"sources":["../src/react.ts","../src/react/SummonProvider.tsx","../src/react/context.ts","../src/react/fallbacks.tsx","../src/react/storeHooks.ts","../src/react/keepAlive.ts","../src/react/loaderCache.ts","../src/react/events.ts","../src/react/SummonHost.tsx","../src/react/hostRenders.ts","../src/react/instanceBody.tsx","../src/react/OverlayErrorBoundary.tsx","../src/react/instance.tsx","../src/react/hooks.ts"],"sourcesContent":["// @ai-matrx/summon/react — the render layer: provider (own store context), declare-once\n// definitions, the host, the lazy loader with its boundary and fallbacks, and the hooks.\nexport { SummonProvider, DEFAULT_IMPORT_TIMEOUT_MS, DEFAULT_KEEP_ALIVE_LIMIT, DEFAULT_STALL_WARN_MS, type SummonProviderProps } from \"./react/SummonProvider\";\nexport {\n SummonStoreContext,\n type OverlayRenderContext,\n type OverlayLoadingFallbackProps,\n type OverlayErrorFallbackProps,\n type OverlayErrorExtrasContext,\n} from \"./react/context\";\nexport {\n useSummonSelector,\n useSummonDispatch,\n useSummonStore,\n useSummonPorts,\n useOptionalSummonPorts,\n useOptionalSummonStore,\n type SummonReactDispatch,\n type SummonReactStore,\n} from \"./react/storeHooks\";\nexport {\n defineOverlay,\n CALLBACK_GROUP_KEY,\n type OverlayDefinition,\n type OverlaySpec,\n type HostableOverlay,\n type OverlayHandle,\n type OverlayOpener,\n type OverlayOpenOptions,\n type OverlayControllerProps,\n type OverlayEmitter,\n} from \"@ai-matrx/summon/define\";\nexport type { OverlayRenderProps } from \"./react/instanceBody\";\nexport { emitOverlayEvent, type OverlayEventMap, type OverlayHandlers } from \"./react/events\";\nexport type { RenderModule, RenderLoader } from \"./react/loaderCache\";\nexport { SummonHost, useCloseOnNavigation, type SummonHostProps } from \"./react/SummonHost\";\nexport { MISSING_RENDER_ERROR, type ErasedRenderLoader, type OverlayRenderMap } from \"./react/hostRenders\";\nexport { SummonRoot, type SummonRootProps, configureSummonHost, type SummonHostConfig } from \"@ai-matrx/summon/root\";\nexport {\n useOverlayInstance,\n useOptionalOverlayInstance,\n useOverlayState,\n type OverlayInstanceContextValue,\n type OverlayStateSetter,\n} from \"./react/instance\";\nexport { useIsOverlayOpen, useOpenOverlay, useCloseOverlay, type OpenOverlayOptions } from \"./react/hooks\";\n// Also on `./url`; lives here so a render module can publish its link without loading the link section.\nexport { useOverlayLink } from \"@ai-matrx/summon/root\";\nexport { OverlayErrorBoundary, type OverlayErrorBoundaryProps } from \"./react/OverlayErrorBoundary\";\nexport { OverlayErrorFallback, OverlayLoadingFallback, normalizeOverlayError, type NormalizedOverlayError } from \"./react/fallbacks\";\nexport { chunkTimeoutError } from \"./react/loaderCache\";\n","// `<SummonProvider>` — mounts the overlays store on the package's own context (the host's store\n// when passed — AI Matrx mounts `summonReducers` into its one store — else a private store made\n// once), the resolved ports, and the render-layer knobs (fallbacks, error extras, wrapper,\n// keep-alive cap, import timeout).\n\nimport { useEffect, useMemo, useRef, useState, type ComponentType, type ReactNode } from \"react\";\nimport { Provider } from \"react-redux\";\nimport type { Store } from \"@reduxjs/toolkit\";\nimport { resolvePorts, type SummonPorts } from \"@ai-matrx/summon\";\nimport { createSummonStore } from \"@ai-matrx/summon\";\nimport {\n SummonConfigContext,\n SummonPortsContext,\n SummonStoreContext,\n type OverlayErrorExtrasContext,\n type OverlayErrorFallbackProps,\n type OverlayLoadingFallbackProps,\n type OverlayRenderContext,\n type SummonReactConfig,\n} from \"./context\";\nimport { OverlayErrorFallback, OverlayLoadingFallback } from \"./fallbacks\";\nimport { KeepAliveRegistry } from \"./keepAlive\";\nimport { LoaderCache } from \"./loaderCache\";\n\nimport { DEFAULT_IMPORT_TIMEOUT_MS, DEFAULT_KEEP_ALIVE_LIMIT, DEFAULT_STALL_WARN_MS } from \"./storeHooks\";\nexport { DEFAULT_IMPORT_TIMEOUT_MS, DEFAULT_KEEP_ALIVE_LIMIT, DEFAULT_STALL_WARN_MS };\n\nexport interface SummonProviderProps {\n /** The host's Redux store with `summonReducers` mounted at their root keys. Omit for a private store. */\n readonly store?: Store<unknown>;\n /** Host ports; anything omitted uses the working default. */\n readonly ports?: Partial<SummonPorts>;\n readonly fallbacks?: {\n readonly loading?: ComponentType<OverlayLoadingFallbackProps>;\n readonly error?: ComponentType<OverlayErrorFallbackProps>;\n };\n /** Extra controls in the default error card's footer (AI Matrx: \"Copy for AI\"). */\n readonly errorReportExtras?: (context: OverlayErrorExtrasContext) => ReactNode;\n /** Wrap every rendered overlay (AI Matrx: its surface layer boundary). */\n readonly renderWrapper?: (node: ReactNode, context: OverlayRenderContext) => ReactNode;\n /** Most closed-but-alive (`keepAlive: \"hidden\"`) instances kept mounted. Default 8. */\n readonly keepAliveLimit?: number;\n /** A render-module import that has not settled by then becomes a ChunkLoadError. Default 12 s. */\n readonly importTimeoutMs?: number;\n /** When the loading fallback reports a stall to the error port. Default 10 s. */\n readonly stallWarnMs?: number;\n readonly children?: ReactNode;\n}\n\nexport function SummonProvider({\n store,\n ports,\n fallbacks,\n errorReportExtras,\n renderWrapper,\n keepAliveLimit = DEFAULT_KEEP_ALIVE_LIMIT,\n importTimeoutMs = DEFAULT_IMPORT_TIMEOUT_MS,\n stallWarnMs = DEFAULT_STALL_WARN_MS,\n children,\n}: SummonProviderProps) {\n const resolvedPorts = useMemo(() => resolvePorts(ports), [ports]);\n const [privateStore] = useState(() => (store ? null : createSummonStore({ ports: resolvedPorts })));\n const activeStore: Store<unknown> = store ?? (privateStore as Store<unknown>);\n\n const timeoutRef = useRef(importTimeoutMs);\n timeoutRef.current = importTimeoutMs;\n const [keepAlive] = useState(() => new KeepAliveRegistry(keepAliveLimit));\n const [loaders] = useState(() => new LoaderCache({ timeoutMs: () => timeoutRef.current }));\n useEffect(() => keepAlive.setLimit(keepAliveLimit), [keepAlive, keepAliveLimit]);\n\n const loading = fallbacks?.loading ?? OverlayLoadingFallback;\n const error = fallbacks?.error ?? OverlayErrorFallback;\n const config = useMemo<SummonReactConfig>(\n () => ({\n loadingFallback: loading,\n errorFallback: error,\n errorReportExtras: errorReportExtras ?? null,\n renderWrapper: renderWrapper ?? null,\n importTimeoutMs,\n stallWarnMs,\n keepAlive,\n loaders,\n }),\n [loading, error, errorReportExtras, renderWrapper, importTimeoutMs, stallWarnMs, keepAlive, loaders],\n );\n\n return (\n <Provider store={activeStore} context={SummonStoreContext}>\n <SummonPortsContext.Provider value={resolvedPorts}>\n <SummonConfigContext.Provider value={config}>{children}</SummonConfigContext.Provider>\n </SummonPortsContext.Provider>\n </Provider>\n );\n}\n","// The React section's own contexts. The overlays store rides its OWN react-redux context\n// (chat-package pattern), so a private overlays store never collides with a host's store and a\n// host that mounts `summonReducers` into its one store simply passes it in.\n\nimport { createContext, type ComponentType, type ReactNode } from \"react\";\nimport type { KeepAliveRegistry } from \"./keepAlive\";\nimport type { LoaderCache } from \"./loaderCache\";\nimport type { OverlayRenderContext, OverlayErrorExtrasContext } from \"@ai-matrx/summon/root\";\n\n// One identity: the store and ports contexts live in the light root section.\nexport { SummonStoreContext, SummonPortsContext } from \"@ai-matrx/summon/root\";\nexport type { OverlayRenderContext, OverlayErrorExtrasContext };\n\nexport interface OverlayLoadingFallbackProps {\n readonly overlayId: string;\n readonly label: string;\n}\n\nexport interface OverlayErrorFallbackProps {\n readonly overlayId: string;\n readonly instanceId: string;\n readonly label: string;\n readonly error: unknown;\n readonly componentStack: string | null;\n /** Re-import the render module and mount again. */\n readonly retry: () => void;\n /** Close this instance (no reload). */\n readonly close: () => void;\n /** Host-provided extras (AI Matrx: \"Copy for AI\"), already rendered for this error. */\n readonly extras: ReactNode;\n}\n\nexport interface SummonReactConfig {\n readonly loadingFallback: ComponentType<OverlayLoadingFallbackProps>;\n readonly errorFallback: ComponentType<OverlayErrorFallbackProps>;\n readonly errorReportExtras: ((context: OverlayErrorExtrasContext) => ReactNode) | null;\n readonly renderWrapper: ((node: ReactNode, context: OverlayRenderContext) => ReactNode) | null;\n readonly importTimeoutMs: number;\n readonly stallWarnMs: number;\n readonly keepAlive: KeepAliveRegistry;\n readonly loaders: LoaderCache;\n}\n\nexport const SummonConfigContext = createContext<SummonReactConfig | null>(null);\nSummonConfigContext.displayName = \"SummonConfigContext\";\n","// The default loading and error fallbacks every overlay renders through. A host replaces either\n// with `<SummonProvider fallbacks>`; AI Matrx adds its \"Copy for AI\" through `errorReportExtras`.\n// Design-system components and tokens only — no app imports.\n\nimport { useEffect } from \"react\";\nimport { Button } from \"@ai-matrx/design-system\";\nimport type { OverlayErrorFallbackProps, OverlayLoadingFallbackProps } from \"./context\";\nimport { useSummonConfig, useSummonPorts } from \"./storeHooks\";\n\nexport interface NormalizedOverlayError {\n readonly name: string;\n readonly message: string;\n readonly stack: string | null;\n readonly isChunkLoadError: boolean;\n}\n\nexport function normalizeOverlayError(error: unknown): NormalizedOverlayError {\n if (error instanceof Error) {\n const isChunkLoadError =\n error.name === \"ChunkLoadError\" ||\n /Loading chunk [\\w-]+ failed|Failed to fetch dynamically imported module|Importing a module script failed/i.test(\n error.message,\n );\n return { name: error.name, message: error.message, stack: error.stack ?? null, isChunkLoadError };\n }\n return { name: \"Error\", message: typeof error === \"string\" ? error : String(error), stack: null, isChunkLoadError: false };\n}\n\n/**\n * Spinner while the render module is in flight. Never blank. At the stall threshold it reports\n * once through the error port; the loader's import timeout (later) turns a hung import into a\n * real error so the error fallback takes over.\n */\nexport function OverlayLoadingFallback({ overlayId, label }: OverlayLoadingFallbackProps) {\n const ports = useSummonPorts();\n const { stallWarnMs } = useSummonConfig();\n useEffect(() => {\n const timer = setTimeout(() => {\n ports.errors.capture(new Error(`Overlay \"${overlayId}\" still loading after ${stallWarnMs}ms`), {\n stage: \"overlay-load-stall\",\n overlayId,\n level: \"warning\",\n });\n }, stallWarnMs);\n return () => clearTimeout(timer);\n }, [ports, overlayId, stallWarnMs]);\n\n return (\n <div className=\"pointer-events-none fixed inset-0 z-[2147483000] flex items-center justify-center p-4\">\n <div\n role=\"status\"\n aria-label={`Loading ${label}`}\n className=\"pointer-events-auto flex items-center gap-3 rounded-xl border border-border bg-card px-5 py-4 text-sm text-muted-foreground shadow-md\"\n >\n <span aria-hidden className=\"size-4 animate-spin rounded-full border-2 border-border border-t-primary\" />\n <span>Loading…</span>\n </div>\n </div>\n );\n}\n\n/** The error card: what failed, and a way out that never needs a page reload. */\nexport function OverlayErrorFallback({ label, error, retry, close, extras }: OverlayErrorFallbackProps) {\n const e = normalizeOverlayError(error);\n return (\n <div className=\"pointer-events-none fixed inset-0 z-[2147483001] flex items-center justify-center p-4\">\n <div\n role=\"alertdialog\"\n aria-label={`${label} failed to load`}\n className=\"pointer-events-auto flex max-h-[85dvh] w-full max-w-lg flex-col overflow-hidden rounded-xl border border-destructive bg-card shadow-lg\"\n >\n <div className=\"border-b border-border px-5 py-4\">\n <h2 className=\"text-sm font-semibold text-foreground\">{label} failed to load</h2>\n <p className=\"mt-1 text-xs text-muted-foreground\">\n {e.isChunkLoadError ? \"Part of it did not finish loading.\" : \"It hit an error while rendering.\"}\n </p>\n </div>\n <div className=\"min-h-0 flex-1 overflow-auto px-5 py-4\">\n <div className=\"rounded-lg bg-muted px-3 py-2 font-mono text-xs text-foreground\">\n <span className=\"text-destructive\">{e.name}</span>: {e.message}\n </div>\n </div>\n <div className=\"flex items-center justify-between gap-2 border-t border-border px-5 py-3\">\n <div>{extras}</div>\n <div className=\"flex items-center gap-2\">\n <Button variant=\"ghost\" size=\"sm\" onClick={close}>\n Close\n </Button>\n <Button variant=\"primary\" size=\"sm\" onClick={retry}>\n Try again\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n onClick={() => {\n if (typeof window !== \"undefined\") window.location.reload();\n }}\n >\n Reload page\n </Button>\n </div>\n </div>\n </div>\n </div>\n );\n}\n","// The store hooks live in the light root section (one context identity); the render-layer config\n// hook stays here: the nearest SummonProvider's config, else one built from the root's settings.\nimport { useContext } from \"react\";\nimport { getSummonHostConfig, getSummonHostVersion } from \"@ai-matrx/summon/root\";\nimport { globalSlot } from \"@ai-matrx/kit/global-slot\";\nimport { SummonConfigContext, type SummonReactConfig } from \"./context\";\nimport { OverlayErrorFallback, OverlayLoadingFallback } from \"./fallbacks\";\nimport { KeepAliveRegistry } from \"./keepAlive\";\nimport { LoaderCache } from \"./loaderCache\";\n\nexport {\n useSummonSelector,\n useSummonDispatch,\n useSummonStore,\n useSummonPorts,\n useOptionalSummonPorts,\n useOptionalSummonStore,\n type SummonReactDispatch,\n type SummonReactStore,\n} from \"@ai-matrx/summon/root\";\n\nexport const DEFAULT_KEEP_ALIVE_LIMIT = 8;\nexport const DEFAULT_IMPORT_TIMEOUT_MS = 12_000;\nexport const DEFAULT_STALL_WARN_MS = 10_000;\n\ninterface HostConfigSlot {\n version: number;\n config: SummonReactConfig | null;\n keepAlive: KeepAliveRegistry | null;\n loaders: LoaderCache | null;\n}\n\nconst hostConfigSlot = (): HostConfigSlot =>\n globalSlot<HostConfigSlot>(\"ai-matrx.summon.hostReactConfig\", () => ({ version: -1, config: null, keepAlive: null, loaders: null }));\n\n/** The render config when no SummonProvider is above: the root's settings, one keep-alive and loader cache per page. */\nexport function hostReactConfig(): SummonReactConfig {\n const s = hostConfigSlot();\n const version = getSummonHostVersion();\n if (s.config && s.version === version) return s.config;\n const host = getSummonHostConfig();\n s.keepAlive ??= new KeepAliveRegistry(DEFAULT_KEEP_ALIVE_LIMIT);\n s.loaders ??= new LoaderCache({ timeoutMs: () => DEFAULT_IMPORT_TIMEOUT_MS });\n s.config = {\n loadingFallback: OverlayLoadingFallback,\n errorFallback: OverlayErrorFallback,\n errorReportExtras: host.errorReportExtras ?? null,\n renderWrapper: host.renderWrapper ?? null,\n importTimeoutMs: DEFAULT_IMPORT_TIMEOUT_MS,\n stallWarnMs: DEFAULT_STALL_WARN_MS,\n keepAlive: s.keepAlive,\n loaders: s.loaders,\n };\n s.version = version;\n return s.config;\n}\n\nexport function useSummonConfig(): SummonReactConfig {\n return useContext(SummonConfigContext) ?? hostReactConfig();\n}\n","// The provider's LRU of closed-but-alive instances (`keepAlive: \"hidden\"`, C38 R3). Each slot\n// retains its own hidden instances; this registry only keeps the global order and tells the\n// owning slot when one falls off the end, so at most `limit` hidden components stay mounted.\n\nexport class KeepAliveRegistry {\n private readonly order: string[] = [];\n private readonly evictors = new Map<string, () => void>();\n\n private limit: number;\n\n constructor(limit: number) {\n this.limit = limit;\n }\n\n setLimit(limit: number): void {\n this.limit = Math.max(0, Math.floor(limit));\n this.trim();\n }\n\n /** Mark `key` as hidden-alive (most recent). `evict` unmounts it when the cap is exceeded. */\n retain(key: string, evict: () => void): void {\n this.drop(key);\n this.order.push(key);\n this.evictors.set(key, evict);\n this.trim();\n }\n\n /** `key` reopened or its slot went away: no longer counted. */\n release(key: string): void {\n this.drop(key);\n }\n\n size(): number {\n return this.order.length;\n }\n\n private drop(key: string): void {\n const at = this.order.indexOf(key);\n if (at >= 0) this.order.splice(at, 1);\n this.evictors.delete(key);\n }\n\n private trim(): void {\n while (this.order.length > this.limit) {\n const oldest = this.order.shift();\n if (oldest === undefined) return;\n const evict = this.evictors.get(oldest);\n this.evictors.delete(oldest);\n evict?.();\n }\n }\n}\n","// Per-provider cache of each definition's lazily loaded render component. Lives in the provider\n// (React state), never at module level. A definition's render module is fetched the first time\n// one of its instances mounts — never before — and a retry swaps in a FRESH lazy so the import is\n// genuinely attempted again (a React.lazy caches its first rejection forever).\n\nimport { lazy, type ComponentType, type LazyExoticComponent } from \"react\";\n\nexport interface RenderModule<P> {\n readonly default: ComponentType<P>;\n}\n\nexport type RenderLoader<P> = () => Promise<RenderModule<P>>;\n\nexport interface LoaderEntry<P> {\n readonly attempt: number;\n readonly Component: LazyExoticComponent<ComponentType<P>>;\n}\n\nexport interface LoaderCacheOptions {\n readonly timeoutMs: () => number;\n readonly onImportStart?: (key: string, attempt: number) => void;\n}\n\n/** The error a stalled import becomes, so the error boundary always fires. */\nexport function chunkTimeoutError(key: string, timeoutMs: number): Error {\n const error = new Error(\n `Overlay \"${key}\" render module did not load within ${timeoutMs}ms. The import() did not resolve before the recovery timeout.`,\n );\n error.name = \"ChunkLoadError\";\n return error;\n}\n\nfunction raceTimeout<T>(key: string, real: Promise<T>, timeoutMs: number): Promise<T> {\n // A late rejection after the timeout won must not surface as unhandled.\n real.catch(() => undefined);\n let timer: ReturnType<typeof setTimeout> | undefined;\n const timeout = new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(chunkTimeoutError(key, timeoutMs)), timeoutMs);\n });\n return Promise.race([real, timeout]).finally(() => {\n if (timer !== undefined) clearTimeout(timer);\n });\n}\n\nexport class LoaderCache {\n private readonly entries = new Map<string, LoaderEntry<unknown>>();\n\n private readonly options: LoaderCacheOptions;\n\n constructor(options: LoaderCacheOptions) {\n this.options = options;\n }\n\n private create<P>(key: string, loader: RenderLoader<P>, attempt: number): LoaderEntry<P> {\n const Component = lazy(() => {\n this.options.onImportStart?.(key, attempt);\n return raceTimeout(key, loader(), this.options.timeoutMs());\n });\n return { attempt, Component };\n }\n\n /** The current lazy component for `key`, created on first request. */\n get<P>(key: string, loader: RenderLoader<P>): LoaderEntry<P> {\n const existing = this.entries.get(key);\n // Sound by construction: an entry under `key` is only ever created from that key's loader.\n if (existing) return existing as LoaderEntry<P>;\n const created = this.create(key, loader, 0);\n this.entries.set(key, created as LoaderEntry<unknown>);\n return created;\n }\n\n /** Replace `key`'s lazy with a fresh one so the next render re-imports. */\n retry<P>(key: string, loader: RenderLoader<P>, failedAttempt: number): void {\n const existing = this.entries.get(key);\n // Another instance already retried past the failed attempt: share its fresh lazy.\n if (existing && existing.attempt > failedAttempt) return;\n const next = this.create(key, loader, failedAttempt + 1);\n this.entries.set(key, next as LoaderEntry<unknown>);\n }\n}\n","// Overlay events on the render side. Opening (the channel id that rides open data) is light and\n// lives in the root section; here, with the handles registry loaded, an emit first creates any\n// channel still pending and then delivers synchronously. Registered on evaluation so a\n// definition's `useEmit` (light) emits synchronously inside the render tree.\n\nimport { createEventChannel, getEventChannel } from \"@ai-matrx/summon/handles\";\nimport { materializePendingChannels, type OverlayEventMessage } from \"@ai-matrx/summon/open\";\nimport { registerOverlayEmitter } from \"@ai-matrx/summon/root\";\n\nexport type { OverlayEventMap, OverlayHandlers } from \"@ai-matrx/summon/root\";\nexport type { OverlayEventMessage };\n\n/** Deliver one event on a channel; a disposed or unknown channel is a silent no-op by contract. */\nexport function emitOverlayEvent(channelId: string, type: string, payload: unknown): void {\n materializePendingChannels(createEventChannel);\n getEventChannel<OverlayEventMessage>(channelId)?.emit({ type, payload });\n}\n\nregisterOverlayEmitter(emitOverlayEvent);\n","// `<SummonHost definitions>` — registers each definition's metadata and renders every definition\n// through its OWN subscriber (`DefinitionSlot`), so opening overlay A never re-renders B (the old\n// controller held ~440 subscriptions in one component). A closed overlay puts nothing in the tree\n// and fetches no chunk. `keepAlive: \"hidden\"` keeps closed instances mounted inside\n// `<Activity mode=\"hidden\">`, LRU-capped per provider.\n\nimport { Activity, memo, useCallback, useEffect, useRef, useState, type ComponentType, type ReactNode } from \"react\";\nimport { releaseOverlayInstance } from \"@ai-matrx/summon\";\nimport { registerOverlayMeta } from \"@ai-matrx/summon\";\nimport { closeOverlaysBoundToPage, overlayIdsBoundToPage, selectOpenInstances, type OpenInstanceView } from \"@ai-matrx/summon\";\nimport { instanceKey as toInstanceKey, type OverlayRawData } from \"@ai-matrx/summon\";\nimport { dispatchClose, type HostableOverlay } from \"@ai-matrx/summon/root\";\nimport { HostRendersContext, type OverlayRenderMap } from \"./hostRenders\";\nimport { createInstanceBody, type InstanceBodyProps, type OverlayRenderProps } from \"./instanceBody\";\nimport type { RenderLoader } from \"./loaderCache\";\nimport { useSummonConfig, useSummonDispatch, useSummonPorts, useSummonSelector } from \"./storeHooks\";\n\nexport interface SummonHostProps {\n /** Every overlay this host can render — the app's definition list, passed once. */\n readonly definitions: readonly HostableOverlay[];\n /**\n * id → `() => import(\"./<id>.render\")` for definitions declared without `render`. Large apps\n * use it so opener importers never reach a window subtree; a definition's own `render` wins.\n */\n readonly renders?: OverlayRenderMap;\n}\n\nfunction asRawData(data: unknown): OverlayRawData {\n return typeof data === \"object\" && data !== null && !Array.isArray(data) ? (data as OverlayRawData) : null;\n}\n\n/** Equal when the same instances are open with the same data references. */\nfunction sameInstances(a: readonly OpenInstanceView[], b: readonly OpenInstanceView[]): boolean {\n if (a === b) return true;\n if (a.length !== b.length) return false;\n for (let i = 0; i < a.length; i += 1) {\n const x = a[i];\n const y = b[i];\n if (!x || !y || x.instanceId !== y.instanceId || x.data !== y.data) return false;\n }\n return true;\n}\n\n// A definition is light (it carries no render code); the host builds each one's instance body on\n// first render and keeps it for the definition's lifetime.\nconst bodies = new WeakMap<HostableOverlay, ComponentType<InstanceBodyProps>>();\nfunction bodyOf(definition: HostableOverlay): ComponentType<InstanceBodyProps> {\n let body = bodies.get(definition);\n if (!body) {\n const parse = definition.parse ?? ((raw: OverlayRawData) => raw);\n // The definition's loader returns its own render module; erased here like the host map's entries.\n const render = definition.render as RenderLoader<OverlayRenderProps<unknown>> | undefined;\n body = createInstanceBody<unknown>(definition.id, definition.label, render, parse, definition.parse !== undefined);\n bodies.set(definition, body);\n }\n return body;\n}\n\nconst NO_RETAINED: ReadonlyMap<string, OverlayRawData> = new Map();\n\n/** Close-on-navigation: on a pathname change, close every overlay bound to the page. */\nexport function useCloseOnNavigation(): void {\n const ports = useSummonPorts();\n const dispatch = useSummonDispatch();\n useEffect(() => {\n const router = ports.router;\n let previous = router.pathname();\n return router.subscribe(() => {\n const next = router.pathname();\n if (next === previous) return;\n previous = next;\n const overlayIds = overlayIdsBoundToPage();\n if (overlayIds.length > 0) dispatch(closeOverlaysBoundToPage({ overlayIds }));\n });\n }, [ports, dispatch]);\n}\n\ninterface InstanceSlotProps {\n readonly definition: HostableOverlay;\n readonly instanceId: string;\n readonly data: OverlayRawData;\n readonly hidden: boolean;\n}\n\n// Memoized: a slot re-renders only when its own instance changes, never because the host did.\nconst InstanceSlot = memo(function InstanceSlot({ definition, instanceId, data, hidden }: InstanceSlotProps) {\n const dispatch = useSummonDispatch();\n const close = useCallback(() => dispatchClose(dispatch, definition.id, instanceId), [dispatch, definition.id, instanceId]);\n const Body = bodyOf(definition);\n return <Body instanceId={instanceId} instanceKey={toInstanceKey(definition.id, instanceId)} data={data} hidden={hidden} close={close} />;\n});\n\n// Memoized on the definition: the slot re-renders from its own store subscription (one overlay's\n// open instances) and nothing else. Unmemoized, every re-render of the host's parent re-rendered\n// every open overlay's render module (the ~425-renders-in-2-s storm the runtime sweep measured).\nconst DefinitionSlot = memo(function DefinitionSlot({ definition }: { readonly definition: HostableOverlay }) {\n const { keepAlive } = useSummonConfig();\n const dispatch = useSummonDispatch();\n const open = useSummonSelector((state) => selectOpenInstances(state, definition.id), sameInstances);\n const keepHidden = definition.keepAlive === \"hidden\";\n\n // Closed-but-alive instances, derived during render (no unmount/remount flash on close).\n const [retained, setRetained] = useState(NO_RETAINED);\n const [previousOpen, setPreviousOpen] = useState(open);\n if (previousOpen !== open) {\n setPreviousOpen(open);\n if (keepHidden) {\n const openIds = new Set(open.map((instance) => instance.instanceId));\n const next = new Map(retained);\n for (const instance of previousOpen) {\n if (!openIds.has(instance.instanceId)) next.set(instance.instanceId, asRawData(instance.data));\n }\n for (const id of openIds) next.delete(id);\n setRetained(next);\n }\n }\n\n // Mirror the retained set into the provider LRU; eviction unmounts here.\n const registered = useRef(new Set<string>());\n useEffect(() => {\n const seen = registered.current;\n for (const instanceId of retained.keys()) {\n if (seen.has(instanceId)) continue;\n seen.add(instanceId);\n const key = toInstanceKey(definition.id, instanceId);\n keepAlive.retain(key, () => {\n seen.delete(instanceId);\n // Evicted: its handles and saved state go now, as a plain close would have done.\n releaseOverlayInstance(dispatch, key);\n setRetained((current) => {\n if (!current.has(instanceId)) return current;\n const next = new Map(current);\n next.delete(instanceId);\n return next;\n });\n });\n }\n for (const instanceId of [...seen]) {\n if (retained.has(instanceId)) continue;\n seen.delete(instanceId);\n keepAlive.release(toInstanceKey(definition.id, instanceId));\n }\n }, [retained, keepAlive, definition.id, dispatch]);\n useEffect(() => {\n const seen = registered.current;\n return () => {\n for (const instanceId of seen) {\n const key = toInstanceKey(definition.id, instanceId);\n keepAlive.release(key);\n releaseOverlayInstance(dispatch, key);\n }\n seen.clear();\n };\n }, [keepAlive, definition.id, dispatch]);\n\n if (open.length === 0 && retained.size === 0) return null;\n\n const nodes: ReactNode[] = [];\n for (const instance of open) {\n const node = (\n <InstanceSlot key={instance.instanceId} definition={definition} instanceId={instance.instanceId} data={asRawData(instance.data)} hidden={false} />\n );\n nodes.push(\n keepHidden ? (\n <Activity key={instance.instanceId} mode=\"visible\">\n {node}\n </Activity>\n ) : (\n node\n ),\n );\n }\n if (keepHidden) {\n for (const [instanceId, data] of retained) {\n nodes.push(\n <Activity key={instanceId} mode=\"hidden\">\n <InstanceSlot key={instanceId} definition={definition} instanceId={instanceId} data={data} hidden />\n </Activity>,\n );\n }\n }\n return <>{nodes}</>;\n});\n\nexport function SummonHost({ definitions, renders }: SummonHostProps) {\n // Register before any slot renders: links, the close middleware and defaults read the registry.\n const registeredFor = useRef<readonly HostableOverlay[] | null>(null);\n if (registeredFor.current !== definitions) {\n registerOverlayMeta(definitions.map((definition) => definition.meta));\n registeredFor.current = definitions;\n }\n useCloseOnNavigation();\n return (\n <HostRendersContext.Provider value={renders ?? null}>\n {definitions.map((definition) => (\n <DefinitionSlot key={definition.id} definition={definition} />\n ))}\n </HostRendersContext.Provider>\n );\n}\n","// The host-side render map. A definition may omit `render`; the host then resolves the overlay's\n// render module from `<SummonHost renders={…}>`. This keeps import() edges out of every file\n// that imports a definition only to open it: in a large app, ~450 opener importers each gaining\n// an edge to a window subtree multiplied the build graph (the host-build law). One generated map\n// imported by the host alone keeps every import() behind the host's own lazy boundary.\n\nimport { createContext, type JSXElementConstructor } from \"react\";\nimport type { OverlayRenderProps } from \"./instanceBody\";\nimport type { RenderLoader } from \"./loaderCache\";\n\n/**\n * One overlay's loader with its data type erased. `never` data accepts every render component\n * typed `OverlayRenderProps<Data>`, so a map of differently typed render modules type-checks\n * without `any` (JSXElementConstructor, not ComponentType: `defaultProps` would make a class\n * component's props covariant and refuse the erasure).\n */\nexport type ErasedRenderLoader = () => Promise<{ readonly default: JSXElementConstructor<OverlayRenderProps<never>> }>;\n\n/** id → lazy render module, for definitions declared without `render`. */\nexport type OverlayRenderMap = Readonly<Record<string, ErasedRenderLoader>>;\n\nexport const HostRendersContext = createContext<OverlayRenderMap | null>(null);\n\n/** The name of the error an overlay with no render source raises into its error card. */\nexport const MISSING_RENDER_ERROR = \"OverlayRenderMissingError\";\n\nconst missing = new Map<string, () => Promise<never>>();\n\n/**\n * A loader for an overlay that is open but has no render module anywhere (no `render` on the\n * definition and no entry in the host's `renders`). It rejects, so the instance shows the error\n * card; in development it also logs once. Never a silent blank.\n */\nexport function missingRenderLoader<P>(overlayId: string): RenderLoader<P> {\n let loader = missing.get(overlayId);\n if (!loader) {\n const message = `Overlay \"${overlayId}\" is open but has no render module: its definition has no \\`render\\` and <SummonHost renders> has no \"${overlayId}\" entry.`;\n loader = () => {\n if (process.env.NODE_ENV !== \"production\") console.error(`[summon] ${message}`);\n const error = new Error(message);\n error.name = MISSING_RENDER_ERROR;\n return Promise.reject(error);\n };\n missing.set(overlayId, loader);\n }\n return loader;\n}\n","// One open instance, rendered: instance context → host wrapper → error boundary → Suspense →\n// the lazily loaded render module with its typed props. Created per definition (inside\n// `defineOverlay`) so the parsed-data type stays inside the closure and the host deals only in\n// untyped instances — no casts at the host.\n\nimport { Suspense, memo, useContext, useEffect, useMemo, useRef, type ComponentType, type ReactNode } from \"react\";\nimport type { InstanceKey, OverlayRawData } from \"@ai-matrx/summon\";\nimport type { OverlayRenderContext } from \"./context\";\nimport { OverlayErrorBoundary } from \"./OverlayErrorBoundary\";\nimport { OverlayInstanceContext, type OverlayInstanceContextValue } from \"./instance\";\nimport { HostRendersContext, missingRenderLoader } from \"./hostRenders\";\nimport type { RenderLoader } from \"./loaderCache\";\nimport { useSummonConfig, useSummonPorts } from \"./storeHooks\";\n\n/** The props every overlay's render module receives. */\nexport interface OverlayRenderProps<Data = OverlayRawData> {\n readonly overlayId: string;\n readonly instanceId: string;\n /** The open data: raw (narrow it yourself) unless the definition declares `parse`. */\n readonly data: Data;\n readonly isOpen: true;\n readonly close: () => void;\n /** True while kept alive behind a close (`keepAlive: \"hidden\"`). */\n readonly hidden: boolean;\n}\n\n/** What the host hands each instance — no data type, by design. */\nexport interface InstanceBodyProps {\n readonly instanceId: string;\n readonly instanceKey: InstanceKey;\n readonly data: OverlayRawData;\n readonly hidden: boolean;\n readonly close: () => void;\n}\n\ninterface LazyRenderProps<Parsed> {\n readonly overlayId: string;\n readonly instanceId: string;\n readonly data: Parsed;\n readonly hidden: boolean;\n readonly close: () => void;\n readonly render: RenderLoader<OverlayRenderProps<Parsed>>;\n readonly attemptRef: { current: number };\n}\n\nfunction LazyRender<Parsed>({ overlayId, instanceId, data, hidden, close, render, attemptRef }: LazyRenderProps<Parsed>) {\n const { loaders } = useSummonConfig();\n const entry = loaders.get(overlayId, render);\n attemptRef.current = entry.attempt;\n const Render = entry.Component;\n return <Render overlayId={overlayId} instanceId={instanceId} data={data} isOpen close={close} hidden={hidden} />;\n}\n\nexport function createInstanceBody<Parsed>(\n overlayId: string,\n label: string,\n /** The definition's own loader; when absent the host's `renders` map supplies it. */\n ownRender: RenderLoader<OverlayRenderProps<Parsed>> | undefined,\n parse: (raw: OverlayRawData) => Parsed | null,\n /** False when the definition has no `parse`: a null result is then just empty data. */\n refusable: boolean,\n): ComponentType<InstanceBodyProps> {\n function OverlayInstanceBody({ instanceId, instanceKey, data, hidden, close }: InstanceBodyProps) {\n const config = useSummonConfig();\n const ports = useSummonPorts();\n const hostRenders = useContext(HostRendersContext);\n const hostRender = ownRender ? undefined : hostRenders?.[overlayId];\n // The host map is erased (it holds every overlay's loader); the entry under this id was\n // generated from this definition's own render file, so narrowing it to Parsed is sound.\n const render: RenderLoader<OverlayRenderProps<Parsed>> =\n ownRender ?? (hostRender as RenderLoader<OverlayRenderProps<Parsed>> | undefined) ?? missingRenderLoader(overlayId);\n const attemptRef = useRef(0);\n const parsed = useMemo(() => parse(data), [data]);\n const refused = refusable && parsed === null;\n\n useEffect(() => {\n if (!refused) return;\n if (process.env.NODE_ENV !== \"production\") {\n ports.notify.warn(`Overlay \"${overlayId}\" was opened with data its parse() refused; closing it.`, {\n id: `overlays-parse-${instanceKey}`,\n });\n }\n close();\n }, [refused, ports, instanceKey, close]);\n\n const instance = useMemo<OverlayInstanceContextValue>(\n () => ({ overlayId, instanceId, instanceKey, close, hidden, rawData: data }),\n [instanceId, instanceKey, close, hidden, data],\n );\n\n if (refused) return null;\n\n const context: OverlayRenderContext = { overlayId, instanceId, instanceKey, label };\n const body: ReactNode = (\n <OverlayErrorBoundary\n overlayId={overlayId}\n instanceId={instanceId}\n instanceKey={instanceKey}\n label={label}\n errors={ports.errors}\n fallback={config.errorFallback}\n extras={config.errorReportExtras}\n onRetry={() => config.loaders.retry(overlayId, render, attemptRef.current)}\n onClose={close}\n >\n <Suspense fallback={<config.loadingFallback overlayId={overlayId} label={label} />}>\n <LazyRender\n overlayId={overlayId}\n instanceId={instanceId}\n data={parsed as Parsed}\n hidden={hidden}\n close={close}\n render={render}\n attemptRef={attemptRef}\n />\n </Suspense>\n </OverlayErrorBoundary>\n );\n\n return (\n <OverlayInstanceContext.Provider value={instance}>\n {config.renderWrapper ? config.renderWrapper(body, context) : body}\n </OverlayInstanceContext.Provider>\n );\n }\n OverlayInstanceBody.displayName = `Overlay(${overlayId})`;\n // Memoized: props are the instance's own (ids, data reference, hidden, a stable close).\n return memo(OverlayInstanceBody);\n}\n","// A per-instance error boundary. React.lazy + Suspense give a loading state but no error state,\n// so a rejected import (or a render throw) would otherwise unmount the whole host. Outcomes are\n// exactly: the overlay, its loading fallback, or a meaningful error with Close and Try again.\n\nimport { Component, type ComponentType, type ErrorInfo, type ReactNode } from \"react\";\nimport type { ErrorSinkPort } from \"@ai-matrx/summon\";\nimport type { OverlayErrorExtrasContext, OverlayErrorFallbackProps } from \"./context\";\nimport { normalizeOverlayError } from \"./fallbacks\";\n\nexport interface OverlayErrorBoundaryProps {\n readonly overlayId: string;\n readonly instanceId: string;\n readonly instanceKey: string;\n readonly label: string;\n readonly errors: ErrorSinkPort;\n readonly fallback: ComponentType<OverlayErrorFallbackProps>;\n readonly extras: ((context: OverlayErrorExtrasContext) => ReactNode) | null;\n /** Swap in a fresh loader BEFORE the boundary clears, so the remount re-imports. */\n readonly onRetry: () => void;\n readonly onClose: () => void;\n readonly children: ReactNode;\n}\n\ninterface OverlayErrorBoundaryState {\n readonly error: unknown;\n readonly hasError: boolean;\n readonly componentStack: string | null;\n}\n\nconst CLEAR: OverlayErrorBoundaryState = { error: null, hasError: false, componentStack: null };\n\nexport class OverlayErrorBoundary extends Component<OverlayErrorBoundaryProps, OverlayErrorBoundaryState> {\n override state: OverlayErrorBoundaryState = CLEAR;\n\n static getDerivedStateFromError(error: unknown): Partial<OverlayErrorBoundaryState> {\n return { error, hasError: true };\n }\n\n override componentDidCatch(error: unknown, info: ErrorInfo): void {\n const componentStack = info.componentStack ?? null;\n this.setState({ componentStack });\n const e = normalizeOverlayError(error);\n // Loud recovery: a caught overlay error is a real bug or a broken chunk graph.\n this.props.errors.capture(error, {\n boundary: \"OverlayErrorBoundary\",\n overlayId: this.props.overlayId,\n instanceId: this.props.instanceId,\n errorName: e.name,\n isChunkLoadError: e.isChunkLoadError,\n componentStack,\n });\n }\n\n private readonly retry = (): void => {\n this.props.onRetry();\n this.setState(CLEAR);\n };\n\n override render(): ReactNode {\n const { hasError, error, componentStack } = this.state;\n if (!hasError) return this.props.children;\n const { overlayId, instanceId, instanceKey, label, extras, onClose } = this.props;\n const Fallback = this.props.fallback;\n const renderedExtras = extras ? extras({ overlayId, instanceId, instanceKey, label, error, componentStack }) : null;\n return (\n <Fallback\n overlayId={overlayId}\n instanceId={instanceId}\n label={label}\n error={error}\n componentStack={componentStack}\n retry={this.retry}\n close={onClose}\n extras={renderedExtras}\n />\n );\n }\n}\n","// The context every rendered overlay instance provides to its subtree, and the hooks that read\n// it: who am I, close me, am I hidden, and `useOverlayState` — saved component state scoped to\n// the open instance that survives `keepAlive: \"restore\"` (and persistence, when on).\n\nimport { useCallback } from \"react\";\nimport { selectOverlayStateValue, setOverlayStateValue } from \"@ai-matrx/summon\";\nimport { useOverlayInstance } from \"@ai-matrx/summon/root\";\nimport { useSummonDispatch, useSummonSelector, useSummonStore } from \"./storeHooks\";\n\nexport {\n OverlayInstanceContext,\n useOverlayInstance,\n useOptionalOverlayInstance,\n type OverlayInstanceContextValue,\n} from \"@ai-matrx/summon/root\";\n\nexport type OverlayStateSetter<T> = (next: T | ((previous: T) => T)) => void;\n\n/**\n * Saved state for the current overlay instance — `useState`, but kept in the overlays store under\n * `overlayId:instanceId` so it survives `keepAlive: \"restore\"` close/reopen and is persisted when\n * persistence is on. Any descendant of the overlay may call it; the same `name` reads the same\n * value. Values must be serialisable.\n */\nexport function useOverlayState<T>(name: string, initial: T): [T, OverlayStateSetter<T>] {\n const { instanceKey } = useOverlayInstance();\n const dispatch = useSummonDispatch();\n const store = useSummonStore();\n const stored = useSummonSelector((state) => selectOverlayStateValue(state, instanceKey, name));\n const value = stored === undefined ? initial : (stored as T);\n const setValue = useCallback<OverlayStateSetter<T>>(\n (next) => {\n const current = selectOverlayStateValue(store.getState(), instanceKey, name);\n const previous = current === undefined ? initial : (current as T);\n const resolved = typeof next === \"function\" ? (next as (previous: T) => T)(previous) : next;\n dispatch(setOverlayStateValue({ key: instanceKey, name, value: resolved }));\n },\n // `initial` is the first-render default, like useState's; its identity never re-binds.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [dispatch, store, instanceKey, name],\n );\n return [value, setValue];\n}\n","// Id-addressed hooks — the escape hatch when a caller has an overlay id rather than its\n// definition. Typed through the host's `OverlayRegistry` augmentation.\n\nimport { useCallback } from \"react\";\nimport { getOverlayMeta } from \"@ai-matrx/summon\";\nimport { selectIsOverlayOpen } from \"@ai-matrx/summon\";\nimport { DEFAULT_INSTANCE_ID, type OverlayDataOf, type OverlayId } from \"@ai-matrx/summon\";\nimport { dispatchClose, dispatchOpen, newInstanceId, type OverlayHandle } from \"@ai-matrx/summon/root\";\nimport { useSummonDispatch, useSummonSelector } from \"./storeHooks\";\n\n/** True while the instance is open. */\nexport function useIsOverlayOpen(overlayId: OverlayId, instanceId: string = DEFAULT_INSTANCE_ID): boolean {\n return useSummonSelector((state) => selectIsOverlayOpen(state, overlayId, instanceId));\n}\n\nexport interface OpenOverlayOptions<Id extends OverlayId> {\n readonly data?: OverlayDataOf<Id>;\n readonly instanceId?: string;\n}\n\n/**\n * Open an overlay by id. A multi-instance overlay (per its registered definition) gets a fresh\n * instance id when none is given; a single-instance one opens \"default\".\n */\nexport function useOpenOverlay<Id extends OverlayId>(overlayId: Id): (options?: OpenOverlayOptions<Id>) => OverlayHandle {\n const dispatch = useSummonDispatch();\n return useCallback(\n (options?: OpenOverlayOptions<Id>) => {\n const multi = getOverlayMeta(overlayId)?.instance === \"multi\";\n const instanceId = options?.instanceId ?? (multi ? newInstanceId(overlayId) : DEFAULT_INSTANCE_ID);\n dispatchOpen(dispatch, overlayId, instanceId, options?.data ?? null);\n return { overlayId, instanceId, close: () => dispatchClose(dispatch, overlayId, instanceId) };\n },\n [dispatch, overlayId],\n );\n}\n\n/** A stable close function for one instance (pass straight to an `onClose` prop). */\nexport function useCloseOverlay(overlayId: OverlayId, instanceId: string = DEFAULT_INSTANCE_ID): () => void {\n const dispatch = useSummonDispatch();\n return useCallback(() => dispatchClose(dispatch, overlayId, instanceId), [dispatch, overlayId, instanceId]);\n}\n"],"mappings":"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","names":["import_react","import_summon","import_react","import_react","import_root","import_react","Component","import_root","import_jsx_runtime","import_root","import_react","import_summon","import_root","import_react","import_react","import_react","import_jsx_runtime","import_react","import_summon","import_root","import_root","import_jsx_runtime","import_jsx_runtime","InstanceSlot","toInstanceKey","DefinitionSlot","import_root","import_react","import_summon","import_root","import_root"]}
|
package/dist/react.js
CHANGED
|
@@ -178,7 +178,7 @@ function OverlayLoadingFallback({ overlayId, label }) {
|
|
|
178
178
|
{
|
|
179
179
|
role: "status",
|
|
180
180
|
"aria-label": `Loading ${label}`,
|
|
181
|
-
className: "pointer-events-auto flex items-center gap-3 rounded-xl border border-border bg-card px-5 py-4 text-sm text-muted-foreground shadow-
|
|
181
|
+
className: "pointer-events-auto flex items-center gap-3 rounded-xl border border-border bg-card px-5 py-4 text-sm text-muted-foreground shadow-md",
|
|
182
182
|
children: [
|
|
183
183
|
/* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "size-4 animate-spin rounded-full border-2 border-border border-t-primary" }),
|
|
184
184
|
/* @__PURE__ */ jsx("span", { children: "Loading\u2026" })
|
|
@@ -193,7 +193,7 @@ function OverlayErrorFallback({ label, error, retry, close, extras }) {
|
|
|
193
193
|
{
|
|
194
194
|
role: "alertdialog",
|
|
195
195
|
"aria-label": `${label} failed to load`,
|
|
196
|
-
className: "pointer-events-auto flex max-h-[85dvh] w-full max-w-lg flex-col overflow-hidden rounded-xl border border-destructive bg-card shadow-
|
|
196
|
+
className: "pointer-events-auto flex max-h-[85dvh] w-full max-w-lg flex-col overflow-hidden rounded-xl border border-destructive bg-card shadow-lg",
|
|
197
197
|
children: [
|
|
198
198
|
/* @__PURE__ */ jsxs("div", { className: "border-b border-border px-5 py-4", children: [
|
|
199
199
|
/* @__PURE__ */ jsxs("h2", { className: "text-sm font-semibold text-foreground", children: [
|