@meta-1/design 0.0.166 → 0.0.168

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@meta-1/design",
3
- "version": "0.0.166",
3
+ "version": "0.0.168",
4
4
  "keywords": [
5
5
  "easykit",
6
6
  "design",
@@ -25,6 +25,7 @@
25
25
  "@radix-ui/react-alert-dialog": "1.1.2",
26
26
  "@radix-ui/react-avatar": "1.1.1",
27
27
  "@radix-ui/react-checkbox": "1.1.2",
28
+ "@radix-ui/react-context-menu": "^2.2.16",
28
29
  "@radix-ui/react-dialog": "1.1.2",
29
30
  "@radix-ui/react-dismissable-layer": "1.1.1",
30
31
  "@radix-ui/react-dropdown-menu": "2.1.2",
@@ -0,0 +1,198 @@
1
+ import * as React from "react"
2
+ import * as ContextMenuPrimitive from "@radix-ui/react-context-menu"
3
+ import { Check, ChevronRight, Circle } from "lucide-react"
4
+
5
+ import { cn } from "@meta-1/design/lib/utils"
6
+
7
+ const ContextMenu = ContextMenuPrimitive.Root
8
+
9
+ const ContextMenuTrigger = ContextMenuPrimitive.Trigger
10
+
11
+ const ContextMenuGroup = ContextMenuPrimitive.Group
12
+
13
+ const ContextMenuPortal = ContextMenuPrimitive.Portal
14
+
15
+ const ContextMenuSub = ContextMenuPrimitive.Sub
16
+
17
+ const ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup
18
+
19
+ const ContextMenuSubTrigger = React.forwardRef<
20
+ React.ElementRef<typeof ContextMenuPrimitive.SubTrigger>,
21
+ React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubTrigger> & {
22
+ inset?: boolean
23
+ }
24
+ >(({ className, inset, children, ...props }, ref) => (
25
+ <ContextMenuPrimitive.SubTrigger
26
+ ref={ref}
27
+ className={cn(
28
+ "flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
29
+ inset && "pl-8",
30
+ className
31
+ )}
32
+ {...props}
33
+ >
34
+ {children}
35
+ <ChevronRight className="ml-auto h-4 w-4" />
36
+ </ContextMenuPrimitive.SubTrigger>
37
+ ))
38
+ ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName
39
+
40
+ const ContextMenuSubContent = React.forwardRef<
41
+ React.ElementRef<typeof ContextMenuPrimitive.SubContent>,
42
+ React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubContent>
43
+ >(({ className, ...props }, ref) => (
44
+ <ContextMenuPrimitive.SubContent
45
+ ref={ref}
46
+ className={cn(
47
+ "z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-context-menu-content-transform-origin]",
48
+ className
49
+ )}
50
+ {...props}
51
+ />
52
+ ))
53
+ ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName
54
+
55
+ const ContextMenuContent = React.forwardRef<
56
+ React.ElementRef<typeof ContextMenuPrimitive.Content>,
57
+ React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Content>
58
+ >(({ className, ...props }, ref) => (
59
+ <ContextMenuPrimitive.Portal>
60
+ <ContextMenuPrimitive.Content
61
+ ref={ref}
62
+ className={cn(
63
+ "z-50 max-h-[--radix-context-menu-content-available-height] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in fade-in-80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-context-menu-content-transform-origin]",
64
+ className
65
+ )}
66
+ {...props}
67
+ />
68
+ </ContextMenuPrimitive.Portal>
69
+ ))
70
+ ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName
71
+
72
+ const ContextMenuItem = React.forwardRef<
73
+ React.ElementRef<typeof ContextMenuPrimitive.Item>,
74
+ React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Item> & {
75
+ inset?: boolean
76
+ }
77
+ >(({ className, inset, ...props }, ref) => (
78
+ <ContextMenuPrimitive.Item
79
+ ref={ref}
80
+ className={cn(
81
+ "relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
82
+ inset && "pl-8",
83
+ className
84
+ )}
85
+ {...props}
86
+ />
87
+ ))
88
+ ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName
89
+
90
+ const ContextMenuCheckboxItem = React.forwardRef<
91
+ React.ElementRef<typeof ContextMenuPrimitive.CheckboxItem>,
92
+ React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.CheckboxItem>
93
+ >(({ className, children, checked, ...props }, ref) => (
94
+ <ContextMenuPrimitive.CheckboxItem
95
+ ref={ref}
96
+ className={cn(
97
+ "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
98
+ className
99
+ )}
100
+ checked={checked}
101
+ {...props}
102
+ >
103
+ <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
104
+ <ContextMenuPrimitive.ItemIndicator>
105
+ <Check className="h-4 w-4" />
106
+ </ContextMenuPrimitive.ItemIndicator>
107
+ </span>
108
+ {children}
109
+ </ContextMenuPrimitive.CheckboxItem>
110
+ ))
111
+ ContextMenuCheckboxItem.displayName =
112
+ ContextMenuPrimitive.CheckboxItem.displayName
113
+
114
+ const ContextMenuRadioItem = React.forwardRef<
115
+ React.ElementRef<typeof ContextMenuPrimitive.RadioItem>,
116
+ React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.RadioItem>
117
+ >(({ className, children, ...props }, ref) => (
118
+ <ContextMenuPrimitive.RadioItem
119
+ ref={ref}
120
+ className={cn(
121
+ "relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
122
+ className
123
+ )}
124
+ {...props}
125
+ >
126
+ <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
127
+ <ContextMenuPrimitive.ItemIndicator>
128
+ <Circle className="h-2 w-2 fill-current" />
129
+ </ContextMenuPrimitive.ItemIndicator>
130
+ </span>
131
+ {children}
132
+ </ContextMenuPrimitive.RadioItem>
133
+ ))
134
+ ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName
135
+
136
+ const ContextMenuLabel = React.forwardRef<
137
+ React.ElementRef<typeof ContextMenuPrimitive.Label>,
138
+ React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Label> & {
139
+ inset?: boolean
140
+ }
141
+ >(({ className, inset, ...props }, ref) => (
142
+ <ContextMenuPrimitive.Label
143
+ ref={ref}
144
+ className={cn(
145
+ "px-2 py-1.5 text-sm font-semibold text-foreground",
146
+ inset && "pl-8",
147
+ className
148
+ )}
149
+ {...props}
150
+ />
151
+ ))
152
+ ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName
153
+
154
+ const ContextMenuSeparator = React.forwardRef<
155
+ React.ElementRef<typeof ContextMenuPrimitive.Separator>,
156
+ React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Separator>
157
+ >(({ className, ...props }, ref) => (
158
+ <ContextMenuPrimitive.Separator
159
+ ref={ref}
160
+ className={cn("-mx-1 my-1 h-px bg-border", className)}
161
+ {...props}
162
+ />
163
+ ))
164
+ ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName
165
+
166
+ const ContextMenuShortcut = ({
167
+ className,
168
+ ...props
169
+ }: React.HTMLAttributes<HTMLSpanElement>) => {
170
+ return (
171
+ <span
172
+ className={cn(
173
+ "ml-auto text-xs tracking-widest text-muted-foreground",
174
+ className
175
+ )}
176
+ {...props}
177
+ />
178
+ )
179
+ }
180
+ ContextMenuShortcut.displayName = "ContextMenuShortcut"
181
+
182
+ export {
183
+ ContextMenu,
184
+ ContextMenuTrigger,
185
+ ContextMenuContent,
186
+ ContextMenuItem,
187
+ ContextMenuCheckboxItem,
188
+ ContextMenuRadioItem,
189
+ ContextMenuLabel,
190
+ ContextMenuSeparator,
191
+ ContextMenuShortcut,
192
+ ContextMenuGroup,
193
+ ContextMenuPortal,
194
+ ContextMenuSub,
195
+ ContextMenuSubContent,
196
+ ContextMenuSubTrigger,
197
+ ContextMenuRadioGroup,
198
+ }
@@ -0,0 +1,136 @@
1
+ # TagsInput 组件
2
+
3
+ 一个功能丰富的标签输入组件,支持添加、删除标签,带有验证、最大数量限制等特性。
4
+
5
+ ## 功能特性
6
+
7
+ - ✅ 受控/非受控模式
8
+ - ✅ 键盘操作(Enter 添加,Backspace 删除)
9
+ - ✅ 自定义分隔符(默认逗号)
10
+ - ✅ 标签验证
11
+ - ✅ 最大标签数量限制
12
+ - ✅ 最大标签长度限制
13
+ - ✅ 禁止重复标签
14
+ - ✅ 自定义标签渲染
15
+ - ✅ 完整的事件回调
16
+ - ✅ 禁用状态
17
+ - ✅ 自定义样式
18
+
19
+ ## 基础用法
20
+
21
+ ```tsx
22
+ import { TagsInput } from "@meta-1/design";
23
+
24
+ function App() {
25
+ const [tags, setTags] = useState<string[]>([]);
26
+
27
+ return (
28
+ <TagsInput
29
+ value={tags}
30
+ onChange={setTags}
31
+ placeholder="输入标签后按 Enter..."
32
+ />
33
+ );
34
+ }
35
+ ```
36
+
37
+ ## Props
38
+
39
+ | 属性 | 类型 | 默认值 | 说明 |
40
+ |------|------|--------|------|
41
+ | value | `string[]` | - | 受控模式的标签值 |
42
+ | defaultValue | `string[]` | `[]` | 非受控模式的默认值 |
43
+ | onChange | `(value: string[]) => void` | - | 标签变化回调 |
44
+ | placeholder | `string` | - | 输入框占位符 |
45
+ | className | `string` | - | 容器类名 |
46
+ | inputClassName | `string` | - | 输入框类名 |
47
+ | tagClassName | `string` | - | 标签类名 |
48
+ | maxTags | `number` | - | 最大标签数量 |
49
+ | maxLength | `number` | - | 单个标签最大长度 |
50
+ | allowDuplicates | `boolean` | `false` | 是否允许重复标签 |
51
+ | separator | `string \| RegExp` | `","` | 分隔符 |
52
+ | validate | `(tag: string) => boolean` | - | 标签验证函数 |
53
+ | disabled | `boolean` | `false` | 是否禁用 |
54
+ | onTagAdd | `(tag: string) => void` | - | 添加标签回调 |
55
+ | onTagRemove | `(tag: string) => void` | - | 删除标签回调 |
56
+ | renderTag | `(tag: string, index: number, remove: () => void) => ReactNode` | - | 自定义标签渲染 |
57
+
58
+ ## 使用示例
59
+
60
+ ### 最大数量限制
61
+
62
+ ```tsx
63
+ <TagsInput
64
+ maxTags={5}
65
+ value={tags}
66
+ onChange={setTags}
67
+ placeholder="最多 5 个标签"
68
+ />
69
+ ```
70
+
71
+ ### 自定义验证
72
+
73
+ ```tsx
74
+ <TagsInput
75
+ validate={(tag) => /^[a-zA-Z0-9]+$/.test(tag)}
76
+ value={tags}
77
+ onChange={setTags}
78
+ placeholder="只允许字母和数字"
79
+ />
80
+ ```
81
+
82
+ ### 禁止重复
83
+
84
+ ```tsx
85
+ <TagsInput
86
+ allowDuplicates={false}
87
+ value={tags}
88
+ onChange={setTags}
89
+ placeholder="不允许重复标签"
90
+ />
91
+ ```
92
+
93
+ ### 自定义标签渲染
94
+
95
+ ```tsx
96
+ <TagsInput
97
+ renderTag={(tag, index, remove) => (
98
+ <div className="custom-tag">
99
+ #{tag}
100
+ <button onClick={remove}>×</button>
101
+ </div>
102
+ )}
103
+ value={tags}
104
+ onChange={setTags}
105
+ />
106
+ ```
107
+
108
+ ### 事件回调
109
+
110
+ ```tsx
111
+ <TagsInput
112
+ onTagAdd={(tag) => console.log("添加:", tag)}
113
+ onTagRemove={(tag) => console.log("删除:", tag)}
114
+ value={tags}
115
+ onChange={setTags}
116
+ />
117
+ ```
118
+
119
+ ## 键盘操作
120
+
121
+ - **Enter**: 添加当前输入的标签
122
+ - **Backspace**: 当输入框为空时,删除最后一个标签
123
+ - **分隔符** (默认逗号): 添加标签
124
+
125
+ ## 样式自定义
126
+
127
+ 组件支持通过 `className`、`inputClassName` 和 `tagClassName` 来自定义样式:
128
+
129
+ ```tsx
130
+ <TagsInput
131
+ className="border-primary"
132
+ tagClassName="bg-primary text-primary-foreground"
133
+ inputClassName="text-lg"
134
+ />
135
+ ```
136
+
@@ -0,0 +1,212 @@
1
+ import { forwardRef, type KeyboardEvent, useEffect, useRef, useState } from "react";
2
+ import { XIcon } from "lucide-react";
3
+
4
+ import { cn } from "@meta-1/design/lib";
5
+
6
+ export interface TagsInputProps {
7
+ value?: string[];
8
+ defaultValue?: string[];
9
+ onChange?: (value: string[]) => void;
10
+ placeholder?: string;
11
+ className?: string;
12
+ inputClassName?: string;
13
+ tagClassName?: string;
14
+ maxTags?: number;
15
+ maxLength?: number;
16
+ allowDuplicates?: boolean;
17
+ separator?: string | RegExp;
18
+ validate?: (tag: string) => boolean;
19
+ disabled?: boolean;
20
+ onTagAdd?: (tag: string) => void;
21
+ onTagRemove?: (tag: string) => void;
22
+ renderTag?: (tag: string, index: number, remove: () => void) => React.ReactNode;
23
+ }
24
+
25
+ export const TagsInput = forwardRef<HTMLDivElement, TagsInputProps>((props, ref) => {
26
+ const {
27
+ value,
28
+ defaultValue = [],
29
+ onChange,
30
+ placeholder,
31
+ className,
32
+ inputClassName,
33
+ tagClassName,
34
+ maxTags,
35
+ maxLength,
36
+ allowDuplicates = false,
37
+ separator = ",",
38
+ validate,
39
+ disabled = false,
40
+ onTagAdd,
41
+ onTagRemove,
42
+ renderTag,
43
+ } = props;
44
+
45
+ const inputRef = useRef<HTMLInputElement>(null);
46
+ const [inputValue, setInputValue] = useState("");
47
+ const [tags, setTags] = useState<string[]>(value || defaultValue);
48
+
49
+ const isControlled = value !== undefined;
50
+ const currentTags = isControlled ? value : tags;
51
+
52
+ useEffect(() => {
53
+ if (isControlled) {
54
+ setTags(value);
55
+ }
56
+ }, [value, isControlled]);
57
+
58
+ const handleChange = (newTags: string[]) => {
59
+ if (!isControlled) {
60
+ setTags(newTags);
61
+ }
62
+ onChange?.(newTags);
63
+ };
64
+
65
+ const addTag = (tag: string) => {
66
+ const trimmedTag = tag.trim();
67
+
68
+ if (!trimmedTag) return;
69
+
70
+ // 验证标签
71
+ if (validate && !validate(trimmedTag)) return;
72
+
73
+ // 检查最大数量
74
+ if (maxTags && currentTags.length >= maxTags) return;
75
+
76
+ // 检查重复
77
+ if (!allowDuplicates && currentTags.includes(trimmedTag)) return;
78
+
79
+ const newTags = [...currentTags, trimmedTag];
80
+ handleChange(newTags);
81
+ onTagAdd?.(trimmedTag);
82
+ setInputValue("");
83
+ };
84
+
85
+ const removeTag = (index: number) => {
86
+ const tag = currentTags[index];
87
+ const newTags = currentTags.filter((_, i) => i !== index);
88
+ handleChange(newTags);
89
+ onTagRemove?.(tag);
90
+ };
91
+
92
+ const handleKeyDown = (e: KeyboardEvent<HTMLInputElement>) => {
93
+ const target = e.target as HTMLInputElement;
94
+ const value = target.value;
95
+
96
+ // Enter 或分隔符键
97
+ if (e.key === "Enter" || (typeof separator === "string" && e.key === separator)) {
98
+ e.preventDefault();
99
+ if (value) {
100
+ addTag(value);
101
+ }
102
+ return;
103
+ }
104
+
105
+ // Backspace 删除最后一个标签
106
+ if (e.key === "Backspace" && !value && currentTags.length > 0) {
107
+ e.preventDefault();
108
+ removeTag(currentTags.length - 1);
109
+ return;
110
+ }
111
+ };
112
+
113
+ const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
114
+ const value = e.target.value;
115
+
116
+ // 检查是否包含分隔符
117
+ if (separator) {
118
+ const parts = typeof separator === "string" ? value.split(separator) : value.split(separator);
119
+
120
+ if (parts.length > 1) {
121
+ // 添加所有非空部分(除了最后一个)
122
+ parts.slice(0, -1).forEach((part) => {
123
+ if (part.trim()) {
124
+ addTag(part);
125
+ }
126
+ });
127
+ // 保留最后一部分作为输入值
128
+ setInputValue(parts[parts.length - 1]);
129
+ return;
130
+ }
131
+ }
132
+
133
+ // 检查最大长度
134
+ if (maxLength && value.length > maxLength) return;
135
+
136
+ setInputValue(value);
137
+ };
138
+
139
+ const handleBlur = () => {
140
+ if (inputValue.trim()) {
141
+ addTag(inputValue);
142
+ }
143
+ };
144
+
145
+ const handleContainerClick = () => {
146
+ inputRef.current?.focus();
147
+ };
148
+
149
+ const defaultRenderTag = (tag: string, index: number, remove: () => void) => (
150
+ <div
151
+ className={cn(
152
+ "inline-flex items-center gap-1 rounded-md bg-secondary px-2 py-1 text-sm transition-colors",
153
+ "hover:bg-secondary/80",
154
+ disabled && "pointer-events-none opacity-50",
155
+ tagClassName,
156
+ )}
157
+ key={`${tag}-${index}`}
158
+ >
159
+ <span className="max-w-[200px] truncate">{tag}</span>
160
+ {!disabled && (
161
+ <button
162
+ className="inline-flex items-center justify-center rounded-sm opacity-70 hover:opacity-100 focus:outline-none"
163
+ onClick={(e) => {
164
+ e.stopPropagation();
165
+ remove();
166
+ }}
167
+ type="button"
168
+ >
169
+ <XIcon className="h-3 w-3" />
170
+ </button>
171
+ )}
172
+ </div>
173
+ );
174
+
175
+ return (
176
+ <div
177
+ className={cn(
178
+ "flex min-h-9 w-full flex-wrap gap-1.5 rounded-md border border-input bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow]",
179
+ "focus-within:border-ring focus-within:ring-[3px] focus-within:ring-ring/50",
180
+ disabled && "pointer-events-none cursor-not-allowed opacity-50",
181
+ "dark:bg-input/30",
182
+ className,
183
+ )}
184
+ onClick={handleContainerClick}
185
+ ref={ref}
186
+ >
187
+ {currentTags.map((tag, index) =>
188
+ renderTag
189
+ ? renderTag(tag, index, () => removeTag(index))
190
+ : defaultRenderTag(tag, index, () => removeTag(index)),
191
+ )}
192
+
193
+ <input
194
+ className={cn(
195
+ "min-w-[120px] flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground",
196
+ "disabled:pointer-events-none disabled:cursor-not-allowed",
197
+ inputClassName,
198
+ )}
199
+ disabled={disabled || (maxTags !== undefined && currentTags.length >= maxTags)}
200
+ onBlur={handleBlur}
201
+ onChange={handleInputChange}
202
+ onKeyDown={handleKeyDown}
203
+ placeholder={currentTags.length === 0 ? placeholder : undefined}
204
+ ref={inputRef}
205
+ type="text"
206
+ value={inputValue}
207
+ />
208
+ </div>
209
+ );
210
+ });
211
+
212
+ TagsInput.displayName = "TagsInput";
package/src/index.ts CHANGED
@@ -28,6 +28,23 @@ export {
28
28
  CommandSeparator,
29
29
  CommandShortcut,
30
30
  } from "./components/ui/command";
