@almadar/ui 6.52.0 → 6.53.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 (64) hide show
  1. package/dist/{EntityBindingContext-BbxrwSb9.d.ts → AwaitingSkeletonContext-Bh399p1x.d.ts} +17 -2
  2. package/dist/{Canvas3DHost-CWO0tswb.d.ts → Canvas3DHost-B-y2TNij.d.ts} +1 -1
  3. package/dist/{GameAudioProvider-_hPzjqp-.d.ts → GameAudioProvider-DyBvYP2c.d.ts} +1 -1
  4. package/dist/Typography-JGSDH4JP.js +5 -0
  5. package/dist/{UISlotRenderer-CR7SCAMR.js → UISlotRenderer-JT34I3O7.js} +9 -9
  6. package/dist/avl/index.cjs +39792 -40170
  7. package/dist/avl/index.d.ts +5 -2
  8. package/dist/avl/index.js +25 -17
  9. package/dist/{chunk-XUSSAWKL.js → chunk-2LFBQ4IS.js} +1 -1
  10. package/dist/{chunk-EERAGPBW.js → chunk-3EF5SDIJ.js} +31499 -32794
  11. package/dist/{chunk-V5AGW2JN.js → chunk-4OZDHCZV.js} +1 -1
  12. package/dist/{chunk-MSBMVG3B.js → chunk-6O37FCX4.js} +1 -0
  13. package/dist/{chunk-BHZG4PDZ.js → chunk-7LM6I3NA.js} +629 -626
  14. package/dist/chunk-CBIJP5PL.js +284 -0
  15. package/dist/{chunk-CLSLVFSP.js → chunk-GMDMOYXD.js} +2 -2
  16. package/dist/{chunk-NCNP2RKZ.js → chunk-GODZKHAL.js} +2 -2
  17. package/dist/{chunk-QWDKMVLX.js → chunk-IKULQIDX.js} +141 -82
  18. package/dist/{chunk-TWHYH25Q.js → chunk-JRW33U35.js} +80 -80
  19. package/dist/{chunk-G4GMXYMY.js → chunk-KQXXO42S.js} +93 -171
  20. package/dist/chunk-OKWD7LPO.js +80 -0
  21. package/dist/{chunk-YHY5K2Y7.js → chunk-PEST66PN.js} +6 -0
  22. package/dist/{chunk-WB2A6V3I.js → chunk-UGHAADU5.js} +47 -1
  23. package/dist/{chunk-2QB2PXOO.js → chunk-VHTJRS2N.js} +3 -5
  24. package/dist/{chunk-5GCI6C7J.js → chunk-WPNM2KC6.js} +2 -2
  25. package/dist/components/index.cjs +42017 -42467
  26. package/dist/components/index.d.ts +182 -319
  27. package/dist/components/index.js +621 -13
  28. package/dist/context/index.cjs +8 -3
  29. package/dist/context/index.js +3 -3
  30. package/dist/hooks/index.cjs +54 -4
  31. package/dist/hooks/index.js +7 -7
  32. package/dist/lib/drawable/three/index.cjs +47 -1
  33. package/dist/lib/drawable/three/index.d.ts +5 -5
  34. package/dist/lib/drawable/three/index.js +7 -7
  35. package/dist/lib/index.cjs +48 -1
  36. package/dist/lib/index.d.ts +2 -2
  37. package/dist/lib/index.js +6 -5
  38. package/dist/locales/index.cjs +141 -3
  39. package/dist/locales/index.js +95 -3
  40. package/dist/{paintDispatch-DHo3WhaU.d.ts → paintDispatch-_6EhJCiL.d.ts} +3 -3
  41. package/dist/providers/index.cjs +34611 -35020
  42. package/dist/providers/index.d.ts +33 -8
  43. package/dist/providers/index.js +36 -12
  44. package/dist/renderer/index.cjs +6 -0
  45. package/dist/renderer/index.d.ts +1 -1
  46. package/dist/renderer/index.js +1 -1
  47. package/dist/runtime/index.cjs +41106 -41488
  48. package/dist/runtime/index.d.ts +4 -2
  49. package/dist/runtime/index.js +11 -11
  50. package/dist/ssr/index.cjs +375 -137
  51. package/dist/ssr/index.d.cts +5 -1
  52. package/dist/ssr/index.d.ts +5 -1
  53. package/dist/ssr/index.js +311 -73
  54. package/dist/{verificationRegistry-BYD3cVhS.d.ts → verificationRegistry-CD7Xb40L.d.ts} +1 -1
  55. package/locales/ar.json +47 -1
  56. package/locales/en.json +47 -1
  57. package/locales/sl.json +47 -1
  58. package/package.json +6 -6
  59. package/tailwind-preset.cjs +13 -0
  60. package/themes/_base.css +28 -8
  61. package/themes/_contract.md +5 -0
  62. package/dist/Typography-7FRZOS2H.js +0 -5
  63. package/dist/{avl-3d-context-DLteNEwu.d.ts → avl-3d-context-MAt_NuU9.d.ts} +3 -3
  64. package/dist/{chunk-IN3BVW2Z.js → chunk-64WACXM7.js} +14 -14
