@codemation/ui 0.2.0
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/.turbo/turbo-build.log +19 -0
- package/.turbo/turbo-lint.log +4 -0
- package/.turbo/turbo-typecheck.log +4 -0
- package/CHANGELOG.md +25 -0
- package/LICENSE +37 -0
- package/dist/index.cjs +845 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +417 -0
- package/dist/index.d.ts +417 -0
- package/dist/index.js +749 -0
- package/dist/index.js.map +1 -0
- package/package.json +71 -0
- package/src/components/StatusPill.tsx +33 -0
- package/src/components/composite/CodemationDialog.tsx +137 -0
- package/src/components/composite/JsonMonacoEditor.tsx +75 -0
- package/src/components/reui/tree/Tree.tsx +35 -0
- package/src/components/reui/tree/TreeContext.ts +21 -0
- package/src/components/reui/tree/TreeDragLine.tsx +28 -0
- package/src/components/reui/tree/TreeItem.tsx +51 -0
- package/src/components/reui/tree/TreeItemLabel.tsx +58 -0
- package/src/components/ui/badge.tsx +40 -0
- package/src/components/ui/button.tsx +64 -0
- package/src/components/ui/collapsible.tsx +26 -0
- package/src/components/ui/dialog.tsx +137 -0
- package/src/components/ui/dropdown-menu.tsx +239 -0
- package/src/components/ui/input.tsx +20 -0
- package/src/components/ui/label.tsx +18 -0
- package/src/components/ui/select.tsx +171 -0
- package/src/components/ui/switch.tsx +29 -0
- package/src/components/ui/tabs.tsx +76 -0
- package/src/components/ui/textarea.tsx +18 -0
- package/src/index.ts +76 -0
- package/src/lib/cn.ts +6 -0
- package/src/lucide-icons.d.ts +46 -0
- package/test/StatusPill.test.tsx +26 -0
- package/test/primitives.test.tsx +707 -0
- package/test/setup.ts +7 -0
- package/test/ui-components.test.tsx +208 -0
- package/tsconfig.json +11 -0
- package/tsdown.config.ts +10 -0
- package/vitest.ui.config.ts +40 -0
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Select as SelectPrimitive } from "radix-ui";
|
|
5
|
+
|
|
6
|
+
import { cn } from "../../lib/cn";
|
|
7
|
+
import CheckIcon from "lucide-react/dist/esm/icons/check";
|
|
8
|
+
import ChevronDownIcon from "lucide-react/dist/esm/icons/chevron-down";
|
|
9
|
+
import ChevronUpIcon from "lucide-react/dist/esm/icons/chevron-up";
|
|
10
|
+
|
|
11
|
+
function Select({ ...props }: React.ComponentProps<typeof SelectPrimitive.Root>) {
|
|
12
|
+
return <SelectPrimitive.Root data-slot="select" {...props} />;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function SelectGroup({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.Group>) {
|
|
16
|
+
return <SelectPrimitive.Group data-slot="select-group" className={cn("scroll-my-1 p-1", className)} {...props} />;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function SelectValue({ ...props }: React.ComponentProps<typeof SelectPrimitive.Value>) {
|
|
20
|
+
return <SelectPrimitive.Value data-slot="select-value" {...props} />;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function SelectTrigger({
|
|
24
|
+
className,
|
|
25
|
+
size = "default",
|
|
26
|
+
children,
|
|
27
|
+
...props
|
|
28
|
+
}: React.ComponentProps<typeof SelectPrimitive.Trigger> & {
|
|
29
|
+
size?: "sm" | "default";
|
|
30
|
+
}) {
|
|
31
|
+
return (
|
|
32
|
+
<SelectPrimitive.Trigger
|
|
33
|
+
data-slot="select-trigger"
|
|
34
|
+
data-size={size}
|
|
35
|
+
className={cn(
|
|
36
|
+
"flex w-fit items-center justify-between gap-1.5 rounded-md border border-input bg-transparent py-2 pr-2 pl-2.5 text-sm whitespace-nowrap shadow-sm transition-colors outline-none select-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 data-placeholder:text-muted-foreground data-[size=default]:h-8 data-[size=sm]:h-7 data-[size=sm]:rounded-sm *:data-[slot=select-value]:line-clamp-1 *:data-[slot=select-value]:flex *:data-[slot=select-value]:items-center *:data-[slot=select-value]:gap-1.5 dark:bg-input/30 dark:hover:bg-input/50 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
37
|
+
className,
|
|
38
|
+
)}
|
|
39
|
+
{...props}
|
|
40
|
+
>
|
|
41
|
+
{children}
|
|
42
|
+
<SelectPrimitive.Icon asChild>
|
|
43
|
+
<ChevronDownIcon className="pointer-events-none size-4 text-muted-foreground" />
|
|
44
|
+
</SelectPrimitive.Icon>
|
|
45
|
+
</SelectPrimitive.Trigger>
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function SelectContent({
|
|
50
|
+
className,
|
|
51
|
+
children,
|
|
52
|
+
position = "item-aligned",
|
|
53
|
+
align = "center",
|
|
54
|
+
...props
|
|
55
|
+
}: React.ComponentProps<typeof SelectPrimitive.Content>) {
|
|
56
|
+
return (
|
|
57
|
+
<SelectPrimitive.Portal>
|
|
58
|
+
<SelectPrimitive.Content
|
|
59
|
+
data-slot="select-content"
|
|
60
|
+
data-align-trigger={position === "item-aligned"}
|
|
61
|
+
className={cn(
|
|
62
|
+
"relative z-50 max-h-(--radix-select-content-available-height) min-w-36 origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg bg-popover text-popover-foreground shadow-md ring-1 ring-foreground/10 duration-100 data-[align-trigger=true]:animate-none 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 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95",
|
|
63
|
+
position === "popper" &&
|
|
64
|
+
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
|
65
|
+
className,
|
|
66
|
+
)}
|
|
67
|
+
position={position}
|
|
68
|
+
align={align}
|
|
69
|
+
{...props}
|
|
70
|
+
>
|
|
71
|
+
<SelectScrollUpButton />
|
|
72
|
+
<SelectPrimitive.Viewport
|
|
73
|
+
data-position={position}
|
|
74
|
+
className={cn(
|
|
75
|
+
"data-[position=popper]:h-(--radix-select-trigger-height) data-[position=popper]:w-full data-[position=popper]:min-w-(--radix-select-trigger-width)",
|
|
76
|
+
position === "popper" && "",
|
|
77
|
+
)}
|
|
78
|
+
>
|
|
79
|
+
{children}
|
|
80
|
+
</SelectPrimitive.Viewport>
|
|
81
|
+
<SelectScrollDownButton />
|
|
82
|
+
</SelectPrimitive.Content>
|
|
83
|
+
</SelectPrimitive.Portal>
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function SelectLabel({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.Label>) {
|
|
88
|
+
return (
|
|
89
|
+
<SelectPrimitive.Label
|
|
90
|
+
data-slot="select-label"
|
|
91
|
+
className={cn("px-1.5 py-1 text-xs text-muted-foreground", className)}
|
|
92
|
+
{...props}
|
|
93
|
+
/>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function SelectItem({ className, children, ...props }: React.ComponentProps<typeof SelectPrimitive.Item>) {
|
|
98
|
+
return (
|
|
99
|
+
<SelectPrimitive.Item
|
|
100
|
+
data-slot="select-item"
|
|
101
|
+
className={cn(
|
|
102
|
+
"relative flex w-full cursor-default items-center gap-1.5 rounded-md py-1 pr-8 pl-1.5 text-sm outline-hidden select-none hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground not-data-[variant=destructive]:focus:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2",
|
|
103
|
+
className,
|
|
104
|
+
)}
|
|
105
|
+
{...props}
|
|
106
|
+
>
|
|
107
|
+
<span className="pointer-events-none absolute right-2 flex size-4 items-center justify-center">
|
|
108
|
+
<SelectPrimitive.ItemIndicator>
|
|
109
|
+
<CheckIcon className="pointer-events-none" />
|
|
110
|
+
</SelectPrimitive.ItemIndicator>
|
|
111
|
+
</span>
|
|
112
|
+
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
|
113
|
+
</SelectPrimitive.Item>
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function SelectSeparator({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.Separator>) {
|
|
118
|
+
return (
|
|
119
|
+
<SelectPrimitive.Separator
|
|
120
|
+
data-slot="select-separator"
|
|
121
|
+
className={cn("pointer-events-none -mx-1 my-1 h-px bg-border", className)}
|
|
122
|
+
{...props}
|
|
123
|
+
/>
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function SelectScrollUpButton({ className, ...props }: React.ComponentProps<typeof SelectPrimitive.ScrollUpButton>) {
|
|
128
|
+
return (
|
|
129
|
+
<SelectPrimitive.ScrollUpButton
|
|
130
|
+
data-slot="select-scroll-up-button"
|
|
131
|
+
className={cn(
|
|
132
|
+
"z-10 flex cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4",
|
|
133
|
+
className,
|
|
134
|
+
)}
|
|
135
|
+
{...props}
|
|
136
|
+
>
|
|
137
|
+
<ChevronUpIcon />
|
|
138
|
+
</SelectPrimitive.ScrollUpButton>
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function SelectScrollDownButton({
|
|
143
|
+
className,
|
|
144
|
+
...props
|
|
145
|
+
}: React.ComponentProps<typeof SelectPrimitive.ScrollDownButton>) {
|
|
146
|
+
return (
|
|
147
|
+
<SelectPrimitive.ScrollDownButton
|
|
148
|
+
data-slot="select-scroll-down-button"
|
|
149
|
+
className={cn(
|
|
150
|
+
"z-10 flex cursor-default items-center justify-center bg-popover py-1 [&_svg:not([class*='size-'])]:size-4",
|
|
151
|
+
className,
|
|
152
|
+
)}
|
|
153
|
+
{...props}
|
|
154
|
+
>
|
|
155
|
+
<ChevronDownIcon />
|
|
156
|
+
</SelectPrimitive.ScrollDownButton>
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
export {
|
|
161
|
+
Select,
|
|
162
|
+
SelectContent,
|
|
163
|
+
SelectGroup,
|
|
164
|
+
SelectItem,
|
|
165
|
+
SelectLabel,
|
|
166
|
+
SelectScrollDownButton,
|
|
167
|
+
SelectScrollUpButton,
|
|
168
|
+
SelectSeparator,
|
|
169
|
+
SelectTrigger,
|
|
170
|
+
SelectValue,
|
|
171
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Switch as SwitchPrimitive } from "radix-ui";
|
|
3
|
+
import { cn } from "../../lib/cn";
|
|
4
|
+
|
|
5
|
+
function Switch({ className, ...props }: React.ComponentProps<typeof SwitchPrimitive.Root>) {
|
|
6
|
+
return (
|
|
7
|
+
<SwitchPrimitive.Root
|
|
8
|
+
data-slot="switch"
|
|
9
|
+
className={cn(
|
|
10
|
+
"peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-xs transition-[color,box-shadow] outline-none",
|
|
11
|
+
"focus-visible:ring-[3px] focus-visible:ring-ring/50",
|
|
12
|
+
"disabled:cursor-not-allowed disabled:opacity-50",
|
|
13
|
+
"data-[state=checked]:bg-primary data-[state=unchecked]:bg-input dark:data-[state=unchecked]:bg-input/80",
|
|
14
|
+
className,
|
|
15
|
+
)}
|
|
16
|
+
{...props}
|
|
17
|
+
>
|
|
18
|
+
<SwitchPrimitive.Thumb
|
|
19
|
+
data-slot="switch-thumb"
|
|
20
|
+
className={cn(
|
|
21
|
+
"pointer-events-none block size-4 rounded-full bg-white shadow-sm ring-0 transition-transform",
|
|
22
|
+
"data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0",
|
|
23
|
+
)}
|
|
24
|
+
/>
|
|
25
|
+
</SwitchPrimitive.Root>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export { Switch };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
5
|
+
import { Tabs as TabsPrimitive } from "radix-ui";
|
|
6
|
+
|
|
7
|
+
import { cn } from "../../lib/cn";
|
|
8
|
+
|
|
9
|
+
function Tabs({ className, orientation = "horizontal", ...props }: React.ComponentProps<typeof TabsPrimitive.Root>) {
|
|
10
|
+
return (
|
|
11
|
+
<TabsPrimitive.Root
|
|
12
|
+
data-slot="tabs"
|
|
13
|
+
data-orientation={orientation}
|
|
14
|
+
className={cn("group/tabs flex gap-2 data-horizontal:flex-col", className)}
|
|
15
|
+
{...props}
|
|
16
|
+
/>
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const tabsListVariants = cva(
|
|
21
|
+
"group/tabs-list inline-flex w-fit items-center justify-center rounded-lg p-[3px] text-muted-foreground group-data-horizontal/tabs:h-8 group-data-vertical/tabs:h-fit group-data-vertical/tabs:flex-col data-[variant=line]:rounded-none",
|
|
22
|
+
{
|
|
23
|
+
variants: {
|
|
24
|
+
variant: {
|
|
25
|
+
default: "bg-muted",
|
|
26
|
+
line: "gap-1 bg-transparent",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
defaultVariants: {
|
|
30
|
+
variant: "default",
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
function TabsList({
|
|
36
|
+
className,
|
|
37
|
+
variant = "default",
|
|
38
|
+
...props
|
|
39
|
+
}: React.ComponentProps<typeof TabsPrimitive.List> & VariantProps<typeof tabsListVariants>) {
|
|
40
|
+
return (
|
|
41
|
+
<TabsPrimitive.List
|
|
42
|
+
data-slot="tabs-list"
|
|
43
|
+
data-variant={variant}
|
|
44
|
+
className={cn(tabsListVariants({ variant }), className)}
|
|
45
|
+
{...props}
|
|
46
|
+
/>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function TabsTrigger({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Trigger>) {
|
|
51
|
+
return (
|
|
52
|
+
<TabsPrimitive.Trigger
|
|
53
|
+
data-slot="tabs-trigger"
|
|
54
|
+
className={cn(
|
|
55
|
+
"relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-1.5 py-0.5 text-sm font-medium whitespace-nowrap text-foreground/60 transition-all group-data-vertical/tabs:w-full group-data-vertical/tabs:justify-start hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1 focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-50 dark:text-muted-foreground dark:hover:text-foreground group-data-[variant=default]/tabs-list:data-active:shadow-sm group-data-[variant=line]/tabs-list:data-active:shadow-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
56
|
+
"group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-active:bg-transparent dark:group-data-[variant=line]/tabs-list:data-active:border-transparent dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent",
|
|
57
|
+
"data-active:bg-background data-active:text-foreground dark:data-active:border-input dark:data-active:bg-input/30 dark:data-active:text-foreground",
|
|
58
|
+
"after:absolute after:bg-foreground after:opacity-0 after:transition-opacity group-data-horizontal/tabs:after:inset-x-0 group-data-horizontal/tabs:after:bottom-[-5px] group-data-horizontal/tabs:after:h-0.5 group-data-vertical/tabs:after:inset-y-0 group-data-vertical/tabs:after:-right-1 group-data-vertical/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-active:after:opacity-100",
|
|
59
|
+
className,
|
|
60
|
+
)}
|
|
61
|
+
{...props}
|
|
62
|
+
/>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function TabsContent({ className, ...props }: React.ComponentProps<typeof TabsPrimitive.Content>) {
|
|
67
|
+
return (
|
|
68
|
+
<TabsPrimitive.Content
|
|
69
|
+
data-slot="tabs-content"
|
|
70
|
+
className={cn("flex-1 text-sm outline-none", className)}
|
|
71
|
+
{...props}
|
|
72
|
+
/>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
|
|
3
|
+
import { cn } from "../../lib/cn";
|
|
4
|
+
|
|
5
|
+
function Textarea({ className, ...props }: React.ComponentProps<"textarea">) {
|
|
6
|
+
return (
|
|
7
|
+
<textarea
|
|
8
|
+
data-slot="textarea"
|
|
9
|
+
className={cn(
|
|
10
|
+
"flex field-sizing-content min-h-16 w-full rounded-md border border-input bg-transparent px-2.5 py-2 text-base transition-colors outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:bg-input/50 disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive/20 md:text-sm dark:bg-input/30 dark:disabled:bg-input/80 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40",
|
|
11
|
+
className,
|
|
12
|
+
)}
|
|
13
|
+
{...props}
|
|
14
|
+
/>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { Textarea };
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// lib
|
|
2
|
+
export { cn } from "./lib/cn";
|
|
3
|
+
|
|
4
|
+
// shadcn ui primitives
|
|
5
|
+
export { Badge, badgeVariants } from "./components/ui/badge";
|
|
6
|
+
export { Input } from "./components/ui/input";
|
|
7
|
+
export { Label } from "./components/ui/label";
|
|
8
|
+
export { Switch } from "./components/ui/switch";
|
|
9
|
+
export { Button, buttonVariants } from "./components/ui/button";
|
|
10
|
+
export { Collapsible, CollapsibleContent, CollapsibleTrigger } from "./components/ui/collapsible";
|
|
11
|
+
export {
|
|
12
|
+
Dialog,
|
|
13
|
+
DialogClose,
|
|
14
|
+
DialogContent,
|
|
15
|
+
DialogDescription,
|
|
16
|
+
DialogFooter,
|
|
17
|
+
DialogHeader,
|
|
18
|
+
DialogOverlay,
|
|
19
|
+
DialogPortal,
|
|
20
|
+
DialogTitle,
|
|
21
|
+
DialogTrigger,
|
|
22
|
+
} from "./components/ui/dialog";
|
|
23
|
+
export {
|
|
24
|
+
DropdownMenu,
|
|
25
|
+
DropdownMenuCheckboxItem,
|
|
26
|
+
DropdownMenuContent,
|
|
27
|
+
DropdownMenuGroup,
|
|
28
|
+
DropdownMenuLabel,
|
|
29
|
+
DropdownMenuItem,
|
|
30
|
+
DropdownMenuPortal,
|
|
31
|
+
DropdownMenuRadioGroup,
|
|
32
|
+
DropdownMenuRadioItem,
|
|
33
|
+
DropdownMenuSeparator,
|
|
34
|
+
DropdownMenuShortcut,
|
|
35
|
+
DropdownMenuSub,
|
|
36
|
+
DropdownMenuSubContent,
|
|
37
|
+
DropdownMenuSubTrigger,
|
|
38
|
+
DropdownMenuTrigger,
|
|
39
|
+
} from "./components/ui/dropdown-menu";
|
|
40
|
+
export {
|
|
41
|
+
Select,
|
|
42
|
+
SelectContent,
|
|
43
|
+
SelectGroup,
|
|
44
|
+
SelectItem,
|
|
45
|
+
SelectLabel,
|
|
46
|
+
SelectScrollDownButton,
|
|
47
|
+
SelectScrollUpButton,
|
|
48
|
+
SelectSeparator,
|
|
49
|
+
SelectTrigger,
|
|
50
|
+
SelectValue,
|
|
51
|
+
} from "./components/ui/select";
|
|
52
|
+
export { Tabs, TabsContent, TabsList, TabsTrigger, tabsListVariants } from "./components/ui/tabs";
|
|
53
|
+
export { Textarea } from "./components/ui/textarea";
|
|
54
|
+
|
|
55
|
+
// reui/tree
|
|
56
|
+
export { Tree } from "./components/reui/tree/Tree";
|
|
57
|
+
export { TreeContext } from "./components/reui/tree/TreeContext";
|
|
58
|
+
export type { ToggleIconType, TreeContextValue } from "./components/reui/tree/TreeContext";
|
|
59
|
+
export { TreeDragLine } from "./components/reui/tree/TreeDragLine";
|
|
60
|
+
export { TreeItem } from "./components/reui/tree/TreeItem";
|
|
61
|
+
export { TreeItemLabel } from "./components/reui/tree/TreeItemLabel";
|
|
62
|
+
|
|
63
|
+
// composites
|
|
64
|
+
export {
|
|
65
|
+
CodemationDialog,
|
|
66
|
+
type CodemationDialogActionsProps,
|
|
67
|
+
type CodemationDialogCompound,
|
|
68
|
+
type CodemationDialogContentProps,
|
|
69
|
+
type CodemationDialogRootProps,
|
|
70
|
+
type CodemationDialogSize,
|
|
71
|
+
type CodemationDialogTitleProps,
|
|
72
|
+
} from "./components/composite/CodemationDialog";
|
|
73
|
+
export { JsonMonacoEditor } from "./components/composite/JsonMonacoEditor";
|
|
74
|
+
|
|
75
|
+
// StatusPill
|
|
76
|
+
export { StatusPill, type StatusKind, type StatusPillProps } from "./components/StatusPill";
|
package/src/lib/cn.ts
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Module declarations for lucide-react sub-path icon imports.
|
|
3
|
+
*
|
|
4
|
+
* lucide-react@0.577 doesn't ship per-icon `.d.ts` files for the ESM
|
|
5
|
+
* dist paths, so TypeScript can't find declarations for deep imports
|
|
6
|
+
* like `lucide-react/dist/esm/icons/check`. Declaring them `any` here
|
|
7
|
+
* lets the build pass until lucide adds proper sub-path exports or
|
|
8
|
+
* we switch to named imports from the package root.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
declare module "lucide-react/dist/esm/icons/check" {
|
|
12
|
+
const Check: React.FC<React.SVGProps<SVGSVGElement>>;
|
|
13
|
+
export default Check;
|
|
14
|
+
}
|
|
15
|
+
declare module "lucide-react/dist/esm/icons/chevron-down" {
|
|
16
|
+
const ChevronDown: React.FC<React.SVGProps<SVGSVGElement>>;
|
|
17
|
+
export default ChevronDown;
|
|
18
|
+
}
|
|
19
|
+
declare module "lucide-react/dist/esm/icons/chevron-right" {
|
|
20
|
+
const ChevronRight: React.FC<React.SVGProps<SVGSVGElement>>;
|
|
21
|
+
export default ChevronRight;
|
|
22
|
+
}
|
|
23
|
+
declare module "lucide-react/dist/esm/icons/chevron-up" {
|
|
24
|
+
const ChevronUp: React.FC<React.SVGProps<SVGSVGElement>>;
|
|
25
|
+
export default ChevronUp;
|
|
26
|
+
}
|
|
27
|
+
declare module "lucide-react/dist/esm/icons/circle-check-big" {
|
|
28
|
+
const CircleCheckBig: React.FC<React.SVGProps<SVGSVGElement>>;
|
|
29
|
+
export default CircleCheckBig;
|
|
30
|
+
}
|
|
31
|
+
declare module "lucide-react/dist/esm/icons/grip-vertical" {
|
|
32
|
+
const GripVertical: React.FC<React.SVGProps<SVGSVGElement>>;
|
|
33
|
+
export default GripVertical;
|
|
34
|
+
}
|
|
35
|
+
declare module "lucide-react/dist/esm/icons/minus" {
|
|
36
|
+
const Minus: React.FC<React.SVGProps<SVGSVGElement>>;
|
|
37
|
+
export default Minus;
|
|
38
|
+
}
|
|
39
|
+
declare module "lucide-react/dist/esm/icons/plus" {
|
|
40
|
+
const Plus: React.FC<React.SVGProps<SVGSVGElement>>;
|
|
41
|
+
export default Plus;
|
|
42
|
+
}
|
|
43
|
+
declare module "lucide-react/dist/esm/icons/x" {
|
|
44
|
+
const X: React.FC<React.SVGProps<SVGSVGElement>>;
|
|
45
|
+
export default X;
|
|
46
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { render, screen } from "@testing-library/react";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
|
|
4
|
+
import { StatusPill, type StatusKind } from "../src/components/StatusPill";
|
|
5
|
+
|
|
6
|
+
const KINDS: StatusKind[] = ["success", "warning", "danger", "neutral", "info"];
|
|
7
|
+
|
|
8
|
+
describe("StatusPill", () => {
|
|
9
|
+
for (const kind of KINDS) {
|
|
10
|
+
it(`renders ${kind} variant`, () => {
|
|
11
|
+
render(<StatusPill status={kind} />);
|
|
12
|
+
expect(screen.getByText(kind)).toBeInTheDocument();
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
it("renders custom children", () => {
|
|
17
|
+
render(<StatusPill status="success">All good</StatusPill>);
|
|
18
|
+
expect(screen.getByText("All good")).toBeInTheDocument();
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
it("applies custom className", () => {
|
|
22
|
+
render(<StatusPill status="info" className="custom-class" />);
|
|
23
|
+
const el = screen.getByText("info");
|
|
24
|
+
expect(el).toHaveClass("custom-class");
|
|
25
|
+
});
|
|
26
|
+
});
|