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.esm.js CHANGED
@@ -7343,7 +7343,7 @@ const Input$1 = forwardRef(
7343
7343
  );
7344
7344
  Input$1.displayName = "Input";
7345
7345
 
7346
- const sinTildes = (s) => s.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
7346
+ const sinTildes$2 = (s) => s.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
7347
7347
  const Select$1 = forwardRef(
7348
7348
  ({
7349
7349
  options = [],
@@ -7392,7 +7392,7 @@ const Select$1 = forwardRef(
7392
7392
  const selectorRef = useRef(null);
7393
7393
  const [dropdownPosition, setDropdownPosition] = useState(null);
7394
7394
  const filteredOptions = showSearch && searchValue ? options.filter(
7395
- (option) => filterOption ? filterOption(searchValue, option) : sinTildes(option.label).includes(sinTildes(searchValue))
7395
+ (option) => filterOption ? filterOption(searchValue, option) : sinTildes$2(option.label).includes(sinTildes$2(searchValue))
7396
7396
  ) : options;
7397
7397
  const isOptionSelected = (option) => {
7398
7398
  if (mode === "multiple") {
@@ -12320,6 +12320,442 @@ const CurrencyDisplay = ({
12320
12320
  };
12321
12321
  CurrencyDisplay.displayName = "CurrencyDisplay";
12322
12322
 
12323
+ const CARD_VARIANTS = {
12324
+ /** Con sombra: flota sobre el contenido (hojas, diálogos, paneles). */
12325
+ ELEVATED: "elevated"};
12326
+ const CARD_PADDINGS = {
12327
+ MEDIUM: "medium",
12328
+ LARGE: "large"
12329
+ };
12330
+ const CARD_RADII = {
12331
+ NONE: "none",
12332
+ LARGE: "large"
12333
+ };
12334
+
12335
+ const BASE = `${COMPONENT_PREFIX}card`;
12336
+ const Card = React.forwardRef(
12337
+ ({
12338
+ variant = CARD_VARIANTS.ELEVATED,
12339
+ padding = CARD_PADDINGS.MEDIUM,
12340
+ radius = CARD_RADII.LARGE,
12341
+ fullWidth = false,
12342
+ className = "",
12343
+ children,
12344
+ ...rest
12345
+ }, ref) => {
12346
+ const classes = [
12347
+ BASE,
12348
+ `${BASE}--${variant}`,
12349
+ `${BASE}--padding-${padding}`,
12350
+ `${BASE}--radius-${radius}`,
12351
+ fullWidth ? `${BASE}--full-width` : "",
12352
+ className
12353
+ ].filter(Boolean).join(" ");
12354
+ return /* @__PURE__ */ jsx("div", { ref, className: classes, ...rest, children });
12355
+ }
12356
+ );
12357
+ Card.displayName = "Card";
12358
+
12359
+ const CLASS$j = "px-lumi-bottom-sheet";
12360
+ const BottomSheet = ({
12361
+ open,
12362
+ children,
12363
+ onClose,
12364
+ showGrabber = true,
12365
+ closeOnBackdrop = false,
12366
+ closeOnEscape = true,
12367
+ ariaLabelledBy,
12368
+ className = ""
12369
+ }) => {
12370
+ useEffect(() => {
12371
+ if (!open) return;
12372
+ const onKey = (e) => {
12373
+ if (e.key !== "Escape" || !closeOnEscape) return;
12374
+ e.stopPropagation();
12375
+ onClose?.();
12376
+ };
12377
+ document.addEventListener("keydown", onKey, true);
12378
+ const previous = document.body.style.overflow;
12379
+ document.body.style.overflow = "hidden";
12380
+ return () => {
12381
+ document.removeEventListener("keydown", onKey, true);
12382
+ document.body.style.overflow = previous;
12383
+ };
12384
+ }, [open, closeOnEscape, onClose]);
12385
+ if (!open) return null;
12386
+ return createPortal(
12387
+ /* @__PURE__ */ jsxs(
12388
+ "div",
12389
+ {
12390
+ className: [CLASS$j, className].filter(Boolean).join(" "),
12391
+ role: "dialog",
12392
+ "aria-modal": "true",
12393
+ "aria-labelledby": ariaLabelledBy,
12394
+ children: [
12395
+ /* @__PURE__ */ jsx(
12396
+ "div",
12397
+ {
12398
+ className: `${CLASS$j}__backdrop`,
12399
+ "aria-hidden": "true",
12400
+ onClick: closeOnBackdrop ? onClose : void 0
12401
+ }
12402
+ ),
12403
+ /* @__PURE__ */ jsxs(
12404
+ Card,
12405
+ {
12406
+ className: `${CLASS$j}__sheet`,
12407
+ padding: CARD_PADDINGS.LARGE,
12408
+ radius: CARD_RADII.NONE,
12409
+ fullWidth: true,
12410
+ children: [
12411
+ showGrabber && /* @__PURE__ */ jsx("div", { className: `${CLASS$j}__grabber`, "aria-hidden": "true" }),
12412
+ children
12413
+ ]
12414
+ }
12415
+ )
12416
+ ]
12417
+ }
12418
+ ),
12419
+ document.body
12420
+ );
12421
+ };
12422
+ BottomSheet.displayName = "BottomSheet";
12423
+
12424
+ const PHONE_COUNTRIES = [
12425
+ { code: "CO", name: "Colombia", dialCode: "+57", digits: 10 },
12426
+ { code: "EC", name: "Ecuador", dialCode: "+593", digits: 9 },
12427
+ { code: "PE", name: "Per\xFA", dialCode: "+51", digits: 9 },
12428
+ { code: "VE", name: "Venezuela", dialCode: "+58", digits: 10 },
12429
+ { code: "PA", name: "Panam\xE1", dialCode: "+507", digits: 8 },
12430
+ { code: "MX", name: "M\xE9xico", dialCode: "+52", digits: 10 },
12431
+ { code: "AR", name: "Argentina", dialCode: "+54", digits: 10 },
12432
+ { code: "CL", name: "Chile", dialCode: "+56", digits: 9 },
12433
+ { code: "BR", name: "Brasil", dialCode: "+55", digits: 11 },
12434
+ { code: "CR", name: "Costa Rica", dialCode: "+506", digits: 8 },
12435
+ { code: "US", name: "Estados Unidos", dialCode: "+1", digits: 10 },
12436
+ { code: "ES", name: "Espa\xF1a", dialCode: "+34", digits: 9 }
12437
+ ];
12438
+ const DEFAULT_PHONE_COUNTRY = "CO";
12439
+ function flagOf(code) {
12440
+ const c = (code || "").toUpperCase();
12441
+ if (!/^[A-Z]{2}$/.test(c)) return "";
12442
+ return [...c].map((ch) => String.fromCodePoint(127462 + ch.charCodeAt(0) - 65)).join("");
12443
+ }
12444
+ function splitPhone(value, countries, defaultCountry) {
12445
+ const porDefecto = countries.find((c) => c.code === defaultCountry) ?? countries[0];
12446
+ const v = (value ?? "").replace(/[^0-9+]/g, "");
12447
+ if (v.startsWith("+")) {
12448
+ const d = v.slice(1);
12449
+ const match = countries.filter((c) => d.startsWith(c.dialCode.slice(1))).sort((a, b) => b.dialCode.length - a.dialCode.length)[0];
12450
+ if (match) return { country: match, digits: d.slice(match.dialCode.length - 1) };
12451
+ }
12452
+ return { country: porDefecto, digits: v.replace(/\D/g, "") };
12453
+ }
12454
+
12455
+ const CLASS$i = "px-lumi-phone-input";
12456
+ function sinTildes$1(s) {
12457
+ return s.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase();
12458
+ }
12459
+ const PhoneInput = React.forwardRef(
12460
+ ({
12461
+ value,
12462
+ onChange,
12463
+ onBlur,
12464
+ label,
12465
+ placeholder,
12466
+ disabled,
12467
+ readOnly,
12468
+ error,
12469
+ countries = PHONE_COUNTRIES,
12470
+ defaultCountry = DEFAULT_PHONE_COUNTRY,
12471
+ name,
12472
+ id,
12473
+ className,
12474
+ labels
12475
+ }, ref) => {
12476
+ const [paisElegido, setPaisElegido] = useState(defaultCountry);
12477
+ const [abierto, setAbierto] = useState(false);
12478
+ const [busqueda, setBusqueda] = useState("");
12479
+ const { country, digits } = splitPhone(value, countries, value ? defaultCountry : paisElegido);
12480
+ const pais = value ? country : countries.find((c) => c.code === paisElegido) ?? country;
12481
+ const tope = pais.digits ?? 15;
12482
+ const bloqueado = disabled || readOnly;
12483
+ useEffect(() => {
12484
+ if (!abierto) setBusqueda("");
12485
+ }, [abierto]);
12486
+ const visibles = useMemo(() => {
12487
+ const q = sinTildes$1(busqueda.trim());
12488
+ if (!q) return countries;
12489
+ return countries.filter(
12490
+ (c) => sinTildes$1(c.name).includes(q) || c.dialCode.includes(q) || c.code.toLowerCase() === q
12491
+ );
12492
+ }, [busqueda, countries]);
12493
+ const emitir = (c, d) => {
12494
+ onChange?.(d ? `${c.dialCode}${d}` : "");
12495
+ };
12496
+ const handleDigits = (e) => {
12497
+ const d = e.target.value.replace(/\D/g, "").slice(0, tope);
12498
+ emitir(pais, d);
12499
+ };
12500
+ const elegir = (c) => {
12501
+ setPaisElegido(c.code);
12502
+ emitir(c, digits.slice(0, c.digits ?? 15));
12503
+ setAbierto(false);
12504
+ };
12505
+ const tituloId = `${id ?? name ?? "phone"}-pais-titulo`;
12506
+ return /* @__PURE__ */ jsxs("div", { className: [CLASS$i, error && `${CLASS$i}--error`, bloqueado && `${CLASS$i}--disabled`, className].filter(Boolean).join(" "), children: [
12507
+ /* @__PURE__ */ jsxs(
12508
+ "button",
12509
+ {
12510
+ type: "button",
12511
+ className: `${CLASS$i}__country`,
12512
+ "aria-label": `${labels?.pickCountry ?? "Pa\xEDs del celular"}: ${pais.name} ${pais.dialCode}`,
12513
+ "aria-haspopup": "dialog",
12514
+ "aria-expanded": abierto,
12515
+ disabled: bloqueado,
12516
+ onClick: () => setAbierto(true),
12517
+ children: [
12518
+ /* @__PURE__ */ jsx("span", { className: `${CLASS$i}__flag`, "aria-hidden": "true", children: flagOf(pais.code) }),
12519
+ /* @__PURE__ */ jsx("span", { className: `${CLASS$i}__code`, children: pais.dialCode }),
12520
+ /* @__PURE__ */ jsx("span", { className: `${CLASS$i}__caret`, "aria-hidden": "true", children: "\u25BE" })
12521
+ ]
12522
+ }
12523
+ ),
12524
+ /* @__PURE__ */ jsx("div", { className: `${CLASS$i}__digits`, children: /* @__PURE__ */ jsx(
12525
+ Input$1,
12526
+ {
12527
+ ref,
12528
+ id,
12529
+ name,
12530
+ type: "tel",
12531
+ inputMode: "numeric",
12532
+ autoComplete: "tel-national",
12533
+ label,
12534
+ placeholder,
12535
+ value: digits,
12536
+ onChange: handleDigits,
12537
+ onBlur,
12538
+ disabled,
12539
+ readOnly,
12540
+ error
12541
+ }
12542
+ ) }),
12543
+ /* @__PURE__ */ jsxs(
12544
+ BottomSheet,
12545
+ {
12546
+ open: abierto,
12547
+ onClose: () => setAbierto(false),
12548
+ showGrabber: true,
12549
+ closeOnBackdrop: true,
12550
+ ariaLabelledBy: tituloId,
12551
+ className: `${CLASS$i}__sheet`,
12552
+ children: [
12553
+ /* @__PURE__ */ jsxs("div", { className: `${CLASS$i}__sheet-head`, children: [
12554
+ /* @__PURE__ */ jsx("h2", { id: tituloId, className: `${CLASS$i}__sheet-title`, children: labels?.pickCountry ?? "Pa\xEDs del celular" }),
12555
+ /* @__PURE__ */ jsx(
12556
+ "input",
12557
+ {
12558
+ className: `${CLASS$i}__search`,
12559
+ type: "search",
12560
+ value: busqueda,
12561
+ onChange: (e) => setBusqueda(e.target.value),
12562
+ placeholder: labels?.searchPlaceholder ?? "Buscar pa\xEDs o indicativo",
12563
+ autoComplete: "off",
12564
+ "aria-label": labels?.searchPlaceholder ?? "Buscar pa\xEDs o indicativo"
12565
+ }
12566
+ )
12567
+ ] }),
12568
+ /* @__PURE__ */ jsxs("ul", { className: `${CLASS$i}__list`, role: "listbox", "aria-labelledby": tituloId, children: [
12569
+ visibles.map((c) => {
12570
+ const activo = c.code === pais.code;
12571
+ return /* @__PURE__ */ jsx("li", { role: "option", "aria-selected": activo, children: /* @__PURE__ */ jsxs(
12572
+ "button",
12573
+ {
12574
+ type: "button",
12575
+ className: [`${CLASS$i}__option`, activo && `${CLASS$i}__option--selected`].filter(Boolean).join(" "),
12576
+ onClick: () => elegir(c),
12577
+ children: [
12578
+ /* @__PURE__ */ jsx("span", { className: `${CLASS$i}__flag`, "aria-hidden": "true", children: flagOf(c.code) }),
12579
+ /* @__PURE__ */ jsx("span", { className: `${CLASS$i}__option-name`, children: c.name }),
12580
+ /* @__PURE__ */ jsx("span", { className: `${CLASS$i}__option-code`, children: c.dialCode })
12581
+ ]
12582
+ }
12583
+ ) }, c.code);
12584
+ }),
12585
+ visibles.length === 0 && /* @__PURE__ */ jsx("li", { className: `${CLASS$i}__empty`, children: labels?.noResults ?? "Ning\xFAn pa\xEDs coincide." })
12586
+ ] })
12587
+ ]
12588
+ }
12589
+ )
12590
+ ] });
12591
+ }
12592
+ );
12593
+ PhoneInput.displayName = "PhoneInput";
12594
+
12595
+ const CLASS$h = "px-lumi-sheet-select";
12596
+ function sinTildes(s) {
12597
+ return s.normalize("NFD").replace(/[̀-ͯ]/g, "").toLowerCase();
12598
+ }
12599
+ const SheetSelect = React.forwardRef(
12600
+ ({
12601
+ value,
12602
+ onChange,
12603
+ onBlur,
12604
+ options,
12605
+ label,
12606
+ placeholder,
12607
+ disabled,
12608
+ readOnly,
12609
+ error,
12610
+ searchable,
12611
+ notFoundContent,
12612
+ sheetTitle,
12613
+ searchPlaceholder,
12614
+ name,
12615
+ id,
12616
+ className
12617
+ }, ref) => {
12618
+ const [abierto, setAbierto] = useState(false);
12619
+ const [busqueda, setBusqueda] = useState("");
12620
+ const bloqueado = disabled || readOnly;
12621
+ const elegida = options.find((o) => String(o.value) === String(value ?? ""));
12622
+ const conBuscador = searchable ?? true;
12623
+ useEffect(() => {
12624
+ if (!abierto) setBusqueda("");
12625
+ }, [abierto]);
12626
+ const visibles = useMemo(() => {
12627
+ const q = sinTildes(busqueda.trim());
12628
+ if (!q) return options;
12629
+ return options.filter((o) => sinTildes(o.label).includes(q) || sinTildes(o.hint ?? "").includes(q));
12630
+ }, [busqueda, options]);
12631
+ const abrir = () => {
12632
+ if (!bloqueado) setAbierto(true);
12633
+ };
12634
+ const elegir = (o) => {
12635
+ onChange?.(o.value);
12636
+ setAbierto(false);
12637
+ onBlur?.();
12638
+ };
12639
+ const tituloId = `${id ?? name ?? "sheet-select"}-titulo`;
12640
+ const titulo = sheetTitle ?? label?.replace(/\s\*$/, "") ?? "";
12641
+ return /* @__PURE__ */ jsxs("div", { className: [CLASS$h, bloqueado && `${CLASS$h}--disabled`, className].filter(Boolean).join(" "), children: [
12642
+ /* @__PURE__ */ jsx(
12643
+ Input$1,
12644
+ {
12645
+ ref,
12646
+ id,
12647
+ name,
12648
+ label,
12649
+ placeholder: placeholder ?? "Seleccionar...",
12650
+ value: elegida?.label ?? "",
12651
+ readOnly: true,
12652
+ disabled,
12653
+ error,
12654
+ onClick: abrir,
12655
+ onKeyDown: (e) => {
12656
+ if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") {
12657
+ e.preventDefault();
12658
+ abrir();
12659
+ }
12660
+ },
12661
+ role: "combobox",
12662
+ "aria-haspopup": "dialog",
12663
+ "aria-expanded": abierto,
12664
+ className: `${CLASS$h}__field`,
12665
+ suffix: /* @__PURE__ */ 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__ */ jsx("path", { d: "M6 9l6 6 6-6" }) }),
12666
+ onSuffixClick: abrir,
12667
+ suffixAriaLabel: titulo ? `Elegir ${titulo}` : "Elegir"
12668
+ }
12669
+ ),
12670
+ /* @__PURE__ */ jsxs(
12671
+ BottomSheet,
12672
+ {
12673
+ open: abierto,
12674
+ onClose: () => setAbierto(false),
12675
+ showGrabber: true,
12676
+ closeOnBackdrop: true,
12677
+ ariaLabelledBy: tituloId,
12678
+ className: `${CLASS$h}__sheet`,
12679
+ children: [
12680
+ /* @__PURE__ */ jsxs("div", { className: `${CLASS$h}__sheet-head`, children: [
12681
+ /* @__PURE__ */ jsx("h2", { id: tituloId, className: `${CLASS$h}__sheet-title`, children: titulo }),
12682
+ conBuscador && /* @__PURE__ */ jsx(
12683
+ "input",
12684
+ {
12685
+ className: `${CLASS$h}__search`,
12686
+ type: "search",
12687
+ value: busqueda,
12688
+ onChange: (e) => setBusqueda(e.target.value),
12689
+ placeholder: searchPlaceholder ?? "Buscar",
12690
+ autoComplete: "off",
12691
+ "aria-label": searchPlaceholder ?? "Buscar"
12692
+ }
12693
+ )
12694
+ ] }),
12695
+ /* @__PURE__ */ jsxs("ul", { className: `${CLASS$h}__list`, role: "listbox", "aria-labelledby": tituloId, children: [
12696
+ visibles.map((o) => {
12697
+ const activo = elegida?.value === o.value;
12698
+ return /* @__PURE__ */ jsx("li", { role: "option", "aria-selected": activo, children: /* @__PURE__ */ jsxs(
12699
+ "button",
12700
+ {
12701
+ type: "button",
12702
+ className: [`${CLASS$h}__option`, activo && `${CLASS$h}__option--selected`].filter(Boolean).join(" "),
12703
+ onClick: () => elegir(o),
12704
+ children: [
12705
+ /* @__PURE__ */ jsxs("span", { className: `${CLASS$h}__option-text`, children: [
12706
+ /* @__PURE__ */ jsx("span", { className: `${CLASS$h}__option-label`, children: o.label }),
12707
+ o.hint && /* @__PURE__ */ jsx("span", { className: `${CLASS$h}__option-hint`, children: o.hint })
12708
+ ] }),
12709
+ activo && /* @__PURE__ */ 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__ */ jsx("path", { d: "M20 6L9 17l-5-5" }) })
12710
+ ]
12711
+ }
12712
+ ) }, o.value);
12713
+ }),
12714
+ visibles.length === 0 && /* @__PURE__ */ jsx("li", { className: `${CLASS$h}__empty`, children: options.length === 0 ? notFoundContent ?? "No hay opciones disponibles." : "Nada coincide." })
12715
+ ] })
12716
+ ]
12717
+ }
12718
+ )
12719
+ ] });
12720
+ }
12721
+ );
12722
+ SheetSelect.displayName = "SheetSelect";
12723
+
12724
+ const SANITIZE_PRESETS = {
12725
+ /** «abc-123 » → «ABC123». */
12726
+ plate: ["noControl", "alnum", "upper", { maxLength: 8 }],
12727
+ /** «+57 (300) 123-4567» → «573001234567». */
12728
+ phone: ["digits", { maxLength: 15 }],
12729
+ /** «1.000.000» → «1000000». */
12730
+ id: ["digits", { maxLength: 15 }],
12731
+ /** Un nombre: sin control, espacios colapsados, recortado al enviar. */
12732
+ name: ["noControl", "collapseSpaces", { maxLength: 150 }, "trim"],
12733
+ /** Una nota corta. */
12734
+ note: ["noControl", "collapseSpaces", { maxLength: 80 }, "trim"]
12735
+ };
12736
+ const CONTROL = /[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]/g;
12737
+ function expandir(spec) {
12738
+ const lista = Array.isArray(spec) ? spec : [spec];
12739
+ return lista.flatMap((r) => typeof r === "object" && "preset" in r ? SANITIZE_PRESETS[r.preset] ?? [] : [r]);
12740
+ }
12741
+ function aplicar(s, r, live) {
12742
+ if (r === "trim") return live ? s : s.trim();
12743
+ if (r === "upper") return s.toUpperCase();
12744
+ if (r === "lower") return s.toLowerCase();
12745
+ if (r === "digits") return s.replace(/[^0-9]/g, "");
12746
+ if (r === "alnum") return s.replace(/[^A-Za-z0-9]/g, "");
12747
+ if (r === "noControl") return s.replace(CONTROL, "");
12748
+ if (r === "collapseSpaces") return s.replace(/\s{2,}/g, " ");
12749
+ if ("maxLength" in r) return s.slice(0, r.maxLength);
12750
+ if ("strip" in r) return s.replace(new RegExp(r.strip, "g"), "");
12751
+ return s;
12752
+ }
12753
+ function sanitize(value, spec, options = {}) {
12754
+ if (!spec || value === null || value === void 0) return value;
12755
+ if (typeof value !== "string") return value;
12756
+ return expandir(spec).reduce((s, r) => aplicar(s, r, !!options.live), value);
12757
+ }
12758
+
12323
12759
  const renderField = ({
12324
12760
  field,
12325
12761
  control,
@@ -12407,10 +12843,14 @@ const renderField = ({
12407
12843
  }, children: formatValue() })
12408
12844
  ] });
