pixelon 0.9.3 → 0.9.5

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;
@@ -16359,8 +16888,20 @@ function collapseLocationFields(fields, valores) {
16359
16888
  if (f.moleculeType !== "LOCATION" || !f.bind) continue;
16360
16889
  const address = out[f.bind.address];
16361
16890
  if (typeof address !== "string" || !address.trim()) continue;
16362
- out[f.name] = { address };
16891
+ const lat = out[f.bind.lat];
16892
+ const lng = out[f.bind.lng];
16893
+ const source = f.bind.source ? out[f.bind.source] : void 0;
16894
+ const valor = { address };
16895
+ if (typeof lat === "number" && typeof lng === "number") {
16896
+ valor.lat = lat;
16897
+ valor.lng = lng;
16898
+ }
16899
+ if (typeof source === "string" && source) valor.source = source;
16900
+ out[f.name] = valor;
16363
16901
  delete out[f.bind.address];
16902
+ delete out[f.bind.lat];
16903
+ delete out[f.bind.lng];
16904
+ if (f.bind.source) delete out[f.bind.source];
16364
16905
  }
16365
16906
  return out;
16366
16907
  }
@@ -16513,6 +17054,8 @@ function ReactiveCrudChat({ component, eventBus, assistantMessageId }) {
16513
17054
  const moduleKey = pick("module");
16514
17055
  const openCreate = pick("openCreate") === true;
16515
17056
  const prefill = pick("prefill");
17057
+ const createLabel = pick("createLabel");
17058
+ const createdLabel = pick("createdLabel");
16516
17059
  let config;
16517
17060
  if (typeof moduleKey === "string" && resolveModuleConfig) {
16518
17061
  config = resolveModuleConfig(moduleKey);
@@ -16535,7 +17078,7 @@ function ReactiveCrudChat({ component, eventBus, assistantMessageId }) {
16535
17078
  if (!config) return null;
16536
17079
  const title = config.title ?? "Gesti\xF3n";
16537
17080
  const done = openCreate && created;
16538
- const triggerLabel = done ? config.labels?.createdButton ?? "Solicitud enviada" : openCreate ? config.labels?.createButton ?? "Crear" : `Abrir ${title.toLowerCase()}`;
17081
+ const triggerLabel = done ? createdLabel ?? config.labels?.createdButton ?? "Solicitud enviada" : openCreate ? createLabel ?? config.labels?.createButton ?? "Crear" : `Abrir ${title.toLowerCase()}`;
16539
17082
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
16540
17083
  /* @__PURE__ */ jsxRuntime.jsxs(
16541
17084
  "button",
@@ -16605,6 +17148,16 @@ function ReactiveCrudChat({ component, eventBus, assistantMessageId }) {
16605
17148
  ] });
16606
17149
  }
16607
17150
 
17151
+ function plazoVigente(deadline, row) {
17152
+ if (!deadline || !row) return null;
17153
+ const lista = Array.isArray(deadline) ? deadline : [deadline];
17154
+ for (const d of lista) {
17155
+ const at = row[d.field];
17156
+ if (typeof at === "string" && at) return { config: d, at };
17157
+ }
17158
+ return null;
17159
+ }
17160
+
16608
17161
  function restante(hasta) {
16609
17162
  return Math.max(0, hasta - Date.now());
16610
17163
  }
@@ -16716,6 +17269,7 @@ function ServiceActionsPanel({ config, recordId, recordLabel, allowed, sinAccion
16716
17269
  return () => observador.disconnect();
16717
17270
  }, [recordId]);
16718
17271
  const gastada = !esUltima;
17272
+ const plazo = plazoVigente(config.deadline, row);
16719
17273
  const actions = React.useMemo(() => {
16720
17274
  if (!row) return [];
16721
17275
  if (gastada) {
@@ -16747,12 +17301,12 @@ function ServiceActionsPanel({ config, recordId, recordLabel, allowed, sinAccion
16747
17301
  crud.loading && !row && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-crud-item__hint", children: "Cargando\u2026" }),
16748
17302
  !crud.loading && !row && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-crud-item__hint", children: "No se encontr\xF3 el servicio." }),
16749
17303
  gastada && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-chat-crud-item__hint", children: "Este paso ya se gestion\xF3. Contin\xFAa en el mensaje m\xE1s reciente." }),
16750
- row && !gastada && config.deadline && typeof row[config.deadline.field] === "string" && /* @__PURE__ */ jsxRuntime.jsx(
17304
+ row && !gastada && plazo && /* @__PURE__ */ jsxRuntime.jsx(
16751
17305
  DeadlineCountdown,
16752
17306
  {
16753
- deadline: row[config.deadline.field],
16754
- label: config.deadline.label,
16755
- expiredLabel: config.deadline.expiredLabel
17307
+ deadline: plazo.at,
17308
+ label: plazo.config.label,
17309
+ expiredLabel: plazo.config.expiredLabel
16756
17310
  }
16757
17311
  ),
16758
17312
  row && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-chat-crud-item__actions", children: [
@@ -16863,7 +17417,7 @@ function markFitOutliers(points, radiusKm = FIT_RADIUS_KM) {
16863
17417
  return { points: marcados, outside };
16864
17418
  }
16865
17419
 
16866
- const CLASS$9 = `${COMPONENT_PREFIX$1}services-map`;
17420
+ const CLASS$8 = `${COMPONENT_PREFIX$1}services-map`;
16867
17421
  const DEFAULT_HEIGHT = 340;
16868
17422
  function readNumber(row, field) {
16869
17423
  if (!field) return void 0;
@@ -16989,7 +17543,7 @@ const ServicesMap = ({ config, eventBus, apiKey, filter, fill }) => {
16989
17543
  [livePoints]
16990
17544
  );
16991
17545
  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: [
17546
+ 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
17547
  /* @__PURE__ */ jsxRuntime.jsx(
16994
17548
  MapView,
16995
17549
  {
@@ -17003,20 +17557,20 @@ const ServicesMap = ({ config, eventBus, apiKey, filter, fill }) => {
17003
17557
  labels: { emptyText: labels.emptyText }
17004
17558
  }
17005
17559
  ),
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: [
17560
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$8}__notes`, children: [
17561
+ livePoints.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: `${CLASS$8}__note ${CLASS$8}__note--live`, children: [
17008
17562
  (config.live?.labels?.liveText ?? "{n} en movimiento").replace(
17009
17563
  "{n}",
17010
17564
  String(livePoints.length)
17011
17565
  ),
17012
17566
  simulated > 0 && ` \xB7 ${config.live?.labels?.simulatedText ?? "incluye posiciones simuladas"}`
17013
17567
  ] }),
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(
17568
+ 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)) }),
17569
+ 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
17570
  "{n}",
17017
17571
  String(outside)
17018
17572
  ) }),
17019
- failed && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$9}__note`, children: "No se pudieron cargar las ubicaciones." })
17573
+ failed && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$8}__note`, children: "No se pudieron cargar las ubicaciones." })
17020
17574
  ] })
17021
17575
  ] }) });
17022
17576
  };
@@ -17032,7 +17586,7 @@ function lineaSinMapa(labels, missing, failed) {
17032
17586
  return labels.emptyText ?? "Sin ubicaciones para mostrar";
17033
17587
  }
17034
17588
 
17035
- const CLASS$8 = `${COMPONENT_PREFIX$1}service-shortcuts`;
17589
+ const CLASS$7 = `${COMPONENT_PREFIX$1}service-shortcuts`;
17036
17590
  const ICONS = {
17037
17591
  // SPEC-126 — quien DESPACHA tambien necesita sus puertas, y una de ellas son las conversaciones
17038
17592
  // de sus servicios. Los cinco iconos que habia eran todos de quien PIDE una grua.
@@ -17086,16 +17640,16 @@ const ServiceShortcuts = ({
17086
17640
  }) => {
17087
17641
  if (!options?.length) return null;
17088
17642
  const elegido = !!selectedId;
17089
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: [CLASS$8, elegido ? `${CLASS$8}--used` : ""].filter(Boolean).join(" "), children: options.map((o) => {
17643
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: [CLASS$7, elegido ? `${CLASS$7}--used` : ""].filter(Boolean).join(" "), children: options.map((o) => {
17090
17644
  const esElegido = o.id === selectedId;
17091
17645
  return /* @__PURE__ */ jsxRuntime.jsxs(
17092
17646
  "button",
17093
17647
  {
17094
17648
  type: "button",
17095
17649
  className: [
17096
- `${CLASS$8}__item`,
17097
- elegido ? `${CLASS$8}__item--off` : "",
17098
- esElegido ? `${CLASS$8}__item--chosen` : ""
17650
+ `${CLASS$7}__item`,
17651
+ elegido ? `${CLASS$7}__item--off` : "",
17652
+ esElegido ? `${CLASS$7}__item--chosen` : ""
17099
17653
  ].filter(Boolean).join(" "),
17100
17654
  disabled: elegido,
17101
17655
  "aria-disabled": elegido,
@@ -17107,12 +17661,12 @@ const ServiceShortcuts = ({
17107
17661
  else if (o.route) eventBus?.emit(CHAT_EVENT.NAVIGATE, { route: o.route });
17108
17662
  },
17109
17663
  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 })
17664
+ o.icon && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$7}__icon`, children: ICONS[o.icon] }),
17665
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${CLASS$7}__text`, children: [
17666
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$7}__label`, children: o.label }),
17667
+ o.hint && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$7}__hint`, children: o.hint })
17114
17668
  ] }),
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" }) }) })
17669
+ /* @__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
17670
  ]
17117
17671
  },
17118
17672
  o.id
@@ -17681,19 +18235,19 @@ function ChatNavigatorChat({ component, eventBus }) {
17681
18235
  ] });
17682
18236
  }
17683
18237
 
17684
- const CLASS$7 = `${COMPONENT_PREFIX$1}user-tools`;
18238
+ const CLASS$6 = `${COMPONENT_PREFIX$1}user-tools`;
17685
18239
  const UserTools = ({ config, onChange, onAction, className }) => {
17686
18240
  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" ? (
18241
+ return /* @__PURE__ */ jsxRuntime.jsxs("section", { className: [CLASS$6, className].filter(Boolean).join(" "), children: [
18242
+ title && /* @__PURE__ */ jsxRuntime.jsx("h2", { className: `${CLASS$6}__title`, children: title }),
18243
+ description && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$6}__description`, children: description }),
18244
+ /* @__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
18245
  // SPEC-139 T9 — un ajuste que se pulsa: mismo renglón (etiqueta y pista), y en vez
17692
18246
  // 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 })
18247
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$6}__action`, children: [
18248
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${CLASS$6}__text`, children: [
18249
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$6}__label`, children: item.label }),
18250
+ item.hint && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$6}__hint`, children: item.hint })
17697
18251
  ] }),
17698
18252
  /* @__PURE__ */ jsxRuntime.jsx(
17699
18253
  Button,
@@ -17712,13 +18266,13 @@ const UserTools = ({ config, onChange, onAction, className }) => {
17712
18266
  checked: Boolean(item.value),
17713
18267
  disabled: item.disabled,
17714
18268
  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 })
