@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/LICENSE +21 -0
- package/README.md +378 -0
- package/dist/index.cjs +3374 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1836 -0
- package/dist/index.d.ts +1836 -0
- package/dist/index.js +3329 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.css +213 -0
- package/dist/styles.css.map +1 -0
- package/dist/styles.d.cts +2 -0
- package/dist/styles.d.ts +2 -0
- package/package.json +118 -0
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
|