@tipp/ui 1.4.18 → 1.4.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (81) hide show
  1. package/dist/atoms/field-error-wrapper.js +2 -2
  2. package/dist/atoms/index.js +61 -61
  3. package/dist/atoms/pagination.js +2 -2
  4. package/dist/chunk-2L5FFIKE.js +340 -0
  5. package/dist/chunk-2L5FFIKE.js.map +1 -0
  6. package/dist/chunk-3H4ZZDX6.js +347 -0
  7. package/dist/chunk-3H4ZZDX6.js.map +1 -0
  8. package/dist/chunk-4AJJGCHR.js +354 -0
  9. package/dist/chunk-4AJJGCHR.js.map +1 -0
  10. package/dist/chunk-4QAWEAMF.js +340 -0
  11. package/dist/chunk-4QAWEAMF.js.map +1 -0
  12. package/dist/chunk-73EV5JWL.js +343 -0
  13. package/dist/chunk-73EV5JWL.js.map +1 -0
  14. package/dist/chunk-DMK6META.js +341 -0
  15. package/dist/chunk-DMK6META.js.map +1 -0
  16. package/dist/chunk-DTWPFSUG.js +169 -0
  17. package/dist/chunk-DTWPFSUG.js.map +1 -0
  18. package/dist/chunk-E6DAU6RB.js +192 -0
  19. package/dist/chunk-E6DAU6RB.js.map +1 -0
  20. package/dist/chunk-FGOSHO7B.js +343 -0
  21. package/dist/chunk-FGOSHO7B.js.map +1 -0
  22. package/dist/chunk-FIYBLL2Z.js +128 -0
  23. package/dist/chunk-FIYBLL2Z.js.map +1 -0
  24. package/dist/chunk-G2IPPQWC.js +354 -0
  25. package/dist/chunk-G2IPPQWC.js.map +1 -0
  26. package/dist/chunk-HBAMB3GV.js +347 -0
  27. package/dist/chunk-HBAMB3GV.js.map +1 -0
  28. package/dist/chunk-I7R4T7IL.js +169 -0
  29. package/dist/chunk-I7R4T7IL.js.map +1 -0
  30. package/dist/chunk-IOLHHERX.js +341 -0
  31. package/dist/chunk-IOLHHERX.js.map +1 -0
  32. package/dist/chunk-IXDGNHNP.js +345 -0
  33. package/dist/chunk-IXDGNHNP.js.map +1 -0
  34. package/dist/chunk-JQZRRHYW.js +192 -0
  35. package/dist/chunk-JQZRRHYW.js.map +1 -0
  36. package/dist/chunk-JZFBW2BA.js +169 -0
  37. package/dist/chunk-JZFBW2BA.js.map +1 -0
  38. package/dist/chunk-KGKST4RN.js +97 -0
  39. package/dist/chunk-KGKST4RN.js.map +1 -0
  40. package/dist/chunk-MJ3D2VRP.js +97 -0
  41. package/dist/chunk-MJ3D2VRP.js.map +1 -0
  42. package/dist/chunk-N6TISQLQ.js +340 -0
  43. package/dist/chunk-N6TISQLQ.js.map +1 -0
  44. package/dist/chunk-RGO56OV2.js +164 -0
  45. package/dist/chunk-RGO56OV2.js.map +1 -0
  46. package/dist/chunk-RWJ7HBJY.js +128 -0
  47. package/dist/chunk-RWJ7HBJY.js.map +1 -0
  48. package/dist/chunk-TSXQG24Q.js +398 -0
  49. package/dist/chunk-TSXQG24Q.js.map +1 -0
  50. package/dist/chunk-UGCMQWPU.js +343 -0
  51. package/dist/chunk-UGCMQWPU.js.map +1 -0
  52. package/dist/chunk-UWVMOI5J.js +341 -0
  53. package/dist/chunk-UWVMOI5J.js.map +1 -0
  54. package/dist/chunk-W7HWGDR4.js +97 -0
  55. package/dist/chunk-W7HWGDR4.js.map +1 -0
  56. package/dist/chunk-WYUPB5P3.js +349 -0
  57. package/dist/chunk-WYUPB5P3.js.map +1 -0
  58. package/dist/index.cjs +53 -46
  59. package/dist/index.cjs.map +1 -1
  60. package/dist/index.css +5 -0
  61. package/dist/index.css.map +1 -1
  62. package/dist/index.js +74 -74
  63. package/dist/molecules/date-picker/index.js +2 -2
  64. package/dist/molecules/expand-table/index.js +26 -26
  65. package/dist/molecules/expand-table/row.js +25 -25
  66. package/dist/molecules/form.d.cts +1 -1
  67. package/dist/molecules/form.d.ts +1 -1
  68. package/dist/molecules/form.js +2 -2
  69. package/dist/molecules/index.cjs +53 -46
  70. package/dist/molecules/index.cjs.map +1 -1
  71. package/dist/molecules/index.js +31 -31
  72. package/dist/molecules/learning-post.js +3 -3
  73. package/dist/molecules/navigation.js +26 -26
  74. package/dist/molecules/stepper.js +3 -3
  75. package/dist/molecules/tag-selector.cjs +53 -46
  76. package/dist/molecules/tag-selector.cjs.map +1 -1
  77. package/dist/molecules/tag-selector.d.cts +1 -0
  78. package/dist/molecules/tag-selector.d.ts +1 -0
  79. package/dist/molecules/tag-selector.js +26 -26
  80. package/package.json +1 -1
  81. package/src/molecules/tag-selector.tsx +66 -42
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  FieldErrorWrapper
3
- } from "../chunk-DJN2IEY6.js";
4
- import "../chunk-25HMMI7R.js";
3
+ } from "../chunk-QDZS4B6A.js";
5
4
  import "../chunk-52MVZ6AN.js";
