@stealthscale/component-a11y 0.1.0 → 0.1.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.
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-D7D4PA-g.js";
2
- import { n as recipe$1, r as recipe, t as recipe$2 } from "./recipe-BKojQp6r.js";
2
+ import { n as recipe$1, r as recipe, t as recipe$2 } from "./recipe-BM8WGKWH.js";
3
3
  import { c } from "react/compiler-runtime";
4
4
  import { createContext, use, useEffect, useId, useRef, useState } from "react";
5
5
  import { useCallbackRef, useControllableState } from "@stealthscale/hooks";
@@ -7,62 +7,62 @@ import { createRecipeContext, createSlotRecipeContext } from "@stealthscale/them
7
7
  import { jsx } from "react/jsx-runtime";
8
8
  //#region src/roving-focus/context.ts
9
9
  /**
10
- * Binds the group's recipe to the parts that draw it.
10
+ * Binds the roving-focus slot recipe to React.
11
11
  *
12
12
  * @remarks
13
- * Apart from the recipe, because an application's compiler reads the recipe at build time and
14
- * the binding needs the runtime. The root carries the orientation, and every item below it reads
15
- * its classes from the root through a context.
13
+ * The binding is a separate module from the recipe, because the theme compiler imports the recipe
14
+ * at build time and must not load the React runtime. The root resolves the variants, and each
15
+ * item reads its slot class from the root's context.
16
16
  */
17
17
  /**
18
- * Binds the recipe once: the root takes the orientation, and each item draws its slot in it.
18
+ * Creates the roving-focus recipe's `withProvider` binding for the root and `withContext` for the
19
+ * items.
19
20
  */
20
21
  const { withContext: withContext$1, withProvider: withProvider$1 } = createSlotRecipeContext(recipe);
21
22
  //#endregion
22
23
  //#region src/roving-focus/use-roving-focus.ts
23
24
  /**
24
- * Moves one tab stop through a set of controls, so a reader reaches the set with Tab and moves
25
- * inside it with the arrows.
25
+ * Implements a roving tabindex: Tab enters the group once, and the arrow keys move focus inside it.
26
26
  *
27
27
  * @remarks
28
- * A toolbar, a row of tabs and a menu bar are all one stop in the tab order, and the arrows move
29
- * which control that stop is on. The items register themselves rather than being counted by the
30
- * root, because a root cannot see through whatever composes its children. Registration order is
31
- * the order the effects ran, which is source order until something is conditional, so the list
32
- * is sorted by where the items sit in the document: what the arrows follow is what the reader
33
- * sees.
28
+ * A toolbar, a tab list and a menu bar each take one stop in the page's tab order. Items register
29
+ * themselves, because the root cannot see through the components its children are composed
30
+ * from. Registration follows effect order, which differs from source order once an item renders
31
+ * conditionally, so the registry sorts by document position and the arrows follow the order on
32
+ * screen.
34
33
  */
35
34
  /**
36
- * Maps the arrows that run down the page to the step each takes.
35
+ * Maps each block-axis arrow key to its step.
37
36
  */
38
37
  const DOWN_THE_PAGE = {
39
38
  ArrowDown: 1,
40
39
  ArrowUp: -1
41
40
  };
42
41
  /**
43
- * Maps the arrows that run along a line to the step each takes.
42
+ * Maps each inline-axis arrow key to its step in a left-to-right group.
44
43
  */
45
44
  const ALONG_THE_LINE = {
46
45
  ArrowLeft: -1,
47
46
  ArrowRight: 1
48
47
  };
49
48
  /**
50
- * Carries the group down to its items.
49
+ * Context that a root publishes its group on and every item below it reads.
51
50
  */
52
51
  const RovingFocusContext = createContext(void 0);
53
52
  /**
54
- * Orders two items by where they sit in the document.
53
+ * Compares two registrations by document position, for sorting in on-screen order.
55
54
  */
56
55
  function byDocumentPosition(first, second) {
57
56
  return (first.element.compareDocumentPosition(second.element) & Node.DOCUMENT_POSITION_FOLLOWING) === 0 ? 1 : -1;
58
57
  }
59
58
  /**
60
- * Reads what a key asks for, given the arrows the group binds and which way the line runs.
59
+ * Translates a key press into the movement it requests.
61
60
  *
62
- * @param key - The key pressed.
63
- * @param orientation - Which arrows the group moves on.
64
- * @param forward - One where the line runs left to right, minus one where it runs the other way.
65
- * @returns The step or the edge to move to, or nothing where the group does not claim the key.
61
+ * @param key - The `key` value of the keyboard event.
62
+ * @param orientation - The axes the group responds to.
63
+ * @param forward - 1 in a left-to-right group and -1 in a right-to-left one, applied to the
64
+ * inline arrows only.
65
+ * @returns The requested step or end, or undefined when the group does not handle the key.
66
66
  */
