@almadar/ui 6.59.0 → 6.62.0

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.
Files changed (91) hide show
  1. package/dist/BehaviorValueFrame-3ORZHPWQ.css +1252 -0
  2. package/dist/BehaviorValueFrame-QYFJEMN5.js +18 -0
  3. package/dist/TraitValueFrame-2WMYJOA5.css +1252 -0
  4. package/dist/TraitValueFrame-X6IL3UST.js +17 -0
  5. package/dist/Typography-KBATMU2V.js +5 -0
  6. package/dist/{UISlotRenderer-YNY7V2UJ.js → UISlotRenderer-NZBV5BUI.js} +12 -10
  7. package/dist/avl/index.cjs +32263 -28103
  8. package/dist/avl/index.d.ts +36 -13
  9. package/dist/avl/index.js +298 -6130
  10. package/dist/{avl-3d-context-BpBKZIbc.d.ts → avl-3d-context-Dxun3-ri.d.ts} +2 -0
  11. package/dist/{chunk-YYYHH5BA.js → chunk-7JRWELUC.js} +4 -6
  12. package/dist/{chunk-723MJUU3.js → chunk-CXQENFO2.js} +1 -1
  13. package/dist/chunk-D4NAA2JW.js +49 -0
  14. package/dist/{chunk-I5QOYW2Z.js → chunk-DXPCAQJU.js} +205 -2
  15. package/dist/{chunk-J755QADM.js → chunk-EDPUQ2ZJ.js} +327 -18
  16. package/dist/{chunk-4ZGXIW3B.js → chunk-ERDYADVZ.js} +1 -1
  17. package/dist/{chunk-7CVXM2KS.js → chunk-EZ5FSNOE.js} +2 -2
  18. package/dist/{chunk-E6MWYQVZ.js → chunk-G6EFTACU.js} +9713 -786
  19. package/dist/{chunk-MZIDOJMD.js → chunk-GVQOTA7T.js} +2 -1
  20. package/dist/{chunk-Q47ZN2DW.js → chunk-N23SVGTH.js} +83 -1
  21. package/dist/{chunk-KJGVLXEN.js → chunk-N4IJS5DD.js} +50 -116
  22. package/dist/{chunk-LZRW6GXG.js → chunk-QOV3TUAA.js} +2 -3
  23. package/dist/chunk-WBWXBA5H.js +434 -0
  24. package/dist/{chunk-V3FGTQUE.js → chunk-ZR45FGW3.js} +7 -1
  25. package/dist/{cn-DIql5232.d.ts → cn-CDIhHCUC.d.ts} +40 -16
  26. package/dist/components/index.cjs +14779 -4354
  27. package/dist/components/index.d.ts +200 -180
  28. package/dist/components/index.js +16 -17
  29. package/dist/context/index.cjs +9 -1
  30. package/dist/context/index.js +3 -1
  31. package/dist/hooks/index.cjs +78 -9
  32. package/dist/hooks/index.d.ts +43 -2
  33. package/dist/hooks/index.js +6 -7
  34. package/dist/lib/drawable/three/index.cjs +361 -27
  35. package/dist/lib/drawable/three/index.d.ts +2 -2
  36. package/dist/lib/drawable/three/index.js +28 -7
  37. package/dist/lib/index.cjs +117 -5
  38. package/dist/lib/index.d.ts +2 -2
  39. package/dist/lib/index.js +99 -6
  40. package/dist/locales/index.cjs +6 -9
  41. package/dist/locales/index.js +2 -2
  42. package/dist/providers/index.cjs +14137 -1311
  43. package/dist/providers/index.d.ts +36 -4
  44. package/dist/providers/index.js +37 -17
  45. package/dist/runtime/index.cjs +28769 -18640
  46. package/dist/runtime/index.d.ts +70 -3
  47. package/dist/runtime/index.js +15 -381
  48. package/dist/ssr/index.cjs +508 -134
  49. package/dist/ssr/index.d.cts +56 -4
  50. package/dist/ssr/index.d.ts +56 -4
  51. package/dist/ssr/index.js +446 -72
  52. package/dist/{verificationRegistry-B3dj1Zl8.d.ts → verificationRegistry-B5aGl7WF.d.ts} +2 -1
  53. package/locales/ar.json +2 -3
  54. package/locales/en.json +2 -3
  55. package/locales/sl.json +2 -3
  56. package/package.json +8 -8
  57. package/tailwind-preset.cjs +78 -8
  58. package/themes/_base.css +27 -0
  59. package/themes/_contract.md +6 -0
  60. package/themes/_fonts.css +4 -4
  61. package/themes/_foundation.css +11 -0
  62. package/themes/_presets.css +2 -0
  63. package/themes/almadar-website.css +10 -0
  64. package/themes/almadar.css +10 -0
  65. package/themes/atelier.css +10 -0
  66. package/themes/bauhaus.css +10 -0
  67. package/themes/bloomberg-dense.css +10 -0
  68. package/themes/clay.css +10 -0
  69. package/themes/corporate.css +10 -0
  70. package/themes/gazette.css +10 -0
  71. package/themes/glass.css +10 -0
  72. package/themes/kflow.css +5 -0
  73. package/themes/kiosk.css +10 -0
  74. package/themes/linear-clean.css +10 -0
  75. package/themes/material.css +10 -0
  76. package/themes/minimalist.css +10 -0
  77. package/themes/nata.css +304 -0
  78. package/themes/neon.css +10 -0
  79. package/themes/notion-editorial.css +10 -0
  80. package/themes/orb.css +10 -0
  81. package/themes/prism.css +10 -0
  82. package/themes/rawi.css +304 -0
  83. package/themes/retro.css +10 -0
  84. package/themes/risograph.css +10 -0
  85. package/themes/scandi.css +10 -0
  86. package/themes/solarpunk.css +10 -0
  87. package/themes/terminal.css +138 -128
  88. package/dist/Typography-LZTP72Y4.js +0 -5
  89. package/dist/chunk-D2E44ODB.js +0 -350
  90. package/dist/chunk-N7JIG57B.js +0 -138
  91. package/dist/chunk-QJIAJ6EH.js +0 -2256
