@almadar/shell-web 0.0.0-stage → 0.1.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 (274) hide show
  1. package/bundling.d.mts +18 -0
  2. package/bundling.mjs +28 -0
  3. package/dist/ArbitraryClassCompiler-Mzabq-UB.d.ts +100 -0
  4. package/dist/AvlGlyph-JKJOAH23.js +6 -0
  5. package/dist/AvlStateMachine-PI4YGREK.js +8 -0
  6. package/dist/AvlTransitionDetail-ZH7V24UG.js +12 -0
  7. package/dist/AvlTransitionExplainer-ZSRT7L6Y.js +13 -0
  8. package/dist/BehaviorValueFrame-6RUJXT4A.js +29 -0
  9. package/dist/BehaviorValueFrame-SSEMEBTG.css +1756 -0
  10. package/dist/BehaviorView-RFEE5J6E.js +10 -0
  11. package/dist/Canvas3DHost-_Y-5uLM_.d.ts +552 -0
  12. package/dist/EventBusProvider-CVwjkV_2.d.ts +284 -0
  13. package/dist/FileTree-BCFnBEuQ.d.ts +254 -0
  14. package/dist/FlowCanvas-3JRMNJLV.css +1756 -0
  15. package/dist/FlowCanvas-STDC4OWK.js +27 -0
  16. package/dist/GameAudioProvider-Cm9BnvmP.d.ts +93 -0
  17. package/dist/KaTeX_AMS-Regular-CYEKBG2K.woff +0 -0
  18. package/dist/KaTeX_AMS-Regular-JKX5W2C4.ttf +0 -0
  19. package/dist/KaTeX_AMS-Regular-U6PRYMIZ.woff2 +0 -0
  20. package/dist/KaTeX_Caligraphic-Bold-5QL5CMTE.woff2 +0 -0
  21. package/dist/KaTeX_Caligraphic-Bold-WZ3QSGD3.woff +0 -0
  22. package/dist/KaTeX_Caligraphic-Bold-ZTS3R3HK.ttf +0 -0
  23. package/dist/KaTeX_Caligraphic-Regular-3LKEU76G.woff +0 -0
  24. package/dist/KaTeX_Caligraphic-Regular-A7XRTZ5Q.ttf +0 -0
  25. package/dist/KaTeX_Caligraphic-Regular-KX5MEWCF.woff2 +0 -0
  26. package/dist/KaTeX_Fraktur-Bold-2QVFK6NQ.woff2 +0 -0
  27. package/dist/KaTeX_Fraktur-Bold-T4SWXBMT.woff +0 -0
  28. package/dist/KaTeX_Fraktur-Bold-WGHVTYOR.ttf +0 -0
  29. package/dist/KaTeX_Fraktur-Regular-2PEIFJSJ.woff2 +0 -0
  30. package/dist/KaTeX_Fraktur-Regular-5U4OPH2X.ttf +0 -0
  31. package/dist/KaTeX_Fraktur-Regular-PQMHCIK6.woff +0 -0
  32. package/dist/KaTeX_Main-Bold-2GA4IZIN.woff +0 -0
  33. package/dist/KaTeX_Main-Bold-W5FBVCZM.ttf +0 -0
  34. package/dist/KaTeX_Main-Bold-YP5VVQRP.woff2 +0 -0
  35. package/dist/KaTeX_Main-BoldItalic-4P4C7HJH.woff +0 -0
  36. package/dist/KaTeX_Main-BoldItalic-N4V3DX7S.woff2 +0 -0
  37. package/dist/KaTeX_Main-BoldItalic-ODMLBJJQ.ttf +0 -0
  38. package/dist/KaTeX_Main-Italic-I43T2HSR.ttf +0 -0
  39. package/dist/KaTeX_Main-Italic-RELBIK7M.woff2 +0 -0
  40. package/dist/KaTeX_Main-Italic-SASNQFN2.woff +0 -0
  41. package/dist/KaTeX_Main-Regular-ARRPAO67.woff2 +0 -0
  42. package/dist/KaTeX_Main-Regular-P5I74A2A.woff +0 -0
  43. package/dist/KaTeX_Main-Regular-W74P5G27.ttf +0 -0
  44. package/dist/KaTeX_Math-BoldItalic-6EBV3DK5.woff +0 -0
  45. package/dist/KaTeX_Math-BoldItalic-K4WTGH3J.woff2 +0 -0
  46. package/dist/KaTeX_Math-BoldItalic-VB447A4D.ttf +0 -0
  47. package/dist/KaTeX_Math-Italic-6KGCHLFN.woff2 +0 -0
  48. package/dist/KaTeX_Math-Italic-KKK3USB2.woff +0 -0
  49. package/dist/KaTeX_Math-Italic-SON4MRCA.ttf +0 -0
  50. package/dist/KaTeX_SansSerif-Bold-RRNVJFFW.woff2 +0 -0
  51. package/dist/KaTeX_SansSerif-Bold-STQ6RXC7.ttf +0 -0
  52. package/dist/KaTeX_SansSerif-Bold-X5M5EMOD.woff +0 -0
  53. package/dist/KaTeX_SansSerif-Italic-HMPFTM52.woff2 +0 -0
  54. package/dist/KaTeX_SansSerif-Italic-PSN4QKYX.woff +0 -0
  55. package/dist/KaTeX_SansSerif-Italic-WTBAZBGY.ttf +0 -0
  56. package/dist/KaTeX_SansSerif-Regular-2TL3USAE.ttf +0 -0
  57. package/dist/KaTeX_SansSerif-Regular-OQCII6EP.woff +0 -0
  58. package/dist/KaTeX_SansSerif-Regular-XIQ62X4E.woff2 +0 -0
  59. package/dist/KaTeX_Script-Regular-72OLXYNA.ttf +0 -0
  60. package/dist/KaTeX_Script-Regular-A5IFOEBS.woff +0 -0
  61. package/dist/KaTeX_Script-Regular-APUWIHLP.woff2 +0 -0
  62. package/dist/KaTeX_Size1-Regular-4HRHTS65.woff +0 -0
  63. package/dist/KaTeX_Size1-Regular-5LRUTBFT.woff2 +0 -0
  64. package/dist/KaTeX_Size1-Regular-7K6AASVL.ttf +0 -0
  65. package/dist/KaTeX_Size2-Regular-222HN3GT.ttf +0 -0
  66. package/dist/KaTeX_Size2-Regular-K5ZHAIS6.woff +0 -0
  67. package/dist/KaTeX_Size2-Regular-LELKET5D.woff2 +0 -0
  68. package/dist/KaTeX_Size3-Regular-TLFPAHDE.woff +0 -0
  69. package/dist/KaTeX_Size3-Regular-UFCO6WCA.ttf +0 -0
  70. package/dist/KaTeX_Size3-Regular-WQRQ47UD.woff2 +0 -0
  71. package/dist/KaTeX_Size4-Regular-7PGNVPQK.ttf +0 -0
  72. package/dist/KaTeX_Size4-Regular-CDMV7U5C.woff2 +0 -0
  73. package/dist/KaTeX_Size4-Regular-PKMWZHNC.woff +0 -0
  74. package/dist/KaTeX_Typewriter-Regular-3F5K6SQ6.ttf +0 -0
  75. package/dist/KaTeX_Typewriter-Regular-MJMFSK64.woff +0 -0
  76. package/dist/KaTeX_Typewriter-Regular-VBYJ4NRC.woff2 +0 -0
  77. package/dist/KernelEngineContext-BOCQoFwk.d.ts +43 -0
  78. package/dist/LayersPanel-BBQ54IVG.js +7 -0
  79. package/dist/ModuleCard-3TT2X7IW.js +7 -0
  80. package/dist/OrbInspector-K6T6O7GI.js +27 -0
  81. package/dist/OrbInspector-MHLJ6OEE.css +1756 -0
  82. package/dist/Select-mDZIwNqN.d.ts +199 -0
  83. package/dist/ServerBridge-Cm1On51b.d.ts +233 -0
  84. package/dist/ThemeContext-DJmO59xd.d.ts +147 -0
  85. package/dist/TraitValueFrame-2PJGLLVI.js +28 -0
  86. package/dist/TraitValueFrame-4G3KOUBR.css +1756 -0
  87. package/dist/UISlotContext-Dl_ewwCI.d.ts +79 -0
  88. package/dist/UISlotRenderer-JKFSX24W.js +27 -0
  89. package/dist/UISlotRenderer-KVFO6J7R.css +1756 -0
  90. package/dist/UserContext-DqWeZkUZ.d.ts +100 -0
  91. package/dist/auth/browser/index.d.ts +2 -0
  92. package/dist/auth/browser/index.js +1 -0
  93. package/dist/auth/react/index.d.ts +49 -0
  94. package/dist/auth/react/index.js +119 -0
  95. package/dist/avl/index.css +1756 -0
  96. package/dist/avl/index.d.ts +2238 -0
  97. package/dist/avl/index.js +2693 -0
  98. package/dist/avl-3d-context-BIRKWpaL.d.ts +204 -0
  99. package/dist/avl-schema-parser-CtJxJ9KU.d.ts +132 -0
  100. package/dist/avl-zoom-state-CKMVuBFg.d.ts +17 -0
  101. package/dist/chunk-2PY54Z44.js +227 -0
  102. package/dist/chunk-2QOH2HWM.js +95 -0
  103. package/dist/chunk-3BBUBJFF.js +339 -0
  104. package/dist/chunk-42FY4RYA.js +191 -0
  105. package/dist/chunk-5QTYQTPS.js +15 -0
  106. package/dist/chunk-6P3MWXYE.js +440 -0
  107. package/dist/chunk-73SRAB4P.js +1053 -0
  108. package/dist/chunk-A2LR6VQQ.js +349 -0
  109. package/dist/chunk-AILY3XPS.js +562 -0
  110. package/dist/chunk-B4BU77LT.js +432 -0
  111. package/dist/chunk-DFNZUYX4.js +378 -0
  112. package/dist/chunk-DJ433ET5.js +1327 -0
  113. package/dist/chunk-DLZF4PVE.js +24 -0
  114. package/dist/chunk-DYEKAA4L.js +787 -0
  115. package/dist/chunk-DZ42OJQC.js +176 -0
  116. package/dist/chunk-EOWMARUB.js +16 -0
  117. package/dist/chunk-EQAMU2ZC.js +14 -0
  118. package/dist/chunk-FAJDTHWC.js +98 -0
  119. package/dist/chunk-FIW6WN23.js +508 -0
  120. package/dist/chunk-FP3WIKTC.js +303 -0
  121. package/dist/chunk-G7DCAZ22.js +19 -0
  122. package/dist/chunk-GAR5TQ5B.js +199 -0
  123. package/dist/chunk-GKIFONTE.js +131 -0
  124. package/dist/chunk-GYTPOFVC.js +47155 -0
  125. package/dist/chunk-KVQS4GXU.js +328 -0
  126. package/dist/chunk-L2DEKY4J.js +97 -0
  127. package/dist/chunk-L677XGY3.js +701 -0
  128. package/dist/chunk-MBQAMMSE.js +11877 -0
  129. package/dist/chunk-P4LNHAFI.js +1051 -0
  130. package/dist/chunk-P4ZFUQFF.js +93 -0
  131. package/dist/chunk-PC7K4SK7.js +1384 -0
  132. package/dist/chunk-R5O5AUPI.js +573 -0
  133. package/dist/chunk-SGM3FASH.js +672 -0
  134. package/dist/chunk-SJGJJKBY.js +502 -0
  135. package/dist/chunk-TESBIVUA.js +11 -0
  136. package/dist/chunk-TZZBINQY.js +82 -0
  137. package/dist/chunk-U6QRZASX.js +280 -0
  138. package/dist/chunk-VFF5OO47.js +319 -0
  139. package/dist/chunk-YDNJLLG6.js +516 -0
  140. package/dist/chunk-YHMRX6YA.js +455 -0
  141. package/dist/chunk-ZO6MXAS3.js +69 -0
  142. package/dist/components/index.css +1756 -0
  143. package/dist/components/index.d.ts +11093 -0
  144. package/dist/components/index.js +1110 -0
  145. package/dist/context/index.d.ts +9 -0
  146. package/dist/context/index.js +7 -0
  147. package/dist/core.d.ts +2523 -0
  148. package/dist/core.js +2 -0
  149. package/dist/design-classes/index.cjs +429 -0
  150. package/dist/design-classes/index.d.cts +165 -0
  151. package/dist/design-classes/index.d.ts +165 -0
  152. package/dist/design-classes/index.js +397 -0
  153. package/dist/emojiItems-QGSNAABW.js +20 -0
  154. package/dist/fx-CmQjnHmT.d.ts +371 -0
  155. package/dist/hooks/index.d.ts +936 -0
  156. package/dist/hooks/index.js +7 -0
  157. package/dist/index.d.ts +486 -0
  158. package/dist/index.js +38 -0
  159. package/dist/katexPlugin-FA7NX4PE.css +1161 -0
  160. package/dist/katexPlugin-NCDKOOQY.js +2 -0
  161. package/dist/kernel-client-ZH4PSMCN.js +367 -0
  162. package/dist/kernel-wire-B4S8pnP3.d.ts +65 -0
  163. package/dist/lib/index.d.ts +602 -0
  164. package/dist/lib/index.js +1288 -0
  165. package/dist/paintDispatch-ChW5mVuK.d.ts +698 -0
  166. package/dist/parseLessonSegments-GpCeMrb2.d.ts +334 -0
  167. package/dist/perf-CKiBKbkw.d.ts +22 -0
  168. package/dist/perf-Dr28-AgT.d.ts +57 -0
  169. package/dist/prism-AIWGN2X5.js +134 -0
  170. package/dist/providers/index.css +1756 -0
  171. package/dist/providers/index.d.ts +340 -0
  172. package/dist/providers/index.js +30 -0
  173. package/dist/renderer/index.d.ts +467 -0
  174. package/dist/renderer/index.js +3 -0
  175. package/dist/runtime/index.css +1756 -0
  176. package/dist/runtime/index.d.ts +440 -0
  177. package/dist/runtime/index.js +31 -0
  178. package/dist/slot-host-CPzrxLo9.d.ts +48 -0
  179. package/dist/ssr/index.cjs +7631 -0
  180. package/dist/ssr/index.d.cts +487 -0
  181. package/dist/ssr/index.d.ts +487 -0
  182. package/dist/ssr/index.js +7599 -0
  183. package/dist/storage/browser/index.d.ts +1 -0
  184. package/dist/storage/browser/index.js +1 -0
  185. package/dist/test-support.d.ts +35 -0
  186. package/dist/test-support.js +114 -0
  187. package/dist/themeTokens-CRd8AEDF.d.ts +125 -0
  188. package/dist/three/index.css +503 -0
  189. package/dist/three/index.d.ts +1185 -0
  190. package/dist/three/index.js +3896 -0
  191. package/dist/useKeyboardRouter-Dsq553Ur.d.ts +42 -0
  192. package/dist/useUISlots-CiobNFGb.d.ts +211 -0
  193. package/dist/verification-C5pTeMJv.d.ts +66 -0
  194. package/dist/verificationRegistry-CabxhfTv.d.ts +122 -0
  195. package/dist/wrapCallbackForEvent-B9QLbhxX.d.ts +19 -0
  196. package/index.css +199 -0
  197. package/package.json +269 -3
  198. package/src/core/locales/ar.json +1263 -0
  199. package/src/core/locales/en.json +1263 -0
  200. package/src/core/locales/index.ts +54 -0
  201. package/src/core/locales/sl.json +1263 -0
  202. package/src/core/tokens/native-tokens.json +369 -0
  203. package/tailwind-compile.cjs +29 -0
  204. package/tailwind-preset.cjs +991 -0
  205. package/themes/_base.css +451 -0
  206. package/themes/_contract.md +307 -0
  207. package/themes/_fonts-kenney.css +11 -0
  208. package/themes/_fonts.css +12 -0
  209. package/themes/_foundation.css +105 -0
  210. package/themes/_head.css +22 -0
  211. package/themes/_presets.css +67 -0
  212. package/themes/almadar-heritage.css +455 -0
  213. package/themes/almadar-website.css +269 -0
  214. package/themes/almadar.css +269 -0
  215. package/themes/aqua.css +455 -0
  216. package/themes/arabesque.css +459 -0
  217. package/themes/art-deco.css +457 -0
  218. package/themes/art-nouveau.css +459 -0
  219. package/themes/atelier.css +463 -0
  220. package/themes/bauhaus.css +461 -0
  221. package/themes/bloomberg-dense.css +463 -0
  222. package/themes/blueprint.css +457 -0
  223. package/themes/clay.css +449 -0
  224. package/themes/comic.css +453 -0
  225. package/themes/constructivist.css +457 -0
  226. package/themes/corporate.css +449 -0
  227. package/themes/cyberpunk.css +453 -0
  228. package/themes/frutiger-aero.css +458 -0
  229. package/themes/game-adventure.css +201 -0
  230. package/themes/game-rpg.css +203 -0
  231. package/themes/game-sci-fi.css +201 -0
  232. package/themes/game-ui-pack.css +200 -0
  233. package/themes/gazette.css +449 -0
  234. package/themes/glass.css +457 -0
  235. package/themes/gothic.css +453 -0
  236. package/themes/index.css +21 -0
  237. package/themes/ink-wash.css +459 -0
  238. package/themes/kawaii.css +459 -0
  239. package/themes/kflow.css +310 -0
  240. package/themes/kiosk.css +449 -0
  241. package/themes/linear-clean.css +463 -0
  242. package/themes/luxury.css +451 -0
  243. package/themes/mac-classic.css +455 -0
  244. package/themes/material.css +463 -0
  245. package/themes/memphis.css +453 -0
  246. package/themes/mid-century.css +455 -0
  247. package/themes/minimalist.css +449 -0
  248. package/themes/mudcloth.css +459 -0
  249. package/themes/nata.css +310 -0
  250. package/themes/neon.css +453 -0
  251. package/themes/neumorphic.css +451 -0
  252. package/themes/newsprint.css +455 -0
  253. package/themes/notion-editorial.css +463 -0
  254. package/themes/orb.css +465 -0
  255. package/themes/pixel.css +449 -0
  256. package/themes/prism.css +309 -0
  257. package/themes/rawi.css +310 -0
  258. package/themes/retro.css +452 -0
  259. package/themes/risograph.css +463 -0
  260. package/themes/scandi.css +469 -0
  261. package/themes/sketch.css +455 -0
  262. package/themes/solarpunk.css +469 -0
  263. package/themes/steampunk.css +451 -0
  264. package/themes/swiss.css +455 -0
  265. package/themes/terminal.css +466 -0
  266. package/themes/trait-wars.css +487 -0
  267. package/themes/ukiyo-e.css +459 -0
  268. package/themes/vaporwave.css +455 -0
  269. package/themes/victorian.css +453 -0
  270. package/themes/wabi-sabi.css +459 -0
  271. package/themes/win95.css +455 -0
  272. package/themes/wireframe.css +439 -0
  273. package/themes/zine.css +455 -0
  274. package/README.md +0 -3