67
67
  function intentOf(key, orientation, forward) {
68
68
  if (key === "Home") return "start";
@@ -73,17 +73,17 @@ function intentOf(key, orientation, forward) {
73
73
  if (inline !== void 0) return orientation === "vertical" ? void 0 : inline * forward;
74
74
  }
75
75
  /**
76
- * Marks out the one item the group moves to, as a slice of the list it is in.
76
+ * Returns the destination item as the bounds of a one-item slice of the registration list.
77
77
  *
78
78
  * @remarks
79
- * A slice rather than an index, because the list is read at an index that is always inside it
80
- * and a lookup would still be typed as possibly absent. A slice of one is the item, and a slice
81
- * of an empty list is empty, so the caller writes no test for a case that cannot arise.
82
- * @param list - The items, in the order the reader sees them.
83
- * @param intent - The edge or the step the key asked for.
84
- * @param from - The item that holds the tab stop.
85
- * @param wrap - Whether the ends join up.
86
- * @returns The first and last index of the slice holding the item to move to.
79
+ * Slice bounds keep the caller free of a branch. An index is typed as possibly undefined even
80
+ * when it is in range, and slicing an empty list returns an empty list, so a group with no items
81
+ * needs no special case.
82
+ * @param list - The registrations in document order.
83
+ * @param intent - The step or end the key requested.
84
+ * @param from - The identifier of the item with the tab stop.
85
+ * @param wrap - Whether a step past one end continues at the other.
86
+ * @returns The start and end bounds of a slice that contains the destination item.
87
87
  */
88
88
  function spanOf(list, intent, from, wrap) {
89
89
  const last = list.length - 1;
@@ -93,141 +93,129 @@ function spanOf(list, intent, from, wrap) {
93
93
  return [to, to + 1];
94
94
  }
95
95
  /**
96
- * Keeps the items in a ref rather than in state.
96
+ * Creates a registry backed by a ref.
97
97
  *
98
98
  * @remarks
99
- * Nothing drawn depends on the list, only on which item holds the stop, so putting it in state
100
- * would draw the whole group again every time one item mounted, for a change nobody could see.
99
+ * Rendering depends on the active identifier and not on the list, so a list in state would
100
+ * re-render the whole group each time an item mounted, with no visible change.
101
101
  */
102
102
  function useRegistry() {
103
- const $ = c(6);
104
- if ($[0] !== "6879b11696c2d2a5e563183941bb99f80ab3ad4b04bbc8a7ef4c43a80f829e8d") {
105
- for (let $i = 0; $i < 6; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
106
- $[0] = "6879b11696c2d2a5e563183941bb99f80ab3ad4b04bbc8a7ef4c43a80f829e8d";
107
- }
103
+ const $ = c(5);
108
104
  let t0;
109
- if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
105
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
110
106
  t0 = [];
111
- $[1] = t0;
112
- } else t0 = $[1];
107
+ $[0] = t0;
108
+ } else t0 = $[0];
113
109
  const items = useRef(t0);
114
110
  let t1;
115
- if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
111
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
116
112
  t1 = (registration) => {
117
113
  items.current = [...items.current, registration];
118
114
  };
119
- $[2] = t1;
120
- } else t1 = $[2];
115
+ $[1] = t1;
116
+ } else t1 = $[1];
121
117
  const add = t1;
122
118
  let t2;
123
- if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
119
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
124
120
  t2 = (node) => items.current.some((item) => item.element.contains(node));
125
- $[3] = t2;
126
- } else t2 = $[3];
127
- const holds = t2;
121
+ $[2] = t2;
122
+ } else t2 = $[2];
123
+ const contains = t2;
128
124
  let t3;
129
- if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
125
+ if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
130
126
  t3 = () => items.current.toSorted(byDocumentPosition);
131
- $[4] = t3;
132
- } else t3 = $[4];
127
+ $[3] = t3;
128
+ } else t3 = $[3];
133
129
  const ordered = t3;
134
130
  let t4;
135
- if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
131
+ if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
136
132
  const remove = (id) => {
137
133
  items.current = items.current.filter((item_0) => item_0.id !== id);
138
134
  };
139
135
  t4 = {
140
136
  add,
141
- holds,
137
+ contains,
142
138
  ordered,
143
139
  remove
144
140
  };
