@ai-matrx/summon 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/react.cjs CHANGED
@@ -40,6 +40,7 @@ __export(react_exports, {
40
40
  useOpenOverlay: () => useOpenOverlay,
41
41
  useOptionalOverlayInstance: () => useOptionalOverlayInstance,
42
42
  useOptionalSummonPorts: () => useOptionalSummonPorts,
43
+ useOptionalSummonStore: () => useOptionalSummonStore,
43
44
  useOverlayInstance: () => useOverlayInstance,
44
45
  useOverlayState: () => useOverlayState,
45
46
  useSummonDispatch: () => useSummonDispatch,
@@ -84,6 +85,10 @@ function useSummonPorts() {
84
85
  function useOptionalSummonPorts() {
85
86
  return (0, import_react2.useContext)(SummonPortsContext) ?? import_summon.DEFAULT_PORTS;
86
87
  }
88
+ function useOptionalSummonStore() {
89
+ const context = (0, import_react2.useContext)(SummonStoreContext);
90
+ return context ? context.store : null;
91
+ }
87
92
  function useSummonConfig() {
88
93
  const config = (0, import_react2.useContext)(SummonConfigContext);
89
94
  if (!config) throw new Error(MISSING_PROVIDER);
@@ -173,12 +178,12 @@ function OverlayErrorFallback({ label, error, retry, close, extras }) {
173
178
 
174
179
  // src/react/keepAlive.ts
175
180
  var KeepAliveRegistry = class {
181
+ order = [];
182
+ evictors = /* @__PURE__ */ new Map();
183
+ limit;
176
184
  constructor(limit) {
177
185
  this.limit = limit;
178
186
  }
179
- limit;
180
- order = [];
181
- evictors = /* @__PURE__ */ new Map();
182
187
  setLimit(limit) {
183
188
  this.limit = Math.max(0, Math.floor(limit));
184
189
  this.trim();
@@ -233,11 +238,11 @@ function raceTimeout(key, real, timeoutMs) {
233
238
  });
234
239
  }
235
240
  var LoaderCache = class {
241
+ entries = /* @__PURE__ */ new Map();
242
+ options;
236
243
  constructor(options) {
237
244
  this.options = options;
238
245
  }
239
- options;
240
- entries = /* @__PURE__ */ new Map();
241
246
  create(key, loader, attempt) {
242
247
  const Component2 = (0, import_react4.lazy)(() => {
243
248
  this.options.onImportStart?.(key, attempt);
@@ -488,7 +493,7 @@ function createInstanceBody(overlayId, label, render, parse, refusable) {
488
493
  return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(OverlayInstanceContext.Provider, { value: instance, children: config.renderWrapper ? config.renderWrapper(body, context) : body });
489
494
  }
490
495
  OverlayInstanceBody.displayName = `Overlay(${overlayId})`;
491
- return OverlayInstanceBody;
496
+ return (0, import_react8.memo)(OverlayInstanceBody);
492
497
  }
493
498
 
494
499
  // src/react/defineOverlay.tsx
@@ -619,13 +624,13 @@ function useCloseOnNavigation() {
619
624
  });
620
625
  }, [ports, dispatch]);
621
626
  }
622
- function InstanceSlot({ definition, instanceId, data, hidden }) {
627
+ var InstanceSlot = (0, import_react10.memo)(function InstanceSlot2({ definition, instanceId, data, hidden }) {
623
628
  const dispatch = useSummonDispatch();
624
629
  const close = (0, import_react10.useCallback)(() => dispatchClose(dispatch, definition.id, instanceId), [dispatch, definition.id, instanceId]);
625
630
  const Body = definition.Body;
626
631
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(Body, { instanceId, instanceKey: (0, import_summon12.instanceKey)(definition.id, instanceId), data, hidden, close });
627
- }
628
- function DefinitionSlot({ definition }) {
632
+ });
633
+ var DefinitionSlot = (0, import_react10.memo)(function DefinitionSlot2({ definition }) {
629
634
  const { keepAlive } = useSummonConfig();
630
635
  const dispatch = useSummonDispatch();
631
636
  const open = useSummonSelector((state) => (0, import_summon11.selectOpenInstances)(state, definition.id), sameInstances);
@@ -695,7 +700,7 @@ function DefinitionSlot({ definition }) {
695
700
  }
696
701
  }
697
702
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_jsx_runtime5.Fragment, { children: nodes });
698
- }
703
+ });
699
704
  function SummonHost({ definitions }) {
700
705
  const registeredFor = (0, import_react10.useRef)(null);
701
706
  if (registeredFor.current !== definitions) {
@@ -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/defineOverlay.tsx","../src/react/dispatchers.ts","../src/react/events.ts","../src/react/instanceBody.tsx","../src/react/OverlayErrorBoundary.tsx","../src/react/instance.tsx","../src/react/SummonHost.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 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 \"./react/defineOverlay\";\nexport type { OverlayRenderProps } from \"./react/instanceBody\";\nexport type { OverlayEventMap, OverlayHandlers } from \"./react/events\";\nexport type { RenderModule, RenderLoader } from \"./react/loaderCache\";\nexport { SummonHost, useCloseOnNavigation, type SummonHostProps } from \"./react/SummonHost\";\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\";\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\nexport const DEFAULT_KEEP_ALIVE_LIMIT = 8;\nexport const DEFAULT_IMPORT_TIMEOUT_MS = 12_000;\nexport const DEFAULT_STALL_WARN_MS = 10_000;\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 { ReactReduxContextValue } from \"react-redux\";\nimport type { SummonPorts } from \"@ai-matrx/summon\";\nimport type { KeepAliveRegistry } from \"./keepAlive\";\nimport type { LoaderCache } from \"./loaderCache\";\n\nexport const SummonStoreContext = createContext<ReactReduxContextValue | null>(null);\nSummonStoreContext.displayName = \"SummonStoreContext\";\n\nexport const SummonPortsContext = createContext<SummonPorts | null>(null);\nSummonPortsContext.displayName = \"SummonPortsContext\";\n\n/** What every slot hands to `renderWrapper`, error extras and the fallbacks. */\nexport interface OverlayRenderContext {\n readonly overlayId: string;\n readonly instanceId: string;\n readonly instanceKey: string;\n readonly label: string;\n}\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 OverlayErrorExtrasContext extends OverlayRenderContext {\n readonly error: unknown;\n readonly componentStack: string | null;\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","// Typed hooks over the package's own store context. Every package component reads the overlays\n// store through these, never react-redux's default context, so a host's own <Provider> and the\n// overlays store never collide.\n\nimport { useContext } from \"react\";\nimport {\n createDispatchHook,\n createSelectorHook,\n createStoreHook,\n type UseDispatch,\n type UseSelector,\n type UseStore,\n} from \"react-redux\";\nimport type { Dispatch, Store, UnknownAction } from \"@reduxjs/toolkit\";\nimport type { SummonRootState } from \"@ai-matrx/summon\";\nimport { DEFAULT_PORTS, type SummonPorts } from \"@ai-matrx/summon\";\nimport { SummonConfigContext, SummonPortsContext, SummonStoreContext, type SummonReactConfig } from \"./context\";\n\n/** Dispatch as the React section uses it: plain actions (thunks are the host's business). */\nexport type SummonReactDispatch = Dispatch<UnknownAction>;\n\n/** The store as the React section sees it: the overlays slices at their root keys (a host store has more). */\nexport type SummonReactStore = Store<SummonRootState>;\n\n/** Select from the overlays store. */\nexport const useSummonSelector: UseSelector<SummonRootState> = createSelectorHook(SummonStoreContext).withTypes<SummonRootState>();\n\n/** The overlays store's dispatch. */\nexport const useSummonDispatch: UseDispatch<SummonReactDispatch> = createDispatchHook(SummonStoreContext).withTypes<SummonReactDispatch>();\n\n/** The overlays store itself (for `getState()` inside callbacks). */\nexport const useSummonStore: UseStore<SummonReactStore> = createStoreHook(SummonStoreContext).withTypes<SummonReactStore>();\n\nconst MISSING_PROVIDER =\n \"[summon] No <SummonProvider> above this component. Wrap the app (or the part that opens overlays) in <SummonProvider>.\";\n\n/** The resolved ports of the nearest provider. */\nexport function useSummonPorts(): SummonPorts {\n const ports = useContext(SummonPortsContext);\n if (!ports) throw new Error(MISSING_PROVIDER);\n return ports;\n}\n\n/**\n * The provider's ports, or the working defaults when no SummonProvider is above — for\n * components that are usable page-local without the system (dialogs, sheets).\n */\nexport function useOptionalSummonPorts(): SummonPorts {\n return useContext(SummonPortsContext) ?? DEFAULT_PORTS;\n}\n\nexport function useSummonConfig(): SummonReactConfig {\n const config = useContext(SummonConfigContext);\n if (!config) throw new Error(MISSING_PROVIDER);\n return config;\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 constructor(private limit: number) {}\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 constructor(private readonly options: LoaderCacheOptions) {}\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","// `defineOverlay` — the declare-once API (C38 R2). One light definition per overlay carries its\n// metadata and a lazy `render` import; the definition generates the opener hook, the declarative\n// Controller, the open/close hooks and a typed event emitter. The host renders definitions; the\n// render module is the old controller block, moved verbatim, and is fetched only when opened.\n\nimport { useCallback, useEffect, useMemo, useRef, useState, type ComponentType } from \"react\";\nimport {\n DEFAULT_INSTANCE_ID,\n instanceKey as toInstanceKey,\n type InstanceKey,\n type OverlayDefinitionMeta,\n type OverlayRawData,\n type AnyOverlayMeta,\n} from \"@ai-matrx/summon\";\nimport { selectIsOverlayOpen } from \"@ai-matrx/summon\";\nimport { dispatchClose, dispatchOpen, newInstanceId } from \"./dispatchers\";\nimport { emitOverlayEvent, openOverlayEventChannel, type OverlayEventMap, type OverlayHandlers } from \"./events\";\nimport { createInstanceBody, type InstanceBodyProps, type OverlayRenderProps } from \"./instanceBody\";\nimport { useOptionalOverlayInstance } from \"./instance\";\nimport type { RenderModule } from \"./loaderCache\";\nimport { useSummonDispatch, useSummonSelector, type SummonReactDispatch } from \"./storeHooks\";\n\n/** The open-data key that carries an overlay's event channel id (the old callback-group key). */\nexport const CALLBACK_GROUP_KEY = \"callbackGroupId\";\n\nexport interface OverlayHandle {\n readonly overlayId: string;\n readonly instanceId: string;\n close(): void;\n}\n\nexport interface OverlayOpenOptions<Data, Events extends OverlayEventMap> {\n readonly data?: Data;\n /** Single-instance overlays ignore it unless given; multi-instance generate one when omitted. */\n readonly instanceId?: string;\n /** Plain functions; they reach the caller through an event channel owned by the instance. */\n readonly handlers?: OverlayHandlers<Events>;\n}\n\nexport type OverlayOpener<Data, Events extends OverlayEventMap> = (options?: OverlayOpenOptions<Data, Events>) => OverlayHandle;\n\nexport type OverlayControllerProps<Data, Events extends OverlayEventMap> = Data & {\n readonly instanceId?: string;\n readonly handlers?: OverlayHandlers<Events>;\n};\n\nexport type OverlayEmitter<Events extends OverlayEventMap> = <K extends keyof Events & string>(event: K, payload: Events[K]) => void;\n\n/** What a definition file passes to `defineOverlay<Data>()(…)`. */\nexport interface OverlaySpec<Id extends string, Data, Parsed> extends OverlayDefinitionMeta<Id, Data> {\n /** The lazily loaded render module. Its default export receives `OverlayRenderProps<Parsed>`. */\n readonly render: () => Promise<RenderModule<OverlayRenderProps<NoInfer<Parsed>>>>;\n /** Narrow raw open data once. `null` = refuse: the instance is closed with a warning. */\n readonly parse?: (raw: OverlayRawData) => Parsed | null;\n}\n\n/** The type-erased half the host renders; no data types cross this line. */\nexport interface HostableOverlay {\n readonly id: string;\n readonly label: string;\n readonly instance: \"single\" | \"multi\";\n readonly keepAlive: \"none\" | \"hidden\" | \"restore\";\n /** The metadata the core registry stores (links, window options, defaults…). */\n readonly meta: AnyOverlayMeta;\n readonly Body: ComponentType<InstanceBodyProps>;\n}\n\nexport interface OverlayDefinition<Id extends string, Data, Parsed, Events extends OverlayEventMap>\n extends Omit<OverlayDefinitionMeta<Id, Data>, \"id\" | \"instance\" | \"keepAlive\">,\n HostableOverlay {\n readonly id: Id;\n readonly render: () => Promise<RenderModule<OverlayRenderProps<Parsed>>>;\n /** Imperative opener: `const open = def.useSummon(); open({ data })` → handle. */\n useSummon(): OverlayOpener<Data, Events>;\n /** Declarative form: opens on mount, closes on unmount, re-opens when its data changes. */\n readonly Controller: (props: OverlayControllerProps<Data, Events>) => null;\n useIsOpen(instanceId?: string): boolean;\n /** `const close = def.useClose(); close(instanceId?)`. */\n useClose(): (instanceId?: string) => void;\n /** Inside the render tree: emit a declared event to the opener's handlers. */\n useEmit(): OverlayEmitter<Events>;\n}\n\nfunction openWith<Data, Events extends OverlayEventMap>(\n dispatch: SummonReactDispatch,\n id: string,\n multi: boolean,\n options: OverlayOpenOptions<Data, Events> | undefined,\n): OverlayHandle {\n const instanceId = options?.instanceId ?? (multi ? newInstanceId(id) : DEFAULT_INSTANCE_ID);\n const key = toInstanceKey(id, instanceId);\n const data: Record<string, unknown> = {};\n const given: unknown = options?.data;\n if (typeof given === \"object\" && given !== null) Object.assign(data, given);\n const handlers = options?.handlers;\n if (handlers) data[CALLBACK_GROUP_KEY] = openOverlayEventChannel<Events>(key, () => handlers);\n dispatchOpen(dispatch, id, instanceId, data);\n return { overlayId: id, instanceId, close: () => dispatchClose(dispatch, id, instanceId) };\n}\n\n/** Stable identity for the serialisable part of Controller props (functions never reopen). */\nfunction dataSignature(data: Readonly<Record<string, unknown>>): string {\n try {\n return JSON.stringify(data, (_key, value: unknown) => (typeof value === \"function\" ? undefined : value));\n } catch {\n return String(Date.now());\n }\n}\n\n/**\n * Declare an overlay once. Curried so `Data` (and `Events`) are named while the id and the\n * parsed-data type are inferred:\n *\n * export const notesWindow = defineOverlay<NotesWindowData>()({\n * id: \"notesWindow\", label: \"Notes\", render: () => import(\"./notesWindow.render\"),\n * });\n */\nexport function defineOverlay<Data extends object = Record<string, never>, Events extends OverlayEventMap = Record<never, never>>() {\n return function define<const Id extends string, Parsed = OverlayRawData>(\n spec: OverlaySpec<Id, Data, Parsed>,\n ): OverlayDefinition<Id, Data, Parsed, Events> {\n const id = spec.id;\n const multi = spec.instance === \"multi\";\n // Without `parse`, Parsed is OverlayRawData (NoInfer keeps the render module from widening it).\n const parse = spec.parse ?? ((raw: OverlayRawData) => raw as Parsed);\n const Body = createInstanceBody<Parsed>(id, spec.label, spec.render, parse, spec.parse !== undefined);\n // The registry stores every definition's metadata under one erased type (AnyOverlayMeta).\n const meta: AnyOverlayMeta = spec;\n\n function useSummon(): OverlayOpener<Data, Events> {\n const dispatch = useSummonDispatch();\n return useCallback((options) => openWith(dispatch, id, multi, options), [dispatch]);\n }\n\n function useIsOpen(instanceId: string = DEFAULT_INSTANCE_ID): boolean {\n return useSummonSelector((state) => selectIsOverlayOpen(state, id, instanceId));\n }\n\n function useClose(): (instanceId?: string) => void {\n const dispatch = useSummonDispatch();\n return useCallback((instanceId?: string) => dispatchClose(dispatch, id, instanceId ?? DEFAULT_INSTANCE_ID), [dispatch]);\n }\n\n function useEmit(): OverlayEmitter<Events> {\n const instance = useOptionalOverlayInstance();\n const channelId = instance?.overlayId === id ? instance.rawData?.[CALLBACK_GROUP_KEY] : undefined;\n return useCallback<OverlayEmitter<Events>>(\n (event, payload) => {\n if (typeof channelId === \"string\") emitOverlayEvent(channelId, event, payload);\n },\n [channelId],\n );\n }\n\n function Controller(props: OverlayControllerProps<Data, Events>): null {\n const dispatch = useSummonDispatch();\n const [ownInstanceId] = useState(() => (multi ? newInstanceId(id) : DEFAULT_INSTANCE_ID));\n const instanceId = props.instanceId ?? ownInstanceId;\n // Latest handlers, read at emit time: a new function identity never reopens the overlay.\n const handlersRef = useRef(props.handlers);\n handlersRef.current = props.handlers;\n const hasHandlers = props.handlers !== undefined;\n\n const data = useMemo(() => {\n const out: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(props)) {\n if (key !== \"instanceId\" && key !== \"handlers\") out[key] = value;\n }\n return out;\n }, [props]);\n const signature = dataSignature(data);\n const dataRef = useRef(data);\n dataRef.current = data;\n\n useEffect(() => {\n const key: InstanceKey = toInstanceKey(id, instanceId);\n const open: Record<string, unknown> = { ...dataRef.current };\n if (hasHandlers) open[CALLBACK_GROUP_KEY] = openOverlayEventChannel<Events>(key, () => handlersRef.current);\n dispatchOpen(dispatch, id, instanceId, open);\n return () => dispatchClose(dispatch, id, instanceId);\n }, [dispatch, instanceId, signature, hasHandlers]);\n\n return null;\n }\n Controller.displayName = `${id}Controller`;\n\n return {\n ...spec,\n id,\n label: spec.label,\n instance: multi ? \"multi\" : \"single\",\n keepAlive: spec.keepAlive ?? \"none\",\n meta,\n Body,\n useSummon,\n Controller,\n useIsOpen,\n useClose,\n useEmit,\n };\n };\n}\n","// The one place the React section turns an untyped (string) overlay id into the core's typed\n// action creators. Inside the package `OverlayId` is `string`; a host that augments the registry\n// narrows it to its ids, and these keep compiling there because definitions carry their own id.\n\nimport { closeOverlay, openOverlay } from \"@ai-matrx/summon\";\nimport { DEFAULT_INSTANCE_ID, type OverlayDataOf, type OverlayId } from \"@ai-matrx/summon\";\nimport type { SummonReactDispatch } from \"./storeHooks\";\n\nexport function newInstanceId(overlayId: string): string {\n return `${overlayId}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n}\n\nexport function dispatchOpen(dispatch: SummonReactDispatch, overlayId: string, instanceId: string, data: unknown): void {\n dispatch(\n openOverlay({\n overlayId: overlayId as OverlayId,\n instanceId,\n data: (data ?? null) as OverlayDataOf<OverlayId> | null,\n }),\n );\n}\n\nexport function dispatchClose(dispatch: SummonReactDispatch, overlayId: string, instanceId: string = DEFAULT_INSTANCE_ID): void {\n dispatch(closeOverlay({ overlayId: overlayId as OverlayId, instanceId }));\n}\n","// Callback-aware opening: callers pass plain handler functions; the opener puts them behind a\n// handles event channel owned by the instance (`overlayId:instanceId`) and only the channel's id\n// rides open data. Closing the instance disposes the channel (the core close middleware calls\n// `disposeOwner`), so no opener disposes by hand.\n\nimport { createEventChannel, getEventChannel } from \"@ai-matrx/summon/handles\";\nimport type { InstanceKey } from \"@ai-matrx/summon\";\n\n/** Event name → payload, declared once per overlay: `defineOverlay<Data, { uploaded: Result }>()`. */\nexport type OverlayEventMap = Record<string, unknown>;\n\nexport type OverlayHandlers<Events extends OverlayEventMap> = {\n readonly [K in keyof Events]?: (payload: Events[K]) => void;\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\n/** Open a channel owned by `owner` that forwards each event to the handler `getHandlers` returns now. */\nexport function openOverlayEventChannel<Events extends OverlayEventMap>(\n owner: InstanceKey,\n getHandlers: () => OverlayHandlers<Events> | undefined,\n): string {\n const channel = createEventChannel<OverlayEventMessage>({ owner });\n channel.subscribe((message) => {\n const handlers = getHandlers() as Readonly<Record<string, ((payload: unknown) => void) | undefined>> | undefined;\n handlers?.[message.type]?.(message.payload);\n });\n return channel.id;\n}\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 getEventChannel<OverlayEventMessage>(channelId)?.emit({ type, payload });\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, 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 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 render: RenderLoader<OverlayRenderProps<Parsed>>,\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 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 return 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 { createContext, useCallback, useContext } from \"react\";\nimport type { InstanceKey, OverlayRawData } from \"@ai-matrx/summon\";\nimport { selectOverlayStateValue, setOverlayStateValue } from \"@ai-matrx/summon\";\nimport { useSummonDispatch, useSummonSelector, useSummonStore } from \"./storeHooks\";\n\nexport interface OverlayInstanceContextValue {\n readonly overlayId: string;\n readonly instanceId: string;\n readonly instanceKey: InstanceKey;\n readonly close: () => void;\n readonly hidden: boolean;\n /** The open data as it arrived (pre-parse); event emitters read their channel id from it. */\n readonly rawData: OverlayRawData;\n}\n\nexport const OverlayInstanceContext = createContext<OverlayInstanceContextValue | null>(null);\nOverlayInstanceContext.displayName = \"OverlayInstanceContext\";\n\n/** The open instance this component renders inside. Throws outside an overlay. */\nexport function useOverlayInstance(): OverlayInstanceContextValue {\n const value = useContext(OverlayInstanceContext);\n if (!value) {\n throw new Error(\"[summon] useOverlayInstance() was called outside a rendered overlay.\");\n }\n return value;\n}\n\n/** Same as `useOverlayInstance`, but `null` outside an overlay. */\nexport function useOptionalOverlayInstance(): OverlayInstanceContextValue | null {\n return useContext(OverlayInstanceContext);\n}\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","// `<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, useCallback, useEffect, useRef, useState, 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 type { HostableOverlay } from \"./defineOverlay\";\nimport { dispatchClose } from \"./dispatchers\";\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\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\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\nfunction 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 = definition.Body;\n return <Body instanceId={instanceId} instanceKey={toInstanceKey(definition.id, instanceId)} data={data} hidden={hidden} close={close} />;\n}\n\nfunction 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 }: 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 <>\n {definitions.map((definition) => (\n <DefinitionSlot key={definition.id} definition={definition} />\n ))}\n </>\n );\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 type { OverlayHandle } from \"./defineOverlay\";\nimport { dispatchClose, dispatchOpen, newInstanceId } from \"./dispatchers\";\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_react_redux","import_summon","import_react","import_react","import_react","Component","import_jsx_runtime","import_react","import_summon","import_summon","import_react","import_react","import_jsx_runtime","import_react","import_summon","import_jsx_runtime","toInstanceKey","import_react","import_summon","import_jsx_runtime","toInstanceKey","import_react","import_summon"]}
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/defineOverlay.tsx","../src/react/dispatchers.ts","../src/react/events.ts","../src/react/instanceBody.tsx","../src/react/OverlayErrorBoundary.tsx","../src/react/instance.tsx","../src/react/SummonHost.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 \"./react/defineOverlay\";\nexport type { OverlayRenderProps } from \"./react/instanceBody\";\nexport type { OverlayEventMap, OverlayHandlers } from \"./react/events\";\nexport type { RenderModule, RenderLoader } from \"./react/loaderCache\";\nexport { SummonHost, useCloseOnNavigation, type SummonHostProps } from \"./react/SummonHost\";\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\";\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\nexport const DEFAULT_KEEP_ALIVE_LIMIT = 8;\nexport const DEFAULT_IMPORT_TIMEOUT_MS = 12_000;\nexport const DEFAULT_STALL_WARN_MS = 10_000;\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 { ReactReduxContextValue } from \"react-redux\";\nimport type { SummonPorts } from \"@ai-matrx/summon\";\nimport type { KeepAliveRegistry } from \"./keepAlive\";\nimport type { LoaderCache } from \"./loaderCache\";\n\nexport const SummonStoreContext = createContext<ReactReduxContextValue | null>(null);\nSummonStoreContext.displayName = \"SummonStoreContext\";\n\nexport const SummonPortsContext = createContext<SummonPorts | null>(null);\nSummonPortsContext.displayName = \"SummonPortsContext\";\n\n/** What every slot hands to `renderWrapper`, error extras and the fallbacks. */\nexport interface OverlayRenderContext {\n readonly overlayId: string;\n readonly instanceId: string;\n readonly instanceKey: string;\n readonly label: string;\n}\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 OverlayErrorExtrasContext extends OverlayRenderContext {\n readonly error: unknown;\n readonly componentStack: string | null;\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","// Typed hooks over the package's own store context. Every package component reads the overlays\n// store through these, never react-redux's default context, so a host's own <Provider> and the\n// overlays store never collide.\n\nimport { useContext } from \"react\";\nimport {\n createDispatchHook,\n createSelectorHook,\n createStoreHook,\n type UseDispatch,\n type UseSelector,\n type UseStore,\n} from \"react-redux\";\nimport type { Dispatch, Store, UnknownAction } from \"@reduxjs/toolkit\";\nimport type { SummonRootState } from \"@ai-matrx/summon\";\nimport { DEFAULT_PORTS, type SummonPorts } from \"@ai-matrx/summon\";\nimport { SummonConfigContext, SummonPortsContext, SummonStoreContext, type SummonReactConfig } from \"./context\";\n\n/** Dispatch as the React section uses it: plain actions (thunks are the host's business). */\nexport type SummonReactDispatch = Dispatch<UnknownAction>;\n\n/** The store as the React section sees it: the overlays slices at their root keys (a host store has more). */\nexport type SummonReactStore = Store<SummonRootState>;\n\n/** Select from the overlays store. */\nexport const useSummonSelector: UseSelector<SummonRootState> = createSelectorHook(SummonStoreContext).withTypes<SummonRootState>();\n\n/** The overlays store's dispatch. */\nexport const useSummonDispatch: UseDispatch<SummonReactDispatch> = createDispatchHook(SummonStoreContext).withTypes<SummonReactDispatch>();\n\n/** The overlays store itself (for `getState()` inside callbacks). */\nexport const useSummonStore: UseStore<SummonReactStore> = createStoreHook(SummonStoreContext).withTypes<SummonReactStore>();\n\nconst MISSING_PROVIDER =\n \"[summon] No <SummonProvider> above this component. Wrap the app (or the part that opens overlays) in <SummonProvider>.\";\n\n/** The resolved ports of the nearest provider. */\nexport function useSummonPorts(): SummonPorts {\n const ports = useContext(SummonPortsContext);\n if (!ports) throw new Error(MISSING_PROVIDER);\n return ports;\n}\n\n/**\n * The provider's ports, or the working defaults when no SummonProvider is above — for\n * components that are usable page-local without the system (dialogs, sheets).\n */\nexport function useOptionalSummonPorts(): SummonPorts {\n return useContext(SummonPortsContext) ?? DEFAULT_PORTS;\n}\n\n/**\n * The nearest provider's store, or `null` when no SummonProvider is above — for packages that\n * mount their own provider only when the host has none (chat's windows on a bare host).\n */\nexport function useOptionalSummonStore(): SummonReactStore | null {\n const context = useContext(SummonStoreContext);\n return context ? (context.store as unknown as SummonReactStore) : null;\n}\n\nexport function useSummonConfig(): SummonReactConfig {\n const config = useContext(SummonConfigContext);\n if (!config) throw new Error(MISSING_PROVIDER);\n return config;\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","// `defineOverlay` — the declare-once API (C38 R2). One light definition per overlay carries its\n// metadata and a lazy `render` import; the definition generates the opener hook, the declarative\n// Controller, the open/close hooks and a typed event emitter. The host renders definitions; the\n// render module is the old controller block, moved verbatim, and is fetched only when opened.\n\nimport { useCallback, useEffect, useMemo, useRef, useState, type ComponentType } from \"react\";\nimport {\n DEFAULT_INSTANCE_ID,\n instanceKey as toInstanceKey,\n type InstanceKey,\n type OverlayDefinitionMeta,\n type OverlayRawData,\n type AnyOverlayMeta,\n} from \"@ai-matrx/summon\";\nimport { selectIsOverlayOpen } from \"@ai-matrx/summon\";\nimport { dispatchClose, dispatchOpen, newInstanceId } from \"./dispatchers\";\nimport { emitOverlayEvent, openOverlayEventChannel, type OverlayEventMap, type OverlayHandlers } from \"./events\";\nimport { createInstanceBody, type InstanceBodyProps, type OverlayRenderProps } from \"./instanceBody\";\nimport { useOptionalOverlayInstance } from \"./instance\";\nimport type { RenderModule } from \"./loaderCache\";\nimport { useSummonDispatch, useSummonSelector, type SummonReactDispatch } from \"./storeHooks\";\n\n/** The open-data key that carries an overlay's event channel id (the old callback-group key). */\nexport const CALLBACK_GROUP_KEY = \"callbackGroupId\";\n\nexport interface OverlayHandle {\n readonly overlayId: string;\n readonly instanceId: string;\n close(): void;\n}\n\nexport interface OverlayOpenOptions<Data, Events extends OverlayEventMap> {\n readonly data?: Data;\n /** Single-instance overlays ignore it unless given; multi-instance generate one when omitted. */\n readonly instanceId?: string;\n /** Plain functions; they reach the caller through an event channel owned by the instance. */\n readonly handlers?: OverlayHandlers<Events>;\n}\n\nexport type OverlayOpener<Data, Events extends OverlayEventMap> = (options?: OverlayOpenOptions<Data, Events>) => OverlayHandle;\n\nexport type OverlayControllerProps<Data, Events extends OverlayEventMap> = Data & {\n readonly instanceId?: string;\n readonly handlers?: OverlayHandlers<Events>;\n};\n\nexport type OverlayEmitter<Events extends OverlayEventMap> = <K extends keyof Events & string>(event: K, payload: Events[K]) => void;\n\n/** What a definition file passes to `defineOverlay<Data>()(…)`. */\nexport interface OverlaySpec<Id extends string, Data, Parsed> extends OverlayDefinitionMeta<Id, Data> {\n /** The lazily loaded render module. Its default export receives `OverlayRenderProps<Parsed>`. */\n readonly render: () => Promise<RenderModule<OverlayRenderProps<NoInfer<Parsed>>>>;\n /** Narrow raw open data once. `null` = refuse: the instance is closed with a warning. */\n readonly parse?: (raw: OverlayRawData) => Parsed | null;\n}\n\n/** The type-erased half the host renders; no data types cross this line. */\nexport interface HostableOverlay {\n readonly id: string;\n readonly label: string;\n readonly instance: \"single\" | \"multi\";\n readonly keepAlive: \"none\" | \"hidden\" | \"restore\";\n /** The metadata the core registry stores (links, window options, defaults…). */\n readonly meta: AnyOverlayMeta;\n readonly Body: ComponentType<InstanceBodyProps>;\n}\n\nexport interface OverlayDefinition<Id extends string, Data, Parsed, Events extends OverlayEventMap>\n extends Omit<OverlayDefinitionMeta<Id, Data>, \"id\" | \"instance\" | \"keepAlive\">,\n HostableOverlay {\n readonly id: Id;\n readonly render: () => Promise<RenderModule<OverlayRenderProps<Parsed>>>;\n /** Imperative opener: `const open = def.useSummon(); open({ data })` → handle. */\n useSummon(): OverlayOpener<Data, Events>;\n /** Declarative form: opens on mount, closes on unmount, re-opens when its data changes. */\n readonly Controller: (props: OverlayControllerProps<Data, Events>) => null;\n useIsOpen(instanceId?: string): boolean;\n /** `const close = def.useClose(); close(instanceId?)`. */\n useClose(): (instanceId?: string) => void;\n /** Inside the render tree: emit a declared event to the opener's handlers. */\n useEmit(): OverlayEmitter<Events>;\n}\n\nfunction openWith<Data, Events extends OverlayEventMap>(\n dispatch: SummonReactDispatch,\n id: string,\n multi: boolean,\n options: OverlayOpenOptions<Data, Events> | undefined,\n): OverlayHandle {\n const instanceId = options?.instanceId ?? (multi ? newInstanceId(id) : DEFAULT_INSTANCE_ID);\n const key = toInstanceKey(id, instanceId);\n const data: Record<string, unknown> = {};\n const given: unknown = options?.data;\n if (typeof given === \"object\" && given !== null) Object.assign(data, given);\n const handlers = options?.handlers;\n if (handlers) data[CALLBACK_GROUP_KEY] = openOverlayEventChannel<Events>(key, () => handlers);\n dispatchOpen(dispatch, id, instanceId, data);\n return { overlayId: id, instanceId, close: () => dispatchClose(dispatch, id, instanceId) };\n}\n\n/** Stable identity for the serialisable part of Controller props (functions never reopen). */\nfunction dataSignature(data: Readonly<Record<string, unknown>>): string {\n try {\n return JSON.stringify(data, (_key, value: unknown) => (typeof value === \"function\" ? undefined : value));\n } catch {\n return String(Date.now());\n }\n}\n\n/**\n * Declare an overlay once. Curried so `Data` (and `Events`) are named while the id and the\n * parsed-data type are inferred:\n *\n * export const notesWindow = defineOverlay<NotesWindowData>()({\n * id: \"notesWindow\", label: \"Notes\", render: () => import(\"./notesWindow.render\"),\n * });\n */\nexport function defineOverlay<Data extends object = Record<string, never>, Events extends OverlayEventMap = Record<never, never>>() {\n return function define<const Id extends string, Parsed = OverlayRawData>(\n spec: OverlaySpec<Id, Data, Parsed>,\n ): OverlayDefinition<Id, Data, Parsed, Events> {\n const id = spec.id;\n const multi = spec.instance === \"multi\";\n // Without `parse`, Parsed is OverlayRawData (NoInfer keeps the render module from widening it).\n const parse = spec.parse ?? ((raw: OverlayRawData) => raw as Parsed);\n const Body = createInstanceBody<Parsed>(id, spec.label, spec.render, parse, spec.parse !== undefined);\n // The registry stores every definition's metadata under one erased type (AnyOverlayMeta).\n const meta: AnyOverlayMeta = spec;\n\n function useSummon(): OverlayOpener<Data, Events> {\n const dispatch = useSummonDispatch();\n return useCallback((options) => openWith(dispatch, id, multi, options), [dispatch]);\n }\n\n function useIsOpen(instanceId: string = DEFAULT_INSTANCE_ID): boolean {\n return useSummonSelector((state) => selectIsOverlayOpen(state, id, instanceId));\n }\n\n function useClose(): (instanceId?: string) => void {\n const dispatch = useSummonDispatch();\n return useCallback((instanceId?: string) => dispatchClose(dispatch, id, instanceId ?? DEFAULT_INSTANCE_ID), [dispatch]);\n }\n\n function useEmit(): OverlayEmitter<Events> {\n const instance = useOptionalOverlayInstance();\n const channelId = instance?.overlayId === id ? instance.rawData?.[CALLBACK_GROUP_KEY] : undefined;\n return useCallback<OverlayEmitter<Events>>(\n (event, payload) => {\n if (typeof channelId === \"string\") emitOverlayEvent(channelId, event, payload);\n },\n [channelId],\n );\n }\n\n function Controller(props: OverlayControllerProps<Data, Events>): null {\n const dispatch = useSummonDispatch();\n const [ownInstanceId] = useState(() => (multi ? newInstanceId(id) : DEFAULT_INSTANCE_ID));\n const instanceId = props.instanceId ?? ownInstanceId;\n // Latest handlers, read at emit time: a new function identity never reopens the overlay.\n const handlersRef = useRef(props.handlers);\n handlersRef.current = props.handlers;\n const hasHandlers = props.handlers !== undefined;\n\n const data = useMemo(() => {\n const out: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(props)) {\n if (key !== \"instanceId\" && key !== \"handlers\") out[key] = value;\n }\n return out;\n }, [props]);\n const signature = dataSignature(data);\n const dataRef = useRef(data);\n dataRef.current = data;\n\n useEffect(() => {\n const key: InstanceKey = toInstanceKey(id, instanceId);\n const open: Record<string, unknown> = { ...dataRef.current };\n if (hasHandlers) open[CALLBACK_GROUP_KEY] = openOverlayEventChannel<Events>(key, () => handlersRef.current);\n dispatchOpen(dispatch, id, instanceId, open);\n return () => dispatchClose(dispatch, id, instanceId);\n }, [dispatch, instanceId, signature, hasHandlers]);\n\n return null;\n }\n Controller.displayName = `${id}Controller`;\n\n return {\n ...spec,\n id,\n label: spec.label,\n instance: multi ? \"multi\" : \"single\",\n keepAlive: spec.keepAlive ?? \"none\",\n meta,\n Body,\n useSummon,\n Controller,\n useIsOpen,\n useClose,\n useEmit,\n };\n };\n}\n","// The one place the React section turns an untyped (string) overlay id into the core's typed\n// action creators. Inside the package `OverlayId` is `string`; a host that augments the registry\n// narrows it to its ids, and these keep compiling there because definitions carry their own id.\n\nimport { closeOverlay, openOverlay } from \"@ai-matrx/summon\";\nimport { DEFAULT_INSTANCE_ID, type OverlayDataOf, type OverlayId } from \"@ai-matrx/summon\";\nimport type { SummonReactDispatch } from \"./storeHooks\";\n\nexport function newInstanceId(overlayId: string): string {\n return `${overlayId}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;\n}\n\nexport function dispatchOpen(dispatch: SummonReactDispatch, overlayId: string, instanceId: string, data: unknown): void {\n dispatch(\n openOverlay({\n overlayId: overlayId as OverlayId,\n instanceId,\n data: (data ?? null) as OverlayDataOf<OverlayId> | null,\n }),\n );\n}\n\nexport function dispatchClose(dispatch: SummonReactDispatch, overlayId: string, instanceId: string = DEFAULT_INSTANCE_ID): void {\n dispatch(closeOverlay({ overlayId: overlayId as OverlayId, instanceId }));\n}\n","// Callback-aware opening: callers pass plain handler functions; the opener puts them behind a\n// handles event channel owned by the instance (`overlayId:instanceId`) and only the channel's id\n// rides open data. Closing the instance disposes the channel (the core close middleware calls\n// `disposeOwner`), so no opener disposes by hand.\n\nimport { createEventChannel, getEventChannel } from \"@ai-matrx/summon/handles\";\nimport type { InstanceKey } from \"@ai-matrx/summon\";\n\n/** Event name → payload, declared once per overlay: `defineOverlay<Data, { uploaded: Result }>()`. */\nexport type OverlayEventMap = Record<string, unknown>;\n\nexport type OverlayHandlers<Events extends OverlayEventMap> = {\n readonly [K in keyof Events]?: (payload: Events[K]) => void;\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\n/** Open a channel owned by `owner` that forwards each event to the handler `getHandlers` returns now. */\nexport function openOverlayEventChannel<Events extends OverlayEventMap>(\n owner: InstanceKey,\n getHandlers: () => OverlayHandlers<Events> | undefined,\n): string {\n const channel = createEventChannel<OverlayEventMessage>({ owner });\n channel.subscribe((message) => {\n const handlers = getHandlers() as Readonly<Record<string, ((payload: unknown) => void) | undefined>> | undefined;\n handlers?.[message.type]?.(message.payload);\n });\n return channel.id;\n}\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 getEventChannel<OverlayEventMessage>(channelId)?.emit({ type, payload });\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, 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 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 render: RenderLoader<OverlayRenderProps<Parsed>>,\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 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 { createContext, useCallback, useContext } from \"react\";\nimport type { InstanceKey, OverlayRawData } from \"@ai-matrx/summon\";\nimport { selectOverlayStateValue, setOverlayStateValue } from \"@ai-matrx/summon\";\nimport { useSummonDispatch, useSummonSelector, useSummonStore } from \"./storeHooks\";\n\nexport interface OverlayInstanceContextValue {\n readonly overlayId: string;\n readonly instanceId: string;\n readonly instanceKey: InstanceKey;\n readonly close: () => void;\n readonly hidden: boolean;\n /** The open data as it arrived (pre-parse); event emitters read their channel id from it. */\n readonly rawData: OverlayRawData;\n}\n\nexport const OverlayInstanceContext = createContext<OverlayInstanceContextValue | null>(null);\nOverlayInstanceContext.displayName = \"OverlayInstanceContext\";\n\n/** The open instance this component renders inside. Throws outside an overlay. */\nexport function useOverlayInstance(): OverlayInstanceContextValue {\n const value = useContext(OverlayInstanceContext);\n if (!value) {\n throw new Error(\"[summon] useOverlayInstance() was called outside a rendered overlay.\");\n }\n return value;\n}\n\n/** Same as `useOverlayInstance`, but `null` outside an overlay. */\nexport function useOptionalOverlayInstance(): OverlayInstanceContextValue | null {\n return useContext(OverlayInstanceContext);\n}\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","// `<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 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 type { HostableOverlay } from \"./defineOverlay\";\nimport { dispatchClose } from \"./dispatchers\";\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\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\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 = definition.Body;\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 }: 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 <>\n {definitions.map((definition) => (\n <DefinitionSlot key={definition.id} definition={definition} />\n ))}\n </>\n );\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 type { OverlayHandle } from \"./defineOverlay\";\nimport { dispatchClose, dispatchOpen, newInstanceId } from \"./dispatchers\";\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_react_redux","import_summon","import_react","import_react","import_react","Component","import_jsx_runtime","import_react","import_summon","import_summon","import_react","import_react","import_jsx_runtime","import_react","import_summon","import_jsx_runtime","toInstanceKey","import_react","import_summon","import_jsx_runtime","InstanceSlot","toInstanceKey","DefinitionSlot","import_react","import_summon"]}
package/dist/react.d.cts CHANGED
@@ -85,6 +85,11 @@ declare function useSummonPorts(): SummonPorts;
85
85
  * components that are usable page-local without the system (dialogs, sheets).
