ics-ui-kit 0.1.16 → 0.1.18

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.
Files changed (46) hide show
  1. package/dist/{CheckboxField-2zNFubvm.js → CheckboxField-limFbMk2.js} +43 -43
  2. package/dist/CheckboxField-limFbMk2.js.map +1 -0
  3. package/dist/{Command-D5zgJ7-y.js → Command-B7ZRyW8w.js} +2 -2
  4. package/dist/Command-B7ZRyW8w.js.map +1 -0
  5. package/dist/{FormFooterTemplate-Cfn5Nmge.js → FormFooterTemplate-BRrgrxAu.js} +2 -2
  6. package/dist/{FormFooterTemplate-Cfn5Nmge.js.map → FormFooterTemplate-BRrgrxAu.js.map} +1 -1
  7. package/dist/{InputGroup-BvD9Igmt.js → InputGroup-BcRWP-zL.js} +20 -22
  8. package/dist/InputGroup-BcRWP-zL.js.map +1 -0
  9. package/dist/{Select-MLPTpIl5.js → Select-D9juHX8o.js} +7 -8
  10. package/dist/{Select-MLPTpIl5.js.map → Select-D9juHX8o.js.map} +1 -1
  11. package/dist/{TextInput-Cj50ImXi.js → TextInput-Db0ylY91.js} +2 -2
  12. package/dist/{TextInput-Cj50ImXi.js.map → TextInput-Db0ylY91.js.map} +1 -1
  13. package/dist/blocks/auth/otp-form.js +1 -1
  14. package/dist/components/checkbox.js +1 -1
  15. package/dist/components/command.js +1 -1
  16. package/dist/components/dialog.js +1 -1
  17. package/dist/components/drawer.js +1 -1
  18. package/dist/components/form.js +1 -1
  19. package/dist/components/image-uploader.js +8 -8
  20. package/dist/components/image-uploader.js.map +1 -1
  21. package/dist/components/input.js +5 -5
  22. package/dist/components/radio-group.js +10 -10
  23. package/dist/components/radio-group.js.map +1 -1
  24. package/dist/components/search-select.js +40 -40
  25. package/dist/components/search-select.js.map +1 -1
  26. package/dist/components/select/Select.d.ts +0 -3
  27. package/dist/components/select.js +1 -1
  28. package/dist/components/sidebar.js +1 -1
  29. package/dist/components/table/tree.js +1 -1
  30. package/dist/components/table.js +1 -1
  31. package/dist/components/tag-input.js +2 -2
  32. package/dist/components/textarea.js +1 -1
  33. package/dist/{inputBaseStyles-DbzD_jvq.js → inputBaseStyles-BfZIWuQ6.js} +5 -5
  34. package/dist/inputBaseStyles-BfZIWuQ6.js.map +1 -0
  35. package/dist/styles-scoped.css +93 -132
  36. package/dist/styles.css +93 -132
  37. package/dist/theme.css +4 -12
  38. package/dist/{treeModel-jvOXFZvK.js → treeModel-BlJWP4sc.js} +2 -2
  39. package/dist/treeModel-BlJWP4sc.js.map +1 -0
  40. package/package.json +1 -1
  41. package/tailwind.preset.js +10 -14
  42. package/dist/CheckboxField-2zNFubvm.js.map +0 -1
  43. package/dist/Command-D5zgJ7-y.js.map +0 -1
  44. package/dist/InputGroup-BvD9Igmt.js.map +0 -1
  45. package/dist/inputBaseStyles-DbzD_jvq.js.map +0 -1
  46. package/dist/treeModel-jvOXFZvK.js.map +0 -1
@@ -2,10 +2,10 @@ import { jsx as e, jsxs as D, Fragment as q } from "react/jsx-runtime";
2
2
  import F, { useState as w, useCallback as x, useEffect as A, forwardRef as ee, useMemo as M, useRef as H } from "react";
3
3
  import { T as Q } from "../index-BVqs-uqP.js";
4
4
  import { u as K, S as fe } from "../SearchSelectTag-CA7Ie3Nx.js";
5
- import { b as Se, g as re, C as te, c as ne, e as ge, i as ve } from "../Command-D5zgJ7-y.js";
5
+ import { b as Se, g as re, C as te, c as ne, e as ge, i as ve } from "../Command-B7ZRyW8w.js";
6
6
  import { I as j } from "../Icon-DH3ev9GK.js";
7
7
  import { b as ye, P as _, a as $ } from "../Popover-CRVD7AtB.js";
8
- import { m as Ce, s as be } from "../Select-MLPTpIl5.js";
8
+ import { m as be, s as Ce } from "../Select-D9juHX8o.js";
9
9
  import { C as Ne } from "../chevron-down-CAOItu8X.js";
10
10
  import { C as ae } from "../check-CeyaOoZv.js";
11
11
  import { L as se } from "../Loader-BpHiL6W-.js";
