@trycompai/design-system 1.0.0 → 1.0.1
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 +2 -2
- package/src/components/atoms/index.ts +19 -0
- package/src/components/atoms/kbd.tsx +21 -0
- package/src/components/{ui → atoms}/slider.tsx +4 -4
- package/src/components/{ui → atoms}/textarea.tsx +8 -2
- package/src/components/{ui → atoms}/toggle.tsx +2 -5
- package/src/components/{ui → molecules}/breadcrumb.tsx +1 -1
- package/src/components/molecules/empty.tsx +82 -0
- package/src/components/{ui → molecules}/field.tsx +16 -37
- package/src/components/{ui → molecules}/hover-card.tsx +2 -8
- package/src/components/molecules/index.ts +26 -0
- package/src/components/{ui → molecules}/input-group.tsx +1 -1
- package/src/components/molecules/input-otp.tsx +70 -0
- package/src/components/{ui → molecules}/item.tsx +18 -36
- package/src/components/{ui → molecules}/page-header.tsx +2 -2
- package/src/components/{ui → molecules}/pagination.tsx +10 -19
- package/src/components/{ui → molecules}/radio-group.tsx +4 -8
- package/src/components/{ui → molecules}/scroll-area.tsx +8 -11
- package/src/components/{ui → molecules}/section.tsx +2 -2
- package/src/components/{ui → molecules}/select.tsx +17 -5
- package/src/components/{ui → molecules}/table.tsx +11 -2
- package/src/components/{ui → molecules}/toggle-group.tsx +1 -1
- package/src/components/organisms/alert-dialog.tsx +135 -0
- package/src/components/{ui → organisms}/calendar.tsx +2 -3
- package/src/components/{ui → organisms}/carousel.tsx +6 -8
- package/src/components/{ui → organisms}/chart.tsx +9 -24
- package/src/components/{ui → organisms}/combobox.tsx +2 -2
- package/src/components/{ui → organisms}/context-menu.tsx +19 -49
- package/src/components/{ui → organisms}/dialog.tsx +1 -1
- package/src/components/organisms/index.ts +16 -0
- package/src/components/organisms/navigation-menu.tsx +137 -0
- package/src/components/{ui → organisms}/sheet.tsx +6 -6
- package/src/components/{ui → organisms}/sidebar.tsx +42 -83
- package/src/components/{ui → organisms}/sonner.tsx +7 -9
- package/src/components/ui/index.ts +3 -61
- package/src/styles/globals.css +12 -0
- package/src/components/ui/alert-dialog.tsx +0 -161
- package/src/components/ui/empty.tsx +0 -94
- package/src/components/ui/input-otp.tsx +0 -84
- package/src/components/ui/kbd.tsx +0 -26
- package/src/components/ui/navigation-menu.tsx +0 -147
- /package/src/components/{ui → atoms}/aspect-ratio.tsx +0 -0
- /package/src/components/{ui → atoms}/avatar.tsx +0 -0
- /package/src/components/{ui → atoms}/badge.tsx +0 -0
- /package/src/components/{ui → atoms}/button.tsx +0 -0
- /package/src/components/{ui → atoms}/checkbox.tsx +0 -0
- /package/src/components/{ui → atoms}/container.tsx +0 -0
- /package/src/components/{ui → atoms}/heading.tsx +0 -0
- /package/src/components/{ui → atoms}/input.tsx +0 -0
- /package/src/components/{ui → atoms}/label.tsx +0 -0
- /package/src/components/{ui → atoms}/progress.tsx +0 -0
- /package/src/components/{ui → atoms}/separator.tsx +0 -0
- /package/src/components/{ui → atoms}/skeleton.tsx +0 -0
- /package/src/components/{ui → atoms}/spinner.tsx +0 -0
- /package/src/components/{ui → atoms}/switch.tsx +0 -0
- /package/src/components/{ui → atoms}/text.tsx +0 -0
- /package/src/components/{ui → molecules}/accordion.tsx +0 -0
- /package/src/components/{ui → molecules}/alert.tsx +0 -0
- /package/src/components/{ui → molecules}/button-group.tsx +0 -0
- /package/src/components/{ui → molecules}/card.tsx +0 -0
- /package/src/components/{ui → molecules}/collapsible.tsx +0 -0
- /package/src/components/{ui → molecules}/grid.tsx +0 -0
- /package/src/components/{ui → molecules}/popover.tsx +0 -0
- /package/src/components/{ui → molecules}/resizable.tsx +0 -0
- /package/src/components/{ui → molecules}/stack.tsx +0 -0
- /package/src/components/{ui → molecules}/tabs.tsx +0 -0
- /package/src/components/{ui → molecules}/tooltip.tsx +0 -0
- /package/src/components/{ui → organisms}/command.tsx +0 -0
- /package/src/components/{ui → organisms}/drawer.tsx +0 -0
- /package/src/components/{ui → organisms}/dropdown-menu.tsx +0 -0
- /package/src/components/{ui → organisms}/menubar.tsx +0 -0
- /package/src/components/{ui → organisms}/page-layout.tsx +0 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trycompai/design-system",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "Design system for Comp AI - shadcn-style components with Tailwind CSS",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.ts",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"repository": {
|
|
49
49
|
"type": "git",
|
|
50
50
|
"url": "git+https://github.com/trycompai/comp.git",
|
|
51
|
-
"directory": "packages/
|
|
51
|
+
"directory": "packages/design-system"
|
|
52
52
|
},
|
|
53
53
|
"license": "MIT",
|
|
54
54
|
"keywords": [
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export * from './aspect-ratio';
|
|
2
|
+
export * from './avatar';
|
|
3
|
+
export * from './badge';
|
|
4
|
+
export * from './button';
|
|
5
|
+
export * from './checkbox';
|
|
6
|
+
export * from './container';
|
|
7
|
+
export * from './heading';
|
|
8
|
+
export * from './input';
|
|
9
|
+
export * from './kbd';
|
|
10
|
+
export * from './label';
|
|
11
|
+
export * from './progress';
|
|
12
|
+
export * from './separator';
|
|
13
|
+
export * from './skeleton';
|
|
14
|
+
export * from './slider';
|
|
15
|
+
export * from './spinner';
|
|
16
|
+
export * from './switch';
|
|
17
|
+
export * from './text';
|
|
18
|
+
export * from './textarea';
|
|
19
|
+
export * from './toggle';
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
function Kbd({ ...props }: Omit<React.ComponentProps<'kbd'>, 'className'>) {
|
|
2
|
+
return (
|
|
3
|
+
<kbd
|
|
4
|
+
data-slot="kbd"
|
|
5
|
+
className="bg-muted text-muted-foreground [[data-slot=tooltip-content]_&]:bg-background/20 [[data-slot=tooltip-content]_&]:text-background dark:[[data-slot=tooltip-content]_&]:bg-background/10 h-5 w-fit min-w-5 gap-1 rounded-sm px-1 font-sans text-xs font-medium [&_svg:not([class*='size-'])]:size-3 pointer-events-none inline-flex items-center justify-center select-none"
|
|
6
|
+
{...props}
|
|
7
|
+
/>
|
|
8
|
+
);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function KbdGroup({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
|
|
12
|
+
return (
|
|
13
|
+
<kbd
|
|
14
|
+
data-slot="kbd-group"
|
|
15
|
+
className="gap-1 inline-flex items-center"
|
|
16
|
+
{...props}
|
|
17
|
+
/>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export { Kbd, KbdGroup };
|
|
@@ -17,7 +17,7 @@ function Slider({
|
|
|
17
17
|
|
|
18
18
|
return (
|
|
19
19
|
<SliderPrimitive.Root
|
|
20
|
-
className="data-horizontal:w-full data-vertical:h-full"
|
|
20
|
+
className="data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full"
|
|
21
21
|
data-slot="slider"
|
|
22
22
|
defaultValue={defaultValue}
|
|
23
23
|
value={value}
|
|
@@ -26,14 +26,14 @@ function Slider({
|
|
|
26
26
|
thumbAlignment="edge"
|
|
27
27
|
{...props}
|
|
28
28
|
>
|
|
29
|
-
<SliderPrimitive.Control className="data-vertical:min-h-40 relative flex w-full touch-none items-center select-none data-disabled:opacity-50 data-vertical:h-full data-vertical:w-auto data-vertical:flex-col">
|
|
29
|
+
<SliderPrimitive.Control className="data-[orientation=vertical]:min-h-40 relative flex w-full touch-none items-center select-none data-disabled:opacity-50 data-[orientation=vertical]:h-full data-[orientation=vertical]:w-auto data-[orientation=vertical]:flex-col">
|
|
30
30
|
<SliderPrimitive.Track
|
|
31
31
|
data-slot="slider-track"
|
|
32
|
-
className="bg-
|
|
32
|
+
className="bg-border rounded-full h-1.5 w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-1.5 relative overflow-hidden select-none"
|
|
33
33
|
>
|
|
34
34
|
<SliderPrimitive.Indicator
|
|
35
35
|
data-slot="slider-range"
|
|
36
|
-
className="bg-primary select-none
|
|
36
|
+
className="bg-primary select-none h-full data-[orientation=vertical]:w-full"
|
|
37
37
|
/>
|
|
38
38
|
</SliderPrimitive.Track>
|
|
39
39
|
{Array.from({ length: _values.length }, (_, index) => (
|
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
|
|
3
|
-
function Textarea({
|
|
3
|
+
function Textarea({
|
|
4
|
+
size = 'default',
|
|
5
|
+
...props
|
|
6
|
+
}: Omit<React.ComponentProps<'textarea'>, 'className'> & {
|
|
7
|
+
size?: 'sm' | 'default' | 'lg' | 'full';
|
|
8
|
+
}) {
|
|
4
9
|
return (
|
|
5
10
|
<textarea
|
|
6
11
|
data-slot="textarea"
|
|
7
|
-
|
|
12
|
+
data-size={size}
|
|
13
|
+
className="border-input dark:bg-input/30 focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 disabled:bg-input/50 dark:disabled:bg-input/80 rounded-lg border bg-transparent px-2.5 py-2 text-base transition-colors focus-visible:ring-[3px] aria-invalid:ring-[3px] md:text-sm placeholder:text-muted-foreground flex field-sizing-content min-h-16 outline-none disabled:cursor-not-allowed disabled:opacity-50 data-[size=sm]:w-xs data-[size=default]:w-md data-[size=lg]:w-xl data-[size=full]:w-full"
|
|
8
14
|
{...props}
|
|
9
15
|
/>
|
|
10
16
|
);
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { Toggle as TogglePrimitive } from '@base-ui/react/toggle';
|
|
2
2
|
import { cva, type VariantProps } from 'class-variance-authority';
|
|
3
3
|
|
|
4
|
-
import { cn } from '../../../lib/utils';
|
|
5
|
-
|
|
6
4
|
const toggleVariants = cva(
|
|
7
5
|
"hover:text-foreground aria-pressed:bg-muted focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive gap-1 rounded-md text-sm font-medium transition-[color,box-shadow] [&_svg:not([class*='size-'])]:size-4 group/toggle hover:bg-muted inline-flex items-center justify-center whitespace-nowrap outline-none focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
8
6
|
{
|
|
@@ -25,15 +23,14 @@ const toggleVariants = cva(
|
|
|
25
23
|
);
|
|
26
24
|
|
|
27
25
|
function Toggle({
|
|
28
|
-
className,
|
|
29
26
|
variant = 'default',
|
|
30
27
|
size = 'default',
|
|
31
28
|
...props
|
|
32
|
-
}: TogglePrimitive.Props & VariantProps<typeof toggleVariants>) {
|
|
29
|
+
}: Omit<TogglePrimitive.Props, 'className'> & VariantProps<typeof toggleVariants>) {
|
|
33
30
|
return (
|
|
34
31
|
<TogglePrimitive
|
|
35
32
|
data-slot="toggle"
|
|
36
|
-
className={
|
|
33
|
+
className={toggleVariants({ variant, size })}
|
|
37
34
|
{...props}
|
|
38
35
|
/>
|
|
39
36
|
);
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { cva, type VariantProps } from 'class-variance-authority';
|
|
2
|
+
|
|
3
|
+
function Empty({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
|
|
4
|
+
return (
|
|
5
|
+
<div
|
|
6
|
+
data-slot="empty"
|
|
7
|
+
className="gap-4 rounded-lg border-dashed p-12 flex w-full min-w-0 flex-1 flex-col items-center justify-center text-center text-balance"
|
|
8
|
+
{...props}
|
|
9
|
+
/>
|
|
10
|
+
);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function EmptyHeader({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
|
|
14
|
+
return (
|
|
15
|
+
<div
|
|
16
|
+
data-slot="empty-header"
|
|
17
|
+
className="gap-2 flex max-w-sm flex-col items-center"
|
|
18
|
+
{...props}
|
|
19
|
+
/>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const emptyMediaVariants = cva(
|
|
24
|
+
'mb-2 flex shrink-0 items-center justify-center [&_svg]:pointer-events-none [&_svg]:shrink-0',
|
|
25
|
+
{
|
|
26
|
+
variants: {
|
|
27
|
+
variant: {
|
|
28
|
+
default: 'bg-transparent',
|
|
29
|
+
icon: "bg-muted text-foreground flex size-10 shrink-0 items-center justify-center rounded-lg [&_svg:not([class*='size-'])]:size-6",
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
defaultVariants: {
|
|
33
|
+
variant: 'default',
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
function EmptyMedia({
|
|
39
|
+
variant = 'default',
|
|
40
|
+
...props
|
|
41
|
+
}: Omit<React.ComponentProps<'div'>, 'className'> & VariantProps<typeof emptyMediaVariants>) {
|
|
42
|
+
return (
|
|
43
|
+
<div
|
|
44
|
+
data-slot="empty-icon"
|
|
45
|
+
data-variant={variant}
|
|
46
|
+
className={emptyMediaVariants({ variant })}
|
|
47
|
+
{...props}
|
|
48
|
+
/>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function EmptyTitle({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
|
|
53
|
+
return (
|
|
54
|
+
<div
|
|
55
|
+
data-slot="empty-title"
|
|
56
|
+
className="text-lg font-medium tracking-tight"
|
|
57
|
+
{...props}
|
|
58
|
+
/>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function EmptyDescription({ ...props }: Omit<React.ComponentProps<'p'>, 'className'>) {
|
|
63
|
+
return (
|
|
64
|
+
<div
|
|
65
|
+
data-slot="empty-description"
|
|
66
|
+
className="text-sm/relaxed text-muted-foreground [&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4"
|
|
67
|
+
{...props}
|
|
68
|
+
/>
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function EmptyContent({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
|
|
73
|
+
return (
|
|
74
|
+
<div
|
|
75
|
+
data-slot="empty-content"
|
|
76
|
+
className="gap-4 text-sm flex w-full max-w-sm min-w-0 flex-col items-center text-balance"
|
|
77
|
+
{...props}
|
|
78
|
+
/>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTitle };
|
|
@@ -4,47 +4,36 @@ import { cva, type VariantProps } from 'class-variance-authority';
|
|
|
4
4
|
import { useMemo } from 'react';
|
|
5
5
|
|
|
6
6
|
import { Separator as SeparatorPrimitive } from '@base-ui/react/separator';
|
|
7
|
-
import { cn } from '../../../lib/utils';
|
|
8
7
|
|
|
9
|
-
function FieldSet({
|
|
8
|
+
function FieldSet({ ...props }: Omit<React.ComponentProps<'fieldset'>, 'className'>) {
|
|
10
9
|
return (
|
|
11
10
|
<fieldset
|
|
12
11
|
data-slot="field-set"
|
|
13
|
-
className=
|
|
14
|
-
'gap-4 has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3 flex flex-col',
|
|
15
|
-
className,
|
|
16
|
-
)}
|
|
12
|
+
className="gap-4 has-[>[data-slot=checkbox-group]]:gap-3 has-[>[data-slot=radio-group]]:gap-3 flex flex-col"
|
|
17
13
|
{...props}
|
|
18
14
|
/>
|
|
19
15
|
);
|
|
20
16
|
}
|
|
21
17
|
|
|
22
18
|
function FieldLegend({
|
|
23
|
-
className,
|
|
24
19
|
variant = 'legend',
|
|
25
20
|
...props
|
|
26
|
-
}: React.ComponentProps<'legend'> & { variant?: 'legend' | 'label' }) {
|
|
21
|
+
}: Omit<React.ComponentProps<'legend'>, 'className'> & { variant?: 'legend' | 'label' }) {
|
|
27
22
|
return (
|
|
28
23
|
<legend
|
|
29
24
|
data-slot="field-legend"
|
|
30
25
|
data-variant={variant}
|
|
31
|
-
className=
|
|
32
|
-
'mb-1.5 font-medium data-[variant=label]:text-sm data-[variant=legend]:text-base',
|
|
33
|
-
className,
|
|
34
|
-
)}
|
|
26
|
+
className="mb-1.5 font-medium data-[variant=label]:text-sm data-[variant=legend]:text-base"
|
|
35
27
|
{...props}
|
|
36
28
|
/>
|
|
37
29
|
);
|
|
38
30
|
}
|
|
39
31
|
|
|
40
|
-
function FieldGroup({
|
|
32
|
+
function FieldGroup({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
|
|
41
33
|
return (
|
|
42
34
|
<div
|
|
43
35
|
data-slot="field-group"
|
|
44
|
-
className=
|
|
45
|
-
'gap-5 data-[slot=checkbox-group]:gap-3 [&>[data-slot=field-group]]:gap-4 group/field-group @container/field-group flex w-full flex-col',
|
|
46
|
-
className,
|
|
47
|
-
)}
|
|
36
|
+
className="gap-5 data-[slot=checkbox-group]:gap-3 [&>[data-slot=field-group]]:gap-4 group/field-group @container/field-group flex w-full flex-col"
|
|
48
37
|
{...props}
|
|
49
38
|
/>
|
|
50
39
|
);
|
|
@@ -66,26 +55,25 @@ const fieldVariants = cva('data-[invalid=true]:text-destructive gap-2 group/fiel
|
|
|
66
55
|
});
|
|
67
56
|
|
|
68
57
|
function Field({
|
|
69
|
-
className,
|
|
70
58
|
orientation = 'vertical',
|
|
71
59
|
...props
|
|
72
|
-
}: React.ComponentProps<'div'> & VariantProps<typeof fieldVariants>) {
|
|
60
|
+
}: Omit<React.ComponentProps<'div'>, 'className'> & VariantProps<typeof fieldVariants>) {
|
|
73
61
|
return (
|
|
74
62
|
<div
|
|
75
63
|
role="group"
|
|
76
64
|
data-slot="field"
|
|
77
65
|
data-orientation={orientation}
|
|
78
|
-
className={
|
|
66
|
+
className={fieldVariants({ orientation })}
|
|
79
67
|
{...props}
|
|
80
68
|
/>
|
|
81
69
|
);
|
|
82
70
|
}
|
|
83
71
|
|
|
84
|
-
function FieldContent({
|
|
72
|
+
function FieldContent({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
|
|
85
73
|
return (
|
|
86
74
|
<div
|
|
87
75
|
data-slot="field-content"
|
|
88
|
-
className=
|
|
76
|
+
className="gap-0.5 group/field-content flex flex-1 flex-col leading-snug"
|
|
89
77
|
{...props}
|
|
90
78
|
/>
|
|
91
79
|
);
|
|
@@ -101,29 +89,21 @@ function FieldLabel({ ...props }: Omit<React.ComponentProps<'label'>, 'className
|
|
|
101
89
|
);
|
|
102
90
|
}
|
|
103
91
|
|
|
104
|
-
function FieldTitle({
|
|
92
|
+
function FieldTitle({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
|
|
105
93
|
return (
|
|
106
94
|
<div
|
|
107
95
|
data-slot="field-label"
|
|
108
|
-
className=
|
|
109
|
-
'gap-2 text-sm font-medium group-data-[disabled=true]/field:opacity-50 flex w-fit items-center leading-snug',
|
|
110
|
-
className,
|
|
111
|
-
)}
|
|
96
|
+
className="gap-2 text-sm font-medium group-data-[disabled=true]/field:opacity-50 flex w-fit items-center leading-snug"
|
|
112
97
|
{...props}
|
|
113
98
|
/>
|
|
114
99
|
);
|
|
115
100
|
}
|
|
116
101
|
|
|
117
|
-
function FieldDescription({
|
|
102
|
+
function FieldDescription({ ...props }: Omit<React.ComponentProps<'p'>, 'className'>) {
|
|
118
103
|
return (
|
|
119
104
|
<p
|
|
120
105
|
data-slot="field-description"
|
|
121
|
-
className=
|
|
122
|
-
'text-muted-foreground text-left text-sm [[data-variant=legend]+&]:-mt-1.5 leading-normal font-normal group-has-[[data-orientation=horizontal]]/field:text-balance',
|
|
123
|
-
'last:mt-0 nth-last-2:-mt-1',
|
|
124
|
-
'[&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4',
|
|
125
|
-
className,
|
|
126
|
-
)}
|
|
106
|
+
className="text-muted-foreground text-left text-sm [[data-variant=legend]+&]:-mt-1.5 leading-normal font-normal group-has-[[data-orientation=horizontal]]/field:text-balance last:mt-0 nth-last-2:-mt-1 [&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4"
|
|
127
107
|
{...props}
|
|
128
108
|
/>
|
|
129
109
|
);
|
|
@@ -156,11 +136,10 @@ function FieldSeparator({
|
|
|
156
136
|
}
|
|
157
137
|
|
|
158
138
|
function FieldError({
|
|
159
|
-
className,
|
|
160
139
|
children,
|
|
161
140
|
errors,
|
|
162
141
|
...props
|
|
163
|
-
}: React.ComponentProps<'div'> & {
|
|
142
|
+
}: Omit<React.ComponentProps<'div'>, 'className'> & {
|
|
164
143
|
errors?: Array<{ message?: string } | undefined>;
|
|
165
144
|
}) {
|
|
166
145
|
const content = useMemo(() => {
|
|
@@ -193,7 +172,7 @@ function FieldError({
|
|
|
193
172
|
<div
|
|
194
173
|
role="alert"
|
|
195
174
|
data-slot="field-error"
|
|
196
|
-
className=
|
|
175
|
+
className="text-destructive text-sm font-normal"
|
|
197
176
|
{...props}
|
|
198
177
|
>
|
|
199
178
|
{content}
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
import { PreviewCard as PreviewCardPrimitive } from '@base-ui/react/preview-card';
|
|
4
4
|
|
|
5
|
-
import { cn } from '../../../lib/utils';
|
|
6
|
-
|
|
7
5
|
function HoverCard({ ...props }: PreviewCardPrimitive.Root.Props) {
|
|
8
6
|
return <PreviewCardPrimitive.Root data-slot="hover-card" {...props} />;
|
|
9
7
|
}
|
|
@@ -13,13 +11,12 @@ function HoverCardTrigger({ ...props }: PreviewCardPrimitive.Trigger.Props) {
|
|
|
13
11
|
}
|
|
14
12
|
|
|
15
13
|
function HoverCardContent({
|
|
16
|
-
className,
|
|
17
14
|
side = 'bottom',
|
|
18
15
|
sideOffset = 4,
|
|
19
16
|
align = 'center',
|
|
20
17
|
alignOffset = 4,
|
|
21
18
|
...props
|
|
22
|
-
}: PreviewCardPrimitive.Popup.Props &
|
|
19
|
+
}: Omit<PreviewCardPrimitive.Popup.Props, 'className'> &
|
|
23
20
|
Pick<PreviewCardPrimitive.Positioner.Props, 'align' | 'alignOffset' | 'side' | 'sideOffset'>) {
|
|
24
21
|
return (
|
|
25
22
|
<PreviewCardPrimitive.Portal data-slot="hover-card-portal">
|
|
@@ -32,10 +29,7 @@ function HoverCardContent({
|
|
|
32
29
|
>
|
|
33
30
|
<PreviewCardPrimitive.Popup
|
|
34
31
|
data-slot="hover-card-content"
|
|
35
|
-
className=
|
|
36
|
-
'data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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 ring-foreground/10 bg-popover text-popover-foreground w-64 rounded-lg p-4 text-sm shadow-md ring-1 duration-100 z-50 origin-(--transform-origin) outline-hidden',
|
|
37
|
-
className,
|
|
38
|
-
)}
|
|
32
|
+
className="data-open:animate-in data-closed:animate-out data-closed:fade-out-0 data-open:fade-in-0 data-closed:zoom-out-95 data-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 ring-foreground/10 bg-popover text-popover-foreground w-64 rounded-lg p-4 text-sm shadow-md ring-1 duration-100 z-50 origin-(--transform-origin) outline-hidden"
|
|
39
33
|
{...props}
|
|
40
34
|
/>
|
|
41
35
|
</PreviewCardPrimitive.Positioner>
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export * from './accordion';
|
|
2
|
+
export * from './alert';
|
|
3
|
+
export * from './breadcrumb';
|
|
4
|
+
export * from './button-group';
|
|
5
|
+
export * from './card';
|
|
6
|
+
export * from './collapsible';
|
|
7
|
+
export * from './empty';
|
|
8
|
+
export * from './field';
|
|
9
|
+
export * from './grid';
|
|
10
|
+
export * from './hover-card';
|
|
11
|
+
export * from './input-group';
|
|
12
|
+
export * from './input-otp';
|
|
13
|
+
export * from './item';
|
|
14
|
+
export * from './page-header';
|
|
15
|
+
export * from './pagination';
|
|
16
|
+
export * from './popover';
|
|
17
|
+
export * from './radio-group';
|
|
18
|
+
export * from './resizable';
|
|
19
|
+
export * from './scroll-area';
|
|
20
|
+
export * from './section';
|
|
21
|
+
export * from './select';
|
|
22
|
+
export * from './stack';
|
|
23
|
+
export * from './table';
|
|
24
|
+
export * from './tabs';
|
|
25
|
+
export * from './toggle-group';
|
|
26
|
+
export * from './tooltip';
|
|
@@ -4,7 +4,7 @@ import { cva, type VariantProps } from 'class-variance-authority';
|
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
|
|
6
6
|
import { cn } from '../../../lib/utils';
|
|
7
|
-
import { buttonVariants } from '
|
|
7
|
+
import { buttonVariants } from '../atoms/button';
|
|
8
8
|
|
|
9
9
|
function InputGroup({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
|
|
10
10
|
return (
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { OTPInput, OTPInputContext } from 'input-otp';
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
|
|
4
|
+
import { MinusIcon } from 'lucide-react';
|
|
5
|
+
|
|
6
|
+
function InputOTP({
|
|
7
|
+
className: _className,
|
|
8
|
+
...props
|
|
9
|
+
}: React.ComponentProps<typeof OTPInput>) {
|
|
10
|
+
return (
|
|
11
|
+
<OTPInput
|
|
12
|
+
data-slot="input-otp"
|
|
13
|
+
containerClassName="cn-input-otp flex items-center has-disabled:opacity-50"
|
|
14
|
+
spellCheck={false}
|
|
15
|
+
className="disabled:cursor-not-allowed"
|
|
16
|
+
{...props}
|
|
17
|
+
/>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function InputOTPGroup({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
|
|
22
|
+
return (
|
|
23
|
+
<div
|
|
24
|
+
data-slot="input-otp-group"
|
|
25
|
+
className="has-aria-invalid:ring-destructive/20 dark:has-aria-invalid:ring-destructive/40 has-aria-invalid:border-destructive rounded-md has-aria-invalid:ring-[3px] flex items-center"
|
|
26
|
+
{...props}
|
|
27
|
+
/>
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function InputOTPSlot({
|
|
32
|
+
index,
|
|
33
|
+
...props
|
|
34
|
+
}: Omit<React.ComponentProps<'div'>, 'className'> & {
|
|
35
|
+
index: number;
|
|
36
|
+
}) {
|
|
37
|
+
const inputOTPContext = React.useContext(OTPInputContext);
|
|
38
|
+
const { char, hasFakeCaret, isActive } = inputOTPContext?.slots[index] ?? {};
|
|
39
|
+
|
|
40
|
+
return (
|
|
41
|
+
<div
|
|
42
|
+
data-slot="input-otp-slot"
|
|
43
|
+
data-active={isActive}
|
|
44
|
+
className="dark:bg-input/30 border-input data-[active=true]:border-ring data-[active=true]:ring-ring/50 data-[active=true]:aria-invalid:ring-destructive/20 dark:data-[active=true]:aria-invalid:ring-destructive/40 aria-invalid:border-destructive data-[active=true]:aria-invalid:border-destructive size-9 border-y border-r text-sm shadow-xs transition-all outline-none first:rounded-l-md first:border-l last:rounded-r-md data-[active=true]:ring-[3px] relative flex items-center justify-center data-[active=true]:z-10"
|
|
45
|
+
{...props}
|
|
46
|
+
>
|
|
47
|
+
{char}
|
|
48
|
+
{hasFakeCaret && (
|
|
49
|
+
<div className="pointer-events-none absolute inset-0 flex items-center justify-center">
|
|
50
|
+
<div className="animate-caret-blink bg-foreground h-4 w-px duration-1000 bg-foreground h-4 w-px" />
|
|
51
|
+
</div>
|
|
52
|
+
)}
|
|
53
|
+
</div>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function InputOTPSeparator({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
|
|
58
|
+
return (
|
|
59
|
+
<div
|
|
60
|
+
data-slot="input-otp-separator"
|
|
61
|
+
className="[&_svg:not([class*='size-'])]:size-4 flex items-center"
|
|
62
|
+
role="separator"
|
|
63
|
+
{...props}
|
|
64
|
+
>
|
|
65
|
+
<MinusIcon />
|
|
66
|
+
</div>
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export { InputOTP, InputOTPGroup, InputOTPSeparator, InputOTPSlot };
|
|
@@ -1,20 +1,15 @@
|
|
|
1
1
|
import { mergeProps } from '@base-ui/react/merge-props';
|
|
2
2
|
import { useRender } from '@base-ui/react/use-render';
|
|
3
3
|
import { cva, type VariantProps } from 'class-variance-authority';
|
|
4
|
-
import * as React from 'react';
|
|
5
4
|
|
|
6
5
|
import { Separator as SeparatorPrimitive } from '@base-ui/react/separator';
|
|
7
|
-
import { cn } from '../../../lib/utils';
|
|
8
6
|
|
|
9
|
-
function ItemGroup({
|
|
7
|
+
function ItemGroup({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
|
|
10
8
|
return (
|
|
11
9
|
<div
|
|
12
10
|
role="list"
|
|
13
11
|
data-slot="item-group"
|
|
14
|
-
className=
|
|
15
|
-
'gap-4 has-[[data-size=sm]]:gap-2.5 has-[[data-size=xs]]:gap-2 group/item-group flex w-full flex-col',
|
|
16
|
-
className,
|
|
17
|
-
)}
|
|
12
|
+
className="gap-4 has-[[data-size=sm]]:gap-2.5 has-[[data-size=xs]]:gap-2 group/item-group flex w-full flex-col"
|
|
18
13
|
{...props}
|
|
19
14
|
/>
|
|
20
15
|
);
|
|
@@ -54,17 +49,16 @@ const itemVariants = cva(
|
|
|
54
49
|
);
|
|
55
50
|
|
|
56
51
|
function Item({
|
|
57
|
-
className,
|
|
58
52
|
variant = 'default',
|
|
59
53
|
size = 'default',
|
|
60
54
|
render,
|
|
61
55
|
...props
|
|
62
|
-
}: useRender.ComponentProps<'div'> & VariantProps<typeof itemVariants>) {
|
|
56
|
+
}: Omit<useRender.ComponentProps<'div'>, 'className'> & VariantProps<typeof itemVariants>) {
|
|
63
57
|
return useRender({
|
|
64
58
|
defaultTagName: 'div',
|
|
65
59
|
props: mergeProps<'div'>(
|
|
66
60
|
{
|
|
67
|
-
className:
|
|
61
|
+
className: itemVariants({ variant, size }),
|
|
68
62
|
},
|
|
69
63
|
props,
|
|
70
64
|
),
|
|
@@ -95,80 +89,68 @@ const itemMediaVariants = cva(
|
|
|
95
89
|
);
|
|
96
90
|
|
|
97
91
|
function ItemMedia({
|
|
98
|
-
className,
|
|
99
92
|
variant = 'default',
|
|
100
93
|
...props
|
|
101
|
-
}: React.ComponentProps<'div'> & VariantProps<typeof itemMediaVariants>) {
|
|
94
|
+
}: Omit<React.ComponentProps<'div'>, 'className'> & VariantProps<typeof itemMediaVariants>) {
|
|
102
95
|
return (
|
|
103
96
|
<div
|
|
104
97
|
data-slot="item-media"
|
|
105
98
|
data-variant={variant}
|
|
106
|
-
className={
|
|
99
|
+
className={itemMediaVariants({ variant })}
|
|
107
100
|
{...props}
|
|
108
101
|
/>
|
|
109
102
|
);
|
|
110
103
|
}
|
|
111
104
|
|
|
112
|
-
function ItemContent({
|
|
105
|
+
function ItemContent({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
|
|
113
106
|
return (
|
|
114
107
|
<div
|
|
115
108
|
data-slot="item-content"
|
|
116
|
-
className=
|
|
117
|
-
'gap-1 group-data-[size=xs]/item:gap-0 flex flex-1 flex-col [&+[data-slot=item-content]]:flex-none',
|
|
118
|
-
className,
|
|
119
|
-
)}
|
|
109
|
+
className="gap-1 group-data-[size=xs]/item:gap-0 flex flex-1 flex-col [&+[data-slot=item-content]]:flex-none"
|
|
120
110
|
{...props}
|
|
121
111
|
/>
|
|
122
112
|
);
|
|
123
113
|
}
|
|
124
114
|
|
|
125
|
-
function ItemTitle({
|
|
115
|
+
function ItemTitle({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
|
|
126
116
|
return (
|
|
127
117
|
<div
|
|
128
118
|
data-slot="item-title"
|
|
129
|
-
className=
|
|
130
|
-
'gap-2 text-sm leading-snug font-medium underline-offset-4 line-clamp-1 flex w-fit items-center',
|
|
131
|
-
className,
|
|
132
|
-
)}
|
|
119
|
+
className="gap-2 text-sm leading-snug font-medium underline-offset-4 line-clamp-1 flex w-fit items-center"
|
|
133
120
|
{...props}
|
|
134
121
|
/>
|
|
135
122
|
);
|
|
136
123
|
}
|
|
137
124
|
|
|
138
|
-
function ItemDescription({
|
|
125
|
+
function ItemDescription({ ...props }: Omit<React.ComponentProps<'p'>, 'className'>) {
|
|
139
126
|
return (
|
|
140
127
|
<p
|
|
141
128
|
data-slot="item-description"
|
|
142
|
-
className=
|
|
143
|
-
'text-muted-foreground text-left text-sm leading-normal group-data-[size=xs]/item:text-xs [&>a:hover]:text-primary line-clamp-2 font-normal [&>a]:underline [&>a]:underline-offset-4',
|
|
144
|
-
className,
|
|
145
|
-
)}
|
|
129
|
+
className="text-muted-foreground text-left text-sm leading-normal group-data-[size=xs]/item:text-xs [&>a:hover]:text-primary line-clamp-2 font-normal [&>a]:underline [&>a]:underline-offset-4"
|
|
146
130
|
{...props}
|
|
147
131
|
/>
|
|
148
132
|
);
|
|
149
133
|
}
|
|
150
134
|
|
|
151
|
-
function ItemActions({
|
|
152
|
-
return
|
|
153
|
-
<div data-slot="item-actions" className={cn('gap-2 flex items-center', className)} {...props} />
|
|
154
|
-
);
|
|
135
|
+
function ItemActions({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
|
|
136
|
+
return <div data-slot="item-actions" className="gap-2 flex items-center" {...props} />;
|
|
155
137
|
}
|
|
156
138
|
|
|
157
|
-
function ItemHeader({
|
|
139
|
+
function ItemHeader({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
|
|
158
140
|
return (
|
|
159
141
|
<div
|
|
160
142
|
data-slot="item-header"
|
|
161
|
-
className=
|
|
143
|
+
className="gap-2 flex basis-full items-center justify-between"
|
|
162
144
|
{...props}
|
|
163
145
|
/>
|
|
164
146
|
);
|
|
165
147
|
}
|
|
166
148
|
|
|
167
|
-
function ItemFooter({
|
|
149
|
+
function ItemFooter({ ...props }: Omit<React.ComponentProps<'div'>, 'className'>) {
|
|
168
150
|
return (
|
|
169
151
|
<div
|
|
170
152
|
data-slot="item-footer"
|
|
171
|
-
className=
|
|
153
|
+
className="gap-2 flex basis-full items-center justify-between"
|
|
172
154
|
{...props}
|
|
173
155
|
/>
|
|
174
156
|
);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as React from 'react';
|
|
2
2
|
|
|
3
|
-
import { Heading } from '
|
|
3
|
+
import { Heading } from '../atoms/heading';
|
|
4
|
+
import { Text } from '../atoms/text';
|
|
4
5
|
import { Stack } from './stack';
|
|
5
|
-
import { Text } from './text';
|
|
6
6
|
|
|
7
7
|
interface PageHeaderProps extends Omit<React.ComponentProps<'div'>, 'className'> {
|
|
8
8
|
title: string;
|