@sesionario/blocks 1.8.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use client";
2
2
  import * as React6 from 'react';
3
- import { createContext, useContext, useState, useRef, useEffect, useLayoutEffect, useCallback, useMemo } from 'react';
3
+ import { createContext, useContext, useState, useRef, useEffect, useLayoutEffect, useCallback, useId, useMemo } from 'react';
4
4
  import { ChevronsUpDown, CheckIcon, Smile, SearchIcon, Search, Clock, Flag, Hash, Lightbulb, Trophy, Plane, Apple, Leaf, Hand, Loader2, AlertTriangle, Inbox, X, ChevronLeft, ChevronRight, Monitor, Sun, Moon, Building2, Check, Plus, Languages, Upload, Move, ZoomOut, ZoomIn, RotateCcw, RotateCw, Grid3X3, RefreshCw, User, Pencil, Play, AlertCircle, VolumeX, Pause, Volume1, Volume2, Settings, PictureInPicture2, Minimize, Maximize, BadgeCheck, ArrowDownIcon, MessageCircleDashedIcon, MessageCircle, XIcon } from 'lucide-react';
5
5
  import { clsx } from 'clsx';
6
6
  import { twMerge } from 'tailwind-merge';
@@ -1380,7 +1380,7 @@ function LanguageSwitcher({
1380
1380
  const sizes = sizeClasses2[size];
1381
1381
  const shapeClass = shapeClasses2[shape];
1382
1382
  const reduceMotion = useReducedMotion();
1383
- const defaultLabels4 = {
1383
+ const defaultLabels5 = {
1384
1384
  language: labels.language ?? "Language"
1385
1385
  };
1386
1386
  if (variant === "mini") {
@@ -1390,7 +1390,7 @@ function LanguageSwitcher({
1390
1390
  {
1391
1391
  variant: "ghost",
1392
1392
  size: "icon",
1393
- "aria-label": defaultLabels4.language,
1393
+ "aria-label": defaultLabels5.language,
1394
1394
  className: cn(sizes.buttonMini, shapeClass, className),
1395
1395
  children: /* @__PURE__ */ jsx(Languages, { className: sizes.iconMini })
1396
1396
  }
@@ -4317,6 +4317,18 @@ function useDebouncedValueStrict(value, delayMs) {
4317
4317
  }, [value, delayMs]);
4318
4318
  return debounced;
4319
4319
  }
4320
+ function useMediaQuery2(query) {
4321
+ const [matches, setMatches] = useState(false);
4322
+ useEffect(() => {
4323
+ if (typeof window === "undefined" || !window.matchMedia) return;
4324
+ const mql = window.matchMedia(query);
4325
+ const onChange = () => setMatches(mql.matches);
4326
+ onChange();
4327
+ mql.addEventListener("change", onChange);
4328
+ return () => mql.removeEventListener("change", onChange);
4329
+ }, [query]);
4330
+ return matches;
4331
+ }
4320
4332
  function useSearchHotkey(options = {}) {
4321
4333
  const { defaultOpen = false, disabled = false } = options;
4322
4334
  const [open, setOpen] = useState(defaultOpen);
@@ -4334,6 +4346,22 @@ function useSearchHotkey(options = {}) {
4334
4346
  }, [disabled]);
4335
4347
  return { open, setOpen, toggle };
4336
4348
  }
4349
+
4350
+ // src/components/search/fuzzy.ts
4351
+ function normalize(value) {
4352
+ return value.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
4353
+ }
4354
+ function fuzzyMatch(query, target) {
4355
+ const q = normalize(query.trim());
4356
+ if (!q) return true;
4357
+ const t = normalize(target);
4358
+ if (t.includes(q)) return true;
4359
+ let qi = 0;
4360
+ for (let ti = 0; ti < t.length && qi < q.length; ti++) {
4361
+ if (t[ti] === q[qi]) qi++;
4362
+ }
4363
+ return qi === q.length;
4364
+ }
4337
4365
  function Command({
4338
4366
  className,
4339
4367
  ...props
@@ -4451,6 +4479,19 @@ function CommandGroup({
4451
4479
  }
4452
4480
  );
4453
4481
  }
4482
+ function CommandSeparator({
4483
+ className,
4484
+ ...props
4485
+ }) {
4486
+ return /* @__PURE__ */ jsx(
4487
+ Command$1.Separator,
4488
+ {
4489
+ "data-slot": "command-separator",
4490
+ className: cn("-mx-1 h-px bg-border", className),
4491
+ ...props
4492
+ }
4493
+ );
4494
+ }
4454
4495
  function CommandItem({
4455
4496
  className,
4456
4497
  ...props
@@ -4467,23 +4508,584 @@ function CommandItem({
4467
4508
  }
4468
4509
  );
4469
4510
  }
4470
-
4471
- // src/components/search/fuzzy.ts
4472
- function normalize(value) {
4473
- return value.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "");
4511
+ function OptionRow({
4512
+ entry,
4513
+ selected,
4514
+ onSelect,
4515
+ renderOption
4516
+ }) {
4517
+ return /* @__PURE__ */ jsxs(
4518
+ CommandItem,
4519
+ {
4520
+ value: entry.value,
4521
+ keywords: [entry.label],
4522
+ onSelect,
4523
+ "data-checked": selected || void 0,
4524
+ children: [
4525
+ renderOption ? renderOption(entry.item, { selected }) : /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: entry.label }),
4526
+ /* @__PURE__ */ jsx(
4527
+ CheckIcon,
4528
+ {
4529
+ className: cn(
4530
+ "ml-auto size-4 shrink-0",
4531
+ selected ? "opacity-100" : "opacity-0"
4532
+ )
4533
+ }
4534
+ )
4535
+ ]
4536
+ },
4537
+ entry.value
4538
+ );
4474
4539
  }
4475
- function fuzzyMatch(query, target) {
4476
- const q = normalize(query.trim());
4477
- if (!q) return true;
4478
- const t = normalize(target);
4479
- if (t.includes(q)) return true;
4480
- let qi = 0;
4481
- for (let ti = 0; ti < t.length && qi < q.length; ti++) {
4482
- if (t[ti] === q[qi]) qi++;
4483
- }
4484
- return qi === q.length;
4540
+ function SearchablePickerList({
4541
+ query,
4542
+ onQueryChange,
4543
+ labels,
4544
+ isLoading,
4545
+ hasError,
4546
+ recommended,
4547
+ recent,
4548
+ results,
4549
+ selectedValues,
4550
+ mode,
4551
+ allowEmpty,
4552
+ emptyLabel,
4553
+ onSelectEmpty,
4554
+ onSelectItem,
4555
+ renderOption,
4556
+ createOption,
4557
+ onLoadMore,
4558
+ hasMore,
4559
+ isLoadingMore,
4560
+ listClassName
4561
+ }) {
4562
+ const hasPinned = recommended.length > 0 || recent.length > 0;
4563
+ const hasResults = results.length > 0;
4564
+ const showEmpty = !isLoading && !hasError && !hasPinned && !hasResults && !(allowEmpty && mode === "single");
4565
+ return /* @__PURE__ */ jsxs(Command, { shouldFilter: false, className: "flex h-full min-h-0 flex-col", children: [
4566
+ /* @__PURE__ */ jsx(
4567
+ CommandInput,
4568
+ {
4569
+ placeholder: labels.searchPlaceholder,
4570
+ value: query,
4571
+ onValueChange: onQueryChange
4572
+ }
4573
+ ),
4574
+ /* @__PURE__ */ jsxs(CommandList, { className: cn("min-h-0 flex-1", listClassName), children: [
4575
+ isLoading ? /* @__PURE__ */ jsxs(
4576
+ "div",
4577
+ {
4578
+ className: "flex items-center justify-center gap-2 py-6 text-sm text-muted-foreground",
4579
+ role: "status",
4580
+ children: [
4581
+ /* @__PURE__ */ jsx(Loader2, { className: "size-4 animate-spin", "aria-hidden": true }),
4582
+ labels.loading
4583
+ ]
4584
+ }
4585
+ ) : null,
4586
+ hasError && !isLoading ? /* @__PURE__ */ jsx(
4587
+ "div",
4588
+ {
4589
+ className: "py-6 text-center text-sm text-destructive",
4590
+ role: "alert",
4591
+ children: labels.error
4592
+ }
4593
+ ) : null,
4594
+ showEmpty ? /* @__PURE__ */ jsx(CommandEmpty, { children: labels.empty }) : null,
4595
+ allowEmpty && mode === "single" && !query.trim() ? /* @__PURE__ */ jsx(CommandGroup, { children: /* @__PURE__ */ jsxs(
4596
+ CommandItem,
4597
+ {
4598
+ value: "__empty__",
4599
+ onSelect: () => onSelectEmpty?.(),
4600
+ "data-checked": !selectedValues.size || void 0,
4601
+ children: [
4602
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-muted-foreground", children: emptyLabel }),
4603
+ /* @__PURE__ */ jsx(
4604
+ CheckIcon,
4605
+ {
4606
+ className: cn(
4607
+ "ml-auto size-4 shrink-0",
4608
+ selectedValues.size === 0 ? "opacity-100" : "opacity-0"
4609
+ )
4610
+ }
4611
+ )
4612
+ ]
4613
+ }
4614
+ ) }) : null,
4615
+ recommended.length > 0 ? /* @__PURE__ */ jsx(CommandGroup, { heading: labels.recommended, children: recommended.map((entry) => /* @__PURE__ */ jsx(
4616
+ OptionRow,
4617
+ {
4618
+ entry,
4619
+ selected: selectedValues.has(entry.value),
4620
+ onSelect: () => onSelectItem(entry.value),
4621
+ renderOption
4622
+ },
4623
+ `rec-${entry.value}`
4624
+ )) }) : null,
4625
+ recent.length > 0 ? /* @__PURE__ */ jsx(CommandGroup, { heading: labels.recent, children: recent.map((entry) => /* @__PURE__ */ jsx(
4626
+ OptionRow,
4627
+ {
4628
+ entry,
4629
+ selected: selectedValues.has(entry.value),
4630
+ onSelect: () => onSelectItem(entry.value),
4631
+ renderOption
4632
+ },
4633
+ `recent-${entry.value}`
4634
+ )) }) : null,
4635
+ hasPinned && hasResults ? /* @__PURE__ */ jsx(CommandSeparator, {}) : null,
4636
+ hasResults ? /* @__PURE__ */ jsx(CommandGroup, { heading: hasPinned ? labels.results : void 0, children: results.map((entry) => /* @__PURE__ */ jsx(
4637
+ OptionRow,
4638
+ {
4639
+ entry,
4640
+ selected: selectedValues.has(entry.value),
4641
+ onSelect: () => onSelectItem(entry.value),
4642
+ renderOption
4643
+ },
4644
+ `res-${entry.value}`
4645
+ )) }) : null,
4646
+ hasMore && onLoadMore ? /* @__PURE__ */ jsx("div", { className: "p-2", children: /* @__PURE__ */ jsx(
4647
+ Button,
4648
+ {
4649
+ type: "button",
4650
+ variant: "ghost",
4651
+ size: "sm",
4652
+ className: "w-full",
4653
+ disabled: isLoadingMore,
4654
+ onClick: () => void onLoadMore(),
4655
+ children: isLoadingMore ? /* @__PURE__ */ jsxs(Fragment, { children: [
4656
+ /* @__PURE__ */ jsx(Loader2, { className: "size-4 animate-spin", "aria-hidden": true }),
4657
+ labels.loading
4658
+ ] }) : labels.loadMore
4659
+ }
4660
+ ) }) : null,
4661
+ createOption ? /* @__PURE__ */ jsxs(Fragment, { children: [
4662
+ /* @__PURE__ */ jsx(CommandSeparator, {}),
4663
+ /* @__PURE__ */ jsx(CommandGroup, { children: /* @__PURE__ */ jsx(
4664
+ CommandItem,
4665
+ {
4666
+ value: "__create__",
4667
+ onSelect: () => createOption.onSelect(),
4668
+ children: createOption.label
4669
+ }
4670
+ ) })
4671
+ ] }) : null
4672
+ ] })
4673
+ ] });
4485
4674
  }
4486
4675
  var defaultLabels3 = {
4676
+ placeholder: "Seleccionar\u2026",
4677
+ searchPlaceholder: "Buscar\u2026",
4678
+ empty: "No se encontraron resultados",
4679
+ loading: "Cargando\u2026",
4680
+ error: "No se pudo cargar la lista",
4681
+ recommended: "Recomendados",
4682
+ recent: "Recientes",
4683
+ results: "Resultados",
4684
+ done: "Listo",
4685
+ cancel: "Cancelar",
4686
+ clear: "Limpiar",
4687
+ selectedCount: (count) => count === 1 ? "1 seleccionado" : `${count} seleccionados`,
4688
+ emptyOption: "Ninguno",
4689
+ loadMore: "Cargar m\xE1s",
4690
+ dialogTitle: "Seleccionar"
4691
+ };
4692
+ function toListItems(items, getOptionValue, getOptionLabel) {
4693
+ if (!items?.length) return [];
4694
+ return items.map((item) => ({
4695
+ item,
4696
+ value: getOptionValue(item),
4697
+ label: getOptionLabel(item)
4698
+ }));
4699
+ }
4700
+ function dedupeByValue(items, exclude = /* @__PURE__ */ new Set()) {
4701
+ const seen = new Set(exclude);
4702
+ const out = [];
4703
+ for (const entry of items) {
4704
+ if (seen.has(entry.value)) continue;
4705
+ seen.add(entry.value);
4706
+ out.push(entry);
4707
+ }
4708
+ return out;
4709
+ }
4710
+ function matchesQuery(entry, query, getOptionKeywords) {
4711
+ if (!query.trim()) return true;
4712
+ if (fuzzyMatch(query, entry.label)) return true;
4713
+ return getOptionKeywords?.(entry.item)?.some(
4714
+ (keyword) => fuzzyMatch(query, keyword)
4715
+ ) ?? false;
4716
+ }
4717
+ function SearchablePicker(props) {
4718
+ const {
4719
+ options,
4720
+ fetchOptions,
4721
+ getOptionValue,
4722
+ getOptionLabel,
4723
+ getOptionKeywords,
4724
+ renderOption,
4725
+ renderValue,
4726
+ pinned,
4727
+ labels: userLabels,
4728
+ minQueryLength = 0,
4729
+ debounceMs = 200,
4730
+ disabled,
4731
+ open: openProp,
4732
+ onOpenChange,
4733
+ clearable,
4734
+ allowEmpty,
4735
+ emptyLabel,
4736
+ keepOpenOnSelect,
4737
+ maxSelected,
4738
+ createOption,
4739
+ onLoadMore,
4740
+ hasMore,
4741
+ className,
4742
+ triggerClassName: triggerClassName2,
4743
+ id,
4744
+ "aria-labelledby": ariaLabelledBy,
4745
+ "aria-label": ariaLabel
4746
+ } = props;
4747
+ const mode = props.mode ?? "single";
4748
+ const labels = { ...defaultLabels3, ...userLabels };
4749
+ const resolvedEmptyLabel = emptyLabel ?? labels.emptyOption;
4750
+ const isMobile = useMediaQuery2("(max-width: 767px)");
4751
+ const generatedId = useId();
4752
+ const triggerId = id ?? generatedId;
4753
+ const [uncontrolledOpen, setUncontrolledOpen] = useState(false);
4754
+ const open = openProp ?? uncontrolledOpen;
4755
+ const setOpen = useCallback(
4756
+ (next) => {
4757
+ onOpenChange?.(next);
4758
+ if (openProp === void 0) setUncontrolledOpen(next);
4759
+ },
4760
+ [onOpenChange, openProp]
4761
+ );
4762
+ const [query, setQuery] = useState("");
4763
+ const [remoteItems, setRemoteItems] = useState([]);
4764
+ const [isLoading, setIsLoading] = useState(false);
4765
+ const [hasError, setHasError] = useState(false);
4766
+ const [isLoadingMore, setIsLoadingMore] = useState(false);
4767
+ const debouncedQuery = useDebouncedValue(query, debounceMs);
4768
+ const requestIdRef = useRef(0);
4769
+ const knownItemsRef = useRef(/* @__PURE__ */ new Map());
4770
+ const rememberItems = useCallback(
4771
+ (items) => {
4772
+ for (const item of items) {
4773
+ knownItemsRef.current.set(getOptionValue(item), item);
4774
+ }
4775
+ },
4776
+ [getOptionValue]
4777
+ );
4778
+ useEffect(() => {
4779
+ if (options) rememberItems(options);
4780
+ if (pinned?.recommended) rememberItems(pinned.recommended);
4781
+ if (pinned?.recent) rememberItems(pinned.recent);
4782
+ }, [options, pinned, rememberItems]);
4783
+ useEffect(() => {
4784
+ if (!open) {
4785
+ setQuery("");
4786
+ setRemoteItems([]);
4787
+ setHasError(false);
4788
+ setIsLoading(false);
4789
+ }
4790
+ }, [open]);
4791
+ const trimmedDebounced = debouncedQuery.trim();
4792
+ const shouldFetch = Boolean(fetchOptions) && open && trimmedDebounced.length >= minQueryLength && (trimmedDebounced.length > 0 || !options);
4793
+ useEffect(() => {
4794
+ if (!shouldFetch || !fetchOptions) {
4795
+ if (!trimmedDebounced) {
4796
+ setRemoteItems([]);
4797
+ setHasError(false);
4798
+ setIsLoading(false);
4799
+ }
4800
+ return;
4801
+ }
4802
+ const requestId = ++requestIdRef.current;
4803
+ setIsLoading(true);
4804
+ setHasError(false);
4805
+ fetchOptions(trimmedDebounced).then((result) => {
4806
+ if (requestIdRef.current !== requestId) return;
4807
+ setRemoteItems(result);
4808
+ rememberItems(result);
4809
+ }).catch(() => {
4810
+ if (requestIdRef.current !== requestId) return;
4811
+ setRemoteItems([]);
4812
+ setHasError(true);
4813
+ }).finally(() => {
4814
+ if (requestIdRef.current !== requestId) return;
4815
+ setIsLoading(false);
4816
+ });
4817
+ }, [shouldFetch, fetchOptions, trimmedDebounced, rememberItems]);
4818
+ const selectedValues = useMemo(() => {
4819
+ if (mode === "multiple") {
4820
+ const multiValue = props.value ?? [];
4821
+ return new Set(multiValue);
4822
+ }
4823
+ const singleValue = props.value;
4824
+ return singleValue ? /* @__PURE__ */ new Set([singleValue]) : /* @__PURE__ */ new Set();
4825
+ }, [mode, props]);
4826
+ const selectedValueKey = mode === "multiple" ? (props.value ?? []).join("\0") : props.value ?? "";
4827
+ const selectedItems = useMemo(() => {
4828
+ const values = mode === "multiple" ? selectedValueKey ? selectedValueKey.split("\0") : [] : selectedValueKey ? [selectedValueKey] : [];
4829
+ return values.map((value) => knownItemsRef.current.get(value)).filter((item) => item !== void 0);
4830
+ }, [mode, selectedValueKey, options, pinned, remoteItems]);
4831
+ const queryForFilter = query.trim();
4832
+ const recommended = useMemo(() => {
4833
+ if (queryForFilter) return [];
4834
+ const pinnedValues = /* @__PURE__ */ new Set();
4835
+ const items = dedupeByValue(
4836
+ toListItems(pinned?.recommended, getOptionValue, getOptionLabel)
4837
+ );
4838
+ for (const entry of items) pinnedValues.add(entry.value);
4839
+ return items;
4840
+ }, [queryForFilter, pinned?.recommended, getOptionValue, getOptionLabel]);
4841
+ const recent = useMemo(() => {
4842
+ if (queryForFilter) return [];
4843
+ const exclude = new Set(recommended.map((e) => e.value));
4844
+ return dedupeByValue(
4845
+ toListItems(pinned?.recent, getOptionValue, getOptionLabel),
4846
+ exclude
4847
+ );
4848
+ }, [
4849
+ queryForFilter,
4850
+ pinned?.recent,
4851
+ recommended,
4852
+ getOptionValue,
4853
+ getOptionLabel
4854
+ ]);
4855
+ const pinnedValueSet = useMemo(() => {
4856
+ const set = /* @__PURE__ */ new Set();
4857
+ for (const entry of recommended) set.add(entry.value);
4858
+ for (const entry of recent) set.add(entry.value);
4859
+ return set;
4860
+ }, [recommended, recent]);
4861
+ const results = useMemo(() => {
4862
+ const usingRemote = Boolean(fetchOptions) && trimmedDebounced.length >= minQueryLength && (trimmedDebounced.length > 0 || !options);
4863
+ if (usingRemote) {
4864
+ return dedupeByValue(
4865
+ toListItems(remoteItems, getOptionValue, getOptionLabel),
4866
+ queryForFilter ? /* @__PURE__ */ new Set() : pinnedValueSet
4867
+ );
4868
+ }
4869
+ const staticItems = toListItems(options, getOptionValue, getOptionLabel);
4870
+ const filtered = staticItems.filter(
4871
+ (entry) => matchesQuery(entry, queryForFilter, getOptionKeywords)
4872
+ );
4873
+ return dedupeByValue(filtered, queryForFilter ? /* @__PURE__ */ new Set() : pinnedValueSet);
4874
+ }, [
4875
+ fetchOptions,
4876
+ trimmedDebounced,
4877
+ minQueryLength,
4878
+ options,
4879
+ remoteItems,
4880
+ getOptionValue,
4881
+ getOptionLabel,
4882
+ getOptionKeywords,
4883
+ queryForFilter,
4884
+ pinnedValueSet
4885
+ ]);
4886
+ const closeOnSelect = keepOpenOnSelect !== void 0 ? !keepOpenOnSelect : mode === "single";
4887
+ const handleSelectEmpty = useCallback(() => {
4888
+ if (mode === "single") {
4889
+ props.onValueChange?.(
4890
+ null
4891
+ );
4892
+ }
4893
+ if (closeOnSelect) setOpen(false);
4894
+ }, [mode, props, closeOnSelect, setOpen]);
4895
+ const handleSelectItem = useCallback(
4896
+ (value) => {
4897
+ if (mode === "multiple") {
4898
+ const current = props.value ?? [];
4899
+ const onChange = props.onValueChange;
4900
+ const exists = current.includes(value);
4901
+ if (exists) {
4902
+ onChange?.(current.filter((v) => v !== value));
4903
+ } else if (maxSelected !== void 0 && current.length >= maxSelected) {
4904
+ return;
4905
+ } else {
4906
+ onChange?.([...current, value]);
4907
+ }
4908
+ if (closeOnSelect) setOpen(false);
4909
+ return;
4910
+ }
4911
+ props.onValueChange?.(
4912
+ value
4913
+ );
4914
+ if (closeOnSelect) setOpen(false);
4915
+ },
4916
+ [mode, props, maxSelected, closeOnSelect, setOpen]
4917
+ );
4918
+ const handleClear = useCallback(
4919
+ (event) => {
4920
+ event.preventDefault();
4921
+ event.stopPropagation();
4922
+ if (mode === "multiple") {
4923
+ props.onValueChange?.(
4924
+ []
4925
+ );
4926
+ } else {
4927
+ props.onValueChange?.(null);
4928
+ }
4929
+ },
4930
+ [mode, props]
4931
+ );
4932
+ const handleLoadMore = useCallback(async () => {
4933
+ if (!onLoadMore || isLoadingMore) return;
4934
+ setIsLoadingMore(true);
4935
+ try {
4936
+ await onLoadMore();
4937
+ } finally {
4938
+ setIsLoadingMore(false);
4939
+ }
4940
+ }, [onLoadMore, isLoadingMore]);
4941
+ const triggerLabel = useMemo(() => {
4942
+ if (renderValue) {
4943
+ if (mode === "multiple") {
4944
+ return renderValue(selectedItems);
4945
+ }
4946
+ return renderValue(selectedItems[0] ?? null);
4947
+ }
4948
+ if (mode === "multiple") {
4949
+ const count = selectedValues.size;
4950
+ if (count === 0) {
4951
+ return /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: labels.placeholder });
4952
+ }
4953
+ if (selectedItems.length === 1) {
4954
+ return getOptionLabel(selectedItems[0]);
4955
+ }
4956
+ return labels.selectedCount(count);
4957
+ }
4958
+ if (selectedValues.size === 0) {
4959
+ return /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: allowEmpty ? resolvedEmptyLabel : labels.placeholder });
4960
+ }
4961
+ if (selectedItems[0]) {
4962
+ return getOptionLabel(selectedItems[0]);
4963
+ }
4964
+ const only = [...selectedValues][0];
4965
+ return only ?? labels.placeholder;
4966
+ }, [
4967
+ renderValue,
4968
+ mode,
4969
+ selectedItems,
4970
+ selectedValues,
4971
+ labels,
4972
+ getOptionLabel,
4973
+ allowEmpty,
4974
+ resolvedEmptyLabel
4975
+ ]);
4976
+ const showClear = clearable && !disabled && (mode === "multiple" ? selectedValues.size > 0 : selectedValues.size > 0);
4977
+ const list = /* @__PURE__ */ jsx(
4978
+ SearchablePickerList,
4979
+ {
4980
+ query,
4981
+ onQueryChange: setQuery,
4982
+ labels,
4983
+ isLoading,
4984
+ hasError,
4985
+ recommended,
4986
+ recent,
4987
+ results,
4988
+ selectedValues,
4989
+ mode,
4990
+ allowEmpty,
4991
+ emptyLabel: resolvedEmptyLabel,
4992
+ onSelectEmpty: handleSelectEmpty,
4993
+ onSelectItem: handleSelectItem,
4994
+ renderOption,
4995
+ createOption,
4996
+ onLoadMore: onLoadMore ? handleLoadMore : void 0,
4997
+ hasMore,
4998
+ isLoadingMore,
4999
+ listClassName: isMobile ? "max-h-[min(50vh,360px)]" : "max-h-72"
5000
+ }
5001
+ );
5002
+ const triggerButton = /* @__PURE__ */ jsxs(
5003
+ Button,
5004
+ {
5005
+ type: "button",
5006
+ variant: "outline",
5007
+ role: "combobox",
5008
+ id: triggerId,
5009
+ "aria-expanded": open,
5010
+ "aria-labelledby": ariaLabelledBy,
5011
+ "aria-label": ariaLabel ?? labels.placeholder,
5012
+ disabled,
5013
+ className: cn("w-full justify-between font-normal", triggerClassName2),
5014
+ children: [
5015
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate text-left", children: triggerLabel }),
5016
+ /* @__PURE__ */ jsx(ChevronsUpDown, { className: "ml-2 size-4 shrink-0 opacity-50", "aria-hidden": true })
5017
+ ]
5018
+ }
5019
+ );
5020
+ const clearButton = showClear ? /* @__PURE__ */ jsx(
5021
+ Button,
5022
+ {
5023
+ type: "button",
5024
+ variant: "ghost",
5025
+ size: "icon-sm",
5026
+ "aria-label": labels.clear,
5027
+ disabled,
5028
+ className: "shrink-0",
5029
+ onClick: handleClear,
5030
+ children: /* @__PURE__ */ jsx(X, { className: "size-4" })
5031
+ }
5032
+ ) : null;
5033
+ if (isMobile) {
5034
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex w-full items-center gap-1", className), children: [
5035
+ /* @__PURE__ */ jsx(
5036
+ "div",
5037
+ {
5038
+ className: "min-w-0 flex-1",
5039
+ onClick: () => {
5040
+ if (!disabled) setOpen(true);
5041
+ },
5042
+ children: triggerButton
5043
+ }
5044
+ ),
5045
+ clearButton,
5046
+ /* @__PURE__ */ jsx(Drawer, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxs(DrawerContent, { className: "max-h-[90vh]", children: [
5047
+ /* @__PURE__ */ jsx(DrawerHeader, { className: "text-left", children: /* @__PURE__ */ jsx(DrawerTitle, { children: labels.dialogTitle }) }),
5048
+ /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-hidden px-2 pb-2", children: list }),
5049
+ mode === "multiple" ? /* @__PURE__ */ jsxs(DrawerFooter, { className: "flex-row gap-2", children: [
5050
+ /* @__PURE__ */ jsx(
5051
+ Button,
5052
+ {
5053
+ type: "button",
5054
+ variant: "outline",
5055
+ className: "flex-1",
5056
+ onClick: () => setOpen(false),
5057
+ children: labels.cancel
5058
+ }
5059
+ ),
5060
+ /* @__PURE__ */ jsx(
5061
+ Button,
5062
+ {
5063
+ type: "button",
5064
+ className: "flex-1",
5065
+ onClick: () => setOpen(false),
5066
+ children: labels.done
5067
+ }
5068
+ )
5069
+ ] }) : null
5070
+ ] }) })
5071
+ ] });
5072
+ }
5073
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex w-full items-center gap-1", className), children: [
5074
+ /* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsxs(Popover, { open, onOpenChange: setOpen, modal: true, children: [
5075
+ /* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: triggerButton }),
5076
+ /* @__PURE__ */ jsx(
5077
+ PopoverContent,
5078
+ {
5079
+ className: "w-[var(--radix-popover-trigger-width)] min-w-[240px] p-0",
5080
+ align: "start",
5081
+ children: list
5082
+ }
5083
+ )
5084
+ ] }) }),
5085
+ clearButton
5086
+ ] });
5087
+ }
5088
+ var defaultLabels4 = {
4487
5089
  placeholder: "Buscar en toda la plataforma\u2026",
4488
5090
  dialogTitle: "Buscar",
4489
5091
  dialogDescription: "Busca funcionalidades, eventos, documentos y m\xE1s",
@@ -4517,7 +5119,7 @@ function SearchCommand({
4517
5119
  debounceMs = 200,
4518
5120
  className
4519
5121
  }) {
4520
- const labels = { ...defaultLabels3, ...userLabels };
5122
+ const labels = { ...defaultLabels4, ...userLabels };
4521
5123
  const [query, setQuery] = useState("");
4522
5124
  const [hits, setHits] = useState([]);
4523
5125
  const [isLoading, setIsLoading] = useState(false);
@@ -5398,18 +6000,6 @@ function ChatMessageList({
5398
6000
  /* @__PURE__ */ jsx(MessageScrollerButton, {})
5399
6001
  ] }) });