@@ -1,4 +1,4 @@
1
- import { EventPayload, OrbitalDefinition, PersistenceAdapter, ServiceParams, TraitConfig, UserContext, ResolvedTraitBinding, ResolvedPage, ResolvedEntity, ResolvedTrait, ResolvedIR, OrbitalSchema, PatternConfig, ResolvedPatternProps, EventSource, SExpr, EntityData, MessageCatalogs } from '@almadar/core';
1
+ import { EventPayload, OrbitalDefinition, PersistenceAdapter, ServiceParams, TraitConfig, UserContext, ResolvedTraitBinding, ResolvedPage, ResolvedEntity, ResolvedTrait, ResolvedIR, OrbitalSchema, PatternConfig, ResolvedPatternProps, EventSource, SExpr, EntityData, ViewerAuthority, MessageCatalogs, TraitValue, TraitValueMountResult, BehaviorRef, BehaviorValueMountResult } from '@almadar/core';
2
2
  export { ResolvedEntity, ResolvedIR, ResolvedPage, ResolvedTrait, ResolvedTraitBinding } from '@almadar/core';
3
3
  import { TraitState, EventTransport, AccessTokenProvider, SchemaLoader } from '@almadar/runtime';
4
4
  export { AccessTokenProvider, ClientEventBus, CreateClientEffectHandlersOptions, SlotSetter, createClientEffectHandlers } from '@almadar/runtime';