@@ -61,7 +61,7 @@ const Te = ({
61
61
  }), le = ({ children: r, className: t }) => /* @__PURE__ */ e("span", { className: De({ className: t }), children: r }), Re = Q({
62
62
  base: "pointer-events-none self-center pl-1.5 text-muted"
63
63
  }), Ve = ({ children: r, className: t }) => /* @__PURE__ */ e("span", { className: Re({ className: t }), children: r }), Pe = Q({
64
- extend: be,
64
+ extend: Ce,
65
65
  base: "group/search-select-trigger min-h-10 items-start py-[0.3125rem] pl-1.5 pr-3 lg:min-h-9 lg:py-[0.3125rem] lg:pl-1.5 lg:pr-2.5",
66
66
  slots: {
67
67
  buttonWrapper: "ml-auto flex gap-2.5 pl-2.5",
@@ -87,8 +87,8 @@ const Te = ({
87
87
  c && /* @__PURE__ */ e("div", { className: i.startIcon(), children: c }),
88
88
  t !== void 0 ? t : /* @__PURE__ */ e(Ve, { children: l }),
89
89
  /* @__PURE__ */ D("div", { className: i.buttonWrapper(), children: [
90
- f && /* @__PURE__ */ e("div", { className: i.iconWrapper(), children: /* @__PURE__ */ e(Ce, { onClear: f, className: i.clearButton() }) }),
91
- !n && /* @__PURE__ */ e("div", { className: i.iconWrapper(), children: /* @__PURE__ */ e(j, { icon: Ne, className: i.icon() }) })
90
+ f && /* @__PURE__ */ e("div", { className: i.iconWrapper(), children: /* @__PURE__ */ e(be, { onClear: f, className: i.clearButton() }) }),
91
+ /* @__PURE__ */ e("div", { className: i.iconWrapper(), children: /* @__PURE__ */ e(j, { icon: Ne, className: i.icon() }) })
92
92
  ] })
93
93
  ]
94
94
  }
@@ -119,7 +119,7 @@ const Ee = Q({ base: "" }), oe = ee(
119
119
  onChange: d,
120
120
  onClear: u,
121
121
  disabled: S,
122
- invalid: b,
122
+ invalid: C,
123
123
  searchPlaceholder: v = "Найти",
124
124
  emptyText: g = "Результатов не найдено",
125
125
  shouldFilter: p = !0,
@@ -129,7 +129,7 @@ const Ee = Q({ base: "" }), oe = ee(
129
129
  startIcon: R,
130
130
  hideSearch: L,
131
131
  ...V
132
- } = r, [P, C] = w(!1), [T, N] = w(""), { selectedValue: E, selectedOption: W, setSelectedByLabel: J } = Te({
132
+ } = r, [P, b] = w(!1), [T, N] = w(""), { selectedValue: E, selectedOption: W, setSelectedByLabel: J } = Te({
133
133
  options: s,
134
134
  value: o,
135
135
  defaultValue: h,
@@ -137,9 +137,9 @@ const Ee = Q({ base: "" }), oe = ee(
137
137
  onChange: d
138
138
  }), U = x(
139
139
  (O) => {
140
- J(O), C(!1);
140
+ J(O), b(!1);
141
141
  },
142
- [J, C]
142
+ [J, b]
143
143
  ), de = x(
144
144
  (O) => {
145
145
  N(O), y?.(O);
@@ -147,7 +147,7 @@ const Ee = Q({ base: "" }), oe = ee(
147
147
  [y]
148
148
  ), ue = x(
149
149
  (O) => {
150
- C(O), I?.(O);
150
+ b(O), I?.(O);
151
151
  },
152
152
  [I]
153
153
  ), X = M(() => {
@@ -195,7 +195,7 @@ const Ee = Q({ base: "" }), oe = ee(
195
195
  {
196
196
  onClear: X ? u : void 0,
197
197
  disabled: S,
198
- invalid: b,
198
+ invalid: C,
199
199
  open: P,
200
200
  placeholder: f,
201
201
  id: n,
@@ -261,7 +261,7 @@ const Ae = (r, t) => {
261
261
  const y = c || l;
262
262
  y && !u && S(n.find((I) => I.value === y));
263
263
  }, [l, c, n, u]);
264
- const { visibleOptions: b, hasMoreItems: v } = M(() => {
264
+ const { visibleOptions: C, hasMoreItems: v } = M(() => {
265
265
  const y = i ? n.map((L) => ({
266
266
  option: L,
267
267
  score: s(L.label, i)
@@ -285,7 +285,7 @@ const Ae = (r, t) => {
285
285
  {
286
286
  ...f,
287
287
  ref: t,
288
- options: b,
288
+ options: C,
289
289
  value: c,
290
290
  defaultValue: l,
291
291
  valueOption: u,
@@ -309,15 +309,15 @@ const ke = ({ loadOptions: r }) => {
309
309
  const u = ++o.current, S = new AbortController();
310
310
  f.current = S, s("loading"), c(null);
311
311
  try {
312
- const b = await r({
312
+ const C = await r({
313
313
  searchQuery: d,
314
314
  signal: S.signal
315
315
  });
316
316
  if (u !== o.current) return;
317
- n(b.options), s("success");
318
- } catch (b) {
319
- if (b instanceof Error && b.name === "AbortError" || u !== o.current) return;
320
- c(b instanceof Error ? b.message : "Неизвестная ошибка"), s("error");
317
+ n(C.options), s("success");
318
+ } catch (C) {
319
+ if (C instanceof Error && C.name === "AbortError" || u !== o.current) return;
320
+ c(C instanceof Error ? C.message : "Неизвестная ошибка"), s("error");
321
321
  }
322
322
  },
323
323
  [r, h]
@@ -349,7 +349,7 @@ const ke = ({ loadOptions: r }) => {
349
349
  index: g,
350
350
  isSelected: a?.(v) ?? !1,
351
351
  isDisabled: v.disabled ?? !1
352
- })), [r, a]), b = x(
352
+ })), [r, a]), C = x(
353
353
  ({
354
354
  option: v,
355
355
  isSelected: g,
@@ -381,7 +381,7 @@ const ke = ({ loadOptions: r }) => {
381
381
  value: v.label,
382
382
  onSelect: m ? void 0 : f,
383
383
  disabled: m,
384
- children: b({
384
+ children: C({
385
385
  option: v,
386
386
  isSelected: p,
387
387
  isDisabled: m,
@@ -405,7 +405,7 @@ const ke = ({ loadOptions: r }) => {
405
405
  onSelect: d,
406
406
  isSelected: u,
407
407
  hideSearch: S
408
- } = r, [b, v] = w(""), g = Oe(b, s), { options: p, loadingState: m, error: y, loadData: I } = ke({
408
+ } = r, [C, v] = w(""), g = Oe(C, s), { options: p, loadingState: m, error: y, loadData: I } = ke({
409
409
  loadOptions: t
410
410
  }), R = M(() => n === "auto" ? !0 : n === "input" ? g.length >= a : !1, [n, g, a]);
411
411
  A(() => {
@@ -450,7 +450,7 @@ const ke = ({ loadOptions: r }) => {
450
450
  startIcon: o,
451
451
  onClear: h,
452
452
  ...i
453
- } = r, [d, u] = w(!1), [S, b] = K({
453
+ } = r, [d, u] = w(!1), [S, C] = K({
454
454
  value: a,
455
455
  defaultValue: s,
456
456
  onChange: f
@@ -465,9 +465,9 @@ const ke = ({ loadOptions: r }) => {
465
465
  }
466
466
  }, [S, t]), g = x(
467
467
  (m) => {
468
- m && b(m), u(!1);
468
+ m && C(m), u(!1);
469
469
  },
470
- [b, u]
470
+ [C, u]
471
471
  ), p = x(
472
472
  (m) => S?.value === m.value,
473
473
  [S]
@@ -502,27 +502,27 @@ const ke = ({ loadOptions: r }) => {
502
502
  renderOption: d,
503
503
  startIcon: u,
504
504
  portalContainer: S,
505
- ...b
505
+ ...C
506
506
  } = r, [v, g] = w(!1), [p, m] = K({
507
507
  value: a,
508
508
  defaultValue: s,
509
509
  onChange: l
510
510
  }), y = x(
511
- (C) => {
512
- if (C) {
513
- const T = p?.find((N) => N.value === C.value);
514
- m(T ? (N) => N?.filter((E) => E.value !== C.value) || [] : (N) => [...N || [], C]);
511
+ (b) => {
512
+ if (b) {
513
+ const T = p?.find((N) => N.value === b.value);
514
+ m(T ? (N) => N?.filter((E) => E.value !== b.value) || [] : (N) => [...N || [], b]);
515
515
  }
516
516
  o || g(!1);
517
517
  },
518
518
  [p, o, m, g]
519
519
  ), I = x(
520
- (C) => {
521
- p?.find((N) => N.value === C.value) && m((N) => N?.filter((E) => E.value !== C.value) || []);
520
+ (b) => {
521
+ p?.find((N) => N.value === b.value) && m((N) => N?.filter((E) => E.value !== b.value) || []);
522
522
  },
523
523
  [p, m]
524
524
  ), R = x(
525
- (C) => p?.some((T) => T.value === C.value) ?? !1,
525
+ (b) => p?.some((T) => T.value === b.value) ?? !1,
526
526
  [p]
527
527
  ), { handleKeyDown: L, isFocused: V } = we({
528
528
  items: p || [],
@@ -530,13 +530,13 @@ const ke = ({ loadOptions: r }) => {
530
530
  onDelete: I
531
531
  }), P = M(() => {
532
532
  if (!(!p || p.length === 0))
533
- return p.map((C, T) => {
533
+ return p.map((b, T) => {
534
534
  if (d) {
535
535
  const N = d({
536
- option: C,
536
+ option: b,
537
537
  type: "trigger",
538
538
  onClose: () => {
539
- I(C);
539
+ I(b);
540
540
  }
541
541
  });
542
542
  if (N !== void 0)
@@ -546,19 +546,19 @@ const ke = ({ loadOptions: r }) => {
546
546
  fe,
547
547
  {
548
548
  onLabelClick: (N) => {
549
- N.preventDefault(), i?.(C);
549
+ N.preventDefault(), i?.(b);
550
550
  },
551
551
  onClose: (N) => {
552
- N.preventDefault(), I(C);
552
+ N.preventDefault(), I(b);
553
553
  },
554
554
  isFocused: V(T),
555
- children: C.label
555
+ children: b.label
556
556
  },
557
- C.value
557
+ b.value
558
558
  );
559
559
  });
560
560
  }, [p, d, I, i, V]);
561
- return /* @__PURE__ */ e("div", { className: t, children: /* @__PURE__ */ D(_, { open: v, onOpenChange: g, ...b, children: [
561
+ return /* @__PURE__ */ e("div", { className: t, children: /* @__PURE__ */ D(_, { open: v, onOpenChange: g, ...C, children: [
562
562
  /* @__PURE__ */ e($, { asChild: !0, children: /* @__PURE__ */ e(
563
563
  k,
564
564
  {
@@ -1 +1 @@
1
- {"version":3,"file":"search-select.js","sources":["../../src/hooks/useSearchSelect.ts","../../src/components/search-select/components/SearchSelectTextValue.tsx","../../src/components/search-select/components/SearchSelectPlaceholder.tsx","../../src/components/search-select/components/SearchSelectTrigger.tsx","../../src/components/search-select/search-select/components/SearchSelectContent.tsx","../../src/components/search-select/search-select/components/SearchSelectInput.tsx","../../src/components/search-select/search-select/SearchSelect.tsx","../../src/components/search-select/search-select/components/LoadMoreTrigger.tsx","../../src/components/search-select/search-select/utils/fuzzyFilter.ts","../../src/components/search-select/search-select/LazySearchSelect.tsx","../../src/components/search-select/search-select/components/SearchSelectSeparator.tsx","../../src/components/search-select/async-search-select/hooks/useAsyncDataLoader.ts","../../src/components/search-select/async-search-select/components/AsyncSearchSelectContent.tsx","../../src/components/search-select/async-search-select/components/AsyncSearchSelectPopoverContent.tsx","../../src/components/search-select/async-search-select/AsyncSearchSelect.tsx","../../src/components/search-select/multi-select/MultiSelect.tsx"],"sourcesContent":["import { useCallback, useState, useEffect } from \"react\";\nimport { useControllableState } from \"./useControllableState\";\n\nexport interface SearchSelectOption {\n\t/** Уникальный идентификатор опции */\n\tvalue: string | number;\n\t/** Отображаемый текст */\n\tlabel: string;\n\t/** Состояние отключения опции */\n\tdisabled?: boolean;\n}\n\ninterface UseSearchSelectProps<T extends SearchSelectOption = SearchSelectOption> {\n\t/** Список опций */\n\toptions: T[];\n\t/** Текущее выбранное значение (controlled режим) */\n\tvalue?: T[\"value\"];\n\t/** Значение по умолчанию (uncontrolled режим) */\n\tdefaultValue?: T[\"value\"];\n\t/** Callback при выборе опции */\n\tonChange?: (value: T[\"value\"], option: T) => void;\n\t/**\n\t * Значение по умолчанию для выбранной опции. Используется, когда выбранная опция\n\t * отсутствует в текущем списке options. Это может произойти при изменении фильтра\n\t * или при использовании виртуальной (ленивой) загрузки данных.\n\t * */\n\tvalueOption?: T;\n}\n\nexport const useSearchSelect = <T extends SearchSelectOption = SearchSelectOption>({\n\toptions,\n\tvalue,\n\tdefaultValue,\n\tonChange,\n\tvalueOption\n}: UseSearchSelectProps<T>) => {\n\t// Сохраняем выбранную опцию отдельно, чтобы она не терялась при фильтрации\n\tconst [selectedOption, setSelectedOption] = useState<T | undefined>(undefined);\n\n\tconst memoizedOnChange = useCallback(\n\t\t(newValue: T[\"value\"] | undefined) => {\n\t\t\tif (newValue !== undefined) {\n\t\t\t\tconst option = options.find((option) => option.value === newValue) || selectedOption;\n\t\t\t\tif (option && option.value === newValue) {\n\t\t\t\t\tsetSelectedOption(option);\n\t\t\t\t\tonChange?.(newValue, option);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[onChange, options, selectedOption]\n\t);\n\n\tconst [selectedValue, setSelectedValue] = useControllableState<T[\"value\"] | undefined>({\n\t\tvalue,\n\t\tdefaultValue,\n\t\tonChange: memoizedOnChange\n\t});\n\n\t// Синхронизируем selectedOption с selectedValue при изменении selectedValue или options\n\tuseEffect(() => {\n\t\tif (selectedValue !== undefined) {\n\t\t\t// Если selectedOption уже соответствует selectedValue, ничего не делаем\n\t\t\tif (selectedOption && selectedOption.value === selectedValue) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Ищем опцию в текущих options\n\t\t\tconst currentOption = options.find((option) => option.value === selectedValue);\n\t\t\tif (currentOption) {\n\t\t\t\tsetSelectedOption(currentOption);\n\t\t\t} else if (valueOption && valueOption.value === selectedValue) {\n\t\t\t\tsetSelectedOption(valueOption);\n\t\t\t}\n\t\t} else {\n\t\t\tsetSelectedOption(undefined);\n\t\t}\n\t}, [selectedValue, options, selectedOption, valueOption]);\n\n\tconst setSelectedByLabel = useCallback(\n\t\t(label: string) => {\n\t\t\t// CommandItem работает с label, а не с value, поэтому нужно найти опцию по label\n\t\t\tconst option = options.find((option) => option.label === label);\n\t\t\tif (option) {\n\t\t\t\tsetSelectedValue(option.value);\n\t\t\t}\n\t\t},\n\t\t[setSelectedValue, options]\n\t);\n\n\treturn {\n\t\tselectedValue,\n\t\tselectedOption,\n\t\tsetSelectedByLabel,\n\t\tsetSelectedValue\n\t};\n};\n","import React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nconst searchSelectTextValueStyles = tv({\n\tbase: \"self-center pl-1.5\"\n});\n\ninterface SearchSelectTextValueProps {\n\tchildren: React.ReactNode;\n\tclassName?: string;\n}\n\nexport const SearchSelectTextValue: React.FC<SearchSelectTextValueProps> = ({ children, className }) => {\n\treturn <span className={searchSelectTextValueStyles({ className })}>{children}</span>;\n};\n","import React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nconst searchSelectPlaceholderStyles = tv({\n\tbase: \"pointer-events-none self-center pl-1.5 text-muted\"\n});\n\ninterface SearchSelectPlaceholderProps {\n\tchildren: React.ReactNode;\n\tclassName?: string;\n}\n\nexport const SearchSelectPlaceholder: React.FC<SearchSelectPlaceholderProps> = ({ children, className }) => {\n\treturn <span className={searchSelectPlaceholderStyles({ className })}>{children}</span>;\n};\n","import { Icon } from \"@/components/icon/Icon\";\nimport { selectTriggerStyles } from \"@/components/select/Select\";\nimport { ChevronDownIcon } from \"lucide-react\";\nimport React from \"react\";\nimport { tv } from \"tailwind-variants\";\nimport { SearchSelectPlaceholder } from \"./SearchSelectPlaceholder\";\nimport { SelectTriggerClearButton } from \"@/components/select/components/SelectTriggerClearButton\";\n\nconst searchSelectTriggerStyles = tv({\n\textend: selectTriggerStyles,\n\tbase: \"group/search-select-trigger min-h-10 items-start py-[0.3125rem] pl-1.5 pr-3 lg:min-h-9 lg:py-[0.3125rem] lg:pl-1.5 lg:pr-2.5\",\n\tslots: {\n\t\tbuttonWrapper: \"ml-auto flex gap-2.5 pl-2.5\",\n\t\ticonWrapper: \"min-h-7 lg:min-h-6\",\n\t\tstartIcon: \"flex min-h-7 items-center pl-1.5 pr-0.5 text-muted lg:min-h-6\",\n\t\tclearButton:\n\t\t\t\"h-auto p-0 opacity-0 group-hover/search-select-trigger:opacity-100 group-focus-visible/search-select-trigger:opacity-100\"\n\t}\n});\n\ninterface SearchSelectTriggerProps extends React.ComponentPropsWithoutRef<\"button\"> {\n\t/** Состояние отключения */\n\tdisabled?: boolean;\n\t/** Состояние ошибки */\n\tinvalid?: boolean;\n\t/** Текст placeholder */\n\tplaceholder?: string;\n\t/** Состояние открытия. Используется для проставления accessibility аттрибутов */\n\topen?: boolean;\n\t/** Иконка, отображаемая в начале текстового поля */\n\tstartIcon?: React.ReactNode;\n\t/** Callback при очистке значения */\n\tonClear?: () => void;\n}\n\n/**\n * Компонент отображения триггера для SearchSelect.\n * Выполняет роль кнопки, которая открывает Popover с опциями.\n * Может отображать значение или placeholder в зависимости от наличия дочерних элементов.\n * Не содержит сам триггер, а только стилизует кнопку.\n */\nexport const SearchSelectTrigger = React.forwardRef<HTMLButtonElement, SearchSelectTriggerProps>(\n\t({ className, children, disabled, open, invalid, placeholder, startIcon, onClear, ...props }, ref) => {\n\t\tconst styles = searchSelectTriggerStyles({ disabled, invalid });\n\n\t\treturn (\n\t\t\t<button\n\t\t\t\t{...props}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tclassName={styles.base({ className })}\n\t\t\t\tref={ref}\n\t\t\t\trole=\"combobox\"\n\t\t\t\taria-expanded={open}\n\t\t\t\taria-invalid={invalid}\n\t\t\t\taria-haspopup=\"listbox\"\n\t\t\t>\n\t\t\t\t{startIcon && <div className={styles.startIcon()}>{startIcon}</div>}\n\t\t\t\t{children !== undefined ? children : <SearchSelectPlaceholder>{placeholder}</SearchSelectPlaceholder>}\n\t\t\t\t<div className={styles.buttonWrapper()}>\n\t\t\t\t\t{onClear && (\n\t\t\t\t\t\t<div className={styles.iconWrapper()}>\n\t\t\t\t\t\t\t<SelectTriggerClearButton onClear={onClear} className={styles.clearButton()} />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t\t{!disabled && (\n\t\t\t\t\t\t<div className={styles.iconWrapper()}>\n\t\t\t\t\t\t\t<Icon icon={ChevronDownIcon} className={styles.icon()} />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t</div>\n\t\t\t</button>\n\t\t);\n\t}\n);\n\nSearchSelectTrigger.displayName = \"SearchSelectTrigger\";\n","import { PopoverContent } from \"@/components/popover\";\nimport React, { ComponentPropsWithoutRef } from \"react\";\nimport { tv } from \"tailwind-variants\";\n\ntype SearchSelectContentProps = ComponentPropsWithoutRef<typeof PopoverContent>;\n\nconst searchSelectContentStyles = tv({\n\tbase: \"w-full min-w-[var(--radix-popper-anchor-width)] border-secondary-border p-0\"\n});\n\n/**\n * Контейнер содержимого для SearchSelect.\n * Обертка вокруг PopoverContent с настроенными стилями и интеграцией с Command.\n * Планируется рефакторинг для вынесения input логики.\n */\nexport const SearchSelectContent = React.forwardRef<React.ElementRef<typeof PopoverContent>, SearchSelectContentProps>(\n\t({ className, children, ...props }, ref) => {\n\t\treturn (\n\t\t\t<PopoverContent ref={ref} className={searchSelectContentStyles({ className })} align=\"start\" {...props}>\n\t\t\t\t{children}\n\t\t\t</PopoverContent>\n\t\t);\n\t}\n);\n\nSearchSelectContent.displayName = \"SearchSelectContent\";\n","import { CommandInput } from \"@/components/command/Command\";\nimport { Command as CommandPrimitive } from \"cmdk\";\nimport React from \"react\";\n\nexport const SearchSelectInput = React.forwardRef<\n\tReact.ElementRef<typeof CommandPrimitive.Input>,\n\tReact.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>\n>(({ placeholder = \"Find\", ...props }, ref) => {\n\treturn <CommandInput ref={ref} placeholder={placeholder} {...props} />;\n});\n\nSearchSelectInput.displayName = \"SearchSelectInput\";\n","import { CheckIcon } from \"lucide-react\";\nimport { ComponentPropsWithoutRef, forwardRef, useCallback, useMemo, useState } from \"react\";\nimport { tv } from \"tailwind-variants\";\nimport { SearchSelectOption, useSearchSelect } from \"../../../hooks/useSearchSelect\";\nimport { Command, CommandEmpty, CommandItem, CommandList } from \"../../command/Command\";\nimport { Icon } from \"../../icon/Icon\";\nimport { Popover, PopoverTrigger } from \"../../popover\";\nimport { SearchSelectTextValue } from \"../components/SearchSelectTextValue\";\nimport { SearchSelectTrigger } from \"../components/SearchSelectTrigger\";\nimport { SearchSelectContent } from \"./components/SearchSelectContent\";\nimport { SearchSelectInput } from \"./components/SearchSelectInput\";\n\nconst searchSelectStyles = tv({ base: \"\" });\n\nexport type RenderOptionProps<T extends SearchSelectOption = SearchSelectOption> = {\n\t/** Отображаемая опция */\n\toption: T;\n} & (RenderOptionInTriggerProps | RenderOptionInListProps);\n\nexport type RenderOptionInTriggerProps = {\n\t/** Тип рендера. Если `trigger`, то опция рендерится в триггере в качестве текущего значения компонента. */\n\ttype: \"trigger\";\n};\n\nexport type RenderOptionInListProps = {\n\t/** Тип рендера. Если `list`, то опция рендерится в списке опций. */\n\ttype: \"list\";\n\t/** Выбрана ли опция в данный момент */\n\tisSelected: boolean;\n\t/** Отключена ли опция */\n\tisDisabled: boolean;\n\t/** Текущий поисковый запрос для подсветки совпадений */\n\tsearchQuery: string;\n\t/** Индекс элемента в списке */\n\tindex: number;\n};\n\ntype PopoverProps = ComponentPropsWithoutRef<typeof Popover>;\nexport interface SearchSelectProps<T extends SearchSelectOption = SearchSelectOption>\n\textends Omit<PopoverProps, \"children\"> {\n\t/** Идентификатор поля в форме. Позволяет связать компонент с полем формы. */\n\tid?: string;\n\t/** Событие blur */\n\tonBlur?: (e: React.FocusEvent<HTMLButtonElement>) => void;\n\t/** Дополнительные классы для контейнера */\n\tclassName?: string;\n\t/** Список опций */\n\toptions: T[];\n\t/** Значение по умолчанию для выбранной опции. Используется, когда выбранная опция\n\t * отсутствует в текущем списке options. Это может произойти при изменении фильтра\n\t * или при использовании виртуальной (ленивой) загрузки данных.\n\t * */\n\tvalueOption?: T;\n\t/**\n\t * Кастомная функция рендера опции.\n\t * Используется для отображения как в trigger (type: \"trigger\"), так и в списке (type: \"list\").\n\t */\n\trenderOption?: (props: RenderOptionProps<T>) => React.ReactNode;\n\t/** Текст placeholder, отображается когда ничего не выбрано */\n\tplaceholder?: string;\n\t/** Текущее выбранное значение (controlled режим) */\n\tvalue?: T[\"value\"];\n\t/** Значение по умолчанию (uncontrolled режим) */\n\tdefaultValue?: T[\"value\"];\n\t/** Callback при выборе опции */\n\tonChange?: (value: T[\"value\"], option: T) => void;\n\t/** Callback при очистке значения */\n\tonClear?: () => void;\n\t/** Состояние отключения */\n\tdisabled?: boolean;\n\t/** Состояние ошибки */\n\tinvalid?: boolean;\n\t/** Текст placeholder для поиска */\n\tsearchPlaceholder?: string;\n\t/** Текст для пустого состояния */\n\temptyText?: string;\n\t/** Использовать встроенную фильтрацию cmdk. По умолчанию true */\n\tshouldFilter?: boolean;\n\t/** Контент, отображаемый в конце списка (например, для триггера загрузки) */\n\tfooterContent?: React.ReactNode;\n\t/** Callback при изменении поискового запроса */\n\tonSearchChange?: (value: string) => void;\n\t/** Callback при изменении состояния открытия */\n\tonOpenChange?: (open: boolean) => void;\n\t/** Иконка, отображаемая в начале поля */\n\tstartIcon?: React.ReactNode;\n\t/** Скрыть поле поиска */\n\thideSearch?: boolean;\n}\n\nexport const SearchSelect = forwardRef(\n\t<T extends SearchSelectOption = SearchSelectOption>(\n\t\tprops: SearchSelectProps<T>,\n\t\tref: React.ForwardedRef<HTMLButtonElement>\n\t) => {\n\t\tconst {\n\t\t\tid,\n\t\t\tclassName,\n\t\t\toptions,\n\t\t\tvalueOption,\n\t\t\trenderOption,\n\t\t\tplaceholder = \"Выберите значение\",\n\t\t\tvalue,\n\t\t\tdefaultValue,\n\t\t\tonBlur,\n\t\t\tonChange,\n\t\t\tonClear,\n\t\t\tdisabled,\n\t\t\tinvalid,\n\t\t\tsearchPlaceholder = \"Найти\",\n\t\t\temptyText = \"Результатов не найдено\",\n\t\t\tshouldFilter = true,\n\t\t\tfooterContent,\n\t\t\tonSearchChange,\n\t\t\tonOpenChange,\n\t\t\tstartIcon,\n\t\t\thideSearch,\n\t\t\t...popoverProps\n\t\t} = props;\n\n\t\tconst [open, setOpen] = useState(false);\n\t\tconst [searchQuery, setSearchQuery] = useState(\"\");\n\n\t\tconst { selectedValue, selectedOption, setSelectedByLabel } = useSearchSelect({\n\t\t\toptions,\n\t\t\tvalue,\n\t\t\tdefaultValue,\n\t\t\tvalueOption,\n\t\t\tonChange\n\t\t});\n\n\t\tconst handleSelect = useCallback(\n\t\t\t(label: string) => {\n\t\t\t\tsetSelectedByLabel(label);\n\t\t\t\tsetOpen(false);\n\t\t\t},\n\t\t\t[setSelectedByLabel, setOpen]\n\t\t);\n\n\t\tconst handleSearchChange = useCallback(\n\t\t\t(value: string) => {\n\t\t\t\tsetSearchQuery(value);\n\t\t\t\tonSearchChange?.(value);\n\t\t\t},\n\t\t\t[onSearchChange]\n\t\t);\n\n\t\tconst handleOpenChange = useCallback(\n\t\t\t(open: boolean) => {\n\t\t\t\tsetOpen(open);\n\t\t\t\tonOpenChange?.(open);\n\t\t\t},\n\t\t\t[onOpenChange]\n\t\t);\n\n\t\tconst displayValue = useMemo(() => {\n\t\t\tif (!selectedOption) return undefined;\n\t\t\tif (renderOption) {\n\t\t\t\tconst item = renderOption({ option: selectedOption, type: \"trigger\" });\n\t\t\t\tif (item !== undefined) {\n\t\t\t\t\treturn item;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn <SearchSelectTextValue>{selectedOption.label}</SearchSelectTextValue>;\n\t\t}, [selectedOption, renderOption]);\n\n\t\tconst renderedOptions = useMemo(() => {\n\t\t\treturn options.map((option, index) => {\n\t\t\t\tconst isDisabled = option.disabled ?? false;\n\t\t\t\tconst isSelected = selectedValue === option.value;\n\n\t\t\t\tconst renderOptionItem = () => {\n\t\t\t\t\tif (renderOption) {\n\t\t\t\t\t\tconst customRender = renderOption({\n\t\t\t\t\t\t\toption,\n\t\t\t\t\t\t\ttype: \"list\",\n\t\t\t\t\t\t\tisSelected,\n\t\t\t\t\t\t\tisDisabled,\n\t\t\t\t\t\t\tsearchQuery,\n\t\t\t\t\t\t\tindex\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (customRender !== undefined) {\n\t\t\t\t\t\t\treturn customRender;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t{option.label}\n\t\t\t\t\t\t\t{isSelected && <Icon icon={CheckIcon} className=\"ml-auto\" />}\n\t\t\t\t\t\t</>\n\t\t\t\t\t);\n\t\t\t\t};\n\n\t\t\t\treturn (\n\t\t\t\t\t<CommandItem\n\t\t\t\t\t\tkey={option.value}\n\t\t\t\t\t\tvalue={option.label}\n\t\t\t\t\t\tonSelect={isDisabled ? undefined : handleSelect}\n\t\t\t\t\t\tdisabled={isDisabled}\n\t\t\t\t\t>\n\t\t\t\t\t\t{renderOptionItem()}\n\t\t\t\t\t</CommandItem>\n\t\t\t\t);\n\t\t\t});\n\t\t}, [options, selectedValue, handleSelect, renderOption, searchQuery]);\n\n\t\treturn (\n\t\t\t<Popover {...popoverProps} open={open} onOpenChange={handleOpenChange}>\n\t\t\t\t<div className={searchSelectStyles({ className })}>\n\t\t\t\t\t<PopoverTrigger asChild>\n\t\t\t\t\t\t<SearchSelectTrigger\n\t\t\t\t\t\t\tonClear={displayValue ? onClear : undefined}\n\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\tinvalid={invalid}\n\t\t\t\t\t\t\topen={open}\n\t\t\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t\t\tid={id}\n\t\t\t\t\t\t\tonBlur={onBlur}\n\t\t\t\t\t\t\tref={ref}\n\t\t\t\t\t\t\tstartIcon={startIcon}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{displayValue}\n\t\t\t\t\t\t</SearchSelectTrigger>\n\t\t\t\t\t</PopoverTrigger>\n\t\t\t\t\t<SearchSelectContent>\n\t\t\t\t\t\t<Command shouldFilter={shouldFilter}>\n\t\t\t\t\t\t\t{!hideSearch && (\n\t\t\t\t\t\t\t\t<SearchSelectInput placeholder={searchPlaceholder} onValueChange={handleSearchChange} />\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t<CommandList key={`list-${searchQuery}`} className=\"p-1\">\n\t\t\t\t\t\t\t\t{renderedOptions}\n\t\t\t\t\t\t\t\t<CommandEmpty>{emptyText}</CommandEmpty>\n\t\t\t\t\t\t\t\t{footerContent}\n\t\t\t\t\t\t\t</CommandList>\n\t\t\t\t\t\t</Command>\n\t\t\t\t\t</SearchSelectContent>\n\t\t\t\t</div>\n\t\t\t</Popover>\n\t\t);\n\t}\n) as (<T extends SearchSelectOption = SearchSelectOption>(\n\tprops: SearchSelectProps<T> & { ref?: React.ForwardedRef<HTMLButtonElement> }\n) => React.ReactElement) & { displayName?: string };\n\nSearchSelect.displayName = \"SearchSelect\";\n","import { Loader } from \"@/components/loader\";\nimport React, { useEffect, useRef } from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nconst loadMoreTriggerStyles = tv({\n\tbase: \"py-2 text-center text-sm text-muted-foreground\"\n});\n\nexport interface LoadMoreTriggerProps {\n\t/** Callback, который вызывается когда триггер становится видимым */\n\tonLoad: () => void;\n\t/** Есть ли еще элементы для загрузки */\n\thasMore: boolean;\n\t/** Текст индикатора загрузки */\n\tloadingText?: string;\n\t/** Дополнительные CSS классы */\n\tclassName?: string;\n}\n\n/**\n * Компонент для автоматической загрузки дополнительных элементов при прокрутке.\n * Отображает индикатор загрузки и автоматически вызывает `onLoad` когда пользователь\n * доскроллит до этого элемента.\n */\nexport const LoadMoreTrigger = React.forwardRef<HTMLDivElement, LoadMoreTriggerProps>(\n\t({ onLoad, hasMore, loadingText = \"Загрузка...\", className }, ref) => {\n\t\tconst triggerRef = useRef<HTMLDivElement>(null);\n\t\tconst styles = loadMoreTriggerStyles({ className });\n\n\t\tReact.useImperativeHandle(ref, () => triggerRef.current as HTMLDivElement);\n\n\t\tuseEffect(() => {\n\t\t\tconst trigger = triggerRef.current;\n\t\t\tif (!trigger || !hasMore) return;\n\n\t\t\tconst observer = new IntersectionObserver(\n\t\t\t\t([entry]) => {\n\t\t\t\t\tif (entry.isIntersecting) {\n\t\t\t\t\t\tonLoad();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{ rootMargin: \"50px\" }\n\t\t\t);\n\n\t\t\tobserver.observe(trigger);\n\n\t\t\treturn () => {\n\t\t\t\tobserver.disconnect();\n\t\t\t};\n\t\t}, [onLoad, hasMore]);\n\n\t\tif (!hasMore) return null;\n\n\t\treturn (\n\t\t\t<div ref={triggerRef} className={styles}>\n\t\t\t\t<Loader className=\"flex-row\">{loadingText}</Loader>\n\t\t\t</div>\n\t\t);\n\t}\n);\n\nLoadMoreTrigger.displayName = \"LoadMoreTrigger\";\n","/**\n * Простой fuzzy filter для поиска\n * Возвращает число от 0 до 3, где большее число означает лучшее совпадение\n */\nexport const defaultFuzzyFilter = (value: string, search: string): number => {\n\tif (!search.trim()) return 1; // Пустой поиск - показываем все\n\n\tconst valueLower = value.toLowerCase().trim();\n\tconst searchLower = search.toLowerCase().trim();\n\n\t// Точное совпадение с началом - наивысший приоритет\n\tif (valueLower.startsWith(searchLower)) return 3;\n\n\t// Содержит подстроку - высокий приоритет\n\tif (valueLower.includes(searchLower)) return 2;\n\n\t// Fuzzy match - проверяем, что все символы поиска есть в правильном порядке\n\tlet searchIndex = 0;\n\tfor (let i = 0; i < valueLower.length && searchIndex < searchLower.length; i++) {\n\t\tif (valueLower[i] === searchLower[searchIndex]) {\n\t\t\tsearchIndex++;\n\t\t}\n\t}\n\n\t// Если нашли все символы поиска в правильном порядке - низкий приоритет\n\treturn searchIndex === searchLower.length ? 1 : 0;\n};\n\n/**\n * Тип функции фильтрации\n */\nexport type FilterFunction = (value: string, search: string) => number;\n","import { forwardRef, useCallback, useEffect, useMemo, useState } from \"react\";\nimport { SearchSelect, SearchSelectProps } from \"./SearchSelect\";\nimport { SearchSelectOption } from \"../../../hooks/useSearchSelect\";\nimport { LoadMoreTrigger } from \"./components/LoadMoreTrigger\";\nimport { defaultFuzzyFilter, FilterFunction } from \"./utils/fuzzyFilter\";\n\nexport interface LazySearchSelectProps<T extends SearchSelectOption = SearchSelectOption>\n\textends Omit<\n\t\tSearchSelectProps<T>,\n\t\t\"options\" | \"shouldFilter\" | \"footerContent\" | \"onSearchChange\" | \"valueOption\"\n\t> {\n\t/** Полный список опций */\n\toptions: T[];\n\t/** Количество элементов на странице */\n\tpageSize?: number;\n\t/** Кастомная функция фильтрации. По умолчанию используется встроенный fuzzy search */\n\tfilter?: FilterFunction;\n}\n\nexport const LazySearchSelect = forwardRef<HTMLButtonElement, LazySearchSelectProps>(\n\t<T extends SearchSelectOption = SearchSelectOption>(\n\t\tprops: LazySearchSelectProps<T>,\n\t\tref: React.ForwardedRef<HTMLButtonElement>\n\t) => {\n\t\tconst {\n\t\t\toptions,\n\t\t\tpageSize = 50,\n\t\t\tfilter = defaultFuzzyFilter,\n\t\t\tdefaultValue,\n\t\t\tvalue,\n\t\t\t...searchSelectProps\n\t\t} = props;\n\n\t\tconst [visibleCount, setVisibleCount] = useState(pageSize);\n\t\tconst [searchQuery, setSearchQuery] = useState(\"\");\n\t\tconst [valueOption, setValueOption] = useState<T | undefined>(undefined);\n\n\t\t// При изменении поиска сбрасываем счетчик видимых элементов\n\t\tuseEffect(() => setVisibleCount(pageSize), [searchQuery, pageSize]);\n\n\t\tuseEffect(() => {\n\t\t\tconst currentValue = value || defaultValue;\n\t\t\tif (currentValue && !valueOption) {\n\t\t\t\tsetValueOption(options.find((option) => option.value === currentValue));\n\t\t\t}\n\t\t}, [defaultValue, value, options, valueOption]);\n\n\t\t// Фильтрация и ограничение элементов\n\t\tconst { visibleOptions, hasMoreItems } = useMemo(() => {\n\t\t\t// Сначала фильтруем и ранжируем по поисковому запросу\n\t\t\tconst filteredAndRanked = searchQuery\n\t\t\t\t? options\n\t\t\t\t\t\t.map((option) => ({\n\t\t\t\t\t\t\toption,\n\t\t\t\t\t\t\tscore: filter(option.label, searchQuery)\n\t\t\t\t\t\t}))\n\t\t\t\t\t\t.filter(({ score }) => score > 0) // Убираем элементы с нулевым скором\n\t\t\t\t\t\t.sort((a, b) => b.score - a.score) // Сортируем по убыванию скора\n\t\t\t\t\t\t.map(({ option }) => option)\n\t\t\t\t: options;\n\n\t\t\t// Затем ограничиваем количество видимых элементов\n\t\t\tconst visible = filteredAndRanked.slice(0, visibleCount);\n\t\t\tconst hasMore = visibleCount < filteredAndRanked.length;\n\n\t\t\treturn {\n\t\t\t\tvisibleOptions: visible,\n\t\t\t\thasMoreItems: hasMore\n\t\t\t};\n\t\t}, [options, searchQuery, visibleCount, filter]);\n\n\t\t// Обработчик загрузки следующей порции\n\t\tconst handleLoadMore = useCallback(() => {\n\t\t\tsetVisibleCount((prev) => prev + pageSize);\n\t\t}, [pageSize]);\n\n\t\tconst handleSearchChange = useCallback((value: string) => {\n\t\t\tsetSearchQuery(value);\n\t\t}, []);\n\n\t\t// Сброс поиска при открытии\n\t\tconst handleOpenChange = useCallback(\n\t\t\t(open: boolean) => {\n\t\t\t\tif (open && searchQuery) setSearchQuery(\"\");\n\t\t\t},\n\t\t\t[searchQuery, setSearchQuery]\n\t\t);\n\n\t\treturn (\n\t\t\t<SearchSelect<T>\n\t\t\t\t{...searchSelectProps}\n\t\t\t\tref={ref}\n\t\t\t\toptions={visibleOptions}\n\t\t\t\tvalue={value}\n\t\t\t\tdefaultValue={defaultValue}\n\t\t\t\tvalueOption={valueOption}\n\t\t\t\tshouldFilter={false}\n\t\t\t\tfooterContent={<LoadMoreTrigger onLoad={handleLoadMore} hasMore={hasMoreItems} />}\n\t\t\t\tonSearchChange={handleSearchChange}\n\t\t\t\tonOpenChange={handleOpenChange}\n\t\t\t/>\n\t\t);\n\t}\n) as (<T extends SearchSelectOption = SearchSelectOption>(\n\tprops: LazySearchSelectProps<T> & { ref?: React.ForwardedRef<HTMLButtonElement> }\n) => React.ReactElement) & { displayName?: string };\n\nLazySearchSelect.displayName = \"LazySearchSelect\";\n","import React from \"react\";\nimport { CommandSeparator } from \"@/components/command/Command\";\nimport { ComponentPropsWithoutRef } from \"react\";\nimport { Command as CommandPrimitive } from \"cmdk\";\n\ntype SearchSelectSeparatorProps = ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>;\n\n/**\n * Разделитель для SearchSelect.\n * Простая обертка вокруг CommandSeparator.\n */\nexport const SearchSelectSeparator = React.forwardRef<\n\tReact.ElementRef<typeof CommandPrimitive.Separator>,\n\tSearchSelectSeparatorProps\n>((props, ref) => {\n\treturn <CommandSeparator ref={ref} {...props} />;\n});\n\nSearchSelectSeparator.displayName = \"SearchSelectSeparator\";\n","import { useCallback, useEffect, useRef, useState } from \"react\";\n\nexport type LoadingState = \"idle\" | \"loading\" | \"success\" | \"error\";\n\nexport interface LoadOptionsParams {\n\tsearchQuery: string;\n\tsignal?: AbortSignal;\n}\n\nexport interface LoadOptionsResult<T> {\n\toptions: T[];\n}\n\ninterface UseAsyncDataLoaderOptions<T> {\n\t/** Функция загрузки данных */\n\tloadOptions: (params: LoadOptionsParams) => Promise<LoadOptionsResult<T>>;\n}\n\ninterface UseAsyncDataLoaderReturn<T> {\n\t/** Текущие загруженные элементы */\n\toptions: T[];\n\t/** Состояние загрузки */\n\tloadingState: LoadingState;\n\t/** Текст ошибки, если загрузка не удалась */\n\terror: string | null;\n\t/** Функция загрузки данных */\n\tloadData: (query: string) => Promise<void>;\n\t/** Функция отмены текущих запросов */\n\tcancelRequests: () => void;\n}\n\n/**\n * Хук для асинхронной загрузки данных с защитой от race conditions\n *\n * Решает следующие проблемы:\n * - Race conditions при быстром вводе пользователя\n * - Мерцание интерфейса из-за множественных запросов\n * - Неправильный порядок получения ответов от сервера\n * - Обработка отмены запросов при размонтировании компонента\n *\n * @example\n * ```tsx\n * const { options, loadingState, loadData } = useAsyncDataLoader({\n * loadOptions: async ({ searchQuery }) => {\n * const response = await fetch(`/api/search?q=${searchQuery}`);\n * return response.json();\n * }\n * });\n *\n * // Загрузить данные\n * loadData(\"search query\");\n * ```\n */\nexport const useAsyncDataLoader = <T>({ loadOptions }: UseAsyncDataLoaderOptions<T>): UseAsyncDataLoaderReturn<T> => {\n\tconst [options, setItems] = useState<T[]>([]);\n\tconst [loadingState, setLoadingState] = useState<LoadingState>(\"idle\");\n\tconst [error, setError] = useState<string | null>(null);\n\n\t// Refs для управления race conditions\n\tconst abortControllerRef = useRef<AbortController | null>(null);\n\tconst requestSequenceRef = useRef(0);\n\n\t// Функция для отмены предыдущих запросов\n\tconst cancelRequests = useCallback(() => {\n\t\tif (abortControllerRef.current) {\n\t\t\tabortControllerRef.current.abort();\n\t\t}\n\t}, []);\n\n\t// Основная функция загрузки данных\n\tconst loadData = useCallback(\n\t\tasync (query: string) => {\n\t\t\t// Отменяем предыдущие запросы\n\t\t\tcancelRequests();\n\n\t\t\t// Увеличиваем sequence для отслеживания порядка\n\t\t\tconst currentSequence = ++requestSequenceRef.current;\n\n\t\t\t// Создаем новый AbortController\n\t\t\tconst abortController = new AbortController();\n\t\t\tabortControllerRef.current = abortController;\n\n\t\t\tsetLoadingState(\"loading\");\n\t\t\tsetError(null);\n\n\t\t\ttry {\n\t\t\t\tconst result = await loadOptions({\n\t\t\t\t\tsearchQuery: query,\n\t\t\t\t\tsignal: abortController.signal\n\t\t\t\t});\n\n\t\t\t\t// Проверяем, что запрос еще актуален\n\t\t\t\tif (currentSequence !== requestSequenceRef.current) return;\n\n\t\t\t\tsetItems(result.options);\n\t\t\t\tsetLoadingState(\"success\");\n\t\t\t} catch (err) {\n\t\t\t\t// Игнорируем AbortError - это нормальная отмена\n\t\t\t\tif (err instanceof Error && err.name === \"AbortError\") return;\n\t\t\t\tif (currentSequence !== requestSequenceRef.current) return;\n\n\t\t\t\tsetError(err instanceof Error ? err.message : \"Неизвестная ошибка\");\n\t\t\t\tsetLoadingState(\"error\");\n\t\t\t}\n\t\t},\n\t\t[loadOptions, cancelRequests]\n\t);\n\n\t// Cleanup при размонтировании компонента\n\tuseEffect(() => {\n\t\treturn () => cancelRequests();\n\t}, [cancelRequests]);\n\n\treturn {\n\t\toptions,\n\t\tloadingState,\n\t\terror,\n\t\tloadData,\n\t\tcancelRequests\n\t};\n};\n","import { EmptyState } from \"@/components/empty-state\";\nimport { ErrorState } from \"@/components/error-state\";\nimport { HintState } from \"@/components/hint-state\";\nimport { Loader } from \"@/components/loader\";\nimport { CheckIcon } from \"lucide-react\";\nimport { useMemo, useCallback } from \"react\";\nimport { CommandItem } from \"../../../command/Command\";\nimport { Icon } from \"../../../icon/Icon\";\nimport type { LoadingState, RenderOptionProps, SearchSelectOption } from \"../types\";\nimport React from \"react\";\n\ninterface AsyncSearchSelectContentProps<T extends SearchSelectOption = SearchSelectOption> {\n\t/** Текущие опции для отображения */\n\toptions: T[];\n\t/** Состояние загрузки */\n\tloadingState: LoadingState;\n\t/** Текст ошибки, если есть */\n\terror: string | null;\n\t/** Функция проверки выбранности элемента */\n\tisSelected?: (value: T) => boolean;\n\t/** Текущий поисковый запрос */\n\tsearchQuery: string;\n\t/** Режим загрузки */\n\tloadMode: \"auto\" | \"input\";\n\t/** Минимальная длина запроса для режима input */\n\tminInputLength: number;\n\t/** Функция обработки выбора опции */\n\tonSelect: (label: string) => void;\n\t/** Кастомная функция рендера опции */\n\trenderOption?: (props: RenderOptionProps<T>) => React.ReactNode;\n\t/** Текст во время загрузки */\n\tloadingText: string;\n\t/** Текст при ошибке загрузки */\n\terrorText: string;\n\t/** Текст подсказки для ввода */\n\tinputHintText: string;\n\t/** Текст для пустого состояния */\n\temptyText: string;\n}\n\n/**\n * Компонент для рендера содержимого AsyncSearchSelect\n *\n * Отвечает за отображение разных состояний:\n * - Загрузка\n * - Ошибка\n * - Подсказка для ввода\n * - Пустое состояние\n * - Список опций\n */\nexport const AsyncSearchSelectContent = <T extends SearchSelectOption = SearchSelectOption>({\n\toptions,\n\tloadingState,\n\terror,\n\tisSelected,\n\tsearchQuery,\n\tloadMode,\n\tminInputLength,\n\tonSelect,\n\trenderOption,\n\tloadingText,\n\terrorText,\n\tinputHintText,\n\temptyText\n}: AsyncSearchSelectContentProps<T>) => {\n\t// Мемоизируем опции с предвычисленным состоянием выбранности\n\tconst optionsWithSelection = useMemo(() => {\n\t\treturn options.map((option, index) => ({\n\t\t\toption,\n\t\t\tindex,\n\t\t\tisSelected: isSelected?.(option) ?? false,\n\t\t\tisDisabled: option.disabled ?? false\n\t\t}));\n\t}, [options, isSelected]);\n\n\tconst renderOptionItem = useCallback(\n\t\t({\n\t\t\toption,\n\t\t\tisSelected: selected,\n\t\t\tisDisabled: disabled,\n\t\t\tindex\n\t\t}: {\n\t\t\toption: T;\n\t\t\tisSelected: boolean;\n\t\t\tisDisabled: boolean;\n\t\t\tindex: number;\n\t\t}) => {\n\t\t\tif (renderOption) {\n\t\t\t\tconst customRender = renderOption({\n\t\t\t\t\toption,\n\t\t\t\t\ttype: \"list\",\n\t\t\t\t\tisSelected: selected,\n\t\t\t\t\tisDisabled: disabled,\n\t\t\t\t\tsearchQuery,\n\t\t\t\t\tindex\n\t\t\t\t});\n\t\t\t\tif (customRender !== undefined) {\n\t\t\t\t\treturn customRender;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn (\n\t\t\t\t<>\n\t\t\t\t\t{option.label}\n\t\t\t\t\t{selected && <Icon icon={CheckIcon} className=\"ml-auto\" />}\n\t\t\t\t</>\n\t\t\t);\n\t\t},\n\t\t[renderOption, searchQuery]\n\t);\n\n\t// Состояние ошибки\n\tif (loadingState === \"error\") {\n\t\treturn <ErrorState className=\"py-6\">{error || errorText}</ErrorState>;\n\t}\n\n\t// Состояние загрузки\n\tif (loadingState === \"loading\") {\n\t\treturn <Loader className=\"py-6\">{loadingText}</Loader>;\n\t}\n\n\t// Подсказка для режима input\n\tif (loadMode === \"input\" && searchQuery.length < minInputLength) {\n\t\treturn <HintState className=\"py-6\">{inputHintText}</HintState>;\n\t}\n\n\t// Пустое состояние\n\tif (options.length === 0 && loadingState === \"success\") {\n\t\treturn <EmptyState className=\"py-6\">{emptyText}</EmptyState>;\n\t}\n\n\t// Список опций\n\treturn (\n\t\t<>\n\t\t\t{optionsWithSelection.map(({ option, index, isSelected: selected, isDisabled: disabled }) => (\n\t\t\t\t<CommandItem\n\t\t\t\t\tkey={option.value}\n\t\t\t\t\tvalue={option.label}\n\t\t\t\t\tonSelect={disabled ? undefined : onSelect}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t>\n\t\t\t\t\t{renderOptionItem({\n\t\t\t\t\t\toption,\n\t\t\t\t\t\tisSelected: selected,\n\t\t\t\t\t\tisDisabled: disabled,\n\t\t\t\t\t\tindex\n\t\t\t\t\t})}\n\t\t\t\t</CommandItem>\n\t\t\t))}\n\t\t</>\n\t);\n};\n","import { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { useDebounce } from \"../../../../hooks/useDebounce\";\nimport { Command, CommandList } from \"../../../command/Command\";\nimport { SearchSelectInput } from \"../../search-select/components/SearchSelectInput\";\nimport { useAsyncDataLoader } from \"../hooks/useAsyncDataLoader\";\nimport type { AsyncSearchSelectProps, SearchSelectOption } from \"../types\";\nimport { AsyncSearchSelectContent } from \"./AsyncSearchSelectContent\";\n\ninterface AsyncSearchSelectPopoverContentProps<T extends SearchSelectOption = SearchSelectOption>\n\textends Pick<\n\t\tAsyncSearchSelectProps<T>,\n\t\t| \"loadOptions\"\n\t\t| \"loadMode\"\n\t\t| \"minInputLength\"\n\t\t| \"debounceMs\"\n\t\t| \"searchPlaceholder\"\n\t\t| \"loadingText\"\n\t\t| \"errorText\"\n\t\t| \"inputHintText\"\n\t\t| \"emptyText\"\n\t\t| \"renderOption\"\n\t\t| \"hideSearch\"\n\t> {\n\tonSelect: (value: T | null) => void;\n\tisSelected?: (value: T) => boolean;\n}\n\nexport const AsyncSearchSelectPopoverContent = <T extends SearchSelectOption = SearchSelectOption>(\n\tprops: AsyncSearchSelectPopoverContentProps<T>\n) => {\n\tconst {\n\t\tloadOptions,\n\t\tloadMode = \"auto\",\n\t\tminInputLength = 3,\n\t\tdebounceMs = 300,\n\t\tsearchPlaceholder = \"Найти\",\n\t\tloadingText = \"Загружаем...\",\n\t\terrorText = \"Ошибка загрузки\",\n\t\tinputHintText = \"Введите текст для поиска\",\n\t\temptyText = \"Результатов не найдено\",\n\t\trenderOption,\n\t\tonSelect,\n\t\tisSelected,\n\t\thideSearch\n\t} = props;\n\n\tconst [searchQuery, setSearchQuery] = useState(\"\");\n\n\t// Дебаунсированный поисковый запрос для загрузки данных\n\tconst debouncedSearchQuery = useDebounce(searchQuery, debounceMs);\n\n\tconst { options, loadingState, error, loadData } = useAsyncDataLoader<T>({\n\t\tloadOptions\n\t});\n\n\tconst shouldLoad = useMemo(() => {\n\t\tif (loadMode === \"auto\") return true;\n\t\tif (loadMode === \"input\") return debouncedSearchQuery.length >= minInputLength;\n\t\treturn false;\n\t}, [loadMode, debouncedSearchQuery, minInputLength]);\n\n\t// Загрузка при изменении условий\n\tuseEffect(() => {\n\t\tif (shouldLoad) loadData(debouncedSearchQuery);\n\t}, [shouldLoad, debouncedSearchQuery, loadData]);\n\n\tconst handleSelect = useCallback(\n\t\t(label: string) => {\n\t\t\tonSelect(options.find((option) => option.label === label) || null);\n\t\t},\n\t\t[onSelect, options]\n\t);\n\n\treturn (\n\t\t<Command shouldFilter={false}>\n\t\t\t{!hideSearch && <SearchSelectInput placeholder={searchPlaceholder} onValueChange={setSearchQuery} />}\n\t\t\t<CommandList key={`list-${debouncedSearchQuery}`} className=\"p-1\">\n\t\t\t\t<AsyncSearchSelectContent\n\t\t\t\t\toptions={options}\n\t\t\t\t\tloadingState={loadingState}\n\t\t\t\t\terror={error}\n\t\t\t\t\tisSelected={isSelected}\n\t\t\t\t\tsearchQuery={debouncedSearchQuery}\n\t\t\t\t\tloadMode={loadMode}\n\t\t\t\t\tminInputLength={minInputLength}\n\t\t\t\t\tonSelect={handleSelect}\n\t\t\t\t\trenderOption={renderOption}\n\t\t\t\t\tloadingText={loadingText}\n\t\t\t\t\terrorText={errorText}\n\t\t\t\t\tinputHintText={inputHintText}\n\t\t\t\t\temptyText={emptyText}\n\t\t\t\t/>\n\t\t\t</CommandList>\n\t\t</Command>\n\t);\n};\n","import { useControllableState } from \"@/hooks/useControllableState\";\nimport { useCallback, useMemo, useState } from \"react\";\nimport { Popover, PopoverTrigger } from \"../../popover\";\nimport { SearchSelectTextValue } from \"../components/SearchSelectTextValue\";\nimport { SearchSelectTrigger } from \"../components/SearchSelectTrigger\";\nimport { SearchSelectContent } from \"../search-select/components/SearchSelectContent\";\nimport { AsyncSearchSelectPopoverContent } from \"./components/AsyncSearchSelectPopoverContent\";\nimport type { AsyncSearchSelectProps, SearchSelectOption } from \"./types\";\n\nexport const AsyncSearchSelect = <T extends SearchSelectOption = SearchSelectOption>(\n\tprops: AsyncSearchSelectProps<T>\n) => {\n\tconst {\n\t\trenderOption,\n\t\tplaceholder = \"Выберите значение\",\n\t\tvalue,\n\t\tdefaultValue,\n\t\tdisabled,\n\t\tinvalid,\n\t\tonChange,\n\t\tstartIcon,\n\t\tonClear,\n\t\t...popoverProps\n\t} = props;\n\n\tconst [open, setOpen] = useState(false);\n\n\tconst [currentOption, setCurrentOption] = useControllableState<T>({\n\t\tvalue,\n\t\tdefaultValue,\n\t\tonChange\n\t});\n\n\tconst displayValue = useMemo(() => {\n\t\tif (!currentOption) return undefined;\n\t\tif (renderOption) {\n\t\t\tconst item = renderOption({ option: currentOption, type: \"trigger\" });\n\t\t\tif (item !== undefined) {\n\t\t\t\treturn item;\n\t\t\t}\n\t\t}\n\t\treturn <SearchSelectTextValue>{currentOption.label}</SearchSelectTextValue>;\n\t}, [currentOption, renderOption]);\n\n\tconst onSelect = useCallback(\n\t\t(option: T | null) => {\n\t\t\tif (option) setCurrentOption(option);\n\t\t\tsetOpen(false);\n\t\t},\n\t\t[setCurrentOption, setOpen]\n\t);\n\n\tconst isSelected = useCallback(\n\t\t(option: T) => {\n\t\t\treturn currentOption?.value === option.value;\n\t\t},\n\t\t[currentOption]\n\t);\n\n\treturn (\n\t\t<Popover {...popoverProps} open={open} onOpenChange={setOpen}>\n\t\t\t<PopoverTrigger asChild>\n\t\t\t\t<SearchSelectTrigger\n\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tinvalid={invalid}\n\t\t\t\t\topen={open}\n\t\t\t\t\tstartIcon={startIcon}\n\t\t\t\t\tonClear={displayValue ? onClear : undefined}\n\t\t\t\t>\n\t\t\t\t\t{displayValue}\n\t\t\t\t</SearchSelectTrigger>\n\t\t\t</PopoverTrigger>\n\t\t\t<SearchSelectContent>\n\t\t\t\t<AsyncSearchSelectPopoverContent {...props} onSelect={onSelect} isSelected={isSelected} />\n\t\t\t</SearchSelectContent>\n\t\t</Popover>\n\t);\n};\n","import { useControllableState } from \"@/hooks/useControllableState\";\nimport { useItemsKeyboardNavigation } from \"@/hooks/useItemsKeyboardNavigation\";\nimport { PopoverProps } from \"@radix-ui/react-popover\";\nimport { useCallback, useMemo, useState } from \"react\";\nimport { SearchSelectOption } from \"../../../hooks/useSearchSelect\";\nimport { Popover, PopoverTrigger } from \"../../popover\";\nimport { AsyncSearchSelectPopoverContent } from \"../async-search-select/components/AsyncSearchSelectPopoverContent\";\nimport { LoadOptionsParams, LoadOptionsResult } from \"../async-search-select/types\";\nimport { SearchSelectTag } from \"../components/SearchSelectTag\";\nimport { SearchSelectTrigger } from \"../components/SearchSelectTrigger\";\nimport { SearchSelectContent } from \"../search-select/components/SearchSelectContent\";\n\n/**\n * Пропсы для рендера опции в trigger (кнопке)\n */\nexport type RenderOptionInTriggerProps = {\n\ttype: \"trigger\";\n\tonClose?: () => void;\n};\n\n/**\n * Пропсы для рендера опции в списке\n */\nexport type RenderOptionInListProps = {\n\ttype: \"list\";\n\t/** Выбрана ли опция в данный момент */\n\tisSelected: boolean;\n\t/** Отключена ли опция */\n\tisDisabled: boolean;\n\t/** Текущий поисковый запрос для подсветки совпадений */\n\tsearchQuery: string;\n\t/** Индекс элемента в списке */\n\tindex: number;\n};\n\n/**\n * Объединенный тип для рендера опции\n */\nexport type RenderOptionProps<T extends SearchSelectOption = SearchSelectOption> = {\n\toption: T;\n} & (RenderOptionInTriggerProps | RenderOptionInListProps);\n\nexport interface MultiSelectProps<T extends SearchSelectOption = SearchSelectOption> {\n\t/** Дополнительные классы для контейнера */\n\tclassName?: string;\n\t/** Флаг для отключения компонента */\n\tdisabled?: boolean;\n\t/** Текст placeholder, отображается когда ничего не выбрано */\n\tplaceholder?: string;\n\t/** Текущие выбранные опции (controlled режим) */\n\tvalue?: T[];\n\t/** Опции по умолчанию (uncontrolled режим) */\n\tdefaultValue?: T[];\n\t/** Callback при изменении выбранных опций */\n\tonChange?: (options: T[]) => void;\n\t/** Callback при очистке значения */\n\tonClear?: () => void;\n\t/** Оставлять поповер открытым после выбора элемента */\n\tkeepOpenOnSelect?: boolean;\n\t/** Обработчик клика по названию выбранного тега */\n\tonLabelClick?: (option: T) => void;\n\t/** Функция загрузки опций */\n\tloadOptions: (params: LoadOptionsParams) => Promise<LoadOptionsResult<T>>;\n\t/** Режим загрузки опций */\n\tloadMode?: \"auto\" | \"input\";\n\t/** Минимальное количество символов для начала загрузки (только для режима \"input\") */\n\tminInputLength?: number;\n\t/** Задержка перед отправкой запроса в миллисекундах (debounce) */\n\tdebounceMs?: number;\n\t/** Текст подсказки для режима \"input\", когда пользователь еще не ввел символы */\n\tinputHintText?: string;\n\t/** Текст во время загрузки */\n\tloadingText?: string;\n\t/** Текст при ошибке загрузки */\n\terrorText?: string;\n\t/** Кастомная функция рендера опции */\n\trenderOption?: (props: RenderOptionProps<T>) => React.ReactNode;\n\t/** Текст placeholder для поиска */\n\tsearchPlaceholder?: string;\n\t/** Текст для пустого состояния */\n\temptyText?: string;\n\t/** Дополнительные пропсы для Popover */\n\tpopoverProps?: PopoverProps;\n\t/** Состояние ошибки */\n\tinvalid?: boolean;\n\t/** Иконка, отображаемая в начале поля */\n\tstartIcon?: React.ReactNode;\n\t/** Скрыть поле поиска */\n\thideSearch?: boolean;\n\t/** Контейнер для портала контента. Если не указан, используется usePortalContainer */\n\tportalContainer?: HTMLElement;\n}\n\n/**\n * Компонент для множественного выбора элементов из списка\n */\nexport const MultiSelect = <T extends SearchSelectOption = SearchSelectOption>(props: MultiSelectProps<T>) => {\n\tconst {\n\t\tclassName,\n\t\tplaceholder = \"Выберите значение\",\n\t\tvalue,\n\t\tdefaultValue,\n\t\tonChange,\n\t\tdisabled,\n\t\tinvalid,\n\t\tkeepOpenOnSelect = true,\n\t\tonClear,\n\t\tonLabelClick,\n\t\trenderOption,\n\t\tstartIcon,\n\t\tportalContainer,\n\t\t...popoverProps\n\t} = props;\n\n\tconst [open, setOpen] = useState(false);\n\n\tconst [selectedOptions, setSelectedOptions] = useControllableState<T[]>({\n\t\tvalue,\n\t\tdefaultValue,\n\t\tonChange\n\t});\n\n\tconst onSelect = useCallback(\n\t\t(option: T | null) => {\n\t\t\tif (option) {\n\t\t\t\tconst isAlreadySelected = selectedOptions?.find((o) => o.value === option.value);\n\t\t\t\tif (isAlreadySelected) {\n\t\t\t\t\tsetSelectedOptions((prev) => {\n\t\t\t\t\t\treturn prev?.filter((o) => o.value !== option.value) || [];\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tsetSelectedOptions((prev) => {\n\t\t\t\t\t\treturn [...(prev || []), option];\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!keepOpenOnSelect) {\n\t\t\t\tsetOpen(false);\n\t\t\t}\n\t\t},\n\t\t[selectedOptions, keepOpenOnSelect, setSelectedOptions, setOpen]\n\t);\n\n\tconst handleClose = useCallback(\n\t\t(option: T) => {\n\t\t\tconst isSelected = selectedOptions?.find((o) => o.value === option.value);\n\t\t\tif (isSelected) {\n\t\t\t\tsetSelectedOptions((prev) => {\n\t\t\t\t\treturn prev?.filter((o) => o.value !== option.value) || [];\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\t[selectedOptions, setSelectedOptions]\n\t);\n\n\tconst isSelected = useCallback(\n\t\t(option: T) => {\n\t\t\treturn selectedOptions?.some((selectedOption) => selectedOption.value === option.value) ?? false;\n\t\t},\n\t\t[selectedOptions]\n\t);\n\n\tconst { handleKeyDown, isFocused } = useItemsKeyboardNavigation({\n\t\titems: selectedOptions || [],\n\t\tonEnter: onLabelClick,\n\t\tonDelete: handleClose\n\t});\n\n\tconst displayValue = useMemo(() => {\n\t\tif (!selectedOptions || selectedOptions.length === 0) return undefined;\n\n\t\treturn selectedOptions.map((option, index) => {\n\t\t\tif (renderOption) {\n\t\t\t\tconst item = renderOption({\n\t\t\t\t\toption,\n\t\t\t\t\ttype: \"trigger\",\n\t\t\t\t\tonClose: () => {\n\t\t\t\t\t\thandleClose(option);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tif (item !== undefined) {\n\t\t\t\t\treturn item;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn (\n\t\t\t\t<SearchSelectTag\n\t\t\t\t\tkey={option.value}\n\t\t\t\t\tonLabelClick={(e) => {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\tonLabelClick?.(option);\n\t\t\t\t\t}}\n\t\t\t\t\tonClose={(e) => {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\thandleClose(option);\n\t\t\t\t\t}}\n\t\t\t\t\tisFocused={isFocused(index)}\n\t\t\t\t>\n\t\t\t\t\t{option.label}\n\t\t\t\t</SearchSelectTag>\n\t\t\t);\n\t\t});\n\t}, [selectedOptions, renderOption, handleClose, onLabelClick, isFocused]);\n\n\treturn (\n\t\t<div className={className}>\n\t\t\t<Popover open={open} onOpenChange={setOpen} {...popoverProps}>\n\t\t\t\t<PopoverTrigger asChild>\n\t\t\t\t\t<SearchSelectTrigger\n\t\t\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\topen={open}\n\t\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t\tinvalid={invalid}\n\t\t\t\t\t\tstartIcon={startIcon}\n\t\t\t\t\t\tonClear={onClear}\n\t\t\t\t\t\tclassName=\"h-auto lg:h-auto\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{displayValue && <div className=\"flex flex-wrap gap-1.5 lg:gap-1\">{displayValue}</div>}\n\t\t\t\t\t</SearchSelectTrigger>\n\t\t\t\t</PopoverTrigger>\n\t\t\t\t<SearchSelectContent portalContainer={portalContainer}>\n\t\t\t\t\t<AsyncSearchSelectPopoverContent {...props} onSelect={onSelect} isSelected={isSelected} />\n\t\t\t\t</SearchSelectContent>\n\t\t\t</Popover>\n\t\t</div>\n\t);\n};\n\nMultiSelect.displayName = \"MultiSelect\";\n"],"names":["useSearchSelect","options","value","defaultValue","onChange","valueOption","selectedOption","setSelectedOption","useState","memoizedOnChange","useCallback","newValue","option","selectedValue","setSelectedValue","useControllableState","useEffect","currentOption","setSelectedByLabel","label","searchSelectTextValueStyles","tv","SearchSelectTextValue","children","className","jsx","searchSelectPlaceholderStyles","SearchSelectPlaceholder","searchSelectTriggerStyles","selectTriggerStyles","SearchSelectTrigger","React","disabled","open","invalid","placeholder","startIcon","onClear","props","ref","styles","jsxs","SelectTriggerClearButton","Icon","ChevronDownIcon","searchSelectContentStyles","SearchSelectContent","PopoverContent","SearchSelectInput","CommandInput","searchSelectStyles","SearchSelect","forwardRef","id","renderOption","onBlur","searchPlaceholder","emptyText","shouldFilter","footerContent","onSearchChange","onOpenChange","hideSearch","popoverProps","setOpen","searchQuery","setSearchQuery","handleSelect","handleSearchChange","handleOpenChange","displayValue","useMemo","item","renderedOptions","index","isDisabled","isSelected","renderOptionItem","customRender","Fragment","CheckIcon","CommandItem","Popover","PopoverTrigger","Command","CommandList","CommandEmpty","loadMoreTriggerStyles","LoadMoreTrigger","onLoad","hasMore","loadingText","triggerRef","useRef","trigger","observer","entry","Loader","defaultFuzzyFilter","search","valueLower","searchLower","searchIndex","i","LazySearchSelect","pageSize","filter","searchSelectProps","visibleCount","setVisibleCount","setValueOption","currentValue","visibleOptions","hasMoreItems","filteredAndRanked","score","a","b","visible","handleLoadMore","prev","SearchSelectSeparator","CommandSeparator","useAsyncDataLoader","loadOptions","setItems","loadingState","setLoadingState","error","setError","abortControllerRef","requestSequenceRef","cancelRequests","loadData","query","currentSequence","abortController","result","err","AsyncSearchSelectContent","loadMode","minInputLength","onSelect","errorText","inputHintText","optionsWithSelection","selected","ErrorState","HintState","EmptyState","AsyncSearchSelectPopoverContent","debounceMs","debouncedSearchQuery","useDebounce","shouldLoad","AsyncSearchSelect","setCurrentOption","MultiSelect","keepOpenOnSelect","onLabelClick","portalContainer","selectedOptions","setSelectedOptions","isAlreadySelected","o","handleClose","handleKeyDown","isFocused","useItemsKeyboardNavigation","SearchSelectTag","e"],"mappings":"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"}
1
+ {"version":3,"file":"search-select.js","sources":["../../src/hooks/useSearchSelect.ts","../../src/components/search-select/components/SearchSelectTextValue.tsx","../../src/components/search-select/components/SearchSelectPlaceholder.tsx","../../src/components/search-select/components/SearchSelectTrigger.tsx","../../src/components/search-select/search-select/components/SearchSelectContent.tsx","../../src/components/search-select/search-select/components/SearchSelectInput.tsx","../../src/components/search-select/search-select/SearchSelect.tsx","../../src/components/search-select/search-select/components/LoadMoreTrigger.tsx","../../src/components/search-select/search-select/utils/fuzzyFilter.ts","../../src/components/search-select/search-select/LazySearchSelect.tsx","../../src/components/search-select/search-select/components/SearchSelectSeparator.tsx","../../src/components/search-select/async-search-select/hooks/useAsyncDataLoader.ts","../../src/components/search-select/async-search-select/components/AsyncSearchSelectContent.tsx","../../src/components/search-select/async-search-select/components/AsyncSearchSelectPopoverContent.tsx","../../src/components/search-select/async-search-select/AsyncSearchSelect.tsx","../../src/components/search-select/multi-select/MultiSelect.tsx"],"sourcesContent":["import { useCallback, useState, useEffect } from \"react\";\nimport { useControllableState } from \"./useControllableState\";\n\nexport interface SearchSelectOption {\n\t/** Уникальный идентификатор опции */\n\tvalue: string | number;\n\t/** Отображаемый текст */\n\tlabel: string;\n\t/** Состояние отключения опции */\n\tdisabled?: boolean;\n}\n\ninterface UseSearchSelectProps<T extends SearchSelectOption = SearchSelectOption> {\n\t/** Список опций */\n\toptions: T[];\n\t/** Текущее выбранное значение (controlled режим) */\n\tvalue?: T[\"value\"];\n\t/** Значение по умолчанию (uncontrolled режим) */\n\tdefaultValue?: T[\"value\"];\n\t/** Callback при выборе опции */\n\tonChange?: (value: T[\"value\"], option: T) => void;\n\t/**\n\t * Значение по умолчанию для выбранной опции. Используется, когда выбранная опция\n\t * отсутствует в текущем списке options. Это может произойти при изменении фильтра\n\t * или при использовании виртуальной (ленивой) загрузки данных.\n\t * */\n\tvalueOption?: T;\n}\n\nexport const useSearchSelect = <T extends SearchSelectOption = SearchSelectOption>({\n\toptions,\n\tvalue,\n\tdefaultValue,\n\tonChange,\n\tvalueOption\n}: UseSearchSelectProps<T>) => {\n\t// Сохраняем выбранную опцию отдельно, чтобы она не терялась при фильтрации\n\tconst [selectedOption, setSelectedOption] = useState<T | undefined>(undefined);\n\n\tconst memoizedOnChange = useCallback(\n\t\t(newValue: T[\"value\"] | undefined) => {\n\t\t\tif (newValue !== undefined) {\n\t\t\t\tconst option = options.find((option) => option.value === newValue) || selectedOption;\n\t\t\t\tif (option && option.value === newValue) {\n\t\t\t\t\tsetSelectedOption(option);\n\t\t\t\t\tonChange?.(newValue, option);\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\t\t[onChange, options, selectedOption]\n\t);\n\n\tconst [selectedValue, setSelectedValue] = useControllableState<T[\"value\"] | undefined>({\n\t\tvalue,\n\t\tdefaultValue,\n\t\tonChange: memoizedOnChange\n\t});\n\n\t// Синхронизируем selectedOption с selectedValue при изменении selectedValue или options\n\tuseEffect(() => {\n\t\tif (selectedValue !== undefined) {\n\t\t\t// Если selectedOption уже соответствует selectedValue, ничего не делаем\n\t\t\tif (selectedOption && selectedOption.value === selectedValue) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Ищем опцию в текущих options\n\t\t\tconst currentOption = options.find((option) => option.value === selectedValue);\n\t\t\tif (currentOption) {\n\t\t\t\tsetSelectedOption(currentOption);\n\t\t\t} else if (valueOption && valueOption.value === selectedValue) {\n\t\t\t\tsetSelectedOption(valueOption);\n\t\t\t}\n\t\t} else {\n\t\t\tsetSelectedOption(undefined);\n\t\t}\n\t}, [selectedValue, options, selectedOption, valueOption]);\n\n\tconst setSelectedByLabel = useCallback(\n\t\t(label: string) => {\n\t\t\t// CommandItem работает с label, а не с value, поэтому нужно найти опцию по label\n\t\t\tconst option = options.find((option) => option.label === label);\n\t\t\tif (option) {\n\t\t\t\tsetSelectedValue(option.value);\n\t\t\t}\n\t\t},\n\t\t[setSelectedValue, options]\n\t);\n\n\treturn {\n\t\tselectedValue,\n\t\tselectedOption,\n\t\tsetSelectedByLabel,\n\t\tsetSelectedValue\n\t};\n};\n","import React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nconst searchSelectTextValueStyles = tv({\n\tbase: \"self-center pl-1.5\"\n});\n\ninterface SearchSelectTextValueProps {\n\tchildren: React.ReactNode;\n\tclassName?: string;\n}\n\nexport const SearchSelectTextValue: React.FC<SearchSelectTextValueProps> = ({ children, className }) => {\n\treturn <span className={searchSelectTextValueStyles({ className })}>{children}</span>;\n};\n","import React from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nconst searchSelectPlaceholderStyles = tv({\n\tbase: \"pointer-events-none self-center pl-1.5 text-muted\"\n});\n\ninterface SearchSelectPlaceholderProps {\n\tchildren: React.ReactNode;\n\tclassName?: string;\n}\n\nexport const SearchSelectPlaceholder: React.FC<SearchSelectPlaceholderProps> = ({ children, className }) => {\n\treturn <span className={searchSelectPlaceholderStyles({ className })}>{children}</span>;\n};\n","import { Icon } from \"@/components/icon/Icon\";\nimport { selectTriggerStyles } from \"@/components/select/Select\";\nimport { ChevronDownIcon } from \"lucide-react\";\nimport React from \"react\";\nimport { tv } from \"tailwind-variants\";\nimport { SearchSelectPlaceholder } from \"./SearchSelectPlaceholder\";\nimport { SelectTriggerClearButton } from \"@/components/select/components/SelectTriggerClearButton\";\n\nconst searchSelectTriggerStyles = tv({\n\textend: selectTriggerStyles,\n\tbase: \"group/search-select-trigger min-h-10 items-start py-[0.3125rem] pl-1.5 pr-3 lg:min-h-9 lg:py-[0.3125rem] lg:pl-1.5 lg:pr-2.5\",\n\tslots: {\n\t\tbuttonWrapper: \"ml-auto flex gap-2.5 pl-2.5\",\n\t\ticonWrapper: \"min-h-7 lg:min-h-6\",\n\t\tstartIcon: \"flex min-h-7 items-center pl-1.5 pr-0.5 text-muted lg:min-h-6\",\n\t\tclearButton:\n\t\t\t\"h-auto p-0 opacity-0 group-hover/search-select-trigger:opacity-100 group-focus-visible/search-select-trigger:opacity-100\"\n\t}\n});\n\ninterface SearchSelectTriggerProps extends React.ComponentPropsWithoutRef<\"button\"> {\n\t/** Состояние отключения */\n\tdisabled?: boolean;\n\t/** Состояние ошибки */\n\tinvalid?: boolean;\n\t/** Текст placeholder */\n\tplaceholder?: string;\n\t/** Состояние открытия. Используется для проставления accessibility аттрибутов */\n\topen?: boolean;\n\t/** Иконка, отображаемая в начале текстового поля */\n\tstartIcon?: React.ReactNode;\n\t/** Callback при очистке значения */\n\tonClear?: () => void;\n}\n\n/**\n * Компонент отображения триггера для SearchSelect.\n * Выполняет роль кнопки, которая открывает Popover с опциями.\n * Может отображать значение или placeholder в зависимости от наличия дочерних элементов.\n * Не содержит сам триггер, а только стилизует кнопку.\n */\nexport const SearchSelectTrigger = React.forwardRef<HTMLButtonElement, SearchSelectTriggerProps>(\n\t({ className, children, disabled, open, invalid, placeholder, startIcon, onClear, ...props }, ref) => {\n\t\tconst styles = searchSelectTriggerStyles({ disabled, invalid });\n\n\t\treturn (\n\t\t\t<button\n\t\t\t\t{...props}\n\t\t\t\tdisabled={disabled}\n\t\t\t\tclassName={styles.base({ className })}\n\t\t\t\tref={ref}\n\t\t\t\trole=\"combobox\"\n\t\t\t\taria-expanded={open}\n\t\t\t\taria-invalid={invalid}\n\t\t\t\taria-haspopup=\"listbox\"\n\t\t\t>\n\t\t\t\t{startIcon && <div className={styles.startIcon()}>{startIcon}</div>}\n\t\t\t\t{children !== undefined ? children : <SearchSelectPlaceholder>{placeholder}</SearchSelectPlaceholder>}\n\t\t\t\t<div className={styles.buttonWrapper()}>\n\t\t\t\t\t{onClear && (\n\t\t\t\t\t\t<div className={styles.iconWrapper()}>\n\t\t\t\t\t\t\t<SelectTriggerClearButton onClear={onClear} className={styles.clearButton()} />\n\t\t\t\t\t\t</div>\n\t\t\t\t\t)}\n\t\t\t\t\t<div className={styles.iconWrapper()}>\n\t\t\t\t\t\t<Icon icon={ChevronDownIcon} className={styles.icon()} />\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t\t</button>\n\t\t);\n\t}\n);\n\nSearchSelectTrigger.displayName = \"SearchSelectTrigger\";\n","import { PopoverContent } from \"@/components/popover\";\nimport React, { ComponentPropsWithoutRef } from \"react\";\nimport { tv } from \"tailwind-variants\";\n\ntype SearchSelectContentProps = ComponentPropsWithoutRef<typeof PopoverContent>;\n\nconst searchSelectContentStyles = tv({\n\tbase: \"w-full min-w-[var(--radix-popper-anchor-width)] border-secondary-border p-0\"\n});\n\n/**\n * Контейнер содержимого для SearchSelect.\n * Обертка вокруг PopoverContent с настроенными стилями и интеграцией с Command.\n * Планируется рефакторинг для вынесения input логики.\n */\nexport const SearchSelectContent = React.forwardRef<React.ElementRef<typeof PopoverContent>, SearchSelectContentProps>(\n\t({ className, children, ...props }, ref) => {\n\t\treturn (\n\t\t\t<PopoverContent ref={ref} className={searchSelectContentStyles({ className })} align=\"start\" {...props}>\n\t\t\t\t{children}\n\t\t\t</PopoverContent>\n\t\t);\n\t}\n);\n\nSearchSelectContent.displayName = \"SearchSelectContent\";\n","import { CommandInput } from \"@/components/command/Command\";\nimport { Command as CommandPrimitive } from \"cmdk\";\nimport React from \"react\";\n\nexport const SearchSelectInput = React.forwardRef<\n\tReact.ElementRef<typeof CommandPrimitive.Input>,\n\tReact.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>\n>(({ placeholder = \"Find\", ...props }, ref) => {\n\treturn <CommandInput ref={ref} placeholder={placeholder} {...props} />;\n});\n\nSearchSelectInput.displayName = \"SearchSelectInput\";\n","import { CheckIcon } from \"lucide-react\";\nimport { ComponentPropsWithoutRef, forwardRef, useCallback, useMemo, useState } from \"react\";\nimport { tv } from \"tailwind-variants\";\nimport { SearchSelectOption, useSearchSelect } from \"../../../hooks/useSearchSelect\";\nimport { Command, CommandEmpty, CommandItem, CommandList } from \"../../command/Command\";\nimport { Icon } from \"../../icon/Icon\";\nimport { Popover, PopoverTrigger } from \"../../popover\";\nimport { SearchSelectTextValue } from \"../components/SearchSelectTextValue\";\nimport { SearchSelectTrigger } from \"../components/SearchSelectTrigger\";\nimport { SearchSelectContent } from \"./components/SearchSelectContent\";\nimport { SearchSelectInput } from \"./components/SearchSelectInput\";\n\nconst searchSelectStyles = tv({ base: \"\" });\n\nexport type RenderOptionProps<T extends SearchSelectOption = SearchSelectOption> = {\n\t/** Отображаемая опция */\n\toption: T;\n} & (RenderOptionInTriggerProps | RenderOptionInListProps);\n\nexport type RenderOptionInTriggerProps = {\n\t/** Тип рендера. Если `trigger`, то опция рендерится в триггере в качестве текущего значения компонента. */\n\ttype: \"trigger\";\n};\n\nexport type RenderOptionInListProps = {\n\t/** Тип рендера. Если `list`, то опция рендерится в списке опций. */\n\ttype: \"list\";\n\t/** Выбрана ли опция в данный момент */\n\tisSelected: boolean;\n\t/** Отключена ли опция */\n\tisDisabled: boolean;\n\t/** Текущий поисковый запрос для подсветки совпадений */\n\tsearchQuery: string;\n\t/** Индекс элемента в списке */\n\tindex: number;\n};\n\ntype PopoverProps = ComponentPropsWithoutRef<typeof Popover>;\nexport interface SearchSelectProps<T extends SearchSelectOption = SearchSelectOption>\n\textends Omit<PopoverProps, \"children\"> {\n\t/** Идентификатор поля в форме. Позволяет связать компонент с полем формы. */\n\tid?: string;\n\t/** Событие blur */\n\tonBlur?: (e: React.FocusEvent<HTMLButtonElement>) => void;\n\t/** Дополнительные классы для контейнера */\n\tclassName?: string;\n\t/** Список опций */\n\toptions: T[];\n\t/** Значение по умолчанию для выбранной опции. Используется, когда выбранная опция\n\t * отсутствует в текущем списке options. Это может произойти при изменении фильтра\n\t * или при использовании виртуальной (ленивой) загрузки данных.\n\t * */\n\tvalueOption?: T;\n\t/**\n\t * Кастомная функция рендера опции.\n\t * Используется для отображения как в trigger (type: \"trigger\"), так и в списке (type: \"list\").\n\t */\n\trenderOption?: (props: RenderOptionProps<T>) => React.ReactNode;\n\t/** Текст placeholder, отображается когда ничего не выбрано */\n\tplaceholder?: string;\n\t/** Текущее выбранное значение (controlled режим) */\n\tvalue?: T[\"value\"];\n\t/** Значение по умолчанию (uncontrolled режим) */\n\tdefaultValue?: T[\"value\"];\n\t/** Callback при выборе опции */\n\tonChange?: (value: T[\"value\"], option: T) => void;\n\t/** Callback при очистке значения */\n\tonClear?: () => void;\n\t/** Состояние отключения */\n\tdisabled?: boolean;\n\t/** Состояние ошибки */\n\tinvalid?: boolean;\n\t/** Текст placeholder для поиска */\n\tsearchPlaceholder?: string;\n\t/** Текст для пустого состояния */\n\temptyText?: string;\n\t/** Использовать встроенную фильтрацию cmdk. По умолчанию true */\n\tshouldFilter?: boolean;\n\t/** Контент, отображаемый в конце списка (например, для триггера загрузки) */\n\tfooterContent?: React.ReactNode;\n\t/** Callback при изменении поискового запроса */\n\tonSearchChange?: (value: string) => void;\n\t/** Callback при изменении состояния открытия */\n\tonOpenChange?: (open: boolean) => void;\n\t/** Иконка, отображаемая в начале поля */\n\tstartIcon?: React.ReactNode;\n\t/** Скрыть поле поиска */\n\thideSearch?: boolean;\n}\n\nexport const SearchSelect = forwardRef(\n\t<T extends SearchSelectOption = SearchSelectOption>(\n\t\tprops: SearchSelectProps<T>,\n\t\tref: React.ForwardedRef<HTMLButtonElement>\n\t) => {\n\t\tconst {\n\t\t\tid,\n\t\t\tclassName,\n\t\t\toptions,\n\t\t\tvalueOption,\n\t\t\trenderOption,\n\t\t\tplaceholder = \"Выберите значение\",\n\t\t\tvalue,\n\t\t\tdefaultValue,\n\t\t\tonBlur,\n\t\t\tonChange,\n\t\t\tonClear,\n\t\t\tdisabled,\n\t\t\tinvalid,\n\t\t\tsearchPlaceholder = \"Найти\",\n\t\t\temptyText = \"Результатов не найдено\",\n\t\t\tshouldFilter = true,\n\t\t\tfooterContent,\n\t\t\tonSearchChange,\n\t\t\tonOpenChange,\n\t\t\tstartIcon,\n\t\t\thideSearch,\n\t\t\t...popoverProps\n\t\t} = props;\n\n\t\tconst [open, setOpen] = useState(false);\n\t\tconst [searchQuery, setSearchQuery] = useState(\"\");\n\n\t\tconst { selectedValue, selectedOption, setSelectedByLabel } = useSearchSelect({\n\t\t\toptions,\n\t\t\tvalue,\n\t\t\tdefaultValue,\n\t\t\tvalueOption,\n\t\t\tonChange\n\t\t});\n\n\t\tconst handleSelect = useCallback(\n\t\t\t(label: string) => {\n\t\t\t\tsetSelectedByLabel(label);\n\t\t\t\tsetOpen(false);\n\t\t\t},\n\t\t\t[setSelectedByLabel, setOpen]\n\t\t);\n\n\t\tconst handleSearchChange = useCallback(\n\t\t\t(value: string) => {\n\t\t\t\tsetSearchQuery(value);\n\t\t\t\tonSearchChange?.(value);\n\t\t\t},\n\t\t\t[onSearchChange]\n\t\t);\n\n\t\tconst handleOpenChange = useCallback(\n\t\t\t(open: boolean) => {\n\t\t\t\tsetOpen(open);\n\t\t\t\tonOpenChange?.(open);\n\t\t\t},\n\t\t\t[onOpenChange]\n\t\t);\n\n\t\tconst displayValue = useMemo(() => {\n\t\t\tif (!selectedOption) return undefined;\n\t\t\tif (renderOption) {\n\t\t\t\tconst item = renderOption({ option: selectedOption, type: \"trigger\" });\n\t\t\t\tif (item !== undefined) {\n\t\t\t\t\treturn item;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn <SearchSelectTextValue>{selectedOption.label}</SearchSelectTextValue>;\n\t\t}, [selectedOption, renderOption]);\n\n\t\tconst renderedOptions = useMemo(() => {\n\t\t\treturn options.map((option, index) => {\n\t\t\t\tconst isDisabled = option.disabled ?? false;\n\t\t\t\tconst isSelected = selectedValue === option.value;\n\n\t\t\t\tconst renderOptionItem = () => {\n\t\t\t\t\tif (renderOption) {\n\t\t\t\t\t\tconst customRender = renderOption({\n\t\t\t\t\t\t\toption,\n\t\t\t\t\t\t\ttype: \"list\",\n\t\t\t\t\t\t\tisSelected,\n\t\t\t\t\t\t\tisDisabled,\n\t\t\t\t\t\t\tsearchQuery,\n\t\t\t\t\t\t\tindex\n\t\t\t\t\t\t});\n\t\t\t\t\t\tif (customRender !== undefined) {\n\t\t\t\t\t\t\treturn customRender;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn (\n\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t{option.label}\n\t\t\t\t\t\t\t{isSelected && <Icon icon={CheckIcon} className=\"ml-auto\" />}\n\t\t\t\t\t\t</>\n\t\t\t\t\t);\n\t\t\t\t};\n\n\t\t\t\treturn (\n\t\t\t\t\t<CommandItem\n\t\t\t\t\t\tkey={option.value}\n\t\t\t\t\t\tvalue={option.label}\n\t\t\t\t\t\tonSelect={isDisabled ? undefined : handleSelect}\n\t\t\t\t\t\tdisabled={isDisabled}\n\t\t\t\t\t>\n\t\t\t\t\t\t{renderOptionItem()}\n\t\t\t\t\t</CommandItem>\n\t\t\t\t);\n\t\t\t});\n\t\t}, [options, selectedValue, handleSelect, renderOption, searchQuery]);\n\n\t\treturn (\n\t\t\t<Popover {...popoverProps} open={open} onOpenChange={handleOpenChange}>\n\t\t\t\t<div className={searchSelectStyles({ className })}>\n\t\t\t\t\t<PopoverTrigger asChild>\n\t\t\t\t\t\t<SearchSelectTrigger\n\t\t\t\t\t\t\tonClear={displayValue ? onClear : undefined}\n\t\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\t\tinvalid={invalid}\n\t\t\t\t\t\t\topen={open}\n\t\t\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t\t\tid={id}\n\t\t\t\t\t\t\tonBlur={onBlur}\n\t\t\t\t\t\t\tref={ref}\n\t\t\t\t\t\t\tstartIcon={startIcon}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t{displayValue}\n\t\t\t\t\t\t</SearchSelectTrigger>\n\t\t\t\t\t</PopoverTrigger>\n\t\t\t\t\t<SearchSelectContent>\n\t\t\t\t\t\t<Command shouldFilter={shouldFilter}>\n\t\t\t\t\t\t\t{!hideSearch && (\n\t\t\t\t\t\t\t\t<SearchSelectInput placeholder={searchPlaceholder} onValueChange={handleSearchChange} />\n\t\t\t\t\t\t\t)}\n\t\t\t\t\t\t\t<CommandList key={`list-${searchQuery}`} className=\"p-1\">\n\t\t\t\t\t\t\t\t{renderedOptions}\n\t\t\t\t\t\t\t\t<CommandEmpty>{emptyText}</CommandEmpty>\n\t\t\t\t\t\t\t\t{footerContent}\n\t\t\t\t\t\t\t</CommandList>\n\t\t\t\t\t\t</Command>\n\t\t\t\t\t</SearchSelectContent>\n\t\t\t\t</div>\n\t\t\t</Popover>\n\t\t);\n\t}\n) as (<T extends SearchSelectOption = SearchSelectOption>(\n\tprops: SearchSelectProps<T> & { ref?: React.ForwardedRef<HTMLButtonElement> }\n) => React.ReactElement) & { displayName?: string };\n\nSearchSelect.displayName = \"SearchSelect\";\n","import { Loader } from \"@/components/loader\";\nimport React, { useEffect, useRef } from \"react\";\nimport { tv } from \"tailwind-variants\";\n\nconst loadMoreTriggerStyles = tv({\n\tbase: \"py-2 text-center text-sm text-muted-foreground\"\n});\n\nexport interface LoadMoreTriggerProps {\n\t/** Callback, который вызывается когда триггер становится видимым */\n\tonLoad: () => void;\n\t/** Есть ли еще элементы для загрузки */\n\thasMore: boolean;\n\t/** Текст индикатора загрузки */\n\tloadingText?: string;\n\t/** Дополнительные CSS классы */\n\tclassName?: string;\n}\n\n/**\n * Компонент для автоматической загрузки дополнительных элементов при прокрутке.\n * Отображает индикатор загрузки и автоматически вызывает `onLoad` когда пользователь\n * доскроллит до этого элемента.\n */\nexport const LoadMoreTrigger = React.forwardRef<HTMLDivElement, LoadMoreTriggerProps>(\n\t({ onLoad, hasMore, loadingText = \"Загрузка...\", className }, ref) => {\n\t\tconst triggerRef = useRef<HTMLDivElement>(null);\n\t\tconst styles = loadMoreTriggerStyles({ className });\n\n\t\tReact.useImperativeHandle(ref, () => triggerRef.current as HTMLDivElement);\n\n\t\tuseEffect(() => {\n\t\t\tconst trigger = triggerRef.current;\n\t\t\tif (!trigger || !hasMore) return;\n\n\t\t\tconst observer = new IntersectionObserver(\n\t\t\t\t([entry]) => {\n\t\t\t\t\tif (entry.isIntersecting) {\n\t\t\t\t\t\tonLoad();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{ rootMargin: \"50px\" }\n\t\t\t);\n\n\t\t\tobserver.observe(trigger);\n\n\t\t\treturn () => {\n\t\t\t\tobserver.disconnect();\n\t\t\t};\n\t\t}, [onLoad, hasMore]);\n\n\t\tif (!hasMore) return null;\n\n\t\treturn (\n\t\t\t<div ref={triggerRef} className={styles}>\n\t\t\t\t<Loader className=\"flex-row\">{loadingText}</Loader>\n\t\t\t</div>\n\t\t);\n\t}\n);\n\nLoadMoreTrigger.displayName = \"LoadMoreTrigger\";\n","/**\n * Простой fuzzy filter для поиска\n * Возвращает число от 0 до 3, где большее число означает лучшее совпадение\n */\nexport const defaultFuzzyFilter = (value: string, search: string): number => {\n\tif (!search.trim()) return 1; // Пустой поиск - показываем все\n\n\tconst valueLower = value.toLowerCase().trim();\n\tconst searchLower = search.toLowerCase().trim();\n\n\t// Точное совпадение с началом - наивысший приоритет\n\tif (valueLower.startsWith(searchLower)) return 3;\n\n\t// Содержит подстроку - высокий приоритет\n\tif (valueLower.includes(searchLower)) return 2;\n\n\t// Fuzzy match - проверяем, что все символы поиска есть в правильном порядке\n\tlet searchIndex = 0;\n\tfor (let i = 0; i < valueLower.length && searchIndex < searchLower.length; i++) {\n\t\tif (valueLower[i] === searchLower[searchIndex]) {\n\t\t\tsearchIndex++;\n\t\t}\n\t}\n\n\t// Если нашли все символы поиска в правильном порядке - низкий приоритет\n\treturn searchIndex === searchLower.length ? 1 : 0;\n};\n\n/**\n * Тип функции фильтрации\n */\nexport type FilterFunction = (value: string, search: string) => number;\n","import { forwardRef, useCallback, useEffect, useMemo, useState } from \"react\";\nimport { SearchSelect, SearchSelectProps } from \"./SearchSelect\";\nimport { SearchSelectOption } from \"../../../hooks/useSearchSelect\";\nimport { LoadMoreTrigger } from \"./components/LoadMoreTrigger\";\nimport { defaultFuzzyFilter, FilterFunction } from \"./utils/fuzzyFilter\";\n\nexport interface LazySearchSelectProps<T extends SearchSelectOption = SearchSelectOption>\n\textends Omit<\n\t\tSearchSelectProps<T>,\n\t\t\"options\" | \"shouldFilter\" | \"footerContent\" | \"onSearchChange\" | \"valueOption\"\n\t> {\n\t/** Полный список опций */\n\toptions: T[];\n\t/** Количество элементов на странице */\n\tpageSize?: number;\n\t/** Кастомная функция фильтрации. По умолчанию используется встроенный fuzzy search */\n\tfilter?: FilterFunction;\n}\n\nexport const LazySearchSelect = forwardRef<HTMLButtonElement, LazySearchSelectProps>(\n\t<T extends SearchSelectOption = SearchSelectOption>(\n\t\tprops: LazySearchSelectProps<T>,\n\t\tref: React.ForwardedRef<HTMLButtonElement>\n\t) => {\n\t\tconst {\n\t\t\toptions,\n\t\t\tpageSize = 50,\n\t\t\tfilter = defaultFuzzyFilter,\n\t\t\tdefaultValue,\n\t\t\tvalue,\n\t\t\t...searchSelectProps\n\t\t} = props;\n\n\t\tconst [visibleCount, setVisibleCount] = useState(pageSize);\n\t\tconst [searchQuery, setSearchQuery] = useState(\"\");\n\t\tconst [valueOption, setValueOption] = useState<T | undefined>(undefined);\n\n\t\t// При изменении поиска сбрасываем счетчик видимых элементов\n\t\tuseEffect(() => setVisibleCount(pageSize), [searchQuery, pageSize]);\n\n\t\tuseEffect(() => {\n\t\t\tconst currentValue = value || defaultValue;\n\t\t\tif (currentValue && !valueOption) {\n\t\t\t\tsetValueOption(options.find((option) => option.value === currentValue));\n\t\t\t}\n\t\t}, [defaultValue, value, options, valueOption]);\n\n\t\t// Фильтрация и ограничение элементов\n\t\tconst { visibleOptions, hasMoreItems } = useMemo(() => {\n\t\t\t// Сначала фильтруем и ранжируем по поисковому запросу\n\t\t\tconst filteredAndRanked = searchQuery\n\t\t\t\t? options\n\t\t\t\t\t\t.map((option) => ({\n\t\t\t\t\t\t\toption,\n\t\t\t\t\t\t\tscore: filter(option.label, searchQuery)\n\t\t\t\t\t\t}))\n\t\t\t\t\t\t.filter(({ score }) => score > 0) // Убираем элементы с нулевым скором\n\t\t\t\t\t\t.sort((a, b) => b.score - a.score) // Сортируем по убыванию скора\n\t\t\t\t\t\t.map(({ option }) => option)\n\t\t\t\t: options;\n\n\t\t\t// Затем ограничиваем количество видимых элементов\n\t\t\tconst visible = filteredAndRanked.slice(0, visibleCount);\n\t\t\tconst hasMore = visibleCount < filteredAndRanked.length;\n\n\t\t\treturn {\n\t\t\t\tvisibleOptions: visible,\n\t\t\t\thasMoreItems: hasMore\n\t\t\t};\n\t\t}, [options, searchQuery, visibleCount, filter]);\n\n\t\t// Обработчик загрузки следующей порции\n\t\tconst handleLoadMore = useCallback(() => {\n\t\t\tsetVisibleCount((prev) => prev + pageSize);\n\t\t}, [pageSize]);\n\n\t\tconst handleSearchChange = useCallback((value: string) => {\n\t\t\tsetSearchQuery(value);\n\t\t}, []);\n\n\t\t// Сброс поиска при открытии\n\t\tconst handleOpenChange = useCallback(\n\t\t\t(open: boolean) => {\n\t\t\t\tif (open && searchQuery) setSearchQuery(\"\");\n\t\t\t},\n\t\t\t[searchQuery, setSearchQuery]\n\t\t);\n\n\t\treturn (\n\t\t\t<SearchSelect<T>\n\t\t\t\t{...searchSelectProps}\n\t\t\t\tref={ref}\n\t\t\t\toptions={visibleOptions}\n\t\t\t\tvalue={value}\n\t\t\t\tdefaultValue={defaultValue}\n\t\t\t\tvalueOption={valueOption}\n\t\t\t\tshouldFilter={false}\n\t\t\t\tfooterContent={<LoadMoreTrigger onLoad={handleLoadMore} hasMore={hasMoreItems} />}\n\t\t\t\tonSearchChange={handleSearchChange}\n\t\t\t\tonOpenChange={handleOpenChange}\n\t\t\t/>\n\t\t);\n\t}\n) as (<T extends SearchSelectOption = SearchSelectOption>(\n\tprops: LazySearchSelectProps<T> & { ref?: React.ForwardedRef<HTMLButtonElement> }\n) => React.ReactElement) & { displayName?: string };\n\nLazySearchSelect.displayName = \"LazySearchSelect\";\n","import React from \"react\";\nimport { CommandSeparator } from \"@/components/command/Command\";\nimport { ComponentPropsWithoutRef } from \"react\";\nimport { Command as CommandPrimitive } from \"cmdk\";\n\ntype SearchSelectSeparatorProps = ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>;\n\n/**\n * Разделитель для SearchSelect.\n * Простая обертка вокруг CommandSeparator.\n */\nexport const SearchSelectSeparator = React.forwardRef<\n\tReact.ElementRef<typeof CommandPrimitive.Separator>,\n\tSearchSelectSeparatorProps\n>((props, ref) => {\n\treturn <CommandSeparator ref={ref} {...props} />;\n});\n\nSearchSelectSeparator.displayName = \"SearchSelectSeparator\";\n","import { useCallback, useEffect, useRef, useState } from \"react\";\n\nexport type LoadingState = \"idle\" | \"loading\" | \"success\" | \"error\";\n\nexport interface LoadOptionsParams {\n\tsearchQuery: string;\n\tsignal?: AbortSignal;\n}\n\nexport interface LoadOptionsResult<T> {\n\toptions: T[];\n}\n\ninterface UseAsyncDataLoaderOptions<T> {\n\t/** Функция загрузки данных */\n\tloadOptions: (params: LoadOptionsParams) => Promise<LoadOptionsResult<T>>;\n}\n\ninterface UseAsyncDataLoaderReturn<T> {\n\t/** Текущие загруженные элементы */\n\toptions: T[];\n\t/** Состояние загрузки */\n\tloadingState: LoadingState;\n\t/** Текст ошибки, если загрузка не удалась */\n\terror: string | null;\n\t/** Функция загрузки данных */\n\tloadData: (query: string) => Promise<void>;\n\t/** Функция отмены текущих запросов */\n\tcancelRequests: () => void;\n}\n\n/**\n * Хук для асинхронной загрузки данных с защитой от race conditions\n *\n * Решает следующие проблемы:\n * - Race conditions при быстром вводе пользователя\n * - Мерцание интерфейса из-за множественных запросов\n * - Неправильный порядок получения ответов от сервера\n * - Обработка отмены запросов при размонтировании компонента\n *\n * @example\n * ```tsx\n * const { options, loadingState, loadData } = useAsyncDataLoader({\n * loadOptions: async ({ searchQuery }) => {\n * const response = await fetch(`/api/search?q=${searchQuery}`);\n * return response.json();\n * }\n * });\n *\n * // Загрузить данные\n * loadData(\"search query\");\n * ```\n */\nexport const useAsyncDataLoader = <T>({ loadOptions }: UseAsyncDataLoaderOptions<T>): UseAsyncDataLoaderReturn<T> => {\n\tconst [options, setItems] = useState<T[]>([]);\n\tconst [loadingState, setLoadingState] = useState<LoadingState>(\"idle\");\n\tconst [error, setError] = useState<string | null>(null);\n\n\t// Refs для управления race conditions\n\tconst abortControllerRef = useRef<AbortController | null>(null);\n\tconst requestSequenceRef = useRef(0);\n\n\t// Функция для отмены предыдущих запросов\n\tconst cancelRequests = useCallback(() => {\n\t\tif (abortControllerRef.current) {\n\t\t\tabortControllerRef.current.abort();\n\t\t}\n\t}, []);\n\n\t// Основная функция загрузки данных\n\tconst loadData = useCallback(\n\t\tasync (query: string) => {\n\t\t\t// Отменяем предыдущие запросы\n\t\t\tcancelRequests();\n\n\t\t\t// Увеличиваем sequence для отслеживания порядка\n\t\t\tconst currentSequence = ++requestSequenceRef.current;\n\n\t\t\t// Создаем новый AbortController\n\t\t\tconst abortController = new AbortController();\n\t\t\tabortControllerRef.current = abortController;\n\n\t\t\tsetLoadingState(\"loading\");\n\t\t\tsetError(null);\n\n\t\t\ttry {\n\t\t\t\tconst result = await loadOptions({\n\t\t\t\t\tsearchQuery: query,\n\t\t\t\t\tsignal: abortController.signal\n\t\t\t\t});\n\n\t\t\t\t// Проверяем, что запрос еще актуален\n\t\t\t\tif (currentSequence !== requestSequenceRef.current) return;\n\n\t\t\t\tsetItems(result.options);\n\t\t\t\tsetLoadingState(\"success\");\n\t\t\t} catch (err) {\n\t\t\t\t// Игнорируем AbortError - это нормальная отмена\n\t\t\t\tif (err instanceof Error && err.name === \"AbortError\") return;\n\t\t\t\tif (currentSequence !== requestSequenceRef.current) return;\n\n\t\t\t\tsetError(err instanceof Error ? err.message : \"Неизвестная ошибка\");\n\t\t\t\tsetLoadingState(\"error\");\n\t\t\t}\n\t\t},\n\t\t[loadOptions, cancelRequests]\n\t);\n\n\t// Cleanup при размонтировании компонента\n\tuseEffect(() => {\n\t\treturn () => cancelRequests();\n\t}, [cancelRequests]);\n\n\treturn {\n\t\toptions,\n\t\tloadingState,\n\t\terror,\n\t\tloadData,\n\t\tcancelRequests\n\t};\n};\n","import { EmptyState } from \"@/components/empty-state\";\nimport { ErrorState } from \"@/components/error-state\";\nimport { HintState } from \"@/components/hint-state\";\nimport { Loader } from \"@/components/loader\";\nimport { CheckIcon } from \"lucide-react\";\nimport { useMemo, useCallback } from \"react\";\nimport { CommandItem } from \"../../../command/Command\";\nimport { Icon } from \"../../../icon/Icon\";\nimport type { LoadingState, RenderOptionProps, SearchSelectOption } from \"../types\";\nimport React from \"react\";\n\ninterface AsyncSearchSelectContentProps<T extends SearchSelectOption = SearchSelectOption> {\n\t/** Текущие опции для отображения */\n\toptions: T[];\n\t/** Состояние загрузки */\n\tloadingState: LoadingState;\n\t/** Текст ошибки, если есть */\n\terror: string | null;\n\t/** Функция проверки выбранности элемента */\n\tisSelected?: (value: T) => boolean;\n\t/** Текущий поисковый запрос */\n\tsearchQuery: string;\n\t/** Режим загрузки */\n\tloadMode: \"auto\" | \"input\";\n\t/** Минимальная длина запроса для режима input */\n\tminInputLength: number;\n\t/** Функция обработки выбора опции */\n\tonSelect: (label: string) => void;\n\t/** Кастомная функция рендера опции */\n\trenderOption?: (props: RenderOptionProps<T>) => React.ReactNode;\n\t/** Текст во время загрузки */\n\tloadingText: string;\n\t/** Текст при ошибке загрузки */\n\terrorText: string;\n\t/** Текст подсказки для ввода */\n\tinputHintText: string;\n\t/** Текст для пустого состояния */\n\temptyText: string;\n}\n\n/**\n * Компонент для рендера содержимого AsyncSearchSelect\n *\n * Отвечает за отображение разных состояний:\n * - Загрузка\n * - Ошибка\n * - Подсказка для ввода\n * - Пустое состояние\n * - Список опций\n */\nexport const AsyncSearchSelectContent = <T extends SearchSelectOption = SearchSelectOption>({\n\toptions,\n\tloadingState,\n\terror,\n\tisSelected,\n\tsearchQuery,\n\tloadMode,\n\tminInputLength,\n\tonSelect,\n\trenderOption,\n\tloadingText,\n\terrorText,\n\tinputHintText,\n\temptyText\n}: AsyncSearchSelectContentProps<T>) => {\n\t// Мемоизируем опции с предвычисленным состоянием выбранности\n\tconst optionsWithSelection = useMemo(() => {\n\t\treturn options.map((option, index) => ({\n\t\t\toption,\n\t\t\tindex,\n\t\t\tisSelected: isSelected?.(option) ?? false,\n\t\t\tisDisabled: option.disabled ?? false\n\t\t}));\n\t}, [options, isSelected]);\n\n\tconst renderOptionItem = useCallback(\n\t\t({\n\t\t\toption,\n\t\t\tisSelected: selected,\n\t\t\tisDisabled: disabled,\n\t\t\tindex\n\t\t}: {\n\t\t\toption: T;\n\t\t\tisSelected: boolean;\n\t\t\tisDisabled: boolean;\n\t\t\tindex: number;\n\t\t}) => {\n\t\t\tif (renderOption) {\n\t\t\t\tconst customRender = renderOption({\n\t\t\t\t\toption,\n\t\t\t\t\ttype: \"list\",\n\t\t\t\t\tisSelected: selected,\n\t\t\t\t\tisDisabled: disabled,\n\t\t\t\t\tsearchQuery,\n\t\t\t\t\tindex\n\t\t\t\t});\n\t\t\t\tif (customRender !== undefined) {\n\t\t\t\t\treturn customRender;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn (\n\t\t\t\t<>\n\t\t\t\t\t{option.label}\n\t\t\t\t\t{selected && <Icon icon={CheckIcon} className=\"ml-auto\" />}\n\t\t\t\t</>\n\t\t\t);\n\t\t},\n\t\t[renderOption, searchQuery]\n\t);\n\n\t// Состояние ошибки\n\tif (loadingState === \"error\") {\n\t\treturn <ErrorState className=\"py-6\">{error || errorText}</ErrorState>;\n\t}\n\n\t// Состояние загрузки\n\tif (loadingState === \"loading\") {\n\t\treturn <Loader className=\"py-6\">{loadingText}</Loader>;\n\t}\n\n\t// Подсказка для режима input\n\tif (loadMode === \"input\" && searchQuery.length < minInputLength) {\n\t\treturn <HintState className=\"py-6\">{inputHintText}</HintState>;\n\t}\n\n\t// Пустое состояние\n\tif (options.length === 0 && loadingState === \"success\") {\n\t\treturn <EmptyState className=\"py-6\">{emptyText}</EmptyState>;\n\t}\n\n\t// Список опций\n\treturn (\n\t\t<>\n\t\t\t{optionsWithSelection.map(({ option, index, isSelected: selected, isDisabled: disabled }) => (\n\t\t\t\t<CommandItem\n\t\t\t\t\tkey={option.value}\n\t\t\t\t\tvalue={option.label}\n\t\t\t\t\tonSelect={disabled ? undefined : onSelect}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t>\n\t\t\t\t\t{renderOptionItem({\n\t\t\t\t\t\toption,\n\t\t\t\t\t\tisSelected: selected,\n\t\t\t\t\t\tisDisabled: disabled,\n\t\t\t\t\t\tindex\n\t\t\t\t\t})}\n\t\t\t\t</CommandItem>\n\t\t\t))}\n\t\t</>\n\t);\n};\n","import { useCallback, useEffect, useMemo, useState } from \"react\";\nimport { useDebounce } from \"../../../../hooks/useDebounce\";\nimport { Command, CommandList } from \"../../../command/Command\";\nimport { SearchSelectInput } from \"../../search-select/components/SearchSelectInput\";\nimport { useAsyncDataLoader } from \"../hooks/useAsyncDataLoader\";\nimport type { AsyncSearchSelectProps, SearchSelectOption } from \"../types\";\nimport { AsyncSearchSelectContent } from \"./AsyncSearchSelectContent\";\n\ninterface AsyncSearchSelectPopoverContentProps<T extends SearchSelectOption = SearchSelectOption>\n\textends Pick<\n\t\tAsyncSearchSelectProps<T>,\n\t\t| \"loadOptions\"\n\t\t| \"loadMode\"\n\t\t| \"minInputLength\"\n\t\t| \"debounceMs\"\n\t\t| \"searchPlaceholder\"\n\t\t| \"loadingText\"\n\t\t| \"errorText\"\n\t\t| \"inputHintText\"\n\t\t| \"emptyText\"\n\t\t| \"renderOption\"\n\t\t| \"hideSearch\"\n\t> {\n\tonSelect: (value: T | null) => void;\n\tisSelected?: (value: T) => boolean;\n}\n\nexport const AsyncSearchSelectPopoverContent = <T extends SearchSelectOption = SearchSelectOption>(\n\tprops: AsyncSearchSelectPopoverContentProps<T>\n) => {\n\tconst {\n\t\tloadOptions,\n\t\tloadMode = \"auto\",\n\t\tminInputLength = 3,\n\t\tdebounceMs = 300,\n\t\tsearchPlaceholder = \"Найти\",\n\t\tloadingText = \"Загружаем...\",\n\t\terrorText = \"Ошибка загрузки\",\n\t\tinputHintText = \"Введите текст для поиска\",\n\t\temptyText = \"Результатов не найдено\",\n\t\trenderOption,\n\t\tonSelect,\n\t\tisSelected,\n\t\thideSearch\n\t} = props;\n\n\tconst [searchQuery, setSearchQuery] = useState(\"\");\n\n\t// Дебаунсированный поисковый запрос для загрузки данных\n\tconst debouncedSearchQuery = useDebounce(searchQuery, debounceMs);\n\n\tconst { options, loadingState, error, loadData } = useAsyncDataLoader<T>({\n\t\tloadOptions\n\t});\n\n\tconst shouldLoad = useMemo(() => {\n\t\tif (loadMode === \"auto\") return true;\n\t\tif (loadMode === \"input\") return debouncedSearchQuery.length >= minInputLength;\n\t\treturn false;\n\t}, [loadMode, debouncedSearchQuery, minInputLength]);\n\n\t// Загрузка при изменении условий\n\tuseEffect(() => {\n\t\tif (shouldLoad) loadData(debouncedSearchQuery);\n\t}, [shouldLoad, debouncedSearchQuery, loadData]);\n\n\tconst handleSelect = useCallback(\n\t\t(label: string) => {\n\t\t\tonSelect(options.find((option) => option.label === label) || null);\n\t\t},\n\t\t[onSelect, options]\n\t);\n\n\treturn (\n\t\t<Command shouldFilter={false}>\n\t\t\t{!hideSearch && <SearchSelectInput placeholder={searchPlaceholder} onValueChange={setSearchQuery} />}\n\t\t\t<CommandList key={`list-${debouncedSearchQuery}`} className=\"p-1\">\n\t\t\t\t<AsyncSearchSelectContent\n\t\t\t\t\toptions={options}\n\t\t\t\t\tloadingState={loadingState}\n\t\t\t\t\terror={error}\n\t\t\t\t\tisSelected={isSelected}\n\t\t\t\t\tsearchQuery={debouncedSearchQuery}\n\t\t\t\t\tloadMode={loadMode}\n\t\t\t\t\tminInputLength={minInputLength}\n\t\t\t\t\tonSelect={handleSelect}\n\t\t\t\t\trenderOption={renderOption}\n\t\t\t\t\tloadingText={loadingText}\n\t\t\t\t\terrorText={errorText}\n\t\t\t\t\tinputHintText={inputHintText}\n\t\t\t\t\temptyText={emptyText}\n\t\t\t\t/>\n\t\t\t</CommandList>\n\t\t</Command>\n\t);\n};\n","import { useControllableState } from \"@/hooks/useControllableState\";\nimport { useCallback, useMemo, useState } from \"react\";\nimport { Popover, PopoverTrigger } from \"../../popover\";\nimport { SearchSelectTextValue } from \"../components/SearchSelectTextValue\";\nimport { SearchSelectTrigger } from \"../components/SearchSelectTrigger\";\nimport { SearchSelectContent } from \"../search-select/components/SearchSelectContent\";\nimport { AsyncSearchSelectPopoverContent } from \"./components/AsyncSearchSelectPopoverContent\";\nimport type { AsyncSearchSelectProps, SearchSelectOption } from \"./types\";\n\nexport const AsyncSearchSelect = <T extends SearchSelectOption = SearchSelectOption>(\n\tprops: AsyncSearchSelectProps<T>\n) => {\n\tconst {\n\t\trenderOption,\n\t\tplaceholder = \"Выберите значение\",\n\t\tvalue,\n\t\tdefaultValue,\n\t\tdisabled,\n\t\tinvalid,\n\t\tonChange,\n\t\tstartIcon,\n\t\tonClear,\n\t\t...popoverProps\n\t} = props;\n\n\tconst [open, setOpen] = useState(false);\n\n\tconst [currentOption, setCurrentOption] = useControllableState<T>({\n\t\tvalue,\n\t\tdefaultValue,\n\t\tonChange\n\t});\n\n\tconst displayValue = useMemo(() => {\n\t\tif (!currentOption) return undefined;\n\t\tif (renderOption) {\n\t\t\tconst item = renderOption({ option: currentOption, type: \"trigger\" });\n\t\t\tif (item !== undefined) {\n\t\t\t\treturn item;\n\t\t\t}\n\t\t}\n\t\treturn <SearchSelectTextValue>{currentOption.label}</SearchSelectTextValue>;\n\t}, [currentOption, renderOption]);\n\n\tconst onSelect = useCallback(\n\t\t(option: T | null) => {\n\t\t\tif (option) setCurrentOption(option);\n\t\t\tsetOpen(false);\n\t\t},\n\t\t[setCurrentOption, setOpen]\n\t);\n\n\tconst isSelected = useCallback(\n\t\t(option: T) => {\n\t\t\treturn currentOption?.value === option.value;\n\t\t},\n\t\t[currentOption]\n\t);\n\n\treturn (\n\t\t<Popover {...popoverProps} open={open} onOpenChange={setOpen}>\n\t\t\t<PopoverTrigger asChild>\n\t\t\t\t<SearchSelectTrigger\n\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\tinvalid={invalid}\n\t\t\t\t\topen={open}\n\t\t\t\t\tstartIcon={startIcon}\n\t\t\t\t\tonClear={displayValue ? onClear : undefined}\n\t\t\t\t>\n\t\t\t\t\t{displayValue}\n\t\t\t\t</SearchSelectTrigger>\n\t\t\t</PopoverTrigger>\n\t\t\t<SearchSelectContent>\n\t\t\t\t<AsyncSearchSelectPopoverContent {...props} onSelect={onSelect} isSelected={isSelected} />\n\t\t\t</SearchSelectContent>\n\t\t</Popover>\n\t);\n};\n","import { useControllableState } from \"@/hooks/useControllableState\";\nimport { useItemsKeyboardNavigation } from \"@/hooks/useItemsKeyboardNavigation\";\nimport { PopoverProps } from \"@radix-ui/react-popover\";\nimport { useCallback, useMemo, useState } from \"react\";\nimport { SearchSelectOption } from \"../../../hooks/useSearchSelect\";\nimport { Popover, PopoverTrigger } from \"../../popover\";\nimport { AsyncSearchSelectPopoverContent } from \"../async-search-select/components/AsyncSearchSelectPopoverContent\";\nimport { LoadOptionsParams, LoadOptionsResult } from \"../async-search-select/types\";\nimport { SearchSelectTag } from \"../components/SearchSelectTag\";\nimport { SearchSelectTrigger } from \"../components/SearchSelectTrigger\";\nimport { SearchSelectContent } from \"../search-select/components/SearchSelectContent\";\n\n/**\n * Пропсы для рендера опции в trigger (кнопке)\n */\nexport type RenderOptionInTriggerProps = {\n\ttype: \"trigger\";\n\tonClose?: () => void;\n};\n\n/**\n * Пропсы для рендера опции в списке\n */\nexport type RenderOptionInListProps = {\n\ttype: \"list\";\n\t/** Выбрана ли опция в данный момент */\n\tisSelected: boolean;\n\t/** Отключена ли опция */\n\tisDisabled: boolean;\n\t/** Текущий поисковый запрос для подсветки совпадений */\n\tsearchQuery: string;\n\t/** Индекс элемента в списке */\n\tindex: number;\n};\n\n/**\n * Объединенный тип для рендера опции\n */\nexport type RenderOptionProps<T extends SearchSelectOption = SearchSelectOption> = {\n\toption: T;\n} & (RenderOptionInTriggerProps | RenderOptionInListProps);\n\nexport interface MultiSelectProps<T extends SearchSelectOption = SearchSelectOption> {\n\t/** Дополнительные классы для контейнера */\n\tclassName?: string;\n\t/** Флаг для отключения компонента */\n\tdisabled?: boolean;\n\t/** Текст placeholder, отображается когда ничего не выбрано */\n\tplaceholder?: string;\n\t/** Текущие выбранные опции (controlled режим) */\n\tvalue?: T[];\n\t/** Опции по умолчанию (uncontrolled режим) */\n\tdefaultValue?: T[];\n\t/** Callback при изменении выбранных опций */\n\tonChange?: (options: T[]) => void;\n\t/** Callback при очистке значения */\n\tonClear?: () => void;\n\t/** Оставлять поповер открытым после выбора элемента */\n\tkeepOpenOnSelect?: boolean;\n\t/** Обработчик клика по названию выбранного тега */\n\tonLabelClick?: (option: T) => void;\n\t/** Функция загрузки опций */\n\tloadOptions: (params: LoadOptionsParams) => Promise<LoadOptionsResult<T>>;\n\t/** Режим загрузки опций */\n\tloadMode?: \"auto\" | \"input\";\n\t/** Минимальное количество символов для начала загрузки (только для режима \"input\") */\n\tminInputLength?: number;\n\t/** Задержка перед отправкой запроса в миллисекундах (debounce) */\n\tdebounceMs?: number;\n\t/** Текст подсказки для режима \"input\", когда пользователь еще не ввел символы */\n\tinputHintText?: string;\n\t/** Текст во время загрузки */\n\tloadingText?: string;\n\t/** Текст при ошибке загрузки */\n\terrorText?: string;\n\t/** Кастомная функция рендера опции */\n\trenderOption?: (props: RenderOptionProps<T>) => React.ReactNode;\n\t/** Текст placeholder для поиска */\n\tsearchPlaceholder?: string;\n\t/** Текст для пустого состояния */\n\temptyText?: string;\n\t/** Дополнительные пропсы для Popover */\n\tpopoverProps?: PopoverProps;\n\t/** Состояние ошибки */\n\tinvalid?: boolean;\n\t/** Иконка, отображаемая в начале поля */\n\tstartIcon?: React.ReactNode;\n\t/** Скрыть поле поиска */\n\thideSearch?: boolean;\n\t/** Контейнер для портала контента. Если не указан, используется usePortalContainer */\n\tportalContainer?: HTMLElement;\n}\n\n/**\n * Компонент для множественного выбора элементов из списка\n */\nexport const MultiSelect = <T extends SearchSelectOption = SearchSelectOption>(props: MultiSelectProps<T>) => {\n\tconst {\n\t\tclassName,\n\t\tplaceholder = \"Выберите значение\",\n\t\tvalue,\n\t\tdefaultValue,\n\t\tonChange,\n\t\tdisabled,\n\t\tinvalid,\n\t\tkeepOpenOnSelect = true,\n\t\tonClear,\n\t\tonLabelClick,\n\t\trenderOption,\n\t\tstartIcon,\n\t\tportalContainer,\n\t\t...popoverProps\n\t} = props;\n\n\tconst [open, setOpen] = useState(false);\n\n\tconst [selectedOptions, setSelectedOptions] = useControllableState<T[]>({\n\t\tvalue,\n\t\tdefaultValue,\n\t\tonChange\n\t});\n\n\tconst onSelect = useCallback(\n\t\t(option: T | null) => {\n\t\t\tif (option) {\n\t\t\t\tconst isAlreadySelected = selectedOptions?.find((o) => o.value === option.value);\n\t\t\t\tif (isAlreadySelected) {\n\t\t\t\t\tsetSelectedOptions((prev) => {\n\t\t\t\t\t\treturn prev?.filter((o) => o.value !== option.value) || [];\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\tsetSelectedOptions((prev) => {\n\t\t\t\t\t\treturn [...(prev || []), option];\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!keepOpenOnSelect) {\n\t\t\t\tsetOpen(false);\n\t\t\t}\n\t\t},\n\t\t[selectedOptions, keepOpenOnSelect, setSelectedOptions, setOpen]\n\t);\n\n\tconst handleClose = useCallback(\n\t\t(option: T) => {\n\t\t\tconst isSelected = selectedOptions?.find((o) => o.value === option.value);\n\t\t\tif (isSelected) {\n\t\t\t\tsetSelectedOptions((prev) => {\n\t\t\t\t\treturn prev?.filter((o) => o.value !== option.value) || [];\n\t\t\t\t});\n\t\t\t}\n\t\t},\n\t\t[selectedOptions, setSelectedOptions]\n\t);\n\n\tconst isSelected = useCallback(\n\t\t(option: T) => {\n\t\t\treturn selectedOptions?.some((selectedOption) => selectedOption.value === option.value) ?? false;\n\t\t},\n\t\t[selectedOptions]\n\t);\n\n\tconst { handleKeyDown, isFocused } = useItemsKeyboardNavigation({\n\t\titems: selectedOptions || [],\n\t\tonEnter: onLabelClick,\n\t\tonDelete: handleClose\n\t});\n\n\tconst displayValue = useMemo(() => {\n\t\tif (!selectedOptions || selectedOptions.length === 0) return undefined;\n\n\t\treturn selectedOptions.map((option, index) => {\n\t\t\tif (renderOption) {\n\t\t\t\tconst item = renderOption({\n\t\t\t\t\toption,\n\t\t\t\t\ttype: \"trigger\",\n\t\t\t\t\tonClose: () => {\n\t\t\t\t\t\thandleClose(option);\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tif (item !== undefined) {\n\t\t\t\t\treturn item;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn (\n\t\t\t\t<SearchSelectTag\n\t\t\t\t\tkey={option.value}\n\t\t\t\t\tonLabelClick={(e) => {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\tonLabelClick?.(option);\n\t\t\t\t\t}}\n\t\t\t\t\tonClose={(e) => {\n\t\t\t\t\t\te.preventDefault();\n\t\t\t\t\t\thandleClose(option);\n\t\t\t\t\t}}\n\t\t\t\t\tisFocused={isFocused(index)}\n\t\t\t\t>\n\t\t\t\t\t{option.label}\n\t\t\t\t</SearchSelectTag>\n\t\t\t);\n\t\t});\n\t}, [selectedOptions, renderOption, handleClose, onLabelClick, isFocused]);\n\n\treturn (\n\t\t<div className={className}>\n\t\t\t<Popover open={open} onOpenChange={setOpen} {...popoverProps}>\n\t\t\t\t<PopoverTrigger asChild>\n\t\t\t\t\t<SearchSelectTrigger\n\t\t\t\t\t\tonKeyDown={handleKeyDown}\n\t\t\t\t\t\tdisabled={disabled}\n\t\t\t\t\t\topen={open}\n\t\t\t\t\t\tplaceholder={placeholder}\n\t\t\t\t\t\tinvalid={invalid}\n\t\t\t\t\t\tstartIcon={startIcon}\n\t\t\t\t\t\tonClear={onClear}\n\t\t\t\t\t\tclassName=\"h-auto lg:h-auto\"\n\t\t\t\t\t>\n\t\t\t\t\t\t{displayValue && <div className=\"flex flex-wrap gap-1.5 lg:gap-1\">{displayValue}</div>}\n\t\t\t\t\t</SearchSelectTrigger>\n\t\t\t\t</PopoverTrigger>\n\t\t\t\t<SearchSelectContent portalContainer={portalContainer}>\n\t\t\t\t\t<AsyncSearchSelectPopoverContent {...props} onSelect={onSelect} isSelected={isSelected} />\n\t\t\t\t</SearchSelectContent>\n\t\t\t</Popover>\n\t\t</div>\n\t);\n};\n\nMultiSelect.displayName = \"MultiSelect\";\n"],"names":["useSearchSelect","options","value","defaultValue","onChange","valueOption","selectedOption","setSelectedOption","useState","memoizedOnChange","useCallback","newValue","option","selectedValue","setSelectedValue","useControllableState","useEffect","currentOption","setSelectedByLabel","label","searchSelectTextValueStyles","tv","SearchSelectTextValue","children","className","jsx","searchSelectPlaceholderStyles","SearchSelectPlaceholder","searchSelectTriggerStyles","selectTriggerStyles","SearchSelectTrigger","React","disabled","open","invalid","placeholder","startIcon","onClear","props","ref","styles","jsxs","SelectTriggerClearButton","Icon","ChevronDownIcon","searchSelectContentStyles","SearchSelectContent","PopoverContent","SearchSelectInput","CommandInput","searchSelectStyles","SearchSelect","forwardRef","id","renderOption","onBlur","searchPlaceholder","emptyText","shouldFilter","footerContent","onSearchChange","onOpenChange","hideSearch","popoverProps","setOpen","searchQuery","setSearchQuery","handleSelect","handleSearchChange","handleOpenChange","displayValue","useMemo","item","renderedOptions","index","isDisabled","isSelected","renderOptionItem","customRender","Fragment","CheckIcon","CommandItem","Popover","PopoverTrigger","Command","CommandList","CommandEmpty","loadMoreTriggerStyles","LoadMoreTrigger","onLoad","hasMore","loadingText","triggerRef","useRef","trigger","observer","entry","Loader","defaultFuzzyFilter","search","valueLower","searchLower","searchIndex","i","LazySearchSelect","pageSize","filter","searchSelectProps","visibleCount","setVisibleCount","setValueOption","currentValue","visibleOptions","hasMoreItems","filteredAndRanked","score","a","b","visible","handleLoadMore","prev","SearchSelectSeparator","CommandSeparator","useAsyncDataLoader","loadOptions","setItems","loadingState","setLoadingState","error","setError","abortControllerRef","requestSequenceRef","cancelRequests","loadData","query","currentSequence","abortController","result","err","AsyncSearchSelectContent","loadMode","minInputLength","onSelect","errorText","inputHintText","optionsWithSelection","selected","ErrorState","HintState","EmptyState","AsyncSearchSelectPopoverContent","debounceMs","debouncedSearchQuery","useDebounce","shouldLoad","AsyncSearchSelect","setCurrentOption","MultiSelect","keepOpenOnSelect","onLabelClick","portalContainer","selectedOptions","setSelectedOptions","isAlreadySelected","o","handleClose","handleKeyDown","isFocused","useItemsKeyboardNavigation","SearchSelectTag","e"],"mappings":"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"}