18269
+ label: /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${CLASS$6}__text`, children: [
18270
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$6}__label`, children: item.label }),
18271
+ item.hint && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$6}__hint`, children: item.hint })
17718
18272
  ] })
17719
18273
  }
17720
18274
  ) }, item.id)) }),
17721
- items.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$7}__empty`, children: "No hay herramientas disponibles por ahora." })
18275
+ items.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$6}__empty`, children: "No hay herramientas disponibles por ahora." })
17722
18276
  ] });
17723
18277
  };
17724
18278
  UserTools.displayName = "UserTools";
@@ -18328,7 +18882,7 @@ const ChatHeader = ({
18328
18882
  ] });
18329
18883
  };
18330
18884
 
18331
- const CLASS$6 = `${COMPONENT_PREFIX$1}floating-actions`;
18885
+ const CLASS$5 = `${COMPONENT_PREFIX$1}floating-actions`;
18332
18886
  const ICON_VALUES = new Set(Object.values(ICON_TYPES));
18333
18887
  function renderIcon(icon) {
18334
18888
  if (typeof icon === "string" && ICON_VALUES.has(icon)) {
@@ -18337,23 +18891,23 @@ function renderIcon(icon) {
18337
18891
  return icon;
18338
18892
  }
18339
18893
  function Side({ buttons, align, eventBus }) {
18340
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${CLASS$6}__group ${CLASS$6}__group--${align}`, children: buttons.map((b) => {
18894
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${CLASS$5}__group ${CLASS$5}__group--${align}`, children: buttons.map((b) => {
18341
18895
  const emit = () => {
18342
18896
  if (b.disabled) return;
18343
18897
  eventBus.emit(b.event, b.payload);
18344
18898
  };
18345
18899
  if (b.custom) {
18346
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$6}__slot`, children: [
18900
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$5}__slot`, children: [
18347
18901
  b.custom,
18348
- b.panel && b.open && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${CLASS$6}__panel ${CLASS$6}__panel--${align}`, children: b.panel })
18902
+ b.panel && b.open && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${CLASS$5}__panel ${CLASS$5}__panel--${align}`, children: b.panel })
18349
18903
  ] }, b.id);
18350
18904
  }
18351
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$6}__slot`, children: [
18905
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$5}__slot`, children: [
18352
18906
  /* @__PURE__ */ jsxRuntime.jsxs(
18353
18907
  "button",
18354
18908
  {
18355
18909
  type: "button",
18356
- className: [`${CLASS$6}__button`, b.active ? `${CLASS$6}__button--active` : ""].filter(Boolean).join(" "),
18910
+ className: [`${CLASS$5}__button`, b.active ? `${CLASS$5}__button--active` : ""].filter(Boolean).join(" "),
18357
18911
  "aria-label": b.ariaLabel,
18358
18912
  title: b.ariaLabel,
18359
18913
  "aria-pressed": b.active,
@@ -18361,16 +18915,16 @@ function Side({ buttons, align, eventBus }) {
18361
18915
  onClick: emit,
18362
18916
  children: [
18363
18917
  renderIcon(b.icon),
18364
- b.badge != null && b.badge !== "" && b.badge !== 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$6}__badge`, children: b.badge })
18918
+ b.badge != null && b.badge !== "" && b.badge !== 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$5}__badge`, children: b.badge })
18365
18919
  ]
18366
18920
  }
18367
18921
  ),
18368
- b.panel && b.open && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${CLASS$6}__panel ${CLASS$6}__panel--${align}`, children: b.panel })
18922
+ b.panel && b.open && /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${CLASS$5}__panel ${CLASS$5}__panel--${align}`, children: b.panel })
18369
18923
  ] }, b.id);
18370
18924
  }) });
18371
18925
  }
18372
18926
  const ChatFloatingActions = ({ eventBus, left = [], right = [], offset = 12, glass = false }) => {
18373
- const cls = [CLASS$6, glass ? `${CLASS$6}--glass` : ""].filter(Boolean).join(" ");
18927
+ const cls = [CLASS$5, glass ? `${CLASS$5}--glass` : ""].filter(Boolean).join(" ");
18374
18928
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cls, style: { paddingLeft: offset, paddingRight: offset }, children: [
18375
18929
  /* @__PURE__ */ jsxRuntime.jsx(Side, { buttons: left, align: "left", eventBus }),
18376
18930
  /* @__PURE__ */ jsxRuntime.jsx(Side, { buttons: right, align: "right", eventBus })
@@ -18803,7 +19357,7 @@ const UserMessage = ({
18803
19357
  ] }) });
18804
19358
  };
18805
19359
 
18806
- const CLASS$5 = `${COMPONENT_PREFIX$1}photo-picker`;
19360
+ const CLASS$4 = `${COMPONENT_PREFIX$1}photo-picker`;
18807
19361
  const PhotoPicker = ({
18808
19362
  label,
18809
19363
  hint,
@@ -18828,8 +19382,8 @@ const PhotoPicker = ({
18828
19382
  void onFiles(e.target.files);
18829
19383
  e.target.value = "";
18830
19384
  };
18831
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$5}${error ? ` ${CLASS$5}--error` : ""}`, children: [
18832
- /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${CLASS$5}__label`, children: [
19385
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$4}${error ? ` ${CLASS$4}--error` : ""}`, children: [
19386
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${CLASS$4}__label`, children: [
18833
19387
  label,
18834
19388
  required ? " *" : "",
18835
19389
  hechas > 0 ? ` (${hechas}${max ? `/${max}` : ""})` : ""
@@ -18838,7 +19392,7 @@ const PhotoPicker = ({
18838
19392
  "input",
18839
19393
  {
18840
19394
  ref: galeriaRef,
18841
- className: `${CLASS$5}__native`,
19395
+ className: `${CLASS$4}__native`,
18842
19396
  type: "file",
18843
19397
  accept: "image/*",
18844
19398
  multiple: max !== 1,
@@ -18851,7 +19405,7 @@ const PhotoPicker = ({
18851
19405
  "input",
18852
19406
  {
18853
19407
  ref: camaraRef,
18854
- className: `${CLASS$5}__native`,
19408
+ className: `${CLASS$4}__native`,
18855
19409
  type: "file",
18856
19410
  accept: "image/*",
18857
19411
  capture: "environment",
@@ -18860,15 +19414,15 @@ const PhotoPicker = ({
18860
19414
  "data-testid": "photo-picker-camera"
18861
19415
  }
18862
19416
  ),
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" }),
19417
+ 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: [
19418
+ 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 }) }),
19419
+ e.status === "uploading" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$4}__state`, children: "Subiendo\u2026" }),
19420
+ e.status === "error" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$4}__state ${CLASS$4}__state--error`, children: "No se pudo subir" }),
18867
19421
  onRemove && e.status !== "uploading" && /* @__PURE__ */ jsxRuntime.jsx(
18868
19422
  "button",
18869
19423
  {
18870
19424
  type: "button",
18871
- className: `${CLASS$5}__remove`,
19425
+ className: `${CLASS$4}__remove`,
18872
19426
  onClick: () => onRemove(i),
18873
19427
  "aria-label": `Quitar ${e.name}`,
18874
19428
  disabled,
@@ -18876,12 +19430,12 @@ const PhotoPicker = ({
18876
19430
  }
18877
19431
  )
18878
19432
  ] }, `${e.name}-${i}`)) }),
18879
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$5}__actions`, children: [
19433
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$4}__actions`, children: [
18880
19434
  capture && /* @__PURE__ */ jsxRuntime.jsxs(
18881
19435
  "button",
18882
19436
  {
18883
19437
  type: "button",
18884
- className: `${CLASS$5}__pick`,
19438
+ className: `${CLASS$4}__pick`,
18885
19439
  onClick: () => elegir(camaraRef),
18886
19440
  disabled: disabled || lleno,
18887
19441
  children: [
@@ -18894,7 +19448,7 @@ const PhotoPicker = ({
18894
19448
  "button",
18895
19449
  {
18896
19450
  type: "button",
18897
- className: `${CLASS$5}__pick ${CLASS$5}__pick--secondary`,
19451
+ className: `${CLASS$4}__pick ${CLASS$4}__pick--secondary`,
18898
19452
  onClick: () => elegir(galeriaRef),
18899
19453
  disabled: disabled || lleno,
18900
19454
  children: [
@@ -18904,13 +19458,13 @@ const PhotoPicker = ({
18904
19458
  }
18905
19459
  )
18906
19460
  ] }),
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 })
19461
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$4}__error`, children: error }),
19462
+ !error && subiendo && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$4}__hint`, children: "Espera a que terminen de subir." }),
19463
+ !error && !subiendo && hint && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$4}__hint`, children: hint })
18910
19464
  ] });