@@ -0,0 +1,284 @@
1
+ import { Icon, Button, Switch, Input } from './chunk-3EF5SDIJ.js';
2
+ import { VStack, HStack } from './chunk-7LM6I3NA.js';
3
+ import { Typography } from './chunk-GMDMOYXD.js';
4
+ import { cn } from './chunk-64WACXM7.js';
5
+ import React from 'react';
6
+ import { useTranslate } from '@almadar/ui/hooks';
7
+ import { jsx, jsxs } from 'react/jsx-runtime';
8
+
9
+ var isObj = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
10
+ var isArr = (v) => Array.isArray(v);
11
+ function kindOf(v) {
12
+ if (v === null) return "null";
13
+ if (isArr(v)) return "array";
14
+ if (isObj(v)) return "object";
15
+ if (typeof v === "number") return "number";
16
+ if (typeof v === "boolean") return "boolean";
17
+ return "string";
18
+ }
19
+ var TYPE_LABEL_KEY = {
20
+ string: "jsonTree.type.text",
21
+ number: "jsonTree.type.number",
22
+ boolean: "jsonTree.type.boolean"
23
+ };
24
+ var TYPE_LABEL_SYMBOL = {
25
+ object: "{}",
26
+ array: "[]",
27
+ null: "\u2014"
28
+ };
29
+ function typeLabel(kind, t) {
30
+ if (kind === "object" || kind === "array" || kind === "null") return TYPE_LABEL_SYMBOL[kind];
31
+ return t(TYPE_LABEL_KEY[kind] ?? "");
32
+ }
33
+ var KIND_OPTIONS = ["string", "number", "boolean", "object", "array"];
34
+ function emptyOf(kind) {
35
+ switch (kind) {
36
+ case "object":
37
+ return {};
38
+ case "array":
39
+ return [];
40
+ case "number":
41
+ return 0;
42
+ case "boolean":
43
+ return false;
44
+ case "null":
45
+ return null;
46
+ default:
47
+ return "";
48
+ }
49
+ }
50
+ function templateFrom(arr) {
51
+ if (arr.length === 0) return "";
52
+ const first = arr[0];
53
+ if (isObj(first)) {
54
+ const blank = {};
55
+ for (const k of Object.keys(first)) blank[k] = isObj(first[k]) ? {} : isArr(first[k]) ? [] : first[k];
56
+ return blank;
57
+ }
58
+ if (isArr(first)) return [];
59
+ return emptyOf(kindOf(first));
60
+ }
61
+ function ScalarControl({
62
+ value,
63
+ onChange
64
+ }) {
65
+ if (typeof value === "boolean") {
66
+ return /* @__PURE__ */ jsx(Switch, { checked: value, onChange: (c) => onChange(c) });
67
+ }
68
+ const numeric = typeof value === "number";
69
+ const initial = value === null ? "" : String(value);
70
+ const [draft, setDraft] = React.useState(initial);
71
+ React.useEffect(() => setDraft(initial), [initial]);
72
+ const commit = () => {
73
+ if (numeric) {
74
+ const n = draft.trim() === "" ? 0 : Number(draft);
75
+ onChange(Number.isNaN(n) ? 0 : n);
76
+ } else {
77
+ onChange(draft);
78
+ }
79
+ };
80
+ return /* @__PURE__ */ jsx(
81
+ Input,
82
+ {
83
+ inputType: numeric ? "number" : "text",
84
+ value: draft,
85
+ placeholder: value === null ? "null" : void 0,
86
+ onChange: (e) => setDraft(e.target.value),
87
+ onBlur: commit,
88
+ onKeyDown: (e) => {
89
+ if (e.key === "Enter") commit();
90
+ }
91
+ }
92
+ );
93
+ }
94
+ function KindSelect({
95
+ kind,
96
+ onChange
97
+ }) {
98
+ const { t } = useTranslate();
99
+ return /* @__PURE__ */ jsx(
100
+ "select",
101
+ {
102
+ value: kind === "null" ? "string" : kind,
103
+ onChange: (e) => onChange(e.target.value),
104
+ "aria-label": t("jsonTree.valueType"),
105
+ className: cn(
106
+ "h-6 rounded-interactive bg-muted text-muted-foreground text-[10px] font-mono px-1",
107
+ "border-[length:var(--border-width-thin)] border-border",
108
+ "hover:bg-card focus:outline-none focus:ring-1 focus:ring-ring"
109
+ ),
110
+ children: KIND_OPTIONS.map((k) => /* @__PURE__ */ jsx("option", { value: k, children: typeLabel(k, t) }, k))
111
+ }
112
+ );
113
+ }
114
+ function ValueNode({
115
+ value,
116
+ onChange,
117
+ depth,
118
+ readonly
119
+ }) {
120
+ const kind = kindOf(value);
121
+ if (kind === "object" || kind === "array") {
122
+ return /* @__PURE__ */ jsx(ContainerNode, { value, onChange, depth, readonly });
123
+ }
124
+ if (readonly) {
125
+ return /* @__PURE__ */ jsx(Typography, { variant: "caption", className: "font-mono text-foreground", children: value === null ? "null" : String(value) });
126
+ }
127
+ return /* @__PURE__ */ jsx(ScalarControl, { value, onChange });
128
+ }
129
+ function Row({
130
+ rowKey,
131
+ isArrayItem,
132
+ value,
133
+ depth,
134
+ onValue,
135
+ onRenameKey,
136
+ onChangeKind,
137
+ onRemove,
138
+ readonly
139
+ }) {
140
+ const { t } = useTranslate();
141
+ const [keyDraft, setKeyDraft] = React.useState(rowKey);
142
+ React.useEffect(() => setKeyDraft(rowKey), [rowKey]);
143
+ const container = isObj(value) || isArr(value);
144
+ return /* @__PURE__ */ jsxs(VStack, { gap: "none", className: "group w-max min-w-full", children: [
145
+ /* @__PURE__ */ jsxs(HStack, { gap: "xs", align: "center", className: "py-0.5 w-max", children: [
146
+ readonly ? /* @__PURE__ */ jsx("span", { className: cn(
147
+ "h-6 rounded-interactive bg-muted text-muted-foreground text-[10px] font-mono px-1 flex items-center",
148
+ "border-[length:var(--border-width-thin)] border-border"
149
+ ), children: typeLabel(kindOf(value), t) }) : /* @__PURE__ */ jsx(KindSelect, { kind: kindOf(value), onChange: onChangeKind }),
150
+ isArrayItem ? /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", className: "w-6 shrink-0 font-mono", children: rowKey }) : readonly ? /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", className: "w-20 shrink-0 font-mono truncate", children: rowKey }) : /* @__PURE__ */ jsx("div", { className: "w-20 shrink-0", children: /* @__PURE__ */ jsx(
151
+ Input,
152
+ {
153
+ inputType: "text",
154
+ value: keyDraft,
155
+ onChange: (e) => setKeyDraft(e.target.value),
156
+ onBlur: () => keyDraft !== rowKey && onRenameKey(keyDraft),
157
+ onKeyDown: (e) => {
158
+ if (e.key === "Enter" && keyDraft !== rowKey) onRenameKey(keyDraft);
159
+ },
160
+ className: "font-mono"
161
+ }
162
+ ) }),
163
+ !container && /* @__PURE__ */ jsx("div", { className: "w-48 shrink-0", children: /* @__PURE__ */ jsx(ValueNode, { value, onChange: onValue, depth: depth + 1, readonly }) }),
164
+ !readonly && /* @__PURE__ */ jsx(
165
+ Button,
166
+ {
167
+ variant: "ghost",
168
+ size: "sm",
169
+ icon: "x",
170
+ onClick: onRemove,
171
+ "aria-label": t("common.remove"),
172
+ className: "shrink-0 text-muted-foreground hover:text-error"
173
+ }
174
+ )
175
+ ] }),
176
+ container && /* @__PURE__ */ jsx("div", { className: "pl-2", children: /* @__PURE__ */ jsx(ValueNode, { value, onChange: onValue, depth: depth + 1, readonly }) })
177
+ ] });
178
+ }
179
+ function ContainerNode({
180
+ value,
181
+ onChange,
182
+ depth,
183
+ readonly
184
+ }) {
185
+ const { t } = useTranslate();
186
+ const [open, setOpen] = React.useState(depth < 2);
187
+ const array = isArr(value);
188
+ const entries = array ? value.map((v, i) => [String(i), v]) : Object.entries(value);
189
+ const setObjValue = (key, next) => {
190
+ onChange({ ...value, [key]: next });
191
+ };
192
+ const renameKey = (oldKey, newKey) => {
193
+ if (!newKey || newKey === oldKey) return;
194
+ const out = {};
195
+ for (const [k, v] of Object.entries(value)) out[k === oldKey ? newKey : k] = v;
196
+ onChange(out);
197
+ };
198
+ const removeObjKey = (key) => {
199
+ const out = {};
200
+ for (const [k, v] of Object.entries(value)) if (k !== key) out[k] = v;
201
+ onChange(out);
202
+ };
203
+ const changeObjKind = (key, k) => setObjValue(key, emptyOf(k));
204
+ const setArrValue = (idx, next) => {
205
+ const copy = [...value];
206
+ copy[idx] = next;
207
+ onChange(copy);
208
+ };
209
+ const removeArrIdx = (idx) => onChange(value.filter((_, i) => i !== idx));
210
+ const changeArrKind = (idx, k) => setArrValue(idx, emptyOf(k));
211
+ const add = () => {
212
+ if (array) {
213
+ onChange([...value, templateFrom(value)]);
214
+ } else {
215
+ const obj = value;
216
+ let key = "key";
217
+ let n = 1;
218
+ while (key in obj) {
219
+ key = `key${n}`;
220
+ n += 1;
221
+ }
222
+ onChange({ ...obj, [key]: "" });
223
+ }
224
+ };
225
+ const summaryKey = array ? entries.length === 1 ? "jsonTree.itemCountOne" : "jsonTree.itemCountOther" : entries.length === 1 ? "jsonTree.fieldCountOne" : "jsonTree.fieldCountOther";
226
+ const summary = t(summaryKey, { count: entries.length });
227
+ return /* @__PURE__ */ jsxs(VStack, { gap: "none", className: "w-full", children: [
228
+ /* @__PURE__ */ jsx(HStack, { gap: "xs", align: "center", children: /* @__PURE__ */ jsxs(
229
+ "button",
230
+ {
231
+ type: "button",
232
+ onClick: () => setOpen((o) => !o),
233
+ className: "flex items-center gap-1 text-muted-foreground hover:text-foreground",
234
+ "aria-label": open ? t("jsonTree.collapse") : t("jsonTree.expand"),
235
+ children: [
236
+ /* @__PURE__ */ jsx(Icon, { name: open ? "chevron-down" : "chevron-right", size: "sm" }),
237
+ /* @__PURE__ */ jsx("span", { className: "font-mono text-xs", children: array ? "[ ]" : "{ }" }),
238
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", children: summary })
239
+ ]
240
+ }
241
+ ) }),
242
+ open && /* @__PURE__ */ jsxs(
243
+ VStack,
244
+ {
245
+ gap: "none",
246
+ className: cn("ml-1.5 pl-1.5 w-max min-w-full border-l-[length:var(--border-width-thin)] border-border"),
247
+ children: [
248
+ entries.map(([k, v], idx) => /* @__PURE__ */ jsx(
249
+ Row,
250
+ {
251
+ rowKey: k,
252
+ isArrayItem: array,
253
+ value: v,
254
+ depth,
255
+ onValue: (next) => array ? setArrValue(idx, next) : setObjValue(k, next),
256
+ onRenameKey: (nk) => renameKey(k, nk),
257
+ onChangeKind: (kind) => array ? changeArrKind(idx, kind) : changeObjKind(k, kind),
258
+ onRemove: () => array ? removeArrIdx(idx) : removeObjKey(k),
259
+ readonly
260
+ },
261
+ array ? idx : k
262
+ )),
263
+ !readonly && /* @__PURE__ */ jsx(
264
+ Button,
265
+ {
266
+ variant: "ghost",
267
+ size: "sm",
268
+ icon: "plus",
269
+ label: array ? t("jsonTree.addItem") : t("jsonTree.addField"),
270
+ onClick: add,
271
+ className: "self-start text-muted-foreground"
272
+ }
273
+ )
274
+ ]
275
+ }
276
+ )
277
+ ] });
278
+ }
279
+ var JsonTreeEditor = ({ value, onChange, className, readonly }) => {
280
+ const root = value ?? "";
281
+ return /* @__PURE__ */ jsx("div", { className: cn("w-full overflow-x-auto rounded-container bg-card/40 p-2 border-[length:var(--border-width-thin)] border-border", className), children: /* @__PURE__ */ jsx(ValueNode, { value: root, onChange, depth: 0, readonly }) });
282
+ };
283
+
284
+ export { JsonTreeEditor };
@@ -1,5 +1,5 @@
1
- import { cn, domPassthrough } from './chunk-IN3BVW2Z.js';
2
- import { formatValue } from './chunk-V5AGW2JN.js';
1
+ import { cn, domPassthrough } from './chunk-64WACXM7.js';
2
+ import { formatValue } from './chunk-4OZDHCZV.js';
3
3
  import React from 'react';
