@meta-1/design 0.0.198 → 0.0.200
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 +3 -1
- package/src/assets/locales/en-us.ts +4 -0
- package/src/assets/locales/zh-cn.ts +4 -0
- package/src/assets/locales/zh-tw.ts +4 -0
- package/src/assets/style/theme.css +72 -21
- package/src/components/ui/button.tsx +28 -18
- package/src/components/uix/action/index.tsx +7 -5
- package/src/components/uix/action/style.css +21 -0
- package/src/components/uix/alert/index.tsx +5 -5
- package/src/components/uix/alert-dialog/index.tsx +56 -16
- package/src/components/uix/badge/index.tsx +8 -2
- package/src/components/uix/button/index.tsx +7 -5
- package/src/components/uix/card/index.tsx +7 -4
- package/src/components/uix/checkbox-group/index.tsx +3 -4
- package/src/components/uix/combo-select/index.tsx +99 -129
- package/src/components/uix/command/index.tsx +126 -0
- package/src/components/uix/data-grid/index.tsx +625 -0
- package/src/components/uix/data-grid/overlays.tsx +26 -0
- package/src/components/uix/data-grid/style.css +6 -0
- package/src/components/uix/data-table/index.tsx +17 -8
- package/src/components/uix/date-picker/index.tsx +55 -46
- package/src/components/uix/date-range-picker/index.tsx +116 -36
- package/src/components/uix/dialog/index.tsx +5 -5
- package/src/components/uix/dropdown/index.tsx +1 -1
- package/src/components/uix/input/index.tsx +23 -0
- package/src/components/uix/message/index.tsx +4 -4
- package/src/components/uix/pagination/index.tsx +17 -31
- package/src/components/uix/popover/index.tsx +30 -0
- package/src/components/uix/radio-group/index.tsx +2 -2
- package/src/components/uix/select/index.tsx +6 -2
- package/src/components/uix/sheet/index.tsx +76 -0
- package/src/components/uix/tabs/index.tsx +38 -0
- package/src/components/uix/tags-input/index.tsx +22 -3
- package/src/components/uix/textarea/index.tsx +23 -0
- package/src/components/uix/tooltip/index.tsx +5 -4
- package/src/components/uix/tree/style.css +1 -0
- package/src/components/uix/tree-select/index.tsx +59 -64
- package/src/components/uix/uploader/index.tsx +1 -1
- package/src/components/uix/value-formatter/index.tsx +40 -46
- package/src/index.ts +19 -35
- package/src/lib/utils.ts +50 -1
- package/src/components/uix/breadcrumbs/index.tsx +0 -38
- package/src/components/uix/space/index.tsx +0 -24
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { FC } from "react";
|
|
2
|
+
|
|
3
|
+
import { ScrollArea } from "@meta-1/design/components/ui/scroll-area";
|
|
4
|
+
import {
|
|
5
|
+
SheetClose,
|
|
6
|
+
SheetContent,
|
|
7
|
+
SheetDescription,
|
|
8
|
+
SheetFooter,
|
|
9
|
+
SheetHeader,
|
|
10
|
+
SheetTitle,
|
|
11
|
+
SheetTrigger,
|
|
12
|
+
Sheet as UISheet,
|
|
13
|
+
} from "@meta-1/design/components/ui/sheet";
|
|
14
|
+
import { cn } from "@meta-1/design/lib/utils";
|
|
15
|
+
|
|
16
|
+
export type SheetProps = {
|
|
17
|
+
open?: boolean;
|
|
18
|
+
onOpenChange?: (open: boolean) => void;
|
|
19
|
+
title?: React.ReactNode;
|
|
20
|
+
description?: React.ReactNode;
|
|
21
|
+
content?: React.ReactNode;
|
|
22
|
+
children?: React.ReactNode;
|
|
23
|
+
side?: "top" | "right" | "bottom" | "left";
|
|
24
|
+
className?: string;
|
|
25
|
+
closable?: boolean;
|
|
26
|
+
asChild?: boolean;
|
|
27
|
+
footer?: React.ReactNode;
|
|
28
|
+
maskClosable?: boolean;
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const Sheet: FC<SheetProps> = (props) => {
|
|
32
|
+
const {
|
|
33
|
+
open,
|
|
34
|
+
onOpenChange,
|
|
35
|
+
title,
|
|
36
|
+
description,
|
|
37
|
+
content,
|
|
38
|
+
children,
|
|
39
|
+
side,
|
|
40
|
+
className,
|
|
41
|
+
closable,
|
|
42
|
+
asChild,
|
|
43
|
+
footer,
|
|
44
|
+
maskClosable = true,
|
|
45
|
+
} = props;
|
|
46
|
+
return (
|
|
47
|
+
<UISheet onOpenChange={onOpenChange} open={open}>
|
|
48
|
+
<SheetTrigger asChild={asChild}>{children}</SheetTrigger>
|
|
49
|
+
<SheetContent
|
|
50
|
+
className={cn(
|
|
51
|
+
"gap-sheet",
|
|
52
|
+
"[&>button:last-child]:flex [&>button:last-child]:items-center [&>button:last-child]:justify-center",
|
|
53
|
+
className,
|
|
54
|
+
closable === false && "[&>button:last-child]:hidden",
|
|
55
|
+
)}
|
|
56
|
+
onInteractOutside={(e) => {
|
|
57
|
+
if (!maskClosable) {
|
|
58
|
+
e.preventDefault();
|
|
59
|
+
}
|
|
60
|
+
}}
|
|
61
|
+
side={side}
|
|
62
|
+
>
|
|
63
|
+
<SheetHeader className={cn("p-sheet pb-0", !title && !description && "sr-only")}>
|
|
64
|
+
<SheetTitle className={cn(!title && "sr-only")}>{title || "Sheet"}</SheetTitle>
|
|
65
|
+
<SheetDescription className={cn(!description && "sr-only")}>
|
|
66
|
+
{description || "Sheet content"}
|
|
67
|
+
</SheetDescription>
|
|
68
|
+
</SheetHeader>
|
|
69
|
+
<ScrollArea className="flex-1">{content}</ScrollArea>
|
|
70
|
+
{footer != null && <SheetFooter className="p-sheet pt-0">{footer}</SheetFooter>}
|
|
71
|
+
</SheetContent>
|
|
72
|
+
</UISheet>
|
|
73
|
+
);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export { SheetClose };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { FC } from "react";
|
|
2
|
+
|
|
3
|
+
import { TabsContent, TabsList, TabsTrigger, Tabs as UITabs } from "../../ui/tabs";
|
|
4
|
+
|
|
5
|
+
export type TabsItem = {
|
|
6
|
+
label: string;
|
|
7
|
+
value: string;
|
|
8
|
+
content?: React.ReactNode;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export type TabsProps = {
|
|
12
|
+
items: TabsItem[];
|
|
13
|
+
defaultValue?: string;
|
|
14
|
+
value?: string;
|
|
15
|
+
onChange?: (value: string) => void;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export const Tabs: FC<TabsProps> = (props) => {
|
|
19
|
+
const { items, defaultValue, value, onChange } = props;
|
|
20
|
+
return (
|
|
21
|
+
<UITabs defaultValue={defaultValue} onValueChange={onChange} value={value}>
|
|
22
|
+
<TabsList className="h-tabs-title rounded-tabs-title">
|
|
23
|
+
{items.map((item) => (
|
|
24
|
+
<TabsTrigger className="rounded-tabs-title" key={item.value} value={item.value}>
|
|
25
|
+
{item.label}
|
|
26
|
+
</TabsTrigger>
|
|
27
|
+
))}
|
|
28
|
+
</TabsList>
|
|
29
|
+
{items.map((item) =>
|
|
30
|
+
item.content ? (
|
|
31
|
+
<TabsContent key={item.value} value={item.value}>
|
|
32
|
+
{item.content}
|
|
33
|
+
</TabsContent>
|
|
34
|
+
) : null,
|
|
35
|
+
)}
|
|
36
|
+
</UITabs>
|
|
37
|
+
);
|
|
38
|
+
};
|
|
@@ -17,6 +17,7 @@ export interface TagsInputProps {
|
|
|
17
17
|
separator?: string | RegExp;
|
|
18
18
|
validate?: (tag: string) => boolean;
|
|
19
19
|
disabled?: boolean;
|
|
20
|
+
allowClear?: boolean;
|
|
20
21
|
onTagAdd?: (tag: string) => void;
|
|
21
22
|
onTagRemove?: (tag: string) => void;
|
|
22
23
|
renderTag?: (tag: string, index: number, remove: () => void) => React.ReactNode;
|
|
@@ -37,6 +38,7 @@ export const TagsInput = forwardRef<HTMLDivElement, TagsInputProps>((props, ref)
|
|
|
37
38
|
separator = ",",
|
|
38
39
|
validate,
|
|
39
40
|
disabled = false,
|
|
41
|
+
allowClear = false,
|
|
40
42
|
onTagAdd,
|
|
41
43
|
onTagRemove,
|
|
42
44
|
renderTag,
|
|
@@ -147,10 +149,16 @@ export const TagsInput = forwardRef<HTMLDivElement, TagsInputProps>((props, ref)
|
|
|
147
149
|
inputRef.current?.focus();
|
|
148
150
|
};
|
|
149
151
|
|
|
152
|
+
const clearAll = (e: React.MouseEvent) => {
|
|
153
|
+
e.stopPropagation();
|
|
154
|
+
handleChange([]);
|
|
155
|
+
setInputValue("");
|
|
156
|
+
};
|
|
157
|
+
|
|
150
158
|
const defaultRenderTag = (tag: string, index: number, remove: () => void) => (
|
|
151
159
|
<div
|
|
152
160
|
className={cn(
|
|
153
|
-
"inline-flex items-center gap-
|
|
161
|
+
"inline-flex items-center gap-0.5 rounded-input bg-secondary px-1.5 py-0.5 text-xs transition-colors",
|
|
154
162
|
"hover:bg-secondary/80",
|
|
155
163
|
disabled && "pointer-events-none opacity-50",
|
|
156
164
|
tagClassName,
|
|
@@ -167,7 +175,7 @@ export const TagsInput = forwardRef<HTMLDivElement, TagsInputProps>((props, ref)
|
|
|
167
175
|
}}
|
|
168
176
|
type="button"
|
|
169
177
|
>
|
|
170
|
-
<XIcon className="
|
|
178
|
+
<XIcon className="size-4" />
|
|
171
179
|
</button>
|
|
172
180
|
)}
|
|
173
181
|
</div>
|
|
@@ -176,7 +184,8 @@ export const TagsInput = forwardRef<HTMLDivElement, TagsInputProps>((props, ref)
|
|
|
176
184
|
return (
|
|
177
185
|
<div
|
|
178
186
|
className={cn(
|
|
179
|
-
"flex min-h-
|
|
187
|
+
"group relative flex min-h-input w-full flex-wrap gap-0.5 rounded-input border border-input bg-transparent py-0.5 text-sm shadow-xs transition-[color,box-shadow]",
|
|
188
|
+
currentTags.length > 0 ? "px-0.5" : "px-input",
|
|
180
189
|
"focus-within:border-ring focus-within:ring-[3px] focus-within:ring-ring/50",
|
|
181
190
|
disabled && "pointer-events-none cursor-not-allowed opacity-50",
|
|
182
191
|
"dark:bg-input/30",
|
|
@@ -195,6 +204,7 @@ export const TagsInput = forwardRef<HTMLDivElement, TagsInputProps>((props, ref)
|
|
|
195
204
|
className={cn(
|
|
196
205
|
"min-w-[120px] flex-1 bg-transparent text-sm outline-none placeholder:text-muted-foreground",
|
|
197
206
|
"disabled:pointer-events-none disabled:cursor-not-allowed",
|
|
207
|
+
allowClear && currentTags.length > 0 && "pr-6",
|
|
198
208
|
inputClassName,
|
|
199
209
|
)}
|
|
200
210
|
disabled={disabled || (maxTags !== undefined && currentTags.length >= maxTags)}
|
|
@@ -208,6 +218,15 @@ export const TagsInput = forwardRef<HTMLDivElement, TagsInputProps>((props, ref)
|
|
|
208
218
|
type="text"
|
|
209
219
|
value={inputValue}
|
|
210
220
|
/>
|
|
221
|
+
|
|
222
|
+
{allowClear && currentTags.length > 0 && !disabled && (
|
|
223
|
+
<div
|
|
224
|
+
className="absolute top-0 right-0 z-10 hidden h-full cursor-pointer items-center justify-center px-2 group-hover:flex"
|
|
225
|
+
onClick={clearAll}
|
|
226
|
+
>
|
|
227
|
+
<XIcon className="size-4 opacity-50" />
|
|
228
|
+
</div>
|
|
229
|
+
)}
|
|
211
230
|
</div>
|
|
212
231
|
);
|
|
213
232
|
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { forwardRef } from "react";
|
|
2
|
+
|
|
3
|
+
import { Textarea as UITextarea } from "@meta-1/design/components/ui/textarea";
|
|
4
|
+
import { cn } from "@meta-1/design/lib/utils";
|
|
5
|
+
|
|
6
|
+
export interface TextareaProps extends Omit<React.ComponentProps<"textarea">, "onChange"> {
|
|
7
|
+
className?: string;
|
|
8
|
+
onChange?: (value: string) => void;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export const Textarea = forwardRef<HTMLTextAreaElement, TextareaProps>((props, forwardedRef) => {
|
|
12
|
+
const { className, onChange, ...rest } = props;
|
|
13
|
+
const elementRef = forwardedRef;
|
|
14
|
+
|
|
15
|
+
return (
|
|
16
|
+
<UITextarea
|
|
17
|
+
className={cn("rounded-input p-input", className)}
|
|
18
|
+
onChange={(e) => onChange?.(e.target.value)}
|
|
19
|
+
{...rest}
|
|
20
|
+
ref={elementRef}
|
|
21
|
+
/>
|
|
22
|
+
);
|
|
23
|
+
});
|
|
@@ -4,8 +4,9 @@ import {
|
|
|
4
4
|
TooltipContent,
|
|
5
5
|
TooltipProvider,
|
|
6
6
|
TooltipTrigger,
|
|
7
|
-
Tooltip as
|
|
7
|
+
Tooltip as UITooltip,
|
|
8
8
|
} from "@meta-1/design/components/ui/tooltip";
|
|
9
|
+
import { cn } from "@meta-1/design/lib/utils";
|
|
9
10
|
|
|
10
11
|
type Side = "top" | "right" | "bottom" | "left";
|
|
11
12
|
|
|
@@ -21,12 +22,12 @@ export const Tooltip: FC<TooltipProps> = (props) => {
|
|
|
21
22
|
const { open, onOpenChange, className } = props;
|
|
22
23
|
return (
|
|
23
24
|
<TooltipProvider>
|
|
24
|
-
<
|
|
25
|
+
<UITooltip onOpenChange={onOpenChange} open={open}>
|
|
25
26
|
<TooltipTrigger asChild={true}>{props.children}</TooltipTrigger>
|
|
26
|
-
<TooltipContent className={className} side={props.side}>
|
|
27
|
+
<TooltipContent className={cn("rounded-tooltip p-tooltip", className)} side={props.side}>
|
|
27
28
|
{props.content}
|
|
28
29
|
</TooltipContent>
|
|
29
|
-
</
|
|
30
|
+
</UITooltip>
|
|
30
31
|
</TooltipProvider>
|
|
31
32
|
);
|
|
32
33
|
};
|
|
@@ -2,19 +2,7 @@ import { type FC, type ReactNode, useEffect, useMemo, useRef, useState } from "r
|
|
|
2
2
|
import { CaretSortIcon, Cross2Icon } from "@radix-ui/react-icons";
|
|
3
3
|
import classNames from "classnames";
|
|
4
4
|
|
|
5
|
-
import {
|
|
6
|
-
cn,
|
|
7
|
-
Empty,
|
|
8
|
-
type EmptyProps,
|
|
9
|
-
Popover,
|
|
10
|
-
PopoverContent,
|
|
11
|
-
PopoverTrigger,
|
|
12
|
-
ScrollArea,
|
|
13
|
-
Spin,
|
|
14
|
-
Tree,
|
|
15
|
-
type TreeData,
|
|
16
|
-
useSize,
|
|
17
|
-
} from "@meta-1/design";
|
|
5
|
+
import { cn, Empty, type EmptyProps, Popover, ScrollArea, Spin, Tree, type TreeData, useSize } from "@meta-1/design";
|
|
18
6
|
import { Button } from "@meta-1/design/components/ui/button";
|
|
19
7
|
|
|
20
8
|
export type TreeSelectProps = {
|
|
@@ -80,60 +68,67 @@ export const TreeSelect: FC<TreeSelectProps> = (props) => {
|
|
|
80
68
|
}
|
|
81
69
|
}, [value]);
|
|
82
70
|
|
|
71
|
+
const content = (
|
|
72
|
+
<ScrollArea className={classNames("flex max-h-[30vh] flex-col", contentClassName)}>
|
|
73
|
+
{treeData?.length ? (
|
|
74
|
+
<Tree
|
|
75
|
+
expandedKeys={expandedKeys}
|
|
76
|
+
onExpand={(expandedKeys) => setExpandedKeys(expandedKeys as string[])}
|
|
77
|
+
onSelect={(selectedKeys, { selected }) => {
|
|
78
|
+
if (selected) {
|
|
79
|
+
onChange?.(selectedKeys[0] as string);
|
|
80
|
+
setSelectedKeys(selectedKeys as string[]);
|
|
81
|
+
}
|
|
82
|
+
setOpen(false);
|
|
83
|
+
}}
|
|
84
|
+
selectedKeys={selectedKeys}
|
|
85
|
+
treeData={treeData}
|
|
86
|
+
/>
|
|
87
|
+
) : (
|
|
88
|
+
<Empty {...(emptyProps ?? {})} />
|
|
89
|
+
)}
|
|
90
|
+
</ScrollArea>
|
|
91
|
+
);
|
|
92
|
+
|
|
83
93
|
return (
|
|
84
|
-
<Popover
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
onChange?.(undefined);
|
|
108
|
-
e.stopPropagation();
|
|
109
|
-
}}
|
|
110
|
-
/>
|
|
111
|
-
</div>
|
|
112
|
-
)}
|
|
113
|
-
</div>
|
|
114
|
-
</Button>
|
|
115
|
-
</PopoverTrigger>
|
|
116
|
-
<PopoverContent className="p-0" style={{ width: size.width }}>
|
|
117
|
-
<ScrollArea className={classNames("flex max-h-[30vh] flex-col", contentClassName)}>
|
|
118
|
-
{treeData?.length ? (
|
|
119
|
-
<Tree
|
|
120
|
-
expandedKeys={expandedKeys}
|
|
121
|
-
onExpand={(expandedKeys) => setExpandedKeys(expandedKeys as string[])}
|
|
122
|
-
onSelect={(selectedKeys, { selected }) => {
|
|
123
|
-
if (selected) {
|
|
124
|
-
onChange?.(selectedKeys[0] as string);
|
|
125
|
-
setSelectedKeys(selectedKeys as string[]);
|
|
126
|
-
}
|
|
127
|
-
setOpen(false);
|
|
128
|
-
}}
|
|
129
|
-
selectedKeys={selectedKeys}
|
|
130
|
-
treeData={treeData}
|
|
131
|
-
/>
|
|
94
|
+
<Popover
|
|
95
|
+
asChild
|
|
96
|
+
className="p-0"
|
|
97
|
+
content={content}
|
|
98
|
+
disabled={loading || disabled}
|
|
99
|
+
onOpenChange={setOpen}
|
|
100
|
+
open={open}
|
|
101
|
+
style={{ width: size.width }}
|
|
102
|
+
>
|
|
103
|
+
<Button
|
|
104
|
+
aria-expanded={open}
|
|
105
|
+
className={cn(
|
|
106
|
+
"group h-9 min-w-[150px] items-center justify-between px-2 py-1 align-middle hover:bg-secondary/40",
|
|
107
|
+
className,
|
|
108
|
+
)}
|
|
109
|
+
disabled={loading || disabled}
|
|
110
|
+
ref={containerRef}
|
|
111
|
+
variant="outline"
|
|
112
|
+
>
|
|
113
|
+
<div className="flex flex-1 items-center justify-center">
|
|
114
|
+
<div className="flex flex-1">{showValue}</div>
|
|
115
|
+
{loading ? (
|
|
116
|
+
<Spin />
|
|
132
117
|
) : (
|
|
133
|
-
<
|
|
118
|
+
<div className="flex items-center">
|
|
119
|
+
<CaretSortIcon className={cn("block h-4 w-4", showClear ? "group-hover:hidden" : "")} />
|
|
120
|
+
<Cross2Icon
|
|
121
|
+
className={cn("hidden h-4 w-4", showClear ? "group-hover:block" : "")}
|
|
122
|
+
onClick={(e) => {
|
|
123
|
+
setSelectedKeys([]);
|
|
124
|
+
onChange?.(undefined);
|
|
125
|
+
e.stopPropagation();
|
|
126
|
+
}}
|
|
127
|
+
/>
|
|
128
|
+
</div>
|
|
134
129
|
)}
|
|
135
|
-
</
|
|
136
|
-
</
|
|
130
|
+
</div>
|
|
131
|
+
</Button>
|
|
137
132
|
</Popover>
|
|
138
133
|
);
|
|
139
134
|
};
|
|
@@ -222,7 +222,7 @@ export const Uploader = forwardRef<HTMLDivElement, UploaderProps>((props, forwar
|
|
|
222
222
|
<div
|
|
223
223
|
className={cn(
|
|
224
224
|
"flex items-center justify-center p-6 text-card-foreground/50",
|
|
225
|
-
"rounded-
|
|
225
|
+
"rounded-input border-2 border-border border-dashed bg-card",
|
|
226
226
|
"cursor-default",
|
|
227
227
|
"focus:border-primary",
|
|
228
228
|
isMaxFilesReached && "cursor-not-allowed opacity-50",
|
|
@@ -1,59 +1,53 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { forwardRef, type PropsWithChildren } from "react";
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
// biome-ignore lint/suspicious/noExplicitAny: <formatter functions can accept any value type>
|
|
4
|
+
export type Formatter = (value: any) => any;
|
|
5
|
+
export type Formatters = Formatter[];
|
|
4
6
|
|
|
5
|
-
// biome-ignore lint/suspicious/noExplicitAny: <
|
|
6
|
-
export
|
|
7
|
-
// biome-ignore lint/suspicious/noExplicitAny: <functionMap>
|
|
8
|
-
export type FunctionMap = Record<string, (value: any, ...args: any[]) => any>;
|
|
9
|
-
|
|
10
|
-
const _handles: FunctionMap = {};
|
|
11
|
-
|
|
12
|
-
export const register = (handles: FunctionMap) => {
|
|
13
|
-
Object.assign(_handles, handles);
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
// biome-ignore lint/suspicious/noExplicitAny: <v>
|
|
17
|
-
export const formatValue = (v: any, formatters: Formatters, all?: FunctionMap) => {
|
|
18
|
-
// biome-ignore lint/suspicious/noExplicitAny: <merged>
|
|
19
|
-
const merged: any = { ...BUILT_IN, ..._handles, ...(all ?? {}) };
|
|
20
|
-
// biome-ignore lint/suspicious/noExplicitAny: <fallback>
|
|
21
|
-
const fallback = (v: any, ..._p: any[]) => v;
|
|
22
|
-
// biome-ignore lint/suspicious/noExplicitAny: <params>
|
|
23
|
-
let params: any[] = [];
|
|
7
|
+
// biome-ignore lint/suspicious/noExplicitAny: <formatter functions can accept any value type>
|
|
8
|
+
export const formatValue = (v: any, formatters: Formatters) => {
|
|
24
9
|
let result = v;
|
|
25
10
|
|
|
26
|
-
for (const
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
call = merged[filter[0]] || fallback;
|
|
34
|
-
params = filter[1];
|
|
35
|
-
}
|
|
36
|
-
try {
|
|
37
|
-
result = call(result, ...params);
|
|
38
|
-
} catch {
|
|
39
|
-
console.log("formatter error", filter);
|
|
11
|
+
for (const formatter of formatters) {
|
|
12
|
+
if (typeof formatter === "function") {
|
|
13
|
+
try {
|
|
14
|
+
result = formatter(result);
|
|
15
|
+
} catch (error) {
|
|
16
|
+
console.warn("Formatter error:", error);
|
|
17
|
+
}
|
|
40
18
|
}
|
|
41
19
|
}
|
|
42
20
|
return result;
|
|
43
21
|
};
|
|
44
22
|
|
|
45
23
|
export interface ValueFormatterProps extends PropsWithChildren {
|
|
46
|
-
// biome-ignore lint/suspicious/noExplicitAny: <value>
|
|
24
|
+
// biome-ignore lint/suspicious/noExplicitAny: <formatters chain can transform value to any type>
|
|
47
25
|
value?: any;
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
26
|
+
formatters?: Formatters;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function ValueFormatterInner(props: ValueFormatterProps, _ref: React.ForwardedRef<never>) {
|
|
30
|
+
const { formatters = [], value, children } = props;
|
|
31
|
+
const v = value === 0 ? value : value || children;
|
|
32
|
+
const formatted = formatValue(v, formatters);
|
|
33
|
+
return <>{formatted}</>;
|
|
51
34
|
}
|
|
52
35
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
36
|
+
ValueFormatterInner.displayName = "ValueFormatter";
|
|
37
|
+
|
|
38
|
+
export const ValueFormatter = forwardRef(ValueFormatterInner);
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* 类型辅助函数,用于为 formatters 提供类型信息
|
|
42
|
+
* 使用示例:
|
|
43
|
+
* ```tsx
|
|
44
|
+
* const formatters = createFormatters<string[]>([
|
|
45
|
+
* (v) => v.join("|"),
|
|
46
|
+
* (v) => v.toUpperCase(),
|
|
47
|
+
* ]);
|
|
48
|
+
* <ValueFormatter value={["a", "b"]} formatters={formatters} />
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export function createFormatters<TInput = any>(formatters: Array<(value: TInput) => any>): Formatters {
|
|
52
|
+
return formatters as Formatters;
|
|
53
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -17,16 +17,6 @@ export {
|
|
|
17
17
|
BreadcrumbSeparator,
|
|
18
18
|
} from "./components/ui/breadcrumb";
|
|
19
19
|
export { Calendar } from "./components/ui/calendar";
|
|
20
|
-
export {
|
|
21
|
-
Command,
|
|
22
|
-
CommandEmpty,
|
|
23
|
-
CommandGroup,
|
|
24
|
-
CommandInput,
|
|
25
|
-
CommandItem,
|
|
26
|
-
CommandList,
|
|
27
|
-
CommandSeparator,
|
|
28
|
-
CommandShortcut,
|
|
29
|
-
} from "./components/ui/command";
|
|
30
20
|
export {
|
|
31
21
|
ContextMenu,
|
|
32
22
|
ContextMenuCheckboxItem,
|
|
@@ -50,13 +40,7 @@ export {
|
|
|
50
40
|
HoverCardContent,
|
|
51
41
|
HoverCardTrigger,
|
|
52
42
|
} from "./components/ui/hover-card";
|
|
53
|
-
export { Input } from "./components/ui/input";
|
|
54
43
|
export * from "./components/ui/navigation-menu";
|
|
55
|
-
export {
|
|
56
|
-
Popover,
|
|
57
|
-
PopoverContent,
|
|
58
|
-
PopoverTrigger,
|
|
59
|
-
} from "./components/ui/popover";
|
|
60
44
|
export { Progress } from "./components/ui/progress";
|
|
61
45
|
export {
|
|
62
46
|
ResizableHandle,
|
|
@@ -65,16 +49,6 @@ export {
|
|
|
65
49
|
} from "./components/ui/resizable";
|
|
66
50
|
export { ScrollArea, ScrollBar } from "./components/ui/scroll-area";
|
|
67
51
|
export { Separator } from "./components/ui/separator";
|
|
68
|
-
export {
|
|
69
|
-
Sheet,
|
|
70
|
-
SheetClose,
|
|
71
|
-
SheetContent,
|
|
72
|
-
SheetDescription,
|
|
73
|
-
SheetFooter,
|
|
74
|
-
SheetHeader,
|
|
75
|
-
SheetTitle,
|
|
76
|
-
SheetTrigger,
|
|
77
|
-
} from "./components/ui/sheet";
|
|
78
52
|
export { Skeleton } from "./components/ui/skeleton";
|
|
79
53
|
export { Slider } from "./components/ui/slider";
|
|
80
54
|
// base
|
|
@@ -89,21 +63,17 @@ export {
|
|
|
89
63
|
TableHeader,
|
|
90
64
|
TableRow,
|
|
91
65
|
} from "./components/ui/table";
|
|
92
|
-
export { Tabs, TabsContent, TabsList, TabsTrigger } from "./components/ui/tabs";
|
|
93
|
-
export { Textarea } from "./components/ui/textarea";
|
|
94
66
|
// advanced components
|
|
95
67
|
export type { ActionProps } from "./components/uix/action";
|
|
96
68
|
export { Action } from "./components/uix/action";
|
|
97
69
|
export type { AlertProps } from "./components/uix/alert";
|
|
98
70
|
export { Alert } from "./components/uix/alert";
|
|
99
|
-
export type { ConfirmProps } from "./components/uix/alert-dialog";
|
|
71
|
+
export type { AlertDialogProps, ConfirmProps } from "./components/uix/alert-dialog";
|
|
100
72
|
export { useAlert } from "./components/uix/alert-dialog";
|
|
101
73
|
export type { AvatarProps } from "./components/uix/avatar";
|
|
102
74
|
export { Avatar } from "./components/uix/avatar";
|
|
103
75
|
export type { BadgeProps, BadgeVariant } from "./components/uix/badge";
|
|
104
76
|
export { Badge } from "./components/uix/badge";
|
|
105
|
-
export type { BreadcrumbsItemProps, BreadcrumbsProps } from "./components/uix/breadcrumbs";
|
|
106
|
-
export { Breadcrumbs, BreadcrumbsItem } from "./components/uix/breadcrumbs";
|
|
107
77
|
export type { BroadcastChannelProviderProps } from "./components/uix/broadcast-channel-context";
|
|
108
78
|
export { BroadcastChannelProvider, useBroadcastChannel } from "./components/uix/broadcast-channel-context";
|
|
109
79
|
export type { ButtonProps } from "./components/uix/button";
|
|
@@ -116,13 +86,17 @@ export type { CheckboxGroupOptionProps, CheckboxGroupProps } from "./components/
|
|
|
116
86
|
export { CheckboxGroup } from "./components/uix/checkbox-group";
|
|
117
87
|
export type { ComboSelectOptionProps, ComboSelectProps, ComboSelectValueType } from "./components/uix/combo-select";
|
|
118
88
|
export { ComboSelect } from "./components/uix/combo-select";
|
|
89
|
+
export type { CommandItemProps, CommandProps } from "./components/uix/command";
|
|
90
|
+
export { Command } from "./components/uix/command";
|
|
119
91
|
export type { ConfigProviderProps } from "./components/uix/config-provider";
|
|
120
92
|
export { ConfigProvider } from "./components/uix/config-provider";
|
|
93
|
+
export type { DataGridColumn, DataGridProps, StickyColumnProps } from "./components/uix/data-grid";
|
|
94
|
+
export { DataGrid } from "./components/uix/data-grid";
|
|
121
95
|
export type { DataTableColumn, DataTableProps } from "./components/uix/data-table";
|
|
122
96
|
export { DataTable } from "./components/uix/data-table";
|
|
123
97
|
export type { DatePickerProps } from "./components/uix/date-picker";
|
|
124
98
|
export { DatePicker } from "./components/uix/date-picker";
|
|
125
|
-
export type { DateRangePickerProps } from "./components/uix/date-range-picker";
|
|
99
|
+
export type { DateRange, DateRangePickerProps } from "./components/uix/date-range-picker";
|
|
126
100
|
export { DateRangePicker } from "./components/uix/date-range-picker";
|
|
127
101
|
export type { DialogProps } from "./components/uix/dialog";
|
|
128
102
|
export { Dialog } from "./components/uix/dialog";
|
|
@@ -138,26 +112,36 @@ export type { FieldItem, FormInstance, FormProps, RenderProps } from "./componen
|
|
|
138
112
|
export { Form, FormItem } from "./components/uix/form";
|
|
139
113
|
export type { ImageProps } from "./components/uix/image";
|
|
140
114
|
export { Image } from "./components/uix/image";
|
|
115
|
+
export { Input } from "./components/uix/input";
|
|
141
116
|
export type { LoadingProps } from "./components/uix/loading";
|
|
142
117
|
export { Loading } from "./components/uix/loading";
|
|
143
118
|
export { useMessage } from "./components/uix/message";
|
|
144
119
|
export type { PaginationProps } from "./components/uix/pagination";
|
|
145
120
|
export { Pagination } from "./components/uix/pagination";
|
|
121
|
+
export type { PopoverProps } from "./components/uix/popover";
|
|
122
|
+
export { Popover } from "./components/uix/popover";
|
|
146
123
|
export type { RadioGroupOptionProps, RadioGroupProps } from "./components/uix/radio-group";
|
|
147
124
|
export { RadioGroup } from "./components/uix/radio-group";
|
|
148
125
|
export type { ResultProps } from "./components/uix/result";
|
|
149
126
|
export { Result } from "./components/uix/result";
|
|
150
127
|
export type { SelectOptionProps, SelectProps } from "./components/uix/select";
|
|
151
128
|
export { Select } from "./components/uix/select";
|
|
152
|
-
export {
|
|
129
|
+
export type { SheetProps } from "./components/uix/sheet";
|
|
130
|
+
export {
|
|
131
|
+
Sheet,
|
|
132
|
+
SheetClose,
|
|
133
|
+
} from "./components/uix/sheet";
|
|
153
134
|
export type { SpinProps } from "./components/uix/spin";
|
|
154
135
|
export { Spin } from "./components/uix/spin";
|
|
155
136
|
export type { StepsItemProps, StepsProps } from "./components/uix/steps";
|
|
156
137
|
export { Steps, StepsItem } from "./components/uix/steps";
|
|
157
138
|
export type { SwitchProps } from "./components/uix/switch";
|
|
158
139
|
export { Switch } from "./components/uix/switch";
|
|
140
|
+
export type { TabsItem, TabsProps } from "./components/uix/tabs";
|
|
141
|
+
export { Tabs } from "./components/uix/tabs";
|
|
159
142
|
export type { TagsInputProps } from "./components/uix/tags-input";
|
|
160
143
|
export { TagsInput } from "./components/uix/tags-input";
|
|
144
|
+
export { Textarea } from "./components/uix/textarea";
|
|
161
145
|
export type { TooltipProps } from "./components/uix/tooltip";
|
|
162
146
|
export { Tooltip } from "./components/uix/tooltip";
|
|
163
147
|
export type { TreeData, TreeProps } from "./components/uix/tree";
|
|
@@ -169,8 +153,8 @@ export { TreeTable } from "./components/uix/tree-table";
|
|
|
169
153
|
export type { UploaderProps } from "./components/uix/uploader";
|
|
170
154
|
export { Uploader } from "./components/uix/uploader";
|
|
171
155
|
export type { HandleProps, UploadFile } from "./components/uix/uploader/type";
|
|
172
|
-
export type { ValueFormatterProps } from "./components/uix/value-formatter";
|
|
173
|
-
export {
|
|
156
|
+
export type { Formatters, ValueFormatterProps } from "./components/uix/value-formatter";
|
|
157
|
+
export { createFormatters, ValueFormatter } from "./components/uix/value-formatter";
|
|
174
158
|
// custom hooks
|
|
175
159
|
export * from "./hooks";
|
|
176
160
|
// utils
|