@stealthscale/component-a11y 0.1.0 → 0.1.3

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,598 +1,2 @@
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";
3
- import { c } from "react/compiler-runtime";
4
- import { createContext, use, useEffect, useId, useRef, useState } from "react";
5
- import { useCallbackRef, useControllableState } from "@stealthscale/hooks";
6
- import { createRecipeContext, createSlotRecipeContext } from "@stealthscale/theme";
7
- import { jsx } from "react/jsx-runtime";
8
- //#region src/roving-focus/context.ts
9
- /**
10
- * Binds the group's recipe to the parts that draw it.
11
- *
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.
16
- */
17
- /**
18
- * Binds the recipe once: the root takes the orientation, and each item draws its slot in it.
19
- */
20
- const { withContext: withContext$1, withProvider: withProvider$1 } = createSlotRecipeContext(recipe);
21
- //#endregion
22
- //#region src/roving-focus/use-roving-focus.ts
23
- /**
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.
26
- *
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.
34
- */
35
- /**
36
- * Maps the arrows that run down the page to the step each takes.
37
- */
38
- const DOWN_THE_PAGE = {
39
- ArrowDown: 1,
40
- ArrowUp: -1
41
- };
42
- /**
43
- * Maps the arrows that run along a line to the step each takes.
44
- */
45
- const ALONG_THE_LINE = {
46
- ArrowLeft: -1,
47
- ArrowRight: 1
48
- };
49
- /**
50
- * Carries the group down to its items.
51
- */
52
- const RovingFocusContext = createContext(void 0);
53
- /**
54
- * Orders two items by where they sit in the document.
55
- */
56
- function byDocumentPosition(first, second) {
57
- return (first.element.compareDocumentPosition(second.element) & Node.DOCUMENT_POSITION_FOLLOWING) === 0 ? 1 : -1;
58
- }
59
- /**
60
- * Reads what a key asks for, given the arrows the group binds and which way the line runs.
61
- *
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.
66
- */
67
- function intentOf(key, orientation, forward) {
68
- if (key === "Home") return "start";
69
- if (key === "End") return "end";
70
- const block = DOWN_THE_PAGE[key];
71
- if (block !== void 0) return orientation === "horizontal" ? void 0 : block;
72
- const inline = ALONG_THE_LINE[key];
73
- if (inline !== void 0) return orientation === "vertical" ? void 0 : inline * forward;
74
- }
75
- /**
76
- * Marks out the one item the group moves to, as a slice of the list it is in.
77
- *
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.
87
- */
88
- function spanOf(list, intent, from, wrap) {
89
- const last = list.length - 1;
90
- const at = list.findIndex((item) => item.id === from);
91
- const here = at === -1 ? 0 : at;
92
- const to = intent === "start" ? 0 : intent === "end" ? last : wrap ? (here + intent + list.length) % list.length : Math.min(last, Math.max(0, here + intent));
93
- return [to, to + 1];
94
- }
95
- /**
96
- * Keeps the items in a ref rather than in state.
97
- *
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.
101
- */
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
- }
108
- let t0;
109
- if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
110
- t0 = [];
111
- $[1] = t0;
112
- } else t0 = $[1];
113
- const items = useRef(t0);
114
- let t1;
115
- if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
116
- t1 = (registration) => {
117
- items.current = [...items.current, registration];
118
- };
119
- $[2] = t1;
120
- } else t1 = $[2];
121
- const add = t1;
122
- let t2;
123
- if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
124
- t2 = (node) => items.current.some((item) => item.element.contains(node));
125
- $[3] = t2;
126
- } else t2 = $[3];
127
- const holds = t2;
128
- let t3;
129
- if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
130
- t3 = () => items.current.toSorted(byDocumentPosition);
131
- $[4] = t3;
132
- } else t3 = $[4];
133
- const ordered = t3;
134
- let t4;
135
- if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
136
- const remove = (id) => {
137
- items.current = items.current.filter((item_0) => item_0.id !== id);
138
- };
139
- t4 = {
140
- add,
141
- holds,
142
- ordered,
143
- remove
144
- };
145
- $[5] = t4;
146
- } else t4 = $[5];
147
- return t4;
148
- }
149
- /**
150
- * Keeps which item holds the tab stop, driven from above where a caller drives it.
151
- */
152
- 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
- }
158
- const { activeId: driven, defaultActiveId, onActiveIdChange } = props;
159
- let t0;
160
- if ($[1] !== defaultActiveId || $[2] !== driven || $[3] !== onActiveIdChange) {
161
- t0 = {
162
- defaultValue: defaultActiveId,
163
- onChange: onActiveIdChange,
164
- value: driven
165
- };
166
- $[1] = defaultActiveId;
167
- $[2] = driven;
168
- $[3] = onActiveIdChange;
169
- $[4] = t0;
170
- } else t0 = $[4];
171
- const [activeId, setActiveId] = useControllableState(t0);
172
- const stop = useRef(activeId);
173
- let t1;
174
- let t2;
175
- if ($[5] !== activeId) {
176
- t1 = () => {
177
- stop.current = activeId;
178
- };
179
- t2 = [activeId];
180
- $[5] = activeId;
181
- $[6] = t1;
182
- $[7] = t2;
183
- } else {
184
- t1 = $[6];
185
- t2 = $[7];
186
- }
187
- useEffect(t1, t2);
188
- let t3;
189
- if ($[8] !== setActiveId) {
190
- t3 = (next) => {
191
- stop.current = next;
192
- setActiveId(next);
193
- };
194
- $[8] = setActiveId;
195
- $[9] = t3;
196
- } else t3 = $[9];
197
- const claim = useCallbackRef(t3);
198
- let t4;
199
- if ($[10] !== activeId || $[11] !== claim) {
200
- t4 = {
201
- activeId,
202
- claim,
203
- stop
204
- };
205
- $[10] = activeId;
206
- $[11] = claim;
207
- $[12] = t4;
208
- } else t4 = $[12];
209
- return t4;
210
- }
211
- /**
212
- * Moves one tab stop through the items that register with it.
213
- *
214
- * @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.
219
- */
220
- 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
- }
226
- const { orientation, wrap } = props;
227
- const { add, holds, ordered, remove } = useRegistry();
228
- const { activeId, claim, stop } = useTabStop(props);
229
- let t0;
230
- if ($[1] !== add || $[2] !== claim || $[3] !== ordered || $[4] !== remove || $[5] !== stop.current) {
231
- t0 = (registration) => {
232
- add(registration);
233
- if (stop.current === void 0) claim(registration.id);
234
- return () => {
235
- remove(registration.id);
236
- if (stop.current === registration.id) claim(ordered()[0]?.id);
237
- };
238
- };
239
- $[1] = add;
240
- $[2] = claim;
241
- $[3] = ordered;
242
- $[4] = remove;
243
- $[5] = stop.current;
244
- $[6] = t0;
245
- } else t0 = $[6];
246
- const register = useCallbackRef(t0);
247
- let t1;
248
- if ($[7] !== claim || $[8] !== holds || $[9] !== ordered || $[10] !== orientation || $[11] !== stop.current || $[12] !== wrap) {
249
- t1 = (event) => {
250
- if (event.ctrlKey || event.metaKey || event.altKey) return;
251
- const { target } = event;
252
- if (!(target instanceof Node) || !holds(target)) return;
253
- const rightToLeft = globalThis.getComputedStyle(event.currentTarget).direction === "rtl";
254
- const intent = intentOf(event.key, orientation, rightToLeft ? -1 : 1);
255
- if (intent === void 0) return;
256
- for (const moving of ordered().slice(...spanOf(ordered(), intent, stop.current, wrap))) {
257
- claim(moving.id);
258
- moving.element.focus();
259
- }
260
- event.preventDefault();
261
- };
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];
270
- const onKeyDown = useCallbackRef(t1);
271
- let t2;
272
- if ($[14] !== claim) {
273
- t2 = (id) => {
274
- claim(id);
275
- };
276
- $[14] = claim;
277
- $[15] = t2;
278
- } else t2 = $[15];
279
- const onFocus = useCallbackRef(t2);
280
- let t3;
281
- if ($[16] !== activeId || $[17] !== onFocus || $[18] !== register) {
282
- t3 = {
283
- activeId,
284
- onFocus,
285
- register
286
- };
287
- $[16] = activeId;
288
- $[17] = onFocus;
289
- $[18] = register;
290
- $[19] = t3;
291
- } else t3 = $[19];
292
- const t4 = t3;
293
- let t5;
294
- if ($[20] !== onKeyDown || $[21] !== t4) {
295
- t5 = {
296
- group: t4,
297
- onKeyDown
298
- };
299
- $[20] = onKeyDown;
300
- $[21] = t4;
301
- $[22] = t5;
302
- } else t5 = $[22];
303
- return t5;
304
- }
305
- //#endregion
306
- //#region src/roving-focus/item.tsx
307
- /**
308
- * Draws one item of the group, which holds the tab stop when the arrows reach it.
309
- *
310
- * @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.
317
- */
318
- /**
319
- * Draws the element an item is laid out on.
320
- */
321
- const Shell$1 = withContext$1("div", "item");
322
- /**
323
- * Takes the tab stop when the arrows reach it, and leaves the tab order otherwise.
324
- *
325
- * @throws {@link Error} When it is drawn outside a group.
326
- */
327
- 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
- }
333
- let handed;
334
- let named;
335
- let rest;
336
- let t0;
337
- if ($[1] !== props) {
338
- ({disabled: t0, id: named, ref: handed, ...rest} = props);
339
- $[1] = props;
340
- $[2] = handed;
341
- $[3] = named;
342
- $[4] = rest;
343
- $[5] = t0;
344
- } else {
345
- handed = $[2];
346
- named = $[3];
347
- rest = $[4];
348
- t0 = $[5];
349
- }
350
- const disabled = t0 === void 0 ? false : t0;
351
- const group = use(RovingFocusContext);
352
- if (group === void 0) throw new Error("RovingFocus.Item is drawn inside RovingFocus.Root and nowhere else.");
353
- const generated = useId();
354
- const id = named ?? generated;
355
- const { activeId, onFocus, register } = group;
356
- const [element, setElement] = useState(null);
357
- let t1;
358
- if ($[6] !== handed) {
359
- t1 = (node) => {
360
- setElement(node);
361
- if (typeof handed === "function") handed(node);
362
- else if (handed !== null && handed !== void 0) handed.current = node;
363
- };
364
- $[6] = handed;
365
- $[7] = t1;
366
- } else t1 = $[7];
367
- const attach = useCallbackRef(t1);
368
- let t2;
369
- if ($[8] !== disabled || $[9] !== id || $[10] !== onFocus) {
370
- t2 = () => {
371
- if (!disabled) onFocus(id);
372
- };
373
- $[8] = disabled;
374
- $[9] = id;
375
- $[10] = onFocus;
376
- $[11] = t2;
377
- } else t2 = $[11];
378
- const claim = useCallbackRef(t2);
379
- let t3;
380
- let t4;
381
- if ($[12] !== disabled || $[13] !== element || $[14] !== id || $[15] !== register) {
382
- t3 = () => {
383
- if (element === null || disabled) return;
384
- return register({
385
- element,
386
- id
387
- });
388
- };
389
- t4 = [
390
- disabled,
391
- element,
392
- id,
393
- register
394
- ];
395
- $[12] = disabled;
396
- $[13] = element;
397
- $[14] = id;
398
- $[15] = register;
399
- $[16] = t3;
400
- $[17] = t4;
401
- } else {
402
- t3 = $[16];
403
- t4 = $[17];
404
- }
405
- useEffect(t3, t4);
406
- const t5 = disabled || void 0;
407
- const t6 = activeId === id ? "" : void 0;
408
- const t7 = disabled ? "" : void 0;
409
- const t8 = !disabled && activeId === id ? 0 : -1;
410
- let t9;
411
- if ($[18] !== attach || $[19] !== claim || $[20] !== id || $[21] !== rest || $[22] !== t5 || $[23] !== t6 || $[24] !== t7 || $[25] !== t8) {
412
- t9 = /* @__PURE__ */ jsx(Shell$1, {
413
- "aria-disabled": t5,
414
- "data-active": t6,
415
- "data-disabled": t7,
416
- id,
417
- onFocus: claim,
418
- ref: attach,
419
- tabIndex: t8,
420
- ...rest
421
- });
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];
432
- return t9;
433
- }
434
- //#endregion
435
- //#region src/roving-focus/root.tsx
436
- /**
437
- * Draws the element the group is laid out on.
438
- */
439
- const Shell = withProvider$1("div", "root");
440
- /**
441
- * Keeps one tab stop for the items inside it, and moves it under the arrow keys.
442
- */
443
- 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
- }
449
- let activeId;
450
- let children;
451
- let defaultActiveId;
452
- let onActiveIdChange;
453
- let rest;
454
- let t0;
455
- let t1;
456
- if ($[1] !== props) {
457
- ({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;
466
- } else {
467
- activeId = $[2];
468
- children = $[3];
469
- defaultActiveId = $[4];
470
- onActiveIdChange = $[5];
471
- rest = $[6];
472
- t0 = $[7];
473
- t1 = $[8];
474
- }
475
- const orientation = t0 === void 0 ? "horizontal" : t0;
476
- const wrap = t1 === void 0 ? false : t1;
477
- let t2;
478
- if ($[9] !== activeId || $[10] !== defaultActiveId || $[11] !== onActiveIdChange || $[12] !== orientation || $[13] !== wrap) {
479
- t2 = {
480
- activeId,
481
- defaultActiveId,
482
- onActiveIdChange,
483
- orientation,
484
- wrap
485
- };
486
- $[9] = activeId;
487
- $[10] = defaultActiveId;
488
- $[11] = onActiveIdChange;
489
- $[12] = orientation;
490
- $[13] = wrap;
491
- $[14] = t2;
492
- } else t2 = $[14];
493
- const { group, onKeyDown } = useRovingFocus(t2);
494
- let t3;
495
- if ($[15] !== orientation || $[16] !== rest.role) {
496
- 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];
501
- const told = t3;
502
- let t4;
503
- if ($[18] !== children || $[19] !== onKeyDown || $[20] !== orientation || $[21] !== rest || $[22] !== told) {
504
- t4 = /* @__PURE__ */ jsx(Shell, {
505
- onKeyDown,
506
- orientation,
507
- ...told,
508
- ...rest,
509
- children
510
- });
511
- $[18] = children;
512
- $[19] = onKeyDown;
513
- $[20] = orientation;
514
- $[21] = rest;
515
- $[22] = told;
516
- $[23] = t4;
517
- } else t4 = $[23];
518
- let t5;
519
- if ($[24] !== group || $[25] !== t4) {
520
- t5 = /* @__PURE__ */ jsx(RovingFocusContext, {
521
- value: group,
522
- children: t4
523
- });
524
- $[24] = group;
525
- $[25] = t4;
526
- $[26] = t5;
527
- } else t5 = $[26];
528
- return t5;
529
- }
530
- //#endregion
531
- //#region src/roving-focus/index.ts
532
- var roving_focus_exports = /* @__PURE__ */ __exportAll({
533
- Item: () => Item,
534
- Root: () => Root
535
- });
536
- //#endregion
537
- //#region src/skip-nav/context.ts
538
- /**
539
- * Binds the skip link's recipe to the parts that draw it.
540
- *
541
- * @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.
546
- */
547
- /**
548
- * Binds the recipe once, for the link and for the target it jumps to.
549
- */
550
- const { withProvider } = createSlotRecipeContext(recipe$1);
551
- //#endregion
552
- //#region src/skip-nav/link.ts
553
- /**
554
- * The fragment the link points at and the target answers to, where neither states one.
555
- */
556
- const SKIP_NAV_TARGET = "content";
557
- /**
558
- * Jumps a keyboard past the navigation to the page's content.
559
- */
560
- const Link = withProvider("a", "link", { defaultProps: { href: `#${SKIP_NAV_TARGET}` } });
561
- //#endregion
562
- //#region src/skip-nav/target.ts
563
- /**
564
- * Takes the focus the skip link sends, and draws nothing.
565
- */
566
- const Target = withProvider("div", "target", { defaultProps: {
567
- id: SKIP_NAV_TARGET,
568
- tabIndex: -1
569
- } });
570
- //#endregion
571
- //#region src/skip-nav/index.ts
572
- var skip_nav_exports = /* @__PURE__ */ __exportAll({
573
- Link: () => Link,
574
- SKIP_NAV_TARGET: () => SKIP_NAV_TARGET,
575
- Target: () => Target
576
- });
577
- //#endregion
578
- //#region src/visually-hidden/context.ts
579
- /**
580
- * Binds the hidden text's recipe to the element that draws it.
581
- *
582
- * @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.
586
- */
587
- /**
588
- * Binds the recipe once, for the hidden text and for whatever sets its variants from above.
589
- */
590
- const { PropsProvider, withContext } = createRecipeContext(recipe$2);
591
- //#endregion
592
- //#region src/visually-hidden/visually-hidden.ts
593
- /**
594
- * Reads its words to a screen reader and draws them nowhere.
595
- */
596
- const VisuallyHidden = withContext("span");
597
- //#endregion
1
+ import { n as PropsProvider, o as roving_focus_exports, r as skip_nav_exports, t as VisuallyHidden } from "./shared-UZQEmdYt.js";
598
2
  export { roving_focus_exports as RovingFocus, skip_nav_exports as SkipNav, VisuallyHidden, PropsProvider as VisuallyHiddenPropsProvider };
@@ -0,0 +1,42 @@
1
+ {
2
+ "format": 1,
3
+ "pages": [
4
+ {
5
+ "about": "roving-focus.about",
6
+ "group": "",
7
+ "id": "components/a11y/roving-focus",
8
+ "module": "roving-focus/roving-focus.js",
9
+ "namespace": "",
10
+ "props": "roving-focus/roving-focus.props.js",
11
+ "specimen": "src/roving-focus/roving-focus.specimen.tsx",
12
+ "title": "roving-focus.title"
13
+ },
14
+ {
15
+ "about": "skip-nav.about",
16
+ "group": "",
17
+ "id": "components/a11y/skip-nav",
18
+ "module": "skip-nav/skip-nav.js",
19
+ "namespace": "",
20
+ "props": "skip-nav/skip-nav.props.js",
21
+ "specimen": "src/skip-nav/skip-nav.specimen.tsx",
22
+ "title": "skip-nav.title"
23
+ },
24
+ {
25
+ "about": "visually-hidden.about",
26
+ "group": "",
27
+ "id": "components/a11y/visually-hidden",
28
+ "module": "visually-hidden/visually-hidden.js",
29
+ "namespace": "",
30
+ "props": "visually-hidden/visually-hidden.props.js",
31
+ "specimen": "src/visually-hidden/visually-hidden.specimen.tsx",
32
+ "title": "visually-hidden.title"
33
+ }
34
+ ],
35
+ "requires": {
36
+ "@stealthscale/component-actions": "^0.2.0",
37
+ "@stealthscale/component-layout": "^0.2.0",
38
+ "@stealthscale/component-typography": "^0.3.0",
39
+ "@stealthscale/specimen": "^0.3.0",
40
+ "lucide-react": "^1.52.0"
41
+ }
42
+ }