@aurora-ds/components 1.0.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/esm/index.js CHANGED
@@ -1,185 +1,303 @@
1
1
  import { jsx, jsxs, Fragment as Fragment$1 } from 'react/jsx-runtime';
2
- import { createVariants, createStyles, useTheme, keyframes, cx, createTheme } from '@aurora-ds/theme';
2
+ import { keyframes, createVariants, createStyles, useTheme, cx, createTheme } from '@aurora-ds/theme';
3
3
  import * as React from 'react';
4
4
  import { createElement, Fragment, useRef, useState, useCallback, useEffect, useId, isValidElement, cloneElement, useLayoutEffect, useMemo, createContext, useContext } from 'react';
5
5
  import { createPortal } from 'react-dom';
6
6
 
7
- const BADGE_VARIANTS_LIST = ['filled', 'outlined', 'subtle', 'subtleOutlined'];
8
- /**
9
- * Builds compound variants combining `variant` × `color` for the Badge.
10
- * Returns one entry per (color, variant) pair with static color styles.
11
- */
12
- const buildBadgeCompoundVariants = (theme) => {
7
+ function _extends$8() { return _extends$8 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$8.apply(null, arguments); }
8
+ const AlertErrorIcon = props => /*#__PURE__*/React.createElement("svg", _extends$8({
9
+ xmlns: "http://www.w3.org/2000/svg",
10
+ width: 24,
11
+ height: 24,
12
+ fill: "none",
13
+ stroke: "currentColor",
14
+ strokeLinecap: "round",
15
+ strokeLinejoin: "round",
16
+ strokeWidth: 2
17
+ }, props), /*#__PURE__*/React.createElement("circle", {
18
+ cx: 12,
19
+ cy: 12,
20
+ r: 10
21
+ }), /*#__PURE__*/React.createElement("path", {
22
+ d: "m15 9-6 6M9 9l6 6"
23
+ }));
24
+
25
+ function _extends$7() { return _extends$7 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$7.apply(null, arguments); }
26
+ const AlertInfoIcon = props => /*#__PURE__*/React.createElement("svg", _extends$7({
27
+ xmlns: "http://www.w3.org/2000/svg",
28
+ width: 24,
29
+ height: 24,
30
+ fill: "none",
31
+ stroke: "currentColor",
32
+ strokeLinecap: "round",
33
+ strokeLinejoin: "round",
34
+ strokeWidth: 2
35
+ }, props), /*#__PURE__*/React.createElement("circle", {
36
+ cx: 12,
37
+ cy: 12,
38
+ r: 10
39
+ }), /*#__PURE__*/React.createElement("path", {
40
+ d: "M12 16v-4M12 8h.01"
41
+ }));
42
+
43
+ function _extends$6() { return _extends$6 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$6.apply(null, arguments); }
44
+ const AlertSuccessIcon = props => /*#__PURE__*/React.createElement("svg", _extends$6({
45
+ xmlns: "http://www.w3.org/2000/svg",
46
+ width: 24,
47
+ height: 24,
48
+ fill: "none",
49
+ stroke: "currentColor",
50
+ strokeLinecap: "round",
51
+ strokeLinejoin: "round",
52
+ strokeWidth: 2
53
+ }, props), /*#__PURE__*/React.createElement("circle", {
54
+ cx: 12,
55
+ cy: 12,
56
+ r: 10
57
+ }), /*#__PURE__*/React.createElement("path", {
58
+ d: "m9 12 2 2 4-4"
59
+ }));
60
+
61
+ function _extends$5() { return _extends$5 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$5.apply(null, arguments); }
62
+ const AlertWarningIcon = props => /*#__PURE__*/React.createElement("svg", _extends$5({
63
+ xmlns: "http://www.w3.org/2000/svg",
64
+ width: 24,
65
+ height: 24,
66
+ fill: "none",
67
+ stroke: "currentColor",
68
+ strokeLinecap: "round",
69
+ strokeLinejoin: "round",
70
+ strokeWidth: 2
71
+ }, props), /*#__PURE__*/React.createElement("path", {
72
+ d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3M12 9v4M12 17h.01"
73
+ }));
74
+
75
+ function _extends$4() { return _extends$4 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$4.apply(null, arguments); }
76
+ const ChevronDownIcon = props => /*#__PURE__*/React.createElement("svg", _extends$4({
77
+ xmlns: "http://www.w3.org/2000/svg",
78
+ width: 24,
79
+ height: 24,
80
+ fill: "none",
81
+ stroke: "currentColor",
82
+ strokeLinecap: "round",
83
+ strokeLinejoin: "round",
84
+ strokeWidth: 2,
85
+ className: "prefix__lucide prefix__lucide-chevron-down-icon prefix__lucide-chevron-down"
86
+ }, props), /*#__PURE__*/React.createElement("path", {
87
+ d: "m6 9 6 6 6-6"
88
+ }));
89
+
90
+ function _extends$3() { return _extends$3 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$3.apply(null, arguments); }
91
+ const CloseIcon = props => /*#__PURE__*/React.createElement("svg", _extends$3({
92
+ xmlns: "http://www.w3.org/2000/svg",
93
+ fill: "none",
94
+ stroke: "currentColor",
95
+ strokeLinecap: "round",
96
+ strokeLinejoin: "round",
97
+ strokeWidth: 2,
98
+ "aria-hidden": "true",
99
+ viewBox: "0 0 24 24"
100
+ }, props), /*#__PURE__*/React.createElement("path", {
101
+ d: "M18 6 6 18M6 6l12 12"
102
+ }));
103
+
104
+ function _extends$2() { return _extends$2 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$2.apply(null, arguments); }
105
+ const EyeIcon = props => /*#__PURE__*/React.createElement("svg", _extends$2({
106
+ xmlns: "http://www.w3.org/2000/svg",
107
+ width: 24,
108
+ height: 24,
109
+ fill: "none",
110
+ stroke: "currentColor",
111
+ strokeLinecap: "round",
112
+ strokeLinejoin: "round",
113
+ strokeWidth: 2,
114
+ className: "prefix__lucide prefix__lucide-eye-icon prefix__lucide-eye"
115
+ }, props), /*#__PURE__*/React.createElement("path", {
116
+ d: "M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0"
117
+ }), /*#__PURE__*/React.createElement("circle", {
118
+ cx: 12,
119
+ cy: 12,
120
+ r: 3
121
+ }));
122
+
123
+ function _extends$1() { return _extends$1 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$1.apply(null, arguments); }
124
+ const EyeSlashIcon = props => /*#__PURE__*/React.createElement("svg", _extends$1({
125
+ xmlns: "http://www.w3.org/2000/svg",
126
+ width: 24,
127
+ height: 24,
128
+ fill: "none",
129
+ stroke: "currentColor",
130
+ strokeLinecap: "round",
131
+ strokeLinejoin: "round",
132
+ strokeWidth: 2,
133
+ className: "prefix__lucide prefix__lucide-eye-off-icon prefix__lucide-eye-off"
134
+ }, props), /*#__PURE__*/React.createElement("path", {
135
+ d: "M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.8 10.8 0 0 1-1.444 2.49M14.084 14.158a3 3 0 0 1-4.242-4.242"
136
+ }), /*#__PURE__*/React.createElement("path", {
137
+ d: "M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143M2 2l20 20"
138
+ }));
139
+
140
+ function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
141
+ const SpinnerIcon = props => /*#__PURE__*/React.createElement("svg", _extends({
142
+ xmlns: "http://www.w3.org/2000/svg",
143
+ fill: "none",
144
+ viewBox: "0 0 24 24"
145
+ }, props), /*#__PURE__*/React.createElement("circle", {
146
+ cx: 12,
147
+ cy: 12,
148
+ r: 10,
149
+ stroke: "currentColor",
150
+ strokeWidth: 2,
151
+ opacity: 0.25
152
+ }), /*#__PURE__*/React.createElement("path", {
153
+ stroke: "currentColor",
154
+ strokeLinecap: "round",
155
+ strokeWidth: 2,
156
+ d: "M12 2a10 10 0 0 1 10 10"
157
+ }));
158
+
159
+ const IconRegistry = {
160
+ AlertInfoIcon};
161
+
162
+ const spinAnimation = keyframes({
163
+ '0%': { transform: 'rotate(0deg)' },
164
+ '100%': { transform: 'rotate(360deg)' },
165
+ });
166
+ const skeletonShimmerAnimation = keyframes({
167
+ '0%': { backgroundPosition: '100% 50%' },
168
+ '100%': { backgroundPosition: '0% 50%' },
169
+ });
170
+
171
+ const APPEARANCES = ['contained', 'outlined', 'text'];
172
+ const buildActionButtonVariantBase = (theme) => ({
173
+ position: 'relative',
174
+ display: 'inline-flex',
175
+ alignItems: 'center',
176
+ justifyContent: 'center',
177
+ boxSizing: 'border-box',
178
+ border: '1px solid transparent',
179
+ borderRadius: theme.radius.md,
180
+ fontFamily: 'inherit',
181
+ userSelect: 'none',
182
+ cursor: 'pointer',
183
+ outline: 'none',
184
+ transition: `background-color ${theme.transition.fast}, border-color ${theme.transition.fast}, color ${theme.transition.fast}, box-shadow ${theme.transition.fast}`,
185
+ ':focus-visible': { boxShadow: theme.shadows.focus },
186
+ ':disabled': { cursor: 'not-allowed', opacity: theme.opacity.high, boxShadow: 'none' },
187
+ });
188
+ const buildActionButtonCompoundVariants = (theme) => {
13
189
  const c = theme.colors;
14
190
  const intents = {
15
- default: {
16
- bg: c.defaultMain,
17
- on: c.textInverse,
18
- fg: c.defaultMain,
19
- fgStrong: c.defaultHover,
20
- subtle: c.defaultSubtle,
21
- border: c.defaultMain,
22
- },
23
191
  primary: {
24
- bg: c.primaryMain,
25
- on: c.primaryOn,
26
- fg: c.primaryMain,
27
- fgStrong: c.primaryHover,
28
- subtle: c.primarySubtle,
29
- border: c.primaryMain,
192
+ main: c.primaryMain, hover: c.primaryHover, active: c.primaryActive,
193
+ on: c.primaryOn, subtle: c.primarySubtle, subtleHover: c.primarySubtleHover, subtleActive: c.primarySubtleActive,
194
+ fg: c.primaryMain, fgHover: c.primaryHover, border: c.primaryMain,
30
195
  },
31
196
  secondary: {
32
- bg: c.secondaryMain,
33
- on: c.secondaryOn,
34
- fg: c.secondaryOn,
35
- fgStrong: c.secondaryOn,
36
- subtle: c.secondarySubtle,
37
- border: c.borderStrong,
38
- },
39
- success: {
40
- bg: c.successMain,
41
- on: c.successOn,
42
- fg: c.successMain,
43
- fgStrong: c.successHover,
44
- subtle: c.successSubtle,
45
- border: c.successMain,
46
- },
47
- warning: {
48
- bg: c.warningMain,
49
- on: c.warningOn,
50
- fg: c.warningMain,
51
- fgStrong: c.warningHover,
52
- subtle: c.warningSubtle,
53
- border: c.warningMain,
197
+ main: c.secondaryMain, hover: c.secondaryHover, active: c.secondaryActive,
198
+ on: c.secondaryOn, subtle: c.secondarySubtle, subtleHover: c.secondarySubtleHover, subtleActive: c.secondarySubtleActive,
199
+ fg: c.secondaryOn, fgHover: c.secondaryOn, border: c.borderStrong,
54
200
  },
55
- error: {
56
- bg: c.errorMain,
57
- on: c.errorOn,
58
- fg: c.errorMain,
59
- fgStrong: c.errorHover,
60
- subtle: c.errorSubtle,
61
- border: c.errorMain,
201
+ neutral: {
202
+ main: c.defaultMain, hover: c.defaultHover, active: c.defaultActive,
203
+ on: c.textInverse, subtle: c.defaultSubtle, subtleHover: c.defaultSubtleHover, subtleActive: c.defaultSubtleActive,
204
+ fg: c.defaultMain, fgHover: c.defaultHover, border: c.defaultMain,
62
205
  },
63
206
  info: {
64
- bg: c.infoMain,
65
- on: c.infoOn,
66
- fg: c.infoMain,
67
- fgStrong: c.infoHover,
68
- subtle: c.infoSubtle,
69
- border: c.infoMain,
207
+ main: c.infoMain, hover: c.infoHover, active: c.infoActive,
208
+ on: c.infoOn, subtle: c.infoSubtle, subtleHover: c.infoSubtleHover, subtleActive: c.infoSubtleActive,
209
+ fg: c.infoMain, fgHover: c.infoHover, border: c.infoMain,
70
210
  },
71
- orange: {
72
- bg: c.orangeMain,
73
- on: c.orangeOn,
74
- fg: c.orangeMain,
75
- fgStrong: c.orangeHover,
76
- subtle: c.orangeSubtle,
77
- border: c.orangeMain,
211
+ success: {
212
+ main: c.successMain, hover: c.successHover, active: c.successActive,
213
+ on: c.successOn, subtle: c.successSubtle, subtleHover: c.successSubtleHover, subtleActive: c.successSubtleActive,
214
+ fg: c.successMain, fgHover: c.successHover, border: c.successMain,
78
215
  },
79
- pink: {
80
- bg: c.pinkMain,
81
- on: c.pinkOn,
82
- fg: c.pinkMain,
83
- fgStrong: c.pinkHover,
84
- subtle: c.pinkSubtle,
85
- border: c.pinkMain,
216
+ warning: {
217
+ main: c.warningMain, hover: c.warningHover, active: c.warningActive,
218
+ on: c.warningOn, subtle: c.warningSubtle, subtleHover: c.warningSubtleHover, subtleActive: c.warningSubtleActive,
219
+ fg: c.warningMain, fgHover: c.warningHover, border: c.warningMain,
86
220
  },
87
- violet: {
88
- bg: c.violetMain,
89
- on: c.violetOn,
90
- fg: c.violetMain,
91
- fgStrong: c.violetHover,
92
- subtle: c.violetSubtle,
93
- border: c.violetMain,
221
+ error: {
222
+ main: c.errorMain, hover: c.errorHover, active: c.errorActive,
223
+ on: c.errorOn, subtle: c.errorSubtle, subtleHover: c.errorSubtleHover, subtleActive: c.errorSubtleActive,
224
+ fg: c.errorMain, fgHover: c.errorHover, border: c.errorMain,
94
225
  },
95
226
  };
96
- const getColorStyles = (intent, appearance) => {
97
- if (appearance === 'filled') {
227
+ const appearanceStyles = (intent, appearance) => {
228
+ if (appearance === 'contained') {
98
229
  return {
99
- backgroundColor: intent.bg,
100
- borderColor: intent.bg,
230
+ backgroundColor: intent.main,
231
+ borderColor: intent.main,
101
232
  color: intent.on,
233
+ boxShadow: theme.shadows.xs,
234
+ ':hover:not(:disabled)': { backgroundColor: intent.hover, borderColor: intent.hover, boxShadow: theme.shadows.sm },
235
+ ':active:not(:disabled)': { backgroundColor: intent.active, borderColor: intent.active, boxShadow: theme.shadows.none },
102
236
  };
103
237
  }
104
238
  if (appearance === 'outlined') {
105
239
  return {
106
240
  backgroundColor: 'transparent',
107
241
  borderColor: intent.border,
108
- color: intent.fgStrong,
109
- };
110
- }
111
- if (appearance === 'subtleOutlined') {
112
- return {
113
- backgroundColor: intent.subtle,
114
- borderColor: intent.border,
115
- color: intent.fgStrong,
242
+ color: intent.fg,
243
+ ':hover:not(:disabled)': { backgroundColor: intent.subtleHover, color: intent.fgHover },
244
+ ':active:not(:disabled)': { backgroundColor: intent.subtleActive, borderColor: intent.active, color: intent.active },
116
245
  };
117
246
  }
118
- // subtle
119
247
  return {
120
- backgroundColor: intent.subtle,
248
+ backgroundColor: 'transparent',
121
249
  borderColor: 'transparent',
122
- color: intent.fgStrong,
250
+ color: intent.fg,
251
+ ':hover:not(:disabled)': { backgroundColor: intent.subtleHover, color: intent.fgHover },
252
+ ':active:not(:disabled)': { backgroundColor: intent.subtleActive, color: intent.active },
123
253
  };
124
254
  };
125
- return Object.keys(intents).flatMap((color) => BADGE_VARIANTS_LIST.map((variant) => ({
255
+ return Object.keys(intents).flatMap((color) => APPEARANCES.map((appearance) => ({
126
256
  color,
127
- variant,
128
- styles: getColorStyles(intents[color], variant),
257
+ variant: appearance,
258
+ styles: appearanceStyles(intents[color], appearance),
129
259
  })));
130
260
  };
131
261
 
132
- const BADGE_VARIANTS = createVariants((theme) => ({
133
- base: {
262
+ const BUTTON_VARIANTS = createVariants((theme) => ({
263
+ base: buildActionButtonVariantBase(theme),
264
+ variants: {
265
+ size: {
266
+ sm: { height: '2rem', padding: `0 ${theme.spacing.sm}`, fontSize: theme.fontSize.xs },
267
+ md: { height: '2.5rem', padding: `0 ${theme.spacing.md}`, fontSize: theme.fontSize.sm },
268
+ lg: { height: '3rem', padding: `0 ${theme.spacing.lg}`, fontSize: theme.fontSize.md },
269
+ },
270
+ // Appearance/color styling is provided entirely by compoundVariants.
271
+ variant: { contained: {}, outlined: {}, text: {} },
272
+ color: { primary: {}, secondary: {}, neutral: {}, info: {}, success: {}, warning: {}, error: {} },
273
+ },
274
+ defaultVariants: { size: 'md', variant: 'contained', color: 'primary' },
275
+ compoundVariants: buildActionButtonCompoundVariants(theme),
276
+ }), { id: 'button' });
277
+ const BUTTON_STYLES = createStyles({
278
+ /** Inner wrapper holding icons + label, centered by the button. */
279
+ content: {
134
280
  display: 'inline-flex',
135
281
  alignItems: 'center',
136
282
  justifyContent: 'center',
137
- gap: theme.spacing.xs,
138
- boxSizing: 'border-box',
139
- borderRadius: theme.radius.full,
140
- border: '1px solid transparent',
141
- fontFamily: 'inherit',
142
- fontWeight: theme.fontWeight.medium,
143
- lineHeight: theme.lineHeight.none,
144
- whiteSpace: 'nowrap',
145
- userSelect: 'none',
283
+ gap: '0.5em',
146
284
  },
147
- variants: {
148
- size: {
149
- sm: {
150
- height: '1.25rem',
151
- padding: `0.125rem ${theme.spacing['xs+']}`,
152
- fontSize: theme.fontSize['2xs'],
153
- },
154
- md: {
155
- height: '1.5rem',
156
- padding: `0.1875rem ${theme.spacing.sm}`,
157
- fontSize: theme.fontSize.xs,
158
- },
159
- lg: {
160
- height: '2rem',
161
- padding: `0.25rem ${theme.spacing.md}`,
162
- fontSize: theme.fontSize.sm,
163
- },
164
- },
165
- // Appearance and color styling is handled entirely by compoundVariants.
166
- variant: { filled: {}, outlined: {}, subtle: {}, subtleOutlined: {} },
167
- color: {
168
- default: {},
169
- primary: {},
170
- secondary: {},
171
- success: {},
172
- warning: {},
173
- error: {},
174
- info: {},
175
- orange: {},
176
- pink: {},
177
- violet: {},
178
- },
285
+ /** Hidden (but keeps width) while loading. */
286
+ contentHidden: { visibility: 'hidden' },
287
+ /** Centers the spinner icon over the button content while loading. */
288
+ spinnerWrap: {
289
+ position: 'absolute',
290
+ inset: 0,
291
+ display: 'inline-flex',
292
+ alignItems: 'center',
293
+ justifyContent: 'center',
179
294
  },
180
- defaultVariants: { size: 'md', variant: 'subtle', color: 'default' },
181
- compoundVariants: buildBadgeCompoundVariants(theme),
182
- }), { id: 'badge' });
295
+ /** Spinning animation applied to the SpinnerIcon wrapper. */
296
+ spinnerIcon: {
297
+ animation: `${spinAnimation} 0.75s linear infinite`,
298
+ '@media (prefers-reduced-motion: reduce)': { animation: 'none' },
299
+ },
300
+ }, { id: 'button-extra' });
183
301
 
184
302
  const ICON_STYLES = createStyles((theme) => ({
185
303
  root: ({ size, strokeColor, fill, backgroundColor, padding, borderRadius }) => ({
@@ -401,39 +519,370 @@ const Text = ({ ref, children, variant = 'span', as, color, fontSize, fontWeight
401
519
  const generatedClassName = TEXT_STYLES.root({
402
520
  variant,
403
521
  color,
404
- fontSize,
405
- fontWeight,
406
- lineHeight,
407
- fontFamily,
408
- underline,
409
- strikethrough,
410
- italic,
411
- noWrap: effectiveLines ? false : noWrap,
412
- preserveWhitespace,
413
- width,
414
- textTransform,
415
- letterSpacing,
416
- textAlign,
417
- });
418
- const mergedClassName = className ? `${generatedClassName} ${className}` : generatedClassName;
419
- const mergedStyle = truncateStyles ? { ...truncateStyles, ...style } : style;
420
- return createElement(tag, {
421
- ref,
422
- className: mergedClassName,
423
- style: mergedStyle,
424
- ...(tag === 'label' && htmlFor !== undefined ? { htmlFor } : {}),
425
- ...rest,
426
- }, parsedChildren);
522
+ fontSize,
523
+ fontWeight,
524
+ lineHeight,
525
+ fontFamily,
526
+ underline,
527
+ strikethrough,
528
+ italic,
529
+ noWrap: effectiveLines ? false : noWrap,
530
+ preserveWhitespace,
531
+ width,
532
+ textTransform,
533
+ letterSpacing,
534
+ textAlign,
535
+ });
536
+ const mergedClassName = className ? `${generatedClassName} ${className}` : generatedClassName;
537
+ const mergedStyle = truncateStyles ? { ...truncateStyles, ...style } : style;
538
+ return createElement(tag, {
539
+ ref,
540
+ className: mergedClassName,
541
+ style: mergedStyle,
542
+ ...(tag === 'label' && htmlFor !== undefined ? { htmlFor } : {}),
543
+ ...rest,
544
+ }, parsedChildren);
545
+ };
546
+
547
+ /** Maps the button size to a Text font-size token so the label scales with the button. */
548
+ const LABEL_FONT_SIZE$1 = {
549
+ sm: 'xs',
550
+ md: 'sm',
551
+ lg: 'md',
552
+ };
553
+ /** Maps the button size to an Icon size token. */
554
+ const ICON_SIZE$2 = {
555
+ sm: 'sm',
556
+ md: 'md',
557
+ lg: 'lg',
558
+ };
559
+ /**
560
+ * Theme-aware button built on `createVariants`.
561
+ *
562
+ * @example <Button onClick={save}>Save</Button>
563
+ * @example <Button variant='outlined' color='error' startIcon={IconRegistry.CloseIcon}>Delete</Button>
564
+ * @example <Button color='success' isLoading width='100%'>Submitting…</Button>
565
+ */
566
+ const Button = ({ ref, variant = 'contained', color = 'primary', size = 'md', width, flexGrow, flexShrink, isLoading = false, startIcon: StartIcon, endIcon: EndIcon, children, className, type = 'button', disabled, style, ...rest }) => {
567
+ const isDisabled = disabled || isLoading;
568
+ const iconSize = ICON_SIZE$2[size];
569
+ const rootClassName = BUTTON_VARIANTS({ variant, color, size }, className);
570
+ const mergedStyle = {
571
+ ...style,
572
+ ...(width !== undefined ? { width } : {}),
573
+ ...(flexGrow !== undefined ? { flexGrow } : {}),
574
+ ...(flexShrink !== undefined ? { flexShrink } : {}),
575
+ };
576
+ return (jsxs("button", { ref: ref, type: type, className: rootClassName, disabled: isDisabled, "aria-busy": isLoading || undefined, style: mergedStyle, ...rest, children: [isLoading && (jsx("span", { className: BUTTON_STYLES.spinnerWrap, children: jsx(Icon, { icon: SpinnerIcon, size: iconSize, className: BUTTON_STYLES.spinnerIcon }) })), jsxs("span", { className: cx(BUTTON_STYLES.content, isLoading && BUTTON_STYLES.contentHidden), children: [StartIcon && (jsx(Icon, { icon: StartIcon, size: iconSize })), children !== undefined && children !== null && (jsx(Text, { variant: 'span', fontSize: LABEL_FONT_SIZE$1[size], fontWeight: 'medium', lineHeight: 'none', children: children })), EndIcon && (jsx(Icon, { icon: EndIcon, size: iconSize }))] })] }));
577
+ };
578
+ Button.displayName = 'Button';
579
+
580
+ const ICON_BUTTON_VARIANTS = createVariants((theme) => ({
581
+ base: buildActionButtonVariantBase(theme),
582
+ variants: {
583
+ size: {
584
+ sm: { width: '2rem', height: '2rem', padding: '0' },
585
+ md: { width: '2.5rem', height: '2.5rem', padding: '0' },
586
+ lg: { width: '3rem', height: '3rem', padding: '0' },
587
+ },
588
+ variant: { contained: {}, outlined: {}, text: {} },
589
+ color: { primary: {}, secondary: {}, neutral: {}, info: {}, success: {}, warning: {}, error: {} },
590
+ },
591
+ defaultVariants: { size: 'md', variant: 'contained', color: 'primary' },
592
+ compoundVariants: buildActionButtonCompoundVariants(theme),
593
+ }), { id: 'icon-button' });
594
+ const ICON_BUTTON_STYLES = createStyles({
595
+ /** Spinning animation applied to the SpinnerIcon. */
596
+ spinnerIcon: {
597
+ animation: `${spinAnimation} 0.75s linear infinite`,
598
+ '@media (prefers-reduced-motion: reduce)': { animation: 'none' },
599
+ },
600
+ /** Hidden (but keeps size) while loading. */
601
+ iconHidden: { visibility: 'hidden' },
602
+ /** Centers the spinner icon absolutely over the button while loading. */
603
+ spinnerWrap: {
604
+ position: 'absolute',
605
+ inset: 0,
606
+ display: 'inline-flex',
607
+ alignItems: 'center',
608
+ justifyContent: 'center',
609
+ },
610
+ }, { id: 'icon-button-extra' });
611
+
612
+ /** Maps the icon-button size to an Icon size token. */
613
+ const ICON_SIZE$1 = {
614
+ sm: 'sm',
615
+ md: 'md',
616
+ lg: 'lg',
617
+ };
618
+ /**
619
+ * Square icon-only button.
620
+ * `ariaLabel` is mandatory since there is no visible text.
621
+ *
622
+ * @example <IconButton icon={CloseIcon} ariaLabel={t('common.close')} />
623
+ * @example <IconButton icon={DeleteIcon} ariaLabel={t('actions.delete')} variant='outlined' color='error' />
624
+ * @example <IconButton icon={SaveIcon} ariaLabel={t('actions.save')} isLoading />
625
+ */
626
+ const IconButton = ({ ref, icon: IconComponent, ariaLabel, variant = 'contained', color = 'primary', size = 'md', isLoading = false, className, type = 'button', disabled, ...rest }) => {
627
+ const isDisabled = disabled || isLoading;
628
+ const iconSize = ICON_SIZE$1[size];
629
+ const rootClassName = ICON_BUTTON_VARIANTS({ variant, color, size }, className);
630
+ return (jsxs("button", { ref: ref, type: type, className: rootClassName, disabled: isDisabled, "aria-label": ariaLabel, "aria-busy": isLoading || undefined, ...rest, children: [isLoading && (jsx("span", { className: ICON_BUTTON_STYLES.spinnerWrap, children: jsx(Icon, { icon: SpinnerIcon, size: iconSize, className: ICON_BUTTON_STYLES.spinnerIcon }) })), jsx(Icon, { icon: IconComponent, size: iconSize, className: cx(isLoading && ICON_BUTTON_STYLES.iconHidden) })] }));
631
+ };
632
+ IconButton.displayName = 'IconButton';
633
+
634
+ const LINK_STYLES = createStyles((theme) => ({
635
+ root: ({ underline = 'hover' }) => ({
636
+ display: 'inline-flex',
637
+ alignItems: 'center',
638
+ gap: '0.25em',
639
+ color: theme.colors.linkMain,
640
+ fontFamily: 'inherit',
641
+ fontSize: 'inherit',
642
+ lineHeight: 'inherit',
643
+ fontWeight: 'inherit',
644
+ textDecoration: underline === 'always' ? 'underline' : 'none',
645
+ cursor: 'pointer',
646
+ borderRadius: theme.radius.xs,
647
+ transition: `color ${theme.transition.fast}`,
648
+ ':hover:not([aria-disabled="true"])': {
649
+ color: theme.colors.linkHover,
650
+ textDecoration: underline !== 'none' ? 'underline' : 'none',
651
+ },
652
+ ':active:not([aria-disabled="true"])': {
653
+ color: theme.colors.linkActive,
654
+ },
655
+ ':focus-visible': {
656
+ outline: `2px solid ${theme.colors.linkMain}`,
657
+ outlineOffset: '2px',
658
+ },
659
+ '&[aria-disabled="true"]': {
660
+ color: theme.colors.linkDisabled,
661
+ cursor: 'not-allowed',
662
+ textDecoration: 'none',
663
+ },
664
+ }),
665
+ icon: {
666
+ display: 'inline-flex',
667
+ alignItems: 'center',
668
+ flexShrink: 0,
669
+ width: '1em',
670
+ height: '1em',
671
+ },
672
+ }), { id: 'link' });
673
+
674
+ /**
675
+ * Theme-aware anchor element with optional icons and underline control.
676
+ *
677
+ * @example <Link href='/about'>About</Link>
678
+ * @example <Link href='https://example.com' external>External site</Link>
679
+ * @example <Link href='/profile' underline='always' startIcon={UserIcon}>Profile</Link>
680
+ * @example <Link href='/terms' underline='none'>Terms</Link>
681
+ */
682
+ const Link = ({ ref, underline = 'hover', external = false, disabled = false, startIcon: StartIcon, endIcon: EndIcon, children, className, onClick, onKeyDown, ...rest }) => {
683
+ const handleClick = (e) => {
684
+ if (disabled) {
685
+ e.preventDefault();
686
+ return;
687
+ }
688
+ onClick?.(e);
689
+ };
690
+ // Prevents Enter navigation when disabled; satisfies jsx-a11y/click-events-have-key-events.
691
+ const handleKeyDown = (e) => {
692
+ if (disabled && e.key === 'Enter') {
693
+ e.preventDefault();
694
+ }
695
+ onKeyDown?.(e);
696
+ };
697
+ return (jsxs("a", { ref: ref, className: cx(LINK_STYLES.root({ underline }), className), "aria-disabled": disabled || undefined, tabIndex: disabled ? -1 : undefined, target: external ? '_blank' : undefined, rel: external ? 'noopener noreferrer' : undefined, onClick: handleClick, onKeyDown: handleKeyDown, ...rest, children: [StartIcon && (jsx("span", { className: LINK_STYLES.icon, "aria-hidden": true, children: jsx(StartIcon, { width: '1em', height: '1em' }) })), children, EndIcon && (jsx("span", { className: LINK_STYLES.icon, "aria-hidden": true, children: jsx(EndIcon, { width: '1em', height: '1em' }) }))] }));
698
+ };
699
+ Link.displayName = 'Link';
700
+
701
+ const BADGE_VARIANTS_LIST = ['filled', 'outlined', 'subtle', 'subtleOutlined'];
702
+ /**
703
+ * Builds compound variants combining `variant` × `color` for the Badge.
704
+ * Returns one entry per (color, variant) pair with static color styles.
705
+ */
706
+ const buildBadgeCompoundVariants = (theme) => {
707
+ const c = theme.colors;
708
+ const intents = {
709
+ default: {
710
+ bg: c.defaultMain,
711
+ on: c.textInverse,
712
+ fg: c.defaultMain,
713
+ fgStrong: c.defaultHover,
714
+ subtle: c.defaultSubtle,
715
+ border: c.defaultMain,
716
+ },
717
+ primary: {
718
+ bg: c.primaryMain,
719
+ on: c.primaryOn,
720
+ fg: c.primaryMain,
721
+ fgStrong: c.primaryHover,
722
+ subtle: c.primarySubtle,
723
+ border: c.primaryMain,
724
+ },
725
+ secondary: {
726
+ bg: c.secondaryMain,
727
+ on: c.secondaryOn,
728
+ fg: c.secondaryOn,
729
+ fgStrong: c.secondaryOn,
730
+ subtle: c.secondarySubtle,
731
+ border: c.borderStrong,
732
+ },
733
+ success: {
734
+ bg: c.successMain,
735
+ on: c.successOn,
736
+ fg: c.successMain,
737
+ fgStrong: c.successHover,
738
+ subtle: c.successSubtle,
739
+ border: c.successMain,
740
+ },
741
+ warning: {
742
+ bg: c.warningMain,
743
+ on: c.warningOn,
744
+ fg: c.warningMain,
745
+ fgStrong: c.warningHover,
746
+ subtle: c.warningSubtle,
747
+ border: c.warningMain,
748
+ },
749
+ error: {
750
+ bg: c.errorMain,
751
+ on: c.errorOn,
752
+ fg: c.errorMain,
753
+ fgStrong: c.errorHover,
754
+ subtle: c.errorSubtle,
755
+ border: c.errorMain,
756
+ },
757
+ info: {
758
+ bg: c.infoMain,
759
+ on: c.infoOn,
760
+ fg: c.infoMain,
761
+ fgStrong: c.infoHover,
762
+ subtle: c.infoSubtle,
763
+ border: c.infoMain,
764
+ },
765
+ orange: {
766
+ bg: c.orangeMain,
767
+ on: c.orangeOn,
768
+ fg: c.orangeMain,
769
+ fgStrong: c.orangeHover,
770
+ subtle: c.orangeSubtle,
771
+ border: c.orangeMain,
772
+ },
773
+ pink: {
774
+ bg: c.pinkMain,
775
+ on: c.pinkOn,
776
+ fg: c.pinkMain,
777
+ fgStrong: c.pinkHover,
778
+ subtle: c.pinkSubtle,
779
+ border: c.pinkMain,
780
+ },
781
+ violet: {
782
+ bg: c.violetMain,
783
+ on: c.violetOn,
784
+ fg: c.violetMain,
785
+ fgStrong: c.violetHover,
786
+ subtle: c.violetSubtle,
787
+ border: c.violetMain,
788
+ },
789
+ };
790
+ const getColorStyles = (intent, appearance) => {
791
+ if (appearance === 'filled') {
792
+ return {
793
+ backgroundColor: intent.bg,
794
+ borderColor: intent.bg,
795
+ color: intent.on,
796
+ };
797
+ }
798
+ if (appearance === 'outlined') {
799
+ return {
800
+ backgroundColor: 'transparent',
801
+ borderColor: intent.border,
802
+ color: intent.fgStrong,
803
+ };
804
+ }
805
+ if (appearance === 'subtleOutlined') {
806
+ return {
807
+ backgroundColor: intent.subtle,
808
+ borderColor: intent.border,
809
+ color: intent.fgStrong,
810
+ };
811
+ }
812
+ // subtle
813
+ return {
814
+ backgroundColor: intent.subtle,
815
+ borderColor: 'transparent',
816
+ color: intent.fgStrong,
817
+ };
818
+ };
819
+ return Object.keys(intents).flatMap((color) => BADGE_VARIANTS_LIST.map((variant) => ({
820
+ color,
821
+ variant,
822
+ styles: getColorStyles(intents[color], variant),
823
+ })));
427
824
  };
428
825
 
826
+ const BADGE_VARIANTS = createVariants((theme) => ({
827
+ base: {
828
+ display: 'inline-flex',
829
+ alignItems: 'center',
830
+ justifyContent: 'center',
831
+ gap: theme.spacing.xs,
832
+ boxSizing: 'border-box',
833
+ borderRadius: theme.radius.full,
834
+ border: '1px solid transparent',
835
+ fontFamily: 'inherit',
836
+ fontWeight: theme.fontWeight.medium,
837
+ lineHeight: theme.lineHeight.none,
838
+ whiteSpace: 'nowrap',
839
+ userSelect: 'none',
840
+ },
841
+ variants: {
842
+ size: {
843
+ sm: {
844
+ height: '1.25rem',
845
+ padding: `0.125rem ${theme.spacing['xs+']}`,
846
+ fontSize: theme.fontSize['2xs'],
847
+ },
848
+ md: {
849
+ height: '1.5rem',
850
+ padding: `0.1875rem ${theme.spacing.sm}`,
851
+ fontSize: theme.fontSize.xs,
852
+ },
853
+ lg: {
854
+ height: '2rem',
855
+ padding: `0.25rem ${theme.spacing.md}`,
856
+ fontSize: theme.fontSize.sm,
857
+ },
858
+ },
859
+ // Appearance and color styling is handled entirely by compoundVariants.
860
+ variant: { filled: {}, outlined: {}, subtle: {}, subtleOutlined: {} },
861
+ color: {
862
+ default: {},
863
+ primary: {},
864
+ secondary: {},
865
+ success: {},
866
+ warning: {},
867
+ error: {},
868
+ info: {},
869
+ orange: {},
870
+ pink: {},
871
+ violet: {},
872
+ },
873
+ },
874
+ defaultVariants: { size: 'md', variant: 'subtle', color: 'default' },
875
+ compoundVariants: buildBadgeCompoundVariants(theme),
876
+ }), { id: 'badge' });
877
+
429
878
  /** Maps badge size to an Icon size token. */
430
- const ICON_SIZE$2 = {
879
+ const ICON_SIZE = {
431
880
  sm: 'xs',
432
881
  md: 'xs',
433
882
  lg: 'sm',
434
883
  };
435
884
  /** Maps badge size to a Text font-size token. */
436
- const LABEL_FONT_SIZE$1 = {
885
+ const LABEL_FONT_SIZE = {
437
886
  sm: '2xs',
438
887
  md: 'xs',
439
888
  lg: 'sm',
@@ -468,7 +917,7 @@ const Badge = ({ ref, variant = 'subtle', color = 'default', size = 'md', border
468
917
  };
469
918
  return (jsx("span", { ref: ref, className: rootClassName, style: { ...dotStyle, ...style }, "aria-hidden": true, ...rest }));
470
919
  }
471
- return (jsxs("span", { ref: ref, className: rootClassName, style: { ...(resolvedBorderRadius ? { borderRadius: resolvedBorderRadius } : {}), ...style }, ...rest, children: [effectiveStartIcon && (jsx(Icon, { icon: effectiveStartIcon, size: ICON_SIZE$2[size] })), children !== undefined && children !== null && (jsx(Text, { variant: 'span', fontSize: LABEL_FONT_SIZE$1[size], fontWeight: 'medium', lineHeight: 'none', children: children })), EndIcon && (jsx(Icon, { icon: EndIcon, size: ICON_SIZE$2[size] }))] }));
920
+ return (jsxs("span", { ref: ref, className: rootClassName, style: { ...(resolvedBorderRadius ? { borderRadius: resolvedBorderRadius } : {}), ...style }, ...rest, children: [effectiveStartIcon && (jsx(Icon, { icon: effectiveStartIcon, size: ICON_SIZE[size] })), children !== undefined && children !== null && (jsx(Text, { variant: 'span', fontSize: LABEL_FONT_SIZE[size], fontWeight: 'medium', lineHeight: 'none', children: children })), EndIcon && (jsx(Icon, { icon: EndIcon, size: ICON_SIZE[size] }))] }));
472
921
  };
473
922
  Badge.displayName = 'Badge';
474
923
 
@@ -706,163 +1155,8 @@ const INFO_BUBBLE_STYLES = createStyles((theme) => ({
706
1155
  ':focus-visible': {
707
1156
  boxShadow: theme.shadows.focus,
708
1157
  },
709
- },
710
- }));
711
-
712
- function _extends$8() { return _extends$8 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$8.apply(null, arguments); }
713
- const AlertErrorIcon = props => /*#__PURE__*/React.createElement("svg", _extends$8({
714
- xmlns: "http://www.w3.org/2000/svg",
715
- width: 24,
716
- height: 24,
717
- fill: "none",
718
- stroke: "currentColor",
719
- strokeLinecap: "round",
720
- strokeLinejoin: "round",
721
- strokeWidth: 2
722
- }, props), /*#__PURE__*/React.createElement("circle", {
723
- cx: 12,
724
- cy: 12,
725
- r: 10
726
- }), /*#__PURE__*/React.createElement("path", {
727
- d: "m15 9-6 6M9 9l6 6"
728
- }));
729
-
730
- function _extends$7() { return _extends$7 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$7.apply(null, arguments); }
731
- const AlertInfoIcon = props => /*#__PURE__*/React.createElement("svg", _extends$7({
732
- xmlns: "http://www.w3.org/2000/svg",
733
- width: 24,
734
- height: 24,
735
- fill: "none",
736
- stroke: "currentColor",
737
- strokeLinecap: "round",
738
- strokeLinejoin: "round",
739
- strokeWidth: 2
740
- }, props), /*#__PURE__*/React.createElement("circle", {
741
- cx: 12,
742
- cy: 12,
743
- r: 10
744
- }), /*#__PURE__*/React.createElement("path", {
745
- d: "M12 16v-4M12 8h.01"
746
- }));
747
-
748
- function _extends$6() { return _extends$6 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$6.apply(null, arguments); }
749
- const AlertSuccessIcon = props => /*#__PURE__*/React.createElement("svg", _extends$6({
750
- xmlns: "http://www.w3.org/2000/svg",
751
- width: 24,
752
- height: 24,
753
- fill: "none",
754
- stroke: "currentColor",
755
- strokeLinecap: "round",
756
- strokeLinejoin: "round",
757
- strokeWidth: 2
758
- }, props), /*#__PURE__*/React.createElement("circle", {
759
- cx: 12,
760
- cy: 12,
761
- r: 10
762
- }), /*#__PURE__*/React.createElement("path", {
763
- d: "m9 12 2 2 4-4"
764
- }));
765
-
766
- function _extends$5() { return _extends$5 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$5.apply(null, arguments); }
767
- const AlertWarningIcon = props => /*#__PURE__*/React.createElement("svg", _extends$5({
768
- xmlns: "http://www.w3.org/2000/svg",
769
- width: 24,
770
- height: 24,
771
- fill: "none",
772
- stroke: "currentColor",
773
- strokeLinecap: "round",
774
- strokeLinejoin: "round",
775
- strokeWidth: 2
776
- }, props), /*#__PURE__*/React.createElement("path", {
777
- d: "m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3M12 9v4M12 17h.01"
778
- }));
779
-
780
- function _extends$4() { return _extends$4 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$4.apply(null, arguments); }
781
- const ChevronDownIcon = props => /*#__PURE__*/React.createElement("svg", _extends$4({
782
- xmlns: "http://www.w3.org/2000/svg",
783
- width: 24,
784
- height: 24,
785
- fill: "none",
786
- stroke: "currentColor",
787
- strokeLinecap: "round",
788
- strokeLinejoin: "round",
789
- strokeWidth: 2,
790
- className: "prefix__lucide prefix__lucide-chevron-down-icon prefix__lucide-chevron-down"
791
- }, props), /*#__PURE__*/React.createElement("path", {
792
- d: "m6 9 6 6 6-6"
793
- }));
794
-
795
- function _extends$3() { return _extends$3 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$3.apply(null, arguments); }
796
- const CloseIcon = props => /*#__PURE__*/React.createElement("svg", _extends$3({
797
- xmlns: "http://www.w3.org/2000/svg",
798
- fill: "none",
799
- stroke: "currentColor",
800
- strokeLinecap: "round",
801
- strokeLinejoin: "round",
802
- strokeWidth: 2,
803
- "aria-hidden": "true",
804
- viewBox: "0 0 24 24"
805
- }, props), /*#__PURE__*/React.createElement("path", {
806
- d: "M18 6 6 18M6 6l12 12"
807
- }));
808
-
809
- function _extends$2() { return _extends$2 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$2.apply(null, arguments); }
810
- const EyeIcon = props => /*#__PURE__*/React.createElement("svg", _extends$2({
811
- xmlns: "http://www.w3.org/2000/svg",
812
- width: 24,
813
- height: 24,
814
- fill: "none",
815
- stroke: "currentColor",
816
- strokeLinecap: "round",
817
- strokeLinejoin: "round",
818
- strokeWidth: 2,
819
- className: "prefix__lucide prefix__lucide-eye-icon prefix__lucide-eye"
820
- }, props), /*#__PURE__*/React.createElement("path", {
821
- d: "M2.062 12.348a1 1 0 0 1 0-.696 10.75 10.75 0 0 1 19.876 0 1 1 0 0 1 0 .696 10.75 10.75 0 0 1-19.876 0"
822
- }), /*#__PURE__*/React.createElement("circle", {
823
- cx: 12,
824
- cy: 12,
825
- r: 3
826
- }));
827
-
828
- function _extends$1() { return _extends$1 = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends$1.apply(null, arguments); }
829
- const EyeSlashIcon = props => /*#__PURE__*/React.createElement("svg", _extends$1({
830
- xmlns: "http://www.w3.org/2000/svg",
831
- width: 24,
832
- height: 24,
833
- fill: "none",
834
- stroke: "currentColor",
835
- strokeLinecap: "round",
836
- strokeLinejoin: "round",
837
- strokeWidth: 2,
838
- className: "prefix__lucide prefix__lucide-eye-off-icon prefix__lucide-eye-off"
839
- }, props), /*#__PURE__*/React.createElement("path", {
840
- d: "M10.733 5.076a10.744 10.744 0 0 1 11.205 6.575 1 1 0 0 1 0 .696 10.8 10.8 0 0 1-1.444 2.49M14.084 14.158a3 3 0 0 1-4.242-4.242"
841
- }), /*#__PURE__*/React.createElement("path", {
842
- d: "M17.479 17.499a10.75 10.75 0 0 1-15.417-5.151 1 1 0 0 1 0-.696 10.75 10.75 0 0 1 4.446-5.143M2 2l20 20"
843
- }));
844
-
845
- function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
846
- const SpinnerIcon = props => /*#__PURE__*/React.createElement("svg", _extends({
847
- xmlns: "http://www.w3.org/2000/svg",
848
- fill: "none",
849
- viewBox: "0 0 24 24"
850
- }, props), /*#__PURE__*/React.createElement("circle", {
851
- cx: 12,
852
- cy: 12,
853
- r: 10,
854
- stroke: "currentColor",
855
- strokeWidth: 2,
856
- opacity: 0.25
857
- }), /*#__PURE__*/React.createElement("path", {
858
- stroke: "currentColor",
859
- strokeLinecap: "round",
860
- strokeWidth: 2,
861
- d: "M12 2a10 10 0 0 1 10 10"
862
- }));
863
-
864
- const IconRegistry = {
865
- AlertInfoIcon};
1158
+ },
1159
+ }));
866
1160
 
867
1161
  /**
868
1162
  * InfoBubble
@@ -886,232 +1180,68 @@ const InfoBubble = ({ label, placement = 'top', width = 200, withArrow = true, }
886
1180
  };
887
1181
  InfoBubble.displayName = 'InfoBubble';
888
1182
 
889
- const spinAnimation = keyframes({
890
- '0%': { transform: 'rotate(0deg)' },
891
- '100%': { transform: 'rotate(360deg)' },
892
- });
893
- keyframes({
894
- '0%': { backgroundPosition: '100% 50%' },
895
- '100%': { backgroundPosition: '0% 50%' },
896
- });
897
-
898
- const APPEARANCES = ['contained', 'outlined', 'text'];
899
- const buildActionButtonVariantBase = (theme) => ({
900
- position: 'relative',
901
- display: 'inline-flex',
902
- alignItems: 'center',
903
- justifyContent: 'center',
904
- boxSizing: 'border-box',
905
- border: '1px solid transparent',
906
- borderRadius: theme.radius.md,
907
- fontFamily: 'inherit',
908
- userSelect: 'none',
909
- cursor: 'pointer',
910
- outline: 'none',
911
- transition: `background-color ${theme.transition.fast}, border-color ${theme.transition.fast}, color ${theme.transition.fast}, box-shadow ${theme.transition.fast}`,
912
- ':focus-visible': { boxShadow: theme.shadows.focus },
913
- ':disabled': { cursor: 'not-allowed', opacity: theme.opacity.high, boxShadow: 'none' },
914
- });
915
- const buildActionButtonCompoundVariants = (theme) => {
916
- const c = theme.colors;
917
- const intents = {
918
- primary: {
919
- main: c.primaryMain, hover: c.primaryHover, active: c.primaryActive,
920
- on: c.primaryOn, subtle: c.primarySubtle, subtleHover: c.primarySubtleHover, subtleActive: c.primarySubtleActive,
921
- fg: c.primaryMain, fgHover: c.primaryHover, border: c.primaryMain,
922
- },
923
- secondary: {
924
- main: c.secondaryMain, hover: c.secondaryHover, active: c.secondaryActive,
925
- on: c.secondaryOn, subtle: c.secondarySubtle, subtleHover: c.secondarySubtleHover, subtleActive: c.secondarySubtleActive,
926
- fg: c.secondaryOn, fgHover: c.secondaryOn, border: c.borderStrong,
927
- },
928
- neutral: {
929
- main: c.defaultMain, hover: c.defaultHover, active: c.defaultActive,
930
- on: c.textInverse, subtle: c.defaultSubtle, subtleHover: c.defaultSubtleHover, subtleActive: c.defaultSubtleActive,
931
- fg: c.defaultMain, fgHover: c.defaultHover, border: c.defaultMain,
932
- },
933
- info: {
934
- main: c.infoMain, hover: c.infoHover, active: c.infoActive,
935
- on: c.infoOn, subtle: c.infoSubtle, subtleHover: c.infoSubtleHover, subtleActive: c.infoSubtleActive,
936
- fg: c.infoMain, fgHover: c.infoHover, border: c.infoMain,
937
- },
938
- success: {
939
- main: c.successMain, hover: c.successHover, active: c.successActive,
940
- on: c.successOn, subtle: c.successSubtle, subtleHover: c.successSubtleHover, subtleActive: c.successSubtleActive,
941
- fg: c.successMain, fgHover: c.successHover, border: c.successMain,
942
- },
943
- warning: {
944
- main: c.warningMain, hover: c.warningHover, active: c.warningActive,
945
- on: c.warningOn, subtle: c.warningSubtle, subtleHover: c.warningSubtleHover, subtleActive: c.warningSubtleActive,
946
- fg: c.warningMain, fgHover: c.warningHover, border: c.warningMain,
947
- },
948
- error: {
949
- main: c.errorMain, hover: c.errorHover, active: c.errorActive,
950
- on: c.errorOn, subtle: c.errorSubtle, subtleHover: c.errorSubtleHover, subtleActive: c.errorSubtleActive,
951
- fg: c.errorMain, fgHover: c.errorHover, border: c.errorMain,
952
- },
953
- };
954
- const appearanceStyles = (intent, appearance) => {
955
- if (appearance === 'contained') {
956
- return {
957
- backgroundColor: intent.main,
958
- borderColor: intent.main,
959
- color: intent.on,
960
- boxShadow: theme.shadows.xs,
961
- ':hover:not(:disabled)': { backgroundColor: intent.hover, borderColor: intent.hover, boxShadow: theme.shadows.sm },
962
- ':active:not(:disabled)': { backgroundColor: intent.active, borderColor: intent.active, boxShadow: theme.shadows.none },
963
- };
964
- }
965
- if (appearance === 'outlined') {
966
- return {
967
- backgroundColor: 'transparent',
968
- borderColor: intent.border,
969
- color: intent.fg,
970
- ':hover:not(:disabled)': { backgroundColor: intent.subtleHover, color: intent.fgHover },
971
- ':active:not(:disabled)': { backgroundColor: intent.subtleActive, borderColor: intent.active, color: intent.active },
972
- };
973
- }
974
- return {
975
- backgroundColor: 'transparent',
976
- borderColor: 'transparent',
977
- color: intent.fg,
978
- ':hover:not(:disabled)': { backgroundColor: intent.subtleHover, color: intent.fgHover },
979
- ':active:not(:disabled)': { backgroundColor: intent.subtleActive, color: intent.active },
980
- };
981
- };
982
- return Object.keys(intents).flatMap((color) => APPEARANCES.map((appearance) => ({
983
- color,
984
- variant: appearance,
985
- styles: appearanceStyles(intents[color], appearance),
986
- })));
987
- };
988
-
989
- const BUTTON_VARIANTS = createVariants((theme) => ({
990
- base: buildActionButtonVariantBase(theme),
991
- variants: {
992
- size: {
993
- sm: { height: '2rem', padding: `0 ${theme.spacing.sm}`, fontSize: theme.fontSize.xs },
994
- md: { height: '2.5rem', padding: `0 ${theme.spacing.md}`, fontSize: theme.fontSize.sm },
995
- lg: { height: '3rem', padding: `0 ${theme.spacing.lg}`, fontSize: theme.fontSize.md },
996
- },
997
- // Appearance/color styling is provided entirely by compoundVariants.
998
- variant: { contained: {}, outlined: {}, text: {} },
999
- color: { primary: {}, secondary: {}, neutral: {}, info: {}, success: {}, warning: {}, error: {} },
1000
- },
1001
- defaultVariants: { size: 'md', variant: 'contained', color: 'primary' },
1002
- compoundVariants: buildActionButtonCompoundVariants(theme),
1003
- }), { id: 'button' });
1004
- const BUTTON_STYLES = createStyles({
1005
- /** Inner wrapper holding icons + label, centered by the button. */
1006
- content: {
1007
- display: 'inline-flex',
1008
- alignItems: 'center',
1009
- justifyContent: 'center',
1010
- gap: '0.5em',
1011
- },
1012
- /** Hidden (but keeps width) while loading. */
1013
- contentHidden: { visibility: 'hidden' },
1014
- /** Centers the spinner icon over the button content while loading. */
1015
- spinnerWrap: {
1016
- position: 'absolute',
1017
- inset: 0,
1018
- display: 'inline-flex',
1019
- alignItems: 'center',
1020
- justifyContent: 'center',
1021
- },
1022
- /** Spinning animation applied to the SpinnerIcon wrapper. */
1023
- spinnerIcon: {
1024
- animation: `${spinAnimation} 0.75s linear infinite`,
1025
- '@media (prefers-reduced-motion: reduce)': { animation: 'none' },
1183
+ const SKELETON_VARIANTS = createVariants((theme) => ({
1184
+ base: {
1185
+ display: 'block',
1186
+ boxSizing: 'border-box',
1187
+ backgroundColor: theme.colors.skeletonPrimary,
1188
+ overflow: 'hidden',
1026
1189
  },
1027
- }, { id: 'button-extra' });
1028
-
1029
- /** Maps the button size to a Text font-size token so the label scales with the button. */
1030
- const LABEL_FONT_SIZE = {
1031
- sm: 'xs',
1032
- md: 'sm',
1033
- lg: 'md',
1034
- };
1035
- /** Maps the button size to an Icon size token. */
1036
- const ICON_SIZE$1 = {
1037
- sm: 'sm',
1038
- md: 'md',
1039
- lg: 'lg',
1040
- };
1041
- /**
1042
- * Theme-aware button built on `createVariants`.
1043
- *
1044
- * @example <Button onClick={save}>Save</Button>
1045
- * @example <Button variant='outlined' color='error' startIcon={IconRegistry.CloseIcon}>Delete</Button>
1046
- * @example <Button color='success' isLoading width='100%'>Submitting…</Button>
1047
- */
1048
- const Button = ({ ref, variant = 'contained', color = 'primary', size = 'md', width, flexGrow, flexShrink, isLoading = false, startIcon: StartIcon, endIcon: EndIcon, children, className, type = 'button', disabled, style, ...rest }) => {
1049
- const isDisabled = disabled || isLoading;
1050
- const iconSize = ICON_SIZE$1[size];
1051
- const rootClassName = BUTTON_VARIANTS({ variant, color, size }, className);
1052
- const mergedStyle = {
1053
- ...style,
1054
- ...(width !== undefined ? { width } : {}),
1055
- ...(flexGrow !== undefined ? { flexGrow } : {}),
1056
- ...(flexShrink !== undefined ? { flexShrink } : {}),
1057
- };
1058
- return (jsxs("button", { ref: ref, type: type, className: rootClassName, disabled: isDisabled, "aria-busy": isLoading || undefined, style: mergedStyle, ...rest, children: [isLoading && (jsx("span", { className: BUTTON_STYLES.spinnerWrap, children: jsx(Icon, { icon: SpinnerIcon, size: iconSize, className: BUTTON_STYLES.spinnerIcon }) })), jsxs("span", { className: cx(BUTTON_STYLES.content, isLoading && BUTTON_STYLES.contentHidden), children: [StartIcon && (jsx(Icon, { icon: StartIcon, size: iconSize })), children !== undefined && children !== null && (jsx(Text, { variant: 'span', fontSize: LABEL_FONT_SIZE[size], fontWeight: 'medium', lineHeight: 'none', children: children })), EndIcon && (jsx(Icon, { icon: EndIcon, size: iconSize }))] })] }));
1059
- };
1060
- Button.displayName = 'Button';
1061
-
1062
- const ICON_BUTTON_VARIANTS = createVariants((theme) => ({
1063
- base: buildActionButtonVariantBase(theme),
1064
1190
  variants: {
1065
- size: {
1066
- sm: { width: '2rem', height: '2rem', padding: '0' },
1067
- md: { width: '2.5rem', height: '2.5rem', padding: '0' },
1068
- lg: { width: '3rem', height: '3rem', padding: '0' },
1191
+ variant: {
1192
+ /** Inline-text placeholder: em-relative height, slight vertical scale. */
1193
+ text: {
1194
+ borderRadius: theme.radius.sm,
1195
+ height: '1em',
1196
+ transform: 'scale(1, 0.6)',
1197
+ transformOrigin: '0 60%',
1198
+ width: '100%',
1199
+ },
1200
+ /** Fully rounded placeholder for avatars and icons. */
1201
+ circular: {
1202
+ borderRadius: theme.radius.full,
1203
+ },
1204
+ /** Sharp-cornered placeholder for images and media blocks. */
1205
+ rectangular: {
1206
+ borderRadius: '0',
1207
+ },
1208
+ /** Softly rounded placeholder for cards and chips. */
1209
+ rounded: {
1210
+ borderRadius: theme.radius.md,
1211
+ },
1212
+ },
1213
+ animation: {
1214
+ /** Sliding gradient highlight from right to left. */
1215
+ shimmer: {
1216
+ background: `linear-gradient(90deg, ${theme.colors.skeletonPrimary} 25%, ${theme.colors.skeletonSecondary} 50%, ${theme.colors.skeletonPrimary} 75%)`,
1217
+ backgroundSize: '400% 100%',
1218
+ animation: `${skeletonShimmerAnimation} 2.5s linear infinite`,
1219
+ '@media (prefers-reduced-motion: reduce)': { animation: 'none' },
1220
+ },
1221
+ /** No animation. */
1222
+ none: {},
1069
1223
  },
1070
- variant: { contained: {}, outlined: {}, text: {} },
1071
- color: { primary: {}, secondary: {}, neutral: {}, info: {}, success: {}, warning: {}, error: {} },
1072
- },
1073
- defaultVariants: { size: 'md', variant: 'contained', color: 'primary' },
1074
- compoundVariants: buildActionButtonCompoundVariants(theme),
1075
- }), { id: 'icon-button' });
1076
- const ICON_BUTTON_STYLES = createStyles({
1077
- /** Spinning animation applied to the SpinnerIcon. */
1078
- spinnerIcon: {
1079
- animation: `${spinAnimation} 0.75s linear infinite`,
1080
- '@media (prefers-reduced-motion: reduce)': { animation: 'none' },
1081
- },
1082
- /** Hidden (but keeps size) while loading. */
1083
- iconHidden: { visibility: 'hidden' },
1084
- /** Centers the spinner icon absolutely over the button while loading. */
1085
- spinnerWrap: {
1086
- position: 'absolute',
1087
- inset: 0,
1088
- display: 'inline-flex',
1089
- alignItems: 'center',
1090
- justifyContent: 'center',
1091
1224
  },
1092
- }, { id: 'icon-button-extra' });
1225
+ defaultVariants: { variant: 'rounded', animation: 'shimmer' },
1226
+ }), { id: 'skeleton' });
1093
1227
 
1094
- /** Maps the icon-button size to an Icon size token. */
1095
- const ICON_SIZE = {
1096
- sm: 'sm',
1097
- md: 'md',
1098
- lg: 'lg',
1099
- };
1100
1228
  /**
1101
- * Square icon-only button.
1102
- * `ariaLabel` is mandatory since there is no visible text.
1229
+ * Block-level placeholder rendered while content is loading.
1103
1230
  *
1104
- * @example <IconButton icon={CloseIcon} ariaLabel={t('common.close')} />
1105
- * @example <IconButton icon={DeleteIcon} ariaLabel={t('actions.delete')} variant='outlined' color='error' />
1106
- * @example <IconButton icon={SaveIcon} ariaLabel={t('actions.save')} isLoading />
1231
+ * @example // Text line
1232
+ * <Skeleton variant='text' width={200} />
1233
+ *
1234
+ * @example // Avatar
1235
+ * <Skeleton variant='circular' width={40} height={40} />
1236
+ *
1237
+ * @example // Card thumbnail
1238
+ * <Skeleton variant='rounded' width='100%' height={160} />
1239
+ *
1240
+ * @example // No animation
1241
+ * <Skeleton variant='rectangular' width='100%' height={80} animation={false} />
1107
1242
  */
1108
- const IconButton = ({ ref, icon: IconComponent, ariaLabel, variant = 'contained', color = 'primary', size = 'md', isLoading = false, className, type = 'button', disabled, ...rest }) => {
1109
- const isDisabled = disabled || isLoading;
1110
- const iconSize = ICON_SIZE[size];
1111
- const rootClassName = ICON_BUTTON_VARIANTS({ variant, color, size }, className);
1112
- return (jsxs("button", { ref: ref, type: type, className: rootClassName, disabled: isDisabled, "aria-label": ariaLabel, "aria-busy": isLoading || undefined, ...rest, children: [isLoading && (jsx("span", { className: ICON_BUTTON_STYLES.spinnerWrap, children: jsx(Icon, { icon: SpinnerIcon, size: iconSize, className: ICON_BUTTON_STYLES.spinnerIcon }) })), jsx(Icon, { icon: IconComponent, size: iconSize, className: cx(isLoading && ICON_BUTTON_STYLES.iconHidden) })] }));
1113
- };
1114
- IconButton.displayName = 'IconButton';
1243
+ const Skeleton = ({ ref, variant = 'rectangular', animation = 'shimmer', width, height, className, style, ...rest }) => (jsx("span", { ref: ref, className: SKELETON_VARIANTS({ variant, animation: animation === false ? 'none' : animation }, className), style: { width, height, ...style }, "aria-hidden": true, ...rest }));
1244
+ Skeleton.displayName = 'Skeleton';
1115
1245
 
1116
1246
  /**
1117
1247
  * Thin wrapper around `<form>`. Prevents the default browser submit and
@@ -2128,6 +2258,89 @@ const Select = ({ ref, value, defaultValue, onChange, options, label, helperText
2128
2258
  };
2129
2259
  Select.displayName = 'Select';
2130
2260
 
2261
+ const CARD_VARIANTS = createVariants((theme) => ({
2262
+ base: {
2263
+ boxSizing: 'border-box',
2264
+ borderRadius: theme.radius.lg,
2265
+ border: '1px solid transparent',
2266
+ },
2267
+ variants: {
2268
+ variant: {
2269
+ elevated: {
2270
+ backgroundColor: theme.colors.surfacePaper,
2271
+ boxShadow: theme.shadows.md,
2272
+ },
2273
+ outlined: {
2274
+ backgroundColor: theme.colors.surfacePaper,
2275
+ borderColor: theme.colors.borderMain,
2276
+ },
2277
+ },
2278
+ },
2279
+ defaultVariants: { variant: 'elevated' },
2280
+ }), { id: 'card' });
2281
+
2282
+ const CardHeader = ({ label, icon, actions }) => {
2283
+ return (jsxs(Stack, { alignItems: 'center', justifyContent: 'space-between', gap: 'sm', py: 'sm', px: 'md', children: [jsxs(Stack, { alignItems: 'center', gap: 'sm', flex: 1, minWidth: '0', children: [icon !== undefined && (jsx(Icon, { icon: icon, size: 'md', strokeColor: 'textSecondary' })), jsx(Text, { variant: 'span', fontSize: 'sm', fontWeight: 'semibold', color: 'textPrimary', children: label })] }), actions !== undefined && (jsx(Stack, { alignItems: 'center', gap: 'xs', flexShrink: 0, children: actions }))] }));
2284
+ };
2285
+ CardHeader.displayName = 'Card.Header';
2286
+
2287
+ const CardBody = ({ children, py = 'md', px = 'md', }) => {
2288
+ return (jsx(Box, { py: py, px: px, children: children }));
2289
+ };
2290
+ CardBody.displayName = 'Card.Body';
2291
+
2292
+ const CardBase = ({ ref, variant = 'outlined', className, children, ...rest }) => {
2293
+ return (jsx(Box, { ref: ref, className: cx(CARD_VARIANTS({ variant }), className), ...rest, children: children }));
2294
+ };
2295
+ CardBase.displayName = 'Card';
2296
+ const Card = CardBase;
2297
+ Card.Header = CardHeader;
2298
+ Card.Body = CardBody;
2299
+
2300
+ const GRID_STYLES = createStyles(() => ({
2301
+ root: ({ autoFlow, autoColumns, autoRows, alignContent, justifyItems, placeItems, placeContent, }) => ({
2302
+ ...(autoFlow !== undefined && { gridAutoFlow: autoFlow }),
2303
+ ...(autoColumns !== undefined && { gridAutoColumns: autoColumns }),
2304
+ ...(autoRows !== undefined && { gridAutoRows: autoRows }),
2305
+ ...(alignContent !== undefined && { alignContent }),
2306
+ ...(justifyItems !== undefined && { justifyItems }),
2307
+ ...(placeItems !== undefined && { placeItems }),
2308
+ ...(placeContent !== undefined && { placeContent }),
2309
+ }),
2310
+ }));
2311
+
2312
+ /**
2313
+ * A CSS Grid `Box` with convenience props for common grid patterns.
2314
+ *
2315
+ * Defaults to `display: grid`. The `columns` and `rows` shorthands accept either a
2316
+ * number (expanded to `repeat(n, 1fr)`) or any valid CSS `grid-template-*` string.
2317
+ * All `Box` style props remain available (`gap`, `rowGap`, `columnGap`,
2318
+ * `gridTemplateColumns`, `gridTemplateRows`, `alignItems`, `justifyContent`, …).
2319
+ *
2320
+ * @example <Grid columns={3} gap='md'>…</Grid>
2321
+ * @example <Grid columns='repeat(auto-fill, minmax(200px, 1fr))' gap='lg'>…</Grid>
2322
+ * @example <Grid rows={2} autoFlow='column' gap='sm' alignItems='center'>…</Grid>
2323
+ */
2324
+ const Grid = ({ display = 'grid', columns, rows, autoFlow, autoColumns, autoRows, alignContent, justifyItems, placeItems, placeContent, gridTemplateColumns, gridTemplateRows, className, rowGap = 'sm', columnGap = 'sm', ...rest }) => {
2325
+ const resolvedColumns = columns !== undefined
2326
+ ? (typeof columns === 'number' ? `repeat(${columns}, 1fr)` : columns)
2327
+ : gridTemplateColumns;
2328
+ const resolvedRows = rows !== undefined
2329
+ ? (typeof rows === 'number' ? `repeat(${rows}, 1fr)` : rows)
2330
+ : gridTemplateRows;
2331
+ const gridClassName = GRID_STYLES.root({
2332
+ autoFlow,
2333
+ autoColumns,
2334
+ autoRows,
2335
+ alignContent,
2336
+ justifyItems,
2337
+ placeItems,
2338
+ placeContent,
2339
+ });
2340
+ return (jsx(Box, { display: display, gridTemplateColumns: resolvedColumns, gridTemplateRows: resolvedRows, rowGap: rowGap, columnGap: columnGap, className: cx(gridClassName, className), ...rest }));
2341
+ };
2342
+ Grid.displayName = 'Grid';
2343
+
2131
2344
  const AlertContext = createContext({
2132
2345
  variant: 'default',
2133
2346
  accentColor: 'defaultActive',
@@ -2873,5 +3086,5 @@ const darkTheme = createTheme({
2873
3086
  breakpoints: themeBreakpoints,
2874
3087
  });
2875
3088
 
2876
- export { Alert, Badge, Button, Dialog, Form, Icon, IconButton, InfoBubble, Menu, Select, Switch, Text, TextField, Tooltip, darkTheme, lightTheme };
3089
+ export { Alert, Badge, Box, Button, Card, Dialog, Form, Grid, Icon, IconButton, InfoBubble, Link, Menu, Select, Skeleton, Stack, Switch, Text, TextField, Tooltip, darkTheme, lightTheme };
2877
3090
  //# sourceMappingURL=index.js.map