4
4
  import { useFormatContext } from '@almadar/ui/hooks';
5
5
 
@@ -1,5 +1,5 @@
1
- import { DEFAULT_CURRENCY } from './chunk-V5AGW2JN.js';
2
- import { en_default } from './chunk-WB2A6V3I.js';
1
+ import { DEFAULT_CURRENCY } from './chunk-4OZDHCZV.js';
2
+ import { en_default } from './chunk-UGHAADU5.js';
3
3
  import React, { createContext, useEffect, useContext, useMemo } from 'react';
4
4
 
5
5
  var { $meta: _meta, ...coreMessages } = en_default;
@@ -1,18 +1,18 @@
1
1
  import { runTickFrame } from './chunk-DQTV6QVS.js';
2
- import { ALL_SLOTS } from './chunk-2QB2PXOO.js';
3
- import { UISlotRenderer } from './chunk-EERAGPBW.js';
4
- import { Box } from './chunk-BHZG4PDZ.js';
5
- import { Typography } from './chunk-CLSLVFSP.js';
6
- import { beginPending, endPending } from './chunk-TWHYH25Q.js';
2
+ import { ALL_SLOTS } from './chunk-VHTJRS2N.js';
3
+ import { UISlotRenderer } from './chunk-3EF5SDIJ.js';
4
+ import { Box } from './chunk-7LM6I3NA.js';
5
+ import { Typography } from './chunk-GMDMOYXD.js';
6
+ import { beginPending, endPending } from './chunk-JRW33U35.js';
7
7
  import { useEventBus } from './chunk-6EV3OEBQ.js';
