@cssints/apg-specs 0.0.0-stage → 0.5.1

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 (260) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +65 -2
  3. package/dist/apg/accordion.bridge.d.mts +35 -0
  4. package/dist/apg/accordion.bridge.mjs +326 -0
  5. package/dist/apg/accordion.model.json +8397 -0
  6. package/dist/apg/alert.bridge.d.mts +22 -0
  7. package/dist/apg/alert.bridge.mjs +86 -0
  8. package/dist/apg/alert.model.json +871 -0
  9. package/dist/apg/alertdialog.bridge.d.mts +21 -0
  10. package/dist/apg/alertdialog.bridge.mjs +221 -0
  11. package/dist/apg/alertdialog.model.json +5232 -0
  12. package/dist/apg/breadcrumb.bridge.d.mts +26 -0
  13. package/dist/apg/breadcrumb.bridge.mjs +120 -0
  14. package/dist/apg/breadcrumb.model.json +574 -0
  15. package/dist/apg/button.bridge.d.mts +35 -0
  16. package/dist/apg/button.bridge.mjs +208 -0
  17. package/dist/apg/button.model.json +5814 -0
  18. package/dist/apg/carousel.bridge.d.mts +44 -0
  19. package/dist/apg/carousel.bridge.mjs +262 -0
  20. package/dist/apg/carousel.model.json +8963 -0
  21. package/dist/apg/checkbox-group.bridge.d.mts +25 -0
  22. package/dist/apg/checkbox-group.bridge.mjs +276 -0
  23. package/dist/apg/checkbox-group.model.json +3863 -0
  24. package/dist/apg/checkbox.bridge.d.mts +34 -0
  25. package/dist/apg/checkbox.bridge.mjs +253 -0
  26. package/dist/apg/checkbox.model.json +3158 -0
  27. package/dist/apg/combobox-autocomplete.bridge.d.mts +14 -0
  28. package/dist/apg/combobox-autocomplete.bridge.mjs +326 -0
  29. package/dist/apg/combobox-autocomplete.model.json +11586 -0
  30. package/dist/apg/combobox-dialog.bridge.d.mts +17 -0
  31. package/dist/apg/combobox-dialog.bridge.mjs +250 -0
  32. package/dist/apg/combobox-dialog.model.json +8981 -0
  33. package/dist/apg/combobox-grid.bridge.d.mts +17 -0
  34. package/dist/apg/combobox-grid.bridge.mjs +227 -0
  35. package/dist/apg/combobox-grid.model.json +8554 -0
  36. package/dist/apg/combobox-select-only.bridge.d.mts +24 -0
  37. package/dist/apg/combobox-select-only.bridge.mjs +304 -0
  38. package/dist/apg/combobox-select-only.model.json +7846 -0
  39. package/dist/apg/combobox-tree.bridge.d.mts +17 -0
  40. package/dist/apg/combobox-tree.bridge.mjs +211 -0
  41. package/dist/apg/combobox-tree.model.json +9345 -0
  42. package/dist/apg/dialog-modal.bridge.d.mts +35 -0
  43. package/dist/apg/dialog-modal.bridge.mjs +186 -0
  44. package/dist/apg/dialog-modal.model.json +7580 -0
  45. package/dist/apg/disclosure.bridge.d.mts +25 -0
  46. package/dist/apg/disclosure.bridge.mjs +202 -0
  47. package/dist/apg/disclosure.model.json +4703 -0
  48. package/dist/apg/feed.bridge.d.mts +31 -0
  49. package/dist/apg/feed.bridge.mjs +246 -0
  50. package/dist/apg/feed.model.json +4523 -0
  51. package/dist/apg/grid-selection.bridge.d.mts +13 -0
  52. package/dist/apg/grid-selection.bridge.mjs +160 -0
  53. package/dist/apg/grid-selection.model.json +6974 -0
  54. package/dist/apg/grid-sort.bridge.d.mts +12 -0
  55. package/dist/apg/grid-sort.bridge.mjs +138 -0
  56. package/dist/apg/grid-sort.model.json +3799 -0
  57. package/dist/apg/grid.bridge.d.mts +54 -0
  58. package/dist/apg/grid.bridge.mjs +441 -0
  59. package/dist/apg/grid.model.json +3802 -0
  60. package/dist/apg/link.bridge.d.mts +24 -0
  61. package/dist/apg/link.bridge.mjs +126 -0
  62. package/dist/apg/link.model.json +694 -0
  63. package/dist/apg/listbox-multi.bridge.d.mts +10 -0
  64. package/dist/apg/listbox-multi.bridge.mjs +261 -0
  65. package/dist/apg/listbox-multi.model.json +10893 -0
  66. package/dist/apg/listbox-rearrangeable.bridge.d.mts +20 -0
  67. package/dist/apg/listbox-rearrangeable.bridge.mjs +237 -0
  68. package/dist/apg/listbox-rearrangeable.model.json +17592 -0
  69. package/dist/apg/listbox-shared.d.mts +58 -0
  70. package/dist/apg/listbox-shared.mjs +171 -0
  71. package/dist/apg/listbox-single.bridge.d.mts +10 -0
  72. package/dist/apg/listbox-single.bridge.mjs +196 -0
  73. package/dist/apg/listbox-single.model.json +8024 -0
  74. package/dist/apg/listbox-typeahead.bridge.d.mts +10 -0
  75. package/dist/apg/listbox-typeahead.bridge.mjs +153 -0
  76. package/dist/apg/listbox-typeahead.model.json +5615 -0
  77. package/dist/apg/menu-button.bridge.d.mts +29 -0
  78. package/dist/apg/menu-button.bridge.mjs +259 -0
  79. package/dist/apg/menu-button.model.json +5706 -0
  80. package/dist/apg/menu-checkable.bridge.d.mts +25 -0
  81. package/dist/apg/menu-checkable.bridge.mjs +226 -0
  82. package/dist/apg/menu-checkable.model.json +4277 -0
  83. package/dist/apg/menu-menubar.bridge.d.mts +27 -0
  84. package/dist/apg/menu-menubar.bridge.mjs +273 -0
  85. package/dist/apg/menu-menubar.model.json +9540 -0
  86. package/dist/apg/meter.bridge.d.mts +28 -0
  87. package/dist/apg/meter.bridge.mjs +159 -0
  88. package/dist/apg/meter.model.json +1185 -0
  89. package/dist/apg/player.bridge.d.mts +24 -0
  90. package/dist/apg/player.bridge.mjs +342 -0
  91. package/dist/apg/player.model.json +11013 -0
  92. package/dist/apg/radio.bridge.d.mts +35 -0
  93. package/dist/apg/radio.bridge.mjs +371 -0
  94. package/dist/apg/radio.model.json +5011 -0
  95. package/dist/apg/slider-multithumb.bridge.d.mts +34 -0
  96. package/dist/apg/slider-multithumb.bridge.mjs +365 -0
  97. package/dist/apg/slider-multithumb.model.json +5774 -0
  98. package/dist/apg/slider.bridge.d.mts +54 -0
  99. package/dist/apg/slider.bridge.mjs +359 -0
  100. package/dist/apg/slider.model.json +4881 -0
  101. package/dist/apg/spinbutton.bridge.d.mts +41 -0
  102. package/dist/apg/spinbutton.bridge.mjs +327 -0
  103. package/dist/apg/spinbutton.model.json +7571 -0
  104. package/dist/apg/switch.bridge.d.mts +30 -0
  105. package/dist/apg/switch.bridge.mjs +243 -0
  106. package/dist/apg/switch.model.json +3159 -0
  107. package/dist/apg/tabs.bridge.d.mts +41 -0
  108. package/dist/apg/tabs.bridge.mjs +294 -0
  109. package/dist/apg/tabs.model.json +7659 -0
  110. package/dist/apg/timeline.bridge.d.mts +36 -0
  111. package/dist/apg/timeline.bridge.mjs +265 -0
  112. package/dist/apg/timeline.model.json +6189 -0
  113. package/dist/apg/toolbar.bridge.d.mts +25 -0
  114. package/dist/apg/toolbar.bridge.mjs +307 -0
  115. package/dist/apg/toolbar.model.json +6616 -0
  116. package/dist/apg/tooltip.bridge.d.mts +36 -0
  117. package/dist/apg/tooltip.bridge.mjs +208 -0
  118. package/dist/apg/tooltip.model.json +8295 -0
  119. package/dist/apg/treegrid.bridge.d.mts +28 -0
  120. package/dist/apg/treegrid.bridge.mjs +311 -0
  121. package/dist/apg/treegrid.model.json +17358 -0
  122. package/dist/apg/treeview.bridge.d.mts +26 -0
  123. package/dist/apg/treeview.bridge.mjs +396 -0
  124. package/dist/apg/treeview.model.json +13745 -0
  125. package/dist/apg/windowsplitter.bridge.d.mts +36 -0
  126. package/dist/apg/windowsplitter.bridge.mjs +242 -0
  127. package/dist/apg/windowsplitter.model.json +6253 -0
  128. package/dist/canvas/camera.model.json +6568 -0
  129. package/dist/canvas/canvas.bridge.d.mts +190 -0
  130. package/dist/canvas/canvas.bridge.mjs +729 -0
  131. package/dist/canvas/pointer.model.json +17095 -0
  132. package/dist/scenario.d.mts +233 -0
  133. package/dist/scenario.mjs +313 -0
  134. package/package.json +57 -4
  135. package/scenarios/apg/README.md +221 -0
  136. package/scenarios/apg/accordion.base-ui.json +1005 -0
  137. package/scenarios/apg/accordion.react-aria.json +929 -0
  138. package/scenarios/apg/alert.base-ui.json +81 -0
  139. package/scenarios/apg/alert.react-aria.json +98 -0
  140. package/scenarios/apg/alertdialog.base-ui.json +331 -0
  141. package/scenarios/apg/alertdialog.react-aria.json +225 -0
  142. package/scenarios/apg/breadcrumb.react-aria.json +312 -0
  143. package/scenarios/apg/button.ariakit.json +136 -0
  144. package/scenarios/apg/button.base-ui.json +747 -0
  145. package/scenarios/apg/button.react-aria.json +443 -0
  146. package/scenarios/apg/carousel.apg.json +909 -0
  147. package/scenarios/apg/checkbox.ariakit.json +299 -0
  148. package/scenarios/apg/checkbox.base-ui.json +1126 -0
  149. package/scenarios/apg/checkbox.react-aria.json +518 -0
  150. package/scenarios/apg/combobox.ariakit.json +945 -0
  151. package/scenarios/apg/combobox.base-ui.json +2444 -0
  152. package/scenarios/apg/combobox.react-aria.json +845 -0
  153. package/scenarios/apg/dialog-modal.ariakit.json +1102 -0
  154. package/scenarios/apg/dialog-modal.base-ui.json +775 -0
  155. package/scenarios/apg/dialog-modal.react-aria.json +638 -0
  156. package/scenarios/apg/disclosure.apg.json +349 -0
  157. package/scenarios/apg/disclosure.ariakit.json +163 -0
  158. package/scenarios/apg/disclosure.base-ui.json +451 -0
  159. package/scenarios/apg/disclosure.react-aria.json +643 -0
  160. package/scenarios/apg/feed.apg.json +442 -0
  161. package/scenarios/apg/grid.ariakit.json +197 -0
  162. package/scenarios/apg/grid.base-ui.json +720 -0
  163. package/scenarios/apg/grid.react-aria.json +969 -0
  164. package/scenarios/apg/landmarks.ariakit.json +93 -0
  165. package/scenarios/apg/landmarks.react-aria.json +330 -0
  166. package/scenarios/apg/link.ariakit.json +83 -0
  167. package/scenarios/apg/link.base-ui.json +88 -0
  168. package/scenarios/apg/link.react-aria.json +186 -0
  169. package/scenarios/apg/listbox.ariakit.json +78 -0
  170. package/scenarios/apg/listbox.base-ui.json +163 -0
  171. package/scenarios/apg/listbox.react-aria.json +1118 -0
  172. package/scenarios/apg/menu-button.ariakit.json +924 -0
  173. package/scenarios/apg/menu-button.base-ui.json +1155 -0
  174. package/scenarios/apg/menu-button.react-aria.json +1080 -0
  175. package/scenarios/apg/menubar.ariakit.json +758 -0
  176. package/scenarios/apg/menubar.base-ui.json +673 -0
  177. package/scenarios/apg/meter.base-ui.json +243 -0
  178. package/scenarios/apg/meter.react-aria.json +201 -0
  179. package/scenarios/apg/radio.ariakit.json +459 -0
  180. package/scenarios/apg/radio.base-ui.json +581 -0
  181. package/scenarios/apg/radio.react-aria.json +576 -0
  182. package/scenarios/apg/slider-multithumb.base-ui.json +316 -0
  183. package/scenarios/apg/slider-multithumb.react-aria.json +363 -0
  184. package/scenarios/apg/slider.base-ui.json +544 -0
  185. package/scenarios/apg/slider.react-aria.json +456 -0
  186. package/scenarios/apg/spinbutton.base-ui.json +1688 -0
  187. package/scenarios/apg/spinbutton.react-aria.json +426 -0
  188. package/scenarios/apg/switch.base-ui.json +456 -0
  189. package/scenarios/apg/switch.react-aria.json +303 -0
  190. package/scenarios/apg/table.ariakit.json +65 -0
  191. package/scenarios/apg/table.react-aria.json +221 -0
  192. package/scenarios/apg/tabs.ariakit.json +329 -0
  193. package/scenarios/apg/tabs.base-ui.json +875 -0
  194. package/scenarios/apg/tabs.react-aria.json +644 -0
  195. package/scenarios/apg/toolbar.ariakit.json +595 -0
  196. package/scenarios/apg/toolbar.base-ui.json +1189 -0
  197. package/scenarios/apg/toolbar.react-aria.json +383 -0
  198. package/scenarios/apg/tooltip.ariakit.json +441 -0
  199. package/scenarios/apg/tooltip.base-ui.json +411 -0
  200. package/scenarios/apg/tooltip.react-aria.json +454 -0
  201. package/scenarios/apg/treegrid.apg.json +2558 -0
  202. package/scenarios/apg/treegrid.react-aria.json +5094 -0
  203. package/scenarios/apg/treeview.apg.json +928 -0
  204. package/scenarios/apg/windowsplitter.apg.json +557 -0
  205. package/scenarios/canvas/README.md +69 -0
  206. package/scenarios/canvas/camera.contract.json +237 -0
  207. package/scenarios/canvas/camera.excalidraw.json +57 -0
  208. package/scenarios/canvas/marquee.excalidraw.json +122 -0
  209. package/scenarios/canvas/pan.excalidraw.json +46 -0
  210. package/scenarios/canvas/pointer.contract.json +528 -0
  211. package/scenarios/parts.json +291 -0
  212. package/shared/aria.qnt +186 -0
  213. package/shared/details-group.qnt +50 -0
  214. package/shared/focusgroup.qnt +152 -0
  215. package/shared/invokers.qnt +81 -0
  216. package/shared/popover.qnt +71 -0
  217. package/specs/apg/STATIC.md +103 -0
  218. package/specs/apg/accordion.qnt +578 -0
  219. package/specs/apg/alert.qnt +131 -0
  220. package/specs/apg/alertdialog.qnt +455 -0
  221. package/specs/apg/breadcrumb.qnt +88 -0
  222. package/specs/apg/button.qnt +445 -0
  223. package/specs/apg/carousel.qnt +732 -0
  224. package/specs/apg/checkbox-group.qnt +388 -0
  225. package/specs/apg/checkbox.qnt +394 -0
  226. package/specs/apg/combobox-autocomplete.qnt +764 -0
  227. package/specs/apg/combobox-dialog.qnt +627 -0
  228. package/specs/apg/combobox-grid.qnt +632 -0
  229. package/specs/apg/combobox-select-only.qnt +626 -0
  230. package/specs/apg/combobox-tree.qnt +633 -0
  231. package/specs/apg/dialog-modal.qnt +499 -0
  232. package/specs/apg/disclosure.qnt +309 -0
  233. package/specs/apg/feed.qnt +485 -0
  234. package/specs/apg/grid-selection.qnt +512 -0
  235. package/specs/apg/grid-sort.qnt +330 -0
  236. package/specs/apg/grid.qnt +360 -0
  237. package/specs/apg/link.qnt +119 -0
  238. package/specs/apg/listbox-multi.qnt +799 -0
  239. package/specs/apg/listbox-rearrangeable.qnt +801 -0
  240. package/specs/apg/listbox-single.qnt +511 -0
  241. package/specs/apg/listbox-typeahead.qnt +396 -0
  242. package/specs/apg/menu-button.qnt +363 -0
  243. package/specs/apg/menu-checkable.qnt +304 -0
  244. package/specs/apg/menu-menubar.qnt +531 -0
  245. package/specs/apg/meter.qnt +129 -0
  246. package/specs/apg/player.qnt +1081 -0
  247. package/specs/apg/radio.qnt +394 -0
  248. package/specs/apg/slider-multithumb.qnt +441 -0
  249. package/specs/apg/slider.qnt +396 -0
  250. package/specs/apg/spinbutton.qnt +494 -0
  251. package/specs/apg/switch.qnt +389 -0
  252. package/specs/apg/tabs.qnt +412 -0
  253. package/specs/apg/timeline.qnt +612 -0
  254. package/specs/apg/toolbar.qnt +364 -0
  255. package/specs/apg/tooltip.qnt +553 -0
  256. package/specs/apg/treegrid.qnt +983 -0
  257. package/specs/apg/treeview.qnt +1004 -0
  258. package/specs/apg/windowsplitter.qnt +487 -0
  259. package/specs/canvas/camera.qnt +407 -0
  260. package/specs/canvas/pointer.qnt +841 -0
