@almadar/shell-web 0.1.0 → 1.0.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 (118) hide show
  1. package/dist/{ArbitraryClassCompiler-Mzabq-UB.d.ts → ArbitraryClassCompiler-CO_iASBn.d.ts} +99 -4
  2. package/dist/AvlGlyph-EPJKFEO3.js +6 -0
  3. package/dist/AvlStateMachine-RKZIKNGC.js +9 -0
  4. package/dist/AvlTransitionDetail-63SD6GZF.js +11 -0
  5. package/dist/AvlTransitionExplainer-ZBTLOM3T.js +12 -0
  6. package/dist/BehaviorView-YS5G4GNB.js +11 -0
  7. package/dist/{Canvas3DHost-_Y-5uLM_.d.ts → Canvas3DHost-BkZQB5l2.d.ts} +1 -1
  8. package/dist/{EventBusProvider-CVwjkV_2.d.ts → EventBusProvider-BFFHfN4O.d.ts} +12 -0
  9. package/dist/FlowCanvas-AUMTWMNG.js +26 -0
  10. package/dist/{GameAudioProvider-Cm9BnvmP.d.ts → GameAudioProvider-ceM_n0ey.d.ts} +4 -7
  11. package/dist/KernelEngineContext-CcxGYtlr.d.ts +33 -0
  12. package/dist/LayersPanel-M2LHWUFF.js +6 -0
  13. package/dist/ModuleCard-QHDGK5XK.js +7 -0
  14. package/dist/OrbInspector-QCPEPUPH.js +26 -0
  15. package/dist/{Select-mDZIwNqN.d.ts → Select-B-iDdnvE.d.ts} +16 -30
  16. package/dist/ServerBridge-Bqsj-lOU.d.ts +124 -0
  17. package/dist/UISlotRenderer-C7WWOK43.js +26 -0
  18. package/dist/auth/browser/index.js +1 -0
  19. package/dist/auth/react/index.d.ts +8 -1
  20. package/dist/auth/react/index.js +40 -2
  21. package/dist/avl/index.d.ts +89 -79
  22. package/dist/avl/index.js +38 -38
  23. package/dist/{avl-3d-context-BIRKWpaL.d.ts → avl-3d-context-BycmO6tG.d.ts} +9 -12
  24. package/dist/{chunk-GKIFONTE.js → chunk-3S54FWRC.js} +2 -2
  25. package/dist/{chunk-DYEKAA4L.js → chunk-3VZ36ZKO.js} +240 -252
  26. package/dist/{chunk-PC7K4SK7.js → chunk-4T3P43NS.js} +18 -269
  27. package/dist/{chunk-MBQAMMSE.js → chunk-4YXBKHHM.js} +269 -658
  28. package/dist/{chunk-YDNJLLG6.js → chunk-57DC34LY.js} +19 -10
  29. package/dist/{chunk-SJGJJKBY.js → chunk-AB3X7QTE.js} +6 -3
  30. package/dist/{chunk-AILY3XPS.js → chunk-AE7VCQB6.js} +5 -6
  31. package/dist/{chunk-FAJDTHWC.js → chunk-AGXD77SL.js} +2 -2
  32. package/dist/chunk-AU7O65OX.js +66 -0
  33. package/dist/{chunk-L677XGY3.js → chunk-CPLN6NBQ.js} +5 -5
  34. package/dist/{chunk-DZ42OJQC.js → chunk-DZBQA2OW.js} +1 -1
  35. package/dist/{chunk-2PY54Z44.js → chunk-E6KA4J6N.js} +5 -5
  36. package/dist/{chunk-DJ433ET5.js → chunk-GFXCPUMX.js} +11 -4
  37. package/dist/{chunk-FP3WIKTC.js → chunk-HH5KSMH5.js} +9 -1
  38. package/dist/{chunk-U6QRZASX.js → chunk-ILQXJ2AR.js} +1 -1
  39. package/dist/{chunk-B4BU77LT.js → chunk-ILZ7ORX7.js} +1 -1
  40. package/dist/{chunk-SGM3FASH.js → chunk-K4MOPSEL.js} +14 -12
  41. package/dist/{chunk-GYTPOFVC.js → chunk-LHP2TK7O.js} +7402 -6970
  42. package/dist/{chunk-VFF5OO47.js → chunk-PCR37T3U.js} +15 -38
  43. package/dist/{chunk-R5O5AUPI.js → chunk-PRXQGGCO.js} +93 -86
  44. package/dist/{chunk-42FY4RYA.js → chunk-REXYVBUO.js} +2 -2
  45. package/dist/{chunk-DLZF4PVE.js → chunk-ROICKAU7.js} +3 -3
  46. package/dist/{chunk-KVQS4GXU.js → chunk-SP5CDJ6K.js} +18 -8
  47. package/dist/{chunk-P4LNHAFI.js → chunk-TUPZWTRE.js} +2 -2
  48. package/dist/chunk-TXAUOLWZ.js +490 -0
  49. package/dist/{chunk-EQAMU2ZC.js → chunk-UTDC2NEA.js} +1 -1
  50. package/dist/{chunk-73SRAB4P.js → chunk-UU57VNS2.js} +2 -2
  51. package/dist/{chunk-DFNZUYX4.js → chunk-UXLE3IPR.js} +70 -27
  52. package/dist/{chunk-L2DEKY4J.js → chunk-VO2TTLS5.js} +3 -6
  53. package/dist/{chunk-TESBIVUA.js → chunk-X3DMMX27.js} +2 -2
  54. package/dist/components/index.d.ts +331 -125
  55. package/dist/components/index.js +28 -28
  56. package/dist/context/index.d.ts +2 -3
  57. package/dist/context/index.js +4 -3
  58. package/dist/core.d.ts +93 -17
  59. package/dist/core.js +2 -1
  60. package/dist/design-classes/index.cjs +3 -1
  61. package/dist/design-classes/index.js +3 -1
  62. package/dist/hooks/index.d.ts +40 -5
  63. package/dist/hooks/index.js +5 -4
  64. package/dist/index.d.ts +36 -114
  65. package/dist/index.js +174 -34
  66. package/dist/kernel-client-TZKGHJRY.js +516 -0
  67. package/dist/kernel-wire-wNdAPfhJ.d.ts +88 -0
  68. package/dist/lib/index.d.ts +3 -3
  69. package/dist/lib/index.js +5 -4
  70. package/dist/{paintDispatch-ChW5mVuK.d.ts → paintDispatch-CuJLsr9Y.d.ts} +5 -15
  71. package/dist/{prism-AIWGN2X5.js → prism-X5YWKXO5.js} +5 -3
  72. package/dist/providers/index.d.ts +42 -27
  73. package/dist/providers/index.js +22 -23
  74. package/dist/renderer/index.d.ts +0 -2
  75. package/dist/renderer/index.js +1 -0
  76. package/dist/runtime/index.d.ts +52 -253
  77. package/dist/runtime/index.js +21 -24
  78. package/dist/ssr/index.cjs +2643 -535
  79. package/dist/ssr/index.d.cts +0 -23
  80. package/dist/ssr/index.d.ts +0 -23
  81. package/dist/ssr/index.js +2639 -535
  82. package/dist/storage/browser/index.js +1 -0
  83. package/dist/test-support.d.ts +15 -8
  84. package/dist/test-support.js +91 -24
  85. package/dist/three/index.d.ts +6 -6
  86. package/dist/three/index.js +49 -37
  87. package/dist/{verificationRegistry-CabxhfTv.d.ts → verificationRegistry-CVrcxG1s.d.ts} +3 -3
  88. package/package.json +13 -9
  89. package/src/core/lib/band-shapes.json +7 -0
  90. package/src/core/locales/ar.json +18 -5
  91. package/src/core/locales/en.json +18 -5
  92. package/src/core/locales/sl.json +18 -5
  93. package/tailwind-preset.cjs +30 -1
  94. package/dist/AvlGlyph-JKJOAH23.js +0 -6
  95. package/dist/AvlStateMachine-PI4YGREK.js +0 -8
  96. package/dist/AvlTransitionDetail-ZH7V24UG.js +0 -12
  97. package/dist/AvlTransitionExplainer-ZSRT7L6Y.js +0 -13
  98. package/dist/BehaviorValueFrame-6RUJXT4A.js +0 -29
  99. package/dist/BehaviorValueFrame-SSEMEBTG.css +0 -1756
  100. package/dist/BehaviorView-RFEE5J6E.js +0 -10
  101. package/dist/FlowCanvas-STDC4OWK.js +0 -27
  102. package/dist/KernelEngineContext-BOCQoFwk.d.ts +0 -43
  103. package/dist/LayersPanel-BBQ54IVG.js +0 -7
  104. package/dist/ModuleCard-3TT2X7IW.js +0 -7
  105. package/dist/OrbInspector-K6T6O7GI.js +0 -27
  106. package/dist/ServerBridge-Cm1On51b.d.ts +0 -233
  107. package/dist/TraitValueFrame-2PJGLLVI.js +0 -28
  108. package/dist/TraitValueFrame-4G3KOUBR.css +0 -1756
  109. package/dist/UISlotRenderer-JKFSX24W.js +0 -27
  110. package/dist/UserContext-DqWeZkUZ.d.ts +0 -100
  111. package/dist/chunk-2QOH2HWM.js +0 -95
  112. package/dist/chunk-6P3MWXYE.js +0 -440
  113. package/dist/chunk-FIW6WN23.js +0 -508
  114. package/dist/chunk-GAR5TQ5B.js +0 -199
  115. package/dist/chunk-ZO6MXAS3.js +0 -69
  116. package/dist/kernel-client-ZH4PSMCN.js +0 -367
  117. package/dist/kernel-wire-B4S8pnP3.d.ts +0 -65
  118. package/dist/useKeyboardRouter-Dsq553Ur.d.ts +0 -42