18911
19465
  };
18912
19466
 
18913
- const CLASS$4 = `${COMPONENT_PREFIX$1}credentials-card`;
19467
+ const CLASS$3 = `${COMPONENT_PREFIX$1}credentials-card`;
18914
19468
  async function copiar(texto) {
18915
19469
  try {
18916
19470
  await navigator.clipboard.writeText(texto);
@@ -18927,15 +19481,15 @@ const Fila = ({ row }) => {
18927
19481
  const t = setTimeout(() => setCopiado(false), 1800);
18928
19482
  return () => clearTimeout(t);
18929
19483
  }, [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: [
19484
+ return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: `${CLASS$3}__row`, children: [
19485
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: `${CLASS$3}__label`, children: row.label }),
19486
+ /* @__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)) }),
19487
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: `${CLASS$3}__tools`, children: [
18934
19488
  row.masked && /* @__PURE__ */ jsxRuntime.jsx(
18935
19489
  "button",
18936
19490
  {
18937
19491
  type: "button",
18938
- className: `${CLASS$4}__tool`,
19492
+ className: `${CLASS$3}__tool`,
18939
19493
  onClick: () => setVisible((v) => !v),
18940
19494
  "aria-label": visible ? `Ocultar ${row.label}` : `Ver ${row.label}`,
18941
19495
  children: visible ? "Ocultar" : "Ver"
@@ -18945,7 +19499,7 @@ const Fila = ({ row }) => {
18945
19499
  "button",
18946
19500
  {
18947
19501
  type: "button",
18948
- className: `${CLASS$4}__tool`,
19502
+ className: `${CLASS$3}__tool`,
18949
19503
  onClick: async () => setCopiado(await copiar(row.value)),
18950
19504
  "aria-label": `Copiar ${row.label}`,
18951
19505
  children: copiado ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
@@ -18964,12 +19518,12 @@ const CredentialsCard = ({
18964
19518
  note,
18965
19519
  action,
18966
19520
  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 }) })
19521
+ }) => /* @__PURE__ */ jsxRuntime.jsxs("section", { className: [CLASS$3, className].filter(Boolean).join(" "), "aria-label": title, children: [
19522
+ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: `${CLASS$3}__title`, children: title }),
19523
+ intro && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$3}__intro`, children: intro }),
19524
+ /* @__PURE__ */ jsxRuntime.jsx("ul", { className: `${CLASS$3}__rows`, children: rows.map((r) => /* @__PURE__ */ jsxRuntime.jsx(Fila, { row: r }, r.label)) }),
19525
+ note && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$3}__note`, children: note }),
19526
+ 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
19527
  ] });