8
- import { registerTrait, unregisterTrait, perfTimeAsync } from './chunk-G4GMXYMY.js';
8
+ import { registerTrait, unregisterTrait, perfTimeAsync } from './chunk-KQXXO42S.js';
9
9
  import { bindTraitStateGetter, registerTraitSnapshot, recordTransition, recordingTransport, recordServerResponse } from './chunk-O7OLVVBR.js';
10
- import { isNotificationSlot } from './chunk-YHY5K2Y7.js';
10
+ import { isNotificationSlot } from './chunk-PEST66PN.js';
11
11
  import React, { useState, useMemo, useEffect, useRef, useCallback, useSyncExternalStore } from 'react';
12
12
  import { schemaToIR, getPage, clearSchemaCache as clearSchemaCache$1, applyListenPayloadMapping, buildResolvedTraitConfigs, collectCallsiteCaptureChildren, walkSExpr, isRenderBindingMarker, containsEntityBinding, isSExpr, isEventPayloadValue, RENDER_BINDING_MARKER } from '@almadar/core';
13
13
  import { createLogger } from '@almadar/logger';
14
- import { LIFECYCLE_EVENTS, InMemoryPersistence, createInProcessTransport, buildTraitIndex, createMemoryCircuitStore, createIndexStageRunner, evaluateOrbitalEvent, createClientKernel, collectListenerTargets, createTickScheduler, isValidCronExpression, parseDurationString, UNMOUNT_EVENT, createClientEffectHandlers, EffectExecutor, isSExpression, collectDeclaredConfigDefaults, createContextFromBindings, normalizeCallSiteConfigToValues } from '@almadar/runtime';
15
- import { useUser, useArbitraryClassStyles, getAllPages, matchPathAmong, CurrentPagePathProvider, NavStackProvider, OrbitalProvider, useNavStack, VerificationProvider, EntitySchemaProvider, OrbitalThemeProvider, ServerBridgeProvider, useServerBridge, EntityBindingContext } from '@almadar/ui/providers';
14
+ import { collectListenerTargets, LIFECYCLE_EVENTS, InMemoryPersistence, createInProcessTransport, buildTraitIndex, createMemoryCircuitStore, createIndexStageRunner, evaluateOrbitalEvent, createClientKernel, createTickScheduler, isValidCronExpression, parseDurationString, UNMOUNT_EVENT, createClientEffectHandlers, EffectExecutor, isSExpression, collectDeclaredConfigDefaults, createContextFromBindings, normalizeCallSiteConfigToValues } from '@almadar/runtime';
15
+ import { useUser, useArbitraryClassStyles, getAllPages, matchPathAmong, CurrentPagePathProvider, NavStackProvider, OrbitalProvider, useNavStack, VerificationProvider, EntitySchemaProvider, OrbitalThemeProvider, ServerBridgeProvider, useServerBridge, EntityBindingContext, AwaitingSkeletonContext } from '@almadar/ui/providers';
16
16
  import { evaluateListenPayloadExpr, evaluate, createMinimalContext, evaluateGuard, executeEffects } from '@almadar/evaluator';