5400
6002
  }
5401
- function useMediaQuery2(query) {
5402
- const [matches, setMatches] = useState(false);
5403
- useEffect(() => {
5404
- if (typeof window === "undefined" || !window.matchMedia) return;
5405
- const mql = window.matchMedia(query);
5406
- const onChange = () => setMatches(mql.matches);
5407
- onChange();
5408
- mql.addEventListener("change", onChange);
5409
- return () => mql.removeEventListener("change", onChange);
5410
- }, [query]);
5411
- return matches;
5412
- }
5413
6003
  var RECONNECT_DELAY_MS = 2e3;
5414
6004
  function useSupportConversation({
5415
6005
  client,
@@ -6028,6 +6618,6 @@ function createSupportChatClient(basePath = "/api/chat-svc") {
6028
6618
  };
6029
6619
  }
6030
6620
 
6031
- export { AvatarEditor, AvatarEditorDialog, Bubble, BubbleContent, BubbleGroup, BubbleReactions, ChatMessageList, ConfirmDestructiveDialog, EmojiInput, EmojiPicker, EmojiPickerPopover, EmojiTextarea, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyState, EmptyTitle, ErrorState, ExpandableText, ImageLightbox, LanguageContext, LanguageSwitcher, LoadingState, MEXICO_STATES, MEXICO_STATE_PATHS, Marker, MarkerContent, MarkerIcon, Message, MessageAvatar, MessageContent, MessageFooter, MessageGroup, MessageHeader, MessageScroller, MessageScrollerButton, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport, MexicoMap, OrgSwitcher, PhoneInput, SearchCommand, SupportMessengerProvider, ThemeSwitcher, VerifiedProfessionalBadge, VideoPlayer, avatarFallbackStyle, bubbleVariants, cn, createLiveHlsConfig, createSupportChatClient, createVodHlsConfig, defaultLanguages, describePlaybackError, fuzzyMatch, getAvatarColors, getInitials, insertAtCaret, markerVariants, normalizeEmojiQuery, shouldRetryLiveEdge404, useDebouncedValue, useDebouncedValueStrict, useHlsPlayback, useLanguageContext, usePlaybackStats, useSearchHotkey, useSupportConversation, useSupportMessenger, useSupportMessengerOptional };
6621
+ export { AvatarEditor, AvatarEditorDialog, Bubble, BubbleContent, BubbleGroup, BubbleReactions, ChatMessageList, ConfirmDestructiveDialog, EmojiInput, EmojiPicker, EmojiPickerPopover, EmojiTextarea, Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyState, EmptyTitle, ErrorState, ExpandableText, ImageLightbox, LanguageContext, LanguageSwitcher, LoadingState, MEXICO_STATES, MEXICO_STATE_PATHS, Marker, MarkerContent, MarkerIcon, Message, MessageAvatar, MessageContent, MessageFooter, MessageGroup, MessageHeader, MessageScroller, MessageScrollerButton, MessageScrollerContent, MessageScrollerItem, MessageScrollerProvider, MessageScrollerViewport, MexicoMap, OrgSwitcher, PhoneInput, SearchCommand, SearchablePicker, SupportMessengerProvider, ThemeSwitcher, VerifiedProfessionalBadge, VideoPlayer, avatarFallbackStyle, bubbleVariants, cn, createLiveHlsConfig, createSupportChatClient, createVodHlsConfig, defaultLanguages, describePlaybackError, fuzzyMatch, getAvatarColors, getInitials, insertAtCaret, markerVariants, normalizeEmojiQuery, shouldRetryLiveEdge404, useDebouncedValue, useDebouncedValueStrict, useHlsPlayback, useLanguageContext, useMediaQuery2 as useMediaQuery, usePlaybackStats, useSearchHotkey, useSupportConversation, useSupportMessenger, useSupportMessengerOptional };
6032
6622
  //# sourceMappingURL=index.js.map
6033
6623
  //# sourceMappingURL=index.js.map