@satellatickets/ui 0.0.0 → 0.2.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/web/index.js CHANGED
@@ -1,64 +1,31 @@
1
- import { UIContext, buttonIconSize, createUIContextValue, iconSizePx, textVariantStyles, useBrand, useButton, useColorScheme, useTheme } from "@satellatickets/core";
2
- import { jsx, jsxs } from "react/jsx-runtime";
1
+ import { FormFieldContext, ToastContext, UIContext, buttonIconSize, createFormFieldValue, createToastStore, createUIContextValue, firstEnabledTab, getTabInDirection, iconButtonIconSize, iconSizePx, inputIconSize, isFeedbackTone, textVariantStyles, useBrand, useButton, useColorScheme, useControllableState, useFormFieldControl, useLink, useTheme, useToast } from "@satellatickets/core";
3
2
  import { cssVariables } from "@satellatickets/tokens";
4
- import { useMemo, useSyncExternalStore } from "react";
3
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
4
+ import { useContext, useEffect, useId, useMemo, useRef, useState, useSyncExternalStore } from "react";
5
5
  //#region src/_internal/cx.ts
6
6
  /** Une clases CSS ignorando valores falsos. */
7
7
  function cx(...parts) {
8
8
  return parts.filter(Boolean).join(" ");
9
9
  }
10
10
  //#endregion
11
- //#region src/badge/Badge.module.css
12
- var Badge_module_default = {
13
- "danger": "sui-danger-ZzcBVG",
14
- "info": "sui-info-ZzcBVG",
15
- "root": "sui-root-ZzcBVG",
16
- "success": "sui-success-ZzcBVG",
17
- "warning": "sui-warning-ZzcBVG"
11
+ //#region src/_internal/feedback.ts
12
+ /** El icono refuerza el color: el tono no depende solo de él. */
13
+ const feedbackIcon = {
14
+ success: "circle-check",
15
+ warning: "triangle-alert",
16
+ danger: "circle-x",
17
+ info: "info"
18
18
  };
19
- //#endregion
20
- //#region src/badge/Badge.web.tsx
21
- const variantClass$1 = {
22
- success: Badge_module_default.success,
23
- warning: Badge_module_default.warning,
24
- danger: Badge_module_default.danger,
25
- info: Badge_module_default.info
19
+ /**
20
+ * Si el tono interrumpe al lector de pantalla (`alert`, `assertive`) o espera a que
21
+ * termine de leer (`status`, `polite`).
22
+ */
23
+ const feedbackUrgent = {
24
+ success: false,
25
+ warning: true,
26
+ danger: true,
27
+ info: false
26
28
  };
27
- function Badge({ variant = "info", className, testID, children }) {
28
- return /* @__PURE__ */ jsx("span", {
29
- className: cx(Badge_module_default.root, variantClass$1[variant], className),
30
- "data-testid": testID,
31
- children
32
- });
33
- }
34
- //#endregion
35
- //#region src/box/Box.module.css
36
- var Box_module_default = { "root": "sui-root-SDR9xW" };
37
- //#endregion
38
- //#region src/box/Box.web.tsx
39
- function Box({ as: Tag = "div", padding, paddingX, paddingY, background, radius, borderColor, shadow, flex, className, style, testID, children }) {
40
- const vars = {};
41
- if (padding !== void 0) vars["--box-padding"] = `var(${cssVariables[`space.${padding}`]})`;
42
- if (paddingX !== void 0) vars["--box-padding-x"] = `var(${cssVariables[`space.${paddingX}`]})`;
43
- if (paddingY !== void 0) vars["--box-padding-y"] = `var(${cssVariables[`space.${paddingY}`]})`;
44
- if (background !== void 0) vars["--box-background"] = `var(${cssVariables[`color.bg.${background}`]})`;
45
- if (radius !== void 0) vars["--box-radius"] = `var(${cssVariables[`radius.${radius}`]})`;
46
- if (borderColor !== void 0) {
47
- vars["--box-border-color"] = `var(${cssVariables[`color.border.${borderColor}`]})`;
48
- vars["--box-border-width"] = `var(${cssVariables["borderWidth.thin"]})`;
49
- }
50
- if (shadow !== void 0) vars["--box-shadow"] = `var(${cssVariables[`shadow.${shadow}`]})`;
51
- if (flex !== void 0) vars["--box-flex"] = String(flex);
52
- return /* @__PURE__ */ jsx(Tag, {
53
- className: cx(Box_module_default.root, className),
54
- style: {
55
- ...vars,
56
- ...style
57
- },
58
- "data-testid": testID,
59
- children
60
- });
61
- }
62
29
  //#endregion
63
30
  //#region ../icons/src/icons.ts
64
31
  const icons = {
@@ -331,7 +298,7 @@ const icons = {
331
298
  };
332
299
  //#endregion
333
300
  //#region src/icon/Icon.module.css
334
- var Icon_module_default = { "root": "sui-root-NjYZ8q" };
301
+ var Icon_module_default = { "root": "sui-root-JxbEOq" };
335
302
  //#endregion
336
303
  //#region src/icon/Icon.web.tsx
337
304
  function renderElement(element, index) {
@@ -357,6 +324,10 @@ function renderElement(element, index) {
357
324
  }, index);
358
325
  }
359
326
  }
327
+ /** Variable CSS del color: un color de texto o el icono de un estado de feedback. */
328
+ function colorVariable(color) {
329
+ return isFeedbackTone(color) ? cssVariables[`color.feedback.${color}.icon`] : cssVariables[`color.text.${color}`];
330
+ }
360
331
  function Icon({ name, size = "md", color = "primary", label, className, testID }) {
361
332
  const px = iconSizePx[size];
362
333
  const decorative = label === void 0;
@@ -366,7 +337,7 @@ function Icon({ name, size = "md", color = "primary", label, className, testID }
366
337
  height: px,
367
338
  viewBox: `0 0 24 24`,
368
339
  fill: "none",
369
- stroke: `var(${cssVariables[`color.text.${color}`]})`,
340
+ stroke: `var(${colorVariable(color)})`,
370
341
  strokeWidth: 2,
371
342
  strokeLinecap: "round",
372
343
  strokeLinejoin: "round",
@@ -379,18 +350,36 @@ function Icon({ name, size = "md", color = "primary", label, className, testID }
379
350
  });
380
351
  }
381
352
  //#endregion
353
+ //#region src/button/Button.module.css
354
+ var Button_module_default = {
355
+ "content": "sui-content-FZ-IiW",
356
+ "danger": "sui-danger-FZ-IiW",
357
+ "fullWidth": "sui-fullWidth-FZ-IiW",
358
+ "ghost": "sui-ghost-FZ-IiW",
359
+ "label": "sui-label-FZ-IiW",
360
+ "lg": "sui-lg-FZ-IiW",
361
+ "loading": "sui-loading-FZ-IiW",
362
+ "md": "sui-md-FZ-IiW",
363
+ "primary": "sui-primary-FZ-IiW",
364
+ "root": "sui-root-FZ-IiW",
365
+ "secondary": "sui-secondary-FZ-IiW",
366
+ "sm": "sui-sm-FZ-IiW",
367
+ "spinner": "sui-spinner-FZ-IiW"
368
+ };
369
+ //#endregion
382
370
  //#region src/spinner/Spinner.module.css
383
371
  var Spinner_module_default = {
384
- "icon": "sui-icon-g-Gv2a",
385
- "root": "sui-root-g-Gv2a",
386
- "spin": "sui-spin-g-Gv2a"
372
+ "icon": "sui-icon-iFfE_q",
373
+ "root": "sui-root-iFfE_q",
374
+ "spin": "sui-spin-iFfE_q"
387
375
  };
388
376
  //#endregion
389
377
  //#region src/spinner/Spinner.web.tsx
390
378
  /**
391
- * Indicador de carga indeterminada. Versión mínima (ROADMAP Fase 3): el icono
392
- * `loader-circle` girando. Con `label` es una barra de progreso indeterminada
393
- * para los lectores de pantalla; sin él, es decorativo.
379
+ * Indicador de carga indeterminada: el icono `loader-circle` girando. Con `label` es
380
+ * una barra de progreso indeterminada para los lectores de pantalla; sin él, es
381
+ * decorativo. Con movimiento reducido gira más despacio, pero no se detiene: parado
382
+ * no diría que algo está en curso.
394
383
  */
395
384
  function Spinner({ size = "md", color = "primary", label, className, testID }) {
396
385
  const decorative = label === void 0;
@@ -409,31 +398,179 @@ function Spinner({ size = "md", color = "primary", label, className, testID }) {
409
398
  });
410
399
  }
