@almadar/shell-web 0.0.0-stage → 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 (266) hide show
  1. package/bundling.d.mts +18 -0
  2. package/bundling.mjs +28 -0
  3. package/dist/ArbitraryClassCompiler-CO_iASBn.d.ts +195 -0
  4. package/dist/AvlGlyph-EPJKFEO3.js +6 -0
  5. package/dist/AvlStateMachine-RKZIKNGC.js +9 -0
  6. package/dist/AvlTransitionDetail-63SD6GZF.js +11 -0
  7. package/dist/AvlTransitionExplainer-ZBTLOM3T.js +12 -0
  8. package/dist/BehaviorView-YS5G4GNB.js +11 -0
  9. package/dist/Canvas3DHost-BkZQB5l2.d.ts +552 -0
  10. package/dist/EventBusProvider-BFFHfN4O.d.ts +296 -0
  11. package/dist/FileTree-BCFnBEuQ.d.ts +254 -0
  12. package/dist/FlowCanvas-3JRMNJLV.css +1756 -0
  13. package/dist/FlowCanvas-AUMTWMNG.js +26 -0
  14. package/dist/GameAudioProvider-ceM_n0ey.d.ts +90 -0
  15. package/dist/KaTeX_AMS-Regular-CYEKBG2K.woff +0 -0
  16. package/dist/KaTeX_AMS-Regular-JKX5W2C4.ttf +0 -0
  17. package/dist/KaTeX_AMS-Regular-U6PRYMIZ.woff2 +0 -0
  18. package/dist/KaTeX_Caligraphic-Bold-5QL5CMTE.woff2 +0 -0
  19. package/dist/KaTeX_Caligraphic-Bold-WZ3QSGD3.woff +0 -0
  20. package/dist/KaTeX_Caligraphic-Bold-ZTS3R3HK.ttf +0 -0
  21. package/dist/KaTeX_Caligraphic-Regular-3LKEU76G.woff +0 -0
  22. package/dist/KaTeX_Caligraphic-Regular-A7XRTZ5Q.ttf +0 -0
  23. package/dist/KaTeX_Caligraphic-Regular-KX5MEWCF.woff2 +0 -0
  24. package/dist/KaTeX_Fraktur-Bold-2QVFK6NQ.woff2 +0 -0
  25. package/dist/KaTeX_Fraktur-Bold-T4SWXBMT.woff +0 -0
  26. package/dist/KaTeX_Fraktur-Bold-WGHVTYOR.ttf +0 -0
  27. package/dist/KaTeX_Fraktur-Regular-2PEIFJSJ.woff2 +0 -0
  28. package/dist/KaTeX_Fraktur-Regular-5U4OPH2X.ttf +0 -0
  29. package/dist/KaTeX_Fraktur-Regular-PQMHCIK6.woff +0 -0
  30. package/dist/KaTeX_Main-Bold-2GA4IZIN.woff +0 -0
  31. package/dist/KaTeX_Main-Bold-W5FBVCZM.ttf +0 -0
  32. package/dist/KaTeX_Main-Bold-YP5VVQRP.woff2 +0 -0
  33. package/dist/KaTeX_Main-BoldItalic-4P4C7HJH.woff +0 -0
  34. package/dist/KaTeX_Main-BoldItalic-N4V3DX7S.woff2 +0 -0
  35. package/dist/KaTeX_Main-BoldItalic-ODMLBJJQ.ttf +0 -0
  36. package/dist/KaTeX_Main-Italic-I43T2HSR.ttf +0 -0
  37. package/dist/KaTeX_Main-Italic-RELBIK7M.woff2 +0 -0
  38. package/dist/KaTeX_Main-Italic-SASNQFN2.woff +0 -0
  39. package/dist/KaTeX_Main-Regular-ARRPAO67.woff2 +0 -0
  40. package/dist/KaTeX_Main-Regular-P5I74A2A.woff +0 -0
  41. package/dist/KaTeX_Main-Regular-W74P5G27.ttf +0 -0
  42. package/dist/KaTeX_Math-BoldItalic-6EBV3DK5.woff +0 -0
  43. package/dist/KaTeX_Math-BoldItalic-K4WTGH3J.woff2 +0 -0
  44. package/dist/KaTeX_Math-BoldItalic-VB447A4D.ttf +0 -0
  45. package/dist/KaTeX_Math-Italic-6KGCHLFN.woff2 +0 -0
  46. package/dist/KaTeX_Math-Italic-KKK3USB2.woff +0 -0
  47. package/dist/KaTeX_Math-Italic-SON4MRCA.ttf +0 -0
  48. package/dist/KaTeX_SansSerif-Bold-RRNVJFFW.woff2 +0 -0
  49. package/dist/KaTeX_SansSerif-Bold-STQ6RXC7.ttf +0 -0
  50. package/dist/KaTeX_SansSerif-Bold-X5M5EMOD.woff +0 -0
  51. package/dist/KaTeX_SansSerif-Italic-HMPFTM52.woff2 +0 -0
  52. package/dist/KaTeX_SansSerif-Italic-PSN4QKYX.woff +0 -0
  53. package/dist/KaTeX_SansSerif-Italic-WTBAZBGY.ttf +0 -0
  54. package/dist/KaTeX_SansSerif-Regular-2TL3USAE.ttf +0 -0
  55. package/dist/KaTeX_SansSerif-Regular-OQCII6EP.woff +0 -0
  56. package/dist/KaTeX_SansSerif-Regular-XIQ62X4E.woff2 +0 -0
  57. package/dist/KaTeX_Script-Regular-72OLXYNA.ttf +0 -0
  58. package/dist/KaTeX_Script-Regular-A5IFOEBS.woff +0 -0
  59. package/dist/KaTeX_Script-Regular-APUWIHLP.woff2 +0 -0
  60. package/dist/KaTeX_Size1-Regular-4HRHTS65.woff +0 -0
  61. package/dist/KaTeX_Size1-Regular-5LRUTBFT.woff2 +0 -0
  62. package/dist/KaTeX_Size1-Regular-7K6AASVL.ttf +0 -0
  63. package/dist/KaTeX_Size2-Regular-222HN3GT.ttf +0 -0
  64. package/dist/KaTeX_Size2-Regular-K5ZHAIS6.woff +0 -0
  65. package/dist/KaTeX_Size2-Regular-LELKET5D.woff2 +0 -0
  66. package/dist/KaTeX_Size3-Regular-TLFPAHDE.woff +0 -0
  67. package/dist/KaTeX_Size3-Regular-UFCO6WCA.ttf +0 -0
  68. package/dist/KaTeX_Size3-Regular-WQRQ47UD.woff2 +0 -0
  69. package/dist/KaTeX_Size4-Regular-7PGNVPQK.ttf +0 -0
  70. package/dist/KaTeX_Size4-Regular-CDMV7U5C.woff2 +0 -0
  71. package/dist/KaTeX_Size4-Regular-PKMWZHNC.woff +0 -0
  72. package/dist/KaTeX_Typewriter-Regular-3F5K6SQ6.ttf +0 -0
  73. package/dist/KaTeX_Typewriter-Regular-MJMFSK64.woff +0 -0
  74. package/dist/KaTeX_Typewriter-Regular-VBYJ4NRC.woff2 +0 -0
  75. package/dist/KernelEngineContext-CcxGYtlr.d.ts +33 -0
  76. package/dist/LayersPanel-M2LHWUFF.js +6 -0
  77. package/dist/ModuleCard-QHDGK5XK.js +7 -0
  78. package/dist/OrbInspector-MHLJ6OEE.css +1756 -0
  79. package/dist/OrbInspector-QCPEPUPH.js +26 -0
  80. package/dist/Select-B-iDdnvE.d.ts +185 -0
  81. package/dist/ServerBridge-Bqsj-lOU.d.ts +124 -0
  82. package/dist/ThemeContext-DJmO59xd.d.ts +147 -0
  83. package/dist/UISlotContext-Dl_ewwCI.d.ts +79 -0
  84. package/dist/UISlotRenderer-C7WWOK43.js +26 -0
  85. package/dist/UISlotRenderer-KVFO6J7R.css +1756 -0
  86. package/dist/auth/browser/index.d.ts +2 -0
  87. package/dist/auth/browser/index.js +2 -0
  88. package/dist/auth/react/index.d.ts +56 -0
  89. package/dist/auth/react/index.js +157 -0
  90. package/dist/avl/index.css +1756 -0
  91. package/dist/avl/index.d.ts +2248 -0
  92. package/dist/avl/index.js +2693 -0
  93. package/dist/avl-3d-context-BycmO6tG.d.ts +201 -0
  94. package/dist/avl-schema-parser-CtJxJ9KU.d.ts +132 -0
  95. package/dist/avl-zoom-state-CKMVuBFg.d.ts +17 -0
  96. package/dist/chunk-3BBUBJFF.js +339 -0
  97. package/dist/chunk-3S54FWRC.js +131 -0
  98. package/dist/chunk-3VZ36ZKO.js +775 -0
  99. package/dist/chunk-4T3P43NS.js +1133 -0
  100. package/dist/chunk-4YXBKHHM.js +11488 -0
  101. package/dist/chunk-57DC34LY.js +525 -0
  102. package/dist/chunk-5QTYQTPS.js +15 -0
  103. package/dist/chunk-A2LR6VQQ.js +349 -0
  104. package/dist/chunk-AB3X7QTE.js +505 -0
  105. package/dist/chunk-AE7VCQB6.js +561 -0
  106. package/dist/chunk-AGXD77SL.js +98 -0
  107. package/dist/chunk-AU7O65OX.js +66 -0
  108. package/dist/chunk-CPLN6NBQ.js +701 -0
  109. package/dist/chunk-DZBQA2OW.js +176 -0
  110. package/dist/chunk-E6KA4J6N.js +227 -0
  111. package/dist/chunk-EOWMARUB.js +16 -0
  112. package/dist/chunk-G7DCAZ22.js +19 -0
  113. package/dist/chunk-GFXCPUMX.js +1334 -0
  114. package/dist/chunk-HH5KSMH5.js +311 -0
  115. package/dist/chunk-ILQXJ2AR.js +280 -0
  116. package/dist/chunk-ILZ7ORX7.js +432 -0
  117. package/dist/chunk-K4MOPSEL.js +674 -0
  118. package/dist/chunk-LHP2TK7O.js +47587 -0
  119. package/dist/chunk-P4ZFUQFF.js +93 -0
  120. package/dist/chunk-PCR37T3U.js +296 -0
  121. package/dist/chunk-PRXQGGCO.js +580 -0
  122. package/dist/chunk-REXYVBUO.js +191 -0
  123. package/dist/chunk-ROICKAU7.js +24 -0
  124. package/dist/chunk-SP5CDJ6K.js +338 -0
  125. package/dist/chunk-TUPZWTRE.js +1051 -0
  126. package/dist/chunk-TXAUOLWZ.js +490 -0
  127. package/dist/chunk-TZZBINQY.js +82 -0
  128. package/dist/chunk-UTDC2NEA.js +14 -0
  129. package/dist/chunk-UU57VNS2.js +1053 -0
  130. package/dist/chunk-UXLE3IPR.js +421 -0
  131. package/dist/chunk-VO2TTLS5.js +94 -0
  132. package/dist/chunk-X3DMMX27.js +11 -0
  133. package/dist/chunk-YHMRX6YA.js +455 -0
  134. package/dist/components/index.css +1756 -0
  135. package/dist/components/index.d.ts +11299 -0
  136. package/dist/components/index.js +1110 -0
  137. package/dist/context/index.d.ts +8 -0
  138. package/dist/context/index.js +8 -0
  139. package/dist/core.d.ts +2599 -0
  140. package/dist/core.js +3 -0
  141. package/dist/design-classes/index.cjs +431 -0
  142. package/dist/design-classes/index.d.cts +165 -0
  143. package/dist/design-classes/index.d.ts +165 -0
  144. package/dist/design-classes/index.js +399 -0
  145. package/dist/emojiItems-QGSNAABW.js +20 -0
  146. package/dist/fx-CmQjnHmT.d.ts +371 -0
  147. package/dist/hooks/index.d.ts +971 -0
  148. package/dist/hooks/index.js +8 -0
  149. package/dist/index.d.ts +408 -0
  150. package/dist/index.js +178 -0
  151. package/dist/katexPlugin-FA7NX4PE.css +1161 -0
  152. package/dist/katexPlugin-NCDKOOQY.js +2 -0
  153. package/dist/kernel-client-TZKGHJRY.js +516 -0
  154. package/dist/kernel-wire-wNdAPfhJ.d.ts +88 -0
  155. package/dist/lib/index.d.ts +602 -0
  156. package/dist/lib/index.js +1289 -0
  157. package/dist/paintDispatch-CuJLsr9Y.d.ts +688 -0
  158. package/dist/parseLessonSegments-GpCeMrb2.d.ts +334 -0
  159. package/dist/perf-CKiBKbkw.d.ts +22 -0
  160. package/dist/perf-Dr28-AgT.d.ts +57 -0
  161. package/dist/prism-X5YWKXO5.js +136 -0
  162. package/dist/providers/index.css +1756 -0
  163. package/dist/providers/index.d.ts +355 -0
  164. package/dist/providers/index.js +29 -0
  165. package/dist/renderer/index.d.ts +465 -0
  166. package/dist/renderer/index.js +4 -0
  167. package/dist/runtime/index.css +1756 -0
  168. package/dist/runtime/index.d.ts +239 -0
  169. package/dist/runtime/index.js +28 -0
  170. package/dist/slot-host-CPzrxLo9.d.ts +48 -0
  171. package/dist/ssr/index.cjs +9739 -0
  172. package/dist/ssr/index.d.cts +464 -0
  173. package/dist/ssr/index.d.ts +464 -0
  174. package/dist/ssr/index.js +9703 -0
  175. package/dist/storage/browser/index.d.ts +1 -0
  176. package/dist/storage/browser/index.js +2 -0
  177. package/dist/test-support.d.ts +42 -0
  178. package/dist/test-support.js +181 -0
  179. package/dist/themeTokens-CRd8AEDF.d.ts +125 -0
  180. package/dist/three/index.css +503 -0
  181. package/dist/three/index.d.ts +1185 -0
  182. package/dist/three/index.js +3908 -0
  183. package/dist/useUISlots-CiobNFGb.d.ts +211 -0
  184. package/dist/verification-C5pTeMJv.d.ts +66 -0
  185. package/dist/verificationRegistry-CVrcxG1s.d.ts +122 -0
  186. package/dist/wrapCallbackForEvent-B9QLbhxX.d.ts +19 -0
  187. package/index.css +199 -0
  188. package/package.json +273 -3
  189. package/src/core/lib/band-shapes.json +7 -0
  190. package/src/core/locales/ar.json +1276 -0
  191. package/src/core/locales/en.json +1276 -0
  192. package/src/core/locales/index.ts +54 -0
  193. package/src/core/locales/sl.json +1276 -0
  194. package/src/core/tokens/native-tokens.json +369 -0
  195. package/tailwind-compile.cjs +29 -0
  196. package/tailwind-preset.cjs +1020 -0
  197. package/themes/_base.css +451 -0
  198. package/themes/_contract.md +307 -0
  199. package/themes/_fonts-kenney.css +11 -0
  200. package/themes/_fonts.css +12 -0
  201. package/themes/_foundation.css +105 -0
  202. package/themes/_head.css +22 -0
  203. package/themes/_presets.css +67 -0
  204. package/themes/almadar-heritage.css +455 -0
  205. package/themes/almadar-website.css +269 -0
  206. package/themes/almadar.css +269 -0
  207. package/themes/aqua.css +455 -0
  208. package/themes/arabesque.css +459 -0
  209. package/themes/art-deco.css +457 -0
  210. package/themes/art-nouveau.css +459 -0
  211. package/themes/atelier.css +463 -0
  212. package/themes/bauhaus.css +461 -0
  213. package/themes/bloomberg-dense.css +463 -0
  214. package/themes/blueprint.css +457 -0
  215. package/themes/clay.css +449 -0
  216. package/themes/comic.css +453 -0
  217. package/themes/constructivist.css +457 -0
  218. package/themes/corporate.css +449 -0
  219. package/themes/cyberpunk.css +453 -0
  220. package/themes/frutiger-aero.css +458 -0
  221. package/themes/game-adventure.css +201 -0
  222. package/themes/game-rpg.css +203 -0
  223. package/themes/game-sci-fi.css +201 -0
  224. package/themes/game-ui-pack.css +200 -0
  225. package/themes/gazette.css +449 -0
  226. package/themes/glass.css +457 -0
  227. package/themes/gothic.css +453 -0
  228. package/themes/index.css +21 -0
  229. package/themes/ink-wash.css +459 -0
  230. package/themes/kawaii.css +459 -0
  231. package/themes/kflow.css +310 -0
  232. package/themes/kiosk.css +449 -0
  233. package/themes/linear-clean.css +463 -0
  234. package/themes/luxury.css +451 -0
  235. package/themes/mac-classic.css +455 -0
  236. package/themes/material.css +463 -0
  237. package/themes/memphis.css +453 -0
  238. package/themes/mid-century.css +455 -0
  239. package/themes/minimalist.css +449 -0
  240. package/themes/mudcloth.css +459 -0
  241. package/themes/nata.css +310 -0
  242. package/themes/neon.css +453 -0
  243. package/themes/neumorphic.css +451 -0
  244. package/themes/newsprint.css +455 -0
  245. package/themes/notion-editorial.css +463 -0
  246. package/themes/orb.css +465 -0
  247. package/themes/pixel.css +449 -0
  248. package/themes/prism.css +309 -0
  249. package/themes/rawi.css +310 -0
  250. package/themes/retro.css +452 -0
  251. package/themes/risograph.css +463 -0
  252. package/themes/scandi.css +469 -0
  253. package/themes/sketch.css +455 -0
  254. package/themes/solarpunk.css +469 -0
  255. package/themes/steampunk.css +451 -0
  256. package/themes/swiss.css +455 -0
  257. package/themes/terminal.css +466 -0
  258. package/themes/trait-wars.css +487 -0
  259. package/themes/ukiyo-e.css +459 -0
  260. package/themes/vaporwave.css +455 -0
  261. package/themes/victorian.css +453 -0
  262. package/themes/wabi-sabi.css +459 -0
  263. package/themes/win95.css +455 -0
  264. package/themes/wireframe.css +439 -0
  265. package/themes/zine.css +455 -0
  266. package/README.md +0 -3
