@meta-1/design 0.0.159
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/README.md +412 -0
- package/package.json +138 -0
- package/src/assets/icons/empty.svg +1 -0
- package/src/assets/icons/spin.svg +1 -0
- package/src/assets/locales/en-us.ts +74 -0
- package/src/assets/locales/zh-cn.ts +74 -0
- package/src/assets/locales/zh-tw.ts +74 -0
- package/src/assets/style/theme.css +173 -0
- package/src/components/icons/Empty.tsx +18 -0
- package/src/components/icons/Spin.tsx +16 -0
- package/src/components/icons/index.ts +2 -0
- package/src/components/ui/alert-dialog.tsx +111 -0
- package/src/components/ui/alert.tsx +49 -0
- package/src/components/ui/avatar.tsx +32 -0
- package/src/components/ui/badge.tsx +36 -0
- package/src/components/ui/breadcrumb.tsx +92 -0
- package/src/components/ui/button.tsx +52 -0
- package/src/components/ui/calendar.tsx +56 -0
- package/src/components/ui/card.tsx +56 -0
- package/src/components/ui/checkbox.tsx +28 -0
- package/src/components/ui/command.tsx +137 -0
- package/src/components/ui/dialog.tsx +127 -0
- package/src/components/ui/dropdown-menu.tsx +217 -0
- package/src/components/ui/form.tsx +138 -0
- package/src/components/ui/hover-card.tsx +36 -0
- package/src/components/ui/input-otp.tsx +66 -0
- package/src/components/ui/input.tsx +21 -0
- package/src/components/ui/label.tsx +21 -0
- package/src/components/ui/navigation-menu.tsx +142 -0
- package/src/components/ui/pagination.tsx +118 -0
- package/src/components/ui/popover.tsx +40 -0
- package/src/components/ui/progress.tsx +22 -0
- package/src/components/ui/radio-group.tsx +31 -0
- package/src/components/ui/resizable.tsx +46 -0
- package/src/components/ui/scroll-area.tsx +46 -0
- package/src/components/ui/select.tsx +158 -0
- package/src/components/ui/separator.tsx +26 -0
- package/src/components/ui/sheet.tsx +101 -0
- package/src/components/ui/skeleton.tsx +7 -0
- package/src/components/ui/sonner.tsx +23 -0
- package/src/components/ui/switch.tsx +26 -0
- package/src/components/ui/table.tsx +73 -0
- package/src/components/ui/tabs.tsx +40 -0
- package/src/components/ui/textarea.tsx +18 -0
- package/src/components/ui/tooltip.tsx +46 -0
- package/src/components/uix/action/index.tsx +37 -0
- package/src/components/uix/alert/index.tsx +43 -0
- package/src/components/uix/alert-dialog/index.tsx +109 -0
- package/src/components/uix/avatar/index.tsx +25 -0
- package/src/components/uix/breadcrumbs/index.tsx +38 -0
- package/src/components/uix/broadcast-channel-context/index.tsx +28 -0
- package/src/components/uix/button/index.tsx +29 -0
- package/src/components/uix/card/index.tsx +32 -0
- package/src/components/uix/checkbox/index.tsx +79 -0
- package/src/components/uix/checkbox-group/index.tsx +60 -0
- package/src/components/uix/combo-select/index.tsx +364 -0
- package/src/components/uix/config-provider/index.tsx +31 -0
- package/src/components/uix/data-table/index.tsx +491 -0
- package/src/components/uix/data-table/style.css +40 -0
- package/src/components/uix/date-picker/index.tsx +88 -0
- package/src/components/uix/date-range-picker/index.tsx +71 -0
- package/src/components/uix/dialog/index.tsx +70 -0
- package/src/components/uix/divider/index.tsx +23 -0
- package/src/components/uix/dropdown/index.tsx +117 -0
- package/src/components/uix/empty/index.tsx +29 -0
- package/src/components/uix/filters/index.tsx +105 -0
- package/src/components/uix/form/index.tsx +274 -0
- package/src/components/uix/image/index.tsx +13 -0
- package/src/components/uix/loading/index.tsx +24 -0
- package/src/components/uix/message/index.tsx +21 -0
- package/src/components/uix/pagination/index.tsx +180 -0
- package/src/components/uix/radio-group/index.tsx +35 -0
- package/src/components/uix/result/index.tsx +45 -0
- package/src/components/uix/select/index.tsx +93 -0
- package/src/components/uix/space/index.tsx +24 -0
- package/src/components/uix/spin/index.tsx +12 -0
- package/src/components/uix/steps/index.tsx +67 -0
- package/src/components/uix/switch/index.tsx +33 -0
- package/src/components/uix/tooltip/index.tsx +29 -0
- package/src/components/uix/tree/index.tsx +39 -0
- package/src/components/uix/tree/style.css +75 -0
- package/src/components/uix/tree-select/index.tsx +137 -0
- package/src/components/uix/tree-table/action.tsx +24 -0
- package/src/components/uix/tree-table/config.ts +2 -0
- package/src/components/uix/tree-table/index.tsx +86 -0
- package/src/components/uix/tree-table/utils.tsx +63 -0
- package/src/components/uix/uploader/index.tsx +237 -0
- package/src/components/uix/uploader/type.ts +20 -0
- package/src/components/uix/uploader/utils.ts +41 -0
- package/src/components/uix/value-formatter/index.tsx +59 -0
- package/src/hooks/index.ts +2 -0
- package/src/hooks/resize.ts +29 -0
- package/src/hooks/use.outside.ts +30 -0
- package/src/index.ts +159 -0
- package/src/lib/formatters.ts +13 -0
- package/src/lib/index.ts +4 -0
- package/src/lib/is.ts +6 -0
- package/src/lib/react-dom.ts +98 -0
- package/src/lib/utils.ts +39 -0
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import type * as LabelPrimitive from "@radix-ui/react-label";
|
|
5
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
6
|
+
import {
|
|
7
|
+
Controller,
|
|
8
|
+
type ControllerProps,
|
|
9
|
+
type FieldPath,
|
|
10
|
+
type FieldValues,
|
|
11
|
+
FormProvider,
|
|
12
|
+
useFormContext,
|
|
13
|
+
useFormState,
|
|
14
|
+
} from "react-hook-form";
|
|
15
|
+
|
|
16
|
+
import { Label } from "@meta-1/design/components/ui/label";
|
|
17
|
+
import { cn } from "@meta-1/design/lib/utils";
|
|
18
|
+
|
|
19
|
+
const Form = FormProvider;
|
|
20
|
+
|
|
21
|
+
type FormFieldContextValue<
|
|
22
|
+
TFieldValues extends FieldValues = FieldValues,
|
|
23
|
+
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
|
|
24
|
+
> = {
|
|
25
|
+
name: TName;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const FormFieldContext = React.createContext<FormFieldContextValue>({} as FormFieldContextValue);
|
|
29
|
+
|
|
30
|
+
const FormField = <
|
|
31
|
+
TFieldValues extends FieldValues = FieldValues,
|
|
32
|
+
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
|
|
33
|
+
>({
|
|
34
|
+
...props
|
|
35
|
+
}: ControllerProps<TFieldValues, TName>) => {
|
|
36
|
+
return (
|
|
37
|
+
<FormFieldContext.Provider value={{ name: props.name }}>
|
|
38
|
+
<Controller {...props} />
|
|
39
|
+
</FormFieldContext.Provider>
|
|
40
|
+
);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const useFormField = () => {
|
|
44
|
+
const fieldContext = React.useContext(FormFieldContext);
|
|
45
|
+
const itemContext = React.useContext(FormItemContext);
|
|
46
|
+
const { getFieldState } = useFormContext();
|
|
47
|
+
const formState = useFormState({ name: fieldContext.name });
|
|
48
|
+
const fieldState = getFieldState(fieldContext.name, formState);
|
|
49
|
+
|
|
50
|
+
if (!fieldContext) {
|
|
51
|
+
throw new Error("useFormField should be used within <FormField>");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const { id } = itemContext;
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
id,
|
|
58
|
+
name: fieldContext.name,
|
|
59
|
+
formItemId: `${id}-form-item`,
|
|
60
|
+
formDescriptionId: `${id}-form-item-description`,
|
|
61
|
+
formMessageId: `${id}-form-item-message`,
|
|
62
|
+
...fieldState,
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
type FormItemContextValue = {
|
|
67
|
+
id: string;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const FormItemContext = React.createContext<FormItemContextValue>({} as FormItemContextValue);
|
|
71
|
+
|
|
72
|
+
function FormItem({ className, ...props }: React.ComponentProps<"div">) {
|
|
73
|
+
const id = React.useId();
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<FormItemContext.Provider value={{ id }}>
|
|
77
|
+
<div className={cn("grid gap-2", className)} data-slot="form-item" {...props} />
|
|
78
|
+
</FormItemContext.Provider>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function FormLabel({ className, ...props }: React.ComponentProps<typeof LabelPrimitive.Root>) {
|
|
83
|
+
const { error, formItemId } = useFormField();
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<Label
|
|
87
|
+
className={cn("data-[error=true]:text-destructive", className)}
|
|
88
|
+
data-error={!!error}
|
|
89
|
+
data-slot="form-label"
|
|
90
|
+
htmlFor={formItemId}
|
|
91
|
+
{...props}
|
|
92
|
+
/>
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function FormControl({ ...props }: React.ComponentProps<typeof Slot>) {
|
|
97
|
+
const { error, formItemId, formDescriptionId, formMessageId } = useFormField();
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<Slot
|
|
101
|
+
aria-describedby={!error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`}
|
|
102
|
+
aria-invalid={!!error}
|
|
103
|
+
data-slot="form-control"
|
|
104
|
+
id={formItemId}
|
|
105
|
+
{...props}
|
|
106
|
+
/>
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function FormDescription({ className, ...props }: React.ComponentProps<"p">) {
|
|
111
|
+
const { formDescriptionId } = useFormField();
|
|
112
|
+
|
|
113
|
+
return (
|
|
114
|
+
<p
|
|
115
|
+
className={cn("text-muted-foreground text-sm", className)}
|
|
116
|
+
data-slot="form-description"
|
|
117
|
+
id={formDescriptionId}
|
|
118
|
+
{...props}
|
|
119
|
+
/>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function FormMessage({ className, ...props }: React.ComponentProps<"p">) {
|
|
124
|
+
const { error, formMessageId } = useFormField();
|
|
125
|
+
const body = error ? String(error?.message ?? "") : props.children;
|
|
126
|
+
|
|
127
|
+
if (!body) {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return (
|
|
132
|
+
<p className={cn("text-destructive text-sm", className)} data-slot="form-message" id={formMessageId} {...props}>
|
|
133
|
+
{body}
|
|
134
|
+
</p>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export { useFormField, Form, FormItem, FormLabel, FormControl, FormDescription, FormMessage, FormField };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type * as React from "react";
|
|
2
|
+
import * as HoverCardPrimitive from "@radix-ui/react-hover-card";
|
|
3
|
+
|
|
4
|
+
import { cn } from "@meta-1/design/lib/utils";
|
|
5
|
+
|
|
6
|
+
function HoverCard({ ...props }: React.ComponentProps<typeof HoverCardPrimitive.Root>) {
|
|
7
|
+
return <HoverCardPrimitive.Root data-slot="hover-card" {...props} />;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function HoverCardTrigger({ ...props }: React.ComponentProps<typeof HoverCardPrimitive.Trigger>) {
|
|
11
|
+
return <HoverCardPrimitive.Trigger data-slot="hover-card-trigger" {...props} />;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function HoverCardContent({
|
|
15
|
+
className,
|
|
16
|
+
align = "center",
|
|
17
|
+
sideOffset = 4,
|
|
18
|
+
...props
|
|
19
|
+
}: React.ComponentProps<typeof HoverCardPrimitive.Content>) {
|
|
20
|
+
return (
|
|
21
|
+
<HoverCardPrimitive.Portal data-slot="hover-card-portal">
|
|
22
|
+
<HoverCardPrimitive.Content
|
|
23
|
+
align={align}
|
|
24
|
+
className={cn(
|
|
25
|
+
"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 z-50 w-64 origin-(--radix-hover-card-content-transform-origin) rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-hidden data-[state=closed]:animate-out data-[state=open]:animate-in",
|
|
26
|
+
className,
|
|
27
|
+
)}
|
|
28
|
+
data-slot="hover-card-content"
|
|
29
|
+
sideOffset={sideOffset}
|
|
30
|
+
{...props}
|
|
31
|
+
/>
|
|
32
|
+
</HoverCardPrimitive.Portal>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export { HoverCard, HoverCardTrigger, HoverCardContent };
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { OTPInput, OTPInputContext } from "input-otp";
|
|
3
|
+
import { MinusIcon } from "lucide-react";
|
|
4
|
+
|
|
5
|
+
import { cn } from "@meta-1/design/lib/utils";
|
|
6
|
+
|
|
7
|
+
function InputOTP({
|
|
8
|
+
className,
|
|
9
|
+
containerClassName,
|
|
10
|
+
...props
|
|
11
|
+
}: React.ComponentProps<typeof OTPInput> & {
|
|
12
|
+
containerClassName?: string;
|
|
13
|
+
}) {
|
|
14
|
+
return (
|
|
15
|
+
<OTPInput
|
|
16
|
+
className={cn("disabled:cursor-not-allowed", className)}
|
|
17
|
+
containerClassName={cn("flex items-center gap-2 has-disabled:opacity-50", containerClassName)}
|
|
18
|
+
data-slot="input-otp"
|
|
19
|
+
{...props}
|
|
20
|
+
/>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function InputOTPGroup({ className, ...props }: React.ComponentProps<"div">) {
|
|
25
|
+
return <div className={cn("flex items-center", className)} data-slot="input-otp-group" {...props} />;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function InputOTPSlot({
|
|
29
|
+
index,
|
|
30
|
+
className,
|
|
31
|
+
...props
|
|
32
|
+
}: React.ComponentProps<"div"> & {
|
|
33
|
+
index: number;
|
|
34
|
+
}) {
|
|
35
|
+
const inputOTPContext = React.useContext(OTPInputContext);
|
|
36
|
+
const { char, hasFakeCaret, isActive } = inputOTPContext?.slots[index] ?? {};
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<div
|
|
40
|
+
className={cn(
|
|
41
|
+
"relative flex h-9 w-9 items-center justify-center border-input border-y border-r text-sm shadow-xs outline-none transition-all first:rounded-l-md first:border-l last:rounded-r-md aria-invalid:border-destructive data-[active=true]:z-10 data-[active=true]:border-ring data-[active=true]:ring-[3px] data-[active=true]:ring-ring/50 data-[active=true]:aria-invalid:border-destructive data-[active=true]:aria-invalid:ring-destructive/20 dark:bg-input/30 dark:data-[active=true]:aria-invalid:ring-destructive/40",
|
|
42
|
+
className,
|
|
43
|
+
)}
|
|
44
|
+
data-active={isActive}
|
|
45
|
+
data-slot="input-otp-slot"
|
|
46
|
+
{...props}
|
|
47
|
+
>
|
|
48
|
+
{char}
|
|
49
|
+
{hasFakeCaret && (
|
|
50
|
+
<div className="pointer-events-none absolute inset-0 flex items-center justify-center">
|
|
51
|
+
<div className="h-4 w-px animate-caret-blink bg-foreground duration-1000" />
|
|
52
|
+
</div>
|
|
53
|
+
)}
|
|
54
|
+
</div>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function InputOTPSeparator({ ...props }: React.ComponentProps<"div">) {
|
|
59
|
+
return (
|
|
60
|
+
<div data-slot="input-otp-separator" role="separator" {...props}>
|
|
61
|
+
<MinusIcon />
|
|
62
|
+
</div>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export { InputOTP, InputOTPGroup, InputOTPSlot, InputOTPSeparator };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type * as React from "react";
|
|
2
|
+
|
|
3
|
+
import { cn } from "@meta-1/design/lib/utils";
|
|
4
|
+
|
|
5
|
+
function Input({ className, type, ...props }: React.ComponentProps<"input">) {
|
|
6
|
+
return (
|
|
7
|
+
<input
|
|
8
|
+
className={cn(
|
|
9
|
+
"flex h-9 w-full min-w-0 rounded-md border border-input bg-transparent px-3 py-1 text-base shadow-xs outline-none transition-[color,box-shadow] selection:bg-primary selection:text-primary-foreground file:inline-flex file:h-7 file:border-0 file:bg-transparent file:font-medium file:text-foreground file:text-sm placeholder:text-muted-foreground disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm dark:bg-input/30",
|
|
10
|
+
"focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50",
|
|
11
|
+
"aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40",
|
|
12
|
+
className,
|
|
13
|
+
)}
|
|
14
|
+
data-slot="input"
|
|
15
|
+
type={type}
|
|
16
|
+
{...props}
|
|
17
|
+
/>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export { Input };
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import type * as React from "react";
|
|
4
|
+
import * as LabelPrimitive from "@radix-ui/react-label";
|
|
5
|
+
|
|
6
|
+
import { cn } from "@meta-1/design/lib/utils";
|
|
7
|
+
|
|
8
|
+
function Label({ className, ...props }: React.ComponentProps<typeof LabelPrimitive.Root>) {
|
|
9
|
+
return (
|
|
10
|
+
<LabelPrimitive.Root
|
|
11
|
+
className={cn(
|
|
12
|
+
"flex select-none items-center gap-2 font-medium text-sm leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-50 group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50",
|
|
13
|
+
className,
|
|
14
|
+
)}
|
|
15
|
+
data-slot="label"
|
|
16
|
+
{...props}
|
|
17
|
+
/>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export { Label };
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import type * as React from "react";
|
|
2
|
+
import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu";
|
|
3
|
+
import { cva } from "class-variance-authority";
|
|
4
|
+
import { ChevronDownIcon } from "lucide-react";
|
|
5
|
+
|
|
6
|
+
import { cn } from "@meta-1/design/lib/utils";
|
|
7
|
+
|
|
8
|
+
function NavigationMenu({
|
|
9
|
+
className,
|
|
10
|
+
children,
|
|
11
|
+
viewport = true,
|
|
12
|
+
...props
|
|
13
|
+
}: React.ComponentProps<typeof NavigationMenuPrimitive.Root> & {
|
|
14
|
+
viewport?: boolean;
|
|
15
|
+
}) {
|
|
16
|
+
return (
|
|
17
|
+
<NavigationMenuPrimitive.Root
|
|
18
|
+
className={cn("group/navigation-menu relative flex max-w-max flex-1 items-center justify-center", className)}
|
|
19
|
+
data-slot="navigation-menu"
|
|
20
|
+
data-viewport={viewport}
|
|
21
|
+
{...props}
|
|
22
|
+
>
|
|
23
|
+
{children}
|
|
24
|
+
{viewport && <NavigationMenuViewport />}
|
|
25
|
+
</NavigationMenuPrimitive.Root>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function NavigationMenuList({ className, ...props }: React.ComponentProps<typeof NavigationMenuPrimitive.List>) {
|
|
30
|
+
return (
|
|
31
|
+
<NavigationMenuPrimitive.List
|
|
32
|
+
className={cn("group flex flex-1 list-none items-center justify-center gap-1", className)}
|
|
33
|
+
data-slot="navigation-menu-list"
|
|
34
|
+
{...props}
|
|
35
|
+
/>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function NavigationMenuItem({ className, ...props }: React.ComponentProps<typeof NavigationMenuPrimitive.Item>) {
|
|
40
|
+
return (
|
|
41
|
+
<NavigationMenuPrimitive.Item className={cn("relative", className)} data-slot="navigation-menu-item" {...props} />
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const navigationMenuTriggerStyle = cva(
|
|
46
|
+
"group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 font-medium text-sm outline-none transition-[color,box-shadow] hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus-visible:outline-1 focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 data-[state=open]:bg-accent/50 data-[state=open]:text-accent-foreground data-[state=open]:focus:bg-accent data-[state=open]:hover:bg-accent",
|
|
47
|
+
);
|
|
48
|
+
|
|
49
|
+
function NavigationMenuTrigger({
|
|
50
|
+
className,
|
|
51
|
+
children,
|
|
52
|
+
...props
|
|
53
|
+
}: React.ComponentProps<typeof NavigationMenuPrimitive.Trigger>) {
|
|
54
|
+
return (
|
|
55
|
+
<NavigationMenuPrimitive.Trigger
|
|
56
|
+
className={cn(navigationMenuTriggerStyle(), "group", className)}
|
|
57
|
+
data-slot="navigation-menu-trigger"
|
|
58
|
+
{...props}
|
|
59
|
+
>
|
|
60
|
+
{children}{" "}
|
|
61
|
+
<ChevronDownIcon
|
|
62
|
+
aria-hidden="true"
|
|
63
|
+
className="relative top-[1px] ml-1 size-3 transition duration-300 group-data-[state=open]:rotate-180"
|
|
64
|
+
/>
|
|
65
|
+
</NavigationMenuPrimitive.Trigger>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function NavigationMenuContent({ className, ...props }: React.ComponentProps<typeof NavigationMenuPrimitive.Content>) {
|
|
70
|
+
return (
|
|
71
|
+
<NavigationMenuPrimitive.Content
|
|
72
|
+
className={cn(
|
|
73
|
+
"data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 top-0 left-0 w-full p-2 pr-2.5 data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out md:absolute md:w-auto",
|
|
74
|
+
"group-data-[viewport=false]/navigation-menu:data-[state=closed]:zoom-out-95 group-data-[viewport=false]/navigation-menu:data-[state=open]:zoom-in-95 group-data-[viewport=false]/navigation-menu:data-[state=open]:fade-in-0 group-data-[viewport=false]/navigation-menu:data-[state=closed]:fade-out-0 **:data-[slot=navigation-menu-link]:focus:outline-none **:data-[slot=navigation-menu-link]:focus:ring-0 group-data-[viewport=false]/navigation-menu:top-full group-data-[viewport=false]/navigation-menu:mt-1.5 group-data-[viewport=false]/navigation-menu:overflow-hidden group-data-[viewport=false]/navigation-menu:rounded-md group-data-[viewport=false]/navigation-menu:border group-data-[viewport=false]/navigation-menu:bg-popover group-data-[viewport=false]/navigation-menu:text-popover-foreground group-data-[viewport=false]/navigation-menu:shadow group-data-[viewport=false]/navigation-menu:duration-200 group-data-[viewport=false]/navigation-menu:data-[state=closed]:animate-out group-data-[viewport=false]/navigation-menu:data-[state=open]:animate-in",
|
|
75
|
+
className,
|
|
76
|
+
)}
|
|
77
|
+
data-slot="navigation-menu-content"
|
|
78
|
+
{...props}
|
|
79
|
+
/>
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function NavigationMenuViewport({
|
|
84
|
+
className,
|
|
85
|
+
...props
|
|
86
|
+
}: React.ComponentProps<typeof NavigationMenuPrimitive.Viewport>) {
|
|
87
|
+
return (
|
|
88
|
+
<div className={cn("absolute top-full left-0 isolate z-50 flex justify-center")}>
|
|
89
|
+
<NavigationMenuPrimitive.Viewport
|
|
90
|
+
className={cn(
|
|
91
|
+
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full origin-top-center overflow-hidden rounded-md border bg-popover text-popover-foreground shadow data-[state=closed]:animate-out data-[state=open]:animate-in md:w-[var(--radix-navigation-menu-viewport-width)]",
|
|
92
|
+
className,
|
|
93
|
+
)}
|
|
94
|
+
data-slot="navigation-menu-viewport"
|
|
95
|
+
{...props}
|
|
96
|
+
/>
|
|
97
|
+
</div>
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function NavigationMenuLink({ className, ...props }: React.ComponentProps<typeof NavigationMenuPrimitive.Link>) {
|
|
102
|
+
return (
|
|
103
|
+
<NavigationMenuPrimitive.Link
|
|
104
|
+
className={cn(
|
|
105
|
+
"flex flex-col gap-1 rounded-sm p-2 text-sm outline-none transition-all hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus-visible:outline-1 focus-visible:ring-[3px] focus-visible:ring-ring/50 data-[active=true]:bg-accent/50 data-[active=true]:text-accent-foreground data-[active=true]:focus:bg-accent data-[active=true]:hover:bg-accent [&_svg:not([class*='size-'])]:size-4 [&_svg:not([class*='text-'])]:text-muted-foreground",
|
|
106
|
+
className,
|
|
107
|
+
)}
|
|
108
|
+
data-slot="navigation-menu-link"
|
|
109
|
+
{...props}
|
|
110
|
+
/>
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function NavigationMenuIndicator({
|
|
115
|
+
className,
|
|
116
|
+
...props
|
|
117
|
+
}: React.ComponentProps<typeof NavigationMenuPrimitive.Indicator>) {
|
|
118
|
+
return (
|
|
119
|
+
<NavigationMenuPrimitive.Indicator
|
|
120
|
+
className={cn(
|
|
121
|
+
"data-[state=hidden]:fade-out data-[state=visible]:fade-in top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden data-[state=hidden]:animate-out data-[state=visible]:animate-in",
|
|
122
|
+
className,
|
|
123
|
+
)}
|
|
124
|
+
data-slot="navigation-menu-indicator"
|
|
125
|
+
{...props}
|
|
126
|
+
>
|
|
127
|
+
<div className="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-border shadow-md" />
|
|
128
|
+
</NavigationMenuPrimitive.Indicator>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export {
|
|
133
|
+
NavigationMenu,
|
|
134
|
+
NavigationMenuList,
|
|
135
|
+
NavigationMenuItem,
|
|
136
|
+
NavigationMenuContent,
|
|
137
|
+
NavigationMenuTrigger,
|
|
138
|
+
NavigationMenuLink,
|
|
139
|
+
NavigationMenuIndicator,
|
|
140
|
+
NavigationMenuViewport,
|
|
141
|
+
navigationMenuTriggerStyle,
|
|
142
|
+
};
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react"
|
|
3
|
+
|
|
4
|
+
import { cn } from "@meta-1/design/lib/utils"
|
|
5
|
+
import { ButtonProps } from "@meta-1/design/components/uix/button"
|
|
6
|
+
import { buttonVariants } from "@meta-1/design/components/ui/button"
|
|
7
|
+
|
|
8
|
+
const Pagination = ({ className, ...props }: React.ComponentProps<"nav">) => (
|
|
9
|
+
<nav
|
|
10
|
+
role="navigation"
|
|
11
|
+
aria-label="pagination"
|
|
12
|
+
className={cn("mx-auto flex w-full justify-center", className)}
|
|
13
|
+
{...props}
|
|
14
|
+
/>
|
|
15
|
+
)
|
|
16
|
+
Pagination.displayName = "Pagination"
|
|
17
|
+
|
|
18
|
+
const PaginationContent = React.forwardRef<
|
|
19
|
+
HTMLUListElement,
|
|
20
|
+
React.ComponentProps<"ul">
|
|
21
|
+
>(({ className, ...props }, ref) => (
|
|
22
|
+
<ul
|
|
23
|
+
ref={ref}
|
|
24
|
+
className={cn("flex flex-row items-center gap-1", className)}
|
|
25
|
+
{...props}
|
|
26
|
+
/>
|
|
27
|
+
))
|
|
28
|
+
PaginationContent.displayName = "PaginationContent"
|
|
29
|
+
|
|
30
|
+
const PaginationItem = React.forwardRef<
|
|
31
|
+
HTMLLIElement,
|
|
32
|
+
React.ComponentProps<"li">
|
|
33
|
+
>(({ className, ...props }, ref) => (
|
|
34
|
+
<li ref={ref} className={cn("", className)} {...props} />
|
|
35
|
+
))
|
|
36
|
+
PaginationItem.displayName = "PaginationItem"
|
|
37
|
+
|
|
38
|
+
type PaginationLinkProps = {
|
|
39
|
+
isActive?: boolean
|
|
40
|
+
} & Pick<ButtonProps, "size"> &
|
|
41
|
+
React.ComponentProps<"a">
|
|
42
|
+
|
|
43
|
+
const PaginationLink = ({
|
|
44
|
+
className,
|
|
45
|
+
isActive,
|
|
46
|
+
size = "icon",
|
|
47
|
+
...props
|
|
48
|
+
}: PaginationLinkProps) => (
|
|
49
|
+
<a
|
|
50
|
+
aria-current={isActive ? "page" : undefined}
|
|
51
|
+
className={cn(
|
|
52
|
+
buttonVariants({
|
|
53
|
+
variant: isActive ? "outline" : "ghost",
|
|
54
|
+
size,
|
|
55
|
+
}),
|
|
56
|
+
className
|
|
57
|
+
)}
|
|
58
|
+
{...props}
|
|
59
|
+
/>
|
|
60
|
+
)
|
|
61
|
+
PaginationLink.displayName = "PaginationLink"
|
|
62
|
+
|
|
63
|
+
const PaginationPrevious = ({
|
|
64
|
+
className,
|
|
65
|
+
...props
|
|
66
|
+
}: React.ComponentProps<typeof PaginationLink>) => (
|
|
67
|
+
<PaginationLink
|
|
68
|
+
aria-label="Go to previous page"
|
|
69
|
+
size="default"
|
|
70
|
+
className={cn("gap-1 pl-2.5", className)}
|
|
71
|
+
{...props}
|
|
72
|
+
>
|
|
73
|
+
<ChevronLeft className="h-4 w-4" />
|
|
74
|
+
<span>Previous</span>
|
|
75
|
+
</PaginationLink>
|
|
76
|
+
)
|
|
77
|
+
PaginationPrevious.displayName = "PaginationPrevious"
|
|
78
|
+
|
|
79
|
+
const PaginationNext = ({
|
|
80
|
+
className,
|
|
81
|
+
...props
|
|
82
|
+
}: React.ComponentProps<typeof PaginationLink>) => (
|
|
83
|
+
<PaginationLink
|
|
84
|
+
aria-label="Go to next page"
|
|
85
|
+
size="default"
|
|
86
|
+
className={cn("gap-1 pr-2.5", className)}
|
|
87
|
+
{...props}
|
|
88
|
+
>
|
|
89
|
+
<span>Next</span>
|
|
90
|
+
<ChevronRight className="h-4 w-4" />
|
|
91
|
+
</PaginationLink>
|
|
92
|
+
)
|
|
93
|
+
PaginationNext.displayName = "PaginationNext"
|
|
94
|
+
|
|
95
|
+
const PaginationEllipsis = ({
|
|
96
|
+
className,
|
|
97
|
+
...props
|
|
98
|
+
}: React.ComponentProps<"span">) => (
|
|
99
|
+
<span
|
|
100
|
+
aria-hidden
|
|
101
|
+
className={cn("flex h-9 w-9 items-center justify-center", className)}
|
|
102
|
+
{...props}
|
|
103
|
+
>
|
|
104
|
+
<MoreHorizontal className="h-4 w-4" />
|
|
105
|
+
<span className="sr-only">More pages</span>
|
|
106
|
+
</span>
|
|
107
|
+
)
|
|
108
|
+
PaginationEllipsis.displayName = "PaginationEllipsis"
|
|
109
|
+
|
|
110
|
+
export {
|
|
111
|
+
Pagination,
|
|
112
|
+
PaginationContent,
|
|
113
|
+
PaginationEllipsis,
|
|
114
|
+
PaginationItem,
|
|
115
|
+
PaginationLink,
|
|
116
|
+
PaginationNext,
|
|
117
|
+
PaginationPrevious,
|
|
118
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type * as React from "react";
|
|
2
|
+
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
3
|
+
|
|
4
|
+
import { cn } from "@meta-1/design/lib/utils";
|
|
5
|
+
|
|
6
|
+
function Popover({ ...props }: React.ComponentProps<typeof PopoverPrimitive.Root>) {
|
|
7
|
+
return <PopoverPrimitive.Root data-slot="popover" {...props} />;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
function PopoverTrigger({ ...props }: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {
|
|
11
|
+
return <PopoverPrimitive.Trigger data-slot="popover-trigger" {...props} />;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function PopoverContent({
|
|
15
|
+
className,
|
|
16
|
+
align = "center",
|
|
17
|
+
sideOffset = 4,
|
|
18
|
+
...props
|
|
19
|
+
}: React.ComponentProps<typeof PopoverPrimitive.Content>) {
|
|
20
|
+
return (
|
|
21
|
+
<PopoverPrimitive.Portal>
|
|
22
|
+
<PopoverPrimitive.Content
|
|
23
|
+
align={align}
|
|
24
|
+
className={cn(
|
|
25
|
+
"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 z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-hidden data-[state=closed]:animate-out data-[state=open]:animate-in",
|
|
26
|
+
className,
|
|
27
|
+
)}
|
|
28
|
+
data-slot="popover-content"
|
|
29
|
+
sideOffset={sideOffset}
|
|
30
|
+
{...props}
|
|
31
|
+
/>
|
|
32
|
+
</PopoverPrimitive.Portal>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function PopoverAnchor({ ...props }: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {
|
|
37
|
+
return <PopoverPrimitive.Anchor data-slot="popover-anchor" {...props} />;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type * as React from "react";
|
|
2
|
+
import * as ProgressPrimitive from "@radix-ui/react-progress";
|
|
3
|
+
|
|
4
|
+
import { cn } from "@meta-1/design/lib/utils";
|
|
5
|
+
|
|
6
|
+
function Progress({ className, value, ...props }: React.ComponentProps<typeof ProgressPrimitive.Root>) {
|
|
7
|
+
return (
|
|
8
|
+
<ProgressPrimitive.Root
|
|
9
|
+
className={cn("relative h-2 w-full overflow-hidden rounded-full bg-primary/20", className)}
|
|
10
|
+
data-slot="progress"
|
|
11
|
+
{...props}
|
|
12
|
+
>
|
|
13
|
+
<ProgressPrimitive.Indicator
|
|
14
|
+
className="h-full w-full flex-1 bg-primary transition-all"
|
|
15
|
+
data-slot="progress-indicator"
|
|
16
|
+
style={{ transform: `translateX(-${100 - (value || 0)}%)` }}
|
|
17
|
+
/>
|
|
18
|
+
</ProgressPrimitive.Root>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export { Progress };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type * as React from "react";
|
|
2
|
+
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
|
|
3
|
+
import { CircleIcon } from "lucide-react";
|
|
4
|
+
|
|
5
|
+
import { cn } from "@meta-1/design/lib/utils";
|
|
6
|
+
|
|
7
|
+
function RadioGroup({ className, ...props }: React.ComponentProps<typeof RadioGroupPrimitive.Root>) {
|
|
8
|
+
return <RadioGroupPrimitive.Root className={cn("grid gap-3", className)} data-slot="radio-group" {...props} />;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function RadioGroupItem({ className, ...props }: React.ComponentProps<typeof RadioGroupPrimitive.Item>) {
|
|
12
|
+
return (
|
|
13
|
+
<RadioGroupPrimitive.Item
|
|
14
|
+
className={cn(
|
|
15
|
+
"aspect-square size-4 shrink-0 rounded-full border border-input text-primary shadow-xs outline-none transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:bg-input/30 dark:aria-invalid:ring-destructive/40",
|
|
16
|
+
className,
|
|
17
|
+
)}
|
|
18
|
+
data-slot="radio-group-item"
|
|
19
|
+
{...props}
|
|
20
|
+
>
|
|
21
|
+
<RadioGroupPrimitive.Indicator
|
|
22
|
+
className="relative flex items-center justify-center"
|
|
23
|
+
data-slot="radio-group-indicator"
|
|
24
|
+
>
|
|
25
|
+
<CircleIcon className="-translate-x-1/2 -translate-y-1/2 absolute top-1/2 left-1/2 size-2 fill-primary" />
|
|
26
|
+
</RadioGroupPrimitive.Indicator>
|
|
27
|
+
</RadioGroupPrimitive.Item>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export { RadioGroup, RadioGroupItem };
|