@x1a0f3n9/dsh-client-ui-slots 0.1.5-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.i18n.yaml +6 -0
- package/README.md +104 -0
- package/README.zh.md +104 -0
- package/lib/index.js +433 -0
- package/lib/types/index.d.ts +740 -0
- package/lib/types/renderer.d.ts +215 -0
- package/lib/types/store.d.ts +3 -0
- package/package.json +37 -0
|
@@ -0,0 +1,740 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Slot registry pure core. Owners declare slot
|
|
3
|
+
* contracts by merging into {@link SlotMap}; one `register` call contributes a
|
|
4
|
+
* component AND (optionally) declares child slots, a store seat, and the
|
|
5
|
+
* registrant's business face. Zero runtime dependencies (React types only).
|
|
6
|
+
*
|
|
7
|
+
* SlotMap and the standard-kit interfaces live directly in this entry module:
|
|
8
|
+
* consumer `declare module` augmentation merges with declarations lexically in
|
|
9
|
+
* the augmented module, not with re-exports.
|
|
10
|
+
*/
|
|
11
|
+
import type { ReactNode } from 'react';
|
|
12
|
+
import type { BoundActions, HandleOf, PropsStore, SnapshotSelectorHook, StoreDecl } from '@x1a0f3n9/dsh-client-store';
|
|
13
|
+
import type { HostObservable, KeyedStandardSource } from './renderer.ts';
|
|
14
|
+
export * from './store.ts';
|
|
15
|
+
export * from './renderer.ts';
|
|
16
|
+
/** Slot contract table. Owners extend via declaration merging; entries are {@link SlotEntryDef}. */
|
|
17
|
+
export interface SlotMap {
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Locale namespace table. Dictionary owners extend via declaration merging
|
|
21
|
+
* (exactly like {@link SlotMap}, and declared in this entry module for the
|
|
22
|
+
* same lexical-merge reason): the key is the namespace string, the value is
|
|
23
|
+
* the union of its dictionary keys. Register sites declare one of these
|
|
24
|
+
* namespaces (`locale:`), which puts the typed `t` standard seat on the
|
|
25
|
+
* component props.
|
|
26
|
+
*/
|
|
27
|
+
export interface LocaleNamespaceMap {
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Resource protocol (URL scheme) → the value its provider streams. Declared
|
|
31
|
+
* empty here, the zero-dependency merge point; each protocol owner merges its
|
|
32
|
+
* own member (`file`, later `chat`), and `useResource<P>(address)` narrows its
|
|
33
|
+
* value by `P`. The resource service itself lives in `dsh-client-resources`.
|
|
34
|
+
*/
|
|
35
|
+
export interface ResourceProtocolMap {
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Translate a dictionary key with optional `{name}` template params.
|
|
39
|
+
* `K` narrows the accepted keys to the owning namespace's dictionary union
|
|
40
|
+
* (plus the shared common vocabulary where composed).
|
|
41
|
+
*/
|
|
42
|
+
export type Translate<K extends string = string> = (key: K, params?: Record<string, unknown>) => string;
|
|
43
|
+
/**
|
|
44
|
+
* The shared `common` vocabulary keys as merged by the locale plugin;
|
|
45
|
+
* resolves to `never` in programs without the merge (this package's tests),
|
|
46
|
+
* keeping the union collapse harmless.
|
|
47
|
+
*/
|
|
48
|
+
export type CommonKeyOf = LocaleNamespaceMap extends {
|
|
49
|
+
common: infer C;
|
|
50
|
+
} ? C & string : never;
|
|
51
|
+
/**
|
|
52
|
+
* Key domain of a namespace-bound translate: the namespace's own dictionary
|
|
53
|
+
* union plus the shared common vocabulary (the lookup chain consults common
|
|
54
|
+
* after the namespace misses).
|
|
55
|
+
*/
|
|
56
|
+
export type LocaleKeysOf<N extends keyof LocaleNamespaceMap & string> = (LocaleNamespaceMap[N] & string) | CommonKeyOf;
|
|
57
|
+
/**
|
|
58
|
+
* Namespace-addressed translate — the developer-facing alias over
|
|
59
|
+
* {@link Translate}: `TranslateNS<'model'>` is the translate function of the
|
|
60
|
+
* `model` namespace (key domain = its dictionary union plus the shared
|
|
61
|
+
* common vocabulary), the exact type of the framework-injected `t` seat and
|
|
62
|
+
* of the locale service's typed `bind`.
|
|
63
|
+
*/
|
|
64
|
+
export type TranslateNS<N extends keyof LocaleNamespaceMap & string> = Translate<LocaleKeysOf<N>>;
|
|
65
|
+
/**
|
|
66
|
+
* Dictionary shape for a declared namespace: exactly the keys the namespace
|
|
67
|
+
* merged into {@link LocaleNamespaceMap} — a missing or extra key at a typed
|
|
68
|
+
* registration site is a compile error.
|
|
69
|
+
*/
|
|
70
|
+
export type LocaleDictOf<N extends keyof LocaleNamespaceMap & string> = Record<LocaleNamespaceMap[N] & string, string>;
|
|
71
|
+
/**
|
|
72
|
+
* Locale share of the composed component props: the framework-injected `t`
|
|
73
|
+
* seat, present exactly on entries whose registration declares `locale:`.
|
|
74
|
+
*/
|
|
75
|
+
export type PropsLocale<N> = N extends keyof LocaleNamespaceMap & string ? {
|
|
76
|
+
/** Translate a dictionary key of the declared namespace (or the shared common vocabulary). */
|
|
77
|
+
t: TranslateNS<N>;
|
|
78
|
+
} : object;
|
|
79
|
+
/** Slot cardinality: single occupant, ordered list, key-dispatched, or selector-routed chain. */
|
|
80
|
+
export type SlotKind = 'single' | 'list' | 'keyed' | 'chain';
|
|
81
|
+
/** Slot data context: global, current-session-optional, or strict session-bound. */
|
|
82
|
+
export type SlotScope = 'root' | 'session-maybe' | 'session';
|
|
83
|
+
/**
|
|
84
|
+
* One SlotMap entry: kind/scope axes plus the optional owner-supplied props
|
|
85
|
+
* share (`owner` is what the parent passes at its renderSlot call site; the
|
|
86
|
+
* framework standard kit and the registrant's injected share never enter this
|
|
87
|
+
* table — full component props compose at the component as the four-share
|
|
88
|
+
* intersection, see {@link ComposedProps}).
|
|
89
|
+
*/
|
|
90
|
+
export interface SlotEntryDef {
|
|
91
|
+
kind: SlotKind;
|
|
92
|
+
scope: SlotScope;
|
|
93
|
+
owner?: object;
|
|
94
|
+
/**
|
|
95
|
+
* Optional keyed-entry prop table. A keyed registration contributes one
|
|
96
|
+
* literal key and receives the corresponding prop share; ordinary owner
|
|
97
|
+
* props remain common to every key.
|
|
98
|
+
*/
|
|
99
|
+
keyProps?: Record<string, object>;
|
|
100
|
+
/**
|
|
101
|
+
* Optional opaque context carried by one renderSlot occurrence. Only
|
|
102
|
+
* function-valued members of the slot-level injected hooks compartment
|
|
103
|
+
* receive it; the slot machinery never interprets the value.
|
|
104
|
+
*/
|
|
105
|
+
hookContext?: unknown;
|
|
106
|
+
/**
|
|
107
|
+
* Optional Slot-level inject face supplied by the parent registration's
|
|
108
|
+
* child declaration. Every registered entry receives its bound component
|
|
109
|
+
* face; child registrants do not own or replace this common capability.
|
|
110
|
+
*/
|
|
111
|
+
inject?: object;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Runtime dispatch spec for one slot, recorded from a register call's
|
|
115
|
+
* `children` value. The literal is compile-time checked against the SlotMap
|
|
116
|
+
* entry (`SlotSpec<SlotMap[P]>` in {@link ChildrenDecl}), so kind, scope, and
|
|
117
|
+
* any common inject face are declared at one point and validate each other.
|
|
118
|
+
*/
|
|
119
|
+
export type SlotSpec<E extends SlotEntryDef> = {
|
|
120
|
+
kind: E['kind'];
|
|
121
|
+
scope: E['scope'];
|
|
122
|
+
} & ('inject' extends keyof E ? E extends {
|
|
123
|
+
inject: infer Injected extends object;
|
|
124
|
+
} ? {
|
|
125
|
+
inject: Injected;
|
|
126
|
+
} : {
|
|
127
|
+
inject?: object;
|
|
128
|
+
} : {
|
|
129
|
+
inject?: never;
|
|
130
|
+
});
|
|
131
|
+
/**
|
|
132
|
+
* Child-slot declaration table for register(): keys are the declared (and
|
|
133
|
+
* thereby render-authorized) slot names, values are their runtime dispatch
|
|
134
|
+
* specs. Declaring is claiming: the registering entry becomes the only entry
|
|
135
|
+
* allowed to render these keys.
|
|
136
|
+
*/
|
|
137
|
+
export type ChildrenDecl = {
|
|
138
|
+
[P in keyof SlotMap & string]?: SlotSpec<SlotMap[P]>;
|
|
139
|
+
};
|
|
140
|
+
/** Owner-supplied props share for a slot key ({} for entries declaring no `owner`). */
|
|
141
|
+
export type OwnerOf<K extends keyof SlotMap & string> = SlotMap[K] extends {
|
|
142
|
+
owner: infer O extends object;
|
|
143
|
+
} ? O : object;
|
|
144
|
+
/** Registration/dispatch key domain of one keyed slot. */
|
|
145
|
+
export type EntryKeyOf<K extends keyof SlotMap & string> = SlotMap[K] extends {
|
|
146
|
+
kind: 'keyed';
|
|
147
|
+
keyProps: infer P extends object;
|
|
148
|
+
} ? keyof P & string : string;
|
|
149
|
+
/** Key-dependent props supplied by the owner at one keyed dispatch site. */
|
|
150
|
+
export type KeyPropsOf<K extends keyof SlotMap & string, EntryKey extends EntryKeyOf<K>> = SlotMap[K] extends {
|
|
151
|
+
kind: 'keyed';
|
|
152
|
+
keyProps: infer P extends object;
|
|
153
|
+
} ? EntryKey extends keyof P ? P[EntryKey] extends object ? P[EntryKey] : never : never : object;
|
|
154
|
+
/** Opaque per-render occurrence context declared by one slot. */
|
|
155
|
+
export type HookContextOf<K extends keyof SlotMap & string> = SlotMap[K] extends {
|
|
156
|
+
hookContext: infer Context;
|
|
157
|
+
} ? Context : never;
|
|
158
|
+
/** Common render-occurrence inject face declared by one slot. */
|
|
159
|
+
export type SlotInjectOf<K extends keyof SlotMap & string> = SlotMap[K] extends {
|
|
160
|
+
inject: infer Injected extends object;
|
|
161
|
+
} ? Injected : object;
|
|
162
|
+
/** Scope axis of a slot key's SlotMap entry. */
|
|
163
|
+
export type ScopeOf<K extends keyof SlotMap & string> = SlotMap[K]['scope'];
|
|
164
|
+
/**
|
|
165
|
+
* Framework standard kit delivered to every session-scope slot component.
|
|
166
|
+
* Declared empty here (zero-dependency layer): `ui-session` merges the
|
|
167
|
+
* Session lifecycle hook, projection hook, and Session identity; domain UI
|
|
168
|
+
* adapters merge their own standard hooks exactly as consumers merge SlotMap keys.
|
|
169
|
+
*/
|
|
170
|
+
export interface SessionStandardProps {
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Framework standard kit delivered to current-session-optional slots. Its
|
|
174
|
+
* hooks stay callable while no session is selected and return `undefined`
|
|
175
|
+
* until one becomes current; `ui-session` and domain UI adapters merge the
|
|
176
|
+
* concrete members.
|
|
177
|
+
*/
|
|
178
|
+
export interface SessionMaybeStandardProps {
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Framework standard kit delivered to EVERY slot component (the global seat).
|
|
182
|
+
* Declared empty here; each owning UI adapter merges the global selector hooks
|
|
183
|
+
* that shared page composition consumes.
|
|
184
|
+
*/
|
|
185
|
+
export interface GlobalStandardProps {
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* The session id type as `ui-session`'s SessionStandardProps merge declares it
|
|
189
|
+
* (branded); falls back to `string` in programs without the merge (this
|
|
190
|
+
* package's own tests).
|
|
191
|
+
*/
|
|
192
|
+
export type SessionIdOf = SessionStandardProps extends {
|
|
193
|
+
sessionId: infer S;
|
|
194
|
+
} ? S : string;
|
|
195
|
+
/**
|
|
196
|
+
* Runtime props share for a slot key: owner share (parent's renderSlot call
|
|
197
|
+
* site) + session standard kit (session scope only) + the global seat.
|
|
198
|
+
*/
|
|
199
|
+
export type PropsRuntime<K extends keyof SlotMap & string, EntryKey extends EntryKeyOf<K> = EntryKeyOf<K>> = OwnerOf<K> & KeyPropsOf<K, EntryKey> & SlotInjectFace<SlotInjectOf<K>> & (ScopeOf<K> extends 'session' ? SessionStandardProps : ScopeOf<K> extends 'session-maybe' ? SessionMaybeStandardProps : object) & GlobalStandardProps;
|
|
200
|
+
/** renderSlot dispatch options: keyed dispatch key, list filtering, and empty fallback. */
|
|
201
|
+
export interface RenderOpts<EntryKey extends string = string> {
|
|
202
|
+
entryKey?: EntryKey;
|
|
203
|
+
only?: string;
|
|
204
|
+
fallback?: ReactNode;
|
|
205
|
+
/** Type-erased runtime seat; PropsRenderSlots narrows or removes it per slot declaration. */
|
|
206
|
+
hookContext?: unknown;
|
|
207
|
+
}
|
|
208
|
+
/** renderSlotChain dispatch options. */
|
|
209
|
+
export interface ChainRenderOpts {
|
|
210
|
+
/** The owner's fallback body, rendered when every entry's selector declines. */
|
|
211
|
+
fallback?: ReactNode;
|
|
212
|
+
/** Render only the owner fallback without resolving or dispatching the chain's scope. */
|
|
213
|
+
fallbackOnly?: boolean;
|
|
214
|
+
/**
|
|
215
|
+
* Keep the fallback permanently mounted: an election hides it (wrapped,
|
|
216
|
+
* display:none) instead of unmounting it, and the all-decline case shows it
|
|
217
|
+
* as-is — fallback-held state (composer drafts, DOM state) survives a
|
|
218
|
+
* takeover. Chain kind only; the sole consumer is the
|
|
219
|
+
* `conversation.composer` chain.
|
|
220
|
+
*/
|
|
221
|
+
overlay?: boolean;
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* Chain-entry selector: the routing decision of one chain contribution.
|
|
225
|
+
* Runs at render time in chain order (ascending `priority`, default 0, lower
|
|
226
|
+
* tries first; ties keep registration = assembly order); the first non-null
|
|
227
|
+
* return elects its entry
|
|
228
|
+
* and becomes the component's `matched` prop; `null` passes to the next
|
|
229
|
+
* entry; all-null falls to the owner's {@link ChainRenderOpts} fallback.
|
|
230
|
+
* MUST be pure — a function of the owner props only, no external mutable
|
|
231
|
+
* reads, no side effects (the decline decision lives here, never in a
|
|
232
|
+
* mounted component probing its own props).
|
|
233
|
+
*/
|
|
234
|
+
export type ChainSelect<O extends object, M> = (owner: O) => M | null;
|
|
235
|
+
/** Keys of a slot-key union whose SlotMap entry is chain-kind (renderSlotChain's dispatch domain). */
|
|
236
|
+
export type ChainKeysOf<S extends keyof SlotMap & string> = S extends unknown ? (SlotMap[S]['kind'] extends 'chain' ? S : never) : never;
|
|
237
|
+
/** Keys in a render share whose dispatch occurrence requires hookContext. */
|
|
238
|
+
type ContextualKeysOf<S extends keyof SlotMap & string> = S extends unknown ? (SlotMap[S] extends {
|
|
239
|
+
hookContext: unknown;
|
|
240
|
+
} ? S : never) : never;
|
|
241
|
+
/** Keys in a render share with the ordinary optional options bag. */
|
|
242
|
+
type OrdinaryKeysOf<S extends keyof SlotMap & string> = Exclude<S, ContextualKeysOf<S>>;
|
|
243
|
+
/**
|
|
244
|
+
* Plain and contextual child dispatch signatures. Keeping them as separate
|
|
245
|
+
* call signatures preserves ordinary renderSlot assignability while making a
|
|
246
|
+
* declared hookContext mandatory only for the Slot keys that need it.
|
|
247
|
+
*/
|
|
248
|
+
type RenderSlotFn<S extends keyof SlotMap & string> = ([ContextualKeysOf<S>] extends [never] ? object : {
|
|
249
|
+
<K extends ContextualKeysOf<S>, EntryKey extends EntryKeyOf<K> = EntryKeyOf<K>>(key: K, owner: OwnerOf<K> & KeyPropsOf<K, NoInfer<EntryKey>>, opts: RenderOpts<EntryKey> & {
|
|
250
|
+
hookContext: HookContextOf<K>;
|
|
251
|
+
}): ReactNode;
|
|
252
|
+
}) & ([OrdinaryKeysOf<S>] extends [never] ? object : {
|
|
253
|
+
<K extends OrdinaryKeysOf<S>, EntryKey extends EntryKeyOf<K> = EntryKeyOf<K>>(key: K, owner: OwnerOf<K> & KeyPropsOf<K, NoInfer<EntryKey>>, opts?: Omit<RenderOpts<EntryKey>, 'hookContext'>): ReactNode;
|
|
254
|
+
});
|
|
255
|
+
/**
|
|
256
|
+
* Chain matched share: a chain-slot component receives its selector's
|
|
257
|
+
* non-null result as the framework-injected `matched` prop; other kinds add
|
|
258
|
+
* nothing to the composed constraint.
|
|
259
|
+
*/
|
|
260
|
+
export type MatchedShare<E extends SlotEntryDef, M> = E['kind'] extends 'chain' ? {
|
|
261
|
+
matched: M;
|
|
262
|
+
} : object;
|
|
263
|
+
/** Props of the standard-kit SessionProvider seat. */
|
|
264
|
+
export interface SessionAreaProps {
|
|
265
|
+
/** No-session body (also covers a current id whose session cannot be resolved). */
|
|
266
|
+
empty?: (() => ReactNode) | undefined;
|
|
267
|
+
/** Session body; the framework remounts it per session identity. */
|
|
268
|
+
children: ReactNode;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* Framework-wired session area component. `ui-session` supplies the current
|
|
272
|
+
* Controller binding through the renderer scope adapter; entries that declare
|
|
273
|
+
* session-scoped children receive this component without importing it.
|
|
274
|
+
*/
|
|
275
|
+
export type SessionProviderComponent = (props: SessionAreaProps) => ReactNode;
|
|
276
|
+
/**
|
|
277
|
+
* Child-slot render share: `renderSlot` statically narrowed to the entry's
|
|
278
|
+
* declared children keys. Delegation is plain props passing (hand
|
|
279
|
+
* `props.renderSlot` down); the authorizing identity stays the registering
|
|
280
|
+
* entry. `__renders` is a phantom variance anchor (never materialized):
|
|
281
|
+
* generic method signatures compare loosely across differing key unions, so
|
|
282
|
+
* this contravariant marker is what actually enforces "component key set ⊆
|
|
283
|
+
* children declaration" at the register call site.
|
|
284
|
+
*/
|
|
285
|
+
export type PropsRenderSlots<S extends keyof SlotMap & string> = {
|
|
286
|
+
/**
|
|
287
|
+
* Render a declared non-chain child slot (chain keys dispatch through
|
|
288
|
+
* `renderSlotChain` — their routing lives in entry selectors).
|
|
289
|
+
* @param key - declared child key.
|
|
290
|
+
* @param owner - owner props share for that key (decided at the render site).
|
|
291
|
+
* @param opts - kind dispatch options.
|
|
292
|
+
* @returns rendered node(s).
|
|
293
|
+
*/
|
|
294
|
+
renderSlot: RenderSlotFn<Exclude<S, ChainKeysOf<S>>>;
|
|
295
|
+
readonly __renders?: ((key: S) => void) | undefined;
|
|
296
|
+
} & ([ChainKeysOf<S>] extends [never] ? object : {
|
|
297
|
+
/**
|
|
298
|
+
* Render a declared chain child slot: entry selectors run in chain order
|
|
299
|
+
* over `owner`; the first non-null match renders its component with the
|
|
300
|
+
* selector result injected as `matched`; all-null renders `opts.fallback`.
|
|
301
|
+
* @param key - declared chain child key.
|
|
302
|
+
* @param owner - owner props share (the selectors' routing input).
|
|
303
|
+
* @param opts - fallback body for the all-null case.
|
|
304
|
+
* @returns rendered node(s).
|
|
305
|
+
*/
|
|
306
|
+
renderSlotChain: <K extends ChainKeysOf<S>>(key: K, owner: OwnerOf<K>, opts?: ChainRenderOpts) => ReactNode;
|
|
307
|
+
}) & ('session' extends ScopeOf<S> ? {
|
|
308
|
+
SessionProvider: SessionProviderComponent;
|
|
309
|
+
} : object);
|
|
310
|
+
/**
|
|
311
|
+
* Registration-position component shape: the bare call signature, so composed
|
|
312
|
+
* constraints check through clean parameter contravariance (FC statics add
|
|
313
|
+
* covariant noise rejecting legitimate narrowings).
|
|
314
|
+
*/
|
|
315
|
+
export type SlotComponent<P> = (props: P) => ReactNode;
|
|
316
|
+
/**
|
|
317
|
+
* Registrant hooks compartment: bare observable sources (getSnapshot +
|
|
318
|
+
* subscribe pairs) supplied under the reserved `hooks` key of an entry's
|
|
319
|
+
* inject face. These retain the original source-to-selector binding and do
|
|
320
|
+
* not participate in render-occurrence context.
|
|
321
|
+
*/
|
|
322
|
+
export type HooksSources = Record<string, HostObservable<unknown>>;
|
|
323
|
+
/** Registrant keyed-hooks compartment: stable key-to-observable resolvers. */
|
|
324
|
+
export type KeyedHooksSources = Record<string, KeyedStandardSource>;
|
|
325
|
+
/** Selector Hook over an open family of keyed observable sources. */
|
|
326
|
+
export type KeyedSnapshotSelectorHook<Snapshot> = {
|
|
327
|
+
/** @param key - source key. @returns the current value, or absence when the source is unavailable. */
|
|
328
|
+
(key: string): Snapshot | undefined;
|
|
329
|
+
/**
|
|
330
|
+
* @param key - source key.
|
|
331
|
+
* @param selector - projection over the current keyed value.
|
|
332
|
+
* @param equal - optional selected-value equality.
|
|
333
|
+
* @returns the selected value.
|
|
334
|
+
*/
|
|
335
|
+
<Selected>(key: string, selector: (value: Snapshot | undefined) => Selected, equal?: (left: Selected, right: Selected) => boolean): Selected;
|
|
336
|
+
};
|
|
337
|
+
/** Framework-owned props visible while a slot-level contextual Hook is bound. */
|
|
338
|
+
export type StandardPropsOf<K extends keyof SlotMap & string> = (ScopeOf<K> extends 'session' ? SessionStandardProps : ScopeOf<K> extends 'session-maybe' ? SessionMaybeStandardProps : object) & GlobalStandardProps;
|
|
339
|
+
/**
|
|
340
|
+
* One function-valued slot-level inject.hooks member. The factory is pure and
|
|
341
|
+
* returns the actual custom Hook; it must not invoke a Hook while being bound.
|
|
342
|
+
*/
|
|
343
|
+
export type SlotHookFactory<K extends keyof SlotMap & string, Hook extends (...args: never[]) => unknown> = (standard: StandardPropsOf<K>, hookContext: HookContextOf<K>) => Hook;
|
|
344
|
+
/** Component-side Hook produced from one slot-level inject.hooks member. */
|
|
345
|
+
type BoundHookOf<Definition> = Definition extends HostObservable<infer Snapshot> ? SnapshotSelectorHook<Snapshot> : Definition extends (...args: never[]) => infer Hook ? Hook extends (...args: never[]) => unknown ? Hook : never : never;
|
|
346
|
+
/**
|
|
347
|
+
* Selector-hook share synthesized from a hooks compartment: each source
|
|
348
|
+
* `name` becomes a `use<Name>` selector hook over its snapshot type.
|
|
349
|
+
*/
|
|
350
|
+
export type PropsSlotHooks<HS extends object> = {
|
|
351
|
+
[N in keyof HS & string as `use${Capitalize<N>}`]: BoundHookOf<HS[N]>;
|
|
352
|
+
};
|
|
353
|
+
/** Component-side view of a slot dispatcher's common inject face. */
|
|
354
|
+
export type SlotInjectFace<I extends object> = I extends {
|
|
355
|
+
hooks: infer HS extends object;
|
|
356
|
+
} ? Omit<I, 'hooks'> & PropsSlotHooks<HS> : I;
|
|
357
|
+
/** Selector-hook share synthesized from an entry inject hooks compartment. */
|
|
358
|
+
export type PropsHooks<HS extends HooksSources> = {
|
|
359
|
+
[N in keyof HS & string as `use${Capitalize<N>}`]: SnapshotSelectorHook<HS[N] extends HostObservable<infer T> ? T : never>;
|
|
360
|
+
};
|
|
361
|
+
/** Selector-hook share synthesized from an entry inject keyed-hooks compartment. */
|
|
362
|
+
export type PropsKeyedHooks<HS extends KeyedHooksSources> = {
|
|
363
|
+
[N in keyof HS & string as `use${Capitalize<N>}`]: KeyedSnapshotSelectorHook<HS[N] extends (key: string) => HostObservable<infer T> | undefined ? T : never>;
|
|
364
|
+
};
|
|
365
|
+
/**
|
|
366
|
+
* The component-side view of an inject face: the reserved `hooks`
|
|
367
|
+
* compartment (when declared) arrives as bound `use<Name>` selector hooks;
|
|
368
|
+
* every other member passes through verbatim.
|
|
369
|
+
*/
|
|
370
|
+
export type InjectFace<I extends object> = I extends {
|
|
371
|
+
hooks: infer HS extends HooksSources;
|
|
372
|
+
} ? I extends {
|
|
373
|
+
keyedHooks: infer KS extends KeyedHooksSources;
|
|
374
|
+
} ? Omit<I, 'hooks' | 'keyedHooks'> & PropsHooks<HS> & PropsKeyedHooks<KS> : Omit<I, 'hooks'> & PropsHooks<HS> : I extends {
|
|
375
|
+
keyedHooks: infer KS extends KeyedHooksSources;
|
|
376
|
+
} ? Omit<I, 'keyedHooks'> & PropsKeyedHooks<KS> : I;
|
|
377
|
+
/**
|
|
378
|
+
* The composed component props intersection: runtime share (SlotMap) +
|
|
379
|
+
* child-render share (children declaration) + store share (declared handle) +
|
|
380
|
+
* the registrant's injected business face (its hooks compartment bound, see
|
|
381
|
+
* {@link InjectFace}) + the locale `t` seat (declared namespace, see
|
|
382
|
+
* {@link PropsLocale}). Each share derives from its single source of truth;
|
|
383
|
+
* components reference this composition, never re-type it.
|
|
384
|
+
*/
|
|
385
|
+
export type ComposedProps<K extends keyof SlotMap & string, EntryKey extends EntryKeyOf<K>, S extends keyof SlotMap & string, H, I extends object, M = never, N = undefined> = PropsRuntime<K, EntryKey> & PropsRenderSlots<S> & PropsStore<H> & InjectFace<I> & MatchedShare<SlotMap[K], M> & PropsLocale<N>;
|
|
386
|
+
/**
|
|
387
|
+
* Inject factory parameter list, derived from the registration's declaration:
|
|
388
|
+
* strict session slots receive a definite framework-resolved `sessionId`;
|
|
389
|
+
* session-maybe slots receive the current id or `undefined`; a declared store
|
|
390
|
+
* appends the baked `actions` (the same callbacks the component receives).
|
|
391
|
+
* Business data access happens through the apply closure's ctx — no binding
|
|
392
|
+
* object parameter exists.
|
|
393
|
+
*/
|
|
394
|
+
export type InjectParams<K extends keyof SlotMap & string, H> = ScopeOf<K> extends 'session' ? ([H] extends [StoreDecl] ? [sessionId: SessionIdOf, actions: BoundActions<HandleOf<H>>] : [sessionId: SessionIdOf]) : ScopeOf<K> extends 'session-maybe' ? ([H] extends [StoreDecl] ? [sessionId: SessionIdOf | undefined, actions: BoundActions<HandleOf<H>> | undefined] : [sessionId: SessionIdOf | undefined]) : ([H] extends [StoreDecl] ? [actions: BoundActions<HandleOf<H>>] : []);
|
|
395
|
+
/**
|
|
396
|
+
* A list-entry display label: a plain string, or a thunk re-evaluated per
|
|
397
|
+
* read so registration-time text (nav rows, tabs) follows the active locale
|
|
398
|
+
* without re-registration. Owners resolve through {@link resolveSlotLabel}.
|
|
399
|
+
*/
|
|
400
|
+
export type SlotLabel = string | (() => string);
|
|
401
|
+
/**
|
|
402
|
+
* Kind shape fields carried in register options (keyed dispatch key; list
|
|
403
|
+
* id/order/label; chain select/priority; non-chain priority = cell shadowing rank).
|
|
404
|
+
*/
|
|
405
|
+
export type KindOptions<K extends keyof SlotMap & string, EntryKey extends EntryKeyOf<K>, M = never> = SlotMap[K]['kind'] extends 'keyed' ? {
|
|
406
|
+
key: EntryKey;
|
|
407
|
+
/** Cell shadowing rank (ascending, default 0, lowest renders; same key + same priority throws — see {@link SlotCore.register}). */
|
|
408
|
+
priority?: number;
|
|
409
|
+
} : SlotMap[K]['kind'] extends 'list' ? {
|
|
410
|
+
id: string;
|
|
411
|
+
order?: number;
|
|
412
|
+
label?: SlotLabel;
|
|
413
|
+
/** Cell shadowing rank (ascending, default 0, lowest renders; same id + same priority throws — see {@link SlotCore.register}). */
|
|
414
|
+
priority?: number;
|
|
415
|
+
} : SlotMap[K]['kind'] extends 'chain' ? {
|
|
416
|
+
/** Routing selector, mandatory on chain entries; `M` (the component's `matched` prop) infers from its return. */
|
|
417
|
+
select: ChainSelect<SlotMap[K] extends {
|
|
418
|
+
owner: infer O extends object;
|
|
419
|
+
} ? O : object, M>;
|
|
420
|
+
/** Explicit chain position (ascending, default 0, lower tries first); ties keep registration = assembly order. */
|
|
421
|
+
priority?: number;
|
|
422
|
+
} : {
|
|
423
|
+
/**
|
|
424
|
+
* Cell shadowing rank (ascending, default 0, lowest renders; a
|
|
425
|
+
* same-priority second registration throws — see {@link SlotCore.register}).
|
|
426
|
+
*/
|
|
427
|
+
priority?: number;
|
|
428
|
+
};
|
|
429
|
+
/**
|
|
430
|
+
* Compile-time presence check: an entry declaring children MUST consume
|
|
431
|
+
* `renderSlot` (or `renderSlotChain` when its only children are chain slots)
|
|
432
|
+
* — declaring is claiming; an entry that does not render its children should
|
|
433
|
+
* not declare them. Evaluates to an unsatisfiable intersection member naming
|
|
434
|
+
* the declared keys when violated.
|
|
435
|
+
*/
|
|
436
|
+
type RendersCheck<C, D> = [
|
|
437
|
+
keyof D & keyof SlotMap & string
|
|
438
|
+
] extends [never] ? unknown : C extends (props: infer P) => ReactNode ? ('renderSlot' extends keyof P ? unknown : 'renderSlotChain' extends keyof P ? unknown : {
|
|
439
|
+
'children declared but the component consumes no renderSlot': keyof D & keyof SlotMap & string;
|
|
440
|
+
}) : unknown;
|
|
441
|
+
/** Common register options share (see {@link SlotCore.register} for semantics). */
|
|
442
|
+
type BaseOptions<K extends keyof SlotMap & string, EntryKey extends EntryKeyOf<K>, D extends ChildrenDecl, H, M = never, N = undefined> = {
|
|
443
|
+
/** Target slot key (the entry contributes INTO this slot). */
|
|
444
|
+
name: K;
|
|
445
|
+
/** Child-slot declaration + render authorization + runtime spec, in one table. */
|
|
446
|
+
children?: D;
|
|
447
|
+
/** Store seat: a shared handle (apply-constructed) or an exclusive factory (framework-called per entry x scope). */
|
|
448
|
+
store?: H;
|
|
449
|
+
/**
|
|
450
|
+
* Dictionary namespace of this entry's copy. Declaring it puts the
|
|
451
|
+
* framework-synthesized `t` seat (typed to the namespace's dictionary
|
|
452
|
+
* union) on the component props; rendering requires an installed locale
|
|
453
|
+
* face — fails loud otherwise.
|
|
454
|
+
*/
|
|
455
|
+
locale?: N;
|
|
456
|
+
/** Registrant identity label for diagnostics (the runtime Service wrapper stamps the caller's fiber name). */
|
|
457
|
+
registrant?: string;
|
|
458
|
+
} & KindOptions<K, EntryKey, M>;
|
|
459
|
+
/**
|
|
460
|
+
* One stored registration, as recorded by the core and read by the render
|
|
461
|
+
* machinery (type-erased at this boundary; the registration contract already proved
|
|
462
|
+
* the shares against the component).
|
|
463
|
+
*/
|
|
464
|
+
export interface StoredEntry {
|
|
465
|
+
component: unknown;
|
|
466
|
+
options: {
|
|
467
|
+
key?: string;
|
|
468
|
+
id?: string;
|
|
469
|
+
order?: number;
|
|
470
|
+
label?: SlotLabel;
|
|
471
|
+
priority?: number;
|
|
472
|
+
};
|
|
473
|
+
/** Chain routing selector (type-erased like `inject`; present exactly on chain-slot entries). */
|
|
474
|
+
select?: ((owner: never) => unknown) | undefined;
|
|
475
|
+
/** Registrant business face; positional params derive from the declaration (sessionId?, actions?). */
|
|
476
|
+
inject?: ((...args: never[]) => Record<string, unknown>) | undefined;
|
|
477
|
+
/** Child-slot declaration table (declaration + authorization + runtime spec in one). */
|
|
478
|
+
children?: Readonly<Record<string, SlotSpec<SlotEntryDef>>> | undefined;
|
|
479
|
+
/** Declared store seat (instance resolution and lifecycle live with the host machinery). */
|
|
480
|
+
store?: StoreDecl | undefined;
|
|
481
|
+
/** Declared dictionary namespace (the render machinery synthesizes the `t` seat from it). */
|
|
482
|
+
locale?: string | undefined;
|
|
483
|
+
/** Diagnostics label of who registered. */
|
|
484
|
+
registrant?: string | undefined;
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Resolve a possibly-thunked list label at read time (thunks follow the
|
|
488
|
+
* active locale; owners projecting ledger rows call this instead of reading
|
|
489
|
+
* `options.label` raw).
|
|
490
|
+
* @param label - the stored label.
|
|
491
|
+
* @returns the display string, or undefined when the entry declared none.
|
|
492
|
+
*/
|
|
493
|
+
export declare function resolveSlotLabel(label: SlotLabel | undefined): string | undefined;
|
|
494
|
+
/** JSON-safe live occupant returned by slot inspection. */
|
|
495
|
+
export interface LiveSlotOccupant {
|
|
496
|
+
/** Plugin or package that registered the entry, when known. */
|
|
497
|
+
registrant?: string;
|
|
498
|
+
/** Keyed-slot cell. */
|
|
499
|
+
key?: string;
|
|
500
|
+
/** List-slot cell. */
|
|
501
|
+
id?: string;
|
|
502
|
+
/** List display order. */
|
|
503
|
+
order?: number;
|
|
504
|
+
/** Shadowing or chain priority. */
|
|
505
|
+
priority: number;
|
|
506
|
+
/** Whether the renderer currently selects this entry. */
|
|
507
|
+
active: boolean;
|
|
508
|
+
}
|
|
509
|
+
/** JSON-safe live slot declaration tree. */
|
|
510
|
+
export interface LiveSlotNode {
|
|
511
|
+
/** Exact SlotMap key. */
|
|
512
|
+
name: string;
|
|
513
|
+
/** Slot cardinality. */
|
|
514
|
+
kind: SlotKind;
|
|
515
|
+
/** Runtime data scope. */
|
|
516
|
+
scope: SlotScope;
|
|
517
|
+
/** Diagnostic owner of this declaration. */
|
|
518
|
+
declaredBy?: string;
|
|
519
|
+
/** Current registrations in ledger order. */
|
|
520
|
+
occupants: LiveSlotOccupant[];
|
|
521
|
+
/** Slots declared by entries mounted in this slot. */
|
|
522
|
+
children: LiveSlotNode[];
|
|
523
|
+
}
|
|
524
|
+
/**
|
|
525
|
+
* Pure slot registry (no cordis; event emission and the renderer installation contract
|
|
526
|
+
* live in the runtime Service wrapper).
|
|
527
|
+
*
|
|
528
|
+
* The 'root' slot is the one a-priori declaration, seeded at construction
|
|
529
|
+
* (single/root, declared by the framework) — the render tree's root hole.
|
|
530
|
+
*
|
|
531
|
+
* Change propagation contract: versions bump and {@link SlotCore.onMutate}
|
|
532
|
+
* fires synchronously per mutation (registry state is consistent when they
|
|
533
|
+
* fire); {@link SlotCore.subscribeDeclaration} fires synchronously for each
|
|
534
|
+
* declaration lifetime boundary; {@link SlotCore.subscribe} notifications
|
|
535
|
+
* batch per microtask, so N same-tick mutations produce one notification per
|
|
536
|
+
* touched key. Entry crash reports ({@link SlotCore.reportEntryError}) ride
|
|
537
|
+
* the same mutation channel when they abdicate, then notify
|
|
538
|
+
* {@link SlotCore.onEntryError} synchronously.
|
|
539
|
+
*/
|
|
540
|
+
export declare class SlotCore {
|
|
541
|
+
private records;
|
|
542
|
+
private mutateListeners;
|
|
543
|
+
/** Shared-handle scope ledger: handle → the scope it first mounted under + live mount count. */
|
|
544
|
+
private handleScopes;
|
|
545
|
+
private dirty;
|
|
546
|
+
private flushScheduled;
|
|
547
|
+
/**
|
|
548
|
+
* Entries retired by an abdicating crash report
|
|
549
|
+
* ({@link SlotCore.reportEntryError}): excluded from
|
|
550
|
+
* {@link SlotCore.entriesOfSlot} projections for the rest of their
|
|
551
|
+
* registration's life, while the registration itself stays on the ledger
|
|
552
|
+
* (disposal authority remains with the registrant).
|
|
553
|
+
*/
|
|
554
|
+
private abdicated;
|
|
555
|
+
private entryErrorListeners;
|
|
556
|
+
constructor();
|
|
557
|
+
/**
|
|
558
|
+
* Contribute a component to a declared slot and (optionally) declare child
|
|
559
|
+
* slots, a store seat, and the registrant's business face.
|
|
560
|
+
*
|
|
561
|
+
* Load-time validation (misconfiguration fails loud; the render hot path
|
|
562
|
+
* re-checks nothing): registering into an undeclared slot throws; declaring
|
|
563
|
+
* an already-declared child key throws (one declarer per slot — the message
|
|
564
|
+
* names the first declarer); mounting one shared store handle under slots
|
|
565
|
+
* of different scopes throws. Kind constraints: keyed — missing `key`
|
|
566
|
+
* throws; list — missing `id` throws; chain — missing `select` throws (the
|
|
567
|
+
* selector is the entry's routing seat, see {@link ChainSelect}).
|
|
568
|
+
*
|
|
569
|
+
* Shadowing (single/keyed/list): entries sharing one cell (single — the
|
|
570
|
+
* slot itself; keyed — same `key`; list — same `id`) coexist at distinct
|
|
571
|
+
* priorities, sorted ascending with ties keeping registration order; the
|
|
572
|
+
* cell's lowest live entry renders ({@link SlotCore.entriesOfSlot}). A
|
|
573
|
+
* second registration at an occupied cell's exact priority (default 0)
|
|
574
|
+
* throws naming the occupant, so priority-less composition keeps the
|
|
575
|
+
* historical one-occupant-per-cell fail-loud.
|
|
576
|
+
*
|
|
577
|
+
* Lifecycle: the disposer removes the contribution AND collapses every
|
|
578
|
+
* declared child slot (child entries clear recursively; their stale
|
|
579
|
+
* disposers become no-ops) — one lifecycle axis, no dangling state.
|
|
580
|
+
*
|
|
581
|
+
* @param options - registration options: target `name`, `children`
|
|
582
|
+
* declaration table, `store` seat, `inject` business-face factory, kind
|
|
583
|
+
* shape fields (keyed `key`; list `id`/`order`/`label`).
|
|
584
|
+
* @param component - component honoring the four-share composed props
|
|
585
|
+
* contract ({@link ComposedProps}); checked at this call site.
|
|
586
|
+
* @returns disposer removing the registration and its declarations
|
|
587
|
+
* (idempotent; stale disposers after a cascade are no-ops).
|
|
588
|
+
*/
|
|
589
|
+
register<K extends keyof SlotMap & string, const EntryKey extends EntryKeyOf<K> = EntryKeyOf<K>, const D extends ChildrenDecl = Record<never, never>, H extends StoreDecl | undefined = undefined, M = never, N extends (keyof LocaleNamespaceMap & string) | undefined = undefined, C extends SlotComponent<never> = SlotComponent<never>>(options: BaseOptions<K, EntryKey, D, H, M, N> & {
|
|
590
|
+
inject?: undefined;
|
|
591
|
+
}, component: C & SlotComponent<ComposedProps<K, NoInfer<EntryKey>, keyof NoInfer<D> & keyof SlotMap & string, HandleOf<NoInfer<H>>, object, NoInfer<M>, NoInfer<N>>> & RendersCheck<C, D>): () => void;
|
|
592
|
+
/**
|
|
593
|
+
* Inject-bearing overload: identical semantics to the overload above, plus
|
|
594
|
+
* the registrant's business face — `I` is inferred from the inject
|
|
595
|
+
* factory's return and joins the component's composed-props constraint
|
|
596
|
+
* (factory parameters derive from the declaration, {@link InjectParams}).
|
|
597
|
+
* @param options - registration options plus the `inject` business-face factory.
|
|
598
|
+
* @param component - component honoring the four-share composed props
|
|
599
|
+
* contract including the inject share `I`.
|
|
600
|
+
* @returns disposer removing the registration and its declarations.
|
|
601
|
+
*/
|
|
602
|
+
register<K extends keyof SlotMap & string, I extends object, const EntryKey extends EntryKeyOf<K> = EntryKeyOf<K>, const D extends ChildrenDecl = Record<never, never>, H extends StoreDecl | undefined = undefined, M = never, N extends (keyof LocaleNamespaceMap & string) | undefined = undefined, C extends SlotComponent<never> = SlotComponent<never>>(options: BaseOptions<K, EntryKey, D, H, M, N> & {
|
|
603
|
+
inject: (...args: InjectParams<K, H>) => I;
|
|
604
|
+
}, component: C & SlotComponent<ComposedProps<K, NoInfer<EntryKey>, keyof NoInfer<D> & keyof SlotMap & string, HandleOf<NoInfer<H>>, I, NoInfer<M>, NoInfer<N>>> & RendersCheck<C, D>): () => void;
|
|
605
|
+
/**
|
|
606
|
+
* Whether a previously obtained entry is still registered (the render
|
|
607
|
+
* machinery's stale-authorization probe: a retained renderSlot binding
|
|
608
|
+
* whose entry left the ledger must not render).
|
|
609
|
+
* @param entry - a previously read entry.
|
|
610
|
+
* @returns false once the entry's registration was disposed.
|
|
611
|
+
*/
|
|
612
|
+
isLive(entry: StoredEntry): boolean;
|
|
613
|
+
/**
|
|
614
|
+
* Snapshot the registered entries for a key. Returns the cached array
|
|
615
|
+
* reference (stable between mutations — safe as a uSES getSnapshot source);
|
|
616
|
+
* empty for keys not (or no longer) declared, so renderers may probe ahead
|
|
617
|
+
* of plugin load order.
|
|
618
|
+
* @param key - slot key (dynamic: the render machinery holds keys as strings).
|
|
619
|
+
* @returns entries in registration (list: order) sequence.
|
|
620
|
+
*/
|
|
621
|
+
entries(key: string): readonly StoredEntry[];
|
|
622
|
+
/**
|
|
623
|
+
* Project a key's entries to its shadowing winners: the first live
|
|
624
|
+
* (non-abdicated) entry of each cell in priority order — single: the slot
|
|
625
|
+
* is one cell; keyed: one cell per `key`; list: one cell per `id` (winners
|
|
626
|
+
* keep ledger sequence; list renderers still refine display by `order`).
|
|
627
|
+
* Chain keys return the raw entries unchanged: election consumes every
|
|
628
|
+
* entry, shadowing does not apply. The raw {@link SlotCore.entries} view
|
|
629
|
+
* stays the inspection surface. Builds a fresh array per call — a render
|
|
630
|
+
* body read, not a uSES getSnapshot source.
|
|
631
|
+
* @param key - slot key (dynamic: the render machinery holds keys as strings).
|
|
632
|
+
* @returns the winning entry per occupied cell (empty while undeclared).
|
|
633
|
+
*/
|
|
634
|
+
entriesOfSlot(key: string): readonly StoredEntry[];
|
|
635
|
+
/**
|
|
636
|
+
* Look up a slot's declared spec, narrowed by the SlotMap key.
|
|
637
|
+
* @param key - SlotMap key.
|
|
638
|
+
* @returns the spec, or undefined while undeclared.
|
|
639
|
+
*/
|
|
640
|
+
spec<K extends keyof SlotMap & string>(key: K): SlotSpec<SlotMap[K]> | undefined;
|
|
641
|
+
/**
|
|
642
|
+
* Dynamic-key escape hatch for spec lookup — renderers resolving keys they
|
|
643
|
+
* only hold as strings (generic dispatch) use this wide form; statically
|
|
644
|
+
* keyed callers use {@link SlotCore.spec}.
|
|
645
|
+
* @param key - candidate slot key.
|
|
646
|
+
* @returns the wide-typed spec, or undefined while undeclared.
|
|
647
|
+
*/
|
|
648
|
+
specDynamic(key: string): SlotSpec<SlotEntryDef> | undefined;
|
|
649
|
+
/**
|
|
650
|
+
* Export the current declaration topology without components or executable hooks.
|
|
651
|
+
* @param root - exact Slot key to select; omitted returns every live root.
|
|
652
|
+
* @returns selected live Slot trees, or an empty array when `root` is unavailable.
|
|
653
|
+
*/
|
|
654
|
+
snapshot(root?: string): LiveSlotNode[];
|
|
655
|
+
/**
|
|
656
|
+
* Read the declaration lifetime of a key. Entry additions and removals do
|
|
657
|
+
* not change it; declaration creation and collapse each advance it.
|
|
658
|
+
* @param key - slot key.
|
|
659
|
+
* @returns monotonic epoch (0 before the first declaration).
|
|
660
|
+
*/
|
|
661
|
+
declarationEpoch(key: string): number;
|
|
662
|
+
/**
|
|
663
|
+
* Subscribe to registration changes for a key (microtask-batched).
|
|
664
|
+
* Subscribing ahead of declaration is allowed; the declaration notifies.
|
|
665
|
+
* @param key - slot key.
|
|
666
|
+
* @param fn - change callback.
|
|
667
|
+
* @returns unsubscribe.
|
|
668
|
+
*/
|
|
669
|
+
subscribe(key: string, fn: () => void): () => void;
|
|
670
|
+
/**
|
|
671
|
+
* Subscribe to declaration lifetime boundaries for a key. Notifications
|
|
672
|
+
* are synchronous so declaration teardown finishes before a subsequent
|
|
673
|
+
* same-tick registration can observe stale resources. Ordinary entry
|
|
674
|
+
* mutations do not notify this surface. A children table commits every
|
|
675
|
+
* sibling declaration before its first notification.
|
|
676
|
+
* @param key - slot key.
|
|
677
|
+
* @param fn - declaration or collapse callback.
|
|
678
|
+
* @returns unsubscribe.
|
|
679
|
+
*/
|
|
680
|
+
subscribeDeclaration(key: string, fn: () => void): () => void;
|
|
681
|
+
/**
|
|
682
|
+
* Monotonic version for a key, bumped synchronously per mutation so a
|
|
683
|
+
* uSES getSnapshot read is never stale when its batched notification lands.
|
|
684
|
+
* @param key - slot key.
|
|
685
|
+
* @returns current version (0 for untouched keys).
|
|
686
|
+
*/
|
|
687
|
+
getVersion(key: string): number;
|
|
688
|
+
/**
|
|
689
|
+
* Hook every mutation (the runtime Service wrapper bridges this to ctx.emit).
|
|
690
|
+
* Fires synchronously per mutation, unbatched — event semantics need one
|
|
691
|
+
* emission per change.
|
|
692
|
+
* @param fn - called with the mutated key.
|
|
693
|
+
* @returns unsubscribe.
|
|
694
|
+
*/
|
|
695
|
+
onMutate(fn: (key: string) => void): () => void;
|
|
696
|
+
/**
|
|
697
|
+
* Renderer crash report from an entry boundary. Always notifies
|
|
698
|
+
* {@link SlotCore.onEntryError} listeners; with `info.abdicate` set (the
|
|
699
|
+
* shadowing kinds — single/keyed/list) it first retires the entry from its
|
|
700
|
+
* cell, one-shot: the record's version bumps through the ordinary mutation
|
|
701
|
+
* channel so outlets re-project onto the cell's next survivor, and a
|
|
702
|
+
* repeat abdicating report no-ops entirely. Chain crashes report with
|
|
703
|
+
* `abdicate: false` — election alternatives resolve at select time, so the
|
|
704
|
+
* entry keeps its cell and only the notification fires. The registration
|
|
705
|
+
* itself stays on the ledger either way — raw {@link SlotCore.entries}
|
|
706
|
+
* still lists the entry and its disposer keeps working.
|
|
707
|
+
* @param key - slot key the entry rendered under.
|
|
708
|
+
* @param entry - the crashed entry.
|
|
709
|
+
* @param error - the crash cause, forwarded to listeners verbatim.
|
|
710
|
+
* @param info - `abdicate`: whether the crash retires the entry from its cell.
|
|
711
|
+
*/
|
|
712
|
+
reportEntryError(key: string, entry: StoredEntry, error: unknown, info: {
|
|
713
|
+
abdicate: boolean;
|
|
714
|
+
}): void;
|
|
715
|
+
/**
|
|
716
|
+
* Observe entry boundary crashes (every render-time entry failure the
|
|
717
|
+
* boundaries contain, abdicating or not) — the supervision seam for hosts
|
|
718
|
+
* mirroring contribution health. Fires synchronously per report, after the
|
|
719
|
+
* registry mutated for abdicating crashes (same listener discipline as
|
|
720
|
+
* {@link SlotCore.onMutate}).
|
|
721
|
+
* @param fn - called with the slot key, the crashed entry, the crash
|
|
722
|
+
* cause, and `abdicated`: whether the crash retired the entry from its cell.
|
|
723
|
+
* @returns unsubscribe.
|
|
724
|
+
*/
|
|
725
|
+
onEntryError(fn: (key: string, entry: StoredEntry, error: unknown, info: {
|
|
726
|
+
abdicated: boolean;
|
|
727
|
+
}) => void): () => void;
|
|
728
|
+
/**
|
|
729
|
+
* Cascade for a removed entry: release its store mount and collapse every
|
|
730
|
+
* child slot it declared — specs clear, contributions empty (their stale
|
|
731
|
+
* disposers no-op), recursively down the declaration tree. One lifecycle
|
|
732
|
+
* axis: ledger rows, slots, contributions, and store mounts die together.
|
|
733
|
+
*/
|
|
734
|
+
private releaseEntry;
|
|
735
|
+
private record;
|
|
736
|
+
private markDirty;
|
|
737
|
+
private notifyDeclaration;
|
|
738
|
+
private flush;
|
|
739
|
+
}
|
|
740
|
+
//# sourceMappingURL=index.d.ts.map
|