@bigtablet/design-system 1.24.0 → 1.24.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,11 +1,43 @@
1
1
  "use client";
2
2
  import './index.css';
3
- import * as React6 from 'react';
3
+ import * as React9 from 'react';
4
4
  import { createContext, useContext, useState, useCallback } from 'react';
5
5
  import { jsxs, jsx } from 'react/jsx-runtime';
6
6
  import { createPortal } from 'react-dom';
7
7
  import { ChevronDown, Check, X, Bell, Info, AlertTriangle, XCircle, CheckCircle2 } from 'lucide-react';
8
8
 
9
+ // src/styles/ts/a11y.ts
10
+ var a11y = {
11
+ focusRing: "0 0 0 3px rgba(0, 0, 0, 0.15)",
12
+ focusRingError: "0 0 0 3px rgba(239, 68, 68, 0.15)",
13
+ focusRingSuccess: "0 0 0 3px rgba(16, 185, 129, 0.15)",
14
+ tapMinSize: "44px"
15
+ };
16
+
17
+ // src/styles/ts/border-width.ts
18
+ var baseBorderWidth = {
19
+ "0": "0px",
20
+ "1": "1px",
21
+ "2": "2px"
22
+ };
23
+ var borderWidth = {
24
+ none: baseBorderWidth["0"],
25
+ standard: baseBorderWidth["1"],
26
+ indicator: baseBorderWidth["2"]
27
+ };
28
+
29
+ // src/styles/ts/breakpoints.ts
30
+ var breakpoints = {
31
+ compact: 0,
32
+ // mobile
33
+ medium: 600,
34
+ // tablet
35
+ expanded: 840,
36
+ // small desktop
37
+ large: 1200
38
+ // desktop
39
+ };
40
+
9
41
  // src/styles/ts/colors.ts
10
42
  var baseColors = {
11
43
  brandPrimary: "#121212",
@@ -72,6 +104,55 @@ var colors = {
72
104
  }
73
105
  };
74
106
 
107
+ // src/styles/ts/motion.ts
108
+ var motion = {
109
+ transition: {
110
+ fast: "0.1s ease-in-out",
111
+ base: "0.2s ease-in-out",
112
+ slow: "0.3s ease-in-out",
113
+ emphasized: "0.25s cubic-bezier(0.4, 0, 0.2, 1)",
114
+ bounce: "0.3s cubic-bezier(0.16, 1, 0.3, 1)",
115
+ fade: "0.15s ease-in-out",
116
+ slide: "0.25s ease-in-out",
117
+ scale: "0.2s cubic-bezier(0.2, 0.8, 0.2, 1)",
118
+ state: "0.18s ease-in-out"
119
+ }
120
+ };
121
+
122
+ // src/styles/ts/opacity.ts
123
+ var opacity = {
124
+ "0": 0,
125
+ "5": 0.05,
126
+ "8": 0.08,
127
+ "12": 0.12,
128
+ "16": 0.16,
129
+ "38": 0.38,
130
+ "50": 0.5,
131
+ "80": 0.8,
132
+ "90": 0.9,
133
+ "100": 1
134
+ };
135
+
136
+ // src/styles/ts/radius.ts
137
+ var radius = {
138
+ none: "0px",
139
+ xs: "4px",
140
+ sm: "6px",
141
+ md: "8px",
142
+ lg: "12px",
143
+ xl: "16px",
144
+ full: "9999px"
145
+ };
146
+
147
+ // src/styles/ts/shadows.ts
148
+ var shadows = {
149
+ level1: "0 1px 1px -1px rgba(0, 0, 0, 0.20), 0 3px 3px 0px rgba(0, 0, 0, 0.12)",
150
+ level2: "0 2px 2px -2px rgba(0, 0, 0, 0.20), 0 6px 6px 0px rgba(0, 0, 0, 0.12)",
151
+ level3: "0 3px 3px -3px rgba(0, 0, 0, 0.20), 0 9px 9px 0px rgba(0, 0, 0, 0.12)",
152
+ level4: "0 5px 5px -5px rgba(0, 0, 0, 0.20), 0 15px 15px 0px rgba(0, 0, 0, 0.12)",
153
+ level5: "0 8px 10px -5px rgba(0, 0, 0, 0.20), 0 20px 20px 0px rgba(0, 0, 0, 0.12)"
154
+ };
155
+
75
156
  // src/styles/ts/spacing.ts
