@aurora-ds/components 1.0.0 → 1.1.0

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