@tipp/ui 1.4.21 → 1.4.23
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/atoms/index.cjs +20 -4
- package/dist/atoms/index.cjs.map +1 -1
- package/dist/atoms/index.js +2 -2
- package/dist/atoms/text-area.cjs +10 -2
- package/dist/atoms/text-area.cjs.map +1 -1
- package/dist/atoms/text-area.js +1 -1
- package/dist/atoms/text-field.cjs +10 -2
- package/dist/atoms/text-field.cjs.map +1 -1
- package/dist/atoms/text-field.js +1 -1
- package/dist/chunk-23P5I2JR.js +192 -0
- package/dist/chunk-23P5I2JR.js.map +1 -0
- package/dist/chunk-52V6NWNP.js +350 -0
- package/dist/chunk-52V6NWNP.js.map +1 -0
- package/dist/chunk-7SOSBA77.js +40 -0
- package/dist/chunk-7SOSBA77.js.map +1 -0
- package/dist/chunk-IYEPU2SQ.js +350 -0
- package/dist/chunk-IYEPU2SQ.js.map +1 -0
- package/dist/chunk-SNHHJCBS.js +36 -0
- package/dist/chunk-SNHHJCBS.js.map +1 -0
- package/dist/chunk-SQ7HPPKD.js +360 -0
- package/dist/chunk-SQ7HPPKD.js.map +1 -0
- package/dist/chunk-UEELYPYP.js +40 -0
- package/dist/chunk-UEELYPYP.js.map +1 -0
- package/dist/chunk-WNYDAKKK.js +350 -0
- package/dist/chunk-WNYDAKKK.js.map +1 -0
- package/dist/chunk-XBI2YSRP.js +350 -0
- package/dist/chunk-XBI2YSRP.js.map +1 -0
- package/dist/chunk-YKVMEKVZ.js +36 -0
- package/dist/chunk-YKVMEKVZ.js.map +1 -0
- package/dist/chunk-ZCAMAL6P.js +360 -0
- package/dist/chunk-ZCAMAL6P.js.map +1 -0
- package/dist/index.cjs +35 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +3 -3
- package/dist/molecules/expand-table/index.js +2 -2
- package/dist/molecules/expand-table/row.js +2 -2
- package/dist/molecules/index.cjs +15 -25
- package/dist/molecules/index.cjs.map +1 -1
- package/dist/molecules/index.js +3 -3
- package/dist/molecules/navigation.js +2 -2
- package/dist/molecules/tag-selector.cjs +15 -25
- package/dist/molecules/tag-selector.cjs.map +1 -1
- package/dist/molecules/tag-selector.js +3 -3
- package/package.json +1 -1
- package/src/atoms/text-area.tsx +11 -2
- package/src/atoms/text-field.tsx +12 -2
- package/src/molecules/tag-selector.tsx +15 -30
|
@@ -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
|
@@ -656,7 +656,7 @@ var import_react12 = require("react");
|
|
|
656
656
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
657
657
|
var TextArea = (0, import_react12.forwardRef)(
|
|
658
658
|
(props, ref) => {
|
|
659
|
-
const _a = props, { error, style } = _a, rest = __objRest(_a, ["error", "style"]);
|
|
659
|
+
const _a = props, { error, style, className } = _a, rest = __objRest(_a, ["error", "style", "className"]);
|
|
660
660
|
const fieldStyle = (0, import_react12.useMemo)(() => {
|
|
661
661
|
if (!style && !error)
|
|
662
662
|
return void 0;
|
|
@@ -665,7 +665,15 @@ var TextArea = (0, import_react12.forwardRef)(
|
|
|
665
665
|
} : {};
|
|
666
666
|
return __spreadValues(__spreadValues({}, style || {}), errorStyle);
|
|
667
667
|
}, [error, style]);
|
|
668
|
-
|
|
668
|
+
const classNameStr = error ? `error ${className}` : className;
|
|
669
|
+
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
670
|
+
import_themes45.TextArea,
|
|
671
|
+
__spreadProps(__spreadValues({}, rest), {
|
|
672
|
+
className: classNameStr,
|
|
673
|
+
ref,
|
|
674
|
+
style: fieldStyle
|
|
675
|
+
})
|
|
676
|
+
);
|
|
669
677
|
}
|
|
670
678
|
);
|
|
671
679
|
TextArea.displayName = "TextArea";
|
|
@@ -700,7 +708,7 @@ var import_themes47 = require("@radix-ui/themes");
|
|
|
700
708
|
var import_react14 = require("react");
|
|
701
709
|
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
702
710
|
var Root3 = (0, import_react14.forwardRef)((props, ref) => {
|
|
703
|
-
const _a = props, { error, style } = _a, rest = __objRest(_a, ["error", "style"]);
|
|
711
|
+
const _a = props, { error, style, className } = _a, rest = __objRest(_a, ["error", "style", "className"]);
|
|
704
712
|
const fieldStyle = (0, import_react14.useMemo)(() => {
|
|
705
713
|
if (!style && !error)
|
|
706
714
|
return void 0;
|
|
@@ -709,7 +717,15 @@ var Root3 = (0, import_react14.forwardRef)((props, ref) => {
|
|
|
709
717
|
};
|
|
710
718
|
return __spreadValues(__spreadValues({}, style || {}), errorStyle);
|
|
711
719
|
}, [error, style]);
|
|
712
|
-
|
|
720
|
+
const classNameStr = error ? `error ${className}` : className;
|
|
721
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
722
|
+
import_themes47.TextField.Root,
|
|
723
|
+
__spreadValues({
|
|
724
|
+
className: classNameStr,
|
|
725
|
+
ref,
|
|
726
|
+
style: fieldStyle
|
|
727
|
+
}, rest)
|
|
728
|
+
);
|
|
713
729
|
});
|
|
714
730
|
Root3.displayName = "TextField.Root";
|
|
715
731
|
var TextField = { Root: Root3, Slot: import_themes47.TextField.Slot };
|
|
@@ -1729,17 +1745,17 @@ function TagSelector(props) {
|
|
|
1729
1745
|
placeholder,
|
|
1730
1746
|
maxCount = 0,
|
|
1731
1747
|
DropdownContainer = DefaultDropdownContainer,
|
|
1732
|
-
onChange,
|
|
1733
1748
|
size = "medium",
|
|
1734
1749
|
readOnly,
|
|
1735
1750
|
error
|
|
1736
1751
|
} = props;
|
|
1737
|
-
const [
|
|
1752
|
+
const [_selected, _setSelected] = (0, import_react26.useState)(props.selected || []);
|
|
1753
|
+
const selected = props.selected || _selected;
|
|
1754
|
+
const setSelected = props.onChange || _setSelected;
|
|
1738
1755
|
const [value, setValue] = (0, import_react26.useState)("");
|
|
1739
1756
|
const [focusIndex, setFocusIndex] = (0, import_react26.useState)(null);
|
|
1740
1757
|
const [open, setOpen] = (0, import_react26.useState)(false);
|
|
1741
1758
|
const [focus, setFocus] = (0, import_react26.useState)(false);
|
|
1742
|
-
const isInit = (0, import_react26.useRef)(true);
|
|
1743
1759
|
const fieldRef = (0, import_react26.useRef)(null);
|
|
1744
1760
|
const scrollRef = (0, import_react26.useRef)(null);
|
|
1745
1761
|
const closeRef = (0, import_react26.useRef)();
|
|
@@ -1777,16 +1793,19 @@ function TagSelector(props) {
|
|
|
1777
1793
|
});
|
|
1778
1794
|
return result;
|
|
1779
1795
|
}, [options, selected]);
|
|
1780
|
-
const onDelete = (0, import_react26.useCallback)(
|
|
1781
|
-
|
|
1782
|
-
|
|
1796
|
+
const onDelete = (0, import_react26.useCallback)(
|
|
1797
|
+
(id) => {
|
|
1798
|
+
setSelected(selected.filter((el) => el !== id));
|
|
1799
|
+
},
|
|
1800
|
+
[selected, setSelected]
|
|
1801
|
+
);
|
|
1783
1802
|
const onSelect = (0, import_react26.useCallback)(
|
|
1784
1803
|
(id) => {
|
|
1785
1804
|
if (maxCount && selected.length + 1 > maxCount)
|
|
1786
1805
|
return;
|
|
1787
|
-
setSelected(
|
|
1806
|
+
setSelected([...selected, id]);
|
|
1788
1807
|
},
|
|
1789
|
-
[maxCount, selected]
|
|
1808
|
+
[maxCount, selected, setSelected]
|
|
1790
1809
|
);
|
|
1791
1810
|
const toggleItem = (0, import_react26.useCallback)(
|
|
1792
1811
|
(id) => {
|
|
@@ -1843,7 +1862,7 @@ function TagSelector(props) {
|
|
|
1843
1862
|
break;
|
|
1844
1863
|
case "Backspace":
|
|
1845
1864
|
if (value.length === 0) {
|
|
1846
|
-
setSelected(
|
|
1865
|
+
setSelected(selected.slice(0, -1));
|
|
1847
1866
|
}
|
|
1848
1867
|
break;
|
|
1849
1868
|
case "Escape":
|
|
@@ -1857,7 +1876,9 @@ function TagSelector(props) {
|
|
|
1857
1876
|
setScroll,
|
|
1858
1877
|
options.length,
|
|
1859
1878
|
toggleItem,
|
|
1860
|
-
filteredOptions
|
|
1879
|
+
filteredOptions,
|
|
1880
|
+
setSelected,
|
|
1881
|
+
selected
|
|
1861
1882
|
]
|
|
1862
1883
|
);
|
|
1863
1884
|
const placeholderVisible = (0, import_react26.useMemo)(() => {
|
|
@@ -1869,27 +1890,12 @@ function TagSelector(props) {
|
|
|
1869
1890
|
return false;
|
|
1870
1891
|
return true;
|
|
1871
1892
|
}, [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
1893
|
(0, import_react26.useEffect)(() => {
|
|
1885
1894
|
setFocusIndex(null);
|
|
1886
1895
|
}, [open]);
|
|
1887
1896
|
(0, import_react26.useEffect)(() => {
|
|
1888
1897
|
setFocusIndex(0);
|
|
1889
1898
|
}, [filteredOptions]);
|
|
1890
|
-
(0, import_react26.useEffect)(() => {
|
|
1891
|
-
isInit.current = false;
|
|
1892
|
-
}, []);
|
|
1893
1899
|
const badgeSize = (0, import_react26.useMemo)(() => {
|
|
1894
1900
|
switch (size) {
|
|
1895
1901
|
case "large":
|