@@ -0,0 +1,525 @@
1
+ import { useDraggable, useDropZone } from './chunk-VO2TTLS5.js';
2
+ import { Box, domPassthrough, useTranslate, Icon, pressableProps, Typography } from './chunk-4YXBKHHM.js';
3
+ import React, { createContext, useState, useCallback, useRef, useEffect, useContext } from 'react';
4
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
+
6
+ function fileIcon(name) {
7
+ const ext = name.split(".").pop()?.toLowerCase() ?? "";
8
+ switch (ext) {
9
+ case "ts":
10
+ case "tsx":
11
+ return "file-code";
12
+ case "js":
13
+ case "jsx":
14
+ return "file-code";
15
+ case "json":
16
+ case "orb":
17
+ return "file-json";
18
+ case "css":
19
+ case "scss":
20
+ return "file-text";
21
+ case "md":
22
+ return "file-text";
23
+ case "py":
24
+ return "file-code";
25
+ case "html":
26
+ return "file-code";
27
+ default:
28
+ return "file";
29
+ }
30
+ }
31
+ var TreeNavContext = createContext({ activeKey: void 0, setActive: () => {
32
+ } });
33
+ function levelOf(el) {
34
+ return Number(el.getAttribute("aria-level") ?? "1");
35
+ }
36
+ function treeRowKeyDown(e, state) {
37
+ if (e.target !== e.currentTarget) return;
38
+ const row = e.currentTarget;
39
+ const tree = row.closest('[role="tree"]');
40
+ if (!tree) return;
41
+ const rows = Array.from(tree.querySelectorAll('[role="treeitem"]'));
42
+ const idx = rows.indexOf(row);
43
+ const focusRow = (target) => {
44
+ if (!target) return;
45
+ e.preventDefault();
46
+ target.focus();
47
+ };
48
+ switch (e.key) {
49
+ case "Enter":
50
+ case " ":
51
+ e.preventDefault();
52
+ row.click();
53
+ return;
54
+ case "ArrowDown":
55
+ focusRow(rows[idx + 1]);
56
+ return;
57
+ case "ArrowUp":
58
+ focusRow(rows[idx - 1]);
59
+ return;
60
+ case "Home":
61
+ focusRow(rows[0]);
62
+ return;
63
+ case "End":
64
+ focusRow(rows[rows.length - 1]);
65
+ return;
66
+ case "ArrowRight":
67
+ if (state.expanded === false) {
68
+ e.preventDefault();
69
+ state.toggle();
70
+ } else if (state.expanded === true) {
71
+ const next = rows[idx + 1];
72
+ if (next && levelOf(next) > levelOf(row)) focusRow(next);
73
+ }
74
+ return;
75
+ case "ArrowLeft":
76
+ if (state.expanded === true) {
77
+ e.preventDefault();
78
+ state.toggle();
79
+ } else {
80
+ const level = levelOf(row);
81
+ focusRow(rows.slice(0, idx).reverse().find((r) => levelOf(r) < level));
82
+ }
83
+ return;
84
+ }
85
+ }
86
+ function TreeRoot({
87
+ defaultKey,
88
+ className,
89
+ rest,
90
+ children
91
+ }) {
92
+ const [active, setActive] = useState(void 0);
93
+ const rootRef = useRef(null);
94
+ useEffect(() => {
95
+ if (active === void 0) return;
96
+ if (!rootRef.current?.querySelector('[role="treeitem"][tabindex="0"]')) setActive(void 0);
97
+ });
98
+ const value = React.useMemo(() => ({ activeKey: active ?? defaultKey, setActive }), [active, defaultKey]);
99
+ return /* @__PURE__ */ jsx(TreeNavContext.Provider, { value, children: /* @__PURE__ */ jsx(Box, { ref: rootRef, className: `py-1 overflow-y-auto ${className ?? ""}`, ...domPassthrough(rest), role: "tree", children }) });
100
+ }
101
+ var TreeNodeItem = ({
102
+ node,
103
+ depth,
104
+ indent,
105
+ selectedPath,
106
+ onFileSelect,
107
+ onNodeExpand,
108
+ expandedPaths,
109
+ defaultExpanded = false
110
+ }) => {
111
+ const isDir = node.type === "dir";
112
+ const hasDerived = !isDir && ((node.children?.length ?? 0) > 0 || node.expandable === true);
113
+ const askedRef = useRef(false);
114
+ const revealed = expandedPaths?.includes(node.path) === true;
115
+ useEffect(() => {
116
+ if (!revealed) return;
117
+ setExpanded(true);
118
+ if (node.expandable === true && !askedRef.current) {
119
+ askedRef.current = true;
120
+ onNodeExpand?.(node.path);
121
+ }
122
+ }, [revealed, node.expandable, node.path, onNodeExpand]);
123
+ const [expanded, setExpanded] = useState(isDir && (defaultExpanded || depth < 1));
124
+ const isSelected = node.path === selectedPath;
125
+ const { t } = useTranslate();
126
+ const nav = useContext(TreeNavContext);
127
+ const toggleDerived = useCallback(() => {
128
+ if (!expanded && node.expandable === true && !askedRef.current) {
129
+ askedRef.current = true;
130
+ onNodeExpand?.(node.path);
131
+ }
132
+ setExpanded((prev) => !prev);
133
+ }, [expanded, node.expandable, node.path, onNodeExpand]);
134
+ const handleClick = useCallback(() => {
135
+ if (isDir) {
136
+ setExpanded((prev) => !prev);
137
+ } else {
138
+ onFileSelect?.(node.path);
139
+ }
140
+ }, [isDir, node.path, onFileSelect]);
141
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
142
+ /* @__PURE__ */ jsxs(
143
+ Box,
144
+ {
145
+ className: `flex items-center gap-1.5 py-0.5 px-2 cursor-pointer rounded-interactive transition-colors ${isSelected ? "bg-primary text-primary-foreground" : "hover:bg-muted"}`,
146
+ style: { paddingLeft: depth * indent + 8 },
147
+ onClick: handleClick,
148
+ role: "treeitem",
149
+ tabIndex: nav.activeKey === node.path ? 0 : -1,
150
+ "aria-level": depth + 1,
151
+ "aria-selected": isSelected,
152
+ "aria-expanded": isDir || hasDerived ? expanded : void 0,
153
+ onFocus: () => nav.setActive(node.path),
154
+ onKeyDown: (e) => treeRowKeyDown(e, {
155
+ expanded: isDir || hasDerived ? expanded : void 0,
156
+ toggle: isDir ? () => setExpanded((prev) => !prev) : toggleDerived
157
+ }),
158
+ children: [
159
+ isDir ? /* @__PURE__ */ jsx(
160
+ Icon,
161
+ {
162
+ name: expanded ? "chevron-down" : "chevron-right",
163
+ size: "xs",
164
+ className: "text-[var(--color-muted-foreground)] flex-shrink-0"
165
+ }
166
+ ) : hasDerived ? /* @__PURE__ */ jsx(
167
+ Box,
168
+ {
169
+ ...pressableProps((e) => {
170
+ e.stopPropagation();
171
+ toggleDerived();
172
+ }),
173
+ tabIndex: -1,
174
+ "aria-expanded": expanded,
175
+ "aria-label": expanded ? t("fileTree.collapse") : t("fileTree.expand"),
176
+ "data-testid": `file-tree-toggle-${node.path}`,
177
+ className: "flex-shrink-0 flex items-center",
178
+ children: /* @__PURE__ */ jsx(Icon, { name: expanded ? "chevron-down" : "chevron-right", size: "xs", className: "text-[var(--color-muted-foreground)]" })
179
+ }
180
+ ) : /* @__PURE__ */ jsx(Box, { style: { width: 12, flexShrink: 0 } }),
181
+ /* @__PURE__ */ jsx(
182
+ Icon,
183
+ {
184
+ name: isDir ? expanded ? "folder-open" : "folder" : fileIcon(node.name),
185
+ size: "xs",
186
+ className: isSelected ? "text-inherit" : isDir ? "text-[var(--color-warning)]" : "text-[var(--color-muted-foreground)]"
187
+ }
188
+ ),
189
+ /* @__PURE__ */ jsx(
190
+ Typography,
191
+ {
192
+ variant: "caption",
193
+ className: `truncate font-mono text-xs !text-inherit ${isSelected ? "font-semibold" : ""}`,
194
+ children: node.name
195
+ }
196
+ ),
197
+ node.note !== void 0 && /* @__PURE__ */ jsx(Typography, { variant: "caption", className: `text-[9px] flex-shrink-0 ${isSelected ? "!text-inherit opacity-80" : "text-[var(--color-muted-foreground)]"}`, children: node.note }),
198
+ !isDir && node.size !== void 0 && /* @__PURE__ */ jsx(
199
+ Typography,
200
+ {
201
+ variant: "caption",
202
+ className: `text-[9px] ml-auto flex-shrink-0 ${isSelected ? "!text-inherit opacity-80" : "text-[var(--color-muted-foreground)]"}`,
203
+ children: node.size < 1024 ? `${node.size}B` : `${Math.round(node.size / 1024)}KB`
204
+ }
205
+ )
206
+ ]
207
+ }
208
+ ),
209
+ (isDir || hasDerived) && expanded && node.children && /* @__PURE__ */ jsx(Box, { role: "group", children: node.children.map((child) => /* @__PURE__ */ jsx(
210
+ TreeNodeItem,
211
+ {
212
+ node: child,
213
+ depth: depth + 1,
214
+ indent,
215
+ selectedPath,
216
+ onFileSelect,
217
+ onNodeExpand,
218
+ expandedPaths,
219
+ defaultExpanded: depth < 0
220
+ },
221
+ child.path
222
+ )) })
223
+ ] });
224
+ };
225
+ function siblingsOf(target, roots, childrenByParent) {
226
+ if (target.parentId) {
227
+ const parentSiblings = childrenByParent.get(target.parentId);
228
+ if (parentSiblings?.some((sibling) => sibling.id === target.id)) return parentSiblings;
229
+ }
230
+ return roots;
231
+ }
232
+ var FlatTreeNodeItem = ({
233
+ item,
234
+ depth,
235
+ indent,
236
+ childrenByParent,
237
+ roots,
238
+ onNodeSelect,
239
+ onNodeAction,
240
+ nodeActionIcon,
241
+ nodeActionLabel,
242
+ onNodeReorder,
243
+ selectedId,
244
+ look,
245
+ isExpanded,
246
+ onToggle
247
+ }) => {
248
+ const { t } = useTranslate();
249
+ const children = childrenByParent.get(item.id);
250
+ const hasChildren = !!children && children.length > 0;
251
+ const expanded = hasChildren && isExpanded(item.id, depth);
252
+ const isSelected = selectedId !== void 0 && selectedId !== "" && item.id === selectedId;
253
+ const nav = look === "nav";
254
+ const rowRef = useRef(null);
255
+ const treeNav = useContext(TreeNavContext);
256
+ React.useEffect(() => {
257
+ if (isSelected) rowRef.current?.scrollIntoView({ block: "center" });
258
+ }, [isSelected]);
259
+ const handleClick = useCallback(() => {
260
+ if (hasChildren && !onNodeSelect) onToggle(item.id, expanded);
261
+ onNodeSelect?.(item.id);
262
+ }, [hasChildren, expanded, item.id, onNodeSelect, onToggle]);
263
+ const handleChevron = useCallback((e) => {
264
+ e.stopPropagation();
265
+ onToggle(item.id, expanded);
266
+ }, [item.id, expanded, onToggle]);
267
+ const handleAction = useCallback((e) => {
268
+ e.stopPropagation();
269
+ onNodeAction?.(item.id);
270
+ }, [item.id, onNodeAction]);
271
+ const { dragProps } = useDraggable({
272
+ payload: { kind: "tree-node", data: { id: item.id } },
273
+ disabled: !onNodeReorder
274
+ });
275
+ const handleRowDrop = useCallback(
276
+ (payload, position) => {
277
+ if (!onNodeReorder) return;
278
+ const draggedId = typeof payload.data.id === "string" ? payload.data.id : void 0;
279
+ if (!draggedId || draggedId === item.id) return;
280
+ const rect = rowRef.current?.getBoundingClientRect();
281
+ if (!rect || rect.height === 0) return;
282
+ const relY = position.y - rect.top;
283
+ const third = rect.height / 3;
284
+ if (relY >= third && relY <= third * 2) {
285
+ const existingChildren = childrenByParent.get(item.id);
286
+ onNodeReorder(draggedId, item.id, existingChildren ? existingChildren.length : 0);
287
+ return;
288
+ }
289
+ const siblings = siblingsOf(item, roots, childrenByParent);
290
+ const newParentId = siblings === roots ? null : item.parentId ?? null;
291
+ const targetIndex = siblings.findIndex((sibling) => sibling.id === item.id);
292
+ const index = relY < third ? targetIndex < 0 ? 0 : targetIndex : targetIndex < 0 ? siblings.length : targetIndex + 1;
293
+ onNodeReorder(draggedId, newParentId, index);
294
+ },
295
+ [onNodeReorder, item, roots, childrenByParent]
296
+ );
297
+ const { dropProps } = useDropZone({
298
+ accepts: ["tree-node"],
299
+ onDrop: handleRowDrop,
300
+ disabled: !onNodeReorder
301
+ });
302
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
303
+ /* @__PURE__ */ jsxs(
304
+ Box,
305
+ {
306
+ ref: rowRef,
307
+ className: `group/treerow flex items-center gap-1.5 px-2 cursor-pointer rounded-interactive transition-colors ${nav ? "py-1" : "py-0.5"} ${isSelected ? "bg-primary text-primary-foreground" : nav ? "text-foreground hover:bg-muted" : "hover:bg-muted"}`,
308
+ style: { paddingLeft: depth * indent + 8 },
309
+ onClick: handleClick,
310
+ role: "treeitem",
311
+ tabIndex: treeNav.activeKey === item.id ? 0 : -1,
312
+ "aria-level": depth + 1,
313
+ "aria-selected": isSelected,
314
+ "aria-expanded": hasChildren ? expanded : void 0,
315
+ onFocus: () => treeNav.setActive(item.id),
316
+ onKeyDown: (e) => treeRowKeyDown(e, {
317
+ expanded: hasChildren ? expanded : void 0,
318
+ toggle: () => onToggle(item.id, expanded)
319
+ }),
320
+ ...dragProps,
321
+ ...dropProps,
322
+ children: [
323
+ hasChildren ? /* @__PURE__ */ jsx(Box, { ...pressableProps(handleChevron), tabIndex: -1, className: "flex items-center flex-shrink-0", "aria-label": expanded ? t("fileTree.collapse") : t("fileTree.expand"), children: /* @__PURE__ */ jsx(
324
+ Icon,
325
+ {
326
+ name: expanded ? "chevron-down" : "chevron-right",
327
+ size: "xs",
328
+ className: isSelected ? "text-inherit" : "text-[var(--color-muted-foreground)]"
329
+ }
330
+ ) }) : /* @__PURE__ */ jsx(Box, { style: { width: 12, flexShrink: 0 } }),
331
+ /* @__PURE__ */ jsx(
332
+ Icon,
333
+ {
334
+ name: item.icon || (nav ? "file-text" : hasChildren ? expanded ? "folder-open" : "folder" : "file"),
335
+ size: "xs",
336
+ className: isSelected ? "text-inherit" : nav || !hasChildren ? "text-[var(--color-muted-foreground)]" : "text-[var(--color-warning)]"
337
+ }
338
+ ),
339
+ /* @__PURE__ */ jsx(
340
+ Typography,
341
+ {
342
+ variant: "caption",
343
+ className: `truncate ${nav ? "text-sm" : "font-mono text-xs"} !text-inherit ${isSelected ? "font-semibold" : ""}`,
344
+ children: item.label
345
+ }
346
+ ),
347
+ onNodeAction && /* @__PURE__ */ jsx(
348
+ Box,
349
+ {
350
+ ...pressableProps(handleAction),
351
+ tabIndex: treeNav.activeKey === item.id ? 0 : -1,
352
+ "aria-label": nodeActionLabel ?? t("fileTree.nodeAction"),
353
+ title: nodeActionLabel,
354
+ className: `ml-auto flex-shrink-0 rounded-interactive p-0.5 opacity-0 group-hover/treerow:opacity-100 group-focus-within/treerow:opacity-100 transition-opacity ${isSelected ? "hover:bg-primary-foreground/20" : "hover:bg-border"}`,
355
+ children: /* @__PURE__ */ jsx(Icon, { name: nodeActionIcon ?? "plus", size: "xs", className: "text-inherit" })
356
+ }
357
+ )
358
+ ]
359
+ }
360
+ ),
361
+ hasChildren && expanded && /* @__PURE__ */ jsx(Box, { role: "group", children: children.map((child) => /* @__PURE__ */ jsx(
362
+ FlatTreeNodeItem,
363
+ {
364
+ item: child,
365
+ depth: depth + 1,
366
+ indent,
367
+ childrenByParent,
368
+ roots,
369
+ onNodeSelect,
370
+ onNodeAction,
371
+ nodeActionIcon,
372
+ nodeActionLabel,
373
+ onNodeReorder,
374
+ selectedId,
375
+ look,
376
+ isExpanded,
377
+ onToggle
378
+ },
379
+ child.id
380
+ )) })
381
+ ] });
382
+ };
383
+ function ancestorsOf(id, byId) {
384
+ const out = /* @__PURE__ */ new Set();
385
+ if (!id) return out;
386
+ let cur = byId.get(id)?.parentId;
387
+ while (cur && byId.has(cur) && !out.has(cur)) {
388
+ out.add(cur);
389
+ cur = byId.get(cur)?.parentId;
390
+ }
391
+ return out;
392
+ }
393
+ var FlatFileTree = ({
394
+ items,
395
+ selectedId,
396
+ expandedPaths,
397
+ look = "files",
398
+ onNodeSelect,
399
+ onNodeAction,
400
+ nodeActionIcon,
401
+ nodeActionLabel,
402
+ onNodeReorder,
403
+ className,
404
+ indent = 16,
405
+ ...rest
406
+ }) => {
407
+ const [overrides, setOverrides] = useState(() => /* @__PURE__ */ new Map());
408
+ const byId = React.useMemo(() => new Map(items.map((node) => [node.id, node])), [items]);
409
+ const selectedAncestors = React.useMemo(() => ancestorsOf(selectedId, byId), [selectedId, byId]);
410
+ const listedKey = (expandedPaths ?? []).join("\n");
411
+ const listed = React.useMemo(() => new Set(expandedPaths ?? []), [listedKey]);
412
+ const lastRevealRef = React.useRef(`${selectedId ?? ""}\0${listedKey}`);
413
+ React.useEffect(() => {
414
+ const reveal = `${selectedId ?? ""}\0${listedKey}`;
415
+ if (reveal === lastRevealRef.current) return;
416
+ lastRevealRef.current = reveal;
417
+ const opened = [...selectedAncestors, ...listed];
418
+ setOverrides((prev) => {
419
+ if (!opened.some((a) => prev.get(a) === false)) return prev;
420
+ const next = new Map(prev);
421
+ for (const a of opened) if (next.get(a) === false) next.delete(a);
422
+ return next;
423
+ });
424
+ }, [selectedId, selectedAncestors, listedKey, listed]);
425
+ const isExpanded = useCallback(
426
+ (id, depth) => overrides.get(id) ?? (depth < 1 || selectedAncestors.has(id) || listed.has(id)),
427
+ [overrides, selectedAncestors, listed]
428
+ );
429
+ const onToggle = useCallback((id, effective) => {
430
+ setOverrides((prev) => {
431
+ const next = new Map(prev);
432
+ next.set(id, !effective);
433
+ return next;
434
+ });
435
+ }, []);
436
+ if (items.length === 0) return null;
437
+ const ids = new Set(items.map((node) => node.id));
438
+ const childrenByParent = /* @__PURE__ */ new Map();
439
+ const roots = [];
440
+ for (const item of items) {
441
+ if (item.parentId && ids.has(item.parentId)) {
442
+ const siblings = childrenByParent.get(item.parentId);
443
+ if (siblings) siblings.push(item);
444
+ else childrenByParent.set(item.parentId, [item]);
445
+ } else {
446
+ roots.push(item);
447
+ }
448
+ }
449
+ return /* @__PURE__ */ jsx(TreeRoot, { defaultKey: roots[0]?.id, className, rest, children: roots.map((item) => /* @__PURE__ */ jsx(
450
+ FlatTreeNodeItem,
451
+ {
452
+ item,
453
+ depth: 0,
454
+ indent,
455
+ childrenByParent,
456
+ roots,
457
+ onNodeSelect,
458
+ onNodeAction,
459
+ nodeActionIcon,
460
+ nodeActionLabel,
461
+ onNodeReorder,
462
+ selectedId,
463
+ look,
464
+ isExpanded,
465
+ onToggle
466
+ },
467
+ item.id
468
+ )) });
469
+ };
470
+ var FileTree = ({
471
+ tree,
472
+ items,
473
+ selectedPath,
474
+ selectedId,
475
+ look = "files",
476
+ onFileSelect,
477
+ onNodeExpand,
478
+ expandedPaths,
479
+ onNodeSelect,
480
+ onNodeAction,
481
+ nodeActionIcon,
482
+ nodeActionLabel,
483
+ onNodeReorder,
484
+ className,
485
+ indent = 16,
486
+ ...rest
487
+ }) => {
488
+ if (items) {
489
+ return /* @__PURE__ */ jsx(
490
+ FlatFileTree,
491
+ {
492
+ ...rest,
493
+ items,
494
+ selectedId,
495
+ expandedPaths,
496
+ look,
497
+ onNodeSelect,
498
+ onNodeAction,
499
+ nodeActionIcon,
500
+ nodeActionLabel,
501
+ onNodeReorder,
502
+ className,
503
+ indent
504
+ }
505
+ );
506
+ }
507
+ if (!tree || tree.length === 0) return null;
508
+ return /* @__PURE__ */ jsx(TreeRoot, { defaultKey: tree[0]?.path, className, rest, children: tree.map((node) => /* @__PURE__ */ jsx(
509
+ TreeNodeItem,
510
+ {
511
+ node,
512
+ depth: 0,
513
+ indent,
514
+ selectedPath,
515
+ onFileSelect,
516
+ onNodeExpand,
517
+ expandedPaths,
518
+ defaultExpanded: true
519
+ },
520
+ node.path
521
+ )) });
522
+ };
523
+ FileTree.displayName = "FileTree";
524
+
525
+ export { FileTree };
@@ -0,0 +1,15 @@
1
+ // src/types/slot-host.ts
2
+ function assertUniqueSlotsPerHost(manifest) {
3
+ const seenBySlot = /* @__PURE__ */ new Map();
4
+ for (const [regionId, region] of Object.entries(manifest.regions)) {
5
+ const existingRegionId = seenBySlot.get(region.slot);
6
+ if (existingRegionId !== void 0) {
7
+ throw new Error(
8
+ `assertUniqueSlotsPerHost: regions "${existingRegionId}" and "${regionId}" both bind slot "${region.slot}" \u2014 a slot may be mounted by only one region per host.`
9
+ );
10
+ }
11
+ seenBySlot.set(region.slot, regionId);
12
+ }
13
+ }
14
+
15
+ export { assertUniqueSlotsPerHost };