17
17
  import { getPatternDefinition } from '@almadar/core/patterns';
18
18
  import { isKnownStdOperator } from '@almadar/std/registry';
@@ -270,6 +270,18 @@ function useCircuitKernel(traitBindings, options) {
270
270
  [baseTransport]
271
271
  );
272
272
  const orbitalName = options.orbitals[0]?.name ?? "";
273
+ const topology = useMemo(() => {
274
+ let resolve = () => void 0;
275
+ const promise = new Promise((r) => {
276
+ resolve = r;
277
+ });
278
+ return { promise, resolve };
279
+ }, [effectiveTransport]);
280
+ const awaitTopology = options.awaitTopology === true;
281
+ const confirmedCarries = options.carriesCircuitState ?? false;
282
+ useEffect(() => {
283
+ if (!awaitTopology) topology.resolve({ carriesCircuitState: confirmedCarries });
284
+ }, [awaitTopology, confirmedCarries, topology]);
273
285
  const rawKernel = useMemo(() => createClientKernel({
274
286
  orbitalName,
275
287
  traitIndex,
@@ -282,7 +294,8 @@ function useCircuitKernel(traitBindings, options) {
282
294
  ...options.contextExtensions !== void 0 ? { contextExtensions: options.contextExtensions } : {},
283
295
  ...options.debug !== void 0 ? { debug: options.debug } : {},
284
296
  ...options.logContext !== void 0 ? { logContext: options.logContext } : {},
285
- carriesCircuitState: options.carriesCircuitState ?? false,
297
+ carriesCircuitState: false,
298
+ topology: topology.promise,
286
299
  ...effectiveTransport !== void 0 ? { transport: effectiveTransport } : {}
287
300
  }), [
288
301
  orbitalName,
@@ -296,50 +309,16 @@ function useCircuitKernel(traitBindings, options) {
296
309
  options.contextExtensions,
297
310
  options.debug,
298
311
  options.logContext,
299
- options.carriesCircuitState,
312
+ topology,
300
313
  effectiveTransport
301
314
  ]);
302
- const rawKernelRef = useRef(rawKernel);
303
- rawKernelRef.current = rawKernel;
304
- const awaitTopology = options.awaitTopology === true;
305
- const holdRef = useRef(awaitTopology);
306
- holdRef.current = awaitTopology;
307
- const heldRef = useRef([]);
308
- useEffect(() => {
309
- if (awaitTopology) return;
310
- const held = heldRef.current;
311
- heldRef.current = [];
312
- for (const release of held) release();
313
- }, [awaitTopology, rawKernel]);
314
315
  const kernel = useMemo(() => ({
315
316
  store: rawKernel.store,
316
- dispatch: (request) => {
317
- const stamped = request.clientId !== void 0 ? request : { ...request, clientId: getTabClientId() };
318
- if (!holdRef.current) return rawKernel.dispatch(stamped);
319
- return new Promise((resolve, reject) => {
320
- heldRef.current.push(() => {
321
- rawKernelRef.current.dispatch(stamped).then(resolve, reject);
322
- });
323
- });
324
- }
317
+ dispatch: (request, hooks) => rawKernel.dispatch(request.clientId !== void 0 ? request : { ...request, clientId: getTabClientId() }, hooks),
318
+ dispatchMount: (seeds, hooks, base = {}) => rawKernel.dispatchMount(seeds, hooks, base.clientId !== void 0 ? base : { ...base, clientId: getTabClientId() }),
319
+ dispatchProgress: (request) => rawKernel.dispatchProgress(request.clientId !== void 0 ? request : { ...request, clientId: getTabClientId() })
325
320
  }), [rawKernel]);
326
- const kernelRef = useRef(kernel);
327
- kernelRef.current = kernel;
328
- useEffect(() => {
329
- if (!effectiveTransport?.subscribe) return;
330
- return effectiveTransport.subscribe((emitted) => {
331
- const targets = collectListenerTargets(traitIndex, emitted.source, emitted.event, emitted.payload);
332
- for (const target of targets) {
333
- void kernelRef.current.dispatch({
334
- event: target.triggers,
335
- ...target.payload !== void 0 ? { payload: target.payload } : {},
336
- ...target.entityId !== void 0 ? { entityId: target.entityId } : {},
337
- targetTrait: target.listenerTrait
338
- });
339
- }
340
- }, { clientId: getTabClientId() });
341
- }, [effectiveTransport, traitIndex]);
342
- return { kernel, store, traitIndex };
321
+ return { kernel, store, traitIndex, transport: effectiveTransport };
343
322
  }
344
323
  var log2 = createLogger("almadar:ui:circuit:bus-ingress");
345
324
  function useBusIngress(traitBindings, traitIndex, settle, eventBus) {
@@ -519,7 +498,7 @@ function resolveLambdaBindings(body, params, item, index) {
519
498
  return body;
520
499
  }
521
500
  var LazySlotContentRenderer = React.lazy(
522
- () => import('./UISlotRenderer-CR7SCAMR.js').then((m) => ({ default: m.SlotContentRenderer }))
501
+ () => import('./UISlotRenderer-JT34I3O7.js').then((m) => ({ default: m.SlotContentRenderer }))
523
502
  );
524
503
  function deferLambdaEntityExprs(value) {
525
504
  if (typeof value === "string") {
@@ -1131,6 +1110,25 @@ function sameFields(a, b) {
1131
1110
  }
1132
1111
  return true;
1133
1112
  }
1113
+ function useAwaitingSkeletonSource(store, traitIndex, embeddedTraits) {
1114
+ return useMemo(() => {
1115
+ const activeRenders = () => {
1116
+ const renders = [];
1117
+ for (const awaiting of store.awaiting.list()) {
1118
+ const transitions = traitIndex.byName.get(awaiting.trait)?.irTrait.stateMachine?.transitions ?? [];
1119
+ const taken = transitions.find((t) => t.event === awaiting.event && t.from === awaiting.from);
1120
+ if (taken?.awaitRender) renders.push(...taken.awaitRender);
1121
+ }
1122
+ return renders;
1123
+ };
1124
+ return {
1125
+ forSlot: (slot) => activeRenders().find((r) => r.slot === slot && !(embeddedTraits?.has(r.trait) ?? false))?.skeleton,
1126
+ forTrait: (traitName) => activeRenders().find((r) => r.trait === traitName)?.skeleton,
1127
+ subscribe: (callback) => store.awaiting.subscribeAll(callback),
1128
+ getVersion: () => store.awaiting.getVersion()
1129
+ };
1130
+ }, [store, traitIndex, embeddedTraits]);
1131
+ }
1134
1132
 
1135
1133
  // hooks/useTraitStateMachine.ts
1136
1134
  var stateLog = createLogger("almadar:ui:state-transitions");
@@ -1149,7 +1147,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
1149
1147
  const { user: contextViewer } = useUser();
1150
1148
  const userContext = options.user ?? contextViewer ?? void 0;
1151
1149
  const observer = useMemo(() => createCircuitVerificationObserver(), []);
1152
- const { kernel, store, traitIndex } = useCircuitKernel(traitBindings, {
1150
+ const { kernel, store, traitIndex, transport } = useCircuitKernel(traitBindings, {
1153
1151
  orbitals: options.orbitals,
1154
1152
  ...options.traitConfigsByName !== void 0 ? { traitConfigsByName: options.traitConfigsByName } : {},
1155
1153
  ...options.transport !== void 0 ? { transport: options.transport } : {},
@@ -1179,6 +1177,7 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
1179
1177
  ...userContext !== void 0 ? { user: userContext } : {}
1180
1178
  });
1181
1179
  const entityBindingSource = useEntityBindingSource(store, traitIndex);
1180
+ const awaitingSkeletonSource = useAwaitingSkeletonSource(store, traitIndex, options.embeddedTraits);
1182
1181
  const activeTraitNamesRef = useRef(/* @__PURE__ */ new Set());
1183
1182
  useEffect(() => {
1184
1183
  activeTraitNamesRef.current = new Set(traitIndex.byName.keys());
@@ -1226,6 +1225,35 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
1226
1225
  for (const unreg of snapshotUnregs) unreg();
1227
1226
  };
1228
1227
  }, [traitBindings, store, traitIndex]);
1228
+ const afterSettle = useCallback(async (traitName, eventKey, payload, transitioned, repaints, composedBefore) => {
1229
+ if (transitioned) {
1230
+ const entityByTrait = {};
1231
+ for (const [name, entry] of traitIndex.byName) {
1232
+ const row = store.frames.get(entry.frameKey);
1233
+ if (row !== void 0) entityByTrait[name] = row;
1234
+ }
1235
+ const repainted = new Set(repaints.map((e) => e.traitName));
1236
+ const serverComposed = new Set([...store.callsitePayloads].filter(([child, composed]) => composedBefore.get(child) !== composed).map(([child]) => child));
1237
+ await reRenderCallsiteCaptureChildren(traitName, payload ?? {}, entityByTrait, repainted, serverComposed);
1238
+ }
1239
+ options.onEventProcessed?.(eventKey, payload);
1240
+ }, [traitIndex, store, reRenderCallsiteCaptureChildren, options.onEventProcessed]);
1241
+ const settleOutcome = useCallback(async (traitName, eventKey, payload, outcome, composedBefore) => {
1242
+ recordDispatchVerdict(traitIndex.byName.get(traitName)?.orbitalName ?? traitName, eventKey, { response: outcome.response });
1243
+ const settledEffects = outcome.localPainted && outcome.serverEffects !== void 0 ? outcome.serverEffects : outcome.response;
1244
+ slotFlush.applyClientEffects(
1245
+ settledEffects.clientEffects ?? [],
1246
+ settledEffects.clientEffectsByTrait,
1247
+ options.navigate,
1248
+ options.navigateBack,
1249
+ activeTraitNamesRef.current
1250
+ );
1251
+ for (const emitted of outcome.response.emittedEvents) {
1252
+ eventBus.emit(`UI:${emitted.event}`, emitted.payload, { ...emitted.source ?? {}, dispatched: true });
1253
+ }
1254
+ stateLog.debug("dispatch:settled", { traitName, eventKey, mode: outcome.mode, transitioned: outcome.response.transitioned });
1255
+ await afterSettle(traitName, eventKey, payload, outcome.response.transitioned, outcome.response.clientEffectsByTrait ?? [], composedBefore);
1256
+ }, [slotFlush, traitIndex, eventBus, options.navigate, options.navigateBack, afterSettle]);
1229
1257
  const dispatchAndSettle = useCallback(async (traitName, eventKey, payload, tick) => {
1230
1258
  const entityId = typeof payload?.entityId === "string" ? payload.entityId : void 0;
1231
1259
  const orbitalName = traitIndex.byName.get(traitName)?.orbitalName ?? traitName;
@@ -1256,34 +1284,63 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
1256
1284
  recordDispatchVerdict(orbitalName, eventKey, { error: err instanceof Error ? err : String(err) });
1257
1285
  throw err;
1258
1286
  }
1259
- recordDispatchVerdict(orbitalName, eventKey, { response: outcome.response });
1260
1287
  if (outcome.localPainted && !outcome.response.success && beforeLocalPaint !== void 0) {
1261
1288
  slotFlush.rollback(beforeLocalPaint);
1262
1289
  }
1263
- const settledEffects = outcome.localPainted && outcome.serverEffects !== void 0 ? outcome.serverEffects : outcome.response;
1264
- slotFlush.applyClientEffects(
1265
- settledEffects.clientEffects ?? [],
1266
- settledEffects.clientEffectsByTrait,
1267
- options.navigate,
1268
- options.navigateBack,
1269
- activeTraitNamesRef.current
1270
- );
1271
- for (const emitted of outcome.response.emittedEvents) {
1272
- eventBus.emit(`UI:${emitted.event}`, emitted.payload, { ...emitted.source ?? {}, dispatched: true });
1273
- }
1274
- stateLog.debug("dispatch:settled", { traitName, eventKey, mode: outcome.mode, transitioned: outcome.response.transitioned });
1275
- if (outcome.response.transitioned) {
1276
- const entityByTrait = {};
1277
- for (const [name, entry] of traitIndex.byName) {
1278
- const row = store.frames.get(entry.frameKey);
1279
- if (row !== void 0) entityByTrait[name] = row;
1290
+ await settleOutcome(traitName, eventKey, payload, outcome, composedBefore);
1291
+ }, [kernel, slotFlush, traitIndex, store, options.navigate, options.navigateBack, settleOutcome]);
1292
+ const progressAndSettle = useCallback(async (traitName, eventKey, payload) => {
1293
+ const entityId = typeof payload?.entityId === "string" ? payload.entityId : void 0;
1294
+ const composedBefore = new Map(store.callsitePayloads);
1295
+ const outcome = await kernel.dispatchProgress({
1296
+ event: eventKey,
1297
+ ...payload !== void 0 ? { payload } : {},
1298
+ ...entityId !== void 0 ? { entityId } : {},
1299
+ targetTrait: traitName
1300
+ });
1301
+ await settleOutcome(traitName, eventKey, payload, outcome, composedBefore);
1302
+ }, [kernel, store, settleOutcome]);
1303
+ useEffect(() => {
1304
+ if (!transport?.subscribe) return;
1305
+ return transport.subscribe((emitted, target) => {
1306
+ for (const t of collectListenerTargets(traitIndex, emitted.source, emitted.event, emitted.payload)) {
1307
+ void (target === "origin" ? progressAndSettle(t.listenerTrait, t.triggers, t.payload) : dispatchAndSettle(t.listenerTrait, t.triggers, t.payload));
1280
1308
  }
1281
- const repainted = new Set((outcome.response.clientEffectsByTrait ?? []).map((e) => e.traitName));
1282
- const serverComposed = new Set([...store.callsitePayloads].filter(([child, composed]) => composedBefore.get(child) !== composed).map(([child]) => child));
1283
- await reRenderCallsiteCaptureChildren(traitName, payload ?? {}, entityByTrait, repainted, serverComposed);
1309
+ }, { clientId: getTabClientId() });
1310
+ }, [transport, traitIndex, progressAndSettle, dispatchAndSettle]);
1311
+ const mountAndSettle = useCallback(async (seeds, payload) => {
1312
+ const composedBefore = new Map(store.callsitePayloads);
1313
+ let beforeLocalPaint;
1314
+ let outcome;
1315
+ try {
1316
+ outcome = await kernel.dispatchMount(seeds, {
1317
+ onLocal: (_trait, local) => {
1318
+ if (beforeLocalPaint === void 0) beforeLocalPaint = slotFlush.checkpoint();
1319
+ slotFlush.applyClientEffects(local.clientEffects ?? [], local.clientEffectsByTrait, options.navigate, options.navigateBack, activeTraitNamesRef.current);
1320
+ }
1321
+ }, { payload });
1322
+ } catch (err) {
1323
+ if (beforeLocalPaint !== void 0) slotFlush.rollback(beforeLocalPaint);
1324
+ for (const seed of seeds) {
1325
+ recordDispatchVerdict(traitIndex.byName.get(seed.trait)?.orbitalName ?? seed.trait, seed.event, { error: err instanceof Error ? err : String(err) });
1326
+ }
1327
+ throw err;
1284
1328
  }
1285
- options.onEventProcessed?.(eventKey, payload);
1286
- }, [kernel, slotFlush, traitIndex, store, eventBus, reRenderCallsiteCaptureChildren, options.navigate, options.navigateBack, options.onEventProcessed]);
1329
+ if (!outcome.success && beforeLocalPaint !== void 0) slotFlush.rollback(beforeLocalPaint);
1330
+ slotFlush.applyClientEffects(outcome.serverEffects.clientEffects ?? [], outcome.serverEffects.clientEffectsByTrait, options.navigate, options.navigateBack, activeTraitNamesRef.current);
1331
+ const emitted = [...outcome.seeds.flatMap((seed) => seed.local.emittedEvents), ...outcome.emittedEvents];
1332
+ for (const e of emitted) {
1333
+ eventBus.emit(`UI:${e.event}`, e.payload, { ...e.source ?? {}, dispatched: true });
1334
+ }
1335
+ const serverRepaints = outcome.serverEffects.clientEffectsByTrait ?? [];
1336
+ for (const seed of outcome.seeds) {
1337
+ recordDispatchVerdict(traitIndex.byName.get(seed.trait)?.orbitalName ?? seed.trait, seed.event, {
1338
+ response: { ...seed.local, success: outcome.success, ...outcome.error !== void 0 ? { error: outcome.error } : {} }
1339
+ });
1340
+ stateLog.debug("mount:settled", { traitName: seed.trait, eventKey: seed.event, mode: seed.mode, transitioned: seed.local.transitioned });
1341
+ await afterSettle(seed.trait, seed.event, payload, seed.local.transitioned, [...seed.local.clientEffectsByTrait ?? [], ...serverRepaints], composedBefore);
1342
+ }
1343
+ }, [kernel, slotFlush, traitIndex, store, eventBus, options.navigate, options.navigateBack, afterSettle]);
1287
1344
  useBusIngress(traitBindings, traitIndex, dispatchAndSettle, eventBus);
1288
1345
  const sendEvent = useCallback((eventKey, payload) => {
1289
1346
  const normalized = normalizeEventKey(eventKey);
@@ -1324,17 +1381,19 @@ function useTraitStateMachine(traitBindings, uiSlots, options) {
1324
1381
  if (mount.initialized.has(traitName)) continue;
1325
1382
  mount.initialized.add(traitName);
1326
1383
  const lifecycleEvent = LIFECYCLE_EVENTS.find((evt) => store.manager.canHandleEvent(traitName, evt));
1327
- if (lifecycleEvent !== void 0) entering.push({ traitName, lifecycleEvent });
1384
+ if (lifecycleEvent !== void 0) entering.push({ trait: traitName, event: lifecycleEvent });
1328
1385
  }
1329
- store.mount.mounting(entering.map((e) => e.traitName));
1330
- for (const { traitName, lifecycleEvent } of entering) {
1331
- void dispatchAndSettle(traitName, lifecycleEvent, { ...options.initPayload ?? {} });
1386
+ store.mount.mounting(entering.map((e) => e.trait));
1387
+ if (entering.length > 0) {
1388
+ void mountAndSettle(entering, { ...options.initPayload ?? {} }).catch((err) => {
1389
+ stateLog.warn("mount:failed", { traits: entering.map((e) => e.trait), error: String(err) });
1390
+ });
1332
1391
  }
1333
1392
  mountedRef.current = mount;
1334
- }, [traitBindings, store, dispatchAndSettle, mountKey]);
1393
+ }, [traitBindings, store, mountAndSettle, mountKey]);
1335
1394
  useSyncExternalStore(store.subscribe, store.getVersion, store.getVersion);
1336
1395
  const traitStates = useMemo(() => store.manager.getAllStates(), [store, store.getVersion()]);
1337
- return { traitStates, sendEvent, getTraitState, canHandleEvent, entityBindingSource };
1396
+ return { traitStates, sendEvent, getTraitState, canHandleEvent, entityBindingSource, awaitingSkeletonSource };
1338
1397
  }
1339
1398
 
1340
1399
  // runtime/fitContent.ts
@@ -1405,7 +1464,7 @@ function TraitInitializer({ traits, routeParams, mountKey, orbitals, onNavigate,
1405
1464
  }, localFallbackTimeoutMs ?? 5e3);
1406
1465
  return () => clearTimeout(timer);
1407
1466
  }, [hasBridge, bridge.connected, onLocalFallback, localFallbackTimeoutMs]);
