@dashforge/tw 0.1.0-beta → 0.2.1-beta
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/A11Y.md +130 -0
- package/CHANGELOG.md +231 -0
- package/dist/index.d.ts +1 -82
- package/dist/index.esm.js +1608 -11
- package/dist/src/components/AspectRatio/AspectRatio.d.ts +36 -0
- package/dist/src/components/AspectRatio/AspectRatio.d.ts.map +1 -0
- package/dist/src/components/AspectRatio/aspectRatio.types.d.ts +50 -0
- package/dist/src/components/AspectRatio/aspectRatio.types.d.ts.map +1 -0
- package/dist/src/components/Box/Box.d.ts +36 -0
- package/dist/src/components/Box/Box.d.ts.map +1 -0
- package/dist/src/components/Box/box.types.d.ts +54 -0
- package/dist/src/components/Box/box.types.d.ts.map +1 -0
- package/dist/src/components/Box/box.variants.d.ts +402 -0
- package/dist/src/components/Box/box.variants.d.ts.map +1 -0
- package/dist/src/components/Button/Button.d.ts.map +1 -1
- package/dist/src/components/Checkbox/Checkbox.d.ts.map +1 -1
- package/dist/src/components/Container/Container.d.ts +35 -0
- package/dist/src/components/Container/Container.d.ts.map +1 -0
- package/dist/src/components/Container/container.types.d.ts +41 -0
- package/dist/src/components/Container/container.types.d.ts.map +1 -0
- package/dist/src/components/Container/container.variants.d.ts +93 -0
- package/dist/src/components/Container/container.variants.d.ts.map +1 -0
- package/dist/src/components/Divider/Divider.d.ts +50 -0
- package/dist/src/components/Divider/Divider.d.ts.map +1 -0
- package/dist/src/components/Divider/divider.types.d.ts +47 -0
- package/dist/src/components/Divider/divider.types.d.ts.map +1 -0
- package/dist/src/components/Divider/divider.variants.d.ts +129 -0
- package/dist/src/components/Divider/divider.variants.d.ts.map +1 -0
- package/dist/src/components/Grid/Grid.d.ts +32 -0
- package/dist/src/components/Grid/Grid.d.ts.map +1 -0
- package/dist/src/components/Grid/grid.types.d.ts +103 -0
- package/dist/src/components/Grid/grid.types.d.ts.map +1 -0
- package/dist/src/components/Grid/grid.variants.d.ts +453 -0
- package/dist/src/components/Grid/grid.variants.d.ts.map +1 -0
- package/dist/src/components/NumberField/NumberField.d.ts.map +1 -1
- package/dist/src/components/RadioGroup/RadioGroup.d.ts.map +1 -1
- package/dist/src/components/Stack/Stack.d.ts +24 -0
- package/dist/src/components/Stack/Stack.d.ts.map +1 -0
- package/dist/src/components/Stack/stack.types.d.ts +61 -0
- package/dist/src/components/Stack/stack.types.d.ts.map +1 -0
- package/dist/src/components/Stack/stack.variants.d.ts +163 -0
- package/dist/src/components/Stack/stack.variants.d.ts.map +1 -0
- package/dist/src/components/Typography/Typography.d.ts +42 -0
- package/dist/src/components/Typography/Typography.d.ts.map +1 -0
- package/dist/src/components/Typography/typography.types.d.ts +61 -0
- package/dist/src/components/Typography/typography.types.d.ts.map +1 -0
- package/dist/src/components/Typography/typography.variants.d.ts +167 -0
- package/dist/src/components/Typography/typography.variants.d.ts.map +1 -0
- package/dist/src/components/VisuallyHidden/VisuallyHidden.d.ts +42 -0
- package/dist/src/components/VisuallyHidden/VisuallyHidden.d.ts.map +1 -0
- package/dist/src/components/VisuallyHidden/visuallyHidden.types.d.ts +42 -0
- package/dist/src/components/VisuallyHidden/visuallyHidden.types.d.ts.map +1 -0
- package/dist/src/index.d.ts +23 -1
- package/dist/src/index.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/components/AspectRatio/AspectRatio.test.tsx +173 -0
- package/src/components/AspectRatio/AspectRatio.tsx +73 -0
- package/src/components/AspectRatio/aspectRatio.types.ts +54 -0
- package/src/components/Box/Box.test.tsx +349 -0
- package/src/components/Box/Box.tsx +83 -0
- package/src/components/Box/box.types.ts +61 -0
- package/src/components/Box/box.variants.ts +211 -0
- package/src/components/Button/Button.tsx +11 -0
- package/src/components/Checkbox/Checkbox.tsx +26 -2
- package/src/components/Container/Container.test.tsx +209 -0
- package/src/components/Container/Container.tsx +74 -0
- package/src/components/Container/container.types.ts +45 -0
- package/src/components/Container/container.variants.ts +81 -0
- package/src/components/Divider/Divider.test.tsx +241 -0
- package/src/components/Divider/Divider.tsx +140 -0
- package/src/components/Divider/divider.types.ts +52 -0
- package/src/components/Divider/divider.variants.ts +115 -0
- package/src/components/Grid/Grid.test.tsx +321 -0
- package/src/components/Grid/Grid.tsx +148 -0
- package/src/components/Grid/grid.types.ts +112 -0
- package/src/components/Grid/grid.variants.ts +133 -0
- package/src/components/NumberField/NumberField.tsx +30 -2
- package/src/components/RadioGroup/RadioGroup.tsx +23 -1
- package/src/components/Stack/Stack.test.tsx +309 -0
- package/src/components/Stack/Stack.tsx +115 -0
- package/src/components/Stack/stack.types.ts +68 -0
- package/src/components/Stack/stack.variants.ts +80 -0
- package/src/components/Typography/Typography.test.tsx +230 -0
- package/src/components/Typography/Typography.tsx +112 -0
- package/src/components/Typography/typography.types.ts +65 -0
- package/src/components/Typography/typography.variants.ts +113 -0
- package/src/components/VisuallyHidden/VisuallyHidden.test.tsx +86 -0
- package/src/components/VisuallyHidden/VisuallyHidden.tsx +59 -0
- package/src/components/VisuallyHidden/visuallyHidden.types.ts +45 -0
- package/src/index.ts +50 -1
- package/LICENSE +0 -21
- package/dist/components/AppShell/AppShell.d.ts +0 -32
- package/dist/components/AppShell/AppShell.d.ts.map +0 -1
- package/dist/components/AppShell/appShell.types.d.ts +0 -62
- package/dist/components/AppShell/appShell.types.d.ts.map +0 -1
- package/dist/components/AppShell/appShell.variants.d.ts +0 -65
- package/dist/components/AppShell/appShell.variants.d.ts.map +0 -1
- package/dist/components/Autocomplete/Autocomplete.d.ts +0 -32
- package/dist/components/Autocomplete/Autocomplete.d.ts.map +0 -1
- package/dist/components/Autocomplete/autocomplete.types.d.ts +0 -214
- package/dist/components/Autocomplete/autocomplete.types.d.ts.map +0 -1
- package/dist/components/Autocomplete/autocomplete.variants.d.ts +0 -214
- package/dist/components/Autocomplete/autocomplete.variants.d.ts.map +0 -1
- package/dist/components/Breadcrumbs/Breadcrumbs.d.ts +0 -23
- package/dist/components/Breadcrumbs/Breadcrumbs.d.ts.map +0 -1
- package/dist/components/Breadcrumbs/breadcrumbs.types.d.ts +0 -98
- package/dist/components/Breadcrumbs/breadcrumbs.types.d.ts.map +0 -1
- package/dist/components/Breadcrumbs/breadcrumbs.variants.d.ts +0 -85
- package/dist/components/Breadcrumbs/breadcrumbs.variants.d.ts.map +0 -1
- package/dist/components/Button/Button.d.ts +0 -44
- package/dist/components/Button/Button.d.ts.map +0 -1
- package/dist/components/Button/button.types.d.ts +0 -66
- package/dist/components/Button/button.types.d.ts.map +0 -1
- package/dist/components/Button/button.variants.d.ts +0 -104
- package/dist/components/Button/button.variants.d.ts.map +0 -1
- package/dist/components/Checkbox/Checkbox.d.ts +0 -31
- package/dist/components/Checkbox/Checkbox.d.ts.map +0 -1
- package/dist/components/Checkbox/checkbox.types.d.ts +0 -86
- package/dist/components/Checkbox/checkbox.types.d.ts.map +0 -1
- package/dist/components/Checkbox/checkbox.variants.d.ts +0 -109
- package/dist/components/Checkbox/checkbox.variants.d.ts.map +0 -1
- package/dist/components/ConfirmDialog/ConfirmDialog.d.ts +0 -38
- package/dist/components/ConfirmDialog/ConfirmDialog.d.ts.map +0 -1
- package/dist/components/ConfirmDialog/confirmDialog.types.d.ts +0 -80
- package/dist/components/ConfirmDialog/confirmDialog.types.d.ts.map +0 -1
- package/dist/components/ConfirmDialog/confirmDialog.variants.d.ts +0 -90
- package/dist/components/ConfirmDialog/confirmDialog.variants.d.ts.map +0 -1
- package/dist/components/DateTimePicker/DateTimePicker.d.ts +0 -49
- package/dist/components/DateTimePicker/DateTimePicker.d.ts.map +0 -1
- package/dist/components/DateTimePicker/dateTimePicker.types.d.ts +0 -95
- package/dist/components/DateTimePicker/dateTimePicker.types.d.ts.map +0 -1
- package/dist/components/DateTimePicker/dateTimePicker.variants.d.ts +0 -165
- package/dist/components/DateTimePicker/dateTimePicker.variants.d.ts.map +0 -1
- package/dist/components/LeftNav/LeftNav.d.ts +0 -34
- package/dist/components/LeftNav/LeftNav.d.ts.map +0 -1
- package/dist/components/LeftNav/leftNav.types.d.ts +0 -136
- package/dist/components/LeftNav/leftNav.types.d.ts.map +0 -1
- package/dist/components/LeftNav/leftNav.variants.d.ts +0 -143
- package/dist/components/LeftNav/leftNav.variants.d.ts.map +0 -1
- package/dist/components/NumberField/NumberField.d.ts +0 -18
- package/dist/components/NumberField/NumberField.d.ts.map +0 -1
- package/dist/components/NumberField/numberField.types.d.ts +0 -79
- package/dist/components/NumberField/numberField.types.d.ts.map +0 -1
- package/dist/components/NumberField/numberField.variants.d.ts +0 -169
- package/dist/components/NumberField/numberField.variants.d.ts.map +0 -1
- package/dist/components/OTPField/OTPField.d.ts +0 -25
- package/dist/components/OTPField/OTPField.d.ts.map +0 -1
- package/dist/components/OTPField/otpField.types.d.ts +0 -74
- package/dist/components/OTPField/otpField.types.d.ts.map +0 -1
- package/dist/components/OTPField/otpField.variants.d.ts +0 -105
- package/dist/components/OTPField/otpField.variants.d.ts.map +0 -1
- package/dist/components/RadioGroup/RadioGroup.d.ts +0 -35
- package/dist/components/RadioGroup/RadioGroup.d.ts.map +0 -1
- package/dist/components/RadioGroup/radioGroup.types.d.ts +0 -103
- package/dist/components/RadioGroup/radioGroup.types.d.ts.map +0 -1
- package/dist/components/RadioGroup/radioGroup.variants.d.ts +0 -166
- package/dist/components/RadioGroup/radioGroup.variants.d.ts.map +0 -1
- package/dist/components/Snackbar/Snackbar.d.ts +0 -37
- package/dist/components/Snackbar/Snackbar.d.ts.map +0 -1
- package/dist/components/Snackbar/snackbar.types.d.ts +0 -86
- package/dist/components/Snackbar/snackbar.types.d.ts.map +0 -1
- package/dist/components/Snackbar/snackbar.variants.d.ts +0 -153
- package/dist/components/Snackbar/snackbar.variants.d.ts.map +0 -1
- package/dist/components/Switch/Switch.d.ts +0 -15
- package/dist/components/Switch/Switch.d.ts.map +0 -1
- package/dist/components/Switch/switch.types.d.ts +0 -47
- package/dist/components/Switch/switch.types.d.ts.map +0 -1
- package/dist/components/Switch/switch.variants.d.ts +0 -105
- package/dist/components/Switch/switch.variants.d.ts.map +0 -1
- package/dist/components/TextField/TextField.d.ts +0 -25
- package/dist/components/TextField/TextField.d.ts.map +0 -1
- package/dist/components/TextField/textField.types.d.ts +0 -72
- package/dist/components/TextField/textField.types.d.ts.map +0 -1
- package/dist/components/TextField/textField.variants.d.ts +0 -160
- package/dist/components/TextField/textField.variants.d.ts.map +0 -1
- package/dist/components/Textarea/Textarea.d.ts +0 -16
- package/dist/components/Textarea/Textarea.d.ts.map +0 -1
- package/dist/components/Textarea/textarea.types.d.ts +0 -63
- package/dist/components/Textarea/textarea.types.d.ts.map +0 -1
- package/dist/components/Textarea/textarea.variants.d.ts +0 -197
- package/dist/components/Textarea/textarea.variants.d.ts.map +0 -1
- package/dist/components/TopBar/TopBar.d.ts +0 -33
- package/dist/components/TopBar/TopBar.d.ts.map +0 -1
- package/dist/components/TopBar/topBar.types.d.ts +0 -49
- package/dist/components/TopBar/topBar.types.d.ts.map +0 -1
- package/dist/components/TopBar/topBar.variants.d.ts +0 -79
- package/dist/components/TopBar/topBar.variants.d.ts.map +0 -1
- package/dist/components/_shared/resolveValidationState.d.ts +0 -42
- package/dist/components/_shared/resolveValidationState.d.ts.map +0 -1
- package/dist/hooks/useAccessState.d.ts +0 -37
- package/dist/hooks/useAccessState.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/tsconfig.lib.tsbuildinfo +0 -1
- package/dist/utils/cn.d.ts +0 -26
- package/dist/utils/cn.d.ts.map +0 -1
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { tv, type VariantProps } from 'tailwind-variants';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* `typographyVariants` — the full type scale for the @dashforge/tw library.
|
|
5
|
+
*
|
|
6
|
+
* Mirrors the MUI Typography variant set (h1–h6 · subtitle1/2 · body1/2 ·
|
|
7
|
+
* caption · overline) so the mental model carries over for developers
|
|
8
|
+
* moving between the two ecosystems. Each variant baseline maps to a
|
|
9
|
+
* Tailwind utility chain that resolves through the @dashforge/tw-tokens
|
|
10
|
+
* scale (so the visual stays in sync with the rest of the system when the
|
|
11
|
+
* token theme is patched).
|
|
12
|
+
*
|
|
13
|
+
* Variant axes are intentionally ORTHOGONAL — `variant` chooses the type
|
|
14
|
+
* scale, `weight` overrides the variant's default weight (useful for "h2
|
|
15
|
+
* but lighter"), `color` picks the intent, `align` picks the axis. They
|
|
16
|
+
* never collide, so consumers can mix them freely.
|
|
17
|
+
*
|
|
18
|
+
* Two boolean flags (`truncate`, `noWrap`) encode the most common one-line
|
|
19
|
+
* patterns; `gutterBottom` adds the conventional bottom margin used when a
|
|
20
|
+
* heading precedes a paragraph block (mirror of MUI's same flag).
|
|
21
|
+
*/
|
|
22
|
+
export const typographyVariants = tv({
|
|
23
|
+
base: 'text-inherit',
|
|
24
|
+
|
|
25
|
+
variants: {
|
|
26
|
+
/*
|
|
27
|
+
* `variant` is the type-scale axis.
|
|
28
|
+
*
|
|
29
|
+
* The default font-weight is baked into each variant (headings come
|
|
30
|
+
* with semibold/bold by default). Consumers override per-instance via
|
|
31
|
+
* the `weight` axis below — when set, `weight` wins because it's
|
|
32
|
+
* declared later in the cn() chain and tailwind-merge resolves the
|
|
33
|
+
* last `font-*` to win.
|
|
34
|
+
*/
|
|
35
|
+
variant: {
|
|
36
|
+
h1: 'text-5xl font-bold leading-[1.05] tracking-[-0.025em]',
|
|
37
|
+
h2: 'text-4xl font-bold leading-[1.1] tracking-[-0.022em]',
|
|
38
|
+
h3: 'text-3xl font-semibold leading-[1.15] tracking-[-0.02em]',
|
|
39
|
+
h4: 'text-2xl font-semibold leading-snug tracking-[-0.015em]',
|
|
40
|
+
h5: 'text-xl font-semibold leading-snug',
|
|
41
|
+
h6: 'text-lg font-semibold leading-normal',
|
|
42
|
+
subtitle1: 'text-base font-medium leading-relaxed',
|
|
43
|
+
subtitle2: 'text-sm font-medium leading-relaxed',
|
|
44
|
+
body1: 'text-base font-normal leading-relaxed',
|
|
45
|
+
body2: 'text-sm font-normal leading-relaxed',
|
|
46
|
+
caption: 'text-xs font-normal leading-normal',
|
|
47
|
+
overline: 'text-xs font-semibold uppercase tracking-[0.12em] leading-normal',
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
/*
|
|
51
|
+
* `color` is the intent axis. Pairs with the @dashforge/tw-theme
|
|
52
|
+
* reactive colour vars so the choice survives theme patches and dark
|
|
53
|
+
* mode flips. `inherit` is the escape hatch — used inside a Box that
|
|
54
|
+
* has set its own color (e.g. `<Box variant="solid" color="primary">`
|
|
55
|
+
* paints white text).
|
|
56
|
+
*/
|
|
57
|
+
color: {
|
|
58
|
+
inherit: 'text-inherit',
|
|
59
|
+
primary: 'text-primary-700 dark:text-primary-400',
|
|
60
|
+
secondary: 'text-secondary-700 dark:text-secondary-400',
|
|
61
|
+
success: 'text-success-700 dark:text-success-400',
|
|
62
|
+
warning: 'text-warning-700 dark:text-warning-400',
|
|
63
|
+
danger: 'text-danger-700 dark:text-danger-400',
|
|
64
|
+
info: 'text-info-700 dark:text-info-400',
|
|
65
|
+
neutral: 'text-neutral-900 dark:text-neutral-100',
|
|
66
|
+
muted: 'text-neutral-600 dark:text-neutral-400',
|
|
67
|
+
},
|
|
68
|
+
|
|
69
|
+
/*
|
|
70
|
+
* `weight` overrides the variant's default weight. When unset, the
|
|
71
|
+
* variant's own weight wins. When set, this axis appears LATER in the
|
|
72
|
+
* cn() chain so tailwind-merge resolves to this value.
|
|
73
|
+
*/
|
|
74
|
+
weight: {
|
|
75
|
+
normal: 'font-normal',
|
|
76
|
+
medium: 'font-medium',
|
|
77
|
+
semibold: 'font-semibold',
|
|
78
|
+
bold: 'font-bold',
|
|
79
|
+
extrabold: 'font-extrabold',
|
|
80
|
+
},
|
|
81
|
+
|
|
82
|
+
align: {
|
|
83
|
+
left: 'text-left',
|
|
84
|
+
center: 'text-center',
|
|
85
|
+
right: 'text-right',
|
|
86
|
+
justify: 'text-justify',
|
|
87
|
+
},
|
|
88
|
+
|
|
89
|
+
/*
|
|
90
|
+
* `truncate` collapses to a one-line ellipsis. `noWrap` is the looser
|
|
91
|
+
* sibling — keeps the text on one line but lets it overflow without
|
|
92
|
+
* the `…`. Mutually-exclusive intent-wise; if both are passed,
|
|
93
|
+
* `truncate` wins (later in the cn() chain).
|
|
94
|
+
*/
|
|
95
|
+
truncate: { true: 'truncate' },
|
|
96
|
+
noWrap: { true: 'whitespace-nowrap' },
|
|
97
|
+
|
|
98
|
+
/*
|
|
99
|
+
* `gutterBottom` adds the conventional bottom margin used when a
|
|
100
|
+
* heading precedes a paragraph block. Mirror of MUI's same prop —
|
|
101
|
+
* familiar to developers crossing from the MUI side.
|
|
102
|
+
*/
|
|
103
|
+
gutterBottom: { true: 'mb-3' },
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
defaultVariants: {
|
|
107
|
+
variant: 'body1',
|
|
108
|
+
color: 'inherit',
|
|
109
|
+
align: 'left',
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
export type TypographyVariants = VariantProps<typeof typographyVariants>;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
// @vitest-environment jsdom
|
|
2
|
+
import { describe, it, expect } from 'vitest';
|
|
3
|
+
import { render } from '@testing-library/react';
|
|
4
|
+
import { VisuallyHidden } from './VisuallyHidden.js';
|
|
5
|
+
|
|
6
|
+
describe('<VisuallyHidden>', () => {
|
|
7
|
+
it('renders a <span> by default', () => {
|
|
8
|
+
const { container } = render(<VisuallyHidden>label</VisuallyHidden>);
|
|
9
|
+
expect(container.firstElementChild?.tagName).toBe('SPAN');
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it('has the sr-only class', () => {
|
|
13
|
+
const { container } = render(<VisuallyHidden>label</VisuallyHidden>);
|
|
14
|
+
expect(container.firstElementChild?.className).toContain('sr-only');
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('preserves the text content (so screen readers can read it)', () => {
|
|
18
|
+
const { container } = render(<VisuallyHidden>Close dialog</VisuallyHidden>);
|
|
19
|
+
expect(container.firstElementChild?.textContent).toBe('Close dialog');
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it('as="div" renders <div>', () => {
|
|
23
|
+
const { container } = render(<VisuallyHidden as="div">label</VisuallyHidden>);
|
|
24
|
+
expect(container.firstElementChild?.tagName).toBe('DIV');
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('sx adds utilities (merged with sr-only)', () => {
|
|
28
|
+
const { container } = render(
|
|
29
|
+
<VisuallyHidden sx="text-xs">label</VisuallyHidden>,
|
|
30
|
+
);
|
|
31
|
+
const cls = container.firstElementChild?.className ?? '';
|
|
32
|
+
expect(cls).toContain('sr-only');
|
|
33
|
+
expect(cls).toContain('text-xs');
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('forwards data-* + aria-*', () => {
|
|
37
|
+
const { container } = render(
|
|
38
|
+
<VisuallyHidden data-testid="vh" aria-live="polite">x</VisuallyHidden>,
|
|
39
|
+
);
|
|
40
|
+
const el = container.firstElementChild;
|
|
41
|
+
expect(el?.getAttribute('data-testid')).toBe('vh');
|
|
42
|
+
expect(el?.getAttribute('aria-live')).toBe('polite');
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('typical pattern — icon button label', () => {
|
|
46
|
+
const { container } = render(
|
|
47
|
+
<button type="button">
|
|
48
|
+
<span aria-hidden="true">✕</span>
|
|
49
|
+
<VisuallyHidden>Close</VisuallyHidden>
|
|
50
|
+
</button>,
|
|
51
|
+
);
|
|
52
|
+
const btn = container.querySelector('button');
|
|
53
|
+
// textContent includes the hidden label so AT can read it
|
|
54
|
+
expect(btn?.textContent).toBe('✕Close');
|
|
55
|
+
// visually, the Close span has sr-only
|
|
56
|
+
const hidden = btn?.querySelector('.sr-only');
|
|
57
|
+
expect(hidden?.textContent).toBe('Close');
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// ─── F11-bis edge cases ─────────────────────────────────────────────
|
|
61
|
+
it('empty children renders empty element with sr-only', () => {
|
|
62
|
+
const { container } = render(<VisuallyHidden>{''}</VisuallyHidden>);
|
|
63
|
+
const el = container.firstElementChild;
|
|
64
|
+
expect(el?.className).toContain('sr-only');
|
|
65
|
+
expect(el?.textContent).toBe('');
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it('aria-live="polite" pattern for status announcements', () => {
|
|
69
|
+
const { container } = render(
|
|
70
|
+
<VisuallyHidden aria-live="polite">Saved successfully</VisuallyHidden>,
|
|
71
|
+
);
|
|
72
|
+
const el = container.firstElementChild;
|
|
73
|
+
expect(el?.getAttribute('aria-live')).toBe('polite');
|
|
74
|
+
expect(el?.textContent).toBe('Saved successfully');
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
it('as="div" renders block element (consumer choice for block hidden content)', () => {
|
|
78
|
+
const { container } = render(
|
|
79
|
+
<VisuallyHidden as="div">
|
|
80
|
+
Block content hidden from sight but readable by AT
|
|
81
|
+
</VisuallyHidden>,
|
|
82
|
+
);
|
|
83
|
+
expect(container.firstElementChild?.tagName).toBe('DIV');
|
|
84
|
+
expect(container.firstElementChild?.className).toContain('sr-only');
|
|
85
|
+
});
|
|
86
|
+
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { forwardRef, type ElementType } from 'react';
|
|
2
|
+
import { cn } from '../../utils/cn.js';
|
|
3
|
+
import type { VisuallyHiddenProps } from './visuallyHidden.types.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* `<VisuallyHidden>` — the accessibility primitive.
|
|
7
|
+
*
|
|
8
|
+
* Hides children from sighted users (zero pixels rendered, no layout
|
|
9
|
+
* impact) while keeping them in the accessibility tree. Screen readers
|
|
10
|
+
* speak the content; voice control software uses it for click targets;
|
|
11
|
+
* keyboard users see nothing — same as if it weren't there.
|
|
12
|
+
*
|
|
13
|
+
* Implementation: Tailwind's built-in `sr-only` utility, which expands to:
|
|
14
|
+
*
|
|
15
|
+
* .sr-only {
|
|
16
|
+
* position: absolute;
|
|
17
|
+
* width: 1px;
|
|
18
|
+
* height: 1px;
|
|
19
|
+
* padding: 0;
|
|
20
|
+
* margin: -1px;
|
|
21
|
+
* overflow: hidden;
|
|
22
|
+
* clip: rect(0,0,0,0);
|
|
23
|
+
* white-space: nowrap;
|
|
24
|
+
* border-width: 0;
|
|
25
|
+
* }
|
|
26
|
+
*
|
|
27
|
+
* This is the canonical "visually-hidden but screen-reader-accessible"
|
|
28
|
+
* pattern, also known as the WebAIM clip technique. Critically:
|
|
29
|
+
*
|
|
30
|
+
* • NOT `display: none` (removes from a11y tree)
|
|
31
|
+
* • NOT `visibility: hidden` (also removes from a11y tree)
|
|
32
|
+
* • NOT `opacity: 0` (technically still rendered, doesn't help AT)
|
|
33
|
+
* • NOT `width/height: 0` (collapses, some AT skips it)
|
|
34
|
+
*
|
|
35
|
+
* Default tag is `<span>` (inline) — the 99% case is "label inside a
|
|
36
|
+
* button or link". For block content, override with `as="div"`, but
|
|
37
|
+
* be aware nesting block inside inline is invalid HTML.
|
|
38
|
+
*
|
|
39
|
+
* The component is intentionally tiny (~30 LoC total): one className,
|
|
40
|
+
* one tag. The value is the COMPONENT NAME — `<VisuallyHidden>` reads
|
|
41
|
+
* as an intentional a11y decision in code review, while
|
|
42
|
+
* `className="sr-only"` looks like a typo or a forgotten utility.
|
|
43
|
+
*/
|
|
44
|
+
export const VisuallyHidden = forwardRef<HTMLElement, VisuallyHiddenProps>(
|
|
45
|
+
function VisuallyHidden(props, ref) {
|
|
46
|
+
const { as, sx, children, ...rest } = props;
|
|
47
|
+
|
|
48
|
+
const Tag = (as ?? 'span') as ElementType;
|
|
49
|
+
const classes = cn('sr-only', sx);
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<Tag ref={ref as never} className={classes} {...rest}>
|
|
53
|
+
{children}
|
|
54
|
+
</Tag>
|
|
55
|
+
);
|
|
56
|
+
},
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
VisuallyHidden.displayName = 'VisuallyHidden';
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { ElementType, HTMLAttributes, ReactElement } from 'react';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Props for `<VisuallyHidden>` — the a11y primitive.
|
|
5
|
+
*
|
|
6
|
+
* Hides content visually (zero pixels rendered) while keeping it
|
|
7
|
+
* accessible to assistive technology (screen readers, voice control).
|
|
8
|
+
* The canonical use case: icon-only buttons that need an audible label
|
|
9
|
+
* for non-visual users.
|
|
10
|
+
*
|
|
11
|
+
* <button>
|
|
12
|
+
* <CloseIcon />
|
|
13
|
+
* <VisuallyHidden>Close dialog</VisuallyHidden>
|
|
14
|
+
* </button>
|
|
15
|
+
*
|
|
16
|
+
* Implementation uses Tailwind's `sr-only` utility, which sets
|
|
17
|
+
* `position: absolute; width: 1px; height: 1px; padding: 0;
|
|
18
|
+
* margin: -1px; overflow: hidden; clip: rect(0,0,0,0);
|
|
19
|
+
* white-space: nowrap; border-width: 0;` — the canonical
|
|
20
|
+
* "visually-hidden but screen-reader-accessible" pattern. Better
|
|
21
|
+
* than `display: none` (removes from a11y tree) and better than
|
|
22
|
+
* `visibility: hidden` (also removes from a11y tree).
|
|
23
|
+
*/
|
|
24
|
+
export interface VisuallyHiddenProps
|
|
25
|
+
extends Omit<HTMLAttributes<HTMLElement>, 'className'> {
|
|
26
|
+
/**
|
|
27
|
+
* The text or markup hidden from sighted users but read by AT.
|
|
28
|
+
* Most often a string label.
|
|
29
|
+
*/
|
|
30
|
+
children?: ReactElement | string | number;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Override the rendered HTML tag. Defaults to `'span'` — inline
|
|
34
|
+
* placement is the most common case (label inside a button or link).
|
|
35
|
+
* Use `as="div"` when the hidden content is block-level, but be
|
|
36
|
+
* aware: nesting a block inside an inline parent is invalid HTML.
|
|
37
|
+
*/
|
|
38
|
+
as?: ElementType;
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Utility classes appended to `sr-only`. RARELY needed for this
|
|
42
|
+
* primitive (it's just hidden text) — kept for API parity.
|
|
43
|
+
*/
|
|
44
|
+
sx?: string;
|
|
45
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -174,6 +174,55 @@ export type {
|
|
|
174
174
|
} from './components/Snackbar/snackbar.types.js';
|
|
175
175
|
export { snackbarVariants } from './components/Snackbar/snackbar.variants.js';
|
|
176
176
|
|
|
177
|
+
// F9 foundation: typography + layout primitives. These sit BENEATH
|
|
178
|
+
// every other component (Button's label, TextField's helper text, the
|
|
179
|
+
// surface of an AppShell card) and are what app-level code reaches for
|
|
180
|
+
// before it reaches for any specific UI atom.
|
|
181
|
+
|
|
182
|
+
export { Typography } from './components/Typography/Typography.js';
|
|
183
|
+
export type { TypographyProps } from './components/Typography/typography.types.js';
|
|
184
|
+
export { typographyVariants } from './components/Typography/typography.variants.js';
|
|
185
|
+
|
|
186
|
+
export { Box } from './components/Box/Box.js';
|
|
187
|
+
export type { BoxProps } from './components/Box/box.types.js';
|
|
188
|
+
export { boxVariants } from './components/Box/box.variants.js';
|
|
189
|
+
|
|
190
|
+
export { Stack } from './components/Stack/Stack.js';
|
|
191
|
+
export type { StackProps } from './components/Stack/stack.types.js';
|
|
192
|
+
export { stackVariants } from './components/Stack/stack.variants.js';
|
|
193
|
+
|
|
194
|
+
export { Grid } from './components/Grid/Grid.js';
|
|
195
|
+
export type {
|
|
196
|
+
GridProps,
|
|
197
|
+
GridContainerProps,
|
|
198
|
+
GridItemProps,
|
|
199
|
+
ColSpan,
|
|
200
|
+
GridSpacingStep,
|
|
201
|
+
} from './components/Grid/grid.types.js';
|
|
202
|
+
export { gridVariants } from './components/Grid/grid.variants.js';
|
|
203
|
+
|
|
204
|
+
// F10 foundation completions: Container, Divider, AspectRatio, VisuallyHidden.
|
|
205
|
+
// The page-root chrome + visual separators + content-shape primitives +
|
|
206
|
+
// the a11y baseline. With these, the foundation layer matches what
|
|
207
|
+
// Chakra/Mantine/Joy ship for layout-level primitives.
|
|
208
|
+
|
|
209
|
+
export { Container } from './components/Container/Container.js';
|
|
210
|
+
export type { ContainerProps } from './components/Container/container.types.js';
|
|
211
|
+
export { containerVariants } from './components/Container/container.variants.js';
|
|
212
|
+
|
|
213
|
+
export { Divider } from './components/Divider/Divider.js';
|
|
214
|
+
export type { DividerProps } from './components/Divider/divider.types.js';
|
|
215
|
+
export {
|
|
216
|
+
dividerVariants,
|
|
217
|
+
dividerLineVariants,
|
|
218
|
+
} from './components/Divider/divider.variants.js';
|
|
219
|
+
|
|
220
|
+
export { AspectRatio } from './components/AspectRatio/AspectRatio.js';
|
|
221
|
+
export type { AspectRatioProps } from './components/AspectRatio/aspectRatio.types.js';
|
|
222
|
+
|
|
223
|
+
export { VisuallyHidden } from './components/VisuallyHidden/VisuallyHidden.js';
|
|
224
|
+
export type { VisuallyHiddenProps } from './components/VisuallyHidden/visuallyHidden.types.js';
|
|
225
|
+
|
|
177
226
|
// ───── Hooks ─────
|
|
178
227
|
export { useAccessState } from './hooks/useAccessState.js';
|
|
179
228
|
|
|
@@ -188,4 +237,4 @@ export type { VariantProps } from 'tailwind-variants';
|
|
|
188
237
|
/**
|
|
189
238
|
* Package version (synced with `package.json` at publish time).
|
|
190
239
|
*/
|
|
191
|
-
export const VERSION = '0.1
|
|
240
|
+
export const VERSION = '0.2.1-beta';
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Dashforge
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import type { AppShellProps } from './appShell.types.js';
|
|
2
|
-
/**
|
|
3
|
-
* Dashforge TW AppShell — top-level layout orchestrator.
|
|
4
|
-
*
|
|
5
|
-
* ┌──────────────────────────────────────────┐
|
|
6
|
-
* │ header │ ← `header` slot
|
|
7
|
-
* ├────────┬─────────────────────────────────┤
|
|
8
|
-
* │ │ │
|
|
9
|
-
* │ nav │ main │ ← `nav` + `children`
|
|
10
|
-
* │ │ │
|
|
11
|
-
* ├────────┴─────────────────────────────────┤
|
|
12
|
-
* │ footer │ ← `footer` slot
|
|
13
|
-
* └──────────────────────────────────────────┘
|
|
14
|
-
*
|
|
15
|
-
* **Responsive**:
|
|
16
|
-
* - `≥ md`: nav stays in the inline slot at the left.
|
|
17
|
-
* - `< md`: nav becomes a slide-in drawer toggled by `navOpen`.
|
|
18
|
-
* A backdrop closes the drawer on click (mirrors `<Dialog>` UX).
|
|
19
|
-
*
|
|
20
|
-
* **Body scroll lock**: when the mobile drawer is open we add
|
|
21
|
-
* `overflow-hidden` to `<body>` to prevent dual-scroll wobble. The
|
|
22
|
-
* effect cleans up on close + on unmount.
|
|
23
|
-
*
|
|
24
|
-
* **A11y**:
|
|
25
|
-
* - `<main>` landmark wraps the content area.
|
|
26
|
-
* - `<header>` / `<footer>` come for free from their HTML tags.
|
|
27
|
-
* - The mobile drawer + backdrop participate in the standard
|
|
28
|
-
* "click outside to close" pattern — `Escape` closes the drawer
|
|
29
|
-
* too (added via global keydown).
|
|
30
|
-
*/
|
|
31
|
-
export declare function AppShell(props: AppShellProps): import("react/jsx-runtime").JSX.Element;
|
|
32
|
-
//# sourceMappingURL=AppShell.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"AppShell.d.ts","sourceRoot":"","sources":["../../../src/components/AppShell/AppShell.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,aAAa,2CA+E5C"}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from 'react';
|
|
2
|
-
import type { AppShellVariants } from './appShell.variants.js';
|
|
3
|
-
export interface AppShellSlotProps {
|
|
4
|
-
root?: {
|
|
5
|
-
className?: string;
|
|
6
|
-
};
|
|
7
|
-
header?: {
|
|
8
|
-
className?: string;
|
|
9
|
-
};
|
|
10
|
-
nav?: {
|
|
11
|
-
className?: string;
|
|
12
|
-
};
|
|
13
|
-
navMobile?: {
|
|
14
|
-
className?: string;
|
|
15
|
-
};
|
|
16
|
-
main?: {
|
|
17
|
-
className?: string;
|
|
18
|
-
};
|
|
19
|
-
footer?: {
|
|
20
|
-
className?: string;
|
|
21
|
-
};
|
|
22
|
-
backdrop?: {
|
|
23
|
-
className?: string;
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Props for `<AppShell>`.
|
|
28
|
-
*
|
|
29
|
-
* Top-level layout orchestrator with 4 named slots:
|
|
30
|
-
*
|
|
31
|
-
* - `header` (top, sticky)
|
|
32
|
-
* - `nav` (left side, fixed-width on desktop, drawer on mobile)
|
|
33
|
-
* - `footer` (bottom, non-sticky)
|
|
34
|
-
* - `children` (main content, scrolls independently)
|
|
35
|
-
*
|
|
36
|
-
* Responsive behavior:
|
|
37
|
-
* - **≥ md (768px)**: nav is rendered inline at the left.
|
|
38
|
-
* - **< md**: nav slides in as an overlay drawer when
|
|
39
|
-
* `navOpen={true}` (controlled).
|
|
40
|
-
*
|
|
41
|
-
* The shell is router-agnostic — pass any nav/header content. Typical
|
|
42
|
-
* pairing is `<LeftNav>` + `<TopBar>` (with a hamburger button in
|
|
43
|
-
* `TopBar.start` that flips `navOpen`).
|
|
44
|
-
*/
|
|
45
|
-
export interface AppShellProps extends AppShellVariants {
|
|
46
|
-
header?: ReactNode;
|
|
47
|
-
nav?: ReactNode;
|
|
48
|
-
footer?: ReactNode;
|
|
49
|
-
children?: ReactNode;
|
|
50
|
-
/**
|
|
51
|
-
* Mobile drawer open state. Controlled — provide
|
|
52
|
-
* `onNavOpenChange` to update. When `undefined`, the mobile drawer
|
|
53
|
-
* is always closed (consumer hasn't wired up the toggle yet).
|
|
54
|
-
*/
|
|
55
|
-
navOpen?: boolean;
|
|
56
|
-
onNavOpenChange?: (open: boolean) => void;
|
|
57
|
-
/** Root className shortcut. */
|
|
58
|
-
sx?: string;
|
|
59
|
-
/** Per-slot className overrides. */
|
|
60
|
-
slotProps?: AppShellSlotProps;
|
|
61
|
-
}
|
|
62
|
-
//# sourceMappingURL=appShell.types.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"appShell.types.d.ts","sourceRoot":"","sources":["../../../src/components/AppShell/appShell.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9B,MAAM,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAChC,GAAG,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7B,SAAS,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACnC,IAAI,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9B,MAAM,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAChC,QAAQ,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CACnC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,WAAW,aAAc,SAAQ,gBAAgB;IACrD,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,GAAG,CAAC,EAAE,SAAS,CAAC;IAChB,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;IAC1C,+BAA+B;IAC/B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,oCAAoC;IACpC,SAAS,CAAC,EAAE,iBAAiB,CAAC;CAC/B"}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
import { type VariantProps } from 'tailwind-variants';
|
|
2
|
-
/**
|
|
3
|
-
* Tailwind-variants recipe for `<AppShell>`.
|
|
4
|
-
*
|
|
5
|
-
* Slots:
|
|
6
|
-
* - `root` — outer flex column (full viewport)
|
|
7
|
-
* - `header` — top region
|
|
8
|
-
* - `body` — flex row holding nav + main
|
|
9
|
-
* - `nav` — desktop nav rail (md+)
|
|
10
|
-
* - `navMobile` — mobile drawer (slide-in)
|
|
11
|
-
* - `main` — scrollable content area
|
|
12
|
-
* - `footer` — bottom region
|
|
13
|
-
* - `backdrop` — semi-opaque overlay behind the mobile drawer
|
|
14
|
-
*/
|
|
15
|
-
export declare const appShellVariants: import("tailwind-variants").TVReturnType<{
|
|
16
|
-
navOpen: {
|
|
17
|
-
true: {
|
|
18
|
-
navMobile: string;
|
|
19
|
-
backdrop: string;
|
|
20
|
-
};
|
|
21
|
-
};
|
|
22
|
-
}, {
|
|
23
|
-
root: string;
|
|
24
|
-
header: string;
|
|
25
|
-
body: string;
|
|
26
|
-
nav: string;
|
|
27
|
-
navMobile: string[];
|
|
28
|
-
main: string;
|
|
29
|
-
footer: string;
|
|
30
|
-
backdrop: string[];
|
|
31
|
-
}, undefined, {
|
|
32
|
-
navOpen: {
|
|
33
|
-
true: {
|
|
34
|
-
navMobile: string;
|
|
35
|
-
backdrop: string;
|
|
36
|
-
};
|
|
37
|
-
};
|
|
38
|
-
}, {
|
|
39
|
-
root: string;
|
|
40
|
-
header: string;
|
|
41
|
-
body: string;
|
|
42
|
-
nav: string;
|
|
43
|
-
navMobile: string[];
|
|
44
|
-
main: string;
|
|
45
|
-
footer: string;
|
|
46
|
-
backdrop: string[];
|
|
47
|
-
}, import("tailwind-variants").TVReturnType<{
|
|
48
|
-
navOpen: {
|
|
49
|
-
true: {
|
|
50
|
-
navMobile: string;
|
|
51
|
-
backdrop: string;
|
|
52
|
-
};
|
|
53
|
-
};
|
|
54
|
-
}, {
|
|
55
|
-
root: string;
|
|
56
|
-
header: string;
|
|
57
|
-
body: string;
|
|
58
|
-
nav: string;
|
|
59
|
-
navMobile: string[];
|
|
60
|
-
main: string;
|
|
61
|
-
footer: string;
|
|
62
|
-
backdrop: string[];
|
|
63
|
-
}, undefined, unknown, unknown, undefined>>;
|
|
64
|
-
export type AppShellVariants = VariantProps<typeof appShellVariants>;
|
|
65
|
-
//# sourceMappingURL=appShell.variants.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"appShell.variants.d.ts","sourceRoot":"","sources":["../../../src/components/AppShell/appShell.variants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAM,KAAK,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAE1D;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2CA8B3B,CAAC;AAEH,MAAM,MAAM,gBAAgB,GAAG,YAAY,CAAC,OAAO,gBAAgB,CAAC,CAAC"}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import type { AutocompleteOption, AutocompleteProps } from './autocomplete.types.js';
|
|
2
|
-
/**
|
|
3
|
-
* Dashforge TW Autocomplete — bridge-integrated single-select combobox.
|
|
4
|
-
*
|
|
5
|
-
* **Implementation note (F5-A, rev. 2)**
|
|
6
|
-
*
|
|
7
|
-
* The first revision wrapped `react-aria-components`' `<ComboBox>` to get
|
|
8
|
-
* AAA-grade a11y for free. In practice React Aria's internal state
|
|
9
|
-
* machine fought every controlled-state pattern we tried (the input text
|
|
10
|
-
* would not clear when `selectedKey` went to `null`, even with a forced
|
|
11
|
-
* remount via `key` bumping). To get deterministic behaviour we own all
|
|
12
|
-
* of the state ourselves:
|
|
13
|
-
*
|
|
14
|
-
* - `inputValue` — the visible text in the `<input>`
|
|
15
|
-
* - `isOpen` — popover visibility
|
|
16
|
-
* - `highlightedIndex` — keyboard navigation cursor
|
|
17
|
-
*
|
|
18
|
-
* A11y is still solid:
|
|
19
|
-
* - `role="combobox"` + `aria-autocomplete="list"` on the input
|
|
20
|
-
* - `aria-expanded`, `aria-controls`, `aria-activedescendant`
|
|
21
|
-
* - `role="listbox"` / `role="option"` with `aria-selected`
|
|
22
|
-
* - Full keyboard nav (↑/↓ navigate, Enter selects, Escape closes,
|
|
23
|
-
* Home/End jump, Tab closes, click-outside closes)
|
|
24
|
-
* - Required field gets `aria-required="true"`
|
|
25
|
-
*
|
|
26
|
-
* F5-A scope: single-select, static options, contains-substring filter
|
|
27
|
-
* (case-insensitive). Multi-select, free-solo text, generic option
|
|
28
|
-
* shapes, and async runtime options (`optionsFromFieldData`) are
|
|
29
|
-
* deferred to F5-A-bis.
|
|
30
|
-
*/
|
|
31
|
-
export declare function Autocomplete<TOption = AutocompleteOption>(props: AutocompleteProps<TOption>): import("react/jsx-runtime").JSX.Element | null;
|
|
32
|
-
//# sourceMappingURL=Autocomplete.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Autocomplete.d.ts","sourceRoot":"","sources":["../../../src/components/Autocomplete/Autocomplete.tsx"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EACV,kBAAkB,EAClB,iBAAiB,EAElB,MAAM,yBAAyB,CAAC;AAuCjC;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAG,kBAAkB,EACvD,KAAK,EAAE,iBAAiB,CAAC,OAAO,CAAC,kDAu4BlC"}
|