@sectile/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (299) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +16 -0
  3. package/dist/accordion.d.ts +43 -0
  4. package/dist/accordion.d.ts.map +1 -0
  5. package/dist/accordion.js +83 -0
  6. package/dist/accordion.js.map +1 -0
  7. package/dist/alert-dialog.d.ts +18 -0
  8. package/dist/alert-dialog.d.ts.map +1 -0
  9. package/dist/alert-dialog.js +9 -0
  10. package/dist/alert-dialog.js.map +1 -0
  11. package/dist/calendar.d.ts +2 -0
  12. package/dist/calendar.d.ts.map +1 -0
  13. package/dist/calendar.js +2 -0
  14. package/dist/calendar.js.map +1 -0
  15. package/dist/carousel.d.ts +40 -0
  16. package/dist/carousel.d.ts.map +1 -0
  17. package/dist/carousel.js +51 -0
  18. package/dist/carousel.js.map +1 -0
  19. package/dist/checkbox-group.d.ts +12 -0
  20. package/dist/checkbox-group.d.ts.map +1 -0
  21. package/dist/checkbox-group.js +12 -0
  22. package/dist/checkbox-group.js.map +1 -0
  23. package/dist/checkbox.d.ts +2 -0
  24. package/dist/checkbox.d.ts.map +1 -0
  25. package/dist/checkbox.js +2 -0
  26. package/dist/checkbox.js.map +1 -0
  27. package/dist/combobox.d.ts +16 -0
  28. package/dist/combobox.d.ts.map +1 -0
  29. package/dist/combobox.js +42 -0
  30. package/dist/combobox.js.map +1 -0
  31. package/dist/date-field.d.ts +58 -0
  32. package/dist/date-field.d.ts.map +1 -0
  33. package/dist/date-field.js +233 -0
  34. package/dist/date-field.js.map +1 -0
  35. package/dist/date-picker.d.ts +53 -0
  36. package/dist/date-picker.d.ts.map +1 -0
  37. package/dist/date-picker.js +157 -0
  38. package/dist/date-picker.js.map +1 -0
  39. package/dist/date-range-picker.d.ts +28 -0
  40. package/dist/date-range-picker.d.ts.map +1 -0
  41. package/dist/date-range-picker.js +85 -0
  42. package/dist/date-range-picker.js.map +1 -0
  43. package/dist/date-time-field.d.ts +53 -0
  44. package/dist/date-time-field.d.ts.map +1 -0
  45. package/dist/date-time-field.js +253 -0
  46. package/dist/date-time-field.js.map +1 -0
  47. package/dist/date-time-picker.d.ts +54 -0
  48. package/dist/date-time-picker.d.ts.map +1 -0
  49. package/dist/date-time-picker.js +151 -0
  50. package/dist/date-time-picker.js.map +1 -0
  51. package/dist/date-time-range-picker.d.ts +67 -0
  52. package/dist/date-time-range-picker.d.ts.map +1 -0
  53. package/dist/date-time-range-picker.js +226 -0
  54. package/dist/date-time-range-picker.js.map +1 -0
  55. package/dist/dialog.d.ts +16 -0
  56. package/dist/dialog.d.ts.map +1 -0
  57. package/dist/dialog.js +5 -0
  58. package/dist/dialog.js.map +1 -0
  59. package/dist/disclosure.d.ts +2 -0
  60. package/dist/disclosure.d.ts.map +1 -0
  61. package/dist/disclosure.js +2 -0
  62. package/dist/disclosure.js.map +1 -0
  63. package/dist/feed.d.ts +29 -0
  64. package/dist/feed.d.ts.map +1 -0
  65. package/dist/feed.js +26 -0
  66. package/dist/feed.js.map +1 -0
  67. package/dist/index.d.ts +17 -0
  68. package/dist/index.d.ts.map +1 -0
  69. package/dist/index.js +2 -0
  70. package/dist/index.js.map +1 -0
  71. package/dist/interaction.d.ts +14 -0
  72. package/dist/interaction.d.ts.map +1 -0
  73. package/dist/interaction.js +38 -0
  74. package/dist/interaction.js.map +1 -0
  75. package/dist/internal/composites/calendar.d.ts +35 -0
  76. package/dist/internal/composites/calendar.d.ts.map +1 -0
  77. package/dist/internal/composites/calendar.js +139 -0
  78. package/dist/internal/composites/calendar.js.map +1 -0
  79. package/dist/internal/composites/combobox.d.ts +41 -0
  80. package/dist/internal/composites/combobox.d.ts.map +1 -0
  81. package/dist/internal/composites/combobox.js +184 -0
  82. package/dist/internal/composites/combobox.js.map +1 -0
  83. package/dist/internal/composites/grid-control.d.ts +36 -0
  84. package/dist/internal/composites/grid-control.d.ts.map +1 -0
  85. package/dist/internal/composites/grid-control.js +86 -0
  86. package/dist/internal/composites/grid-control.js.map +1 -0
  87. package/dist/internal/composites/linear-action.d.ts +35 -0
  88. package/dist/internal/composites/linear-action.d.ts.map +1 -0
  89. package/dist/internal/composites/linear-action.js +92 -0
  90. package/dist/internal/composites/linear-action.js.map +1 -0
  91. package/dist/internal/composites/linear-choice.d.ts +41 -0
  92. package/dist/internal/composites/linear-choice.d.ts.map +1 -0
  93. package/dist/internal/composites/linear-choice.js +139 -0
  94. package/dist/internal/composites/linear-choice.js.map +1 -0
  95. package/dist/internal/composites/listbox.d.ts +50 -0
  96. package/dist/internal/composites/listbox.d.ts.map +1 -0
  97. package/dist/internal/composites/listbox.js +243 -0
  98. package/dist/internal/composites/listbox.js.map +1 -0
  99. package/dist/internal/composites/menu.d.ts +28 -0
  100. package/dist/internal/composites/menu.d.ts.map +1 -0
  101. package/dist/internal/composites/menu.js +72 -0
  102. package/dist/internal/composites/menu.js.map +1 -0
  103. package/dist/internal/composites/popup.d.ts +20 -0
  104. package/dist/internal/composites/popup.d.ts.map +1 -0
  105. package/dist/internal/composites/popup.js +8 -0
  106. package/dist/internal/composites/popup.js.map +1 -0
  107. package/dist/internal/composites/slider.d.ts +20 -0
  108. package/dist/internal/composites/slider.d.ts.map +1 -0
  109. package/dist/internal/composites/slider.js +69 -0
  110. package/dist/internal/composites/slider.js.map +1 -0
  111. package/dist/internal/composites/tree-grid.d.ts +65 -0
  112. package/dist/internal/composites/tree-grid.d.ts.map +1 -0
  113. package/dist/internal/composites/tree-grid.js +274 -0
  114. package/dist/internal/composites/tree-grid.js.map +1 -0
  115. package/dist/internal/composites/tree-view.d.ts +39 -0
  116. package/dist/internal/composites/tree-view.d.ts.map +1 -0
  117. package/dist/internal/composites/tree-view.js +175 -0
  118. package/dist/internal/composites/tree-view.js.map +1 -0
  119. package/dist/internal/editing/text.d.ts +64 -0
  120. package/dist/internal/editing/text.d.ts.map +1 -0
  121. package/dist/internal/editing/text.js +238 -0
  122. package/dist/internal/editing/text.js.map +1 -0
  123. package/dist/internal/kernel/decimal.d.ts +22 -0
  124. package/dist/internal/kernel/decimal.d.ts.map +1 -0
  125. package/dist/internal/kernel/decimal.js +137 -0
  126. package/dist/internal/kernel/decimal.js.map +1 -0
  127. package/dist/internal/kernel/foundation.d.ts +12 -0
  128. package/dist/internal/kernel/foundation.d.ts.map +1 -0
  129. package/dist/internal/kernel/foundation.js +132 -0
  130. package/dist/internal/kernel/foundation.js.map +1 -0
  131. package/dist/internal/kernel/indexed-sequence.d.ts +26 -0
  132. package/dist/internal/kernel/indexed-sequence.d.ts.map +1 -0
  133. package/dist/internal/kernel/indexed-sequence.js +117 -0
  134. package/dist/internal/kernel/indexed-sequence.js.map +1 -0
  135. package/dist/internal/kernel/machine.d.ts +8 -0
  136. package/dist/internal/kernel/machine.d.ts.map +1 -0
  137. package/dist/internal/kernel/machine.js +6 -0
  138. package/dist/internal/kernel/machine.js.map +1 -0
  139. package/dist/internal/runtime/revision.d.ts +22 -0
  140. package/dist/internal/runtime/revision.d.ts.map +1 -0
  141. package/dist/internal/runtime/revision.js +72 -0
  142. package/dist/internal/runtime/revision.js.map +1 -0
  143. package/dist/internal/state/checked.d.ts +21 -0
  144. package/dist/internal/state/checked.d.ts.map +1 -0
  145. package/dist/internal/state/checked.js +29 -0
  146. package/dist/internal/state/checked.js.map +1 -0
  147. package/dist/internal/state/cursor.d.ts +13 -0
  148. package/dist/internal/state/cursor.d.ts.map +1 -0
  149. package/dist/internal/state/cursor.js +24 -0
  150. package/dist/internal/state/cursor.js.map +1 -0
  151. package/dist/internal/state/expansion.d.ts +8 -0
  152. package/dist/internal/state/expansion.d.ts.map +1 -0
  153. package/dist/internal/state/expansion.js +23 -0
  154. package/dist/internal/state/expansion.js.map +1 -0
  155. package/dist/internal/state/open-state.d.ts +16 -0
  156. package/dist/internal/state/open-state.d.ts.map +1 -0
  157. package/dist/internal/state/open-state.js +25 -0
  158. package/dist/internal/state/open-state.js.map +1 -0
  159. package/dist/internal/state/selection.d.ts +23 -0
  160. package/dist/internal/state/selection.d.ts.map +1 -0
  161. package/dist/internal/state/selection.js +110 -0
  162. package/dist/internal/state/selection.js.map +1 -0
  163. package/dist/listbox.d.ts +2 -0
  164. package/dist/listbox.d.ts.map +1 -0
  165. package/dist/listbox.js +2 -0
  166. package/dist/listbox.js.map +1 -0
  167. package/dist/menu-button.d.ts +3 -0
  168. package/dist/menu-button.d.ts.map +1 -0
  169. package/dist/menu-button.js +3 -0
  170. package/dist/menu-button.js.map +1 -0
  171. package/dist/menu.d.ts +8 -0
  172. package/dist/menu.d.ts.map +1 -0
  173. package/dist/menu.js +4 -0
  174. package/dist/menu.js.map +1 -0
  175. package/dist/menubar.d.ts +3 -0
  176. package/dist/menubar.d.ts.map +1 -0
  177. package/dist/menubar.js +3 -0
  178. package/dist/menubar.js.map +1 -0
  179. package/dist/multi-thumb-slider.d.ts +35 -0
  180. package/dist/multi-thumb-slider.d.ts.map +1 -0
  181. package/dist/multi-thumb-slider.js +68 -0
  182. package/dist/multi-thumb-slider.js.map +1 -0
  183. package/dist/number-field.d.ts +49 -0
  184. package/dist/number-field.d.ts.map +1 -0
  185. package/dist/number-field.js +454 -0
  186. package/dist/number-field.js.map +1 -0
  187. package/dist/pagination.d.ts +63 -0
  188. package/dist/pagination.d.ts.map +1 -0
  189. package/dist/pagination.js +190 -0
  190. package/dist/pagination.js.map +1 -0
  191. package/dist/pin-input.d.ts +29 -0
  192. package/dist/pin-input.d.ts.map +1 -0
  193. package/dist/pin-input.js +49 -0
  194. package/dist/pin-input.js.map +1 -0
  195. package/dist/quantity-field.d.ts +58 -0
  196. package/dist/quantity-field.d.ts.map +1 -0
  197. package/dist/quantity-field.js +250 -0
  198. package/dist/quantity-field.js.map +1 -0
  199. package/dist/radio-group.d.ts +22 -0
  200. package/dist/radio-group.d.ts.map +1 -0
  201. package/dist/radio-group.js +16 -0
  202. package/dist/radio-group.js.map +1 -0
  203. package/dist/rating.d.ts +17 -0
  204. package/dist/rating.d.ts.map +1 -0
  205. package/dist/rating.js +15 -0
  206. package/dist/rating.js.map +1 -0
  207. package/dist/result.d.ts +10 -0
  208. package/dist/result.d.ts.map +1 -0
  209. package/dist/result.js +19 -0
  210. package/dist/result.js.map +1 -0
  211. package/dist/revision.d.ts +2 -0
  212. package/dist/revision.d.ts.map +1 -0
  213. package/dist/revision.js +2 -0
  214. package/dist/revision.js.map +1 -0
  215. package/dist/select.d.ts +30 -0
  216. package/dist/select.d.ts.map +1 -0
  217. package/dist/select.js +28 -0
  218. package/dist/select.js.map +1 -0
  219. package/dist/shared.d.ts +42 -0
  220. package/dist/shared.d.ts.map +1 -0
  221. package/dist/shared.js +3 -0
  222. package/dist/shared.js.map +1 -0
  223. package/dist/slider.d.ts +2 -0
  224. package/dist/slider.d.ts.map +1 -0
  225. package/dist/slider.js +2 -0
  226. package/dist/slider.js.map +1 -0
  227. package/dist/spin-button.d.ts +29 -0
  228. package/dist/spin-button.d.ts.map +1 -0
  229. package/dist/spin-button.js +61 -0
  230. package/dist/spin-button.js.map +1 -0
  231. package/dist/stepper.d.ts +17 -0
  232. package/dist/stepper.d.ts.map +1 -0
  233. package/dist/stepper.js +12 -0
  234. package/dist/stepper.js.map +1 -0
  235. package/dist/structures/grid.d.ts +27 -0
  236. package/dist/structures/grid.d.ts.map +1 -0
  237. package/dist/structures/grid.js +197 -0
  238. package/dist/structures/grid.js.map +1 -0
  239. package/dist/structures/range.d.ts +39 -0
  240. package/dist/structures/range.d.ts.map +1 -0
  241. package/dist/structures/range.js +242 -0
  242. package/dist/structures/range.js.map +1 -0
  243. package/dist/structures/sequence.d.ts +17 -0
  244. package/dist/structures/sequence.d.ts.map +1 -0
  245. package/dist/structures/sequence.js +24 -0
  246. package/dist/structures/sequence.js.map +1 -0
  247. package/dist/structures/tree.d.ts +32 -0
  248. package/dist/structures/tree.d.ts.map +1 -0
  249. package/dist/structures/tree.js +234 -0
  250. package/dist/structures/tree.js.map +1 -0
  251. package/dist/switch.d.ts +20 -0
  252. package/dist/switch.d.ts.map +1 -0
  253. package/dist/switch.js +4 -0
  254. package/dist/switch.js.map +1 -0
  255. package/dist/tabs.d.ts +15 -0
  256. package/dist/tabs.d.ts.map +1 -0
  257. package/dist/tabs.js +23 -0
  258. package/dist/tabs.js.map +1 -0
  259. package/dist/tags-input.d.ts +41 -0
  260. package/dist/tags-input.d.ts.map +1 -0
  261. package/dist/tags-input.js +44 -0
  262. package/dist/tags-input.js.map +1 -0
  263. package/dist/text.d.ts +2 -0
  264. package/dist/text.d.ts.map +1 -0
  265. package/dist/text.js +2 -0
  266. package/dist/text.js.map +1 -0
  267. package/dist/time-field.d.ts +46 -0
  268. package/dist/time-field.d.ts.map +1 -0
  269. package/dist/time-field.js +148 -0
  270. package/dist/time-field.js.map +1 -0
  271. package/dist/toggle-button.d.ts +19 -0
  272. package/dist/toggle-button.d.ts.map +1 -0
  273. package/dist/toggle-button.js +16 -0
  274. package/dist/toggle-button.js.map +1 -0
  275. package/dist/toolbar.d.ts +2 -0
  276. package/dist/toolbar.d.ts.map +1 -0
  277. package/dist/toolbar.js +2 -0
  278. package/dist/toolbar.js.map +1 -0
  279. package/dist/tooltip.d.ts +2 -0
  280. package/dist/tooltip.d.ts.map +1 -0
  281. package/dist/tooltip.js +2 -0
  282. package/dist/tooltip.js.map +1 -0
  283. package/dist/tree-grid.d.ts +10 -0
  284. package/dist/tree-grid.d.ts.map +1 -0
  285. package/dist/tree-grid.js +14 -0
  286. package/dist/tree-grid.js.map +1 -0
  287. package/dist/tree-view.d.ts +2 -0
  288. package/dist/tree-view.d.ts.map +1 -0
  289. package/dist/tree-view.js +2 -0
  290. package/dist/tree-view.js.map +1 -0
  291. package/dist/units.d.ts +72 -0
  292. package/dist/units.d.ts.map +1 -0
  293. package/dist/units.js +496 -0
  294. package/dist/units.js.map +1 -0
  295. package/dist/window-splitter.d.ts +2 -0
  296. package/dist/window-splitter.d.ts.map +1 -0
  297. package/dist/window-splitter.js +2 -0
  298. package/dist/window-splitter.js.map +1 -0
  299. package/package.json +304 -0