@@ -1,46 +1,11 @@
1
- import { routing_exports } from './chunk-DYEKAA4L.js';
2
1
  import { renderUiEntriesOf } from '@almadar/core/patterns';
3
- import { isInlineTrait } from '@almadar/core';
2
+ import { kernelEvaluator } from '@almadar/core';
4
3
 
5
- function instanceOf(orbital, orbitalId, ref) {
6
- const at = orbitalId === void 0 ? { orbital } : { orbital, orbitalId };
7
- if (isInlineTrait(ref)) return { ...at, name: ref.name, trait: ref };
8
- if (typeof ref === "object" && ref._resolved) return { ...at, name: ref.name ?? ref._resolved.name, trait: ref._resolved };
9
- return null;
10
- }
11
4
  var wiresBySchema = /* @__PURE__ */ new WeakMap();
12
5
  function traitEventWires(schema) {
13
6
  const cached = wiresBySchema.get(schema);
14
7
  if (cached) return cached;
15
- const instances = (schema.orbitals ?? []).flatMap(
16
- (o) => (o.traits ?? []).map((ref) => instanceOf(o.name, o.id, ref)).filter((i) => i !== null)
17
- );
18
- const listensByEvent = /* @__PURE__ */ new Map();
19
- for (const listener of instances) {
20
- for (const listen of listener.trait.listens ?? []) {
21
- const { bareEvent, matcher } = (0, routing_exports.parseListenSource)(listen, listener.orbital);
22
- const bucket = listensByEvent.get(bareEvent);
23
- if (bucket) bucket.push({ listener, matcher });
24
- else listensByEvent.set(bareEvent, [{ listener, matcher }]);
25
- }
26
- }
27
- const wires = [];
28
- for (const emitter of instances) {
29
- const source = { orbital: emitter.orbital, trait: emitter.name, ...emitter.orbitalId ? { orbitalId: emitter.orbitalId } : {}, ...emitter.trait.id ? { traitId: emitter.trait.id } : {} };
30
- for (const emit of emitter.trait.emits ?? []) {
31
- for (const { listener, matcher } of listensByEvent.get(emit.event) ?? []) {
32
- if (listener.orbital === emitter.orbital && listener.name === emitter.name) continue;
33
- if (!matcher(source)) continue;
34
- wires.push({
35
- emitterOrbital: emitter.orbital,
36
- emitterTrait: emitter.name,
37
- listenerOrbital: listener.orbital,
38
- listenerTrait: listener.name,
39
- event: emit.event
40
- });
41
- }
42
- }
43
- }
8
+ const wires = kernelEvaluator().eventWires(schema);
44
9
  wiresBySchema.set(schema, wires);
45
10
  return wires;
46
11
  }
