@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,420 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState, useSyncExternalStore, } from 'react';
3
+ import { CampusContext, useCampus } from './context.js';
4
+ import { CampusNodus } from './CampusNodus.js';
5
+ import { CampusStratum } from './CampusStratum.js';
6
+ import { CampusVelum } from './CampusVelum.js';
7
+ const DEFAULT_MIN_SCALE = 0.1;
8
+ const DEFAULT_MAX_SCALE = 4;
9
+ const DEFAULT_ZOOM_STEP = 1.1;
10
+ const PAN_DRAG_THRESHOLD_SQ = 9;
11
+ const FIT_PADDING = 0.95;
12
+ const GRID_STEP_WORLD = 40;
13
+ // Persist the live viewport this long after the last pan/zoom event. Keeps
14
+ // app state / urls in sync without a store write per frame.
15
+ const VIEWPORT_PERSIST_MS = 140;
16
+ function clamp(v, min, max) {
17
+ return Math.max(min, Math.min(max, v));
18
+ }
19
+ function transformOf(v) {
20
+ return `translate(${v.panX}px, ${v.panY}px) scale(${v.scale})`;
21
+ }
22
+ // Constrain a viewport to the world bounds. When the world is wider than
23
+ // the container at the current scale the pan is clamped so the view sits
24
+ // fully inside the world; when the world is narrower the world is centered
25
+ // (pan = container_dim / 2 places world origin at the view center).
26
+ function clampViewport(v, container, maxDepth, minScale, maxScale) {
27
+ const scale = clamp(v.scale, minScale, maxScale);
28
+ if (!isFinite(maxDepth))
29
+ return { ...v, scale };
30
+ let { panX, panY } = v;
31
+ const worldHalfW = maxDepth * scale;
32
+ const worldHalfH = maxDepth * scale;
33
+ if (2 * worldHalfW >= container.w) {
34
+ panX = clamp(panX, container.w - worldHalfW, worldHalfW);
35
+ }
36
+ else {
37
+ panX = container.w / 2;
38
+ }
39
+ if (2 * worldHalfH >= container.h) {
40
+ panY = clamp(panY, container.h - worldHalfH, worldHalfH);
41
+ }
42
+ else {
43
+ panY = container.h / 2;
44
+ }
45
+ return { scale, panX, panY };
46
+ }
47
+ export function CampusView({ viewport, onViewportChange, maxDepth = Infinity, minScale = DEFAULT_MIN_SCALE, maxScale = DEFAULT_MAX_SCALE, zoomStep = DEFAULT_ZOOM_STEP, showGrid = true, onBackgroundClick, onBackgroundContextMenu, nodes, nodeTypes, nodeLayers, defaultLayer, onNodeCommit, onNodeSelect, onNodeContextMenu, className, style, children, ref, }) {
48
+ const containerRef = useRef(null);
49
+ const wrapperRef = useRef(null);
50
+ const zoomStepRef = useRef(zoomStep);
51
+ const minScaleRef = useRef(minScale);
52
+ const maxScaleRef = useRef(maxScale);
53
+ const commitViewportThrottledRef = useRef(commitViewportThrottled);
54
+ // Container size is shared via context so CampusMappa doesn't have to
55
+ // remeasure independently. ResizeObserver keeps it fresh — important for
56
+ // fit-to-view math after the surrounding shell resizes.
57
+ const [container, setContainer] = useState({ w: 0, h: 0 });
58
+ useEffect(() => {
59
+ const el = containerRef.current;
60
+ if (!el)
61
+ return;
62
+ function measure() {
63
+ const r = el.getBoundingClientRect();
64
+ setContainer({ w: r.width, h: r.height });
65
+ }
66
+ measure();
67
+ const ro = new ResizeObserver(measure);
68
+ ro.observe(el);
69
+ return () => ro.disconnect();
70
+ }, []);
71
+ // ----- Live viewport store -----
72
+ // The single source of truth for the live viewport. Updated imperatively
73
+ // (no setState) so a pan never re-renders the node subtree. Initialized
74
+ // from the prop once; external prop changes are reconciled in an effect.
75
+ const viewportRef = useRef(viewport);
76
+ const listenersRef = useRef(new Set());
77
+ const subscribeViewport = useCallback((listener) => {
78
+ listenersRef.current.add(listener);
79
+ return () => {
80
+ listenersRef.current.delete(listener);
81
+ };
82
+ }, []);
83
+ function notify() {
84
+ listenersRef.current.forEach((l) => l());
85
+ }
86
+ function applyWorldTransform(v) {
87
+ const el = wrapperRef.current;
88
+ if (el)
89
+ el.style.transform = transformOf(v);
90
+ }
91
+ // Debounced persistence. onViewportChange may change identity each render,
92
+ // so read it through a ref.
93
+ const onViewportChangeRef = useRef(onViewportChange);
94
+ onViewportChangeRef.current = onViewportChange;
95
+ const persistTimerRef = useRef(null);
96
+ function schedulePersist() {
97
+ if (persistTimerRef.current !== null)
98
+ window.clearTimeout(persistTimerRef.current);
99
+ persistTimerRef.current = window.setTimeout(() => {
100
+ persistTimerRef.current = null;
101
+ onViewportChangeRef.current(viewportRef.current);
102
+ }, VIEWPORT_PERSIST_MS);
103
+ }
104
+ useEffect(() => () => {
105
+ if (persistTimerRef.current !== null)
106
+ window.clearTimeout(persistTimerRef.current);
107
+ }, []);
108
+ // External viewport changes (programmatic set from outside, persisted-state
109
+ // reload). Ignore echoes of our own debounced writes (prop === live value),
110
+ // otherwise re-seat the live viewport and redraw.
111
+ useEffect(() => {
112
+ const v = viewportRef.current;
113
+ if (viewport.scale === v.scale && viewport.panX === v.panX && viewport.panY === v.panY) {
114
+ return;
115
+ }
116
+ viewportRef.current = viewport;
117
+ applyWorldTransform(viewport);
118
+ notify();
119
+ }, [viewport]);
120
+ // rAF-coalesced viewport commit. A single wheel tick can fire dozens of
121
+ // events; without coalescing each one would mutate the DOM separately.
122
+ const pendingRef = useRef(null);
123
+ const rafRef = useRef(null);
124
+ function commitViewport(v) {
125
+ const clamped = clampViewport(v, container, maxDepth, minScale, maxScale);
126
+ viewportRef.current = clamped;
127
+ applyWorldTransform(clamped); // imperative: no React re-render
128
+ notify(); // grid + minimap redraw (only)
129
+ schedulePersist(); // app-state write, debounced on settle
130
+ }
131
+ function commitViewportThrottled(v) {
132
+ pendingRef.current = v;
133
+ if (rafRef.current === null) {
134
+ rafRef.current = requestAnimationFrame(() => {
135
+ rafRef.current = null;
136
+ const next = pendingRef.current;
137
+ pendingRef.current = null;
138
+ if (next)
139
+ commitViewport(next);
140
+ });
141
+ }
142
+ }
143
+ // ----- Wheel: ctrl/meta + wheel zooms around cursor, plain wheel pans.
144
+ // Native listener (not React's onWheel) so we can preventDefault — React's
145
+ // synthetic wheel is passive and won't suppress the page scroll.
146
+ useEffect(() => {
147
+ zoomStepRef.current = zoomStep;
148
+ minScaleRef.current = minScale;
149
+ maxScaleRef.current = maxScale;
150
+ commitViewportThrottledRef.current = commitViewportThrottled;
151
+ // No dependency array on purpose. This syncs the latest values into refs
152
+ // that the native wheel listener reads without re-subscribing, so it must
153
+ // run on every render. `commitViewportThrottled` is redeclared each render,
154
+ // so the previous array was already "every render" spelled out the long way.
155
+ });
156
+ useEffect(() => {
157
+ const el = containerRef.current;
158
+ if (!el)
159
+ return;
160
+ function onWheel(e) {
161
+ if (!el)
162
+ return;
163
+ const rect = el.getBoundingClientRect();
164
+ const v = viewportRef.current;
165
+ if (e.ctrlKey || e.metaKey) {
166
+ e.preventDefault();
167
+ const mouseX = e.clientX - rect.left;
168
+ const mouseY = e.clientY - rect.top;
169
+ const factor = e.deltaY < 0
170
+ ? zoomStepRef.current
171
+ : 1 / zoomStepRef.current;
172
+ const newScale = clamp(v.scale * factor, minScaleRef.current, maxScaleRef.current);
173
+ const worldX = (mouseX - v.panX) / v.scale;
174
+ const worldY = (mouseY - v.panY) / v.scale;
175
+ commitViewportThrottledRef.current({
176
+ scale: newScale,
177
+ panX: mouseX - worldX * newScale,
178
+ panY: mouseY - worldY * newScale,
179
+ });
180
+ }
181
+ else {
182
+ e.preventDefault();
183
+ const dx = -(e.shiftKey ? e.deltaY : e.deltaX);
184
+ const dy = -(e.shiftKey ? 0 : e.deltaY);
185
+ commitViewportThrottledRef.current({
186
+ scale: v.scale,
187
+ panX: v.panX + dx,
188
+ panY: v.panY + dy,
189
+ });
190
+ }
191
+ }
192
+ el.addEventListener('wheel', onWheel, { passive: false });
193
+ return () => el.removeEventListener('wheel', onWheel);
194
+ }, []);
195
+ // ----- Background pan drag -----
196
+ const panDragRef = useRef(null);
197
+ function isBackgroundTarget(target) {
198
+ return target === containerRef.current || target === wrapperRef.current;
199
+ }
200
+ function onContainerPointerDown(e) {
201
+ if (!isBackgroundTarget(e.target))
202
+ return;
203
+ e.currentTarget.setPointerCapture(e.pointerId);
204
+ const v = viewportRef.current;
205
+ panDragRef.current = {
206
+ startX: e.clientX,
207
+ startY: e.clientY,
208
+ startPanX: v.panX,
209
+ startPanY: v.panY,
210
+ moved: false,
211
+ };
212
+ }
213
+ function onContainerPointerMove(e) {
214
+ const p = panDragRef.current;
215
+ if (!p)
216
+ return;
217
+ const dx = e.clientX - p.startX;
218
+ const dy = e.clientY - p.startY;
219
+ if (!p.moved && dx * dx + dy * dy < PAN_DRAG_THRESHOLD_SQ)
220
+ return;
221
+ if (!p.moved && containerRef.current) {
222
+ // Cursor is set imperatively: pan doesn't re-render so a style-prop
223
+ // wouldn't update.
224
+ containerRef.current.style.cursor = 'grabbing';
225
+ }
226
+ p.moved = true;
227
+ commitViewportThrottled({
228
+ scale: viewportRef.current.scale,
229
+ panX: p.startPanX + dx,
230
+ panY: p.startPanY + dy,
231
+ });
232
+ }
233
+ function onContainerPointerUp(e) {
234
+ const p = panDragRef.current;
235
+ if (!p)
236
+ return;
237
+ e.currentTarget.releasePointerCapture(e.pointerId);
238
+ panDragRef.current = null;
239
+ if (containerRef.current)
240
+ containerRef.current.style.cursor = '';
241
+ if (!p.moved)
242
+ onBackgroundClick?.();
243
+ }
244
+ // ----- Background right-click -----
245
+ function onContainerContextMenu(e) {
246
+ if (!isBackgroundTarget(e.target))
247
+ return;
248
+ onBackgroundContextMenu?.(e);
249
+ }
250
+ // ----- Imperative controller (consumed via ref) -----
251
+ useImperativeHandle(ref, () => ({
252
+ fitToView(bounds) {
253
+ const c = container;
254
+ if (c.w === 0 || c.h === 0)
255
+ return;
256
+ // Default fit target: the full world box. Consumers usually pass
257
+ // the union of their node bounds (so empty space at the edges is
258
+ // ignored even when the world itself is bounded).
259
+ const target = bounds ?? (isFinite(maxDepth)
260
+ ? { x: -maxDepth, y: -maxDepth, w: 2 * maxDepth, h: 2 * maxDepth }
261
+ : { x: 0, y: 0, w: 0, h: 0 });
262
+ if (target.w <= 0 || target.h <= 0)
263
+ return;
264
+ const scale = clamp(Math.min(c.w / target.w, c.h / target.h) * FIT_PADDING, minScale, maxScale);
265
+ const worldCx = target.x + target.w / 2;
266
+ const worldCy = target.y + target.h / 2;
267
+ commitViewport({
268
+ scale,
269
+ panX: c.w / 2 - worldCx * scale,
270
+ panY: c.h / 2 - worldCy * scale,
271
+ });
272
+ },
273
+ centerOn(worldX, worldY) {
274
+ const c = container;
275
+ const v = viewportRef.current;
276
+ if (c.w === 0 || c.h === 0)
277
+ return;
278
+ commitViewport({
279
+ scale: v.scale,
280
+ panX: c.w / 2 - worldX * v.scale,
281
+ panY: c.h / 2 - worldY * v.scale,
282
+ });
283
+ },
284
+ resetViewport() {
285
+ commitViewport({ scale: 1, panX: 0, panY: 0 });
286
+ },
287
+ zoomBy(factor) {
288
+ zoomAroundCenter(viewportRef.current.scale * factor);
289
+ },
290
+ zoomToScale(scale) {
291
+ zoomAroundCenter(scale);
292
+ },
293
+ }),
294
+ // The handle captures `container` and `maxDepth` so it must re-build
295
+ // when those change; everything else flows through refs.
296
+ //
297
+ // `commitViewport` and `zoomAroundCenter` are intentionally absent. They
298
+ // read only container/maxDepth/minScale/maxScale plus refs, and all four
299
+ // are listed here — so the captured closures are never stale. Listing the
300
+ // functions themselves would rebuild the handle on every render, since
301
+ // they are redeclared each time, defeating the memo and forcing every
302
+ // consumer holding the ref to re-run.
303
+ // eslint-disable-next-line react-hooks/exhaustive-deps
304
+ [container, maxDepth, minScale, maxScale]);
305
+ function zoomAroundCenter(rawScale) {
306
+ const c = container;
307
+ if (c.w === 0 || c.h === 0)
308
+ return;
309
+ const v = viewportRef.current;
310
+ const next = clamp(rawScale, minScale, maxScale);
311
+ if (next === v.scale)
312
+ return;
313
+ const cx = c.w / 2;
314
+ const cy = c.h / 2;
315
+ const worldX = (cx - v.panX) / v.scale;
316
+ const worldY = (cy - v.panY) / v.scale;
317
+ commitViewport({
318
+ scale: next,
319
+ panX: cx - worldX * next,
320
+ panY: cy - worldY * next,
321
+ });
322
+ }
323
+ // Bucket nodes into ordered strata. Configured layers come first sorted by
324
+ // `index`; any layer referenced by a node but not configured (including the
325
+ // implicit default) is appended after them. Each stratum carries its node
326
+ // list so the render is a flat strata→nodes walk.
327
+ const strata = useMemo(() => {
328
+ const configured = Object.entries(nodeLayers ?? {})
329
+ .map(([name, config]) => ({ name, config }))
330
+ .sort((a, b) => a.config.index - b.config.index);
331
+ const fallback = defaultLayer ?? configured[0]?.name ?? 'default';
332
+ const buckets = new Map();
333
+ for (const node of nodes ?? []) {
334
+ const layer = node.layer && nodeLayers?.[node.layer] ? node.layer : fallback;
335
+ const bucket = buckets.get(layer);
336
+ if (bucket)
337
+ bucket.push(node);
338
+ else
339
+ buckets.set(layer, [node]);
340
+ }
341
+ const result = [];
342
+ const seen = new Set();
343
+ for (const { name, config } of configured) {
344
+ result.push({ name, config, nodes: buckets.get(name) ?? [] });
345
+ seen.add(name);
346
+ }
347
+ for (const [name, layerNodes] of buckets) {
348
+ if (seen.has(name))
349
+ continue;
350
+ result.push({ name, config: { index: result.length }, nodes: layerNodes });
351
+ }
352
+ return result;
353
+ }, [nodes, nodeLayers, defaultLayer]);
354
+ // Context is intentionally free of the live viewport so node re-renders
355
+ // don't track pan/zoom. It changes only on container/maxDepth.
356
+ const ctxValue = useMemo(() => ({ viewportRef, subscribeViewport, container, maxDepth }), [subscribeViewport, container, maxDepth]);
357
+ return (_jsx(CampusContext.Provider, { value: ctxValue, children: _jsxs("div", { ref: containerRef, className: ['oo-campus', className].filter(Boolean).join(' '), onPointerDown: onContainerPointerDown, onPointerMove: onContainerPointerMove, onPointerUp: onContainerPointerUp, onContextMenu: onContainerContextMenu, style: {
358
+ position: 'relative',
359
+ width: '100%',
360
+ height: '100%',
361
+ overflow: 'hidden',
362
+ background: 'var(--oo-color-surface)',
363
+ touchAction: 'none',
364
+ cursor: 'default',
365
+ ...style,
366
+ }, children: [showGrid ? _jsx(CampusGrid, {}) : null, _jsx("div", { ref: wrapperRef, className: "oo-campus-world", style: {
367
+ position: 'absolute',
368
+ left: 0,
369
+ top: 0,
370
+ width: 0,
371
+ height: 0,
372
+ // Initial transform; live updates are imperative (applyWorldTransform).
373
+ transform: transformOf(viewportRef.current),
374
+ transformOrigin: '0 0',
375
+ }, children: strata.map((stratum) => (_jsx(CampusStratum, { zoom: stratum.config.zoom, pan: stratum.config.pan, zIndex: stratum.config.index, children: stratum.nodes.map((node) => {
376
+ const Renderer = nodeTypes?.[node.type];
377
+ if (!Renderer)
378
+ return null;
379
+ return (_jsx(CampusNodusFrame, { node: node, onCommit: onNodeCommit, onSelect: onNodeSelect, onContextMenu: onNodeContextMenu, children: _jsx(Renderer, { id: node.id, selected: Boolean(node.selected), data: node.data }) }, node.id));
380
+ }) }, stratum.name))) }), _jsx(CampusVelum, { children: children })] }) }));
381
+ }
382
+ function CampusNodusFrame({ node, onCommit, onSelect, onContextMenu, children, }) {
383
+ return (_jsx(CampusNodus, { bounds: node.bounds, selected: node.selected, resizable: node.resizable, movable: node.movable, onCommit: (next) => onCommit?.(node.id, next), onPointerDownCapture: () => {
384
+ if (!node.selected)
385
+ onSelect?.(node.id);
386
+ }, onContextMenu: (e) => {
387
+ e.preventDefault();
388
+ e.stopPropagation();
389
+ onSelect?.(node.id);
390
+ onContextMenu?.(node.id, e);
391
+ }, children: children }));
392
+ }
393
+ // Faint world-space grid background. Two repeating linear gradients (h + v),
394
+ // pinned to the world origin via background-position so the lines stay on
395
+ // integer world coords as the user pans/zooms. Opacity fades at very low
396
+ // zooms (cells smaller than ~6px) and very high zooms (cells filling the
397
+ // viewport) to avoid visual noise.
398
+ //
399
+ // Subscribes to the viewport store directly so it redraws on pan/zoom without
400
+ // CampusView (and therefore the node subtree) re-rendering.
401
+ function CampusGrid() {
402
+ const { viewportRef, subscribeViewport } = useCampus();
403
+ const { panX, panY, scale } = useSyncExternalStore(subscribeViewport, () => viewportRef.current);
404
+ const step = GRID_STEP_WORLD * scale;
405
+ const opacity = step < 6 ? 0 : step > 200 ? 0.04 : Math.min(0.12, step / 200);
406
+ if (opacity <= 0)
407
+ return null;
408
+ const offX = ((panX % step) + step) % step;
409
+ const offY = ((panY % step) + step) % step;
410
+ const stroke = `rgba(128, 128, 128, ${opacity})`;
411
+ return (_jsx("div", { className: "oo-campus-grid", "aria-hidden": true, style: {
412
+ position: 'absolute',
413
+ inset: 0,
414
+ pointerEvents: 'none',
415
+ backgroundImage: `linear-gradient(to right, ${stroke} 1px, transparent 1px),` +
416
+ `linear-gradient(to bottom, ${stroke} 1px, transparent 1px)`,
417
+ backgroundSize: `${step}px ${step}px, ${step}px ${step}px`,
418
+ backgroundPosition: `${offX}px ${offY}px, ${offX}px ${offY}px`,
419
+ } }));
420
+ }
@@ -0,0 +1,13 @@
1
+ import type { MutableRefObject } from 'react';
2
+ import type { CampusViewport } from './types.js';
3
+ export interface CampusContextValue {
4
+ viewportRef: MutableRefObject<CampusViewport>;
5
+ subscribeViewport(listener: () => void): () => void;
6
+ container: {
7
+ w: number;
8
+ h: number;
9
+ };
10
+ maxDepth: number;
11
+ }
12
+ export declare const CampusContext: import("react").Context<CampusContextValue | null>;
13
+ export declare function useCampus(): CampusContextValue;
@@ -0,0 +1,12 @@
1
+ import { createContext, useContext } from 'react';
2
+ export const CampusContext = createContext(null);
3
+ // Throws if used outside <CampusView>. Components that absolutely depend on
4
+ // CampusContext (CampusNodus, CampusMappa) should call this so misuse fails
5
+ // loud at mount instead of silently picking up defaults.
6
+ export function useCampus() {
7
+ const ctx = useContext(CampusContext);
8
+ if (!ctx) {
9
+ throw new Error('useCampus() must be used inside <CampusView>');
10
+ }
11
+ return ctx;
12
+ }
@@ -0,0 +1,14 @@
1
+ export { CampusView } from './CampusView.js';
2
+ export type { CampusViewProps, CampusNodeComponent, CampusNodeTypes, } from './CampusView.js';
3
+ export { CampusNodus } from './CampusNodus.js';
4
+ export type { CampusNodusProps, DragMode, ResizeMode, } from './CampusNodus.js';
5
+ export { CampusStratum } from './CampusStratum.js';
6
+ export type { CampusStratumProps } from './CampusStratum.js';
7
+ export { CampusVelum } from './CampusVelum.js';
8
+ export type { CampusVelumProps } from './CampusVelum.js';
9
+ export { CampusMappa } from './CampusMappa.js';
10
+ export type { CampusMappaProps } from './CampusMappa.js';
11
+ export { useCampus } from './context.js';
12
+ export type { CampusContextValue } from './context.js';
13
+ export { useStratumZoom } from './stratum-context.js';
14
+ export type { CampusBounds, CampusViewport, CampusController, CampusMappaNode, CampusNode, CampusNodeRenderProps, CampusLayerConfig, } from './types.js';
@@ -0,0 +1,11 @@
1
+ // Campus — generic pan/zoom canvas primitives. Originally extracted from
2
+ // SpatialLayout; reusable for flowchart editors, free-form whiteboards,
3
+ // node-graph views, etc. SpatialLayout is now a thin mount-aware adapter
4
+ // over these.
5
+ export { CampusView } from './CampusView.js';
6
+ export { CampusNodus } from './CampusNodus.js';
7
+ export { CampusStratum } from './CampusStratum.js';
8
+ export { CampusVelum } from './CampusVelum.js';
9
+ export { CampusMappa } from './CampusMappa.js';
10
+ export { useCampus } from './context.js';
11
+ export { useStratumZoom } from './stratum-context.js';
@@ -0,0 +1,2 @@
1
+ export declare const StratumContext: import("react").Context<number>;
2
+ export declare function useStratumZoom(): number;
@@ -0,0 +1,10 @@
1
+ import { createContext, useContext } from 'react';
2
+ // Per-stratum effective zoom, published by CampusStratum and read by
3
+ // CampusNodus. A node converts pointer-pixel drag deltas to world pixels by
4
+ // dividing by (viewport.scale × stratumZoom); without the stratum factor a
5
+ // node inside a statically-scaled layer would drift under the cursor.
6
+ // Default 1 means "no extra layer scaling" (the common single-layer case).
7
+ export const StratumContext = createContext(1);
8
+ export function useStratumZoom() {
9
+ return useContext(StratumContext);
10
+ }
@@ -0,0 +1,47 @@
1
+ export interface CampusBounds {
2
+ x: number;
3
+ y: number;
4
+ w: number;
5
+ h: number;
6
+ }
7
+ export interface CampusViewport {
8
+ scale: number;
9
+ panX: number;
10
+ panY: number;
11
+ }
12
+ export interface CampusController {
13
+ fitToView(bounds?: CampusBounds): void;
14
+ centerOn(worldX: number, worldY: number): void;
15
+ resetViewport(): void;
16
+ zoomBy(factor: number): void;
17
+ zoomToScale(scale: number): void;
18
+ }
19
+ export interface CampusMappaNode {
20
+ id: string;
21
+ bounds: CampusBounds;
22
+ color?: string;
23
+ selected?: boolean;
24
+ }
25
+ export interface CampusNode {
26
+ id: string;
27
+ type: string;
28
+ bounds: CampusBounds;
29
+ layer?: string;
30
+ selected?: boolean;
31
+ resizable?: boolean;
32
+ movable?: boolean;
33
+ data?: unknown;
34
+ }
35
+ export interface CampusLayerConfig {
36
+ index: number;
37
+ zoom?: number;
38
+ pan?: {
39
+ x: number;
40
+ y: number;
41
+ };
42
+ }
43
+ export interface CampusNodeRenderProps {
44
+ id: string;
45
+ selected: boolean;
46
+ data: unknown;
47
+ }
@@ -0,0 +1,4 @@
1
+ // Public surface for the Campus primitives (CampusView/CampusNodus/
2
+ // CampusMappa). Kept in its own file so consumers can `import type` without
3
+ // pulling in the React components.
4
+ export {};
@@ -0,0 +1,53 @@
1
+ .oo-barchart {
2
+ display: flex;
3
+ flex-direction: column;
4
+ gap: 4px;
5
+ width: 100%;
6
+ }
7
+ .oo-barchart__track {
8
+ display: flex;
9
+ align-items: flex-end;
10
+ gap: 2px;
11
+ width: 100%;
12
+ }
13
+ .oo-barchart__bar {
14
+ flex: 1;
15
+ min-width: 2px;
16
+ border-radius: 2px 2px 0 0;
17
+ }
18
+ .oo-barchart__bar--stacked {
19
+ display: flex;
20
+ flex-direction: column-reverse;
21
+ overflow: hidden;
22
+ }
23
+ .oo-barchart__bar--grouped {
24
+ display: flex;
25
+ align-items: flex-end;
26
+ gap: 1px;
27
+ height: 100%;
28
+ }
29
+ .oo-barchart__bar--grouped .oo-barchart__seg {
30
+ flex: 1;
31
+ border-radius: 2px 2px 0 0;
32
+ }
33
+ .oo-barchart__seg {
34
+ width: 100%;
35
+ }
36
+ .oo-barchart__labels {
37
+ display: flex;
38
+ gap: 2px;
39
+ }
40
+ .oo-barchart__label {
41
+ flex: 1;
42
+ font-size: var(--oo-font-size-xs);
43
+ color: var(--oo-color-muted);
44
+ text-align: center;
45
+ overflow: hidden;
46
+ text-overflow: ellipsis;
47
+ white-space: nowrap;
48
+ }
49
+ .oo-barchart--empty {
50
+ font-size: var(--oo-font-size-xs);
51
+ color: var(--oo-color-muted);
52
+ font-style: italic;
53
+ }
@@ -0,0 +1,24 @@
1
+ import type { CSSProperties } from 'react';
2
+ import './BarChart.css';
3
+ export interface BarChartSegment {
4
+ value: number;
5
+ color: string;
6
+ label?: string;
7
+ }
8
+ export interface BarChartBar {
9
+ key: string;
10
+ value?: number;
11
+ segments?: BarChartSegment[];
12
+ title?: string;
13
+ label?: string;
14
+ }
15
+ export interface BarChartProps {
16
+ bars: BarChartBar[];
17
+ height?: number;
18
+ mode?: 'stacked' | 'grouped';
19
+ showLabels?: boolean;
20
+ emptyLabel?: string;
21
+ color?: string;
22
+ style?: CSSProperties;
23
+ }
24
+ export declare function BarChart({ bars, height, mode, showLabels, emptyLabel, color, style, }: BarChartProps): import("react").JSX.Element;
@@ -0,0 +1,32 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import './BarChart.css';
3
+ const DEFAULT_COLOR = 'var(--oo-color-accent)';
4
+ function segmentsOf(bar, color) {
5
+ if (bar.segments && bar.segments.length > 0)
6
+ return bar.segments;
7
+ return [{ value: bar.value ?? 0, color }];
8
+ }
9
+ function totalOf(segs) {
10
+ return segs.reduce((sum, s) => sum + s.value, 0);
11
+ }
12
+ export function BarChart({ bars, height = 64, mode = 'stacked', showLabels, emptyLabel, color = DEFAULT_COLOR, style, }) {
13
+ // Bound props can resolve to undefined before their store path is seeded.
14
+ bars = bars ?? [];
15
+ if (bars.length === 0) {
16
+ return (_jsx("div", { className: "oo-barchart oo-barchart--empty", style: style, children: emptyLabel ?? 'No data' }));
17
+ }
18
+ // Scale: grouped compares individual segments; stacked compares bar totals.
19
+ const max = Math.max(1, ...bars.map((b) => {
20
+ const segs = segmentsOf(b, color);
21
+ return mode === 'grouped' ? Math.max(0, ...segs.map((s) => s.value)) : totalOf(segs);
22
+ }));
23
+ return (_jsxs("div", { className: "oo-barchart", style: style, children: [_jsx("div", { className: "oo-barchart__track", style: { height }, children: bars.map((bar) => {
24
+ const segs = segmentsOf(bar, color);
25
+ const total = totalOf(segs);
26
+ const title = bar.title ?? `${bar.label ?? bar.key}: ${total}`;
27
+ if (mode === 'grouped') {
28
+ return (_jsx("div", { className: "oo-barchart__bar oo-barchart__bar--grouped", title: title, children: segs.map((s, i) => (_jsx("div", { className: "oo-barchart__seg", title: s.label, style: { height: `${(s.value / max) * 100}%`, background: s.color, opacity: s.value === 0 ? 0.25 : 1 } }, i))) }, bar.key));
29
+ }
30
+ return (_jsx("div", { className: "oo-barchart__bar oo-barchart__bar--stacked", title: title, style: { height: `${(total / max) * 100}%`, opacity: total === 0 ? 0.25 : 1 }, children: segs.map((s, i) => (_jsx("div", { className: "oo-barchart__seg", title: s.label, style: { height: total > 0 ? `${(s.value / total) * 100}%` : '0%', background: s.color } }, i))) }, bar.key));
31
+ }) }), showLabels ? (_jsx("div", { className: "oo-barchart__labels", children: bars.map((bar) => (_jsx("div", { className: "oo-barchart__label", children: bar.label ?? bar.key }, bar.key))) })) : null] }));
32
+ }
@@ -0,0 +1,15 @@
1
+ .oo-donut {
2
+ position: relative;
3
+ display: inline-flex;
4
+ flex: none;
5
+ }
6
+ .oo-donut__center {
7
+ position: absolute;
8
+ inset: 0;
9
+ display: flex;
10
+ align-items: center;
11
+ justify-content: center;
12
+ font-size: var(--oo-font-size-sm);
13
+ font-weight: 600;
14
+ color: var(--oo-color-text);
15
+ }