@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.
- package/dist/BehaviorValueFrame-3ORZHPWQ.css +1252 -0
- package/dist/BehaviorValueFrame-QYFJEMN5.js +18 -0
- package/dist/TraitValueFrame-2WMYJOA5.css +1252 -0
- package/dist/TraitValueFrame-X6IL3UST.js +17 -0
- package/dist/Typography-KBATMU2V.js +5 -0
- package/dist/{UISlotRenderer-YNY7V2UJ.js → UISlotRenderer-NZBV5BUI.js} +12 -10
- package/dist/avl/index.cjs +32263 -28103
- package/dist/avl/index.d.ts +36 -13
- package/dist/avl/index.js +298 -6130
- package/dist/{avl-3d-context-BpBKZIbc.d.ts → avl-3d-context-Dxun3-ri.d.ts} +2 -0
- package/dist/{chunk-YYYHH5BA.js → chunk-7JRWELUC.js} +4 -6
- package/dist/{chunk-723MJUU3.js → chunk-CXQENFO2.js} +1 -1
- package/dist/chunk-D4NAA2JW.js +49 -0
- package/dist/{chunk-I5QOYW2Z.js → chunk-DXPCAQJU.js} +205 -2
- package/dist/{chunk-J755QADM.js → chunk-EDPUQ2ZJ.js} +327 -18
- package/dist/{chunk-4ZGXIW3B.js → chunk-ERDYADVZ.js} +1 -1
- package/dist/{chunk-7CVXM2KS.js → chunk-EZ5FSNOE.js} +2 -2
- package/dist/{chunk-E6MWYQVZ.js → chunk-G6EFTACU.js} +9713 -786
- package/dist/{chunk-MZIDOJMD.js → chunk-GVQOTA7T.js} +2 -1
- package/dist/{chunk-Q47ZN2DW.js → chunk-N23SVGTH.js} +83 -1
- package/dist/{chunk-KJGVLXEN.js → chunk-N4IJS5DD.js} +50 -116
- package/dist/{chunk-LZRW6GXG.js → chunk-QOV3TUAA.js} +2 -3
- package/dist/chunk-WBWXBA5H.js +434 -0
- package/dist/{chunk-V3FGTQUE.js → chunk-ZR45FGW3.js} +7 -1
- package/dist/{cn-DIql5232.d.ts → cn-CDIhHCUC.d.ts} +40 -16
- package/dist/components/index.cjs +14779 -4354
- package/dist/components/index.d.ts +200 -180
- package/dist/components/index.js +16 -17
- package/dist/context/index.cjs +9 -1
- package/dist/context/index.js +3 -1
- package/dist/hooks/index.cjs +78 -9
- package/dist/hooks/index.d.ts +43 -2
- package/dist/hooks/index.js +6 -7
- package/dist/lib/drawable/three/index.cjs +361 -27
- package/dist/lib/drawable/three/index.d.ts +2 -2
- package/dist/lib/drawable/three/index.js +28 -7
- package/dist/lib/index.cjs +117 -5
- package/dist/lib/index.d.ts +2 -2
- package/dist/lib/index.js +99 -6
- package/dist/locales/index.cjs +6 -9
- package/dist/locales/index.js +2 -2
- package/dist/providers/index.cjs +14137 -1311
- package/dist/providers/index.d.ts +36 -4
- package/dist/providers/index.js +37 -17
- package/dist/runtime/index.cjs +28769 -18640
- package/dist/runtime/index.d.ts +70 -3
- package/dist/runtime/index.js +15 -381
- package/dist/ssr/index.cjs +508 -134
- package/dist/ssr/index.d.cts +56 -4
- package/dist/ssr/index.d.ts +56 -4
- package/dist/ssr/index.js +446 -72
- package/dist/{verificationRegistry-B3dj1Zl8.d.ts → verificationRegistry-B5aGl7WF.d.ts} +2 -1
- package/locales/ar.json +2 -3
- package/locales/en.json +2 -3
- package/locales/sl.json +2 -3
- package/package.json +8 -8
- package/tailwind-preset.cjs +78 -8
- package/themes/_base.css +27 -0
- package/themes/_contract.md +6 -0
- package/themes/_fonts.css +4 -4
- package/themes/_foundation.css +11 -0
- package/themes/_presets.css +2 -0
- package/themes/almadar-website.css +10 -0
- package/themes/almadar.css +10 -0
- package/themes/atelier.css +10 -0
- package/themes/bauhaus.css +10 -0
- package/themes/bloomberg-dense.css +10 -0
- package/themes/clay.css +10 -0
- package/themes/corporate.css +10 -0
- package/themes/gazette.css +10 -0
- package/themes/glass.css +10 -0
- package/themes/kflow.css +5 -0
- package/themes/kiosk.css +10 -0
- package/themes/linear-clean.css +10 -0
- package/themes/material.css +10 -0
- package/themes/minimalist.css +10 -0
- package/themes/nata.css +304 -0
- package/themes/neon.css +10 -0
- package/themes/notion-editorial.css +10 -0
- package/themes/orb.css +10 -0
- package/themes/prism.css +10 -0
- package/themes/rawi.css +304 -0
- package/themes/retro.css +10 -0
- package/themes/risograph.css +10 -0
- package/themes/scandi.css +10 -0
- package/themes/solarpunk.css +10 -0
- package/themes/terminal.css +138 -128
- package/dist/Typography-LZTP72Y4.js +0 -5
- package/dist/chunk-D2E44ODB.js +0 -350
- package/dist/chunk-N7JIG57B.js +0 -138
- package/dist/chunk-QJIAJ6EH.js +0 -2256
package/dist/runtime/index.d.ts
CHANGED
|
@@ -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
|
-
|
|
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 };
|
package/dist/runtime/index.js
CHANGED
|
@@ -1,387 +1,21 @@
|
|
|
1
|
-
export {
|
|
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
|
-
|
|
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 };
|