31
+ export {
32
+ ContextMenu,
33
+ ContextMenuCheckboxItem,
34
+ ContextMenuContent,
35
+ ContextMenuGroup,
36
+ ContextMenuItem,
37
+ ContextMenuLabel,
38
+ ContextMenuPortal,
39
+ ContextMenuRadioGroup,
40
+ ContextMenuRadioItem,
41
+ ContextMenuSeparator,
42
+ ContextMenuShortcut,
43
+ ContextMenuSub,
44
+ ContextMenuSubContent,
45
+ ContextMenuSubTrigger,
46
+ ContextMenuTrigger,
47
+ } from "./components/ui/context-menu";
31
48
  export * from "./components/ui/dropdown-menu";
32
49
  export {
33
50
  HoverCard,
@@ -78,10 +95,10 @@ export {
78
95
  } from "./components/ui/table";
79
96
  export { Tabs, TabsContent, TabsList, TabsTrigger } from "./components/ui/tabs";
80
97
  export { Textarea } from "./components/ui/textarea";
98
+ // extend
81
99
  export type { ActionProps } from "./components/uix/action";
82
100
  export { Action } from "./components/uix/action";
83
101
  export type { AlertProps } from "./components/uix/alert";
84
- // extend
85
102
  export { Alert } from "./components/uix/alert";
86
103
  export type { ConfirmProps } from "./components/uix/alert-dialog";
87
104
  export { useAlert } from "./components/uix/alert-dialog";
@@ -141,6 +158,8 @@ export type { StepsItemProps, StepsProps } from "./components/uix/steps";
141
158
  export { Steps, StepsItem } from "./components/uix/steps";
142
159
  export type { SwitchProps } from "./components/uix/switch";
143
160
  export { Switch } from "./components/uix/switch";
161
+ export type { TagsInputProps } from "./components/uix/tags-input";
162
+ export { TagsInput } from "./components/uix/tags-input";
144
163
  export type { TooltipProps } from "./components/uix/tooltip";
145
164
  export { Tooltip } from "./components/uix/tooltip";
146
165
  export type { TreeData, TreeProps } from "./components/uix/tree";