411
400
  //#endregion
412
- //#region src/button/Button.module.css
413
- var Button_module_default = {
414
- "content": "sui-content--HHqDW",
415
- "danger": "sui-danger--HHqDW",
416
- "fullWidth": "sui-fullWidth--HHqDW",
417
- "ghost": "sui-ghost--HHqDW",
418
- "label": "sui-label--HHqDW",
419
- "lg": "sui-lg--HHqDW",
420
- "loading": "sui-loading--HHqDW",
421
- "md": "sui-md--HHqDW",
422
- "primary": "sui-primary--HHqDW",
423
- "root": "sui-root--HHqDW",
424
- "secondary": "sui-secondary--HHqDW",
425
- "sm": "sui-sm--HHqDW",
426
- "spinner": "sui-spinner--HHqDW"
401
+ //#region src/icon-button/IconButton.module.css
402
+ var IconButton_module_default = {
403
+ "lg": "sui-lg-f0wlja",
404
+ "md": "sui-md-f0wlja",
405
+ "sm": "sui-sm-f0wlja"
406
+ };
407
+ //#endregion
408
+ //#region src/icon-button/IconButton.web.tsx
409
+ const variantClass$3 = {
410
+ primary: Button_module_default.primary,
411
+ secondary: Button_module_default.secondary,
412
+ ghost: Button_module_default.ghost,
413
+ danger: Button_module_default.danger
414
+ };
415
+ const sizeClass$3 = {
416
+ sm: IconButton_module_default.sm,
417
+ md: IconButton_module_default.md,
418
+ lg: IconButton_module_default.lg
419
+ };
420
+ function IconButton({ icon, label, variant = "ghost", size = "md", disabled = false, loading = false, onPress, type = "button", className, style, testID, ref }) {
421
+ const { interactive, press } = useButton({
422
+ disabled,
423
+ loading,
424
+ onPress
425
+ });
426
+ const iconSize = iconButtonIconSize[size];
427
+ function handleClick(event) {
428
+ if (!interactive) event.preventDefault();
429
+ press();
430
+ }
431
+ return /* @__PURE__ */ jsxs("button", {
432
+ ref,
433
+ type,
434
+ className: cx(Button_module_default.root, variantClass$3[variant], sizeClass$3[size], loading && Button_module_default.loading, className),
435
+ style,
436
+ disabled,
437
+ "aria-disabled": loading ? true : void 0,
438
+ "aria-busy": loading ? true : void 0,
439
+ "aria-label": label,
440
+ "data-testid": testID,
441
+ onClick: handleClick,
442
+ children: [/* @__PURE__ */ jsx("span", {
443
+ className: Button_module_default.content,
444
+ children: /* @__PURE__ */ jsx(Icon, {
445
+ name: icon,
446
+ size: iconSize
447
+ })
448
+ }), loading ? /* @__PURE__ */ jsx("span", {
449
+ className: Button_module_default.spinner,
450
+ children: /* @__PURE__ */ jsx(Spinner, { size: iconSize })
451
+ }) : null]
452
+ });
453
+ }
454
+ //#endregion
455
+ //#region src/alert/Alert.module.css
456
+ var Alert_module_default = {
457
+ "close": "sui-close-hPKSzG",
458
+ "content": "sui-content-hPKSzG",
459
+ "danger": "sui-danger-hPKSzG",
460
+ "description": "sui-description-hPKSzG",
461
+ "icon": "sui-icon-hPKSzG",
462
+ "info": "sui-info-hPKSzG",
463
+ "root": "sui-root-hPKSzG",
464
+ "success": "sui-success-hPKSzG",
465
+ "title": "sui-title-hPKSzG",
466
+ "warning": "sui-warning-hPKSzG"
427
467
  };
428
468
  //#endregion
469
+ //#region src/alert/Alert.web.tsx
470
+ const toneClass = {
471
+ success: Alert_module_default.success,
472
+ warning: Alert_module_default.warning,
473
+ danger: Alert_module_default.danger,
474
+ info: Alert_module_default.info
475
+ };
476
+ function Alert({ tone = "info", title, onClose, closeLabel, className, style, testID, children }) {
477
+ const hasDescription = children !== void 0 && children !== null;
478
+ return /* @__PURE__ */ jsxs("div", {
479
+ className: cx(Alert_module_default.root, toneClass[tone], className),
480
+ style,
481
+ role: feedbackUrgent[tone] ? "alert" : "status",
482
+ "data-testid": testID,
483
+ children: [
484
+ /* @__PURE__ */ jsx("span", {
485
+ className: Alert_module_default.icon,
486
+ children: /* @__PURE__ */ jsx(Icon, {
487
+ name: feedbackIcon[tone],
488
+ size: "md",
489
+ color: tone
490
+ })
491
+ }),
492
+ /* @__PURE__ */ jsxs("div", {
493
+ className: Alert_module_default.content,
494
+ children: [title === void 0 ? null : /* @__PURE__ */ jsx("p", {
495
+ className: Alert_module_default.title,
496
+ children: title
497
+ }), hasDescription ? /* @__PURE__ */ jsx("div", {
498
+ className: Alert_module_default.description,
499
+ children
500
+ }) : null]
501
+ }),
502
+ onClose === void 0 ? null : /* @__PURE__ */ jsx(IconButton, {
503
+ icon: "x",
504
+ label: closeLabel,
505
+ size: "sm",
506
+ variant: "ghost",
507
+ onPress: onClose,
508
+ className: Alert_module_default.close
509
+ })
510
+ ]
511
+ });
512
+ }
513
+ //#endregion
514
+ //#region src/badge/Badge.module.css
515
+ var Badge_module_default = {
516
+ "danger": "sui-danger-iCOp0a",
517
+ "info": "sui-info-iCOp0a",
518
+ "root": "sui-root-iCOp0a",
519
+ "success": "sui-success-iCOp0a",
520
+ "warning": "sui-warning-iCOp0a"
521
+ };
522
+ //#endregion
523
+ //#region src/badge/Badge.web.tsx
524
+ const variantClass$2 = {
525
+ success: Badge_module_default.success,
526
+ warning: Badge_module_default.warning,
527
+ danger: Badge_module_default.danger,
528
+ info: Badge_module_default.info
529
+ };
530
+ function Badge({ variant = "info", className, testID, children }) {
531
+ return /* @__PURE__ */ jsx("span", {
532
+ className: cx(Badge_module_default.root, variantClass$2[variant], className),
533
+ "data-testid": testID,
534
+ children
535
+ });
536
+ }
537
+ //#endregion
538
+ //#region src/box/Box.module.css
539
+ var Box_module_default = { "root": "sui-root-fYQz2a" };
540
+ //#endregion
541
+ //#region src/box/Box.web.tsx
542
+ function Box({ as: Tag = "div", padding, paddingX, paddingY, background, radius, borderColor, shadow, flex, className, style, testID, children }) {
543
+ const vars = {};
544
+ if (padding !== void 0) vars["--box-padding"] = `var(${cssVariables[`space.${padding}`]})`;
545
+ if (paddingX !== void 0) vars["--box-padding-x"] = `var(${cssVariables[`space.${paddingX}`]})`;
546
+ if (paddingY !== void 0) vars["--box-padding-y"] = `var(${cssVariables[`space.${paddingY}`]})`;
547
+ if (background !== void 0) vars["--box-background"] = `var(${cssVariables[`color.bg.${background}`]})`;
548
+ if (radius !== void 0) vars["--box-radius"] = `var(${cssVariables[`radius.${radius}`]})`;
549
+ if (borderColor !== void 0) {
550
+ vars["--box-border-color"] = `var(${cssVariables[`color.border.${borderColor}`]})`;
551
+ vars["--box-border-width"] = `var(${cssVariables["borderWidth.thin"]})`;
552
+ }
553
+ if (shadow !== void 0) vars["--box-shadow"] = `var(${cssVariables[`shadow.${shadow}`]})`;
554
+ if (flex !== void 0) vars["--box-flex"] = String(flex);
555
+ return /* @__PURE__ */ jsx(Tag, {
556
+ className: cx(Box_module_default.root, className),
557
+ style: {
558
+ ...vars,
559
+ ...style
560
+ },
561
+ "data-testid": testID,
562
+ children
563
+ });
564
+ }
565
+ //#endregion
429
566
  //#region src/button/Button.web.tsx
430
- const variantClass = {
567
+ const variantClass$1 = {
431
568
  primary: Button_module_default.primary,
432
569
  secondary: Button_module_default.secondary,
433
570
  ghost: Button_module_default.ghost,
434
571
  danger: Button_module_default.danger
435
572
  };
436
- const sizeClass = {
573
+ const sizeClass$2 = {
437
574
  sm: Button_module_default.sm,
438
575
  md: Button_module_default.md,
439
576
  lg: Button_module_default.lg
@@ -452,7 +589,7 @@ function Button({ variant = "primary", size = "md", disabled = false, loading =
452
589
  return /* @__PURE__ */ jsxs("button", {
453
590
  ref,
454
591
  type,
455
- className: cx(Button_module_default.root, variantClass[variant], sizeClass[size], fullWidth && Button_module_default.fullWidth, loading && Button_module_default.loading, className),
592
+ className: cx(Button_module_default.root, variantClass$1[variant], sizeClass$2[size], fullWidth && Button_module_default.fullWidth, loading && Button_module_default.loading, className),
456
593
  style,
457
594
  disabled,
458
595
  "aria-disabled": loading ? true : void 0,
@@ -483,21 +620,613 @@ function Button({ variant = "primary", size = "md", disabled = false, loading =
483
620
  });
484
621
  }
485
622
  //#endregion
623
+ //#region src/card/Card.module.css
624
+ var Card_module_default = {
625
+ "elevated": "sui-elevated-So50QW",
626
+ "interactive": "sui-interactive-So50QW",
627
+ "outlined": "sui-outlined-So50QW",
628
+ "root": "sui-root-So50QW"
629
+ };
630
+ //#endregion
631
+ //#region src/card/Card.web.tsx
632
+ const variantClass = {
633
+ outlined: Card_module_default.outlined,
634
+ elevated: Card_module_default.elevated
635
+ };
636
+ function Card({ variant = "outlined", padding = 4, onPress, accessibilityLabel, className, style, testID, ref, children }) {
637
+ const vars = { "--card-padding": `var(${cssVariables[`space.${padding}`]})` };
638
+ const classes = cx(Card_module_default.root, variantClass[variant], onPress !== void 0 && Card_module_default.interactive, className);
639
+ if (onPress === void 0) return /* @__PURE__ */ jsx("div", {
640
+ ref,
641
+ className: classes,
642
+ style: {
643
+ ...vars,
644
+ ...style
645
+ },
646
+ "data-testid": testID,
647
+ children
648
+ });
649
+ function handleKeyDown(event) {
650
+ if (event.target !== event.currentTarget) return;
651
+ if (event.key !== "Enter" && event.key !== " ") return;
652
+ event.preventDefault();
653
+ onPress?.();
654
+ }
655
+ return /* @__PURE__ */ jsx("div", {
656
+ ref,
657
+ role: "button",
658
+ tabIndex: 0,
659
+ className: classes,
660
+ style: {
661
+ ...vars,
662
+ ...style
663
+ },
664
+ "aria-label": accessibilityLabel,
665
+ "data-testid": testID,
666
+ onClick: onPress,
667
+ onKeyDown: handleKeyDown,
668
+ children
669
+ });
670
+ }
671
+ //#endregion
672
+ //#region src/_internal/mergeRefs.ts
673
+ /** Un solo `ref` que actualiza varios: el interno del componente y el que recibe por props. */
674
+ function mergeRefs(...refs) {
675
+ return (node) => {
676
+ for (const ref of refs) if (typeof ref === "function") ref(node);
677
+ else if (ref !== null && ref !== void 0) ref.current = node;
678
+ };
679
+ }
680
+ //#endregion
681
+ //#region src/checkbox/Checkbox.module.css
682
+ var Checkbox_module_default = {
683
+ "box": "sui-box-iE7-OG",
684
+ "check": "sui-check-iE7-OG",
685
+ "dash": "sui-dash-iE7-OG",
686
+ "disabled": "sui-disabled-iE7-OG",
687
+ "input": "sui-input-iE7-OG",
688
+ "invalid": "sui-invalid-iE7-OG",
689
+ "label": "sui-label-iE7-OG",
690
+ "mark": "sui-mark-iE7-OG",
691
+ "root": "sui-root-iE7-OG"
692
+ };
693
+ //#endregion
694
+ //#region src/checkbox/Checkbox.web.tsx
695
+ function Checkbox({ checked, defaultChecked, indeterminate = false, onCheckedChange, disabled = false, invalid = false, required = false, accessibilityLabel, id, name, value, className, style, testID, ref, children }) {
696
+ const input = useRef(null);
697
+ const setRef = useMemo(() => mergeRefs(input, ref), [ref]);
698
+ useEffect(() => {
699
+ if (input.current !== null) input.current.indeterminate = indeterminate;
700
+ }, [indeterminate]);
701
+ return /* @__PURE__ */ jsxs("label", {
702
+ className: cx(Checkbox_module_default.root, disabled && Checkbox_module_default.disabled, className),
703
+ style,
704
+ children: [
705
+ /* @__PURE__ */ jsx("input", {
706
+ ref: setRef,
707
+ type: "checkbox",
708
+ className: Checkbox_module_default.input,
709
+ id,
710
+ name,
711
+ value,
712
+ ...checked === void 0 ? { defaultChecked } : { checked },
713
+ onChange: (event) => onCheckedChange?.(event.target.checked),
714
+ disabled,
715
+ "aria-label": accessibilityLabel,
716
+ "aria-invalid": invalid ? true : void 0,
717
+ "aria-required": required ? true : void 0,
718
+ "data-testid": testID
719
+ }),
720
+ /* @__PURE__ */ jsxs("span", {
721
+ className: cx(Checkbox_module_default.box, invalid && Checkbox_module_default.invalid),
722
+ "aria-hidden": "true",
723
+ children: [/* @__PURE__ */ jsx(Icon, {
724
+ name: "check",
725
+ size: "sm",
726
+ color: "onPrimary",
727
+ className: cx(Checkbox_module_default.mark, Checkbox_module_default.check)
728
+ }), /* @__PURE__ */ jsx(Icon, {
729
+ name: "minus",
730
+ size: "sm",
731
+ color: "onPrimary",
732
+ className: cx(Checkbox_module_default.mark, Checkbox_module_default.dash)
733
+ })]
734
+ }),
735
+ children === void 0 || children === null ? null : /* @__PURE__ */ jsx("span", {
736
+ className: Checkbox_module_default.label,
737
+ children
738
+ })
739
+ ]
740
+ });
741
+ }
742
+ //#endregion
743
+ //#region src/divider/Divider.module.css
744
+ var Divider_module_default = {
745
+ "horizontal": "sui-horizontal-Ea_Ija",
746
+ "root": "sui-root-Ea_Ija",
747
+ "vertical": "sui-vertical-Ea_Ija"
748
+ };
749
+ //#endregion
750
+ //#region src/divider/Divider.web.tsx
751
+ const orientationClass = {
752
+ horizontal: Divider_module_default.horizontal,
753
+ vertical: Divider_module_default.vertical
754
+ };
755
+ function Divider({ orientation = "horizontal", className, testID }) {
756
+ const classes = cx(Divider_module_default.root, orientationClass[orientation], className);
757
+ return orientation === "horizontal" ? /* @__PURE__ */ jsx("hr", {
758
+ className: classes,
759
+ "data-testid": testID
760
+ }) : /* @__PURE__ */ jsx("div", {
761
+ role: "separator",
762
+ "aria-orientation": "vertical",
763
+ className: classes,
764
+ "data-testid": testID
765
+ });
766
+ }
767
+ //#endregion
768
+ //#region src/form-field/FormField.module.css
769
+ var FormField_module_default = {
770
+ "disabled": "sui-disabled-E2FhZq",
771
+ "error": "sui-error-E2FhZq",
772
+ "errorIcon": "sui-errorIcon-E2FhZq",
773
+ "help": "sui-help-E2FhZq",
774
+ "label": "sui-label-E2FhZq",
775
+ "required": "sui-required-E2FhZq",
776
+ "root": "sui-root-E2FhZq"
777
+ };
778
+ //#endregion
779
+ //#region src/form-field/FormField.web.tsx
780
+ /**
781
+ * Etiqueta, ayuda y error de un control (ADR-037). El `<label>` apunta al `id` que
782
+ * toma el control, y la ayuda y el error se enlazan con `aria-describedby`.
783
+ */
784
+ function FormField({ label, help, error, required = false, disabled = false, className, testID, children }) {
785
+ const baseId = useId();
786
+ const field = useMemo(() => createFormFieldValue(baseId, {
787
+ label,
788
+ help,
789
+ error,
790
+ disabled,
791
+ required
792
+ }), [
793
+ baseId,
794
+ label,
795
+ help,
796
+ error,
797
+ disabled,
798
+ required
799
+ ]);
800
+ return /* @__PURE__ */ jsx(FormFieldContext.Provider, {
801
+ value: field,
802
+ children: /* @__PURE__ */ jsxs("div", {
803
+ className: cx(FormField_module_default.root, disabled && FormField_module_default.disabled, className),
804
+ "data-testid": testID,
805
+ children: [
806
+ /* @__PURE__ */ jsxs("label", {
807
+ className: FormField_module_default.label,
808
+ htmlFor: field.controlId,
809
+ children: [label, required ? /* @__PURE__ */ jsx("span", {
810
+ className: FormField_module_default.required,
811
+ "aria-hidden": "true",
812
+ children: " *"
813
+ }) : null]
814
+ }),
815
+ children,
816
+ field.help === void 0 ? null : /* @__PURE__ */ jsx("p", {
817
+ id: field.helpId,
818
+ className: FormField_module_default.help,
819
+ children: field.help
820
+ }),
821
+ /* @__PURE__ */ jsx("div", {
822
+ "aria-live": "polite",
823
+ children: field.error === void 0 ? null : /* @__PURE__ */ jsxs("p", {
824
+ id: field.errorId,
825
+ className: FormField_module_default.error,
826
+ children: [/* @__PURE__ */ jsx("span", {
827
+ className: FormField_module_default.errorIcon,
828
+ children: /* @__PURE__ */ jsx(Icon, {
829
+ name: "circle-alert",
830
+ size: "sm",
831
+ color: "danger"
832
+ })
833
+ }), field.error]
834
+ })
835
+ })
836
+ ]
837
+ })
838
+ });
839
+ }
840
+ //#endregion
841
+ //#region src/_internal/field.module.css
842
+ var field_module_default = {
843
+ "control": "sui-control-jPIPoq",
844
+ "disabled": "sui-disabled-jPIPoq",
845
+ "field": "sui-field-jPIPoq",
846
+ "invalid": "sui-invalid-jPIPoq",
847
+ "readOnly": "sui-readOnly-jPIPoq"
848
+ };
849
+ //#endregion
850
+ //#region src/input/Input.module.css
851
+ var Input_module_default = {
852
+ "input": "sui-input-DAA5va",
853
+ "lg": "sui-lg-DAA5va",
854
+ "md": "sui-md-DAA5va",
855
+ "root": "sui-root-DAA5va",
856
+ "sm": "sui-sm-DAA5va"
857
+ };
858
+ //#endregion
859
+ //#region src/input/Input.web.tsx
860
+ const typeAttributes = {
861
+ text: { type: "text" },
862
+ email: { type: "email" },
863
+ password: { type: "password" },
864
+ search: { type: "search" },
865
+ tel: { type: "tel" },
866
+ url: { type: "url" },
867
+ number: {
868
+ type: "text",
869
+ inputMode: "decimal"
870
+ }
871
+ };
872
+ const sizeClass$1 = {
873
+ sm: Input_module_default.sm,
874
+ md: Input_module_default.md,
875
+ lg: Input_module_default.lg
876
+ };
877
+ function Input({ value, defaultValue, onChangeText, placeholder, type = "text", size = "md", disabled, readOnly = false, invalid, required, iconStart, iconEnd, maxLength, onFocus, onBlur, onSubmit, accessibilityLabel, id, name, autoComplete, className, style, testID, ref }) {
878
+ const control = useFormFieldControl({
879
+ id,
880
+ invalid,
881
+ disabled,
882
+ required
883
+ });
884
+ const attributes = typeAttributes[type];
885
+ const iconSize = inputIconSize[size];
886
+ const iconColor = control.disabled ? "disabled" : "muted";
887
+ function handleMouseDown(event) {
888
+ const input = event.currentTarget.querySelector("input");
889
+ if (input === null || event.target === input || control.disabled) return;
890
+ event.preventDefault();
891
+ input.focus();
892
+ }
893
+ function handleKeyDown(event) {
894
+ if (event.key === "Enter" && !event.nativeEvent.isComposing) onSubmit?.();
895
+ }
896
+ return /* @__PURE__ */ jsxs("div", {
897
+ className: cx(field_module_default.field, Input_module_default.root, sizeClass$1[size], control.invalid && field_module_default.invalid, readOnly && field_module_default.readOnly, control.disabled && field_module_default.disabled, className),
898
+ style,
899
+ onMouseDown: handleMouseDown,
900
+ children: [
901
+ iconStart === void 0 ? null : /* @__PURE__ */ jsx(Icon, {
902
+ name: iconStart,
903
+ size: iconSize,
904
+ color: iconColor
905
+ }),
906
+ /* @__PURE__ */ jsx("input", {
907
+ ref,
908
+ id: control.id,
909
+ className: cx(field_module_default.control, Input_module_default.input),
910
+ type: attributes.type,
911
+ inputMode: attributes.inputMode,
912
+ name,
913
+ autoComplete,
914
+ ...value === void 0 ? { defaultValue } : { value },
915
+ onChange: (event) => onChangeText?.(event.target.value),
916
+ placeholder,
917
+ disabled: control.disabled,
918
+ readOnly,
919
+ maxLength,
920
+ "aria-label": accessibilityLabel,
921
+ "aria-describedby": control.describedBy,
922
+ "aria-invalid": control.invalid ? true : void 0,
923
+ "aria-required": control.required ? true : void 0,
924
+ "data-testid": testID,
925
+ onFocus,
926
+ onBlur,
927
+ onKeyDown: handleKeyDown
928
+ }),
929
+ iconEnd === void 0 ? null : /* @__PURE__ */ jsx(Icon, {
930
+ name: iconEnd,
931
+ size: iconSize,
932
+ color: iconColor
933
+ })
934
+ ]
935
+ });
936
+ }
937
+ //#endregion
938
+ //#region src/link/Link.module.css
939
+ var Link_module_default = {
940
+ "always": "sui-always-5twIfq",
941
+ "hover": "sui-hover-5twIfq",
942
+ "root": "sui-root-5twIfq",
943
+ "typed": "sui-typed-5twIfq",
944
+ "uppercase": "sui-uppercase-5twIfq"
945
+ };
946
+ //#endregion
947
+ //#region src/link/Link.web.tsx
948
+ const underlineClass = {
949
+ always: Link_module_default.always,
950
+ hover: Link_module_default.hover
951
+ };
952
+ function Link({ href, variant, color = "link", underline = "always", onPress, accessibilityLabel, target, rel, className, style, testID, ref, children }) {
953
+ const { press } = useLink({ onPress });
954
+ const spec = variant === void 0 ? void 0 : textVariantStyles[variant];
955
+ const vars = { "--link-color": `var(${cssVariables[`color.text.${color}`]})` };
956
+ if (spec !== void 0) {
957
+ vars["--link-family"] = `var(${cssVariables[`font.family.${spec.family}`]})`;
958
+ vars["--link-size"] = `var(${cssVariables[`font.size.${spec.size}`]})`;
959
+ vars["--link-line-height"] = `var(${cssVariables[`font.lineHeight.${spec.size}`]})`;
960
+ vars["--link-weight"] = `var(${cssVariables[`font.weight.${spec.weight}`]})`;
961
+ if (spec.letterSpacing !== void 0) vars["--link-letter-spacing"] = `${spec.letterSpacing}px`;
962
+ }
963
+ function handleClick(event) {
964
+ if (event.button !== 0 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
965
+ if (!press()) event.preventDefault();
966
+ }
967
+ return /* @__PURE__ */ jsx("a", {
968
+ ref,
969
+ href,
970
+ target,
971
+ rel: rel ?? (target === "_blank" ? "noopener noreferrer" : void 0),
972
+ className: cx(Link_module_default.root, underlineClass[underline], spec !== void 0 && Link_module_default.typed, spec?.uppercase && Link_module_default.uppercase, className),
973
+ style: {
974
+ ...vars,
975
+ ...style
976
+ },
977
+ "aria-label": accessibilityLabel,
978
+ "data-testid": testID,
979
+ onClick: handleClick,
980
+ children
981
+ });
982
+ }
983
+ //#endregion
984
+ //#region src/modal/Modal.module.css
985
+ var Modal_module_default = {
986
+ "body": "sui-body-M_CPgW",
987
+ "close": "sui-close-M_CPgW",
988
+ "description": "sui-description-M_CPgW",
989
+ "dialog": "sui-dialog-M_CPgW",
990
+ "footer": "sui-footer-M_CPgW",
991
+ "header": "sui-header-M_CPgW",
992
+ "root": "sui-root-M_CPgW",
993
+ "sheet": "sui-sheet-M_CPgW",
994
+ "title": "sui-title-M_CPgW",
995
+ "titles": "sui-titles-M_CPgW"
996
+ };
997
+ //#endregion
998
+ //#region src/modal/ModalDialog.web.tsx
999
+ const presentationClass = {
1000
+ dialog: Modal_module_default.dialog,
1001
+ sheet: Modal_module_default.sheet
1002
+ };
1003
+ /**
1004
+ * La implementación que comparten `Modal` y `Sheet` (ADR-040): un `<dialog>` real
1005
+ * abierto con `showModal()`. El foco, la inercia del fondo y el apilamiento los
1006
+ * resuelve el navegador.
1007
+ */
1008
+ function ModalDialog({ presentation, open, onClose, title, description, closeLabel, dismissible = true, footer, className, style, testID, ref, children }) {
1009
+ const dialog = useRef(null);
1010
+ const setRef = useMemo(() => mergeRefs(dialog, ref), [ref]);
1011
+ const titleId = useId();
1012
+ const descriptionId = useId();
1013
+ useEffect(() => {
1014
+ const element = dialog.current;
1015
+ if (element === null) return;
1016
+ if (open && !element.open) element.showModal();
1017
+ else if (!open && element.open) element.close();
1018
+ }, [open]);
1019
+ function handleCancel(event) {
1020
+ event.preventDefault();
1021
+ if (dismissible) onClose();
1022
+ }
1023
+ function handleNativeClose() {
1024
+ if (open) onClose();
1025
+ }
1026
+ function handleClick(event) {
1027
+ if (event.target === event.currentTarget && dismissible) onClose();
1028
+ }
1029
+ const hasBody = children !== void 0 && children !== null;
1030
+ const hasFooter = footer !== void 0 && footer !== null;
1031
+ return /* @__PURE__ */ jsx("dialog", {
1032
+ ref: setRef,
1033
+ className: cx(Modal_module_default.root, presentationClass[presentation], className),
1034
+ style,
1035
+ "aria-labelledby": titleId,
1036
+ "aria-describedby": description === void 0 ? void 0 : descriptionId,
1037
+ "data-testid": testID,
1038
+ onCancel: handleCancel,
1039
+ onClose: handleNativeClose,
1040
+ onClick: handleClick,
1041
+ children: open ? /* @__PURE__ */ jsxs(Fragment, { children: [
1042
+ /* @__PURE__ */ jsxs("div", {
1043
+ className: Modal_module_default.header,
1044
+ children: [/* @__PURE__ */ jsxs("div", {
1045
+ className: Modal_module_default.titles,
1046
+ children: [/* @__PURE__ */ jsx("h2", {
1047
+ id: titleId,
1048
+ className: Modal_module_default.title,
1049
+ children: title
1050
+ }), description === void 0 ? null : /* @__PURE__ */ jsx("p", {
1051
+ id: descriptionId,
1052
+ className: Modal_module_default.description,
1053
+ children: description
1054
+ })]
1055
+ }), closeLabel === void 0 ? null : /* @__PURE__ */ jsx(IconButton, {
1056
+ icon: "x",
1057
+ label: closeLabel,
1058
+ size: "sm",
1059
+ variant: "ghost",
1060
+ onPress: onClose,
1061
+ className: Modal_module_default.close
1062
+ })]
1063
+ }),
1064
+ hasBody ? /* @__PURE__ */ jsx("div", {
1065
+ className: Modal_module_default.body,
1066
+ children
1067
+ }) : null,
1068
+ hasFooter ? /* @__PURE__ */ jsx("div", {
1069
+ className: Modal_module_default.footer,
1070
+ children: footer
1071
+ }) : null
1072
+ ] }) : null
1073
+ });
1074
+ }
1075
+ //#endregion
1076
+ //#region src/modal/Modal.web.tsx
1077
+ /** Un diálogo centrado (ADR-040). */
1078
+ function Modal(props) {
1079
+ return /* @__PURE__ */ jsx(ModalDialog, {
1080
+ ...props,
1081
+ presentation: "dialog"
1082
+ });
1083
+ }
1084
+ //#endregion
1085
+ //#region src/select/Select.module.css
1086
+ var Select_module_default = {
1087
+ "chevron": "sui-chevron-Rxx4wG",
1088
+ "lg": "sui-lg-Rxx4wG",
1089
+ "md": "sui-md-Rxx4wG",
1090
+ "placeholder": "sui-placeholder-Rxx4wG",
1091
+ "root": "sui-root-Rxx4wG",
1092
+ "select": "sui-select-Rxx4wG",
1093
+ "sm": "sui-sm-Rxx4wG"
1094
+ };
1095
+ //#endregion
1096
+ //#region src/select/Select.web.tsx
1097
+ const sizeClass = {
1098
+ sm: Select_module_default.sm,
1099
+ md: Select_module_default.md,
1100
+ lg: Select_module_default.lg
1101
+ };
1102
+ /**
1103
+ * Un `<select>` real (ADR-038): el teclado, los lectores de pantalla y el selector del
1104
+ * sistema en móvil son los del navegador.
1105
+ */
1106
+ function Select({ options, value, defaultValue, onValueChange, placeholder, size = "md", disabled, invalid, required, accessibilityLabel, id, name, className, style, testID, ref }) {
1107
+ const control = useFormFieldControl({
1108
+ id,
1109
+ invalid,
1110
+ disabled,
1111
+ required
1112
+ });
1113
+ const [current, setCurrent] = useControllableState({
1114
+ value,
1115
+ defaultValue: defaultValue ?? "",
1116
+ onChange: onValueChange
1117
+ });
1118
+ return /* @__PURE__ */ jsxs("div", {
1119
+ className: cx(field_module_default.field, Select_module_default.root, sizeClass[size], control.invalid && field_module_default.invalid, control.disabled && field_module_default.disabled, className),
1120
+ style,
1121
+ children: [/* @__PURE__ */ jsxs("select", {
1122
+ ref,
1123
+ id: control.id,
1124
+ className: cx(field_module_default.control, Select_module_default.select, current === "" && Select_module_default.placeholder),
1125
+ name,
1126
+ value: current,
1127
+ onChange: (event) => setCurrent(event.target.value),
1128
+ disabled: control.disabled,
1129
+ "aria-label": accessibilityLabel,
1130
+ "aria-describedby": control.describedBy,
1131
+ "aria-invalid": control.invalid ? true : void 0,
1132
+ "aria-required": control.required ? true : void 0,
1133
+ "data-testid": testID,
1134
+ children: [/* @__PURE__ */ jsx("option", {
1135
+ value: "",
1136
+ disabled: true,
1137
+ hidden: true,
1138
+ children: placeholder ?? ""
1139
+ }), options.map((option) => /* @__PURE__ */ jsx("option", {
1140
+ value: option.value,
1141
+ disabled: option.disabled,
1142
+ children: option.label
1143
+ }, option.value))]
1144
+ }), /* @__PURE__ */ jsx("span", {
1145
+ className: Select_module_default.chevron,
1146
+ "aria-hidden": "true",
1147
+ children: /* @__PURE__ */ jsx(Icon, {
1148
+ name: "chevron-down",
1149
+ size: inputIconSize[size],
1150
+ color: control.disabled ? "disabled" : "muted"
1151
+ })
1152
+ })]
1153
+ });
1154
+ }
1155
+ //#endregion
1156
+ //#region src/sheet/Sheet.web.tsx
1157
+ /** Un diálogo anclado al borde inferior (ADR-040). Comparte todo con `Modal` salvo dónde se coloca. */
1158
+ function Sheet(props) {
1159
+ return /* @__PURE__ */ jsx(ModalDialog, {
1160
+ ...props,
1161
+ presentation: "sheet"
1162
+ });
1163
+ }
1164
+ //#endregion
1165
+ //#region src/skeleton/Skeleton.module.css
1166
+ var Skeleton_module_default = {
1167
+ "bar": "sui-bar-KsqoQq",
1168
+ "circle": "sui-circle-KsqoQq",
1169
+ "line": "sui-line-KsqoQq",
1170
+ "pulse": "sui-pulse-KsqoQq",
1171
+ "rectangle": "sui-rectangle-KsqoQq",
1172
+ "root": "sui-root-KsqoQq"
1173
+ };
1174
+ //#endregion
1175
+ //#region src/skeleton/Skeleton.web.tsx
1176
+ const shapeClass = {
1177
+ text: Skeleton_module_default.line,
1178
+ rectangle: Skeleton_module_default.rectangle,
1179
+ circle: Skeleton_module_default.circle
1180
+ };
1181
+ function dimension(value) {
1182
+ return typeof value === "number" ? `${value}px` : value;
1183
+ }
1184
+ /** Decorativo: los lectores de pantalla lo ignoran. */
1185
+ function Skeleton({ shape = "text", width, height, variant = "body", lines = 1, className, style, testID }) {
1186
+ const vars = {};
1187
+ if (width !== void 0) vars["--skeleton-width"] = dimension(width);
1188
+ if (shape === "text") {
1189
+ const spec = textVariantStyles[variant];
1190
+ vars["--skeleton-font-size"] = `var(${cssVariables[`font.size.${spec.size}`]})`;
1191
+ vars["--skeleton-line-height"] = `var(${cssVariables[`font.lineHeight.${spec.size}`]})`;
1192
+ return /* @__PURE__ */ jsx("span", {
1193
+ className: cx(Skeleton_module_default.root, className),
1194
+ style: {
1195
+ ...vars,
1196
+ ...style
1197
+ },
1198
+ "aria-hidden": "true",
1199
+ "data-testid": testID,
1200
+ children: Array.from({ length: Math.max(1, lines) }, (_, index) => /* @__PURE__ */ jsx("span", { className: cx(Skeleton_module_default.bar, shapeClass.text) }, index))
1201
+ });
1202
+ }
1203
+ if (height !== void 0) vars["--skeleton-height"] = dimension(height);
1204
+ return /* @__PURE__ */ jsx("span", {
1205
+ className: cx(Skeleton_module_default.root, Skeleton_module_default.bar, shapeClass[shape], className),
1206
+ style: {
1207
+ ...vars,
1208
+ ...style
1209
+ },
1210
+ "aria-hidden": "true",
1211
+ "data-testid": testID
1212
+ });
1213
+ }
1214
+ //#endregion
486
1215
  //#region src/stack/Stack.module.css
487
1216
  var Stack_module_default = {
488
- "alignCenter": "sui-alignCenter-xABqRa",
489
- "alignEnd": "sui-alignEnd-xABqRa",
490
- "alignStart": "sui-alignStart-xABqRa",
491
- "alignStretch": "sui-alignStretch-xABqRa",
492
- "column": "sui-column-xABqRa",
493
- "justifyAround": "sui-justifyAround-xABqRa",
494
- "justifyBetween": "sui-justifyBetween-xABqRa",
495
- "justifyCenter": "sui-justifyCenter-xABqRa",
496
- "justifyEnd": "sui-justifyEnd-xABqRa",
497
- "justifyStart": "sui-justifyStart-xABqRa",
498
- "row": "sui-row-xABqRa",
499
- "stack": "sui-stack-xABqRa",
500
- "wrap": "sui-wrap-xABqRa"
1217
+ "alignCenter": "sui-alignCenter-oAyu1G",
1218
+ "alignEnd": "sui-alignEnd-oAyu1G",
1219
+ "alignStart": "sui-alignStart-oAyu1G",
1220
+ "alignStretch": "sui-alignStretch-oAyu1G",
1221
+ "column": "sui-column-oAyu1G",
1222
+ "justifyAround": "sui-justifyAround-oAyu1G",
1223
+ "justifyBetween": "sui-justifyBetween-oAyu1G",
1224
+ "justifyCenter": "sui-justifyCenter-oAyu1G",
1225
+ "justifyEnd": "sui-justifyEnd-oAyu1G",
1226
+ "justifyStart": "sui-justifyStart-oAyu1G",
1227
+ "row": "sui-row-oAyu1G",
1228
+ "stack": "sui-stack-oAyu1G",
1229
+ "wrap": "sui-wrap-oAyu1G"
501
1230
  };
502
1231
  //#endregion
503
1232
  //#region src/stack/Stack.web.tsx
@@ -530,14 +1259,134 @@ function Stack({ direction = "column", gap, align = "stretch", justify = "start"
530
1259
  });
531
1260
  }
532
1261
  //#endregion
1262
+ //#region src/switch/Switch.module.css
1263
+ var Switch_module_default = {
1264
+ "disabled": "sui-disabled-WH6kOa",
1265
+ "input": "sui-input-WH6kOa",
1266
+ "label": "sui-label-WH6kOa",
1267
+ "root": "sui-root-WH6kOa",
1268
+ "thumb": "sui-thumb-WH6kOa",
1269
+ "track": "sui-track-WH6kOa"
1270
+ };
1271
+ //#endregion
1272
+ //#region src/switch/Switch.web.tsx
1273
+ function Switch({ checked, defaultChecked, onCheckedChange, disabled = false, accessibilityLabel, id, name, value, className, style, testID, ref, children }) {
1274
+ return /* @__PURE__ */ jsxs("label", {
1275
+ className: cx(Switch_module_default.root, disabled && Switch_module_default.disabled, className),
1276
+ style,
1277
+ children: [
1278
+ /* @__PURE__ */ jsx("input", {
1279
+ ref,
1280
+ type: "checkbox",
1281
+ role: "switch",
1282
+ className: Switch_module_default.input,
1283
+ id,
1284
+ name,
1285
+ value,
1286
+ ...checked === void 0 ? { defaultChecked } : { checked },
1287
+ onChange: (event) => onCheckedChange?.(event.target.checked),
1288
+ disabled,
1289
+ "aria-label": accessibilityLabel,
1290
+ "data-testid": testID
1291
+ }),
1292
+ /* @__PURE__ */ jsx("span", {
1293
+ className: Switch_module_default.track,
1294
+ "aria-hidden": "true",
1295
+ children: /* @__PURE__ */ jsx("span", { className: Switch_module_default.thumb })
1296
+ }),
1297
+ children === void 0 || children === null ? null : /* @__PURE__ */ jsx("span", {
1298
+ className: Switch_module_default.label,
1299
+ children
1300
+ })
1301
+ ]
1302
+ });
1303
+ }
1304
+ //#endregion
1305
+ //#region src/tabs/Tabs.module.css
1306
+ var Tabs_module_default = {
1307
+ "list": "sui-list-5aOC0W",
1308
+ "panel": "sui-panel-5aOC0W",
1309
+ "root": "sui-root-5aOC0W",
1310
+ "selected": "sui-selected-5aOC0W",
1311
+ "tab": "sui-tab-5aOC0W"
1312
+ };
1313
+ //#endregion
1314
+ //#region src/tabs/Tabs.web.tsx
1315
+ const keyDirection = {
1316
+ ArrowRight: "next",
1317
+ ArrowLeft: "previous",
1318
+ Home: "first",
1319
+ End: "last"
1320
+ };
1321
+ function Tabs({ items, value, defaultValue, onValueChange, accessibilityLabel, className, style, testID }) {
1322
+ const baseId = useId();
1323
+ const [selected, setSelected] = useControllableState({
1324
+ value,
1325
+ defaultValue: defaultValue ?? firstEnabledTab(items) ?? "",
1326
+ onChange: onValueChange
1327
+ });
1328
+ const tabs = useRef(/* @__PURE__ */ new Map());
1329
+ const selectedIndex = items.findIndex((item) => item.value === selected);
1330
+ const active = items[selectedIndex];
1331
+ const panelId = `${baseId}-panel`;
1332
+ function handleKeyDown(event) {
1333
+ const direction = keyDirection[event.key];
1334
+ if (direction === void 0) return;
1335
+ event.preventDefault();
1336
+ const next = getTabInDirection(items, selected, direction);
1337
+ setSelected(next);
1338
+ tabs.current.get(next)?.focus();
1339
+ }
1340
+ return /* @__PURE__ */ jsxs("div", {
1341
+ className: cx(Tabs_module_default.root, className),
1342
+ style,
1343
+ "data-testid": testID,
1344
+ children: [/* @__PURE__ */ jsx("div", {
1345
+ role: "tablist",
1346
+ "aria-label": accessibilityLabel,
1347
+ className: Tabs_module_default.list,
1348
+ children: items.map((item, index) => {
1349
+ const isSelected = item.value === selected;
1350
+ return /* @__PURE__ */ jsxs("button", {
1351
+ ref: (node) => {
1352
+ if (node === null) tabs.current.delete(item.value);
1353
+ else tabs.current.set(item.value, node);
1354
+ },
1355
+ type: "button",
1356
+ role: "tab",
1357
+ id: `${baseId}-tab-${index}`,
1358
+ "aria-selected": isSelected,
1359
+ "aria-controls": isSelected && item.content !== void 0 ? panelId : void 0,
1360
+ tabIndex: isSelected ? 0 : -1,
1361
+ disabled: item.disabled,
1362
+ className: cx(Tabs_module_default.tab, isSelected && Tabs_module_default.selected),
1363
+ onClick: () => setSelected(item.value),
1364
+ onKeyDown: handleKeyDown,
1365
+ children: [item.icon === void 0 ? null : /* @__PURE__ */ jsx(Icon, {
1366
+ name: item.icon,
1367
+ size: "sm"
1368
+ }), item.label]
1369
+ }, item.value);
1370
+ })
1371
+ }), active?.content === void 0 || active.content === null ? null : /* @__PURE__ */ jsx("div", {
1372
+ role: "tabpanel",
1373
+ id: panelId,
1374
+ "aria-labelledby": `${baseId}-tab-${selectedIndex}`,
1375
+ tabIndex: 0,
1376
+ className: Tabs_module_default.panel,
1377
+ children: active.content
1378
+ })]
1379
+ });
1380
+ }
1381
+ //#endregion
533
1382
  //#region src/text/Text.module.css
534
1383
  var Text_module_default = {
535
- "center": "sui-center-b2Fw3a",
536
- "left": "sui-left-b2Fw3a",
537
- "right": "sui-right-b2Fw3a",
538
- "root": "sui-root-b2Fw3a",
539
- "truncate": "sui-truncate-b2Fw3a",
540
- "uppercase": "sui-uppercase-b2Fw3a"
1384
+ "center": "sui-center-ca3VdW",
1385
+ "left": "sui-left-ca3VdW",
1386
+ "right": "sui-right-ca3VdW",
1387
+ "root": "sui-root-ca3VdW",
1388
+ "truncate": "sui-truncate-ca3VdW",
1389
+ "uppercase": "sui-uppercase-ca3VdW"
541
1390
  };
542
1391
  //#endregion
543
1392
  //#region src/text/Text.web.tsx
@@ -580,8 +1429,141 @@ function Text({ variant = "body", color = "primary", align, truncate = false, as
580
1429
  });
581
1430
  }
582
1431
  //#endregion
1432
+ //#region src/text-area/TextArea.module.css
1433
+ var TextArea_module_default = { "root": "sui-root-c4Gv8W" };
1434
+ //#endregion
1435
+ //#region src/text-area/TextArea.web.tsx
1436
+ function TextArea({ value, defaultValue, onChangeText, placeholder, rows = 3, disabled, readOnly = false, invalid, required, maxLength, onFocus, onBlur, accessibilityLabel, id, name, className, style, testID, ref }) {
1437
+ const control = useFormFieldControl({
1438
+ id,
1439
+ invalid,
1440
+ disabled,
1441
+ required
1442
+ });
1443
+ return /* @__PURE__ */ jsx("textarea", {
1444
+ ref,
1445
+ id: control.id,
1446
+ className: cx(field_module_default.field, TextArea_module_default.root, control.invalid && field_module_default.invalid, readOnly && field_module_default.readOnly, control.disabled && field_module_default.disabled, className),
1447
+ style,
1448
+ rows,
1449
+ name,
1450
+ ...value === void 0 ? { defaultValue } : { value },
1451
+ onChange: (event) => onChangeText?.(event.target.value),
1452
+ placeholder,
1453
+ disabled: control.disabled,
1454
+ readOnly,
1455
+ maxLength,
1456
+ "aria-label": accessibilityLabel,
1457
+ "aria-describedby": control.describedBy,
1458
+ "aria-invalid": control.invalid ? true : void 0,
1459
+ "aria-required": control.required ? true : void 0,
1460
+ "data-testid": testID,
1461
+ onFocus,
1462
+ onBlur
1463
+ });
1464
+ }
1465
+ //#endregion
1466
+ //#region src/toast/Toast.module.css
1467
+ var Toast_module_default = {
1468
+ "actions": "sui-actions-8N5mCG",
1469
+ "content": "sui-content-8N5mCG",
1470
+ "description": "sui-description-8N5mCG",
1471
+ "enter": "sui-enter-8N5mCG",
1472
+ "icon": "sui-icon-8N5mCG",
1473
+ "root": "sui-root-8N5mCG",
1474
+ "title": "sui-title-8N5mCG",
1475
+ "viewport": "sui-viewport-8N5mCG"
1476
+ };
1477
+ //#endregion
1478
+ //#region src/toast/Toast.web.tsx
1479
+ /**
1480
+ * La tarjeta de un toast. Es interna: los toasts se muestran con `useToast` y los
1481
+ * pinta `UIProvider` (ADR-039).
1482
+ */
1483
+ function Toast({ toast, onDismiss }) {
1484
+ const { tone, title, description, action, closeLabel } = toast;
1485
+ return /* @__PURE__ */ jsxs("div", {
1486
+ className: Toast_module_default.root,
1487
+ role: feedbackUrgent[tone] ? "alert" : "status",
1488
+ children: [
1489
+ /* @__PURE__ */ jsx("span", {
1490
+ className: Toast_module_default.icon,
1491
+ children: /* @__PURE__ */ jsx(Icon, {
1492
+ name: feedbackIcon[tone],
1493
+ size: "md",
1494
+ color: tone
1495
+ })
1496
+ }),
1497
+ /* @__PURE__ */ jsxs("div", {
1498
+ className: Toast_module_default.content,
1499
+ children: [/* @__PURE__ */ jsx("p", {
1500
+ className: Toast_module_default.title,
1501
+ children: title
1502
+ }), description === void 0 ? null : /* @__PURE__ */ jsx("p", {
1503
+ className: Toast_module_default.description,
1504
+ children: description
1505
+ })]
1506
+ }),
1507
+ action === void 0 && closeLabel === void 0 ? null : /* @__PURE__ */ jsxs("div", {
1508
+ className: Toast_module_default.actions,
1509
+ children: [action === void 0 ? null : /* @__PURE__ */ jsx(Button, {
1510
+ variant: "ghost",
1511
+ size: "sm",
1512
+ onPress: () => {
1513
+ action.onPress();
1514
+ onDismiss();
1515
+ },
1516
+ children: action.label
1517
+ }), closeLabel === void 0 ? null : /* @__PURE__ */ jsx(IconButton, {
1518
+ icon: "x",
1519
+ label: closeLabel,
1520
+ size: "sm",
1521
+ variant: "ghost",
1522
+ onPress: onDismiss
1523
+ })]
1524
+ })
1525
+ ]
1526
+ });
1527
+ }
1528
+ //#endregion
1529
+ //#region src/toast/ToastViewport.web.tsx
1530
+ /**
1531
+ * La zona donde aparecen los toasts de un `UIProvider` (ADR-039). Existe siempre,
1532
+ * aunque esté vacía: así los lectores de pantalla anuncian cada toast al llegar.
1533
+ */
1534
+ function ToastViewport({ store }) {
1535
+ const toasts = useSyncExternalStore(store.subscribe, store.getSnapshot, store.getSnapshot);
1536
+ return /* @__PURE__ */ jsx("div", {
1537
+ className: Toast_module_default.viewport,
1538
+ "aria-live": "polite",
1539
+ onMouseEnter: store.pause,
1540
+ onMouseLeave: store.resume,
1541
+ onFocus: store.pause,
1542
+ onBlur: store.resume,
1543
+ children: toasts.map((toast) => /* @__PURE__ */ jsx(Toast, {
1544
+ toast,
1545
+ onDismiss: () => store.dismiss(toast.id)
1546
+ }, toast.id))
1547
+ });
1548
+ }
1549
+ //#endregion
1550
+ //#region src/toast/useToastHost.ts
1551
+ /**
1552
+ * La cola de toasts de un `UIProvider` (ADR-039). Uno anidado, por ejemplo para cambiar
1553
+ * de marca en una sección, reutiliza la del de fuera: solo hay una zona de avisos por app.
1554
+ */
1555
+ function useToastHost() {
1556
+ const outer = useContext(ToastContext);
1557
+ const [own] = useState(() => outer === null ? createToastStore() : null);
1558
+ useEffect(() => () => own?.dismiss(), [own]);
1559
+ return {
1560
+ store: outer ?? own ?? createToastStore(),
1561
+ own: outer === null ? own : null
1562
+ };
1563
+ }
1564
+ //#endregion
583
1565
  //#region src/ui-provider/UIProvider.module.css
584
- var UIProvider_module_default = { "root": "sui-root-wZgHIa" };
1566
+ var UIProvider_module_default = { "root": "sui-root-QoB9YG" };
585
1567
  //#endregion
586
1568
  //#region src/ui-provider/UIProvider.web.tsx
587
1569
  const DARK_QUERY = "(prefers-color-scheme: dark)";
@@ -603,7 +1585,8 @@ function useSystemColorScheme() {
603
1585
  }
604
1586
  /**
605
1587
  * Activa tema y marca para todo lo que envuelve (ADR-010). Pone `data-theme` y
606
- * `data-brand` en un contenedor sin caja propia; `tokens.css` hace el resto.
1588
+ * `data-brand` en un contenedor sin caja propia; `tokens.css` hace el resto. También
1589
+ * guarda la cola de toasts y los pinta (ADR-039).
607
1590
  */
608
1591
  function UIProvider({ theme = "system", brand, children }) {
609
1592
  const system = useSystemColorScheme();
@@ -612,15 +1595,19 @@ function UIProvider({ theme = "system", brand, children }) {
612
1595
  system,
613
1596
  brand
614
1597
  ]);
1598
+ const toasts = useToastHost();
615
1599
  return /* @__PURE__ */ jsx(UIContext.Provider, {
616
1600
  value,
617
- children: /* @__PURE__ */ jsx("div", {
618
- className: UIProvider_module_default.root,
619
- "data-theme": value.colorScheme,
620
- "data-brand": brand,
621
- children
1601
+ children: /* @__PURE__ */ jsx(ToastContext.Provider, {
1602
+ value: toasts.store,
1603
+ children: /* @__PURE__ */ jsxs("div", {
1604
+ className: UIProvider_module_default.root,
1605
+ "data-theme": value.colorScheme,
1606
+ "data-brand": brand,
1607
+ children: [children, toasts.own === null ? null : /* @__PURE__ */ jsx(ToastViewport, { store: toasts.own })]
1608
+ })
622
1609
  })
623
1610
  });
624
1611
  }
625
1612
  //#endregion
626
- export { Badge, Box, Button, Icon, Spinner, Stack, Text, UIProvider, useBrand, useColorScheme, useTheme };
1613
+ export { Alert, Badge, Box, Button, Card, Checkbox, Divider, FormField, Icon, IconButton, Input, Link, Modal, Select, Sheet, Skeleton, Spinner, Stack, Switch, Tabs, Text, TextArea, UIProvider, useBrand, useColorScheme, useTheme, useToast };