@bug-on/m3-expressive 1.0.0
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/CHANGELOG.md +110 -0
- package/README.md +110 -0
- package/dist/assets/fonts/GoogleSansFlex-VariableFont.woff2 +0 -0
- package/dist/assets/fonts/MaterialSymbolsOutlined-VariableFont_FILL,GRAD,opsz,wght.ttf +0 -0
- package/dist/assets/fonts/MaterialSymbolsRounded-VariableFont_FILL,GRAD,opsz,wght.ttf +0 -0
- package/dist/assets/fonts/MaterialSymbolsSharp-VariableFont_FILL,GRAD,opsz,wght.ttf +0 -0
- package/dist/assets/loading-indicator.svg +19 -0
- package/dist/assets/material-symbols-cdn.css +65 -0
- package/dist/assets/material-symbols-self-hosted.css +94 -0
- package/dist/buttons.d.mts +180 -0
- package/dist/buttons.d.ts +180 -0
- package/dist/buttons.js +4282 -0
- package/dist/buttons.js.map +1 -0
- package/dist/buttons.mjs +4227 -0
- package/dist/buttons.mjs.map +1 -0
- package/dist/core.d.mts +422 -0
- package/dist/core.d.ts +422 -0
- package/dist/core.js +2581 -0
- package/dist/core.js.map +1 -0
- package/dist/core.mjs +2547 -0
- package/dist/core.mjs.map +1 -0
- package/dist/feedback.d.mts +600 -0
- package/dist/feedback.d.ts +600 -0
- package/dist/feedback.js +2357 -0
- package/dist/feedback.js.map +1 -0
- package/dist/feedback.mjs +2321 -0
- package/dist/feedback.mjs.map +1 -0
- package/dist/forms.d.mts +40 -0
- package/dist/forms.d.ts +40 -0
- package/dist/forms.js +4263 -0
- package/dist/forms.js.map +1 -0
- package/dist/forms.mjs +4228 -0
- package/dist/forms.mjs.map +1 -0
- package/dist/icon-button-D-gs0gfj.d.mts +136 -0
- package/dist/icon-button-D-gs0gfj.d.ts +136 -0
- package/dist/index.css +309 -0
- package/dist/index.css.d.ts +2 -0
- package/dist/index.d.mts +24 -0
- package/dist/index.d.ts +24 -0
- package/dist/index.js +23972 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +23668 -0
- package/dist/index.mjs.map +1 -0
- package/dist/layout.d.mts +610 -0
- package/dist/layout.d.ts +610 -0
- package/dist/layout.js +5091 -0
- package/dist/layout.js.map +1 -0
- package/dist/layout.mjs +5042 -0
- package/dist/layout.mjs.map +1 -0
- package/dist/material-symbols-cdn.css +65 -0
- package/dist/material-symbols-cdn.css.d.ts +2 -0
- package/dist/material-symbols-self-hosted.css +94 -0
- package/dist/material-symbols-self-hosted.css.d.ts +2 -0
- package/dist/md3-DFhj-NZj.d.mts +17 -0
- package/dist/md3-DFhj-NZj.d.ts +17 -0
- package/dist/navigation.d.mts +2766 -0
- package/dist/navigation.d.ts +2766 -0
- package/dist/navigation.js +6684 -0
- package/dist/navigation.js.map +1 -0
- package/dist/navigation.mjs +6573 -0
- package/dist/navigation.mjs.map +1 -0
- package/dist/overlays.d.mts +161 -0
- package/dist/overlays.d.ts +161 -0
- package/dist/overlays.js +3298 -0
- package/dist/overlays.js.map +1 -0
- package/dist/overlays.mjs +3244 -0
- package/dist/overlays.mjs.map +1 -0
- package/dist/pickers.d.mts +1074 -0
- package/dist/pickers.d.ts +1074 -0
- package/dist/pickers.js +4240 -0
- package/dist/pickers.js.map +1 -0
- package/dist/pickers.mjs +4200 -0
- package/dist/pickers.mjs.map +1 -0
- package/dist/plugin.d.mts +1 -0
- package/dist/plugin.d.ts +1 -0
- package/dist/plugin.js +13 -0
- package/dist/plugin.js.map +1 -0
- package/dist/plugin.mjs +3 -0
- package/dist/plugin.mjs.map +1 -0
- package/dist/scroll-area-CVS6HyLl.d.mts +33 -0
- package/dist/scroll-area-CVS6HyLl.d.ts +33 -0
- package/dist/shapes.d.mts +1119 -0
- package/dist/shapes.d.ts +1119 -0
- package/dist/shapes.js +2941 -0
- package/dist/shapes.js.map +1 -0
- package/dist/shapes.mjs +2889 -0
- package/dist/shapes.mjs.map +1 -0
- package/dist/side-sheet-modal-BY6VCC8p.d.mts +553 -0
- package/dist/side-sheet-modal-CglP6KYA.d.ts +553 -0
- package/dist/split-button-trailing-uncheckable-C5CLCIKP.d.ts +731 -0
- package/dist/split-button-trailing-uncheckable-MXj_kyNt.d.mts +731 -0
- package/dist/text-field-eAIpz9z1.d.mts +1038 -0
- package/dist/text-field-eAIpz9z1.d.ts +1038 -0
- package/dist/typography-339RV6v7.d.mts +486 -0
- package/dist/typography-339RV6v7.d.ts +486 -0
- package/dist/typography.css +22 -0
- package/dist/typography.css.d.ts +2 -0
- package/package.json +207 -0
|
@@ -0,0 +1,1038 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
3
|
+
import { VariantProps } from 'class-variance-authority';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @file checkbox.tsx
|
|
7
|
+
* MD3 Expressive Checkbox — 2-state and tri-state support.
|
|
8
|
+
* Spec: https://m3.material.io/components/checkbox/overview
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Tri-state value: `"unchecked"` | `"checked"` | `"indeterminate"`.
|
|
13
|
+
*/
|
|
14
|
+
type CheckboxState = "unchecked" | "checked" | "indeterminate";
|
|
15
|
+
/**
|
|
16
|
+
* Props for `Checkbox`. Supports boolean (`checked`/`onCheckedChange`)
|
|
17
|
+
* and tri-state (`state`/`onStateChange`) modes.
|
|
18
|
+
*/
|
|
19
|
+
interface CheckboxProps {
|
|
20
|
+
/** Controlled checked value (2-state mode). */
|
|
21
|
+
checked?: boolean;
|
|
22
|
+
/** Initial value for uncontrolled mode. @default false */
|
|
23
|
+
defaultChecked?: boolean;
|
|
24
|
+
/** Forces indeterminate rendering regardless of `checked`. */
|
|
25
|
+
indeterminate?: boolean;
|
|
26
|
+
/** Fired on checked change (simple mode). Not called when disabled. */
|
|
27
|
+
onCheckedChange?: (checked: boolean) => void;
|
|
28
|
+
/** Controlled tri-state value. Takes priority over `checked`/`indeterminate`. */
|
|
29
|
+
state?: CheckboxState;
|
|
30
|
+
/** Fired on tri-state change. Cycles: unchecked → checked → indeterminate. */
|
|
31
|
+
onStateChange?: (state: CheckboxState) => void;
|
|
32
|
+
/** Disables interaction and applies 0.38 opacity. */
|
|
33
|
+
disabled?: boolean;
|
|
34
|
+
/** Error state — changes colors to `m3-error` and sets `aria-invalid`. */
|
|
35
|
+
error?: boolean;
|
|
36
|
+
/** Adjacent label text. Wraps checkbox + span in `<label>`. */
|
|
37
|
+
label?: string;
|
|
38
|
+
"aria-label"?: string;
|
|
39
|
+
"aria-labelledby"?: string;
|
|
40
|
+
"aria-describedby"?: string;
|
|
41
|
+
"aria-required"?: boolean;
|
|
42
|
+
/** Passed to the hidden `<input>` for form submission. */
|
|
43
|
+
name?: string;
|
|
44
|
+
/** Passed to the hidden `<input>` for form submission. */
|
|
45
|
+
value?: string;
|
|
46
|
+
/** ID for the hidden `<input>`. Auto-generated when `label` is set. */
|
|
47
|
+
id?: string;
|
|
48
|
+
/** Extra class names on the outermost wrapper. */
|
|
49
|
+
className?: string;
|
|
50
|
+
/** Ref pointing to the hidden `<input type="checkbox">`. */
|
|
51
|
+
ref?: React.Ref<HTMLInputElement>;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* `TriStateCheckbox` props — requires `state` + `onStateChange`.
|
|
55
|
+
*/
|
|
56
|
+
interface TriStateCheckboxProps extends Omit<CheckboxProps, "checked" | "defaultChecked" | "onCheckedChange"> {
|
|
57
|
+
state: CheckboxState;
|
|
58
|
+
onStateChange: (state: CheckboxState) => void;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* MD3 Expressive Checkbox component.
|
|
62
|
+
*
|
|
63
|
+
* Supports 2-state and tri-state patterns. Fully animated per MD3 spec:
|
|
64
|
+
* checkmark draw, indeterminate dash morph, container fill, state layer, and ripple.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```tsx
|
|
68
|
+
* <Checkbox checked={isChecked} onCheckedChange={setIsChecked} label="Accept terms" />
|
|
69
|
+
* <Checkbox state={parentState} onStateChange={setParentState} label="Select all" />
|
|
70
|
+
* <Checkbox error label="Required field" aria-describedby="err-msg" />
|
|
71
|
+
* ```
|
|
72
|
+
* @see https://m3.material.io/components/checkbox/overview
|
|
73
|
+
*/
|
|
74
|
+
declare const Checkbox: React.NamedExoticComponent<Omit<CheckboxProps, "ref"> & React.RefAttributes<HTMLInputElement>>;
|
|
75
|
+
/**
|
|
76
|
+
* MD3 Expressive Tri-State Checkbox.
|
|
77
|
+
*
|
|
78
|
+
* Convenience wrapper around `Checkbox` that enforces `state` + `onStateChange`.
|
|
79
|
+
* Ideal for parent-child selection patterns.
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```tsx
|
|
83
|
+
* <TriStateCheckbox state={parentState} onStateChange={setParentState} label="Select all" />
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
declare const TriStateCheckbox: React.NamedExoticComponent<Omit<TriStateCheckboxProps, "ref"> & React.RefAttributes<HTMLInputElement>>;
|
|
87
|
+
|
|
88
|
+
declare const chipVariants: (props?: ({
|
|
89
|
+
variant?: "input" | "filter" | "assist" | "suggestion" | null | undefined;
|
|
90
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
91
|
+
interface ChipProps extends Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "children"> {
|
|
92
|
+
/**
|
|
93
|
+
* Chip variant.
|
|
94
|
+
* - `assist` → Smart/automated actions. Flat by default, can be elevated.
|
|
95
|
+
* - `filter` → Toggleable tag/filter. Shows animated checkmark when selected.
|
|
96
|
+
* - `input` → Entity representation (tag, contact). Has optional avatar + remove button.
|
|
97
|
+
* - `suggestion` → Contextual suggestions. Like assist, flat by default, can be elevated.
|
|
98
|
+
* @default 'assist'
|
|
99
|
+
*/
|
|
100
|
+
variant?: VariantProps<typeof chipVariants>["variant"];
|
|
101
|
+
/**
|
|
102
|
+
* Renders with elevation shadow (Level 1) and fills background with `surface-container-low`.
|
|
103
|
+
* Applicable to `assist`, `filter` (unselected), and `suggestion` variants.
|
|
104
|
+
* Source: AssistChipTokens.ElevatedContainerColor / SuggestionChipTokens.ElevatedContainerColor
|
|
105
|
+
*/
|
|
106
|
+
elevated?: boolean;
|
|
107
|
+
/**
|
|
108
|
+
* Toggle/selection state.
|
|
109
|
+
* - `filter`: selected → bg `secondary-container`, animated checkmark appears.
|
|
110
|
+
* - `input`: selected → bg `secondary-container`.
|
|
111
|
+
* Used for `role="checkbox"` (filter) / `aria-pressed` (input).
|
|
112
|
+
*/
|
|
113
|
+
selected?: boolean;
|
|
114
|
+
/**
|
|
115
|
+
* Disables the chip. Applies:
|
|
116
|
+
* - `pointer-events-none` – no mouse/touch interaction
|
|
117
|
+
* - `opacity-[0.38]` – DisabledLabelTextOpacity (0.38) per MD3 tokens
|
|
118
|
+
* - `aria-disabled="true"`
|
|
119
|
+
* - `tabIndex={-1}`
|
|
120
|
+
*/
|
|
121
|
+
disabled?: boolean;
|
|
122
|
+
/**
|
|
123
|
+
* Visible label. Required. Can be a string or ReactNode.
|
|
124
|
+
*/
|
|
125
|
+
label: React.ReactNode;
|
|
126
|
+
/**
|
|
127
|
+
* Optional leading icon element (18×18px recommended).
|
|
128
|
+
* For `filter` chips with `selected=true`, this is replaced by an animated checkmark.
|
|
129
|
+
* For `assist`/`suggestion`: icon color → `primary`
|
|
130
|
+
* For `input` (unselected): icon color → `on-surface-variant`
|
|
131
|
+
*/
|
|
132
|
+
leadingIcon?: React.ReactNode;
|
|
133
|
+
/**
|
|
134
|
+
* Optional trailing icon element (18×18px recommended).
|
|
135
|
+
* Color: `on-surface-variant` (unselected) / `on-secondary-container` (selected).
|
|
136
|
+
*/
|
|
137
|
+
trailingIcon?: React.ReactNode;
|
|
138
|
+
/**
|
|
139
|
+
* Avatar element for `input` chips. Takes priority over `leadingIcon`.
|
|
140
|
+
* Rendered as a 24×24px circle (InputChipTokens: AvatarSize = 24.dp, AvatarShape = CornerFull).
|
|
141
|
+
*/
|
|
142
|
+
avatar?: React.ReactNode;
|
|
143
|
+
/**
|
|
144
|
+
* Callback when the trailing remove (×) button is activated on `input` chips.
|
|
145
|
+
* When provided, a dedicated tabbable close button with `aria-label="Remove {label}"` is rendered.
|
|
146
|
+
*/
|
|
147
|
+
onRemove?: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* MD3 Expressive Chip — 4-variant interactive tag component.
|
|
151
|
+
*
|
|
152
|
+
* @remarks
|
|
153
|
+
* - `filter` chips accept `selected` and render an animated checkmark.
|
|
154
|
+
* - `input` chips accept `onRemove` to render a compound close button.
|
|
155
|
+
* - `elevated` is supported on `assist`, `filter` (unselected), and `suggestion`.
|
|
156
|
+
* - Fully accessible: `role="checkbox"` for filter, `role="group"` for compound chips.
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* ```tsx
|
|
160
|
+
* // Assist chip
|
|
161
|
+
* <Chip variant="assist" label="Share" onClick={share} />
|
|
162
|
+
*
|
|
163
|
+
* // Filter chip
|
|
164
|
+
* <Chip variant="filter" label="Unread" selected={showUnread} onClick={toggle} />
|
|
165
|
+
*
|
|
166
|
+
* // Input chip with remove
|
|
167
|
+
* <Chip variant="input" label="React" onRemove={() => removeTag("React")} />
|
|
168
|
+
* ```
|
|
169
|
+
*
|
|
170
|
+
* @see https://m3.material.io/components/chips/overview
|
|
171
|
+
*/
|
|
172
|
+
declare const Chip: React.NamedExoticComponent<ChipProps & React.RefAttributes<HTMLButtonElement>>;
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* @file radio-button.tsx
|
|
176
|
+
* MD3 Expressive RadioButton — single-select with RadioGroup support.
|
|
177
|
+
* Spec: https://m3.material.io/components/radio-button/overview
|
|
178
|
+
*/
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Color variant for `RadioButton`.
|
|
182
|
+
* - `"primary"` — standard selection (default)
|
|
183
|
+
* - `"error"` — error/invalid state
|
|
184
|
+
*/
|
|
185
|
+
type RadioButtonColors = "primary" | "error";
|
|
186
|
+
/** Props for `RadioButton`. */
|
|
187
|
+
interface RadioButtonProps {
|
|
188
|
+
/** Whether this radio is selected. */
|
|
189
|
+
selected?: boolean;
|
|
190
|
+
/** Initial selected state (uncontrolled). @default false */
|
|
191
|
+
defaultSelected?: boolean;
|
|
192
|
+
/** Called when user clicks. Pass `null` to disable interaction. */
|
|
193
|
+
onClick?: (() => void) | null;
|
|
194
|
+
/** Disables the radio — visual disabled state + no interaction. @default false */
|
|
195
|
+
disabled?: boolean;
|
|
196
|
+
/** Color variant. @default "primary" */
|
|
197
|
+
color?: RadioButtonColors;
|
|
198
|
+
/** Error state — changes colors to `m3-error`. @default false */
|
|
199
|
+
error?: boolean;
|
|
200
|
+
/** Adjacent label text. Renders a `<label>` wrapper. */
|
|
201
|
+
label?: string;
|
|
202
|
+
/** Value used for form submission. */
|
|
203
|
+
value?: string;
|
|
204
|
+
/** Name for grouping (used in RadioGroup context). */
|
|
205
|
+
name?: string;
|
|
206
|
+
/** ID for the hidden `<input>`. Auto-generated when `label` is set. */
|
|
207
|
+
id?: string;
|
|
208
|
+
/** Extra class names on the outermost wrapper. */
|
|
209
|
+
className?: string;
|
|
210
|
+
/** ARIA label for the radio when no visible label exists. */
|
|
211
|
+
"aria-label"?: string;
|
|
212
|
+
"aria-labelledby"?: string;
|
|
213
|
+
"aria-describedby"?: string;
|
|
214
|
+
/** Whether the radio is required for form submission. */
|
|
215
|
+
required?: boolean;
|
|
216
|
+
/** Ref to the hidden `<input type="radio">`. */
|
|
217
|
+
ref?: React.Ref<HTMLInputElement>;
|
|
218
|
+
}
|
|
219
|
+
/** Props for `RadioGroup`. */
|
|
220
|
+
interface RadioGroupProps {
|
|
221
|
+
/** The name attribute shared across all child RadioButtons. */
|
|
222
|
+
name: string;
|
|
223
|
+
/** The currently selected value (controlled). */
|
|
224
|
+
value?: string;
|
|
225
|
+
/** Default value (uncontrolled). */
|
|
226
|
+
defaultValue?: string;
|
|
227
|
+
/** Called when selection changes. */
|
|
228
|
+
onValueChange?: (value: string) => void;
|
|
229
|
+
/** Disables all radio buttons in the group. */
|
|
230
|
+
disabled?: boolean;
|
|
231
|
+
/** Error state for the entire group. */
|
|
232
|
+
error?: boolean;
|
|
233
|
+
/** Label for the group (renders as visually hidden or visible heading). */
|
|
234
|
+
label?: string;
|
|
235
|
+
/** ID of an external element that labels this group. */
|
|
236
|
+
"aria-labelledby"?: string;
|
|
237
|
+
/** Direction of layout. @default "vertical" */
|
|
238
|
+
orientation?: "horizontal" | "vertical";
|
|
239
|
+
/** Whether at least one radio in the group must be selected. */
|
|
240
|
+
required?: boolean;
|
|
241
|
+
children: React.ReactNode;
|
|
242
|
+
className?: string;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* MD3 Expressive RadioButton component.
|
|
246
|
+
*
|
|
247
|
+
* Single-select control. Supports standalone (controlled/uncontrolled) and
|
|
248
|
+
* `RadioGroup` context. Animated per MD3 spec: inner dot radius morph,
|
|
249
|
+
* outer ring color transition, state layer, and ripple.
|
|
250
|
+
*
|
|
251
|
+
* @example
|
|
252
|
+
* ```tsx
|
|
253
|
+
* <RadioButton selected={isSelected} onClick={() => setSelected(true)} label="Option A" />
|
|
254
|
+
*
|
|
255
|
+
* <RadioGroup name="plan" value={plan} onValueChange={setPlan}>
|
|
256
|
+
* <RadioButton value="free" label="Free" />
|
|
257
|
+
* <RadioButton value="pro" label="Pro" />
|
|
258
|
+
* </RadioGroup>
|
|
259
|
+
* ```
|
|
260
|
+
* @see https://m3.material.io/components/radio-button/overview
|
|
261
|
+
*/
|
|
262
|
+
declare const RadioButton: React.NamedExoticComponent<Omit<RadioButtonProps, "ref"> & React.RefAttributes<HTMLInputElement>>;
|
|
263
|
+
/**
|
|
264
|
+
* MD3 Expressive RadioGroup component.
|
|
265
|
+
*
|
|
266
|
+
* Groups multiple `RadioButton` components under a shared `name` with keyboard
|
|
267
|
+
* navigation (Arrow keys with wrapping) and ARIA `radiogroup` semantics.
|
|
268
|
+
*
|
|
269
|
+
* @example
|
|
270
|
+
* ```tsx
|
|
271
|
+
* <RadioGroup name="theme" value={theme} onValueChange={setTheme} label="Theme">
|
|
272
|
+
* <RadioButton value="light" label="Light" />
|
|
273
|
+
* <RadioButton value="dark" label="Dark" />
|
|
274
|
+
* <RadioButton value="system" label="System" />
|
|
275
|
+
* </RadioGroup>
|
|
276
|
+
* ```
|
|
277
|
+
* @see https://m3.material.io/components/radio-button/overview
|
|
278
|
+
*/
|
|
279
|
+
declare const RadioGroup: React.NamedExoticComponent<RadioGroupProps & React.RefAttributes<HTMLDivElement>>;
|
|
280
|
+
|
|
281
|
+
/**
|
|
282
|
+
* @file slider.types.ts
|
|
283
|
+
* MD3 Expressive Slider — TypeScript prop definitions.
|
|
284
|
+
* Spec: https://m3.material.io/components/sliders/overview
|
|
285
|
+
* Reference: docs/m3/sliders/Slider.kt
|
|
286
|
+
*/
|
|
287
|
+
|
|
288
|
+
/** Track size variants mapping to physical px values. */
|
|
289
|
+
type SliderTrackSize = "xs" | "s" | "m" | "l" | "xl";
|
|
290
|
+
type SliderVariant = "primary" | "secondary" | "tertiary" | "error";
|
|
291
|
+
type SliderTrackShape = "md3" | "full" | number;
|
|
292
|
+
/** Slider layout direction. */
|
|
293
|
+
type SliderOrientation = "horizontal" | "vertical";
|
|
294
|
+
/**
|
|
295
|
+
* Props for the `<Slider>` component.
|
|
296
|
+
*
|
|
297
|
+
* Supports both controlled (`value` + `onValueChange`) and
|
|
298
|
+
* uncontrolled (`defaultValue`) usage patterns per React standards.
|
|
299
|
+
*
|
|
300
|
+
* @example
|
|
301
|
+
* ```tsx
|
|
302
|
+
* // Controlled
|
|
303
|
+
* <Slider value={volume} onValueChange={setVolume} min={0} max={100} />
|
|
304
|
+
*
|
|
305
|
+
* // Uncontrolled
|
|
306
|
+
* <Slider defaultValue={50} />
|
|
307
|
+
*
|
|
308
|
+
* // Discrete (step snapping)
|
|
309
|
+
* <Slider defaultValue={0} step={10} />
|
|
310
|
+
*
|
|
311
|
+
* // Vertical orientation
|
|
312
|
+
* <Slider defaultValue={50} orientation="vertical" />
|
|
313
|
+
*
|
|
314
|
+
* // Centered active track
|
|
315
|
+
* <Slider defaultValue={0} isCentered />
|
|
316
|
+
* ```
|
|
317
|
+
*/
|
|
318
|
+
interface SliderProps {
|
|
319
|
+
/** Controlled current value. Use with `onValueChange`. */
|
|
320
|
+
value?: number;
|
|
321
|
+
/** Initial value for uncontrolled usage. @default midpoint of min/max */
|
|
322
|
+
defaultValue?: number;
|
|
323
|
+
/** Called whenever the value changes during interaction. */
|
|
324
|
+
onValueChange?: (value: number) => void;
|
|
325
|
+
/** Called when the user finishes dragging / commits a keyboard change. */
|
|
326
|
+
onValueChangeEnd?: (value: number) => void;
|
|
327
|
+
/** Minimum value. @default 0 */
|
|
328
|
+
min?: number;
|
|
329
|
+
/** Maximum value. @default 100 */
|
|
330
|
+
max?: number;
|
|
331
|
+
/**
|
|
332
|
+
* Step size. When > 0, slider snaps to multiples of `step` from `min`
|
|
333
|
+
* and renders tick marks. When 0, slider is continuous.
|
|
334
|
+
* @default 0
|
|
335
|
+
*/
|
|
336
|
+
step?: number;
|
|
337
|
+
/** Layout orientation. @default "horizontal" */
|
|
338
|
+
orientation?: SliderOrientation;
|
|
339
|
+
/**
|
|
340
|
+
* Physical track size.
|
|
341
|
+
* Horizontal: height. Vertical: width.
|
|
342
|
+
* @default "m"
|
|
343
|
+
*/
|
|
344
|
+
trackSize?: SliderTrackSize;
|
|
345
|
+
/**
|
|
346
|
+
* Color variant.
|
|
347
|
+
* @default "primary"
|
|
348
|
+
*/
|
|
349
|
+
variant?: SliderVariant;
|
|
350
|
+
/**
|
|
351
|
+
* When true, the active track segment grows from the center (50%)
|
|
352
|
+
* outward toward the thumb position.
|
|
353
|
+
* @default false
|
|
354
|
+
*/
|
|
355
|
+
isCentered?: boolean;
|
|
356
|
+
/** Disables all interaction. @default false */
|
|
357
|
+
disabled?: boolean;
|
|
358
|
+
/**
|
|
359
|
+
* When true, shows a floating value indicator tooltip above the thumb.
|
|
360
|
+
* @default false
|
|
361
|
+
*/
|
|
362
|
+
showValueIndicator?: boolean;
|
|
363
|
+
/**
|
|
364
|
+
* When true, shows tick marks along the track.
|
|
365
|
+
* Only applicable if `step` > 0.
|
|
366
|
+
* @default false
|
|
367
|
+
*/
|
|
368
|
+
showTicks?: boolean;
|
|
369
|
+
/**
|
|
370
|
+
* Track shape configuration for border radius.
|
|
371
|
+
* - "md3": Default MD3 specific border radius per size
|
|
372
|
+
* - "full": Fully rounded ends (pill shape - size/2)
|
|
373
|
+
* - number: Custom border radius in px
|
|
374
|
+
* @default "md3"
|
|
375
|
+
*/
|
|
376
|
+
trackShape?: SliderTrackShape;
|
|
377
|
+
/**
|
|
378
|
+
* Icon rendered inside the track (inset icon).
|
|
379
|
+
* MD3 spec: only valid for M, L, XL track sizes.
|
|
380
|
+
* The icon moves from the active track to the inactive track
|
|
381
|
+
* when there's not enough space at low values.
|
|
382
|
+
* Do not use with `isCentered` or `RangeSlider`.
|
|
383
|
+
*/
|
|
384
|
+
insetIcon?: React.ReactNode;
|
|
385
|
+
/**
|
|
386
|
+
* Alternate icon shown when value equals `min`.
|
|
387
|
+
* Swaps with `insetIcon` at the minimum value
|
|
388
|
+
* (e.g., a mute icon replacing a volume icon when volume = 0).
|
|
389
|
+
*/
|
|
390
|
+
insetIconAtMin?: React.ReactNode;
|
|
391
|
+
/**
|
|
392
|
+
* Icon rendered inside the track at the trailing end (right side).
|
|
393
|
+
* Only valid for track sizes >= 40dp (e.g. XL).
|
|
394
|
+
*/
|
|
395
|
+
insetIconTrailing?: React.ReactNode;
|
|
396
|
+
/**
|
|
397
|
+
* Alternate icon shown when value equals `max`.
|
|
398
|
+
* Swaps with `insetIconTrailing` at the maximum value.
|
|
399
|
+
*/
|
|
400
|
+
insetIconAtMax?: React.ReactNode;
|
|
401
|
+
/** Additional CSS class applied to the outermost wrapper. */
|
|
402
|
+
className?: string;
|
|
403
|
+
/**
|
|
404
|
+
* Accessible label for the slider when no visible label exists.
|
|
405
|
+
* Required if parent does not have a visible label.
|
|
406
|
+
*/
|
|
407
|
+
"aria-label"?: string;
|
|
408
|
+
/** ID of a visible label element. Required if `aria-label` is not provided. */
|
|
409
|
+
"aria-labelledby"?: string;
|
|
410
|
+
/**
|
|
411
|
+
* Format function for the displayed value in the value indicator tooltip.
|
|
412
|
+
* Defaults to `String(value)`.
|
|
413
|
+
*/
|
|
414
|
+
formatValue?: (value: number) => string;
|
|
415
|
+
}
|
|
416
|
+
/**
|
|
417
|
+
* Props for the `<RangeSlider>` component.
|
|
418
|
+
*
|
|
419
|
+
* Extends `SliderProps` with tuple-based value API.
|
|
420
|
+
* The two thumbs cannot cross each other.
|
|
421
|
+
*
|
|
422
|
+
* @example
|
|
423
|
+
* ```tsx
|
|
424
|
+
* <RangeSlider
|
|
425
|
+
* value={[20, 80]}
|
|
426
|
+
* onValueChange={([start, end]) => setRange([start, end])}
|
|
427
|
+
* />
|
|
428
|
+
* ```
|
|
429
|
+
*/
|
|
430
|
+
interface RangeSliderProps extends Omit<SliderProps, "value" | "defaultValue" | "onValueChange" | "onValueChangeEnd" | "isCentered"> {
|
|
431
|
+
/** Controlled [start, end] tuple. Use with `onValueChange`. */
|
|
432
|
+
value?: [number, number];
|
|
433
|
+
/** Initial [start, end] tuple for uncontrolled usage. */
|
|
434
|
+
defaultValue?: [number, number];
|
|
435
|
+
/** Called whenever [start, end] changes during interaction. */
|
|
436
|
+
onValueChange?: (value: [number, number]) => void;
|
|
437
|
+
/** Called when the user finishes dragging either thumb. */
|
|
438
|
+
onValueChangeEnd?: (value: [number, number]) => void;
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Props for `<SliderThumb>`.
|
|
442
|
+
* @internal
|
|
443
|
+
*/
|
|
444
|
+
interface SliderThumbProps {
|
|
445
|
+
/** Current value (for ARIA). */
|
|
446
|
+
value: number;
|
|
447
|
+
/** Current 0–1 fraction (for positioning). */
|
|
448
|
+
percent: number;
|
|
449
|
+
min: number;
|
|
450
|
+
max: number;
|
|
451
|
+
step: number;
|
|
452
|
+
disabled: boolean;
|
|
453
|
+
orientation: SliderOrientation;
|
|
454
|
+
showValueIndicator: boolean;
|
|
455
|
+
/** For the drag constraint ref. */
|
|
456
|
+
trackRef: React.RefObject<HTMLDivElement | null>;
|
|
457
|
+
trackSize: SliderTrackSize;
|
|
458
|
+
variant: SliderVariant;
|
|
459
|
+
/** Called during pointer drag with new value. */
|
|
460
|
+
onValueChange: (value: number) => void;
|
|
461
|
+
/** Called on drag end / keyboard commit. */
|
|
462
|
+
onValueChangeEnd?: (value: number) => void;
|
|
463
|
+
/** Value display formatter. */
|
|
464
|
+
formatValue?: (value: number) => string;
|
|
465
|
+
/** Unique ID for ARIA. */
|
|
466
|
+
thumbId?: string;
|
|
467
|
+
/** zIndex for RangeSlider layering. */
|
|
468
|
+
zIndex?: number;
|
|
469
|
+
/** Optional accessible label for this specific thumb. */
|
|
470
|
+
"aria-label"?: string;
|
|
471
|
+
"aria-labelledby"?: string;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* @file range-slider.tsx
|
|
476
|
+
* MD3 Expressive RangeSlider — Two-thumb slider with crossover prevention.
|
|
477
|
+
*
|
|
478
|
+
* Extends the core Slider architecture with:
|
|
479
|
+
* - Two SliderThumb instances (start + end)
|
|
480
|
+
* - Crossover prevention: start cannot exceed end and vice versa
|
|
481
|
+
* - Z-index management: last-dragged thumb always on top
|
|
482
|
+
* - Active track spans from startPercent to endPercent
|
|
483
|
+
*
|
|
484
|
+
* Design decisions:
|
|
485
|
+
* - The track renders a custom "range" segment between the two thumbs.
|
|
486
|
+
* - Each thumb has independent onValueChange callbacks + crossover clamping.
|
|
487
|
+
* - Last-active thumb gets zIndex=2 to appear on top when thumbs are at same position.
|
|
488
|
+
*
|
|
489
|
+
* @see https://m3.material.io/components/sliders/overview
|
|
490
|
+
* @see docs/m3/sliders/Slider.kt#RangeSlider
|
|
491
|
+
*/
|
|
492
|
+
|
|
493
|
+
/**
|
|
494
|
+
* MD3 Expressive RangeSlider component.
|
|
495
|
+
*
|
|
496
|
+
* Two-thumb slider where the active track spans between the two thumbs.
|
|
497
|
+
* Thumbs cannot cross each other (crossover prevention built in).
|
|
498
|
+
*
|
|
499
|
+
* @example
|
|
500
|
+
* ```tsx
|
|
501
|
+
* // Controlled
|
|
502
|
+
* <RangeSlider
|
|
503
|
+
* value={[20, 80]}
|
|
504
|
+
* onValueChange={([start, end]) => setRange([start, end])}
|
|
505
|
+
* aria-label="Price range"
|
|
506
|
+
* />
|
|
507
|
+
*
|
|
508
|
+
* // Discrete
|
|
509
|
+
* <RangeSlider defaultValue={[0, 100]} step={10} />
|
|
510
|
+
*
|
|
511
|
+
* // Vertical
|
|
512
|
+
* <div className="h-64">
|
|
513
|
+
* <RangeSlider defaultValue={[25, 75]} orientation="vertical" />
|
|
514
|
+
* </div>
|
|
515
|
+
* ```
|
|
516
|
+
*
|
|
517
|
+
* @see https://m3.material.io/components/sliders/overview
|
|
518
|
+
*/
|
|
519
|
+
declare const RangeSlider: React.NamedExoticComponent<RangeSliderProps & React.RefAttributes<HTMLDivElement>>;
|
|
520
|
+
|
|
521
|
+
/**
|
|
522
|
+
* @file slider.tsx
|
|
523
|
+
* MD3 Expressive Slider — Main composition component.
|
|
524
|
+
*
|
|
525
|
+
* Supports:
|
|
526
|
+
* - Controlled and uncontrolled usage patterns
|
|
527
|
+
* - Horizontal and vertical orientations
|
|
528
|
+
* - Discrete mode (step snapping + tick marks)
|
|
529
|
+
* - Centered active track (isCentered)
|
|
530
|
+
* - Value indicator tooltip
|
|
531
|
+
* - Full keyboard navigation (ARIA Slider pattern)
|
|
532
|
+
* - Click-to-jump on track
|
|
533
|
+
*
|
|
534
|
+
* Architecture: Flat (no Context needed for single thumb variant).
|
|
535
|
+
* Track + Thumb are internal sub-components composed here.
|
|
536
|
+
*
|
|
537
|
+
* @see https://m3.material.io/components/sliders/overview
|
|
538
|
+
* @see docs/m3/sliders/Slider.kt
|
|
539
|
+
*/
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* MD3 Expressive Slider component.
|
|
543
|
+
*
|
|
544
|
+
* A pill-shaped vertical handle that slides along a rounded track.
|
|
545
|
+
* Supports continuous and discrete (step) modes, horizontal/vertical
|
|
546
|
+
* orientations, and centered active track.
|
|
547
|
+
*
|
|
548
|
+
* Features:
|
|
549
|
+
* - M3 Expressive handle: 4px pill that squeezes to 2px on press
|
|
550
|
+
* - 6px transparent gap between track and thumb
|
|
551
|
+
* - Asymmetric corner radii: outer ends=9999px, inner ends=2px
|
|
552
|
+
* - Tick marks for discrete mode
|
|
553
|
+
* - Optional floating value indicator tooltip
|
|
554
|
+
* - Full keyboard navigation per WAI-ARIA Slider pattern
|
|
555
|
+
*
|
|
556
|
+
* @example
|
|
557
|
+
* ```tsx
|
|
558
|
+
* // Basic controlled
|
|
559
|
+
* <Slider value={volume} onValueChange={setVolume} aria-label="Volume" />
|
|
560
|
+
*
|
|
561
|
+
* // Discrete with ticks
|
|
562
|
+
* <Slider defaultValue={0} step={10} min={0} max={100} />
|
|
563
|
+
*
|
|
564
|
+
* // Vertical orientation
|
|
565
|
+
* <div className="h-64">
|
|
566
|
+
* <Slider defaultValue={50} orientation="vertical" aria-label="Brightness" />
|
|
567
|
+
* </div>
|
|
568
|
+
*
|
|
569
|
+
* // Centered active track
|
|
570
|
+
* <Slider defaultValue={0} isCentered showValueIndicator />
|
|
571
|
+
*
|
|
572
|
+
* // Large track with value tooltip
|
|
573
|
+
* <Slider defaultValue={50} trackSize="l" showValueIndicator
|
|
574
|
+
* formatValue={(v) => `${v}%`} />
|
|
575
|
+
* ```
|
|
576
|
+
*
|
|
577
|
+
* @see https://m3.material.io/components/sliders/overview
|
|
578
|
+
*/
|
|
579
|
+
declare const Slider: React.NamedExoticComponent<SliderProps & React.RefAttributes<HTMLDivElement>>;
|
|
580
|
+
|
|
581
|
+
/**
|
|
582
|
+
* @file slider.tokens.ts
|
|
583
|
+
* MD3 Expressive Slider — Design tokens ported from:
|
|
584
|
+
* - SliderTokens.kt (Jetpack Compose M3 Expressive)
|
|
585
|
+
* - M3 Expressive visual spec (handle squeeze, gaps, asymmetric radii)
|
|
586
|
+
*
|
|
587
|
+
* All dimensional values are in px (dp equivalents for web).
|
|
588
|
+
* Colors reference CSS custom properties — do NOT hardcode hex.
|
|
589
|
+
* @see docs/m3/sliders/Slider.kt
|
|
590
|
+
*/
|
|
591
|
+
/**
|
|
592
|
+
* Core dimensional design tokens for the MD3 Expressive Slider.
|
|
593
|
+
* Maps directly from SliderTokens.kt to CSS/JS values.
|
|
594
|
+
*/
|
|
595
|
+
declare const SliderTokens: {
|
|
596
|
+
readonly trackSizes: {
|
|
597
|
+
xs: number;
|
|
598
|
+
s: number;
|
|
599
|
+
m: number;
|
|
600
|
+
l: number;
|
|
601
|
+
xl: number;
|
|
602
|
+
};
|
|
603
|
+
readonly trackShapes: {
|
|
604
|
+
xs: number;
|
|
605
|
+
s: number;
|
|
606
|
+
m: number;
|
|
607
|
+
l: number;
|
|
608
|
+
xl: number;
|
|
609
|
+
};
|
|
610
|
+
/** Thumb height grows with track size */
|
|
611
|
+
readonly thumbHeights: {
|
|
612
|
+
xs: number;
|
|
613
|
+
s: number;
|
|
614
|
+
m: number;
|
|
615
|
+
l: number;
|
|
616
|
+
xl: number;
|
|
617
|
+
};
|
|
618
|
+
/**
|
|
619
|
+
* Thumb width at rest and on hover.
|
|
620
|
+
* MD3 Expressive handle pill: 4dp wide.
|
|
621
|
+
*/
|
|
622
|
+
readonly thumbWidthDefault: 4;
|
|
623
|
+
/**
|
|
624
|
+
* Thumb width while pressed/dragging.
|
|
625
|
+
* "Squeeze" animation: 4dp → 2dp (M3 Expressive behavior).
|
|
626
|
+
*/
|
|
627
|
+
readonly thumbWidthPressed: 2;
|
|
628
|
+
/**
|
|
629
|
+
* Transparent gap between the active/inactive track segments and the thumb.
|
|
630
|
+
* Maps to ActiveHandleLeadingSpace / ActiveHandleTrailingSpace = 6dp.
|
|
631
|
+
*
|
|
632
|
+
* This gap is rendered by mathematically subtracting it from the track
|
|
633
|
+
* segment width — NOT using margin/padding.
|
|
634
|
+
*/
|
|
635
|
+
readonly thumbGap: 6;
|
|
636
|
+
/**
|
|
637
|
+
* Corner radius on the INNER ends of each track segment (facing the thumb).
|
|
638
|
+
* Fixed to 2px according to MD3 Expressive Slider specs (TrackInsideCornerSize).
|
|
639
|
+
* Outer ends use `trackSize / 2` (pill cap) — computed inline per component.
|
|
640
|
+
*/
|
|
641
|
+
readonly trackInnerRadius: 2;
|
|
642
|
+
/** Tick dot size (width and height). = 4dp. */
|
|
643
|
+
readonly tickSize: 4;
|
|
644
|
+
/**
|
|
645
|
+
* Minimum touch target for the thumb wrapper.
|
|
646
|
+
* MD3 requires 48dp minimum touch target for interactive elements.
|
|
647
|
+
*/
|
|
648
|
+
readonly thumbTouchTarget: 48;
|
|
649
|
+
/** Offset above the thumb center for the value indicator tooltip. */
|
|
650
|
+
readonly valueIndicatorOffset: 52;
|
|
651
|
+
/** Standard icon size map for inset icons inside the track. */
|
|
652
|
+
readonly insetIconSizes: {
|
|
653
|
+
xs: number;
|
|
654
|
+
s: number;
|
|
655
|
+
m: number;
|
|
656
|
+
l: number;
|
|
657
|
+
xl: number;
|
|
658
|
+
};
|
|
659
|
+
/**
|
|
660
|
+
* Padding between icon and track edge (horizontal).
|
|
661
|
+
* Keeps the icon visually centered within the pill track.
|
|
662
|
+
*/
|
|
663
|
+
readonly insetIconPadding: 4;
|
|
664
|
+
};
|
|
665
|
+
/**
|
|
666
|
+
* CSS custom property references for Slider colors.
|
|
667
|
+
* Maps to --md-sys-color-* tokens in the MD3 theme system.
|
|
668
|
+
*
|
|
669
|
+
* DO NOT hardcode hex/rgba values — these references automatically
|
|
670
|
+
* adapt to light/dark theme.
|
|
671
|
+
*/
|
|
672
|
+
declare const SliderColors: {
|
|
673
|
+
/** Active track color. Maps to ActiveTrackColor token. */
|
|
674
|
+
readonly activeTrack: "var(--md-sys-color-primary)";
|
|
675
|
+
/** Inactive track color. Maps to InactiveTrackColor token. */
|
|
676
|
+
readonly inactiveTrack: "var(--md-sys-color-secondary-container)";
|
|
677
|
+
/**
|
|
678
|
+
* Disabled track color.
|
|
679
|
+
* Uses opacity + on-surface per MD3 disabled state spec.
|
|
680
|
+
*/
|
|
681
|
+
readonly disabledActiveTrack: "var(--md-sys-color-on-surface)";
|
|
682
|
+
readonly disabledInactiveTrack: "var(--md-sys-color-on-surface)";
|
|
683
|
+
/** Thumb (handle) color. Maps to HandleColor token. */
|
|
684
|
+
readonly thumb: "var(--md-sys-color-primary)";
|
|
685
|
+
/** Disabled thumb color. */
|
|
686
|
+
readonly disabledThumb: "var(--md-sys-color-on-surface)";
|
|
687
|
+
/** Value indicator (tooltip) background. Maps to InverseSurface. */
|
|
688
|
+
readonly valueIndicatorBg: "var(--md-sys-color-inverse-surface)";
|
|
689
|
+
/** Value indicator (tooltip) text. Maps to InverseOnSurface. */
|
|
690
|
+
readonly valueIndicatorText: "var(--md-sys-color-inverse-on-surface)";
|
|
691
|
+
/**
|
|
692
|
+
* Tick on the INACTIVE portion of the track.
|
|
693
|
+
* Maps to TickMarkActiveContainerColor (in spec: primary color stands out).
|
|
694
|
+
*/
|
|
695
|
+
readonly tickOnInactive: "var(--md-sys-color-primary)";
|
|
696
|
+
/**
|
|
697
|
+
* Tick on the ACTIVE portion of the track.
|
|
698
|
+
* Maps to TickMarkInactiveContainerColor (secondary-container blends in).
|
|
699
|
+
*/
|
|
700
|
+
readonly tickOnActive: "var(--md-sys-color-secondary-container)";
|
|
701
|
+
readonly disabledTick: "var(--md-sys-color-on-surface)";
|
|
702
|
+
};
|
|
703
|
+
|
|
704
|
+
/**
|
|
705
|
+
* @file switch.types.ts
|
|
706
|
+
* MD3 Expressive Switch — TypeScript prop definitions.
|
|
707
|
+
* Spec: https://m3.material.io/components/switch/overview
|
|
708
|
+
*/
|
|
709
|
+
|
|
710
|
+
/**
|
|
711
|
+
* Props for the `Switch` component.
|
|
712
|
+
*
|
|
713
|
+
* @example
|
|
714
|
+
* ```tsx
|
|
715
|
+
* <Switch checked={isOn} onCheckedChange={setIsOn} label="Wi-Fi" />
|
|
716
|
+
* ```
|
|
717
|
+
*/
|
|
718
|
+
interface SwitchProps {
|
|
719
|
+
/** Controlled checked (on) state. */
|
|
720
|
+
checked: boolean;
|
|
721
|
+
/** Called when the switch is toggled. Not called when disabled. */
|
|
722
|
+
onCheckedChange: (checked: boolean) => void;
|
|
723
|
+
/** Disables interaction and applies disabled visual state. @default false */
|
|
724
|
+
disabled?: boolean;
|
|
725
|
+
/**
|
|
726
|
+
* Optional icon content rendered inside the thumb.
|
|
727
|
+
* Expected to measure 16dp (SwitchTokens.iconSize).
|
|
728
|
+
*/
|
|
729
|
+
thumbContent?: React.ReactNode;
|
|
730
|
+
/**
|
|
731
|
+
* When true, shows thumb icons in both selected and unselected states.
|
|
732
|
+
* Requires `thumbContent` to be provided.
|
|
733
|
+
* @default false
|
|
734
|
+
*/
|
|
735
|
+
icons?: boolean;
|
|
736
|
+
/**
|
|
737
|
+
* When true, shows the icon only in the selected/checked state.
|
|
738
|
+
* Requires `thumbContent` to be provided.
|
|
739
|
+
* @default false
|
|
740
|
+
*/
|
|
741
|
+
showOnlySelectedIcon?: boolean;
|
|
742
|
+
/**
|
|
743
|
+
* Visible label text rendered adjacent to the switch.
|
|
744
|
+
* When provided, wraps the switch in a `<label>` for accessibility.
|
|
745
|
+
*/
|
|
746
|
+
label?: string;
|
|
747
|
+
/**
|
|
748
|
+
* Overrides the accessible name. Used when no visible `label` is provided.
|
|
749
|
+
* Maps to the `aria-label` attribute.
|
|
750
|
+
*/
|
|
751
|
+
ariaLabel?: string;
|
|
752
|
+
/** Additional CSS class names applied to the outermost wrapper. */
|
|
753
|
+
className?: string;
|
|
754
|
+
/** Override track background color when checked. Defaults to MD3 primary. */
|
|
755
|
+
checkedTrackColor?: string;
|
|
756
|
+
/** Override track background color when unchecked. Defaults to MD3 surface-container-highest. */
|
|
757
|
+
uncheckedTrackColor?: string;
|
|
758
|
+
/** Override thumb color when checked. Defaults to MD3 on-primary. */
|
|
759
|
+
checkedThumbColor?: string;
|
|
760
|
+
/** Override thumb color when unchecked. Defaults to MD3 outline. */
|
|
761
|
+
uncheckedThumbColor?: string;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
/**
|
|
765
|
+
* @file switch.tsx
|
|
766
|
+
* MD3 Expressive Switch — ARIA switch pattern with Framer Motion animations.
|
|
767
|
+
* Spec: https://m3.material.io/components/switch/overview
|
|
768
|
+
*
|
|
769
|
+
* Key decisions:
|
|
770
|
+
* - Uses `<button role="switch">` (no <input>) per MD3 accessibility spec
|
|
771
|
+
* - Framer Motion for ALL animations (thumb x, size morph, state layer, icons)
|
|
772
|
+
* - Hover state via useState (required for Framer Motion color animate)
|
|
773
|
+
* - Disabled colors via rgba() literals (color-mix() not animatable by FM)
|
|
774
|
+
*/
|
|
775
|
+
|
|
776
|
+
/**
|
|
777
|
+
* MD3 Expressive Switch component.
|
|
778
|
+
*
|
|
779
|
+
* Toggles a single item on or off. Implements the ARIA switch pattern
|
|
780
|
+
* (`role="switch"`) without `<input>`. Fully animated per MD3 spec:
|
|
781
|
+
* thumb translation, size morph (16→24→28px), state layer, and icon cross-fade.
|
|
782
|
+
*
|
|
783
|
+
* @example
|
|
784
|
+
* ```tsx
|
|
785
|
+
* <Switch checked={isOn} onCheckedChange={setIsOn} label="Wi-Fi" />
|
|
786
|
+
* <Switch checked={isOn} onCheckedChange={setIsOn} icons thumbContent={<CheckIcon />} />
|
|
787
|
+
* <Switch checked={isOn} onCheckedChange={setIsOn} disabled />
|
|
788
|
+
* ```
|
|
789
|
+
*
|
|
790
|
+
* @see https://m3.material.io/components/switch/overview
|
|
791
|
+
*/
|
|
792
|
+
declare const Switch: React.NamedExoticComponent<SwitchProps & React.RefAttributes<HTMLButtonElement>>;
|
|
793
|
+
|
|
794
|
+
/**
|
|
795
|
+
* @file switch.tokens.ts
|
|
796
|
+
* MD3 Expressive Switch — Design tokens ported from SwitchTokens.kt.
|
|
797
|
+
* All dimensional values are in px (dp equivalent for web).
|
|
798
|
+
* @see docs/m3/switch/SwitchTokens.kt
|
|
799
|
+
*/
|
|
800
|
+
/**
|
|
801
|
+
* Design tokens for the MD3 Expressive Switch component.
|
|
802
|
+
*
|
|
803
|
+
* Maps directly from `SwitchTokens.kt` (v0_210) to CSS/JS values.
|
|
804
|
+
* Use these as the single source of truth for sizing and opacity.
|
|
805
|
+
*
|
|
806
|
+
* Color tokens are NOT included here — they reference CSS custom properties
|
|
807
|
+
* from the project's MD3 theme system (`--md-sys-color-*`).
|
|
808
|
+
*/
|
|
809
|
+
declare const SwitchTokens: {
|
|
810
|
+
/** SwitchTokens.TrackWidth = 52dp */
|
|
811
|
+
readonly trackWidth: 52;
|
|
812
|
+
/** SwitchTokens.TrackHeight = 32dp */
|
|
813
|
+
readonly trackHeight: 32;
|
|
814
|
+
/** SwitchTokens.TrackOutlineWidth = 2dp */
|
|
815
|
+
readonly trackOutlineWidth: 2;
|
|
816
|
+
/** SwitchTokens.SelectedHandleWidth/Height = 24dp */
|
|
817
|
+
readonly selectedHandleSize: 24;
|
|
818
|
+
/** SwitchTokens.UnselectedHandleWidth/Height = 16dp */
|
|
819
|
+
readonly unselectedHandleSize: 16;
|
|
820
|
+
/** SwitchTokens.IconHandleWidth/Height = 24dp (when thumb has icon content) */
|
|
821
|
+
readonly iconHandleSize: 24;
|
|
822
|
+
/** SwitchTokens.PressedHandleWidth/Height = 28dp */
|
|
823
|
+
readonly pressedHandleSize: 28;
|
|
824
|
+
/** SwitchTokens.StateLayerSize = 40dp */
|
|
825
|
+
readonly stateLayerSize: 40;
|
|
826
|
+
/** SwitchTokens.SelectedIconSize / UnselectedIconSize = 16dp */
|
|
827
|
+
readonly iconSize: 16;
|
|
828
|
+
/** SwitchTokens.DisabledTrackOpacity = 0.12 */
|
|
829
|
+
readonly disabledTrackOpacity: 0.12;
|
|
830
|
+
/** SwitchTokens.DisabledSelectedHandleOpacity = 1.0 */
|
|
831
|
+
readonly disabledSelectedHandleOpacity: 1;
|
|
832
|
+
/** SwitchTokens.DisabledUnselectedHandleOpacity = 0.38 */
|
|
833
|
+
readonly disabledUnselectedHandleOpacity: 0.38;
|
|
834
|
+
/** SwitchTokens.DisabledSelectedIconOpacity = 0.38 */
|
|
835
|
+
readonly disabledSelectedIconOpacity: 0.38;
|
|
836
|
+
/** SwitchTokens.DisabledUnselectedIconOpacity = 0.38 */
|
|
837
|
+
readonly disabledUnselectedIconOpacity: 0.38;
|
|
838
|
+
};
|
|
839
|
+
/**
|
|
840
|
+
* CSS custom property references for Switch colors.
|
|
841
|
+
* These map to the project's `--md-sys-color-*` tokens in `colors.css`.
|
|
842
|
+
*
|
|
843
|
+
* DO NOT hardcode hex values — always use these references so the
|
|
844
|
+
* component automatically adapts to light/dark theme switching.
|
|
845
|
+
*/
|
|
846
|
+
declare const SwitchColors: {
|
|
847
|
+
readonly checkedTrack: "var(--md-sys-color-primary)";
|
|
848
|
+
readonly uncheckedTrack: "var(--md-sys-color-surface-container-highest)";
|
|
849
|
+
readonly uncheckedTrackOutline: "var(--md-sys-color-outline)";
|
|
850
|
+
readonly checkedThumb: "var(--md-sys-color-on-primary)";
|
|
851
|
+
readonly uncheckedThumb: "var(--md-sys-color-outline)";
|
|
852
|
+
readonly hoverCheckedThumb: "var(--md-sys-color-primary-container)";
|
|
853
|
+
readonly hoverUncheckedThumb: "var(--md-sys-color-on-surface-variant)";
|
|
854
|
+
readonly disabledCheckedThumb: "var(--md-sys-color-surface)";
|
|
855
|
+
readonly checkedIcon: "var(--md-sys-color-on-primary-container)";
|
|
856
|
+
readonly uncheckedIcon: "var(--md-sys-color-surface-container-highest)";
|
|
857
|
+
readonly checkedStateLayer: "var(--md-sys-color-primary)";
|
|
858
|
+
readonly uncheckedStateLayer: "var(--md-sys-color-on-surface)";
|
|
859
|
+
readonly focusIndicator: "var(--md-sys-color-secondary)";
|
|
860
|
+
};
|
|
861
|
+
|
|
862
|
+
/**
|
|
863
|
+
* @file text-field.types.ts
|
|
864
|
+
* TypeScript interfaces and types for TextField MD3 Expressive component.
|
|
865
|
+
* @see https://m3.material.io/components/text-fields/overview
|
|
866
|
+
*/
|
|
867
|
+
|
|
868
|
+
type TextFieldVariant = "filled" | "outlined";
|
|
869
|
+
type TextFieldInputType = "text" | "email" | "number" | "password" | "search" | "tel" | "url" | "textarea";
|
|
870
|
+
type TextFieldTrailingIconMode = "none" | "clear" | "password-toggle" | "custom";
|
|
871
|
+
/**
|
|
872
|
+
* Imperative handle exposed via forwardRef.
|
|
873
|
+
* Allows parent components to programmatically control the text field.
|
|
874
|
+
*/
|
|
875
|
+
interface TextFieldHandle {
|
|
876
|
+
/** Focuses the input element. */
|
|
877
|
+
focus(): void;
|
|
878
|
+
/** Blurs the input element. */
|
|
879
|
+
blur(): void;
|
|
880
|
+
/** Selects all text in the input. */
|
|
881
|
+
select(): void;
|
|
882
|
+
/** Clears the current value and fires onChange with empty string. */
|
|
883
|
+
clear(): void;
|
|
884
|
+
/** Sets a custom validation message on the native input. */
|
|
885
|
+
setCustomValidity(message: string): void;
|
|
886
|
+
/** Returns true if the input is valid. Does not show validation UI. */
|
|
887
|
+
checkValidity(): boolean;
|
|
888
|
+
/** Returns true if the input is valid. Shows validation UI if invalid. */
|
|
889
|
+
reportValidity(): boolean;
|
|
890
|
+
/** Returns the current value string. */
|
|
891
|
+
getValue(): string;
|
|
892
|
+
/** Returns the underlying input or textarea element. */
|
|
893
|
+
getInputElement(): HTMLInputElement | HTMLTextAreaElement | null;
|
|
894
|
+
}
|
|
895
|
+
interface TextFieldProps {
|
|
896
|
+
/** Filled or outlined variant. @default 'filled' */
|
|
897
|
+
variant?: TextFieldVariant;
|
|
898
|
+
/** Floating label text. Also used as accessible name when no aria-label is set. */
|
|
899
|
+
label?: string;
|
|
900
|
+
/** Controlled value. Use with onChange for controlled mode. */
|
|
901
|
+
value?: string;
|
|
902
|
+
/** Initial value for uncontrolled mode. */
|
|
903
|
+
defaultValue?: string;
|
|
904
|
+
/** Fires when value changes. Receives new value string and native event. */
|
|
905
|
+
onChange?: (value: string, event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
|
|
906
|
+
/** Input type. Use 'textarea' for multi-line input. @default 'text' */
|
|
907
|
+
type?: TextFieldInputType;
|
|
908
|
+
/** Placeholder text — shown only when no label OR label is floated. */
|
|
909
|
+
placeholder?: string;
|
|
910
|
+
name?: string;
|
|
911
|
+
id?: string;
|
|
912
|
+
autoComplete?: string;
|
|
913
|
+
inputMode?: React.HTMLAttributes<HTMLInputElement>["inputMode"];
|
|
914
|
+
/** Number of rows for textarea type. @default 2 */
|
|
915
|
+
rows?: number;
|
|
916
|
+
/** Number of columns for textarea type. @default 20 */
|
|
917
|
+
cols?: number;
|
|
918
|
+
/** Whether the textarea should automatically resize to fit its content. @default false */
|
|
919
|
+
autoResize?: boolean;
|
|
920
|
+
/** Maximum number of rows when autoResize is true. */
|
|
921
|
+
maxRows?: number;
|
|
922
|
+
/** CSS direction override for input text. */
|
|
923
|
+
textDirection?: "ltr" | "rtl" | "";
|
|
924
|
+
/** Marks field as required. Shows asterisk on label. */
|
|
925
|
+
required?: boolean;
|
|
926
|
+
/** Hides the asterisk even when required=true. */
|
|
927
|
+
noAsterisk?: boolean;
|
|
928
|
+
/** Manual error override — forces error visual state. */
|
|
929
|
+
error?: boolean;
|
|
930
|
+
/** Error message shown below the field (replaces supportingText). */
|
|
931
|
+
errorText?: string;
|
|
932
|
+
minLength?: number;
|
|
933
|
+
/** When set, enables character counter display. */
|
|
934
|
+
maxLength?: number;
|
|
935
|
+
min?: string;
|
|
936
|
+
max?: string;
|
|
937
|
+
step?: string;
|
|
938
|
+
pattern?: string;
|
|
939
|
+
/** For type="email" — allows multiple email addresses. */
|
|
940
|
+
multiple?: boolean;
|
|
941
|
+
/** Helper text shown below the field. Replaced by errorText when in error state. */
|
|
942
|
+
supportingText?: string;
|
|
943
|
+
/** Text displayed before the input value (e.g., "$"). */
|
|
944
|
+
prefixText?: string;
|
|
945
|
+
/** Text displayed after the input value (e.g., ".00"). */
|
|
946
|
+
suffixText?: string;
|
|
947
|
+
/** Icon node for the leading slot. Should be 24×24px. */
|
|
948
|
+
leadingIcon?: React.ReactNode;
|
|
949
|
+
/** Custom trailing icon node. Used when trailingIconMode='custom'. */
|
|
950
|
+
trailingIcon?: React.ReactNode;
|
|
951
|
+
/**
|
|
952
|
+
* Built-in trailing icon behavior.
|
|
953
|
+
* - 'none' — no trailing icon
|
|
954
|
+
* - 'clear' — ✕ button, clears value when clicked
|
|
955
|
+
* - 'password-toggle' — eye icon, toggles password visibility
|
|
956
|
+
* - 'custom' — uses trailingIcon prop
|
|
957
|
+
* @default 'none'
|
|
958
|
+
*/
|
|
959
|
+
trailingIconMode?: TextFieldTrailingIconMode;
|
|
960
|
+
disabled?: boolean;
|
|
961
|
+
readOnly?: boolean;
|
|
962
|
+
/** Hides spinner arrows on type="number". */
|
|
963
|
+
noSpinner?: boolean;
|
|
964
|
+
form?: string;
|
|
965
|
+
"aria-label"?: string;
|
|
966
|
+
"aria-describedby"?: string;
|
|
967
|
+
"aria-labelledby"?: string;
|
|
968
|
+
/** Extra class applied to the root wrapper element. */
|
|
969
|
+
className?: string;
|
|
970
|
+
/** Makes the component fill its container width. */
|
|
971
|
+
fullWidth?: boolean;
|
|
972
|
+
/** Dense variant — reduced height (48px instead of 56px). */
|
|
973
|
+
dense?: boolean;
|
|
974
|
+
onFocus?: React.FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>;
|
|
975
|
+
onBlur?: React.FocusEventHandler<HTMLInputElement | HTMLTextAreaElement>;
|
|
976
|
+
onKeyDown?: React.KeyboardEventHandler<HTMLInputElement | HTMLTextAreaElement>;
|
|
977
|
+
onKeyUp?: React.KeyboardEventHandler<HTMLInputElement | HTMLTextAreaElement>;
|
|
978
|
+
ref?: React.Ref<TextFieldHandle>;
|
|
979
|
+
/**
|
|
980
|
+
* Controls when the scrollbars are visible when type="textarea".
|
|
981
|
+
* - `hover`: Show on hover (default)
|
|
982
|
+
* - `scroll`: Show only while scrolling
|
|
983
|
+
* - `always`: Always visible
|
|
984
|
+
* - `none`: Never visible
|
|
985
|
+
*/
|
|
986
|
+
scrollAreaType?: "hover" | "scroll" | "always" | "none";
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
/**
|
|
990
|
+
* @file text-field.tsx
|
|
991
|
+
* MD3 Expressive TextField — Filled & Outlined variants.
|
|
992
|
+
*
|
|
993
|
+
* Features:
|
|
994
|
+
* - Floating label animation (Framer Motion)
|
|
995
|
+
* - Filled (active indicator) and Outlined (notch border) variants
|
|
996
|
+
* - Controlled & uncontrolled value handling
|
|
997
|
+
* - Built-in clear button, password toggle
|
|
998
|
+
* - Prefix / suffix text
|
|
999
|
+
* - Supporting text, error text, character counter
|
|
1000
|
+
* - Leading & trailing icon slots
|
|
1001
|
+
* - Textarea support
|
|
1002
|
+
* - Native form validation + imperative handle
|
|
1003
|
+
* - Full WCAG AA accessibility
|
|
1004
|
+
* - prefers-reduced-motion support
|
|
1005
|
+
*
|
|
1006
|
+
* @see https://m3.material.io/components/text-fields/overview
|
|
1007
|
+
*/
|
|
1008
|
+
|
|
1009
|
+
/**
|
|
1010
|
+
* MD3 Expressive TextField.
|
|
1011
|
+
*
|
|
1012
|
+
* Supports `filled` and `outlined` variants, floating label animation,
|
|
1013
|
+
* prefix/suffix, leading/trailing icons, supporting text, character counter,
|
|
1014
|
+
* textarea mode, clear button, password toggle, and native form validation.
|
|
1015
|
+
*
|
|
1016
|
+
* @example
|
|
1017
|
+
* ```tsx
|
|
1018
|
+
* // Filled (default)
|
|
1019
|
+
* <TextField label="Email" type="email" />
|
|
1020
|
+
*
|
|
1021
|
+
* // Outlined with error
|
|
1022
|
+
* <TextField variant="outlined" label="Username" error errorText="Already taken" />
|
|
1023
|
+
*
|
|
1024
|
+
* // With clear button
|
|
1025
|
+
* <TextField label="Search" trailingIconMode="clear" />
|
|
1026
|
+
*
|
|
1027
|
+
* // Password with toggle
|
|
1028
|
+
* <TextField label="Password" type="password" trailingIconMode="password-toggle" />
|
|
1029
|
+
*
|
|
1030
|
+
* // With character counter
|
|
1031
|
+
* <TextField label="Bio" maxLength={140} supportingText="Describe yourself" />
|
|
1032
|
+
* ```
|
|
1033
|
+
*
|
|
1034
|
+
* @see https://m3.material.io/components/text-fields/overview
|
|
1035
|
+
*/
|
|
1036
|
+
declare const TextField: React.NamedExoticComponent<Omit<TextFieldProps, "ref"> & React.RefAttributes<TextFieldHandle>>;
|
|
1037
|
+
|
|
1038
|
+
export { type TriStateCheckboxProps as A, type SliderThumbProps as B, Checkbox as C, RadioButton as R, Slider as S, TextField as T, type CheckboxProps as a, type CheckboxState as b, Chip as c, type ChipProps as d, type RadioButtonColors as e, type RadioButtonProps as f, RadioGroup as g, type RadioGroupProps as h, RangeSlider as i, type RangeSliderProps as j, SliderColors as k, type SliderOrientation as l, type SliderProps as m, SliderTokens as n, type SliderTrackSize as o, type SliderVariant as p, Switch as q, SwitchColors as r, type SwitchProps as s, SwitchTokens as t, type TextFieldHandle as u, type TextFieldInputType as v, type TextFieldProps as w, type TextFieldTrailingIconMode as x, type TextFieldVariant as y, TriStateCheckbox as z };
|