pixelon 0.9.3 → 0.9.4

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
@@ -7364,7 +7364,7 @@ const Input$1 = React.forwardRef(
7364
7364
  );
7365
7365
  Input$1.displayName = "Input";
7366
7366
 
7367
- const sinTildes = (s) => s.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
7367
+ const sinTildes$2 = (s) => s.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
7368
7368
  const Select$1 = React.forwardRef(
7369
7369
  ({
7370
7370
  options = [],
@@ -7413,7 +7413,7 @@ const Select$1 = React.forwardRef(
7413
7413
  const selectorRef = React.useRef(null);
7414
7414
  const [dropdownPosition, setDropdownPosition] = React.useState(null);
7415
7415
  const filteredOptions = showSearch && searchValue ? options.filter(
7416
- (option) => filterOption ? filterOption(searchValue, option) : sinTildes(option.label).includes(sinTildes(searchValue))
7416
+ (option) => filterOption ? filterOption(searchValue, option) : sinTildes$2(option.label).includes(sinTildes$2(searchValue))
7417
7417
  ) : options;
7418
7418
  const isOptionSelected = (option) => {
7419
7419
  if (mode === "multiple") {
@@ -12341,6 +12341,442 @@ const CurrencyDisplay = ({
12341
12341
  };
12342
12342
  CurrencyDisplay.displayName = "CurrencyDisplay";
12343
12343
 
12344
+ const CARD_VARIANTS = {
12345
+ /** Con sombra: flota sobre el contenido (hojas, diálogos, paneles). */
12346
+ ELEVATED: "elevated"};
12347
+ const CARD_PADDINGS = {
12348
+ MEDIUM: "medium",
12349
+ LARGE: "large"
12350
+ };
12351
+ const CARD_RADII = {
12352
+ NONE: "none",
12353
+ LARGE: "large"
12354
+ };
12355
+
12356
+ const BASE = `${COMPONENT_PREFIX}card`;
12357
+ const Card = React.forwardRef(
12358
+ ({
12359
+ variant = CARD_VARIANTS.ELEVATED,
12360
+ padding = CARD_PADDINGS.MEDIUM,
12361
+ radius = CARD_RADII.LARGE,
12362
+ fullWidth = false,
12363
+ className = "",
12364
+ children,
12365
+ ...rest
12366
+ }, ref) => {
12367
+ const classes = [
12368
+ BASE,
12369
+ `${BASE}--${variant}`,
12370
+ `${BASE}--padding-${padding}`,
12371
+ `${BASE}--radius-${radius}`,
12372
+ fullWidth ? `${BASE}--full-width` : "",
12373
+ className
12374
+ ].filter(Boolean).join(" ");
12375
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: classes, ...rest, children });
12376
+ }
12377
+ );
12378
+ Card.displayName = "Card";
12379
+
12380
+ const CLASS$j = "px-lumi-bottom-sheet";
12381
+ const BottomSheet = ({
12382
+ open,
12383
+ children,
12384
+ onClose,
12385
+ showGrabber = true,
12386
+ closeOnBackdrop = false,
12387
+ closeOnEscape = true,
12388
+ ariaLabelledBy,
12389
+ className = ""
12390
+ }) => {
12391
+ React.useEffect(() => {
12392
+ if (!open) return;
12393
+ const onKey = (e) => {
12394
+ if (e.key !== "Escape" || !closeOnEscape) return;
12395
+ e.stopPropagation();
12396
+ onClose?.();
12397
+ };
12398
+ document.addEventListener("keydown", onKey, true);
12399
+ const previous = document.body.style.overflow;
12400
+ document.body.style.overflow = "hidden";
12401
+ return () => {
12402
+ document.removeEventListener("keydown", onKey, true);
12403
+ document.body.style.overflow = previous;
12404
+ };
12405
+ }, [open, closeOnEscape, onClose]);
12406
+ if (!open) return null;
12407
+ return ReactDOM.createPortal(
12408
+ /* @__PURE__ */ jsxRuntime.jsxs(
12409
+ "div",
12410
+ {
12411
+ className: [CLASS$j, className].filter(Boolean).join(" "),
12412
+ role: "dialog",
12413
+ "aria-modal": "true",
12414
+ "aria-labelledby": ariaLabelledBy,
12415
+ children: [
12416
+ /* @__PURE__ */ jsxRuntime.jsx(
12417
+ "div",
12418
+ {
12419
+ className: `${CLASS$j}__backdrop`,
12420
+ "aria-hidden": "true",
12421
+ onClick: closeOnBackdrop ? onClose : void 0
12422
+ }
12423
+ ),
12424
+ /* @__PURE__ */ jsxRuntime.jsxs(
12425
+ Card,
12426
+ {
12427
+ className: `${CLASS$j}__sheet`,
12428
+ padding: CARD_PADDINGS.LARGE,
12429
+ radius: CARD_RADII.NONE,
12430
+ fullWidth: true,
12431
+ children: [
12432
+ showGrabber && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${CLASS$j}__grabber`, "aria-hidden": "true" }),
12433
+ children
12434
+ ]
12435
+ }
12436
+ )
12437
+ ]
12438
+ }
12439
+ ),
12440
+ document.body
12441
+ );
12442
+ };
12443
+ BottomSheet.displayName = "BottomSheet";
12444
+
12445
+ const PHONE_COUNTRIES = [
12446
+ { code: "CO", name: "Colombia", dialCode: "+57", digits: 10 },
12447
+ { code: "EC", name: "Ecuador", dialCode: "+593", digits: 9 },
12448
+ { code: "PE", name: "Per\xFA", dialCode: "+51", digits: 9 },
12449
+ { code: "VE", name: "Venezuela", dialCode: "+58", digits: 10 },
12450
+ { code: "PA", name: "Panam\xE1", dialCode: "+507", digits: 8 },
12451
+ { code: "MX", name: "M\xE9xico", dialCode: "+52", digits: 10 },
12452
+ { code: "AR", name: "Argentina", dialCode: "+54", digits: 10 },
12453
+ { code: "CL", name: "Chile", dialCode: "+56", digits: 9 },
12454
+ { code: "BR", name: "Brasil", dialCode: "+55", digits: 11 },
12455
+ { code: "CR", name: "Costa Rica", dialCode: "+506", digits: 8 },
12456
+ { code: "US", name: "Estados Unidos", dialCode: "+1", digits: 10 },
12457
+ { code: "ES", name: "Espa\xF1a", dialCode: "+34", digits: 9 }
12458
+ ];
12459
+ const DEFAULT_PHONE_COUNTRY = "CO";
12460
+ function flagOf(code) {
12461
+ const c = (code || "").toUpperCase();
12462
+ if (!/^[A-Z]{2}$/.test(c)) return "";
12463
+ return [...c].map((ch) => String.fromCodePoint(127462 + ch.charCodeAt(0) - 65)).join("");
12464
+ }
12465
+ function splitPhone(value, countries, defaultCountry) {
12466
+ const porDefecto = countries.find((c) => c.code === defaultCountry) ?? countries[0];
12467
+ const v = (value ?? "").replace(/[^0-9+]/g, "");
12468
+ if (v.startsWith("+")) {
12469
+ const d = v.slice(1);
12470
+ const match = countries.filter((c) => d.startsWith(c.dialCode.slice(1))).sort((a, b) => b.dialCode.length - a.dialCode.length)[0];
12471
+ if (match) return { country: match, digits: d.slice(match.dialCode.length - 1) };
12472
+ }
12473
+ return { country: porDefecto, digits: v.replace(/\D/g, "") };
12474
+ }
12475
+
12476
+ const CLASS$i = "px-lumi-phone-input";
12477
+ function sinTildes$1(s) {
12478
+ return s.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase();
12479
+ }
12480
+ const PhoneInput = React.forwardRef(
12481
+ ({
12482
+ value,
12483
+ onChange,
12484
+ onBlur,
12485
+ label,
12486
+ placeholder,
12487
+ disabled,
12488
+ readOnly,
12489
+ error,
12490
+ countries = PHONE_COUNTRIES,
12491
+ defaultCountry = DEFAULT_PHONE_COUNTRY,
12492
+ name,
12493
+ id,
12494
+ className,
12495
+ labels
12496
+ }, ref) => {
12497
+ const [paisElegido, setPaisElegido] = React.useState(defaultCountry);
12498
+ const [abierto, setAbierto] = React.useState(false);
12499
+ const [busqueda, setBusqueda] = React.useState("");
12500
+ const { country, digits } = splitPhone(value, countries, value ? defaultCountry : paisElegido);
12501
+ const pais = value ? country : countries.find((c) => c.code === paisElegido) ?? country;
12502
+ const tope = pais.digits ?? 15;
12503
+ const bloqueado = disabled || readOnly;
12504
+ React.useEffect(() => {
12505
+ if (!abierto) setBusqueda("");
12506
+ }, [abierto]);
12507
+ const visibles = React.useMemo(() => {
12508
+ const q = sinTildes$1(busqueda.trim());
12509
+ if (!q) return countries;
12510
+ return countries.filter(
12511
+ (c) => sinTildes$1(c.name).includes(q) || c.dialCode.includes(q) || c.code.toLowerCase() === q
12512
+ );
12513
+ }, [busqueda, countries]);
12514
+ const emitir = (c, d) => {
12515
+ onChange?.(d ? `${c.dialCode}${d}` : "");
12516
+ };
12517
+ const handleDigits = (e) => {
12518
+ const d = e.target.value.replace(/\D/g, "").slice(0, tope);
12519
+ emitir(pais, d);
12520
+ };
12521
+ const elegir = (c) => {
12522
+ setPaisElegido(c.code);
12523
+ emitir(c, digits.slice(0, c.digits ?? 15));
12524
+ setAbierto(false);
12525
+ };
12526
+ const tituloId = `${id ?? name ?? "phone"}-pais-titulo`;
12527
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: [CLASS$i, error && `${CLASS$i}--error`, bloqueado && `${CLASS$i}--disabled`, className].filter(Boolean).join(" "), children: [
12528
+ /* @__PURE__ */ jsxRuntime.jsxs(
12529
+ "button",
12530
+ {
12531
+ type: "button",
12532
+ className: `${CLASS$i}__country`,
12533
+ "aria-label": `${labels?.pickCountry ?? "Pa\xEDs del celular"}: ${pais.name} ${pais.dialCode}`,
12534
+ "aria-haspopup": "dialog",
12535
+ "aria-expanded": abierto,
12536
+ disabled: bloqueado,
12537
+ onClick: () => setAbierto(true),
12538
+ children: [
12539
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$i}__flag`, "aria-hidden": "true", children: flagOf(pais.code) }),
12540
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$i}__code`, children: pais.dialCode }),
12541
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$i}__caret`, "aria-hidden": "true", children: "\u25BE" })
12542
+ ]
12543
+ }
12544
+ ),
12545
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${CLASS$i}__digits`, children: /* @__PURE__ */ jsxRuntime.jsx(
12546
+ Input$1,
12547
+ {
12548
+ ref,
12549
+ id,
12550
+ name,
12551
+ type: "tel",
12552
+ inputMode: "numeric",
12553
+ autoComplete: "tel-national",
12554
+ label,
12555
+ placeholder,
12556
+ value: digits,
12557
+ onChange: handleDigits,
12558
+ onBlur,
12559
+ disabled,
12560
+ readOnly,
12561
+ error
12562
+ }
12563
+ ) }),
12564
+ /* @__PURE__ */ jsxRuntime.jsxs(
12565
+ BottomSheet,
12566
+ {
12567
+ open: abierto,
12568
+ onClose: () => setAbierto(false),
12569
+ showGrabber: true,
12570
+ closeOnBackdrop: true,
12571
+ ariaLabelledBy: tituloId,
12572
+ className: `${CLASS$i}__sheet`,
12573
+ children: [
12574
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$i}__sheet-head`, children: [
12575
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { id: tituloId, className: `${CLASS$i}__sheet-title`, children: labels?.pickCountry ?? "Pa\xEDs del celular" }),
12576
+ /* @__PURE__ */ jsxRuntime.jsx(
12577
+ "input",
12578
+ {
12579
+ className: `${CLASS$i}__search`,
12580
+ type: "search",
12581
+ value: busqueda,
12582
+ onChange: (e) => setBusqueda(e.target.value),
12583
+ placeholder: labels?.searchPlaceholder ?? "Buscar pa\xEDs o indicativo",
12584
+ autoComplete: "off",
12585
+ "aria-label": labels?.searchPlaceholder ?? "Buscar pa\xEDs o indicativo"
12586
+ }
12587
+ )
12588
+ ] }),
12589
+ /* @__PURE__ */ jsxRuntime.jsxs("ul", { className: `${CLASS$i}__list`, role: "listbox", "aria-labelledby": tituloId, children: [
12590
+ visibles.map((c) => {
12591
+ const activo = c.code === pais.code;
12592
+ return /* @__PURE__ */ jsxRuntime.jsx("li", { role: "option", "aria-selected": activo, children: /* @__PURE__ */ jsxRuntime.jsxs(
12593
+ "button",
12594
+ {
12595
+ type: "button",
12596
+ className: [`${CLASS$i}__option`, activo && `${CLASS$i}__option--selected`].filter(Boolean).join(" "),
12597
+ onClick: () => elegir(c),
12598
+ children: [
12599
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$i}__flag`, "aria-hidden": "true", children: flagOf(c.code) }),
12600
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$i}__option-name`, children: c.name }),
12601
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$i}__option-code`, children: c.dialCode })
12602
+ ]
12603
+ }
12604
+ ) }, c.code);
12605
+ }),
12606
+ visibles.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("li", { className: `${CLASS$i}__empty`, children: labels?.noResults ?? "Ning\xFAn pa\xEDs coincide." })
12607
+ ] })
12608
+ ]
12609
+ }
12610
+ )
12611
+ ] });
12612
+ }
12613
+ );
12614
+ PhoneInput.displayName = "PhoneInput";
12615
+
12616
+ const CLASS$h = "px-lumi-sheet-select";
12617
+ function sinTildes(s) {
12618
+ return s.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase();
12619
+ }
12620
+ const SheetSelect = React.forwardRef(
12621
+ ({
12622
+ value,
12623
+ onChange,
12624
+ onBlur,
12625
+ options,
12626
+ label,
12627
+ placeholder,
12628
+ disabled,
12629
+ readOnly,
12630
+ error,
12631
+ searchable,
12632
+ notFoundContent,
12633
+ sheetTitle,
12634
+ searchPlaceholder,
12635
+ name,
12636
+ id,
12637
+ className
12638
+ }, ref) => {
12639
+ const [abierto, setAbierto] = React.useState(false);
12640
+ const [busqueda, setBusqueda] = React.useState("");
12641
+ const bloqueado = disabled || readOnly;
12642
+ const elegida = options.find((o) => String(o.value) === String(value ?? ""));
12643
+ const conBuscador = searchable ?? true;
12644
+ React.useEffect(() => {
12645
+ if (!abierto) setBusqueda("");
12646
+ }, [abierto]);
12647
+ const visibles = React.useMemo(() => {
12648
+ const q = sinTildes(busqueda.trim());
12649
+ if (!q) return options;
12650
+ return options.filter((o) => sinTildes(o.label).includes(q) || sinTildes(o.hint ?? "").includes(q));
12651
+ }, [busqueda, options]);
12652
+ const abrir = () => {
12653
+ if (!bloqueado) setAbierto(true);
12654
+ };
12655
+ const elegir = (o) => {
12656
+ onChange?.(o.value);
12657
+ setAbierto(false);
12658
+ onBlur?.();
12659
+ };
12660
+ const tituloId = `${id ?? name ?? "sheet-select"}-titulo`;
12661
+ const titulo = sheetTitle ?? label?.replace(/\s\*$/, "") ?? "";
12662
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: [CLASS$h, bloqueado && `${CLASS$h}--disabled`, className].filter(Boolean).join(" "), children: [
12663
+ /* @__PURE__ */ jsxRuntime.jsx(
12664
+ Input$1,
12665
+ {
12666
+ ref,
12667
+ id,
12668
+ name,
12669
+ label,
12670
+ placeholder: placeholder ?? "Seleccionar...",
12671
+ value: elegida?.label ?? "",
12672
+ readOnly: true,
12673
+ disabled,
12674
+ error,
12675
+ onClick: abrir,
12676
+ onKeyDown: (e) => {
12677
+ if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") {
12678
+ e.preventDefault();
12679
+ abrir();
12680
+ }
12681
+ },
12682
+ role: "combobox",
12683
+ "aria-haspopup": "dialog",
12684
+ "aria-expanded": abierto,
12685
+ className: `${CLASS$h}__field`,
12686
+ suffix: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6 9l6 6 6-6" }) }),
12687
+ onSuffixClick: abrir,
12688
+ suffixAriaLabel: titulo ? `Elegir ${titulo}` : "Elegir"
12689
+ }
12690
+ ),
12691
+ /* @__PURE__ */ jsxRuntime.jsxs(
12692
+ BottomSheet,
12693
+ {
12694
+ open: abierto,
12695
+ onClose: () => setAbierto(false),
12696
+ showGrabber: true,
12697
+ closeOnBackdrop: true,
12698
+ ariaLabelledBy: tituloId,
12699
+ className: `${CLASS$h}__sheet`,
12700
+ children: [
12701
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$h}__sheet-head`, children: [
12702
+ /* @__PURE__ */ jsxRuntime.jsx("h2", { id: tituloId, className: `${CLASS$h}__sheet-title`, children: titulo }),
12703
+ conBuscador && /* @__PURE__ */ jsxRuntime.jsx(
12704
+ "input",
12705
+ {
12706
+ className: `${CLASS$h}__search`,
12707
+ type: "search",
12708
+ value: busqueda,
12709
+ onChange: (e) => setBusqueda(e.target.value),
12710
+ placeholder: searchPlaceholder ?? "Buscar",
12711
+ autoComplete: "off",
12712
+ "aria-label": searchPlaceholder ?? "Buscar"
12713
+ }
12714
+ )
12715
+ ] }),
12716
+ /* @__PURE__ */ jsxRuntime.jsxs("ul", { className: `${CLASS$h}__list`, role: "listbox", "aria-labelledby": tituloId, children: [
12717
+ visibles.map((o) => {
12718
+ const activo = elegida?.value === o.value;
12719
+ return /* @__PURE__ */ jsxRuntime.jsx("li", { role: "option", "aria-selected": activo, children: /* @__PURE__ */ jsxRuntime.jsxs(
12720
+ "button",
12721
+ {
12722
+ type: "button",
12723
+ className: [`${CLASS$h}__option`, activo && `${CLASS$h}__option--selected`].filter(Boolean).join(" "),
12724
+ onClick: () => elegir(o),
12725
+ children: [
12726
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${CLASS$h}__option-text`, children: [
12727
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$h}__option-label`, children: o.label }),
12728
+ o.hint && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$h}__option-hint`, children: o.hint })
12729
+ ] }),
12730
+ activo && /* @__PURE__ */ jsxRuntime.jsx("svg", { className: `${CLASS$h}__check`, width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 6L9 17l-5-5" }) })
12731
+ ]
12732
+ }
12733
+ ) }, o.value);
12734
+ }),
12735
+ visibles.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("li", { className: `${CLASS$h}__empty`, children: options.length === 0 ? notFoundContent ?? "No hay opciones disponibles." : "Nada coincide." })
12736
+ ] })
12737
+ ]
12738
+ }
12739
+ )
12740
+ ] });
12741
+ }
12742
+ );
12743
+ SheetSelect.displayName = "SheetSelect";
12744
+
12745
+ const SANITIZE_PRESETS = {
12746
+ /** «abc-123 » → «ABC123». */
12747
+ plate: ["noControl", "alnum", "upper", { maxLength: 8 }],
12748
+ /** «+57 (300) 123-4567» → «573001234567». */
12749
+ phone: ["digits", { maxLength: 15 }],
12750
+ /** «1.000.000» → «1000000». */
12751
+ id: ["digits", { maxLength: 15 }],
12752
+ /** Un nombre: sin control, espacios colapsados, recortado al enviar. */
12753
+ name: ["noControl", "collapseSpaces", { maxLength: 150 }, "trim"],
12754
+ /** Una nota corta. */
12755
+ note: ["noControl", "collapseSpaces", { maxLength: 80 }, "trim"]
12756
+ };
12757
+ const CONTROL = /[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g;
12758
+ function expandir(spec) {
12759
+ const lista = Array.isArray(spec) ? spec : [spec];
12760
+ return lista.flatMap((r) => typeof r === "object" && "preset" in r ? SANITIZE_PRESETS[r.preset] ?? [] : [r]);
12761
+ }
12762
+ function aplicar(s, r, live) {
12763
+ if (r === "trim") return live ? s : s.trim();
12764
+ if (r === "upper") return s.toUpperCase();
12765
+ if (r === "lower") return s.toLowerCase();
12766
+ if (r === "digits") return s.replace(/[^0-9]/g, "");
12767
+ if (r === "alnum") return s.replace(/[^A-Za-z0-9]/g, "");
12768
+ if (r === "noControl") return s.replace(CONTROL, "");
12769
+ if (r === "collapseSpaces") return s.replace(/\s{2,}/g, " ");
12770
+ if ("maxLength" in r) return s.slice(0, r.maxLength);
12771
+ if ("strip" in r) return s.replace(new RegExp(r.strip, "g"), "");
12772
+ return s;
12773
+ }
12774
+ function sanitize(value, spec, options = {}) {
12775
+ if (!spec || value === null || value === void 0) return value;
12776
+ if (typeof value !== "string") return value;
12777
+ return expandir(spec).reduce((s, r) => aplicar(s, r, !!options.live), value);
12778
+ }
12779
+
12344
12780
  const renderField = ({
12345
12781
  field,
12346
12782
  control,
@@ -12428,10 +12864,14 @@ const renderField = ({
12428
12864
  }, children: formatValue() })
12429
12865
  ] });
12430
12866
  }
12867
+ const onChangeLimpio = field.sanitize ? (e) => {
12868
+ const crudo = e && typeof e === "object" && "target" in e ? e.target.value : e;
12869
+ onChange(sanitize(crudo, field.sanitize, { live: true }));
12870
+ } : onChange;
12431
12871
  const commonProps = {
12432
12872
  ...getCommonProps(),
12433
12873
  value: value ?? "",
12434
- onChange,
12874
+ onChange: onChangeLimpio,
12435
12875
  onBlur,
12436
12876
  ref,
12437
12877
  error: error?.message
@@ -12456,8 +12896,26 @@ const renderField = ({
12456
12896
  return /* @__PURE__ */ jsxRuntime.jsx(Input$1, { ...commonProps, type: "email" });
12457
12897
  case "INPUT_PASSWORD":
12458
12898
  return /* @__PURE__ */ jsxRuntime.jsx(Input$1, { ...commonProps, type: "password" });
12459
- case "INPUT_PHONE":
12460
- return /* @__PURE__ */ jsxRuntime.jsx(Input$1, { ...commonProps, type: "tel" });
12899
+ case "INPUT_PHONE": {
12900
+ const { countries, defaultCountry } = uiProps ?? {};
12901
+ return /* @__PURE__ */ jsxRuntime.jsx(
12902
+ PhoneInput,
12903
+ {
12904
+ ref,
12905
+ name,
12906
+ label: fieldLabel,
12907
+ placeholder,
12908
+ disabled: isReadOnly,
12909
+ readOnly: isReadOnly,
12910
+ error: error?.message,
12911
+ value: typeof value === "string" ? value : "",
12912
+ onChange: (v) => onChange(v),
12913
+ onBlur,
12914
+ countries,
12915
+ defaultCountry
12916
+ }
12917
+ );
12918
+ }
12461
12919
  case "INPUT_CURRENCY":
12462
12920
  return /* @__PURE__ */ jsxRuntime.jsx(
12463
12921
  Input$1,
@@ -12483,6 +12941,30 @@ const renderField = ({
12483
12941
  case "TEXTAREA":
12484
12942
  return /* @__PURE__ */ jsxRuntime.jsx(Input$1, { ...commonProps, type: "textarea" });
12485
12943
  case "SELECT":
12944
+ if (uiProps?.picker === "sheet") {
12945
+ return /* @__PURE__ */ jsxRuntime.jsx(
12946
+ SheetSelect,
12947
+ {
12948
+ ref,
12949
+ name,
12950
+ label: fieldLabel,
12951
+ placeholder,
12952
+ disabled: isReadOnly,
12953
+ readOnly: isReadOnly,
12954
+ error: error?.message,
12955
+ value: value == null ? "" : String(value),
12956
+ onChange: (v) => onChange(v),
12957
+ onBlur,
12958
+ options: (options || []).map((o) => ({
12959
+ value: String(o.value),
12960
+ label: String(o.label),
12961
+ hint: o.hint
12962
+ })),
12963
+ searchable: uiProps?.showSearch,
12964
+ notFoundContent: uiProps?.notFoundContent
12965
+ }
12966
+ );
12967
+ }
12486
12968
  return /* @__PURE__ */ jsxRuntime.jsx(
12487
12969
  Select$1,
12488
12970
  {
@@ -12612,8 +13094,11 @@ const transformIncomingValues = (values, fields) => {
12612
13094
  const transformOutgoingValues = (values, fields) => {
12613
13095
  const transformed = { ...values };
12614
13096
  fields.forEach((field) => {
13097
+ if (field.sanitize && values[field.name] !== void 0) {
13098
+ transformed[field.name] = sanitize(values[field.name], field.sanitize);
13099
+ }
12615
13100
  if (field.transformOnSubmit && values[field.name] !== void 0) {
12616
- transformed[field.name] = field.transformOnSubmit(values[field.name]);
13101
+ transformed[field.name] = field.transformOnSubmit(transformed[field.name]);
12617
13102
  }
12618
13103
  });
12619
13104
  return transformed;
@@ -13202,24 +13687,28 @@ function mapFieldsToFormFields(fields, mode) {
13202
13687
  placeholder: field.placeholder,
13203
13688
  uiProps: field.uiProps,
13204
13689
  transformOnSubmit: field.parseValue,
13205
- gridSpan: field.gridSpan
13690
+ gridSpan: field.gridSpan,
13206
13691
  // SPEC-131 T7
13692
+ showIf: field.showIf,
13693
+ // SPEC-181
13694
+ sanitize: field.sanitize
13695
+ // SPEC-183
13207
13696
  }));
13208
13697
  }
13209
13698
 
13210
- const CLASS$h = `${COMPONENT_PREFIX}field-value`;
13699
+ const CLASS$g = `${COMPONENT_PREFIX}field-value`;
13211
13700
  const FieldValue = ({
13212
13701
  label,
13213
13702
  children,
13214
13703
  layout = "inline",
13215
13704
  className
13216
- }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: [CLASS$h, `${CLASS$h}--${layout}`, className].filter(Boolean).join(" "), children: [
13217
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$h}__label`, children: label }),
13218
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$h}__value`, children })
13705
+ }) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: [CLASS$g, `${CLASS$g}--${layout}`, className].filter(Boolean).join(" "), children: [
13706
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$g}__label`, children: label }),
13707
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$g}__value`, children })
13219
13708
  ] });
13220
13709
  FieldValue.displayName = "FieldValue";
13221
13710
 
13222
- const CLASS$g = `${COMPONENT_PREFIX}record-card`;
13711
+ const CLASS$f = `${COMPONENT_PREFIX}record-card`;
13223
13712
  const RecordCard = ({
13224
13713
  title,
13225
13714
  summary,
@@ -13231,20 +13720,20 @@ const RecordCard = ({
13231
13720
  className
13232
13721
  }) => {
13233
13722
  const cuerpoId = React.useId();
13234
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: [CLASS$g, open ? `${CLASS$g}--open` : "", className].filter(Boolean).join(" "), children: [
13723
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: [CLASS$f, open ? `${CLASS$f}--open` : "", className].filter(Boolean).join(" "), children: [
13235
13724
  /* @__PURE__ */ jsxRuntime.jsxs(
13236
13725
  "button",
13237
13726
  {
13238
13727
  type: "button",
13239
- className: `${CLASS$g}__header`,
13728
+ className: `${CLASS$f}__header`,
13240
13729
  "aria-expanded": open,
13241
13730
  "aria-controls": cuerpoId,
13242
13731
  "aria-label": ariaLabel,
13243
13732
  onClick: onToggle,
13244
13733
  children: [
13245
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${CLASS$g}__heading`, children: [
13246
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$g}__title`, children: title }),
13247
- summary && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$g}__summary`, children: summary })
13734
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${CLASS$f}__heading`, children: [
13735
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$f}__title`, children: title }),
13736
+ summary && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$f}__summary`, children: summary })
13248
13737
  ] }),
13249
13738
  /* @__PURE__ */ jsxRuntime.jsx(
13250
13739
  Icon,
@@ -13252,22 +13741,22 @@ const RecordCard = ({
13252
13741
  type: open ? "chevron-up" : "chevron-down",
13253
13742
  width: 18,
13254
13743
  height: 18,
13255
- className: `${CLASS$g}__chevron`,
13744
+ className: `${CLASS$f}__chevron`,
13256
13745
  "aria-hidden": true
13257
13746
  }
13258
13747
  )
13259
13748
  ]
13260
13749
  }
13261
13750
  ),
13262
- open && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$g}__body`, id: cuerpoId, children: [
13751
+ open && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$f}__body`, id: cuerpoId, children: [
13263
13752
  children,
13264
- actions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${CLASS$g}__actions`, children: actions })
13753
+ actions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${CLASS$f}__actions`, children: actions })
13265
13754
  ] })
13266
13755
  ] });
13267
13756
  };
13268
13757
  RecordCard.displayName = "RecordCard";
13269
13758
 
13270
- const CLASS$f = `${COMPONENT_PREFIX}crud-cards`;
13759
+ const CLASS$e = `${COMPONENT_PREFIX}crud-cards`;
13271
13760
  function summaryFields(fields) {
13272
13761
  const visibles = fields.filter((f) => f.showInTable !== false);
13273
13762
  const marcados = visibles.filter((f) => f.summary);
@@ -13286,13 +13775,13 @@ function CardList({
13286
13775
  const claveResumen = new Set(resumen.map((f) => f.key));
13287
13776
  const cuerpo = fields.filter((f) => f.showInTable !== false && !claveResumen.has(f.key));
13288
13777
  if (loading && rows.length === 0) {
13289
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${CLASS$f}__estado`, children: "Cargando..." });
13778
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${CLASS$e}__estado`, children: "Cargando..." });
13290
13779
  }
13291
13780
  if (rows.length === 0) {
13292
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${CLASS$f}__estado`, children: emptyText });
13781
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${CLASS$e}__estado`, children: emptyText });
13293
13782
  }
13294
13783
  const [principal, ...secundarios] = resumen;
13295
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: CLASS$f, children: rows.map((row) => {
13784
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: CLASS$e, children: rows.map((row) => {
13296
13785
  const key = rowKey(row);
13297
13786
  const opciones = buildOptions?.(row) ?? [];
13298
13787
  const titulo = principal ? renderFieldValue(principal, row) : key;
@@ -13309,14 +13798,14 @@ function CardList({
13309
13798
  {
13310
13799
  type: "button",
13311
13800
  className: [
13312
- `${CLASS$f}__accion`,
13801
+ `${CLASS$e}__accion`,
13313
13802
  o.disabled && o.disabledReason ? "is-con-motivo" : ""
13314
13803
  ].filter(Boolean).join(" "),
13315
13804
  disabled: o.disabled,
13316
13805
  onClick: () => void o.onClick(),
13317
13806
  children: [
13318
13807
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: o.label }),
13319
- o.disabled && o.disabledReason && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$f}__motivo`, children: o.disabledReason })
13808
+ o.disabled && o.disabledReason && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$e}__motivo`, children: o.disabledReason })
13320
13809
  ]
13321
13810
  },
13322
13811
  o.label
@@ -13331,7 +13820,7 @@ function CardList({
13331
13820
  }
13332
13821
  CardList.displayName = "CardList";
13333
13822
 
13334
- const CLASS$e = `${COMPONENT_PREFIX}crud-scroll-end`;
13823
+ const CLASS$d = `${COMPONENT_PREFIX}crud-scroll-end`;
13335
13824
  const MARGEN = 24;
13336
13825
  const SELECTOR_CRUD = `.${COMPONENT_PREFIX}table-container, .${COMPONENT_PREFIX}crud-cards`;
13337
13826
  const ScrollToEnd = ({
@@ -13375,7 +13864,7 @@ const ScrollToEnd = ({
13375
13864
  s.scrollTo({ top: s.scrollHeight, behavior: "smooth" });
13376
13865
  }, []);
13377
13866
  if (!visible) return null;
13378
- return /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: CLASS$e, onClick: alFinal, "aria-label": label, title: label, children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { type: "chevron-down", width: 18, height: 18, "aria-hidden": true }) });
13867
+ return /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: CLASS$d, onClick: alFinal, "aria-label": label, title: label, children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { type: "chevron-down", width: 18, height: 18, "aria-hidden": true }) });
13379
13868
  };
13380
13869
  ScrollToEnd.displayName = "ScrollToEnd";
13381
13870
 
@@ -14060,7 +14549,7 @@ function Crud({
14060
14549
  }
14061
14550
  Crud.displayName = "Crud";
14062
14551
 
14063
- const CLASS$d = "px-chat-reactive-crud__chat-link";
14552
+ const CLASS$c = "px-chat-reactive-crud__chat-link";
14064
14553
  function Burbuja() {
14065
14554
  return /* @__PURE__ */ jsxRuntime.jsx(
14066
14555
  "svg",
@@ -14087,7 +14576,7 @@ const ChatLinkCell = ({
14087
14576
  if (targets.length === 1) {
14088
14577
  const t = targets[0];
14089
14578
  const texto = t.label ? `Abrir chat ${t.label}` : "Abrir chat";
14090
- return /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: CLASS$d, "aria-label": texto, title: texto, onClick: () => abrir(t.id), children: /* @__PURE__ */ jsxRuntime.jsx(Burbuja, {}) });
14579
+ return /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: CLASS$c, "aria-label": texto, title: texto, onClick: () => abrir(t.id), children: /* @__PURE__ */ jsxRuntime.jsx(Burbuja, {}) });
14091
14580
  }
14092
14581
  return /* @__PURE__ */ jsxRuntime.jsx(
14093
14582
  DropdownMenu,
@@ -14101,7 +14590,7 @@ const ChatLinkCell = ({
14101
14590
  "button",
14102
14591
  {
14103
14592
  type: "button",
14104
- className: CLASS$d,
14593
+ className: CLASS$c,
14105
14594
  "aria-label": `Abrir chat (${targets.length} conversaciones)`,
14106
14595
  title: "Abrir chat",
14107
14596
  children: /* @__PURE__ */ jsxRuntime.jsx(Burbuja, {})
@@ -14114,6 +14603,18 @@ const ChatLinkCell = ({
14114
14603
  };
14115
14604
  ChatLinkCell.displayName = "ChatLinkCell";
14116
14605
 
14606
+ function obligatorioSiSeVe(s, f, requiredMsg) {
14607
+ if (!f.visibleWhen) return s.required(requiredMsg);
14608
+ const conds = Array.isArray(f.visibleWhen) ? f.visibleWhen : [f.visibleWhen];
14609
+ return s.when(
14610
+ conds.map((c) => c.field),
14611
+ {
14612
+ is: (...vals) => conds.every((c, i) => c.in.includes(String(vals[i]))),
14613
+ then: (sch) => sch.required(requiredMsg),
14614
+ otherwise: (sch) => sch.notRequired()
14615
+ }
14616
+ );
14617
+ }
14117
14618
  function buildCrudYupSchema(fields) {
14118
14619
  const shape = {};
14119
14620
  for (const f of fields) {
@@ -14143,19 +14644,17 @@ function buildCrudYupSchema(fields) {
14143
14644
  }
14144
14645
  if (f.moleculeType === "INPUT_NUMBER" || f.moleculeType === "INPUT_CURRENCY") {
14145
14646
  let s2 = yup__namespace.number().transform((val, orig) => orig === "" || orig === null ? void 0 : val).typeError(`${f.label}: n\xFAmero inv\xE1lido`);
14146
- if (requiredMsg) s2 = s2.required(requiredMsg);
14147
14647
  if (v?.min) s2 = s2.min(Number(v.min.value), v.min.message);
14148
14648
  if (v?.max) s2 = s2.max(Number(v.max.value), v.max.message);
14149
- shape[f.name] = s2;
14649
+ shape[f.name] = requiredMsg ? obligatorioSiSeVe(s2, f, requiredMsg) : s2;
14150
14650
  continue;
14151
14651
  }
14152
14652
  let s = yup__namespace.string();
14153
- if (requiredMsg) s = s.required(requiredMsg);
14154
- if (v?.pattern) s = s.matches(new RegExp(v.pattern.value), v.pattern.message);
14653
+ if (v?.pattern) s = s.matches(new RegExp(v.pattern.value), { message: v.pattern.message, excludeEmptyString: true });
14155
14654
  if (v?.email) s = s.email(v.email);
14156
14655
  if (v?.min) s = s.min(Number(v.min.value), v.min.message);
14157
14656
  if (v?.max) s = s.max(Number(v.max.value), v.max.message);
14158
- shape[f.name] = s;
14657
+ shape[f.name] = requiredMsg ? obligatorioSiSeVe(s, f, requiredMsg) : s;
14159
14658
  }
14160
14659
  return yup__namespace.object().shape(shape);
14161
14660
  }
@@ -14185,7 +14684,14 @@ const datetime = (value) => {
14185
14684
  minute: "2-digit"
14186
14685
  });
14187
14686
  };
14188
- const CRUD_FORMATTERS = { currency, date, datetime };
14687
+ const phone = (value) => {
14688
+ const s = String(value ?? "").trim();
14689
+ const m = /^\+(\d{1,3})(\d{10})$/.exec(s);
14690
+ if (!m) return s;
14691
+ const [, cc, n] = m;
14692
+ return `+${cc} ${n.slice(0, 3)} ${n.slice(3, 6)} ${n.slice(6)}`;
14693
+ };
14694
+ const CRUD_FORMATTERS = { currency, date, datetime, phone };
14189
14695
  function getFormatter(key) {
14190
14696
  return key ? CRUD_FORMATTERS[key] : void 0;
14191
14697
  }
@@ -14420,7 +14926,7 @@ function uploadViaEventBus(eventBus, file, fileType) {
14420
14926
  });
14421
14927
  }
14422
14928
 
14423
- const CLASS$c = `${COMPONENT_PREFIX$1}file-field`;
14929
+ const CLASS$b = `${COMPONENT_PREFIX$1}file-field`;
14424
14930
  function iconoPorNombre(nombre) {
14425
14931
  const ext = nombre.split(".").pop()?.toLowerCase() ?? "";
14426
14932
  if (["png", "jpg", "jpeg", "gif", "webp", "heic", "heif"].includes(ext)) return ICON_TYPES.IMAGE;
@@ -14451,18 +14957,18 @@ const FileField = ({
14451
14957
  const elegir = () => {
14452
14958
  if (!disabled) inputRef.current?.click();
14453
14959
  };
14454
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$c}${error ? ` ${CLASS$c}--error` : ""}`, children: [
14455
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${CLASS$c}__label`, children: [
14960
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$b}${error ? ` ${CLASS$b}--error` : ""}`, children: [
14961
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${CLASS$b}__label`, children: [
14456
14962
  label,
14457
14963
  required ? " *" : "",
14458
14964
  multiple && hechos > 0 ? ` (${hechos})` : ""
14459
14965
  ] }),
14460
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$c}__box`, children: [
14966
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$b}__box`, children: [
14461
14967
  /* @__PURE__ */ jsxRuntime.jsx(
14462
14968
  "input",
14463
14969
  {
14464
14970
  ref: inputRef,
14465
- className: `${CLASS$c}__native`,
14971
+ className: `${CLASS$b}__native`,
14466
14972
  type: "file",
14467
14973
  accept,
14468
14974
  multiple,
@@ -14473,14 +14979,14 @@ const FileField = ({
14473
14979
  }
14474
14980
  }
14475
14981
  ),
14476
- /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: `${CLASS$c}__pick`, onClick: elegir, disabled, children: [
14982
+ /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: `${CLASS$b}__pick`, onClick: elegir, disabled, children: [
14477
14983
  /* @__PURE__ */ jsxRuntime.jsx(Icon$1, { type: ICON_TYPES.UPLOAD, size: "small" }),
14478
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$c}__pick-text`, children: entries.length === 0 ? multiple ? "Toca para elegir archivos" : "Toca para elegir un archivo" : multiple ? "A\xF1adir m\xE1s" : "Cambiar archivo" })
14984
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$b}__pick-text`, children: entries.length === 0 ? multiple ? "Toca para elegir archivos" : "Toca para elegir un archivo" : multiple ? "A\xF1adir m\xE1s" : "Cambiar archivo" })
14479
14985
  ] }),
14480
- entries.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("ul", { className: `${CLASS$c}__list`, children: entries.map((e, i) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: `${CLASS$c}__item ${CLASS$c}__item--${e.status}`, children: [
14481
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$c}__kind`, "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(Icon$1, { type: iconoPorNombre(e.name), size: "small" }) }),
14482
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$c}__name`, children: e.name }),
14483
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${CLASS$c}__state`, children: [
14986
+ entries.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("ul", { className: `${CLASS$b}__list`, children: entries.map((e, i) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: `${CLASS$b}__item ${CLASS$b}__item--${e.status}`, children: [
14987
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$b}__kind`, "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(Icon$1, { type: iconoPorNombre(e.name), size: "small" }) }),
14988
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$b}__name`, children: e.name }),
14989
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${CLASS$b}__state`, children: [
14484
14990
  e.status === "uploading" && "Subiendo\u2026",
14485
14991
  e.status === "done" && (pesoLegible(e.size) || "Listo"),
14486
14992
  e.status === "error" && "No se pudo subir"
@@ -14489,7 +14995,7 @@ const FileField = ({
14489
14995
  "button",
14490
14996
  {
14491
14997
  type: "button",
14492
- className: `${CLASS$c}__remove`,
14998
+ className: `${CLASS$b}__remove`,
14493
14999
  onClick: () => onRemove(i),
14494
15000
  "aria-label": `Quitar ${e.name}`,
14495
15001
  disabled,
@@ -14498,8 +15004,8 @@ const FileField = ({
14498
15004
  )
14499
15005
  ] }, `${e.name}-${i}`)) })
14500
15006
  ] }),
14501
- error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$c}__error`, children: error }),
14502
- !error && subiendo && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$c}__hint`, children: "Espera a que terminen de subir." })
15007
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$b}__error`, children: error }),
15008
+ !error && subiendo && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$b}__hint`, children: "Espera a que terminen de subir." })
14503
15009
  ] });
14504
15010
  };
14505
15011
 
@@ -15661,7 +16167,7 @@ function buildMarkerIcon(name, color = "#dc2626", heading = 0) {
15661
16167
  return `data:image/svg+xml;charset=UTF-8,${encodeURIComponent(svg)}`;
15662
16168
  }
15663
16169
 
15664
- const CLASS$b = `${COMPONENT_PREFIX$1}map-view`;
16170
+ const CLASS$a = `${COMPONENT_PREFIX$1}map-view`;
15665
16171
  const DEFAULT_CENTER = { lat: 4.711, lng: -74.0721 };
15666
16172
  const DEFAULT_ZOOM = 12;
15667
16173
  const DEFAULT_HEIGHT$1 = 320;
@@ -15731,6 +16237,8 @@ const MapView = ({
15731
16237
  eventBus,
15732
16238
  expandable = true,
15733
16239
  fullBleed = false,
16240
+ interactive = true,
16241
+ expandIcon = "expand",
15734
16242
  animateMs,
15735
16243
  className
15736
16244
  }) => {
@@ -15786,7 +16294,12 @@ const MapView = ({
15786
16294
  mapTypeControl: false,
15787
16295
  streetViewControl: false,
15788
16296
  fullscreenControl: false,
15789
- styles: leerEstiloDelTema()
16297
+ styles: leerEstiloDelTema(),
16298
+ // SPEC-182 — un mapa solo para mirar no se queda con el gesto: `none` es la forma oficial
16299
+ // de Google de que el dedo y la rueda sigan desplazando la página. Se fija al crear el mapa
16300
+ // porque el modo no cambia en caliente: quien quiera el otro monta otra instancia (la de
16301
+ // pantalla completa lo es).
16302
+ ...interactive ? {} : { gestureHandling: "none", zoomControl: false, keyboardShortcuts: false }
15790
16303
  });
15791
16304
  mapRef.current.addListener("dragstart", () => {
15792
16305
  followSuspendedRef.current = true;
@@ -15804,7 +16317,7 @@ const MapView = ({
15804
16317
  React.useEffect(() => {
15805
16318
  if (!mapReady || !mapRef.current) return;
15806
16319
  const maps = window.google.maps;
15807
- const editable = !!onMoveRef.current;
16320
+ const editable = interactive && !!onMoveRef.current;
15808
16321
  const alive = new Set(list.map((p) => p.id));
15809
16322
  markersRef.current.forEach((entry, id) => {
15810
16323
  if (alive.has(id)) return;
@@ -15876,7 +16389,7 @@ const MapView = ({
15876
16389
  } else {
15877
16390
  mapRef.current.fitBounds(bounds);
15878
16391
  }
15879
- }, [mapReady, list, animateMs]);
16392
+ }, [mapReady, list, animateMs, interactive]);
15880
16393
  React.useEffect(() => {
15881
16394
  if (!mapReady || !mapRef.current) return;
15882
16395
  const maps = window.google.maps;
@@ -15926,7 +16439,7 @@ const MapView = ({
15926
16439
  if (!mapReady || !mapRef.current) return;
15927
16440
  clickListenerRef.current?.remove?.();
15928
16441
  clickListenerRef.current = null;
15929
- if (!onPointMove || list.length !== 1) return;
16442
+ if (!interactive || !onPointMove || list.length !== 1) return;
15930
16443
  const pointId = list[0].id;
15931
16444
  clickListenerRef.current = mapRef.current.addListener("click", (e) => {
15932
16445
  onMoveRef.current?.(pointId, e.latLng.lat(), e.latLng.lng());
@@ -15935,7 +16448,7 @@ const MapView = ({
15935
16448
  clickListenerRef.current?.remove?.();
15936
16449
  clickListenerRef.current = null;
15937
16450
  };
15938
- }, [mapReady, list, onPointMove]);
16451
+ }, [mapReady, list, onPointMove, interactive]);
15939
16452
  React.useEffect(
15940
16453
  () => () => {
15941
16454
  markersRef.current.forEach((entry) => {
@@ -15962,31 +16475,34 @@ const MapView = ({
15962
16475
  document.body.style.overflow = prev;
15963
16476
  };
15964
16477
  }, [expanded]);
15965
- const rootClass = [CLASS$b, fullBleed && `${CLASS$b}--full-bleed`, className].filter(Boolean).join(" ");
16478
+ const rootClass = [CLASS$a, fullBleed && `${CLASS$a}--full-bleed`, className].filter(Boolean).join(" ");
15966
16479
  if (overQuota) {
15967
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: rootClass, style: { height }, children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$b}__state ${CLASS$b}__state--error`, children: labels?.quotaText ?? "Se alcanz\xF3 el l\xEDmite diario de uso del mapa. Intenta ma\xF1ana." }) });
16480
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: rootClass, style: { height }, children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$a}__state ${CLASS$a}__state--error`, children: labels?.quotaText ?? "Se alcanz\xF3 el l\xEDmite diario de uso del mapa. Intenta ma\xF1ana." }) });
15968
16481
  }
15969
16482
  if (status === "error") {
15970
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: rootClass, style: { height }, children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$b}__state ${CLASS$b}__state--error`, children: labels?.errorText ?? "No se pudo cargar el mapa." }) });
16483
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: rootClass, style: { height }, children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$a}__state ${CLASS$a}__state--error`, children: labels?.errorText ?? "No se pudo cargar el mapa." }) });
15971
16484
  }
15972
16485
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: rootClass, style: fullBleed ? void 0 : { height }, children: [
15973
- status !== "ready" && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$b}__state`, children: labels?.loadingText ?? "Cargando mapa\u2026" }),
15974
- /* @__PURE__ */ jsxRuntime.jsx("div", { ref: nodeRef, className: `${CLASS$b}__canvas`, "aria-label": "Mapa", role: "application" }),
15975
- status === "ready" && list.length === 0 && allRoutes.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$b}__empty`, children: labels?.emptyText ?? "Sin ubicaciones para mostrar" }),
15976
- status === "ready" && onPointMove && list.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$b}__empty`, children: labels?.moveHint ?? "Arrastra el pin o toca el mapa para ajustar" }),
16486
+ status !== "ready" && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$a}__state`, children: labels?.loadingText ?? "Cargando mapa\u2026" }),
16487
+ /* @__PURE__ */ jsxRuntime.jsx("div", { ref: nodeRef, className: `${CLASS$a}__canvas`, "aria-label": "Mapa", role: "application" }),
16488
+ status === "ready" && list.length === 0 && allRoutes.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$a}__empty`, children: labels?.emptyText ?? "Sin ubicaciones para mostrar" }),
16489
+ status === "ready" && interactive && onPointMove && list.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$a}__empty`, children: labels?.moveHint ?? "Arrastra el pin o toca el mapa para ajustar" }),
15977
16490
  status === "ready" && expandable && !fullBleed && /* @__PURE__ */ jsxRuntime.jsx(
15978
16491
  "button",
15979
16492
  {
15980
16493
  type: "button",
15981
- className: `${CLASS$b}__expand`,
15982
- "aria-label": labels?.expandAria ?? "Ver el mapa en pantalla completa",
15983
- title: labels?.expandAria ?? "Pantalla completa",
16494
+ className: `${CLASS$a}__expand`,
16495
+ "aria-label": labels?.expandAria ?? (expandIcon === "edit" ? "Ajustar el punto en el mapa" : "Ver el mapa en pantalla completa"),
16496
+ title: labels?.expandAria ?? (expandIcon === "edit" ? "Ajustar el punto" : "Pantalla completa"),
15984
16497
  onClick: () => setExpanded(true),
15985
- children: /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7" }) })
16498
+ children: expandIcon === "edit" ? /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
16499
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 20h9" }),
16500
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z" })
16501
+ ] }) : /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7" }) })
15986
16502
  }
15987
16503
  ),
15988
16504
  expanded && ReactDOM.createPortal(
15989
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$b}-fs`, role: "dialog", "aria-modal": "true", "aria-label": "Mapa", children: [
16505
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$a}-fs`, role: "dialog", "aria-modal": "true", "aria-label": "Mapa", children: [
15990
16506
  /* @__PURE__ */ jsxRuntime.jsx(
15991
16507
  MapView,
15992
16508
  {
@@ -16000,7 +16516,7 @@ const MapView = ({
16000
16516
  "button",
16001
16517
  {
16002
16518
  type: "button",
16003
- className: `${CLASS$b}-fs__close`,
16519
+ className: `${CLASS$a}-fs__close`,
16004
16520
  "aria-label": labels?.closeAria ?? "Cerrar el mapa",
16005
16521
  onClick: () => setExpanded(false),
16006
16522
  children: /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
@@ -16116,7 +16632,7 @@ function reverseGeocode(lat, lng) {
16116
16632
  });
16117
16633
  }
16118
16634
 
16119
- const CLASS$a = `${COMPONENT_PREFIX$1}location-field`;
16635
+ const CLASS$9 = `${COMPONENT_PREFIX$1}location-field`;
16120
16636
  const GPS_TIMEOUT_MS = 1e4;
16121
16637
  const CONFIRM_MAP_HEIGHT = 180;
16122
16638
  const LocationField = ({
@@ -16189,16 +16705,16 @@ const LocationField = ({
16189
16705
  }
16190
16706
  };
16191
16707
  const hasPoint = value?.lat != null && value?.lng != null;
16192
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$a}${error ? ` ${CLASS$a}--error` : ""}`, ref: boxRef, children: [
16193
- label && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${CLASS$a}__label`, children: [
16708
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$9}${error ? ` ${CLASS$9}--error` : ""}`, ref: boxRef, children: [
16709
+ label && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${CLASS$9}__label`, children: [
16194
16710
  label,
16195
16711
  required ? " *" : ""
16196
16712
  ] }),
16197
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$a}__row`, children: [
16713
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$9}__row`, children: [
16198
16714
  /* @__PURE__ */ jsxRuntime.jsx(
16199
16715
  "input",
16200
16716
  {
16201
- className: `${CLASS$a}__input`,
16717
+ className: `${CLASS$9}__input`,
16202
16718
  type: "text",
16203
16719
  value: text,
16204
16720
  disabled,
@@ -16212,7 +16728,7 @@ const LocationField = ({
16212
16728
  "button",
16213
16729
  {
16214
16730
  type: "button",
16215
- className: `${CLASS$a}__gps`,
16731
+ className: `${CLASS$9}__gps`,
16216
16732
  onClick: useMyLocation,
16217
16733
  disabled: disabled || gps === "locating",
16218
16734
  title: labels?.useMyLocation ?? "Enviar mi ubicaci\xF3n",
@@ -16226,21 +16742,24 @@ const LocationField = ({
16226
16742
  }
16227
16743
  )
16228
16744
  ] }),
16229
- open && suggestions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("ul", { className: `${CLASS$a}__suggestions`, children: suggestions.map((s) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => void pickSuggestion(s.id, s.description), children: s.description }) }, s.id)) }),
16230
- error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$a}__error`, children: error }),
16231
- gps === "denied" && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$a}__hint ${CLASS$a}__hint--warn`, children: labels?.permissionDenied ?? "No diste permiso de ubicaci\xF3n. Puedes escribir la direcci\xF3n." }),
16232
- gps === "unavailable" && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$a}__hint ${CLASS$a}__hint--warn`, children: labels?.unavailable ?? "No pudimos obtener tu ubicaci\xF3n. Puedes escribir la direcci\xF3n." }),
16233
- hasPoint && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$a}__confirm`, children: [
16745
+ open && suggestions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("ul", { className: `${CLASS$9}__suggestions`, children: suggestions.map((s) => /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => void pickSuggestion(s.id, s.description), children: s.description }) }, s.id)) }),
16746
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$9}__error`, children: error }),
16747
+ gps === "denied" && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$9}__hint ${CLASS$9}__hint--warn`, children: labels?.permissionDenied ?? "No diste permiso de ubicaci\xF3n. Puedes escribir la direcci\xF3n." }),
16748
+ gps === "unavailable" && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$9}__hint ${CLASS$9}__hint--warn`, children: labels?.unavailable ?? "No pudimos obtener tu ubicaci\xF3n. Puedes escribir la direcci\xF3n." }),
16749
+ hasPoint && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$9}__confirm`, children: [
16234
16750
  /* @__PURE__ */ jsxRuntime.jsx(
16235
16751
  MapView,
16236
16752
  {
16237
16753
  apiKey,
16238
16754
  points: [{ id: "sel", lat: value.lat, lng: value.lng, label: value?.address }],
16239
16755
  height: CONFIRM_MAP_HEIGHT,
16240
- onPointMove: (id, lat, lng) => void movePoint(id, lat, lng)
16756
+ onPointMove: (id, lat, lng) => void movePoint(id, lat, lng),
16757
+ interactive: false,
16758
+ expandIcon: "edit",
16759
+ labels: { expandAria: labels?.editAria ?? "Ajustar el punto en el mapa" }
16241
16760
  }
16242
16761
  ),
16243
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$a}__hint`, children: labels?.confirmHint ?? "Verifica que el punto sea correcto." })
16762
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$9}__hint`, children: labels?.confirmHint ?? "El pin marca d\xF3nde est\xE1 el veh\xEDculo. Si no es el punto exacto, toca el l\xE1piz: en el mapa grande puedes arrastrar el pin o tocar el lugar correcto." })
16244
16763
  ] })
16245
16764
  ] });
16246
16765
  };
@@ -16272,6 +16791,8 @@ function toRenderField(f, loaded, eventBus, mapsApiKey, loadError) {
16272
16791
  // y, a media fila, su campo hermano se quedaba con ~400px de blanco al lado. Medido entre
16273
16792
  // «¿En qué situación está?» y «¿A dónde lo llevamos?» del formulario de solicitud.
16274
16793
  gridSpan: 2,
16794
+ showIf: showIfDe(f),
16795
+ // SPEC-181
16275
16796
  uiProps: {
16276
16797
  // SPEC-074 — `error` viene del render de CUSTOM (DynamicForm ya lo pasaba) y aquí se
16277
16798
  // desechaba: el campo obligatorio más importante era el único mudo.
@@ -16304,14 +16825,22 @@ function toRenderField(f, loaded, eventBus, mapsApiKey, loadError) {
16304
16825
  columnWidth: f.columnWidth,
16305
16826
  fixed: f.fixed,
16306
16827
  align: f.align,
16828
+ showIf: showIfDe(f),
16829
+ // SPEC-181
16830
+ sanitize: f.sanitize,
16831
+ // SPEC-183
16307
16832
  // SPEC-106 T8 — con un fallo de carga, el desplegable dice que no se pudo preguntar en vez
16308
16833
  // de «no hay opciones disponibles», que es una respuesta y no la tenemos.
16309
- uiProps: loadError ? { options: options ?? [], notFoundContent: loadError, ...f.searchable ? { showSearch: true } : {} } : options ? { options, ...f.searchable ? { showSearch: true } : {} } : void 0,
16834
+ uiProps: loadError ? { options: options ?? [], notFoundContent: loadError, ...f.searchable ? { showSearch: true } : {}, ...f.picker ? { picker: f.picker } : {} } : options ? { options, ...f.searchable ? { showSearch: true } : {}, ...f.picker ? { picker: f.picker } : {} } : f.picker ? { picker: f.picker } : void 0,
16310
16835
  formatValue
16311
16836
  };
16312
16837
  }
16313
16838
  const cumpleCondicion = (c, row) => c.in.includes(String(row[c.field]));
16314
16839
  const cumplenTodas = (c, row) => (Array.isArray(c) ? c : [c]).every((x) => cumpleCondicion(x, row));
16840
+ function showIfDe(f) {
16841
+ const cond = f.visibleWhen;
16842
+ return cond ? (values) => cumplenTodas(cond, values) : void 0;
16843
+ }
16315
16844
  function matchesVisibleWhen(a, row) {
16316
16845
  if (a.hiddenWhen && cumplenTodas(a.hiddenWhen, row)) return false;
16317
16846
  if (!a.visibleWhen) return true;
@@ -16863,7 +17392,7 @@ function markFitOutliers(points, radiusKm = FIT_RADIUS_KM) {
16863
17392
  return { points: marcados, outside };
16864
17393
  }
16865
17394
 
16866
- const CLASS$9 = `${COMPONENT_PREFIX$1}services-map`;
17395
+ const CLASS$8 = `${COMPONENT_PREFIX$1}services-map`;
16867
17396
  const DEFAULT_HEIGHT = 340;
16868
17397
  function readNumber(row, field) {
16869
17398
  if (!field) return void 0;
@@ -16989,7 +17518,7 @@ const ServicesMap = ({ config, eventBus, apiKey, filter, fill }) => {
16989
17518
  [livePoints]
16990
17519
  );
16991
17520
  const nadaQueDibujar = rows !== null && allPoints.length === 0 && route.length === 0;
16992
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: fill ? `${CLASS$9} ${CLASS$9}--fill` : CLASS$9, children: rows === null ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$9}__state`, children: labels.loadingText ?? "Cargando ubicaciones\u2026" }) : nadaQueDibujar ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$9}__state`, children: lineaSinMapa(labels, missing, failed) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
17521
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: fill ? `${CLASS$8} ${CLASS$8}--fill` : CLASS$8, children: rows === null ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$8}__state`, children: labels.loadingText ?? "Cargando ubicaciones\u2026" }) : nadaQueDibujar ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$8}__state`, children: lineaSinMapa(labels, missing, failed) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
16993
17522
  /* @__PURE__ */ jsxRuntime.jsx(
16994
17523
  MapView,
16995
17524
  {
@@ -17003,20 +17532,20 @@ const ServicesMap = ({ config, eventBus, apiKey, filter, fill }) => {
17003
17532
  labels: { emptyText: labels.emptyText }
17004
17533
  }
17005
17534
  ),
17006
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$9}__notes`, children: [
17007
- livePoints.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: `${CLASS$9}__note ${CLASS$9}__note--live`, children: [
17535
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$8}__notes`, children: [
17536
+ livePoints.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: `${CLASS$8}__note ${CLASS$8}__note--live`, children: [
17008
17537
  (config.live?.labels?.liveText ?? "{n} en movimiento").replace(
17009
17538
  "{n}",
17010
17539
  String(livePoints.length)
17011
17540
  ),
17012
17541
  simulated > 0 && ` \xB7 ${config.live?.labels?.simulatedText ?? "incluye posiciones simuladas"}`
17013
17542
  ] }),
17014
- missing > 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$9}__note`, children: ((missing === 1 ? labels.missingTextOne : void 0) ?? labels.missingText ?? "{n} sin ubicaci\xF3n registrada").replace("{n}", String(missing)) }),
17015
- outside > 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$9}__note`, children: (labels.outsideText ?? "{n} fuera de la zona (aleja el mapa para verlos)").replace(
17543
+ missing > 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$8}__note`, children: ((missing === 1 ? labels.missingTextOne : void 0) ?? labels.missingText ?? "{n} sin ubicaci\xF3n registrada").replace("{n}", String(missing)) }),
17544
+ outside > 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$8}__note`, children: (labels.outsideText ?? "{n} fuera de la zona (aleja el mapa para verlos)").replace(
17016
17545
  "{n}",
17017
17546
  String(outside)
17018
17547
  ) }),
17019
- failed && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$9}__note`, children: "No se pudieron cargar las ubicaciones." })
17548
+ failed && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$8}__note`, children: "No se pudieron cargar las ubicaciones." })
17020
17549
  ] })
17021
17550
  ] }) });
17022
17551
  };
@@ -17032,7 +17561,7 @@ function lineaSinMapa(labels, missing, failed) {
17032
17561
  return labels.emptyText ?? "Sin ubicaciones para mostrar";
17033
17562
  }
17034
17563
 
17035
- const CLASS$8 = `${COMPONENT_PREFIX$1}service-shortcuts`;
17564
+ const CLASS$7 = `${COMPONENT_PREFIX$1}service-shortcuts`;
17036
17565
  const ICONS = {
17037
17566
  // SPEC-126 — quien DESPACHA tambien necesita sus puertas, y una de ellas son las conversaciones
17038
17567
  // de sus servicios. Los cinco iconos que habia eran todos de quien PIDE una grua.
@@ -17086,16 +17615,16 @@ const ServiceShortcuts = ({
17086
17615
  }) => {
17087
17616
  if (!options?.length) return null;
17088
17617
  const elegido = !!selectedId;
17089
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: [CLASS$8, elegido ? `${CLASS$8}--used` : ""].filter(Boolean).join(" "), children: options.map((o) => {
17618
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: [CLASS$7, elegido ? `${CLASS$7}--used` : ""].filter(Boolean).join(" "), children: options.map((o) => {
17090
17619
  const esElegido = o.id === selectedId;
17091
17620
  return /* @__PURE__ */ jsxRuntime.jsxs(
17092
17621
  "button",
17093
17622
  {
17094
17623
  type: "button",
17095
17624
  className: [
17096
- `${CLASS$8}__item`,
17097
- elegido ? `${CLASS$8}__item--off` : "",
17098
- esElegido ? `${CLASS$8}__item--chosen` : ""
17625
+ `${CLASS$7}__item`,
17626
+ elegido ? `${CLASS$7}__item--off` : "",
17627
+ esElegido ? `${CLASS$7}__item--chosen` : ""
17099
17628
  ].filter(Boolean).join(" "),
17100
17629
  disabled: elegido,
17101
17630
  "aria-disabled": elegido,
@@ -17107,12 +17636,12 @@ const ServiceShortcuts = ({
17107
17636
  else if (o.route) eventBus?.emit(CHAT_EVENT.NAVIGATE, { route: o.route });
17108
17637
  },
17109
17638
  children: [
17110
- o.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$8}__icon`, children: ICONS[o.icon] }),
17111
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${CLASS$8}__text`, children: [
17112
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$8}__label`, children: o.label }),
17113
- o.hint && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$8}__hint`, children: o.hint })
17639
+ o.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$7}__icon`, children: ICONS[o.icon] }),
17640
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${CLASS$7}__text`, children: [
17641
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$7}__label`, children: o.label }),
17642
+ o.hint && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$7}__hint`, children: o.hint })
17114
17643
  ] }),
17115
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$8}__arrow`, children: esElegido ? CHECK : elegido ? null : /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "9 18 15 12 9 6" }) }) })
17644
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$7}__arrow`, children: esElegido ? CHECK : elegido ? null : /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "9 18 15 12 9 6" }) }) })
17116
17645
  ]
17117
17646
  },
17118
17647
  o.id
@@ -17681,19 +18210,19 @@ function ChatNavigatorChat({ component, eventBus }) {
17681
18210
  ] });
17682
18211
  }
17683
18212
 
17684
- const CLASS$7 = `${COMPONENT_PREFIX$1}user-tools`;
18213
+ const CLASS$6 = `${COMPONENT_PREFIX$1}user-tools`;
17685
18214
  const UserTools = ({ config, onChange, onAction, className }) => {
17686
18215
  const { title, description, items } = config;
17687
- return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: [CLASS$7, className].filter(Boolean).join(" "), children: [
17688
- title && /* @__PURE__ */ jsxRuntime.jsx("h2", { className: `${CLASS$7}__title`, children: title }),
17689
- description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$7}__description`, children: description }),
17690
- /* @__PURE__ */ jsxRuntime.jsx("ul", { className: `${CLASS$7}__list`, children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsx("li", { className: `${CLASS$7}__item`, children: item.kind === "action" ? (
18216
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: [CLASS$6, className].filter(Boolean).join(" "), children: [
18217
+ title && /* @__PURE__ */ jsxRuntime.jsx("h2", { className: `${CLASS$6}__title`, children: title }),
18218
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$6}__description`, children: description }),
18219
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: `${CLASS$6}__list`, children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsx("li", { className: `${CLASS$6}__item`, children: item.kind === "action" ? (
17691
18220
  // SPEC-139 T9 — un ajuste que se pulsa: mismo renglón (etiqueta y pista), y en vez
17692
18221
  // de la caja, un botón que dice lo que hace.
17693
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$7}__action`, children: [
17694
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${CLASS$7}__text`, children: [
17695
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$7}__label`, children: item.label }),
17696
- item.hint && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$7}__hint`, children: item.hint })
18222
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$6}__action`, children: [
18223
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${CLASS$6}__text`, children: [
18224
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$6}__label`, children: item.label }),
18225
+ item.hint && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$6}__hint`, children: item.hint })
17697
18226
  ] }),
17698
18227
  /* @__PURE__ */ jsxRuntime.jsx(
17699
18228
  Button,
@@ -17712,13 +18241,13 @@ const UserTools = ({ config, onChange, onAction, className }) => {
17712
18241
  checked: Boolean(item.value),
17713
18242
  disabled: item.disabled,
17714
18243
  onChange: (checked) => onChange?.(item.id, checked),
17715
- label: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${CLASS$7}__text`, children: [
17716
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$7}__label`, children: item.label }),
17717
- item.hint && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$7}__hint`, children: item.hint })
18244
+ label: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${CLASS$6}__text`, children: [
18245
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$6}__label`, children: item.label }),
18246
+ item.hint && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$6}__hint`, children: item.hint })
17718
18247
  ] })
17719
18248
  }
17720
18249
  ) }, item.id)) }),
17721
- items.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$7}__empty`, children: "No hay herramientas disponibles por ahora." })
18250
+ items.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$6}__empty`, children: "No hay herramientas disponibles por ahora." })
17722
18251
  ] });
17723
18252
  };
17724
18253
  UserTools.displayName = "UserTools";
@@ -18328,7 +18857,7 @@ const ChatHeader = ({
18328
18857
  ] });
18329
18858
  };
18330
18859
 
18331
- const CLASS$6 = `${COMPONENT_PREFIX$1}floating-actions`;
18860
+ const CLASS$5 = `${COMPONENT_PREFIX$1}floating-actions`;
18332
18861
  const ICON_VALUES = new Set(Object.values(ICON_TYPES));
18333
18862
  function renderIcon(icon) {
18334
18863
  if (typeof icon === "string" && ICON_VALUES.has(icon)) {
@@ -18337,23 +18866,23 @@ function renderIcon(icon) {
18337
18866
  return icon;
18338
18867
  }
18339
18868
  function Side({ buttons, align, eventBus }) {
18340
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${CLASS$6}__group ${CLASS$6}__group--${align}`, children: buttons.map((b) => {
18869
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${CLASS$5}__group ${CLASS$5}__group--${align}`, children: buttons.map((b) => {
18341
18870
  const emit = () => {
18342
18871
  if (b.disabled) return;
18343
18872
  eventBus.emit(b.event, b.payload);
18344
18873
  };
18345
18874
  if (b.custom) {
18346
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$6}__slot`, children: [
18875
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$5}__slot`, children: [
18347
18876
  b.custom,
18348
- b.panel && b.open && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${CLASS$6}__panel ${CLASS$6}__panel--${align}`, children: b.panel })
18877
+ b.panel && b.open && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${CLASS$5}__panel ${CLASS$5}__panel--${align}`, children: b.panel })
18349
18878
  ] }, b.id);
18350
18879
  }
18351
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$6}__slot`, children: [
18880
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$5}__slot`, children: [
18352
18881
  /* @__PURE__ */ jsxRuntime.jsxs(
18353
18882
  "button",
18354
18883
  {
18355
18884
  type: "button",
18356
- className: [`${CLASS$6}__button`, b.active ? `${CLASS$6}__button--active` : ""].filter(Boolean).join(" "),
18885
+ className: [`${CLASS$5}__button`, b.active ? `${CLASS$5}__button--active` : ""].filter(Boolean).join(" "),
18357
18886
  "aria-label": b.ariaLabel,
18358
18887
  title: b.ariaLabel,
18359
18888
  "aria-pressed": b.active,
@@ -18361,16 +18890,16 @@ function Side({ buttons, align, eventBus }) {
18361
18890
  onClick: emit,
18362
18891
  children: [
18363
18892
  renderIcon(b.icon),
18364
- b.badge != null && b.badge !== "" && b.badge !== 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$6}__badge`, children: b.badge })
18893
+ b.badge != null && b.badge !== "" && b.badge !== 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$5}__badge`, children: b.badge })
18365
18894
  ]
18366
18895
  }
18367
18896
  ),
18368
- b.panel && b.open && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${CLASS$6}__panel ${CLASS$6}__panel--${align}`, children: b.panel })
18897
+ b.panel && b.open && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${CLASS$5}__panel ${CLASS$5}__panel--${align}`, children: b.panel })
18369
18898
  ] }, b.id);
18370
18899
  }) });
18371
18900
  }
18372
18901
  const ChatFloatingActions = ({ eventBus, left = [], right = [], offset = 12, glass = false }) => {
18373
- const cls = [CLASS$6, glass ? `${CLASS$6}--glass` : ""].filter(Boolean).join(" ");
18902
+ const cls = [CLASS$5, glass ? `${CLASS$5}--glass` : ""].filter(Boolean).join(" ");
18374
18903
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cls, style: { paddingLeft: offset, paddingRight: offset }, children: [
18375
18904
  /* @__PURE__ */ jsxRuntime.jsx(Side, { buttons: left, align: "left", eventBus }),
18376
18905
  /* @__PURE__ */ jsxRuntime.jsx(Side, { buttons: right, align: "right", eventBus })
@@ -18803,7 +19332,7 @@ const UserMessage = ({
18803
19332
  ] }) });
18804
19333
  };
18805
19334
 
18806
- const CLASS$5 = `${COMPONENT_PREFIX$1}photo-picker`;
19335
+ const CLASS$4 = `${COMPONENT_PREFIX$1}photo-picker`;
18807
19336
  const PhotoPicker = ({
18808
19337
  label,
18809
19338
  hint,
@@ -18828,8 +19357,8 @@ const PhotoPicker = ({
18828
19357
  void onFiles(e.target.files);
18829
19358
  e.target.value = "";
18830
19359
  };
18831
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$5}${error ? ` ${CLASS$5}--error` : ""}`, children: [
18832
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${CLASS$5}__label`, children: [
19360
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$4}${error ? ` ${CLASS$4}--error` : ""}`, children: [
19361
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${CLASS$4}__label`, children: [
18833
19362
  label,
18834
19363
  required ? " *" : "",
18835
19364
  hechas > 0 ? ` (${hechas}${max ? `/${max}` : ""})` : ""
@@ -18838,7 +19367,7 @@ const PhotoPicker = ({
18838
19367
  "input",
18839
19368
  {
18840
19369
  ref: galeriaRef,
18841
- className: `${CLASS$5}__native`,
19370
+ className: `${CLASS$4}__native`,
18842
19371
  type: "file",
18843
19372
  accept: "image/*",
18844
19373
  multiple: max !== 1,
@@ -18851,7 +19380,7 @@ const PhotoPicker = ({
18851
19380
  "input",
18852
19381
  {
18853
19382
  ref: camaraRef,
18854
- className: `${CLASS$5}__native`,
19383
+ className: `${CLASS$4}__native`,
18855
19384
  type: "file",
18856
19385
  accept: "image/*",
18857
19386
  capture: "environment",
@@ -18860,15 +19389,15 @@ const PhotoPicker = ({
18860
19389
  "data-testid": "photo-picker-camera"
18861
19390
  }
18862
19391
  ),
18863
- entries.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("ul", { className: `${CLASS$5}__grid`, children: entries.map((e, i) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: `${CLASS$5}__thumb ${CLASS$5}__thumb--${e.status}`, children: [
18864
- e.previewUrl ? /* @__PURE__ */ jsxRuntime.jsx("img", { className: `${CLASS$5}__img`, src: e.previewUrl, alt: e.name }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$5}__placeholder`, "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(Icon$1, { type: ICON_TYPES.IMAGE }) }),
18865
- e.status === "uploading" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$5}__state`, children: "Subiendo\u2026" }),
18866
- e.status === "error" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$5}__state ${CLASS$5}__state--error`, children: "No se pudo subir" }),
19392
+ entries.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("ul", { className: `${CLASS$4}__grid`, children: entries.map((e, i) => /* @__PURE__ */ jsxRuntime.jsxs("li", { className: `${CLASS$4}__thumb ${CLASS$4}__thumb--${e.status}`, children: [
19393
+ e.previewUrl ? /* @__PURE__ */ jsxRuntime.jsx("img", { className: `${CLASS$4}__img`, src: e.previewUrl, alt: e.name }) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$4}__placeholder`, "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(Icon$1, { type: ICON_TYPES.IMAGE }) }),
19394
+ e.status === "uploading" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$4}__state`, children: "Subiendo\u2026" }),
19395
+ e.status === "error" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$4}__state ${CLASS$4}__state--error`, children: "No se pudo subir" }),
18867
19396
  onRemove && e.status !== "uploading" && /* @__PURE__ */ jsxRuntime.jsx(
18868
19397
  "button",
18869
19398
  {
18870
19399
  type: "button",
18871
- className: `${CLASS$5}__remove`,
19400
+ className: `${CLASS$4}__remove`,
18872
19401
  onClick: () => onRemove(i),
18873
19402
  "aria-label": `Quitar ${e.name}`,
18874
19403
  disabled,
@@ -18876,12 +19405,12 @@ const PhotoPicker = ({
18876
19405
  }
18877
19406
  )
18878
19407
  ] }, `${e.name}-${i}`)) }),
18879
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$5}__actions`, children: [
19408
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$4}__actions`, children: [
18880
19409
  capture && /* @__PURE__ */ jsxRuntime.jsxs(
18881
19410
  "button",
18882
19411
  {
18883
19412
  type: "button",
18884
- className: `${CLASS$5}__pick`,
19413
+ className: `${CLASS$4}__pick`,
18885
19414
  onClick: () => elegir(camaraRef),
18886
19415
  disabled: disabled || lleno,
18887
19416
  children: [
@@ -18894,7 +19423,7 @@ const PhotoPicker = ({
18894
19423
  "button",
18895
19424
  {
18896
19425
  type: "button",
18897
- className: `${CLASS$5}__pick ${CLASS$5}__pick--secondary`,
19426
+ className: `${CLASS$4}__pick ${CLASS$4}__pick--secondary`,
18898
19427
  onClick: () => elegir(galeriaRef),
18899
19428
  disabled: disabled || lleno,
18900
19429
  children: [
@@ -18904,13 +19433,13 @@ const PhotoPicker = ({
18904
19433
  }
18905
19434
  )
18906
19435
  ] }),
18907
- error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$5}__error`, children: error }),
18908
- !error && subiendo && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$5}__hint`, children: "Espera a que terminen de subir." }),
18909
- !error && !subiendo && hint && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$5}__hint`, children: hint })
19436
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$4}__error`, children: error }),
19437
+ !error && subiendo && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$4}__hint`, children: "Espera a que terminen de subir." }),
19438
+ !error && !subiendo && hint && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$4}__hint`, children: hint })
18910
19439
  ] });
18911
19440
  };
18912
19441
 
18913
- const CLASS$4 = `${COMPONENT_PREFIX$1}credentials-card`;
19442
+ const CLASS$3 = `${COMPONENT_PREFIX$1}credentials-card`;
18914
19443
  async function copiar(texto) {
18915
19444
  try {
18916
19445
  await navigator.clipboard.writeText(texto);
@@ -18927,15 +19456,15 @@ const Fila = ({ row }) => {
18927
19456
  const t = setTimeout(() => setCopiado(false), 1800);
18928
19457
  return () => clearTimeout(t);
18929
19458
  }, [copiado]);
18930
- return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: `${CLASS$4}__row`, children: [
18931
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$4}__label`, children: row.label }),
18932
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$4}__value`, "data-testid": `credential-${row.label}`, children: visible ? row.value : "\u2022".repeat(Math.min(row.value.length, 12)) }),
18933
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${CLASS$4}__tools`, children: [
19459
+ return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: `${CLASS$3}__row`, children: [
19460
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$3}__label`, children: row.label }),
19461
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$3}__value`, "data-testid": `credential-${row.label}`, children: visible ? row.value : "\u2022".repeat(Math.min(row.value.length, 12)) }),
19462
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${CLASS$3}__tools`, children: [
18934
19463
  row.masked && /* @__PURE__ */ jsxRuntime.jsx(
18935
19464
  "button",
18936
19465
  {
18937
19466
  type: "button",
18938
- className: `${CLASS$4}__tool`,
19467
+ className: `${CLASS$3}__tool`,
18939
19468
  onClick: () => setVisible((v) => !v),
18940
19469
  "aria-label": visible ? `Ocultar ${row.label}` : `Ver ${row.label}`,
18941
19470
  children: visible ? "Ocultar" : "Ver"
@@ -18945,7 +19474,7 @@ const Fila = ({ row }) => {
18945
19474
  "button",
18946
19475
  {
18947
19476
  type: "button",
18948
- className: `${CLASS$4}__tool`,
19477
+ className: `${CLASS$3}__tool`,
18949
19478
  onClick: async () => setCopiado(await copiar(row.value)),
18950
19479
  "aria-label": `Copiar ${row.label}`,
18951
19480
  children: copiado ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -18964,12 +19493,12 @@ const CredentialsCard = ({
18964
19493
  note,
18965
19494
  action,
18966
19495
  className
18967
- }) => /* @__PURE__ */ jsxRuntime.jsxs("section", { className: [CLASS$4, className].filter(Boolean).join(" "), "aria-label": title, children: [
18968
- /* @__PURE__ */ jsxRuntime.jsx("h3", { className: `${CLASS$4}__title`, children: title }),
18969
- intro && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$4}__intro`, children: intro }),
18970
- /* @__PURE__ */ jsxRuntime.jsx("ul", { className: `${CLASS$4}__rows`, children: rows.map((r) => /* @__PURE__ */ jsxRuntime.jsx(Fila, { row: r }, r.label)) }),
18971
- note && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$4}__note`, children: note }),
18972
- action && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${CLASS$4}__action`, children: /* @__PURE__ */ jsxRuntime.jsx(Button, { fullWidth: true, onClick: action.onClick, disabled: action.disabled, children: action.label }) })
19496
+ }) => /* @__PURE__ */ jsxRuntime.jsxs("section", { className: [CLASS$3, className].filter(Boolean).join(" "), "aria-label": title, children: [
19497
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: `${CLASS$3}__title`, children: title }),
19498
+ intro && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$3}__intro`, children: intro }),
19499
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: `${CLASS$3}__rows`, children: rows.map((r) => /* @__PURE__ */ jsxRuntime.jsx(Fila, { row: r }, r.label)) }),
19500
+ note && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$3}__note`, children: note }),
19501
+ action && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${CLASS$3}__action`, children: /* @__PURE__ */ jsxRuntime.jsx(Button, { fullWidth: true, onClick: action.onClick, disabled: action.disabled, children: action.label }) })
18973
19502
  ] });
18974
19503
  CredentialsCard.displayName = "CredentialsCard";
18975
19504
 
@@ -19141,7 +19670,7 @@ const TextArea = React.forwardRef(
19141
19670
  );
19142
19671
  TextArea.displayName = "TextArea";
19143
19672
 
19144
- const CLASS$3 = `${COMPONENT_PREFIX$1}support-request-form`;
19673
+ const CLASS$2 = `${COMPONENT_PREFIX$1}support-request-form`;
19145
19674
  const VACIO = { name: "", email: "", phone: "", subject: "", message: "" };
19146
19675
  function faltantes(v) {
19147
19676
  if (v.name.trim().length < 2) return "Escribe tu nombre.";
@@ -19186,14 +19715,14 @@ const SupportRequestForm = ({
19186
19715
  return /* @__PURE__ */ jsxRuntime.jsxs(
19187
19716
  "form",
19188
19717
  {
19189
- className: [CLASS$3, sent ? `${CLASS$3}--sent` : "", className].filter(Boolean).join(" "),
19718
+ className: [CLASS$2, sent ? `${CLASS$2}--sent` : "", className].filter(Boolean).join(" "),
19190
19719
  onSubmit: enviar,
19191
19720
  noValidate: true,
19192
19721
  children: [
19193
- /* @__PURE__ */ jsxRuntime.jsx("h4", { className: `${CLASS$3}__title`, children: title }),
19194
- intro && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$3}__intro`, children: intro }),
19195
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$3}__fields`, children: [
19196
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$3}__row`, children: [
19722
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: `${CLASS$2}__title`, children: title }),
19723
+ intro && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$2}__intro`, children: intro }),
19724
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$2}__fields`, children: [
19725
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$2}__row`, children: [
19197
19726
  /* @__PURE__ */ jsxRuntime.jsx(Input$1, { label: "Nombre", value: values.name, onChange: set("name"), fullWidth: true, disabled: sent, autoComplete: "name" }),
19198
19727
  /* @__PURE__ */ jsxRuntime.jsx(Input$1, { label: "Tel\xE9fono (opcional)", value: values.phone, onChange: set("phone"), fullWidth: true, disabled: sent, inputMode: "tel", autoComplete: "tel" })
19199
19728
  ] }),
@@ -19201,13 +19730,13 @@ const SupportRequestForm = ({
19201
19730
  /* @__PURE__ */ jsxRuntime.jsx(Input$1, { label: "Asunto", value: values.subject, onChange: set("subject"), fullWidth: true, disabled: sent }),
19202
19731
  /* @__PURE__ */ jsxRuntime.jsx(TextArea, { label: "Mensaje", value: values.message, onChange: set("message"), fullWidth: true, disabled: sent, minRows: 3, maxLength: 4e3, showCount: true })
19203
19732
  ] }),
19204
- error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$3}__error`, role: "alert", children: error }),
19205
- sent ? /* @__PURE__ */ jsxRuntime.jsxs("p", { className: `${CLASS$3}__done`, role: "status", children: [
19733
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$2}__error`, role: "alert", children: error }),
19734
+ sent ? /* @__PURE__ */ jsxRuntime.jsxs("p", { className: `${CLASS$2}__done`, role: "status", children: [
19206
19735
  /* @__PURE__ */ jsxRuntime.jsx(Icon$1, { type: ICON_TYPES.CHECK, size: "small" }),
19207
19736
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: sentLabel })
19208
19737
  ] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
19209
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${CLASS$3}__actions`, children: /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "submit", variant: "primary", isLoading: enviando, disabled: enviando, children: submitLabel }) }),
19210
- note && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$3}__note`, children: note })
19738
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${CLASS$2}__actions`, children: /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "submit", variant: "primary", isLoading: enviando, disabled: enviando, children: submitLabel }) }),
19739
+ note && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$2}__note`, children: note })
19211
19740
  ] })
19212
19741
  ]
19213
19742
  }
@@ -22140,105 +22669,6 @@ const Notification = ({
22140
22669
  };
22141
22670
  Notification.displayName = "Notification";
22142
22671
 
22143
- const CARD_VARIANTS = {
22144
- /** Con sombra: flota sobre el contenido (hojas, diálogos, paneles). */
22145
- ELEVATED: "elevated"};
22146
- const CARD_PADDINGS = {
22147
- MEDIUM: "medium",
22148
- LARGE: "large"
22149
- };
22150
- const CARD_RADII = {
22151
- NONE: "none",
22152
- LARGE: "large"
22153
- };
22154
-
22155
- const BASE = `${COMPONENT_PREFIX}card`;
22156
- const Card = React.forwardRef(
22157
- ({
22158
- variant = CARD_VARIANTS.ELEVATED,
22159
- padding = CARD_PADDINGS.MEDIUM,
22160
- radius = CARD_RADII.LARGE,
22161
- fullWidth = false,
22162
- className = "",
22163
- children,
22164
- ...rest
22165
- }, ref) => {
22166
- const classes = [
22167
- BASE,
22168
- `${BASE}--${variant}`,
22169
- `${BASE}--padding-${padding}`,
22170
- `${BASE}--radius-${radius}`,
22171
- fullWidth ? `${BASE}--full-width` : "",
22172
- className
22173
- ].filter(Boolean).join(" ");
22174
- return /* @__PURE__ */ jsxRuntime.jsx("div", { ref, className: classes, ...rest, children });
22175
- }
22176
- );
22177
- Card.displayName = "Card";
22178
-
22179
- const CLASS$2 = "px-lumi-bottom-sheet";
22180
- const BottomSheet = ({
22181
- open,
22182
- children,
22183
- onClose,
22184
- showGrabber = true,
22185
- closeOnBackdrop = false,
22186
- closeOnEscape = true,
22187
- ariaLabelledBy,
22188
- className = ""
22189
- }) => {
22190
- React.useEffect(() => {
22191
- if (!open) return;
22192
- const onKey = (e) => {
22193
- if (e.key === "Escape" && closeOnEscape) onClose?.();
22194
- };
22195
- document.addEventListener("keydown", onKey);
22196
- const previous = document.body.style.overflow;
22197
- document.body.style.overflow = "hidden";
22198
- return () => {
22199
- document.removeEventListener("keydown", onKey);
22200
- document.body.style.overflow = previous;
22201
- };
22202
- }, [open, closeOnEscape, onClose]);
22203
- if (!open) return null;
22204
- return ReactDOM.createPortal(
22205
- /* @__PURE__ */ jsxRuntime.jsxs(
22206
- "div",
22207
- {
22208
- className: [CLASS$2, className].filter(Boolean).join(" "),
22209
- role: "dialog",
22210
- "aria-modal": "true",
22211
- "aria-labelledby": ariaLabelledBy,
22212
- children: [
22213
- /* @__PURE__ */ jsxRuntime.jsx(
22214
- "div",
22215
- {
22216
- className: `${CLASS$2}__backdrop`,
22217
- "aria-hidden": "true",
22218
- onClick: closeOnBackdrop ? onClose : void 0
22219
- }
22220
- ),
22221
- /* @__PURE__ */ jsxRuntime.jsxs(
22222
- Card,
22223
- {
22224
- className: `${CLASS$2}__sheet`,
22225
- padding: CARD_PADDINGS.LARGE,
22226
- radius: CARD_RADII.NONE,
22227
- fullWidth: true,
22228
- children: [
22229
- showGrabber && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${CLASS$2}__grabber`, "aria-hidden": "true" }),
22230
- children
22231
- ]
22232
- }
22233
- )
22234
- ]
22235
- }
22236
- ),
22237
- document.body
22238
- );
22239
- };
22240
- BottomSheet.displayName = "BottomSheet";
22241
-
22242
22672
  const CLASS$1 = `${COMPONENT_PREFIX}live-indicator`;
