@tipp/ui 1.4.21 → 1.4.22

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.
@@ -0,0 +1,360 @@
1
+ import {
2
+ ScrollArea
3
+ } from "./chunk-ZKZDVS7G.js";
4
+ import {
5
+ Popover
6
+ } from "./chunk-5AVBYDPB.js";
7
+ import {
8
+ Flex
9
+ } from "./chunk-25HMMI7R.js";
10
+ import {
11
+ Grid
12
+ } from "./chunk-EGEQY3KT.js";
13
+ import {
14
+ Typo
15
+ } from "./chunk-52MVZ6AN.js";
16
+ import {
17
+ Button
18
+ } from "./chunk-U7JPP7WJ.js";
19
+ import {
20
+ CheckIcon
21
+ } from "./chunk-F77ES5Y3.js";
22
+ import {
23
+ AutoSizingInput
24
+ } from "./chunk-YJCCE5WP.js";
25
+ import {
26
+ Badge
27
+ } from "./chunk-EWD4AO5N.js";
28
+
29
+ // src/molecules/tag-selector.tsx
30
+ import {
31
+ useCallback,
32
+ useEffect,
33
+ useMemo,
34
+ useRef,
35
+ useState
36
+ } from "react";
37
+ import {
38
+ ChevronRightIcon,
39
+ Cross1Icon,
40
+ MagnifyingGlassIcon
41
+ } from "@radix-ui/react-icons";
42
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
43
+ var OPTION_HEIGHT = 32;
44
+ var DefaultDropdownContainer = (props) => {
45
+ return props.children;
46
+ };
47
+ function TagSelector(props) {
48
+ const {
49
+ options = [],
50
+ tagRender,
51
+ placeholder,
52
+ maxCount = 0,
53
+ DropdownContainer = DefaultDropdownContainer,
54
+ onChange,
55
+ size = "medium",
56
+ readOnly,
57
+ error
58
+ } = props;
59
+ const [selected, setSelected] = useState(props.selected || []);
60
+ const [value, setValue] = useState("");
61
+ const [focusIndex, setFocusIndex] = useState(null);
62
+ const [open, setOpen] = useState(false);
63
+ const [focus, setFocus] = useState(false);
64
+ const isInit = useRef(true);
65
+ const fieldRef = useRef(null);
66
+ const scrollRef = useRef(null);
67
+ const closeRef = useRef();
68
+ const onFocus = useCallback(() => {
69
+ clearTimeout(closeRef.current);
70
+ setFocus(true);
71
+ setOpen(true);
72
+ }, []);
73
+ const onBlur = useCallback(() => {
74
+ closeRef.current = setTimeout(() => {
75
+ setFocus(false);
76
+ setOpen(false);
77
+ setTimeout(() => {
78
+ setValue("");
79
+ }, 100);
80
+ }, 300);
81
+ }, []);
82
+ const onChangeValue = useCallback(
83
+ (e) => {
84
+ setValue(e.target.value);
85
+ },
86
+ []
87
+ );
88
+ const filteredOptions = useMemo(() => {
89
+ return options.filter((option) => {
90
+ return option.name.includes(value);
91
+ });
92
+ }, [options, value]);
93
+ const selectedItem = useMemo(() => {
94
+ const result = [];
95
+ selected.forEach((id) => {
96
+ const maybeItem = options.find((option) => option.id === id);
97
+ if (maybeItem)
98
+ result.push(maybeItem);
99
+ });
100
+ return result;
101
+ }, [options, selected]);
102
+ const onDelete = useCallback((id) => {
103
+ setSelected((prev) => prev.filter((el) => el !== id));
104
+ }, []);
105
+ const onSelect = useCallback(
106
+ (id) => {
107
+ if (maxCount && selected.length + 1 > maxCount)
108
+ return;
109
+ setSelected((prev) => [...prev, id]);
110
+ },
111
+ [maxCount, selected]
112
+ );
113
+ const toggleItem = useCallback(
114
+ (id) => {
115
+ if (selected.includes(id)) {
116
+ onDelete(id);
117
+ } else {
118
+ onSelect(id);
119
+ }
120
+ },
121
+ [onDelete, onSelect, selected]
122
+ );
123
+ const setScroll = useCallback((index) => {
124
+ if (scrollRef.current) {
125
+ const scrollTop = scrollRef.current.scrollTop;
126
+ const clientHeight = scrollRef.current.clientHeight;
127
+ const focusTop = index * OPTION_HEIGHT;
128
+ if (focusTop < scrollTop) {
129
+ scrollRef.current.scrollTop = focusTop;
130
+ } else if (focusTop + OPTION_HEIGHT > scrollTop + clientHeight) {
131
+ scrollRef.current.scrollTop = focusTop + OPTION_HEIGHT - clientHeight;
132
+ }
133
+ }
134
+ }, []);
135
+ const handleKeyDown = useCallback(
136
+ (e) => {
137
+ var _a;
138
+ const key = e.key;
139
+ switch (key) {
140
+ case "ArrowDown": {
141
+ e.preventDefault();
142
+ let newFocus = 0;
143
+ if (typeof focusIndex === "number") {
144
+ newFocus = focusIndex + 1 >= options.length ? 0 : focusIndex + 1;
145
+ }
146
+ setFocusIndex(newFocus);
147
+ setScroll(newFocus);
148
+ break;
149
+ }
150
+ case "ArrowUp": {
151
+ e.preventDefault();
152
+ let newFocus = 0;
153
+ if (typeof focusIndex === "number") {
154
+ newFocus = focusIndex - 1 < 0 ? options.length - 1 : focusIndex - 1;
155
+ }
156
+ setFocusIndex(newFocus);
157
+ setScroll(newFocus);
158
+ break;
159
+ }
160
+ case "Enter":
161
+ setValue("");
162
+ if (focusIndex !== null) {
163
+ toggleItem((_a = filteredOptions[focusIndex]) == null ? void 0 : _a.id);
164
+ }
165
+ break;
166
+ case "Backspace":
167
+ if (value.length === 0) {
168
+ setSelected((prev) => prev.slice(0, -1));
169
+ }
170
+ break;
171
+ case "Escape":
172
+ setOpen(false);
173
+ break;
174
+ }
175
+ },
176
+ [
177
+ focusIndex,
178
+ value.length,
179
+ setScroll,
180
+ options.length,
181
+ toggleItem,
182
+ filteredOptions
183
+ ]
184
+ );
185
+ const placeholderVisible = useMemo(() => {
186
+ if (selectedItem.length)
187
+ return false;
188
+ if (value)
189
+ return false;
190
+ if (focus)
191
+ return false;
192
+ return true;
193
+ }, [focus, selectedItem.length, value]);
194
+ useEffect(() => {
195
+ if (isInit.current) {
196
+ return;
197
+ }
198
+ onChange == null ? void 0 : onChange(selected);
199
+ }, [[...selected].sort().join(",")]);
200
+ useEffect(() => {
201
+ if (isInit.current) {
202
+ return;
203
+ }
204
+ setSelected(props.selected || []);
205
+ }, [[...props.selected || []].sort().join(",")]);
206
+ useEffect(() => {
207
+ setFocusIndex(null);
208
+ }, [open]);
209
+ useEffect(() => {
210
+ setFocusIndex(0);
211
+ }, [filteredOptions]);
212
+ useEffect(() => {
213
+ isInit.current = false;
214
+ }, []);
215
+ const badgeSize = useMemo(() => {
216
+ switch (size) {
217
+ case "large":
218
+ return "large";
219
+ case "medium":
220
+ case "small":
221
+ default:
222
+ return "small";
223
+ }
224
+ }, [size]);
225
+ const placeholderVariant = useMemo(() => {
226
+ switch (size) {
227
+ case "large":
228
+ return "subtitle";
229
+ case "medium":
230
+ default:
231
+ return "body";
232
+ }
233
+ }, [size]);
234
+ const focusClassName = focus ? " focused" : "";
235
+ const readOnlyClassName = readOnly ? " read-only" : "";
236
+ const errorClassName = error ? " error" : "";
237
+ const readonlyContent = /* @__PURE__ */ jsx(Flex, { gap: "1", children: selectedItem.map((item) => {
238
+ return tagRender ? tagRender(item) : /* @__PURE__ */ jsx(Badge, { size: badgeSize, children: item.name }, item.id);
239
+ }) });
240
+ const editContent = /* @__PURE__ */ jsxs(Fragment, { children: [
241
+ /* @__PURE__ */ jsxs(
242
+ Flex,
243
+ {
244
+ align: "center",
245
+ gap: "1",
246
+ maxWidth: "100%",
247
+ overflow: "hidden",
248
+ wrap: "wrap",
249
+ children: [
250
+ selectedItem.map((item) => {
251
+ return tagRender ? tagRender(item) : /* @__PURE__ */ jsxs(Badge, { size: badgeSize, children: [
252
+ item.name,
253
+ /* @__PURE__ */ jsx(
254
+ Button,
255
+ {
256
+ onClick: () => {
257
+ onDelete(item.id);
258
+ },
259
+ variant: "transparent",
260
+ children: /* @__PURE__ */ jsx(Cross1Icon, {})
261
+ }
262
+ )
263
+ ] }, item.id);
264
+ }),
265
+ placeholderVisible ? /* @__PURE__ */ jsx(Typo, { color: "gray", variant: placeholderVariant, children: placeholder }) : null,
266
+ /* @__PURE__ */ jsx(
267
+ AutoSizingInput,
268
+ {
269
+ onBlur,
270
+ onChange: onChangeValue,
271
+ onFocus,
272
+ onKeyDown: handleKeyDown,
273
+ ref: fieldRef,
274
+ value
275
+ }
276
+ )
277
+ ]
278
+ }
279
+ ),
280
+ focus ? /* @__PURE__ */ jsx(MagnifyingGlassIcon, {}) : /* @__PURE__ */ jsx(ChevronRightIcon, {})
281
+ ] });
282
+ return /* @__PURE__ */ jsxs(Popover.Root, { open: Boolean(filteredOptions.length) && open, children: [
283
+ /* @__PURE__ */ jsx(Popover.Trigger, { style: { position: "relative" }, children: /* @__PURE__ */ jsx(
284
+ Grid,
285
+ {
286
+ align: "center",
287
+ className: `tag-selector ${size} ${focusClassName}${readOnlyClassName}${errorClassName}`,
288
+ columns: "1fr auto",
289
+ gap: "1",
290
+ onClick: () => {
291
+ var _a;
292
+ return !readOnly && ((_a = fieldRef.current) == null ? void 0 : _a.focus());
293
+ },
294
+ children: readOnly ? readonlyContent : editContent
295
+ }
296
+ ) }),
297
+ /* @__PURE__ */ jsx(
298
+ Popover.Content,
299
+ {
300
+ onOpenAutoFocus: (e) => {
301
+ e.preventDefault();
302
+ },
303
+ children: /* @__PURE__ */ jsx(
304
+ DropdownContainer,
305
+ {
306
+ currentItem: filteredOptions[focusIndex || 0],
307
+ items: filteredOptions,
308
+ children: /* @__PURE__ */ jsx(
309
+ ScrollArea,
310
+ {
311
+ ref: scrollRef,
312
+ scrollbars: "vertical",
313
+ style: { height: OPTION_HEIGHT * 8 },
314
+ type: "auto",
315
+ children: /* @__PURE__ */ jsx(Flex, { direction: "column", children: filteredOptions.map((item, i) => {
316
+ const isSelected = Boolean(
317
+ selected.find((el) => el === item.id)
318
+ );
319
+ const isFocus = i === focusIndex;
320
+ return /* @__PURE__ */ jsx(
321
+ Button,
322
+ {
323
+ className: `tag-selector-button ${isFocus ? "focus" : ""}`,
324
+ onClick: () => {
325
+ var _a;
326
+ toggleItem(item.id);
327
+ (_a = fieldRef.current) == null ? void 0 : _a.focus();
328
+ },
329
+ onMouseEnter: () => {
330
+ setFocusIndex(i);
331
+ },
332
+ style: {
333
+ width: "100%",
334
+ background: isFocus ? "var(--accent-a3)" : void 0,
335
+ color: "var(--gray-12)",
336
+ fontWeight: 400,
337
+ boxShadow: "none"
338
+ },
339
+ variant: isSelected ? "soft" : "outline",
340
+ children: /* @__PURE__ */ jsxs(Flex, { justify: "between", width: "100%", children: [
341
+ item.name,
342
+ isSelected ? /* @__PURE__ */ jsx(CheckIcon, {}) : null
343
+ ] })
344
+ },
345
+ item.id
346
+ );
347
+ }) })
348
+ }
349
+ )
350
+ }
351
+ )
352
+ }
353
+ )
354
+ ] });
355
+ }
356
+
357
+ export {
358
+ TagSelector
359
+ };
360
+ //# sourceMappingURL=chunk-ZCAMAL6P.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/molecules/tag-selector.tsx"],"sourcesContent":["import React, {\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport {\n ChevronRightIcon,\n Cross1Icon,\n MagnifyingGlassIcon,\n} from '@radix-ui/react-icons';\nimport { Popover } from '../atoms/popover';\nimport { Flex } from '../atoms/flex';\nimport { Button } from '../atoms/button';\nimport type { BadgeProps } from '../atoms/badge';\nimport { Badge } from '../atoms/badge';\nimport { CheckIcon } from '../icon';\nimport { ScrollArea } from '../atoms/scroll-area';\nimport { Grid } from '../atoms/grid';\nimport type { TypoProps } from '../atoms';\nimport { AutoSizingInput, Typo } from '../atoms';\n\ntype ID = string;\ninterface Item {\n name: string;\n id: ID;\n}\n\nconst OPTION_HEIGHT = 32;\n\nexport interface TagSelectorProps<T extends Item> {\n options?: T[];\n selected?: ID[];\n placeholder?: string;\n disabled?: boolean;\n maxCount?: number;\n style?: React.CSSProperties;\n size?: 'large' | 'medium' | 'small';\n readOnly?: boolean;\n error?: boolean;\n\n onChange?: (selected: ID[]) => void;\n tagRender?: (item: T) => React.ReactElement;\n DropdownContainer?: DropdownContainer<T>;\n}\ntype DropdownContainer<T> = (props: {\n items: T[];\n children: React.ReactElement;\n currentItem?: T;\n}) => React.ReactElement;\n\nconst DefaultDropdownContainer = (props: {\n children: React.ReactElement;\n}): React.ReactElement => {\n return props.children;\n};\n\nexport function TagSelector<T extends Item>(\n props: TagSelectorProps<T>\n): React.ReactElement {\n const {\n options = [],\n tagRender,\n placeholder,\n maxCount = 0,\n DropdownContainer = DefaultDropdownContainer,\n onChange,\n size = 'medium',\n readOnly,\n error,\n } = props;\n const [selected, setSelected] = useState<string[]>(props.selected || []);\n const [value, setValue] = useState<string>('');\n const [focusIndex, setFocusIndex] = useState<number | null>(null);\n const [open, setOpen] = useState(false);\n const [focus, setFocus] = useState(false);\n const isInit = useRef(true);\n\n const fieldRef = useRef<HTMLInputElement>(null);\n const scrollRef = useRef<HTMLDivElement>(null);\n\n const closeRef = useRef<ReturnType<typeof setTimeout>>();\n\n const onFocus = useCallback(() => {\n clearTimeout(closeRef.current);\n setFocus(true);\n setOpen(true);\n }, []);\n\n const onBlur = useCallback(() => {\n closeRef.current = setTimeout(() => {\n setFocus(false);\n setOpen(false);\n setTimeout(() => {\n setValue('');\n }, 100);\n }, 300);\n }, []);\n\n const onChangeValue = useCallback<React.ChangeEventHandler<HTMLInputElement>>(\n (e) => {\n setValue(e.target.value);\n },\n []\n );\n\n const filteredOptions = useMemo<T[]>(() => {\n return options.filter((option) => {\n return option.name.includes(value);\n });\n }, [options, value]);\n\n const selectedItem = useMemo<T[]>(() => {\n const result = [] as T[];\n selected.forEach((id) => {\n const maybeItem = options.find((option) => option.id === id);\n if (maybeItem) result.push(maybeItem);\n });\n return result;\n }, [options, selected]);\n\n const onDelete = useCallback((id: string) => {\n setSelected((prev) => prev.filter((el) => el !== id));\n }, []);\n\n const onSelect = useCallback(\n (id: string) => {\n if (maxCount && selected.length + 1 > maxCount) return;\n setSelected((prev) => [...prev, id]);\n },\n [maxCount, selected]\n );\n\n const toggleItem = useCallback(\n (id: string) => {\n if (selected.includes(id)) {\n onDelete(id);\n } else {\n onSelect(id);\n }\n },\n [onDelete, onSelect, selected]\n );\n\n const setScroll = useCallback((index: number): void => {\n if (scrollRef.current) {\n const scrollTop = scrollRef.current.scrollTop;\n const clientHeight = scrollRef.current.clientHeight;\n const focusTop = index * OPTION_HEIGHT;\n if (focusTop < scrollTop) {\n scrollRef.current.scrollTop = focusTop;\n } else if (focusTop + OPTION_HEIGHT > scrollTop + clientHeight) {\n scrollRef.current.scrollTop = focusTop + OPTION_HEIGHT - clientHeight;\n }\n }\n }, []);\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n const key = e.key;\n\n switch (key) {\n case 'ArrowDown': {\n e.preventDefault();\n let newFocus = 0;\n if (typeof focusIndex === 'number') {\n newFocus = focusIndex + 1 >= options.length ? 0 : focusIndex + 1;\n }\n setFocusIndex(newFocus);\n setScroll(newFocus);\n break;\n }\n\n case 'ArrowUp': {\n e.preventDefault();\n let newFocus = 0;\n if (typeof focusIndex === 'number') {\n newFocus = focusIndex - 1 < 0 ? options.length - 1 : focusIndex - 1;\n }\n setFocusIndex(newFocus);\n setScroll(newFocus);\n break;\n }\n\n case 'Enter':\n setValue('');\n if (focusIndex !== null) {\n toggleItem(filteredOptions[focusIndex]?.id);\n }\n break;\n\n case 'Backspace':\n if (value.length === 0) {\n setSelected((prev) => prev.slice(0, -1));\n }\n break;\n\n case 'Escape':\n setOpen(false);\n break;\n }\n },\n [\n focusIndex,\n value.length,\n setScroll,\n options.length,\n toggleItem,\n filteredOptions,\n ]\n );\n\n const placeholderVisible = useMemo(() => {\n if (selectedItem.length) return false;\n if (value) return false;\n if (focus) return false;\n return true;\n }, [focus, selectedItem.length, value]);\n\n useEffect(() => {\n if (isInit.current) {\n return;\n }\n onChange?.(selected);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- 주소값 변경 방지\n }, [[...selected].sort().join(',')]);\n\n useEffect(() => {\n if (isInit.current) {\n return;\n }\n setSelected(props.selected || []);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- 주소값 변경 방지\n }, [[...(props.selected || [])].sort().join(',')]);\n\n useEffect(() => {\n setFocusIndex(null);\n }, [open]);\n\n useEffect(() => {\n setFocusIndex(0);\n }, [filteredOptions]);\n\n useEffect(() => {\n isInit.current = false;\n }, []);\n\n const badgeSize = useMemo<BadgeProps['size']>(() => {\n switch (size) {\n case 'large':\n return 'large';\n case 'medium':\n case 'small':\n default:\n return 'small';\n }\n }, [size]);\n\n const placeholderVariant = useMemo<TypoProps['variant']>(() => {\n switch (size) {\n case 'large':\n return 'subtitle';\n case 'medium':\n default:\n return 'body';\n }\n }, [size]);\n\n const focusClassName = focus ? ' focused' : '';\n const readOnlyClassName = readOnly ? ' read-only' : '';\n const errorClassName = error ? ' error' : '';\n\n const readonlyContent = (\n <Flex gap=\"1\">\n {selectedItem.map((item) => {\n return tagRender ? (\n tagRender(item)\n ) : (\n <Badge key={item.id} size={badgeSize}>\n {item.name}\n </Badge>\n );\n })}\n </Flex>\n );\n\n const editContent = (\n <>\n <Flex\n align=\"center\"\n gap=\"1\"\n maxWidth=\"100%\"\n overflow=\"hidden\"\n wrap=\"wrap\"\n >\n {selectedItem.map((item) => {\n return tagRender ? (\n tagRender(item)\n ) : (\n <Badge key={item.id} size={badgeSize}>\n {item.name}\n <Button\n onClick={() => {\n onDelete(item.id);\n }}\n variant=\"transparent\"\n >\n <Cross1Icon />\n </Button>\n </Badge>\n );\n })}\n {placeholderVisible ? (\n <Typo color=\"gray\" variant={placeholderVariant}>\n {placeholder}\n </Typo>\n ) : null}\n <AutoSizingInput\n onBlur={onBlur}\n onChange={onChangeValue}\n onFocus={onFocus}\n onKeyDown={handleKeyDown}\n ref={fieldRef}\n value={value}\n />\n </Flex>\n {focus ? <MagnifyingGlassIcon /> : <ChevronRightIcon />}\n </>\n );\n return (\n <Popover.Root open={Boolean(filteredOptions.length) && open}>\n <Popover.Trigger style={{ position: 'relative' }}>\n <Grid\n align=\"center\"\n className={`tag-selector ${size} ${focusClassName}${readOnlyClassName}${errorClassName}`}\n columns=\"1fr auto\"\n gap=\"1\"\n onClick={() => !readOnly && fieldRef.current?.focus()}\n >\n {readOnly ? readonlyContent : editContent}\n </Grid>\n </Popover.Trigger>\n\n <Popover.Content\n onOpenAutoFocus={(e) => {\n e.preventDefault();\n }}\n >\n <DropdownContainer\n currentItem={filteredOptions[focusIndex || 0]}\n items={filteredOptions}\n >\n <ScrollArea\n ref={scrollRef}\n scrollbars=\"vertical\"\n style={{ height: OPTION_HEIGHT * 8 }}\n type=\"auto\"\n >\n <Flex direction=\"column\">\n {filteredOptions.map((item, i) => {\n const isSelected = Boolean(\n selected.find((el) => el === item.id)\n );\n const isFocus = i === focusIndex;\n\n return (\n <Button\n className={`tag-selector-button ${isFocus ? 'focus' : ''}`}\n key={item.id}\n onClick={() => {\n toggleItem(item.id);\n fieldRef.current?.focus();\n }}\n onMouseEnter={() => {\n setFocusIndex(i);\n }}\n style={{\n width: '100%',\n background: isFocus ? 'var(--accent-a3)' : undefined,\n color: 'var(--gray-12)',\n fontWeight: 400,\n boxShadow: 'none',\n }}\n variant={isSelected ? 'soft' : 'outline'}\n >\n <Flex justify=\"between\" width=\"100%\">\n {item.name}\n {isSelected ? <CheckIcon /> : null}\n </Flex>\n </Button>\n );\n })}\n </Flex>\n </ScrollArea>\n </DropdownContainer>\n </Popover.Content>\n </Popover.Root>\n );\n}\n"],"mappings":"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","names":[]}
package/dist/index.cjs CHANGED
@@ -1729,17 +1729,17 @@ function TagSelector(props) {
1729
1729
  placeholder,
1730
1730
  maxCount = 0,
1731
1731
  DropdownContainer = DefaultDropdownContainer,
1732
- onChange,
1733
1732
  size = "medium",
1734
1733
  readOnly,
1735
1734
  error
1736
1735
  } = props;