18974
19528
  CredentialsCard.displayName = "CredentialsCard";
18975
19529
 
@@ -19141,7 +19695,7 @@ const TextArea = React.forwardRef(
19141
19695
  );
19142
19696
  TextArea.displayName = "TextArea";
19143
19697
 
19144
- const CLASS$3 = `${COMPONENT_PREFIX$1}support-request-form`;
19698
+ const CLASS$2 = `${COMPONENT_PREFIX$1}support-request-form`;
19145
19699
  const VACIO = { name: "", email: "", phone: "", subject: "", message: "" };
19146
19700
  function faltantes(v) {
19147
19701
  if (v.name.trim().length < 2) return "Escribe tu nombre.";
@@ -19186,14 +19740,14 @@ const SupportRequestForm = ({
19186
19740
  return /* @__PURE__ */ jsxRuntime.jsxs(
19187
19741
  "form",
19188
19742
  {
19189
- className: [CLASS$3, sent ? `${CLASS$3}--sent` : "", className].filter(Boolean).join(" "),
19743
+ className: [CLASS$2, sent ? `${CLASS$2}--sent` : "", className].filter(Boolean).join(" "),
19190
19744
  onSubmit: enviar,
19191
19745
  noValidate: true,
19192
19746
  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: [
19747
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: `${CLASS$2}__title`, children: title }),
19748
+ intro && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$2}__intro`, children: intro }),
19749
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$2}__fields`, children: [
19750
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${CLASS$2}__row`, children: [
19197
19751
  /* @__PURE__ */ jsxRuntime.jsx(Input$1, { label: "Nombre", value: values.name, onChange: set("name"), fullWidth: true, disabled: sent, autoComplete: "name" }),
19198
19752
  /* @__PURE__ */ jsxRuntime.jsx(Input$1, { label: "Tel\xE9fono (opcional)", value: values.phone, onChange: set("phone"), fullWidth: true, disabled: sent, inputMode: "tel", autoComplete: "tel" })
19199
19753
  ] }),
@@ -19201,13 +19755,13 @@ const SupportRequestForm = ({
19201
19755
  /* @__PURE__ */ jsxRuntime.jsx(Input$1, { label: "Asunto", value: values.subject, onChange: set("subject"), fullWidth: true, disabled: sent }),
19202
19756
  /* @__PURE__ */ jsxRuntime.jsx(TextArea, { label: "Mensaje", value: values.message, onChange: set("message"), fullWidth: true, disabled: sent, minRows: 3, maxLength: 4e3, showCount: true })
19203
19757
  ] }),
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: [
19758
+ error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$2}__error`, role: "alert", children: error }),
19759
+ sent ? /* @__PURE__ */ jsxRuntime.jsxs("p", { className: `${CLASS$2}__done`, role: "status", children: [
19206
19760
  /* @__PURE__ */ jsxRuntime.jsx(Icon$1, { type: ICON_TYPES.CHECK, size: "small" }),
19207
19761
  /* @__PURE__ */ jsxRuntime.jsx("span", { children: sentLabel })
19208
19762
  ] }) : /* @__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 })
19763
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: `${CLASS$2}__actions`, children: /* @__PURE__ */ jsxRuntime.jsx(Button, { type: "submit", variant: "primary", isLoading: enviando, disabled: enviando, children: submitLabel }) }),
19764
+ note && /* @__PURE__ */ jsxRuntime.jsx("p", { className: `${CLASS$2}__note`, children: note })
19211
19765
  ] })
