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.
- package/dist/{CheckboxField-2zNFubvm.js → CheckboxField-limFbMk2.js} +43 -43
- package/dist/CheckboxField-limFbMk2.js.map +1 -0
- package/dist/{Command-D5zgJ7-y.js → Command-B7ZRyW8w.js} +2 -2
- package/dist/Command-B7ZRyW8w.js.map +1 -0
- package/dist/{FormFooterTemplate-Cfn5Nmge.js → FormFooterTemplate-BRrgrxAu.js} +2 -2
- package/dist/{FormFooterTemplate-Cfn5Nmge.js.map → FormFooterTemplate-BRrgrxAu.js.map} +1 -1
- package/dist/{InputGroup-BvD9Igmt.js → InputGroup-BcRWP-zL.js} +20 -22
- package/dist/InputGroup-BcRWP-zL.js.map +1 -0
- package/dist/{Select-MLPTpIl5.js → Select-D9juHX8o.js} +7 -8
- package/dist/{Select-MLPTpIl5.js.map → Select-D9juHX8o.js.map} +1 -1
- package/dist/{TextInput-Cj50ImXi.js → TextInput-Db0ylY91.js} +2 -2
- package/dist/{TextInput-Cj50ImXi.js.map → TextInput-Db0ylY91.js.map} +1 -1
- package/dist/blocks/auth/otp-form.js +1 -1
- package/dist/components/checkbox.js +1 -1
- package/dist/components/command.js +1 -1
- package/dist/components/dialog.js +1 -1
- package/dist/components/drawer.js +1 -1
- package/dist/components/form.js +1 -1
- package/dist/components/image-uploader.js +8 -8
- package/dist/components/image-uploader.js.map +1 -1
- package/dist/components/input.js +5 -5
- package/dist/components/radio-group.js +10 -10
- package/dist/components/radio-group.js.map +1 -1
- package/dist/components/search-select.js +40 -40
- package/dist/components/search-select.js.map +1 -1
- package/dist/components/select/Select.d.ts +0 -3
- package/dist/components/select.js +1 -1
- package/dist/components/sidebar.js +1 -1
- package/dist/components/table/tree.js +1 -1
- package/dist/components/table.js +1 -1
- package/dist/components/tag-input.js +2 -2
- package/dist/components/textarea.js +1 -1
- package/dist/{inputBaseStyles-DbzD_jvq.js → inputBaseStyles-BfZIWuQ6.js} +5 -5
- package/dist/inputBaseStyles-BfZIWuQ6.js.map +1 -0
- package/dist/styles-scoped.css +93 -132
- package/dist/styles.css +93 -132
- package/dist/theme.css +4 -12
- package/dist/{treeModel-jvOXFZvK.js → treeModel-BlJWP4sc.js} +2 -2
- package/dist/treeModel-BlJWP4sc.js.map +1 -0
- package/package.json +1 -1
- package/tailwind.preset.js +10 -14
- package/dist/CheckboxField-2zNFubvm.js.map +0 -1
- package/dist/Command-D5zgJ7-y.js.map +0 -1
- package/dist/InputGroup-BvD9Igmt.js.map +0 -1
- package/dist/inputBaseStyles-DbzD_jvq.js.map +0 -1
- 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-
|
|
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
|
|
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:
|
|
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(
|
|
91
|
-
|
|
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:
|
|
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,
|
|
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),
|
|
140
|
+
J(O), b(!1);
|
|
141
141
|
},
|
|
142
|
-
[J,
|
|
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
|
-
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
|
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(
|
|
318
|
-
} catch (
|
|
319
|
-
if (
|
|
320
|
-
c(
|
|
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]),
|
|
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:
|
|
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, [
|
|
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,
|
|
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 &&
|
|
468
|
+
m && C(m), u(!1);
|
|
469
469
|
},
|
|
470
|
-
[
|
|
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
|
-
...
|
|
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
|
-
(
|
|
512
|
-
if (
|
|
513
|
-
const T = p?.find((N) => N.value ===
|
|
514
|
-
m(T ? (N) => N?.filter((E) => E.value !==
|
|
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
|
-
(
|
|
521
|
-
p?.find((N) => N.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
|
-
(
|
|
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((
|
|
533
|
+
return p.map((b, T) => {
|
|
534
534
|
if (d) {
|
|
535
535
|
const N = d({
|
|
536
|
-
option:
|
|
536
|
+
option: b,
|
|
537
537
|
type: "trigger",
|
|
538
538
|
onClose: () => {
|
|
539
|
-
I(
|
|
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?.(
|
|
549
|
+
N.preventDefault(), i?.(b);
|
|
550
550
|
},
|
|
551
551
|
onClose: (N) => {
|
|
552
|
-
N.preventDefault(), I(
|
|
552
|
+
N.preventDefault(), I(b);
|
|
553
553
|
},
|
|
554
554
|
isFocused: V(T),
|
|
555
|
-
children:
|
|
555
|
+
children: b.label
|
|
556
556
|
},
|
|
557
|
-
|
|
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, ...
|
|
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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"}
|