@almadar/ui 6.59.0 → 6.61.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 (90) hide show
  1. package/dist/BehaviorValueFrame-3ORZHPWQ.css +1252 -0
  2. package/dist/BehaviorValueFrame-QTD7BWOI.js +18 -0
  3. package/dist/TraitValueFrame-2WMYJOA5.css +1252 -0
  4. package/dist/TraitValueFrame-WOXNLLMM.js +17 -0
  5. package/dist/Typography-BY4A2NBY.js +5 -0
  6. package/dist/{UISlotRenderer-YNY7V2UJ.js → UISlotRenderer-EEOXSJCI.js} +10 -8
  7. package/dist/avl/index.cjs +31974 -27856
  8. package/dist/avl/index.d.ts +36 -13
  9. package/dist/avl/index.js +296 -6128
  10. package/dist/{avl-3d-context-BpBKZIbc.d.ts → avl-3d-context-Dxun3-ri.d.ts} +2 -0
  11. package/dist/{chunk-E6MWYQVZ.js → chunk-6PV4LASE.js} +9493 -641
  12. package/dist/{chunk-723MJUU3.js → chunk-6ZCU3BQN.js} +1 -1
  13. package/dist/{chunk-7CVXM2KS.js → chunk-7NIU5GDC.js} +2 -2
  14. package/dist/{chunk-YYYHH5BA.js → chunk-CB64IOYD.js} +0 -4
  15. package/dist/{chunk-MZIDOJMD.js → chunk-EIIQGOZW.js} +2 -1
  16. package/dist/chunk-F7NZ3KZQ.js +434 -0
  17. package/dist/{chunk-LZRW6GXG.js → chunk-FYX64CDL.js} +0 -2
  18. package/dist/{chunk-4ZGXIW3B.js → chunk-KZRAMPM6.js} +1 -1
  19. package/dist/chunk-LUREMDI3.js +49 -0
  20. package/dist/{chunk-J755QADM.js → chunk-MGN6B6OQ.js} +318 -18
  21. package/dist/{chunk-Q47ZN2DW.js → chunk-N23SVGTH.js} +83 -1
  22. package/dist/{chunk-KJGVLXEN.js → chunk-N4IJS5DD.js} +50 -116
  23. package/dist/{chunk-I5QOYW2Z.js → chunk-UTSDPJUP.js} +205 -2
  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 +14423 -4100
  27. package/dist/components/index.d.ts +160 -172
  28. package/dist/components/index.js +14 -15
  29. package/dist/context/index.cjs +9 -1
  30. package/dist/context/index.js +3 -1
  31. package/dist/hooks/index.cjs +72 -6
  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 +350 -26
  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 +90 -4
  38. package/dist/lib/index.d.ts +2 -2
  39. package/dist/lib/index.js +74 -6
  40. package/dist/locales/index.cjs +0 -6
  41. package/dist/locales/index.js +2 -2
  42. package/dist/providers/index.cjs +13846 -1062
  43. package/dist/providers/index.d.ts +36 -4
  44. package/dist/providers/index.js +35 -15
  45. package/dist/runtime/index.cjs +28395 -18308
  46. package/dist/runtime/index.d.ts +65 -3
  47. package/dist/runtime/index.js +13 -379
  48. package/dist/ssr/index.cjs +506 -133
  49. package/dist/ssr/index.d.cts +56 -4
  50. package/dist/ssr/index.d.ts +56 -4
  51. package/dist/ssr/index.js +444 -71
  52. package/dist/{verificationRegistry-B3dj1Zl8.d.ts → verificationRegistry-B5aGl7WF.d.ts} +2 -1
  53. package/locales/ar.json +0 -2
  54. package/locales/en.json +0 -2
  55. package/locales/sl.json +0 -2
  56. package/package.json +7 -7
  57. package/tailwind-preset.cjs +78 -8
  58. package/themes/_contract.md +6 -0
  59. package/themes/_fonts.css +4 -4
  60. package/themes/_foundation.css +11 -0
  61. package/themes/_presets.css +2 -0
  62. package/themes/almadar-website.css +10 -0
  63. package/themes/almadar.css +10 -0
  64. package/themes/atelier.css +10 -0
  65. package/themes/bauhaus.css +10 -0
  66. package/themes/bloomberg-dense.css +10 -0
  67. package/themes/clay.css +10 -0
  68. package/themes/corporate.css +10 -0
  69. package/themes/gazette.css +10 -0
  70. package/themes/glass.css +10 -0
  71. package/themes/kflow.css +5 -0
  72. package/themes/kiosk.css +10 -0
  73. package/themes/linear-clean.css +10 -0
  74. package/themes/material.css +10 -0
  75. package/themes/minimalist.css +10 -0
  76. package/themes/nata.css +304 -0
  77. package/themes/neon.css +10 -0
  78. package/themes/notion-editorial.css +10 -0
  79. package/themes/orb.css +10 -0
  80. package/themes/prism.css +10 -0
  81. package/themes/rawi.css +304 -0
  82. package/themes/retro.css +10 -0
  83. package/themes/risograph.css +10 -0
  84. package/themes/scandi.css +10 -0
  85. package/themes/solarpunk.css +10 -0
  86. package/themes/terminal.css +138 -128
  87. package/dist/Typography-LZTP72Y4.js +0 -5
  88. package/dist/chunk-D2E44ODB.js +0 -350
  89. package/dist/chunk-N7JIG57B.js +0 -138
  90. package/dist/chunk-QJIAJ6EH.js +0 -2256
