@mbao01/common 0.0.43 → 0.0.44

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 (63) hide show
  1. package/dist/types/components/DatetimePicker/DatetimeGrid.d.ts +26 -0
  2. package/dist/types/components/DatetimePicker/DatetimePicker.d.ts +13 -0
  3. package/dist/types/components/DatetimePicker/constants.d.ts +15 -0
  4. package/dist/types/components/DatetimePicker/index.d.ts +1 -0
  5. package/dist/types/components/DatetimePicker/types.d.ts +25 -0
  6. package/dist/types/components/Form/DatetimeInput/DatetimeCalendar.d.ts +5 -0
  7. package/dist/types/components/Form/DatetimeInput/DatetimeInput.d.ts +83 -0
  8. package/dist/types/components/Form/DatetimeInput/DatetimeInputContext.d.ts +2 -0
  9. package/dist/types/components/Form/DatetimeInput/NaturalLanguageInput.d.ts +5 -0
  10. package/dist/types/components/Form/DatetimeInput/TimePicker.d.ts +1 -0
  11. package/dist/types/components/Form/DatetimeInput/constants.d.ts +24 -0
  12. package/dist/types/components/Form/DatetimeInput/helpers.d.ts +27 -0
  13. package/dist/types/components/Form/DatetimeInput/hooks/index.d.ts +1 -0
  14. package/dist/types/components/Form/DatetimeInput/hooks/useDateInput/index.d.ts +1 -0
  15. package/dist/types/components/Form/DatetimeInput/hooks/useDateInput/useDateInput.d.ts +1 -0
  16. package/dist/types/components/Form/DatetimeInput/index.d.ts +1 -0
  17. package/dist/types/components/Form/DatetimeInput/types.d.ts +31 -0
  18. package/dist/types/components/Form/MultiSelect/MultiSelect.d.ts +46 -0
  19. package/dist/types/components/Form/MultiSelect/MultiSelectContext.d.ts +2 -0
  20. package/dist/types/components/Form/MultiSelect/constants.d.ts +19 -0
  21. package/dist/types/components/Form/MultiSelect/hooks/index.d.ts +1 -0
  22. package/dist/types/components/Form/MultiSelect/hooks/useMultiSelect/index.d.ts +1 -0
  23. package/dist/types/components/Form/MultiSelect/hooks/useMultiSelect/useMultiSelect.d.ts +1 -0
  24. package/dist/types/components/Form/MultiSelect/index.d.ts +1 -0
  25. package/dist/types/components/Form/MultiSelect/types.d.ts +31 -0
  26. package/dist/types/components/Form/TagsInput/TagsInput.d.ts +13 -0
  27. package/dist/types/components/Form/TagsInput/constants.d.ts +16 -0
  28. package/dist/types/components/Form/TagsInput/index.d.ts +1 -0
  29. package/dist/types/components/Form/TagsInput/types.d.ts +9 -0
  30. package/dist/types/components/Form/index.d.ts +2 -0
  31. package/dist/types/index.d.ts +1 -0
  32. package/package.json +4 -2
  33. package/src/components/DatetimePicker/DatetimeGrid.tsx +59 -0
  34. package/src/components/DatetimePicker/DatetimePicker.tsx +59 -0
  35. package/src/components/DatetimePicker/constants.ts +102 -0
  36. package/src/components/DatetimePicker/index.ts +1 -0
  37. package/src/components/DatetimePicker/types.ts +36 -0
  38. package/src/components/Form/DatetimeInput/DatetimeCalendar.tsx +68 -0
  39. package/src/components/Form/DatetimeInput/DatetimeInput.tsx +90 -0
  40. package/src/components/Form/DatetimeInput/DatetimeInputContext.tsx +4 -0
  41. package/src/components/Form/DatetimeInput/NaturalLanguageInput.tsx +73 -0
  42. package/src/components/Form/DatetimeInput/TimePicker.tsx +202 -0
  43. package/src/components/Form/DatetimeInput/constants.ts +135 -0
  44. package/src/components/Form/DatetimeInput/helpers.ts +93 -0
  45. package/src/components/Form/DatetimeInput/hooks/index.ts +1 -0
  46. package/src/components/Form/DatetimeInput/hooks/useDateInput/index.ts +1 -0
  47. package/src/components/Form/DatetimeInput/hooks/useDateInput/useDateInput.ts +10 -0
  48. package/src/components/Form/DatetimeInput/index.ts +1 -0
  49. package/src/components/Form/DatetimeInput/types.ts +36 -0
  50. package/src/components/Form/MultiSelect/MultiSelect.tsx +348 -0
  51. package/src/components/Form/MultiSelect/MultiSelectContext.tsx +4 -0
  52. package/src/components/Form/MultiSelect/constants.ts +103 -0
  53. package/src/components/Form/MultiSelect/hooks/index.ts +1 -0
  54. package/src/components/Form/MultiSelect/hooks/useMultiSelect/index.ts +1 -0
  55. package/src/components/Form/MultiSelect/hooks/useMultiSelect/useMultiSelect.ts +10 -0
  56. package/src/components/Form/MultiSelect/index.ts +1 -0
  57. package/src/components/Form/MultiSelect/types.ts +46 -0
  58. package/src/components/Form/TagsInput/TagsInput.tsx +278 -0
  59. package/src/components/Form/TagsInput/constants.ts +87 -0
  60. package/src/components/Form/TagsInput/index.ts +1 -0
  61. package/src/components/Form/TagsInput/types.ts +10 -0
  62. package/src/components/Form/index.ts +2 -0
  63. package/src/index.ts +1 -0
