@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,27 @@
1
+ import { ActionStep, Probe, ScenarioConfig, SpecBridge } from "../scenario.mjs";
2
+ //#region src/apg/menu-menubar.bridge.d.ts
3
+ /**
4
+ * Menubar vocabulary <-> `specs/apg/menu-menubar.qnt`, shared by the spec
5
+ * driver and the DOM driver. The spec's fixture is fixed:
6
+ *
7
+ * menubar: 1 File (menu of 3, item 2 has a submenu of 2) 2 Edit (menu of 2)
8
+ * 3 About (no menu)
9
+ *
10
+ * `menuitem:0` is a menubar item; `menuitem:0/1` item 2 of File's menu;
11
+ * `menuitem:0/1/0` item 1 of that submenu; `menu:0` / `submenu:1` are the
12
+ * popups. Config keys other than `items` / `orientation` are unsupported.
13
+ */
14
+ export interface MenuMenubarConfig {
15
+ readonly items: ReadonlyArray<string>;
16
+ readonly orientation: "horizontal" | "vertical";
17
+ readonly controlled: boolean;
18
+ readonly accepts: boolean;
19
+ /** The controlled open top menu (0..2). */
20
+ readonly value: number;
21
+ }
22
+ export declare const menuMenubarConfig: (config: ScenarioConfig) => MenuMenubarConfig;
23
+ export declare const menuMenubarBridge: SpecBridge;
24
+ /** The user-level steps a differential walk draws from. */
25
+ export declare const menuMenubarSteps: ReadonlyArray<ActionStep>;
26
+ export declare const menuMenubarProbe: Probe;
27
+ //#endregion
@@ -0,0 +1,273 @@
1
+ import { Unsupported } from "../scenario.mjs";
2
+ //#region src/apg/menu-menubar.bridge.ts
3
+ const specEvent = (tag, params = {}) => ({
4
+ _tag: tag,
5
+ ...params
6
+ });
7
+ const CONFIG_KEYS = /* @__PURE__ */ new Set([
8
+ "items",
9
+ "orientation",
10
+ "controlled",
11
+ "accepts",
12
+ "value"
13
+ ]);
14
+ const toItems = (value) => {
15
+ if (Array.isArray(value) && value.every((v) => typeof v === "string")) return value;
16
+ throw new Unsupported(`items ${JSON.stringify(value)}`);
17
+ };
18
+ const menuMenubarConfig = (config) => {
19
+ let items = [];
20
+ let orientation = "horizontal";
21
+ let controlled = false;
22
+ let accepts = true;
23
+ let value = 0;
24
+ for (const [key, raw] of Object.entries(config)) {
25
+ if (!CONFIG_KEYS.has(key)) throw new Unsupported(`config ${key}=${JSON.stringify(raw)}`);
26
+ if (key === "items") items = toItems(raw);
27
+ else if (key === "orientation") {
28
+ if (raw !== "horizontal" && raw !== "vertical") throw new Unsupported(`orientation ${JSON.stringify(raw)}`);
29
+ orientation = raw;
30
+ } else if (key === "controlled") controlled = raw === true;
31
+ else if (key === "accepts") {
32
+ controlled = true;
33
+ accepts = raw === true;
34
+ } else if (key === "value") {
35
+ const top = typeof raw === "number" ? raw : NaN;
36
+ if (top < 0 || top > 2 || !Number.isInteger(top)) throw new Unsupported(`value ${JSON.stringify(raw)}`);
37
+ controlled = true;
38
+ value = top;
39
+ }
40
+ }
41
+ if (items.length === 0) throw new Unsupported("config has no items");
42
+ return {
43
+ items,
44
+ orientation,
45
+ controlled,
46
+ accepts,
47
+ value
48
+ };
49
+ };
50
+ /** `menuitem:0/1` -> the numeric path. */
51
+ const pathOf = (target) => {
52
+ return target.replace(/^menuitem:/, "").split("/").filter((part) => part.length > 0).map((part) => {
53
+ const value = Number(part);
54
+ if (!Number.isInteger(value)) throw new Unsupported(`target ${target}`);
55
+ return value;
56
+ });
57
+ };
58
+ const hasSubDom = (bar, item) => bar === 0 && item === 1;
59
+ const menuSize = (bar) => {
60
+ if (bar === 0) return 3;
61
+ if (bar === 1) return 2;
62
+ return 0;
63
+ };
64
+ const assertTarget = (target) => {
65
+ if (target === void 0 || target === "menubar" || target === "outside") return;
66
+ if (target === "submenu:1") return;
67
+ const menu = /^menu:(\d+)$/.exec(target);
68
+ if (menu?.[1] !== void 0) {
69
+ if (Number(menu[1]) > 1) throw new Unsupported(`target ${target}`);
70
+ return;
71
+ }
72
+ if (!target.startsWith("menuitem:")) throw new Unsupported(`target ${target}`);
73
+ const path = pathOf(target);
74
+ if (path.length === 1) {
75
+ if ((path[0] ?? 0) > 2) throw new Unsupported(`target ${target}`);
76
+ return;
77
+ }
78
+ if (path.length === 2) {
79
+ const bar = path[0] ?? 0;
80
+ const item = path[1] ?? 0;
81
+ if (bar > 2 || item >= menuSize(bar)) throw new Unsupported(`target ${target}`);
82
+ return;
83
+ }
84
+ if (path.length === 3) {
85
+ if (!hasSubDom(path[0] ?? 0, path[1] ?? 0) || (path[2] ?? 0) > 1) throw new Unsupported(`target ${target}`);
86
+ return;
87
+ }
88
+ throw new Unsupported(`target ${target}`);
89
+ };
90
+ const keyEvent = (key) => {
91
+ switch (key) {
92
+ case "Enter": return specEvent("activate", { key: "Enter" });
93
+ case " ":
94
+ case "Space": return specEvent("activate", { key: "Space" });
95
+ case "ArrowRight": return specEvent("arrow_right");
96
+ case "ArrowLeft": return specEvent("arrow_left");
97
+ case "ArrowDown": return specEvent("arrow_down");
98
+ case "ArrowUp": return specEvent("arrow_up");
99
+ case "Home": return specEvent("key_home");
100
+ case "End": return specEvent("key_end");
101
+ case "Escape": return specEvent("escape");
102
+ case "Tab":
103
+ case "Shift+Tab": return specEvent("tab_out");
104
+ default: throw new Unsupported(`key ${key ?? ""}`);
105
+ }
106
+ };
107
+ const charCode = (text) => {
108
+ switch ((text ?? "").slice(0, 1).toLowerCase()) {
109
+ case "a":
110
+ case "1": return 1n;
111
+ case "b":
112
+ case "2": return 2n;
113
+ case "c":
114
+ case "3": return 3n;
115
+ default: return 1n;
116
+ }
117
+ };
118
+ const programmatic = (step) => {
119
+ switch (step.prop) {
120
+ case "focus": return [specEvent("focus_in")];
121
+ case "leave": return [specEvent("tab_out")];
122
+ case "key": {
123
+ const key = step.value?.["key"];
124
+ if (typeof key !== "string") throw new Unsupported(`prop key ${JSON.stringify(step.value)}`);
125
+ return [keyEvent(key)];
126
+ }
127
+ case "typeahead": return [specEvent("typeahead", { ch: BigInt(Number(step.value)) })];
128
+ case "type": return [specEvent("typeahead", { ch: charCode(String(step.value)) })];
129
+ case "setValue": {
130
+ const top = typeof step.value === "number" ? step.value : NaN;
131
+ if (top < 0 || top > 2 || !Number.isInteger(top)) throw new Unsupported(`prop setValue=${JSON.stringify(step.value)}`);
132
+ return [specEvent("setValue", { t: BigInt(top) })];
133
+ }
134
+ case "hostToggle": return [specEvent("hostToggle")];
135
+ default: throw new Unsupported(`prop ${step.prop ?? ""}`);
136
+ }
137
+ };
138
+ const hasMenu = (bar) => bar === 1 || bar === 2;
139
+ const hasSub = (bar, item) => bar === 1 && item === 2;
140
+ const menuMenubarBridge = {
141
+ setup: (config) => {
142
+ const mount = menuMenubarConfig(config);
143
+ return [
144
+ ...mount.controlled ? [specEvent("control")] : [],
145
+ ...mount.controlled && mount.accepts ? [specEvent("acceptRequests")] : [],
146
+ ...mount.controlled && mount.value !== 0 ? [specEvent("setValue", { t: BigInt(mount.value) })] : []
147
+ ];
148
+ },
149
+ event: (step) => {
150
+ if (step.repeat === true) throw new Unsupported("key repeat");
151
+ assertTarget(step.target);
152
+ switch (step.event) {
153
+ case "focus": return [specEvent("focus_in")];
154
+ case "blur": return [specEvent("tab_out")];
155
+ case "click": return [];
156
+ case "key": return [keyEvent(step.key)];
157
+ case "type": throw new Unsupported(`type ${step.text ?? ""}`);
158
+ case "hover":
159
+ case "unhover":
160
+ case "wait": return [];
161
+ case "prop": return programmatic(step);
162
+ default: throw new Unsupported(`event ${step.event}`);
163
+ }
164
+ },
165
+ focus: (state) => {
166
+ const level = Number(state["focusLevel"]);
167
+ if (level === 1) return `menuitem:${Number(state["barStop"]) - 1}`;
168
+ if (level === 2) return `menuitem:${Number(state["openTop"]) - 1}/${Number(state["focusIdx"]) - 1}`;
169
+ if (level === 3) return `menuitem:${Number(state["openTop"]) - 1}/${Number(state["openSub"]) - 1}/${Number(state["focusIdx"]) - 1}`;
170
+ return null;
171
+ },
172
+ attr: (state, target, name) => {
173
+ if (target === "menubar") {
174
+ if (name === "role") return "menubar";
175
+ if (name === "aria-orientation") return "horizontal";
176
+ throw new Unsupported(`attribute ${name} on menubar`);
177
+ }
178
+ if (!target.startsWith("menuitem")) throw new Unsupported(`attribute ${name} on ${target}`);
179
+ const path = pathOf(target);
180
+ const barStop = Number(state["barStop"]);
181
+ const openTop = Number(state["openTop"]);
182
+ const openSub = Number(state["openSub"]);
183
+ if (path.length === 1) {
184
+ const bar = (path[0] ?? 0) + 1;
185
+ if (name === "aria-haspopup") return hasMenu(bar) ? "menu" : null;
186
+ if (name === "aria-expanded") {
187
+ if (!hasMenu(bar)) return null;
188
+ return openTop === bar ? "true" : "false";
189
+ }
190
+ if (name === "tabindex") return barStop === bar ? "0" : "-1";
191
+ } else if (path.length === 2) {
192
+ const bar = (path[0] ?? 0) + 1;
193
+ const item = (path[1] ?? 0) + 1;
194
+ if (name === "aria-haspopup") return hasSub(bar, item) ? "menu" : null;
195
+ if (name === "aria-expanded") {
196
+ if (!hasSub(bar, item)) return null;
197
+ return openTop === bar && openSub === item ? "true" : "false";
198
+ }
199
+ }
200
+ throw new Unsupported(`attribute ${name} on ${target}`);
201
+ },
202
+ visible: (state) => {
203
+ const openTop = Number(state["openTop"]);
204
+ const openSub = Number(state["openSub"]);
205
+ return [...openTop > 0 ? [`menu:${openTop - 1}`] : [], ...openSub > 0 ? ["submenu:1"] : []];
206
+ },
207
+ events: () => []
208
+ };
209
+ /** The user-level steps a differential walk draws from. */
210
+ const menuMenubarSteps = [
211
+ {
212
+ event: "prop",
213
+ prop: "focus"
214
+ },
215
+ {
216
+ event: "prop",
217
+ prop: "leave"
218
+ },
219
+ {
220
+ event: "prop",
221
+ prop: "key",
222
+ value: { key: "ArrowRight" }
223
+ },
224
+ {
225
+ event: "prop",
226
+ prop: "key",
227
+ value: { key: "ArrowLeft" }
228
+ },
229
+ {
230
+ event: "prop",
231
+ prop: "key",
232
+ value: { key: "ArrowDown" }
233
+ },
234
+ {
235
+ event: "prop",
236
+ prop: "key",
237
+ value: { key: "ArrowUp" }
238
+ },
239
+ {
240
+ event: "prop",
241
+ prop: "key",
242
+ value: { key: "Enter" }
243
+ },
244
+ {
245
+ event: "prop",
246
+ prop: "key",
247
+ value: { key: "Space" }
248
+ },
249
+ {
250
+ event: "prop",
251
+ prop: "key",
252
+ value: { key: "Escape" }
253
+ }
254
+ ];
255
+ const menuMenubarProbe = {
256
+ attrs: [
257
+ ["menubar", "role"],
258
+ ["menuitem:0", "aria-haspopup"],
259
+ ["menuitem:0", "aria-expanded"],
260
+ ["menuitem:0", "tabindex"],
261
+ ["menuitem:1", "aria-haspopup"],
262
+ ["menuitem:1", "aria-expanded"],
263
+ ["menuitem:1", "tabindex"],
264
+ ["menuitem:2", "aria-haspopup"],
265
+ ["menuitem:2", "tabindex"],
266
+ ["menu:0", "hidden"],
267
+ ["menu:1", "hidden"],
268
+ ["submenu:1", "hidden"]
269
+ ],
270
+ events: []
271
+ };
272
+ //#endregion
273
+ export { menuMenubarBridge, menuMenubarConfig, menuMenubarProbe, menuMenubarSteps };