19212
19766
  ]
19213
19767
  }
@@ -22140,105 +22694,6 @@ const Notification = ({
22140
22694
  };
22141
22695
  Notification.displayName = "Notification";
22142
22696
 
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
22697
  const CLASS$1 = `${COMPONENT_PREFIX}live-indicator`;
22243
22698
  const LiveIndicator = ({
22244
22699
  label,
@@ -25435,6 +25890,7 @@ exports.ChatUserAttachments = UserAttachments;
25435
25890
  exports.ChatUserMessage = UserMessage;
25436
25891
  exports.ChatWidget = ChatWidget;
25437
25892
  exports.CredentialsCard = CredentialsCard;
25893
+ exports.DEFAULT_PHONE_COUNTRY = DEFAULT_PHONE_COUNTRY;
25438
25894
  exports.FileField = FileField;
25439
25895
  exports.LUMI_BADGE_VARIANTS = BADGE_VARIANTS;
25440
25896
  exports.LUMI_DEFAULT_TITLES = DEFAULT_TITLES;
@@ -25481,10 +25937,12 @@ exports.LumiMenuItem = MenuItem;
25481
25937
  exports.LumiMenuItemGroup = MenuItemGroup;
25482
25938
  exports.LumiNotification = Notification;
25483
25939
  exports.LumiPagination = Pagination;
25940
+ exports.LumiPhoneInput = PhoneInput;
25484
25941
  exports.LumiPopover = Popover;
25485
25942
  exports.LumiQRCode = QRCode;
25486
25943
  exports.LumiRecordCard = RecordCard;
25487
25944
  exports.LumiSelect = Select$1;
25945
+ exports.LumiSheetSelect = SheetSelect;
25488
25946
  exports.LumiStepIndicator = StepIndicator;
25489
25947
  exports.LumiStepper = Stepper;
25490
25948
  exports.LumiSubMenu = SubMenu;
@@ -25494,8 +25952,10 @@ exports.LumiTextArea = TextArea;
25494
25952
  exports.LumiTimeInput = TimeInput$1;
25495
25953
  exports.LumiTooltip = Tooltip;
25496
25954
  exports.MapView = MapView;
25955
+ exports.PHONE_COUNTRIES = PHONE_COUNTRIES;
25497
25956
  exports.PhotoPicker = PhotoPicker;
25498
25957
  exports.ReactiveCrud = ReactiveCrud;
25958
+ exports.SANITIZE_PRESETS = SANITIZE_PRESETS;
25499
25959
  exports.ServiceShortcuts = ServiceShortcuts;
25500
25960
  exports.ServicesMap = ServicesMap;
25501
25961
  exports.SessionExpiryPrompt = SessionExpiryPrompt;
@@ -25510,11 +25970,14 @@ exports.createStoreMerger = createStoreMerger;
25510
25970
  exports.deepMerge = deepMerge;
25511
25971
  exports.disabledReasonFor = disabledReasonFor;
25512
25972
  exports.fetchViaEventBus = fetchViaEventBus;
25973
+ exports.flagOf = flagOf;
25513
25974
  exports.getLastFleetSnapshot = getLastFleetSnapshot;
25514
25975
  exports.matchesDisabledWhen = matchesDisabledWhen;
25515
25976
  exports.matchesDoneWhen = matchesDoneWhen;
25516
25977
  exports.matchesVisibleWhen = matchesVisibleWhen;
25517
25978
  exports.registerChatComponents = registerChatComponents;
25979
+ exports.sanitize = sanitize;
25518
25980
  exports.setLastFleetSnapshot = setLastFleetSnapshot;
25981
+ exports.splitPhone = splitPhone;
25519
25982
  exports.useChatConfig = useChatConfig;
25520
25983
  exports.useReactiveCrud = useReactiveCrud;