@tinybigui/react 0.1.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,3329 @@
1
+ import $7jXr9$clsx, { clsx } from 'clsx';
2
+ import { twMerge } from 'tailwind-merge';
3
+ import { argbFromHex, themeFromSourceColor } from '@material/material-color-utilities';
4
+ export { argbFromHex, hexFromArgb } from '@material/material-color-utilities';
5
+ import $3whtM$react, { forwardRef, useRef, createContext, useEffect, useContext, useState, useCallback, useMemo, useReducer } from 'react';
6
+ import { useButton, useTextField, useFocusRing, useCheckbox, VisuallyHidden, mergeProps, useSwitch, useRadioGroup, useRadio } from 'react-aria';
7
+ import { jsx, jsxs } from 'react/jsx-runtime';
8
+ import { cva } from 'class-variance-authority';
9
+
10
+ // src/utils/cn.ts
11
+ function cn(...inputs) {
12
+ return twMerge(clsx(inputs));
13
+ }
14
+ function getColorValue(variable, element = document.documentElement) {
15
+ const varName = variable.startsWith("--") ? variable : `--${variable}`;
16
+ return getComputedStyle(element).getPropertyValue(varName).trim();
17
+ }
18
+ function getMD3Color(role) {
19
+ return getColorValue(`--md-sys-color-${role}`);
20
+ }
21
+ function withOpacity(color, opacity) {
22
+ const hex = color.replace("#", "");
23
+ const alpha = Math.round(Math.max(0, Math.min(1, opacity)) * 255).toString(16).padStart(2, "0");
24
+ return `#${hex}${alpha}`;
25
+ }
26
+ function hexToRgb(hex) {
27
+ const h = hex.replace("#", "");
28
+ const r = parseInt(h.substring(0, 2), 16);
29
+ const g = parseInt(h.substring(2, 4), 16);
30
+ const b = parseInt(h.substring(4, 6), 16);
31
+ return { r, g, b };
32
+ }
33
+ function rgbToHex(r, g, b) {
34
+ const toHex = (n) => {
35
+ const hex = Math.max(0, Math.min(255, Math.round(n))).toString(16);
36
+ return hex.padStart(2, "0");
37
+ };
38
+ return `#${toHex(r)}${toHex(g)}${toHex(b)}`;
39
+ }
40
+ function generateMD3Theme(seedColor) {
41
+ const argb = argbFromHex(seedColor);
42
+ return themeFromSourceColor(argb);
43
+ }
44
+ var STATE_LAYER_OPACITY = {
45
+ hover: 0.08,
46
+ focus: 0.12,
47
+ press: 0.12,
48
+ drag: 0.16
49
+ };
50
+ function applyStateLayer(color, state) {
51
+ return withOpacity(color, STATE_LAYER_OPACITY[state]);
52
+ }
53
+
54
+ // src/utils/typography.ts
55
+ function getTypographyToken(style, property) {
56
+ return getColorValue(`--md-sys-typescale-${style}-${property}`);
57
+ }
58
+ function getTypographyStyle(style, includeFontFamily = false) {
59
+ const styleObject = {
60
+ fontSize: getTypographyToken(style, "size"),
61
+ lineHeight: getTypographyToken(style, "line-height"),
62
+ fontWeight: getTypographyToken(style, "weight"),
63
+ letterSpacing: getTypographyToken(style, "tracking")
64
+ };
65
+ if (includeFontFamily) {
66
+ styleObject.fontFamily = getColorValue("--md-sys-typescale-font-family-plain");
67
+ }
68
+ return styleObject;
69
+ }
70
+ function getFontFamily(variant = "plain") {
71
+ return getColorValue(`--md-sys-typescale-font-family-${variant}`);
72
+ }
73
+ var TYPOGRAPHY_ELEMENT_MAP = {
74
+ h1: "display-large",
75
+ h2: "display-medium",
76
+ h3: "headline-large",
77
+ h4: "headline-medium",
78
+ h5: "headline-small",
79
+ h6: "title-large",
80
+ p: "body-large",
81
+ span: "body-medium",
82
+ small: "body-small",
83
+ button: "label-large",
84
+ label: "label-medium",
85
+ caption: "label-small"
86
+ };
87
+ function getTypographyForElement(element) {
88
+ return TYPOGRAPHY_ELEMENT_MAP[element];
89
+ }
90
+ var TYPOGRAPHY_USAGE = {
91
+ display: "Large, expressive text for hero sections and marketing",
92
+ headline: "High-emphasis text for titles and important headings",
93
+ title: "Medium-emphasis text for section headers and card titles",
94
+ body: "Plain text for paragraphs, lists, and general content",
95
+ label: "UI labels, buttons, tabs, and form elements"
96
+ };
97
+ function getTypographyClassName(style) {
98
+ return `text-${style}`;
99
+ }
100
+ function getResponsiveTypography(mobile, tablet, desktop) {
101
+ return {
102
+ mobile: getTypographyStyle(mobile),
103
+ ...tablet && { tablet: getTypographyStyle(tablet) },
104
+ ...desktop && { desktop: getTypographyStyle(desktop) }
105
+ };
106
+ }
107
+ function remToPx(rem) {
108
+ const remValue = parseFloat(rem.replace("rem", ""));
109
+ return remValue * 16;
110
+ }
111
+ function pxToRem(px) {
112
+ const pxValue = typeof px === "string" ? parseFloat(px.replace("px", "")) : px;
113
+ return `${pxValue / 16}rem`;
114
+ }
115
+ function truncateText(lines = 1) {
116
+ if (lines === 1) {
117
+ return {
118
+ overflow: "hidden",
119
+ textOverflow: "ellipsis",
120
+ whiteSpace: "nowrap"
121
+ };
122
+ }
123
+ return {
124
+ display: "-webkit-box",
125
+ WebkitLineClamp: lines,
126
+ WebkitBoxOrient: "vertical",
127
+ overflow: "hidden",
128
+ textOverflow: "ellipsis"
129
+ };
130
+ }
131
+ var $bdb11010cef70236$export$d41a04c74483c6ef = /* @__PURE__ */ new Map();
132
+ if (typeof FinalizationRegistry !== "undefined") new FinalizationRegistry((heldValue) => {
133
+ $bdb11010cef70236$export$d41a04c74483c6ef.delete(heldValue);
134
+ });
135
+ function $bdb11010cef70236$export$cd8c9cb68f842629(idA, idB) {
136
+ if (idA === idB) return idA;
137
+ let setIdsA = $bdb11010cef70236$export$d41a04c74483c6ef.get(idA);
138
+ if (setIdsA) {
139
+ setIdsA.forEach((ref) => ref.current = idB);
140
+ return idB;
141
+ }
142
+ let setIdsB = $bdb11010cef70236$export$d41a04c74483c6ef.get(idB);
143
+ if (setIdsB) {
144
+ setIdsB.forEach((ref) => ref.current = idA);
145
+ return idA;
146
+ }
147
+ return idB;
148
+ }
149
+
150
+ // ../../node_modules/.pnpm/@react-aria+utils@3.32.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@react-aria/utils/dist/chain.mjs
151
+ function $ff5963eb1fccf552$export$e08e3b67e392101e(...callbacks) {
152
+ return (...args) => {
153
+ for (let callback of callbacks) if (typeof callback === "function") callback(...args);
154
+ };
155
+ }
156
+ function $3ef42575df84b30b$export$9d1611c77c2fe928(...args) {
157
+ let result = {
158
+ ...args[0]
159
+ };
160
+ for (let i = 1; i < args.length; i++) {
161
+ let props = args[i];
162
+ for (let key in props) {
163
+ let a = result[key];
164
+ let b = props[key];
165
+ if (typeof a === "function" && typeof b === "function" && // This is a lot faster than a regex.
166
+ key[0] === "o" && key[1] === "n" && key.charCodeAt(2) >= /* 'A' */
167
+ 65 && key.charCodeAt(2) <= /* 'Z' */
168
+ 90) result[key] = ($ff5963eb1fccf552$export$e08e3b67e392101e)(a, b);
169
+ else if ((key === "className" || key === "UNSAFE_className") && typeof a === "string" && typeof b === "string") result[key] = ($7jXr9$clsx)(a, b);
170
+ else if (key === "id" && a && b) result.id = ($bdb11010cef70236$export$cd8c9cb68f842629)(a, b);
171
+ else result[key] = b !== void 0 ? b : a;
172
+ }
173
+ }
174
+ return result;
175
+ }
176
+
177
+ // ../../node_modules/.pnpm/@react-aria+utils@3.32.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@react-aria/utils/dist/filterDOMProps.mjs
178
+ var $65484d02dcb7eb3e$var$DOMPropNames = /* @__PURE__ */ new Set([
179
+ "id"
180
+ ]);
181
+ var $65484d02dcb7eb3e$var$labelablePropNames = /* @__PURE__ */ new Set([
182
+ "aria-label",
183
+ "aria-labelledby",
184
+ "aria-describedby",
185
+ "aria-details"
186
+ ]);
187
+ var $65484d02dcb7eb3e$var$linkPropNames = /* @__PURE__ */ new Set([
188
+ "href",
189
+ "hrefLang",
190
+ "target",
191
+ "rel",
192
+ "download",
193
+ "ping",
194
+ "referrerPolicy"
195
+ ]);
196
+ var $65484d02dcb7eb3e$var$globalAttrs = /* @__PURE__ */ new Set([
197
+ "dir",
198
+ "lang",
199
+ "hidden",
200
+ "inert",
201
+ "translate"
202
+ ]);
203
+ var $65484d02dcb7eb3e$var$globalEvents = /* @__PURE__ */ new Set([
204
+ "onClick",
205
+ "onAuxClick",
206
+ "onContextMenu",
207
+ "onDoubleClick",
208
+ "onMouseDown",
209
+ "onMouseEnter",
210
+ "onMouseLeave",
211
+ "onMouseMove",
212
+ "onMouseOut",
213
+ "onMouseOver",
214
+ "onMouseUp",
215
+ "onTouchCancel",
216
+ "onTouchEnd",
217
+ "onTouchMove",
218
+ "onTouchStart",
219
+ "onPointerDown",
220
+ "onPointerMove",
221
+ "onPointerUp",
222
+ "onPointerCancel",
223
+ "onPointerEnter",
224
+ "onPointerLeave",
225
+ "onPointerOver",
226
+ "onPointerOut",
227
+ "onGotPointerCapture",
228
+ "onLostPointerCapture",
229
+ "onScroll",
230
+ "onWheel",
231
+ "onAnimationStart",
232
+ "onAnimationEnd",
233
+ "onAnimationIteration",
234
+ "onTransitionCancel",
235
+ "onTransitionEnd",
236
+ "onTransitionRun",
237
+ "onTransitionStart"
238
+ ]);
239
+ var $65484d02dcb7eb3e$var$propRe = /^(data-.*)$/;
240
+ function $65484d02dcb7eb3e$export$457c3d6518dd4c6f(props, opts = {}) {
241
+ let { labelable, isLink, global, events = global, propNames } = opts;
242
+ let filteredProps = {};
243
+ for (const prop in props) if (Object.prototype.hasOwnProperty.call(props, prop) && ($65484d02dcb7eb3e$var$DOMPropNames.has(prop) || labelable && $65484d02dcb7eb3e$var$labelablePropNames.has(prop) || isLink && $65484d02dcb7eb3e$var$linkPropNames.has(prop) || global && $65484d02dcb7eb3e$var$globalAttrs.has(prop) || events && ($65484d02dcb7eb3e$var$globalEvents.has(prop) || prop.endsWith("Capture") && $65484d02dcb7eb3e$var$globalEvents.has(prop.slice(0, -7))) || (propNames === null || propNames === void 0 ? void 0 : propNames.has(prop)) || $65484d02dcb7eb3e$var$propRe.test(prop))) filteredProps[prop] = props[prop];
244
+ return filteredProps;
245
+ }
246
+ var $458b0a5536c1a7cf$var$_React_useInsertionEffect;
247
+ var $458b0a5536c1a7cf$var$useEarlyEffect = typeof document !== "undefined" ? ($458b0a5536c1a7cf$var$_React_useInsertionEffect = ($3whtM$react)["useInsertionEffect"]) !== null && $458b0a5536c1a7cf$var$_React_useInsertionEffect !== void 0 ? $458b0a5536c1a7cf$var$_React_useInsertionEffect : ($3whtM$react).useLayoutEffect : () => {
248
+ };
249
+ function $458b0a5536c1a7cf$export$40bfa8c7b0832715(value, defaultValue, onChange) {
250
+ let [stateValue, setStateValue] = (useState)(value || defaultValue);
251
+ let valueRef = (useRef)(stateValue);
252
+ let isControlledRef = (useRef)(value !== void 0);
253
+ let isControlled = value !== void 0;
254
+ (useEffect)(() => {
255
+ let wasControlled = isControlledRef.current;
256
+ if (wasControlled !== isControlled && process.env.NODE_ENV !== "production") console.warn(`WARN: A component changed from ${wasControlled ? "controlled" : "uncontrolled"} to ${isControlled ? "controlled" : "uncontrolled"}.`);
257
+ isControlledRef.current = isControlled;
258
+ }, [
259
+ isControlled
260
+ ]);
261
+ let currentValue = isControlled ? value : stateValue;
262
+ $458b0a5536c1a7cf$var$useEarlyEffect(() => {
263
+ valueRef.current = currentValue;
264
+ });
265
+ let [, forceUpdate] = (useReducer)(() => ({}), {});
266
+ let setValue = (useCallback)((value2, ...args) => {
267
+ let newValue = typeof value2 === "function" ? value2(valueRef.current) : value2;
268
+ if (!Object.is(valueRef.current, newValue)) {
269
+ valueRef.current = newValue;
270
+ setStateValue(newValue);
271
+ forceUpdate();
272
+ onChange === null || onChange === void 0 ? void 0 : onChange(newValue, ...args);
273
+ }
274
+ }, [
275
+ onChange
276
+ ]);
277
+ return [
278
+ currentValue,
279
+ setValue
280
+ ];
281
+ }
282
+ var ButtonHeadless = forwardRef(
283
+ ({ className, children, tabIndex = 0, onMouseDown, type, ...restProps }, forwardedRef) => {
284
+ const internalRef = useRef(null);
285
+ const ref = forwardedRef ?? internalRef;
286
+ const { buttonProps } = useButton(
287
+ {
288
+ ...restProps,
289
+ // Ensure element type is 'button' for proper semantics
290
+ elementType: "button"
291
+ },
292
+ ref
293
+ );
294
+ const {
295
+ isDisabled: _isDisabled,
296
+ onPress: _onPress,
297
+ onPressStart: _onPressStart,
298
+ onPressEnd: _onPressEnd,
299
+ onPressChange: _onPressChange,
300
+ onPressUp: _onPressUp,
301
+ ...htmlAttrs
302
+ } = restProps;
303
+ const mergedProps = $3ef42575df84b30b$export$9d1611c77c2fe928(
304
+ buttonProps,
305
+ {
306
+ tabIndex,
307
+ className,
308
+ onMouseDown
309
+ },
310
+ htmlAttrs
311
+ // Pass through only HTML attributes (title, data-*, etc.)
312
+ );
313
+ return (
314
+ // eslint-disable-next-line react/button-has-type -- type is dynamically passed from props
315
+ /* @__PURE__ */ jsx("button", { ...mergedProps, ref, type: type ?? "button", children })
316
+ );
317
+ }
318
+ );
319
+ ButtonHeadless.displayName = "ButtonHeadless";
320
+ var buttonVariants = cva(
321
+ [
322
+ // Base classes (always applied)
323
+ "relative inline-flex items-center justify-center cursor-pointer",
324
+ "overflow-hidden rounded-full font-medium",
325
+ "transition-all duration-200",
326
+ "tracking-[0.1px]",
327
+ // MD3 spec: +0.1px letter-spacing for label-large
328
+ "focus-visible:outline-primary focus-visible:outline-2 focus-visible:outline-offset-2",
329
+ // State layers (hover, focus, active) - MD3 spec: 8%/12%/12% opacity
330
+ "before:absolute before:inset-0 before:rounded-[inherit] before:transition-opacity before:duration-200",
331
+ "before:bg-current before:opacity-0",
332
+ "hover:before:opacity-8",
333
+ "focus-visible:before:opacity-12",
334
+ "active:before:opacity-12"
335
+ ],
336
+ {
337
+ variants: {
338
+ /**
339
+ * Button variant (MD3 specification)
340
+ */
341
+ variant: {
342
+ filled: "shadow-none hover:shadow-elevation-1",
343
+ // MD3: gains elevation on hover
344
+ outlined: "bg-transparent border border-outline",
345
+ tonal: "",
346
+ elevated: "shadow-elevation-1 hover:shadow-elevation-2",
347
+ // MD3: level 1 → level 2 on hover
348
+ text: "bg-transparent"
349
+ },
350
+ /**
351
+ * Color scheme (MD3 color roles)
352
+ */
353
+ color: {
354
+ primary: "",
355
+ secondary: "",
356
+ tertiary: "",
357
+ error: ""
358
+ },
359
+ /**
360
+ * Button size
361
+ */
362
+ size: {
363
+ small: "h-8 px-4 text-sm gap-2",
364
+ medium: "h-10 px-6 text-sm gap-2",
365
+ large: "h-12 px-8 text-base gap-3"
366
+ },
367
+ /**
368
+ * Full width variant
369
+ */
370
+ fullWidth: {
371
+ true: "w-full",
372
+ false: ""
373
+ },
374
+ /**
375
+ * Disabled state (MD3 spec: container 12% opacity, content 38% opacity)
376
+ */
377
+ disabled: {
378
+ true: [
379
+ "pointer-events-none cursor-not-allowed",
380
+ "bg-on-surface/12",
381
+ // MD3: disabled container uses on-surface at 12%
382
+ "text-on-surface/38",
383
+ // MD3: disabled text/icons use on-surface at 38%
384
+ "border-on-surface/12",
385
+ // For outlined variant
386
+ "shadow-none"
387
+ // Remove elevation when disabled
388
+ ],
389
+ false: ""
390
+ },
391
+ /**
392
+ * Loading state
393
+ */
394
+ loading: {
395
+ true: "cursor-wait",
396
+ false: ""
397
+ }
398
+ },
399
+ /**
400
+ * Compound variants - combinations of variant + color
401
+ */
402
+ compoundVariants: [
403
+ // ====================
404
+ // FILLED VARIANTS
405
+ // ====================
406
+ {
407
+ variant: "filled",
408
+ color: "primary",
409
+ className: "bg-primary text-on-primary"
410
+ },
411
+ {
412
+ variant: "filled",
413
+ color: "secondary",
414
+ className: "bg-secondary text-on-secondary"
415
+ },
416
+ {
417
+ variant: "filled",
418
+ color: "tertiary",
419
+ className: "bg-tertiary text-on-tertiary"
420
+ },
421
+ {
422
+ variant: "filled",
423
+ color: "error",
424
+ className: "bg-error text-on-error"
425
+ },
426
+ // ====================
427
+ // OUTLINED VARIANTS
428
+ // ====================
429
+ {
430
+ variant: "outlined",
431
+ color: "primary",
432
+ className: "text-primary"
433
+ },
434
+ {
435
+ variant: "outlined",
436
+ color: "secondary",
437
+ className: "text-secondary"
438
+ },
439
+ {
440
+ variant: "outlined",
441
+ color: "tertiary",
442
+ className: "text-tertiary"
443
+ },
444
+ {
445
+ variant: "outlined",
446
+ color: "error",
447
+ className: "text-error"
448
+ },
449
+ // ====================
450
+ // TONAL VARIANTS
451
+ // ====================
452
+ {
453
+ variant: "tonal",
454
+ color: "primary",
455
+ className: "bg-secondary-container text-on-secondary-container"
456
+ },
457
+ {
458
+ variant: "tonal",
459
+ color: "secondary",
460
+ className: "bg-secondary-container text-on-secondary-container"
461
+ },
462
+ {
463
+ variant: "tonal",
464
+ color: "tertiary",
465
+ className: "bg-tertiary-container text-on-tertiary-container"
466
+ },
467
+ {
468
+ variant: "tonal",
469
+ color: "error",
470
+ className: "bg-error-container text-on-error-container"
471
+ },
472
+ // ====================
473
+ // ELEVATED VARIANTS
474
+ // ====================
475
+ {
476
+ variant: "elevated",
477
+ color: "primary",
478
+ className: "bg-surface-container-low text-primary"
479
+ },
480
+ {
481
+ variant: "elevated",
482
+ color: "secondary",
483
+ className: "bg-surface-container-low text-secondary"
484
+ },
485
+ {
486
+ variant: "elevated",
487
+ color: "tertiary",
488
+ className: "bg-surface-container-low text-tertiary"
489
+ },
490
+ {
491
+ variant: "elevated",
492
+ color: "error",
493
+ className: "bg-surface-container-low text-error"
494
+ },
495
+ // ====================
496
+ // TEXT VARIANTS
497
+ // ====================
498
+ {
499
+ variant: "text",
500
+ color: "primary",
501
+ className: "text-primary"
502
+ },
503
+ {
504
+ variant: "text",
505
+ color: "secondary",
506
+ className: "text-secondary"
507
+ },
508
+ {
509
+ variant: "text",
510
+ color: "tertiary",
511
+ className: "text-tertiary"
512
+ },
513
+ {
514
+ variant: "text",
515
+ color: "error",
516
+ className: "text-error"
517
+ }
518
+ ],
519
+ /**
520
+ * Default variants
521
+ */
522
+ defaultVariants: {
523
+ variant: "filled",
524
+ color: "primary",
525
+ size: "medium",
526
+ fullWidth: false,
527
+ disabled: false,
528
+ loading: false
529
+ }
530
+ }
531
+ );
532
+ function useRipple(options = {}) {
533
+ const { disabled = false, color = "currentColor", duration = 450 } = options;
534
+ const [ripples, setRipples] = useState([]);
535
+ const rippleKeyCounter = useRef(0);
536
+ const onMouseDown = useCallback(
537
+ (event) => {
538
+ if (disabled) return;
539
+ const element = event.currentTarget;
540
+ const rect = element.getBoundingClientRect();
541
+ const x = event.clientX - rect.left;
542
+ const y = event.clientY - rect.top;
543
+ const sizeX = Math.max(x, rect.width - x);
544
+ const sizeY = Math.max(y, rect.height - y);
545
+ const size = Math.sqrt(sizeX ** 2 + sizeY ** 2) * 2;
546
+ const key = rippleKeyCounter.current++;
547
+ setRipples((prev) => [...prev, { key, x, y, size }]);
548
+ setTimeout(() => {
549
+ setRipples((prev) => prev.filter((r) => r.key !== key));
550
+ }, duration);
551
+ },
552
+ [disabled, duration]
553
+ );
554
+ const rippleElements = disabled ? null : /* @__PURE__ */ jsx(
555
+ "span",
556
+ {
557
+ "data-ripple-container": true,
558
+ className: "pointer-events-none absolute inset-0 overflow-hidden rounded-[inherit]",
559
+ children: ripples.map((ripple) => /* @__PURE__ */ jsx(
560
+ "span",
561
+ {
562
+ className: "animate-ripple absolute rounded-full opacity-12",
563
+ style: {
564
+ left: ripple.x,
565
+ top: ripple.y,
566
+ width: ripple.size,
567
+ height: ripple.size,
568
+ transform: "translate(-50%, -50%) scale(0)",
569
+ backgroundColor: color,
570
+ animationDuration: `${duration}ms`
571
+ }
572
+ },
573
+ ripple.key
574
+ ))
575
+ }
576
+ );
577
+ return {
578
+ onMouseDown,
579
+ ripples: rippleElements
580
+ };
581
+ }
582
+ var Spinner = () => /* @__PURE__ */ jsxs(
583
+ "svg",
584
+ {
585
+ role: "progressbar",
586
+ "aria-label": "Loading",
587
+ className: "h-4 w-4 animate-spin",
588
+ xmlns: "http://www.w3.org/2000/svg",
589
+ fill: "none",
590
+ viewBox: "0 0 24 24",
591
+ children: [
592
+ /* @__PURE__ */ jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
593
+ /* @__PURE__ */ jsx(
594
+ "path",
595
+ {
596
+ className: "opacity-75",
597
+ fill: "currentColor",
598
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
599
+ }
600
+ )
601
+ ]
602
+ }
603
+ );
604
+ var Button = forwardRef(
605
+ ({
606
+ // Variant props (CVA)
607
+ variant = "filled",
608
+ color = "primary",
609
+ size = "medium",
610
+ fullWidth = false,
611
+ // Content props
612
+ icon,
613
+ trailingIcon,
614
+ children,
615
+ // State props
616
+ loading = false,
617
+ disableRipple = false,
618
+ isDisabled = false,
619
+ // Styling
620
+ className,
621
+ // Other props
622
+ tabIndex = 0,
623
+ type = "button",
624
+ onPress,
625
+ ...props
626
+ }, ref) => {
627
+ if (process.env.NODE_ENV === "development") {
628
+ if (!children) {
629
+ console.warn(
630
+ "[Button] Button should have text content. Use IconButton for icon-only buttons."
631
+ );
632
+ }
633
+ if (icon && trailingIcon) {
634
+ console.warn("[Button] Button should have either icon or trailingIcon, not both.");
635
+ }
636
+ }
637
+ const isButtonDisabled = isDisabled || loading;
638
+ const { onMouseDown: handleRipple, ripples } = useRipple({
639
+ disabled: isButtonDisabled || disableRipple
640
+ });
641
+ return /* @__PURE__ */ jsxs(
642
+ ButtonHeadless,
643
+ {
644
+ ...props,
645
+ ref,
646
+ type,
647
+ isDisabled: isButtonDisabled,
648
+ ...onPress && { onPress },
649
+ tabIndex,
650
+ onMouseDown: handleRipple,
651
+ className: cn(
652
+ // Apply CVA variants
653
+ buttonVariants({
654
+ variant,
655
+ color,
656
+ size,
657
+ fullWidth,
658
+ disabled: isButtonDisabled,
659
+ loading
660
+ }),
661
+ // User custom classes
662
+ className
663
+ ),
664
+ children: [
665
+ ripples,
666
+ icon && /* @__PURE__ */ jsx("span", { className: cn("relative z-10 inline-flex shrink-0", loading && "invisible"), children: icon }),
667
+ loading && /* @__PURE__ */ jsx("span", { className: "relative z-10", children: /* @__PURE__ */ jsx(Spinner, {}) }),
668
+ /* @__PURE__ */ jsx("span", { className: "relative z-10 inline-flex items-center", children }),
669
+ trailingIcon && /* @__PURE__ */ jsx("span", { className: cn("relative z-10 inline-flex shrink-0", loading && "invisible"), children: trailingIcon })
670
+ ]
671
+ }
672
+ );
673
+ }
674
+ );
675
+ Button.displayName = "Button";
676
+ var IconButtonHeadless = forwardRef(
677
+ ({
678
+ className,
679
+ children,
680
+ tabIndex = 0,
681
+ onMouseDown,
682
+ type,
683
+ selected,
684
+ "aria-label": ariaLabel,
685
+ title,
686
+ ...props
687
+ }, forwardedRef) => {
688
+ const internalRef = useRef(null);
689
+ const ref = forwardedRef ?? internalRef;
690
+ const { buttonProps } = useButton(
691
+ {
692
+ ...props,
693
+ // Ensure element type is 'button' for proper semantics
694
+ elementType: "button",
695
+ // Pass aria-label
696
+ "aria-label": ariaLabel
697
+ },
698
+ ref
699
+ );
700
+ const domProps = $65484d02dcb7eb3e$export$457c3d6518dd4c6f(props);
701
+ const mergedProps = $3ef42575df84b30b$export$9d1611c77c2fe928(
702
+ buttonProps,
703
+ domProps,
704
+ {
705
+ tabIndex,
706
+ className,
707
+ onMouseDown,
708
+ type: type ?? "button",
709
+ // Add aria-pressed for toggle buttons (only if selected is defined)
710
+ ...selected !== void 0 && { "aria-pressed": selected },
711
+ // Add title if provided
712
+ ...title && { title }
713
+ }
714
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
715
+ );
716
+ return (
717
+ // eslint-disable-next-line react/button-has-type
718
+ /* @__PURE__ */ jsx("button", { ...mergedProps, ref, type: type ?? "button", children })
719
+ );
720
+ }
721
+ );
722
+ IconButtonHeadless.displayName = "IconButtonHeadless";
723
+ var iconButtonVariants = cva(
724
+ [
725
+ // Base classes (always applied)
726
+ "relative inline-flex items-center justify-center",
727
+ "overflow-hidden rounded-full",
728
+ // Circular shape
729
+ "transition-all duration-200",
730
+ "focus-visible:outline-primary focus-visible:outline-2 focus-visible:outline-offset-2",
731
+ // State layers (hover, focus, active)
732
+ "before:absolute before:inset-0 before:rounded-[inherit] before:transition-opacity before:duration-200",
733
+ "before:bg-current before:opacity-0",
734
+ "hover:before:opacity-8",
735
+ "focus-visible:before:opacity-12",
736
+ "active:before:opacity-12"
737
+ ],
738
+ {
739
+ variants: {
740
+ /**
741
+ * Button variant (MD3 specification)
742
+ */
743
+ variant: {
744
+ standard: "bg-transparent",
745
+ // No background
746
+ filled: "shadow-none",
747
+ // Solid background
748
+ tonal: "",
749
+ // Container background
750
+ outlined: "bg-transparent border border-outline"
751
+ },
752
+ /**
753
+ * Color scheme (MD3 color roles)
754
+ */
755
+ color: {
756
+ primary: "",
757
+ secondary: "",
758
+ tertiary: "",
759
+ error: ""
760
+ },
761
+ /**
762
+ * Button size (square dimensions)
763
+ */
764
+ size: {
765
+ small: "h-8 w-8",
766
+ // 32×32px
767
+ medium: "h-10 w-10",
768
+ // 40×40px (default)
769
+ large: "h-12 w-12"
770
+ // 48×48px
771
+ },
772
+ /**
773
+ * Selected state (for toggle buttons)
774
+ */
775
+ selected: {
776
+ true: "",
777
+ false: ""
778
+ },
779
+ /**
780
+ * Disabled state
781
+ */
782
+ isDisabled: {
783
+ true: "pointer-events-none cursor-not-allowed opacity-38",
784
+ false: ""
785
+ }
786
+ },
787
+ /**
788
+ * Compound variants - combinations of variant + color + selected
789
+ */
790
+ compoundVariants: [
791
+ // ====================
792
+ // STANDARD VARIANTS
793
+ // ====================
794
+ {
795
+ variant: "standard",
796
+ selected: false,
797
+ className: "text-on-surface-variant"
798
+ },
799
+ {
800
+ variant: "standard",
801
+ selected: true,
802
+ className: "text-primary"
803
+ },
804
+ // ====================
805
+ // FILLED VARIANTS (UNSELECTED)
806
+ // ====================
807
+ {
808
+ variant: "filled",
809
+ color: "primary",
810
+ selected: false,
811
+ className: "bg-primary text-on-primary"
812
+ },
813
+ {
814
+ variant: "filled",
815
+ color: "secondary",
816
+ selected: false,
817
+ className: "bg-secondary text-on-secondary"
818
+ },
819
+ {
820
+ variant: "filled",
821
+ color: "tertiary",
822
+ selected: false,
823
+ className: "bg-tertiary text-on-tertiary"
824
+ },
825
+ {
826
+ variant: "filled",
827
+ color: "error",
828
+ selected: false,
829
+ className: "bg-error text-on-error"
830
+ },
831
+ // ====================
832
+ // FILLED VARIANTS (SELECTED - uses container colors)
833
+ // ====================
834
+ {
835
+ variant: "filled",
836
+ color: "primary",
837
+ selected: true,
838
+ className: "bg-primary-container text-on-primary-container"
839
+ },
840
+ {
841
+ variant: "filled",
842
+ color: "secondary",
843
+ selected: true,
844
+ className: "bg-secondary-container text-on-secondary-container"
845
+ },
846
+ {
847
+ variant: "filled",
848
+ color: "tertiary",
849
+ selected: true,
850
+ className: "bg-tertiary-container text-on-tertiary-container"
851
+ },
852
+ {
853
+ variant: "filled",
854
+ color: "error",
855
+ selected: true,
856
+ className: "bg-error-container text-on-error-container"
857
+ },
858
+ // ====================
859
+ // TONAL VARIANTS (UNSELECTED)
860
+ // ====================
861
+ {
862
+ variant: "tonal",
863
+ color: "primary",
864
+ selected: false,
865
+ className: "bg-secondary-container text-on-secondary-container"
866
+ },
867
+ {
868
+ variant: "tonal",
869
+ color: "secondary",
870
+ selected: false,
871
+ className: "bg-secondary-container text-on-secondary-container"
872
+ },
873
+ {
874
+ variant: "tonal",
875
+ color: "tertiary",
876
+ selected: false,
877
+ className: "bg-tertiary-container text-on-tertiary-container"
878
+ },
879
+ {
880
+ variant: "tonal",
881
+ color: "error",
882
+ selected: false,
883
+ className: "bg-error-container text-on-error-container"
884
+ },
885
+ // ====================
886
+ // TONAL VARIANTS (SELECTED - uses tertiary container)
887
+ // ====================
888
+ {
889
+ variant: "tonal",
890
+ selected: true,
891
+ className: "bg-tertiary-container text-on-tertiary-container"
892
+ },
893
+ // ====================
894
+ // OUTLINED VARIANTS (UNSELECTED)
895
+ // ====================
896
+ {
897
+ variant: "outlined",
898
+ selected: false,
899
+ className: "text-on-surface-variant"
900
+ },
901
+ // ====================
902
+ // OUTLINED VARIANTS (SELECTED - uses inverse colors)
903
+ // ====================
904
+ {
905
+ variant: "outlined",
906
+ selected: true,
907
+ className: "bg-inverse-surface text-inverse-on-surface border-transparent"
908
+ }
909
+ ],
910
+ /**
911
+ * Default variants
912
+ */
913
+ defaultVariants: {
914
+ variant: "standard",
915
+ color: "primary",
916
+ size: "medium",
917
+ selected: false,
918
+ isDisabled: false
919
+ }
920
+ }
921
+ );
922
+ var IconButton = forwardRef(
923
+ ({
924
+ // Variant props (CVA)
925
+ variant = "standard",
926
+ color = "primary",
927
+ size = "medium",
928
+ // IconButton specific props
929
+ children,
930
+ selected,
931
+ disableRipple = false,
932
+ className,
933
+ // React Aria props
934
+ isDisabled: propIsDisabled = false,
935
+ onPress,
936
+ onMouseDown,
937
+ "aria-label": ariaLabel,
938
+ title,
939
+ ...props
940
+ }, ref) => {
941
+ if (process.env.NODE_ENV === "development") {
942
+ if (!ariaLabel) {
943
+ console.error(
944
+ "[IconButton] aria-label is required for IconButton. Icon-only buttons need accessible labels for screen readers."
945
+ );
946
+ }
947
+ if (!children) {
948
+ console.warn("[IconButton] IconButton should have an icon as children.");
949
+ }
950
+ }
951
+ const isDisabled = propIsDisabled;
952
+ const { onMouseDown: handleRipple, ripples } = useRipple({
953
+ disabled: isDisabled || disableRipple
954
+ });
955
+ const mergedOnMouseDown = (e) => {
956
+ onMouseDown?.(e);
957
+ handleRipple(e);
958
+ };
959
+ const mergedPropsValue = $3ef42575df84b30b$export$9d1611c77c2fe928(props, {
960
+ ...onPress && { onPress },
961
+ onMouseDown: mergedOnMouseDown,
962
+ isDisabled
963
+ });
964
+ return /* @__PURE__ */ jsxs(
965
+ IconButtonHeadless,
966
+ {
967
+ ref,
968
+ className: cn(
969
+ // Base classes
970
+ "relative inline-flex items-center justify-center",
971
+ "overflow-hidden rounded-full",
972
+ // Circular shape
973
+ "transition-all duration-200",
974
+ "focus-visible:outline-primary focus-visible:outline-2 focus-visible:outline-offset-2",
975
+ // State layers (hover, focus, active)
976
+ "before:absolute before:inset-0 before:rounded-[inherit] before:transition-opacity before:duration-200",
977
+ "before:bg-current before:opacity-0",
978
+ "hover:before:opacity-8",
979
+ "focus-visible:before:opacity-12",
980
+ "active:before:opacity-12",
981
+ // CVA variants
982
+ iconButtonVariants({ variant, color, size, selected: selected ?? false, isDisabled }),
983
+ // User custom classes
984
+ className
985
+ ),
986
+ "aria-label": ariaLabel,
987
+ ...selected !== void 0 && { selected },
988
+ ...title && { title },
989
+ ...mergedPropsValue,
990
+ children: [
991
+ ripples,
992
+ /* @__PURE__ */ jsx("span", { className: "relative z-10 inline-flex shrink-0", children })
993
+ ]
994
+ }
995
+ );
996
+ }
997
+ );
998
+ IconButton.displayName = "IconButton";
999
+ var FABHeadless = forwardRef(
1000
+ ({
1001
+ className,
1002
+ children,
1003
+ tabIndex = 0,
1004
+ onMouseDown,
1005
+ type,
1006
+ "aria-label": ariaLabel,
1007
+ title,
1008
+ ...props
1009
+ }, forwardedRef) => {
1010
+ const internalRef = useRef(null);
1011
+ const ref = forwardedRef ?? internalRef;
1012
+ const { buttonProps } = useButton(
1013
+ {
1014
+ ...props,
1015
+ elementType: "button"
1016
+ },
1017
+ ref
1018
+ );
1019
+ const domProps = $65484d02dcb7eb3e$export$457c3d6518dd4c6f(props);
1020
+ const mergedProps = $3ef42575df84b30b$export$9d1611c77c2fe928(buttonProps, domProps, {
1021
+ tabIndex,
1022
+ className,
1023
+ onMouseDown,
1024
+ type: type ?? "button",
1025
+ "aria-label": ariaLabel,
1026
+ // Add aria-label
1027
+ // Add title if provided
1028
+ ...title && { title }
1029
+ });
1030
+ return (
1031
+ // eslint-disable-next-line react/button-has-type
1032
+ /* @__PURE__ */ jsx("button", { ...mergedProps, ref, children })
1033
+ );
1034
+ }
1035
+ );
1036
+ FABHeadless.displayName = "FABHeadless";
1037
+ var fabVariants = cva(
1038
+ [
1039
+ // Base classes (always applied)
1040
+ "relative inline-flex items-center justify-center",
1041
+ "overflow-hidden",
1042
+ "transition-all duration-200",
1043
+ "focus-visible:outline-primary focus-visible:outline-2 focus-visible:outline-offset-2",
1044
+ "shrink-0",
1045
+ // Prevent shrinking in flex containers
1046
+ // State layers (hover, focus, active)
1047
+ "before:absolute before:inset-0 before:rounded-[inherit] before:transition-opacity before:duration-200",
1048
+ "before:bg-current before:opacity-0",
1049
+ "hover:before:opacity-8",
1050
+ "focus-visible:before:opacity-12",
1051
+ "active:before:opacity-12",
1052
+ // Elevation (floating appearance)
1053
+ "shadow-elevation-3",
1054
+ // Default elevation
1055
+ "hover:shadow-elevation-4"
1056
+ // Hover elevation
1057
+ ],
1058
+ {
1059
+ variants: {
1060
+ /**
1061
+ * FAB size (controls dimensions and icon size)
1062
+ */
1063
+ size: {
1064
+ small: [
1065
+ "h-10 w-10",
1066
+ // 40×40px
1067
+ "p-2",
1068
+ // 8px padding for 24px icon
1069
+ "rounded-xl",
1070
+ // 12px corner radius (not fully rounded!)
1071
+ "m-1"
1072
+ // 4px margin for 48×48px touch target
1073
+ ],
1074
+ medium: [
1075
+ "h-14 w-14",
1076
+ // 56×56px
1077
+ "p-4",
1078
+ // 16px padding for 24px icon
1079
+ "rounded-2xl"
1080
+ // 16px corner radius
1081
+ ],
1082
+ large: [
1083
+ "h-24 w-24",
1084
+ // 96×96px
1085
+ "p-[30px]",
1086
+ // 30px padding for 36px icon
1087
+ "rounded-[28px]"
1088
+ // 28px corner radius (custom value)
1089
+ ],
1090
+ extended: [
1091
+ "h-14",
1092
+ // 56px height (same as medium)
1093
+ "rounded-2xl",
1094
+ // 16px corner radius
1095
+ "pl-4 pr-5",
1096
+ // Asymmetric padding: 16px leading, 20px trailing
1097
+ "gap-2"
1098
+ // 8px gap between icon and text
1099
+ ]
1100
+ },
1101
+ /**
1102
+ * Color scheme (MD3 color roles)
1103
+ */
1104
+ color: {
1105
+ primary: "",
1106
+ secondary: "",
1107
+ tertiary: "",
1108
+ surface: ""
1109
+ },
1110
+ /**
1111
+ * Disabled state
1112
+ */
1113
+ isDisabled: {
1114
+ true: "pointer-events-none cursor-not-allowed !bg-on-surface/12 !text-on-surface/38 !shadow-none",
1115
+ false: ""
1116
+ }
1117
+ },
1118
+ /**
1119
+ * Compound variants - combinations of size + color
1120
+ */
1121
+ compoundVariants: [
1122
+ // ====================
1123
+ // PRIMARY COLOR
1124
+ // ====================
1125
+ {
1126
+ color: "primary",
1127
+ size: "small",
1128
+ className: "bg-primary-container text-on-primary-container"
1129
+ },
1130
+ {
1131
+ color: "primary",
1132
+ size: "medium",
1133
+ className: "bg-primary-container text-on-primary-container"
1134
+ },
1135
+ {
1136
+ color: "primary",
1137
+ size: "large",
1138
+ className: "bg-primary-container text-on-primary-container"
1139
+ },
1140
+ {
1141
+ color: "primary",
1142
+ size: "extended",
1143
+ className: "bg-primary-container text-on-primary-container"
1144
+ },
1145
+ // ====================
1146
+ // SECONDARY COLOR
1147
+ // ====================
1148
+ {
1149
+ color: "secondary",
1150
+ size: "small",
1151
+ className: "bg-secondary-container text-on-secondary-container"
1152
+ },
1153
+ {
1154
+ color: "secondary",
1155
+ size: "medium",
1156
+ className: "bg-secondary-container text-on-secondary-container"
1157
+ },
1158
+ {
1159
+ color: "secondary",
1160
+ size: "large",
1161
+ className: "bg-secondary-container text-on-secondary-container"
1162
+ },
1163
+ {
1164
+ color: "secondary",
1165
+ size: "extended",
1166
+ className: "bg-secondary-container text-on-secondary-container"
1167
+ },
1168
+ // ====================
1169
+ // TERTIARY COLOR
1170
+ // ====================
1171
+ {
1172
+ color: "tertiary",
1173
+ size: "small",
1174
+ className: "bg-tertiary-container text-on-tertiary-container"
1175
+ },
1176
+ {
1177
+ color: "tertiary",
1178
+ size: "medium",
1179
+ className: "bg-tertiary-container text-on-tertiary-container"
1180
+ },
1181
+ {
1182
+ color: "tertiary",
1183
+ size: "large",
1184
+ className: "bg-tertiary-container text-on-tertiary-container"
1185
+ },
1186
+ {
1187
+ color: "tertiary",
1188
+ size: "extended",
1189
+ className: "bg-tertiary-container text-on-tertiary-container"
1190
+ },
1191
+ // ====================
1192
+ // SURFACE COLOR
1193
+ // ====================
1194
+ {
1195
+ color: "surface",
1196
+ size: "small",
1197
+ className: "bg-surface text-primary"
1198
+ },
1199
+ {
1200
+ color: "surface",
1201
+ size: "medium",
1202
+ className: "bg-surface text-primary"
1203
+ },
1204
+ {
1205
+ color: "surface",
1206
+ size: "large",
1207
+ className: "bg-surface text-primary"
1208
+ },
1209
+ {
1210
+ color: "surface",
1211
+ size: "extended",
1212
+ className: "bg-surface text-primary"
1213
+ }
1214
+ ],
1215
+ /**
1216
+ * Default variants
1217
+ */
1218
+ defaultVariants: {
1219
+ size: "medium",
1220
+ color: "primary",
1221
+ isDisabled: false
1222
+ }
1223
+ }
1224
+ );
1225
+ var Spinner2 = () => /* @__PURE__ */ jsxs(
1226
+ "svg",
1227
+ {
1228
+ role: "progressbar",
1229
+ "aria-label": "Loading",
1230
+ className: "h-6 w-6 animate-spin",
1231
+ xmlns: "http://www.w3.org/2000/svg",
1232
+ fill: "none",
1233
+ viewBox: "0 0 24 24",
1234
+ children: [
1235
+ /* @__PURE__ */ jsx("circle", { className: "opacity-25", cx: "12", cy: "12", r: "10", stroke: "currentColor", strokeWidth: "4" }),
1236
+ /* @__PURE__ */ jsx(
1237
+ "path",
1238
+ {
1239
+ className: "opacity-75",
1240
+ fill: "currentColor",
1241
+ d: "M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
1242
+ }
1243
+ )
1244
+ ]
1245
+ }
1246
+ );
1247
+ var FAB = forwardRef(
1248
+ ({
1249
+ // Variant props (CVA)
1250
+ size = "medium",
1251
+ color = "primary",
1252
+ // FAB specific props
1253
+ icon,
1254
+ children,
1255
+ "aria-label": ariaLabel,
1256
+ loading = false,
1257
+ disableRipple = false,
1258
+ className,
1259
+ // React Aria props
1260
+ isDisabled: propIsDisabled = false,
1261
+ onPress,
1262
+ onMouseDown,
1263
+ title,
1264
+ ...props
1265
+ }, ref) => {
1266
+ if (process.env.NODE_ENV === "development") {
1267
+ if (!icon) {
1268
+ console.warn("[FAB] FAB must have an icon. Please provide the icon prop.");
1269
+ }
1270
+ if (size === "extended" && !children) {
1271
+ console.warn("[FAB] Extended FAB requires text label as children.");
1272
+ }
1273
+ if (size !== "extended" && children) {
1274
+ console.warn(
1275
+ "[FAB] Children (text) is only used for extended FAB. For icon-only FAB, use icon prop only."
1276
+ );
1277
+ }
1278
+ }
1279
+ const isDisabled = propIsDisabled || loading;
1280
+ const { onMouseDown: handleRipple, ripples } = useRipple({
1281
+ disabled: isDisabled || disableRipple
1282
+ });
1283
+ const mergedOnMouseDown = (e) => {
1284
+ onMouseDown?.(e);
1285
+ handleRipple(e);
1286
+ };
1287
+ const mergedPropsValue = $3ef42575df84b30b$export$9d1611c77c2fe928(props, {
1288
+ ...onPress && { onPress },
1289
+ onMouseDown: mergedOnMouseDown,
1290
+ isDisabled
1291
+ });
1292
+ return /* @__PURE__ */ jsxs(
1293
+ FABHeadless,
1294
+ {
1295
+ ref,
1296
+ className: cn(
1297
+ // Base classes
1298
+ "relative inline-flex items-center justify-center",
1299
+ "overflow-hidden transition-all duration-200",
1300
+ "focus-visible:outline-primary focus-visible:outline-2 focus-visible:outline-offset-2",
1301
+ "shrink-0",
1302
+ // State layers (hover, focus, active)
1303
+ "before:absolute before:inset-0 before:rounded-[inherit] before:transition-opacity before:duration-200",
1304
+ "before:bg-current before:opacity-0",
1305
+ "hover:before:opacity-8",
1306
+ "focus-visible:before:opacity-12",
1307
+ "active:before:opacity-12",
1308
+ // Elevation
1309
+ "shadow-elevation-3 hover:shadow-elevation-4",
1310
+ // CVA variants
1311
+ fabVariants({ size, color, isDisabled }),
1312
+ // User custom classes
1313
+ className
1314
+ ),
1315
+ "aria-label": ariaLabel,
1316
+ ...title && { title },
1317
+ ...mergedPropsValue,
1318
+ children: [
1319
+ ripples,
1320
+ icon && /* @__PURE__ */ jsx("span", { className: cn("relative z-10 inline-flex shrink-0", loading && "invisible"), children: icon }),
1321
+ loading && /* @__PURE__ */ jsx("span", { className: "relative z-10", children: /* @__PURE__ */ jsx(Spinner2, {}) }),
1322
+ size === "extended" && children && /* @__PURE__ */ jsx("span", { className: "relative z-10 inline-flex items-center text-sm font-medium tracking-[0.1px]", children })
1323
+ ]
1324
+ }
1325
+ );
1326
+ }
1327
+ );
1328
+ FAB.displayName = "FAB";
1329
+ var textFieldContainerVariants = cva(
1330
+ [
1331
+ // Base container styles
1332
+ "relative inline-flex flex-col"
1333
+ ],
1334
+ {
1335
+ variants: {
1336
+ fullWidth: {
1337
+ true: "w-full",
1338
+ false: "w-auto"
1339
+ }
1340
+ },
1341
+ defaultVariants: {
1342
+ fullWidth: false
1343
+ }
1344
+ }
1345
+ );
1346
+ var textFieldWrapperVariants = cva(
1347
+ [
1348
+ // Base wrapper styles
1349
+ "relative inline-flex items-center w-full",
1350
+ "transition-all duration-200",
1351
+ "rounded-t"
1352
+ ],
1353
+ {
1354
+ variants: {
1355
+ variant: {
1356
+ filled: ["bg-surface-container-highest", "border-b-2 border-on-surface-variant"],
1357
+ outlined: ["bg-transparent", "border border-outline", "rounded-b"]
1358
+ },
1359
+ size: {
1360
+ small: "min-h-10",
1361
+ medium: "min-h-12",
1362
+ large: "min-h-14"
1363
+ },
1364
+ disabled: {
1365
+ true: ["cursor-not-allowed", "opacity-38"],
1366
+ false: ""
1367
+ },
1368
+ error: {
1369
+ true: "",
1370
+ false: ""
1371
+ },
1372
+ focused: {
1373
+ true: "",
1374
+ false: ""
1375
+ }
1376
+ },
1377
+ compoundVariants: [
1378
+ // FILLED VARIANT - Focused state
1379
+ {
1380
+ variant: "filled",
1381
+ focused: true,
1382
+ error: false,
1383
+ className: "border-primary"
1384
+ },
1385
+ // FILLED VARIANT - Error state
1386
+ {
1387
+ variant: "filled",
1388
+ error: true,
1389
+ className: "border-error"
1390
+ },
1391
+ // FILLED VARIANT - Hover state (handled via group-hover in parent)
1392
+ {
1393
+ variant: "filled",
1394
+ disabled: false,
1395
+ className: "hover:bg-on-surface/[0.08]"
1396
+ },
1397
+ // OUTLINED VARIANT - Focused state
1398
+ {
1399
+ variant: "outlined",
1400
+ focused: true,
1401
+ error: false,
1402
+ className: "border-2 border-primary"
1403
+ },
1404
+ // OUTLINED VARIANT - Error state
1405
+ {
1406
+ variant: "outlined",
1407
+ error: true,
1408
+ className: "border-2 border-error"
1409
+ },
1410
+ // OUTLINED VARIANT - Hover state
1411
+ {
1412
+ variant: "outlined",
1413
+ disabled: false,
1414
+ className: "hover:border-on-surface"
1415
+ }
1416
+ ],
1417
+ defaultVariants: {
1418
+ variant: "filled",
1419
+ size: "medium",
1420
+ disabled: false,
1421
+ error: false,
1422
+ focused: false
1423
+ }
1424
+ }
1425
+ );
1426
+ var textFieldInputVariants = cva(
1427
+ [
1428
+ // Base input styles
1429
+ "w-full bg-transparent outline-none",
1430
+ "text-on-surface text-base",
1431
+ "placeholder:text-on-surface-variant placeholder:opacity-60",
1432
+ "transition-colors duration-200"
1433
+ ],
1434
+ {
1435
+ variants: {
1436
+ variant: {
1437
+ filled: "px-4",
1438
+ outlined: "px-4"
1439
+ },
1440
+ size: {
1441
+ small: "h-10 py-2 text-sm",
1442
+ medium: "h-12 py-3 text-base",
1443
+ large: "h-14 py-4 text-lg"
1444
+ },
1445
+ disabled: {
1446
+ true: "cursor-not-allowed",
1447
+ false: ""
1448
+ },
1449
+ hasLeadingIcon: {
1450
+ true: "pl-12",
1451
+ false: ""
1452
+ },
1453
+ hasTrailingIcon: {
1454
+ true: "pr-12",
1455
+ false: ""
1456
+ },
1457
+ multiline: {
1458
+ true: "resize-y",
1459
+ false: ""
1460
+ }
1461
+ },
1462
+ defaultVariants: {
1463
+ variant: "filled",
1464
+ size: "medium",
1465
+ disabled: false,
1466
+ hasLeadingIcon: false,
1467
+ hasTrailingIcon: false,
1468
+ multiline: false
1469
+ }
1470
+ }
1471
+ );
1472
+ var textFieldLabelVariants = cva(
1473
+ [
1474
+ // Base label styles
1475
+ "absolute left-4 transition-all duration-200 pointer-events-none",
1476
+ "text-on-surface-variant origin-top-left"
1477
+ ],
1478
+ {
1479
+ variants: {
1480
+ variant: {
1481
+ filled: "top-4",
1482
+ outlined: "top-3 bg-surface px-1"
1483
+ },
1484
+ size: {
1485
+ small: "text-sm",
1486
+ medium: "text-base",
1487
+ large: "text-lg"
1488
+ },
1489
+ floating: {
1490
+ true: "-translate-y-6 scale-75",
1491
+ false: "scale-100"
1492
+ },
1493
+ focused: {
1494
+ true: "text-primary",
1495
+ false: ""
1496
+ },
1497
+ error: {
1498
+ true: "text-error",
1499
+ false: ""
1500
+ },
1501
+ disabled: {
1502
+ true: "text-on-surface/38",
1503
+ false: ""
1504
+ },
1505
+ hasLeadingIcon: {
1506
+ true: "left-12",
1507
+ false: ""
1508
+ }
1509
+ },
1510
+ compoundVariants: [
1511
+ // Outlined variant floating label positioning
1512
+ {
1513
+ variant: "outlined",
1514
+ floating: true,
1515
+ className: "-top-2"
1516
+ }
1517
+ ],
1518
+ defaultVariants: {
1519
+ variant: "filled",
1520
+ size: "medium",
1521
+ floating: false,
1522
+ focused: false,
1523
+ error: false,
1524
+ disabled: false,
1525
+ hasLeadingIcon: false
1526
+ }
1527
+ }
1528
+ );
1529
+ var textFieldIconVariants = cva(
1530
+ [
1531
+ // Base icon styles
1532
+ "absolute flex items-center justify-center",
1533
+ "text-on-surface-variant transition-colors duration-200",
1534
+ "pointer-events-none"
1535
+ ],
1536
+ {
1537
+ variants: {
1538
+ position: {
1539
+ leading: "left-3",
1540
+ trailing: "right-3"
1541
+ },
1542
+ size: {
1543
+ small: "w-5 h-5",
1544
+ medium: "w-6 h-6",
1545
+ large: "w-7 h-7"
1546
+ },
1547
+ disabled: {
1548
+ true: "opacity-38",
1549
+ false: ""
1550
+ }
1551
+ },
1552
+ defaultVariants: {
1553
+ position: "leading",
1554
+ size: "medium",
1555
+ disabled: false
1556
+ }
1557
+ }
1558
+ );
1559
+ var textFieldHelperTextVariants = cva(
1560
+ [
1561
+ // Base helper text styles
1562
+ "text-xs mt-1 px-4 transition-colors duration-200"
1563
+ ],
1564
+ {
1565
+ variants: {
1566
+ type: {
1567
+ description: "text-on-surface-variant",
1568
+ error: "text-error"
1569
+ },
1570
+ disabled: {
1571
+ true: "opacity-38",
1572
+ false: ""
1573
+ }
1574
+ },
1575
+ defaultVariants: {
1576
+ type: "description",
1577
+ disabled: false
1578
+ }
1579
+ }
1580
+ );
1581
+ var textFieldCharacterCountVariants = cva(
1582
+ [
1583
+ // Base character counter styles
1584
+ "text-xs mt-1 px-4 text-right text-on-surface-variant transition-colors duration-200"
1585
+ ],
1586
+ {
1587
+ variants: {
1588
+ exceeded: {
1589
+ true: "text-error",
1590
+ false: ""
1591
+ },
1592
+ disabled: {
1593
+ true: "opacity-38",
1594
+ false: ""
1595
+ }
1596
+ },
1597
+ defaultVariants: {
1598
+ exceeded: false,
1599
+ disabled: false
1600
+ }
1601
+ }
1602
+ );
1603
+ var TextFieldHeadless = forwardRef(
1604
+ ({
1605
+ label,
1606
+ description,
1607
+ errorMessage,
1608
+ fullWidth = false,
1609
+ multiline = false,
1610
+ rows = 3,
1611
+ className,
1612
+ inputClassName,
1613
+ labelClassName,
1614
+ descriptionClassName,
1615
+ errorClassName,
1616
+ isInvalid,
1617
+ children,
1618
+ ...restProps
1619
+ }, forwardedRef) => {
1620
+ const internalRef = useRef(null);
1621
+ const ref = forwardedRef ?? internalRef;
1622
+ const inputElementType = multiline ? "textarea" : "input";
1623
+ const {
1624
+ labelProps,
1625
+ inputProps,
1626
+ descriptionProps,
1627
+ errorMessageProps,
1628
+ isInvalid: ariaIsInvalid,
1629
+ validationErrors
1630
+ } = useTextField(
1631
+ {
1632
+ label,
1633
+ description,
1634
+ errorMessage,
1635
+ isInvalid: isInvalid ?? false,
1636
+ inputElementType,
1637
+ ...restProps
1638
+ },
1639
+ ref
1640
+ );
1641
+ const { isFocused, isFocusVisible, focusProps } = useFocusRing({ within: false });
1642
+ const invalid = isInvalid ?? ariaIsInvalid;
1643
+ const showErrorMessage = invalid && (errorMessage ?? validationErrors.length > 0);
1644
+ const displayErrorMessage = errorMessage ?? validationErrors.join(" ");
1645
+ const currentValue = typeof inputProps.value === "string" ? inputProps.value : typeof inputProps.defaultValue === "string" ? inputProps.defaultValue : "";
1646
+ if (typeof children === "function") {
1647
+ const mergedInputProps2 = $3ef42575df84b30b$export$9d1611c77c2fe928(
1648
+ inputProps,
1649
+ focusProps
1650
+ );
1651
+ return children({
1652
+ labelProps,
1653
+ inputProps: mergedInputProps2,
1654
+ descriptionProps,
1655
+ errorMessageProps,
1656
+ isInvalid: invalid,
1657
+ isFocused,
1658
+ isFocusVisible,
1659
+ currentValue,
1660
+ inputRef: ref
1661
+ });
1662
+ }
1663
+ const {
1664
+ isDisabled: _isDisabled,
1665
+ isRequired: _isRequired,
1666
+ isReadOnly: _isReadOnly,
1667
+ validationBehavior: _validationBehavior,
1668
+ validate: _validate,
1669
+ autoFocus: _autoFocus,
1670
+ value: _value,
1671
+ defaultValue: _defaultValue,
1672
+ onChange: _onChange,
1673
+ onFocus: _onFocus,
1674
+ onBlur: _onBlur,
1675
+ onKeyDown: _onKeyDown,
1676
+ onKeyUp: _onKeyUp,
1677
+ onCopy: _onCopy,
1678
+ onCut: _onCut,
1679
+ onPaste: _onPaste,
1680
+ onCompositionStart: _onCompositionStart,
1681
+ onCompositionEnd: _onCompositionEnd,
1682
+ onCompositionUpdate: _onCompositionUpdate,
1683
+ onSelect: _onSelect,
1684
+ onBeforeInput: _onBeforeInput,
1685
+ onInput: _onInput,
1686
+ onFocusChange: _onFocusChange,
1687
+ ...htmlAttrs
1688
+ } = restProps;
1689
+ const mergedInputProps = $3ef42575df84b30b$export$9d1611c77c2fe928(inputProps, focusProps, htmlAttrs, {
1690
+ className: inputClassName
1691
+ });
1692
+ return /* @__PURE__ */ jsxs("div", { className, style: fullWidth ? { width: "100%" } : void 0, children: [
1693
+ label && /* @__PURE__ */ jsx("label", { ...labelProps, className: labelClassName, children: label }),
1694
+ multiline ? /* @__PURE__ */ jsx(
1695
+ "textarea",
1696
+ {
1697
+ ...mergedInputProps,
1698
+ ref,
1699
+ rows
1700
+ }
1701
+ ) : /* @__PURE__ */ jsx("input", { ...mergedInputProps, ref }),
1702
+ description && !showErrorMessage && /* @__PURE__ */ jsx("div", { ...descriptionProps, className: descriptionClassName, children: description }),
1703
+ showErrorMessage && /* @__PURE__ */ jsx("div", { ...errorMessageProps, className: errorClassName, children: displayErrorMessage })
1704
+ ] });
1705
+ }
1706
+ );
1707
+ TextFieldHeadless.displayName = "TextFieldHeadless";
1708
+ var TextField = forwardRef(
1709
+ ({
1710
+ variant = "filled",
1711
+ size = "medium",
1712
+ label,
1713
+ description,
1714
+ errorMessage,
1715
+ leadingIcon,
1716
+ trailingIcon,
1717
+ characterCount = false,
1718
+ maxLength,
1719
+ fullWidth = false,
1720
+ multiline = false,
1721
+ rows = 3,
1722
+ className,
1723
+ isDisabled = false,
1724
+ isInvalid = false,
1725
+ isRequired = false,
1726
+ isReadOnly = false,
1727
+ value,
1728
+ defaultValue,
1729
+ onChange,
1730
+ onFocus,
1731
+ onBlur,
1732
+ spellCheck,
1733
+ ...props
1734
+ }, ref) => {
1735
+ const spellCheckProp = spellCheck === void 0 ? void 0 : typeof spellCheck === "string" ? spellCheck === "true" : spellCheck;
1736
+ const headlessProps = {
1737
+ ...label !== void 0 ? { label } : {},
1738
+ ...description !== void 0 ? { description } : {},
1739
+ ...errorMessage !== void 0 ? { errorMessage } : {},
1740
+ ...value !== void 0 ? { value } : {},
1741
+ ...defaultValue !== void 0 ? { defaultValue } : {},
1742
+ ...onChange !== void 0 ? { onChange } : {},
1743
+ ...onFocus !== void 0 ? { onFocus } : {},
1744
+ ...onBlur !== void 0 ? { onBlur } : {},
1745
+ ...maxLength !== void 0 ? { maxLength } : {},
1746
+ fullWidth,
1747
+ multiline,
1748
+ rows,
1749
+ isDisabled,
1750
+ isInvalid,
1751
+ isRequired,
1752
+ isReadOnly,
1753
+ ...props
1754
+ };
1755
+ return /* @__PURE__ */ jsx(TextFieldHeadless, { ref, ...headlessProps, children: ({
1756
+ labelProps,
1757
+ inputProps,
1758
+ descriptionProps,
1759
+ errorMessageProps,
1760
+ isInvalid: fieldIsInvalid,
1761
+ isFocused,
1762
+ currentValue,
1763
+ inputRef
1764
+ }) => {
1765
+ const hasValue = currentValue.length > 0;
1766
+ const shouldFloatLabel = isFocused || hasValue;
1767
+ const characterLength = currentValue.length;
1768
+ const isCharacterLimitExceeded = maxLength ? characterLength > maxLength : false;
1769
+ return /* @__PURE__ */ jsxs("div", { className: cn(textFieldContainerVariants({ fullWidth }), className), children: [
1770
+ /* @__PURE__ */ jsxs(
1771
+ "div",
1772
+ {
1773
+ className: cn(
1774
+ textFieldWrapperVariants({
1775
+ variant,
1776
+ size,
1777
+ disabled: isDisabled,
1778
+ error: fieldIsInvalid,
1779
+ focused: isFocused
1780
+ })
1781
+ ),
1782
+ children: [
1783
+ leadingIcon && /* @__PURE__ */ jsx(
1784
+ "span",
1785
+ {
1786
+ className: textFieldIconVariants({
1787
+ position: "leading",
1788
+ size,
1789
+ disabled: isDisabled
1790
+ }),
1791
+ children: leadingIcon
1792
+ }
1793
+ ),
1794
+ label && /* @__PURE__ */ jsxs(
1795
+ "label",
1796
+ {
1797
+ ...labelProps,
1798
+ className: cn(
1799
+ textFieldLabelVariants({
1800
+ variant,
1801
+ size,
1802
+ floating: shouldFloatLabel,
1803
+ focused: isFocused,
1804
+ error: fieldIsInvalid,
1805
+ disabled: isDisabled,
1806
+ hasLeadingIcon: !!leadingIcon
1807
+ })
1808
+ ),
1809
+ children: [
1810
+ label,
1811
+ isRequired && " *"
1812
+ ]
1813
+ }
1814
+ ),
1815
+ multiline ? /* @__PURE__ */ jsx(
1816
+ "textarea",
1817
+ {
1818
+ ...inputProps,
1819
+ ref: inputRef,
1820
+ className: cn(
1821
+ textFieldInputVariants({
1822
+ variant,
1823
+ size,
1824
+ disabled: isDisabled,
1825
+ hasLeadingIcon: !!leadingIcon,
1826
+ hasTrailingIcon: !!trailingIcon,
1827
+ multiline: true
1828
+ })
1829
+ ),
1830
+ rows,
1831
+ spellCheck: spellCheckProp
1832
+ }
1833
+ ) : /* @__PURE__ */ jsx(
1834
+ "input",
1835
+ {
1836
+ ...inputProps,
1837
+ ref: inputRef,
1838
+ className: cn(
1839
+ textFieldInputVariants({
1840
+ variant,
1841
+ size,
1842
+ disabled: isDisabled,
1843
+ hasLeadingIcon: !!leadingIcon,
1844
+ hasTrailingIcon: !!trailingIcon,
1845
+ multiline: false
1846
+ })
1847
+ ),
1848
+ spellCheck: spellCheckProp
1849
+ }
1850
+ ),
1851
+ trailingIcon && /* @__PURE__ */ jsx(
1852
+ "span",
1853
+ {
1854
+ className: textFieldIconVariants({
1855
+ position: "trailing",
1856
+ size,
1857
+ disabled: isDisabled
1858
+ }),
1859
+ children: trailingIcon
1860
+ }
1861
+ )
1862
+ ]
1863
+ }
1864
+ ),
1865
+ description && !fieldIsInvalid && /* @__PURE__ */ jsx(
1866
+ "div",
1867
+ {
1868
+ ...descriptionProps,
1869
+ className: textFieldHelperTextVariants({
1870
+ type: "description",
1871
+ disabled: isDisabled
1872
+ }),
1873
+ children: description
1874
+ }
1875
+ ),
1876
+ fieldIsInvalid && errorMessage && /* @__PURE__ */ jsx(
1877
+ "div",
1878
+ {
1879
+ ...errorMessageProps,
1880
+ className: textFieldHelperTextVariants({
1881
+ type: "error",
1882
+ disabled: isDisabled
1883
+ }),
1884
+ children: errorMessage
1885
+ }
1886
+ ),
1887
+ characterCount && maxLength && /* @__PURE__ */ jsxs(
1888
+ "div",
1889
+ {
1890
+ className: textFieldCharacterCountVariants({
1891
+ exceeded: isCharacterLimitExceeded,
1892
+ disabled: isDisabled
1893
+ }),
1894
+ children: [
1895
+ characterLength,
1896
+ " / ",
1897
+ maxLength
1898
+ ]
1899
+ }
1900
+ )
1901
+ ] });
1902
+ } });
1903
+ }
1904
+ );
1905
+ TextField.displayName = "TextField";
1906
+ var $e5be200c675c3b3a$export$aca958c65c314e6c = {
1907
+ badInput: false,
1908
+ customError: false,
1909
+ patternMismatch: false,
1910
+ rangeOverflow: false,
1911
+ rangeUnderflow: false,
1912
+ stepMismatch: false,
1913
+ tooLong: false,
1914
+ tooShort: false,
1915
+ typeMismatch: false,
1916
+ valueMissing: false,
1917
+ valid: true
1918
+ };
1919
+ var $e5be200c675c3b3a$var$CUSTOM_VALIDITY_STATE = {
1920
+ ...$e5be200c675c3b3a$export$aca958c65c314e6c,
1921
+ customError: true,
1922
+ valid: false
1923
+ };
1924
+ var $e5be200c675c3b3a$export$dad6ae84456c676a = {
1925
+ isInvalid: false,
1926
+ validationDetails: $e5be200c675c3b3a$export$aca958c65c314e6c,
1927
+ validationErrors: []
1928
+ };
1929
+ var $e5be200c675c3b3a$export$571b5131b7e65c11 = (createContext)({});
1930
+ var $e5be200c675c3b3a$export$a763b9476acd3eb = "__formValidationState" + Date.now();
1931
+ function $e5be200c675c3b3a$export$fc1a364ae1f3ff10(props) {
1932
+ if (props[$e5be200c675c3b3a$export$a763b9476acd3eb]) {
1933
+ let { realtimeValidation, displayValidation, updateValidation, resetValidation, commitValidation } = props[$e5be200c675c3b3a$export$a763b9476acd3eb];
1934
+ return {
1935
+ realtimeValidation,
1936
+ displayValidation,
1937
+ updateValidation,
1938
+ resetValidation,
1939
+ commitValidation
1940
+ };
1941
+ }
1942
+ return $e5be200c675c3b3a$var$useFormValidationStateImpl(props);
1943
+ }
1944
+ function $e5be200c675c3b3a$var$useFormValidationStateImpl(props) {
1945
+ let { isInvalid, validationState, name, value, builtinValidation, validate, validationBehavior = "aria" } = props;
1946
+ if (validationState) isInvalid || (isInvalid = validationState === "invalid");
1947
+ let controlledError = isInvalid !== void 0 ? {
1948
+ isInvalid,
1949
+ validationErrors: [],
1950
+ validationDetails: $e5be200c675c3b3a$var$CUSTOM_VALIDITY_STATE
1951
+ } : null;
1952
+ let clientError = (useMemo)(() => {
1953
+ if (!validate || value == null) return null;
1954
+ let validateErrors = $e5be200c675c3b3a$var$runValidate(validate, value);
1955
+ return $e5be200c675c3b3a$var$getValidationResult(validateErrors);
1956
+ }, [
1957
+ validate,
1958
+ value
1959
+ ]);
1960
+ if (builtinValidation === null || builtinValidation === void 0 ? void 0 : builtinValidation.validationDetails.valid) builtinValidation = void 0;
1961
+ let serverErrors = (useContext)($e5be200c675c3b3a$export$571b5131b7e65c11);
1962
+ let serverErrorMessages = (useMemo)(() => {
1963
+ if (name) return Array.isArray(name) ? name.flatMap((name2) => $e5be200c675c3b3a$var$asArray(serverErrors[name2])) : $e5be200c675c3b3a$var$asArray(serverErrors[name]);
1964
+ return [];
1965
+ }, [
1966
+ serverErrors,
1967
+ name
1968
+ ]);
1969
+ let [lastServerErrors, setLastServerErrors] = (useState)(serverErrors);
1970
+ let [isServerErrorCleared, setServerErrorCleared] = (useState)(false);
1971
+ if (serverErrors !== lastServerErrors) {
1972
+ setLastServerErrors(serverErrors);
1973
+ setServerErrorCleared(false);
1974
+ }
1975
+ let serverError = (useMemo)(() => $e5be200c675c3b3a$var$getValidationResult(isServerErrorCleared ? [] : serverErrorMessages), [
1976
+ isServerErrorCleared,
1977
+ serverErrorMessages
1978
+ ]);
1979
+ let nextValidation = (useRef)($e5be200c675c3b3a$export$dad6ae84456c676a);
1980
+ let [currentValidity, setCurrentValidity] = (useState)($e5be200c675c3b3a$export$dad6ae84456c676a);
1981
+ let lastError = (useRef)($e5be200c675c3b3a$export$dad6ae84456c676a);
1982
+ let commitValidation = () => {
1983
+ if (!commitQueued) return;
1984
+ setCommitQueued(false);
1985
+ let error = clientError || builtinValidation || nextValidation.current;
1986
+ if (!$e5be200c675c3b3a$var$isEqualValidation(error, lastError.current)) {
1987
+ lastError.current = error;
1988
+ setCurrentValidity(error);
1989
+ }
1990
+ };
1991
+ let [commitQueued, setCommitQueued] = (useState)(false);
1992
+ (useEffect)(commitValidation);
1993
+ let realtimeValidation = controlledError || serverError || clientError || builtinValidation || $e5be200c675c3b3a$export$dad6ae84456c676a;
1994
+ let displayValidation = validationBehavior === "native" ? controlledError || serverError || currentValidity : controlledError || serverError || clientError || builtinValidation || currentValidity;
1995
+ return {
1996
+ realtimeValidation,
1997
+ displayValidation,
1998
+ updateValidation(value2) {
1999
+ if (validationBehavior === "aria" && !$e5be200c675c3b3a$var$isEqualValidation(currentValidity, value2)) setCurrentValidity(value2);
2000
+ else nextValidation.current = value2;
2001
+ },
2002
+ resetValidation() {
2003
+ let error = $e5be200c675c3b3a$export$dad6ae84456c676a;
2004
+ if (!$e5be200c675c3b3a$var$isEqualValidation(error, lastError.current)) {
2005
+ lastError.current = error;
2006
+ setCurrentValidity(error);
2007
+ }
2008
+ if (validationBehavior === "native") setCommitQueued(false);
2009
+ setServerErrorCleared(true);
2010
+ },
2011
+ commitValidation() {
2012
+ if (validationBehavior === "native") setCommitQueued(true);
2013
+ setServerErrorCleared(true);
2014
+ }
2015
+ };
2016
+ }
2017
+ function $e5be200c675c3b3a$var$asArray(v) {
2018
+ if (!v) return [];
2019
+ return Array.isArray(v) ? v : [
2020
+ v
2021
+ ];
2022
+ }
2023
+ function $e5be200c675c3b3a$var$runValidate(validate, value) {
2024
+ if (typeof validate === "function") {
2025
+ let e = validate(value);
2026
+ if (e && typeof e !== "boolean") return $e5be200c675c3b3a$var$asArray(e);
2027
+ }
2028
+ return [];
2029
+ }
2030
+ function $e5be200c675c3b3a$var$getValidationResult(errors) {
2031
+ return errors.length ? {
2032
+ isInvalid: true,
2033
+ validationErrors: errors,
2034
+ validationDetails: $e5be200c675c3b3a$var$CUSTOM_VALIDITY_STATE
2035
+ } : null;
2036
+ }
2037
+ function $e5be200c675c3b3a$var$isEqualValidation(a, b) {
2038
+ if (a === b) return true;
2039
+ return !!a && !!b && a.isInvalid === b.isInvalid && a.validationErrors.length === b.validationErrors.length && a.validationErrors.every((a2, i) => a2 === b.validationErrors[i]) && Object.entries(a.validationDetails).every(([k, v]) => b.validationDetails[k] === v);
2040
+ }
2041
+ var $a54cdc5c1942b639$var$instance = Math.round(Math.random() * 1e10);
2042
+ var $a54cdc5c1942b639$var$i = 0;
2043
+ function $a54cdc5c1942b639$export$bca9d026f8e704eb(props) {
2044
+ let name = (useMemo)(() => props.name || `radio-group-${$a54cdc5c1942b639$var$instance}-${++$a54cdc5c1942b639$var$i}`, [
2045
+ props.name
2046
+ ]);
2047
+ var _props_defaultValue;
2048
+ let [selectedValue, setSelected] = ($458b0a5536c1a7cf$export$40bfa8c7b0832715)(props.value, (_props_defaultValue = props.defaultValue) !== null && _props_defaultValue !== void 0 ? _props_defaultValue : null, props.onChange);
2049
+ let [initialValue] = (useState)(selectedValue);
2050
+ let [lastFocusedValue, setLastFocusedValue] = (useState)(null);
2051
+ let validation = ($e5be200c675c3b3a$export$fc1a364ae1f3ff10)({
2052
+ ...props,
2053
+ value: selectedValue
2054
+ });
2055
+ let setSelectedValue = (value) => {
2056
+ if (!props.isReadOnly && !props.isDisabled) {
2057
+ setSelected(value);
2058
+ validation.commitValidation();
2059
+ }
2060
+ };
2061
+ let isInvalid = validation.displayValidation.isInvalid;
2062
+ var _props_defaultValue1;
2063
+ return {
2064
+ ...validation,
2065
+ name,
2066
+ selectedValue,
2067
+ defaultSelectedValue: props.value !== void 0 ? initialValue : (_props_defaultValue1 = props.defaultValue) !== null && _props_defaultValue1 !== void 0 ? _props_defaultValue1 : null,
2068
+ setSelectedValue,
2069
+ lastFocusedValue,
2070
+ setLastFocusedValue,
2071
+ isDisabled: props.isDisabled || false,
2072
+ isReadOnly: props.isReadOnly || false,
2073
+ isRequired: props.isRequired || false,
2074
+ validationState: props.validationState || (isInvalid ? "invalid" : null),
2075
+ isInvalid
2076
+ };
2077
+ }
2078
+ function $3017fa7ffdddec74$export$8042c6c013fd5226(props = {}) {
2079
+ let { isReadOnly } = props;
2080
+ let [isSelected, setSelected] = ($458b0a5536c1a7cf$export$40bfa8c7b0832715)(props.isSelected, props.defaultSelected || false, props.onChange);
2081
+ let [initialValue] = (useState)(isSelected);
2082
+ function updateSelected(value) {
2083
+ if (!isReadOnly) setSelected(value);
2084
+ }
2085
+ function toggleState() {
2086
+ if (!isReadOnly) setSelected(!isSelected);
2087
+ }
2088
+ var _props_defaultSelected;
2089
+ return {
2090
+ isSelected,
2091
+ defaultSelected: (_props_defaultSelected = props.defaultSelected) !== null && _props_defaultSelected !== void 0 ? _props_defaultSelected : initialValue,
2092
+ setSelected: updateSelected,
2093
+ toggle: toggleState
2094
+ };
2095
+ }
2096
+ var checkboxVariants = cva(
2097
+ [
2098
+ // Base classes (always applied to label wrapper)
2099
+ "relative inline-flex items-center cursor-pointer select-none",
2100
+ "transition-opacity duration-200"
2101
+ ],
2102
+ {
2103
+ variants: {
2104
+ /**
2105
+ * Disabled state
2106
+ */
2107
+ disabled: {
2108
+ true: "opacity-38 cursor-not-allowed pointer-events-none",
2109
+ false: ""
2110
+ }
2111
+ },
2112
+ defaultVariants: {
2113
+ disabled: false
2114
+ }
2115
+ }
2116
+ );
2117
+ var checkboxContainerVariants = cva(
2118
+ [
2119
+ // Base classes for checkbox visual container
2120
+ "relative inline-flex items-center justify-center",
2121
+ "w-10 h-10",
2122
+ // 40x40dp touch target (MD3 spec)
2123
+ "flex-shrink-0",
2124
+ "transition-all duration-200",
2125
+ // State layer (hover, focus, active) - MD3 spec: 8%/12%/12% opacity
2126
+ "before:absolute before:inset-0 before:rounded-full before:transition-opacity before:duration-200",
2127
+ "before:bg-current before:opacity-0",
2128
+ "hover:before:opacity-8",
2129
+ "active:before:opacity-12"
2130
+ ],
2131
+ {
2132
+ variants: {
2133
+ /**
2134
+ * Checkbox state (determines visual appearance)
2135
+ */
2136
+ state: {
2137
+ unchecked: "text-on-surface-variant",
2138
+ checked: "text-primary",
2139
+ indeterminate: "text-primary"
2140
+ },
2141
+ /**
2142
+ * Error/invalid state
2143
+ */
2144
+ isInvalid: {
2145
+ true: "text-error",
2146
+ false: ""
2147
+ },
2148
+ /**
2149
+ * Disabled state
2150
+ */
2151
+ disabled: {
2152
+ true: "text-on-surface pointer-events-none",
2153
+ false: ""
2154
+ }
2155
+ },
2156
+ compoundVariants: [
2157
+ // Error state overrides normal colors for all states
2158
+ {
2159
+ state: "unchecked",
2160
+ isInvalid: true,
2161
+ disabled: false,
2162
+ className: "text-error"
2163
+ },
2164
+ {
2165
+ state: "checked",
2166
+ isInvalid: true,
2167
+ disabled: false,
2168
+ className: "text-error"
2169
+ },
2170
+ {
2171
+ state: "indeterminate",
2172
+ isInvalid: true,
2173
+ disabled: false,
2174
+ className: "text-error"
2175
+ }
2176
+ ],
2177
+ defaultVariants: {
2178
+ state: "unchecked",
2179
+ isInvalid: false,
2180
+ disabled: false
2181
+ }
2182
+ }
2183
+ );
2184
+ var checkboxIconBoxVariants = cva(
2185
+ [
2186
+ // Base classes for the checkbox box
2187
+ // Note: Border radius is applied via SVG rx/ry attributes (2dp) in the component
2188
+ "transition-all duration-200"
2189
+ ],
2190
+ {
2191
+ variants: {
2192
+ /**
2193
+ * Checkbox state
2194
+ */
2195
+ state: {
2196
+ unchecked: [
2197
+ "fill-transparent",
2198
+ "stroke-outline",
2199
+ // MD3: outline color for unchecked
2200
+ "stroke-2"
2201
+ // MD3: 2dp outline width
2202
+ ],
2203
+ checked: [
2204
+ "fill-current",
2205
+ // Uses parent text color (primary or error)
2206
+ "stroke-none"
2207
+ ],
2208
+ indeterminate: [
2209
+ "fill-current",
2210
+ // Uses parent text color (primary or error)
2211
+ "stroke-none"
2212
+ ]
2213
+ },
2214
+ /**
2215
+ * Disabled state
2216
+ */
2217
+ disabled: {
2218
+ true: ["fill-transparent", "stroke-current", "stroke-2"],
2219
+ false: ""
2220
+ }
2221
+ },
2222
+ compoundVariants: [
2223
+ // Disabled state overrides fill for checked/indeterminate
2224
+ {
2225
+ state: "checked",
2226
+ disabled: true,
2227
+ className: "fill-current stroke-none"
2228
+ },
2229
+ {
2230
+ state: "indeterminate",
2231
+ disabled: true,
2232
+ className: "fill-current stroke-none"
2233
+ }
2234
+ ],
2235
+ defaultVariants: {
2236
+ state: "unchecked",
2237
+ disabled: false
2238
+ }
2239
+ }
2240
+ );
2241
+ var checkboxIconVariants = cva(
2242
+ [
2243
+ "fill-current",
2244
+ // Inherits color from parent
2245
+ "transition-all duration-200"
2246
+ ],
2247
+ {
2248
+ variants: {
2249
+ /**
2250
+ * Icon type
2251
+ */
2252
+ type: {
2253
+ check: "",
2254
+ // Checkmark icon
2255
+ dash: ""
2256
+ // Dash/minus icon
2257
+ }
2258
+ },
2259
+ defaultVariants: {
2260
+ type: "check"
2261
+ }
2262
+ }
2263
+ );
2264
+ var checkboxLabelVariants = cva(
2265
+ [
2266
+ "text-sm",
2267
+ // MD3: Body Medium (14px)
2268
+ "text-on-surface",
2269
+ "select-none",
2270
+ "ml-4"
2271
+ // 16px spacing between checkbox and label (MD3 standard)
2272
+ ],
2273
+ {
2274
+ variants: {
2275
+ disabled: {
2276
+ true: "",
2277
+ false: ""
2278
+ }
2279
+ },
2280
+ defaultVariants: {
2281
+ disabled: false
2282
+ }
2283
+ }
2284
+ );
2285
+ var Checkbox = forwardRef(
2286
+ ({
2287
+ // Content props
2288
+ children,
2289
+ // State props
2290
+ isIndeterminate = false,
2291
+ isInvalid = false,
2292
+ disableRipple = false,
2293
+ isDisabled = false,
2294
+ // Styling
2295
+ className,
2296
+ // Other props
2297
+ ...props
2298
+ }, forwardedRef) => {
2299
+ const internalRef = useRef(null);
2300
+ const ref = forwardedRef ?? internalRef;
2301
+ const htmlAttrs = props;
2302
+ const dataTestId = htmlAttrs["data-testid"];
2303
+ const htmlId = htmlAttrs.id;
2304
+ const htmlTitle = htmlAttrs.title;
2305
+ const {
2306
+ "data-testid": _dataTestId,
2307
+ id: _htmlId,
2308
+ title: _htmlTitle,
2309
+ ...restPropsWithoutHtmlAttrs
2310
+ } = props;
2311
+ const state = $3017fa7ffdddec74$export$8042c6c013fd5226(restPropsWithoutHtmlAttrs);
2312
+ const { inputProps, labelProps } = useCheckbox(
2313
+ restPropsWithoutHtmlAttrs,
2314
+ state,
2315
+ ref
2316
+ );
2317
+ const { isFocusVisible, focusProps } = useFocusRing();
2318
+ const isSelected = state.isSelected;
2319
+ const visualState = isIndeterminate ? "indeterminate" : isSelected ? "checked" : "unchecked";
2320
+ const { onMouseDown: handleRipple, ripples } = useRipple({
2321
+ disabled: isDisabled || disableRipple
2322
+ });
2323
+ useEffect(() => {
2324
+ if (ref.current) {
2325
+ ref.current.indeterminate = isIndeterminate;
2326
+ }
2327
+ }, [isIndeterminate, ref]);
2328
+ if (process.env.NODE_ENV === "development") {
2329
+ const ariaProps = restPropsWithoutHtmlAttrs;
2330
+ if (!children && !ariaProps["aria-label"] && !ariaProps["aria-labelledby"]) {
2331
+ console.warn(
2332
+ "[Checkbox] Checkbox should have a label (children) or aria-label for accessibility."
2333
+ );
2334
+ }
2335
+ }
2336
+ return /* @__PURE__ */ jsxs(
2337
+ "label",
2338
+ {
2339
+ ...labelProps,
2340
+ className: cn(
2341
+ checkboxVariants({
2342
+ disabled: isDisabled
2343
+ }),
2344
+ className
2345
+ ),
2346
+ "data-testid": dataTestId,
2347
+ title: htmlTitle,
2348
+ children: [
2349
+ /* @__PURE__ */ jsx(VisuallyHidden, { children: /* @__PURE__ */ jsx("input", { ...mergeProps(inputProps, focusProps), ref, id: htmlId }) }),
2350
+ /* @__PURE__ */ jsxs(
2351
+ "div",
2352
+ {
2353
+ role: "presentation",
2354
+ className: cn(
2355
+ checkboxContainerVariants({
2356
+ state: visualState,
2357
+ isInvalid,
2358
+ disabled: isDisabled
2359
+ })
2360
+ ),
2361
+ onMouseDown: handleRipple,
2362
+ children: [
2363
+ ripples,
2364
+ /* @__PURE__ */ jsxs(
2365
+ "svg",
2366
+ {
2367
+ width: "18",
2368
+ height: "18",
2369
+ viewBox: "0 0 18 18",
2370
+ "aria-hidden": "true",
2371
+ className: "relative z-10",
2372
+ children: [
2373
+ /* @__PURE__ */ jsx(
2374
+ "rect",
2375
+ {
2376
+ x: "0",
2377
+ y: "0",
2378
+ width: "18",
2379
+ height: "18",
2380
+ rx: "2",
2381
+ ry: "2",
2382
+ className: cn(
2383
+ checkboxIconBoxVariants({
2384
+ state: visualState,
2385
+ disabled: isDisabled
2386
+ })
2387
+ )
2388
+ }
2389
+ ),
2390
+ isSelected && !isIndeterminate && /* @__PURE__ */ jsx(
2391
+ "path",
2392
+ {
2393
+ d: "M14.1 4.5L6.3 12.3l-3.4-3.4L1.5 10.3l4.8 4.8 9.2-9.2z",
2394
+ className: cn(checkboxIconVariants({ type: "check" }), "fill-on-primary")
2395
+ }
2396
+ ),
2397
+ isIndeterminate && /* @__PURE__ */ jsx(
2398
+ "rect",
2399
+ {
2400
+ x: "4",
2401
+ y: "8",
2402
+ width: "10",
2403
+ height: "2",
2404
+ className: cn(checkboxIconVariants({ type: "dash" }), "fill-on-primary")
2405
+ }
2406
+ ),
2407
+ isFocusVisible && /* @__PURE__ */ jsx(
2408
+ "rect",
2409
+ {
2410
+ x: "-3",
2411
+ y: "-3",
2412
+ width: "24",
2413
+ height: "24",
2414
+ rx: "12",
2415
+ fill: "none",
2416
+ stroke: "currentColor",
2417
+ strokeWidth: "2",
2418
+ className: "animate-pulse"
2419
+ }
2420
+ )
2421
+ ]
2422
+ }
2423
+ )
2424
+ ]
2425
+ }
2426
+ ),
2427
+ children && /* @__PURE__ */ jsx(
2428
+ "span",
2429
+ {
2430
+ className: cn(
2431
+ checkboxLabelVariants({
2432
+ disabled: isDisabled
2433
+ })
2434
+ ),
2435
+ children
2436
+ }
2437
+ )
2438
+ ]
2439
+ }
2440
+ );
2441
+ }
2442
+ );
2443
+ Checkbox.displayName = "Checkbox";
2444
+ var switchVariants = cva(
2445
+ [
2446
+ // Base classes (always applied to label wrapper)
2447
+ "relative inline-flex items-center cursor-pointer select-none",
2448
+ "transition-opacity duration-200"
2449
+ ],
2450
+ {
2451
+ variants: {
2452
+ /**
2453
+ * Disabled state
2454
+ */
2455
+ disabled: {
2456
+ true: "opacity-38 cursor-not-allowed pointer-events-none",
2457
+ false: ""
2458
+ }
2459
+ },
2460
+ defaultVariants: {
2461
+ disabled: false
2462
+ }
2463
+ }
2464
+ );
2465
+ var switchTrackVariants = cva(
2466
+ [
2467
+ // Base classes for track
2468
+ "relative flex items-center",
2469
+ "w-[52px] h-[32px]",
2470
+ // MD3 spec: 52x32dp
2471
+ "rounded-full",
2472
+ // MD3 spec: border-radius 16dp (full)
2473
+ "transition-all duration-200"
2474
+ ],
2475
+ {
2476
+ variants: {
2477
+ /**
2478
+ * Switch state (determines track color)
2479
+ */
2480
+ selected: {
2481
+ true: "bg-primary",
2482
+ // MD3: selected track
2483
+ false: "bg-surface-container-highest"
2484
+ // MD3: unselected track
2485
+ },
2486
+ /**
2487
+ * Disabled state
2488
+ */
2489
+ disabled: {
2490
+ true: "bg-on-surface/12",
2491
+ // MD3: 12% opacity for disabled
2492
+ false: ""
2493
+ }
2494
+ },
2495
+ compoundVariants: [
2496
+ // Disabled state overrides normal colors
2497
+ {
2498
+ selected: true,
2499
+ disabled: true,
2500
+ className: "bg-on-surface/12"
2501
+ },
2502
+ {
2503
+ selected: false,
2504
+ disabled: true,
2505
+ className: "bg-on-surface/12"
2506
+ }
2507
+ ],
2508
+ defaultVariants: {
2509
+ selected: false,
2510
+ disabled: false
2511
+ }
2512
+ }
2513
+ );
2514
+ var switchHandleContainerVariants = cva(
2515
+ [
2516
+ // Base classes for handle container (includes state layer)
2517
+ "absolute flex items-center justify-center",
2518
+ "rounded-full",
2519
+ "transition-all duration-200",
2520
+ // State layer (hover, focus, active) - MD3 spec: 8%/12%/12% opacity
2521
+ "before:absolute before:inset-0 before:rounded-full before:transition-opacity before:duration-200",
2522
+ "before:bg-current before:opacity-0",
2523
+ "hover:before:opacity-8",
2524
+ "active:before:opacity-12"
2525
+ ],
2526
+ {
2527
+ variants: {
2528
+ /**
2529
+ * Switch state (determines handle position and size)
2530
+ */
2531
+ selected: {
2532
+ true: [
2533
+ "left-[28px]",
2534
+ // Position when ON (52px - 24px = 28px)
2535
+ "text-primary"
2536
+ // State layer color
2537
+ ],
2538
+ false: [
2539
+ "left-[8px]",
2540
+ // Position when OFF (centered in left half)
2541
+ "text-on-surface-variant"
2542
+ // State layer color
2543
+ ]
2544
+ },
2545
+ /**
2546
+ * Pressed state (increases handle size)
2547
+ */
2548
+ pressed: {
2549
+ true: "w-[28px] h-[28px]",
2550
+ // MD3: 28dp when pressed
2551
+ false: ""
2552
+ },
2553
+ /**
2554
+ * Disabled state
2555
+ */
2556
+ disabled: {
2557
+ true: "pointer-events-none",
2558
+ false: ""
2559
+ }
2560
+ },
2561
+ compoundVariants: [
2562
+ // Size depends on selected + pressed state
2563
+ {
2564
+ selected: true,
2565
+ pressed: false,
2566
+ className: "w-[24px] h-[24px]"
2567
+ // MD3: 24dp when selected
2568
+ },
2569
+ {
2570
+ selected: false,
2571
+ pressed: false,
2572
+ className: "w-[16px] h-[16px]"
2573
+ // MD3: 16dp when unselected
2574
+ }
2575
+ ],
2576
+ defaultVariants: {
2577
+ selected: false,
2578
+ pressed: false,
2579
+ disabled: false
2580
+ }
2581
+ }
2582
+ );
2583
+ var switchHandleVariants = cva(
2584
+ [
2585
+ // Base classes for the handle
2586
+ "relative z-10 rounded-full",
2587
+ "transition-all duration-200",
2588
+ "flex items-center justify-center"
2589
+ ],
2590
+ {
2591
+ variants: {
2592
+ /**
2593
+ * Switch state (determines handle color and size)
2594
+ */
2595
+ selected: {
2596
+ true: "bg-on-primary",
2597
+ // MD3: on-primary when selected
2598
+ false: "bg-outline"
2599
+ // MD3: outline when unselected
2600
+ },
2601
+ /**
2602
+ * Pressed state
2603
+ */
2604
+ pressed: {
2605
+ true: "w-[28px] h-[28px]",
2606
+ // MD3: 28dp when pressed
2607
+ false: ""
2608
+ },
2609
+ /**
2610
+ * Disabled state
2611
+ */
2612
+ disabled: {
2613
+ true: "bg-on-surface/38",
2614
+ // MD3: 38% opacity for disabled
2615
+ false: ""
2616
+ }
2617
+ },
2618
+ compoundVariants: [
2619
+ // Size depends on selected + pressed state
2620
+ {
2621
+ selected: true,
2622
+ pressed: false,
2623
+ className: "w-[24px] h-[24px]"
2624
+ // MD3: 24dp when selected
2625
+ },
2626
+ {
2627
+ selected: false,
2628
+ pressed: false,
2629
+ className: "w-[16px] h-[16px]"
2630
+ // MD3: 16dp when unselected
2631
+ },
2632
+ // Disabled state overrides normal colors
2633
+ {
2634
+ selected: true,
2635
+ disabled: true,
2636
+ className: "bg-on-surface/38"
2637
+ },
2638
+ {
2639
+ selected: false,
2640
+ disabled: true,
2641
+ className: "bg-on-surface/38"
2642
+ }
2643
+ ],
2644
+ defaultVariants: {
2645
+ selected: false,
2646
+ pressed: false,
2647
+ disabled: false
2648
+ }
2649
+ }
2650
+ );
2651
+ var switchIconVariants = cva(
2652
+ [
2653
+ // Base classes for icons
2654
+ "w-4 h-4",
2655
+ // MD3: 16x16dp icon size
2656
+ "transition-all duration-200"
2657
+ ],
2658
+ {
2659
+ variants: {
2660
+ /**
2661
+ * Icon visibility based on state
2662
+ */
2663
+ visible: {
2664
+ true: "opacity-100",
2665
+ false: "opacity-0"
2666
+ },
2667
+ /**
2668
+ * Disabled state
2669
+ */
2670
+ disabled: {
2671
+ true: "opacity-38",
2672
+ false: ""
2673
+ }
2674
+ },
2675
+ defaultVariants: {
2676
+ visible: true,
2677
+ disabled: false
2678
+ }
2679
+ }
2680
+ );
2681
+ var switchLabelVariants = cva(
2682
+ [
2683
+ "text-sm",
2684
+ // MD3: Body Medium (14px)
2685
+ "text-on-surface",
2686
+ "select-none",
2687
+ "ml-4"
2688
+ // 16px spacing between switch and label (MD3 standard)
2689
+ ],
2690
+ {
2691
+ variants: {
2692
+ disabled: {
2693
+ true: "",
2694
+ false: ""
2695
+ }
2696
+ },
2697
+ defaultVariants: {
2698
+ disabled: false
2699
+ }
2700
+ }
2701
+ );
2702
+ var Switch = forwardRef(
2703
+ ({
2704
+ // Content props
2705
+ children,
2706
+ icon,
2707
+ selectedIcon,
2708
+ // State props
2709
+ disableRipple = false,
2710
+ isDisabled = false,
2711
+ // Styling
2712
+ className,
2713
+ // Other props
2714
+ ...props
2715
+ }, forwardedRef) => {
2716
+ const internalRef = useRef(null);
2717
+ const ref = forwardedRef ?? internalRef;
2718
+ const htmlAttrs = props;
2719
+ const dataTestId = htmlAttrs["data-testid"];
2720
+ const htmlId = htmlAttrs.id;
2721
+ const htmlTitle = htmlAttrs.title;
2722
+ const {
2723
+ "data-testid": _dataTestId,
2724
+ id: _htmlId,
2725
+ title: _htmlTitle,
2726
+ ...restPropsWithoutHtmlAttrs
2727
+ } = props;
2728
+ const state = $3017fa7ffdddec74$export$8042c6c013fd5226(restPropsWithoutHtmlAttrs);
2729
+ const { inputProps, labelProps, isPressed } = useSwitch(
2730
+ restPropsWithoutHtmlAttrs,
2731
+ state,
2732
+ ref
2733
+ );
2734
+ const { isFocusVisible, focusProps } = useFocusRing();
2735
+ const isSelected = state.isSelected;
2736
+ const { onMouseDown: handleRipple, ripples } = useRipple({
2737
+ disabled: isDisabled || disableRipple
2738
+ });
2739
+ if (process.env.NODE_ENV === "development") {
2740
+ const ariaProps = restPropsWithoutHtmlAttrs;
2741
+ if (!children && !ariaProps["aria-label"] && !ariaProps["aria-labelledby"]) {
2742
+ console.warn(
2743
+ "[Switch] Switch should have a label (children) or aria-label for accessibility."
2744
+ );
2745
+ }
2746
+ }
2747
+ return /* @__PURE__ */ jsxs(
2748
+ "label",
2749
+ {
2750
+ ...labelProps,
2751
+ className: cn(
2752
+ switchVariants({
2753
+ disabled: isDisabled
2754
+ }),
2755
+ className
2756
+ ),
2757
+ "data-testid": dataTestId,
2758
+ title: htmlTitle,
2759
+ children: [
2760
+ /* @__PURE__ */ jsx(VisuallyHidden, { children: /* @__PURE__ */ jsx("input", { ...mergeProps(inputProps, focusProps), ref, id: htmlId }) }),
2761
+ /* @__PURE__ */ jsxs(
2762
+ "div",
2763
+ {
2764
+ role: "presentation",
2765
+ className: cn(
2766
+ switchTrackVariants({
2767
+ selected: isSelected,
2768
+ disabled: isDisabled
2769
+ })
2770
+ ),
2771
+ children: [
2772
+ isFocusVisible && /* @__PURE__ */ jsx(
2773
+ "div",
2774
+ {
2775
+ className: "border-primary absolute inset-[-4px] animate-pulse rounded-full border-2",
2776
+ "aria-hidden": "true"
2777
+ }
2778
+ ),
2779
+ /* @__PURE__ */ jsxs(
2780
+ "div",
2781
+ {
2782
+ className: cn(
2783
+ switchHandleContainerVariants({
2784
+ selected: isSelected,
2785
+ pressed: isPressed,
2786
+ disabled: isDisabled
2787
+ })
2788
+ ),
2789
+ onMouseDown: handleRipple,
2790
+ role: "presentation",
2791
+ children: [
2792
+ ripples,
2793
+ /* @__PURE__ */ jsxs(
2794
+ "div",
2795
+ {
2796
+ className: cn(
2797
+ switchHandleVariants({
2798
+ selected: isSelected,
2799
+ pressed: isPressed,
2800
+ disabled: isDisabled
2801
+ })
2802
+ ),
2803
+ children: [
2804
+ !isSelected && icon && /* @__PURE__ */ jsx(
2805
+ "div",
2806
+ {
2807
+ className: cn(
2808
+ switchIconVariants({
2809
+ visible: !isSelected,
2810
+ disabled: isDisabled
2811
+ })
2812
+ ),
2813
+ children: icon
2814
+ }
2815
+ ),
2816
+ isSelected && selectedIcon && /* @__PURE__ */ jsx(
2817
+ "div",
2818
+ {
2819
+ className: cn(
2820
+ switchIconVariants({
2821
+ visible: isSelected,
2822
+ disabled: isDisabled
2823
+ })
2824
+ ),
2825
+ children: selectedIcon
2826
+ }
2827
+ )
2828
+ ]
2829
+ }
2830
+ )
2831
+ ]
2832
+ }
2833
+ )
2834
+ ]
2835
+ }
2836
+ ),
2837
+ children && /* @__PURE__ */ jsx(
2838
+ "span",
2839
+ {
2840
+ className: cn(
2841
+ switchLabelVariants({
2842
+ disabled: isDisabled
2843
+ })
2844
+ ),
2845
+ children
2846
+ }
2847
+ )
2848
+ ]
2849
+ }
2850
+ );
2851
+ }
2852
+ );
2853
+ Switch.displayName = "Switch";
2854
+ var RadioGroupContext = createContext(null);
2855
+ var RadioGroupHeadless = forwardRef(
2856
+ ({ className, children, renderLabel, ...props }, forwardedRef) => {
2857
+ const internalRef = useRef(null);
2858
+ const ref = forwardedRef ?? internalRef;
2859
+ const state = $a54cdc5c1942b639$export$bca9d026f8e704eb(props);
2860
+ const { radioGroupProps, labelProps } = useRadioGroup(props, state);
2861
+ const dataTestId = props["data-testid"];
2862
+ return /* @__PURE__ */ jsxs("div", { ...radioGroupProps, ref, className, "data-testid": dataTestId, children: [
2863
+ props.label && (renderLabel ? renderLabel(labelProps) : /* @__PURE__ */ jsx("span", { ...labelProps, children: props.label })),
2864
+ /* @__PURE__ */ jsx(RadioGroupContext.Provider, { value: state, children })
2865
+ ] });
2866
+ }
2867
+ );
2868
+ RadioGroupHeadless.displayName = "RadioGroupHeadless";
2869
+ var radioGroupVariants = cva(
2870
+ [
2871
+ // Base classes (always applied to group wrapper)
2872
+ "flex",
2873
+ "gap-4"
2874
+ // 16px spacing between radios (MD3 standard)
2875
+ ],
2876
+ {
2877
+ variants: {
2878
+ /**
2879
+ * Layout orientation
2880
+ */
2881
+ orientation: {
2882
+ vertical: "flex-col",
2883
+ horizontal: "flex-row flex-wrap"
2884
+ },
2885
+ /**
2886
+ * Disabled state
2887
+ */
2888
+ disabled: {
2889
+ true: "",
2890
+ false: ""
2891
+ }
2892
+ },
2893
+ defaultVariants: {
2894
+ orientation: "vertical",
2895
+ disabled: false
2896
+ }
2897
+ }
2898
+ );
2899
+ var radioGroupLabelVariants = cva(
2900
+ [
2901
+ "text-sm font-medium",
2902
+ // MD3: Body Medium
2903
+ "text-on-surface",
2904
+ "mb-3"
2905
+ // Spacing below label (12px)
2906
+ ],
2907
+ {
2908
+ variants: {
2909
+ disabled: {
2910
+ true: "opacity-38",
2911
+ false: ""
2912
+ }
2913
+ },
2914
+ defaultVariants: {
2915
+ disabled: false
2916
+ }
2917
+ }
2918
+ );
2919
+ var radioVariants = cva(
2920
+ [
2921
+ // Base classes (always applied to label wrapper)
2922
+ "relative inline-flex items-center cursor-pointer select-none",
2923
+ "transition-opacity duration-200"
2924
+ ],
2925
+ {
2926
+ variants: {
2927
+ /**
2928
+ * Disabled state
2929
+ */
2930
+ disabled: {
2931
+ true: "opacity-38 cursor-not-allowed pointer-events-none",
2932
+ false: ""
2933
+ }
2934
+ },
2935
+ defaultVariants: {
2936
+ disabled: false
2937
+ }
2938
+ }
2939
+ );
2940
+ var radioContainerVariants = cva(
2941
+ [
2942
+ // Base classes for radio visual container
2943
+ "relative inline-flex items-center justify-center",
2944
+ "w-10 h-10",
2945
+ // 40x40dp touch target (MD3 spec)
2946
+ "flex-shrink-0",
2947
+ "transition-all duration-200",
2948
+ // State layer (hover, focus, active) - MD3 spec: 8%/12%/12% opacity
2949
+ "before:absolute before:inset-0 before:rounded-full before:transition-opacity before:duration-200",
2950
+ "before:bg-current before:opacity-0",
2951
+ "hover:before:opacity-8",
2952
+ "active:before:opacity-12"
2953
+ ],
2954
+ {
2955
+ variants: {
2956
+ /**
2957
+ * Radio state (determines visual appearance)
2958
+ */
2959
+ state: {
2960
+ unselected: "text-on-surface-variant",
2961
+ selected: "text-primary"
2962
+ },
2963
+ /**
2964
+ * Error/invalid state
2965
+ */
2966
+ isInvalid: {
2967
+ true: "text-error",
2968
+ false: ""
2969
+ },
2970
+ /**
2971
+ * Disabled state
2972
+ */
2973
+ disabled: {
2974
+ true: "text-on-surface pointer-events-none",
2975
+ false: ""
2976
+ }
2977
+ },
2978
+ compoundVariants: [
2979
+ // Error state overrides normal colors for all states
2980
+ {
2981
+ state: "unselected",
2982
+ isInvalid: true,
2983
+ disabled: false,
2984
+ className: "text-error"
2985
+ },
2986
+ {
2987
+ state: "selected",
2988
+ isInvalid: true,
2989
+ disabled: false,
2990
+ className: "text-error"
2991
+ }
2992
+ ],
2993
+ defaultVariants: {
2994
+ state: "unselected",
2995
+ isInvalid: false,
2996
+ disabled: false
2997
+ }
2998
+ }
2999
+ );
3000
+ var radioIconOuterVariants = cva(
3001
+ [
3002
+ // Base classes for the radio outer circle
3003
+ "transition-all duration-200"
3004
+ ],
3005
+ {
3006
+ variants: {
3007
+ /**
3008
+ * Radio state
3009
+ */
3010
+ state: {
3011
+ unselected: [
3012
+ "fill-transparent",
3013
+ "stroke-current",
3014
+ // Uses parent text color (on-surface-variant or error)
3015
+ "stroke-2"
3016
+ // MD3: 2dp outline width
3017
+ ],
3018
+ selected: [
3019
+ "fill-current",
3020
+ // Uses parent text color (primary or error)
3021
+ "stroke-none"
3022
+ ]
3023
+ },
3024
+ /**
3025
+ * Disabled state
3026
+ */
3027
+ disabled: {
3028
+ true: ["fill-transparent", "stroke-current", "stroke-2"],
3029
+ false: ""
3030
+ }
3031
+ },
3032
+ compoundVariants: [
3033
+ // Disabled + selected state overrides fill
3034
+ {
3035
+ state: "selected",
3036
+ disabled: true,
3037
+ className: "fill-current stroke-none"
3038
+ }
3039
+ ],
3040
+ defaultVariants: {
3041
+ state: "unselected",
3042
+ disabled: false
3043
+ }
3044
+ }
3045
+ );
3046
+ var radioIconInnerVariants = cva(
3047
+ [
3048
+ "fill-current",
3049
+ // Inherits color from parent (on-primary)
3050
+ "transition-all duration-200"
3051
+ ],
3052
+ {
3053
+ variants: {
3054
+ /**
3055
+ * Visibility based on state
3056
+ */
3057
+ visible: {
3058
+ true: "opacity-100 scale-100",
3059
+ false: "opacity-0 scale-0"
3060
+ }
3061
+ },
3062
+ defaultVariants: {
3063
+ visible: false
3064
+ }
3065
+ }
3066
+ );
3067
+ var radioLabelVariants = cva(
3068
+ [
3069
+ "text-sm",
3070
+ // MD3: Body Medium (14px)
3071
+ "text-on-surface",
3072
+ "select-none",
3073
+ "ml-4"
3074
+ // 16px spacing between radio and label (MD3 standard)
3075
+ ],
3076
+ {
3077
+ variants: {
3078
+ disabled: {
3079
+ true: "",
3080
+ false: ""
3081
+ }
3082
+ },
3083
+ defaultVariants: {
3084
+ disabled: false
3085
+ }
3086
+ }
3087
+ );
3088
+ var Radio = forwardRef(
3089
+ ({
3090
+ // Content props
3091
+ children,
3092
+ // State props
3093
+ disableRipple = false,
3094
+ isDisabled = false,
3095
+ // Styling
3096
+ className,
3097
+ // Other props
3098
+ ...props
3099
+ }, forwardedRef) => {
3100
+ const state = useContext(RadioGroupContext);
3101
+ if (!state) {
3102
+ throw new Error("Radio must be used within a RadioGroup");
3103
+ }
3104
+ const internalRef = useRef(null);
3105
+ const ref = forwardedRef ?? internalRef;
3106
+ const htmlAttrs = props;
3107
+ const dataTestId = htmlAttrs["data-testid"];
3108
+ const htmlId = htmlAttrs.id;
3109
+ const htmlTitle = htmlAttrs.title;
3110
+ const {
3111
+ "data-testid": _dataTestId,
3112
+ id: _htmlId,
3113
+ title: _htmlTitle,
3114
+ ...restPropsWithoutHtmlAttrs
3115
+ } = props;
3116
+ const {
3117
+ inputProps,
3118
+ isSelected,
3119
+ isDisabled: radioIsDisabled
3120
+ } = useRadio(
3121
+ {
3122
+ ...restPropsWithoutHtmlAttrs,
3123
+ value: props.value
3124
+ },
3125
+ state,
3126
+ ref
3127
+ );
3128
+ const { isFocusVisible, focusProps } = useFocusRing();
3129
+ const finalIsDisabled = isDisabled || radioIsDisabled;
3130
+ const visualState = isSelected ? "selected" : "unselected";
3131
+ const { onMouseDown: handleRipple, ripples } = useRipple({
3132
+ disabled: finalIsDisabled || disableRipple
3133
+ });
3134
+ if (process.env.NODE_ENV === "development") {
3135
+ const ariaProps = restPropsWithoutHtmlAttrs;
3136
+ if (!children && !ariaProps["aria-label"] && !ariaProps["aria-labelledby"]) {
3137
+ console.warn(
3138
+ "[Radio] Radio should have a label (children) or aria-label for accessibility."
3139
+ );
3140
+ }
3141
+ }
3142
+ const isInvalid = state.validationState === "invalid";
3143
+ return /* @__PURE__ */ jsxs(
3144
+ "label",
3145
+ {
3146
+ className: cn(
3147
+ radioVariants({
3148
+ disabled: finalIsDisabled
3149
+ }),
3150
+ className
3151
+ ),
3152
+ "data-testid": dataTestId,
3153
+ title: htmlTitle,
3154
+ children: [
3155
+ /* @__PURE__ */ jsx(VisuallyHidden, { children: /* @__PURE__ */ jsx("input", { ...mergeProps(inputProps, focusProps), ref, id: htmlId }) }),
3156
+ /* @__PURE__ */ jsxs(
3157
+ "div",
3158
+ {
3159
+ role: "presentation",
3160
+ className: cn(
3161
+ radioContainerVariants({
3162
+ state: visualState,
3163
+ isInvalid,
3164
+ disabled: finalIsDisabled
3165
+ })
3166
+ ),
3167
+ onMouseDown: handleRipple,
3168
+ children: [
3169
+ ripples,
3170
+ /* @__PURE__ */ jsxs(
3171
+ "svg",
3172
+ {
3173
+ width: "20",
3174
+ height: "20",
3175
+ viewBox: "0 0 20 20",
3176
+ "aria-hidden": "true",
3177
+ className: "relative z-10",
3178
+ children: [
3179
+ /* @__PURE__ */ jsx(
3180
+ "circle",
3181
+ {
3182
+ cx: "10",
3183
+ cy: "10",
3184
+ r: "9",
3185
+ className: cn(
3186
+ radioIconOuterVariants({
3187
+ state: visualState,
3188
+ disabled: finalIsDisabled
3189
+ })
3190
+ )
3191
+ }
3192
+ ),
3193
+ /* @__PURE__ */ jsx(
3194
+ "circle",
3195
+ {
3196
+ cx: "10",
3197
+ cy: "10",
3198
+ r: "5",
3199
+ className: cn(
3200
+ radioIconInnerVariants({
3201
+ visible: isSelected
3202
+ })
3203
+ ),
3204
+ style: { fill: "var(--color-on-primary)" }
3205
+ }
3206
+ ),
3207
+ isFocusVisible && /* @__PURE__ */ jsx(
3208
+ "circle",
3209
+ {
3210
+ cx: "10",
3211
+ cy: "10",
3212
+ r: "13",
3213
+ fill: "none",
3214
+ stroke: "currentColor",
3215
+ strokeWidth: "2",
3216
+ className: "animate-pulse"
3217
+ }
3218
+ )
3219
+ ]
3220
+ }
3221
+ )
3222
+ ]
3223
+ }
3224
+ ),
3225
+ children && /* @__PURE__ */ jsx(
3226
+ "span",
3227
+ {
3228
+ className: cn(
3229
+ radioLabelVariants({
3230
+ disabled: finalIsDisabled
3231
+ })
3232
+ ),
3233
+ children
3234
+ }
3235
+ )
3236
+ ]
3237
+ }
3238
+ );
3239
+ }
3240
+ );
3241
+ Radio.displayName = "Radio";
3242
+ var RadioGroup = forwardRef(
3243
+ ({
3244
+ // Content props
3245
+ children,
3246
+ // State props
3247
+ orientation = "vertical",
3248
+ isInvalid = false,
3249
+ isDisabled = false,
3250
+ // Styling
3251
+ className,
3252
+ // Other props
3253
+ ...props
3254
+ }, ref) => {
3255
+ const htmlAttrs = props;
3256
+ const dataTestId = htmlAttrs["data-testid"];
3257
+ const { "data-testid": _dataTestId, ...restPropsWithoutHtmlAttrs } = props;
3258
+ if (process.env.NODE_ENV === "development") {
3259
+ const ariaProps = restPropsWithoutHtmlAttrs;
3260
+ if (!ariaProps.label && !ariaProps["aria-label"] && !ariaProps["aria-labelledby"]) {
3261
+ console.warn(
3262
+ "[RadioGroup] RadioGroup should have a label or aria-label for accessibility."
3263
+ );
3264
+ }
3265
+ }
3266
+ return /* @__PURE__ */ jsx(
3267
+ RadioGroupHeadless,
3268
+ {
3269
+ ...restPropsWithoutHtmlAttrs,
3270
+ isDisabled,
3271
+ ref,
3272
+ className: cn("flex flex-col", className),
3273
+ "data-testid": dataTestId,
3274
+ renderLabel: (labelProps) => /* @__PURE__ */ jsx(
3275
+ "div",
3276
+ {
3277
+ ...labelProps,
3278
+ className: cn(
3279
+ radioGroupLabelVariants({
3280
+ disabled: isDisabled
3281
+ })
3282
+ ),
3283
+ children: props.label
3284
+ }
3285
+ ),
3286
+ children: /* @__PURE__ */ jsx(
3287
+ "div",
3288
+ {
3289
+ className: cn(
3290
+ radioGroupVariants({
3291
+ orientation,
3292
+ disabled: isDisabled
3293
+ })
3294
+ ),
3295
+ children
3296
+ }
3297
+ )
3298
+ }
3299
+ );
3300
+ }
3301
+ );
3302
+ RadioGroup.displayName = "RadioGroup";
3303
+ var RadioHeadless = forwardRef(
3304
+ ({ className, children, renderRadio, ...props }, forwardedRef) => {
3305
+ const state = useContext(RadioGroupContext);
3306
+ if (!state) {
3307
+ throw new Error("RadioHeadless must be used within a RadioGroupHeadless");
3308
+ }
3309
+ const internalRef = useRef(null);
3310
+ const ref = forwardedRef ?? internalRef;
3311
+ const { inputProps, isSelected, isDisabled, isPressed } = useRadio(props, state, ref);
3312
+ const { isFocusVisible, focusProps } = useFocusRing();
3313
+ return /* @__PURE__ */ jsxs("label", { className, children: [
3314
+ /* @__PURE__ */ jsx("input", { ...inputProps, ...focusProps, ref }),
3315
+ renderRadio?.({
3316
+ isSelected,
3317
+ isDisabled,
3318
+ isFocusVisible,
3319
+ isPressed
3320
+ }),
3321
+ children
3322
+ ] });
3323
+ }
3324
+ );
3325
+ RadioHeadless.displayName = "RadioHeadless";
3326
+
3327
+ export { Button, Checkbox, FAB, FABHeadless, IconButton, IconButtonHeadless, Radio, RadioGroup, RadioGroupHeadless, RadioHeadless, STATE_LAYER_OPACITY, Switch, TYPOGRAPHY_ELEMENT_MAP, TYPOGRAPHY_USAGE, TextField, applyStateLayer, cn, generateMD3Theme, getColorValue, getFontFamily, getMD3Color, getResponsiveTypography, getTypographyClassName, getTypographyForElement, getTypographyStyle, getTypographyToken, hexToRgb, pxToRem, remToPx, rgbToHex, truncateText, withOpacity };
3328
+ //# sourceMappingURL=index.js.map
3329
+ //# sourceMappingURL=index.js.map