5
+ import "../chunk-25HMMI7R.js";
6
6
  import "../chunk-N552FDTV.js";
7
7
  export {
8
8
  FieldErrorWrapper
@@ -1,7 +1,26 @@
1
1
  import "../chunk-KTVZ4KLX.js";
2
2
  import {
3
3
  Form
4
- } from "../chunk-OHBL3CTQ.js";
4
+ } from "../chunk-DWCPI2UN.js";
5
+ import {
6
+ TextArea
7
+ } from "../chunk-TTYPIX4R.js";
8
+ import {
9
+ TextField
10
+ } from "../chunk-YY45YYJE.js";
11
+ import {
12
+ ToastContainer,
13
+ toast
14
+ } from "../chunk-CYYWMYE7.js";
15
+ import {
16
+ Select
17
+ } from "../chunk-3JRNKBMN.js";
18
+ import {
19
+ Separator
20
+ } from "../chunk-HYITAA4J.js";
21
+ import {
22
+ Skeleton
23
+ } from "../chunk-5H3YPCZK.js";
5
24
  import {
6
25
  Spinner
7
26
  } from "../chunk-FR2GDOU2.js";
@@ -18,15 +37,14 @@ import {
18
37
  Tabs
19
38
  } from "../chunk-5ZITU5L7.js";
20
39
  import {
21
- TextArea
22
- } from "../chunk-TTYPIX4R.js";
40
+ Progress
41
+ } from "../chunk-365QMK4D.js";
23
42
  import {
24
- TextField
25
- } from "../chunk-YY45YYJE.js";
43
+ Quote
44
+ } from "../chunk-YO3BQW6S.js";
26
45
  import {
27
- ToastContainer,
28
- toast
29
- } from "../chunk-CYYWMYE7.js";
46
+ RadioCards
47
+ } from "../chunk-6IVCARWS.js";
30
48
  import {
31
49
  RadioGroup
32
50
  } from "../chunk-6DJOIRMF.js";
@@ -43,14 +61,8 @@ import {
43
61
  SegmentedControl
44
62
  } from "../chunk-TVDKGMBI.js";
45
63
  import {
46
- Select
47
- } from "../chunk-3JRNKBMN.js";
48
- import {
49
- Separator
50
- } from "../chunk-HYITAA4J.js";
51
- import {
52
- Skeleton
53
- } from "../chunk-5H3YPCZK.js";
64
+ HoverCard
65
+ } from "../chunk-O3T3TM3V.js";
54
66
  import {
55
67
  Inset
56
68
  } from "../chunk-XQOL7UBI.js";
