@softov/scena 0.1.2

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 (496) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +42 -0
  3. package/dist/controls/command.d.ts +18 -0
  4. package/dist/controls/command.js +150 -0
  5. package/dist/controls/events.d.ts +3 -0
  6. package/dist/controls/events.js +43 -0
  7. package/dist/controls/index.d.ts +10 -0
  8. package/dist/controls/index.js +10 -0
  9. package/dist/controls/keybinding.d.ts +9 -0
  10. package/dist/controls/keybinding.js +94 -0
  11. package/dist/controls/layout.d.ts +16 -0
  12. package/dist/controls/layout.js +201 -0
  13. package/dist/controls/manifest.d.ts +21 -0
  14. package/dist/controls/manifest.js +219 -0
  15. package/dist/controls/session.d.ts +16 -0
  16. package/dist/controls/session.js +95 -0
  17. package/dist/controls/shell.d.ts +8 -0
  18. package/dist/controls/shell.js +48 -0
  19. package/dist/controls/storage/layout-local.d.ts +6 -0
  20. package/dist/controls/storage/layout-local.js +47 -0
  21. package/dist/controls/storage/session-local.d.ts +5 -0
  22. package/dist/controls/storage/session-local.js +38 -0
  23. package/dist/controls/when.d.ts +7 -0
  24. package/dist/controls/when.js +226 -0
  25. package/dist/converters/a2ui-v0.10.d.ts +23 -0
  26. package/dist/converters/a2ui-v0.10.js +136 -0
  27. package/dist/converters/index.d.ts +1 -0
  28. package/dist/converters/index.js +1 -0
  29. package/dist/core/backends/modus-backend.d.ts +13 -0
  30. package/dist/core/backends/modus-backend.js +115 -0
  31. package/dist/core/backends/storage-backend.d.ts +7 -0
  32. package/dist/core/backends/storage-backend.js +73 -0
  33. package/dist/core/backends/yjs-backend.d.ts +3 -0
  34. package/dist/core/backends/yjs-backend.js +44 -0
  35. package/dist/core/binding-resolver.d.ts +7 -0
  36. package/dist/core/binding-resolver.js +106 -0
  37. package/dist/core/component-graph.d.ts +6 -0
  38. package/dist/core/component-graph.js +77 -0
  39. package/dist/core/component-registry.d.ts +7 -0
  40. package/dist/core/component-registry.js +87 -0
  41. package/dist/core/computed-dsl.d.ts +2 -0
  42. package/dist/core/computed-dsl.js +267 -0
  43. package/dist/core/converter-registry.d.ts +2 -0
  44. package/dist/core/converter-registry.js +37 -0
  45. package/dist/core/disposable.d.ts +3 -0
  46. package/dist/core/disposable.js +19 -0
  47. package/dist/core/dynamic-resolver.d.ts +12 -0
  48. package/dist/core/dynamic-resolver.js +134 -0
  49. package/dist/core/index.d.ts +44 -0
  50. package/dist/core/index.js +48 -0
  51. package/dist/core/label.d.ts +2 -0
  52. package/dist/core/label.js +14 -0
  53. package/dist/core/mount-menu.d.ts +2 -0
  54. package/dist/core/mount-menu.js +23 -0
  55. package/dist/core/mount-surface.d.ts +15 -0
  56. package/dist/core/mount-surface.js +214 -0
  57. package/dist/core/path-resolver.d.ts +14 -0
  58. package/dist/core/path-resolver.js +169 -0
  59. package/dist/core/permissions.d.ts +2 -0
  60. package/dist/core/permissions.js +50 -0
  61. package/dist/core/reactive-store.d.ts +17 -0
  62. package/dist/core/reactive-store.js +496 -0
  63. package/dist/core/scena.d.ts +2 -0
  64. package/dist/core/scena.js +115 -0
  65. package/dist/core/surface-presentation.d.ts +6 -0
  66. package/dist/core/surface-presentation.js +12 -0
  67. package/dist/i18n/i18n-backend.d.ts +2 -0
  68. package/dist/i18n/i18n-backend.js +35 -0
  69. package/dist/i18n/registry.d.ts +32 -0
  70. package/dist/i18n/registry.js +200 -0
  71. package/dist/porta/Limen.css +50 -0
  72. package/dist/porta/Limen.d.ts +16 -0
  73. package/dist/porta/Limen.js +14 -0
  74. package/dist/porta/PortaContext.d.ts +10 -0
  75. package/dist/porta/PortaContext.js +20 -0
  76. package/dist/porta/PortaLock.css +14 -0
  77. package/dist/porta/PortaLock.d.ts +10 -0
  78. package/dist/porta/PortaLock.js +13 -0
  79. package/dist/porta/SigillumGate.d.ts +8 -0
  80. package/dist/porta/SigillumGate.js +7 -0
  81. package/dist/porta/commands.d.ts +3 -0
  82. package/dist/porta/commands.js +125 -0
  83. package/dist/porta/index.d.ts +18 -0
  84. package/dist/porta/index.js +22 -0
  85. package/dist/porta/login-form.block.d.ts +2 -0
  86. package/dist/porta/login-form.block.js +7 -0
  87. package/dist/porta/match.d.ts +2 -0
  88. package/dist/porta/match.js +20 -0
  89. package/dist/porta/provider.d.ts +59 -0
  90. package/dist/porta/provider.js +1 -0
  91. package/dist/porta/providers/examples/google-oauth.d.ts +6 -0
  92. package/dist/porta/providers/examples/google-oauth.js +21 -0
  93. package/dist/porta/providers/examples/index.d.ts +6 -0
  94. package/dist/porta/providers/examples/index.js +3 -0
  95. package/dist/porta/providers/examples/magic-link.d.ts +8 -0
  96. package/dist/porta/providers/examples/magic-link.js +31 -0
  97. package/dist/porta/providers/examples/sms-otp.d.ts +9 -0
  98. package/dist/porta/providers/examples/sms-otp.js +31 -0
  99. package/dist/porta/providers/password.d.ts +12 -0
  100. package/dist/porta/providers/password.js +46 -0
  101. package/dist/porta/register-blocks.d.ts +3 -0
  102. package/dist/porta/register-blocks.js +31 -0
  103. package/dist/porta/register.d.ts +15 -0
  104. package/dist/porta/register.js +31 -0
  105. package/dist/porta/sigillum.d.ts +19 -0
  106. package/dist/porta/sigillum.js +41 -0
  107. package/dist/react/DefaultShell.d.ts +1 -0
  108. package/dist/react/DefaultShell.js +37 -0
  109. package/dist/react/Scena.d.ts +9 -0
  110. package/dist/react/Scena.js +20 -0
  111. package/dist/react/ScenaProvider.d.ts +8 -0
  112. package/dist/react/ScenaProvider.js +13 -0
  113. package/dist/react/ShellSplitter.d.ts +13 -0
  114. package/dist/react/ShellSplitter.js +88 -0
  115. package/dist/react/SurfaceArea.d.ts +13 -0
  116. package/dist/react/SurfaceArea.js +75 -0
  117. package/dist/react/Translate.d.ts +8 -0
  118. package/dist/react/Translate.js +10 -0
  119. package/dist/react/ViewMount.d.ts +12 -0
  120. package/dist/react/ViewMount.js +268 -0
  121. package/dist/react/core.d.ts +6 -0
  122. package/dist/react/core.js +10 -0
  123. package/dist/react/hooks/useCommand.d.ts +1 -0
  124. package/dist/react/hooks/useCommand.js +6 -0
  125. package/dist/react/hooks/useI18n.d.ts +9 -0
  126. package/dist/react/hooks/useI18n.js +16 -0
  127. package/dist/react/hooks/useLabel.d.ts +2 -0
  128. package/dist/react/hooks/useLabel.js +19 -0
  129. package/dist/react/hooks/useLayout.d.ts +2 -0
  130. package/dist/react/hooks/useLayout.js +10 -0
  131. package/dist/react/hooks/useMounts.d.ts +2 -0
  132. package/dist/react/hooks/useMounts.js +17 -0
  133. package/dist/react/hooks/useStore.d.ts +3 -0
  134. package/dist/react/hooks/useStore.js +40 -0
  135. package/dist/react/hooks/useStoreLabel.d.ts +3 -0
  136. package/dist/react/hooks/useStoreLabel.js +25 -0
  137. package/dist/react/hooks/useSurfacePresentation.d.ts +4 -0
  138. package/dist/react/hooks/useSurfacePresentation.js +16 -0
  139. package/dist/react/index.d.ts +20 -0
  140. package/dist/react/index.js +20 -0
  141. package/dist/react/mount-context.d.ts +8 -0
  142. package/dist/react/mount-context.js +20 -0
  143. package/dist/react/useSurfaceResize.d.ts +39 -0
  144. package/dist/react/useSurfaceResize.js +135 -0
  145. package/dist/runtime/args-schema.d.ts +11 -0
  146. package/dist/runtime/args-schema.js +45 -0
  147. package/dist/runtime/builtins.d.ts +3 -0
  148. package/dist/runtime/builtins.js +193 -0
  149. package/dist/runtime/client-handlers.d.ts +3 -0
  150. package/dist/runtime/client-handlers.js +19 -0
  151. package/dist/runtime/in-memory-socket.d.ts +7 -0
  152. package/dist/runtime/in-memory-socket.js +53 -0
  153. package/dist/runtime/index.d.ts +10 -0
  154. package/dist/runtime/index.js +7 -0
  155. package/dist/runtime/layout-commands.d.ts +5 -0
  156. package/dist/runtime/layout-commands.js +548 -0
  157. package/dist/runtime/opener-commands.d.ts +17 -0
  158. package/dist/runtime/opener-commands.js +96 -0
  159. package/dist/runtime/surface-bridge.d.ts +15 -0
  160. package/dist/runtime/surface-bridge.js +116 -0
  161. package/dist/styles/bar.css +155 -0
  162. package/dist/styles/base.css +285 -0
  163. package/dist/styles/geometry.css +32 -0
  164. package/dist/styles/index.d.ts +29 -0
  165. package/dist/styles/index.js +109 -0
  166. package/dist/styles/scrollbar.css +45 -0
  167. package/dist/styles/surface.css +179 -0
  168. package/dist/styles/theme.css +3 -0
  169. package/dist/styles/themes/dark.css +30 -0
  170. package/dist/styles/themes/light.css +1 -0
  171. package/dist/styles/themes/tokens.css +222 -0
  172. package/dist/types/binding-resolver.d.ts +30 -0
  173. package/dist/types/binding-resolver.js +1 -0
  174. package/dist/types/colors.d.ts +7 -0
  175. package/dist/types/colors.js +59 -0
  176. package/dist/types/command.d.ts +62 -0
  177. package/dist/types/command.js +1 -0
  178. package/dist/types/component-graph.d.ts +72 -0
  179. package/dist/types/component-graph.js +40 -0
  180. package/dist/types/component-registry.d.ts +70 -0
  181. package/dist/types/component-registry.js +1 -0
  182. package/dist/types/converter-registry.d.ts +17 -0
  183. package/dist/types/converter-registry.js +1 -0
  184. package/dist/types/disposable.d.ts +3 -0
  185. package/dist/types/disposable.js +1 -0
  186. package/dist/types/events.d.ts +75 -0
  187. package/dist/types/events.js +1 -0
  188. package/dist/types/host.d.ts +50 -0
  189. package/dist/types/host.js +1 -0
  190. package/dist/types/index.d.ts +23 -0
  191. package/dist/types/index.js +23 -0
  192. package/dist/types/keybinding.d.ts +36 -0
  193. package/dist/types/keybinding.js +1 -0
  194. package/dist/types/label.d.ts +9 -0
  195. package/dist/types/label.js +1 -0
  196. package/dist/types/layout.d.ts +117 -0
  197. package/dist/types/layout.js +1 -0
  198. package/dist/types/manifest.d.ts +152 -0
  199. package/dist/types/manifest.js +1 -0
  200. package/dist/types/mount-menu.d.ts +8 -0
  201. package/dist/types/mount-menu.js +1 -0
  202. package/dist/types/mount-surface.d.ts +87 -0
  203. package/dist/types/mount-surface.js +1 -0
  204. package/dist/types/permissions.d.ts +18 -0
  205. package/dist/types/permissions.js +1 -0
  206. package/dist/types/query.d.ts +34 -0
  207. package/dist/types/query.js +7 -0
  208. package/dist/types/reactive-store.d.ts +39 -0
  209. package/dist/types/reactive-store.js +1 -0
  210. package/dist/types/scena.d.ts +53 -0
  211. package/dist/types/scena.js +1 -0
  212. package/dist/types/scope-backend.d.ts +16 -0
  213. package/dist/types/scope-backend.js +1 -0
  214. package/dist/types/session.d.ts +39 -0
  215. package/dist/types/session.js +1 -0
  216. package/dist/types/shell.d.ts +21 -0
  217. package/dist/types/shell.js +1 -0
  218. package/dist/types/when.d.ts +10 -0
  219. package/dist/types/when.js +1 -0
  220. package/dist/ui/_utils.d.ts +8 -0
  221. package/dist/ui/_utils.js +53 -0
  222. package/dist/ui/campus/CampusMappa.d.ts +18 -0
  223. package/dist/ui/campus/CampusMappa.js +106 -0
  224. package/dist/ui/campus/CampusNodus.d.ts +25 -0
  225. package/dist/ui/campus/CampusNodus.js +211 -0
  226. package/dist/ui/campus/CampusStratum.d.ts +13 -0
  227. package/dist/ui/campus/CampusStratum.js +20 -0
  228. package/dist/ui/campus/CampusVelum.d.ts +7 -0
  229. package/dist/ui/campus/CampusVelum.js +12 -0
  230. package/dist/ui/campus/CampusView.d.ts +27 -0
  231. package/dist/ui/campus/CampusView.js +420 -0
  232. package/dist/ui/campus/context.d.ts +13 -0
  233. package/dist/ui/campus/context.js +12 -0
  234. package/dist/ui/campus/index.d.ts +14 -0
  235. package/dist/ui/campus/index.js +11 -0
  236. package/dist/ui/campus/stratum-context.d.ts +2 -0
  237. package/dist/ui/campus/stratum-context.js +10 -0
  238. package/dist/ui/campus/types.d.ts +47 -0
  239. package/dist/ui/campus/types.js +4 -0
  240. package/dist/ui/chart/BarChart.css +53 -0
  241. package/dist/ui/chart/BarChart.d.ts +24 -0
  242. package/dist/ui/chart/BarChart.js +32 -0
  243. package/dist/ui/chart/Donut.css +15 -0
  244. package/dist/ui/chart/Donut.d.ts +15 -0
  245. package/dist/ui/chart/Donut.js +18 -0
  246. package/dist/ui/chart/LineChart.css +8 -0
  247. package/dist/ui/chart/LineChart.d.ts +24 -0
  248. package/dist/ui/chart/LineChart.js +29 -0
  249. package/dist/ui/chart/catalog.d.ts +2 -0
  250. package/dist/ui/chart/catalog.js +7 -0
  251. package/dist/ui/chart/index.d.ts +6 -0
  252. package/dist/ui/chart/index.js +4 -0
  253. package/dist/ui/control/Button.css +7 -0
  254. package/dist/ui/control/Button.d.ts +17 -0
  255. package/dist/ui/control/Button.js +17 -0
  256. package/dist/ui/control/CheckBox.css +16 -0
  257. package/dist/ui/control/CheckBox.d.ts +15 -0
  258. package/dist/ui/control/CheckBox.js +23 -0
  259. package/dist/ui/control/Checks.css +6 -0
  260. package/dist/ui/control/Checks.d.ts +9 -0
  261. package/dist/ui/control/Checks.js +10 -0
  262. package/dist/ui/control/ChoicePicker.css +16 -0
  263. package/dist/ui/control/ChoicePicker.d.ts +25 -0
  264. package/dist/ui/control/ChoicePicker.js +38 -0
  265. package/dist/ui/control/DateTimeInput.css +1 -0
  266. package/dist/ui/control/DateTimeInput.d.ts +22 -0
  267. package/dist/ui/control/DateTimeInput.js +41 -0
  268. package/dist/ui/control/LocaleToggle.css +38 -0
  269. package/dist/ui/control/LocaleToggle.d.ts +11 -0
  270. package/dist/ui/control/LocaleToggle.js +23 -0
  271. package/dist/ui/control/ReloadButton.d.ts +6 -0
  272. package/dist/ui/control/ReloadButton.js +9 -0
  273. package/dist/ui/control/Slider.css +2 -0
  274. package/dist/ui/control/Slider.d.ts +21 -0
  275. package/dist/ui/control/Slider.js +37 -0
  276. package/dist/ui/control/TextField.css +0 -0
  277. package/dist/ui/control/TextField.d.ts +25 -0
  278. package/dist/ui/control/TextField.js +36 -0
  279. package/dist/ui/control/_field-parts.css +102 -0
  280. package/dist/ui/control/_field-parts.d.ts +15 -0
  281. package/dist/ui/control/_field-parts.js +17 -0
  282. package/dist/ui/control/catalog.d.ts +2 -0
  283. package/dist/ui/control/catalog.js +10 -0
  284. package/dist/ui/control/index.d.ts +13 -0
  285. package/dist/ui/control/index.js +11 -0
  286. package/dist/ui/data/DataTable.d.ts +19 -0
  287. package/dist/ui/data/DataTable.js +20 -0
  288. package/dist/ui/data/Filter.d.ts +13 -0
  289. package/dist/ui/data/Filter.js +56 -0
  290. package/dist/ui/data/List.css +16 -0
  291. package/dist/ui/data/List.d.ts +15 -0
  292. package/dist/ui/data/List.js +18 -0
  293. package/dist/ui/data/Listable.css +245 -0
  294. package/dist/ui/data/Listable.d.ts +60 -0
  295. package/dist/ui/data/Listable.js +209 -0
  296. package/dist/ui/data/Pagination.d.ts +5 -0
  297. package/dist/ui/data/Pagination.js +43 -0
  298. package/dist/ui/data/Tree.css +118 -0
  299. package/dist/ui/data/Tree.d.ts +45 -0
  300. package/dist/ui/data/Tree.js +170 -0
  301. package/dist/ui/data/catalog.d.ts +2 -0
  302. package/dist/ui/data/catalog.js +7 -0
  303. package/dist/ui/data/index.d.ts +11 -0
  304. package/dist/ui/data/index.js +7 -0
  305. package/dist/ui/display/AddPlaceholder.d.ts +6 -0
  306. package/dist/ui/display/AddPlaceholder.js +24 -0
  307. package/dist/ui/display/Alert.css +42 -0
  308. package/dist/ui/display/Alert.d.ts +14 -0
  309. package/dist/ui/display/Alert.js +13 -0
  310. package/dist/ui/display/Avatar.css +19 -0
  311. package/dist/ui/display/Avatar.d.ts +16 -0
  312. package/dist/ui/display/Avatar.js +52 -0
  313. package/dist/ui/display/Badge.css +26 -0
  314. package/dist/ui/display/Badge.d.ts +16 -0
  315. package/dist/ui/display/Badge.js +9 -0
  316. package/dist/ui/display/Card.css +15 -0
  317. package/dist/ui/display/Card.d.ts +11 -0
  318. package/dist/ui/display/Card.js +8 -0
  319. package/dist/ui/display/DetailContainer.d.ts +6 -0
  320. package/dist/ui/display/DetailContainer.js +7 -0
  321. package/dist/ui/display/DetailHeader.css +53 -0
  322. package/dist/ui/display/DetailHeader.d.ts +22 -0
  323. package/dist/ui/display/DetailHeader.js +8 -0
  324. package/dist/ui/display/DetailList.css +26 -0
  325. package/dist/ui/display/DetailList.d.ts +13 -0
  326. package/dist/ui/display/DetailList.js +5 -0
  327. package/dist/ui/display/DetailNotFound.d.ts +17 -0
  328. package/dist/ui/display/DetailNotFound.js +39 -0
  329. package/dist/ui/display/Divider.css +6 -0
  330. package/dist/ui/display/Divider.d.ts +8 -0
  331. package/dist/ui/display/Divider.js +16 -0
  332. package/dist/ui/display/Divisor.css +30 -0
  333. package/dist/ui/display/Divisor.d.ts +11 -0
  334. package/dist/ui/display/Divisor.js +43 -0
  335. package/dist/ui/display/Icon.css +10 -0
  336. package/dist/ui/display/Icon.d.ts +14 -0
  337. package/dist/ui/display/Icon.js +144 -0
  338. package/dist/ui/display/Image.css +1 -0
  339. package/dist/ui/display/Image.d.ts +16 -0
  340. package/dist/ui/display/Image.js +19 -0
  341. package/dist/ui/display/Markdown.css +38 -0
  342. package/dist/ui/display/Markdown.d.ts +8 -0
  343. package/dist/ui/display/Markdown.js +140 -0
  344. package/dist/ui/display/Progress.css +39 -0
  345. package/dist/ui/display/Progress.d.ts +15 -0
  346. package/dist/ui/display/Progress.js +17 -0
  347. package/dist/ui/display/SectionTitle.d.ts +6 -0
  348. package/dist/ui/display/SectionTitle.js +6 -0
  349. package/dist/ui/display/Skeleton.css +20 -0
  350. package/dist/ui/display/Skeleton.d.ts +11 -0
  351. package/dist/ui/display/Skeleton.js +11 -0
  352. package/dist/ui/display/Spinner.css +20 -0
  353. package/dist/ui/display/Spinner.d.ts +12 -0
  354. package/dist/ui/display/Spinner.js +12 -0
  355. package/dist/ui/display/Svg.d.ts +13 -0
  356. package/dist/ui/display/Svg.js +17 -0
  357. package/dist/ui/display/Text.css +20 -0
  358. package/dist/ui/display/Text.d.ts +13 -0
  359. package/dist/ui/display/Text.js +15 -0
  360. package/dist/ui/display/catalog.d.ts +2 -0
  361. package/dist/ui/display/catalog.js +12 -0
  362. package/dist/ui/display/index.d.ts +22 -0
  363. package/dist/ui/display/index.js +14 -0
  364. package/dist/ui/embed/HtmlEmbed.d.ts +12 -0
  365. package/dist/ui/embed/HtmlEmbed.js +16 -0
  366. package/dist/ui/embed/index.d.ts +2 -0
  367. package/dist/ui/embed/index.js +1 -0
  368. package/dist/ui/forms/DangerZone.d.ts +8 -0
  369. package/dist/ui/forms/DangerZone.js +31 -0
  370. package/dist/ui/forms/Field.css +15 -0
  371. package/dist/ui/forms/Field.d.ts +28 -0
  372. package/dist/ui/forms/Field.js +25 -0
  373. package/dist/ui/forms/FieldGroup.css +15 -0
  374. package/dist/ui/forms/FieldGroup.d.ts +7 -0
  375. package/dist/ui/forms/FieldGroup.js +7 -0
  376. package/dist/ui/forms/Form.css +14 -0
  377. package/dist/ui/forms/Form.d.ts +18 -0
  378. package/dist/ui/forms/Form.js +17 -0
  379. package/dist/ui/forms/FormActions.css +11 -0
  380. package/dist/ui/forms/FormActions.d.ts +18 -0
  381. package/dist/ui/forms/FormActions.js +10 -0
  382. package/dist/ui/forms/FormSection.css +19 -0
  383. package/dist/ui/forms/FormSection.d.ts +7 -0
  384. package/dist/ui/forms/FormSection.js +7 -0
  385. package/dist/ui/forms/LoginForm.css +105 -0
  386. package/dist/ui/forms/LoginForm.d.ts +12 -0
  387. package/dist/ui/forms/LoginForm.js +137 -0
  388. package/dist/ui/forms/SchemaForm.css +81 -0
  389. package/dist/ui/forms/SchemaForm.d.ts +26 -0
  390. package/dist/ui/forms/SchemaForm.js +186 -0
  391. package/dist/ui/forms/SettingsContainer.d.ts +8 -0
  392. package/dist/ui/forms/SettingsContainer.js +8 -0
  393. package/dist/ui/forms/catalog.d.ts +2 -0
  394. package/dist/ui/forms/catalog.js +11 -0
  395. package/dist/ui/forms/index.d.ts +19 -0
  396. package/dist/ui/forms/index.js +12 -0
  397. package/dist/ui/forms/schema-walk.d.ts +50 -0
  398. package/dist/ui/forms/schema-walk.js +116 -0
  399. package/dist/ui/index.d.ts +58 -0
  400. package/dist/ui/index.js +63 -0
  401. package/dist/ui/layout/BarLayout.d.ts +2 -0
  402. package/dist/ui/layout/BarLayout.js +18 -0
  403. package/dist/ui/layout/Column.css +6 -0
  404. package/dist/ui/layout/Column.d.ts +12 -0
  405. package/dist/ui/layout/Column.js +13 -0
  406. package/dist/ui/layout/FloatingLayout.d.ts +2 -0
  407. package/dist/ui/layout/FloatingLayout.js +12 -0
  408. package/dist/ui/layout/Grid.css +5 -0
  409. package/dist/ui/layout/Grid.d.ts +13 -0
  410. package/dist/ui/layout/Grid.js +19 -0
  411. package/dist/ui/layout/InlineLayout.d.ts +2 -0
  412. package/dist/ui/layout/InlineLayout.js +13 -0
  413. package/dist/ui/layout/MountTitle.d.ts +12 -0
  414. package/dist/ui/layout/MountTitle.js +42 -0
  415. package/dist/ui/layout/RailLayout.d.ts +2 -0
  416. package/dist/ui/layout/RailLayout.js +38 -0
  417. package/dist/ui/layout/Row.css +16 -0
  418. package/dist/ui/layout/Row.d.ts +13 -0
  419. package/dist/ui/layout/Row.js +21 -0
  420. package/dist/ui/layout/SectionHeader.d.ts +10 -0
  421. package/dist/ui/layout/SectionHeader.js +65 -0
  422. package/dist/ui/layout/SingleLayout.d.ts +2 -0
  423. package/dist/ui/layout/SingleLayout.js +25 -0
  424. package/dist/ui/layout/SpatialCard.d.ts +9 -0
  425. package/dist/ui/layout/SpatialCard.js +30 -0
  426. package/dist/ui/layout/SpatialLayout.d.ts +2 -0
  427. package/dist/ui/layout/SpatialLayout.js +446 -0
  428. package/dist/ui/layout/SplitLayout.d.ts +2 -0
  429. package/dist/ui/layout/SplitLayout.js +159 -0
  430. package/dist/ui/layout/Splitter.d.ts +12 -0
  431. package/dist/ui/layout/Splitter.js +64 -0
  432. package/dist/ui/layout/StackHeader.d.ts +9 -0
  433. package/dist/ui/layout/StackHeader.js +87 -0
  434. package/dist/ui/layout/StackLayout.d.ts +2 -0
  435. package/dist/ui/layout/StackLayout.js +137 -0
  436. package/dist/ui/layout/TabLayout.d.ts +2 -0
  437. package/dist/ui/layout/TabLayout.js +145 -0
  438. package/dist/ui/layout/TabPanelLayout.d.ts +20 -0
  439. package/dist/ui/layout/TabPanelLayout.js +615 -0
  440. package/dist/ui/layout/catalog.d.ts +2 -0
  441. package/dist/ui/layout/catalog.js +10 -0
  442. package/dist/ui/layout/index.d.ts +17 -0
  443. package/dist/ui/layout/index.js +17 -0
  444. package/dist/ui/layout/register.d.ts +3 -0
  445. package/dist/ui/layout/register.js +25 -0
  446. package/dist/ui/media/Audio.css +1 -0
  447. package/dist/ui/media/Audio.d.ts +12 -0
  448. package/dist/ui/media/Audio.js +8 -0
  449. package/dist/ui/media/Video.css +1 -0
  450. package/dist/ui/media/Video.d.ts +16 -0
  451. package/dist/ui/media/Video.js +9 -0
  452. package/dist/ui/media/catalog.d.ts +2 -0
  453. package/dist/ui/media/catalog.js +5 -0
  454. package/dist/ui/media/index.d.ts +2 -0
  455. package/dist/ui/media/index.js +3 -0
  456. package/dist/ui/menu/ActionList.css +262 -0
  457. package/dist/ui/menu/ActionList.d.ts +19 -0
  458. package/dist/ui/menu/ActionList.js +369 -0
  459. package/dist/ui/menu/ContainerMenu.d.ts +13 -0
  460. package/dist/ui/menu/ContainerMenu.js +57 -0
  461. package/dist/ui/menu/ContextMenu.d.ts +27 -0
  462. package/dist/ui/menu/ContextMenu.js +93 -0
  463. package/dist/ui/menu/index.d.ts +10 -0
  464. package/dist/ui/menu/index.js +7 -0
  465. package/dist/ui/menu/token.d.ts +22 -0
  466. package/dist/ui/menu/token.js +145 -0
  467. package/dist/ui/menu/useChatPicker.d.ts +24 -0
  468. package/dist/ui/menu/useChatPicker.js +210 -0
  469. package/dist/ui/navigation/Breadcrumb.css +30 -0
  470. package/dist/ui/navigation/Breadcrumb.d.ts +14 -0
  471. package/dist/ui/navigation/Breadcrumb.js +12 -0
  472. package/dist/ui/navigation/Link.css +13 -0
  473. package/dist/ui/navigation/Link.d.ts +18 -0
  474. package/dist/ui/navigation/Link.js +43 -0
  475. package/dist/ui/navigation/Tabs.css +39 -0
  476. package/dist/ui/navigation/Tabs.d.ts +18 -0
  477. package/dist/ui/navigation/Tabs.js +55 -0
  478. package/dist/ui/navigation/Toolbar.css +25 -0
  479. package/dist/ui/navigation/Toolbar.d.ts +12 -0
  480. package/dist/ui/navigation/Toolbar.js +21 -0
  481. package/dist/ui/navigation/catalog.d.ts +2 -0
  482. package/dist/ui/navigation/catalog.js +5 -0
  483. package/dist/ui/navigation/index.d.ts +8 -0
  484. package/dist/ui/navigation/index.js +5 -0
  485. package/dist/ui/overlay/Modal.css +35 -0
  486. package/dist/ui/overlay/Modal.d.ts +12 -0
  487. package/dist/ui/overlay/Modal.js +57 -0
  488. package/dist/ui/overlay/Popup.d.ts +12 -0
  489. package/dist/ui/overlay/Popup.js +74 -0
  490. package/dist/ui/overlay/catalog.d.ts +2 -0
  491. package/dist/ui/overlay/catalog.js +4 -0
  492. package/dist/ui/overlay/index.d.ts +1 -0
  493. package/dist/ui/overlay/index.js +2 -0
  494. package/dist/ui/register.d.ts +6 -0
  495. package/dist/ui/register.js +26 -0
  496. package/package.json +115 -0