1737
- const [selected, setSelected] = (0, import_react26.useState)(props.selected || []);
1736
+ const [_selected, _setSelected] = (0, import_react26.useState)(props.selected || []);
1737
+ const selected = props.selected || _selected;
1738
+ const setSelected = props.onChange || _setSelected;
1738
1739
  const [value, setValue] = (0, import_react26.useState)("");
1739
1740
  const [focusIndex, setFocusIndex] = (0, import_react26.useState)(null);
1740
1741
  const [open, setOpen] = (0, import_react26.useState)(false);
1741
1742
  const [focus, setFocus] = (0, import_react26.useState)(false);
1742
- const isInit = (0, import_react26.useRef)(true);
1743
1743
  const fieldRef = (0, import_react26.useRef)(null);
1744
1744
  const scrollRef = (0, import_react26.useRef)(null);
1745
1745
  const closeRef = (0, import_react26.useRef)();
@@ -1777,16 +1777,19 @@ function TagSelector(props) {
1777
1777
  });
1778
1778
  return result;
1779
1779
  }, [options, selected]);
1780
- const onDelete = (0, import_react26.useCallback)((id) => {
1781
- setSelected((prev) => prev.filter((el) => el !== id));
1782
- }, []);
1780
+ const onDelete = (0, import_react26.useCallback)(
1781
+ (id) => {
1782
+ setSelected(selected.filter((el) => el !== id));
1783
+ },
1784
+ [selected, setSelected]
1785
+ );
1783
1786
  const onSelect = (0, import_react26.useCallback)(
1784
1787
  (id) => {
1785
1788
  if (maxCount && selected.length + 1 > maxCount)
1786
1789
  return;
1787
- setSelected((prev) => [...prev, id]);
1790
+ setSelected([...selected, id]);
1788
1791
  },
1789
- [maxCount, selected]
1792
+ [maxCount, selected, setSelected]
1790
1793
  );