@@ -62,25 +74,37 @@ import {
62
74
  } from "../chunk-SIM6HKVI.js";
63
75
  import {
64
76
  Pagination
65
- } from "../chunk-3GR5ZATM.js";
77
+ } from "../chunk-RWJ7HBJY.js";
78
+ import {
79
+ IconButton
80
+ } from "../chunk-O3DNDMV3.js";
66
81
  import {
67
82
  Popover
68
83
  } from "../chunk-5AVBYDPB.js";
69
84
  import {
70
- Progress
71
- } from "../chunk-365QMK4D.js";
85
+ Content,
86
+ Drawer,
87
+ Root,
88
+ Trigger
89
+ } from "../chunk-UC627KGO.js";
72
90
  import {
73
- Quote
74
- } from "../chunk-YO3BQW6S.js";
91
+ DropdownMenu
92
+ } from "../chunk-4WFMOFN2.js";
75
93
  import {
76
- RadioCards
77
- } from "../chunk-6IVCARWS.js";
94
+ EllipsisTooltip
95
+ } from "../chunk-WKFZ5MMN.js";
96
+ import {
97
+ Tooltip
98
+ } from "../chunk-ACVANQJ4.js";
78
99
  import {
79
100
  Em
80
101
  } from "../chunk-2DZ2Y3JI.js";
81
102
  import {
82
103
  FieldErrorWrapper
83
- } from "../chunk-DJN2IEY6.js";
104
+ } from "../chunk-QDZS4B6A.js";
105
+ import {
106
+ Typo
107
+ } from "../chunk-52MVZ6AN.js";
84
108
  import {
85
109
  Flex
86
110
  } from "../chunk-25HMMI7R.js";
@@ -91,11 +115,14 @@ import {
91
115
  Heading
92
116
  } from "../chunk-HK224ADT.js";
93
117
  import {
94
- HoverCard
95
- } from "../chunk-O3T3TM3V.js";
118
+ CheckboxCards
119
+ } from "../chunk-MIMJ7LON.js";
96
120
  import {
97
- IconButton
98
- } from "../chunk-O3DNDMV3.js";
121
+ CheckboxGroup
122
+ } from "../chunk-IQEEPHOY.js";
123
+ import {
124
+ Checkbox
125
+ } from "../chunk-LHCDPZ5E.js";
99
126
  import {
100
127
  Code
101
128
  } from "../chunk-OHMOP5PV.js";
@@ -112,23 +139,14 @@ import {
112
139
  Dialog
113
140
  } from "../chunk-2VD5Y72N.js";
114
141
  import {
115
- Content,
116
- Drawer,
117
- Root,
118
- Trigger
119
- } from "../chunk-UC627KGO.js";
120
- import {
121
- DropdownMenu
122
- } from "../chunk-4WFMOFN2.js";
123
- import {
124
- EllipsisTooltip
125
- } from "../chunk-WKFZ5MMN.js";
142
+ Avatar
143
+ } from "../chunk-3SSSCLJ5.js";
126
144
  import {
127
- Tooltip
128
- } from "../chunk-ACVANQJ4.js";
145
+ Badge
146
+ } from "../chunk-EWD4AO5N.js";
129
147
  import {
130
- Typo
131
- } from "../chunk-52MVZ6AN.js";
148
+ Blockquote
149
+ } from "../chunk-YGL6SWKN.js";
132
150
  import {
133
151
  Box
134
152
  } from "../chunk-4Y5BEXVN.js";