@@ -0,0 +1,28 @@
1
+ import { ActionStep, Probe, ScenarioConfig, SpecBridge } from "../scenario.mjs";
2
+ //#region src/apg/treegrid.bridge.d.ts
3
+ export type TreegridNav = "rowsFirst" | "cellsFirst" | "cellsOnly";
4
+ export type TreegridSelection = "single" | "multi";
5
+ /** The spec fixes a 3-column, 7-row tree (`treegrid.qnt`). */
6
+ export declare const TREEGRID_ROWS = 7;
7
+ export declare const TREEGRID_COLS = 3;
8
+ export interface TreegridConfig {
9
+ readonly nav: TreegridNav;
10
+ readonly selection: TreegridSelection;
11
+ /** Controlled: the host owns the selected rows and this is the only thing that changes them. */
12
+ readonly controlled: boolean;
13
+ /** Controlled only: the host writes every request's intent back as the value. */
14
+ readonly accepts: boolean;
15
+ /** The controlled (or initial) selected rows. */
16
+ readonly selected: ReadonlyArray<number>;
17
+ }
18
+ /**
19
+ * Scenario `config` -> mount options. The spec models a fixed tree only, so any
20
+ * dynamic `tree` / `columns` / `expanded` config is `Unsupported`. `controlled`
21
+ * (with `accepts`) is a host that owns the selection; a bare `selected` array is
22
+ * a pinned value, i.e. a host that rejects every request.
23
+ */
24
+ export declare const treegridConfig: (config: ScenarioConfig) => TreegridConfig;
25
+ export declare const treegridBridge: SpecBridge;
26
+ export declare const treegridSteps: ReadonlyArray<ActionStep>;
27
+ export declare const treegridProbe: Probe;
28
+ //#endregion
@@ -0,0 +1,311 @@
1
+ import { Unsupported } from "../scenario.mjs";
2
+ //#region src/apg/treegrid.bridge.ts
3
+ const specEvent = (tag, params = {}) => ({
4
+ _tag: tag,
5
+ ...params
6
+ });
7
+ const num = (value) => Number(value ?? 0);
8
+ /** The spec fixes a 3-column, 7-row tree (`treegrid.qnt`). */
9
+ const TREEGRID_ROWS = 7;
10
+ const TREEGRID_COLS = 3;
11
+ /** The spec's parent map: A > {A.1, A.2 > {A.2.1}}, B > {B.1, B.2}. */
12
+ const PARENTS = [
13
+ -1,
14
+ 0,
15
+ 0,
16
+ 2,
17
+ -1,
18
+ 4,
19
+ 4
20
+ ];
21
+ const ROWS = 7;
22
+ const rowIndicesOf = (value) => {
23
+ if (!Array.isArray(value)) throw new Unsupported(`selected=${JSON.stringify(value)}`);
24
+ const rows = [];
25
+ for (const entry of value) {
26
+ let row = NaN;
27
+ if (typeof entry === "number") row = entry;
28
+ else if (typeof entry === "string") row = Number(entry);
29
+ if (!Number.isInteger(row) || row < 0 || row >= ROWS) throw new Unsupported(`selected row ${JSON.stringify(entry)}`);
30
+ rows.push(row);
31
+ }
32
+ return rows;
33
+ };
34
+ /**
35
+ * Scenario `config` -> mount options. The spec models a fixed tree only, so any
36
+ * dynamic `tree` / `columns` / `expanded` config is `Unsupported`. `controlled`
37
+ * (with `accepts`) is a host that owns the selection; a bare `selected` array is
38
+ * a pinned value, i.e. a host that rejects every request.
39
+ */
40
+ const treegridConfig = (config) => {
41
+ let nav = "rowsFirst";
42
+ let selection = "single";
43
+ let controlled = false;
44
+ let accepts = false;
45
+ let pinned = false;
46
+ let selected = [];
47
+ for (const [key, value] of Object.entries(config)) if (key === "nav" || key === "navModel") {
48
+ if (value !== "rowsFirst" && value !== "cellsFirst" && value !== "cellsOnly") throw new Unsupported(`config ${key}=${JSON.stringify(value)}`);
49
+ nav = value;
50
+ } else if (key === "selection" || key === "selMode") {
51
+ if (value !== "single" && value !== "multi") throw new Unsupported(`config ${key}=${JSON.stringify(value)}`);
52
+ selection = value;
53
+ } else if (key === "controlled" && typeof value === "boolean") {
54
+ controlled = value;
55
+ accepts = value;
56
+ } else if (key === "accepts" && typeof value === "boolean") {
57
+ controlled = true;
58
+ accepts = value;
59
+ } else if (key === "selected") {
60
+ selected = rowIndicesOf(value);
61
+ controlled = true;
62
+ pinned = true;
63
+ } else throw new Unsupported(`config ${key}=${JSON.stringify(value)}`);
64
+ if (pinned) accepts = false;
65
+ return {
66
+ nav,
67
+ selection,
68
+ controlled,
69
+ accepts,
70
+ selected
71
+ };
72
+ };
73
+ const parentOf = (row) => PARENTS[row] ?? -1;
74
+ const hasChildren = (row) => PARENTS.some((parent) => parent === row);
75
+ const childCount = (parent) => PARENTS.filter((p) => p === parent).length;
76
+ const isExpanded = (state, row) => {
77
+ if (row === 0) return state["exp0"] === true;
78
+ if (row === 2) return state["exp2"] === true;
79
+ if (row === 4) return state["exp4"] === true;
80
+ return false;
81
+ };
82
+ const visible = (state, row) => {
83
+ if (row < 0 || row >= 7) return false;
84
+ let p = parentOf(row);
85
+ while (p >= 0) {
86
+ if (!isExpanded(state, p)) return false;
87
+ p = parentOf(p);
88
+ }
89
+ return true;
90
+ };
91
+ const ariaLevel = (row) => {
92
+ let level = 1;
93
+ let p = parentOf(row);
94
+ while (p >= 0) {
95
+ level += 1;
96
+ p = parentOf(p);
97
+ }
98
+ return level;
99
+ };
100
+ const ariaSetSize = (row) => {
101
+ const p = parentOf(row);
102
+ return p < 0 ? PARENTS.filter((x) => x < 0).length : childCount(p);
103
+ };
104
+ const ariaPosInSet = (row) => {
105
+ const p = parentOf(row);
106
+ let pos = 0;
107
+ for (let r = 0; r <= row; r += 1) if (parentOf(r) === p) pos += 1;
108
+ return pos;
109
+ };
110
+ const bitSet = (mask, row) => (mask & 1 << row) !== 0;
111
+ const maskOfRows = (rows) => rows.reduce((mask, row) => mask | 1 << row, 0);
112
+ const rowsOf = (mask) => Array.from({ length: 7 }, (_, row) => row).filter((row) => bitSet(mask, row));
113
+ const CELL = /^cell:(\d+),(\d+)$/;
114
+ const ROW = /^row:(\d+)$/;
115
+ const EXPANDER = /^row:(\d+)\/expander$/;
116
+ const cellOf = (target) => {
117
+ const match = CELL.exec(target ?? "");
118
+ if (match === null) throw new Unsupported(`target ${target ?? ""}`);
119
+ return {
120
+ row: Number(match[1]),
121
+ col: Number(match[2])
122
+ };
123
+ };
124
+ const KEY_EVENTS = /* @__PURE__ */ new Map([
125
+ ["ArrowRight", "right"],
126
+ ["ArrowLeft", "left"],
127
+ ["ArrowDown", "down"],
128
+ ["ArrowUp", "up"],
129
+ ["Home", "home"],
130
+ ["End", "end"],
131
+ ["Control+Home", "ctrlHome"],
132
+ ["Control+End", "ctrlEnd"],
133
+ ["Enter", "enter"],
134
+ ["Shift+Space", "toggleSelect"],
135
+ ["Control+a", "selectAll"],
136
+ ["Shift+ArrowDown", "extendDown"],
137
+ ["Shift+ArrowUp", "extendUp"]
138
+ ]);
139
+ const treegridBridge = {
140
+ setup: (config) => {
141
+ const value = treegridConfig(config);
142
+ return [
143
+ ...value.nav === "rowsFirst" ? [] : [specEvent("configureNav", { nav: value.nav })],
144
+ ...value.selection === "single" ? [] : [specEvent("configureSel", { sel: value.selection })],
145
+ ...value.controlled ? [
146
+ specEvent("control"),
147
+ ...value.accepts ? [specEvent("acceptRequests")] : [],
148
+ ...value.selected.length > 0 ? [specEvent("setValue", { v: BigInt(maskOfRows(value.selected)) })] : []
149
+ ] : []
150
+ ];
151
+ },
152
+ event: (step) => {
153
+ switch (step.event) {
154
+ case "focus":
155
+ if (step.target === void 0 || step.target === "grid") return [specEvent("focusIn")];
156
+ if (CELL.test(step.target)) {
157
+ const { row, col } = cellOf(step.target);
158
+ return [specEvent("clickCell", { cell: BigInt(row * 3 + col) })];
159
+ }
160
+ throw new Unsupported(`focus ${step.target}`);
161
+ case "blur": return [specEvent("blur")];
162
+ case "click": {
163
+ const expander = EXPANDER.exec(step.target ?? "");
164
+ if (expander !== null) {
165
+ const row = Number(expander[1]);
166
+ if (!hasChildren(row)) throw new Unsupported(`expander ${step.target}`);
167
+ return [specEvent("toggleRow", { r: BigInt(row) })];
168
+ }
169
+ const { row, col } = cellOf(step.target);
170
+ return [specEvent("clickCell", { cell: BigInt(row * 3 + col) })];
171
+ }
172
+ case "key": {
173
+ const tag = KEY_EVENTS.get(step.key ?? "");
174
+ if (tag === void 0) throw new Unsupported(`key ${step.key ?? ""}`);
175
+ return [specEvent(tag)];
176
+ }
177
+ case "hover":
178
+ case "unhover": return [];
179
+ case "prop": switch (step.prop) {
180
+ case "nav":
181
+ case "navModel":
182
+ if (step.value !== "rowsFirst" && step.value !== "cellsFirst" && step.value !== "cellsOnly") throw new Unsupported(`prop nav=${JSON.stringify(step.value)}`);
183
+ return [specEvent("configureNav", { nav: step.value })];
184
+ case "selection":
185
+ case "selMode":
186
+ if (step.value !== "single" && step.value !== "multi") throw new Unsupported(`prop selection=${JSON.stringify(step.value)}`);
187
+ return [specEvent("configureSel", { sel: step.value })];
188
+ case "selected":
189
+ case "setValue": return [specEvent("setValue", { v: BigInt(maskOfRows(rowIndicesOf(step.value))) })];
190
+ case "hostToggle": return [specEvent("hostToggle", { r: 0n })];
191
+ default: throw new Unsupported(`prop ${step.prop ?? ""}`);
192
+ }
193
+ default: throw new Unsupported(`event ${step.event}`);
194
+ }
195
+ },
196
+ focus: (state) => {
197
+ if (state["inGrid"] !== true) return null;
198
+ return state["kind"] === "row" ? `row:${num(state["frow"])}` : `cell:${num(state["frow"])},${num(state["fcol"])}`;
199
+ },
200
+ attr: (state, target, name) => {
201
+ if (target === "grid") {
202
+ if (name === "aria-multiselectable") return state["selMode"] === "multi" ? "true" : null;
203
+ throw new Unsupported(`attribute ${name} on grid`);
204
+ }
205
+ const rowMatch = ROW.exec(target);
206
+ if (rowMatch !== null) {
207
+ const row = Number(rowMatch[1]);
208
+ switch (name) {
209
+ case "aria-level": return String(ariaLevel(row));
210
+ case "aria-setsize": return String(ariaSetSize(row));
211
+ case "aria-posinset": return String(ariaPosInSet(row));
212
+ case "aria-expanded": return hasChildren(row) ? isExpanded(state, row) ? "true" : "false" : null;
213
+ case "aria-selected":
214
+ if (bitSet(num(state["selMask"]), row)) return "true";
215
+ return state["selMode"] === "multi" ? "false" : null;
216
+ case "tabindex": return visible(state, row) && state["kind"] === "row" && num(state["frow"]) === row ? "0" : "-1";
217
+ default: throw new Unsupported(`attribute ${name} on ${target}`);
218
+ }
219
+ }
220
+ const cell = cellOf(target);
221
+ if (name === "tabindex") return visible(state, cell.row) && state["kind"] === "cell" && num(state["frow"]) === cell.row && num(state["fcol"]) === cell.col ? "0" : "-1";
222
+ throw new Unsupported(`attribute ${name} on ${target}`);
223
+ },
224
+ visible: () => [],
225
+ events: (before, after) => before["requests"] === after["requests"] ? [] : [["onSelectionChange", rowsOf(Number(after["requested"]))]]
226
+ };
227
+ const treegridSteps = [
228
+ ...Array.from({ length: 21 }, (_, index) => ({
229
+ event: "click",
230
+ target: `cell:${Math.floor(index / 3)},${index % 3}`
231
+ })),
232
+ {
233
+ event: "click",
234
+ target: "row:0/expander"
235
+ },
236
+ {
237
+ event: "click",
238
+ target: "row:2/expander"
239
+ },
240
+ {
241
+ event: "click",
242
+ target: "row:4/expander"
243
+ },
244
+ ...[
245
+ "ArrowRight",
246
+ "ArrowLeft",
247
+ "ArrowDown",
248
+ "ArrowUp",
249
+ "Home",
250
+ "End",
251
+ "Control+Home",
252
+ "Control+End",
253
+ "Enter",
254
+ "Shift+Space",
255
+ "Control+a",
256
+ "Shift+ArrowDown",
257
+ "Shift+ArrowUp"
258
+ ].map((key) => ({
259
+ event: "key",
260
+ key,
261
+ target: "grid"
262
+ })),
263
+ {
264
+ event: "focus",
265
+ target: "grid"
266
+ },
267
+ {
268
+ event: "blur",
269
+ target: "grid"
270
+ },
271
+ {
272
+ event: "prop",
273
+ prop: "hostToggle"
274
+ },
275
+ {
276
+ event: "prop",
277
+ prop: "selected",
278
+ value: [0]
279
+ },
280
+ {
281
+ event: "prop",
282
+ prop: "selected",
283
+ value: [4]
284
+ },
285
+ {
286
+ event: "prop",
287
+ prop: "selected",
288
+ value: []
289
+ }
290
+ ];
291
+ const treegridProbe = {
292
+ attrs: [
293
+ ["grid", "aria-multiselectable"],
294
+ ...Array.from({ length: 7 }, (_, row) => {
295
+ return [
296
+ [`row:${row}`, "aria-level"],
297
+ [`row:${row}`, "aria-setsize"],
298
+ [`row:${row}`, "aria-posinset"],
299
+ [`row:${row}`, "aria-expanded"],
300
+ [`row:${row}`, "aria-selected"],
301
+ [`row:${row}`, "tabindex"]
302
+ ];
303
+ }).flat(),
304
+ ...Array.from({ length: 21 }, (_, index) => {
305
+ return [`cell:${Math.floor(index / 3)},${index % 3}`, "tabindex"];
306
+ })
307
+ ],
308
+ events: ["onSelectionChange"]
309
+ };
310
+ //#endregion
311
+ export { TREEGRID_COLS, TREEGRID_ROWS, treegridBridge, treegridConfig, treegridProbe, treegridSteps };