@@ -206,6 +206,13 @@ interface OrbPreviewProps {
206
206
  * it does on the server. Omitted → anonymous.
207
207
  */
208
208
  user?: UserData | null;
209
+ /**
210
+ * What the host's auth provider has resolved the viewer to be. An
211
+ * `access: authenticated` page mounts only on `authenticated`; any other
212
+ * resolved value sends the viewer to the app's `signIn` route. Omitted → the
213
+ * host offers no sign-in (`unavailable`).
214
+ */
215
+ authority?: ViewerAuthority;
209
216
  /**
210
217
  * Sandbox mode, for previews embedded in a host app (e.g. the studio
211
218
  * canvas): the event bus stays context-local, navigation stays in memory
@@ -246,8 +253,20 @@ interface OrbPreviewProps {
246
253
  * loaded behavior hands links back to the schema that imported it.
247
254
  */
248
255
  onUnmatchedNavigate?: (path: string) => void;
256
+ /**
257
+ * The host's own sign-in (`HOST_SIGN_IN_ROUTE`, `/login`): navigating there —
258
+ * including an `access: authenticated` page sending its viewer to
259
+ * `signIn: "/login"` — calls this with the return path instead of routing to a
260
+ * page. Omitted → the host offers no sign-in and nothing happens.
261
+ */
262
+ onSignIn?: (returnTo?: string) => void;
263
+ /**
264
+ * The host's session sign-out, called on the system event `UI:SIGN_OUT` (a
265
+ * Sign out inside the circuit). Omitted → the host offers no sign-out.
266
+ */
267
+ onSignOut?: () => void;
249
268
  }
250
- declare function OrbPreview({ schema, mockData, autoMock, height, className, serverUrl, transport, getAccessToken, initialPagePath, isolated, fit, onPageChange, user, localFallbackTimeoutMs, themeOverride, lazyLoader, schemaPath, onUnmatchedNavigate, }: OrbPreviewProps): React__default.ReactElement;
269
+ declare function OrbPreview({ schema, mockData, autoMock, height, className, serverUrl, transport, getAccessToken, initialPagePath, isolated, fit, onPageChange, user, authority, localFallbackTimeoutMs, themeOverride, lazyLoader, schemaPath, onUnmatchedNavigate, onSignIn, onSignOut, }: OrbPreviewProps): React__default.ReactElement;
251
270
  declare namespace OrbPreview {
252
271
  var displayName: string;
253
272
  }