76
157
  var spacing = {
77
158
  "0": "0px",
@@ -90,6 +171,32 @@ var spacing = {
90
171
  "48": "48px"
91
172
  };
92
173
 
174
+ // src/styles/ts/skeleton.ts
175
+ var skeleton = {
176
+ color: {
177
+ base: baseColors.neutral50,
178
+ wave: baseColors.neutral200,
179
+ highlight: baseColors.neutral0
180
+ },
181
+ gradient: `linear-gradient(90deg, ${baseColors.neutral50} 25%, ${baseColors.neutral0} 37%, ${baseColors.neutral200} 63%)`,
182
+ radius: {
183
+ sm: radius.sm,
184
+ md: radius.md,
185
+ lg: radius.lg
186
+ },
187
+ height: {
188
+ xs: spacing["4"],
189
+ sm: spacing["8"],
190
+ md: spacing["12"],
191
+ lg: spacing["16"],
192
+ xl: spacing["20"]
193
+ },
194
+ animation: {
195
+ duration: "1.4s",
196
+ timing: "ease-in-out"
197
+ }
198
+ };
199
+
93
200
  // src/styles/ts/typography.ts
94
201
  var baseTypography = {
95
202
  fontFamily: {
@@ -136,146 +243,197 @@ var typography = {
136
243
  primary: `'${baseTypography.fontFamily.primary}', sans-serif`
137
244
  },
138
245
  display: {
139
- large: { fontSize: fs["48"], fontWeight: fw.regular, lineHeight: lh["60"], letterSpacing: ls.normal },
140
- largeMedium: { fontSize: fs["48"], fontWeight: fw.medium, lineHeight: lh["60"], letterSpacing: ls.normal },
141
- medium: { fontSize: fs["40"], fontWeight: fw.regular, lineHeight: lh["50"], letterSpacing: ls.normal },
142
- mediumMedium: { fontSize: fs["40"], fontWeight: fw.medium, lineHeight: lh["50"], letterSpacing: ls.normal },
143
- small: { fontSize: fs["32"], fontWeight: fw.regular, lineHeight: lh["40"], letterSpacing: ls.normal },
144
- smallMedium: { fontSize: fs["32"], fontWeight: fw.medium, lineHeight: lh["40"], letterSpacing: ls.normal }
246
+ large: {
247
+ fontSize: fs["48"],
248
+ fontWeight: fw.regular,
249
+ lineHeight: lh["60"],
250
+ letterSpacing: ls.normal
251
+ },
252
+ largeMedium: {
253
+ fontSize: fs["48"],
254
+ fontWeight: fw.medium,
255
+ lineHeight: lh["60"],
256
+ letterSpacing: ls.normal
257
+ },
258
+ medium: {
259
+ fontSize: fs["40"],
260
+ fontWeight: fw.regular,
261
+ lineHeight: lh["50"],
262
+ letterSpacing: ls.normal
263
+ },
264
+ mediumMedium: {
265
+ fontSize: fs["40"],
266
+ fontWeight: fw.medium,
267
+ lineHeight: lh["50"],
268
+ letterSpacing: ls.normal
269
+ },
270
+ small: {
271
+ fontSize: fs["32"],
272
+ fontWeight: fw.regular,
273
+ lineHeight: lh["40"],
274
+ letterSpacing: ls.normal
275
+ },
276
+ smallMedium: {
277
+ fontSize: fs["32"],
278
+ fontWeight: fw.medium,
279
+ lineHeight: lh["40"],
280
+ letterSpacing: ls.normal
281
+ }
145
282
  },
146
283
  heading: {
147
- large: { fontSize: fs["28"], fontWeight: fw.regular, lineHeight: lh["36"], letterSpacing: ls.normal },
148
- largeMedium: { fontSize: fs["28"], fontWeight: fw.medium, lineHeight: lh["36"], letterSpacing: ls.normal },
149
- medium: { fontSize: fs["24"], fontWeight: fw.regular, lineHeight: lh["32"], letterSpacing: ls.normal },
150
- mediumMedium: { fontSize: fs["24"], fontWeight: fw.medium, lineHeight: lh["32"], letterSpacing: ls.normal },
151
- small: { fontSize: fs["20"], fontWeight: fw.regular, lineHeight: lh["28"], letterSpacing: ls.normal },
152
- smallMedium: { fontSize: fs["20"], fontWeight: fw.medium, lineHeight: lh["28"], letterSpacing: ls.normal }
284
+ large: {
285
+ fontSize: fs["28"],
286
+ fontWeight: fw.regular,
287
+ lineHeight: lh["36"],
288
+ letterSpacing: ls.normal
289
+ },
290
+ largeMedium: {
291
+ fontSize: fs["28"],
292
+ fontWeight: fw.medium,
293
+ lineHeight: lh["36"],
294
+ letterSpacing: ls.normal
295
+ },
296
+ medium: {
297
+ fontSize: fs["24"],
298
+ fontWeight: fw.regular,
299
+ lineHeight: lh["32"],
300
+ letterSpacing: ls.normal
301
+ },
302
+ mediumMedium: {
303
+ fontSize: fs["24"],
304
+ fontWeight: fw.medium,
305
+ lineHeight: lh["32"],
306
+ letterSpacing: ls.normal
307
+ },
308
+ small: {
309
+ fontSize: fs["20"],
310
+ fontWeight: fw.regular,
311
+ lineHeight: lh["28"],
312
+ letterSpacing: ls.normal
313
+ },
314
+ smallMedium: {
315
+ fontSize: fs["20"],
316
+ fontWeight: fw.medium,
317
+ lineHeight: lh["28"],
318
+ letterSpacing: ls.normal
319
+ }
153
320
  },
154
321
  title: {
155
- large: { fontSize: fs["18"], fontWeight: fw.regular, lineHeight: lh["24"], letterSpacing: ls.normal },
156
- largeMedium: { fontSize: fs["18"], fontWeight: fw.medium, lineHeight: lh["24"], letterSpacing: ls.normal },
157
- medium: { fontSize: fs["16"], fontWeight: fw.regular, lineHeight: lh["24"], letterSpacing: ls.normal },
158
- mediumMedium: { fontSize: fs["16"], fontWeight: fw.medium, lineHeight: lh["24"], letterSpacing: ls.normal },
159
- small: { fontSize: fs["14"], fontWeight: fw.regular, lineHeight: lh["20"], letterSpacing: ls.normal },
160
- smallMedium: { fontSize: fs["14"], fontWeight: fw.medium, lineHeight: lh["20"], letterSpacing: ls.normal }
322
+ large: {
323
+ fontSize: fs["18"],
324
+ fontWeight: fw.regular,
325
+ lineHeight: lh["24"],
326
+ letterSpacing: ls.normal
327
+ },
328
+ largeMedium: {
329
+ fontSize: fs["18"],
330
+ fontWeight: fw.medium,
331
+ lineHeight: lh["24"],
332
+ letterSpacing: ls.normal
333
+ },
334
+ medium: {
335
+ fontSize: fs["16"],
336
+ fontWeight: fw.regular,
337
+ lineHeight: lh["24"],
338
+ letterSpacing: ls.normal
339
+ },
340
+ mediumMedium: {
341
+ fontSize: fs["16"],
342
+ fontWeight: fw.medium,
343
+ lineHeight: lh["24"],
344
+ letterSpacing: ls.normal
345
+ },
346
+ small: {
347
+ fontSize: fs["14"],
348
+ fontWeight: fw.regular,
349
+ lineHeight: lh["20"],
350
+ letterSpacing: ls.normal
351
+ },
352
+ smallMedium: {
353
+ fontSize: fs["14"],
354
+ fontWeight: fw.medium,
355
+ lineHeight: lh["20"],
356
+ letterSpacing: ls.normal
357
+ }
161
358
  },
162
359
  body: {
163
- large: { fontSize: fs["16"], fontWeight: fw.regular, lineHeight: lh["24"], letterSpacing: ls.normal },
164
- largeMedium: { fontSize: fs["16"], fontWeight: fw.medium, lineHeight: lh["24"], letterSpacing: ls.normal },
165
- medium: { fontSize: fs["15"], fontWeight: fw.regular, lineHeight: lh["22-5"], letterSpacing: ls.normal },
166
- mediumMedium: { fontSize: fs["15"], fontWeight: fw.medium, lineHeight: lh["22-5"], letterSpacing: ls.normal },
167
- small: { fontSize: fs["14"], fontWeight: fw.regular, lineHeight: lh["20"], letterSpacing: ls.normal },
168
- smallMedium: { fontSize: fs["14"], fontWeight: fw.medium, lineHeight: lh["20"], letterSpacing: ls.normal }
360
+ large: {
361
+ fontSize: fs["16"],
362
+ fontWeight: fw.regular,
363
+ lineHeight: lh["24"],
364
+ letterSpacing: ls.normal
365
+ },
366
+ largeMedium: {
367
+ fontSize: fs["16"],
368
+ fontWeight: fw.medium,
369
+ lineHeight: lh["24"],
370
+ letterSpacing: ls.normal
371
+ },
372
+ medium: {
373
+ fontSize: fs["15"],
374
+ fontWeight: fw.regular,
375
+ lineHeight: lh["22-5"],
376
+ letterSpacing: ls.normal
377
+ },
378
+ mediumMedium: {
379
+ fontSize: fs["15"],
380
+ fontWeight: fw.medium,
381
+ lineHeight: lh["22-5"],
382
+ letterSpacing: ls.normal
383
+ },
384
+ small: {
385
+ fontSize: fs["14"],
386
+ fontWeight: fw.regular,
387
+ lineHeight: lh["20"],
388
+ letterSpacing: ls.normal
389
+ },
390
+ smallMedium: {
391
+ fontSize: fs["14"],
392
+ fontWeight: fw.medium,
393
+ lineHeight: lh["20"],
394
+ letterSpacing: ls.normal
395
+ }
169
396
  },
170
397
  label: {
171
- large: { fontSize: fs["14"], fontWeight: fw.regular, lineHeight: lh["20"], letterSpacing: ls.normal },
172
- largeMedium: { fontSize: fs["14"], fontWeight: fw.medium, lineHeight: lh["20"], letterSpacing: ls.normal },
173
- medium: { fontSize: fs["13"], fontWeight: fw.regular, lineHeight: lh["18"], letterSpacing: ls.normal },
174
- mediumMedium: { fontSize: fs["13"], fontWeight: fw.medium, lineHeight: lh["18"], letterSpacing: ls.normal },
175
- small: { fontSize: fs["12"], fontWeight: fw.regular, lineHeight: lh["16"], letterSpacing: ls.normal },
176
- smallMedium: { fontSize: fs["12"], fontWeight: fw.medium, lineHeight: lh["16"], letterSpacing: ls.normal }
177
- }
178
- };
179
-
180
- // src/styles/ts/radius.ts
181
- var radius = {
182
- none: "0px",
183
- xs: "4px",
184
- sm: "6px",
185
- md: "8px",
186
- lg: "12px",
187
- xl: "16px",
188
- full: "9999px"
189
- };
190
-
191
- // src/styles/ts/shadows.ts
192
- var shadows = {
193
- level1: "0 1px 1px -1px rgba(0, 0, 0, 0.20), 0 3px 3px 0px rgba(0, 0, 0, 0.12)",
194
- level2: "0 2px 2px -2px rgba(0, 0, 0, 0.20), 0 6px 6px 0px rgba(0, 0, 0, 0.12)",
195
- level3: "0 3px 3px -3px rgba(0, 0, 0, 0.20), 0 9px 9px 0px rgba(0, 0, 0, 0.12)",
196
- level4: "0 5px 5px -5px rgba(0, 0, 0, 0.20), 0 15px 15px 0px rgba(0, 0, 0, 0.12)",
197
- level5: "0 8px 10px -5px rgba(0, 0, 0, 0.20), 0 20px 20px 0px rgba(0, 0, 0, 0.12)"
198
- };
199
-
200
- // src/styles/ts/border-width.ts
201
- var baseBorderWidth = {
202
- "0": "0px",
203
- "1": "1px",
204
- "2": "2px"
205
- };
206
- var borderWidth = {
207
- none: baseBorderWidth["0"],
208
- standard: baseBorderWidth["1"],
209
- indicator: baseBorderWidth["2"]
210
- };
211
-
212
- // src/styles/ts/opacity.ts
213
- var opacity = {
214
- "0": 0,
215
- "5": 0.05,
216
- "8": 0.08,
217
- "12": 0.12,
218
- "16": 0.16,
219
- "38": 0.38,
220
- "50": 0.5,
221
- "80": 0.8,
222
- "90": 0.9,
223
- "100": 1
224
- };
225
-
226
- // src/styles/ts/motion.ts
227
- var motion = {
228
- transition: {
229
- fast: "0.1s ease-in-out",
230
- base: "0.2s ease-in-out",
231
- slow: "0.3s ease-in-out",
232
- emphasized: "0.25s cubic-bezier(0.4, 0, 0.2, 1)",
233
- bounce: "0.3s cubic-bezier(0.16, 1, 0.3, 1)",
234
- fade: "0.15s ease-in-out",
235
- slide: "0.25s ease-in-out",
236
- scale: "0.2s cubic-bezier(0.2, 0.8, 0.2, 1)",
237
- state: "0.18s ease-in-out"
238
- }
239
- };
240
-
241
- // src/styles/ts/skeleton.ts
242
- var skeleton = {
243
- color: {
244
- base: baseColors.neutral50,
245
- wave: baseColors.neutral200,
246
- highlight: baseColors.neutral0
247
- },
248
- gradient: `linear-gradient(90deg, ${baseColors.neutral50} 25%, ${baseColors.neutral0} 37%, ${baseColors.neutral200} 63%)`,
249
- radius: {
250
- sm: radius.sm,
251
- md: radius.md,
252
- lg: radius.lg
253
- },
254
- height: {
255
- xs: spacing["4"],
256
- sm: spacing["8"],
257
- md: spacing["12"],
258
- lg: spacing["16"],
259
- xl: spacing["20"]
260
- },
261
- animation: {
262
- duration: "1.4s",
263
- timing: "ease-in-out"
398
+ large: {
399
+ fontSize: fs["14"],
400
+ fontWeight: fw.regular,
401
+ lineHeight: lh["20"],
402
+ letterSpacing: ls.normal
403
+ },
404
+ largeMedium: {
405
+ fontSize: fs["14"],
406
+ fontWeight: fw.medium,
407
+ lineHeight: lh["20"],
408
+ letterSpacing: ls.normal
409
+ },
410
+ medium: {
411
+ fontSize: fs["13"],
412
+ fontWeight: fw.regular,
413
+ lineHeight: lh["18"],
414
+ letterSpacing: ls.normal
415
+ },
416
+ mediumMedium: {
417
+ fontSize: fs["13"],
418
+ fontWeight: fw.medium,
419
+ lineHeight: lh["18"],
420
+ letterSpacing: ls.normal
421
+ },
422
+ small: {
423
+ fontSize: fs["12"],
424
+ fontWeight: fw.regular,
425
+ lineHeight: lh["16"],
426
+ letterSpacing: ls.normal
427
+ },
428
+ smallMedium: {
429
+ fontSize: fs["12"],
430
+ fontWeight: fw.medium,
431
+ lineHeight: lh["16"],
432
+ letterSpacing: ls.normal
433
+ }
264
434
  }
265
435
  };
266
436
 
267
- // src/styles/ts/breakpoints.ts
268
- var breakpoints = {
269
- compact: 0,
270
- // mobile
271
- medium: 600,
272
- // tablet
273
- expanded: 840,
274
- // small desktop
275
- large: 1200
276
- // desktop
277
- };
278
-
279
437
  // src/styles/ts/z-index.ts
280
438
  var zIndex = {
281
439
  level0: 0,
@@ -286,14 +444,6 @@ var zIndex = {
286
444
  level5: 1e3
287
445
  };
288
446
 
289
- // src/styles/ts/a11y.ts
290
- var a11y = {
291
- focusRing: "0 0 0 3px rgba(0, 0, 0, 0.15)",
292
- focusRingError: "0 0 0 3px rgba(239, 68, 68, 0.15)",
293
- focusRingSuccess: "0 0 0 3px rgba(16, 185, 129, 0.15)",
294
- tapMinSize: "44px"
295
- };
296
-
297
447
  // src/utils/cn.ts
298
448
  var cn = (...classes) => {
299
449
  const classNames = [];
@@ -308,7 +458,7 @@ var cn = (...classes) => {
308
458
  }
309
459
  } else if (typeof item === "object") {
310
460
  for (const key in item) {
311
- if (Object.prototype.hasOwnProperty.call(item, key) && item[key]) {
461
+ if (Object.hasOwn(item, key) && item[key]) {
312
462
  classNames.push(key);
313
463
  }
314
464
  }
@@ -325,8 +475,8 @@ var FOCUSABLE_SELECTORS = [
325
475
  '[tabindex]:not([tabindex="-1"])'
326
476
  ].join(", ");
327
477
  function useFocusTrap(containerRef, isActive) {
328
- const previousActiveElement = React6.useRef(null);
329
- React6.useEffect(() => {
478
+ const previousActiveElement = React9.useRef(null);
479
+ React9.useEffect(() => {
330
480
  if (!isActive) return;
331
481
  const container = containerRef.current;
332
482
  if (!container) return;
@@ -370,9 +520,7 @@ function useFocusTrap(containerRef, isActive) {
370
520
  if (wasTabIndexAdded) {
371
521
  container.removeAttribute("tabindex");
372
522
  }
373
- if (previousActiveElement.current && previousActiveElement.current.focus) {
374
- previousActiveElement.current.focus();
375
- }
523
+ previousActiveElement.current?.focus();
376
524
  };
377
525
  }, [isActive, containerRef]);
378
526
  }
@@ -406,9 +554,7 @@ var useAlert = () => {
406
554
  }
407
555
  return context;
408
556
  };
409
- var AlertProvider = ({
410
- children
411
- }) => {
557
+ var AlertProvider = ({ children }) => {
412
558
  const [alertState, setAlertState] = useState({
413
559
  isOpen: false
414
560
  });
@@ -457,20 +603,15 @@ var AlertModal = ({
457
603
  onCancel,
458
604
  onClose
459
605
  }) => {
460
- const panelRef = React6.useRef(null);
606
+ const panelRef = React9.useRef(null);
461
607
  useFocusTrap(panelRef, true);
462
- const modalClassName = [
463
- "alert_modal",
464
- `alert_variant_${variant}`
465
- ].filter(Boolean).join(" ");
466
- const actionsClassName = [
467
- "alert_actions",
468
- `alert_actions_${actionsAlign}`
469
- ].filter(Boolean).join(" ");
608
+ const modalClassName = ["alert_modal", `alert_variant_${variant}`].filter(Boolean).join(" ");
609
+ const actionsClassName = ["alert_actions", `alert_actions_${actionsAlign}`].filter(Boolean).join(" ");
470
610
  return /* @__PURE__ */ jsx(
471
611
  "div",
472
612
  {
473
613
  className: "alert_overlay",
614
+ role: "presentation",
474
615
  onClick: onClose,
475
616
  onKeyDown: (e) => e.key === "Escape" && onClose(),
476
617
  children: /* @__PURE__ */ jsxs(
@@ -479,6 +620,9 @@ var AlertModal = ({
479
620
  ref: panelRef,
480
621
  className: modalClassName,
481
622
  onClick: (e) => e.stopPropagation(),
623
+ onKeyDown: (e) => {
624
+ if (e.key !== "Escape") e.stopPropagation();
625
+ },
482
626
  role: "alertdialog",
483
627
  "aria-modal": "true",
484
628
  "aria-labelledby": "alert_title",
@@ -487,24 +631,8 @@ var AlertModal = ({
487
631
  title && /* @__PURE__ */ jsx("div", { className: "alert_title", id: "alert_title", children: title }),
488
632
  message && /* @__PURE__ */ jsx("div", { className: "alert_message", id: "alert_message", children: message }),
489
633
  /* @__PURE__ */ jsxs("div", { className: actionsClassName, children: [
490
- showCancel && /* @__PURE__ */ jsx(
491
- "button",
492
- {
493
- type: "button",
494
- className: "alert_button alert_button_cancel",
495
- onClick: onCancel,
496
- children: cancelText
497
- }
498
- ),
499
- /* @__PURE__ */ jsx(
500
- "button",
501
- {
502
- type: "button",
503
- className: "alert_button alert_button_confirm",
504
- onClick: onConfirm,
505
- children: confirmText
506
- }
507
- )
634
+ showCancel && /* @__PURE__ */ jsx("button", { type: "button", className: "alert_button alert_button_cancel", onClick: onCancel, children: cancelText }),
635
+ /* @__PURE__ */ jsx("button", { type: "button", className: "alert_button alert_button_confirm", onClick: onConfirm, children: confirmText })
508
636
  ] })
509
637
  ]
510
638
  }
@@ -523,42 +651,7 @@ var Spinner = ({ size = 24, ariaLabel = "Loading" }) => {
523
651
  }
524
652
  );
525
653
  };
526
- var TopLoading = ({
527
- progress,
528
- color,
529
- height = 3,
530
- isLoading = true,
531
- ariaLabel = "Page loading"
532
- }) => {
533
- if (!isLoading) return null;
534
- const isIndeterminate = progress === void 0;
535
- return /* @__PURE__ */ jsx(
536
- "div",
537
- {
538
- className: "top_loading",
539
- style: { height },
540
- role: "progressbar",
541
- "aria-valuemin": 0,
542
- "aria-valuemax": 100,
543
- "aria-valuenow": isIndeterminate ? void 0 : progress,
544
- "aria-label": ariaLabel,
545
- children: /* @__PURE__ */ jsx(
546
- "div",
547
- {
548
- className: [
549
- "top_loading_bar",
550
- isIndeterminate && "top_loading_indeterminate"
551
- ].filter(Boolean).join(" "),
552
- style: {
553
- width: isIndeterminate ? void 0 : `${progress}%`,
554
- backgroundColor: color
555
- }
556
- }
557
- )
558
- }
559
- );
560
- };
561
- var ToastContext = React6.createContext(null);
654
+ var ToastContext = React9.createContext(null);
562
655
  var VARIANT_ICONS = {
563
656
  success: /* @__PURE__ */ jsx(CheckCircle2, { size: 18 }),
564
657
  error: /* @__PURE__ */ jsx(XCircle, { size: 18 }),
@@ -567,63 +660,48 @@ var VARIANT_ICONS = {
567
660
  default: /* @__PURE__ */ jsx(Bell, { size: 18 })
568
661
  };
569
662
  var ToastItemComponent = ({ item, onRemove, closeAriaLabel }) => {
570
- const [exiting, setExiting] = React6.useState(false);
571
- const closingRef = React6.useRef(false);
572
- const close = React6.useCallback(() => {
663
+ const [exiting, setExiting] = React9.useState(false);
664
+ const closingRef = React9.useRef(false);
665
+ const close = React9.useCallback(() => {
573
666
  if (closingRef.current) return;
574
667
  closingRef.current = true;
575
668
  setExiting(true);
576
669
  setTimeout(() => onRemove(item.id), 260);
577
670
  }, [item.id, onRemove]);
578
- const itemClassName = [
579
- "toast_item",
580
- exiting && "toast_item_exiting"
581
- ].filter(Boolean).join(" ");
582
- return /* @__PURE__ */ jsxs(
583
- "div",
584
- {
585
- className: itemClassName,
586
- role: item.variant === "error" ? "alert" : "status",
587
- children: [
588
- /* @__PURE__ */ jsx("span", { className: `toast_icon toast_icon_${item.variant}`, "aria-hidden": "true", children: VARIANT_ICONS[item.variant] }),
589
- /* @__PURE__ */ jsx("span", { className: "toast_message", children: item.message }),
590
- /* @__PURE__ */ jsx(
591
- "button",
592
- {
593
- type: "button",
594
- className: "toast_close",
595
- onClick: close,
596
- "aria-label": closeAriaLabel,
597
- children: /* @__PURE__ */ jsx(X, { size: 14 })
598
- }
599
- ),
600
- /* @__PURE__ */ jsx(
601
- "div",
602
- {
603
- className: `toast_progress toast_progress_${item.variant}`,
604
- style: { "--toast-duration": `${item.duration}ms` },
605
- onAnimationEnd: close,
606
- "aria-hidden": "true"
607
- }
608
- )
609
- ]
610
- }
611
- );
671
+ const itemClassName = ["toast_item", exiting && "toast_item_exiting"].filter(Boolean).join(" ");
672
+ return /* @__PURE__ */ jsxs("div", { className: itemClassName, role: item.variant === "error" ? "alert" : "status", children: [
673
+ /* @__PURE__ */ jsx("span", { className: `toast_icon toast_icon_${item.variant}`, "aria-hidden": "true", children: VARIANT_ICONS[item.variant] }),
674
+ /* @__PURE__ */ jsx("span", { className: "toast_message", children: item.message }),
675
+ /* @__PURE__ */ jsx("button", { type: "button", className: "toast_close", onClick: close, "aria-label": closeAriaLabel, children: /* @__PURE__ */ jsx(X, { size: 14 }) }),
676
+ /* @__PURE__ */ jsx(
677
+ "div",
678
+ {
679
+ className: `toast_progress toast_progress_${item.variant}`,
680
+ style: { "--toast-duration": `${item.duration}ms` },
681
+ onAnimationEnd: close,
682
+ "aria-hidden": "true"
683
+ }
684
+ )
685
+ ] });
612
686
  };
613
- var ToastProvider = ({ children, maxCount = 5, closeAriaLabel = "Close" }) => {
614
- const [toasts, setToasts] = React6.useState([]);
615
- const [isMounted, setIsMounted] = React6.useState(false);
616
- React6.useEffect(() => {
687
+ var ToastProvider = ({
688
+ children,
689
+ maxCount = 5,
690
+ closeAriaLabel = "Close"
691
+ }) => {
692
+ const [toasts, setToasts] = React9.useState([]);
693
+ const [isMounted, setIsMounted] = React9.useState(false);
694
+ React9.useEffect(() => {
617
695
  setIsMounted(true);
618
696
  }, []);
619
- const addToast = React6.useCallback(
697
+ const addToast = React9.useCallback(
620
698
  (message, variant, duration = 3e3) => {
621
699
  const id = crypto.randomUUID();
622
700
  setToasts((prev) => [{ id, message, variant, duration }, ...prev].slice(0, maxCount));
623
701
  },
624
702
  [maxCount]
625
703
  );
626
- const removeToast = React6.useCallback((id) => {
704
+ const removeToast = React9.useCallback((id) => {
627
705
  setToasts((prev) => prev.filter((t) => t.id !== id));
628
706
  }, []);
629
707
  return /* @__PURE__ */ jsxs(ToastContext.Provider, { value: { addToast }, children: [
@@ -633,6 +711,7 @@ var ToastProvider = ({ children, maxCount = 5, closeAriaLabel = "Close" }) => {
633
711
  "div",
634
712
  {
635
713
  className: "toast_container",
714
+ role: "region",
636
715
  "aria-live": "polite",
637
716
  "aria-atomic": "false",
638
717
  "aria-label": "Notifications",
@@ -669,52 +748,168 @@ var useToast = () => {
669
748
  message: (message, duration) => ctx.addToast(message, "default", duration)
670
749
  };
671
750
  };
672
- var Button = ({
673
- variant = "primary",
751
+ var TopLoading = ({
752
+ progress,
753
+ color,
754
+ height = 3,
755
+ isLoading = true,
756
+ ariaLabel = "Page loading"
757
+ }) => {
758
+ if (!isLoading) return null;
759
+ const isIndeterminate = progress === void 0;
760
+ return /* @__PURE__ */ jsx(
761
+ "div",
762
+ {
763
+ className: "top_loading",
764
+ style: { height },
765
+ role: "progressbar",
766
+ "aria-valuemin": 0,
767
+ "aria-valuemax": 100,
768
+ "aria-valuenow": isIndeterminate ? void 0 : progress,
769
+ "aria-label": ariaLabel,
770
+ children: /* @__PURE__ */ jsx(
771
+ "div",
772
+ {
773
+ className: ["top_loading_bar", isIndeterminate && "top_loading_indeterminate"].filter(Boolean).join(" "),
774
+ style: {
775
+ width: isIndeterminate ? void 0 : `${progress}%`,
776
+ backgroundColor: color
777
+ }
778
+ }
779
+ )
780
+ }
781
+ );
782
+ };
783
+ var Checkbox = ({
784
+ label,
674
785
  size = "md",
675
- fullWidth = true,
676
- width,
786
+ indeterminate,
677
787
  className,
678
- style,
788
+ ref,
679
789
  ...props
680
790
  }) => {
681
- const buttonClassName = cn(
682
- "button",
683
- `button_variant_${variant}`,
684
- `button_size_${size}`,
685
- fullWidth && !width && "button_full_width",
686
- className
687
- );
688
- const buttonStyle = width ? { ...style, width } : style;
689
- return /* @__PURE__ */ jsx("button", { className: buttonClassName, style: buttonStyle, ...props });
690
- };
691
- var Checkbox = ({ label, size = "md", indeterminate, className, ref, ...props }) => {
692
- const inputRef = React6.useRef(null);
693
- React6.useImperativeHandle(ref, () => inputRef.current);
694
- React6.useEffect(() => {
791
+ const inputRef = React9.useRef(null);
792
+ React9.useImperativeHandle(ref, () => inputRef.current);
793
+ React9.useEffect(() => {
695
794
  if (!inputRef.current) return;
696
795
  inputRef.current.indeterminate = Boolean(indeterminate);
697
796
  }, [indeterminate]);
698
- const rootClassName = cn(
699
- "checkbox",
700
- `checkbox_size_${size}`,
701
- className
702
- );
797
+ const rootClassName = cn("checkbox", `checkbox_size_${size}`, className);
703
798
  return /* @__PURE__ */ jsxs("label", { className: rootClassName, children: [
704
- /* @__PURE__ */ jsx(
705
- "input",
706
- {
707
- ref: inputRef,
708
- type: "checkbox",
709
- className: "checkbox_input",
710
- ...props
711
- }
712
- ),
799
+ /* @__PURE__ */ jsx("input", { ref: inputRef, type: "checkbox", className: "checkbox_input", ...props }),
713
800
  /* @__PURE__ */ jsx("span", { className: "checkbox_box", "aria-hidden": "true" }),
714
801
  label ? /* @__PURE__ */ jsx("span", { className: "checkbox_label", children: label }) : null
715
802
  ] });
716
803
  };
717
804
  Checkbox.displayName = "Checkbox";
805
+ var pad = (n) => String(n).padStart(2, "0");
806
+ var getDaysInMonth = (year, month) => new Date(year, month, 0).getDate();
807
+ var normalizeWidth = (v) => typeof v === "number" ? `${v}px` : v;
808
+ var DatePicker = ({
809
+ label,
810
+ value,
811
+ onChange,
812
+ mode = "year-month-day",
813
+ startYear = 1950,
814
+ endYear = (/* @__PURE__ */ new Date()).getFullYear() + 10,
815
+ minDate,
816
+ selectableRange = "all",
817
+ disabled,
818
+ fullWidth = true,
819
+ width,
820
+ yearLabel = "Year",
821
+ monthLabel = "Month",
822
+ dayLabel = "Day",
823
+ minDateSrFormat = "Minimum date: {date}",
824
+ selectableRangeUntilTodaySrText = "Selectable up to today"
825
+ }) => {
826
+ const groupId = React9.useId();
827
+ const constraintId = React9.useId();
828
+ const today = /* @__PURE__ */ new Date();
829
+ const todayYear = today.getFullYear();
830
+ const todayMonth = today.getMonth() + 1;
831
+ const todayDay = today.getDate();
832
+ const [y, m, d] = value?.split("-").map(Number) ?? [];
833
+ const [minY, minM, minD] = minDate?.split("-").map(Number) ?? [];
834
+ const year = y ?? "";
835
+ const month = m ?? "";
836
+ const day = d ?? "";
837
+ const maxYear = selectableRange === "until-today" ? todayYear : endYear;
838
+ const minMonth = minY && year === minY ? minM : 1;
839
+ const maxMonth = selectableRange === "until-today" && year === todayYear ? todayMonth : 12;
840
+ const minDay = minY && minM && year === minY && month === minM ? minD : 1;
841
+ const maxDay = selectableRange === "until-today" && year === todayYear && month === todayMonth ? todayDay : getDaysInMonth(year || todayYear, month || 1);
842
+ const days = year && month ? Math.min(getDaysInMonth(year, month), maxDay) : 31;
843
+ const clampDay = (year2, month2, day2) => Math.min(day2, getDaysInMonth(year2, month2));
844
+ const emit = (yy, mm, dd) => {
845
+ if (mode === "year-month") {
846
+ onChange(`${yy}-${pad(mm)}`);
847
+ return;
848
+ }
849
+ const safeDay = clampDay(yy, mm, dd ?? 1);
850
+ onChange(`${yy}-${pad(mm)}-${pad(safeDay)}`);
851
+ };
852
+ const containerStyle = width ? { width: normalizeWidth(width) } : void 0;
853
+ const rootClassName = cn("date_picker", { date_picker_full_width: fullWidth && !width });
854
+ const constraintParts = [];
855
+ if (minDate) constraintParts.push(minDateSrFormat.replace("{date}", minDate));
856
+ if (selectableRange === "until-today") constraintParts.push(selectableRangeUntilTodaySrText);
857
+ const constraintDesc = constraintParts.join(". ");
858
+ return /* @__PURE__ */ jsxs("div", { className: rootClassName, style: containerStyle, children: [
859
+ label && /* @__PURE__ */ jsx("span", { className: "date_picker_label", id: groupId, children: label }),
860
+ constraintDesc && /* @__PURE__ */ jsx("span", { id: constraintId, className: "date_picker_sr_only", children: constraintDesc }),
861
+ /* @__PURE__ */ jsxs(
862
+ "div",
863
+ {
864
+ className: "date_picker_fields",
865
+ role: "group",
866
+ "aria-labelledby": label ? groupId : void 0,
867
+ "aria-describedby": constraintDesc ? constraintId : void 0,
868
+ children: [
869
+ /* @__PURE__ */ jsxs(
870
+ "select",
871
+ {
872
+ "aria-label": yearLabel,
873
+ value: year,
874
+ disabled,
875
+ onChange: (e) => emit(Number(e.target.value), month || minMonth, day || minDay),
876
+ children: [
877
+ /* @__PURE__ */ jsx("option", { value: "", children: yearLabel }),
878
+ Array.from({ length: maxYear - startYear + 1 }, (_, i) => startYear + i).map((y2) => /* @__PURE__ */ jsx("option", { value: y2, children: y2 }, y2))
879
+ ]
880
+ }
881
+ ),
882
+ /* @__PURE__ */ jsxs(
883
+ "select",
884
+ {
885
+ "aria-label": monthLabel,
886
+ value: month,
887
+ disabled: disabled || !year,
888
+ onChange: (e) => emit(year, Number(e.target.value), day || minDay),
889
+ children: [
890
+ /* @__PURE__ */ jsx("option", { value: "", children: monthLabel }),
891
+ Array.from({ length: maxMonth - minMonth + 1 }, (_, i) => minMonth + i).map((m2) => /* @__PURE__ */ jsx("option", { value: m2, children: pad(m2) }, m2))
892
+ ]
893
+ }
894
+ ),
895
+ mode === "year-month-day" && /* @__PURE__ */ jsxs(
896
+ "select",
897
+ {
898
+ "aria-label": dayLabel,
899
+ value: day,
900
+ disabled: disabled || !month,
901
+ onChange: (e) => emit(year, month, Number(e.target.value)),
902
+ children: [
903
+ /* @__PURE__ */ jsx("option", { value: "", children: dayLabel }),
904
+ Array.from({ length: days - minDay + 1 }, (_, i) => minDay + i).map((d2) => /* @__PURE__ */ jsx("option", { value: d2, children: pad(d2) }, d2))
905
+ ]
906
+ }
907
+ )
908
+ ]
909
+ }
910
+ )
911
+ ] });
912
+ };
718
913
  var FileInput = ({
719
914
  label = "Choose file",
720
915
  onFiles,
@@ -723,13 +918,9 @@ var FileInput = ({
723
918
  disabled,
724
919
  ...props
725
920
  }) => {
726
- const inputId = React6.useId();
727
- const helperId = React6.useId();
728
- const rootClassName = [
729
- "file_input",
730
- disabled && "file_input_disabled",
731
- className ?? ""
732
- ].filter(Boolean).join(" ");
921
+ const inputId = React9.useId();
922
+ const helperId = React9.useId();
923
+ const rootClassName = ["file_input", disabled && "file_input_disabled", className ?? ""].filter(Boolean).join(" ");
733
924
  return /* @__PURE__ */ jsxs("div", { className: rootClassName, children: [
734
925
  /* @__PURE__ */ jsx(
735
926
  "input",
@@ -748,11 +939,7 @@ var FileInput = ({
748
939
  ] });
749
940
  };
750
941
  var Radio = ({ label, size = "md", className, ref, ...props }) => {
751
- const rootClassName = cn(
752
- "radio",
753
- `radio_size_${size}`,
754
- className
755
- );
942
+ const rootClassName = cn("radio", `radio_size_${size}`, className);
756
943
  return /* @__PURE__ */ jsxs("label", { className: rootClassName, children: [
757
944
  /* @__PURE__ */ jsx("input", { ref, type: "radio", className: "radio_input", ...props }),
758
945
  /* @__PURE__ */ jsx("span", { className: "radio_dot", "aria-hidden": "true" }),
@@ -760,6 +947,159 @@ var Radio = ({ label, size = "md", className, ref, ...props }) => {
760
947
  ] });
761
948
  };
762
949
  Radio.displayName = "Radio";
950
+ var Switch = ({
951
+ checked,
952
+ defaultChecked,
953
+ onChange,
954
+ size = "md",
955
+ disabled,
956
+ className,
957
+ ariaLabel,
958
+ ref,
959
+ ...props
960
+ }) => {
961
+ const isControlled = checked !== void 0;
962
+ const [innerChecked, setInnerChecked] = React9.useState(!!defaultChecked);
963
+ const isOn = isControlled ? !!checked : innerChecked;
964
+ const handleToggle = () => {
965
+ if (disabled) return;
966
+ const next = !isOn;
967
+ if (!isControlled) setInnerChecked(next);
968
+ onChange?.(next);
969
+ };
970
+ const rootClassName = cn(
971
+ "switch",
972
+ `switch_size_${size}`,
973
+ { switch_on: isOn, switch_disabled: disabled },
974
+ className
975
+ );
976
+ return /* @__PURE__ */ jsx(
977
+ "button",
978
+ {
979
+ ref,
980
+ type: "button",
981
+ role: "switch",
982
+ "aria-checked": isOn,
983
+ "aria-label": ariaLabel,
984
+ disabled,
985
+ onClick: handleToggle,
986
+ className: rootClassName,
987
+ ...props,
988
+ children: /* @__PURE__ */ jsx("span", { className: "switch_thumb" })
989
+ }
990
+ );
991
+ };
992
+ Switch.displayName = "Switch";
993
+ var TextField = ({
994
+ id,
995
+ label,
996
+ helperText,
997
+ error,
998
+ success,
999
+ variant = "outline",
1000
+ size = "md",
1001
+ leftIcon,
1002
+ rightIcon,
1003
+ fullWidth,
1004
+ className,
1005
+ onChangeAction,
1006
+ value,
1007
+ defaultValue,
1008
+ transformValue,
1009
+ ref,
1010
+ ...props
1011
+ }) => {
1012
+ const generatedId = React9.useId();
1013
+ const inputId = id ?? generatedId;
1014
+ const helperId = helperText ? `${inputId}-help` : void 0;
1015
+ const isControlled = value !== void 0;
1016
+ const applyTransform = (nextValue) => transformValue ? transformValue(nextValue) : nextValue;
1017
+ const [innerValue, setInnerValue] = React9.useState(
1018
+ () => applyTransform(value ?? defaultValue ?? "")
1019
+ );
1020
+ const isComposingRef = React9.useRef(false);
1021
+ React9.useEffect(() => {
1022
+ if (!isControlled) return;
1023
+ const nextValue = value ?? "";
1024
+ setInnerValue(transformValue ? transformValue(nextValue) : nextValue);
1025
+ }, [isControlled, value, transformValue]);
1026
+ const rootClassName = cn("text_field", { text_field_full_width: fullWidth }, className);
1027
+ const inputClassName = cn(
1028
+ "text_field_input",
1029
+ `text_field_variant_${variant}`,
1030
+ `text_field_size_${size}`,
1031
+ {
1032
+ text_field_with_left: !!leftIcon,
1033
+ text_field_with_right: !!rightIcon,
1034
+ text_field_error: !!error,
1035
+ text_field_success: !!success
1036
+ }
1037
+ );
1038
+ const helperClassName = cn("text_field_helper", {
1039
+ text_field_helper_error: error,
1040
+ text_field_helper_success: success
1041
+ });
1042
+ return /* @__PURE__ */ jsxs("div", { className: rootClassName, children: [
1043
+ label ? /* @__PURE__ */ jsx("label", { className: "text_field_label", htmlFor: inputId, children: label }) : null,
1044
+ /* @__PURE__ */ jsxs("div", { className: "text_field_wrap", children: [
1045
+ leftIcon ? /* @__PURE__ */ jsx("span", { className: "text_field_icon text_field_icon_left", "aria-hidden": "true", children: leftIcon }) : null,
1046
+ /* @__PURE__ */ jsx(
1047
+ "input",
1048
+ {
1049
+ id: inputId,
1050
+ ref,
1051
+ className: inputClassName,
1052
+ "aria-invalid": !!error,
1053
+ "aria-describedby": helperId,
1054
+ ...props,
1055
+ value: innerValue,
1056
+ onCompositionStart: () => {
1057
+ isComposingRef.current = true;
1058
+ },
1059
+ onCompositionEnd: (event) => {
1060
+ isComposingRef.current = false;
1061
+ const rawValue = event.currentTarget.value;
1062
+ const nextValue = applyTransform(rawValue);
1063
+ setInnerValue(nextValue);
1064
+ onChangeAction?.(nextValue);
1065
+ },
1066
+ onChange: (event) => {
1067
+ const rawValue = event.target.value;
1068
+ if (isComposingRef.current) {
1069
+ setInnerValue(rawValue);
1070
+ return;
1071
+ }
1072
+ const nextValue = applyTransform(rawValue);
1073
+ setInnerValue(nextValue);
1074
+ onChangeAction?.(nextValue);
1075
+ }
1076
+ }
1077
+ ),
1078
+ rightIcon ? /* @__PURE__ */ jsx("span", { className: "text_field_icon text_field_icon_right", "aria-hidden": "true", children: rightIcon }) : null
1079
+ ] }),
1080
+ helperText ? /* @__PURE__ */ jsx("div", { id: helperId, className: helperClassName, children: helperText }) : null
1081
+ ] });
1082
+ };
1083
+ TextField.displayName = "TextField";
1084
+ var Button = ({
1085
+ variant = "primary",
1086
+ size = "md",
1087
+ fullWidth = true,
1088
+ width,
1089
+ className,
1090
+ style,
1091
+ ...props
1092
+ }) => {
1093
+ const buttonClassName = cn(
1094
+ "button",
1095
+ `button_variant_${variant}`,
1096
+ `button_size_${size}`,
1097
+ fullWidth && !width && "button_full_width",
1098
+ className
1099
+ );
1100
+ const buttonStyle = width ? { ...style, width } : style;
1101
+ return /* @__PURE__ */ jsx("button", { className: buttonClassName, style: buttonStyle, ...props });
1102
+ };
763
1103
  var Select = ({
764
1104
  id,
765
1105
  label,
@@ -775,21 +1115,21 @@ var Select = ({
775
1115
  className,
776
1116
  textAlign = "left"
777
1117
  }) => {
778
- const internalId = React6.useId();
1118
+ const internalId = React9.useId();
779
1119
  const selectId = id ?? internalId;
780
1120
  const isControlled = value !== void 0;
781
- const [internalValue, setInternalValue] = React6.useState(defaultValue);
1121
+ const [internalValue, setInternalValue] = React9.useState(defaultValue);
782
1122
  const currentValue = isControlled ? value ?? null : internalValue;
783
- const [isOpen, setIsOpen] = React6.useState(false);
784
- const [activeIndex, setActiveIndex] = React6.useState(-1);
785
- const [dropUp, setDropUp] = React6.useState(false);
786
- const wrapperRef = React6.useRef(null);
787
- const controlRef = React6.useRef(null);
788
- const currentOption = React6.useMemo(
1123
+ const [isOpen, setIsOpen] = React9.useState(false);
1124
+ const [activeIndex, setActiveIndex] = React9.useState(-1);
1125
+ const [dropUp, setDropUp] = React9.useState(false);
1126
+ const wrapperRef = React9.useRef(null);
1127
+ const controlRef = React9.useRef(null);
1128
+ const currentOption = React9.useMemo(
789
1129
  () => options.find((o) => o.value === currentValue) ?? null,
790
1130
  [options, currentValue]
791
1131
  );
792
- const setValue = React6.useCallback(
1132
+ const setValue = React9.useCallback(
793
1133
  (next) => {
794
1134
  const option = options.find((o) => o.value === next) ?? null;
795
1135
  if (!isControlled) setInternalValue(next);
@@ -797,12 +1137,12 @@ var Select = ({
797
1137
  },
798
1138
  [isControlled, onChange, options]
799
1139
  );
800
- const handleOutsideClick = React6.useEffectEvent((e) => {
1140
+ const handleOutsideClick = React9.useEffectEvent((e) => {
801
1141
  if (!wrapperRef.current?.contains(e.target)) {
802
1142
  setIsOpen(false);
803
1143
  }
804
1144
  });
805
- React6.useEffect(() => {
1145
+ React9.useEffect(() => {
806
1146
  document.addEventListener("mousedown", handleOutsideClick);
807
1147
  return () => document.removeEventListener("mousedown", handleOutsideClick);
808
1148
  }, []);
@@ -867,12 +1207,17 @@ var Select = ({
867
1207
  break;
868
1208
  }
869
1209
  };
870
- React6.useEffect(() => {
1210
+ React9.useEffect(() => {
871
1211
  if (!isOpen) return;
872
1212
  const idx = options.findIndex((o) => o.value === currentValue && !o.disabled);
873
- setActiveIndex(idx >= 0 ? idx : Math.max(0, options.findIndex((o) => !o.disabled)));
1213
+ setActiveIndex(
1214
+ idx >= 0 ? idx : Math.max(
1215
+ 0,
1216
+ options.findIndex((o) => !o.disabled)
1217
+ )
1218
+ );
874
1219
  }, [isOpen, options, currentValue]);
875
- React6.useLayoutEffect(() => {
1220
+ React9.useLayoutEffect(() => {
876
1221
  if (!isOpen || !controlRef.current) return;
877
1222
  const rect = controlRef.current.getBoundingClientRect();
878
1223
  const listHeight = Math.min(options.length * 40, 288);
@@ -885,54 +1230,56 @@ var Select = ({
885
1230
  "select_control",
886
1231
  `select_variant_${variant}`,
887
1232
  `select_size_${size}`,
888
- { is_open: isOpen, is_disabled: disabled }
889
- );
890
- const listClassName = cn("select_list", { select_list_up: dropUp });
891
- return /* @__PURE__ */ jsxs("div", { ref: wrapperRef, className: rootClassName, style: fullWidth ? { width: "100%" } : void 0, children: [
892
- label && /* @__PURE__ */ jsx("label", { htmlFor: selectId, className: "select_label", children: label }),
893
- /* @__PURE__ */ jsxs(
894
- "button",
895
- {
896
- ref: controlRef,
897
- id: selectId,
898
- type: "button",
899
- className: controlClassName,
900
- "aria-haspopup": "listbox",
901
- "aria-expanded": isOpen,
902
- "aria-controls": `${selectId}_listbox`,
903
- onClick: () => !disabled && setIsOpen((o) => !o),
904
- onKeyDown,
905
- disabled,
906
- children: [
907
- /* @__PURE__ */ jsx(
908
- "span",
909
- {
910
- className: currentOption ? "select_value" : "select_placeholder",
911
- style: textAlign === "left" ? { textAlign: "start" } : void 0,
912
- children: currentOption ? currentOption.label : placeholder
913
- }
914
- ),
915
- /* @__PURE__ */ jsx("span", { className: "select_icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx(ChevronDown, { size: 16 }) })
916
- ]
917
- }
918
- ),
919
- isOpen && /* @__PURE__ */ jsx(
920
- "ul",
921
- {
922
- id: `${selectId}_listbox`,
923
- role: "listbox",
924
- className: listClassName,
925
- children: options.map((opt, i) => {
1233
+ { is_open: isOpen, is_disabled: disabled }
1234
+ );
1235
+ const listClassName = cn("select_list", { select_list_up: dropUp });
1236
+ return /* @__PURE__ */ jsxs(
1237
+ "div",
1238
+ {
1239
+ ref: wrapperRef,
1240
+ className: rootClassName,
1241
+ style: fullWidth ? { width: "100%" } : void 0,
1242
+ children: [
1243
+ label && /* @__PURE__ */ jsx("label", { htmlFor: selectId, className: "select_label", children: label }),
1244
+ /* @__PURE__ */ jsxs(
1245
+ "button",
1246
+ {
1247
+ ref: controlRef,
1248
+ id: selectId,
1249
+ type: "button",
1250
+ className: controlClassName,
1251
+ "aria-haspopup": "listbox",
1252
+ "aria-expanded": isOpen,
1253
+ "aria-controls": `${selectId}_listbox`,
1254
+ onClick: () => !disabled && setIsOpen((o) => !o),
1255
+ onKeyDown,
1256
+ disabled,
1257
+ children: [
1258
+ /* @__PURE__ */ jsx(
1259
+ "span",
1260
+ {
1261
+ className: currentOption ? "select_value" : "select_placeholder",
1262
+ style: textAlign === "left" ? { textAlign: "start" } : void 0,
1263
+ children: currentOption ? currentOption.label : placeholder
1264
+ }
1265
+ ),
1266
+ /* @__PURE__ */ jsx("span", { className: "select_icon", "aria-hidden": "true", children: /* @__PURE__ */ jsx(ChevronDown, { size: 16 }) })
1267
+ ]
1268
+ }
1269
+ ),
1270
+ isOpen && /* @__PURE__ */ jsx("div", { id: `${selectId}_listbox`, role: "listbox", className: listClassName, children: options.map((opt, i) => {
926
1271
  const selected = currentValue === opt.value;
927
1272
  const active = i === activeIndex;
928
- const optionClassName = cn(
929
- "select_option",
930
- { is_selected: selected, is_active: active, is_disabled: opt.disabled }
931
- );
1273
+ const optionClassName = cn("select_option", {
1274
+ is_selected: selected,
1275
+ is_active: active,
1276
+ is_disabled: opt.disabled
1277
+ });
932
1278
  return /* @__PURE__ */ jsxs(
933
- "li",
1279
+ "div",
934
1280
  {
935
1281
  role: "option",
1282
+ tabIndex: -1,
936
1283
  "aria-selected": selected,
937
1284
  "aria-disabled": opt.disabled ? true : void 0,
938
1285
  className: optionClassName,
@@ -942,6 +1289,14 @@ var Select = ({
942
1289
  setValue(opt.value);
943
1290
  setIsOpen(false);
944
1291
  },
1292
+ onKeyDown: (e) => {
1293
+ if (opt.disabled) return;
1294
+ if (e.key === "Enter" || e.key === " ") {
1295
+ e.preventDefault();
1296
+ setValue(opt.value);
1297
+ setIsOpen(false);
1298
+ }
1299
+ },
945
1300
  children: [
946
1301
  /* @__PURE__ */ jsx("span", { children: opt.label }),
947
1302
  selected && /* @__PURE__ */ jsx(Check, { size: 16, "aria-hidden": "true" })
@@ -949,265 +1304,10 @@ var Select = ({
949
1304
  },
950
1305
  opt.value
951
1306
  );
952
- })
953
- }
954
- )
955
- ] });
956
- };
957
- var Switch = ({
958
- checked,
959
- defaultChecked,
960
- onChange,
961
- size = "md",
962
- disabled,
963
- className,
964
- ariaLabel,
965
- ref,
966
- ...props
967
- }) => {
968
- const isControlled = checked !== void 0;
969
- const [innerChecked, setInnerChecked] = React6.useState(!!defaultChecked);
970
- const isOn = isControlled ? !!checked : innerChecked;
971
- const handleToggle = () => {
972
- if (disabled) return;
973
- const next = !isOn;
974
- if (!isControlled) setInnerChecked(next);
975
- onChange?.(next);
976
- };
977
- const rootClassName = cn(
978
- "switch",
979
- `switch_size_${size}`,
980
- { switch_on: isOn, switch_disabled: disabled },
981
- className
982
- );
983
- return /* @__PURE__ */ jsx(
984
- "button",
985
- {
986
- ref,
987
- type: "button",
988
- role: "switch",
989
- "aria-checked": isOn,
990
- "aria-label": ariaLabel,
991
- disabled,
992
- onClick: handleToggle,
993
- className: rootClassName,
994
- ...props,
995
- children: /* @__PURE__ */ jsx("span", { className: "switch_thumb" })
996
- }
997
- );
998
- };
999
- Switch.displayName = "Switch";
1000
- var TextField = ({
1001
- id,
1002
- label,
1003
- helperText,
1004
- error,
1005
- success,
1006
- variant = "outline",
1007
- size = "md",
1008
- leftIcon,
1009
- rightIcon,
1010
- fullWidth,
1011
- className,
1012
- onChangeAction,
1013
- value,
1014
- defaultValue,
1015
- transformValue,
1016
- ref,
1017
- ...props
1018
- }) => {
1019
- const inputId = id ?? React6.useId();
1020
- const helperId = helperText ? `${inputId}-help` : void 0;
1021
- const isControlled = value !== void 0;
1022
- const applyTransform = (nextValue) => transformValue ? transformValue(nextValue) : nextValue;
1023
- const [innerValue, setInnerValue] = React6.useState(
1024
- () => applyTransform(value ?? defaultValue ?? "")
1025
- );
1026
- const isComposingRef = React6.useRef(false);
1027
- React6.useEffect(() => {
1028
- if (!isControlled) return;
1029
- setInnerValue(applyTransform(value ?? ""));
1030
- }, [isControlled, value, transformValue]);
1031
- const rootClassName = cn(
1032
- "text_field",
1033
- { text_field_full_width: fullWidth },
1034
- className
1035
- );
1036
- const inputClassName = cn(
1037
- "text_field_input",
1038
- `text_field_variant_${variant}`,
1039
- `text_field_size_${size}`,
1040
- {
1041
- text_field_with_left: !!leftIcon,
1042
- text_field_with_right: !!rightIcon,
1043
- text_field_error: !!error,
1044
- text_field_success: !!success
1045
- }
1046
- );
1047
- const helperClassName = cn(
1048
- "text_field_helper",
1049
- {
1050
- text_field_helper_error: error,
1051
- text_field_helper_success: success
1307
+ }) })
1308
+ ]
1052
1309
  }
1053
1310
  );
1054
- return /* @__PURE__ */ jsxs("div", { className: rootClassName, children: [
1055
- label ? /* @__PURE__ */ jsx("label", { className: "text_field_label", htmlFor: inputId, children: label }) : null,
1056
- /* @__PURE__ */ jsxs("div", { className: "text_field_wrap", children: [
1057
- leftIcon ? /* @__PURE__ */ jsx("span", { className: "text_field_icon text_field_icon_left", "aria-hidden": "true", children: leftIcon }) : null,
1058
- /* @__PURE__ */ jsx(
1059
- "input",
1060
- {
1061
- id: inputId,
1062
- ref,
1063
- className: inputClassName,
1064
- "aria-invalid": !!error,
1065
- "aria-describedby": helperId,
1066
- ...props,
1067
- value: innerValue,
1068
- onCompositionStart: () => {
1069
- isComposingRef.current = true;
1070
- },
1071
- onCompositionEnd: (event) => {
1072
- isComposingRef.current = false;
1073
- const rawValue = event.currentTarget.value;
1074
- const nextValue = applyTransform(rawValue);
1075
- setInnerValue(nextValue);
1076
- onChangeAction?.(nextValue);
1077
- },
1078
- onChange: (event) => {
1079
- const rawValue = event.target.value;
1080
- if (isComposingRef.current) {
1081
- setInnerValue(rawValue);
1082
- return;
1083
- }
1084
- const nextValue = applyTransform(rawValue);
1085
- setInnerValue(nextValue);
1086
- onChangeAction?.(nextValue);
1087
- }
1088
- }
1089
- ),
1090
- rightIcon ? /* @__PURE__ */ jsx("span", { className: "text_field_icon text_field_icon_right", "aria-hidden": "true", children: rightIcon }) : null
1091
- ] }),
1092
- helperText ? /* @__PURE__ */ jsx("div", { id: helperId, className: helperClassName, children: helperText }) : null
1093
- ] });
1094
- };
1095
- TextField.displayName = "TextField";
1096
- var pad = (n) => String(n).padStart(2, "0");
1097
- var getDaysInMonth = (year, month) => new Date(year, month, 0).getDate();
1098
- var normalizeWidth = (v) => typeof v === "number" ? `${v}px` : v;
1099
- var DatePicker = ({
1100
- label,
1101
- value,
1102
- onChange,
1103
- mode = "year-month-day",
1104
- startYear = 1950,
1105
- endYear = (/* @__PURE__ */ new Date()).getFullYear() + 10,
1106
- minDate,
1107
- selectableRange = "all",
1108
- disabled,
1109
- fullWidth = true,
1110
- width,
1111
- yearLabel = "Year",
1112
- monthLabel = "Month",
1113
- dayLabel = "Day",
1114
- minDateSrFormat = "Minimum date: {date}",
1115
- selectableRangeUntilTodaySrText = "Selectable up to today"
1116
- }) => {
1117
- const groupId = React6.useId();
1118
- const constraintId = React6.useId();
1119
- const today = /* @__PURE__ */ new Date();
1120
- const todayYear = today.getFullYear();
1121
- const todayMonth = today.getMonth() + 1;
1122
- const todayDay = today.getDate();
1123
- const [y, m, d] = value?.split("-").map(Number) ?? [];
1124
- const [minY, minM, minD] = minDate?.split("-").map(Number) ?? [];
1125
- const year = y ?? "";
1126
- const month = m ?? "";
1127
- const day = d ?? "";
1128
- const maxYear = selectableRange === "until-today" ? todayYear : endYear;
1129
- const minMonth = minY && year === minY ? minM : 1;
1130
- const maxMonth = selectableRange === "until-today" && year === todayYear ? todayMonth : 12;
1131
- const minDay = minY && minM && year === minY && month === minM ? minD : 1;
1132
- const maxDay = selectableRange === "until-today" && year === todayYear && month === todayMonth ? todayDay : getDaysInMonth(year || todayYear, month || 1);
1133
- const days = year && month ? Math.min(getDaysInMonth(year, month), maxDay) : 31;
1134
- const clampDay = (year2, month2, day2) => Math.min(day2, getDaysInMonth(year2, month2));
1135
- const emit = (yy, mm, dd) => {
1136
- if (mode === "year-month") {
1137
- onChange(`${yy}-${pad(mm)}`);
1138
- return;
1139
- }
1140
- const safeDay = clampDay(yy, mm, dd ?? 1);
1141
- onChange(`${yy}-${pad(mm)}-${pad(safeDay)}`);
1142
- };
1143
- const containerStyle = width ? { width: normalizeWidth(width) } : void 0;
1144
- const rootClassName = cn("date_picker", { date_picker_full_width: fullWidth && !width });
1145
- const constraintParts = [];
1146
- if (minDate) constraintParts.push(minDateSrFormat.replace("{date}", minDate));
1147
- if (selectableRange === "until-today") constraintParts.push(selectableRangeUntilTodaySrText);
1148
- const constraintDesc = constraintParts.join(". ");
1149
- return /* @__PURE__ */ jsxs("div", { className: rootClassName, style: containerStyle, children: [
1150
- label && /* @__PURE__ */ jsx("label", { className: "date_picker_label", id: groupId, children: label }),
1151
- constraintDesc && /* @__PURE__ */ jsx("span", { id: constraintId, className: "date_picker_sr_only", children: constraintDesc }),
1152
- /* @__PURE__ */ jsxs(
1153
- "div",
1154
- {
1155
- className: "date_picker_fields",
1156
- role: "group",
1157
- "aria-labelledby": label ? groupId : void 0,
1158
- "aria-describedby": constraintDesc ? constraintId : void 0,
1159
- children: [
1160
- /* @__PURE__ */ jsxs(
1161
- "select",
1162
- {
1163
- "aria-label": yearLabel,
1164
- value: year,
1165
- disabled,
1166
- onChange: (e) => emit(Number(e.target.value), month || minMonth, day || minDay),
1167
- children: [
1168
- /* @__PURE__ */ jsx("option", { value: "", children: yearLabel }),
1169
- Array.from(
1170
- { length: maxYear - startYear + 1 },
1171
- (_, i) => startYear + i
1172
- ).map((y2) => /* @__PURE__ */ jsx("option", { value: y2, children: y2 }, y2))
1173
- ]
1174
- }
1175
- ),
1176
- /* @__PURE__ */ jsxs(
1177
- "select",
1178
- {
1179
- "aria-label": monthLabel,
1180
- value: month,
1181
- disabled: disabled || !year,
1182
- onChange: (e) => emit(year, Number(e.target.value), day || minDay),
1183
- children: [
1184
- /* @__PURE__ */ jsx("option", { value: "", children: monthLabel }),
1185
- Array.from({ length: maxMonth - minMonth + 1 }, (_, i) => minMonth + i).map(
1186
- (m2) => /* @__PURE__ */ jsx("option", { value: m2, children: pad(m2) }, m2)
1187
- )
1188
- ]
1189
- }
1190
- ),
1191
- mode === "year-month-day" && /* @__PURE__ */ jsxs(
1192
- "select",
1193
- {
1194
- "aria-label": dayLabel,
1195
- value: day,
1196
- disabled: disabled || !month,
1197
- onChange: (e) => emit(year, month, Number(e.target.value)),
1198
- children: [
1199
- /* @__PURE__ */ jsx("option", { value: "", children: dayLabel }),
1200
- Array.from(
1201
- { length: days - minDay + 1 },
1202
- (_, i) => minDay + i
1203
- ).map((d2) => /* @__PURE__ */ jsx("option", { value: d2, children: pad(d2) }, d2))
1204
- ]
1205
- }
1206
- )
1207
- ]
1208
- }
1209
- )
1210
- ] });
1211
1311
  };
1212
1312
  var range = (start, end) => {
1213
1313
  const out = [];
@@ -1238,13 +1338,16 @@ var getPaginationItems = (page, totalPages) => {
1238
1338
  items.push(last);
1239
1339
  return items;
1240
1340
  };
1241
- var Pagination = ({ page, totalPages, onChange, prevLabel = "Previous page", nextLabel = "Next page" }) => {
1341
+ var Pagination = ({
1342
+ page,
1343
+ totalPages,
1344
+ onChange,
1345
+ prevLabel = "Previous page",
1346
+ nextLabel = "Next page"
1347
+ }) => {
1242
1348
  const prevDisabled = page <= 1;
1243
1349
  const nextDisabled = page >= totalPages;
1244
- const items = React6.useMemo(
1245
- () => getPaginationItems(page, totalPages),
1246
- [page, totalPages]
1247
- );
1350
+ const items = React9.useMemo(() => getPaginationItems(page, totalPages), [page, totalPages]);
1248
1351
  return /* @__PURE__ */ jsxs("nav", { className: "pagination", "aria-label": "Pagination", children: [
1249
1352
  /* @__PURE__ */ jsx(
1250
1353
  "button",
@@ -1257,16 +1360,13 @@ var Pagination = ({ page, totalPages, onChange, prevLabel = "Previous page", nex
1257
1360
  children: "\u2039"
1258
1361
  }
1259
1362
  ),
1260
- /* @__PURE__ */ jsx("div", { className: "pagination_pages", role: "list", children: items.map((it, idx) => {
1363
+ /* @__PURE__ */ jsx("ul", { className: "pagination_pages", children: items.map((it, idx) => {
1261
1364
  if (it === "ellipsis") {
1262
- return /* @__PURE__ */ jsx("span", { className: "pagination_ellipsis", "aria-hidden": "true", children: "\u2026" }, `e-${idx}`);
1365
+ return /* @__PURE__ */ jsx("li", { className: "pagination_ellipsis", "aria-hidden": "true", children: "\u2026" }, `e-${idx}`);
1263
1366
  }
1264
1367
  const isActive = it === page;
1265
- const buttonClassName = cn(
1266
- "pagination_page_button",
1267
- { pagination_active: isActive }
1268
- );
1269
- return /* @__PURE__ */ jsx("span", { role: "listitem", children: /* @__PURE__ */ jsx(
1368
+ const buttonClassName = cn("pagination_page_button", { pagination_active: isActive });
1369
+ return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx(
1270
1370
  "button",
1271
1371
  {
1272
1372
  type: "button",
@@ -1301,18 +1401,18 @@ var Modal = ({
1301
1401
  ariaLabel,
1302
1402
  ...props
1303
1403
  }) => {
1304
- const panelRef = React6.useRef(null);
1305
- const titleId = React6.useId();
1404
+ const panelRef = React9.useRef(null);
1405
+ const titleId = React9.useId();
1306
1406
  useFocusTrap(panelRef, open);
1307
- const handleEscape = React6.useEffectEvent((e) => {
1407
+ const handleEscape = React9.useEffectEvent((e) => {
1308
1408
  if (e.key === "Escape") onClose?.();
1309
1409
  });
1310
- React6.useEffect(() => {
1410
+ React9.useEffect(() => {
1311
1411
  if (!open) return;
1312
1412
  document.addEventListener("keydown", handleEscape);
1313
1413
  return () => document.removeEventListener("keydown", handleEscape);
1314
1414
  }, [open]);
1315
- React6.useEffect(() => {
1415
+ React9.useEffect(() => {
1316
1416
  if (!open) return;
1317
1417
  const body = document.body;
1318
1418
  const openModals = parseInt(body.dataset.openModals || "0", 10);
@@ -1345,13 +1445,20 @@ var Modal = ({
1345
1445
  "aria-labelledby": hasTitle && !ariaLabel ? titleId : void 0,
1346
1446
  "aria-label": !hasTitle ? ariaLabel ?? "Dialog" : ariaLabel,
1347
1447
  onClick: () => closeOnOverlay && onClose?.(),
1448
+ onKeyDown: (e) => {
1449
+ if (e.key === "Escape") onClose?.();
1450
+ },
1348
1451
  children: /* @__PURE__ */ jsxs(
1349
1452
  "div",
1350
1453
  {
1351
1454
  ref: panelRef,
1352
1455
  className: panelClassName,
1353
1456
  style: { width },
1457
+ role: "document",
1354
1458
  onClick: (e) => e.stopPropagation(),
1459
+ onKeyDown: (e) => {
1460
+ if (e.key !== "Escape") e.stopPropagation();
1461
+ },
1355
1462
  ...props,
1356
1463
  children: [
1357
1464
  title && /* @__PURE__ */ jsx("div", { id: titleId, className: "modal_header", children: title }),