@@ -0,0 +1,28 @@
1
+ import type { Result, StableID } from '../../shared.js';
2
+ import type { Tree } from '../../structures/tree.js';
3
+ import { type CursorState } from '../state/cursor.js';
4
+ export interface MenuState<ID extends StableID = StableID> {
5
+ readonly open: boolean;
6
+ readonly cursor: CursorState<ID>;
7
+ readonly openPath: readonly ID[];
8
+ }
9
+ export type MenuEvent<ID extends StableID = StableID> = 'open-popup' | 'close-popup' | 'next' | 'previous' | 'first' | 'last' | 'open-submenu' | 'close-submenu' | 'invoke' | 'escape' | {
10
+ readonly type: 'focus';
11
+ readonly id: ID;
12
+ };
13
+ export type MenuCommand<ID extends StableID = StableID> = {
14
+ readonly type: 'focus' | 'invoke';
15
+ readonly id: ID;
16
+ } | {
17
+ readonly type: 'restore-focus';
18
+ };
19
+ export interface MenuUpdate<ID extends StableID = StableID> {
20
+ readonly state: MenuState<ID>;
21
+ readonly commands: readonly MenuCommand<ID>[];
22
+ }
23
+ export interface MenuPolicies<ID extends StableID = StableID> {
24
+ readonly disabled?: (id: ID) => boolean;
25
+ }
26
+ export declare function createMenuState<ID extends StableID>(tree: Tree<ID>, open?: boolean, current?: ID | null, openPath?: readonly ID[]): Result<MenuState<ID>>;
27
+ export declare function applyMenuEvent<ID extends StableID>(tree: Tree<ID>, state: MenuState<ID>, event: MenuEvent<ID>, policies?: MenuPolicies<ID>): Result<MenuUpdate<ID>>;
28
+ //# sourceMappingURL=menu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menu.d.ts","sourceRoot":"","sources":["../../../src/internal/composites/menu.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AACxD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAGrD,OAAO,EAAqB,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEzE,MAAM,WAAW,SAAS,CAAC,EAAE,SAAS,QAAQ,GAAG,QAAQ;IAAI,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC,EAAE,CAAC,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,EAAE,EAAE,CAAA;CAAE;AACzJ,MAAM,MAAM,SAAS,CAAC,EAAE,SAAS,QAAQ,GAAG,QAAQ,IAAI,YAAY,GAAG,aAAa,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,GAAG,MAAM,GAAG,cAAc,GAAG,eAAe,GAAG,QAAQ,GAAG,QAAQ,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAA;CAAE,CAAC;AACrO,MAAM,MAAM,WAAW,CAAC,EAAE,SAAS,QAAQ,GAAG,QAAQ,IAAI;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,GAAG,QAAQ,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAA;CAAE,CAAC;AACtJ,MAAM,WAAW,UAAU,CAAC,EAAE,SAAS,QAAQ,GAAG,QAAQ;IAAI,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,WAAW,CAAC,EAAE,CAAC,EAAE,CAAA;CAAE;AAC5I,MAAM,WAAW,YAAY,CAAC,EAAE,SAAS,QAAQ,GAAG,QAAQ;IAAI,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,EAAE,KAAK,OAAO,CAAA;CAAE;AAEzG,wBAAgB,eAAe,CAAC,EAAE,SAAS,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,UAAQ,EAAE,OAAO,GAAE,EAAE,GAAG,IAAW,EAAE,QAAQ,GAAE,SAAS,EAAE,EAAO,GAAG,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAOjK;AAED,wBAAgB,cAAc,CAAC,EAAE,SAAS,QAAQ,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC,EAAE,QAAQ,GAAE,YAAY,CAAC,EAAE,CAAM,GAAG,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,CAcvK"}
@@ -0,0 +1,72 @@
1
+ import { fail, ok } from '../kernel/foundation.js';
2
+ import { createMachineUpdate } from '../kernel/machine.js';
3
+ import { createCursorState } from '../state/cursor.js';
4
+ export function createMenuState(tree, open = false, current = null, openPath = []) {
5
+ const normalized = tree.normalizeExpansion(openPath).ids;
6
+ if (normalized.length !== openPath.length || normalized.some((id, index) => id !== openPath[index]))
7
+ return fail('construction', 'invalid-menu-open-path', 'Menu open path must contain ordered branch identities.');
8
+ for (let index = 1; index < openPath.length; index += 1)
9
+ if (tree.parentOf(openPath[index]) !== openPath[index - 1])
10
+ return fail('construction', 'disconnected-menu-open-path', 'Menu open path must be one ancestor chain.');
11
+ if (!open && (current !== null || openPath.length > 0))
12
+ return fail('construction', 'closed-menu-has-active-state', 'Closed menu cannot own a cursor or submenu path.');
13
+ if (open && current !== null && !tree.visible(openPath).contains(current))
14
+ return fail('construction', 'menu-cursor-hidden', 'Menu cursor must be visible.');
15
+ return ok(Object.freeze({ open, cursor: createCursorState(current), openPath: Object.freeze([...openPath]) }));
16
+ }
17
+ export function applyMenuEvent(tree, state, event, policies = {}) {
18
+ const valid = createMenuState(tree, state.open, state.cursor.current, state.openPath);
19
+ if (!valid.ok)
20
+ return { ok: false, error: { ...valid.error, class: 'transition-rejection' } };
21
+ if (event === 'open-popup') {
22
+ if (state.open)
23
+ return createMachineUpdate(state);
24
+ const id = tree.roots.at(0);
25
+ return createMachineUpdate(menuState(true, id, []), id === null ? [] : [{ type: 'focus', id }]);
26
+ }
27
+ if (event === 'close-popup')
28
+ return createMachineUpdate(menuState(false, null, []), state.open ? [{ type: 'restore-focus' }] : []);
29
+ if (!state.open)
30
+ return fail('transition-rejection', 'menu-closed', 'Menu events require an open menu.');
31
+ if (typeof event === 'object') {
32
+ if (!tree.visible(state.openPath).contains(event.id))
33
+ return fail('transition-rejection', 'menu-target-hidden', 'Direct menu focus requires a visible item.');
34
+ return createMachineUpdate(menuState(true, event.id, pathFor(tree, event.id, state.openPath)), [{ type: 'focus', id: event.id }]);
35
+ }
36
+ const current = state.cursor.current;
37
+ if (event === 'escape')
38
+ return closeLevel(tree, state);
39
+ if (current === null) {
40
+ const id = tree.roots.at(event === 'last' ? tree.roots.size - 1 : 0);
41
+ return createMachineUpdate(menuState(true, id, []), id === null ? [] : [{ type: 'focus', id }]);
42
+ }
43
+ if (event === 'next' || event === 'previous' || event === 'first' || event === 'last') {
44
+ const siblings = tree.parentOf(current) === null ? tree.roots : tree.childrenOf(tree.parentOf(current));
45
+ if (siblings === null || siblings.size === 0)
46
+ return createMachineUpdate(state);
47
+ const index = siblings.indexOf(current) ?? 0;
48
+ const target = event === 'first' ? 0 : event === 'last' ? siblings.size - 1 : (index + (event === 'next' ? 1 : -1) + siblings.size) % siblings.size;
49
+ const id = siblings.at(target);
50
+ return id === null ? createMachineUpdate(state) : createMachineUpdate(menuState(true, id, state.openPath), [{ type: 'focus', id }]);
51
+ }
52
+ if (event === 'open-submenu') {
53
+ if (policies.disabled?.(current) === true)
54
+ return createMachineUpdate(state);
55
+ const child = tree.childrenOf(current)?.at(0) ?? null;
56
+ if (child === null)
57
+ return createMachineUpdate(state);
58
+ const path = [...(tree.ancestorsOf(current) ?? [])].reverse().filter((id) => tree.isLeaf(id) === false);
59
+ path.push(current);
60
+ return createMachineUpdate(menuState(true, child, path), [{ type: 'focus', id: child }]);
61
+ }
62
+ if (event === 'close-submenu')
63
+ return closeLevel(tree, state);
64
+ if (tree.isLeaf(current) !== true || policies.disabled?.(current) === true)
65
+ return createMachineUpdate(state);
66
+ return createMachineUpdate(menuState(false, null, []), [{ type: 'invoke', id: current }, { type: 'restore-focus' }]);
67
+ }
68
+ function closeLevel(tree, state) { const current = state.cursor.current; const parent = current === null ? null : tree.parentOf(current); if (parent === null)
69
+ return createMachineUpdate(menuState(false, null, []), [{ type: 'restore-focus' }]); const path = state.openPath.filter((id) => id !== parent && !(tree.ancestorsOf(id) ?? []).includes(parent)); return createMachineUpdate(menuState(true, parent, path), [{ type: 'focus', id: parent }]); }
70
+ function pathFor(tree, id, currentPath) { const ancestors = new Set(tree.ancestorsOf(id) ?? []); return currentPath.filter((branch) => ancestors.has(branch)); }
71
+ function menuState(open, current, openPath) { return Object.freeze({ open, cursor: createCursorState(current), openPath: Object.freeze([...openPath]) }); }
72
+ //# sourceMappingURL=menu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"menu.js","sourceRoot":"","sources":["../../../src/internal/composites/menu.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import type { Result } from '../../shared.js';
2
+ export interface PopupState {
3
+ readonly open: boolean;
4
+ }
5
+ export type PopupEvent = 'open' | 'close' | 'toggle' | {
6
+ readonly type: 'set-open';
7
+ readonly open: boolean;
8
+ };
9
+ export type PopupCommand = {
10
+ readonly type: 'popup-opened';
11
+ } | {
12
+ readonly type: 'popup-closed';
13
+ };
14
+ export interface PopupUpdate {
15
+ readonly state: PopupState;
16
+ readonly commands: readonly PopupCommand[];
17
+ }
18
+ export declare function createPopupState(open?: boolean): Result<PopupState>;
19
+ export declare function applyPopupEvent(state: PopupState, event: PopupEvent): Result<PopupUpdate>;
20
+ //# sourceMappingURL=popup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"popup.d.ts","sourceRoot":"","sources":["../../../src/internal/composites/popup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAI,EAAC,MAAM,EAAC,MAAI,iBAAiB,CAAC;AACzC,MAAM,WAAW,UAAU;IAAC,QAAQ,CAAC,IAAI,EAAC,OAAO,CAAA;CAAC;AAAA,MAAM,MAAM,UAAU,GAAC,MAAM,GAAC,OAAO,GAAC,QAAQ,GAAC;IAAC,QAAQ,CAAC,IAAI,EAAC,UAAU,CAAC;IAAA,QAAQ,CAAC,IAAI,EAAC,OAAO,CAAA;CAAC,CAAC;AAAA,MAAM,MAAM,YAAY,GAAC;IAAC,QAAQ,CAAC,IAAI,EAAC,cAAc,CAAA;CAAC,GAAC;IAAC,QAAQ,CAAC,IAAI,EAAC,cAAc,CAAA;CAAC,CAAC;AAAA,MAAM,WAAW,WAAW;IAAC,QAAQ,CAAC,KAAK,EAAC,UAAU,CAAC;IAAA,QAAQ,CAAC,QAAQ,EAAC,SAAS,YAAY,EAAE,CAAA;CAAC;AAC1U,wBAAgB,gBAAgB,CAAC,IAAI,UAAM,GAAE,MAAM,CAAC,UAAU,CAAC,CAAyI;AACxM,wBAAgB,eAAe,CAAC,KAAK,EAAC,UAAU,EAAC,KAAK,EAAC,UAAU,GAAE,MAAM,CAAC,WAAW,CAAC,CAAwjB"}
@@ -0,0 +1,8 @@
1
+ import { fail, ok } from '../kernel/foundation.js';
2
+ import { createMachineUpdate } from '../kernel/machine.js';
3
+ export function createPopupState(open = false) { return typeof open === 'boolean' ? ok(Object.freeze({ open })) : fail('construction', 'invalid-popup-state', 'Popup open state must be boolean.'); }
4
+ export function applyPopupEvent(state, event) { if (typeof state.open !== 'boolean')
5
+ return fail('transition-rejection', 'invalid-popup-state', 'Popup open state must be boolean.'); const next = typeof event === 'object' ? event.type === 'set-open' && typeof event.open === 'boolean' ? event.open : null : event === 'toggle' ? !state.open : event === 'open' ? true : event === 'close' ? false : null; if (next === null)
6
+ return fail('transition-rejection', 'invalid-popup-event', 'Popup event is not accepted.'); if (next === state.open)
7
+ return createMachineUpdate(state); return createMachineUpdate(Object.freeze({ open: next }), [{ type: next ? 'popup-opened' : 'popup-closed' }]); }
8
+ //# sourceMappingURL=popup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"popup.js","sourceRoot":"","sources":["../../../src/internal/composites/popup.ts"],"names":[],"mappings":"AAAyC,OAAM,EAAC,IAAI,EAAC,EAAE,EAAC,MAAI,yBAAyB,CAAC;AAAA,OAAM,EAAC,mBAAmB,EAAC,MAAI,sBAAsB,CAAC;AAE5I,MAAM,UAAU,gBAAgB,CAAC,IAAI,GAAC,KAAK,IAAqB,OAAO,OAAO,IAAI,KAAG,SAAS,CAAA,CAAC,CAAA,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,EAAC,IAAI,EAAC,CAAC,CAAC,CAAA,CAAC,CAAA,IAAI,CAAC,cAAc,EAAC,qBAAqB,EAAC,mCAAmC,CAAC,CAAA,CAAA,CAAC;AACxM,MAAM,UAAU,eAAe,CAAC,KAAgB,EAAC,KAAgB,IAAsB,IAAG,OAAO,KAAK,CAAC,IAAI,KAAG,SAAS;IAAC,OAAO,IAAI,CAAC,sBAAsB,EAAC,qBAAqB,EAAC,mCAAmC,CAAC,CAAC,CAAA,MAAM,IAAI,GAAC,OAAO,KAAK,KAAG,QAAQ,CAAA,CAAC,CAAA,KAAK,CAAC,IAAI,KAAG,UAAU,IAAE,OAAO,KAAK,CAAC,IAAI,KAAG,SAAS,CAAA,CAAC,CAAA,KAAK,CAAC,IAAI,CAAA,CAAC,CAAA,IAAI,CAAA,CAAC,CAAA,KAAK,KAAG,QAAQ,CAAA,CAAC,CAAA,CAAC,KAAK,CAAC,IAAI,CAAA,CAAC,CAAA,KAAK,KAAG,MAAM,CAAA,CAAC,CAAA,IAAI,CAAA,CAAC,CAAA,KAAK,KAAG,OAAO,CAAA,CAAC,CAAA,KAAK,CAAA,CAAC,CAAA,IAAI,CAAC,CAAA,IAAG,IAAI,KAAG,IAAI;IAAC,OAAO,IAAI,CAAC,sBAAsB,EAAC,qBAAqB,EAAC,8BAA8B,CAAC,CAAC,CAAA,IAAG,IAAI,KAAG,KAAK,CAAC,IAAI;IAAC,OAAO,mBAAmB,CAAC,KAAK,CAAC,CAAC,CAAA,OAAO,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC,EAAC,IAAI,EAAC,IAAI,EAAC,CAAC,EAAC,CAAC,EAAC,IAAI,EAAC,IAAI,CAAA,CAAC,CAAA,cAAc,CAAA,CAAC,CAAA,cAAc,EAAC,CAAC,CAAC,CAAA,CAAA,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { Result } from '../../shared.js';
2
+ import type { QuantizedRange } from '../../structures/range.js';
3
+ export type SliderEvent = 'increment' | 'decrement' | 'page-up' | 'page-down' | 'home' | 'end' | {
4
+ readonly type: 'set-tick';
5
+ readonly tick: number;
6
+ };
7
+ export interface SliderState {
8
+ readonly tick: number;
9
+ }
10
+ export interface SliderCommand {
11
+ readonly type: 'announce-tick';
12
+ readonly tick: number;
13
+ }
14
+ export interface SliderUpdate {
15
+ readonly state: SliderState;
16
+ readonly commands: readonly SliderCommand[];
17
+ }
18
+ export declare function createSliderState(range: QuantizedRange, tick?: number): Result<SliderState>;
19
+ export declare function applySliderEvent(range: QuantizedRange, state: SliderState, event: SliderEvent, page?: number): Result<SliderUpdate>;
20
+ //# sourceMappingURL=slider.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slider.d.ts","sourceRoot":"","sources":["../../../src/internal/composites/slider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAIhE,MAAM,MAAM,WAAW,GACnB,WAAW,GACX,WAAW,GACX,SAAS,GACT,WAAW,GACX,MAAM,GACN,KAAK,GACL;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzD,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAC;CAC7C;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,cAAc,EACrB,IAAI,SAAI,GACP,MAAM,CAAC,WAAW,CAAC,CAUrB;AAED,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,cAAc,EACrB,KAAK,EAAE,WAAW,EAClB,KAAK,EAAE,WAAW,EAClB,IAAI,SAAI,GACP,MAAM,CAAC,YAAY,CAAC,CAgEtB"}
@@ -0,0 +1,69 @@
1
+ import { fail, ok } from '../kernel/foundation.js';
2
+ import { createMachineUpdate } from '../kernel/machine.js';
3
+ export function createSliderState(range, tick = 0) {
4
+ if (!isSliderTick(range, tick)) {
5
+ return fail('construction', 'slider-tick-outside-range', 'Slider tick must be a safe integer inside the quantized range.', { tick, count: range.count });
6
+ }
7
+ return ok(sliderState(tick));
8
+ }
9
+ export function applySliderEvent(range, state, event, page = 2) {
10
+ if (!isSliderTick(range, state.tick)) {
11
+ return fail('transition-rejection', 'slider-tick-outside-range', 'Slider tick must be a safe integer inside the quantized range.', { tick: state.tick, count: range.count });
12
+ }
13
+ if (!isSliderEvent(event)) {
14
+ return fail('transition-rejection', 'invalid-slider-event', 'Slider event must be increment, decrement, page-up, page-down, home, or end.', { event });
15
+ }
16
+ if (!Number.isSafeInteger(page) || page < 1) {
17
+ return fail('transition-rejection', 'invalid-slider-page', 'Slider page must be a positive safe integer.', { page });
18
+ }
19
+ if (typeof event === 'object') {
20
+ if (!isSliderTick(range, event.tick)) {
21
+ return fail('transition-rejection', 'slider-tick-outside-range', 'Direct slider input requires a tick inside the quantized range.', { tick: event.tick, count: range.count });
22
+ }
23
+ if (event.tick === state.tick)
24
+ return createMachineUpdate(state);
25
+ return createMachineUpdate(sliderState(event.tick), [{ type: 'announce-tick', tick: event.tick }]);
26
+ }
27
+ let tick;
28
+ switch (event) {
29
+ case 'increment':
30
+ tick = state.tick === range.count ? range.count : state.tick + 1;
31
+ break;
32
+ case 'decrement':
33
+ tick = state.tick === 0 ? 0 : state.tick - 1;
34
+ break;
35
+ case 'page-up':
36
+ tick = page >= range.count - state.tick ? range.count : state.tick + page;
37
+ break;
38
+ case 'page-down':
39
+ tick = page >= state.tick ? 0 : state.tick - page;
40
+ break;
41
+ case 'home':
42
+ tick = 0;
43
+ break;
44
+ case 'end':
45
+ tick = range.count;
46
+ break;
47
+ }
48
+ if (tick === state.tick)
49
+ return createMachineUpdate(state);
50
+ const next = sliderState(tick);
51
+ return createMachineUpdate(next, [{ type: 'announce-tick', tick }]);
52
+ }
53
+ function isSliderTick(range, tick) {
54
+ return Number.isSafeInteger(tick) && tick >= 0 && tick <= range.count;
55
+ }
56
+ function isSliderEvent(value) {
57
+ return typeof value === 'string' ? (value === 'increment' ||
58
+ value === 'decrement' ||
59
+ value === 'page-up' ||
60
+ value === 'page-down' ||
61
+ value === 'home' ||
62
+ value === 'end') : typeof value === 'object' && value !== null
63
+ && 'type' in value && value.type === 'set-tick'
64
+ && 'tick' in value && typeof value.tick === 'number';
65
+ }
66
+ function sliderState(tick) {
67
+ return Object.freeze({ tick });
68
+ }
69
+ //# sourceMappingURL=slider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"slider.js","sourceRoot":"","sources":["../../../src/internal/composites/slider.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ import type { AxisBoundaryPolicy, GridDirection, Result, StableID } from '../../shared.js';
2
+ import type { Grid } from '../../structures/grid.js';
3
+ import type { Tree } from '../../structures/tree.js';
4
+ import { type CursorState } from '../state/cursor.js';
5
+ import { type ExpansionState } from '../state/expansion.js';
6
+ import { type SelectionSnapshotInput, type SelectionState } from '../state/selection.js';
7
+ export type TreeGridEditMode = 'navigation' | 'editing';
8
+ export type TreeGridEvent<RowID extends StableID = StableID, CellID extends StableID = StableID> = GridDirection | 'expand' | 'collapse' | 'select' | 'start-edit' | 'commit-edit' | 'cancel-edit' | {
9
+ readonly type: 'focus';
10
+ readonly id: CellID;
11
+ } | {
12
+ readonly type: 'select';
13
+ readonly id: CellID;
14
+ } | {
15
+ readonly type: 'start-edit';
16
+ readonly id: CellID;
17
+ } | {
18
+ readonly type: 'set-expanded';
19
+ readonly id: RowID;
20
+ readonly open: boolean;
21
+ };
22
+ export type TreeGridCommand<CellID extends StableID = StableID> = {
23
+ readonly type: 'focus';
24
+ readonly id: CellID;
25
+ } | {
26
+ readonly type: 'begin-edit';
27
+ readonly id: CellID;
28
+ } | {
29
+ readonly type: 'commit-edit';
30
+ readonly id: CellID;
31
+ } | {
32
+ readonly type: 'cancel-edit';
33
+ readonly id: CellID;
34
+ };
35
+ export interface TreeGridModel<RowID extends StableID = StableID, CellID extends StableID = StableID> {
36
+ readonly tree: Tree<RowID>;
37
+ readonly grid: Grid<CellID>;
38
+ readonly rowIDs: readonly RowID[];
39
+ rowIndexOf(id: RowID): number | null;
40
+ rowOfCell(id: CellID): RowID | null;
41
+ }
42
+ export interface TreeGridState<RowID extends StableID = StableID, CellID extends StableID = StableID> {
43
+ readonly expansion: ExpansionState<RowID>;
44
+ readonly cursor: CursorState<CellID>;
45
+ readonly selection: SelectionState<CellID>;
46
+ readonly editMode: TreeGridEditMode;
47
+ }
48
+ export interface TreeGridStateInput<RowID extends StableID = StableID, CellID extends StableID = StableID> extends SelectionSnapshotInput<CellID> {
49
+ readonly expanded?: Iterable<RowID>;
50
+ readonly current?: CellID | null;
51
+ readonly editMode?: TreeGridEditMode;
52
+ }
53
+ export interface TreeGridPolicies<CellID extends StableID = StableID> {
54
+ readonly eligible?: (id: CellID) => boolean;
55
+ readonly boundary?: AxisBoundaryPolicy;
56
+ readonly maxScan?: number;
57
+ }
58
+ export interface TreeGridUpdate<RowID extends StableID = StableID, CellID extends StableID = StableID> {
59
+ readonly state: TreeGridState<RowID, CellID>;
60
+ readonly commands: readonly TreeGridCommand<CellID>[];
61
+ }
62
+ export declare function createTreeGridModel<RowID extends StableID, CellID extends StableID>(tree: Tree<RowID>, grid: Grid<CellID>, rowIDs: readonly RowID[]): Result<TreeGridModel<RowID, CellID>>;
63
+ export declare function createTreeGridState<RowID extends StableID, CellID extends StableID>(model: TreeGridModel<RowID, CellID>, input?: TreeGridStateInput<RowID, CellID>): Result<TreeGridState<RowID, CellID>>;
64
+ export declare function applyTreeGridEvent<RowID extends StableID, CellID extends StableID>(model: TreeGridModel<RowID, CellID>, state: TreeGridState<RowID, CellID>, event: TreeGridEvent<RowID, CellID>, policies?: TreeGridPolicies<CellID>): Result<TreeGridUpdate<RowID, CellID>>;
65
+ //# sourceMappingURL=tree-grid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tree-grid.d.ts","sourceRoot":"","sources":["../../../src/internal/composites/tree-grid.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,274 @@
1
+ import { fail, freezeArray, ok } from '../kernel/foundation.js';
2
+ import { findEligibleFromEdge, IndexedSequence } from '../kernel/indexed-sequence.js';
3
+ import { createMachineUpdate } from '../kernel/machine.js';
4
+ import { createCursorState } from '../state/cursor.js';
5
+ import { createExpansionState, setExpansionOpen, } from '../state/expansion.js';
6
+ import { createSelectionState, selectOne, } from '../state/selection.js';
7
+ class IndexedTreeGridModel {
8
+ tree;
9
+ grid;
10
+ rowIDs;
11
+ #rowIndices;
12
+ constructor(tree, grid, rowIDs) {
13
+ this.tree = tree;
14
+ this.grid = grid;
15
+ this.rowIDs = freezeArray(rowIDs);
16
+ this.#rowIndices = new Map(this.rowIDs.map((id, index) => [id, index]));
17
+ Object.freeze(this);
18
+ }
19
+ rowIndexOf(id) {
20
+ return this.#rowIndices.get(id) ?? null;
21
+ }
22
+ rowOfCell(id) {
23
+ const position = this.grid.positionOf(id);
24
+ return position === null ? null : (this.rowIDs[position.row] ?? null);
25
+ }
26
+ }
27
+ export function createTreeGridModel(tree, grid, rowIDs) {
28
+ if (rowIDs.length !== grid.rowCount || rowIDs.length !== tree.size) {
29
+ return fail('construction', 'tree-grid-row-count-mismatch', 'Tree-grid must map every tree row to exactly one grid row.', { mappedRows: rowIDs.length, gridRows: grid.rowCount, treeRows: tree.size });
30
+ }
31
+ const seen = new Set();
32
+ for (let index = 0; index < rowIDs.length; index += 1) {
33
+ const id = rowIDs[index];
34
+ if (id === undefined || !tree.has(id)) {
35
+ return fail('construction', 'tree-grid-row-outside-tree', 'Every mapped tree-grid row must exist in the tree.', { index, id });
36
+ }
37
+ if (seen.has(id)) {
38
+ return fail('construction', 'duplicate-tree-grid-row', 'Each tree row must map to one grid row.', { index, id });
39
+ }
40
+ seen.add(id);
41
+ }
42
+ return ok(new IndexedTreeGridModel(tree, grid, rowIDs));
43
+ }
44
+ export function createTreeGridState(model, input = {}) {
45
+ const expansion = createExpansionState(model.tree, input.expanded ?? []);
46
+ const visible = visibleCells(model, expansion);
47
+ const current = input.current ?? null;
48
+ if (current !== null && !visible.contains(current)) {
49
+ return fail('construction', 'tree-grid-cursor-hidden', 'Tree-grid cursor must belong to a visible row.', { current });
50
+ }
51
+ const selection = createSelectionState(allCells(model), 'single', input);
52
+ if (!selection.ok)
53
+ return selection;
54
+ const editMode = input.editMode ?? 'navigation';
55
+ if (!isTreeGridEditMode(editMode)) {
56
+ return fail('construction', 'invalid-tree-grid-edit-mode', 'Tree-grid edit mode must be navigation or editing.', { editMode });
57
+ }
58
+ if (editMode === 'editing' && current === null) {
59
+ return fail('construction', 'tree-grid-edit-without-cursor', 'Tree-grid editing requires a current cell.');
60
+ }
61
+ return ok(treeGridState(expansion, createCursorState(current), selection.value, editMode));
62
+ }
63
+ export function applyTreeGridEvent(model, state, event, policies = {}) {
64
+ const expansion = createExpansionState(model.tree, state.expansion.ids);
65
+ const visible = visibleCells(model, expansion);
66
+ const domain = allCells(model);
67
+ const stateError = validateTreeGridState(visible, domain, state);
68
+ if (stateError !== null)
69
+ return { ok: false, error: stateError };
70
+ if (!isTreeGridEvent(event)) {
71
+ return fail('transition-rejection', 'invalid-tree-grid-event', 'Tree-grid event is not part of the accepted event vocabulary.', { event });
72
+ }
73
+ const boundary = policies.boundary ?? 'stop';
74
+ if (boundary !== 'stop' && boundary !== 'wrap-axis') {
75
+ return fail('transition-rejection', 'invalid-tree-grid-boundary', 'Tree-grid boundary must be stop or wrap-axis.', { boundary });
76
+ }
77
+ if (policies.eligible !== undefined && typeof policies.eligible !== 'function') {
78
+ return fail('transition-rejection', 'invalid-eligibility-policy', 'Tree-grid eligibility policy must be a function.');
79
+ }
80
+ const normalized = sameExpansion(expansion, state.expansion)
81
+ ? state
82
+ : treeGridState(expansion, state.cursor, state.selection, state.editMode);
83
+ const current = state.cursor.current;
84
+ if (typeof event === 'object') {
85
+ if (event.type === 'set-expanded') {
86
+ if (!model.tree.has(event.id)) {
87
+ return fail('transition-rejection', 'tree-grid-row-outside-tree', 'Direct tree-grid expansion requires a row in the tree.', { id: event.id });
88
+ }
89
+ const nextExpansion = setExpansionOpen(expansion, event.id, event.open, model.tree);
90
+ const nextVisible = visibleCells(model, nextExpansion);
91
+ const rowIndex = model.rowIndexOf(event.id);
92
+ const target = current === null || nextVisible.contains(current)
93
+ ? current
94
+ : (rowIndex === null ? null : model.grid.row(rowIndex)?.at(0) ?? null);
95
+ return createMachineUpdate(treeGridState(nextExpansion, createCursorState(target), state.selection, 'navigation'), target === null || target === current ? [] : [{ type: 'focus', id: target }]);
96
+ }
97
+ if (!visible.contains(event.id) || policies.eligible?.(event.id) === false) {
98
+ return fail('transition-rejection', 'tree-grid-target-unavailable', 'Direct tree-grid cell events require an eligible visible cell.', { id: event.id });
99
+ }
100
+ const cursor = createCursorState(event.id);
101
+ if (event.type === 'focus') {
102
+ return createMachineUpdate(treeGridState(expansion, cursor, state.selection, 'navigation'), [{ type: 'focus', id: event.id }]);
103
+ }
104
+ const selection = selectOne(state.selection, event.id, domain);
105
+ if (event.type === 'select') {
106
+ return createMachineUpdate(treeGridState(expansion, cursor, selection, 'navigation'), [{ type: 'focus', id: event.id }]);
107
+ }
108
+ return createMachineUpdate(treeGridState(expansion, cursor, selection, 'editing'), [{ type: 'focus', id: event.id }, { type: 'begin-edit', id: event.id }]);
109
+ }
110
+ if (event === 'commit-edit' || event === 'cancel-edit') {
111
+ if (state.editMode !== 'editing' || current === null) {
112
+ return fail('transition-rejection', 'tree-grid-not-editing', 'Tree-grid can only finish an active edit.');
113
+ }
114
+ return createMachineUpdate(treeGridState(expansion, state.cursor, state.selection, 'navigation'), [{ type: event, id: current }]);
115
+ }
116
+ if (state.editMode === 'editing') {
117
+ if (event === 'start-edit')
118
+ return createMachineUpdate(normalized);
119
+ return fail('transition-rejection', 'tree-grid-edit-active', 'Tree-grid navigation is suspended while a cell edit is active.', { event });
120
+ }
121
+ if (event === 'start-edit') {
122
+ if (current === null) {
123
+ return fail('transition-rejection', 'no-cursor', 'Tree-grid editing requires a cursor.');
124
+ }
125
+ return createMachineUpdate(treeGridState(expansion, state.cursor, state.selection, 'editing'), [{ type: 'begin-edit', id: current }]);
126
+ }
127
+ if (event === 'select') {
128
+ if (current === null) {
129
+ return fail('transition-rejection', 'no-cursor', 'Tree-grid selection requires a cursor.');
130
+ }
131
+ const selection = selectOne(state.selection, current, domain);
132
+ return createMachineUpdate(selection === state.selection
133
+ ? normalized
134
+ : treeGridState(expansion, state.cursor, selection, 'navigation'));
135
+ }
136
+ if (event === 'expand' || event === 'collapse') {
137
+ if (current === null)
138
+ return createMachineUpdate(normalized);
139
+ const row = model.rowOfCell(current);
140
+ if (row === null)
141
+ return createMachineUpdate(normalized);
142
+ const nextExpansion = setExpansionOpen(expansion, row, event === 'expand', model.tree);
143
+ return createMachineUpdate(nextExpansion === expansion
144
+ ? normalized
145
+ : treeGridState(nextExpansion, state.cursor, state.selection, 'navigation'));
146
+ }
147
+ const eligible = policies.eligible ?? (() => true);
148
+ let target;
149
+ if (current === null) {
150
+ const initial = findEligibleFromEdge(visible, event === 'right' || event === 'down' ? 1 : -1, {
151
+ eligible,
152
+ ...(policies.maxScan === undefined ? {} : { maxScan: policies.maxScan }),
153
+ });
154
+ if (!initial.ok)
155
+ return initial;
156
+ target = initial.value;
157
+ }
158
+ else {
159
+ const visibleRows = new Set(model.tree.visible(expansion).ids);
160
+ const movement = model.grid.move(current, event, boundary, {
161
+ eligible: (id) => {
162
+ const row = model.rowOfCell(id);
163
+ return row !== null && visibleRows.has(row) && eligible(id);
164
+ },
165
+ ...(policies.maxScan === undefined ? {} : { maxScan: policies.maxScan }),
166
+ });
167
+ if (movement.kind === 'resource-rejected')
168
+ return { ok: false, error: movement.error };
169
+ target = movement.kind === 'found' ? movement.id : null;
170
+ }
171
+ if (target === null)
172
+ return createMachineUpdate(normalized);
173
+ return createMachineUpdate(treeGridState(expansion, createCursorState(target), state.selection, 'navigation'), [{ type: 'focus', id: target }]);
174
+ }
175
+ function allCells(model) {
176
+ return cellsWhere(model, () => true);
177
+ }
178
+ function visibleCells(model, expansion) {
179
+ const visibleRows = new Set(model.tree.visible(expansion).ids);
180
+ return cellsWhere(model, (row) => visibleRows.has(row));
181
+ }
182
+ function cellsWhere(model, includeRow) {
183
+ const ids = [];
184
+ for (let rowIndex = 0; rowIndex < model.grid.rowCount; rowIndex += 1) {
185
+ const row = model.rowIDs[rowIndex];
186
+ if (row === undefined || !includeRow(row))
187
+ continue;
188
+ for (let column = 0; column < model.grid.columnCount; column += 1) {
189
+ const id = model.grid.cellAt(rowIndex, column);
190
+ if (id !== null)
191
+ ids.push(id);
192
+ }
193
+ }
194
+ return new IndexedSequence(ids);
195
+ }
196
+ function validateTreeGridState(visible, domain, state) {
197
+ if (!isTreeGridEditMode(state.editMode)) {
198
+ return {
199
+ class: 'transition-rejection',
200
+ code: 'invalid-tree-grid-edit-mode',
201
+ message: 'Tree-grid edit mode must be navigation or editing.',
202
+ };
203
+ }
204
+ if (state.cursor.current !== null && !visible.contains(state.cursor.current)) {
205
+ return {
206
+ class: 'transition-rejection',
207
+ code: 'tree-grid-cursor-hidden',
208
+ message: 'Tree-grid cursor must remain on a visible row.',
209
+ details: { current: state.cursor.current },
210
+ };
211
+ }
212
+ if (state.editMode === 'editing' && state.cursor.current === null) {
213
+ return {
214
+ class: 'transition-rejection',
215
+ code: 'tree-grid-edit-without-cursor',
216
+ message: 'Tree-grid editing requires a current cell.',
217
+ };
218
+ }
219
+ if (state.selection.size > 1 || state.selection.selected.length !== state.selection.size) {
220
+ return {
221
+ class: 'transition-rejection',
222
+ code: 'invalid-tree-grid-selection',
223
+ message: 'Tree-grid selection must contain at most one identity.',
224
+ };
225
+ }
226
+ for (const id of state.selection.selected) {
227
+ if (!domain.contains(id) || !state.selection.has(id)) {
228
+ return {
229
+ class: 'transition-rejection',
230
+ code: 'tree-grid-selection-outside-grid',
231
+ message: 'Tree-grid selection must agree with the cell grid.',
232
+ details: { id },
233
+ };
234
+ }
235
+ }
236
+ if (state.selection.anchor !== null && !domain.contains(state.selection.anchor)) {
237
+ return {
238
+ class: 'transition-rejection',
239
+ code: 'tree-grid-anchor-outside-grid',
240
+ message: 'Tree-grid selection anchor must exist in the cell grid.',
241
+ details: { anchor: state.selection.anchor },
242
+ };
243
+ }
244
+ return null;
245
+ }
246
+ function treeGridState(expansion, cursor, selection, editMode) {
247
+ return Object.freeze({ expansion, cursor, selection, editMode });
248
+ }
249
+ function sameExpansion(left, right) {
250
+ return left.ids.length === right.ids.length && left.ids.every((id, index) => id === right.ids[index]);
251
+ }
252
+ function isTreeGridEditMode(value) {
253
+ return value === 'navigation' || value === 'editing';
254
+ }
255
+ function isTreeGridEvent(value) {
256
+ if (typeof value === 'string')
257
+ return [
258
+ 'left',
259
+ 'right',
260
+ 'up',
261
+ 'down',
262
+ 'expand',
263
+ 'collapse',
264
+ 'select',
265
+ 'start-edit',
266
+ 'commit-edit',
267
+ 'cancel-edit',
268
+ ].includes(value);
269
+ return typeof value === 'object' && value !== null
270
+ && 'type' in value && 'id' in value && typeof value.id === 'string'
271
+ && (value.type === 'focus' || value.type === 'select' || value.type === 'start-edit'
272
+ || (value.type === 'set-expanded' && 'open' in value && typeof value.open === 'boolean'));
273
+ }
274
+ //# sourceMappingURL=tree-grid.js.map