@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,25 @@
1
+ import { ActionStep, Probe, ScenarioConfig, SpecBridge } from "../scenario.mjs";
2
+ //#region src/apg/toolbar.bridge.d.ts
3
+ export type ToolbarOrientation = "horizontal" | "vertical";
4
+ export interface ToolbarConfig {
5
+ readonly items: ReadonlyArray<string>;
6
+ readonly orientation: ToolbarOrientation;
7
+ readonly wrap: boolean;
8
+ readonly disabled: ReadonlyArray<number>;
9
+ }
10
+ /**
11
+ * Toolbar vocabulary <-> `specs/apg/toolbar.qnt`. The spec's fixture is fixed at
12
+ * five items (0 menu-button, 1 button, 2 text, 3 spin, 4 button); the fixture
13
+ * maps item-kind tokens onto that shape, and a `menutrigger` token becomes item
14
+ * 0. The roving-tabindex part is the platform's `focusgroup` contract (see
15
+ * `shared/focusgroup.qnt`); this bridge reads the spec's delta (axis, wrap,
16
+ * disabled-but-focusable, embedded consumers) plus the menu-button: while the
17
+ * menu is open, focus is the menu item, the popup is visible and item 0 carries
18
+ * aria-expanded.
19
+ */
20
+ export declare const toolbarConfig: (config: ScenarioConfig) => ToolbarConfig;
21
+ export declare const toolbarBridge: SpecBridge;
22
+ /** The user-level steps a differential walk draws from. */
23
+ export declare const toolbarSteps: ReadonlyArray<ActionStep>;
24
+ export declare const toolbarProbe: Probe;
25
+ //#endregion
@@ -0,0 +1,307 @@
1
+ import { Unsupported } from "../scenario.mjs";
2
+ //#region src/apg/toolbar.bridge.ts
3
+ const specEvent = (tag, params = {}) => ({
4
+ _tag: tag,
5
+ ...params
6
+ });
7
+ const UNMODELLED_TOKENS = /* @__PURE__ */ new Set([
8
+ "separator",
9
+ "combobox",
10
+ "numberfield",
11
+ "modaltrigger",
12
+ "group"
13
+ ]);
14
+ const isMenuTrigger = (entry) => entry.toLowerCase().includes("menutrigger");
15
+ const toItems = (value) => {
16
+ if (typeof value === "number") {
17
+ if (!Number.isInteger(value) || value < 0) throw new Unsupported(`items ${String(value)}`);
18
+ return Array.from({ length: value }, () => "button");
19
+ }
20
+ if (Array.isArray(value) && value.every((v) => typeof v === "string")) {
21
+ for (const entry of value) {
22
+ if (isMenuTrigger(entry)) continue;
23
+ if (entry.includes(":") || UNMODELLED_TOKENS.has(entry.toLowerCase())) throw new Unsupported(`item ${entry}`);
24
+ }
25
+ return value.map((entry) => isMenuTrigger(entry) ? "menutrigger" : entry);
26
+ }
27
+ throw new Unsupported(`items ${JSON.stringify(value)}`);
28
+ };
29
+ const toIndices = (value) => {
30
+ if (Array.isArray(value) && value.every((v) => typeof v === "number" && Number.isInteger(v))) return value;
31
+ throw new Unsupported(`disabled ${JSON.stringify(value)}`);
32
+ };
33
+ /**
34
+ * Toolbar vocabulary <-> `specs/apg/toolbar.qnt`. The spec's fixture is fixed at
35
+ * five items (0 menu-button, 1 button, 2 text, 3 spin, 4 button); the fixture
36
+ * maps item-kind tokens onto that shape, and a `menutrigger` token becomes item
37
+ * 0. The roving-tabindex part is the platform's `focusgroup` contract (see
38
+ * `shared/focusgroup.qnt`); this bridge reads the spec's delta (axis, wrap,
39
+ * disabled-but-focusable, embedded consumers) plus the menu-button: while the
40
+ * menu is open, focus is the menu item, the popup is visible and item 0 carries
41
+ * aria-expanded.
42
+ */
43
+ const toolbarConfig = (config) => {
44
+ let items = [];
45
+ let orientation = "horizontal";
46
+ let wrap = false;
47
+ let disabled = [];
48
+ for (const [key, value] of Object.entries(config)) switch (key) {
49
+ case "items":
50
+ items = toItems(value);
51
+ break;
52
+ case "orientation":
53
+ if (value !== "horizontal" && value !== "vertical") throw new Unsupported(`orientation ${JSON.stringify(value)}`);
54
+ orientation = value;
55
+ break;
56
+ case "loopFocus":
57
+ wrap = value === true;
58
+ break;
59
+ case "disabled":
60
+ case "disabledIndices":
61
+ disabled = toIndices(value);
62
+ break;
63
+ case "direction":
64
+ if (value !== "ltr") throw new Unsupported(`direction ${JSON.stringify(value)}`);
65
+ break;
66
+ case "role":
67
+ if (value !== "toolbar") throw new Unsupported(`role ${JSON.stringify(value)}`);
68
+ break;
69
+ case "composite":
70
+ if (value !== true) throw new Unsupported(`composite ${JSON.stringify(value)}`);
71
+ break;
72
+ default: throw new Unsupported(`config ${key}=${JSON.stringify(value)}`);
73
+ }
74
+ if (items.length === 0) throw new Unsupported("config has no items");
75
+ return {
76
+ items,
77
+ orientation,
78
+ wrap,
79
+ disabled
80
+ };
81
+ };
82
+ const BIT = [
83
+ 1n,
84
+ 2n,
85
+ 4n,
86
+ 8n,
87
+ 16n
88
+ ];
89
+ const bit = (index) => BIT[index] ?? 0n;
90
+ const isDisabledIn = (mask, index) => mask / bit(index) % 2n === 1n;
91
+ const keyEvent = (key) => {
92
+ switch (key) {
93
+ case "ArrowLeft":
94
+ case "ArrowRight":
95
+ case "ArrowUp":
96
+ case "ArrowDown":
97
+ case "Home":
98
+ case "End": return specEvent("key", { k: key.replace("Arrow", "") });
99
+ case "Enter":
100
+ case " ":
101
+ case "Space": return specEvent("activate");
102
+ case "Escape": return specEvent("escape");
103
+ case "Tab": return specEvent("tab", { back: false });
104
+ case "Shift+Tab": return specEvent("tab", { back: true });
105
+ default: throw new Unsupported(`key ${key ?? ""}`);
106
+ }
107
+ };
108
+ const itemIndexOf = (target) => {
109
+ const match = /^item:(\d+)$/.exec(target ?? "item:0");
110
+ if (match?.[1] === void 0) throw new Unsupported(`target ${target ?? ""}`);
111
+ return Number(match[1]);
112
+ };
113
+ const programmatic = (step) => {
114
+ switch (step.prop) {
115
+ case "tabIn": return [specEvent("tabIn")];
116
+ case "leave": return [specEvent("leave")];
117
+ case "tab": return [specEvent("tab", { back: step.value?.["back"] === true })];
118
+ case "click": return [specEvent("click", { idx: BigInt(Number(step.value)) })];
119
+ case "key": {
120
+ const key = step.value?.["k"];
121
+ if (typeof key !== "string") throw new Unsupported(`prop key ${JSON.stringify(step.value)}`);
122
+ const named = [
123
+ "Left",
124
+ "Right",
125
+ "Up",
126
+ "Down"
127
+ ].includes(key) ? `Arrow${key}` : key;
128
+ return [keyEvent(named)];
129
+ }
130
+ case "activate": return [specEvent("activate")];
131
+ case "toggleDisabled": return [specEvent("toggleDisabled", { idx: BigInt(Number(step.value)) })];
132
+ case "flipOrientation": return [specEvent("flipOrientation")];
133
+ case "flipWrap": return [specEvent("flipWrap")];
134
+ default: throw new Unsupported(`prop ${step.prop ?? ""}`);
135
+ }
136
+ };
137
+ const toolbarBridge = {
138
+ setup: (config) => {
139
+ const mount = toolbarConfig(config);
140
+ return [
141
+ ...mount.orientation === "vertical" ? [specEvent("flipOrientation")] : [],
142
+ ...mount.wrap ? [specEvent("flipWrap")] : [],
143
+ ...mount.disabled.map((index) => specEvent("toggleDisabled", { idx: BigInt(index) }))
144
+ ];
145
+ },
146
+ event: (step) => {
147
+ if (step.repeat === true) throw new Unsupported("key repeat");
148
+ switch (step.event) {
149
+ case "focus": return [specEvent("tabIn")];
150
+ case "blur": return [specEvent("leave")];
151
+ case "click": return [specEvent("click", { idx: BigInt(itemIndexOf(step.target)) })];
152
+ case "key": return [keyEvent(step.key)];
153
+ case "hover":
154
+ case "unhover":
155
+ case "wait": return [];
156
+ case "prop": return programmatic(step);
157
+ default: throw new Unsupported(`event ${step.event}`);
158
+ }
159
+ },
160
+ focus: (state) => {
161
+ if (state["menuOpen"] === true) return `menuitem:${Number(state["menuIndex"])}`;
162
+ const focus = Number(state["focus"]);
163
+ return focus >= 0 ? `item:${focus}` : null;
164
+ },
165
+ attr: (state, target, name) => {
166
+ if (target === "toolbar") {
167
+ if (name === "role") return "toolbar";
168
+ if (name === "aria-orientation") return String(state["orientation"]);
169
+ throw new Unsupported(`attribute ${name} on toolbar`);
170
+ }
171
+ const index = itemIndexOf(target);
172
+ if (name === "tabindex") return Number(state["tabStop"]) === index ? "0" : "-1";
173
+ if (name === "aria-disabled") {
174
+ const mask = typeof state["disabledMask"] === "bigint" ? state["disabledMask"] : 0n;
175
+ return isDisabledIn(mask, index) ? "true" : null;
176
+ }
177
+ if (index === 0 && name === "aria-haspopup") return "menu";
178
+ if (index === 0 && name === "aria-expanded") return String(state["menuOpen"] === true);
179
+ throw new Unsupported(`attribute ${name} on ${target}`);
180
+ },
181
+ visible: (state) => state["menuOpen"] === true ? ["popup"] : [],
182
+ events: () => []
183
+ };
184
+ /** The user-level steps a differential walk draws from. */
185
+ const toolbarSteps = [
186
+ {
187
+ event: "prop",
188
+ prop: "tabIn"
189
+ },
190
+ {
191
+ event: "prop",
192
+ prop: "leave"
193
+ },
194
+ {
195
+ event: "prop",
196
+ prop: "tab",
197
+ value: { back: false }
198
+ },
199
+ {
200
+ event: "prop",
201
+ prop: "tab",
202
+ value: { back: true }
203
+ },
204
+ {
205
+ event: "prop",
206
+ prop: "click",
207
+ value: 0
208
+ },
209
+ {
210
+ event: "prop",
211
+ prop: "click",
212
+ value: 1
213
+ },
214
+ {
215
+ event: "prop",
216
+ prop: "click",
217
+ value: 2
218
+ },
219
+ {
220
+ event: "prop",
221
+ prop: "click",
222
+ value: 3
223
+ },
224
+ {
225
+ event: "prop",
226
+ prop: "click",
227
+ value: 4
228
+ },
229
+ {
230
+ event: "prop",
231
+ prop: "key",
232
+ value: { k: "Left" }
233
+ },
234
+ {
235
+ event: "prop",
236
+ prop: "key",
237
+ value: { k: "Right" }
238
+ },
239
+ {
240
+ event: "prop",
241
+ prop: "key",
242
+ value: { k: "Up" }
243
+ },
244
+ {
245
+ event: "prop",
246
+ prop: "key",
247
+ value: { k: "Down" }
248
+ },
249
+ {
250
+ event: "prop",
251
+ prop: "key",
252
+ value: { k: "Home" }
253
+ },
254
+ {
255
+ event: "prop",
256
+ prop: "key",
257
+ value: { k: "End" }
258
+ },
259
+ {
260
+ event: "prop",
261
+ prop: "key",
262
+ value: { k: "Escape" }
263
+ },
264
+ {
265
+ event: "prop",
266
+ prop: "activate"
267
+ },
268
+ {
269
+ event: "prop",
270
+ prop: "toggleDisabled",
271
+ value: 0
272
+ },
273
+ {
274
+ event: "prop",
275
+ prop: "toggleDisabled",
276
+ value: 3
277
+ },
278
+ {
279
+ event: "prop",
280
+ prop: "flipOrientation"
281
+ },
282
+ {
283
+ event: "prop",
284
+ prop: "flipWrap"
285
+ }
286
+ ];
287
+ const toolbarProbe = {
288
+ attrs: [
289
+ ["toolbar", "role"],
290
+ ["toolbar", "aria-orientation"],
291
+ ["item:0", "tabindex"],
292
+ ["item:0", "aria-disabled"],
293
+ ["item:0", "aria-haspopup"],
294
+ ["item:0", "aria-expanded"],
295
+ ["item:1", "tabindex"],
296
+ ["item:1", "aria-disabled"],
297
+ ["item:2", "tabindex"],
298
+ ["item:2", "aria-disabled"],
299
+ ["item:3", "tabindex"],
300
+ ["item:3", "aria-disabled"],
301
+ ["item:4", "tabindex"],
302
+ ["item:4", "aria-disabled"]
303
+ ],
304
+ events: []
305
+ };
306
+ //#endregion
307
+ export { toolbarBridge, toolbarConfig, toolbarProbe, toolbarSteps };