@@ -1,4 +1,4 @@
1
- import { en_default } from './chunk-LZRW6GXG.js';
1
+ import { en_default } from './chunk-FYX64CDL.js';
2
2
 
3
3
  // lib/format.ts
4
4
  var { $meta: _meta, ...coreMessages } = en_default;
@@ -1,5 +1,5 @@
1
- import { avlBlend, AVL_INK, EFFECT_CATEGORY_COLORS, OPERATOR_CATEGORY_COLORS, avlTint, Box, VStack, effectCategoryOf } from './chunk-J755QADM.js';
2
- import { Typography } from './chunk-4ZGXIW3B.js';
1
+ import { avlBlend, AVL_INK, EFFECT_CATEGORY_COLORS, OPERATOR_CATEGORY_COLORS, avlTint, Box, VStack, effectCategoryOf } from './chunk-MGN6B6OQ.js';
2
+ import { Typography } from './chunk-KZRAMPM6.js';
3
3
  import { Vector3, QuadraticBezierCurve3, MathUtils, Quaternion } from 'three';
4
4
  import { EntityPersistenceSchema } from '@almadar/core';
5
5
  import { getStdOperatorMeta } from '@almadar/std/registry';
@@ -130,7 +130,6 @@ var ar_default = {
130
130
  "aria.upvote": "\u062A\u0635\u0648\u064A\u062A \u0625\u064A\u062C\u0627\u0628\u064A",
131
131
  "aria.downvote": "\u062A\u0635\u0648\u064A\u062A \u0633\u0644\u0628\u064A",
132
132
  "aria.qrScanner": "\u0645\u0627\u0633\u062D QR",
133
- "aria.mockScanDev": "\u0645\u0633\u062D \u062A\u062C\u0631\u064A\u0628\u064A (\u062A\u0637\u0648\u064A\u0631)",
134
133
  "aria.openMenu": "\u0641\u062A\u062D \u0627\u0644\u0642\u0627\u0626\u0645\u0629",
135
134
  "aria.closeMenu": "\u0625\u063A\u0644\u0627\u0642 \u0627\u0644\u0642\u0627\u0626\u0645\u0629",
136
135
  "aria.openSidebar": "\u0641\u062A\u062D \u0627\u0644\u0634\u0631\u064A\u0637 \u0627\u0644\u062C\u0627\u0646\u0628\u064A",
@@ -328,7 +327,6 @@ var ar_default = {
328
327
  "qrScanner.pauseScanning": "\u0625\u064A\u0642\u0627\u0641 \u0627\u0644\u0645\u0633\u062D \u0645\u0624\u0642\u062A\u064B\u0627",
329
328
  "qrScanner.switchToFrontCamera": "\u0627\u0644\u062A\u0628\u062F\u064A\u0644 \u0625\u0644\u0649 \u0627\u0644\u0643\u0627\u0645\u064A\u0631\u0627 \u0627\u0644\u0623\u0645\u0627\u0645\u064A\u0629",
330
329
  "qrScanner.switchToRearCamera": "\u0627\u0644\u062A\u0628\u062F\u064A\u0644 \u0625\u0644\u0649 \u0627\u0644\u0643\u0627\u0645\u064A\u0631\u0627 \u0627\u0644\u062E\u0644\u0641\u064A\u0629",
331
- "qrScanner.mockScan": "\u0645\u0633\u062D \u062A\u062C\u0631\u064A\u0628\u064A",
332
330
  "docSearch.placeholder": "\u0627\u0644\u0628\u062D\u062B \u0641\u064A \u0627\u0644\u0648\u062B\u0627\u0626\u0642...",
333
331
  "stateMachine.loading": "\u062C\u0627\u0631\u064D \u062A\u062D\u0645\u064A\u0644 \u0622\u0644\u0629 \u0627\u0644\u062D\u0627\u0644\u0629\u2026",
334
332
  "stateMachine.noStateMachine": "\u0644\u0627 \u062A\u0648\u062C\u062F \u0622\u0644\u0629 \u062D\u0627\u0644\u0629 \u0644\u0639\u0631\u0636\u0647\u0627",
@@ -1389,7 +1387,6 @@ var sl_default = {
1389
1387
  "aria.upvote": "Glasuj za",
1390
1388
  "aria.downvote": "Glasuj proti",
1391
1389
  "aria.qrScanner": "QR skener",
1392
- "aria.mockScanDev": "Simuliraj skeniranje (dev)",
1393
1390
  "aria.openMenu": "Odpri meni",
1394
1391
  "aria.closeMenu": "Zapri meni",
1395
1392
  "aria.openSidebar": "Odpri stransko vrstico",
@@ -1587,7 +1584,6 @@ var sl_default = {
1587
1584
  "qrScanner.pauseScanning": "Za\u010Dasno ustavi skeniranje",
1588
1585
  "qrScanner.switchToFrontCamera": "Preklopi na sprednjo kamero",
1589
1586
  "qrScanner.switchToRearCamera": "Preklopi na zadnjo kamero",
1590
- "qrScanner.mockScan": "Preizkusno skeniranje",
1591
1587
  "docSearch.placeholder": "Iskanje po dokumentaciji...",
1592
1588
  "stateMachine.loading": "Nalaganje stanjskega stroja\u2026",
1593
1589
  "stateMachine.noStateMachine": "Ni stanjskega stroja za prikaz",
@@ -1,4 +1,4 @@
1
- import { beginPending, endPending } from './chunk-I5QOYW2Z.js';
1
+ import { claimDelivery, beginPending, endPending } from './chunk-UTSDPJUP.js';
2
2
  import { useEventBus } from './chunk-CHNC4UYE.js';
3
3
  import { useState, useCallback, useEffect, useMemo, useRef } from 'react';
4
4
  import { createLogger } from '@almadar/logger';
@@ -857,6 +857,7 @@ function useUIEvents(dispatch, traitName, validEvents, eventBusInstance) {
857
857
  if (event.source && event.source.dispatched) {
858
858
  return;
859
859
  }
860
+ if (!claimDelivery(event.source, traitName, smEvent)) return;
860
861
  const pendingKey = event.source?.pendingKey;
861
862
  const settled = dispatch(smEvent, event.payload);
862
863
  if (pendingKey !== void 0 && settled instanceof Promise) {
@@ -0,0 +1,434 @@
1
+ import { LoadingState, ErrorState, UISlotComponent } from './chunk-6PV4LASE.js';
2
+ import { useEventBus } from './chunk-CHNC4UYE.js';
3
+ import { createContext, useMemo, useState, useRef, useCallback, useContext, useEffect } from 'react';
4
+ import { UISlotProvider, useUISlots } from '@almadar/ui/context';
5
+ import { OrbitalServerRuntime } from '@almadar/runtime/OrbitalServerRuntime';
6
+ import { UI_SLOTS } from '@almadar/core';
7
+ import { createLogger } from '@almadar/logger';
8
+ import { useTranslate } from '@almadar/ui/hooks';
9
+ import { jsxs, jsx } from 'react/jsx-runtime';
10
+
11
+ var log = createLogger("almadar:ui:plugin-host");
12
+ var UI_SLOT_SET = new Set(UI_SLOTS);
13
+ function isUISlot(value) {
14
+ return UI_SLOT_SET.has(value);
15
+ }
16
+ var OrbitalPluginHostContext = createContext(null);
17
+ function useOrbitalPluginHostContext(caller) {
18
+ const ctx = useContext(OrbitalPluginHostContext);
19
+ if (!ctx) {
20
+ throw new Error(`${caller} must be used within an <OrbitalPluginHost>.`);
21
+ }
22
+ return ctx;
23
+ }
24
+ function isTraitState(value) {
25
+ return value !== void 0 && typeof value.currentState === "string";
26
+ }
27
+ function toTraitState(runtime, orbital, trait, stateName, lastEvent) {
28
+ if (runtime) {
29
+ const raw = runtime.getState(orbital, trait);
30
+ if (isTraitState(raw)) return raw;
31
+ }
32
+ return { traitName: trait, currentState: stateName, previousState: null, lastEvent, context: {} };
33
+ }
34
+ function isKeymapValue(value) {
35
+ if (value === null || value === void 0 || typeof value !== "object" || Array.isArray(value)) return false;
36
+ return Object.values(value).every((entry) => Array.isArray(entry) && entry.every((k) => typeof k === "string"));
37
+ }
38
+ function findInlineTrait(schema, orbitalName, traitName) {
39
+ const orbital = schema.orbitals.find((o) => o.name === orbitalName);
40
+ if (!orbital) return void 0;
41
+ for (const ref of orbital.traits) {
42
+ if (typeof ref === "string") continue;
43
+ if ("ref" in ref) continue;
44
+ if (ref.name === traitName) return ref;
45
+ }
46
+ return void 0;
47
+ }
48
+ function readKeymapConfig(trait, knob) {
49
+ const declared = trait?.config?.[knob]?.default;
50
+ return isKeymapValue(declared) ? declared : {};
51
+ }
52
+ function traitNamesOf(orbital) {
53
+ const names = [];
54
+ for (const ref of orbital.traits) {
55
+ if (typeof ref === "string") {
56
+ names.push(ref);
57
+ } else if ("ref" in ref) {
58
+ if (ref.name) names.push(ref.name);
59
+ } else {
60
+ names.push(ref.name);
61
+ }
62
+ }
63
+ return names;
64
+ }
65
+ function useDeclaredCaptureTable(opts) {
66
+ const { pluginId, orbital, trait, keymapKnob = "keymap", target = "shell" } = opts;
67
+ const ctx = useOrbitalPluginHostContext("useDeclaredCaptureTable");
68
+ return useMemo(() => {
69
+ const schema = ctx.getPluginSchema(pluginId);
70
+ const inlineTrait = schema ? findInlineTrait(schema, orbital, trait) : void 0;
71
+ const keymap = readKeymapConfig(inlineTrait, keymapKnob);
72
+ const currentState = ctx.getState(pluginId, orbital, trait)?.currentState;
73
+ const keys = currentState !== void 0 ? keymap[currentState] ?? [] : [];
74
+ const entry = { mode: currentState ?? "unknown", keys: new Set(keys) };
75
+ const targets = Array.isArray(target) ? target : [target];
76
+ const table = {};
77
+ for (const t of targets) table[t] = entry;
78
+ return table;
79
+ }, [ctx, pluginId, orbital, trait, keymapKnob, target]);
80
+ }
81
+ function useOrbitalPluginHost() {
82
+ const ctx = useOrbitalPluginHostContext("useOrbitalPluginHost");
83
+ return { getState: ctx.getState, lastEvent: ctx.lastEvent, errors: ctx.errors };
84
+ }
85
+ function buildMockEffectHandlers(opts) {
86
+ const { pluginId, denySet, slotsRef, renderedSlotsRef, navigateRef } = opts;
87
+ const handlers = {
88
+ renderUI: (slot, pattern, props, priority) => {
89
+ if (!isUISlot(slot)) {
90
+ log.warn("renderUI:unknown-slot", { pluginId, slot });
91
+ return;
92
+ }
93
+ if (pattern === null) {
94
+ slotsRef.current.clearBySource(slot, pluginId);
95
+ return;
96
+ }
97
+ renderedSlotsRef.current.add(slot);
98
+ const { type, ...inline } = pattern;
99
+ slotsRef.current.render({
100
+ target: slot,
101
+ pattern: type,
102
+ props: { ...inline, ...props ?? {} },
103
+ priority,
104
+ sourceTrait: pluginId
105
+ });
106
+ }
107
+ };
108
+ if (denySet.has("navigate")) {
109
+ handlers.navigate = (path) => log.warn("navigate:denied", { pluginId, path });
110
+ } else if (navigateRef.current) {
111
+ handlers.navigate = (path) => navigateRef.current?.(path);
112
+ }
113
+ if (denySet.has("persist")) {
114
+ handlers.persist = async (action, entityType) => {
115
+ log.warn("persist:denied", { pluginId, action, entityType });
116
+ return void 0;
117
+ };
118
+ }
119
+ if (denySet.has("call-service")) {
120
+ handlers.callService = async (service, action) => {
121
+ log.warn("call-service:denied", { pluginId, service, action });
122
+ return null;
123
+ };
124
+ }
125
+ return handlers;
126
+ }
127
+ function PluginRuntimeMount({
128
+ plugin,
129
+ mode,
130
+ transport,
131
+ deny,
132
+ navigate,
133
+ onTransition,
134
+ onDispatched,
135
+ onError
136
+ }) {
137
+ const bus = useEventBus();
138
+ const { locale } = useTranslate();
139
+ const slots = useUISlots();
140
+ const slotsRef = useRef(slots);
141
+ slotsRef.current = slots;
142
+ const renderedSlotsRef = useRef(/* @__PURE__ */ new Set());
143
+ const navigateRef = useRef(navigate);
144
+ navigateRef.current = navigate;
145
+ const [mockRuntime] = useState(() => {
146
+ if (mode !== "mock") return void 0;
147
+ return new OrbitalServerRuntime({
148
+ mode: "mock",
149
+ debug: false,
150
+ effectHandlers: buildMockEffectHandlers({
151
+ pluginId: plugin.id,
152
+ denySet: new Set(deny ?? []),
153
+ slotsRef,
154
+ renderedSlotsRef,
155
+ navigateRef
156
+ })
157
+ });
158
+ });
159
+ const registrationReady = useMemo(() => {
160
+ if (mockRuntime) return mockRuntime.register(plugin.schema);
161
+ if (mode === "server" && transport) return transport.register(plugin.schema);
162
+ return Promise.resolve();
163
+ }, [mockRuntime, transport, mode, plugin.schema]);
164
+ useEffect(() => {
165
+ if (mode === "server" && !transport) {
166
+ onError(plugin.id, 'OrbitalPluginHost: mode "server" requires a transport');
167
+ }
168
+ }, [mode, transport, plugin.id, onError]);
169
+ const teardownTimerRef = useRef(null);
170
+ useEffect(() => {
171
+ if (teardownTimerRef.current !== null) {
172
+ clearTimeout(teardownTimerRef.current);
173
+ teardownTimerRef.current = null;
174
+ }
175
+ return () => {
176
+ teardownTimerRef.current = setTimeout(() => {
177
+ teardownTimerRef.current = null;
178
+ if (mockRuntime) {
179
+ mockRuntime.unregisterAll();
180
+ } else if (mode === "server" && transport) {
181
+ void transport.unregister();
182
+ }
183
+ for (const slot of renderedSlotsRef.current) {
184
+ slotsRef.current.clearBySource(slot, plugin.id);
185
+ }
186
+ }, 0);
187
+ };
188
+ }, [mockRuntime, transport, mode, plugin.id]);
189
+ const ownOrbitals = useMemo(
190
+ () => new Set(plugin.schema.orbitals.map((o) => o.name)),
191
+ [plugin.schema]
192
+ );
193
+ const inboundBusEvents = useMemo(
194
+ () => new Set(plugin.inbound.map((row) => row.busEvent)),
195
+ [plugin.inbound]
196
+ );
197
+ const inboundTriggerNames = useMemo(
198
+ () => new Set(plugin.inbound.map((row) => row.trigger)),
199
+ [plugin.inbound]
200
+ );
201
+ const snapshotAllStates = useCallback(() => {
202
+ const states = [];
203
+ if (!mockRuntime) return states;
204
+ for (const orbital of plugin.schema.orbitals) {
205
+ for (const traitName of traitNamesOf(orbital)) {
206
+ const raw = mockRuntime.getState(orbital.name, traitName);
207
+ if (isTraitState(raw)) states.push([orbital.name, traitName, raw]);
208
+ }
209
+ }
210
+ return states;
211
+ }, [mockRuntime, plugin.schema]);
212
+ useEffect(() => {
213
+ let cancelled = false;
214
+ void registrationReady.then(() => {
215
+ if (cancelled || !mockRuntime) return;
216
+ const states = snapshotAllStates();
217
+ if (states.length > 0) onDispatched(plugin.id, null, states);
218
+ }).catch((err) => {
219
+ if (!cancelled) onError(plugin.id, err instanceof Error ? err.message : String(err));
220
+ });
221
+ return () => {
222
+ cancelled = true;
223
+ };
224
+ }, [registrationReady, mockRuntime, plugin, onDispatched, onError, snapshotAllStates]);
225
+ useEffect(() => {
226
+ if (!mockRuntime) return;
227
+ let timer = null;
228
+ const scheduleResync = () => {
229
+ if (timer !== null) return;
230
+ timer = setTimeout(() => {
231
+ timer = null;
232
+ const states = snapshotAllStates();
233
+ if (states.length > 0) onDispatched(plugin.id, null, states);
234
+ }, 0);
235
+ };
236
+ const unsub = mockRuntime.getEventBus().onAny(scheduleResync);
237
+ return () => {
238
+ unsub();
239
+ if (timer !== null) clearTimeout(timer);
240
+ };
241
+ }, [mockRuntime, plugin.id, onDispatched, snapshotAllStates]);
242
+ useEffect(() => {
243
+ if (!mockRuntime) return;
244
+ const rebroadcast = /* @__PURE__ */ new WeakSet();
245
+ const unsub = mockRuntime.getEventBus().onAny((event) => {
246
+ if (rebroadcast.has(event)) return;
247
+ if (inboundBusEvents.has(event.type) || inboundTriggerNames.has(event.type)) return;
248
+ const sourceOrbital = event.source?.orbital;
249
+ if (sourceOrbital === void 0 || !ownOrbitals.has(sourceOrbital)) return;
250
+ rebroadcast.add(event);
251
+ bus.emit(`UI:${event.type}`, event.payload, event.source);
252
+ });
253
+ return () => {
254
+ unsub();
255
+ };
256
+ }, [mockRuntime, bus, ownOrbitals, inboundBusEvents, inboundTriggerNames]);
257
+ const dispatch = useCallback(
258
+ async (row, payload) => {
259
+ await registrationReady;
260
+ let response;
261
+ if (mockRuntime) {
262
+ response = await mockRuntime.processOrbitalEvent(row.orbital, {
263
+ event: row.trigger,
264
+ payload,
265
+ targetTrait: row.trait,
266
+ locale
267
+ });
268
+ } else if (mode === "server" && transport) {
269
+ response = await transport.send(row.orbital, { event: row.trigger, payload, locale });
270
+ } else {
271
+ return;
272
+ }
273
+ if (!response.success) {
274
+ onError(plugin.id, response.error ?? `${plugin.id}: ${row.trigger} failed`);
275
+ }
276
+ if (!mockRuntime) {
277
+ for (const entry of response.emittedEvents ?? []) {
278
+ if (entry.event === row.trigger) continue;
279
+ if (inboundBusEvents.has(entry.event)) continue;
280
+ const sourceOrbital = entry.source?.orbital;
281
+ if (sourceOrbital !== void 0 && ownOrbitals.has(sourceOrbital)) {
282
+ bus.emit(`UI:${entry.event}`, entry.payload, entry.source);
283
+ }
284
+ }
285
+ }
286
+ const states = [];
287
+ for (const [traitName, stateName] of Object.entries(response.states)) {
288
+ states.push([row.orbital, traitName, toTraitState(mockRuntime, row.orbital, traitName, stateName, row.trigger)]);
289
+ onTransition?.(plugin.id, row.orbital, traitName, stateName);
290
+ }
291
+ onDispatched(plugin.id, row.trigger, states);
292
+ },
293
+ [registrationReady, mockRuntime, mode, transport, locale, plugin, bus, ownOrbitals, inboundBusEvents, onError, onTransition, onDispatched]
294
+ );
295
+ useEffect(() => {
296
+ const unsubs = plugin.inbound.map(
297
+ (row) => bus.on(`UI:${row.busEvent}`, (event) => {
298
+ void dispatch(row, event.payload).catch((err) => {
299
+ onError(plugin.id, err instanceof Error ? err.message : String(err));
300
+ });
301
+ })
302
+ );
303
+ return () => {
304
+ for (const unsub of unsubs) unsub();
305
+ };
306
+ }, [bus, plugin, dispatch, onError]);
307
+ return null;
308
+ }
309
+ function OrbitalPluginHost({
310
+ plugins,
311
+ mode = "mock",
312
+ transport,
313
+ deny,
314
+ navigate,
315
+ onTransition,
316
+ children
317
+ }) {
318
+ const [tick, setTick] = useState(0);
319
+ const [errors, setErrors] = useState({});
320
+ const statesRef = useRef(/* @__PURE__ */ new Map());
321
+ const lastEventRef = useRef(/* @__PURE__ */ new Map());
322
+ const pluginSchemas = useMemo(
323
+ () => new Map(plugins.map((plugin) => [plugin.id, plugin.schema])),
324
+ [plugins]
325
+ );
326
+ const handleDispatched = useCallback(
327
+ (pluginId, trigger, states) => {
328
+ if (trigger !== null) {
329
+ lastEventRef.current.set(pluginId, trigger);
330
+ }
331
+ let byKey = statesRef.current.get(pluginId);
332
+ if (!byKey) {
333
+ byKey = /* @__PURE__ */ new Map();
334
+ statesRef.current.set(pluginId, byKey);
335
+ }
336
+ for (const [orbital, trait, state] of states) {
337
+ byKey.set(`${orbital}.${trait}`, state);
338
+ }
339
+ setTick((t) => t + 1);
340
+ },
341
+ []
342
+ );
343
+ const handleError = useCallback((pluginId, message) => {
344
+ setErrors((prev) => prev[pluginId] === message ? prev : { ...prev, [pluginId]: message });
345
+ }, []);
346
+ const contextValue = useMemo(
347
+ () => ({
348
+ getState: (pluginId, orbital, trait) => statesRef.current.get(pluginId)?.get(`${orbital}.${trait}`),
349
+ lastEvent: (pluginId) => lastEventRef.current.get(pluginId),
350
+ errors,
351
+ tick,
352
+ getPluginSchema: (pluginId) => pluginSchemas.get(pluginId)
353
+ }),
354
+ [errors, tick, pluginSchemas]
355
+ );
356
+ return /* @__PURE__ */ jsxs(OrbitalPluginHostContext.Provider, { value: contextValue, children: [
357
+ plugins.map((plugin) => /* @__PURE__ */ jsx(
358
+ PluginRuntimeMount,
359
+ {
360
+ plugin,
361
+ mode,
362
+ transport,
363
+ deny,
364
+ navigate,
365
+ onTransition,
366
+ onDispatched: handleDispatched,
367
+ onError: handleError
368
+ },
369
+ plugin.id
370
+ )),
371
+ children ?? null
372
+ ] });
373
+ }
374
+ var TraitValueMountContext = createContext(null);
375
+ function TraitValueMountProvider({ host, children }) {
376
+ return /* @__PURE__ */ jsx(TraitValueMountContext.Provider, { value: host, children });
377
+ }
378
+ function initEventOf(key) {
379
+ return `TRAIT_VALUE_MOUNTED:${key}`;
380
+ }
381
+ function MountedInit({ event }) {
382
+ const bus = useEventBus();
383
+ useEffect(() => {
384
+ bus.emit(`UI:${event}`, {});
385
+ }, [bus, event]);
386
+ return null;
387
+ }
388
+ function TraitValueFrame({ value }) {
389
+ const host = useContext(TraitValueMountContext);
390
+ const key = useMemo(() => JSON.stringify(value), [value]);
391
+ const latest = useRef(value);
392
+ latest.current = value;
393
+ const [state, setState] = useState({ status: "loading" });
394
+ useEffect(() => {
395
+ const current = latest.current;
396
+ if (host === null) {
397
+ setState({ status: "error", message: `No trait-value host is configured to mount ${current.behavior}.traits.${current.trait}` });
398
+ return;
399
+ }
400
+ let live = true;
401
+ setState({ status: "loading" });
402
+ void host.mount(current).then((result) => {
403
+ if (!live) return;
404
+ if (!result.ok) {
405
+ const detail = (result.errors ?? []).map((e) => `${e.code}: ${e.message}`).join("\n");
406
+ setState({ status: "error", message: detail.length > 0 ? `${result.error}
407
+ ${detail}` : result.error });
408
+ return;
409
+ }
410
+ const initEvent = initEventOf(key);
411
+ setState({
412
+ status: "ready",
413
+ initEvent,
414
+ plugin: {
415
+ id: key,
416
+ schema: result.mounted.schema,
417
+ inbound: [{ busEvent: initEvent, orbital: result.mounted.orbital, trait: result.mounted.trait, trigger: "INIT" }]
418
+ }
419
+ });
420
+ });
421
+ return () => {
422
+ live = false;
423
+ };
424
+ }, [host, key]);
425
+ if (state.status === "loading") return /* @__PURE__ */ jsx(LoadingState, {});
426
+ if (state.status === "error") return /* @__PURE__ */ jsx(ErrorState, { message: state.message });
427
+ return /* @__PURE__ */ jsx(UISlotProvider, { children: /* @__PURE__ */ jsxs(OrbitalPluginHost, { plugins: [state.plugin], mode: host?.mode ?? "mock", transport: host?.transport, children: [
428
+ /* @__PURE__ */ jsx(MountedInit, { event: state.initEvent }),
429
+ /* @__PURE__ */ jsx(UISlotComponent, { slot: "main" })
430
+ ] }) });
431
+ }
432
+ var TraitValueFrame_default = TraitValueFrame;
433
+
434
+ export { OrbitalPluginHost, TraitValueFrame, TraitValueFrame_default, TraitValueMountContext, TraitValueMountProvider, useDeclaredCaptureTable, useOrbitalPluginHost };
@@ -134,7 +134,6 @@ var en_default = {
134
134
  "aria.upvote": "Upvote",
135
135
  "aria.downvote": "Downvote",
136
136
  "aria.qrScanner": "QR scanner",
137
- "aria.mockScanDev": "Mock scan (dev)",
138
137
  "aria.openMenu": "Open menu",
139
138
  "aria.closeMenu": "Close menu",
140
139
  "aria.openSidebar": "Open sidebar",
@@ -332,7 +331,6 @@ var en_default = {
332
331
  "qrScanner.pauseScanning": "Pause scanning",
333
332
  "qrScanner.switchToFrontCamera": "Switch to front camera",
334
333
  "qrScanner.switchToRearCamera": "Switch to rear camera",
335
- "qrScanner.mockScan": "Mock Scan",
336
334
  "docSearch.placeholder": "Search documentation...",
337
335
  "stateMachine.loading": "Loading state machine\u2026",
338
336
  "stateMachine.noStateMachine": "No state machine to visualize",
@@ -1,5 +1,5 @@
1
1
  import { cn, domPassthrough } from './chunk-64WACXM7.js';
2
- import { formatValue } from './chunk-723MJUU3.js';
2
+ import { formatValue } from './chunk-6ZCU3BQN.js';
3
3
  import React from 'react';
4
4
  import { useFormatContext } from '@almadar/ui/hooks';
5
5
 
@@ -0,0 +1,49 @@
1
+ import { TraitValueMountContext } from './chunk-F7NZ3KZQ.js';
2
+ import { LoadingState, ErrorState, OrbPreview } from './chunk-6PV4LASE.js';
3
+ import { useContext, useMemo, useRef, useState, useEffect } from 'react';
4
+ import { jsx } from 'react/jsx-runtime';
5
+
6
+ function BehaviorValueFrame({ value }) {
7
+ const host = useContext(TraitValueMountContext);
8
+ const key = useMemo(() => JSON.stringify(value), [value]);
9
+ const latest = useRef(value);
10
+ latest.current = value;
11
+ const [state, setState] = useState({ status: "loading" });
12
+ useEffect(() => {
13
+ const current = latest.current;
14
+ const mountBehavior = host?.mountBehavior;
15
+ if (mountBehavior === void 0) {
16
+ setState({ status: "error", message: `This host cannot run behavior ${current.behavior}` });
17
+ return;
18
+ }
19
+ let live = true;
20
+ setState({ status: "loading" });
21
+ void mountBehavior(current).then((result) => {
22
+ if (!live) return;
23
+ if (!result.ok) {
24
+ const detail = (result.errors ?? []).map((e) => `${e.code}: ${e.message}`).join("\n");
25
+ setState({ status: "error", message: detail.length > 0 ? `${result.error}
26
+ ${detail}` : result.error });
27
+ return;
28
+ }
29
+ setState({ status: "ready", mounted: result.mounted });
30
+ });
31
+ return () => {
32
+ live = false;
33
+ };
34
+ }, [host, key]);
35
+ if (state.status === "loading") return /* @__PURE__ */ jsx(LoadingState, {});
36
+ if (state.status === "error") return /* @__PURE__ */ jsx(ErrorState, { message: state.message });
37
+ return /* @__PURE__ */ jsx(
38
+ OrbPreview,
39
+ {
40
+ schema: state.mounted.schema,
41
+ initialPagePath: state.mounted.firstPage,
42
+ isolated: true,
43
+ ...host?.behaviorTransport !== void 0 ? { transport: host.behaviorTransport } : {}
44
+ }
45
+ );
46
+ }
47
+ var BehaviorValueFrame_default = BehaviorValueFrame;
48
+
49
+ export { BehaviorValueFrame, BehaviorValueFrame_default };