@jxrstudios/jxr 1.0.9 → 1.0.11
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/bin/jxr.js +6 -0
- package/dist/index.d.ts +43 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +57 -2
- package/dist/jxr-server-manager.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/jxr-server-manager.ts +57 -1
- package/zzz_react_template/App.tsx +43 -156
- package/zzz_react_template/components/ErrorBoundary.tsx +62 -0
- package/zzz_react_template/components/ManusDialog.tsx +85 -0
- package/zzz_react_template/components/Map.tsx +155 -0
- package/zzz_react_template/components/jxr/CodeEditor.tsx +313 -0
- package/zzz_react_template/components/jxr/FileExplorer.tsx +230 -0
- package/zzz_react_template/components/jxr/IDEShell.tsx +159 -0
- package/zzz_react_template/components/jxr/LandingPage.tsx +414 -0
- package/zzz_react_template/components/jxr/LivePreview.tsx +169 -0
- package/zzz_react_template/components/jxr/PerformanceDashboard.tsx +379 -0
- package/zzz_react_template/components/jxr/TopBar.tsx +149 -0
- package/zzz_react_template/components/ui/accordion.tsx +64 -0
- package/zzz_react_template/components/ui/alert-dialog.tsx +155 -0
- package/zzz_react_template/components/ui/alert.tsx +66 -0
- package/zzz_react_template/components/ui/aspect-ratio.tsx +9 -0
- package/zzz_react_template/components/ui/avatar.tsx +51 -0
- package/zzz_react_template/components/ui/badge.tsx +46 -0
- package/zzz_react_template/components/ui/breadcrumb.tsx +109 -0
- package/zzz_react_template/components/ui/button-group.tsx +83 -0
- package/zzz_react_template/components/ui/button.tsx +60 -0
- package/zzz_react_template/components/ui/calendar.tsx +211 -0
- package/zzz_react_template/components/ui/card.tsx +92 -0
- package/zzz_react_template/components/ui/carousel.tsx +239 -0
- package/zzz_react_template/components/ui/chart.tsx +355 -0
- package/zzz_react_template/components/ui/checkbox.tsx +30 -0
- package/zzz_react_template/components/ui/collapsible.tsx +31 -0
- package/zzz_react_template/components/ui/command.tsx +184 -0
- package/zzz_react_template/components/ui/context-menu.tsx +250 -0
- package/zzz_react_template/components/ui/dialog.tsx +209 -0
- package/zzz_react_template/components/ui/drawer.tsx +133 -0
- package/zzz_react_template/components/ui/dropdown-menu.tsx +255 -0
- package/zzz_react_template/components/ui/empty.tsx +104 -0
- package/zzz_react_template/components/ui/field.tsx +242 -0
- package/zzz_react_template/components/ui/form.tsx +168 -0
- package/zzz_react_template/components/ui/hover-card.tsx +42 -0
- package/zzz_react_template/components/ui/input-group.tsx +168 -0
- package/zzz_react_template/components/ui/input-otp.tsx +75 -0
- package/zzz_react_template/components/ui/input.tsx +70 -0
- package/zzz_react_template/components/ui/item.tsx +193 -0
- package/zzz_react_template/components/ui/kbd.tsx +28 -0
- package/zzz_react_template/components/ui/label.tsx +22 -0
- package/zzz_react_template/components/ui/menubar.tsx +274 -0
- package/zzz_react_template/components/ui/navigation-menu.tsx +168 -0
- package/zzz_react_template/components/ui/pagination.tsx +127 -0
- package/zzz_react_template/components/ui/popover.tsx +46 -0
- package/zzz_react_template/components/ui/progress.tsx +29 -0
- package/zzz_react_template/components/ui/radio-group.tsx +43 -0
- package/zzz_react_template/components/ui/resizable.tsx +54 -0
- package/zzz_react_template/components/ui/scroll-area.tsx +56 -0
- package/zzz_react_template/components/ui/select.tsx +185 -0
- package/zzz_react_template/components/ui/separator.tsx +26 -0
- package/zzz_react_template/components/ui/sheet.tsx +139 -0
- package/zzz_react_template/components/ui/sidebar.tsx +734 -0
- package/zzz_react_template/components/ui/skeleton.tsx +13 -0
- package/zzz_react_template/components/ui/slider.tsx +61 -0
- package/zzz_react_template/components/ui/sonner.tsx +23 -0
- package/zzz_react_template/components/ui/spinner.tsx +16 -0
- package/zzz_react_template/components/ui/switch.tsx +29 -0
- package/zzz_react_template/components/ui/table.tsx +114 -0
- package/zzz_react_template/components/ui/tabs.tsx +64 -0
- package/zzz_react_template/components/ui/textarea.tsx +67 -0
- package/zzz_react_template/components/ui/toggle-group.tsx +73 -0
- package/zzz_react_template/components/ui/toggle.tsx +45 -0
- package/zzz_react_template/components/ui/tooltip.tsx +59 -0
- package/zzz_react_template/const.ts +17 -0
- package/zzz_react_template/contexts/JXRContext.tsx +264 -0
- package/zzz_react_template/contexts/ThemeContext.tsx +64 -0
- package/zzz_react_template/hooks/useComposition.ts +81 -0
- package/zzz_react_template/hooks/useMobile.tsx +21 -0
- package/zzz_react_template/hooks/usePersistFn.ts +20 -0
- package/zzz_react_template/index.css +518 -11
- package/zzz_react_template/lib/jxr-runtime/index.ts +201 -0
- package/zzz_react_template/lib/jxr-runtime/module-resolver.ts +520 -0
- package/zzz_react_template/lib/jxr-runtime/moq-transport.ts +267 -0
- package/zzz_react_template/lib/jxr-runtime/web-crypto.ts +279 -0
- package/zzz_react_template/lib/jxr-runtime/worker-pool.ts +321 -0
- package/zzz_react_template/lib/utils.ts +6 -0
- package/zzz_react_template/main.tsx +4 -9
- package/zzz_react_template/pages/Docs.tsx +955 -0
- package/zzz_react_template/pages/Home.tsx +1080 -0
- package/zzz_react_template/pages/NotFound.tsx +105 -0
- package/zzz_react_template/tsconfig.json +24 -0
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { Slot } from "@radix-ui/react-slot";
|
|
3
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/utils";
|
|
6
|
+
import { Separator } from "@/components/ui/separator";
|
|
7
|
+
|
|
8
|
+
function ItemGroup({ className, ...props }: React.ComponentProps<"div">) {
|
|
9
|
+
return (
|
|
10
|
+
<div
|
|
11
|
+
role="list"
|
|
12
|
+
data-slot="item-group"
|
|
13
|
+
className={cn("group/item-group flex flex-col", className)}
|
|
14
|
+
{...props}
|
|
15
|
+
/>
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function ItemSeparator({
|
|
20
|
+
className,
|
|
21
|
+
...props
|
|
22
|
+
}: React.ComponentProps<typeof Separator>) {
|
|
23
|
+
return (
|
|
24
|
+
<Separator
|
|
25
|
+
data-slot="item-separator"
|
|
26
|
+
orientation="horizontal"
|
|
27
|
+
className={cn("my-0", className)}
|
|
28
|
+
{...props}
|
|
29
|
+
/>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const itemVariants = cva(
|
|
34
|
+
"group/item flex items-center border border-transparent text-sm rounded-md transition-colors [a]:hover:bg-accent/50 [a]:transition-colors duration-100 flex-wrap outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
|
|
35
|
+
{
|
|
36
|
+
variants: {
|
|
37
|
+
variant: {
|
|
38
|
+
default: "bg-transparent",
|
|
39
|
+
outline: "border-border",
|
|
40
|
+
muted: "bg-muted/50",
|
|
41
|
+
},
|
|
42
|
+
size: {
|
|
43
|
+
default: "p-4 gap-4 ",
|
|
44
|
+
sm: "py-3 px-4 gap-2.5",
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
defaultVariants: {
|
|
48
|
+
variant: "default",
|
|
49
|
+
size: "default",
|
|
50
|
+
},
|
|
51
|
+
}
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
function Item({
|
|
55
|
+
className,
|
|
56
|
+
variant = "default",
|
|
57
|
+
size = "default",
|
|
58
|
+
asChild = false,
|
|
59
|
+
...props
|
|
60
|
+
}: React.ComponentProps<"div"> &
|
|
61
|
+
VariantProps<typeof itemVariants> & { asChild?: boolean }) {
|
|
62
|
+
const Comp = asChild ? Slot : "div";
|
|
63
|
+
return (
|
|
64
|
+
<Comp
|
|
65
|
+
data-slot="item"
|
|
66
|
+
data-variant={variant}
|
|
67
|
+
data-size={size}
|
|
68
|
+
className={cn(itemVariants({ variant, size, className }))}
|
|
69
|
+
{...props}
|
|
70
|
+
/>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const itemMediaVariants = cva(
|
|
75
|
+
"flex shrink-0 items-center justify-center gap-2 group-has-[[data-slot=item-description]]/item:self-start [&_svg]:pointer-events-none group-has-[[data-slot=item-description]]/item:translate-y-0.5",
|
|
76
|
+
{
|
|
77
|
+
variants: {
|
|
78
|
+
variant: {
|
|
79
|
+
default: "bg-transparent",
|
|
80
|
+
icon: "size-8 border rounded-sm bg-muted [&_svg:not([class*='size-'])]:size-4",
|
|
81
|
+
image:
|
|
82
|
+
"size-10 rounded-sm overflow-hidden [&_img]:size-full [&_img]:object-cover",
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
defaultVariants: {
|
|
86
|
+
variant: "default",
|
|
87
|
+
},
|
|
88
|
+
}
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
function ItemMedia({
|
|
92
|
+
className,
|
|
93
|
+
variant = "default",
|
|
94
|
+
...props
|
|
95
|
+
}: React.ComponentProps<"div"> & VariantProps<typeof itemMediaVariants>) {
|
|
96
|
+
return (
|
|
97
|
+
<div
|
|
98
|
+
data-slot="item-media"
|
|
99
|
+
data-variant={variant}
|
|
100
|
+
className={cn(itemMediaVariants({ variant, className }))}
|
|
101
|
+
{...props}
|
|
102
|
+
/>
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function ItemContent({ className, ...props }: React.ComponentProps<"div">) {
|
|
107
|
+
return (
|
|
108
|
+
<div
|
|
109
|
+
data-slot="item-content"
|
|
110
|
+
className={cn(
|
|
111
|
+
"flex flex-1 flex-col gap-1 [&+[data-slot=item-content]]:flex-none",
|
|
112
|
+
className
|
|
113
|
+
)}
|
|
114
|
+
{...props}
|
|
115
|
+
/>
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function ItemTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
120
|
+
return (
|
|
121
|
+
<div
|
|
122
|
+
data-slot="item-title"
|
|
123
|
+
className={cn(
|
|
124
|
+
"flex w-fit items-center gap-2 text-sm leading-snug font-medium",
|
|
125
|
+
className
|
|
126
|
+
)}
|
|
127
|
+
{...props}
|
|
128
|
+
/>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function ItemDescription({ className, ...props }: React.ComponentProps<"p">) {
|
|
133
|
+
return (
|
|
134
|
+
<p
|
|
135
|
+
data-slot="item-description"
|
|
136
|
+
className={cn(
|
|
137
|
+
"text-muted-foreground line-clamp-2 text-sm leading-normal font-normal text-balance",
|
|
138
|
+
"[&>a:hover]:text-primary [&>a]:underline [&>a]:underline-offset-4",
|
|
139
|
+
className
|
|
140
|
+
)}
|
|
141
|
+
{...props}
|
|
142
|
+
/>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function ItemActions({ className, ...props }: React.ComponentProps<"div">) {
|
|
147
|
+
return (
|
|
148
|
+
<div
|
|
149
|
+
data-slot="item-actions"
|
|
150
|
+
className={cn("flex items-center gap-2", className)}
|
|
151
|
+
{...props}
|
|
152
|
+
/>
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function ItemHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
157
|
+
return (
|
|
158
|
+
<div
|
|
159
|
+
data-slot="item-header"
|
|
160
|
+
className={cn(
|
|
161
|
+
"flex basis-full items-center justify-between gap-2",
|
|
162
|
+
className
|
|
163
|
+
)}
|
|
164
|
+
{...props}
|
|
165
|
+
/>
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function ItemFooter({ className, ...props }: React.ComponentProps<"div">) {
|
|
170
|
+
return (
|
|
171
|
+
<div
|
|
172
|
+
data-slot="item-footer"
|
|
173
|
+
className={cn(
|
|
174
|
+
"flex basis-full items-center justify-between gap-2",
|
|
175
|
+
className
|
|
176
|
+
)}
|
|
177
|
+
{...props}
|
|
178
|
+
/>
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export {
|
|
183
|
+
Item,
|
|
184
|
+
ItemMedia,
|
|
185
|
+
ItemContent,
|
|
186
|
+
ItemActions,
|
|
187
|
+
ItemGroup,
|
|
188
|
+
ItemSeparator,
|
|
189
|
+
ItemTitle,
|
|
190
|
+
ItemDescription,
|
|
191
|
+
ItemHeader,
|
|
192
|
+
ItemFooter,
|
|
193
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { cn } from "@/lib/utils";
|
|
2
|
+
|
|
3
|
+
function Kbd({ className, ...props }: React.ComponentProps<"kbd">) {
|
|
4
|
+
return (
|
|
5
|
+
<kbd
|
|
6
|
+
data-slot="kbd"
|
|
7
|
+
className={cn(
|
|
8
|
+
"bg-muted text-muted-foreground pointer-events-none inline-flex h-5 w-fit min-w-5 items-center justify-center gap-1 rounded-sm px-1 font-sans text-xs font-medium select-none",
|
|
9
|
+
"[&_svg:not([class*='size-'])]:size-3",
|
|
10
|
+
"[[data-slot=tooltip-content]_&]:bg-background/20 [[data-slot=tooltip-content]_&]:text-background dark:[[data-slot=tooltip-content]_&]:bg-background/10",
|
|
11
|
+
className
|
|
12
|
+
)}
|
|
13
|
+
{...props}
|
|
14
|
+
/>
|
|
15
|
+
);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function KbdGroup({ className, ...props }: React.ComponentProps<"div">) {
|
|
19
|
+
return (
|
|
20
|
+
<kbd
|
|
21
|
+
data-slot="kbd-group"
|
|
22
|
+
className={cn("inline-flex items-center gap-1", className)}
|
|
23
|
+
{...props}
|
|
24
|
+
/>
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { Kbd, KbdGroup };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as LabelPrimitive from "@radix-ui/react-label";
|
|
3
|
+
|
|
4
|
+
import { cn } from "@/lib/utils";
|
|
5
|
+
|
|
6
|
+
function Label({
|
|
7
|
+
className,
|
|
8
|
+
...props
|
|
9
|
+
}: React.ComponentProps<typeof LabelPrimitive.Root>) {
|
|
10
|
+
return (
|
|
11
|
+
<LabelPrimitive.Root
|
|
12
|
+
data-slot="label"
|
|
13
|
+
className={cn(
|
|
14
|
+
"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
|
|
15
|
+
className
|
|
16
|
+
)}
|
|
17
|
+
{...props}
|
|
18
|
+
/>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export { Label };
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as MenubarPrimitive from "@radix-ui/react-menubar";
|
|
3
|
+
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react";
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/utils";
|
|
6
|
+
|
|
7
|
+
function Menubar({
|
|
8
|
+
className,
|
|
9
|
+
...props
|
|
10
|
+
}: React.ComponentProps<typeof MenubarPrimitive.Root>) {
|
|
11
|
+
return (
|
|
12
|
+
<MenubarPrimitive.Root
|
|
13
|
+
data-slot="menubar"
|
|
14
|
+
className={cn(
|
|
15
|
+
"bg-background flex h-9 items-center gap-1 rounded-md border p-1 shadow-xs",
|
|
16
|
+
className
|
|
17
|
+
)}
|
|
18
|
+
{...props}
|
|
19
|
+
/>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function MenubarMenu({
|
|
24
|
+
...props
|
|
25
|
+
}: React.ComponentProps<typeof MenubarPrimitive.Menu>) {
|
|
26
|
+
return <MenubarPrimitive.Menu data-slot="menubar-menu" {...props} />;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function MenubarGroup({
|
|
30
|
+
...props
|
|
31
|
+
}: React.ComponentProps<typeof MenubarPrimitive.Group>) {
|
|
32
|
+
return <MenubarPrimitive.Group data-slot="menubar-group" {...props} />;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function MenubarPortal({
|
|
36
|
+
...props
|
|
37
|
+
}: React.ComponentProps<typeof MenubarPrimitive.Portal>) {
|
|
38
|
+
return <MenubarPrimitive.Portal data-slot="menubar-portal" {...props} />;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function MenubarRadioGroup({
|
|
42
|
+
...props
|
|
43
|
+
}: React.ComponentProps<typeof MenubarPrimitive.RadioGroup>) {
|
|
44
|
+
return (
|
|
45
|
+
<MenubarPrimitive.RadioGroup data-slot="menubar-radio-group" {...props} />
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function MenubarTrigger({
|
|
50
|
+
className,
|
|
51
|
+
...props
|
|
52
|
+
}: React.ComponentProps<typeof MenubarPrimitive.Trigger>) {
|
|
53
|
+
return (
|
|
54
|
+
<MenubarPrimitive.Trigger
|
|
55
|
+
data-slot="menubar-trigger"
|
|
56
|
+
className={cn(
|
|
57
|
+
"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex items-center rounded-sm px-2 py-1 text-sm font-medium outline-hidden select-none",
|
|
58
|
+
className
|
|
59
|
+
)}
|
|
60
|
+
{...props}
|
|
61
|
+
/>
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function MenubarContent({
|
|
66
|
+
className,
|
|
67
|
+
align = "start",
|
|
68
|
+
alignOffset = -4,
|
|
69
|
+
sideOffset = 8,
|
|
70
|
+
...props
|
|
71
|
+
}: React.ComponentProps<typeof MenubarPrimitive.Content>) {
|
|
72
|
+
return (
|
|
73
|
+
<MenubarPortal>
|
|
74
|
+
<MenubarPrimitive.Content
|
|
75
|
+
data-slot="menubar-content"
|
|
76
|
+
align={align}
|
|
77
|
+
alignOffset={alignOffset}
|
|
78
|
+
sideOffset={sideOffset}
|
|
79
|
+
className={cn(
|
|
80
|
+
"bg-popover text-popover-foreground data-[state=open]:animate-in 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 min-w-[12rem] origin-(--radix-menubar-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-md",
|
|
81
|
+
className
|
|
82
|
+
)}
|
|
83
|
+
{...props}
|
|
84
|
+
/>
|
|
85
|
+
</MenubarPortal>
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function MenubarItem({
|
|
90
|
+
className,
|
|
91
|
+
inset,
|
|
92
|
+
variant = "default",
|
|
93
|
+
...props
|
|
94
|
+
}: React.ComponentProps<typeof MenubarPrimitive.Item> & {
|
|
95
|
+
inset?: boolean;
|
|
96
|
+
variant?: "default" | "destructive";
|
|
97
|
+
}) {
|
|
98
|
+
return (
|
|
99
|
+
<MenubarPrimitive.Item
|
|
100
|
+
data-slot="menubar-item"
|
|
101
|
+
data-inset={inset}
|
|
102
|
+
data-variant={variant}
|
|
103
|
+
className={cn(
|
|
104
|
+
"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
105
|
+
className
|
|
106
|
+
)}
|
|
107
|
+
{...props}
|
|
108
|
+
/>
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function MenubarCheckboxItem({
|
|
113
|
+
className,
|
|
114
|
+
children,
|
|
115
|
+
checked,
|
|
116
|
+
...props
|
|
117
|
+
}: React.ComponentProps<typeof MenubarPrimitive.CheckboxItem>) {
|
|
118
|
+
return (
|
|
119
|
+
<MenubarPrimitive.CheckboxItem
|
|
120
|
+
data-slot="menubar-checkbox-item"
|
|
121
|
+
className={cn(
|
|
122
|
+
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-xs py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
123
|
+
className
|
|
124
|
+
)}
|
|
125
|
+
checked={checked}
|
|
126
|
+
{...props}
|
|
127
|
+
>
|
|
128
|
+
<span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
|
|
129
|
+
<MenubarPrimitive.ItemIndicator>
|
|
130
|
+
<CheckIcon className="size-4" />
|
|
131
|
+
</MenubarPrimitive.ItemIndicator>
|
|
132
|
+
</span>
|
|
133
|
+
{children}
|
|
134
|
+
</MenubarPrimitive.CheckboxItem>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function MenubarRadioItem({
|
|
139
|
+
className,
|
|
140
|
+
children,
|
|
141
|
+
...props
|
|
142
|
+
}: React.ComponentProps<typeof MenubarPrimitive.RadioItem>) {
|
|
143
|
+
return (
|
|
144
|
+
<MenubarPrimitive.RadioItem
|
|
145
|
+
data-slot="menubar-radio-item"
|
|
146
|
+
className={cn(
|
|
147
|
+
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-xs py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
148
|
+
className
|
|
149
|
+
)}
|
|
150
|
+
{...props}
|
|
151
|
+
>
|
|
152
|
+
<span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
|
|
153
|
+
<MenubarPrimitive.ItemIndicator>
|
|
154
|
+
<CircleIcon className="size-2 fill-current" />
|
|
155
|
+
</MenubarPrimitive.ItemIndicator>
|
|
156
|
+
</span>
|
|
157
|
+
{children}
|
|
158
|
+
</MenubarPrimitive.RadioItem>
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function MenubarLabel({
|
|
163
|
+
className,
|
|
164
|
+
inset,
|
|
165
|
+
...props
|
|
166
|
+
}: React.ComponentProps<typeof MenubarPrimitive.Label> & {
|
|
167
|
+
inset?: boolean;
|
|
168
|
+
}) {
|
|
169
|
+
return (
|
|
170
|
+
<MenubarPrimitive.Label
|
|
171
|
+
data-slot="menubar-label"
|
|
172
|
+
data-inset={inset}
|
|
173
|
+
className={cn(
|
|
174
|
+
"px-2 py-1.5 text-sm font-medium data-[inset]:pl-8",
|
|
175
|
+
className
|
|
176
|
+
)}
|
|
177
|
+
{...props}
|
|
178
|
+
/>
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function MenubarSeparator({
|
|
183
|
+
className,
|
|
184
|
+
...props
|
|
185
|
+
}: React.ComponentProps<typeof MenubarPrimitive.Separator>) {
|
|
186
|
+
return (
|
|
187
|
+
<MenubarPrimitive.Separator
|
|
188
|
+
data-slot="menubar-separator"
|
|
189
|
+
className={cn("bg-border -mx-1 my-1 h-px", className)}
|
|
190
|
+
{...props}
|
|
191
|
+
/>
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function MenubarShortcut({
|
|
196
|
+
className,
|
|
197
|
+
...props
|
|
198
|
+
}: React.ComponentProps<"span">) {
|
|
199
|
+
return (
|
|
200
|
+
<span
|
|
201
|
+
data-slot="menubar-shortcut"
|
|
202
|
+
className={cn(
|
|
203
|
+
"text-muted-foreground ml-auto text-xs tracking-widest",
|
|
204
|
+
className
|
|
205
|
+
)}
|
|
206
|
+
{...props}
|
|
207
|
+
/>
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function MenubarSub({
|
|
212
|
+
...props
|
|
213
|
+
}: React.ComponentProps<typeof MenubarPrimitive.Sub>) {
|
|
214
|
+
return <MenubarPrimitive.Sub data-slot="menubar-sub" {...props} />;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function MenubarSubTrigger({
|
|
218
|
+
className,
|
|
219
|
+
inset,
|
|
220
|
+
children,
|
|
221
|
+
...props
|
|
222
|
+
}: React.ComponentProps<typeof MenubarPrimitive.SubTrigger> & {
|
|
223
|
+
inset?: boolean;
|
|
224
|
+
}) {
|
|
225
|
+
return (
|
|
226
|
+
<MenubarPrimitive.SubTrigger
|
|
227
|
+
data-slot="menubar-sub-trigger"
|
|
228
|
+
data-inset={inset}
|
|
229
|
+
className={cn(
|
|
230
|
+
"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-none select-none data-[inset]:pl-8",
|
|
231
|
+
className
|
|
232
|
+
)}
|
|
233
|
+
{...props}
|
|
234
|
+
>
|
|
235
|
+
{children}
|
|
236
|
+
<ChevronRightIcon className="ml-auto h-4 w-4" />
|
|
237
|
+
</MenubarPrimitive.SubTrigger>
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function MenubarSubContent({
|
|
242
|
+
className,
|
|
243
|
+
...props
|
|
244
|
+
}: React.ComponentProps<typeof MenubarPrimitive.SubContent>) {
|
|
245
|
+
return (
|
|
246
|
+
<MenubarPrimitive.SubContent
|
|
247
|
+
data-slot="menubar-sub-content"
|
|
248
|
+
className={cn(
|
|
249
|
+
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-menubar-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg",
|
|
250
|
+
className
|
|
251
|
+
)}
|
|
252
|
+
{...props}
|
|
253
|
+
/>
|
|
254
|
+
);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
export {
|
|
258
|
+
Menubar,
|
|
259
|
+
MenubarPortal,
|
|
260
|
+
MenubarMenu,
|
|
261
|
+
MenubarTrigger,
|
|
262
|
+
MenubarContent,
|
|
263
|
+
MenubarGroup,
|
|
264
|
+
MenubarSeparator,
|
|
265
|
+
MenubarLabel,
|
|
266
|
+
MenubarItem,
|
|
267
|
+
MenubarShortcut,
|
|
268
|
+
MenubarCheckboxItem,
|
|
269
|
+
MenubarRadioGroup,
|
|
270
|
+
MenubarRadioItem,
|
|
271
|
+
MenubarSub,
|
|
272
|
+
MenubarSubTrigger,
|
|
273
|
+
MenubarSubContent,
|
|
274
|
+
};
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import * 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 "@/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
|
+
data-slot="navigation-menu"
|
|
19
|
+
data-viewport={viewport}
|
|
20
|
+
className={cn(
|
|
21
|
+
"group/navigation-menu relative flex max-w-max flex-1 items-center justify-center",
|
|
22
|
+
className
|
|
23
|
+
)}
|
|
24
|
+
{...props}
|
|
25
|
+
>
|
|
26
|
+
{children}
|
|
27
|
+
{viewport && <NavigationMenuViewport />}
|
|
28
|
+
</NavigationMenuPrimitive.Root>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function NavigationMenuList({
|
|
33
|
+
className,
|
|
34
|
+
...props
|
|
35
|
+
}: React.ComponentProps<typeof NavigationMenuPrimitive.List>) {
|
|
36
|
+
return (
|
|
37
|
+
<NavigationMenuPrimitive.List
|
|
38
|
+
data-slot="navigation-menu-list"
|
|
39
|
+
className={cn(
|
|
40
|
+
"group flex flex-1 list-none items-center justify-center gap-1",
|
|
41
|
+
className
|
|
42
|
+
)}
|
|
43
|
+
{...props}
|
|
44
|
+
/>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function NavigationMenuItem({
|
|
49
|
+
className,
|
|
50
|
+
...props
|
|
51
|
+
}: React.ComponentProps<typeof NavigationMenuPrimitive.Item>) {
|
|
52
|
+
return (
|
|
53
|
+
<NavigationMenuPrimitive.Item
|
|
54
|
+
data-slot="navigation-menu-item"
|
|
55
|
+
className={cn("relative", className)}
|
|
56
|
+
{...props}
|
|
57
|
+
/>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const navigationMenuTriggerStyle = cva(
|
|
62
|
+
"group inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=open]:hover:bg-accent data-[state=open]:text-accent-foreground data-[state=open]:focus:bg-accent data-[state=open]:bg-accent/50 focus-visible:ring-ring/50 outline-none transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1"
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
function NavigationMenuTrigger({
|
|
66
|
+
className,
|
|
67
|
+
children,
|
|
68
|
+
...props
|
|
69
|
+
}: React.ComponentProps<typeof NavigationMenuPrimitive.Trigger>) {
|
|
70
|
+
return (
|
|
71
|
+
<NavigationMenuPrimitive.Trigger
|
|
72
|
+
data-slot="navigation-menu-trigger"
|
|
73
|
+
className={cn(navigationMenuTriggerStyle(), "group", className)}
|
|
74
|
+
{...props}
|
|
75
|
+
>
|
|
76
|
+
{children}{" "}
|
|
77
|
+
<ChevronDownIcon
|
|
78
|
+
className="relative top-[1px] ml-1 size-3 transition duration-300 group-data-[state=open]:rotate-180"
|
|
79
|
+
aria-hidden="true"
|
|
80
|
+
/>
|
|
81
|
+
</NavigationMenuPrimitive.Trigger>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function NavigationMenuContent({
|
|
86
|
+
className,
|
|
87
|
+
...props
|
|
88
|
+
}: React.ComponentProps<typeof NavigationMenuPrimitive.Content>) {
|
|
89
|
+
return (
|
|
90
|
+
<NavigationMenuPrimitive.Content
|
|
91
|
+
data-slot="navigation-menu-content"
|
|
92
|
+
className={cn(
|
|
93
|
+
"data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out 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 md:absolute md:w-auto",
|
|
94
|
+
"group-data-[viewport=false]/navigation-menu:bg-popover group-data-[viewport=false]/navigation-menu:text-popover-foreground group-data-[viewport=false]/navigation-menu:data-[state=open]:animate-in group-data-[viewport=false]/navigation-menu:data-[state=closed]:animate-out 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 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:shadow group-data-[viewport=false]/navigation-menu:duration-200 **:data-[slot=navigation-menu-link]:focus:ring-0 **:data-[slot=navigation-menu-link]:focus:outline-none",
|
|
95
|
+
className
|
|
96
|
+
)}
|
|
97
|
+
{...props}
|
|
98
|
+
/>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function NavigationMenuViewport({
|
|
103
|
+
className,
|
|
104
|
+
...props
|
|
105
|
+
}: React.ComponentProps<typeof NavigationMenuPrimitive.Viewport>) {
|
|
106
|
+
return (
|
|
107
|
+
<div
|
|
108
|
+
className={cn(
|
|
109
|
+
"absolute top-full left-0 isolate z-50 flex justify-center"
|
|
110
|
+
)}
|
|
111
|
+
>
|
|
112
|
+
<NavigationMenuPrimitive.Viewport
|
|
113
|
+
data-slot="navigation-menu-viewport"
|
|
114
|
+
className={cn(
|
|
115
|
+
"origin-top-center bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out 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 overflow-hidden rounded-md border shadow md:w-[var(--radix-navigation-menu-viewport-width)]",
|
|
116
|
+
className
|
|
117
|
+
)}
|
|
118
|
+
{...props}
|
|
119
|
+
/>
|
|
120
|
+
</div>
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
function NavigationMenuLink({
|
|
125
|
+
className,
|
|
126
|
+
...props
|
|
127
|
+
}: React.ComponentProps<typeof NavigationMenuPrimitive.Link>) {
|
|
128
|
+
return (
|
|
129
|
+
<NavigationMenuPrimitive.Link
|
|
130
|
+
data-slot="navigation-menu-link"
|
|
131
|
+
className={cn(
|
|
132
|
+
"data-[active=true]:focus:bg-accent data-[active=true]:hover:bg-accent data-[active=true]:bg-accent/50 data-[active=true]:text-accent-foreground hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus-visible:ring-ring/50 [&_svg:not([class*='text-'])]:text-muted-foreground flex flex-col gap-1 rounded-sm p-2 text-sm transition-all outline-none focus-visible:ring-[3px] focus-visible:outline-1 [&_svg:not([class*='size-'])]:size-4",
|
|
133
|
+
className
|
|
134
|
+
)}
|
|
135
|
+
{...props}
|
|
136
|
+
/>
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
function NavigationMenuIndicator({
|
|
141
|
+
className,
|
|
142
|
+
...props
|
|
143
|
+
}: React.ComponentProps<typeof NavigationMenuPrimitive.Indicator>) {
|
|
144
|
+
return (
|
|
145
|
+
<NavigationMenuPrimitive.Indicator
|
|
146
|
+
data-slot="navigation-menu-indicator"
|
|
147
|
+
className={cn(
|
|
148
|
+
"data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden",
|
|
149
|
+
className
|
|
150
|
+
)}
|
|
151
|
+
{...props}
|
|
152
|
+
>
|
|
153
|
+
<div className="bg-border relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm shadow-md" />
|
|
154
|
+
</NavigationMenuPrimitive.Indicator>
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export {
|
|
159
|
+
NavigationMenu,
|
|
160
|
+
NavigationMenuList,
|
|
161
|
+
NavigationMenuItem,
|
|
162
|
+
NavigationMenuContent,
|
|
163
|
+
NavigationMenuTrigger,
|
|
164
|
+
NavigationMenuLink,
|
|
165
|
+
NavigationMenuIndicator,
|
|
166
|
+
NavigationMenuViewport,
|
|
167
|
+
navigationMenuTriggerStyle,
|
|
168
|
+
};
|