@@ -404,4 +423,52 @@ declare function useOrbitalPluginHost(): {
404
423
  */
405
424
  declare function OrbitalPluginHost({ plugins, mode, transport, deny, navigate, onTransition, children, }: OrbitalPluginHostProps): React__default.ReactElement;
406
425
 
407
- export { BrowserPlayground, type BrowserPlaygroundProps, OrbPreview, type OrbPreviewProps, OrbitalPluginHost, type OrbitalPluginHostProps, type PluginHostDenyVerb, type PluginHostInbound, type PluginHostPlugin, type ResolvedSchemaResult, ServerBridgeTransport, type SlotPatternEntry, type SlotSource, type TraitStateMachineResult, type UseTraitStateMachineOptions, clearSchemaCache, useDeclaredCaptureTable, useOrbitalPluginHost, useResolvedSchema, useTraitStateMachine };
426
+ /**
427
+ * TraitValueFrame — renders a trait VALUE (a trait of an installed behavior held
428
+ * as data, language trio) where a render tree embeds it, the data-bound sibling
429
+ * of `TraitFrame`'s `@trait.X` lens.
430
+ *
431
+ * The host turns the value into a runnable program (`TraitValueMountProvider`'s
432
+ * `mount`: a validated, resolved one-orbital wrapper — the binding's admission
433
+ * check), and the frame runs it through the plugin host's own runtime, bridged
434
+ * to the ambient event bus, inside a scoped slot provider so the trait's UI
435
+ * paints HERE rather than into the app's shared slots. `INIT` reaches the
436
+ * mounted trait through the plugin host's declared inbound table.
437
+ *
438
+ * @packageDocumentation
439
+ */
440
+
441
+ /** How the host mounts trait values: the resolver plus the plugin-host execution mode. */
442
+ interface TraitValueMountHost {
443
+ mount: (value: TraitValue) => Promise<TraitValueMountResult>;
444
+ /** 'mock' (default): in-memory, as a preview. 'server': through `transport`. */
445
+ mode?: 'mock' | 'server';
446
+ transport?: EventTransport;
447
+ /** Mounts a whole behavior value (`BehaviorValueFrame`); a host without it cannot run behavior values. */
448
+ mountBehavior?: (value: BehaviorRef) => Promise<BehaviorValueMountResult>;
449
+ /** Where a mounted behavior value's events run; in-memory when omitted. */
450
+ behaviorTransport?: ServerBridgeTransport;
451
+ }
452
+ declare function TraitValueMountProvider({ host, children }: {
453
+ host: TraitValueMountHost;
454
+ children: ReactNode;
455
+ }): React__default.ReactElement;
456
+ declare function TraitValueFrame({ value }: {
457
+ value: TraitValue;
458
+ }): React__default.ReactElement;
459
+
460
+ /**
461
+ * BehaviorValueFrame — renders a whole behavior VALUE (`.lolo` type `behavior`,
462
+ * `behavior/ref`) where a render tree embeds it: the host mounts the program
463
+ * (validated at 0/0 and resolved), and the frame runs it in place through an
464
+ * isolated `OrbPreview` — its own event bus, in-memory navigation starting at the
465
+ * program's first page, the host URL untouched.
466
+ *
467
+ * @packageDocumentation
468
+ */
469
+
470
+ declare function BehaviorValueFrame({ value }: {
471
+ value: BehaviorRef;
472
+ }): React__default.ReactElement;
473
+
474
+ export { BehaviorValueFrame, BrowserPlayground, type BrowserPlaygroundProps, OrbPreview, type OrbPreviewProps, OrbitalPluginHost, type OrbitalPluginHostProps, type PluginHostDenyVerb, type PluginHostInbound, type PluginHostPlugin, type ResolvedSchemaResult, ServerBridgeTransport, type SlotPatternEntry, type SlotSource, type TraitStateMachineResult, TraitValueFrame, type TraitValueMountHost, TraitValueMountProvider, type UseTraitStateMachineOptions, clearSchemaCache, useDeclaredCaptureTable, useOrbitalPluginHost, useResolvedSchema, useTraitStateMachine };
@@ -1,387 +1,21 @@
1
- export { BrowserPlayground, OrbPreview, adjustSchemaForMockData, buildMockData, clearSchemaCache, prepareSchemaForPreview, useResolvedSchema, useTraitStateMachine } from '../chunk-QJIAJ6EH.js';
1
+ export { BehaviorValueFrame } from '../chunk-D4NAA2JW.js';
2
+ export { OrbitalPluginHost, TraitValueFrame, TraitValueMountProvider, useDeclaredCaptureTable, useOrbitalPluginHost } from '../chunk-WBWXBA5H.js';
2
3
  export { assertUniqueSlotsPerHost } from '../chunk-O2EIWXWE.js';
3
- import '../chunk-N7JIG57B.js';
4
- import '../chunk-L3MTZ3RH.js';
5
- import '../chunk-YYYHH5BA.js';
6
- export { wrapCallbackForEvent } from '../chunk-E6MWYQVZ.js';
7
- import '../chunk-J755QADM.js';
8
- import '../chunk-4ZGXIW3B.js';
9
- import '../chunk-I5QOYW2Z.js';
10
- import '../chunk-XJTHMW4G.js';
11
- import { useEventBus } from '../chunk-CHNC4UYE.js';
12
- export { PERF_NAMESPACE, clearPerf, perfEnd, perfStart, perfTime, profilerOnRender, usePerfBuffer } from '../chunk-KJGVLXEN.js';
13
- import '../chunk-Q47ZN2DW.js';
14
- import '../chunk-64WACXM7.js';
15
- import '../chunk-723MJUU3.js';
16
- import '../chunk-LZRW6GXG.js';
4
+ export { BrowserPlayground, OrbPreview, adjustSchemaForMockData, buildMockData, clearSchemaCache, prepareSchemaForPreview, useResolvedSchema, useTraitStateMachine, wrapCallbackForEvent } from '../chunk-G6EFTACU.js';
17
5
  import '../chunk-PQKU62LK.js';
6
+ import '../chunk-EDPUQ2ZJ.js';
7
+ import '../chunk-ERDYADVZ.js';
8
+ import '../chunk-DXPCAQJU.js';
9
+ import '../chunk-XJTHMW4G.js';
10
+ import '../chunk-CHNC4UYE.js';
11
+ import '../chunk-L3MTZ3RH.js';
18
12
  import '../chunk-PEST66PN.js';
13
+ import '../chunk-7JRWELUC.js';
14
+ export { PERF_NAMESPACE, clearPerf, perfEnd, perfStart, perfTime, profilerOnRender, usePerfBuffer } from '../chunk-N4IJS5DD.js';
15
+ import '../chunk-N23SVGTH.js';
16
+ import '../chunk-64WACXM7.js';
17
+ import '../chunk-CXQENFO2.js';
18
+ import '../chunk-QOV3TUAA.js';
19
19
  import '../chunk-QPXIAUJD.js';
20
20
  export { EntitySchemaProvider, ServerBridgeProvider, TraitContext, TraitProvider, useEntitySchema, useEntitySchemaOptional, useServerBridge, useTrait, useTraitContext } from '@almadar/ui/providers';
21
21
  export { createClientEffectHandlers } from '@almadar/runtime';
22
- import { createContext, useMemo, useState, useRef, useCallback, useContext, useEffect } from 'react';
23
- import { OrbitalServerRuntime } from '@almadar/runtime/OrbitalServerRuntime';
24
- import { UI_SLOTS } from '@almadar/core';
25
- import { createLogger } from '@almadar/logger';
26
- import { useTranslate } from '@almadar/ui/hooks';
27
- import { useUISlots } from '@almadar/ui/context';
28
- import { jsxs, jsx } from 'react/jsx-runtime';
29
-
30
- var log = createLogger("almadar:ui:plugin-host");
31
- var UI_SLOT_SET = new Set(UI_SLOTS);
32
- function isUISlot(value) {
33
- return UI_SLOT_SET.has(value);
34
- }
35
- var OrbitalPluginHostContext = createContext(null);
36
- function useOrbitalPluginHostContext(caller) {
37
- const ctx = useContext(OrbitalPluginHostContext);
38
- if (!ctx) {
39
- throw new Error(`${caller} must be used within an <OrbitalPluginHost>.`);
40
- }
41
- return ctx;
42
- }
43
- function isTraitState(value) {
44
- return value !== void 0 && typeof value.currentState === "string";
45
- }
46
- function toTraitState(runtime, orbital, trait, stateName, lastEvent) {
47
- if (runtime) {
48
- const raw = runtime.getState(orbital, trait);
49
- if (isTraitState(raw)) return raw;
50
- }
51
- return { traitName: trait, currentState: stateName, previousState: null, lastEvent, context: {} };
52
- }
53
- function isKeymapValue(value) {
54
- if (value === null || value === void 0 || typeof value !== "object" || Array.isArray(value)) return false;
55
- return Object.values(value).every((entry) => Array.isArray(entry) && entry.every((k) => typeof k === "string"));
56
- }
57
- function findInlineTrait(schema, orbitalName, traitName) {
58
- const orbital = schema.orbitals.find((o) => o.name === orbitalName);
59
- if (!orbital) return void 0;
60
- for (const ref of orbital.traits) {
61
- if (typeof ref === "string") continue;
62
- if ("ref" in ref) continue;
63
- if (ref.name === traitName) return ref;
64
- }
65
- return void 0;
66
- }
67
- function readKeymapConfig(trait, knob) {
68
- const declared = trait?.config?.[knob]?.default;
69
- return isKeymapValue(declared) ? declared : {};
70
- }
71
- function traitNamesOf(orbital) {
72
- const names = [];
73
- for (const ref of orbital.traits) {
74
- if (typeof ref === "string") {
75
- names.push(ref);
76
- } else if ("ref" in ref) {
77
- if (ref.name) names.push(ref.name);
78
- } else {
79
- names.push(ref.name);
80
- }
81
- }
82
- return names;
83
- }
84
- function useDeclaredCaptureTable(opts) {
85
- const { pluginId, orbital, trait, keymapKnob = "keymap", target = "shell" } = opts;
86
- const ctx = useOrbitalPluginHostContext("useDeclaredCaptureTable");
87
- return useMemo(() => {
88
- const schema = ctx.getPluginSchema(pluginId);
89
- const inlineTrait = schema ? findInlineTrait(schema, orbital, trait) : void 0;
90
- const keymap = readKeymapConfig(inlineTrait, keymapKnob);
91
- const currentState = ctx.getState(pluginId, orbital, trait)?.currentState;
92
- const keys = currentState !== void 0 ? keymap[currentState] ?? [] : [];
93
- const entry = { mode: currentState ?? "unknown", keys: new Set(keys) };
94
- const targets = Array.isArray(target) ? target : [target];
95
- const table = {};
96
- for (const t of targets) table[t] = entry;
97
- return table;
98
- }, [ctx, pluginId, orbital, trait, keymapKnob, target]);
99
- }
100
- function useOrbitalPluginHost() {
101
- const ctx = useOrbitalPluginHostContext("useOrbitalPluginHost");
102
- return { getState: ctx.getState, lastEvent: ctx.lastEvent, errors: ctx.errors };
103
- }
104
- function buildMockEffectHandlers(opts) {
105
- const { pluginId, denySet, slotsRef, renderedSlotsRef, navigateRef } = opts;
106
- const handlers = {
107
- renderUI: (slot, pattern, props, priority) => {
108
- if (!isUISlot(slot)) {
109
- log.warn("renderUI:unknown-slot", { pluginId, slot });
110
- return;
111
- }
112
- if (pattern === null) {
113
- slotsRef.current.clearBySource(slot, pluginId);
114
- return;
115
- }
116
- renderedSlotsRef.current.add(slot);
117
- slotsRef.current.render({ target: slot, pattern: pattern.type, props, priority, sourceTrait: pluginId });
118
- }
119
- };
120
- if (denySet.has("navigate")) {
121
- handlers.navigate = (path) => log.warn("navigate:denied", { pluginId, path });
122
- } else if (navigateRef.current) {
123
- handlers.navigate = (path) => navigateRef.current?.(path);
124
- }
125
- if (denySet.has("persist")) {
126
- handlers.persist = async (action, entityType) => {
127
- log.warn("persist:denied", { pluginId, action, entityType });
128
- return void 0;
129
- };
130
- }
131
- if (denySet.has("call-service")) {
132
- handlers.callService = async (service, action) => {
133
- log.warn("call-service:denied", { pluginId, service, action });
134
- return null;
135
- };
136
- }
137
- return handlers;
138
- }
139
- function PluginRuntimeMount({
140
- plugin,
141
- mode,
142
- transport,
143
- deny,
144
- navigate,
145
- onTransition,
146
- onDispatched,
147
- onError
148
- }) {
149
- const bus = useEventBus();
150
- const { locale } = useTranslate();
151
- const slots = useUISlots();
152
- const slotsRef = useRef(slots);
153
- slotsRef.current = slots;
154
- const renderedSlotsRef = useRef(/* @__PURE__ */ new Set());
155
- const navigateRef = useRef(navigate);
156
- navigateRef.current = navigate;
157
- const [mockRuntime] = useState(() => {
158
- if (mode !== "mock") return void 0;
159
- return new OrbitalServerRuntime({
160
- mode: "mock",
161
- debug: false,
162
- effectHandlers: buildMockEffectHandlers({
163
- pluginId: plugin.id,
164
- denySet: new Set(deny ?? []),
165
- slotsRef,
166
- renderedSlotsRef,
167
- navigateRef
168
- })
169
- });
170
- });
171
- const registrationReady = useMemo(() => {
172
- if (mockRuntime) return mockRuntime.register(plugin.schema);
173
- if (mode === "server" && transport) return transport.register(plugin.schema);
174
- return Promise.resolve();
175
- }, [mockRuntime, transport, mode, plugin.schema]);
176
- useEffect(() => {
177
- if (mode === "server" && !transport) {
178
- onError(plugin.id, 'OrbitalPluginHost: mode "server" requires a transport');
179
- }
180
- }, [mode, transport, plugin.id, onError]);
181
- const teardownTimerRef = useRef(null);
182
- useEffect(() => {
183
- if (teardownTimerRef.current !== null) {
184
- clearTimeout(teardownTimerRef.current);
185
- teardownTimerRef.current = null;
186
- }
187
- return () => {
188
- teardownTimerRef.current = setTimeout(() => {
189
- teardownTimerRef.current = null;
190
- if (mockRuntime) {
191
- mockRuntime.unregisterAll();
192
- } else if (mode === "server" && transport) {
193
- void transport.unregister();
194
- }
195
- for (const slot of renderedSlotsRef.current) {
196
- slotsRef.current.clearBySource(slot, plugin.id);
197
- }
198
- }, 0);
199
- };
200
- }, [mockRuntime, transport, mode, plugin.id]);
201
- const ownOrbitals = useMemo(
202
- () => new Set(plugin.schema.orbitals.map((o) => o.name)),
203
- [plugin.schema]
204
- );
205
- const inboundBusEvents = useMemo(
206
- () => new Set(plugin.inbound.map((row) => row.busEvent)),
207
- [plugin.inbound]
208
- );
209
- const inboundTriggerNames = useMemo(
210
- () => new Set(plugin.inbound.map((row) => row.trigger)),
211
- [plugin.inbound]
212
- );
213
- const snapshotAllStates = useCallback(() => {
214
- const states = [];
215
- if (!mockRuntime) return states;
216
- for (const orbital of plugin.schema.orbitals) {
217
- for (const traitName of traitNamesOf(orbital)) {
218
- const raw = mockRuntime.getState(orbital.name, traitName);
219
- if (isTraitState(raw)) states.push([orbital.name, traitName, raw]);
220
- }
221
- }
222
- return states;
223
- }, [mockRuntime, plugin.schema]);
224
- useEffect(() => {
225
- let cancelled = false;
226
- void registrationReady.then(() => {
227
- if (cancelled || !mockRuntime) return;
228
- const states = snapshotAllStates();
229
- if (states.length > 0) onDispatched(plugin.id, null, states);
230
- }).catch((err) => {
231
- if (!cancelled) onError(plugin.id, err instanceof Error ? err.message : String(err));
232
- });
233
- return () => {
234
- cancelled = true;
235
- };
236
- }, [registrationReady, mockRuntime, plugin, onDispatched, onError, snapshotAllStates]);
237
- useEffect(() => {
238
- if (!mockRuntime) return;
239
- let timer = null;
240
- const scheduleResync = () => {
241
- if (timer !== null) return;
242
- timer = setTimeout(() => {
243
- timer = null;
244
- const states = snapshotAllStates();
245
- if (states.length > 0) onDispatched(plugin.id, null, states);
246
- }, 0);
247
- };
248
- const unsub = mockRuntime.getEventBus().onAny(scheduleResync);
249
- return () => {
250
- unsub();
251
- if (timer !== null) clearTimeout(timer);
252
- };
253
- }, [mockRuntime, plugin.id, onDispatched, snapshotAllStates]);
254
- useEffect(() => {
255
- if (!mockRuntime) return;
256
- const rebroadcast = /* @__PURE__ */ new WeakSet();
257
- const unsub = mockRuntime.getEventBus().onAny((event) => {
258
- if (rebroadcast.has(event)) return;
259
- if (inboundBusEvents.has(event.type) || inboundTriggerNames.has(event.type)) return;
260
- const sourceOrbital = event.source?.orbital;
261
- if (sourceOrbital === void 0 || !ownOrbitals.has(sourceOrbital)) return;
262
- rebroadcast.add(event);
263
- bus.emit(`UI:${event.type}`, event.payload, event.source);
264
- });
265
- return () => {
266
- unsub();
267
- };
268
- }, [mockRuntime, bus, ownOrbitals, inboundBusEvents, inboundTriggerNames]);
269
- const dispatch = useCallback(
270
- async (row, payload) => {
271
- await registrationReady;
272
- let response;
273
- if (mockRuntime) {
274
- response = await mockRuntime.processOrbitalEvent(row.orbital, {
275
- event: row.trigger,
276
- payload,
277
- targetTrait: row.trait,
278
- locale
279
- });
280
- } else if (mode === "server" && transport) {
281
- response = await transport.send(row.orbital, { event: row.trigger, payload, locale });
282
- } else {
283
- return;
284
- }
285
- if (!response.success) {
286
- onError(plugin.id, response.error ?? `${plugin.id}: ${row.trigger} failed`);
287
- }
288
- if (!mockRuntime) {
289
- for (const entry of response.emittedEvents ?? []) {
290
- if (entry.event === row.trigger) continue;
291
- if (inboundBusEvents.has(entry.event)) continue;
292
- const sourceOrbital = entry.source?.orbital;
293
- if (sourceOrbital !== void 0 && ownOrbitals.has(sourceOrbital)) {
294
- bus.emit(`UI:${entry.event}`, entry.payload, entry.source);
295
- }
296
- }
297
- }
298
- const states = [];
299
- for (const [traitName, stateName] of Object.entries(response.states)) {
300
- states.push([row.orbital, traitName, toTraitState(mockRuntime, row.orbital, traitName, stateName, row.trigger)]);
301
- onTransition?.(plugin.id, row.orbital, traitName, stateName);
302
- }
303
- onDispatched(plugin.id, row.trigger, states);
304
- },
305
- [registrationReady, mockRuntime, mode, transport, locale, plugin, bus, ownOrbitals, inboundBusEvents, onError, onTransition, onDispatched]
306
- );
307
- useEffect(() => {
308
- const unsubs = plugin.inbound.map(
309
- (row) => bus.on(`UI:${row.busEvent}`, (event) => {
310
- void dispatch(row, event.payload).catch((err) => {
311
- onError(plugin.id, err instanceof Error ? err.message : String(err));
312
- });
313
- })
314
- );
315
- return () => {
316
- for (const unsub of unsubs) unsub();
317
- };
318
- }, [bus, plugin, dispatch, onError]);
319
- return null;
320
- }
321
- function OrbitalPluginHost({
322
- plugins,
323
- mode = "mock",
324
- transport,
325
- deny,
326
- navigate,
327
- onTransition,
328
- children
329
- }) {
330
- const [tick, setTick] = useState(0);
331
- const [errors, setErrors] = useState({});
332
- const statesRef = useRef(/* @__PURE__ */ new Map());
333
- const lastEventRef = useRef(/* @__PURE__ */ new Map());
334
- const pluginSchemas = useMemo(
335
- () => new Map(plugins.map((plugin) => [plugin.id, plugin.schema])),
336
- [plugins]
337
- );
338
- const handleDispatched = useCallback(
339
- (pluginId, trigger, states) => {
340
- if (trigger !== null) {
341
- lastEventRef.current.set(pluginId, trigger);
342
- }
343
- let byKey = statesRef.current.get(pluginId);
344
- if (!byKey) {
345
- byKey = /* @__PURE__ */ new Map();
346
- statesRef.current.set(pluginId, byKey);
347
- }
348
- for (const [orbital, trait, state] of states) {
349
- byKey.set(`${orbital}.${trait}`, state);
350
- }
351
- setTick((t) => t + 1);
352
- },
353
- []
354
- );
355
- const handleError = useCallback((pluginId, message) => {
356
- setErrors((prev) => prev[pluginId] === message ? prev : { ...prev, [pluginId]: message });
357
- }, []);
358
- const contextValue = useMemo(
359
- () => ({
360
- getState: (pluginId, orbital, trait) => statesRef.current.get(pluginId)?.get(`${orbital}.${trait}`),
361
- lastEvent: (pluginId) => lastEventRef.current.get(pluginId),
362
- errors,
363
- tick,
364
- getPluginSchema: (pluginId) => pluginSchemas.get(pluginId)
365
- }),
366
- [errors, tick, pluginSchemas]
367
- );
368
- return /* @__PURE__ */ jsxs(OrbitalPluginHostContext.Provider, { value: contextValue, children: [
369
- plugins.map((plugin) => /* @__PURE__ */ jsx(
370
- PluginRuntimeMount,
371
- {
372
- plugin,
373
- mode,
374
- transport,
375
- deny,
376
- navigate,
377
- onTransition,
378
- onDispatched: handleDispatched,
379
- onError: handleError
380
- },
381
- plugin.id
382
- )),
383
- children ?? null
384
- ] });
385
- }
386
-
387
- export { OrbitalPluginHost, useDeclaredCaptureTable, useOrbitalPluginHost };