@@ -143,15 +161,6 @@ import {
143
161
  import {
144
162
  Card
145
163
  } from "../chunk-UVKNLJDZ.js";
146
- import {
147
- CheckboxCards
148
- } from "../chunk-MIMJ7LON.js";
149
- import {
150
- CheckboxGroup
151
- } from "../chunk-IQEEPHOY.js";
152
- import {
153
- Checkbox
154
- } from "../chunk-LHCDPZ5E.js";
155
164
  import "../chunk-F77ES5Y3.js";
156
165
  import {
157
166
  AlertDialog
@@ -162,15 +171,6 @@ import {
162
171
  import {
163
172
  AutoSizingInput
164
173
  } from "../chunk-YJCCE5WP.js";
165
- import {
166
- Avatar
167
- } from "../chunk-3SSSCLJ5.js";
168
- import {
169
- Badge
170
- } from "../chunk-EWD4AO5N.js";
171
- import {
172
- Blockquote
173
- } from "../chunk-YGL6SWKN.js";
174
174
  import "../chunk-N552FDTV.js";
175
175
  export {
176
176
  AlertDialog,
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  Pagination
3
- } from "../chunk-3GR5ZATM.js";
4
- import "../chunk-25HMMI7R.js";
3
+ } from "../chunk-RWJ7HBJY.js";
5
4
  import "../chunk-O3DNDMV3.js";
6
5
  import "../chunk-52MVZ6AN.js";
6
+ import "../chunk-25HMMI7R.js";
7
7
  import "../chunk-F77ES5Y3.js";
8
8
  import "../chunk-N552FDTV.js";
9
9
  export {
@@ -0,0 +1,340 @@
1
+ import {
2
+ ScrollArea
3
+ } from "./chunk-ZKZDVS7G.js";
4
+ import {
5
+ Popover
6
+ } from "./chunk-5AVBYDPB.js";
7
+ import {
8
+ AutoSizingInput
9
+ } from "./chunk-YJCCE5WP.js";
10
+ import {
11
+ Grid
12
+ } from "./chunk-EGEQY3KT.js";
13
+ import {
14
+ Badge
15
+ } from "./chunk-EWD4AO5N.js";
16
+ import {
17
+ Button
18
+ } from "./chunk-U7JPP7WJ.js";
19
+ import {
20
+ Flex
21
+ } from "./chunk-25HMMI7R.js";
22
+ import {
23
+ Typo
24
+ } from "./chunk-52MVZ6AN.js";
25
+ import {
26
+ CheckIcon
27
+ } from "./chunk-F77ES5Y3.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 { 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
+ } = props;
57
+ const [selected, setSelected] = useState(props.selected || []);
58
+ const [value, setValue] = useState("");
59
+ const [focusIndex, setFocusIndex] = useState(null);
60
+ const [open, setOpen] = useState(false);
61
+ const [focus, setFocus] = useState(false);
62
+ const fieldRef = useRef(null);
63
+ const scrollRef = useRef(null);
64
+ const closeRef = useRef();
65
+ const onFocus = useCallback(() => {
66
+ clearTimeout(closeRef.current);
67
+ setFocus(true);
68
+ setOpen(true);
69
+ }, []);
70
+ const onBlur = useCallback(() => {
71
+ closeRef.current = setTimeout(() => {
72
+ setFocus(false);
73
+ setOpen(false);
74
+ setTimeout(() => {
75
+ setValue("");
76
+ }, 100);
77
+ }, 300);
78
+ }, []);
79
+ const onChangeValue = useCallback(
80
+ (e) => {
81
+ setValue(e.target.value);
82
+ },
83
+ []
84
+ );
85
+ const filteredOptions = useMemo(() => {
86
+ return options.filter((option) => {
87
+ return option.name.includes(value);
88
+ });
89
+ }, [options, value]);
90
+ const selectedItem = useMemo(() => {
91
+ const result = [];
92
+ selected.forEach((id) => {
93
+ const maybeItem = options.find((option) => option.id === id);
94
+ if (maybeItem)
95
+ result.push(maybeItem);
96
+ });
97
+ return result;
98
+ }, [options, selected]);
99
+ const onDelete = useCallback((id) => {
100
+ setSelected((prev) => prev.filter((el) => el !== id));
101
+ }, []);
102
+ const onSelect = useCallback(
103
+ (id) => {
104
+ if (maxCount && selected.length + 1 > maxCount)
105
+ return;
106
+ setSelected((prev) => [...prev, id]);
107
+ },
108
+ [maxCount, selected]
109
+ );
110
+ const toggleItem = useCallback(
111
+ (id) => {
112
+ if (selected.includes(id)) {
113
+ onDelete(id);
114
+ } else {
115
+ onSelect(id);
116
+ }
117
+ },
118
+ [onDelete, onSelect, selected]
119
+ );
120
+ const setScroll = useCallback((index) => {
121
+ if (scrollRef.current) {
122
+ const scrollTop = scrollRef.current.scrollTop;
123
+ const clientHeight = scrollRef.current.clientHeight;
124
+ const focusTop = index * OPTION_HEIGHT;
125
+ if (focusTop < scrollTop) {
126
+ scrollRef.current.scrollTop = focusTop;
127
+ } else if (focusTop + OPTION_HEIGHT > scrollTop + clientHeight) {
128
+ scrollRef.current.scrollTop = focusTop + OPTION_HEIGHT - clientHeight;
129
+ }
130
+ }
131
+ }, []);
132
+ const handleKeyDown = useCallback(
133
+ (e) => {
134
+ var _a;
135
+ const key = e.key;
136
+ switch (key) {
137
+ case "ArrowDown": {
138
+ e.preventDefault();
139
+ let newFocus = 0;
140
+ if (typeof focusIndex === "number") {
141
+ newFocus = focusIndex + 1 >= options.length ? 0 : focusIndex + 1;
142
+ }
143
+ setFocusIndex(newFocus);
144
+ setScroll(newFocus);
145
+ break;
146
+ }
147
+ case "ArrowUp": {
148
+ e.preventDefault();
149
+ let newFocus = 0;
150
+ if (typeof focusIndex === "number") {
151
+ newFocus = focusIndex - 1 < 0 ? options.length - 1 : focusIndex - 1;
152
+ }
153
+ setFocusIndex(newFocus);
154
+ setScroll(newFocus);
155
+ break;
156
+ }
157
+ case "Enter":
158
+ setValue("");
159
+ if (focusIndex !== null) {
160
+ toggleItem((_a = filteredOptions[focusIndex]) == null ? void 0 : _a.id);
161
+ }
162
+ break;
163
+ case "Backspace":
164
+ if (value.length === 0) {
165
+ setSelected((prev) => prev.slice(0, -1));
166
+ }
167
+ break;
168
+ case "Escape":
169
+ setOpen(false);
170
+ break;
171
+ }
172
+ },
173
+ [
174
+ focusIndex,
175
+ value.length,
176
+ setScroll,
177
+ options.length,
178
+ toggleItem,
179
+ filteredOptions
180
+ ]
181
+ );
182
+ const placeholderVisible = useMemo(() => {
183
+ if (selectedItem.length)
184
+ return false;
185
+ if (value)
186
+ return false;
187
+ if (focus)
188
+ return false;
189
+ return true;
190
+ }, [focus, selectedItem.length, value]);
191
+ useEffect(() => {
192
+ onChange == null ? void 0 : onChange(selected);
193
+ }, [[...selected].sort().join(",")]);
194
+ useEffect(() => {
195
+ setSelected(props.selected || []);
196
+ }, [[...props.selected || []].sort().join(",")]);
197
+ useEffect(() => {
198
+ setFocusIndex(null);
199
+ }, [open]);
200
+ useEffect(() => {
201
+ setFocusIndex(0);
202
+ }, [filteredOptions]);
203
+ const badgeSize = useMemo(() => {
204
+ switch (size) {
205
+ case "large":
206
+ return "large";
207
+ case "medium":
208
+ case "small":
209
+ default:
210
+ return "small";
211
+ }
212
+ }, [size]);
213
+ const placeholderVariant = useMemo(() => {
214
+ switch (size) {
215
+ case "large":
216
+ return "subtitle";
217
+ case "medium":
218
+ default:
219
+ return "body";
220
+ }
221
+ }, [size]);
222
+ return /* @__PURE__ */ jsxs(Popover.Root, { open: Boolean(filteredOptions.length) && open, children: [
223
+ /* @__PURE__ */ jsx(Popover.Trigger, { children: /* @__PURE__ */ jsxs(
224
+ Grid,
225
+ {
226
+ align: "center",
227
+ className: `tag-selector ${focus ? "focused" : ""} ${size}`,
228
+ columns: "1fr auto",
229
+ gap: "1",
230
+ onClick: () => {
231
+ var _a;
232
+ return (_a = fieldRef.current) == null ? void 0 : _a.focus();
233
+ },
234
+ children: [
235
+ /* @__PURE__ */ jsxs(
236
+ Flex,
237
+ {
238
+ align: "center",
239
+ gap: "1",
240
+ maxWidth: "100%",
241
+ overflow: "hidden",
242
+ wrap: "wrap",
243
+ children: [
244
+ selectedItem.map((item) => {
245
+ return tagRender ? tagRender(item) : /* @__PURE__ */ jsxs(Badge, { size: badgeSize, children: [
246
+ item.name,
247
+ /* @__PURE__ */ jsx(
248
+ Button,
249
+ {
250
+ onClick: () => {
251
+ onDelete(item.id);
252
+ },
253
+ variant: "transparent",
254
+ children: /* @__PURE__ */ jsx(Cross1Icon, {})
255
+ }
256
+ )
257
+ ] }, item.id);
258
+ }),
259
+ placeholderVisible ? /* @__PURE__ */ jsx(Typo, { color: "gray", variant: placeholderVariant, children: placeholder }) : null,
260
+ /* @__PURE__ */ jsx(
261
+ AutoSizingInput,
262
+ {
263
+ onBlur,
264
+ onChange: onChangeValue,
265
+ onFocus,
266
+ onKeyDown: handleKeyDown,
267
+ ref: fieldRef,
268
+ value
269
+ }
270
+ )
271
+ ]
272
+ }
273
+ ),
274
+ focus ? /* @__PURE__ */ jsx(MagnifyingGlassIcon, {}) : /* @__PURE__ */ jsx(ChevronRightIcon, {})
275
+ ]
276
+ }
277
+ ) }),
278
+ /* @__PURE__ */ jsx(
279
+ Popover.Content,
280
+ {
281
+ onOpenAutoFocus: (e) => {
282
+ e.preventDefault();
283
+ },
284
+ children: /* @__PURE__ */ jsx(
285
+ DropdownContainer,
286
+ {
287
+ currentItem: filteredOptions[focusIndex || 0],
288
+ items: filteredOptions,
289
+ children: /* @__PURE__ */ jsx(
290
+ ScrollArea,
291
+ {
292
+ ref: scrollRef,
293
+ scrollbars: "vertical",
294
+ style: { height: OPTION_HEIGHT * 8 },
295
+ type: "auto",
296
+ children: /* @__PURE__ */ jsx(Flex, { direction: "column", children: filteredOptions.map((item, i) => {
297
+ const isSelected = Boolean(
298
+ selected.find((el) => el === item.id)
299
+ );
300
+ const isFocus = i === focusIndex;
301
+ return /* @__PURE__ */ jsx(
302
+ Button,
303
+ {
304
+ onClick: () => {
305
+ var _a;
306
+ toggleItem(item.id);
307
+ (_a = fieldRef.current) == null ? void 0 : _a.focus();
308
+ },
309
+ onMouseEnter: () => {
310
+ setFocusIndex(i);
311
+ },
312
+ style: {
313
+ width: "100%",
314
+ background: isFocus ? "var(--accent-a3)" : void 0,
315
+ color: "var(--gray-12)",
316
+ fontWeight: 400,
317
+ boxShadow: "none"
318
+ },
319
+ variant: isSelected ? "soft" : "outline",
320
+ children: /* @__PURE__ */ jsxs(Flex, { justify: "between", width: "100%", children: [
321
+ item.name,
322
+ isSelected ? /* @__PURE__ */ jsx(CheckIcon, {}) : null
323
+ ] })
324
+ },
325
+ item.id
326
+ );
327
+ }) })
328
+ }
329
+ )
330
+ }
331
+ )
332
+ }
333
+ )
334
+ ] });
335
+ }
336
+
337
+ export {
338
+ TagSelector
339
+ };
340
+ //# sourceMappingURL=chunk-2L5FFIKE.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\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 } = 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\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 onChange?.(selected);\n // eslint-disable-next-line react-hooks/exhaustive-deps -- 주소값 변경 방지\n }, [[...selected].sort().join(',')]);\n\n useEffect(() => {\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 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 return (\n <Popover.Root open={Boolean(filteredOptions.length) && open}>\n <Popover.Trigger>\n <Grid\n align=\"center\"\n className={`tag-selector ${focus ? 'focused' : ''} ${size}`}\n columns=\"1fr auto\"\n gap=\"1\"\n onClick={() => fieldRef.current?.focus()}\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 </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 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":[]}