12409
12845
  }
12846
+ const onChangeLimpio = field.sanitize ? (e) => {
12847
+ const crudo = e && typeof e === "object" && "target" in e ? e.target.value : e;
12848
+ onChange(sanitize(crudo, field.sanitize, { live: true }));
12849
+ } : onChange;
12410
12850
  const commonProps = {
12411
12851
  ...getCommonProps(),
12412
12852
  value: value ?? "",
12413
- onChange,
12853
+ onChange: onChangeLimpio,
12414
12854
  onBlur,
12415
12855
  ref,
12416
12856
  error: error?.message
@@ -12435,8 +12875,26 @@ const renderField = ({
12435
12875
  return /* @__PURE__ */ jsx(Input$1, { ...commonProps, type: "email" });
12436
12876
  case "INPUT_PASSWORD":
12437
12877
  return /* @__PURE__ */ jsx(Input$1, { ...commonProps, type: "password" });
12438
- case "INPUT_PHONE":
12439
- return /* @__PURE__ */ jsx(Input$1, { ...commonProps, type: "tel" });
12878
+ case "INPUT_PHONE": {
12879
+ const { countries, defaultCountry } = uiProps ?? {};
12880
+ return /* @__PURE__ */ jsx(
12881
+ PhoneInput,
12882
+ {
12883
+ ref,
12884
+ name,
12885
+ label: fieldLabel,
12886
+ placeholder,
12887
+ disabled: isReadOnly,
12888
+ readOnly: isReadOnly,
12889
+ error: error?.message,
12890
+ value: typeof value === "string" ? value : "",
12891
+ onChange: (v) => onChange(v),
12892
+ onBlur,
12893
+ countries,
12894
+ defaultCountry
12895
+ }
12896
+ );
12897
+ }
12440
12898
  case "INPUT_CURRENCY":
12441
12899
  return /* @__PURE__ */ jsx(
12442
12900
  Input$1,
@@ -12462,6 +12920,30 @@ const renderField = ({
12462
12920
  case "TEXTAREA":
12463
12921
  return /* @__PURE__ */ jsx(Input$1, { ...commonProps, type: "textarea" });
12464
12922
  case "SELECT":
12923
+ if (uiProps?.picker === "sheet") {
12924
+ return /* @__PURE__ */ jsx(
12925
+ SheetSelect,
12926
+ {
12927
+ ref,
12928
+ name,
12929
+ label: fieldLabel,
12930
+ placeholder,
12931
+ disabled: isReadOnly,
12932
+ readOnly: isReadOnly,
12933
+ error: error?.message,
12934
+ value: value == null ? "" : String(value),
12935
+ onChange: (v) => onChange(v),
12936
+ onBlur,
12937
+ options: (options || []).map((o) => ({
12938
+ value: String(o.value),
12939
+ label: String(o.label),
12940
+ hint: o.hint
12941
+ })),
12942
+ searchable: uiProps?.showSearch,
12943
+ notFoundContent: uiProps?.notFoundContent
12944
+ }
12945
+ );
12946
+ }
12465
12947
  return /* @__PURE__ */ jsx(
12466
12948
  Select$1,
12467
12949
  {
@@ -12591,8 +13073,11 @@ const transformIncomingValues = (values, fields) => {
12591
13073
  const transformOutgoingValues = (values, fields) => {
12592
13074
  const transformed = { ...values };
12593
13075
  fields.forEach((field) => {
13076
+ if (field.sanitize && values[field.name] !== void 0) {
13077
+ transformed[field.name] = sanitize(values[field.name], field.sanitize);
13078
+ }
12594
13079
  if (field.transformOnSubmit && values[field.name] !== void 0) {
12595
- transformed[field.name] = field.transformOnSubmit(values[field.name]);
13080
+ transformed[field.name] = field.transformOnSubmit(transformed[field.name]);
12596
13081
  }
12597
13082
  });
12598
13083
  return transformed;
@@ -13181,24 +13666,28 @@ function mapFieldsToFormFields(fields, mode) {
13181
13666
  placeholder: field.placeholder,
13182
13667
  uiProps: field.uiProps,
13183
13668
  transformOnSubmit: field.parseValue,
13184
- gridSpan: field.gridSpan
13669
+ gridSpan: field.gridSpan,
13185
13670
  // SPEC-131 T7
13671
+ showIf: field.showIf,
13672
+ // SPEC-181
13673
+ sanitize: field.sanitize
13674
+ // SPEC-183
13186
13675
  }));
13187
13676
  }
13188
13677
 
13189
- const CLASS$h = `${COMPONENT_PREFIX}field-value`;
13678
+ const CLASS$g = `${COMPONENT_PREFIX}field-value`;
13190
13679
  const FieldValue = ({
13191
13680
  label,
13192
13681
  children,
13193
13682
  layout = "inline",
13194
13683
  className
13195
- }) => /* @__PURE__ */ jsxs("div", { className: [CLASS$h, `${CLASS$h}--${layout}`, className].filter(Boolean).join(" "), children: [
13196
- /* @__PURE__ */ jsx("span", { className: `${CLASS$h}__label`, children: label }),
13197
- /* @__PURE__ */ jsx("span", { className: `${CLASS$h}__value`, children })
13684
+ }) => /* @__PURE__ */ jsxs("div", { className: [CLASS$g, `${CLASS$g}--${layout}`, className].filter(Boolean).join(" "), children: [
13685
+ /* @__PURE__ */ jsx("span", { className: `${CLASS$g}__label`, children: label }),
13686
+ /* @__PURE__ */ jsx("span", { className: `${CLASS$g}__value`, children })
13198
13687
  ] });
13199
13688
  FieldValue.displayName = "FieldValue";
13200
13689
 
13201
- const CLASS$g = `${COMPONENT_PREFIX}record-card`;
13690
+ const CLASS$f = `${COMPONENT_PREFIX}record-card`;
13202
13691
  const RecordCard = ({
13203
13692
  title,
13204
13693
  summary,
@@ -13210,20 +13699,20 @@ const RecordCard = ({
13210
13699
  className
13211
13700
  }) => {
13212
13701
  const cuerpoId = useId();
13213
- return /* @__PURE__ */ jsxs("div", { className: [CLASS$g, open ? `${CLASS$g}--open` : "", className].filter(Boolean).join(" "), children: [
13702
+ return /* @__PURE__ */ jsxs("div", { className: [CLASS$f, open ? `${CLASS$f}--open` : "", className].filter(Boolean).join(" "), children: [
13214
13703
  /* @__PURE__ */ jsxs(
13215
13704
  "button",
13216
13705
  {
13217
13706
  type: "button",
13218
- className: `${CLASS$g}__header`,
13707
+ className: `${CLASS$f}__header`,
13219
13708
  "aria-expanded": open,
13220
13709
  "aria-controls": cuerpoId,
13221
13710
  "aria-label": ariaLabel,
13222
13711
  onClick: onToggle,
13223
13712
  children: [
13224
- /* @__PURE__ */ jsxs("span", { className: `${CLASS$g}__heading`, children: [
13225
- /* @__PURE__ */ jsx("span", { className: `${CLASS$g}__title`, children: title }),
13226
- summary && /* @__PURE__ */ jsx("span", { className: `${CLASS$g}__summary`, children: summary })
13713
+ /* @__PURE__ */ jsxs("span", { className: `${CLASS$f}__heading`, children: [
13714
+ /* @__PURE__ */ jsx("span", { className: `${CLASS$f}__title`, children: title }),
13715
+ summary && /* @__PURE__ */ jsx("span", { className: `${CLASS$f}__summary`, children: summary })
13227
13716
  ] }),
13228
13717
  /* @__PURE__ */ jsx(
13229
13718
  Icon,
@@ -13231,22 +13720,22 @@ const RecordCard = ({
13231
13720
  type: open ? "chevron-up" : "chevron-down",
13232
13721
  width: 18,
13233
13722
  height: 18,
13234
- className: `${CLASS$g}__chevron`,
13723
+ className: `${CLASS$f}__chevron`,
13235
13724
  "aria-hidden": true
13236
13725
  }
13237
13726
  )
13238
13727
  ]
13239
13728
  }
13240
13729
  ),
13241
- open && /* @__PURE__ */ jsxs("div", { className: `${CLASS$g}__body`, id: cuerpoId, children: [
13730
+ open && /* @__PURE__ */ jsxs("div", { className: `${CLASS$f}__body`, id: cuerpoId, children: [
13242
13731
  children,
13243
- actions && /* @__PURE__ */ jsx("div", { className: `${CLASS$g}__actions`, children: actions })
13732
+ actions && /* @__PURE__ */ jsx("div", { className: `${CLASS$f}__actions`, children: actions })
13244
13733
  ] })
13245
13734
  ] });
13246
13735
  };
13247
13736
  RecordCard.displayName = "RecordCard";
13248
13737
 
13249
- const CLASS$f = `${COMPONENT_PREFIX}crud-cards`;
13738
+ const CLASS$e = `${COMPONENT_PREFIX}crud-cards`;
13250
13739
  function summaryFields(fields) {
13251
13740
  const visibles = fields.filter((f) => f.showInTable !== false);
13252
13741
  const marcados = visibles.filter((f) => f.summary);
@@ -13265,13 +13754,13 @@ function CardList({
13265
13754
  const claveResumen = new Set(resumen.map((f) => f.key));
13266
13755
  const cuerpo = fields.filter((f) => f.showInTable !== false && !claveResumen.has(f.key));
13267
13756
  if (loading && rows.length === 0) {
13268
- return /* @__PURE__ */ jsx("div", { className: `${CLASS$f}__estado`, children: "Cargando..." });
13757
+ return /* @__PURE__ */ jsx("div", { className: `${CLASS$e}__estado`, children: "Cargando..." });
13269
13758
  }
13270
13759
  if (rows.length === 0) {
13271
- return /* @__PURE__ */ jsx("div", { className: `${CLASS$f}__estado`, children: emptyText });
13760
+ return /* @__PURE__ */ jsx("div", { className: `${CLASS$e}__estado`, children: emptyText });
13272
13761
  }
13273
13762
  const [principal, ...secundarios] = resumen;
13274
- return /* @__PURE__ */ jsx("div", { className: CLASS$f, children: rows.map((row) => {
13763
+ return /* @__PURE__ */ jsx("div", { className: CLASS$e, children: rows.map((row) => {
13275
13764
  const key = rowKey(row);
13276
13765
  const opciones = buildOptions?.(row) ?? [];
13277
13766
  const titulo = principal ? renderFieldValue(principal, row) : key;
@@ -13288,14 +13777,14 @@ function CardList({
13288
13777
  {
13289
13778
  type: "button",
13290
13779
  className: [
13291
- `${CLASS$f}__accion`,
13780
+ `${CLASS$e}__accion`,
13292
13781
  o.disabled && o.disabledReason ? "is-con-motivo" : ""
13293
13782
  ].filter(Boolean).join(" "),
13294
13783
  disabled: o.disabled,
13295
13784
  onClick: () => void o.onClick(),
13296
13785
  children: [
13297
13786
  /* @__PURE__ */ jsx("span", { children: o.label }),
13298
- o.disabled && o.disabledReason && /* @__PURE__ */ jsx("span", { className: `${CLASS$f}__motivo`, children: o.disabledReason })
13787
+ o.disabled && o.disabledReason && /* @__PURE__ */ jsx("span", { className: `${CLASS$e}__motivo`, children: o.disabledReason })
13299
13788
  ]
13300
13789
  },
13301
13790
  o.label
@@ -13310,7 +13799,7 @@ function CardList({
13310
13799
  }
13311
13800
  CardList.displayName = "CardList";
13312
13801
 
13313
- const CLASS$e = `${COMPONENT_PREFIX}crud-scroll-end`;
13802
+ const CLASS$d = `${COMPONENT_PREFIX}crud-scroll-end`;
13314
13803
  const MARGEN = 24;
13315
13804
  const SELECTOR_CRUD = `.${COMPONENT_PREFIX}table-container, .${COMPONENT_PREFIX}crud-cards`;
13316
13805
  const ScrollToEnd = ({
@@ -13354,7 +13843,7 @@ const ScrollToEnd = ({
13354
13843
  s.scrollTo({ top: s.scrollHeight, behavior: "smooth" });
13355
13844
  }, []);
13356
13845
  if (!visible) return null;
13357
- return /* @__PURE__ */ jsx("button", { type: "button", className: CLASS$e, onClick: alFinal, "aria-label": label, title: label, children: /* @__PURE__ */ jsx(Icon, { type: "chevron-down", width: 18, height: 18, "aria-hidden": true }) });
13846
+ return /* @__PURE__ */ jsx("button", { type: "button", className: CLASS$d, onClick: alFinal, "aria-label": label, title: label, children: /* @__PURE__ */ jsx(Icon, { type: "chevron-down", width: 18, height: 18, "aria-hidden": true }) });
13358
13847
  };
13359
13848
  ScrollToEnd.displayName = "ScrollToEnd";
13360
13849
 
@@ -14039,7 +14528,7 @@ function Crud({
14039
14528
  }
14040
14529
  Crud.displayName = "Crud";
14041
14530
 
14042
- const CLASS$d = "px-chat-reactive-crud__chat-link";
14531
+ const CLASS$c = "px-chat-reactive-crud__chat-link";
14043
14532
  function Burbuja() {
14044
14533
  return /* @__PURE__ */ jsx(
14045
14534
  "svg",
@@ -14066,7 +14555,7 @@ const ChatLinkCell = ({
14066
14555
  if (targets.length === 1) {
14067
14556
  const t = targets[0];
14068
14557
  const texto = t.label ? `Abrir chat ${t.label}` : "Abrir chat";
14069
- return /* @__PURE__ */ jsx("button", { type: "button", className: CLASS$d, "aria-label": texto, title: texto, onClick: () => abrir(t.id), children: /* @__PURE__ */ jsx(Burbuja, {}) });
14558
+ return /* @__PURE__ */ jsx("button", { type: "button", className: CLASS$c, "aria-label": texto, title: texto, onClick: () => abrir(t.id), children: /* @__PURE__ */ jsx(Burbuja, {}) });
14070
14559
  }
14071
14560
  return /* @__PURE__ */ jsx(
14072
14561
  DropdownMenu,
@@ -14080,7 +14569,7 @@ const ChatLinkCell = ({
14080
14569
  "button",
14081
14570
  {
14082
14571
  type: "button",
14083
- className: CLASS$d,
14572
+ className: CLASS$c,
14084
14573
  "aria-label": `Abrir chat (${targets.length} conversaciones)`,
14085
14574
  title: "Abrir chat",
14086
14575
  children: /* @__PURE__ */ jsx(Burbuja, {})
@@ -14093,6 +14582,18 @@ const ChatLinkCell = ({
14093
14582
  };
14094
14583
  ChatLinkCell.displayName = "ChatLinkCell";
14095
14584
 
14585
+ function obligatorioSiSeVe(s, f, requiredMsg) {
14586
+ if (!f.visibleWhen) return s.required(requiredMsg);
14587
+ const conds = Array.isArray(f.visibleWhen) ? f.visibleWhen : [f.visibleWhen];
14588
+ return s.when(
14589
+ conds.map((c) => c.field),
14590
+ {
14591
+ is: (...vals) => conds.every((c, i) => c.in.includes(String(vals[i]))),
14592
+ then: (sch) => sch.required(requiredMsg),
14593
+ otherwise: (sch) => sch.notRequired()
14594
+ }
14595
+ );
14596
+ }
14096
14597
  function buildCrudYupSchema(fields) {
14097
14598
  const shape = {};
14098
14599
  for (const f of fields) {
@@ -14122,19 +14623,17 @@ function buildCrudYupSchema(fields) {
14122
14623
  }
14123
14624
  if (f.moleculeType === "INPUT_NUMBER" || f.moleculeType === "INPUT_CURRENCY") {
14124
14625
  let s2 = yup.number().transform((val, orig) => orig === "" || orig === null ? void 0 : val).typeError(`${f.label}: n\xFAmero inv\xE1lido`);
14125
- if (requiredMsg) s2 = s2.required(requiredMsg);
14126
14626
  if (v?.min) s2 = s2.min(Number(v.min.value), v.min.message);
14127
14627
  if (v?.max) s2 = s2.max(Number(v.max.value), v.max.message);
14128
- shape[f.name] = s2;
14628
+ shape[f.name] = requiredMsg ? obligatorioSiSeVe(s2, f, requiredMsg) : s2;
14129
14629
  continue;
14130
14630
  }
14131
14631
  let s = yup.string();
14132
- if (requiredMsg) s = s.required(requiredMsg);
14133
- if (v?.pattern) s = s.matches(new RegExp(v.pattern.value), v.pattern.message);
14632
+ if (v?.pattern) s = s.matches(new RegExp(v.pattern.value), { message: v.pattern.message, excludeEmptyString: true });
14134
14633
  if (v?.email) s = s.email(v.email);
14135
14634
  if (v?.min) s = s.min(Number(v.min.value), v.min.message);
14136
14635
  if (v?.max) s = s.max(Number(v.max.value), v.max.message);
14137
- shape[f.name] = s;
14636
+ shape[f.name] = requiredMsg ? obligatorioSiSeVe(s, f, requiredMsg) : s;
14138
14637
  }
14139
14638
  return yup.object().shape(shape);
14140
14639
  }
@@ -14164,7 +14663,14 @@ const datetime = (value) => {
14164
14663
  minute: "2-digit"
14165
14664
  });
14166
14665
  };
14167
- const CRUD_FORMATTERS = { currency, date, datetime };
14666
+ const phone = (value) => {
14667
+ const s = String(value ?? "").trim();
14668
+ const m = /^\+(\d{1,3})(\d{10})$/.exec(s);
14669
+ if (!m) return s;
14670
+ const [, cc, n] = m;
14671
+ return `+${cc} ${n.slice(0, 3)} ${n.slice(3, 6)} ${n.slice(6)}`;
14672
+ };
14673
+ const CRUD_FORMATTERS = { currency, date, datetime, phone };
14168
14674
  function getFormatter(key) {
14169
14675
  return key ? CRUD_FORMATTERS[key] : void 0;
14170
14676
  }
@@ -14399,7 +14905,7 @@ function uploadViaEventBus(eventBus, file, fileType) {
14399
14905
  });
14400
14906
  }
14401
14907
 
14402
- const CLASS$c = `${COMPONENT_PREFIX$1}file-field`;
14908
+ const CLASS$b = `${COMPONENT_PREFIX$1}file-field`;
14403
14909
  function iconoPorNombre(nombre) {
14404
14910
  const ext = nombre.split(".").pop()?.toLowerCase() ?? "";
14405
14911
  if (["png", "jpg", "jpeg", "gif", "webp", "heic", "heif"].includes(ext)) return ICON_TYPES.IMAGE;
@@ -14430,18 +14936,18 @@ const FileField = ({
14430
14936
  const elegir = () => {
14431
14937
  if (!disabled) inputRef.current?.click();
14432
14938
  };
14433
- return /* @__PURE__ */ jsxs("div", { className: `${CLASS$c}${error ? ` ${CLASS$c}--error` : ""}`, children: [
14434
- /* @__PURE__ */ jsxs("span", { className: `${CLASS$c}__label`, children: [
14939
+ return /* @__PURE__ */ jsxs("div", { className: `${CLASS$b}${error ? ` ${CLASS$b}--error` : ""}`, children: [
14940
+ /* @__PURE__ */ jsxs("span", { className: `${CLASS$b}__label`, children: [
14435
14941
  label,
14436
14942
  required ? " *" : "",
14437
14943
  multiple && hechos > 0 ? ` (${hechos})` : ""
14438
14944
  ] }),
14439
- /* @__PURE__ */ jsxs("div", { className: `${CLASS$c}__box`, children: [
14945
+ /* @__PURE__ */ jsxs("div", { className: `${CLASS$b}__box`, children: [
14440
14946
  /* @__PURE__ */ jsx(
14441
14947
  "input",
14442
14948
  {
14443
14949
  ref: inputRef,
14444
- className: `${CLASS$c}__native`,
14950
+ className: `${CLASS$b}__native`,
14445
14951
  type: "file",
14446
14952
  accept,
14447
14953
  multiple,
@@ -14452,14 +14958,14 @@ const FileField = ({
14452
14958
  }
14453
14959
  }
14454
14960
  ),
14455
- /* @__PURE__ */ jsxs("button", { type: "button", className: `${CLASS$c}__pick`, onClick: elegir, disabled, children: [
14961
+ /* @__PURE__ */ jsxs("button", { type: "button", className: `${CLASS$b}__pick`, onClick: elegir, disabled, children: [
14456
14962
  /* @__PURE__ */ jsx(Icon$1, { type: ICON_TYPES.UPLOAD, size: "small" }),
14457
- /* @__PURE__ */ 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" })
14963
+ /* @__PURE__ */ 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" })
14458
14964
  ] }),
14459
- entries.length > 0 && /* @__PURE__ */ jsx("ul", { className: `${CLASS$c}__list`, children: entries.map((e, i) => /* @__PURE__ */ jsxs("li", { className: `${CLASS$c}__item ${CLASS$c}__item--${e.status}`, children: [
14460
- /* @__PURE__ */ jsx("span", { className: `${CLASS$c}__kind`, "aria-hidden": "true", children: /* @__PURE__ */ jsx(Icon$1, { type: iconoPorNombre(e.name), size: "small" }) }),
14461
- /* @__PURE__ */ jsx("span", { className: `${CLASS$c}__name`, children: e.name }),
14462
- /* @__PURE__ */ jsxs("span", { className: `${CLASS$c}__state`, children: [
14965
+ entries.length > 0 && /* @__PURE__ */ jsx("ul", { className: `${CLASS$b}__list`, children: entries.map((e, i) => /* @__PURE__ */ jsxs("li", { className: `${CLASS$b}__item ${CLASS$b}__item--${e.status}`, children: [
14966
+ /* @__PURE__ */ jsx("span", { className: `${CLASS$b}__kind`, "aria-hidden": "true", children: /* @__PURE__ */ jsx(Icon$1, { type: iconoPorNombre(e.name), size: "small" }) }),
14967
+ /* @__PURE__ */ jsx("span", { className: `${CLASS$b}__name`, children: e.name }),
14968
+ /* @__PURE__ */ jsxs("span", { className: `${CLASS$b}__state`, children: [
14463
14969
  e.status === "uploading" && "Subiendo\u2026",
14464
14970
  e.status === "done" && (pesoLegible(e.size) || "Listo"),
14465
14971
  e.status === "error" && "No se pudo subir"
@@ -14468,7 +14974,7 @@ const FileField = ({
14468
14974
  "button",
14469
14975
  {
14470
14976
  type: "button",
14471
- className: `${CLASS$c}__remove`,
14977
+ className: `${CLASS$b}__remove`,
14472
14978
  onClick: () => onRemove(i),
14473
14979
  "aria-label": `Quitar ${e.name}`,
14474
14980
  disabled,
@@ -14477,8 +14983,8 @@ const FileField = ({
14477
14983
  )
14478
14984
  ] }, `${e.name}-${i}`)) })
14479
14985
  ] }),
14480
- error && /* @__PURE__ */ jsx("p", { className: `${CLASS$c}__error`, children: error }),
14481
- !error && subiendo && /* @__PURE__ */ jsx("p", { className: `${CLASS$c}__hint`, children: "Espera a que terminen de subir." })
14986
+ error && /* @__PURE__ */ jsx("p", { className: `${CLASS$b}__error`, children: error }),
14987
+ !error && subiendo && /* @__PURE__ */ jsx("p", { className: `${CLASS$b}__hint`, children: "Espera a que terminen de subir." })
14482
14988
  ] });
14483
14989
  };
14484
14990
 
@@ -15640,7 +16146,7 @@ function buildMarkerIcon(name, color = "#dc2626", heading = 0) {
15640
16146
  return `data:image/svg+xml;charset=UTF-8,${encodeURIComponent(svg)}`;
15641
16147
  }
15642
16148
 
15643
- const CLASS$b = `${COMPONENT_PREFIX$1}map-view`;
16149
+ const CLASS$a = `${COMPONENT_PREFIX$1}map-view`;
15644
16150
  const DEFAULT_CENTER = { lat: 4.711, lng: -74.0721 };
15645
16151
  const DEFAULT_ZOOM = 12;
15646
16152
  const DEFAULT_HEIGHT$1 = 320;
@@ -15710,6 +16216,8 @@ const MapView = ({
15710
16216
  eventBus,
15711
16217
  expandable = true,
15712
16218
  fullBleed = false,
16219
+ interactive = true,
16220
+ expandIcon = "expand",
15713
16221
  animateMs,
15714
16222
  className
15715
16223
  }) => {
@@ -15765,7 +16273,12 @@ const MapView = ({
15765
16273
  mapTypeControl: false,
15766
16274
  streetViewControl: false,
15767
16275
  fullscreenControl: false,
15768
- styles: leerEstiloDelTema()
16276
+ styles: leerEstiloDelTema(),
16277
+ // SPEC-182 — un mapa solo para mirar no se queda con el gesto: `none` es la forma oficial
16278
+ // de Google de que el dedo y la rueda sigan desplazando la página. Se fija al crear el mapa
16279
+ // porque el modo no cambia en caliente: quien quiera el otro monta otra instancia (la de
16280
+ // pantalla completa lo es).
16281
+ ...interactive ? {} : { gestureHandling: "none", zoomControl: false, keyboardShortcuts: false }
15769
16282
  });
15770
16283
  mapRef.current.addListener("dragstart", () => {
15771
16284
  followSuspendedRef.current = true;
@@ -15783,7 +16296,7 @@ const MapView = ({
15783
16296
  useEffect(() => {
15784
16297
  if (!mapReady || !mapRef.current) return;
15785
16298
  const maps = window.google.maps;
15786
- const editable = !!onMoveRef.current;
16299
+ const editable = interactive && !!onMoveRef.current;
15787
16300
  const alive = new Set(list.map((p) => p.id));
15788
16301
  markersRef.current.forEach((entry, id) => {
15789
16302
  if (alive.has(id)) return;
@@ -15855,7 +16368,7 @@ const MapView = ({
15855
16368
  } else {
15856
16369
  mapRef.current.fitBounds(bounds);
15857
16370
  }
15858
- }, [mapReady, list, animateMs]);
16371
+ }, [mapReady, list, animateMs, interactive]);
15859
16372
  useEffect(() => {
15860
16373
  if (!mapReady || !mapRef.current) return;
15861
16374
  const maps = window.google.maps;
@@ -15905,7 +16418,7 @@ const MapView = ({
15905
16418
  if (!mapReady || !mapRef.current) return;
15906
16419
  clickListenerRef.current?.remove?.();
15907
16420
  clickListenerRef.current = null;
15908
- if (!onPointMove || list.length !== 1) return;
16421
+ if (!interactive || !onPointMove || list.length !== 1) return;
15909
16422
  const pointId = list[0].id;
15910
16423
  clickListenerRef.current = mapRef.current.addListener("click", (e) => {
15911
16424
  onMoveRef.current?.(pointId, e.latLng.lat(), e.latLng.lng());
@@ -15914,7 +16427,7 @@ const MapView = ({
15914
16427
  clickListenerRef.current?.remove?.();
15915
16428
  clickListenerRef.current = null;
15916
16429
  };
15917
- }, [mapReady, list, onPointMove]);
16430
+ }, [mapReady, list, onPointMove, interactive]);
15918
16431
  useEffect(
15919
16432
  () => () => {
15920
16433
  markersRef.current.forEach((entry) => {
@@ -15941,31 +16454,34 @@ const MapView = ({
15941
16454
  document.body.style.overflow = prev;
15942
16455
  };
15943
16456
  }, [expanded]);
15944
- const rootClass = [CLASS$b, fullBleed && `${CLASS$b}--full-bleed`, className].filter(Boolean).join(" ");
16457
+ const rootClass = [CLASS$a, fullBleed && `${CLASS$a}--full-bleed`, className].filter(Boolean).join(" ");
15945
16458
  if (overQuota) {
15946
- return /* @__PURE__ */ jsx("div", { className: rootClass, style: { height }, children: /* @__PURE__ */ 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." }) });
16459
+ return /* @__PURE__ */ jsx("div", { className: rootClass, style: { height }, children: /* @__PURE__ */ 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." }) });
15947
16460
  }
15948
16461
  if (status === "error") {
15949
- return /* @__PURE__ */ jsx("div", { className: rootClass, style: { height }, children: /* @__PURE__ */ jsx("p", { className: `${CLASS$b}__state ${CLASS$b}__state--error`, children: labels?.errorText ?? "No se pudo cargar el mapa." }) });
16462
+ return /* @__PURE__ */ jsx("div", { className: rootClass, style: { height }, children: /* @__PURE__ */ jsx("p", { className: `${CLASS$a}__state ${CLASS$a}__state--error`, children: labels?.errorText ?? "No se pudo cargar el mapa." }) });
15950
16463
  }
15951
16464
  return /* @__PURE__ */ jsxs("div", { className: rootClass, style: fullBleed ? void 0 : { height }, children: [
15952
- status !== "ready" && /* @__PURE__ */ jsx("p", { className: `${CLASS$b}__state`, children: labels?.loadingText ?? "Cargando mapa\u2026" }),
15953
- /* @__PURE__ */ jsx("div", { ref: nodeRef, className: `${CLASS$b}__canvas`, "aria-label": "Mapa", role: "application" }),
15954
- status === "ready" && list.length === 0 && allRoutes.length === 0 && /* @__PURE__ */ jsx("p", { className: `${CLASS$b}__empty`, children: labels?.emptyText ?? "Sin ubicaciones para mostrar" }),
15955
- status === "ready" && onPointMove && list.length > 0 && /* @__PURE__ */ jsx("p", { className: `${CLASS$b}__empty`, children: labels?.moveHint ?? "Arrastra el pin o toca el mapa para ajustar" }),
16465
+ status !== "ready" && /* @__PURE__ */ jsx("p", { className: `${CLASS$a}__state`, children: labels?.loadingText ?? "Cargando mapa\u2026" }),
16466
+ /* @__PURE__ */ jsx("div", { ref: nodeRef, className: `${CLASS$a}__canvas`, "aria-label": "Mapa", role: "application" }),
16467
+ status === "ready" && list.length === 0 && allRoutes.length === 0 && /* @__PURE__ */ jsx("p", { className: `${CLASS$a}__empty`, children: labels?.emptyText ?? "Sin ubicaciones para mostrar" }),
16468
+ status === "ready" && interactive && onPointMove && list.length > 0 && /* @__PURE__ */ jsx("p", { className: `${CLASS$a}__empty`, children: labels?.moveHint ?? "Arrastra el pin o toca el mapa para ajustar" }),
15956
16469
  status === "ready" && expandable && !fullBleed && /* @__PURE__ */ jsx(
15957
16470
  "button",
15958
16471
  {
15959
16472
  type: "button",
15960
- className: `${CLASS$b}__expand`,
15961
- "aria-label": labels?.expandAria ?? "Ver el mapa en pantalla completa",
15962
- title: labels?.expandAria ?? "Pantalla completa",
16473
+ className: `${CLASS$a}__expand`,
16474
+ "aria-label": labels?.expandAria ?? (expandIcon === "edit" ? "Ajustar el punto en el mapa" : "Ver el mapa en pantalla completa"),
16475
+ title: labels?.expandAria ?? (expandIcon === "edit" ? "Ajustar el punto" : "Pantalla completa"),
15963
16476
  onClick: () => setExpanded(true),
15964
- children: /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7" }) })
16477
+ children: expandIcon === "edit" ? /* @__PURE__ */ jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
16478
+ /* @__PURE__ */ jsx("path", { d: "M12 20h9" }),
16479
+ /* @__PURE__ */ jsx("path", { d: "M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4L16.5 3.5z" })
16480
+ ] }) : /* @__PURE__ */ jsx("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M15 3h6v6M9 21H3v-6M21 3l-7 7M3 21l7-7" }) })
15965
16481
  }
15966
16482
  ),
15967
16483
  expanded && createPortal(
15968
- /* @__PURE__ */ jsxs("div", { className: `${CLASS$b}-fs`, role: "dialog", "aria-modal": "true", "aria-label": "Mapa", children: [
16484
+ /* @__PURE__ */ jsxs("div", { className: `${CLASS$a}-fs`, role: "dialog", "aria-modal": "true", "aria-label": "Mapa", children: [
15969
16485
  /* @__PURE__ */ jsx(
15970
16486
  MapView,
15971
16487
  {
@@ -15979,7 +16495,7 @@ const MapView = ({
15979
16495
  "button",
15980
16496
  {
15981
16497
  type: "button",
15982
- className: `${CLASS$b}-fs__close`,
16498
+ className: `${CLASS$a}-fs__close`,
15983
16499
  "aria-label": labels?.closeAria ?? "Cerrar el mapa",
15984
16500
  onClick: () => setExpanded(false),
15985
16501
  children: /* @__PURE__ */ jsxs("svg", { width: "22", height: "22", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
@@ -16095,7 +16611,7 @@ function reverseGeocode(lat, lng) {
16095
16611
  });
16096
16612
  }
16097
16613
 
16098
- const CLASS$a = `${COMPONENT_PREFIX$1}location-field`;
16614
+ const CLASS$9 = `${COMPONENT_PREFIX$1}location-field`;
16099
16615
  const GPS_TIMEOUT_MS = 1e4;
16100
16616
  const CONFIRM_MAP_HEIGHT = 180;
16101
16617
  const LocationField = ({
@@ -16168,16 +16684,16 @@ const LocationField = ({
16168
16684
  }
16169
16685
  };
16170
16686
  const hasPoint = value?.lat != null && value?.lng != null;
16171
- return /* @__PURE__ */ jsxs("div", { className: `${CLASS$a}${error ? ` ${CLASS$a}--error` : ""}`, ref: boxRef, children: [
16172
- label && /* @__PURE__ */ jsxs("span", { className: `${CLASS$a}__label`, children: [
16687
+ return /* @__PURE__ */ jsxs("div", { className: `${CLASS$9}${error ? ` ${CLASS$9}--error` : ""}`, ref: boxRef, children: [
16688
+ label && /* @__PURE__ */ jsxs("span", { className: `${CLASS$9}__label`, children: [
16173
16689
  label,
16174
16690
  required ? " *" : ""
16175
16691
  ] }),
16176
- /* @__PURE__ */ jsxs("div", { className: `${CLASS$a}__row`, children: [
16692
+ /* @__PURE__ */ jsxs("div", { className: `${CLASS$9}__row`, children: [
16177
16693
  /* @__PURE__ */ jsx(
16178
16694
  "input",
16179
16695
  {
16180
- className: `${CLASS$a}__input`,
16696
+ className: `${CLASS$9}__input`,
16181
16697
  type: "text",
16182
16698
  value: text,
16183
16699
  disabled,
@@ -16191,7 +16707,7 @@ const LocationField = ({
16191
16707
  "button",
16192
16708
  {
16193
16709
  type: "button",
16194
- className: `${CLASS$a}__gps`,
16710
+ className: `${CLASS$9}__gps`,
16195
16711
  onClick: useMyLocation,
16196
16712
  disabled: disabled || gps === "locating",
16197
16713
  title: labels?.useMyLocation ?? "Enviar mi ubicaci\xF3n",
@@ -16205,21 +16721,24 @@ const LocationField = ({
16205
16721
  }
16206
16722
  )
16207
16723
  ] }),
16208
- open && suggestions.length > 0 && /* @__PURE__ */ jsx("ul", { className: `${CLASS$a}__suggestions`, children: suggestions.map((s) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("button", { type: "button", onClick: () => void pickSuggestion(s.id, s.description), children: s.description }) }, s.id)) }),
16209
- error && /* @__PURE__ */ jsx("p", { className: `${CLASS$a}__error`, children: error }),
16210
- gps === "denied" && /* @__PURE__ */ jsx("p", { className: `${CLASS$a}__hint ${CLASS$a}__hint--warn`, children: labels?.permissionDenied ?? "No diste permiso de ubicaci\xF3n. Puedes escribir la direcci\xF3n." }),
16211
- gps === "unavailable" && /* @__PURE__ */ jsx("p", { className: `${CLASS$a}__hint ${CLASS$a}__hint--warn`, children: labels?.unavailable ?? "No pudimos obtener tu ubicaci\xF3n. Puedes escribir la direcci\xF3n." }),
16212
- hasPoint && /* @__PURE__ */ jsxs("div", { className: `${CLASS$a}__confirm`, children: [
16724
+ open && suggestions.length > 0 && /* @__PURE__ */ jsx("ul", { className: `${CLASS$9}__suggestions`, children: suggestions.map((s) => /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsx("button", { type: "button", onClick: () => void pickSuggestion(s.id, s.description), children: s.description }) }, s.id)) }),
16725
+ error && /* @__PURE__ */ jsx("p", { className: `${CLASS$9}__error`, children: error }),
16726
+ gps === "denied" && /* @__PURE__ */ jsx("p", { className: `${CLASS$9}__hint ${CLASS$9}__hint--warn`, children: labels?.permissionDenied ?? "No diste permiso de ubicaci\xF3n. Puedes escribir la direcci\xF3n." }),
16727
+ gps === "unavailable" && /* @__PURE__ */ jsx("p", { className: `${CLASS$9}__hint ${CLASS$9}__hint--warn`, children: labels?.unavailable ?? "No pudimos obtener tu ubicaci\xF3n. Puedes escribir la direcci\xF3n." }),
16728
+ hasPoint && /* @__PURE__ */ jsxs("div", { className: `${CLASS$9}__confirm`, children: [
16213
16729
  /* @__PURE__ */ jsx(
16214
16730
  MapView,
16215
16731
  {
16216
16732
  apiKey,
16217
16733
  points: [{ id: "sel", lat: value.lat, lng: value.lng, label: value?.address }],
16218
16734
  height: CONFIRM_MAP_HEIGHT,
16219
- onPointMove: (id, lat, lng) => void movePoint(id, lat, lng)
16735
+ onPointMove: (id, lat, lng) => void movePoint(id, lat, lng),
16736
+ interactive: false,
16737
+ expandIcon: "edit",
16738
+ labels: { expandAria: labels?.editAria ?? "Ajustar el punto en el mapa" }
16220
16739
  }
16221
16740
  ),
16222
- /* @__PURE__ */ jsx("p", { className: `${CLASS$a}__hint`, children: labels?.confirmHint ?? "Verifica que el punto sea correcto." })
16741
+ /* @__PURE__ */ 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." })
16223
16742
  ] })
16224
16743
  ] });
16225
16744
  };
@@ -16251,6 +16770,8 @@ function toRenderField(f, loaded, eventBus, mapsApiKey, loadError) {
16251
16770
  // y, a media fila, su campo hermano se quedaba con ~400px de blanco al lado. Medido entre
16252
16771
  // «¿En qué situación está?» y «¿A dónde lo llevamos?» del formulario de solicitud.
16253
16772
  gridSpan: 2,
16773
+ showIf: showIfDe(f),
16774
+ // SPEC-181
16254
16775
  uiProps: {
16255
16776
  // SPEC-074 — `error` viene del render de CUSTOM (DynamicForm ya lo pasaba) y aquí se
16256
16777
  // desechaba: el campo obligatorio más importante era el único mudo.
@@ -16283,14 +16804,22 @@ function toRenderField(f, loaded, eventBus, mapsApiKey, loadError) {
16283
16804
  columnWidth: f.columnWidth,
16284
16805
  fixed: f.fixed,
16285
16806
  align: f.align,
16807
+ showIf: showIfDe(f),
16808
+ // SPEC-181
16809
+ sanitize: f.sanitize,
16810
+ // SPEC-183
16286
16811
  // SPEC-106 T8 — con un fallo de carga, el desplegable dice que no se pudo preguntar en vez
16287
16812
  // de «no hay opciones disponibles», que es una respuesta y no la tenemos.
16288
- uiProps: loadError ? { options: options ?? [], notFoundContent: loadError, ...f.searchable ? { showSearch: true } : {} } : options ? { options, ...f.searchable ? { showSearch: true } : {} } : void 0,
16813
+ 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,
16289
16814
  formatValue
16290
16815
  };
16291
16816
  }
16292
16817
  const cumpleCondicion = (c, row) => c.in.includes(String(row[c.field]));
16293
16818
  const cumplenTodas = (c, row) => (Array.isArray(c) ? c : [c]).every((x) => cumpleCondicion(x, row));
16819
+ function showIfDe(f) {
16820
+ const cond = f.visibleWhen;
16821
+ return cond ? (values) => cumplenTodas(cond, values) : void 0;
16822
+ }
16294
16823
  function matchesVisibleWhen(a, row) {
16295
16824
  if (a.hiddenWhen && cumplenTodas(a.hiddenWhen, row)) return false;
16296
16825
  if (!a.visibleWhen) return true;
@@ -16338,8 +16867,20 @@ function collapseLocationFields(fields, valores) {
16338
16867
  if (f.moleculeType !== "LOCATION" || !f.bind) continue;
16339
16868
  const address = out[f.bind.address];
16340
16869
  if (typeof address !== "string" || !address.trim()) continue;
16341
- out[f.name] = { address };
16870
+ const lat = out[f.bind.lat];
16871
+ const lng = out[f.bind.lng];
16872
+ const source = f.bind.source ? out[f.bind.source] : void 0;
16873
+ const valor = { address };
16874
+ if (typeof lat === "number" && typeof lng === "number") {
16875
+ valor.lat = lat;
16876
+ valor.lng = lng;
16877
+ }
16878
+ if (typeof source === "string" && source) valor.source = source;
16879
+ out[f.name] = valor;
16342
16880
  delete out[f.bind.address];
16881
+ delete out[f.bind.lat];
16882
+ delete out[f.bind.lng];
16883
+ if (f.bind.source) delete out[f.bind.source];
16343
16884
  }
16344
16885
  return out;
16345
16886
  }
@@ -16492,6 +17033,8 @@ function ReactiveCrudChat({ component, eventBus, assistantMessageId }) {
16492
17033
  const moduleKey = pick("module");
16493
17034
  const openCreate = pick("openCreate") === true;
16494
17035
  const prefill = pick("prefill");
17036
+ const createLabel = pick("createLabel");
17037
+ const createdLabel = pick("createdLabel");
16495
17038
  let config;
16496
17039
  if (typeof moduleKey === "string" && resolveModuleConfig) {
16497
17040
  config = resolveModuleConfig(moduleKey);
@@ -16514,7 +17057,7 @@ function ReactiveCrudChat({ component, eventBus, assistantMessageId }) {
16514
17057
  if (!config) return null;
16515
17058
  const title = config.title ?? "Gesti\xF3n";
16516
17059
  const done = openCreate && created;
16517
- const triggerLabel = done ? config.labels?.createdButton ?? "Solicitud enviada" : openCreate ? config.labels?.createButton ?? "Crear" : `Abrir ${title.toLowerCase()}`;
17060
+ const triggerLabel = done ? createdLabel ?? config.labels?.createdButton ?? "Solicitud enviada" : openCreate ? createLabel ?? config.labels?.createButton ?? "Crear" : `Abrir ${title.toLowerCase()}`;
16518
17061
  return /* @__PURE__ */ jsxs(Fragment, { children: [
16519
17062
  /* @__PURE__ */ jsxs(
16520
17063
  "button",
@@ -16584,6 +17127,16 @@ function ReactiveCrudChat({ component, eventBus, assistantMessageId }) {
16584
17127
  ] });
16585
17128
  }
16586
17129
 
17130
+ function plazoVigente(deadline, row) {
17131
+ if (!deadline || !row) return null;
17132
+ const lista = Array.isArray(deadline) ? deadline : [deadline];
17133
+ for (const d of lista) {
17134
+ const at = row[d.field];
17135
+ if (typeof at === "string" && at) return { config: d, at };
17136
+ }
17137
+ return null;
17138
+ }
17139
+
16587
17140
  function restante(hasta) {
16588
17141
  return Math.max(0, hasta - Date.now());
16589
17142
  }
@@ -16695,6 +17248,7 @@ function ServiceActionsPanel({ config, recordId, recordLabel, allowed, sinAccion
16695
17248
  return () => observador.disconnect();
16696
17249
  }, [recordId]);
16697
17250
  const gastada = !esUltima;
17251
+ const plazo = plazoVigente(config.deadline, row);
16698
17252
  const actions = useMemo(() => {
16699
17253
  if (!row) return [];
16700
17254
  if (gastada) {
@@ -16726,12 +17280,12 @@ function ServiceActionsPanel({ config, recordId, recordLabel, allowed, sinAccion
16726
17280
  crud.loading && !row && /* @__PURE__ */ jsx("div", { className: "px-chat-crud-item__hint", children: "Cargando\u2026" }),
16727
17281
  !crud.loading && !row && /* @__PURE__ */ jsx("div", { className: "px-chat-crud-item__hint", children: "No se encontr\xF3 el servicio." }),
16728
17282
  gastada && /* @__PURE__ */ jsx("div", { className: "px-chat-crud-item__hint", children: "Este paso ya se gestion\xF3. Contin\xFAa en el mensaje m\xE1s reciente." }),
16729
- row && !gastada && config.deadline && typeof row[config.deadline.field] === "string" && /* @__PURE__ */ jsx(
17283
+ row && !gastada && plazo && /* @__PURE__ */ jsx(
16730
17284
  DeadlineCountdown,
16731
17285
  {
16732
- deadline: row[config.deadline.field],
16733
- label: config.deadline.label,
16734
- expiredLabel: config.deadline.expiredLabel
17286
+ deadline: plazo.at,
17287
+ label: plazo.config.label,
17288
+ expiredLabel: plazo.config.expiredLabel
16735
17289
  }
16736
17290
  ),
16737
17291
  row && /* @__PURE__ */ jsxs("div", { className: "px-chat-crud-item__actions", children: [
@@ -16842,7 +17396,7 @@ function markFitOutliers(points, radiusKm = FIT_RADIUS_KM) {
16842
17396
  return { points: marcados, outside };
16843
17397
  }
16844
17398
 
16845
- const CLASS$9 = `${COMPONENT_PREFIX$1}services-map`;
17399
+ const CLASS$8 = `${COMPONENT_PREFIX$1}services-map`;
16846
17400
  const DEFAULT_HEIGHT = 340;
16847
17401
  function readNumber(row, field) {
16848
17402
  if (!field) return void 0;
@@ -16968,7 +17522,7 @@ const ServicesMap = ({ config, eventBus, apiKey, filter, fill }) => {
16968
17522
  [livePoints]
16969
17523
  );
16970
17524
  const nadaQueDibujar = rows !== null && allPoints.length === 0 && route.length === 0;
16971
- return /* @__PURE__ */ jsx("div", { className: fill ? `${CLASS$9} ${CLASS$9}--fill` : CLASS$9, children: rows === null ? /* @__PURE__ */ jsx("p", { className: `${CLASS$9}__state`, children: labels.loadingText ?? "Cargando ubicaciones\u2026" }) : nadaQueDibujar ? /* @__PURE__ */ jsx("p", { className: `${CLASS$9}__state`, children: lineaSinMapa(labels, missing, failed) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
17525
+ return /* @__PURE__ */ jsx("div", { className: fill ? `${CLASS$8} ${CLASS$8}--fill` : CLASS$8, children: rows === null ? /* @__PURE__ */ jsx("p", { className: `${CLASS$8}__state`, children: labels.loadingText ?? "Cargando ubicaciones\u2026" }) : nadaQueDibujar ? /* @__PURE__ */ jsx("p", { className: `${CLASS$8}__state`, children: lineaSinMapa(labels, missing, failed) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
16972
17526
  /* @__PURE__ */ jsx(
16973
17527
  MapView,
16974
17528
  {
@@ -16982,20 +17536,20 @@ const ServicesMap = ({ config, eventBus, apiKey, filter, fill }) => {
16982
17536
  labels: { emptyText: labels.emptyText }
16983
17537
  }
16984
17538
  ),
16985
- /* @__PURE__ */ jsxs("div", { className: `${CLASS$9}__notes`, children: [
16986
- livePoints.length > 0 && /* @__PURE__ */ jsxs("p", { className: `${CLASS$9}__note ${CLASS$9}__note--live`, children: [
17539
+ /* @__PURE__ */ jsxs("div", { className: `${CLASS$8}__notes`, children: [
17540
+ livePoints.length > 0 && /* @__PURE__ */ jsxs("p", { className: `${CLASS$8}__note ${CLASS$8}__note--live`, children: [
16987
17541
  (config.live?.labels?.liveText ?? "{n} en movimiento").replace(
16988
17542
  "{n}",
16989
17543
  String(livePoints.length)
16990
17544
  ),
16991
17545
  simulated > 0 && ` \xB7 ${config.live?.labels?.simulatedText ?? "incluye posiciones simuladas"}`
16992
17546
  ] }),
16993
- missing > 0 && /* @__PURE__ */ jsx("p", { className: `${CLASS$9}__note`, children: ((missing === 1 ? labels.missingTextOne : void 0) ?? labels.missingText ?? "{n} sin ubicaci\xF3n registrada").replace("{n}", String(missing)) }),
16994
- outside > 0 && /* @__PURE__ */ jsx("p", { className: `${CLASS$9}__note`, children: (labels.outsideText ?? "{n} fuera de la zona (aleja el mapa para verlos)").replace(
17547
+ missing > 0 && /* @__PURE__ */ jsx("p", { className: `${CLASS$8}__note`, children: ((missing === 1 ? labels.missingTextOne : void 0) ?? labels.missingText ?? "{n} sin ubicaci\xF3n registrada").replace("{n}", String(missing)) }),
17548
+ outside > 0 && /* @__PURE__ */ jsx("p", { className: `${CLASS$8}__note`, children: (labels.outsideText ?? "{n} fuera de la zona (aleja el mapa para verlos)").replace(
16995
17549
  "{n}",
16996
17550
  String(outside)
16997
17551
  ) }),
16998
- failed && /* @__PURE__ */ jsx("p", { className: `${CLASS$9}__note`, children: "No se pudieron cargar las ubicaciones." })
17552
+ failed && /* @__PURE__ */ jsx("p", { className: `${CLASS$8}__note`, children: "No se pudieron cargar las ubicaciones." })
16999
17553
  ] })
17000
17554
  ] }) });
17001
17555
  };
@@ -17011,7 +17565,7 @@ function lineaSinMapa(labels, missing, failed) {
17011
17565
  return labels.emptyText ?? "Sin ubicaciones para mostrar";
17012
17566
  }
17013
17567
 
17014
- const CLASS$8 = `${COMPONENT_PREFIX$1}service-shortcuts`;
17568
+ const CLASS$7 = `${COMPONENT_PREFIX$1}service-shortcuts`;
17015
17569
  const ICONS = {
17016
17570
  // SPEC-126 — quien DESPACHA tambien necesita sus puertas, y una de ellas son las conversaciones
17017
17571
  // de sus servicios. Los cinco iconos que habia eran todos de quien PIDE una grua.
@@ -17065,16 +17619,16 @@ const ServiceShortcuts = ({
17065
17619
  }) => {
17066
17620
  if (!options?.length) return null;
17067
17621
  const elegido = !!selectedId;
17068
- return /* @__PURE__ */ jsx("div", { className: [CLASS$8, elegido ? `${CLASS$8}--used` : ""].filter(Boolean).join(" "), children: options.map((o) => {
17622
+ return /* @__PURE__ */ jsx("div", { className: [CLASS$7, elegido ? `${CLASS$7}--used` : ""].filter(Boolean).join(" "), children: options.map((o) => {
17069
17623
  const esElegido = o.id === selectedId;
17070
17624
  return /* @__PURE__ */ jsxs(
17071
17625
  "button",
17072
17626
  {
17073
17627
  type: "button",
17074
17628
  className: [
17075
- `${CLASS$8}__item`,
17076
- elegido ? `${CLASS$8}__item--off` : "",
17077
- esElegido ? `${CLASS$8}__item--chosen` : ""
17629
+ `${CLASS$7}__item`,
17630
+ elegido ? `${CLASS$7}__item--off` : "",
17631
+ esElegido ? `${CLASS$7}__item--chosen` : ""
17078
17632
  ].filter(Boolean).join(" "),
17079
17633
  disabled: elegido,
17080
17634
  "aria-disabled": elegido,
@@ -17086,12 +17640,12 @@ const ServiceShortcuts = ({
17086
17640
  else if (o.route) eventBus?.emit(CHAT_EVENT.NAVIGATE, { route: o.route });
17087
17641
  },
17088
17642
  children: [
17089
- o.icon && /* @__PURE__ */ jsx("span", { className: `${CLASS$8}__icon`, children: ICONS[o.icon] }),
17090
- /* @__PURE__ */ jsxs("span", { className: `${CLASS$8}__text`, children: [
17091
- /* @__PURE__ */ jsx("span", { className: `${CLASS$8}__label`, children: o.label }),
17092
- o.hint && /* @__PURE__ */ jsx("span", { className: `${CLASS$8}__hint`, children: o.hint })
17643
+ o.icon && /* @__PURE__ */ jsx("span", { className: `${CLASS$7}__icon`, children: ICONS[o.icon] }),
17644
+ /* @__PURE__ */ jsxs("span", { className: `${CLASS$7}__text`, children: [
17645
+ /* @__PURE__ */ jsx("span", { className: `${CLASS$7}__label`, children: o.label }),
17646
+ o.hint && /* @__PURE__ */ jsx("span", { className: `${CLASS$7}__hint`, children: o.hint })
17093
17647
  ] }),
17094
- /* @__PURE__ */ jsx("span", { className: `${CLASS$8}__arrow`, children: esElegido ? CHECK : elegido ? null : /* @__PURE__ */ jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("polyline", { points: "9 18 15 12 9 6" }) }) })
17648
+ /* @__PURE__ */ jsx("span", { className: `${CLASS$7}__arrow`, children: esElegido ? CHECK : elegido ? null : /* @__PURE__ */ jsx("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("polyline", { points: "9 18 15 12 9 6" }) }) })
17095
17649
  ]
17096
17650
  },
17097
17651
  o.id
@@ -17660,19 +18214,19 @@ function ChatNavigatorChat({ component, eventBus }) {
17660
18214
  ] });
17661
18215
  }
17662
18216
 
17663
- const CLASS$7 = `${COMPONENT_PREFIX$1}user-tools`;
18217
+ const CLASS$6 = `${COMPONENT_PREFIX$1}user-tools`;
17664
18218
  const UserTools = ({ config, onChange, onAction, className }) => {
17665
18219
  const { title, description, items } = config;
17666
- return /* @__PURE__ */ jsxs("section", { className: [CLASS$7, className].filter(Boolean).join(" "), children: [
17667
- title && /* @__PURE__ */ jsx("h2", { className: `${CLASS$7}__title`, children: title }),
17668
- description && /* @__PURE__ */ jsx("p", { className: `${CLASS$7}__description`, children: description }),
17669
- /* @__PURE__ */ jsx("ul", { className: `${CLASS$7}__list`, children: items.map((item) => /* @__PURE__ */ jsx("li", { className: `${CLASS$7}__item`, children: item.kind === "action" ? (
18220
+ return /* @__PURE__ */ jsxs("section", { className: [CLASS$6, className].filter(Boolean).join(" "), children: [
18221
+ title && /* @__PURE__ */ jsx("h2", { className: `${CLASS$6}__title`, children: title }),
18222
+ description && /* @__PURE__ */ jsx("p", { className: `${CLASS$6}__description`, children: description }),
18223
+ /* @__PURE__ */ jsx("ul", { className: `${CLASS$6}__list`, children: items.map((item) => /* @__PURE__ */ jsx("li", { className: `${CLASS$6}__item`, children: item.kind === "action" ? (
17670
18224
  // SPEC-139 T9 — un ajuste que se pulsa: mismo renglón (etiqueta y pista), y en vez
17671
18225
  // de la caja, un botón que dice lo que hace.
17672
- /* @__PURE__ */ jsxs("div", { className: `${CLASS$7}__action`, children: [
17673
- /* @__PURE__ */ jsxs("span", { className: `${CLASS$7}__text`, children: [
17674
- /* @__PURE__ */ jsx("span", { className: `${CLASS$7}__label`, children: item.label }),
17675
- item.hint && /* @__PURE__ */ jsx("span", { className: `${CLASS$7}__hint`, children: item.hint })
18226
+ /* @__PURE__ */ jsxs("div", { className: `${CLASS$6}__action`, children: [
18227
+ /* @__PURE__ */ jsxs("span", { className: `${CLASS$6}__text`, children: [
18228
+ /* @__PURE__ */ jsx("span", { className: `${CLASS$6}__label`, children: item.label }),
18229
+ item.hint && /* @__PURE__ */ jsx("span", { className: `${CLASS$6}__hint`, children: item.hint })
17676
18230
  ] }),
17677
18231
  /* @__PURE__ */ jsx(
17678
18232
  Button,
@@ -17691,13 +18245,13 @@ const UserTools = ({ config, onChange, onAction, className }) => {
17691
18245
  checked: Boolean(item.value),
17692
18246
  disabled: item.disabled,
17693
18247
  onChange: (checked) => onChange?.(item.id, checked),
17694
- label: /* @__PURE__ */ jsxs("span", { className: `${CLASS$7}__text`, children: [
17695
- /* @__PURE__ */ jsx("span", { className: `${CLASS$7}__label`, children: item.label }),
17696
- item.hint && /* @__PURE__ */ jsx("span", { className: `${CLASS$7}__hint`, children: item.hint })
18248
+ label: /* @__PURE__ */ jsxs("span", { className: `${CLASS$6}__text`, children: [
18249
+ /* @__PURE__ */ jsx("span", { className: `${CLASS$6}__label`, children: item.label }),
18250
+ item.hint && /* @__PURE__ */ jsx("span", { className: `${CLASS$6}__hint`, children: item.hint })
17697
18251
  ] })
17698
18252
  }
17699
18253
  ) }, item.id)) }),
17700
- items.length === 0 && /* @__PURE__ */ jsx("p", { className: `${CLASS$7}__empty`, children: "No hay herramientas disponibles por ahora." })
18254
+ items.length === 0 && /* @__PURE__ */ jsx("p", { className: `${CLASS$6}__empty`, children: "No hay herramientas disponibles por ahora." })
17701
18255
  ] });
17702
18256
  };
17703
18257
  UserTools.displayName = "UserTools";
@@ -18307,7 +18861,7 @@ const ChatHeader = ({
18307
18861
  ] });
18308
18862
  };
18309
18863
 
18310
- const CLASS$6 = `${COMPONENT_PREFIX$1}floating-actions`;
18864
+ const CLASS$5 = `${COMPONENT_PREFIX$1}floating-actions`;
18311
18865
  const ICON_VALUES = new Set(Object.values(ICON_TYPES));
18312
18866
  function renderIcon(icon) {
18313
18867
  if (typeof icon === "string" && ICON_VALUES.has(icon)) {
@@ -18316,23 +18870,23 @@ function renderIcon(icon) {
18316
18870
  return icon;
18317
18871
  }
18318
18872
  function Side({ buttons, align, eventBus }) {
18319
- return /* @__PURE__ */ jsx("div", { className: `${CLASS$6}__group ${CLASS$6}__group--${align}`, children: buttons.map((b) => {
18873
+ return /* @__PURE__ */ jsx("div", { className: `${CLASS$5}__group ${CLASS$5}__group--${align}`, children: buttons.map((b) => {
18320
18874
  const emit = () => {
18321
18875
  if (b.disabled) return;
18322
18876
  eventBus.emit(b.event, b.payload);
18323
18877
  };
18324
18878
  if (b.custom) {
18325
- return /* @__PURE__ */ jsxs("div", { className: `${CLASS$6}__slot`, children: [
18879
+ return /* @__PURE__ */ jsxs("div", { className: `${CLASS$5}__slot`, children: [
18326
18880
  b.custom,
18327
- b.panel && b.open && /* @__PURE__ */ jsx("div", { className: `${CLASS$6}__panel ${CLASS$6}__panel--${align}`, children: b.panel })
18881
+ b.panel && b.open && /* @__PURE__ */ jsx("div", { className: `${CLASS$5}__panel ${CLASS$5}__panel--${align}`, children: b.panel })
18328
18882
  ] }, b.id);
18329
18883
  }
18330
- return /* @__PURE__ */ jsxs("div", { className: `${CLASS$6}__slot`, children: [
18884
+ return /* @__PURE__ */ jsxs("div", { className: `${CLASS$5}__slot`, children: [
18331
18885
  /* @__PURE__ */ jsxs(
18332
18886
  "button",
18333
18887
  {
18334
18888
  type: "button",
18335
- className: [`${CLASS$6}__button`, b.active ? `${CLASS$6}__button--active` : ""].filter(Boolean).join(" "),
18889
+ className: [`${CLASS$5}__button`, b.active ? `${CLASS$5}__button--active` : ""].filter(Boolean).join(" "),
18336
18890
  "aria-label": b.ariaLabel,
18337
18891
  title: b.ariaLabel,
18338
18892
  "aria-pressed": b.active,
@@ -18340,16 +18894,16 @@ function Side({ buttons, align, eventBus }) {
18340
18894
  onClick: emit,
18341
18895
  children: [
18342
18896
  renderIcon(b.icon),
18343
- b.badge != null && b.badge !== "" && b.badge !== 0 && /* @__PURE__ */ jsx("span", { className: `${CLASS$6}__badge`, children: b.badge })
18897
+ b.badge != null && b.badge !== "" && b.badge !== 0 && /* @__PURE__ */ jsx("span", { className: `${CLASS$5}__badge`, children: b.badge })
18344
18898
  ]
18345
18899
  }
18346
18900
  ),
18347
- b.panel && b.open && /* @__PURE__ */ jsx("div", { className: `${CLASS$6}__panel ${CLASS$6}__panel--${align}`, children: b.panel })
18901
+ b.panel && b.open && /* @__PURE__ */ jsx("div", { className: `${CLASS$5}__panel ${CLASS$5}__panel--${align}`, children: b.panel })
18348
18902
  ] }, b.id);
18349
18903
  }) });
18350
18904
  }
18351
18905
  const ChatFloatingActions = ({ eventBus, left = [], right = [], offset = 12, glass = false }) => {
18352
- const cls = [CLASS$6, glass ? `${CLASS$6}--glass` : ""].filter(Boolean).join(" ");
18906
+ const cls = [CLASS$5, glass ? `${CLASS$5}--glass` : ""].filter(Boolean).join(" ");
18353
18907
  return /* @__PURE__ */ jsxs("div", { className: cls, style: { paddingLeft: offset, paddingRight: offset }, children: [
18354
18908
  /* @__PURE__ */ jsx(Side, { buttons: left, align: "left", eventBus }),
18355
18909
  /* @__PURE__ */ jsx(Side, { buttons: right, align: "right", eventBus })
@@ -18782,7 +19336,7 @@ const UserMessage = ({
18782
19336
  ] }) });
18783
19337
  };
18784
19338
 
18785
- const CLASS$5 = `${COMPONENT_PREFIX$1}photo-picker`;
19339
+ const CLASS$4 = `${COMPONENT_PREFIX$1}photo-picker`;
18786
19340
  const PhotoPicker = ({
18787
19341
  label,
18788
19342
  hint,
@@ -18807,8 +19361,8 @@ const PhotoPicker = ({
18807
19361
  void onFiles(e.target.files);
18808
19362
  e.target.value = "";
18809
19363
  };
18810
- return /* @__PURE__ */ jsxs("div", { className: `${CLASS$5}${error ? ` ${CLASS$5}--error` : ""}`, children: [
18811
- /* @__PURE__ */ jsxs("span", { className: `${CLASS$5}__label`, children: [
19364
+ return /* @__PURE__ */ jsxs("div", { className: `${CLASS$4}${error ? ` ${CLASS$4}--error` : ""}`, children: [
19365
+ /* @__PURE__ */ jsxs("span", { className: `${CLASS$4}__label`, children: [
18812
19366
  label,
18813
19367
  required ? " *" : "",
18814
19368
  hechas > 0 ? ` (${hechas}${max ? `/${max}` : ""})` : ""
@@ -18817,7 +19371,7 @@ const PhotoPicker = ({
18817
19371
  "input",
18818
19372
  {
18819
19373
  ref: galeriaRef,
18820
- className: `${CLASS$5}__native`,
19374
+ className: `${CLASS$4}__native`,
18821
19375
  type: "file",
18822
19376
  accept: "image/*",
18823
19377
  multiple: max !== 1,
@@ -18830,7 +19384,7 @@ const PhotoPicker = ({
18830
19384
  "input",
18831
19385
  {
18832
19386
  ref: camaraRef,
18833
- className: `${CLASS$5}__native`,
19387
+ className: `${CLASS$4}__native`,
18834
19388
  type: "file",
18835
19389
  accept: "image/*",
18836
19390
  capture: "environment",
@@ -18839,15 +19393,15 @@ const PhotoPicker = ({
18839
19393
  "data-testid": "photo-picker-camera"
18840
19394
  }
18841
19395
  ),
18842
- entries.length > 0 && /* @__PURE__ */ jsx("ul", { className: `${CLASS$5}__grid`, children: entries.map((e, i) => /* @__PURE__ */ jsxs("li", { className: `${CLASS$5}__thumb ${CLASS$5}__thumb--${e.status}`, children: [
18843
- e.previewUrl ? /* @__PURE__ */ jsx("img", { className: `${CLASS$5}__img`, src: e.previewUrl, alt: e.name }) : /* @__PURE__ */ jsx("span", { className: `${CLASS$5}__placeholder`, "aria-hidden": "true", children: /* @__PURE__ */ jsx(Icon$1, { type: ICON_TYPES.IMAGE }) }),
18844
- e.status === "uploading" && /* @__PURE__ */ jsx("span", { className: `${CLASS$5}__state`, children: "Subiendo\u2026" }),
18845
- e.status === "error" && /* @__PURE__ */ jsx("span", { className: `${CLASS$5}__state ${CLASS$5}__state--error`, children: "No se pudo subir" }),
19396
+ entries.length > 0 && /* @__PURE__ */ jsx("ul", { className: `${CLASS$4}__grid`, children: entries.map((e, i) => /* @__PURE__ */ jsxs("li", { className: `${CLASS$4}__thumb ${CLASS$4}__thumb--${e.status}`, children: [
19397
+ e.previewUrl ? /* @__PURE__ */ jsx("img", { className: `${CLASS$4}__img`, src: e.previewUrl, alt: e.name }) : /* @__PURE__ */ jsx("span", { className: `${CLASS$4}__placeholder`, "aria-hidden": "true", children: /* @__PURE__ */ jsx(Icon$1, { type: ICON_TYPES.IMAGE }) }),
19398
+ e.status === "uploading" && /* @__PURE__ */ jsx("span", { className: `${CLASS$4}__state`, children: "Subiendo\u2026" }),
19399
+ e.status === "error" && /* @__PURE__ */ jsx("span", { className: `${CLASS$4}__state ${CLASS$4}__state--error`, children: "No se pudo subir" }),
18846
19400
  onRemove && e.status !== "uploading" && /* @__PURE__ */ jsx(
18847
19401
  "button",
18848
19402
  {
18849
19403
  type: "button",
18850
- className: `${CLASS$5}__remove`,
19404
+ className: `${CLASS$4}__remove`,
18851
19405
  onClick: () => onRemove(i),
18852
19406
  "aria-label": `Quitar ${e.name}`,
18853
19407
  disabled,
@@ -18855,12 +19409,12 @@ const PhotoPicker = ({
18855
19409
  }
18856
19410
  )
18857
19411
  ] }, `${e.name}-${i}`)) }),
18858
- /* @__PURE__ */ jsxs("div", { className: `${CLASS$5}__actions`, children: [
19412
+ /* @__PURE__ */ jsxs("div", { className: `${CLASS$4}__actions`, children: [
18859
19413
  capture && /* @__PURE__ */ jsxs(
18860
19414
  "button",
18861
19415
  {
18862
19416
  type: "button",
18863
- className: `${CLASS$5}__pick`,
19417
+ className: `${CLASS$4}__pick`,
18864
19418
  onClick: () => elegir(camaraRef),
18865
19419
  disabled: disabled || lleno,
18866
19420
  children: [
@@ -18873,7 +19427,7 @@ const PhotoPicker = ({
18873
19427
  "button",
18874
19428
  {
18875
19429
  type: "button",
18876
- className: `${CLASS$5}__pick ${CLASS$5}__pick--secondary`,
19430
+ className: `${CLASS$4}__pick ${CLASS$4}__pick--secondary`,
18877
19431
  onClick: () => elegir(galeriaRef),
18878
19432
  disabled: disabled || lleno,
18879
19433
  children: [
@@ -18883,13 +19437,13 @@ const PhotoPicker = ({
18883
19437
  }
18884
19438
  )
18885
19439
  ] }),
18886
- error && /* @__PURE__ */ jsx("p", { className: `${CLASS$5}__error`, children: error }),
18887
- !error && subiendo && /* @__PURE__ */ jsx("p", { className: `${CLASS$5}__hint`, children: "Espera a que terminen de subir." }),
18888
- !error && !subiendo && hint && /* @__PURE__ */ jsx("p", { className: `${CLASS$5}__hint`, children: hint })
19440
+ error && /* @__PURE__ */ jsx("p", { className: `${CLASS$4}__error`, children: error }),
19441
+ !error && subiendo && /* @__PURE__ */ jsx("p", { className: `${CLASS$4}__hint`, children: "Espera a que terminen de subir." }),
19442
+ !error && !subiendo && hint && /* @__PURE__ */ jsx("p", { className: `${CLASS$4}__hint`, children: hint })
18889
19443
  ] });
18890
19444
  };
18891
19445
 
18892
- const CLASS$4 = `${COMPONENT_PREFIX$1}credentials-card`;
19446
+ const CLASS$3 = `${COMPONENT_PREFIX$1}credentials-card`;
18893
19447
  async function copiar(texto) {
18894
19448
  try {
18895
19449
  await navigator.clipboard.writeText(texto);
@@ -18906,15 +19460,15 @@ const Fila = ({ row }) => {
18906
19460
  const t = setTimeout(() => setCopiado(false), 1800);
18907
19461
  return () => clearTimeout(t);
18908
19462
  }, [copiado]);
18909
- return /* @__PURE__ */ jsxs("li", { className: `${CLASS$4}__row`, children: [
18910
- /* @__PURE__ */ jsx("span", { className: `${CLASS$4}__label`, children: row.label }),
18911
- /* @__PURE__ */ jsx("span", { className: `${CLASS$4}__value`, "data-testid": `credential-${row.label}`, children: visible ? row.value : "\u2022".repeat(Math.min(row.value.length, 12)) }),
18912
- /* @__PURE__ */ jsxs("span", { className: `${CLASS$4}__tools`, children: [
19463
+ return /* @__PURE__ */ jsxs("li", { className: `${CLASS$3}__row`, children: [
19464
+ /* @__PURE__ */ jsx("span", { className: `${CLASS$3}__label`, children: row.label }),
19465
+ /* @__PURE__ */ jsx("span", { className: `${CLASS$3}__value`, "data-testid": `credential-${row.label}`, children: visible ? row.value : "\u2022".repeat(Math.min(row.value.length, 12)) }),
19466
+ /* @__PURE__ */ jsxs("span", { className: `${CLASS$3}__tools`, children: [
18913
19467
  row.masked && /* @__PURE__ */ jsx(
18914
19468
  "button",
18915
19469
  {
18916
19470
  type: "button",
18917
- className: `${CLASS$4}__tool`,
19471
+ className: `${CLASS$3}__tool`,
18918
19472
  onClick: () => setVisible((v) => !v),
18919
19473
  "aria-label": visible ? `Ocultar ${row.label}` : `Ver ${row.label}`,
18920
19474
  children: visible ? "Ocultar" : "Ver"
@@ -18924,7 +19478,7 @@ const Fila = ({ row }) => {
18924
19478
  "button",
18925
19479
  {
18926
19480
  type: "button",
18927
- className: `${CLASS$4}__tool`,
19481
+ className: `${CLASS$3}__tool`,
18928
19482
  onClick: async () => setCopiado(await copiar(row.value)),
18929
19483
  "aria-label": `Copiar ${row.label}`,
18930
19484
  children: copiado ? /* @__PURE__ */ jsxs(Fragment, { children: [
@@ -18943,12 +19497,12 @@ const CredentialsCard = ({
18943
19497
  note,
18944
19498
  action,
18945
19499
  className
18946
- }) => /* @__PURE__ */ jsxs("section", { className: [CLASS$4, className].filter(Boolean).join(" "), "aria-label": title, children: [
18947
- /* @__PURE__ */ jsx("h3", { className: `${CLASS$4}__title`, children: title }),
18948
- intro && /* @__PURE__ */ jsx("p", { className: `${CLASS$4}__intro`, children: intro }),
18949
- /* @__PURE__ */ jsx("ul", { className: `${CLASS$4}__rows`, children: rows.map((r) => /* @__PURE__ */ jsx(Fila, { row: r }, r.label)) }),
18950
- note && /* @__PURE__ */ jsx("p", { className: `${CLASS$4}__note`, children: note }),
18951
- action && /* @__PURE__ */ jsx("div", { className: `${CLASS$4}__action`, children: /* @__PURE__ */ jsx(Button, { fullWidth: true, onClick: action.onClick, disabled: action.disabled, children: action.label }) })
19500
+ }) => /* @__PURE__ */ jsxs("section", { className: [CLASS$3, className].filter(Boolean).join(" "), "aria-label": title, children: [
19501
+ /* @__PURE__ */ jsx("h3", { className: `${CLASS$3}__title`, children: title }),
19502
+ intro && /* @__PURE__ */ jsx("p", { className: `${CLASS$3}__intro`, children: intro }),
19503
+ /* @__PURE__ */ jsx("ul", { className: `${CLASS$3}__rows`, children: rows.map((r) => /* @__PURE__ */ jsx(Fila, { row: r }, r.label)) }),
19504
+ note && /* @__PURE__ */ jsx("p", { className: `${CLASS$3}__note`, children: note }),
19505
+ action && /* @__PURE__ */ jsx("div", { className: `${CLASS$3}__action`, children: /* @__PURE__ */ jsx(Button, { fullWidth: true, onClick: action.onClick, disabled: action.disabled, children: action.label }) })
18952
19506
  ] });
18953
19507
  CredentialsCard.displayName = "CredentialsCard";
18954
19508
 
@@ -19120,7 +19674,7 @@ const TextArea = forwardRef(
19120
19674
  );
19121
19675
  TextArea.displayName = "TextArea";
19122
19676
 
19123
- const CLASS$3 = `${COMPONENT_PREFIX$1}support-request-form`;
19677
+ const CLASS$2 = `${COMPONENT_PREFIX$1}support-request-form`;
19124
19678
  const VACIO = { name: "", email: "", phone: "", subject: "", message: "" };
19125
19679
  function faltantes(v) {
19126
19680
  if (v.name.trim().length < 2) return "Escribe tu nombre.";
@@ -19165,14 +19719,14 @@ const SupportRequestForm = ({
19165
19719
  return /* @__PURE__ */ jsxs(
19166
19720
  "form",
19167
19721
  {
19168
- className: [CLASS$3, sent ? `${CLASS$3}--sent` : "", className].filter(Boolean).join(" "),
19722
+ className: [CLASS$2, sent ? `${CLASS$2}--sent` : "", className].filter(Boolean).join(" "),
19169
19723
  onSubmit: enviar,
19170
19724
  noValidate: true,
19171
19725
  children: [
19172
- /* @__PURE__ */ jsx("h4", { className: `${CLASS$3}__title`, children: title }),
19173
- intro && /* @__PURE__ */ jsx("p", { className: `${CLASS$3}__intro`, children: intro }),
19174
- /* @__PURE__ */ jsxs("div", { className: `${CLASS$3}__fields`, children: [
19175
- /* @__PURE__ */ jsxs("div", { className: `${CLASS$3}__row`, children: [
19726
+ /* @__PURE__ */ jsx("h4", { className: `${CLASS$2}__title`, children: title }),
19727
+ intro && /* @__PURE__ */ jsx("p", { className: `${CLASS$2}__intro`, children: intro }),
19728
+ /* @__PURE__ */ jsxs("div", { className: `${CLASS$2}__fields`, children: [
19729
+ /* @__PURE__ */ jsxs("div", { className: `${CLASS$2}__row`, children: [
19176
19730
  /* @__PURE__ */ jsx(Input$1, { label: "Nombre", value: values.name, onChange: set("name"), fullWidth: true, disabled: sent, autoComplete: "name" }),
19177
19731
  /* @__PURE__ */ jsx(Input$1, { label: "Tel\xE9fono (opcional)", value: values.phone, onChange: set("phone"), fullWidth: true, disabled: sent, inputMode: "tel", autoComplete: "tel" })
19178
19732
  ] }),
@@ -19180,13 +19734,13 @@ const SupportRequestForm = ({
19180
19734
  /* @__PURE__ */ jsx(Input$1, { label: "Asunto", value: values.subject, onChange: set("subject"), fullWidth: true, disabled: sent }),
19181
19735
  /* @__PURE__ */ jsx(TextArea, { label: "Mensaje", value: values.message, onChange: set("message"), fullWidth: true, disabled: sent, minRows: 3, maxLength: 4e3, showCount: true })
19182
19736
  ] }),
19183
- error && /* @__PURE__ */ jsx("p", { className: `${CLASS$3}__error`, role: "alert", children: error }),
19184
- sent ? /* @__PURE__ */ jsxs("p", { className: `${CLASS$3}__done`, role: "status", children: [
19737
+ error && /* @__PURE__ */ jsx("p", { className: `${CLASS$2}__error`, role: "alert", children: error }),
19738
+ sent ? /* @__PURE__ */ jsxs("p", { className: `${CLASS$2}__done`, role: "status", children: [
19185
19739
  /* @__PURE__ */ jsx(Icon$1, { type: ICON_TYPES.CHECK, size: "small" }),
19186
19740
  /* @__PURE__ */ jsx("span", { children: sentLabel })
19187
19741
  ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
19188
- /* @__PURE__ */ jsx("div", { className: `${CLASS$3}__actions`, children: /* @__PURE__ */ jsx(Button, { type: "submit", variant: "primary", isLoading: enviando, disabled: enviando, children: submitLabel }) }),
19189
- note && /* @__PURE__ */ jsx("p", { className: `${CLASS$3}__note`, children: note })
19742
+ /* @__PURE__ */ jsx("div", { className: `${CLASS$2}__actions`, children: /* @__PURE__ */ jsx(Button, { type: "submit", variant: "primary", isLoading: enviando, disabled: enviando, children: submitLabel }) }),
19743
+ note && /* @__PURE__ */ jsx("p", { className: `${CLASS$2}__note`, children: note })
19190
19744
  ] })
19191
19745
  ]
19192
19746
  }
@@ -22119,105 +22673,6 @@ const Notification = ({
22119
22673
  };
22120
22674
  Notification.displayName = "Notification";
22121
22675
 
22122
- const CARD_VARIANTS = {
22123
- /** Con sombra: flota sobre el contenido (hojas, diálogos, paneles). */
22124
- ELEVATED: "elevated"};
22125
- const CARD_PADDINGS = {
22126
- MEDIUM: "medium",
22127
- LARGE: "large"
22128
- };
22129
- const CARD_RADII = {
22130
- NONE: "none",
22131
- LARGE: "large"
22132
- };
22133
-
22134
- const BASE = `${COMPONENT_PREFIX}card`;
22135
- const Card = React.forwardRef(
22136
- ({
22137
- variant = CARD_VARIANTS.ELEVATED,
22138
- padding = CARD_PADDINGS.MEDIUM,
22139
- radius = CARD_RADII.LARGE,
22140
- fullWidth = false,
22141
- className = "",
22142
- children,
22143
- ...rest
22144
- }, ref) => {
22145
- const classes = [
22146
- BASE,
22147
- `${BASE}--${variant}`,
22148
- `${BASE}--padding-${padding}`,
22149
- `${BASE}--radius-${radius}`,
22150
- fullWidth ? `${BASE}--full-width` : "",
22151
- className
22152
- ].filter(Boolean).join(" ");
22153
- return /* @__PURE__ */ jsx("div", { ref, className: classes, ...rest, children });
22154
- }
22155
- );
22156
- Card.displayName = "Card";
22157
-
22158
- const CLASS$2 = "px-lumi-bottom-sheet";
22159
- const BottomSheet = ({
22160
- open,
22161
- children,
22162
- onClose,
22163
- showGrabber = true,
22164
- closeOnBackdrop = false,
22165
- closeOnEscape = true,
22166
- ariaLabelledBy,
22167
- className = ""
22168
- }) => {
22169
- useEffect(() => {
22170
- if (!open) return;
22171
- const onKey = (e) => {
22172
- if (e.key === "Escape" && closeOnEscape) onClose?.();
22173
- };
22174
- document.addEventListener("keydown", onKey);
22175
- const previous = document.body.style.overflow;
22176
- document.body.style.overflow = "hidden";
22177
- return () => {
22178
- document.removeEventListener("keydown", onKey);
22179
- document.body.style.overflow = previous;
22180
- };
22181
- }, [open, closeOnEscape, onClose]);
22182
- if (!open) return null;
22183
- return createPortal(
22184
- /* @__PURE__ */ jsxs(
22185
- "div",
22186
- {
22187
- className: [CLASS$2, className].filter(Boolean).join(" "),
22188
- role: "dialog",
22189
- "aria-modal": "true",
22190
- "aria-labelledby": ariaLabelledBy,
22191
- children: [
22192
- /* @__PURE__ */ jsx(
22193
- "div",
22194
- {
22195
- className: `${CLASS$2}__backdrop`,
22196
- "aria-hidden": "true",
22197
- onClick: closeOnBackdrop ? onClose : void 0
22198
- }
22199
- ),
22200
- /* @__PURE__ */ jsxs(
22201
- Card,
22202
- {
22203
- className: `${CLASS$2}__sheet`,
22204
- padding: CARD_PADDINGS.LARGE,
22205
- radius: CARD_RADII.NONE,
22206
- fullWidth: true,
22207
- children: [
22208
- showGrabber && /* @__PURE__ */ jsx("div", { className: `${CLASS$2}__grabber`, "aria-hidden": "true" }),
22209
- children
22210
- ]
22211
- }
22212
- )
22213
- ]
22214
- }
22215
- ),
22216
- document.body
22217
- );
22218
- };
22219
- BottomSheet.displayName = "BottomSheet";
22220
-
22221
22676
  const CLASS$1 = `${COMPONENT_PREFIX}live-indicator`;
22222
22677
  const LiveIndicator = ({
22223
22678
  label,
@@ -25378,4 +25833,4 @@ function buildBreadcrumbPath(items, targetKey, currentPath = []) {
25378
25833
  return [];
25379
25834
  }
25380
25835
 
25381
- export { ActionFormDrawer, BottomSheet, CHAT_CONFIG_DEFAULTS, CHAT_EVENT, ICON_TYPES as CHAT_ICON_TYPES, CarouselDisplay, Chat, AssistantMessage as ChatAssistantMessage, AssistantThinkingIndicator as ChatAssistantThinkingIndicator, AttachmentPreview as ChatAttachmentPreview, Avatar as ChatAvatar, Button$1 as ChatButton, ChatConfigProvider, DateDivider as ChatDateDivider, FileViewer as ChatFileViewer, ChatFloatingActions, FullscreenViewer as ChatFullscreenViewer, ChatHeader as ChatHeaderComponent, Icon$1 as ChatIcon, Input$2 as ChatInput, ChatInput as ChatInputComponent, Link as ChatLink, Loader$1 as ChatLoader, Logo as ChatLogo, MessageStatus as ChatMessageStatus, Modal as ChatModal, ChatNavigator, Select$2 as ChatSelect, SelectMenu as ChatSelectMenu, StructuredContent as ChatStructuredContent, Text as ChatText, Textarea as ChatTextarea, UserAttachments as ChatUserAttachments, UserMessage as ChatUserMessage, ChatWidget, CredentialsCard, FileField, BADGE_VARIANTS as LUMI_BADGE_VARIANTS, DEFAULT_TITLES as LUMI_DEFAULT_TITLES, LUMI_ICON_TYPES, LiveIndicator, LocationField, ActionBar as LumiActionBar, Badge as LumiBadge, Base as LumiBase, BaseNavbar as LumiBaseNavbar, BaseWorkspace as LumiBaseWorkspace, Breadcrumb as LumiBreadcrumb, BreadcrumbItem as LumiBreadcrumbItem, BreadcrumbSeparator as LumiBreadcrumbSeparator, Button as LumiButton, Calendar as LumiCalendar, Card as LumiCard, Checkbox$1 as LumiCheckbox, Crud as LumiCrud, CurrencyDisplay as LumiCurrencyDisplay, Dashboard as LumiDashboard, DashboardNavbar as LumiDashboardNavbar, DashboardSidebar as LumiDashboardSidebar, DashboardWorkspace as LumiDashboardWorkspace, DateDisplay as LumiDateDisplay, DateInput$1 as LumiDateInput, Drawer as LumiDrawer, DropdownMenu as LumiDropdownMenu, DynamicForm as LumiDynamicForm, FieldValue as LumiFieldValue, Filter as LumiFilter, FilterRow as LumiFilterRow, Checkbox as LumiFormCheckbox, DateInput as LumiFormDateInput, FormDrawer as LumiFormDrawer, Input as LumiFormInput, Select as LumiFormSelect, TimeInput as LumiFormTimeInput, Icon as LumiIcon, Input$1 as LumiInput, Loader as LumiLoader, Menu as LumiMenu, MenuItem as LumiMenuItem, MenuItemGroup as LumiMenuItemGroup, Notification as LumiNotification, Pagination as LumiPagination, Popover as LumiPopover, QRCode as LumiQRCode, RecordCard as LumiRecordCard, Select$1 as LumiSelect, StepIndicator as LumiStepIndicator, Stepper as LumiStepper, SubMenu as LumiSubMenu, Table as LumiTable, Tabs as LumiTabs, TextArea as LumiTextArea, TimeInput$1 as LumiTimeInput, Tooltip as LumiTooltip, MapView, PhotoPicker, ReactiveCrud, ServiceShortcuts, ServicesMap, SessionExpiryPrompt, SupportRequestForm, UserTools, chatEventBus, clearChatComponents, createDeepPropertySubscriber, createEventBus, createStore, createStoreMerger, deepMerge, disabledReasonFor, fetchViaEventBus, getLastFleetSnapshot, matchesDisabledWhen, matchesDoneWhen, matchesVisibleWhen, registerChatComponents, setLastFleetSnapshot, useChatConfig, useReactiveCrud };
25836
+ export { ActionFormDrawer, BottomSheet, CHAT_CONFIG_DEFAULTS, CHAT_EVENT, ICON_TYPES as CHAT_ICON_TYPES, CarouselDisplay, Chat, AssistantMessage as ChatAssistantMessage, AssistantThinkingIndicator as ChatAssistantThinkingIndicator, AttachmentPreview as ChatAttachmentPreview, Avatar as ChatAvatar, Button$1 as ChatButton, ChatConfigProvider, DateDivider as ChatDateDivider, FileViewer as ChatFileViewer, ChatFloatingActions, FullscreenViewer as ChatFullscreenViewer, ChatHeader as ChatHeaderComponent, Icon$1 as ChatIcon, Input$2 as ChatInput, ChatInput as ChatInputComponent, Link as ChatLink, Loader$1 as ChatLoader, Logo as ChatLogo, MessageStatus as ChatMessageStatus, Modal as ChatModal, ChatNavigator, Select$2 as ChatSelect, SelectMenu as ChatSelectMenu, StructuredContent as ChatStructuredContent, Text as ChatText, Textarea as ChatTextarea, UserAttachments as ChatUserAttachments, UserMessage as ChatUserMessage, ChatWidget, CredentialsCard, DEFAULT_PHONE_COUNTRY, FileField, BADGE_VARIANTS as LUMI_BADGE_VARIANTS, DEFAULT_TITLES as LUMI_DEFAULT_TITLES, LUMI_ICON_TYPES, LiveIndicator, LocationField, ActionBar as LumiActionBar, Badge as LumiBadge, Base as LumiBase, BaseNavbar as LumiBaseNavbar, BaseWorkspace as LumiBaseWorkspace, Breadcrumb as LumiBreadcrumb, BreadcrumbItem as LumiBreadcrumbItem, BreadcrumbSeparator as LumiBreadcrumbSeparator, Button as LumiButton, Calendar as LumiCalendar, Card as LumiCard, Checkbox$1 as LumiCheckbox, Crud as LumiCrud, CurrencyDisplay as LumiCurrencyDisplay, Dashboard as LumiDashboard, DashboardNavbar as LumiDashboardNavbar, DashboardSidebar as LumiDashboardSidebar, DashboardWorkspace as LumiDashboardWorkspace, DateDisplay as LumiDateDisplay, DateInput$1 as LumiDateInput, Drawer as LumiDrawer, DropdownMenu as LumiDropdownMenu, DynamicForm as LumiDynamicForm, FieldValue as LumiFieldValue, Filter as LumiFilter, FilterRow as LumiFilterRow, Checkbox as LumiFormCheckbox, DateInput as LumiFormDateInput, FormDrawer as LumiFormDrawer, Input as LumiFormInput, Select as LumiFormSelect, TimeInput as LumiFormTimeInput, Icon as LumiIcon, Input$1 as LumiInput, Loader as LumiLoader, Menu as LumiMenu, MenuItem as LumiMenuItem, MenuItemGroup as LumiMenuItemGroup, Notification as LumiNotification, Pagination as LumiPagination, PhoneInput as LumiPhoneInput, Popover as LumiPopover, QRCode as LumiQRCode, RecordCard as LumiRecordCard, Select$1 as LumiSelect, SheetSelect as LumiSheetSelect, StepIndicator as LumiStepIndicator, Stepper as LumiStepper, SubMenu as LumiSubMenu, Table as LumiTable, Tabs as LumiTabs, TextArea as LumiTextArea, TimeInput$1 as LumiTimeInput, Tooltip as LumiTooltip, MapView, PHONE_COUNTRIES, PhotoPicker, ReactiveCrud, SANITIZE_PRESETS, ServiceShortcuts, ServicesMap, SessionExpiryPrompt, SupportRequestForm, UserTools, chatEventBus, clearChatComponents, createDeepPropertySubscriber, createEventBus, createStore, createStoreMerger, deepMerge, disabledReasonFor, fetchViaEventBus, flagOf, getLastFleetSnapshot, matchesDisabledWhen, matchesDoneWhen, matchesVisibleWhen, registerChatComponents, sanitize, setLastFleetSnapshot, splitPhone, useChatConfig, useReactiveCrud };