1791
1794
  const toggleItem = (0, import_react26.useCallback)(
1792
1795
  (id) => {
@@ -1843,7 +1846,7 @@ function TagSelector(props) {
1843
1846
  break;
1844
1847
  case "Backspace":
1845
1848
  if (value.length === 0) {
1846
- setSelected((prev) => prev.slice(0, -1));
1849
+ setSelected(selected.slice(0, -1));
1847
1850
  }
1848
1851
  break;
1849
1852
  case "Escape":
@@ -1857,7 +1860,9 @@ function TagSelector(props) {
1857
1860
  setScroll,
1858
1861
  options.length,
1859
1862
  toggleItem,
1860
- filteredOptions
1863
+ filteredOptions,
1864
+ setSelected,
1865
+ selected
1861
1866
  ]
1862
1867
  );
1863
1868
  const placeholderVisible = (0, import_react26.useMemo)(() => {
@@ -1869,27 +1874,12 @@ function TagSelector(props) {
1869
1874
  return false;
1870
1875
  return true;
1871
1876
  }, [focus, selectedItem.length, value]);
1872
- (0, import_react26.useEffect)(() => {
1873
- if (isInit.current) {
1874
- return;
1875
- }
1876
- onChange == null ? void 0 : onChange(selected);
1877
- }, [[...selected].sort().join(",")]);
1878
- (0, import_react26.useEffect)(() => {
1879
- if (isInit.current) {
1880
- return;
1881
- }
1882
- setSelected(props.selected || []);
1883
- }, [[...props.selected || []].sort().join(",")]);
1884
1877
  (0, import_react26.useEffect)(() => {
1885
1878
  setFocusIndex(null);
1886
1879
  }, [open]);
1887
1880
  (0, import_react26.useEffect)(() => {
1888
1881
  setFocusIndex(0);
1889
1882
  }, [filteredOptions]);
1890
- (0, import_react26.useEffect)(() => {
1891
- isInit.current = false;
1892
- }, []);
1893
1883
  const badgeSize = (0, import_react26.useMemo)(() => {
1894
1884
  switch (size) {
1895
1885
  case "large":