@@ -269,6 +234,18 @@ function traitLevelFromDescription(description) {
269
234
  description.events.listens
270
235
  );
271
236
  }
237
+ function traitLevelFromMounted(trait) {
238
+ return {
239
+ name: trait.trait,
240
+ linkedEntity: trait.linkedEntity ?? "",
241
+ states: trait.states.map((s) => ({ name: s.name, isInitial: s.isInitial, isTerminal: s.isTerminal })),
242
+ transitions: trait.transitions.flatMap(
243
+ (t) => t.from.map((from) => ({ from, to: t.to, event: t.event, guard: null, effects: [], index: t.index }))
244
+ ),
245
+ emittedEvents: trait.emits,
246
+ listenedEvents: trait.listens.map((l) => l.event)
247
+ };
248
+ }
272
249
  function traitLevelOf(name, linkedEntity, sm, emittedEvents, listenedEvents) {
273
250
  const states = getStates(sm).map((s) => ({
274
251
  name: s.name ?? "",
@@ -316,4 +293,4 @@ function parseTransitionLevel(schema, orbitalName, traitName, transitionIndex) {
316
293
  };
317
294
  }
318
295
 
319
- export { parseApplicationLevel, parseOrbitalLevel, parseTraitLevel, parseTransitionLevel, programTraits, traitEventWires, traitLevelFromDescription, traitLevelFromTrait, traitTransitionRenderUi };
296
+ export { parseApplicationLevel, parseOrbitalLevel, parseTraitLevel, parseTransitionLevel, programTraits, traitEventWires, traitLevelFromDescription, traitLevelFromMounted, traitLevelFromTrait, traitTransitionRenderUi };
@@ -1,7 +1,30 @@
1
- import { useEventBus, useTranslate } from './chunk-MBQAMMSE.js';
2
- import { useRef, useEffect, useCallback, useState, useMemo } from 'react';
1
+ import { useEventBus, useTranslate } from './chunk-4YXBKHHM.js';
2
+ import { createContext, useMemo, useContext, useRef, useEffect, useCallback, useState } from 'react';
3
+ import { jsx } from 'react/jsx-runtime';
3
4
  import { resolvePageMeta } from '@almadar/core';
4
5
 
6
+ function createEditorFocus() {
7
+ let current = null;
8
+ return {
9
+ focused: () => current,
10
+ focus: (editorId) => {
11
+ current = editorId;
12
+ },
13
+ blur: (editorId) => {
14
+ if (current === editorId) current = null;
15
+ }
16
+ };
17
+ }
18
+ var INERT_EDITOR_FOCUS = { focused: () => null, focus: () => void 0, blur: () => void 0 };
19
+ var EditorFocusContext = createContext(INERT_EDITOR_FOCUS);
20
+ var EditorFocusProvider = ({ children }) => {
21
+ const focus = useMemo(createEditorFocus, []);
22
+ return /* @__PURE__ */ jsx(EditorFocusContext.Provider, { value: focus, children });
23
+ };
24
+ EditorFocusProvider.displayName = "EditorFocusProvider";
25
+ function useEditorFocus() {
26
+ return useContext(EditorFocusContext);
27
+ }
5
28
  function mergeCaptureTables(tables) {
6
29
  const merged = {};
7
30
  for (const table of tables) {
@@ -32,38 +55,18 @@ function keyChord(event) {
32
55
  function useKeyboardRouter(options) {
33
56
  const {
34
57
  captureTable,
35
- editorFocusEvent = "EDITOR_FOCUS",
36
- editorBlurEvent = "EDITOR_BLUR",
37
58
  keyEvent = "KEY",
38
59
  enabled = true
39
60
  } = options;
40
61
  const eventBus = useEventBus();
41
62
  const captureTableRef = useRef(captureTable);
42
63
  captureTableRef.current = captureTable;
43
- const focusedEditorIdRef = useRef(null);
44
- useEffect(() => {
45
- const unsubFocus = eventBus.on(`UI:${editorFocusEvent}`, (event) => {
46
- const editorId = event.payload?.editorId;
47
- if (typeof editorId === "string") {
48
- focusedEditorIdRef.current = editorId;
49
- }
50
- });
51
- const unsubBlur = eventBus.on(`UI:${editorBlurEvent}`, (event) => {
52
- const editorId = event.payload?.editorId;
53
- if (typeof editorId === "string" && focusedEditorIdRef.current === editorId) {
54
- focusedEditorIdRef.current = null;
55
- }
56
- });
57
- return () => {
58
- unsubFocus();
59
- unsubBlur();
60
- };
61
- }, [eventBus, editorFocusEvent, editorBlurEvent]);
64
+ const editorFocus = useEditorFocus();
62
65
  useEffect(() => {
63
66
  if (!enabled) return;
64
67
  const handleKeyDown = (event) => {
65
68
  if (event.isComposing) return;
66
- const target = focusedEditorIdRef.current ?? "shell";
69
+ const target = editorFocus.focused() ?? "shell";
67
70
  const entry = captureTableRef.current[target];
68
71
  const captured = entry !== void 0 && (entry.keys.has(event.key) || entry.keys.has(keyChord(event)));
69
72
  if (captured) {
@@ -84,7 +87,7 @@ function useKeyboardRouter(options) {
84
87
  return () => {
85
88
  window.removeEventListener("keydown", handleKeyDown, { capture: true });
86
89
  };
87
- }, [eventBus, enabled, keyEvent]);
90
+ }, [eventBus, editorFocus, enabled, keyEvent]);
88
91
  }
89
92
  function useSwipeGesture(callbacks, options = {}) {
90
93
  const { threshold = 50, velocityThreshold = 0.3, preventDefault = false } = options;
@@ -372,66 +375,6 @@ function parseQueryBinding(binding) {
372
375
  field: parts.length > 1 ? parts.slice(1).join(".") : void 0
373
376
  };
374
377
  }
375
- function usePullToRefresh(onRefresh, options = {}) {
376
- const { threshold = 60, maxPull = 120 } = options;
377
- const [pullDistance, setPullDistance] = useState(0);
378
- const [isPulling, setIsPulling] = useState(false);
379
- const [isRefreshing, setIsRefreshing] = useState(false);
380
- const startY = useRef(0);
381
- const scrollTopRef = useRef(0);
382
- const onTouchStart = useCallback((e) => {
383
- const container = e.currentTarget;
384
- scrollTopRef.current = container.scrollTop;
385
- if (scrollTopRef.current <= 0) {
386
- startY.current = e.touches[0].clientY;
387
- setIsPulling(true);
388
- }
389
- }, []);
390
- const onTouchMove = useCallback((e) => {
391
- if (!isPulling || isRefreshing) return;
392
- const container = e.currentTarget;
393
- if (container.scrollTop > 0) {
394
- setPullDistance(0);
395
- return;
396
- }
397
- const dy = e.touches[0].clientY - startY.current;
398
- if (dy > 0) {
399
- const distance = Math.min(dy * 0.5, maxPull);
400
- setPullDistance(distance);
401
- }
402
- }, [isPulling, isRefreshing, maxPull]);
403
- const onTouchEnd = useCallback(() => {
404
- if (!isPulling) return;
405
- setIsPulling(false);
406
- if (pullDistance >= threshold && !isRefreshing) {
407
- setIsRefreshing(true);
408
- setPullDistance(threshold);
409
- onRefresh();
410
- } else {
411
- setPullDistance(0);
412
- }
413
- }, [isPulling, pullDistance, threshold, isRefreshing, onRefresh]);
414
- const endRefresh = useCallback(() => {
415
- setIsRefreshing(false);
416
- setPullDistance(0);
417
- }, []);
418
- const containerProps = {
419
- onTouchStart,
420
- onTouchMove,
421
- onTouchEnd,
422
- style: {
423
- transform: pullDistance > 0 ? `translateY(${pullDistance}px)` : void 0,
424
- transition: isPulling ? "none" : "transform 300ms ease-out"
425
- }
426
- };
427
- return {
428
- pullDistance,
429
- isPulling,
430
- isRefreshing,
431
- containerProps,
432
- endRefresh
433
- };
434
- }
435
378
 
436
379
  // src/lib/bus-claim.ts
437
380
  var claims = /* @__PURE__ */ new WeakMap();
@@ -447,6 +390,10 @@ function claimDelivery(source, trait, event) {
447
390
  seen.add(key);
448
391
  return true;
449
392
  }
393
+ var DISPATCH_CLAIM = "$dispatch";
394
+ function claimDispatch(source, event) {
395
+ return claimDelivery(source, DISPATCH_CLAIM, event);
396
+ }
450
397
  var OWNED = "data-orb-head";
451
398
  var shellTitle;
452
399
  function ownedTag(tag, attrs) {
@@ -501,6 +448,66 @@ function usePageHead(input) {
501
448
  };
502
449
  }, [active, title, description, isPublic, canonical, siteName, locale, hreflangKey]);
503
450
  }
451
+ function usePullToRefresh(onRefresh, options = {}) {
452
+ const { threshold = 60, maxPull = 120 } = options;
453
+ const [pullDistance, setPullDistance] = useState(0);
454
+ const [isPulling, setIsPulling] = useState(false);
455
+ const [isRefreshing, setIsRefreshing] = useState(false);
456
+ const startY = useRef(0);
457
+ const scrollTopRef = useRef(0);
458
+ const onTouchStart = useCallback((e) => {
459
+ const container = e.currentTarget;
460
+ scrollTopRef.current = container.scrollTop;
461
+ if (scrollTopRef.current <= 0) {
462
+ startY.current = e.touches[0].clientY;
463
+ setIsPulling(true);
464
+ }
465
+ }, []);
466
+ const onTouchMove = useCallback((e) => {
467
+ if (!isPulling || isRefreshing) return;
468
+ const container = e.currentTarget;
469
+ if (container.scrollTop > 0) {
470
+ setPullDistance(0);
471
+ return;
472
+ }
473
+ const dy = e.touches[0].clientY - startY.current;
474
+ if (dy > 0) {
475
+ const distance = Math.min(dy * 0.5, maxPull);
476
+ setPullDistance(distance);
477
+ }
478
+ }, [isPulling, isRefreshing, maxPull]);
479
+ const onTouchEnd = useCallback(() => {
480
+ if (!isPulling) return;
481
+ setIsPulling(false);
482
+ if (pullDistance >= threshold && !isRefreshing) {
483
+ setIsRefreshing(true);
484
+ setPullDistance(threshold);
485
+ onRefresh();
486
+ } else {
487
+ setPullDistance(0);
488
+ }
489
+ }, [isPulling, pullDistance, threshold, isRefreshing, onRefresh]);
490
+ const endRefresh = useCallback(() => {
491
+ setIsRefreshing(false);
492
+ setPullDistance(0);
493
+ }, []);
494
+ const containerProps = {
495
+ onTouchStart,
496
+ onTouchMove,
497
+ onTouchEnd,
498
+ style: {
499
+ transform: pullDistance > 0 ? `translateY(${pullDistance}px)` : void 0,
500
+ transition: isPulling ? "none" : "transform 300ms ease-out"
501
+ }
502
+ };
503
+ return {
504
+ pullDistance,
505
+ isPulling,
506
+ isRefreshing,
507
+ containerProps,
508
+ endRefresh
509
+ };
510
+ }
504
511
  function useDragReorder(initialItems, onReorder) {
505
512
  const [items, setItems] = useState(initialItems);
506
513
  const [dragIndex, setDragIndex] = useState(-1);
@@ -570,4 +577,4 @@ function useDragReorder(initialItems, onReorder) {
570
577
  };
571
578
  }
572
579
 
573
- export { claimDelivery, keyChord, mergeCaptureTables, parseQueryBinding, useAuthContext, useCanvasGestures, useDragReorder, useKeyboardRouter, useLongPress, usePageHead, usePullToRefresh, useQuerySingleton, useSwipeGesture };
580
+ export { EditorFocusProvider, claimDelivery, claimDispatch, keyChord, mergeCaptureTables, parseQueryBinding, useAuthContext, useCanvasGestures, useDragReorder, useEditorFocus, useKeyboardRouter, useLongPress, usePageHead, usePullToRefresh, useQuerySingleton, useSwipeGesture };
@@ -1,5 +1,5 @@
1
- import { traitLevelFromDescription } from './chunk-VFF5OO47.js';
2
- import { useContentSurface, useEventBus, Typography, Icon, cn, domPassthrough } from './chunk-MBQAMMSE.js';
1
+ import { traitLevelFromDescription } from './chunk-PCR37T3U.js';
2
+ import { useContentSurface, useEventBus, Typography, Icon, cn, domPassthrough } from './chunk-4YXBKHHM.js';
3
3
  import { useState } from 'react';
4
4
  import { jsx, jsxs } from 'react/jsx-runtime';
5
5
 
@@ -1,6 +1,6 @@
1
- import { AvlStateMachine } from './chunk-KVQS4GXU.js';
2
- import { EmptyState } from './chunk-FAJDTHWC.js';
3
- import { useTranslate, Box, domPassthrough } from './chunk-MBQAMMSE.js';
1
+ import { AvlStateMachine } from './chunk-SP5CDJ6K.js';
2
+ import { EmptyState } from './chunk-AGXD77SL.js';
3
+ import { useTranslate, Box, domPassthrough } from './chunk-4YXBKHHM.js';
4
4
  import { jsx } from 'react/jsx-runtime';
5
5
 
6
6
  var BehaviorView = ({ data, ...rest }) => {
@@ -1,8 +1,8 @@
1
- import { useContainerWidth, computeTraitLayout, roundedEdgePath } from './chunk-GAR5TQ5B.js';
2
- import { AvlExplain, AvlEffectChip } from './chunk-SJGJJKBY.js';
1
+ import { useContainerWidth, computeTraitLayout, roundedEdgePath } from './chunk-TXAUOLWZ.js';
2
+ import { AvlExplain, AvlEffectChip } from './chunk-AB3X7QTE.js';
3
3
  import { gearTeethPath } from './chunk-TZZBINQY.js';
4
- import { AVL_INK, AVL_FONT, AVL_STROKE, avlTint } from './chunk-DFNZUYX4.js';
5
- import { domPassthrough, useTranslate, useEventBus, useMediaQuery, Box, Typography } from './chunk-MBQAMMSE.js';
4
+ import { AVL_INK, AVL_FONT, AVL_STROKE, avlTint } from './chunk-UXLE3IPR.js';
5
+ import { domPassthrough, useTranslate, useEventBus, useMediaQuery, Box, Typography, Button } from './chunk-4YXBKHHM.js';
6
6
  import { useState, useRef, useMemo, useEffect } from 'react';
7
7
  import { formatSExpr } from '@almadar/core';
8
8
  import { createLogger } from '@almadar/logger';
@@ -65,19 +65,25 @@ var AvlStateMachine = ({
65
65
  const clickable = transitionClickEvent !== void 0 || onTransitionClick !== void 0;
66
66
  const reduceMotion = useMediaQuery("(prefers-reduced-motion: reduce)");
67
67
  const [layout, setLayout] = useState(null);
68
+ const [layoutFailed, setLayoutFailed] = useState(false);
69
+ const [layoutAttempt, setLayoutAttempt] = useState(0);
68
70
  const hostRef = useRef(null);
69
71
  const hostWidth = useContainerWidth(hostRef);
70
72
  const traitKey = useMemo(() => JSON.stringify(trait), [trait]);
71
73
  useEffect(() => {
72
74
  if (trait.states.length === 0) return;
73
75
  let live = true;
76
+ setLayoutFailed(false);
74
77
  computeTraitLayout(trait, metricsFor(nodeShape, direction)).then((l) => {
75
78
  if (live) setLayout(l);
76
- }).catch((error) => log.error("layout-failed", { trait: trait.name, error: error instanceof Error ? error : String(error) }));
79
+ }).catch((error) => {
80
+ log.error("layout-failed", { trait: trait.name, error: error instanceof Error ? error : String(error) });
81
+ if (live) setLayoutFailed(true);
82
+ });
77
83
  return () => {
78
84
  live = false;
79
85
  };
80
- }, [traitKey, nodeShape, direction]);
86
+ }, [traitKey, nodeShape, direction, layoutAttempt]);
81
87
  useEffect(() => {
82
88
  const host = hostRef.current;
83
89
  if (!followActive || layout === null || host === null || activeState === void 0) return;
@@ -270,6 +276,7 @@ var AvlStateMachine = ({
270
276
  transition: "border-color var(--duration-normal, 200ms), box-shadow var(--duration-normal, 200ms)"
271
277
  },
272
278
  children: [
279
+ pending ? /* @__PURE__ */ jsx(Box, { as: "span", className: "sr-only", children: t("avl.pendingSourceState") }) : null,
273
280
  visit !== void 0 && !active ? /* @__PURE__ */ jsx(
274
281
  Box,
275
282
  {
@@ -308,7 +315,10 @@ var AvlStateMachine = ({
308
315
  s.name
309
316
  );
310
317
  })
311
- ] }) }) : /* @__PURE__ */ jsx(Box, { className: "flex items-center justify-center py-10", children: /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", children: t("avl.computingLayout") }) }) })
318
+ ] }) }) : layoutFailed ? /* @__PURE__ */ jsxs(Box, { role: "alert", className: "flex flex-col items-center justify-center gap-2 py-10", children: [
319
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", children: t("avl.layoutFailed") }),
320
+ /* @__PURE__ */ jsx(Button, { variant: "ghost", size: "sm", label: t("common.retry"), onClick: () => setLayoutAttempt((n) => n + 1) })
321
+ ] }) : /* @__PURE__ */ jsx(Box, { className: "flex items-center justify-center py-10", children: /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", children: t("avl.computingLayout") }) }) })
312
322
  ] });
313
323
  };
314
324
  var Rail = ({ kind, event }) => /* @__PURE__ */ jsxs(
@@ -325,4 +335,4 @@ var Rail = ({ kind, event }) => /* @__PURE__ */ jsxs(
325
335
  );
326
336
  AvlStateMachine.displayName = "AvlStateMachine";
327
337
 
328
- export { AvlStateMachine };
338
+ export { AvlStateMachine, BODY_CHAR, MARGIN, MAX_SCALE, MIN_SCALE, MONO_CHAR, PILL_H, metricsFor, pillWidth };
@@ -1,5 +1,5 @@
1
- import { perfStore, pushPerfEntry } from './chunk-DYEKAA4L.js';
2
- import { isMotionEnabled } from './chunk-MBQAMMSE.js';
1
+ import { perfStore, pushPerfEntry } from './chunk-3VZ36ZKO.js';
2
+ import { isMotionEnabled } from './chunk-4YXBKHHM.js';
3
3
  import { useRef, useLayoutEffect, useSyncExternalStore } from 'react';
4
4
  import { ENTER_DELAY_STEPS, ENTER_ANIMATIONS, isFileValue } from '@almadar/core';
5
5
  export { getNestedValue } from '@almadar/core';