1408
- const { entityBindingSource } = useTraitStateMachine(traits, uiSlots, {
1467
+ const { entityBindingSource, awaitingSkeletonSource } = useTraitStateMachine(traits, uiSlots, {
1409
1468
  orbitals,
1410
1469
  ...onNavigate !== void 0 ? { navigate: onNavigate } : {},
1411
1470
  ...onNavigateBack !== void 0 ? { navigateBack: onNavigateBack } : {},
@@ -1416,7 +1475,7 @@ function TraitInitializer({ traits, routeParams, mountKey, orbitals, onNavigate,
1416
1475
  ...mountKey !== void 0 ? { mountKey } : {},
1417
1476
  ...hasBridge ? { transport: bridge.transport, carriesCircuitState: bridge.carriesCircuitState, awaitTopology: !bridge.topologyKnown } : { persistence }
1418
1477
  });
1419
- return /* @__PURE__ */ jsx(EntityBindingContext.Provider, { value: entityBindingSource, children });
1478
+ return /* @__PURE__ */ jsx(EntityBindingContext.Provider, { value: entityBindingSource, children: /* @__PURE__ */ jsx(AwaitingSkeletonContext.Provider, { value: awaitingSkeletonSource, children }) });
1420
1479
  }
1421
1480
  var CONTENT_STAGE_WIDTH = 480;
1422
1481
  function FitToBox({ children, mode = "box" }) {