@@ -0,0 +1,60 @@
1
+ import { type CSSProperties, type DragEvent as ReactDragEvent, type ReactNode } from 'react';
2
+ import type { BindingPath } from '../../types/component-graph.js';
3
+ import './Listable.css';
4
+ export interface ListableRenderContext {
5
+ tableMode: boolean;
6
+ containerWidth: number;
7
+ }
8
+ export interface ListableCellProps {
9
+ style?: CSSProperties;
10
+ className?: string;
11
+ }
12
+ export interface ListableTitleProps {
13
+ title?: string;
14
+ hidden?: boolean;
15
+ style?: CSSProperties;
16
+ className?: string;
17
+ }
18
+ export interface ListableColumn<T> {
19
+ key: string;
20
+ label: ReactNode;
21
+ render: (item: T, ctx: ListableRenderContext) => ReactNode;
22
+ hidden?: boolean;
23
+ mode?: 'list' | 'table';
24
+ visible?: (item: T) => boolean;
25
+ sortable?: boolean | ((a: T, b: T) => number);
26
+ cellProps?: (item: T, ctx: ListableRenderContext) => ListableCellProps;
27
+ titleProps?: (item: T | undefined, ctx: ListableRenderContext) => ListableTitleProps;
28
+ align?: 'left' | 'right';
29
+ width?: string | ((ctx: ListableRenderContext) => string);
30
+ showAt?: number;
31
+ style?: CSSProperties;
32
+ }
33
+ export interface ListableSort {
34
+ key: string;
35
+ direction: 'asc' | 'desc';
36
+ }
37
+ export interface ListableProps<T> {
38
+ items: T[];
39
+ columns: ListableColumn<T>[];
40
+ getKey: (item: T) => string;
41
+ title?: ReactNode;
42
+ toolbar?: ReactNode;
43
+ selectedKey?: string | null;
44
+ onSelect?: (item: T) => void;
45
+ onActivate?: (item: T) => void;
46
+ initialSort?: ListableSort;
47
+ sort?: ListableSort | null;
48
+ onSortChange?: (next: ListableSort | null) => void;
49
+ tableBreakpoint?: number;
50
+ renderListRow?: (item: T) => ReactNode;
51
+ contextMenuSlot?: string;
52
+ contextFor?: (item: T) => Record<string, unknown>;
53
+ contextDataContext?: BindingPath;
54
+ onRowDragStart?: (e: ReactDragEvent<HTMLElement>, item: T) => void;
55
+ emptyState?: ReactNode;
56
+ className?: string;
57
+ style?: CSSProperties;
58
+ manageKeys?: boolean;
59
+ }
60
+ export declare function Listable<T>({ items, columns, getKey, title, toolbar, selectedKey, onSelect, onActivate, initialSort, sort, onSortChange, tableBreakpoint, renderListRow, contextMenuSlot, contextFor, contextDataContext, onRowDragStart, emptyState, className, style, manageKeys, }: ListableProps<T>): ReactNode;
@@ -0,0 +1,209 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useMemo, useRef, useState, } from 'react';
3
+ import { ContextMenu } from '../menu/ContextMenu.js';
4
+ import './Listable.css';
5
+ function getValueAt(item, key) {
6
+ if (item == null || typeof item !== 'object')
7
+ return undefined;
8
+ return item[key];
9
+ }
10
+ function defaultCompare(a, b, key) {
11
+ const va = getValueAt(a, key);
12
+ const vb = getValueAt(b, key);
13
+ if (va == null && vb == null)
14
+ return 0;
15
+ if (va == null)
16
+ return -1;
17
+ if (vb == null)
18
+ return 1;
19
+ if (typeof va === 'number' && typeof vb === 'number')
20
+ return va - vb;
21
+ return String(va).localeCompare(String(vb));
22
+ }
23
+ function sortItems(items, columns, sort) {
24
+ if (!sort)
25
+ return items;
26
+ const col = columns.find((c) => c.key === sort.key);
27
+ if (!col || !col.sortable)
28
+ return items;
29
+ const cmp = typeof col.sortable === 'function'
30
+ ? col.sortable
31
+ : (a, b) => defaultCompare(a, b, col.key);
32
+ const sign = sort.direction === 'asc' ? 1 : -1;
33
+ return [...items].sort((a, b) => sign * cmp(a, b));
34
+ }
35
+ const DEFAULT_TABLE_BREAKPOINT = 480;
36
+ export function Listable({ items, columns, getKey, title, toolbar, selectedKey, onSelect, onActivate, initialSort, sort, onSortChange, tableBreakpoint = DEFAULT_TABLE_BREAKPOINT, renderListRow, contextMenuSlot, contextFor, contextDataContext, onRowDragStart, emptyState, className, style, manageKeys = false, }) {
37
+ const rootRef = useRef(null);
38
+ const [containerWidth, setContainerWidth] = useState(0);
39
+ const [internalSort, setInternalSort] = useState(initialSort ?? null);
40
+ useEffect(() => {
41
+ const el = rootRef.current;
42
+ if (!el)
43
+ return;
44
+ const ro = new ResizeObserver(([entry]) => {
45
+ if (entry)
46
+ setContainerWidth(entry.contentRect.width);
47
+ });
48
+ ro.observe(el);
49
+ return () => ro.disconnect();
50
+ }, []);
51
+ const tableMode = containerWidth >= tableBreakpoint;
52
+ const sortControlled = sort !== undefined;
53
+ const activeSort = sortControlled ? sort : internalSort;
54
+ const visibleColumns = useMemo(() => columns.filter((c) => !c.hidden &&
55
+ (tableMode || c.mode !== 'table') &&
56
+ (c.showAt == null || containerWidth >= c.showAt)), [columns, tableMode, containerWidth]);
57
+ // Declared before the track template, which now depends on it: a column's
58
+ // width may be a function of the measured container.
59
+ const renderCtx = useMemo(() => ({ tableMode, containerWidth }), [tableMode, containerWidth]);
60
+ // One track per visible column, in order — so a cell's position in the row
61
+ // is exactly its position in `columns` and nothing has to be placed by hand.
62
+ const gridTemplate = useMemo(() => visibleColumns
63
+ .map((c) => (typeof c.width === 'function' ? c.width(renderCtx) : c.width))
64
+ .map((track) => track ?? 'minmax(0, 1fr)')
65
+ .join(' '), [visibleColumns, renderCtx]);
66
+ const sortedItems = useMemo(() => sortItems(items, columns, activeSort ?? null), [items, columns, activeSort]);
67
+ function handleHeaderClick(col) {
68
+ if (!col.sortable)
69
+ return;
70
+ const cur = activeSort;
71
+ const next = !cur || cur.key !== col.key
72
+ ? { key: col.key, direction: 'asc' }
73
+ : cur.direction === 'asc'
74
+ ? { key: col.key, direction: 'desc' }
75
+ : null;
76
+ if (sortControlled)
77
+ onSortChange?.(next);
78
+ else
79
+ setInternalSort(next);
80
+ }
81
+ // Scroll the selected row into view when it changes externally.
82
+ useEffect(() => {
83
+ if (!selectedKey || !rootRef.current)
84
+ return;
85
+ const row = rootRef.current.querySelector(`[data-key="${cssEscape(selectedKey)}"]`);
86
+ if (row)
87
+ row.scrollIntoView({ block: 'nearest' });
88
+ }, [selectedKey]);
89
+ // ── Keyboard ───────────────────────────────────────────────────────────
90
+ const selectedIndex = selectedKey
91
+ ? sortedItems.findIndex((it) => getKey(it) === selectedKey)
92
+ : -1;
93
+ function handleKeyDown(e) {
94
+ if (sortedItems.length === 0)
95
+ return;
96
+ const cur = selectedIndex >= 0 ? selectedIndex : 0;
97
+ switch (e.key) {
98
+ case 'ArrowDown': {
99
+ e.preventDefault();
100
+ const next = sortedItems[Math.min(sortedItems.length - 1, cur + 1)];
101
+ if (next)
102
+ onSelect?.(next);
103
+ return;
104
+ }
105
+ case 'ArrowUp': {
106
+ e.preventDefault();
107
+ const next = sortedItems[Math.max(0, cur - 1)];
108
+ if (next)
109
+ onSelect?.(next);
110
+ return;
111
+ }
112
+ case 'Enter':
113
+ case ' ': {
114
+ e.preventDefault();
115
+ const it = sortedItems[cur];
116
+ if (it)
117
+ onActivate?.(it);
118
+ return;
119
+ }
120
+ }
121
+ }
122
+ // ── Context menu ───────────────────────────────────────────────────────
123
+ const [menu, setMenu] = useState(null);
124
+ function openContextMenu(e, item) {
125
+ if (!contextMenuSlot)
126
+ return;
127
+ e.preventDefault();
128
+ e.stopPropagation();
129
+ // onSelect?.(item);
130
+ setMenu({ x: e.clientX, y: e.clientY, item });
131
+ }
132
+ // One table cell. Placement is the cell's own business via `cellProps`; a
133
+ // wrapped cell needs none, because the strip it sits in is what the grid
134
+ // places.
135
+ function renderTableCell(col, item) {
136
+ const extra = col.cellProps?.(item, renderCtx);
137
+ // `col.style` was declared and then only ever applied in the stacked row,
138
+ // so a column that set one was silently ignored in table mode. The per-row
139
+ // props win over it, being the more specific of the two.
140
+ const style = col.style === undefined && extra?.style === undefined
141
+ ? undefined
142
+ : { ...col.style, ...extra?.style };
143
+ return (_jsx("div", { role: "cell", className: extra?.className === undefined
144
+ ? 'oo-listable__cell'
145
+ : `oo-listable__cell ${extra.className}`, "data-align": col.align ?? 'left', title: col.titleProps?.(item, renderCtx).title,
146
+ // `undefined` rather than `{}` when there is nothing to say: an empty
147
+ // object literal is a new reference on every render, which is a prop
148
+ // change on every cell of every row.
149
+ style: style, children: renderCellContent(col, item) }, col.key));
150
+ }
151
+ // One header cell.
152
+ function renderHeadCell(col) {
153
+ const isSorted = activeSort?.key === col.key;
154
+ // No row to speak of: the header is one cell for the whole column.
155
+ const head = col.titleProps?.(undefined, renderCtx);
156
+ return (_jsx("div", { role: "columnheader", className: head?.className === undefined
157
+ ? 'oo-listable__head-cell'
158
+ : `oo-listable__head-cell ${head.className}`, "data-align": col.align ?? 'left', "data-sortable": col.sortable ? 'true' : undefined, "data-sorted": isSorted ? activeSort.direction : undefined, title: col.sortable && typeof col.label === 'string' ? `Sort by ${col.label}` : undefined, onClick: col.sortable ? () => handleHeaderClick(col) : undefined, style: head?.style, children: head?.hidden === true ? null : (_jsxs(_Fragment, { children: [_jsx("span", { className: "oo-listable__head-label", children: col.label }), isSorted ? (_jsx("span", { className: "oo-listable__sort-arrow", "aria-hidden": "true", children: activeSort.direction === 'asc' ? '▲' : '▼' })) : null] })) }, col.key));
159
+ }
160
+ // ── Render helpers ─────────────────────────────────────────────────────
161
+ function renderCellContent(col, item) {
162
+ if (col.visible && !col.visible(item))
163
+ return null;
164
+ return col.render(item, renderCtx);
165
+ }
166
+ function renderTableRow(item) {
167
+ const key = getKey(item);
168
+ const selected = key === selectedKey;
169
+ return (_jsx("div", { role: "row", "data-key": key, "data-selected": selected ? 'true' : undefined, className: "oo-listable__item oo-listable__row", draggable: onRowDragStart ? true : undefined, onDragStart: onRowDragStart ? (e) => onRowDragStart(e, item) : undefined, onClick: () => {
170
+ onSelect?.(item);
171
+ }, onDoubleClick: () => onActivate?.(item), onContextMenu: (e) => openContextMenu(e, item), style: {
172
+ cursor: onSelect ? 'pointer' : undefined
173
+ }, children: visibleColumns.map((col) => renderTableCell(col, item)) }, key));
174
+ }
175
+ function renderStackedRow(item) {
176
+ const key = getKey(item);
177
+ const selected = key === selectedKey;
178
+ return (_jsx("div", { role: "row", "data-key": key, "data-selected": selected ? 'true' : undefined, className: "oo-listable__item oo-listable__stack", draggable: onRowDragStart ? true : undefined, onDragStart: onRowDragStart ? (e) => onRowDragStart(e, item) : undefined, onClick: () => onSelect?.(item), onDoubleClick: () => onActivate?.(item), onContextMenu: (e) => openContextMenu(e, item), style: {
179
+ cursor: onSelect ? 'pointer' : undefined
180
+ }, children: renderListRow
181
+ ? renderListRow(item)
182
+ : visibleColumns.map((col) => {
183
+ const content = renderCellContent(col, item);
184
+ if (content == null)
185
+ return null;
186
+ // Same contract in both modes. `ctx.tableMode` is false here, so
187
+ // a column that only wants to reposition in the table can say so
188
+ // without this branch having to know about it.
189
+ const extra = col.cellProps?.(item, renderCtx);
190
+ return (_jsx("div", { className: extra?.className === undefined
191
+ ? 'oo-listable__list-cell'
192
+ : `oo-listable__list-cell ${extra.className}`, title: col.titleProps?.(item, renderCtx).title, style: col.style === undefined && extra?.style === undefined
193
+ ? undefined
194
+ : { ...col.style, ...extra?.style }, children: _jsx("span", { className: "oo-listable__list-value", children: content }) }, col.key));
195
+ }) }, key));
196
+ }
197
+ return (_jsxs("div", { ref: rootRef, role: "table", tabIndex: 0, className: ['oo-listable', className].filter(Boolean).join(' '), "data-mode": tableMode ? 'table' : 'list', style: style, onKeyDown: manageKeys ? handleKeyDown : undefined, children: [title || toolbar ? (_jsxs("header", { className: "oo-listable__header", children: [title ? _jsx("h2", { className: "oo-listable__title", children: title }) : null, toolbar] })) : null, sortedItems.length === 0 ? (_jsx("div", { className: "oo-listable__empty", children: emptyState ?? 'Empty' })) : (
198
+ // Single grid container in table mode — head-row and every data row
199
+ // are subgrids that inherit these column tracks, so `auto`/`minmax`
200
+ // sizing is shared and head cells align with their data cells.
201
+ _jsxs("div", { className: "oo-listable__rows", role: "rowgroup", style: tableMode
202
+ ? { ['--oo-listable-template']: gridTemplate }
203
+ : undefined, children: [tableMode ? (_jsx("div", { role: "row", className: "oo-listable__head-row", children: visibleColumns.map((col) => renderHeadCell(col)) })) : null, sortedItems.map((it) => (tableMode ? renderTableRow(it) : renderStackedRow(it)))] })), menu && contextMenuSlot ? (_jsx(ContextMenu, { x: menu.x, y: menu.y, onClose: () => setMenu(null), spec: { query: { slot: contextMenuSlot }, footerHints: true }, context: contextFor ? contextFor(menu.item) : undefined, dataContext: contextDataContext })) : null] }));
204
+ }
205
+ // Cheap CSS-selector escape so a key with `"` or `]` doesn't break the
206
+ // querySelector used by scrollIntoView. Same shape as Tree.tsx.
207
+ function cssEscape(s) {
208
+ return s.replace(/(["\\\]])/g, '\\$1');
209
+ }
@@ -0,0 +1,5 @@
1
+ import type { ReactNode } from 'react';
2
+ export interface PaginationProps {
3
+ namespace: string;
4
+ }
5
+ export declare function Pagination({ namespace }: PaginationProps): ReactNode;
@@ -0,0 +1,43 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useScena } from '../../react/ScenaProvider.js';
3
+ import { useStore } from '../../react/hooks/useStore.js';
4
+ import { useI18n } from '../../react/hooks/useI18n.js';
5
+ // Generic pager bound to a resource's query/view. Writes `$/<ns>/query.page`;
6
+ // the data provider re-resolves the view (server window or client slice).
7
+ // Hidden when everything fits on one page.
8
+ export function Pagination({ namespace }) {
9
+ const scena = useScena();
10
+ const { t } = useI18n('query');
11
+ const view = useStore(`$/${namespace}/view`);
12
+ const query = useStore(`$/${namespace}/query`);
13
+ const total = view?.total ?? 0;
14
+ const page = query?.page ?? 1;
15
+ const pageSize = query?.pageSize ?? 50;
16
+ const pages = Math.max(1, Math.ceil(total / pageSize));
17
+ if (total <= pageSize)
18
+ return null;
19
+ const setPage = (p) => scena.store.set(`$/${namespace}/query`, {
20
+ ...query,
21
+ page: Math.min(pages, Math.max(1, p)),
22
+ });
23
+ return (_jsxs("div", { style: bar, children: [_jsx("button", { style: btn, disabled: page <= 1, onClick: () => setPage(page - 1), "aria-label": "Previous", children: "\u2039" }), _jsx("span", { style: { fontSize: 12, color: 'var(--oo-color-muted, #8a8f98)' }, children: t('pageOf', { page, pages, fallback: '{page} / {pages}' }) }), _jsx("button", { style: btn, disabled: page >= pages, onClick: () => setPage(page + 1), "aria-label": "Next", children: "\u203A" })] }));
24
+ }
25
+ const bar = {
26
+ display: 'flex',
27
+ alignItems: 'center',
28
+ justifyContent: 'center',
29
+ gap: 10,
30
+ padding: '6px 8px',
31
+ borderTop: '1px solid var(--oo-color-border, #2b2f37)',
32
+ };
33
+ const btn = {
34
+ appearance: 'none',
35
+ background: 'none',
36
+ border: '1px solid var(--oo-color-border, #2b2f37)',
37
+ borderRadius: 4,
38
+ color: 'var(--oo-color-text, #e6e8eb)',
39
+ cursor: 'pointer',
40
+ width: 24,
41
+ height: 24,
42
+ lineHeight: '20px',
43
+ };
@@ -0,0 +1,118 @@
1
+ .oo-tree {
2
+ display: flex;
3
+ flex-direction: column;
4
+ height: 100%;
5
+ min-height: 0;
6
+ outline: none;
7
+ user-select: none;
8
+ font-size: var(--oo-font-size-sm);
9
+ color: var(--oo-color-fg);
10
+ }
11
+ .oo-tree:focus-visible {
12
+ outline: 1px solid var(--oo-color-accent);
13
+ outline-offset: -1px;
14
+ }
15
+
16
+ .oo-tree__header {
17
+ flex: 0 0 auto;
18
+ padding: var(--oo-spacing-sm);
19
+ border-bottom: 1px solid var(--oo-color-border);
20
+ display: flex;
21
+ justify-content: space-between;
22
+ align-items: center;
23
+ gap: var(--oo-spacing-sm);
24
+ }
25
+ .oo-tree__title {
26
+ margin: 0;
27
+ font-size: var(--oo-font-size-xs);
28
+ font-weight: 700;
29
+ text-transform: uppercase;
30
+ letter-spacing: 0.06em;
31
+ color: var(--oo-color-muted);
32
+ }
33
+
34
+ .oo-tree__rows {
35
+ flex: 1 1 auto;
36
+ min-height: 0;
37
+ overflow: auto;
38
+ padding: 2px 0;
39
+ }
40
+
41
+ .oo-tree__row {
42
+ display: flex;
43
+ align-items: center;
44
+ gap: 4px;
45
+ height: 24px;
46
+ padding: 0 8px 0 6px;
47
+ cursor: pointer;
48
+ color: inherit;
49
+ position: relative;
50
+ }
51
+ .oo-tree__row:hover {
52
+ color: var(--oo-color-surface);
53
+ background: var(--oo-color-active);
54
+ }
55
+ .oo-tree__row[data-selected='true'] {
56
+ color: var(--oo-color-surface);
57
+ background: var(--oo-color-active);
58
+ box-shadow: inset 2px 0 0 var(--oo-color-accent);
59
+ }
60
+ /* Drop target under an active drag — dotted outline (no layout shift). */
61
+ .oo-tree__row[data-drag-over='true'] {
62
+ outline: 2px dotted var(--oo-color-accent);
63
+ outline-offset: -2px;
64
+ background: var(--oo-color-active);
65
+ }
66
+
67
+ .oo-tree__twisty {
68
+ width: 16px;
69
+ height: 16px;
70
+ flex: 0 0 auto;
71
+ display: inline-flex;
72
+ align-items: center;
73
+ justify-content: center;
74
+ border: none;
75
+ background: transparent;
76
+ cursor: pointer;
77
+ color: var(--oo-color-muted);
78
+ font-size: 10px;
79
+ line-height: 1;
80
+ padding: 0;
81
+ transition: transform 80ms ease-out;
82
+ transform: rotate(0deg);
83
+ }
84
+ .oo-tree__twisty[data-expanded='true'] {
85
+ transform: rotate(90deg);
86
+ }
87
+ .oo-tree__twisty--leaf {
88
+ pointer-events: none;
89
+ visibility: hidden;
90
+ }
91
+
92
+ .oo-tree__icon {
93
+ flex: 0 0 auto;
94
+ }
95
+
96
+ .oo-tree__label {
97
+ flex: 1 1 auto;
98
+ min-width: 0;
99
+ overflow: hidden;
100
+ text-overflow: ellipsis;
101
+ white-space: nowrap;
102
+ }
103
+
104
+ .oo-tree__trailing {
105
+ flex: 0 0 auto;
106
+ color: var(--oo-color-muted);
107
+ font-size: var(--oo-font-size-xs);
108
+ }
109
+
110
+ .oo-tree__empty {
111
+ flex: 1 1 auto;
112
+ display: flex;
113
+ align-items: center;
114
+ justify-content: center;
115
+ color: var(--oo-color-muted);
116
+ font-size: var(--oo-font-size-xs);
117
+ padding: var(--oo-spacing-md);
118
+ }
@@ -0,0 +1,45 @@
1
+ import { type ClipboardEvent as ReactClipboardEvent, type CSSProperties, type DragEvent as ReactDragEvent, type ReactNode } from 'react';
2
+ import type { BindingPath } from '../../types/component-graph.js';
3
+ import type { PickerAction } from '../../types/host.js';
4
+ import './Tree.css';
5
+ export interface TreeNode<T = unknown> {
6
+ key: string;
7
+ label: ReactNode;
8
+ icon?: string;
9
+ color?: string;
10
+ trailing?: ReactNode;
11
+ data?: T;
12
+ children?: TreeNode<T>[];
13
+ draggable?: boolean;
14
+ dropAccepting?: boolean;
15
+ }
16
+ export interface TreeProps<T = unknown> {
17
+ nodes: TreeNode<T>[];
18
+ title?: ReactNode;
19
+ toolbar?: ReactNode;
20
+ selectedKey?: string | null;
21
+ onSelect?: (node: TreeNode<T>) => void;
22
+ onActivate?: (node: TreeNode<T>) => void;
23
+ expanded?: Set<string>;
24
+ defaultExpanded?: Iterable<string>;
25
+ onExpandedChange?: (next: Set<string>) => void;
26
+ renderItem?: (node: TreeNode<T>, ctx: {
27
+ selected: boolean;
28
+ expanded: boolean;
29
+ depth: number;
30
+ }) => ReactNode;
31
+ contextMenuSlot?: string;
32
+ contextFor?: (node: TreeNode<T>) => Record<string, unknown>;
33
+ contextDataContext?: BindingPath;
34
+ contextExtraItems?: (node: TreeNode<T>) => PickerAction[];
35
+ onDragStart?: (e: ReactDragEvent<HTMLDivElement>, node: TreeNode<T>) => void;
36
+ onDragOver?: (e: ReactDragEvent<HTMLDivElement>, node: TreeNode<T>) => void;
37
+ onDragEnd?: (e: ReactDragEvent<HTMLDivElement>, node: TreeNode<T>) => void;
38
+ onDrop?: (e: ReactDragEvent<HTMLDivElement>, node: TreeNode<T>) => void;
39
+ onCopy?: (e: ReactClipboardEvent<HTMLDivElement>, node: TreeNode<T> | null) => void;
40
+ onPaste?: (e: ReactClipboardEvent<HTMLDivElement>, node: TreeNode<T> | null) => void;
41
+ emptyState?: ReactNode;
42
+ className?: string;
43
+ style?: CSSProperties;
44
+ }
45
+ export declare function Tree<T = unknown>({ nodes, title, toolbar, selectedKey, onSelect, onActivate, expanded: controlledExpanded, defaultExpanded, onExpandedChange, renderItem, contextMenuSlot, contextFor, contextDataContext, contextExtraItems, onDragStart, onDragOver, onDragEnd, onDrop, onCopy, onPaste, emptyState, className, style, }: TreeProps<T>): ReactNode;
@@ -0,0 +1,170 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useMemo, useRef, useState, } from 'react';
3
+ import { ContextMenu } from '../menu/ContextMenu.js';
4
+ import './Tree.css';
5
+ import { resolveColorVar } from '../../types/colors.js';
6
+ function flatten(nodes, expanded, depth = 0, parentKey = null, out = []) {
7
+ for (const n of nodes) {
8
+ const hasChildren = n.children !== undefined;
9
+ const isExpanded = hasChildren && expanded.has(n.key);
10
+ out.push({ node: n, depth, hasChildren, expanded: isExpanded, parentKey });
11
+ if (isExpanded && n.children)
12
+ flatten(n.children, expanded, depth + 1, n.key, out);
13
+ }
14
+ return out;
15
+ }
16
+ export function Tree({ nodes, title, toolbar, selectedKey, onSelect, onActivate, expanded: controlledExpanded, defaultExpanded, onExpandedChange, renderItem, contextMenuSlot, contextFor, contextDataContext, contextExtraItems, onDragStart, onDragOver, onDragEnd, onDrop, onCopy, onPaste, emptyState, className, style, }) {
17
+ // Expansion state — controlled vs uncontrolled.
18
+ const [internalExpanded, setInternalExpanded] = useState(() => new Set(defaultExpanded ?? []));
19
+ const expanded = controlledExpanded ?? internalExpanded;
20
+ const setExpanded = useCallback((next) => {
21
+ if (onExpandedChange)
22
+ onExpandedChange(next);
23
+ if (controlledExpanded === undefined)
24
+ setInternalExpanded(next);
25
+ }, [controlledExpanded, onExpandedChange]);
26
+ const flat = useMemo(() => flatten(nodes, expanded), [nodes, expanded]);
27
+ // Context-menu state per click.
28
+ const [menu, setMenu] = useState(null);
29
+ // Which drop-accepting row is currently under the drag (for the drop outline).
30
+ const [dragOverKey, setDragOverKey] = useState(null);
31
+ function handleRowDragOver(e, node) {
32
+ onDragOver?.(e, node);
33
+ if (node.dropAccepting)
34
+ setDragOverKey(node.key);
35
+ }
36
+ function handleRowDragLeave(e, node) {
37
+ // Drag events bubble through child elements; ignore leaves that stay inside the row.
38
+ if (e.currentTarget.contains(e.relatedTarget))
39
+ return;
40
+ setDragOverKey((k) => (k === node.key ? null : k));
41
+ }
42
+ function handleRowDrop(e, node) {
43
+ setDragOverKey(null);
44
+ onDrop?.(e, node);
45
+ }
46
+ // Scroll the selected row into view when it changes externally.
47
+ const rootRef = useRef(null);
48
+ useEffect(() => {
49
+ if (!selectedKey || !rootRef.current)
50
+ return;
51
+ const row = rootRef.current.querySelector(`[data-key="${cssEscape(selectedKey)}"]`);
52
+ if (row)
53
+ row.scrollIntoView({ block: 'nearest' });
54
+ }, [selectedKey]);
55
+ function toggleExpand(key) {
56
+ const next = new Set(expanded);
57
+ if (next.has(key))
58
+ next.delete(key);
59
+ else
60
+ next.add(key);
61
+ setExpanded(next);
62
+ }
63
+ // ----- Keyboard -----
64
+ const selectedIndex = selectedKey
65
+ ? flat.findIndex((r) => r.node.key === selectedKey)
66
+ : -1;
67
+ function handleKeyDown(e) {
68
+ if (flat.length === 0)
69
+ return;
70
+ const cur = selectedIndex >= 0 ? selectedIndex : 0;
71
+ const row = flat[cur];
72
+ switch (e.key) {
73
+ case 'ArrowDown': {
74
+ e.preventDefault();
75
+ const next = flat[Math.min(flat.length - 1, cur + 1)];
76
+ if (next)
77
+ onSelect?.(next.node);
78
+ return;
79
+ }
80
+ case 'ArrowUp': {
81
+ e.preventDefault();
82
+ const next = flat[Math.max(0, cur - 1)];
83
+ if (next)
84
+ onSelect?.(next.node);
85
+ return;
86
+ }
87
+ case 'ArrowRight': {
88
+ e.preventDefault();
89
+ if (!row)
90
+ return;
91
+ if (row.hasChildren && !row.expanded) {
92
+ toggleExpand(row.node.key);
93
+ }
94
+ else if (row.hasChildren && row.expanded) {
95
+ const child = flat[cur + 1];
96
+ if (child)
97
+ onSelect?.(child.node);
98
+ }
99
+ return;
100
+ }
101
+ case 'ArrowLeft': {
102
+ e.preventDefault();
103
+ if (!row)
104
+ return;
105
+ if (row.hasChildren && row.expanded) {
106
+ toggleExpand(row.node.key);
107
+ }
108
+ else if (row.parentKey) {
109
+ const parent = flat.find((r) => r.node.key === row.parentKey);
110
+ if (parent)
111
+ onSelect?.(parent.node);
112
+ }
113
+ return;
114
+ }
115
+ case 'Enter':
116
+ case ' ': {
117
+ e.preventDefault();
118
+ if (!row)
119
+ return;
120
+ if (row.hasChildren)
121
+ toggleExpand(row.node.key);
122
+ else
123
+ onActivate?.(row.node);
124
+ return;
125
+ }
126
+ }
127
+ }
128
+ // Right-click → ContextMenu (when contextMenuSlot is set).
129
+ function openContextMenu(e, node) {
130
+ if (!contextMenuSlot)
131
+ return;
132
+ e.preventDefault();
133
+ e.stopPropagation();
134
+ onSelect?.(node);
135
+ setMenu({ x: e.clientX, y: e.clientY, node });
136
+ }
137
+ // Clipboard surface — focus owner gets these.
138
+ function onTreeCopy(e) {
139
+ const node = selectedKey ? flat.find((r) => r.node.key === selectedKey)?.node ?? null : null;
140
+ onCopy?.(e, node);
141
+ }
142
+ function onTreePaste(e) {
143
+ const node = selectedKey ? flat.find((r) => r.node.key === selectedKey)?.node ?? null : null;
144
+ onPaste?.(e, node);
145
+ }
146
+ return (_jsxs("div", { ref: rootRef, role: "tree", tabIndex: 0, className: ['oo-tree', className].filter(Boolean).join(' '), style: style, onKeyDown: handleKeyDown, onCopy: onCopy ? onTreeCopy : undefined, onPaste: onPaste ? onTreePaste : undefined, onDragEnd: () => setDragOverKey(null), children: [title || toolbar ? (_jsxs("header", { className: "oo-tree__header", children: [title ? _jsx("h2", { className: "oo-tree__title", children: title }) : null, toolbar] })) : null, flat.length === 0 ? (_jsx("div", { className: "oo-tree__empty", children: emptyState ?? 'Empty' })) : (_jsx("div", { className: "oo-tree__rows", role: "presentation", children: flat.map((row) => {
147
+ const { node, depth, hasChildren, expanded: rowExpanded } = row;
148
+ const selected = node.key === selectedKey;
149
+ return (_jsxs("div", { role: "treeitem", "aria-level": depth + 1, "aria-expanded": hasChildren ? rowExpanded : undefined, "aria-selected": selected, "data-key": node.key, "data-selected": selected ? 'true' : undefined, "data-drag-over": node.key === dragOverKey ? 'true' : undefined, tabIndex: -1, draggable: node.draggable ?? false, className: `oo-tree__row ${node.draggable ? 'oo-draggable' : ''}`, style: { paddingLeft: depth * 14 + 6 }, onClick: () => onSelect?.(node), onDoubleClick: () => {
150
+ if (hasChildren)
151
+ toggleExpand(node.key);
152
+ else
153
+ onActivate?.(node);
154
+ }, onContextMenu: (e) => openContextMenu(e, node), onDragStart: onDragStart ? (e) => onDragStart(e, node) : undefined, onDragOver: onDragOver ? (e) => handleRowDragOver(e, node) : undefined, onDragLeave: onDragOver ? (e) => handleRowDragLeave(e, node) : undefined, onDragEnd: onDragEnd ? (e) => onDragEnd(e, node) : undefined, onDrop: onDrop ? (e) => handleRowDrop(e, node) : undefined, children: [hasChildren ? (_jsx("button", { type: "button", "aria-label": rowExpanded ? 'Collapse' : 'Expand', className: "oo-tree__twisty", "data-expanded": rowExpanded ? 'true' : undefined, onClick: (e) => {
155
+ e.stopPropagation();
156
+ toggleExpand(node.key);
157
+ }, children: "\u25B8" })) : (_jsx("span", { className: "oo-tree__twisty oo-tree__twisty--leaf" })), renderItem ? (renderItem(node, { selected, expanded: rowExpanded, depth })) : (_jsx(DefaultRowBody, { node: node }))] }, node.key));
158
+ }) })), menu && contextMenuSlot ? (_jsx(ContextMenu, { x: menu.x, y: menu.y, onClose: () => setMenu(null), spec: { query: { slot: contextMenuSlot }, extraItems: contextExtraItems ? contextExtraItems(menu.node) : undefined, footerHints: true }, context: contextFor ? contextFor(menu.node) : undefined, dataContext: contextDataContext })) : null] }));
159
+ }
160
+ function DefaultRowBody({ node }) {
161
+ const iconStyle = node.color
162
+ ? { ['--oo-color']: resolveColorVar(node.color) }
163
+ : undefined;
164
+ return (_jsxs(_Fragment, { children: [_jsx("span", { className: "oo-icon oo-tree__icon", style: iconStyle, children: node.icon ?? '·' }), _jsx("span", { className: "oo-tree__label", children: node.label }), node.trailing ? _jsx("span", { className: "oo-tree__trailing", children: node.trailing }) : null] }));
165
+ }
166
+ // Cheap CSS-selector escape so a node key with `"` or `]` doesn't break the
167
+ // querySelector used by scrollIntoView. Avoids a full polyfill.
168
+ function cssEscape(s) {
169
+ return s.replace(/(["\\\]])/g, '\\$1');
170
+ }
@@ -0,0 +1,2 @@
1
+ import type { ComponentDefinition } from '../../types/component-registry.js';
2
+ export declare const CATALOG_DATA_MAP: ComponentDefinition[];
@@ -0,0 +1,7 @@
1
+ // Catalog registration for data components (dynamic import — no eager load).
2
+ export const CATALOG_DATA_MAP = [
3
+ { component: 'List', category: 'inline', renderer: { kind: 'react', load: () => import('./List.js').then((m) => ({ default: m.List })) } },
4
+ { component: 'DataTable', category: 'inline', renderer: { kind: 'react', load: () => import('./DataTable.js').then((m) => ({ default: m.DataTable })) } },
5
+ { component: 'Pagination', category: 'inline', renderer: { kind: 'react', load: () => import('./Pagination.js').then((m) => ({ default: m.Pagination })) } },
6
+ { component: 'Filter', category: 'inline', renderer: { kind: 'react', load: () => import('./Filter.js').then((m) => ({ default: m.Filter })) } },
7
+ ];