86
86
  */
87
87
  declare function useOptionalSummonPorts(): SummonPorts;
88
+ /**
89
+ * The nearest provider's store, or `null` when no SummonProvider is above — for packages that
90
+ * mount their own provider only when the host has none (chat's windows on a bare host).
91
+ */
92
+ declare function useOptionalSummonStore(): SummonReactStore | null;
88
93
 
89
94
  /** Event name → payload, declared once per overlay: `defineOverlay<Data, { uploaded: Result }>()`. */
90
95
  type OverlayEventMap = Record<string, unknown>;
@@ -258,4 +263,4 @@ declare function OverlayLoadingFallback({ overlayId, label }: OverlayLoadingFall
258
263
  /** The error card: what failed, and a way out that never needs a page reload. */
259
264
  declare function OverlayErrorFallback({ label, error, retry, close, extras }: OverlayErrorFallbackProps): react.JSX.Element;
260
265
 
261
- export { CALLBACK_GROUP_KEY, DEFAULT_IMPORT_TIMEOUT_MS, DEFAULT_KEEP_ALIVE_LIMIT, DEFAULT_STALL_WARN_MS, type HostableOverlay, type NormalizedOverlayError, type OpenOverlayOptions, type OverlayControllerProps, type OverlayDefinition, type OverlayEmitter, OverlayErrorBoundary, type OverlayErrorBoundaryProps, type OverlayErrorExtrasContext, OverlayErrorFallback, type OverlayErrorFallbackProps, type OverlayEventMap, type OverlayHandle, type OverlayHandlers, type OverlayInstanceContextValue, OverlayLoadingFallback, type OverlayLoadingFallbackProps, type OverlayOpenOptions, type OverlayOpener, type OverlayRenderContext, type OverlayRenderProps, type OverlaySpec, type OverlayStateSetter, type RenderLoader, type RenderModule, SummonHost, type SummonHostProps, SummonProvider, type SummonProviderProps, type SummonReactDispatch, type SummonReactStore, SummonStoreContext, chunkTimeoutError, defineOverlay, normalizeOverlayError, useCloseOnNavigation, useCloseOverlay, useIsOverlayOpen, useOpenOverlay, useOptionalOverlayInstance, useOptionalSummonPorts, useOverlayInstance, useOverlayState, useSummonDispatch, useSummonPorts, useSummonSelector, useSummonStore };
266
+ export { CALLBACK_GROUP_KEY, DEFAULT_IMPORT_TIMEOUT_MS, DEFAULT_KEEP_ALIVE_LIMIT, DEFAULT_STALL_WARN_MS, type HostableOverlay, type NormalizedOverlayError, type OpenOverlayOptions, type OverlayControllerProps, type OverlayDefinition, type OverlayEmitter, OverlayErrorBoundary, type OverlayErrorBoundaryProps, type OverlayErrorExtrasContext, OverlayErrorFallback, type OverlayErrorFallbackProps, type OverlayEventMap, type OverlayHandle, type OverlayHandlers, type OverlayInstanceContextValue, OverlayLoadingFallback, type OverlayLoadingFallbackProps, type OverlayOpenOptions, type OverlayOpener, type OverlayRenderContext, type OverlayRenderProps, type OverlaySpec, type OverlayStateSetter, type RenderLoader, type RenderModule, SummonHost, type SummonHostProps, SummonProvider, type SummonProviderProps, type SummonReactDispatch, type SummonReactStore, SummonStoreContext, chunkTimeoutError, defineOverlay, normalizeOverlayError, useCloseOnNavigation, useCloseOverlay, useIsOverlayOpen, useOpenOverlay, useOptionalOverlayInstance, useOptionalSummonPorts, useOptionalSummonStore, useOverlayInstance, useOverlayState, useSummonDispatch, useSummonPorts, useSummonSelector, useSummonStore };
package/dist/react.d.ts CHANGED
@@ -85,6 +85,11 @@ declare function useSummonPorts(): SummonPorts;
85
85
  * components that are usable page-local without the system (dialogs, sheets).
86
86
  */
87
87
  declare function useOptionalSummonPorts(): SummonPorts;
88
+ /**
89
+ * The nearest provider's store, or `null` when no SummonProvider is above — for packages that
90
+ * mount their own provider only when the host has none (chat's windows on a bare host).
91
+ */
92
+ declare function useOptionalSummonStore(): SummonReactStore | null;
88
93
 
89
94
  /** Event name → payload, declared once per overlay: `defineOverlay<Data, { uploaded: Result }>()`. */
90
95
  type OverlayEventMap = Record<string, unknown>;
@@ -258,4 +263,4 @@ declare function OverlayLoadingFallback({ overlayId, label }: OverlayLoadingFall
258
263
  /** The error card: what failed, and a way out that never needs a page reload. */
259
264
  declare function OverlayErrorFallback({ label, error, retry, close, extras }: OverlayErrorFallbackProps): react.JSX.Element;
260
265
 
261
- export { CALLBACK_GROUP_KEY, DEFAULT_IMPORT_TIMEOUT_MS, DEFAULT_KEEP_ALIVE_LIMIT, DEFAULT_STALL_WARN_MS, type HostableOverlay, type NormalizedOverlayError, type OpenOverlayOptions, type OverlayControllerProps, type OverlayDefinition, type OverlayEmitter, OverlayErrorBoundary, type OverlayErrorBoundaryProps, type OverlayErrorExtrasContext, OverlayErrorFallback, type OverlayErrorFallbackProps, type OverlayEventMap, type OverlayHandle, type OverlayHandlers, type OverlayInstanceContextValue, OverlayLoadingFallback, type OverlayLoadingFallbackProps, type OverlayOpenOptions, type OverlayOpener, type OverlayRenderContext, type OverlayRenderProps, type OverlaySpec, type OverlayStateSetter, type RenderLoader, type RenderModule, SummonHost, type SummonHostProps, SummonProvider, type SummonProviderProps, type SummonReactDispatch, type SummonReactStore, SummonStoreContext, chunkTimeoutError, defineOverlay, normalizeOverlayError, useCloseOnNavigation, useCloseOverlay, useIsOverlayOpen, useOpenOverlay, useOptionalOverlayInstance, useOptionalSummonPorts, useOverlayInstance, useOverlayState, useSummonDispatch, useSummonPorts, useSummonSelector, useSummonStore };
266
+ export { CALLBACK_GROUP_KEY, DEFAULT_IMPORT_TIMEOUT_MS, DEFAULT_KEEP_ALIVE_LIMIT, DEFAULT_STALL_WARN_MS, type HostableOverlay, type NormalizedOverlayError, type OpenOverlayOptions, type OverlayControllerProps, type OverlayDefinition, type OverlayEmitter, OverlayErrorBoundary, type OverlayErrorBoundaryProps, type OverlayErrorExtrasContext, OverlayErrorFallback, type OverlayErrorFallbackProps, type OverlayEventMap, type OverlayHandle, type OverlayHandlers, type OverlayInstanceContextValue, OverlayLoadingFallback, type OverlayLoadingFallbackProps, type OverlayOpenOptions, type OverlayOpener, type OverlayRenderContext, type OverlayRenderProps, type OverlaySpec, type OverlayStateSetter, type RenderLoader, type RenderModule, SummonHost, type SummonHostProps, SummonProvider, type SummonProviderProps, type SummonReactDispatch, type SummonReactStore, SummonStoreContext, chunkTimeoutError, defineOverlay, normalizeOverlayError, useCloseOnNavigation, useCloseOverlay, useIsOverlayOpen, useOpenOverlay, useOptionalOverlayInstance, useOptionalSummonPorts, useOptionalSummonStore, useOverlayInstance, useOverlayState, useSummonDispatch, useSummonPorts, useSummonSelector, useSummonStore };
package/dist/react.js CHANGED
@@ -39,6 +39,10 @@ function useSummonPorts() {
39
39
  function useOptionalSummonPorts() {
40
40
  return useContext(SummonPortsContext) ?? DEFAULT_PORTS;
41
41
  }
42
+ function useOptionalSummonStore() {
43
+ const context = useContext(SummonStoreContext);
44
+ return context ? context.store : null;
45
+ }
42
46
  function useSummonConfig() {
43
47
  const config = useContext(SummonConfigContext);
44
48
  if (!config) throw new Error(MISSING_PROVIDER);
@@ -128,12 +132,12 @@ function OverlayErrorFallback({ label, error, retry, close, extras }) {
128
132
 
129
133
  // src/react/keepAlive.ts
130
134
  var KeepAliveRegistry = class {
135
+ order = [];
136
+ evictors = /* @__PURE__ */ new Map();
137
+ limit;
131
138
  constructor(limit) {
132
139
  this.limit = limit;
133
140
  }
134
- limit;
135
- order = [];
136
- evictors = /* @__PURE__ */ new Map();
137
141
  setLimit(limit) {
138
142
  this.limit = Math.max(0, Math.floor(limit));
139
143
  this.trim();
@@ -188,11 +192,11 @@ function raceTimeout(key, real, timeoutMs) {
188
192
  });
189
193
  }
190
194
  var LoaderCache = class {
195
+ entries = /* @__PURE__ */ new Map();
196
+ options;
191
197
  constructor(options) {
192
198
  this.options = options;
193
199
  }
194
- options;
195
- entries = /* @__PURE__ */ new Map();
196
200
  create(key, loader, attempt) {
197
201
  const Component2 = lazy(() => {
198
202
  this.options.onImportStart?.(key, attempt);
@@ -301,7 +305,7 @@ function emitOverlayEvent(channelId, type, payload) {
301
305
  }
302
306
 
303
307
  // src/react/instanceBody.tsx
304
- import { Suspense, useEffect as useEffect3, useMemo as useMemo2, useRef as useRef2 } from "react";
308
+ import { Suspense, memo, useEffect as useEffect3, useMemo as useMemo2, useRef as useRef2 } from "react";
305
309
 
306
310
  // src/react/OverlayErrorBoundary.tsx
307
311
  import { Component } from "react";
@@ -446,7 +450,7 @@ function createInstanceBody(overlayId, label, render, parse, refusable) {
446
450
  return /* @__PURE__ */ jsx4(OverlayInstanceContext.Provider, { value: instance, children: config.renderWrapper ? config.renderWrapper(body, context) : body });
447
451
  }
448
452
  OverlayInstanceBody.displayName = `Overlay(${overlayId})`;
449
- return OverlayInstanceBody;
453
+ return memo(OverlayInstanceBody);
450
454
  }
451
455
 
452
456
  // src/react/defineOverlay.tsx
@@ -542,7 +546,7 @@ function defineOverlay() {
542
546
  }
543
547
 
544
548
  // src/react/SummonHost.tsx
545
- import { Activity, useCallback as useCallback3, useEffect as useEffect5, useRef as useRef4, useState as useState3 } from "react";
549
+ import { Activity, memo as memo2, useCallback as useCallback3, useEffect as useEffect5, useRef as useRef4, useState as useState3 } from "react";
546
550
  import { releaseOverlayInstance } from "@ai-matrx/summon";
547
551
  import { registerOverlayMeta } from "@ai-matrx/summon";
548
552
  import { closeOverlaysBoundToPage, overlayIdsBoundToPage, selectOpenInstances } from "@ai-matrx/summon";
@@ -577,13 +581,13 @@ function useCloseOnNavigation() {
577
581
  });
578
582
  }, [ports, dispatch]);
579
583
  }
580
- function InstanceSlot({ definition, instanceId, data, hidden }) {
584
+ var InstanceSlot = memo2(function InstanceSlot2({ definition, instanceId, data, hidden }) {
581
585
  const dispatch = useSummonDispatch();
582
586
  const close = useCallback3(() => dispatchClose(dispatch, definition.id, instanceId), [dispatch, definition.id, instanceId]);
583
587
  const Body = definition.Body;
584
588
  return /* @__PURE__ */ jsx5(Body, { instanceId, instanceKey: toInstanceKey2(definition.id, instanceId), data, hidden, close });
585
- }
586
- function DefinitionSlot({ definition }) {
589
+ });
590
+ var DefinitionSlot = memo2(function DefinitionSlot2({ definition }) {
587
591
  const { keepAlive } = useSummonConfig();
588
592
  const dispatch = useSummonDispatch();
589
593
  const open = useSummonSelector((state) => selectOpenInstances(state, definition.id), sameInstances);
@@ -653,7 +657,7 @@ function DefinitionSlot({ definition }) {
653
657
  }
654
658
  }
655
659
  return /* @__PURE__ */ jsx5(Fragment, { children: nodes });
656
- }
660
+ });
657
661
  function SummonHost({ definitions }) {
658
662
  const registeredFor = useRef4(null);
659
663
  if (registeredFor.current !== definitions) {
@@ -708,6 +712,7 @@ export {
708
712
  useOpenOverlay,
709
713
  useOptionalOverlayInstance,
710
714
  useOptionalSummonPorts,
715
+ useOptionalSummonStore,
711
716
  useOverlayInstance,
712
717
  useOverlayState,
713
718
  useSummonDispatch,