@cssints/apg-specs 0.0.0-stage → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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,41 @@
1
+ import { ActionStep, Probe, ScenarioConfig, SpecBridge } from "../scenario.mjs";
2
+ //#region src/apg/spinbutton.bridge.d.ts
3
+ /**
4
+ * Spinbutton vocabulary <-> `specs/apg/spinbutton.qnt`, shared by the spec
5
+ * driver and the DOM driver.
6
+ *
7
+ * Parts: `input` (role=spinbutton, the only tab stop), `increment` and
8
+ * `decrement` (tabindex -1), plus the fixture `group`. The spec fixes min 1,
9
+ * max 12, step 1, page 3 and initial value 5; config that changes the range,
10
+ * step or start value is `Unsupported`. The uncommitted draft is a fixed pool
11
+ * of sample texts (`"" / "5" / "12" / "13" / "0" / "abc"`), so a scenario `type`
12
+ * step is `Unsupported` (the replay driver cannot type either); the walk enters
13
+ * the pool through `prop: type` steps, mirroring the listbox typeahead bridge.
14
+ *
15
+ * Controlled (map ticket rt1p): `controlled` puts the committed value in a host;
16
+ * a `value` alongside it pins the host (a rejecting host), `controlled` alone
17
+ * accepts every request. `setValue` / `hostToggle` are the host writing the
18
+ * value; they are inert while uncontrolled.
19
+ *
20
+ * `wrap` maps to `setWrap`; `buttons` only says the fixture renders the
21
+ * steppers and is neutral.
22
+ */
23
+ export interface SpinbuttonConfig {
24
+ readonly value: number;
25
+ readonly min: number;
26
+ readonly max: number;
27
+ readonly step: number;
28
+ readonly largeStep: number;
29
+ readonly wrap: boolean;
30
+ readonly buttons: boolean;
31
+ readonly controlled: boolean;
32
+ /** Controlled only: the host writes every request's intent back as the value. */
33
+ readonly accepts: boolean;
34
+ }
35
+ /** Scenario `config` -> what both targets are mounted with. */
36
+ export declare const spinbuttonConfig: (config: ScenarioConfig) => SpinbuttonConfig;
37
+ export declare const spinbuttonBridge: SpecBridge;
38
+ /** The user-level steps a differential walk draws from. */
39
+ export declare const spinbuttonSteps: ReadonlyArray<ActionStep>;
40
+ export declare const spinbuttonProbe: Probe;
41
+ //#endregion
@@ -0,0 +1,327 @@
1
+ import { Unsupported } from "../scenario.mjs";
2
+ //#region src/apg/spinbutton.bridge.ts
3
+ const specEvent = (tag, params = {}) => ({
4
+ _tag: tag,
5
+ ...params
6
+ });
7
+ const MIN = 1;
8
+ const MAX = 12;
9
+ const STEP = 1;
10
+ const LARGE_STEP = 3;
11
+ const INITIAL_VALUE = 5;
12
+ const DRAFT_POOL = /* @__PURE__ */ new Set([
13
+ "",
14
+ "5",
15
+ "12",
16
+ "13",
17
+ "0",
18
+ "abc"
19
+ ]);
20
+ const numberEquals = (key, value, expected) => {
21
+ if (typeof value !== "number" || value !== expected) throw new Unsupported(`config ${key}=${JSON.stringify(value)}`);
22
+ };
23
+ /** Scenario `config` -> what both targets are mounted with. */
24
+ const spinbuttonConfig = (config) => {
25
+ let value = INITIAL_VALUE;
26
+ let min = MIN;
27
+ let max = MAX;
28
+ let step = STEP;
29
+ let largeStep = LARGE_STEP;
30
+ let wrap = false;
31
+ let buttons = false;
32
+ let controlled = false;
33
+ let pinned = false;
34
+ for (const [key, raw] of Object.entries(config)) switch (key) {
35
+ case "value": {
36
+ const number = Number(raw);
37
+ if (number !== INITIAL_VALUE) throw new Unsupported(`config ${key}=${JSON.stringify(raw)}`);
38
+ value = number;
39
+ pinned = true;
40
+ break;
41
+ }
42
+ case "defaultValue": {
43
+ const number = Number(raw);
44
+ if (number !== INITIAL_VALUE) throw new Unsupported(`config ${key}=${JSON.stringify(raw)}`);
45
+ value = number;
46
+ break;
47
+ }
48
+ case "min":
49
+ numberEquals(key, raw, MIN);
50
+ min = MIN;
51
+ break;
52
+ case "max":
53
+ numberEquals(key, raw, MAX);
54
+ max = MAX;
55
+ break;
56
+ case "step":
57
+ numberEquals(key, raw, STEP);
58
+ step = STEP;
59
+ break;
60
+ case "smallStep":
61
+ numberEquals(key, raw, STEP);
62
+ break;
63
+ case "largeStep":
64
+ numberEquals(key, raw, LARGE_STEP);
65
+ largeStep = LARGE_STEP;
66
+ break;
67
+ case "wrap":
68
+ if (typeof raw !== "boolean") throw new Unsupported(`config wrap=${JSON.stringify(raw)}`);
69
+ wrap = raw;
70
+ break;
71
+ case "buttons":
72
+ if (typeof raw !== "boolean") throw new Unsupported(`config buttons=${JSON.stringify(raw)}`);
73
+ buttons = raw;
74
+ break;
75
+ case "controlled":
76
+ if (typeof raw !== "boolean") throw new Unsupported(`config controlled=${JSON.stringify(raw)}`);
77
+ controlled = raw;
78
+ break;
79
+ default: throw new Unsupported(`config ${key}=${JSON.stringify(raw)}`);
80
+ }
81
+ return {
82
+ value,
83
+ min,
84
+ max,
85
+ step,
86
+ largeStep,
87
+ wrap,
88
+ buttons,
89
+ controlled,
90
+ accepts: controlled && !pinned
91
+ };
92
+ };
93
+ const partOf = (target) => {
94
+ const part = (target ?? "input").replace(/:\d+$/, "");
95
+ if (part === "input") return "input";
96
+ if (part === "increment") return "increment";
97
+ if (part === "decrement") return "decrement";
98
+ throw new Unsupported(`part ${part}`);
99
+ };
100
+ const onInput = (step) => {
101
+ if (partOf(step.target) !== "input") throw new Unsupported(`${step.event} on ${step.target ?? "input"}`);
102
+ };
103
+ const KEY_ACTIONS = /* @__PURE__ */ new Map([
104
+ ["ArrowUp", "arrowUp"],
105
+ ["ArrowDown", "arrowDown"],
106
+ ["PageUp", "pageUp"],
107
+ ["PageDown", "pageDown"],
108
+ ["Home", "home"],
109
+ ["End", "end"],
110
+ ["Enter", "commit"],
111
+ ["Escape", "revert"]
112
+ ]);
113
+ const draftInRange = (text) => {
114
+ const number = Number(text);
115
+ return text.trim() !== "" && Number.isFinite(number) && number >= MIN && number <= MAX;
116
+ };
117
+ const programmatic = (step) => {
118
+ switch (step.prop) {
119
+ case "type": {
120
+ const text = step.value;
121
+ if (typeof text !== "string" || !DRAFT_POOL.has(text)) throw new Unsupported(`type ${JSON.stringify(text)}`);
122
+ return [specEvent("typeText", { text })];
123
+ }
124
+ case "wrap":
125
+ if (typeof step.value !== "boolean") throw new Unsupported(`wrap ${JSON.stringify(step.value)}`);
126
+ return [specEvent("setWrap", { mode: step.value })];
127
+ case "setValue": {
128
+ if (typeof step.value !== "number") throw new Unsupported(`prop setValue=${JSON.stringify(step.value)}`);
129
+ const value = Math.round(step.value);
130
+ if (value !== step.value || value < MIN || value > MAX) throw new Unsupported(`setValue ${JSON.stringify(step.value)}`);
131
+ return [specEvent("setValue", { v: BigInt(value) })];
132
+ }
133
+ case "hostToggle": return [specEvent("hostToggle")];
134
+ default: throw new Unsupported(`prop ${step.prop ?? ""}`);
135
+ }
136
+ };
137
+ const spinbuttonBridge = {
138
+ setup: (config) => {
139
+ const mount = spinbuttonConfig(config);
140
+ return [...mount.controlled ? [
141
+ specEvent("control"),
142
+ ...mount.accepts ? [specEvent("acceptRequests")] : [],
143
+ ...mount.accepts ? [] : [specEvent("setValue", { v: BigInt(mount.value) })]
144
+ ] : [], ...mount.wrap ? [specEvent("setWrap", { mode: true })] : []];
145
+ },
146
+ event: (step) => {
147
+ switch (step.event) {
148
+ case "focus":
149
+ onInput(step);
150
+ return [specEvent("focus")];
151
+ case "blur":
152
+ onInput(step);
153
+ return [specEvent("blur")];
154
+ case "key": {
155
+ onInput(step);
156
+ const action = KEY_ACTIONS.get(step.key ?? "");
157
+ if (action === void 0 || step.repeat === true) throw new Unsupported(`key ${step.key ?? ""}`);
158
+ return [specEvent("focus"), specEvent(action)];
159
+ }
160
+ case "click": {
161
+ const part = partOf(step.target);
162
+ if (part === "increment") return [specEvent("clickIncrement")];
163
+ if (part === "decrement") return [specEvent("clickDecrement")];
164
+ throw new Unsupported(`click on ${step.target ?? ""}`);
165
+ }
166
+ case "hover":
167
+ case "unhover": return [];
168
+ case "prop": return programmatic(step);
169
+ default: throw new Unsupported(`event ${step.event}`);
170
+ }
171
+ },
172
+ value: (state) => ({ input: state["editing"] === true ? String(state["draft"] ?? "") : String(state["value"]) }),
173
+ focus: (state) => state["focused"] === true ? "input:0" : null,
174
+ attr: (state, target, name) => {
175
+ const value = Number(state["value"]);
176
+ const part = partOf(target);
177
+ if (part === "input") switch (name) {
178
+ case "role": return "spinbutton";
179
+ case "aria-valuenow": return String(value);
180
+ case "aria-valuemin": return String(MIN);
181
+ case "aria-valuemax": return String(MAX);
182
+ case "aria-invalid": return state["editing"] === true && !draftInRange(String(state["draft"])) ? "true" : null;
183
+ case "tabindex": return "0";
184
+ default: throw new Unsupported(`attribute ${name} on ${target}`);
185
+ }
186
+ if (part === "increment") {
187
+ if (name === "aria-disabled") return state["wrap"] === false && value === MAX ? "true" : null;
188
+ if (name === "tabindex") return "-1";
189
+ throw new Unsupported(`attribute ${name} on ${target}`);
190
+ }
191
+ if (name === "aria-disabled") return state["wrap"] === false && value === MIN ? "true" : null;
192
+ if (name === "tabindex") return "-1";
193
+ throw new Unsupported(`attribute ${name} on ${target}`);
194
+ },
195
+ visible: () => [],
196
+ events: (before, after) => before["requests"] === after["requests"] ? [] : [["onValueChange", Number(after["requested"])]]
197
+ };
198
+ /** The user-level steps a differential walk draws from. */
199
+ const spinbuttonSteps = [
200
+ {
201
+ event: "focus",
202
+ target: "input"
203
+ },
204
+ {
205
+ event: "blur",
206
+ target: "input"
207
+ },
208
+ {
209
+ event: "key",
210
+ target: "input",
211
+ key: "ArrowUp"
212
+ },
213
+ {
214
+ event: "key",
215
+ target: "input",
216
+ key: "ArrowDown"
217
+ },
218
+ {
219
+ event: "key",
220
+ target: "input",
221
+ key: "PageUp"
222
+ },
223
+ {
224
+ event: "key",
225
+ target: "input",
226
+ key: "PageDown"
227
+ },
228
+ {
229
+ event: "key",
230
+ target: "input",
231
+ key: "Home"
232
+ },
233
+ {
234
+ event: "key",
235
+ target: "input",
236
+ key: "End"
237
+ },
238
+ {
239
+ event: "key",
240
+ target: "input",
241
+ key: "Enter"
242
+ },
243
+ {
244
+ event: "key",
245
+ target: "input",
246
+ key: "Escape"
247
+ },
248
+ {
249
+ event: "click",
250
+ target: "increment"
251
+ },
252
+ {
253
+ event: "click",
254
+ target: "decrement"
255
+ },
256
+ {
257
+ event: "prop",
258
+ prop: "type",
259
+ value: "12"
260
+ },
261
+ {
262
+ event: "prop",
263
+ prop: "type",
264
+ value: "13"
265
+ },
266
+ {
267
+ event: "prop",
268
+ prop: "type",
269
+ value: "5"
270
+ },
271
+ {
272
+ event: "prop",
273
+ prop: "type",
274
+ value: "abc"
275
+ },
276
+ {
277
+ event: "prop",
278
+ prop: "type",
279
+ value: ""
280
+ },
281
+ {
282
+ event: "prop",
283
+ prop: "wrap",
284
+ value: true
285
+ },
286
+ {
287
+ event: "prop",
288
+ prop: "wrap",
289
+ value: false
290
+ },
291
+ {
292
+ event: "prop",
293
+ prop: "setValue",
294
+ value: 1
295
+ },
296
+ {
297
+ event: "prop",
298
+ prop: "setValue",
299
+ value: 5
300
+ },
301
+ {
302
+ event: "prop",
303
+ prop: "setValue",
304
+ value: 12
305
+ },
306
+ {
307
+ event: "prop",
308
+ prop: "hostToggle"
309
+ }
310
+ ];
311
+ const spinbuttonProbe = {
312
+ attrs: [
313
+ ["input:0", "role"],
314
+ ["input:0", "aria-valuenow"],
315
+ ["input:0", "aria-valuemin"],
316
+ ["input:0", "aria-valuemax"],
317
+ ["input:0", "aria-invalid"],
318
+ ["input:0", "tabindex"],
319
+ ["increment", "aria-disabled"],
320
+ ["decrement", "aria-disabled"],
321
+ ["increment", "tabindex"],
322
+ ["decrement", "tabindex"]
323
+ ],
324
+ events: ["onValueChange"]
325
+ };
326
+ //#endregion
327
+ export { spinbuttonBridge, spinbuttonConfig, spinbuttonProbe, spinbuttonSteps };