145
- $[5] = t4;
146
- } else t4 = $[5];
141
+ $[4] = t4;
142
+ } else t4 = $[4];
147
143
  return t4;
148
144
  }
149
145
  /**
150
- * Keeps which item holds the tab stop, driven from above where a caller drives it.
146
+ * Tracks which item has the tab stop, and defers to the caller when the group is controlled.
151
147
  */
152
148
  function useTabStop(props) {
153
- const $ = c(13);
154
- if ($[0] !== "6879b11696c2d2a5e563183941bb99f80ab3ad4b04bbc8a7ef4c43a80f829e8d") {
155
- for (let $i = 0; $i < 13; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
156
- $[0] = "6879b11696c2d2a5e563183941bb99f80ab3ad4b04bbc8a7ef4c43a80f829e8d";
157
- }
149
+ const $ = c(12);
158
150
  const { activeId: driven, defaultActiveId, onActiveIdChange } = props;
159
151
  let t0;
160
- if ($[1] !== defaultActiveId || $[2] !== driven || $[3] !== onActiveIdChange) {
152
+ if ($[0] !== defaultActiveId || $[1] !== driven || $[2] !== onActiveIdChange) {
161
153
  t0 = {
162
154
  defaultValue: defaultActiveId,
163
155
  onChange: onActiveIdChange,
164
156
  value: driven
165
157
  };
166
- $[1] = defaultActiveId;
167
- $[2] = driven;
168
- $[3] = onActiveIdChange;
169
- $[4] = t0;
170
- } else t0 = $[4];
158
+ $[0] = defaultActiveId;
159
+ $[1] = driven;
160
+ $[2] = onActiveIdChange;
161
+ $[3] = t0;
162
+ } else t0 = $[3];
171
163
  const [activeId, setActiveId] = useControllableState(t0);
172
164
  const stop = useRef(activeId);
173
165
  let t1;
174
166
  let t2;
175
- if ($[5] !== activeId) {
167
+ if ($[4] !== activeId) {
176
168
  t1 = () => {
177
169
  stop.current = activeId;
178
170
  };
179
171
  t2 = [activeId];
180
- $[5] = activeId;
181
- $[6] = t1;
182
- $[7] = t2;
172
+ $[4] = activeId;
173
+ $[5] = t1;
174
+ $[6] = t2;
183
175
  } else {
184
- t1 = $[6];
185
- t2 = $[7];
176
+ t1 = $[5];
177
+ t2 = $[6];
186
178
  }
187
179
  useEffect(t1, t2);
188
180
  let t3;
189
- if ($[8] !== setActiveId) {
181
+ if ($[7] !== setActiveId) {
190
182
  t3 = (next) => {
191
183
  stop.current = next;
192
184
  setActiveId(next);
193
185
  };
194
- $[8] = setActiveId;
195
- $[9] = t3;
196
- } else t3 = $[9];
186
+ $[7] = setActiveId;
187
+ $[8] = t3;
188
+ } else t3 = $[8];
197
189
  const claim = useCallbackRef(t3);
198
190
  let t4;
199
- if ($[10] !== activeId || $[11] !== claim) {
191
+ if ($[9] !== activeId || $[10] !== claim) {
200
192
  t4 = {
201
193
  activeId,
202
194
  claim,
203
195
  stop
204
196
  };
205
- $[10] = activeId;
206
- $[11] = claim;
207
- $[12] = t4;
208
- } else t4 = $[12];
197
+ $[9] = activeId;
198
+ $[10] = claim;
199
+ $[11] = t4;
200
+ } else t4 = $[11];
209
201
  return t4;
210
202
  }
211
203
  /**
212
- * Moves one tab stop through the items that register with it.
204
+ * Moves one tab stop across the items that register with the group.
213
205
  *
214
206
  * @remarks
215
- * The first item to register takes the stop, so a group is reachable by Tab from its first
216
- * render. An item that leaves while it holds the stop hands it to whatever is first, so the
217
- * group never drops out of the tab order.
218
- * @returns The group the items read, and the handler the root binds.
207
+ * The first item to register takes the stop, so Tab reaches the group from its first render.
208
+ * When the item with the stop unmounts, the stop passes to the first remaining item in document
209
+ * order, so the group stays in the tab order.
210
+ * @returns The context value for the items and the key handler for the root.
219
211
  */
220
212
  function useRovingFocus(props) {
221
- const $ = c(23);
222
- if ($[0] !== "6879b11696c2d2a5e563183941bb99f80ab3ad4b04bbc8a7ef4c43a80f829e8d") {
223
- for (let $i = 0; $i < 23; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
224
- $[0] = "6879b11696c2d2a5e563183941bb99f80ab3ad4b04bbc8a7ef4c43a80f829e8d";
225
- }
213
+ const $ = c(22);
226
214
  const { orientation, wrap } = props;
227
- const { add, holds, ordered, remove } = useRegistry();
215
+ const { add, contains, ordered, remove } = useRegistry();
228
216
  const { activeId, claim, stop } = useTabStop(props);
229
217
  let t0;
230
- if ($[1] !== add || $[2] !== claim || $[3] !== ordered || $[4] !== remove || $[5] !== stop.current) {
218
+ if ($[0] !== add || $[1] !== claim || $[2] !== ordered || $[3] !== remove || $[4] !== stop.current) {
231
219
  t0 = (registration) => {
232
220
  add(registration);
233
221
  if (stop.current === void 0) claim(registration.id);
@@ -236,20 +224,20 @@ function useRovingFocus(props) {
236
224
  if (stop.current === registration.id) claim(ordered()[0]?.id);
237
225
  };
238
226
  };
239
- $[1] = add;
240
- $[2] = claim;
241
- $[3] = ordered;
242
- $[4] = remove;
243
- $[5] = stop.current;
244
- $[6] = t0;
245
- } else t0 = $[6];
227
+ $[0] = add;
228
+ $[1] = claim;
229
+ $[2] = ordered;
230
+ $[3] = remove;
231
+ $[4] = stop.current;
232
+ $[5] = t0;
233
+ } else t0 = $[5];
246
234
  const register = useCallbackRef(t0);
247
235
  let t1;
248
- if ($[7] !== claim || $[8] !== holds || $[9] !== ordered || $[10] !== orientation || $[11] !== stop.current || $[12] !== wrap) {
236
+ if ($[6] !== claim || $[7] !== contains || $[8] !== ordered || $[9] !== orientation || $[10] !== stop.current || $[11] !== wrap) {
249
237
  t1 = (event) => {
250
238
  if (event.ctrlKey || event.metaKey || event.altKey) return;
251
239
  const { target } = event;
252
- if (!(target instanceof Node) || !holds(target)) return;
240
+ if (!(target instanceof Node) || !contains(target)) return;
253
241
  const rightToLeft = globalThis.getComputedStyle(event.currentTarget).direction === "rtl";
254
242
  const intent = intentOf(event.key, orientation, rightToLeft ? -1 : 1);
255
243
  if (intent === void 0) return;
@@ -259,126 +247,125 @@ function useRovingFocus(props) {
259
247
  }
260
248
  event.preventDefault();
261
249
  };
262
- $[7] = claim;
263
- $[8] = holds;
264
- $[9] = ordered;
265
- $[10] = orientation;
266
- $[11] = stop.current;
267
- $[12] = wrap;
268
- $[13] = t1;
269
- } else t1 = $[13];
250
+ $[6] = claim;
251
+ $[7] = contains;
252
+ $[8] = ordered;
253
+ $[9] = orientation;
254
+ $[10] = stop.current;
255
+ $[11] = wrap;
256
+ $[12] = t1;
257
+ } else t1 = $[12];
270
258
  const onKeyDown = useCallbackRef(t1);
271
259
  let t2;
272
- if ($[14] !== claim) {
260
+ if ($[13] !== claim) {
273
261
  t2 = (id) => {
274
262
  claim(id);
275
263
  };
276
- $[14] = claim;
277
- $[15] = t2;
278
- } else t2 = $[15];
264
+ $[13] = claim;
265
+ $[14] = t2;
266
+ } else t2 = $[14];
279
267
  const onFocus = useCallbackRef(t2);
280
268
  let t3;
281
- if ($[16] !== activeId || $[17] !== onFocus || $[18] !== register) {
269
+ if ($[15] !== activeId || $[16] !== onFocus || $[17] !== register) {
282
270
  t3 = {
283
271
  activeId,
284
272
  onFocus,
285
273
  register
286
274
  };
287
- $[16] = activeId;
288
- $[17] = onFocus;
289
- $[18] = register;
290
- $[19] = t3;
291
- } else t3 = $[19];
275
+ $[15] = activeId;
276
+ $[16] = onFocus;
277
+ $[17] = register;
278
+ $[18] = t3;
279
+ } else t3 = $[18];
292
280
  const t4 = t3;
293
281
  let t5;
294
- if ($[20] !== onKeyDown || $[21] !== t4) {
282
+ if ($[19] !== onKeyDown || $[20] !== t4) {
295
283
  t5 = {
296
284
  group: t4,
297
285
  onKeyDown
298
286
  };
299
- $[20] = onKeyDown;
300
- $[21] = t4;
301
- $[22] = t5;
302
- } else t5 = $[22];
287
+ $[19] = onKeyDown;
288
+ $[20] = t4;
289
+ $[21] = t5;
290
+ } else t5 = $[21];
303
291
  return t5;
304
292
  }
305
293
  //#endregion
306
294
  //#region src/roving-focus/item.tsx
307
295
  /**
308
- * Draws one item of the group, which holds the tab stop when the arrows reach it.
296
+ * Renders one item of a roving focus group.
309
297
  *
310
298
  * @remarks
311
- * Exactly one item is reachable by Tab and every other is at minus one, which is what makes the
312
- * whole group one stop in the tab order. A disabled item registers with nothing, so the arrows
313
- * pass over it, and it does not claim the stop when a pointer focuses it: an item that claimed
314
- * the stop without registering would leave the stop pointing at nothing and take the group out
315
- * of the tab order. The element is kept in state rather than in a ref, because the effect that
316
- * registers it has to run again once the element is there, and a ref changing starts no effect.
299
+ * One item has `tabIndex` 0 and every other has -1, so the group is one stop in the tab order. A
300
+ * disabled item does not register, so the arrows step past it. It also refuses the stop when a
301
+ * pointer focuses it, because a stop on an unregistered item is unreachable by the arrows and
302
+ * removes the group from the tab order. The element is in state and not in a ref, so the
303
+ * registering effect runs again once the node exists. The group keys on the registration, so
304
+ * the item writes the DOM `id` only when the caller passes one, and a control rendered as an item
305
+ * keeps an id it needs, such as the one a menu trigger references. The item with the stop has
306
+ * `data-stop` and not `data-active`, because the theme styles `[data-active]` as a pressed
307
+ * control.
317
308
  */
318
309
  /**
319
- * Draws the element an item is laid out on.
310
+ * Renders a `div` element with the item slot's classes.
320
311
  */
321
312
  const Shell$1 = withContext$1("div", "item");
322
313
  /**
323
- * Takes the tab stop when the arrows reach it, and leaves the tab order otherwise.
314
+ * Renders an item with `tabIndex` 0 while it has the tab stop and -1 otherwise.
324
315
  *
325
- * @throws {@link Error} When it is drawn outside a group.
316
+ * @throws {@link Error} When rendered outside a root.
326
317
  */
327
318
  function Item(props) {
328
- const $ = c(27);
329
- if ($[0] !== "906ba9f383c3499089f80a6d094880677f9a2e49a204ba65b1f93dfa19d6065b") {
330
- for (let $i = 0; $i < 27; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
331
- $[0] = "906ba9f383c3499089f80a6d094880677f9a2e49a204ba65b1f93dfa19d6065b";
332
- }
319
+ const $ = c(26);
333
320
  let handed;
334
321
  let named;
335
322
  let rest;
336
323
  let t0;
337
- if ($[1] !== props) {
324
+ if ($[0] !== props) {
338
325
  ({disabled: t0, id: named, ref: handed, ...rest} = props);
339
- $[1] = props;
340
- $[2] = handed;
341
- $[3] = named;
342
- $[4] = rest;
343
- $[5] = t0;
326
+ $[0] = props;
327
+ $[1] = handed;
328
+ $[2] = named;
329
+ $[3] = rest;
330
+ $[4] = t0;
344
331
  } else {
345
- handed = $[2];
346
- named = $[3];
347
- rest = $[4];
348
- t0 = $[5];
332
+ handed = $[1];
333
+ named = $[2];
334
+ rest = $[3];
335
+ t0 = $[4];
349
336
  }
350
337
  const disabled = t0 === void 0 ? false : t0;
351
338
  const group = use(RovingFocusContext);
352
- if (group === void 0) throw new Error("RovingFocus.Item is drawn inside RovingFocus.Root and nowhere else.");
339
+ if (group === void 0) throw new Error("RovingFocus.Item must be rendered inside RovingFocus.Root.");
353
340
  const generated = useId();
354
341
  const id = named ?? generated;
355
342
  const { activeId, onFocus, register } = group;
356
343
  const [element, setElement] = useState(null);
357
344
  let t1;
358
- if ($[6] !== handed) {
345
+ if ($[5] !== handed) {
359
346
  t1 = (node) => {
360
347
  setElement(node);
361
348
  if (typeof handed === "function") handed(node);
362
349
  else if (handed !== null && handed !== void 0) handed.current = node;
363
350
  };
364
- $[6] = handed;
365
- $[7] = t1;
366
- } else t1 = $[7];
351
+ $[5] = handed;
352
+ $[6] = t1;
353
+ } else t1 = $[6];
367
354
  const attach = useCallbackRef(t1);
368
355
  let t2;
369
- if ($[8] !== disabled || $[9] !== id || $[10] !== onFocus) {
356
+ if ($[7] !== disabled || $[8] !== id || $[9] !== onFocus) {
370
357
  t2 = () => {
371
358
  if (!disabled) onFocus(id);
372
359
  };
373
- $[8] = disabled;
374
- $[9] = id;
375
- $[10] = onFocus;
376
- $[11] = t2;
377
- } else t2 = $[11];
360
+ $[7] = disabled;
361
+ $[8] = id;
362
+ $[9] = onFocus;
363
+ $[10] = t2;
364
+ } else t2 = $[10];
378
365
  const claim = useCallbackRef(t2);
379
366
  let t3;
380
367
  let t4;
381
- if ($[12] !== disabled || $[13] !== element || $[14] !== id || $[15] !== register) {
368
+ if ($[11] !== disabled || $[12] !== element || $[13] !== id || $[14] !== register) {
382
369
  t3 = () => {
383
370
  if (element === null || disabled) return;
384
371
  return register({
@@ -392,60 +379,56 @@ function Item(props) {
392
379
  id,
393
380
  register
394
381
  ];
395
- $[12] = disabled;
396
- $[13] = element;
397
- $[14] = id;
398
- $[15] = register;
399
- $[16] = t3;
400
- $[17] = t4;
382
+ $[11] = disabled;
383
+ $[12] = element;
384
+ $[13] = id;
385
+ $[14] = register;
386
+ $[15] = t3;
387
+ $[16] = t4;
401
388
  } else {
402
- t3 = $[16];
403
- t4 = $[17];
389
+ t3 = $[15];
390
+ t4 = $[16];
404
391
  }
405
392
  useEffect(t3, t4);
406
393
  const t5 = disabled || void 0;
407
- const t6 = activeId === id ? "" : void 0;
408
- const t7 = disabled ? "" : void 0;
394
+ const t6 = disabled ? "" : void 0;
395
+ const t7 = activeId === id ? "" : void 0;
409
396
  const t8 = !disabled && activeId === id ? 0 : -1;
410
397
  let t9;
411
- if ($[18] !== attach || $[19] !== claim || $[20] !== id || $[21] !== rest || $[22] !== t5 || $[23] !== t6 || $[24] !== t7 || $[25] !== t8) {
398
+ if ($[17] !== attach || $[18] !== claim || $[19] !== named || $[20] !== rest || $[21] !== t5 || $[22] !== t6 || $[23] !== t7 || $[24] !== t8) {
412
399
  t9 = /* @__PURE__ */ jsx(Shell$1, {
413
400
  "aria-disabled": t5,
414
- "data-active": t6,
415
- "data-disabled": t7,
416
- id,
401
+ "data-disabled": t6,
402
+ "data-stop": t7,
403
+ id: named,
417
404
  onFocus: claim,
418
405
  ref: attach,
419
406
  tabIndex: t8,
420
407
  ...rest
421
408
  });
422
- $[18] = attach;
423
- $[19] = claim;
424
- $[20] = id;
425
- $[21] = rest;
426
- $[22] = t5;
427
- $[23] = t6;
428
- $[24] = t7;
429
- $[25] = t8;
430
- $[26] = t9;
431
- } else t9 = $[26];
409
+ $[17] = attach;
410
+ $[18] = claim;
411
+ $[19] = named;
412
+ $[20] = rest;
413
+ $[21] = t5;
414
+ $[22] = t6;
415
+ $[23] = t7;
416
+ $[24] = t8;
417
+ $[25] = t9;
418
+ } else t9 = $[25];
432
419
  return t9;
433
420
  }
434
421
  //#endregion
435
422
  //#region src/roving-focus/root.tsx
436
423
  /**
437
- * Draws the element the group is laid out on.
424
+ * Renders a `div` element with the root slot's classes.
438
425
  */
439
426
  const Shell = withProvider$1("div", "root");
440
427
  /**
441
- * Keeps one tab stop for the items inside it, and moves it under the arrow keys.
428
+ * Keeps one tab stop for the items below it and moves the stop on the arrow keys.
442
429
  */
443
430
  function Root(props) {
444
- const $ = c(27);
445
- if ($[0] !== "16a674b835753bf9fd806b5c17b8426cf42995a3c3e2732778987a1e4a0700e7") {
446
- for (let $i = 0; $i < 27; $i += 1) $[$i] = Symbol.for("react.memo_cache_sentinel");
447
- $[0] = "16a674b835753bf9fd806b5c17b8426cf42995a3c3e2732778987a1e4a0700e7";
448
- }
431
+ const $ = c(26);
449
432
  let activeId;
450
433
  let children;
451
434
  let defaultActiveId;
@@ -453,29 +436,29 @@ function Root(props) {
453
436
  let rest;
454
437
  let t0;
455
438
  let t1;
456
- if ($[1] !== props) {
439
+ if ($[0] !== props) {
457
440
  ({activeId, children, defaultActiveId, onActiveIdChange, orientation: t0, wrap: t1, ...rest} = props);
458
- $[1] = props;
459
- $[2] = activeId;
460
- $[3] = children;
461
- $[4] = defaultActiveId;
462
- $[5] = onActiveIdChange;
463
- $[6] = rest;
464
- $[7] = t0;
465
- $[8] = t1;
441
+ $[0] = props;
442
+ $[1] = activeId;
443
+ $[2] = children;
444
+ $[3] = defaultActiveId;
445
+ $[4] = onActiveIdChange;
446
+ $[5] = rest;
447
+ $[6] = t0;
448
+ $[7] = t1;
466
449
  } else {
467
- activeId = $[2];
468
- children = $[3];
469
- defaultActiveId = $[4];
470
- onActiveIdChange = $[5];
471
- rest = $[6];
472
- t0 = $[7];
473
- t1 = $[8];
450
+ activeId = $[1];
451
+ children = $[2];
452
+ defaultActiveId = $[3];
453
+ onActiveIdChange = $[4];
454
+ rest = $[5];
455
+ t0 = $[6];
456
+ t1 = $[7];
474
457
  }
475
458
  const orientation = t0 === void 0 ? "horizontal" : t0;
476
459
  const wrap = t1 === void 0 ? false : t1;
477
460
  let t2;
478
- if ($[9] !== activeId || $[10] !== defaultActiveId || $[11] !== onActiveIdChange || $[12] !== orientation || $[13] !== wrap) {
461
+ if ($[8] !== activeId || $[9] !== defaultActiveId || $[10] !== onActiveIdChange || $[11] !== orientation || $[12] !== wrap) {
479
462
  t2 = {
480
463
  activeId,
481
464
  defaultActiveId,
@@ -483,24 +466,24 @@ function Root(props) {
483
466
  orientation,
484
467
  wrap
485
468
  };
486
- $[9] = activeId;
487
- $[10] = defaultActiveId;
488
- $[11] = onActiveIdChange;
489
- $[12] = orientation;
490
- $[13] = wrap;
491
- $[14] = t2;
492
- } else t2 = $[14];
469
+ $[8] = activeId;
470
+ $[9] = defaultActiveId;
471
+ $[10] = onActiveIdChange;
472
+ $[11] = orientation;
473
+ $[12] = wrap;
474
+ $[13] = t2;
475
+ } else t2 = $[13];
493
476
  const { group, onKeyDown } = useRovingFocus(t2);
494
477
  let t3;
495
- if ($[15] !== orientation || $[16] !== rest.role) {
478
+ if ($[14] !== orientation || $[15] !== rest.role) {
496
479
  t3 = rest.role !== void 0 && orientation !== "both" ? { "aria-orientation": orientation } : void 0;
497
- $[15] = orientation;
498
- $[16] = rest.role;
499
- $[17] = t3;
500
- } else t3 = $[17];
480
+ $[14] = orientation;
481
+ $[15] = rest.role;
482
+ $[16] = t3;
483
+ } else t3 = $[16];
501
484
  const told = t3;
502
485
  let t4;
503
- if ($[18] !== children || $[19] !== onKeyDown || $[20] !== orientation || $[21] !== rest || $[22] !== told) {
486
+ if ($[17] !== children || $[18] !== onKeyDown || $[19] !== orientation || $[20] !== rest || $[21] !== told) {
504
487
  t4 = /* @__PURE__ */ jsx(Shell, {
505
488
  onKeyDown,
506
489
  orientation,
@@ -508,23 +491,23 @@ function Root(props) {
508
491
  ...rest,
509
492
  children
510
493
  });
511
- $[18] = children;
512
- $[19] = onKeyDown;
513
- $[20] = orientation;
514
- $[21] = rest;
515
- $[22] = told;
516
- $[23] = t4;
517
- } else t4 = $[23];
494
+ $[17] = children;
495
+ $[18] = onKeyDown;
496
+ $[19] = orientation;
497
+ $[20] = rest;
498
+ $[21] = told;
499
+ $[22] = t4;
500
+ } else t4 = $[22];
518
501
  let t5;
519
- if ($[24] !== group || $[25] !== t4) {
502
+ if ($[23] !== group || $[24] !== t4) {
520
503
  t5 = /* @__PURE__ */ jsx(RovingFocusContext, {
521
504
  value: group,
522
505
  children: t4
523
506
  });
524
- $[24] = group;
525
- $[25] = t4;
526
- $[26] = t5;
527
- } else t5 = $[26];
507
+ $[23] = group;
508
+ $[24] = t4;
509
+ $[25] = t5;
510
+ } else t5 = $[25];
528
511
  return t5;
529
512
  }
530
513
  //#endregion
@@ -536,32 +519,32 @@ var roving_focus_exports = /* @__PURE__ */ __exportAll({
536
519
  //#endregion
537
520
  //#region src/skip-nav/context.ts
538
521
  /**
539
- * Binds the skip link's recipe to the parts that draw it.
522
+ * Binds the skip-nav slot recipe to React.
540
523
  *
541
524
  * @remarks
542
- * Apart from the recipe, because an application's compiler reads the recipe at build time and
543
- * the binding needs the runtime. Neither part takes a variant, so each is bound on its own
544
- * rather than one providing for the other: a page puts the link at the top and the target
545
- * further down, and the two are never nested.
525
+ * The binding is a separate module from the recipe, because the theme compiler imports the recipe
526
+ * at build time and must not load the React runtime. The link and the target each use
527
+ * `withProvider`, because neither is rendered inside the other.
546
528
  */
547
529
  /**
548
- * Binds the recipe once, for the link and for the target it jumps to.
530
+ * Creates the skip-nav recipe's `withProvider` binding.
549
531
  */
550
532
  const { withProvider } = createSlotRecipeContext(recipe$1);
551
533
  //#endregion
552
534
  //#region src/skip-nav/link.ts
553
535
  /**
554
- * The fragment the link points at and the target answers to, where neither states one.
536
+ * Fragment identifier that the link's `href` and the target's `id` default to.
555
537
  */
556
538
  const SKIP_NAV_TARGET = "content";
557
539
  /**
558
- * Jumps a keyboard past the navigation to the page's content.
540
+ * Renders an `a` element with the link slot's classes, pointing at `#content` by default.
559
541
  */
560
542
  const Link = withProvider("a", "link", { defaultProps: { href: `#${SKIP_NAV_TARGET}` } });
561
543
  //#endregion
562
544
  //#region src/skip-nav/target.ts
563
545
  /**
564
- * Takes the focus the skip link sends, and draws nothing.
546
+ * Renders a `div` element with the target slot's classes, `id="content"` and `tabIndex` -1 by
547
+ * default.
565
548
  */
566
549
  const Target = withProvider("div", "target", { defaultProps: {
567
550
  id: SKIP_NAV_TARGET,
@@ -577,21 +560,24 @@ var skip_nav_exports = /* @__PURE__ */ __exportAll({
577
560
  //#endregion
578
561
  //#region src/visually-hidden/context.ts
579
562
  /**
580
- * Binds the hidden text's recipe to the element that draws it.
563
+ * Binds the visually-hidden recipe to React.
581
564
  *
582
565
  * @remarks
583
- * Apart from the recipe, because an application's compiler reads the recipe at build time and
584
- * the binding needs the runtime. A recipe file that also bound one would put the runtime behind
585
- * every compiler configuration that reads it.
566
+ * The binding is a separate module from the recipe, because the theme compiler imports the recipe
567
+ * at build time and must not load the React runtime.
586
568
  */
587
569
  /**
588
- * Binds the recipe once, for the hidden text and for whatever sets its variants from above.
570
+ * Creates the visually-hidden recipe's `withContext` binding and its `PropsProvider`.
571
+ *
572
+ * @remarks
573
+ * `PropsProvider` sets variants on every element bound below it. The package exports it as
574
+ * `VisuallyHiddenPropsProvider`.
589
575
  */
590
576
  const { PropsProvider, withContext } = createRecipeContext(recipe$2);
591
577
  //#endregion
592
578
  //#region src/visually-hidden/visually-hidden.ts
593
579
  /**
594
- * Reads its words to a screen reader and draws them nowhere.
580
+ * Renders a `span` element with the classes of the visually-hidden recipe.
595
581
  */
596
582
  const VisuallyHidden = withContext("span");
597
583
  //#endregion