@@ -0,0 +1,103 @@
1
+ import { cva } from "../../../libs";
2
+
3
+ export const getMultiSelectClasses = cva(
4
+ "overflow-visible bg-transparent flex flex-col h-fit w-fit"
5
+ );
6
+
7
+ export const getMultiSelectTriggerClasses = cva(
8
+ "flex items-center flex-wrap gap-1 h-fit px-1 py-2 rounded-md transition-all overflow-hidden",
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default: "border-0",
13
+ accent: "border border-accent",
14
+ error: "border border-error",
15
+ ghost: "border border-ghost",
16
+ info: "border border-info",
17
+ primary: "border border-primary",
18
+ secondary: "border border-secondary",
19
+ success: "border border-success",
20
+ warning: "border border-warning",
21
+ },
22
+ outline: {
23
+ true: "border",
24
+ },
25
+ disabled: {
26
+ true: "border-base-300",
27
+ },
28
+ wide: {
29
+ true: "w-full",
30
+ },
31
+ size: {
32
+ xs: "min-h-6 leading-relaxed px-2 py-1 text-xs",
33
+ sm: "min-h-8 leading-8 px-3 py-1.5 text-sm",
34
+ md: "min-h-12 leading-loose px-4 text-sm",
35
+ lg: "min-h-16 leading-loose px-6 text-lg",
36
+ },
37
+ },
38
+ compoundVariants: [
39
+ {
40
+ size: undefined,
41
+ className: "min-h-10 px-4",
42
+ },
43
+ {
44
+ variant: undefined,
45
+ outline: true,
46
+ className: "border-neutral-content",
47
+ },
48
+ {
49
+ variant: "default",
50
+ outline: true,
51
+ className: "border-base-content",
52
+ },
53
+ ],
54
+ }
55
+ );
56
+
57
+ export const getMultiSelectItemClasses = cva(
58
+ "rounded-md cursor-pointer px-2 py-1 transition-colors flex justify-between",
59
+ {
60
+ variants: {
61
+ included: {
62
+ true: "opacity-50 cursor-default",
63
+ },
64
+ disabled: {
65
+ true: "opacity-50 cursor-not-allowed",
66
+ },
67
+ size: {
68
+ xs: "p-1 text-xs",
69
+ sm: "px-1.5 text-sm",
70
+ md: "px-2 text-sm",
71
+ lg: "px-3 text-lg",
72
+ },
73
+ },
74
+ }
75
+ );
76
+
77
+ export const getMultiSelectListClasses = cva(
78
+ "p-2 flex flex-col gap-2 rounded-md scrollbar-thin scrollbar-track-transparent transition-colors scrollbar-thumb-muted-foreground dark:scrollbar-thumb-muted scrollbar-thumb-rounded-lg w-full absolute bg-background shadow-md z-10 border border-muted top-0",
79
+ {
80
+ variants: {
81
+ size: {
82
+ xs: "p-1",
83
+ sm: "p-1.5",
84
+ md: "p-2",
85
+ lg: "p-3",
86
+ },
87
+ },
88
+ }
89
+ );
90
+
91
+ export const getMultiSelectTagClasses = cva(
92
+ "relative flex items-center gap-1 [&>span]:truncate [&>span]:max-w-24 aria-disabled:opacity-50 aria-disabled:cursor-not-allowed focus-visible:outline-none",
93
+ {
94
+ variants: {
95
+ size: {
96
+ xs: "px-0.5 [&>span]:max-w-20 rounded",
97
+ sm: "px-1",
98
+ md: "px-1.5 [&>span]:max-w-28",
99
+ lg: "px-2 [&>span]:max-w-32",
100
+ },
101
+ },
102
+ }
103
+ );
@@ -0,0 +1 @@
1
+ export { useMultiSelect } from "./useMultiSelect";
@@ -0,0 +1 @@
1
+ export { useMultiSelect } from "./useMultiSelect";
@@ -0,0 +1,10 @@
1
+ import { useContext } from "react";
2
+ import { MultiSelectContext } from "../../MultiSelectContext";
3
+
4
+ export const useMultiSelect = () => {
5
+ const context = useContext(MultiSelectContext);
6
+ if (!context) {
7
+ throw new Error("useMultiSelect must be used within MultiSelectProvider");
8
+ }
9
+ return context;
10
+ };
@@ -0,0 +1 @@
1
+ export { MultiSelect } from "./MultiSelect";
@@ -0,0 +1,46 @@
1
+ import { ComponentPropsWithoutRef, HTMLAttributes } from "react";
2
+ import { VariantProps } from "../../../libs";
3
+ import { Command } from "../../Command";
4
+ import {
5
+ getMultiSelectItemClasses,
6
+ getMultiSelectListClasses,
7
+ getMultiSelectTriggerClasses,
8
+ } from "./constants";
9
+
10
+ export type Item = {
11
+ value: string;
12
+ label?: string;
13
+ };
14
+
15
+ export type MultiSelectProps = React.ComponentPropsWithoutRef<typeof Command> & {
16
+ loop?: boolean;
17
+ values: Item["value"][];
18
+ onValuesChange: (value: string[]) => void;
19
+ };
20
+
21
+ export type MultiSelectContextProps = {
22
+ values: Item["value"][];
23
+ onValueChange: (value: Item["value"], label?: Item["label"]) => void;
24
+ items: Item[];
25
+ open: boolean;
26
+ setOpen: (value: boolean) => void;
27
+ inputValue: string;
28
+ setInputValue: React.Dispatch<React.SetStateAction<string>>;
29
+ activeIndex: number;
30
+ setActiveIndex: React.Dispatch<React.SetStateAction<number>>;
31
+ ref: React.RefObject<HTMLInputElement>;
32
+ handleSelect: (e: React.SyntheticEvent<HTMLInputElement>) => void;
33
+ };
34
+
35
+ export type MultiSelectTriggerProps = HTMLAttributes<HTMLDivElement> &
36
+ VariantProps<typeof getMultiSelectTriggerClasses>;
37
+
38
+ export type MultiSelectInputProps = ComponentPropsWithoutRef<typeof Command.Input>;
39
+
40
+ export type MultiSelectContentProps = HTMLAttributes<HTMLDivElement>;
41
+
42
+ export type MultiSelectListProps = ComponentPropsWithoutRef<typeof Command.List> &
43
+ VariantProps<typeof getMultiSelectListClasses>;
44
+ export type MultiSelectItemProps = Item &
45
+ ComponentPropsWithoutRef<typeof Command.Item> &
46
+ VariantProps<typeof getMultiSelectItemClasses>;
@@ -0,0 +1,278 @@
1
+ "use client";
2
+
3
+ import type { ChangeEvent, ClipboardEvent, KeyboardEvent, MouseEvent, SyntheticEvent } from "react";
4
+ import { forwardRef, useCallback, useEffect, useRef, useState } from "react";
5
+ import { Cross2Icon } from "@radix-ui/react-icons";
6
+ import type { TagsInputProps } from "./types";
7
+ import { cn } from "../../../utilities";
8
+ import { Badge } from "../../Badge";
9
+ import { Input } from "../Input";
10
+ import {
11
+ FORMATTING_REGEX,
12
+ getTagClasses,
13
+ getTagDeleteClasses,
14
+ getTagsClasses,
15
+ getTagsInputClasses,
16
+ SPLITTER_REGEX,
17
+ } from "./constants";
18
+
19
+ export const TagsInput = forwardRef<HTMLDivElement, TagsInputProps>(
20
+ (
21
+ {
22
+ onChange,
23
+ defaultTags,
24
+ placeholder,
25
+ maxItems,
26
+ minItems,
27
+ className,
28
+ dir,
29
+ size,
30
+ wide,
31
+ outline,
32
+ variant,
33
+ disabled,
34
+ "aria-label": ariaLabel,
35
+ ...props
36
+ },
37
+ ref
38
+ ) => {
39
+ const inputRef = useRef<HTMLInputElement>(null);
40
+ const [activeIndex, setActiveIndex] = useState(-1);
41
+ const [inputValue, setInputValue] = useState("");
42
+ const [disableInput, setDisableInput] = useState(false);
43
+ const [disableButton, setDisableButton] = useState(false);
44
+ const [isValueSelected, setIsValueSelected] = useState(false);
45
+ const [selectedValue, setSelectedValue] = useState("");
46
+ const [tags, setTags] = useState<string[]>(defaultTags ?? []);
47
+
48
+ const parseMinItems = minItems ?? 0;
49
+ const parseMaxItems = maxItems ?? Infinity;
50
+
51
+ useEffect(() => {
52
+ if (onChange) {
53
+ onChange(tags, inputValue);
54
+ }
55
+ // eslint-disable-next-line react-hooks/exhaustive-deps
56
+ }, [tags]);
57
+
58
+ useEffect(() => {
59
+ const verifyDisable = () => {
60
+ if (tags.length - 1 >= parseMinItems) {
61
+ setDisableButton(false);
62
+ } else {
63
+ setDisableButton(true);
64
+ }
65
+ if (tags.length + 1 <= parseMaxItems) {
66
+ setDisableInput(false);
67
+ } else {
68
+ setDisableInput(true);
69
+ }
70
+ };
71
+ verifyDisable();
72
+ }, [tags, parseMinItems, parseMaxItems]);
73
+
74
+ const onValueChangeHandler = useCallback(
75
+ (tag: string) => {
76
+ if (!tags.includes(tag) && tags.length < parseMaxItems) {
77
+ setTags([...tags, tag]);
78
+ }
79
+ },
80
+ [tags, parseMaxItems]
81
+ );
82
+
83
+ const removeValue = useCallback(
84
+ (tag: string) => {
85
+ if (tags.includes(tag) && tags.length > parseMinItems) {
86
+ setTags([...tags.filter((item) => item !== tag)]);
87
+ }
88
+ },
89
+ [tags, parseMinItems]
90
+ );
91
+
92
+ const handleSelect = useCallback(
93
+ (e: SyntheticEvent<HTMLInputElement>) => {
94
+ const target = e.currentTarget;
95
+ const selection = target.value.substring(
96
+ target.selectionStart ?? 0,
97
+ target.selectionEnd ?? 0
98
+ );
99
+
100
+ setSelectedValue(selection);
101
+ setIsValueSelected(selection === inputValue);
102
+ },
103
+ [inputValue]
104
+ );
105
+
106
+ const handlePaste = useCallback(
107
+ (e: ClipboardEvent<HTMLInputElement>) => {
108
+ e.preventDefault();
109
+ const items = e.clipboardData.getData("text").split(SPLITTER_REGEX);
110
+ const newTags = [...tags];
111
+ items.forEach((item) => {
112
+ const parsedItem = item.replaceAll(FORMATTING_REGEX, "").trim();
113
+ if (
114
+ parsedItem.length > 0 &&
115
+ !newTags.includes(parsedItem) &&
116
+ newTags.length < parseMaxItems
117
+ ) {
118
+ newTags.push(parsedItem);
119
+ }
120
+ });
121
+ setTags(newTags);
122
+ setInputValue("");
123
+ },
124
+ [tags, parseMaxItems]
125
+ );
126
+
127
+ const handleKeyDown = useCallback(
128
+ (e: KeyboardEvent<HTMLInputElement>) => {
129
+ const target = e.currentTarget;
130
+
131
+ if (["ArrowLeft", "ArrowRight", "Backspace", "Delete", "Escape", "Enter"].includes(e.key)) {
132
+ e.stopPropagation();
133
+
134
+ const moveNext = () => {
135
+ const nextIndex = activeIndex + 1 > tags.length - 1 ? -1 : activeIndex + 1;
136
+ if (nextIndex === -1 && inputRef.current) {
137
+ inputRef.current.focus();
138
+ const inputLen = inputRef.current.value.length;
139
+ inputRef.current.setSelectionRange(inputLen, inputLen);
140
+ }
141
+ setActiveIndex(nextIndex);
142
+ };
143
+
144
+ const movePrev = () => {
145
+ const prevIndex = activeIndex - 1 < 0 ? tags.length - 1 : activeIndex - 1;
146
+ setActiveIndex(prevIndex);
147
+ };
148
+
149
+ const moveCurrent = () => {
150
+ const newIndex =
151
+ activeIndex - 1 <= 0 ? (tags.length - 1 === 0 ? -1 : 0) : activeIndex - 1;
152
+ setActiveIndex(newIndex);
153
+ };
154
+
155
+ switch (e.key) {
156
+ case "ArrowLeft":
157
+ if (dir === "rtl") {
158
+ if (tags.length > 0 && activeIndex !== -1) {
159
+ moveNext();
160
+ }
161
+ } else {
162
+ if (tags.length > 0 && target.selectionStart === 0) {
163
+ movePrev();
164
+ }
165
+ }
166
+ break;
167
+
168
+ case "ArrowRight":
169
+ if (dir === "rtl") {
170
+ if (tags.length > 0) {
171
+ movePrev();
172
+ }
173
+ } else {
174
+ if (tags.length > 0 && activeIndex !== -1) {
175
+ moveNext();
176
+ }
177
+ }
178
+ break;
179
+
180
+ case "Backspace":
181
+ case "Delete":
182
+ if (tags.length > 0) {
183
+ if (activeIndex !== -1 && activeIndex < tags.length) {
184
+ removeValue(tags[activeIndex]);
185
+ moveCurrent();
186
+ } else {
187
+ if (target.selectionStart === 0) {
188
+ if (selectedValue === inputValue || isValueSelected) {
189
+ removeValue(tags[tags.length - 1]);
190
+ }
191
+ }
192
+ }
193
+ }
194
+ break;
195
+
196
+ case "Escape":
197
+ setActiveIndex(activeIndex === -1 ? tags.length - 1 : -1);
198
+ break;
199
+
200
+ case "Enter":
201
+ if (inputValue.trim() !== "") {
202
+ e.preventDefault();
203
+ onValueChangeHandler(inputValue);
204
+ setInputValue("");
205
+ }
206
+ break;
207
+ }
208
+ }
209
+ },
210
+ // eslint-disable-next-line react-hooks/exhaustive-deps
211
+ [dir, activeIndex, tags, inputValue, removeValue]
212
+ );
213
+
214
+ const handleMouseDown = useCallback((e: MouseEvent) => {
215
+ e.preventDefault();
216
+ e.stopPropagation();
217
+ }, []);
218
+
219
+ const handleChange = useCallback((e: ChangeEvent<HTMLInputElement>) => {
220
+ setInputValue(e.currentTarget.value);
221
+ }, []);
222
+
223
+ return (
224
+ <div
225
+ {...props}
226
+ ref={ref}
227
+ dir={dir}
228
+ className={cn(getTagsClasses({ size, wide, outline, variant, disabled }), className)}
229
+ >
230
+ {tags.map((tag, index) => (
231
+ <Badge
232
+ tabIndex={activeIndex !== -1 ? 0 : activeIndex}
233
+ key={tag}
234
+ size={size}
235
+ aria-disabled={disableButton}
236
+ data-active={activeIndex === index}
237
+ className={cn(getTagClasses({ size }), {
238
+ "ring-1 ring-inset opacity-80": !disableButton && activeIndex === index,
239
+ })}
240
+ variant={variant === "default" ? "neutral" : variant}
241
+ >
242
+ <span className="truncate max-w-24">{tag}</span>
243
+ <button
244
+ type="button"
245
+ aria-label={`Remove ${tag} option`}
246
+ aria-roledescription="button to remove option"
247
+ disabled={disableButton}
248
+ onMouseDown={handleMouseDown}
249
+ onClick={() => removeValue(tag)}
250
+ className={cn(getTagDeleteClasses())}
251
+ >
252
+ <span className="sr-only">Remove {tag} option</span>
253
+ <Cross2Icon className="h-4 w-4" />
254
+ </button>
255
+ </Badge>
256
+ ))}
257
+ <Input
258
+ ref={inputRef}
259
+ tabIndex={0}
260
+ onSelect={handleSelect}
261
+ aria-label={ariaLabel}
262
+ disabled={disableInput}
263
+ onKeyDown={handleKeyDown}
264
+ onPaste={handlePaste}
265
+ value={inputValue}
266
+ onChange={activeIndex === -1 ? handleChange : undefined}
267
+ placeholder={placeholder}
268
+ onClick={() => setActiveIndex(-1)}
269
+ className={cn(getTagsInputClasses({ size }), {
270
+ "caret-transparent": activeIndex !== -1,
271
+ })}
272
+ />
273
+ </div>
274
+ );
275
+ }
276
+ );
277
+
278
+ TagsInput.displayName = "TagsInput";
@@ -0,0 +1,87 @@
1
+ import { cva } from "../../../libs";
2
+
3
+ export const SPLITTER_REGEX = /[\n#?=&\t,./-]+/; // used for identifying the split char and used with pasting
4
+
5
+ export const FORMATTING_REGEX = /^[^a-zA-Z0-9]*|[^a-zA-Z0-9]*$/g; // used for formatting the pasted element for the correct value format to be added
6
+
7
+ export const getTagsClasses = cva(
8
+ "flex items-center flex-wrap gap-1 h-fit px-1 py-2 rounded-md transition-all overflow-hidden",
9
+ {
10
+ variants: {
11
+ variant: {
12
+ default: "border-0",
13
+ accent: "border border-accent",
14
+ error: "border border-error",
15
+ ghost: "border border-ghost",
16
+ info: "border border-info",
17
+ primary: "border border-primary",
18
+ secondary: "border border-secondary",
19
+ success: "border border-success",
20
+ warning: "border border-warning",
21
+ },
22
+ outline: {
23
+ true: "border",
24
+ },
25
+ disabled: {
26
+ true: "border-base-300",
27
+ },
28
+ wide: {
29
+ true: "w-full",
30
+ },
31
+ size: {
32
+ xs: "min-h-6 leading-relaxed px-2 py-1 text-xs",
33
+ sm: "min-h-8 leading-8 px-3 py-1.5 text-sm",
34
+ md: "min-h-12 leading-loose px-4 text-sm",
35
+ lg: "min-h-16 leading-loose px-5 text-lg",
36
+ },
37
+ },
38
+ compoundVariants: [
39
+ {
40
+ size: undefined,
41
+ className: "min-h-10 px-4",
42
+ },
43
+ {
44
+ variant: undefined,
45
+ outline: true,
46
+ className: "border-neutral-content",
47
+ },
48
+ {
49
+ variant: "default",
50
+ outline: true,
51
+ className: "border-base-content",
52
+ },
53
+ ],
54
+ }
55
+ );
56
+
57
+ export const getTagClasses = cva(
58
+ "relative flex items-center gap-1 [&>span]:truncate [&>span]:max-w-24 aria-disabled:opacity-50 aria-disabled:cursor-not-allowed focus-visible:outline-none",
59
+ {
60
+ variants: {
61
+ size: {
62
+ xs: "px-0.5 [&>span]:max-w-20 rounded",
63
+ sm: "px-1",
64
+ md: "px-1.5 [&>span]:max-w-28",
65
+ lg: "px-2 [&>span]:max-w-32",
66
+ },
67
+ },
68
+ }
69
+ );
70
+
71
+ export const getTagsInputClasses = cva(
72
+ "outline-0 border-none h-5 min-w-fit flex-1 focus-visible:outline-0 focus-visible:ring-0 focus-visible:ring-offset-0 focus-visible:border-0 placeholder:text-muted-foreground px-1",
73
+ {
74
+ variants: {
75
+ size: {
76
+ xs: "h-3 leading-relaxed text-xs",
77
+ sm: "h-4 leading-8 text-sm",
78
+ md: "h-5 text-sm",
79
+ lg: "h-6 text-lg",
80
+ },
81
+ },
82
+ }
83
+ );
84
+
85
+ export const getTagDeleteClasses = cva(
86
+ "transition-all duration-300 disabled:cursor-not-allowed [&:hover:not(:disabled)]:opacity-80"
87
+ );
@@ -0,0 +1 @@
1
+ export { TagsInput } from "./TagsInput";
@@ -0,0 +1,10 @@
1
+ import { type VariantProps } from "../../../libs";
2
+ import { getTagsClasses } from "./constants";
3
+
4
+ export type TagsInputProps = React.HTMLAttributes<HTMLDivElement> & {
5
+ defaultTags?: string[];
6
+ onChange?: (value: string[], inputValue: string) => void;
7
+ placeholder?: string;
8
+ maxItems?: number;
9
+ minItems?: number;
10
+ } & VariantProps<typeof getTagsClasses>;
@@ -1,3 +1,4 @@
1
+ export { DatetimeInput } from "./DatetimeInput";
1
2
  export { Input } from "./Input";
2
3
  export { OtpInput } from "./OtpInput";
3
4
  export { Phone } from "./Phone";
@@ -7,6 +8,7 @@ export { Select } from "./Select";
7
8
  export { Slider } from "./Slider";
8
9
  export { Switch } from "./Switch";
9
10
  export { Checkbox } from "./Checkbox";
11
+ export { TagsInput } from "./TagsInput";
10
12
  export { Textarea } from "./Textarea";
11
13
  export { TextField } from "./TextField";
12
14
  export { Label } from "./components/Label";
package/src/index.ts CHANGED
@@ -26,6 +26,7 @@ export * from "./components/Tabs";
26
26
  export * from "./components/Text";
27
27
 
28
28
  /** data input */
29
+ export * from "./components/DatetimePicker";
29
30
  export * from "./components/FileUploader";
30
31
  export * from "./components/Form";
31
32
  export * from "./components/Combobox";