22243
22673
  const LiveIndicator = ({
22244
22674
  label,
@@ -25435,6 +25865,7 @@ exports.ChatUserAttachments = UserAttachments;
25435
25865
  exports.ChatUserMessage = UserMessage;
25436
25866
  exports.ChatWidget = ChatWidget;
25437
25867
  exports.CredentialsCard = CredentialsCard;
25868
+ exports.DEFAULT_PHONE_COUNTRY = DEFAULT_PHONE_COUNTRY;
25438
25869
  exports.FileField = FileField;
25439
25870
  exports.LUMI_BADGE_VARIANTS = BADGE_VARIANTS;
25440
25871
  exports.LUMI_DEFAULT_TITLES = DEFAULT_TITLES;
@@ -25481,10 +25912,12 @@ exports.LumiMenuItem = MenuItem;
25481
25912
  exports.LumiMenuItemGroup = MenuItemGroup;
25482
25913
  exports.LumiNotification = Notification;
25483
25914
  exports.LumiPagination = Pagination;
25915
+ exports.LumiPhoneInput = PhoneInput;
25484
25916
  exports.LumiPopover = Popover;
25485
25917
  exports.LumiQRCode = QRCode;
25486
25918
  exports.LumiRecordCard = RecordCard;
25487
25919
  exports.LumiSelect = Select$1;
25920
+ exports.LumiSheetSelect = SheetSelect;
25488
25921
  exports.LumiStepIndicator = StepIndicator;
25489
25922
  exports.LumiStepper = Stepper;
25490
25923
  exports.LumiSubMenu = SubMenu;
@@ -25494,8 +25927,10 @@ exports.LumiTextArea = TextArea;
25494
25927
  exports.LumiTimeInput = TimeInput$1;
25495
25928
  exports.LumiTooltip = Tooltip;
25496
25929
  exports.MapView = MapView;
25930
+ exports.PHONE_COUNTRIES = PHONE_COUNTRIES;
25497
25931
  exports.PhotoPicker = PhotoPicker;
25498
25932
  exports.ReactiveCrud = ReactiveCrud;
25933
+ exports.SANITIZE_PRESETS = SANITIZE_PRESETS;
25499
25934
  exports.ServiceShortcuts = ServiceShortcuts;
25500
25935
  exports.ServicesMap = ServicesMap;
25501
25936
  exports.SessionExpiryPrompt = SessionExpiryPrompt;
@@ -25510,11 +25945,14 @@ exports.createStoreMerger = createStoreMerger;
25510
25945
  exports.deepMerge = deepMerge;
25511
25946
  exports.disabledReasonFor = disabledReasonFor;
25512
25947
  exports.fetchViaEventBus = fetchViaEventBus;
25948
+ exports.flagOf = flagOf;
25513
25949
  exports.getLastFleetSnapshot = getLastFleetSnapshot;
25514
25950
  exports.matchesDisabledWhen = matchesDisabledWhen;
25515
25951
  exports.matchesDoneWhen = matchesDoneWhen;
25516
25952
  exports.matchesVisibleWhen = matchesVisibleWhen;
25517
25953
  exports.registerChatComponents = registerChatComponents;
25954
+ exports.sanitize = sanitize;
25518
25955
  exports.setLastFleetSnapshot = setLastFleetSnapshot;
25956
+ exports.splitPhone = splitPhone;
25519
25957
  exports.useChatConfig = useChatConfig;
25520
25958
  exports.useReactiveCrud = useReactiveCrud;