@@ -0,0 +1,672 @@
1
+ import { JsonTreeEditor } from './chunk-U6QRZASX.js';
2
+ import { transitionPlayback, Accordion } from './chunk-42FY4RYA.js';
3
+ import { EmptyState } from './chunk-FAJDTHWC.js';
4
+ import { useContainerWidth, roundedEdgePath } from './chunk-GAR5TQ5B.js';
5
+ import { AvlExplain, AvlEffectChip } from './chunk-SJGJJKBY.js';
6
+ import { AvlEffect } from './chunk-DZ42OJQC.js';
7
+ import { parseTraitLevel } from './chunk-VFF5OO47.js';
8
+ import { AVL_INK, AVL_FONT, effectZoneOf, avlTint, OPERATOR_CATEGORY_COLORS, avlBlend } from './chunk-DFNZUYX4.js';
9
+ import { useTranslate, useMediaQuery, Box, Typography, Card, VStack, HStack, Badge, Button } from './chunk-MBQAMMSE.js';
10
+ import { useRef, useMemo, useState } from 'react';
11
+ import { formatSExpr, isBinding } from '@almadar/core';
12
+ import { operatorVisualForm, getStdOperatorMeta } from '@almadar/std/registry';
13
+ import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
14
+
15
+ var MONO = 7.4;
16
+ var ROW = 40;
17
+ var GAP_X = 112;
18
+ var GAP_Y = 16;
19
+ var PAD = 12;
20
+ var keyOf = (path) => path.join(".");
21
+ function leafLabel(expr) {
22
+ if (typeof expr === "string") return isBinding(expr) ? expr : JSON.stringify(expr);
23
+ if (expr === null) return "null";
24
+ if (typeof expr === "number" || typeof expr === "boolean") return String(expr);
25
+ return Array.isArray(expr) ? "[\u2026]" : "{\u2026}";
26
+ }
27
+ function build(expr, path) {
28
+ const base = { key: keyOf(path), path, expr, x: 0, y: 0, w: 0, h: 0, bandTop: 0, bandBottom: 0, wireLabels: [] };
29
+ if (Array.isArray(expr) && expr.length > 0 && typeof expr[0] === "string") {
30
+ const op = expr[0];
31
+ const args = expr.slice(1);
32
+ const form = operatorVisualForm(op) ?? "unknown";
33
+ if (form === "scope" && Array.isArray(args[0])) {
34
+ const pairs = args[0];
35
+ const bindings = pairs.map((pair, i) => {
36
+ const value = Array.isArray(pair) ? pair[1] : pair;
37
+ return build(value, [...path, 1, i, 1]);
38
+ });
39
+ const names = pairs.map((pair) => Array.isArray(pair) && typeof pair[0] === "string" ? pair[0] : "");
40
+ const body = args.slice(1).map((a, i) => build(a, [...path, i + 2]));
41
+ return { ...base, kind: "call", label: op, form, children: [...bindings, ...body], wireLabels: [...names, ...body.map(() => "")] };
42
+ }
43
+ if (form === "template") {
44
+ const params = args[0];
45
+ const body = args.slice(1).map((a, i) => build(a, [...path, i + 2]));
46
+ const paramText = Array.isArray(params) ? params.join(" ") : typeof params === "string" ? params : "";
47
+ return { ...base, kind: "call", label: `fn [${paramText}]`, form, children: body, wireLabels: body.map(() => "") };
48
+ }
49
+ const children = args.map((a, i) => build(a, [...path, i + 1]));
50
+ return { ...base, kind: "call", label: op, form, children, wireLabels: children.map(() => "") };
51
+ }
52
+ if (Array.isArray(expr)) {
53
+ const children = expr.map((a, i) => build(a, [...path, i]));
54
+ return { ...base, kind: "array", label: "[ ]", form: null, children, wireLabels: children.map((_, i) => String(i)) };
55
+ }
56
+ if (expr !== null && typeof expr === "object") {
57
+ const entries = Object.entries(expr);
58
+ const children = entries.map(([k, v]) => build(v, [...path, k]));
59
+ return { ...base, kind: "object", label: "{ }", form: null, children, wireLabels: entries.map(([k]) => k) };
60
+ }
61
+ return { ...base, kind: isBinding(expr) ? "binding" : "literal", label: leafLabel(expr), form: null, children: [] };
62
+ }
63
+ function size(n) {
64
+ n.children.forEach(size);
65
+ const ports = Math.max(1, n.children.length);
66
+ if (n.kind === "binding" || n.kind === "literal") {
67
+ n.w = Math.max(40, Math.round(n.label.length * MONO + 26));
68
+ n.h = 28;
69
+ return;
70
+ }
71
+ const labelW = Math.round(n.label.length * MONO + 28);
72
+ switch (n.form) {
73
+ case "series":
74
+ case "parallel":
75
+ n.w = Math.max(labelW, 120);
76
+ n.h = Math.max(ROW + 16, ports * 40 + 26);
77
+ return;
78
+ case "conveyor":
79
+ n.w = Math.max(labelW, 200);
80
+ n.h = Math.max(64, ports * 30 + 14);
81
+ return;
82
+ case "ladder":
83
+ n.w = Math.max(labelW, 80);
84
+ n.h = Math.max(ROW, ports * 30 + 14);
85
+ return;
86
+ case "actuator":
87
+ n.w = Math.max(labelW + 22, 96);
88
+ n.h = Math.max(ROW, ports * 26 + 12);
89
+ return;
90
+ default:
91
+ n.w = Math.max(labelW, 56);
92
+ n.h = Math.max(ROW, ports * 26 + 12);
93
+ }
94
+ }
95
+ function place(n, right, top) {
96
+ n.x = right - n.w;
97
+ if (n.children.length === 0) {
98
+ n.bandTop = top;
99
+ n.bandBottom = top + n.h;
100
+ n.y = top;
101
+ return n.h;
102
+ }
103
+ let cursor = top;
104
+ const childRight = n.x - GAP_X;
105
+ for (const child of n.children) {
106
+ const band2 = place(child, childRight, cursor);
107
+ cursor += band2 + GAP_Y;
108
+ }
109
+ const childrenBottom = cursor - GAP_Y;
110
+ const span = childrenBottom - top;
111
+ const band = Math.max(span, n.h);
112
+ n.bandTop = top;
113
+ n.bandBottom = top + band;
114
+ n.y = top + (band - n.h) / 2;
115
+ return band;
116
+ }
117
+ function subtreeWidth(n) {
118
+ return n.w + (n.children.length ? GAP_X + Math.max(...n.children.map(subtreeWidth)) : 0);
119
+ }
120
+ function shift(n, dx, dy) {
121
+ n.x += dx;
122
+ n.y += dy;
123
+ n.bandTop += dy;
124
+ n.bandBottom += dy;
125
+ n.children.forEach((c) => shift(c, dx, dy));
126
+ }
127
+ function buildCircuit(expr) {
128
+ const root = build(expr, []);
129
+ size(root);
130
+ const width = subtreeWidth(root);
131
+ const height = place(root, width, 0);
132
+ shift(root, PAD, PAD);
133
+ return { root, w: width + 2 * PAD, h: height + 2 * PAD };
134
+ }
135
+ function portY(n, i) {
136
+ const count = Math.max(1, n.children.length);
137
+ return n.y + n.h * (i + 1) / (count + 1);
138
+ }
139
+ function circuitState(trace, cursor) {
140
+ const out = /* @__PURE__ */ new Map();
141
+ const get = (k) => {
142
+ let s = out.get(k);
143
+ if (!s) {
144
+ s = { status: "idle", results: [] };
145
+ out.set(k, s);
146
+ }
147
+ return s;
148
+ };
149
+ for (let i = 0; i <= cursor && i < trace.length; i++) {
150
+ const step = trace[i];
151
+ const s = get(keyOf(step.path));
152
+ if (step.kind === "enter") s.status = "active";
153
+ else if (step.kind === "skip") s.status = "skipped";
154
+ else if (step.kind === "exit") {
155
+ if (step.error !== void 0) {
156
+ s.status = "error";
157
+ s.error = step.error;
158
+ } else {
159
+ s.status = "done";
160
+ s.value = step.value;
161
+ s.results.push(step.value ?? null);
162
+ }
163
+ }
164
+ }
165
+ return out;
166
+ }
167
+ function activeStack(trace, cursor) {
168
+ const stack = [];
169
+ for (let i = 0; i <= cursor && i < trace.length; i++) {
170
+ const step = trace[i];
171
+ const k = keyOf(step.path);
172
+ if (step.kind === "enter") stack.push(k);
173
+ else if (step.kind === "exit") {
174
+ const at = stack.lastIndexOf(k);
175
+ if (at >= 0) stack.splice(at, 1);
176
+ }
177
+ }
178
+ return stack;
179
+ }
180
+ var MIN_SCALE = 0.85;
181
+ var MAX_SCALE = 1.2;
182
+ var IDLE = { status: "idle", results: [] };
183
+ function truthy(v) {
184
+ return v !== void 0 && v !== null && v !== false && v !== 0 && v !== "";
185
+ }
186
+ function fmt(v) {
187
+ if (v === void 0) return "";
188
+ if (v === null || typeof v !== "object") return typeof v === "string" ? JSON.stringify(v) : String(v);
189
+ if (Array.isArray(v)) {
190
+ return v.length <= 4 && v.every((x) => x === null || typeof x !== "object") ? `[${v.map(fmt).join(" ")}]` : `[${v.length}]`;
191
+ }
192
+ const keys = Object.keys(v);
193
+ return keys.length <= 3 ? `{${keys.join(", ")}}` : `{${keys.length}}`;
194
+ }
195
+ function opColor(op) {
196
+ const meta = getStdOperatorMeta(op);
197
+ return meta ? OPERATOR_CATEGORY_COLORS[meta.category] : AVL_INK.quiet;
198
+ }
199
+ var AvlCircuit = ({ expr, trace, cursor, title, showCode = true, className }) => {
200
+ const { t } = useTranslate();
201
+ const reduceMotion = useMediaQuery("(prefers-reduced-motion: reduce)");
202
+ const hostRef = useRef(null);
203
+ const hostWidth = useContainerWidth(hostRef);
204
+ const circuit = useMemo(() => buildCircuit(expr), [expr]);
205
+ const at = trace ? Math.min(cursor ?? trace.length - 1, trace.length - 1) : -1;
206
+ const states = useMemo(() => trace ? circuitState(trace, at) : /* @__PURE__ */ new Map(), [trace, at]);
207
+ const stack = useMemo(() => trace ? activeStack(trace, at) : [], [trace, at]);
208
+ const nodes = useMemo(() => {
209
+ const out = /* @__PURE__ */ new Map();
210
+ const walk2 = (n) => {
211
+ out.set(n.key, n);
212
+ n.children.forEach(walk2);
213
+ };
214
+ walk2(circuit.root);
215
+ return out;
216
+ }, [circuit]);
217
+ const parents = useMemo(() => {
218
+ const out = /* @__PURE__ */ new Map();
219
+ const walk2 = (n) => {
220
+ n.children.forEach((c) => {
221
+ out.set(c.key, n);
222
+ walk2(c);
223
+ });
224
+ };
225
+ walk2(circuit.root);
226
+ return out;
227
+ }, [circuit]);
228
+ const stateOf = (n) => {
229
+ const s = states.get(n.key) ?? IDLE;
230
+ if (s.status !== "skipped") return s;
231
+ const form = parents.get(n.key)?.form;
232
+ return form === "series" || form === "parallel" || form === "branch" ? s : IDLE;
233
+ };
234
+ const scale = Math.min(MAX_SCALE, Math.max(MIN_SCALE, hostWidth ? hostWidth / (circuit.w + 120) : 1));
235
+ const W = circuit.w + 120;
236
+ const narration = (() => {
237
+ if (!trace || at < 0) return null;
238
+ const step = trace[at];
239
+ const node = nodes.get(step.path.join("."));
240
+ const code = node ? formatSExpr(node.expr) : "";
241
+ if (step.kind === "enter") return t("avl.circuit.evaluating", { code });
242
+ if (step.kind === "skip") return t("avl.circuit.skipped", { code });
243
+ if (step.kind === "iter") return t("avl.circuit.nextItem", { code });
244
+ if (step.error !== void 0) return t("avl.circuit.failed", { code, error: step.error });
245
+ return t("avl.circuit.returned", { code, value: fmt(step.value) });
246
+ })();
247
+ const wire = (parent, child, i) => {
248
+ const s = stateOf(child);
249
+ const x1 = child.x + child.w;
250
+ const y1 = child.y + child.h / 2;
251
+ const x2 = parent.x;
252
+ const y2 = portY(parent, i);
253
+ const xm = x2 - 24;
254
+ const d = roundedEdgePath([{ x: x1, y: y1 }, { x: xm, y: y1 }, { x: xm, y: y2 }, { x: x2, y: y2 }], 8);
255
+ const live = s.status === "done";
256
+ const running = s.status === "active";
257
+ const label = parent.wireLabels[i];
258
+ return /* @__PURE__ */ jsxs("g", { children: [
259
+ /* @__PURE__ */ jsx(
260
+ "path",
261
+ {
262
+ d,
263
+ fill: "none",
264
+ stroke: s.status === "error" ? AVL_INK.fail : live || running ? AVL_INK.focus : AVL_INK.quiet,
265
+ strokeOpacity: s.status === "skipped" ? 0.25 : live || running ? 1 : 0.5,
266
+ strokeWidth: live ? 2 : 1.5,
267
+ strokeDasharray: s.status === "skipped" ? "3 4" : running ? "8 6" : void 0,
268
+ children: running && !reduceMotion ? /* @__PURE__ */ jsx("animate", { attributeName: "stroke-dashoffset", from: "0", to: "-14", dur: "0.8s", repeatCount: "indefinite" }) : null
269
+ }
270
+ ),
271
+ label ? /* @__PURE__ */ jsx("text", { x: xm + 4, y: y2 - 6, fontFamily: AVL_FONT.mono, fontSize: 12, fill: AVL_INK.quiet, children: label }) : null,
272
+ live && s.value !== void 0 ? valueChip((x1 + xm) / 2, y1, s.value, true) : null
273
+ ] }, `w-${child.key}`);
274
+ };
275
+ const valueChip = (x, y, v, centered = false) => {
276
+ const text = fmt(v);
277
+ const w = Math.max(28, text.length * 7.4 + 14);
278
+ if (centered) x -= w / 2;
279
+ const isBool = typeof v === "boolean";
280
+ const tone = isBool ? v ? AVL_INK.pass : AVL_INK.fail : AVL_INK.focus;
281
+ return /* @__PURE__ */ jsxs("g", { children: [
282
+ /* @__PURE__ */ jsx("title", { children: JSON.stringify(v) }),
283
+ /* @__PURE__ */ jsx("rect", { x, y: y - 22, width: w, height: 18, rx: 9, fill: avlTint(tone, 16), stroke: tone, strokeWidth: 1 }),
284
+ /* @__PURE__ */ jsx(
285
+ "text",
286
+ {
287
+ "data-testid": "avl-circuit-value",
288
+ x: x + w / 2,
289
+ y: y - 13,
290
+ textAnchor: "middle",
291
+ dominantBaseline: "central",
292
+ fontFamily: AVL_FONT.mono,
293
+ fontSize: 12,
294
+ fontWeight: 600,
295
+ fill: AVL_INK.text,
296
+ children: text
297
+ }
298
+ )
299
+ ] });
300
+ };
301
+ const switchGlyph = (n, i, cx, cy, vertical) => {
302
+ const child = n.children[i];
303
+ const s = stateOf(child);
304
+ const decided = s.status === "done";
305
+ const closed = decided && truthy(s.value);
306
+ const color = s.status === "skipped" ? AVL_INK.quiet : decided ? closed ? AVL_INK.focus : AVL_INK.fail : AVL_INK.quiet;
307
+ const a = vertical ? { x: cx, y: cy - 13 } : { x: cx - 14, y: cy };
308
+ const b = vertical ? { x: cx, y: cy + 13 } : { x: cx + 14, y: cy };
309
+ const lever = closed || !decided ? b : vertical ? { x: cx + 16, y: cy + 6 } : { x: cx + 8, y: cy - 14 };
310
+ return /* @__PURE__ */ jsxs(
311
+ "g",
312
+ {
313
+ opacity: s.status === "skipped" ? 0.35 : 1,
314
+ ...decided && !closed ? { "data-testid": "avl-circuit-open-switch", "data-key": child.key } : {},
315
+ children: [
316
+ /* @__PURE__ */ jsx("line", { x1: n.x, y1: portY(n, i), x2: vertical ? cx - 4 : cx, y2: cy, stroke: AVL_INK.quiet, strokeWidth: 1, strokeDasharray: "2 3" }),
317
+ /* @__PURE__ */ jsx("circle", { cx: a.x, cy: a.y, r: 2.5, fill: AVL_INK.text }),
318
+ /* @__PURE__ */ jsx("circle", { cx: b.x, cy: b.y, r: 2.5, fill: decided && !closed ? AVL_INK.quiet : AVL_INK.text }),
319
+ /* @__PURE__ */ jsx("line", { x1: a.x, y1: a.y, x2: lever.x, y2: lever.y, stroke: color, strokeWidth: 2.5, strokeLinecap: "round" })
320
+ ]
321
+ },
322
+ `sw-${child.key}`
323
+ );
324
+ };
325
+ const body = (n) => {
326
+ const s = stateOf(n);
327
+ const cx = n.x + n.w / 2;
328
+ const cy = n.y + n.h / 2;
329
+ const tint = n.kind === "call" && n.form !== "template" ? opColor(n.label) : AVL_INK.quiet;
330
+ const frame = (dashed = false) => /* @__PURE__ */ jsx(
331
+ "rect",
332
+ {
333
+ x: n.x,
334
+ y: n.y,
335
+ width: n.w,
336
+ height: n.h,
337
+ rx: n.kind === "binding" || n.kind === "literal" ? n.h / 2 : 10,
338
+ fill: n.kind === "call" ? avlBlend(tint, 12, AVL_INK.surface) : n.kind === "literal" ? AVL_INK.wash : AVL_INK.surface,
339
+ stroke: s.status === "error" ? AVL_INK.fail : s.status === "active" ? AVL_INK.focus : n.kind === "call" ? avlBlend(tint, 55, AVL_INK.line) : AVL_INK.line,
340
+ strokeWidth: s.status === "active" ? 2 : 1,
341
+ strokeDasharray: dashed || n.form === "unknown" ? "5 4" : void 0
342
+ }
343
+ );
344
+ const caption = (text, big = false) => /* @__PURE__ */ jsx(
345
+ "text",
346
+ {
347
+ x: n.form === "series" || n.form === "parallel" || n.form === "conveyor" || n.form === "ladder" ? n.x + 10 : cx,
348
+ y: n.form === "series" || n.form === "parallel" || n.form === "conveyor" || n.form === "ladder" ? n.y + 14 : cy,
349
+ textAnchor: n.form === "series" || n.form === "parallel" || n.form === "conveyor" || n.form === "ladder" ? "start" : "middle",
350
+ dominantBaseline: "central",
351
+ fontFamily: AVL_FONT.mono,
352
+ fontSize: big ? 18 : 12,
353
+ fontWeight: big ? 600 : 500,
354
+ fill: n.kind === "literal" ? AVL_INK.quiet : AVL_INK.text,
355
+ children: text
356
+ }
357
+ );
358
+ if (n.kind !== "call") return /* @__PURE__ */ jsxs(Fragment, { children: [
359
+ frame(),
360
+ caption(n.label)
361
+ ] });
362
+ switch (n.form) {
363
+ case "series": {
364
+ const rx = n.x + n.w - 34;
365
+ const ys = n.children.map((_, i) => portY(n, i));
366
+ let lit = true;
367
+ const segs = [];
368
+ let prev = n.y + 8;
369
+ n.children.forEach((c, i) => {
370
+ const cs = stateOf(c);
371
+ segs.push(/* @__PURE__ */ jsx("line", { x1: rx, y1: prev, x2: rx, y2: ys[i] - 13, stroke: lit ? AVL_INK.focus : AVL_INK.quiet, strokeOpacity: lit ? 1 : 0.4, strokeWidth: 2 }, `r${i}`));
372
+ lit = lit && cs.status === "done" && truthy(cs.value);
373
+ prev = ys[i] + 13;
374
+ });
375
+ segs.push(/* @__PURE__ */ jsx("line", { x1: rx, y1: prev, x2: rx, y2: cy, stroke: lit ? AVL_INK.focus : AVL_INK.quiet, strokeOpacity: lit ? 1 : 0.4, strokeWidth: 2 }, "rend"));
376
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
377
+ frame(),
378
+ caption(n.label),
379
+ segs,
380
+ n.children.map((_, i) => switchGlyph(n, i, rx, ys[i], true))
381
+ ] });
382
+ }
383
+ case "parallel": {
384
+ const l = n.x + 18;
385
+ const r = n.x + n.w - 18;
386
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
387
+ frame(),
388
+ caption(n.label),
389
+ /* @__PURE__ */ jsx("line", { x1: l, y1: portY(n, 0) - 10, x2: l, y2: portY(n, n.children.length - 1) + 10, stroke: AVL_INK.quiet, strokeWidth: 2 }),
390
+ /* @__PURE__ */ jsx("line", { x1: r, y1: portY(n, 0) - 10, x2: r, y2: portY(n, n.children.length - 1) + 10, stroke: AVL_INK.quiet, strokeWidth: 2 }),
391
+ n.children.map((c, i) => {
392
+ const cs = stateOf(c);
393
+ const on = cs.status === "done" && truthy(cs.value);
394
+ const py = portY(n, i);
395
+ return /* @__PURE__ */ jsxs("g", { children: [
396
+ /* @__PURE__ */ jsx("line", { x1: l, y1: py, x2: (l + r) / 2 - 12, y2: py, stroke: on ? AVL_INK.focus : AVL_INK.quiet, strokeWidth: 1.5 }),
397
+ /* @__PURE__ */ jsx("line", { x1: (l + r) / 2 + 12, y1: py, x2: r, y2: py, stroke: on ? AVL_INK.focus : AVL_INK.quiet, strokeWidth: 1.5 }),
398
+ switchGlyph(n, i, (l + r) / 2, py, false)
399
+ ] }, `b${i}`);
400
+ })
401
+ ] });
402
+ }
403
+ case "branch": {
404
+ const cond = stateOf(n.children[0]);
405
+ const takenIndex = cond.status === "done" ? truthy(cond.value) ? 1 : 2 : -1;
406
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
407
+ frame(),
408
+ n.children.slice(1).map((c, j) => {
409
+ const i = j + 1;
410
+ const on = i === takenIndex;
411
+ return /* @__PURE__ */ jsx(
412
+ "path",
413
+ {
414
+ d: `M ${n.x} ${portY(n, i)} C ${cx} ${portY(n, i)}, ${cx} ${cy}, ${n.x + n.w} ${cy}`,
415
+ fill: "none",
416
+ stroke: on ? AVL_INK.focus : AVL_INK.quiet,
417
+ strokeOpacity: on ? 1 : 0.35,
418
+ strokeWidth: on ? 2.5 : 1.5
419
+ },
420
+ `t${i}`
421
+ );
422
+ }),
423
+ /* @__PURE__ */ jsx("line", { x1: n.x, y1: portY(n, 0), x2: cx, y2: cy, stroke: AVL_INK.quiet, strokeWidth: 1, strokeDasharray: "2 3" }),
424
+ /* @__PURE__ */ jsx("text", { x: n.x + 8, y: n.y + 12, fontFamily: AVL_FONT.mono, fontSize: 12, fill: AVL_INK.text, children: n.label })
425
+ ] });
426
+ }
427
+ case "conveyor": {
428
+ const collection = stateOf(n.children[0]);
429
+ const items = Array.isArray(collection.value) ? collection.value : [];
430
+ const lambda = n.children[1];
431
+ const bodyNode = lambda?.children[lambda.children.length - 1];
432
+ const bodyState = bodyNode ? stateOf(bodyNode) : IDLE;
433
+ const results = bodyState.results;
434
+ const beltY = n.y + n.h - 26;
435
+ const step = items.length ? (n.w - 24) / items.length : 0;
436
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
437
+ frame(),
438
+ caption(n.label),
439
+ /* @__PURE__ */ jsx("rect", { x: n.x + 8, y: beltY - 12, width: n.w - 16, height: 24, rx: 12, fill: AVL_INK.wash, stroke: AVL_INK.line }),
440
+ items.map((item, i) => {
441
+ const done = i < results.length;
442
+ const current = bodyState.status === "active" && i === results.length;
443
+ const result = done ? results[i] : void 0;
444
+ const kept = typeof result === "boolean" ? result : true;
445
+ const x = n.x + 12 + i * step;
446
+ return /* @__PURE__ */ jsxs("g", { "data-testid": "avl-circuit-item", "data-result": done ? String(result) : "pending", children: [
447
+ /* @__PURE__ */ jsx("title", { children: JSON.stringify(item) }),
448
+ /* @__PURE__ */ jsx(
449
+ "rect",
450
+ {
451
+ x,
452
+ y: beltY - 9,
453
+ width: step - 6,
454
+ height: 18,
455
+ rx: 9,
456
+ fill: done ? avlTint(kept ? AVL_INK.pass : AVL_INK.fail, 16) : AVL_INK.surface,
457
+ stroke: current ? AVL_INK.focus : done ? kept ? AVL_INK.pass : AVL_INK.fail : AVL_INK.line,
458
+ strokeWidth: current ? 2 : 1,
459
+ opacity: done && !kept ? 0.55 : 1
460
+ }
461
+ ),
462
+ /* @__PURE__ */ jsxs(
463
+ "text",
464
+ {
465
+ x: x + (step - 6) / 2,
466
+ y: beltY,
467
+ textAnchor: "middle",
468
+ dominantBaseline: "central",
469
+ fontFamily: AVL_FONT.mono,
470
+ fontSize: 12,
471
+ fill: AVL_INK.text,
472
+ textDecoration: done && !kept ? "line-through" : void 0,
473
+ children: [
474
+ `#${i + 1}`,
475
+ done ? typeof result === "boolean" ? kept ? " \u2713" : " \u2715" : ` ${fmt(result)}` : ""
476
+ ]
477
+ }
478
+ )
479
+ ] }, `it${i}`);
480
+ })
481
+ ] });
482
+ }
483
+ case "ladder": {
484
+ const rl = n.x + 14;
485
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
486
+ frame(),
487
+ caption(n.label),
488
+ /* @__PURE__ */ jsx("line", { x1: rl, y1: n.y + 22, x2: rl, y2: n.y + n.h - 6, stroke: AVL_INK.focus, strokeWidth: 2 }),
489
+ n.children.map((c, i) => {
490
+ const cs = stateOf(c);
491
+ const color = cs.status === "done" ? AVL_INK.pass : cs.status === "active" ? AVL_INK.focus : cs.status === "error" ? AVL_INK.fail : AVL_INK.quiet;
492
+ return /* @__PURE__ */ jsx("line", { x1: rl, y1: portY(n, i), x2: n.x + n.w - 10, y2: portY(n, i), stroke: color, strokeWidth: cs.status === "idle" ? 1 : 2 }, `r${i}`);
493
+ })
494
+ ] });
495
+ }
496
+ case "actuator": {
497
+ const zone = effectZoneOf(n.label);
498
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
499
+ frame(),
500
+ /* @__PURE__ */ jsx("svg", { x: n.x + 6, y: cy - 9, width: 18, height: 18, viewBox: "-9 -9 18 18", overflow: "visible", children: /* @__PURE__ */ jsx(AvlEffect, { effectType: n.label, size: 7, color: s.status === "done" ? AVL_INK.pass : AVL_INK.quiet }) }),
501
+ /* @__PURE__ */ jsx("text", { x: n.x + 28, y: cy, dominantBaseline: "central", fontFamily: AVL_FONT.mono, fontSize: 12, fontWeight: 600, fill: AVL_INK.text, children: n.label }),
502
+ s.status === "done" && zone ? /* @__PURE__ */ jsxs("text", { "data-testid": "avl-circuit-zone", x: n.x + n.w - 8, y: n.y + n.h + 14, textAnchor: "end", fontFamily: AVL_FONT.mono, fontSize: 12, fill: AVL_INK.pass, children: [
503
+ "\u2192 ",
504
+ t(`avl.circuit.zone.${zone}`)
505
+ ] }) : null
506
+ ] });
507
+ }
508
+ case "invert":
509
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
510
+ /* @__PURE__ */ jsx("path", { d: `M ${n.x + 8} ${n.y + 6} L ${n.x + n.w - 14} ${cy} L ${n.x + 8} ${n.y + n.h - 6} Z`, fill: AVL_INK.surface, stroke: AVL_INK.line }),
511
+ /* @__PURE__ */ jsx("circle", { cx: n.x + n.w - 9, cy, r: 4, fill: AVL_INK.surface, stroke: AVL_INK.line })
512
+ ] });
513
+ case "template":
514
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
515
+ frame(true),
516
+ caption(n.label)
517
+ ] });
518
+ default:
519
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
520
+ frame(),
521
+ caption(n.form === "unknown" ? `${n.label} ?` : n.label, n.label.length <= 2)
522
+ ] });
523
+ }
524
+ };
525
+ const drawn = [];
526
+ const walk = (n) => {
527
+ n.children.forEach((c, i) => {
528
+ walk(c);
529
+ drawn.push(wire(n, c, i));
530
+ });
531
+ const s = stateOf(n);
532
+ drawn.push(
533
+ /* @__PURE__ */ jsxs(
534
+ "g",
535
+ {
536
+ "data-testid": "avl-circuit-node",
537
+ "data-key": n.key,
538
+ "data-kind": n.kind,
539
+ "data-form": n.form ?? "",
540
+ "data-status": s.status,
541
+ opacity: s.status === "skipped" ? 0.35 : 1,
542
+ children: [
543
+ s.status === "active" ? /* @__PURE__ */ jsx("rect", { x: n.x - 4, y: n.y - 4, width: n.w + 8, height: n.h + 8, rx: 14, fill: "none", stroke: AVL_INK.focus, strokeOpacity: 0.22, strokeWidth: 4, children: !reduceMotion ? /* @__PURE__ */ jsx("animate", { attributeName: "stroke-opacity", values: "0.28;0.06;0.28", dur: "1.6s", repeatCount: "indefinite" }) : null }) : null,
544
+ body(n)
545
+ ]
546
+ },
547
+ `n-${n.key}`
548
+ )
549
+ );
550
+ };
551
+ walk(circuit.root);
552
+ const root = circuit.root;
553
+ const rootState = stateOf(root);
554
+ const outY = root.y + root.h / 2;
555
+ return /* @__PURE__ */ jsxs(Box, { className, style: { width: "100%" }, children: [
556
+ title || showCode ? /* @__PURE__ */ jsxs(Box, { className: "pb-2", children: [
557
+ title ? /* @__PURE__ */ jsx(Typography, { variant: "body", weight: "semibold", children: title }) : null,
558
+ showCode ? /* @__PURE__ */ jsx(Box, { as: "code", "data-testid": "avl-circuit-code", style: { display: "block", fontFamily: AVL_FONT.mono, fontSize: 13, color: AVL_INK.quiet, whiteSpace: "pre-wrap" }, children: formatSExpr(expr) }) : null
559
+ ] }) : null,
560
+ /* @__PURE__ */ jsx(Box, { ref: hostRef, className: "overflow-x-auto", style: { width: "100%" }, children: /* @__PURE__ */ jsx(Box, { className: "relative mx-auto", style: { width: W * scale, height: circuit.h * scale }, children: /* @__PURE__ */ jsxs("svg", { width: W * scale, height: circuit.h * scale, viewBox: `0 0 ${W} ${circuit.h}`, role: "img", "aria-label": formatSExpr(expr), children: [
561
+ drawn,
562
+ /* @__PURE__ */ jsx("path", { d: `M ${root.x + root.w} ${outY} H ${root.x + root.w + 38}`, stroke: rootState.status === "done" ? AVL_INK.focus : AVL_INK.quiet, strokeWidth: 2 }),
563
+ rootState.status === "done" && typeof rootState.value === "boolean" ? /* @__PURE__ */ jsx("circle", { cx: root.x + root.w + 48, cy: outY, r: 8, fill: rootState.value ? AVL_INK.pass : AVL_INK.fail }) : null,
564
+ rootState.status === "done" && rootState.value !== void 0 ? valueChip(root.x + root.w + 62, outY + 10, rootState.value) : null
565
+ ] }) }) }),
566
+ narration !== null ? /* @__PURE__ */ jsxs(Box, { className: "pt-2", children: [
567
+ /* @__PURE__ */ jsxs(Box, { "data-testid": "avl-circuit-narration", style: { fontSize: 13, color: AVL_INK.quiet }, children: [
568
+ /* @__PURE__ */ jsx(Box, { as: "span", style: { color: AVL_INK.text, fontWeight: 600 }, children: t("avl.circuit.step", { n: at + 1, total: trace?.length ?? 0 }) }),
569
+ " \u2014 ",
570
+ narration
571
+ ] }),
572
+ stack.length > 0 ? /* @__PURE__ */ jsxs(Box, { className: "flex flex-wrap items-center gap-1 pt-1", style: { fontFamily: AVL_FONT.mono, fontSize: 12, color: AVL_INK.quiet }, children: [
573
+ t("avl.circuit.stack"),
574
+ stack.map((k, i) => /* @__PURE__ */ jsx(
575
+ Box,
576
+ {
577
+ as: "span",
578
+ "data-testid": "avl-circuit-stack-frame",
579
+ className: "rounded px-1.5",
580
+ style: { border: `1px solid ${i === stack.length - 1 ? AVL_INK.focus : AVL_INK.line}`, color: i === stack.length - 1 ? AVL_INK.focus : AVL_INK.quiet, background: AVL_INK.wash },
581
+ children: nodes.get(k)?.label ?? k
582
+ },
583
+ k
584
+ ))
585
+ ] }) : null
586
+ ] }) : null
587
+ ] });
588
+ };
589
+ AvlCircuit.displayName = "AvlCircuit";
590
+ var isConfigObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
591
+ var EffectHeader = ({ type, failed, failedLabel, note }) => /* @__PURE__ */ jsxs(HStack, { gap: "sm", align: "center", children: [
592
+ /* @__PURE__ */ jsx(AvlEffectChip, { effectType: type, size: 18, note }),
593
+ /* @__PURE__ */ jsx(Badge, { variant: "primary", size: "sm", children: type }),
594
+ failed ? /* @__PURE__ */ jsx(Badge, { variant: "danger", size: "sm", children: failedLabel }) : null
595
+ ] });
596
+ var AvlTransitionDetail = ({ schema, transitionIndex, scene, cursor, transition, playback, ...rest }) => {
597
+ const { t } = useTranslate();
598
+ const resolved = useMemo(() => {
599
+ if (transition) return { transition, playback };
600
+ if (schema === void 0 || transitionIndex === void 0) return null;
601
+ const program = typeof schema === "string" ? JSON.parse(schema) : schema;
602
+ const level = parseTraitLevel(program, rest.orbital, rest.trait);
603
+ const found = level?.transitions[transitionIndex];
604
+ if (!level || !found) return null;
605
+ const steps = scene ?? [];
606
+ return { transition: found, playback: playback ?? transitionPlayback(level, rest.orbital, found, steps, cursor ?? steps.length - 1) };
607
+ }, [transition, playback, schema, transitionIndex, scene, cursor, rest.orbital, rest.trait]);
608
+ if (!resolved) return /* @__PURE__ */ jsx(Box, { "data-testid": "avl-transition-missing", children: /* @__PURE__ */ jsx(EmptyState, { icon: "git-branch", title: t("avl.transitionMissing") }) });
609
+ return /* @__PURE__ */ jsx(TransitionDetailBody, { ...rest, transition: resolved.transition, ...resolved.playback ? { playback: resolved.playback } : {} });
610
+ };
611
+ var TransitionDetailBody = ({ orbital, trait, transition, annotations, playback, stepEvent, className }) => {
612
+ const { t } = useTranslate();
613
+ const [payload, setPayload] = useState({});
614
+ const guard = transition.guard ?? null;
615
+ const guardRun = playback?.guard;
616
+ const request = { orbital, trait, from: transition.from, event: transition.event, payload };
617
+ const effectItems = useMemo(
618
+ () => transition.effects.map((effect, i) => {
619
+ const expr = [effect.type, ...effect.args];
620
+ const ran = playback?.effects[i];
621
+ return {
622
+ id: `effect-${i}`,
623
+ header: /* @__PURE__ */ jsx(EffectHeader, { type: effect.type, failed: ran?.status === "failed", failedLabel: t("avl.play.effectFailed"), note: annotations?.effects?.[effect.type] }),
624
+ content: /* @__PURE__ */ jsx(AvlCircuit, { expr, trace: ran?.evalTrace, showCode: true })
625
+ };
626
+ }),
627
+ [transition.effects, playback, t, annotations]
628
+ );
629
+ const openEffects = transition.effects.map((effect, i) => effectZoneOf(effect.type) === "screen" ? null : `effect-${i}`).filter((id) => id !== null);
630
+ return /* @__PURE__ */ jsx(Card, { className: `w-full max-w-5xl mx-auto ${className ?? ""}`, shadow: "md", "data-testid": "avl-transition-detail", children: /* @__PURE__ */ jsx(Box, { className: "p-6", children: /* @__PURE__ */ jsxs(VStack, { gap: "lg", children: [
631
+ /* @__PURE__ */ jsxs(HStack, { gap: "md", justify: "between", align: "center", wrap: true, children: [
632
+ /* @__PURE__ */ jsxs(HStack, { gap: "sm", align: "center", children: [
633
+ /* @__PURE__ */ jsx(Badge, { variant: "neutral", size: "lg", children: transition.from }),
634
+ annotations?.transitions?.[transition.event] ? /* @__PURE__ */ jsx(AvlExplain, { lines: [transition.event], note: annotations.transitions[transition.event], children: /* @__PURE__ */ jsx(Box, { as: "span", tabIndex: 0, "data-testid": "avl-td-event", className: "underline decoration-dotted underline-offset-4 cursor-help", children: /* @__PURE__ */ jsx(Typography, { variant: "body1", weight: "semibold", as: "span", children: transition.event }) }) }) : /* @__PURE__ */ jsx(Box, { as: "span", "data-testid": "avl-td-event", children: /* @__PURE__ */ jsx(Typography, { variant: "body1", weight: "semibold", as: "span", children: transition.event }) }),
635
+ /* @__PURE__ */ jsx(Typography, { variant: "h5", color: "muted", children: "\u2192" }),
636
+ /* @__PURE__ */ jsx(Badge, { variant: "neutral", size: "lg", children: transition.to })
637
+ ] }),
638
+ playback ? /* @__PURE__ */ jsx(HStack, { gap: "xs", align: "center", children: /* @__PURE__ */ jsx(Badge, { variant: playback.fired ? "success" : "warning", size: "md", "data-testid": "avl-transition-verdict", children: playback.fired ? t("avl.play.fired") : guardRun && !guardRun.passed ? t("avl.play.blocked") : t("avl.play.notReached") }) }) : null
639
+ ] }),
640
+ stepEvent ? /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
641
+ /* @__PURE__ */ jsx(Typography, { variant: "overline", color: "muted", children: t("avl.play.payload") }),
642
+ /* @__PURE__ */ jsxs(HStack, { gap: "sm", align: "start", children: [
643
+ /* @__PURE__ */ jsx(Box, { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsx(JsonTreeEditor, { value: payload, onChange: (next) => setPayload(isConfigObject(next) ? next : {}) }) }),
644
+ /* @__PURE__ */ jsx(Button, { variant: "primary", size: "sm", action: stepEvent, actionPayload: request, leftIcon: "skip-forward", children: t("avl.play.step") })
645
+ ] })
646
+ ] }) : null,
647
+ !playback && stepEvent ? /* @__PURE__ */ jsx(Typography, { variant: "small", color: "muted", children: t("avl.play.notPlayed") }) : null,
648
+ guard !== null ? /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
649
+ /* @__PURE__ */ jsxs(HStack, { gap: "sm", align: "center", children: [
650
+ /* @__PURE__ */ jsx(Typography, { variant: "overline", color: "muted", children: t("avl.guard") }),
651
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", "data-testid": "avl-td-guard-caption", children: t("avl.guardCaption") }),
652
+ guardRun ? /* @__PURE__ */ jsx(Badge, { variant: guardRun.passed ? "success" : "danger", size: "sm", children: guardRun.passed ? t("avl.play.guardPassed") : t("avl.play.guardFailed") }) : null
653
+ ] }),
654
+ /* @__PURE__ */ jsx(AvlCircuit, { expr: guard, trace: guardRun?.trace })
655
+ ] }) : null,
656
+ effectItems.length > 0 ? /* @__PURE__ */ jsxs(VStack, { gap: "xs", children: [
657
+ /* @__PURE__ */ jsxs(HStack, { gap: "sm", align: "center", wrap: true, children: [
658
+ /* @__PURE__ */ jsxs(Typography, { variant: "overline", color: "muted", children: [
659
+ t("avl.effects"),
660
+ " (",
661
+ effectItems.length,
662
+ ")"
663
+ ] }),
664
+ /* @__PURE__ */ jsx(Typography, { variant: "caption", color: "muted", "data-testid": "avl-td-effects-caption", children: t("avl.effectsCaption") })
665
+ ] }),
666
+ /* @__PURE__ */ jsx(Accordion, { items: effectItems, multiple: true, defaultOpenItems: openEffects })
667
+ ] }) : null
668
+ ] }) }) });
669
+ };
670
+ AvlTransitionDetail.displayName = "AvlTransitionDetail";
671
+
672
+ export { AvlCircuit, AvlTransitionDetail };