nl-d365boilerplate-vite 1.0.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/.env.example +22 -0
- package/README.md +75 -0
- package/bin/cli.js +84 -0
- package/components.json +22 -0
- package/eslint.config.js +23 -0
- package/getToken.js +197 -0
- package/index.html +30 -0
- package/package.json +69 -0
- package/src/App.tsx +28 -0
- package/src/assets/images/novalogica-logo.svg +24 -0
- package/src/components/nl-header.tsx +165 -0
- package/src/components/page-layout.tsx +78 -0
- package/src/components/page-render.tsx +16 -0
- package/src/components/ui/alert.tsx +66 -0
- package/src/components/ui/badge.tsx +49 -0
- package/src/components/ui/button.tsx +165 -0
- package/src/components/ui/card.tsx +92 -0
- package/src/components/ui/dialog.tsx +156 -0
- package/src/components/ui/input.tsx +23 -0
- package/src/components/ui/label.tsx +23 -0
- package/src/components/ui/separator.tsx +26 -0
- package/src/components/ui/table.tsx +116 -0
- package/src/components/ui/tabs.tsx +91 -0
- package/src/components/ui/theme-toggle.tsx +28 -0
- package/src/config/pages.config.ts +34 -0
- package/src/contexts/dataverse-context.tsx +12 -0
- package/src/contexts/navigation-context.tsx +14 -0
- package/src/hooks/useAccounts.ts +194 -0
- package/src/hooks/useDataverse.ts +11 -0
- package/src/hooks/useNavigation.ts +41 -0
- package/src/index.css +147 -0
- package/src/lib/nav-items.ts +25 -0
- package/src/lib/utils.ts +6 -0
- package/src/main.tsx +12 -0
- package/src/pages/Demo.tsx +465 -0
- package/src/pages/Documentation.tsx +850 -0
- package/src/pages/Home.tsx +132 -0
- package/src/pages/index.ts +4 -0
- package/src/providers/dataverse-provider.tsx +81 -0
- package/src/providers/navigation-provider.tsx +33 -0
- package/src/providers/theme-provider.tsx +92 -0
- package/src/public/novalogica-logo.svg +24 -0
- package/tsconfig.app.json +32 -0
- package/tsconfig.json +17 -0
- package/tsconfig.node.json +26 -0
- package/vite.config.ts +26 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
3
|
+
import { Cancel01Icon } from "hugeicons-react";
|
|
4
|
+
|
|
5
|
+
import { cn } from "@/lib/utils";
|
|
6
|
+
import { Button } from "@/components/ui/button";
|
|
7
|
+
|
|
8
|
+
function Dialog({
|
|
9
|
+
...props
|
|
10
|
+
}: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
|
11
|
+
return <DialogPrimitive.Root data-slot="dialog" {...props} />;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function DialogTrigger({
|
|
15
|
+
...props
|
|
16
|
+
}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
|
|
17
|
+
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function DialogPortal({
|
|
21
|
+
...props
|
|
22
|
+
}: React.ComponentProps<typeof DialogPrimitive.Portal>) {
|
|
23
|
+
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function DialogClose({
|
|
27
|
+
...props
|
|
28
|
+
}: React.ComponentProps<typeof DialogPrimitive.Close>) {
|
|
29
|
+
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function DialogOverlay({
|
|
33
|
+
className,
|
|
34
|
+
...props
|
|
35
|
+
}: React.ComponentProps<typeof DialogPrimitive.Overlay>) {
|
|
36
|
+
return (
|
|
37
|
+
<DialogPrimitive.Overlay
|
|
38
|
+
data-slot="dialog-overlay"
|
|
39
|
+
className={cn(
|
|
40
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
|
|
41
|
+
className,
|
|
42
|
+
)}
|
|
43
|
+
{...props}
|
|
44
|
+
/>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function DialogContent({
|
|
49
|
+
className,
|
|
50
|
+
children,
|
|
51
|
+
showCloseButton = true,
|
|
52
|
+
...props
|
|
53
|
+
}: React.ComponentProps<typeof DialogPrimitive.Content> & {
|
|
54
|
+
showCloseButton?: boolean;
|
|
55
|
+
}) {
|
|
56
|
+
return (
|
|
57
|
+
<DialogPortal data-slot="dialog-portal">
|
|
58
|
+
<DialogOverlay />
|
|
59
|
+
<DialogPrimitive.Content
|
|
60
|
+
data-slot="dialog-content"
|
|
61
|
+
className={cn(
|
|
62
|
+
"bg-background 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 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 outline-none sm:max-w-lg",
|
|
63
|
+
className,
|
|
64
|
+
)}
|
|
65
|
+
{...props}
|
|
66
|
+
>
|
|
67
|
+
{children}
|
|
68
|
+
{showCloseButton && (
|
|
69
|
+
<DialogPrimitive.Close
|
|
70
|
+
data-slot="dialog-close"
|
|
71
|
+
className="ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4"
|
|
72
|
+
>
|
|
73
|
+
<Cancel01Icon />
|
|
74
|
+
<span className="sr-only">Close</span>
|
|
75
|
+
</DialogPrimitive.Close>
|
|
76
|
+
)}
|
|
77
|
+
</DialogPrimitive.Content>
|
|
78
|
+
</DialogPortal>
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function DialogHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
83
|
+
return (
|
|
84
|
+
<div
|
|
85
|
+
data-slot="dialog-header"
|
|
86
|
+
className={cn("flex flex-col gap-2 text-center sm:text-left", className)}
|
|
87
|
+
{...props}
|
|
88
|
+
/>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function DialogFooter({
|
|
93
|
+
className,
|
|
94
|
+
showCloseButton = false,
|
|
95
|
+
children,
|
|
96
|
+
...props
|
|
97
|
+
}: React.ComponentProps<"div"> & {
|
|
98
|
+
showCloseButton?: boolean;
|
|
99
|
+
}) {
|
|
100
|
+
return (
|
|
101
|
+
<div
|
|
102
|
+
data-slot="dialog-footer"
|
|
103
|
+
className={cn(
|
|
104
|
+
"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
|
|
105
|
+
className,
|
|
106
|
+
)}
|
|
107
|
+
{...props}
|
|
108
|
+
>
|
|
109
|
+
{children}
|
|
110
|
+
{showCloseButton && (
|
|
111
|
+
<DialogPrimitive.Close asChild>
|
|
112
|
+
<Button variant="outline">Close</Button>
|
|
113
|
+
</DialogPrimitive.Close>
|
|
114
|
+
)}
|
|
115
|
+
</div>
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function DialogTitle({
|
|
120
|
+
className,
|
|
121
|
+
...props
|
|
122
|
+
}: React.ComponentProps<typeof DialogPrimitive.Title>) {
|
|
123
|
+
return (
|
|
124
|
+
<DialogPrimitive.Title
|
|
125
|
+
data-slot="dialog-title"
|
|
126
|
+
className={cn("text-lg leading-none font-semibold", className)}
|
|
127
|
+
{...props}
|
|
128
|
+
/>
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function DialogDescription({
|
|
133
|
+
className,
|
|
134
|
+
...props
|
|
135
|
+
}: React.ComponentProps<typeof DialogPrimitive.Description>) {
|
|
136
|
+
return (
|
|
137
|
+
<DialogPrimitive.Description
|
|
138
|
+
data-slot="dialog-description"
|
|
139
|
+
className={cn("text-muted-foreground text-sm", className)}
|
|
140
|
+
{...props}
|
|
141
|
+
/>
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export {
|
|
146
|
+
Dialog,
|
|
147
|
+
DialogClose,
|
|
148
|
+
DialogContent,
|
|
149
|
+
DialogDescription,
|
|
150
|
+
DialogFooter,
|
|
151
|
+
DialogHeader,
|
|
152
|
+
DialogOverlay,
|
|
153
|
+
DialogPortal,
|
|
154
|
+
DialogTitle,
|
|
155
|
+
DialogTrigger,
|
|
156
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { cn } from "@/lib/utils";
|
|
3
|
+
|
|
4
|
+
export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {}
|
|
5
|
+
|
|
6
|
+
const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
|
7
|
+
({ className, type, ...props }, ref) => {
|
|
8
|
+
return (
|
|
9
|
+
<input
|
|
10
|
+
type={type}
|
|
11
|
+
className={cn(
|
|
12
|
+
"flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
|
13
|
+
className,
|
|
14
|
+
)}
|
|
15
|
+
ref={ref}
|
|
16
|
+
{...props}
|
|
17
|
+
/>
|
|
18
|
+
);
|
|
19
|
+
},
|
|
20
|
+
);
|
|
21
|
+
Input.displayName = "Input";
|
|
22
|
+
|
|
23
|
+
export { Input };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import * as LabelPrimitive from "@radix-ui/react-label";
|
|
3
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
4
|
+
import { cn } from "@/lib/utils";
|
|
5
|
+
|
|
6
|
+
const labelVariants = cva(
|
|
7
|
+
"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
|
|
8
|
+
);
|
|
9
|
+
|
|
10
|
+
const Label = React.forwardRef<
|
|
11
|
+
React.ElementRef<typeof LabelPrimitive.Root>,
|
|
12
|
+
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root> &
|
|
13
|
+
VariantProps<typeof labelVariants>
|
|
14
|
+
>(({ className, ...props }, ref) => (
|
|
15
|
+
<LabelPrimitive.Root
|
|
16
|
+
ref={ref}
|
|
17
|
+
className={cn(labelVariants(), className)}
|
|
18
|
+
{...props}
|
|
19
|
+
/>
|
|
20
|
+
));
|
|
21
|
+
Label.displayName = LabelPrimitive.Root.displayName;
|
|
22
|
+
|
|
23
|
+
export { Label };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import * as SeparatorPrimitive from "@radix-ui/react-separator"
|
|
3
|
+
|
|
4
|
+
import { cn } from "@/lib/utils"
|
|
5
|
+
|
|
6
|
+
function Separator({
|
|
7
|
+
className,
|
|
8
|
+
orientation = "horizontal",
|
|
9
|
+
decorative = true,
|
|
10
|
+
...props
|
|
11
|
+
}: React.ComponentProps<typeof SeparatorPrimitive.Root>) {
|
|
12
|
+
return (
|
|
13
|
+
<SeparatorPrimitive.Root
|
|
14
|
+
data-slot="separator"
|
|
15
|
+
decorative={decorative}
|
|
16
|
+
orientation={orientation}
|
|
17
|
+
className={cn(
|
|
18
|
+
"bg-border shrink-0 data-[orientation=horizontal]:h-px data-[orientation=horizontal]:w-full data-[orientation=vertical]:h-full data-[orientation=vertical]:w-px",
|
|
19
|
+
className
|
|
20
|
+
)}
|
|
21
|
+
{...props}
|
|
22
|
+
/>
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export { Separator }
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { cn } from "@/lib/utils";
|
|
3
|
+
|
|
4
|
+
const Table = React.forwardRef<
|
|
5
|
+
HTMLTableElement,
|
|
6
|
+
React.HTMLAttributes<HTMLTableElement>
|
|
7
|
+
>(({ className, ...props }, ref) => (
|
|
8
|
+
<div className="relative w-full overflow-auto">
|
|
9
|
+
<table
|
|
10
|
+
ref={ref}
|
|
11
|
+
className={cn("w-full caption-bottom text-sm", className)}
|
|
12
|
+
{...props}
|
|
13
|
+
/>
|
|
14
|
+
</div>
|
|
15
|
+
));
|
|
16
|
+
Table.displayName = "Table";
|
|
17
|
+
|
|
18
|
+
const TableHeader = React.forwardRef<
|
|
19
|
+
HTMLTableSectionElement,
|
|
20
|
+
React.HTMLAttributes<HTMLTableSectionElement>
|
|
21
|
+
>(({ className, ...props }, ref) => (
|
|
22
|
+
<thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />
|
|
23
|
+
));
|
|
24
|
+
TableHeader.displayName = "TableHeader";
|
|
25
|
+
|
|
26
|
+
const TableBody = React.forwardRef<
|
|
27
|
+
HTMLTableSectionElement,
|
|
28
|
+
React.HTMLAttributes<HTMLTableSectionElement>
|
|
29
|
+
>(({ className, ...props }, ref) => (
|
|
30
|
+
<tbody
|
|
31
|
+
ref={ref}
|
|
32
|
+
className={cn("[&_tr:last-child]:border-0", className)}
|
|
33
|
+
{...props}
|
|
34
|
+
/>
|
|
35
|
+
));
|
|
36
|
+
TableBody.displayName = "TableBody";
|
|
37
|
+
|
|
38
|
+
const TableFooter = React.forwardRef<
|
|
39
|
+
HTMLTableSectionElement,
|
|
40
|
+
React.HTMLAttributes<HTMLTableSectionElement>
|
|
41
|
+
>(({ className, ...props }, ref) => (
|
|
42
|
+
<tfoot
|
|
43
|
+
ref={ref}
|
|
44
|
+
className={cn(
|
|
45
|
+
"border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
|
|
46
|
+
className,
|
|
47
|
+
)}
|
|
48
|
+
{...props}
|
|
49
|
+
/>
|
|
50
|
+
));
|
|
51
|
+
TableFooter.displayName = "TableFooter";
|
|
52
|
+
|
|
53
|
+
const TableRow = React.forwardRef<
|
|
54
|
+
HTMLTableRowElement,
|
|
55
|
+
React.HTMLAttributes<HTMLTableRowElement>
|
|
56
|
+
>(({ className, ...props }, ref) => (
|
|
57
|
+
<tr
|
|
58
|
+
ref={ref}
|
|
59
|
+
className={cn(
|
|
60
|
+
"border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted",
|
|
61
|
+
className,
|
|
62
|
+
)}
|
|
63
|
+
{...props}
|
|
64
|
+
/>
|
|
65
|
+
));
|
|
66
|
+
TableRow.displayName = "TableRow";
|
|
67
|
+
|
|
68
|
+
const TableHead = React.forwardRef<
|
|
69
|
+
HTMLTableCellElement,
|
|
70
|
+
React.ThHTMLAttributes<HTMLTableCellElement>
|
|
71
|
+
>(({ className, ...props }, ref) => (
|
|
72
|
+
<th
|
|
73
|
+
ref={ref}
|
|
74
|
+
className={cn(
|
|
75
|
+
"h-12 px-4 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0",
|
|
76
|
+
className,
|
|
77
|
+
)}
|
|
78
|
+
{...props}
|
|
79
|
+
/>
|
|
80
|
+
));
|
|
81
|
+
TableHead.displayName = "TableHead";
|
|
82
|
+
|
|
83
|
+
const TableCell = React.forwardRef<
|
|
84
|
+
HTMLTableCellElement,
|
|
85
|
+
React.TdHTMLAttributes<HTMLTableCellElement>
|
|
86
|
+
>(({ className, ...props }, ref) => (
|
|
87
|
+
<td
|
|
88
|
+
ref={ref}
|
|
89
|
+
className={cn("p-4 align-middle [&:has([role=checkbox])]:pr-0", className)}
|
|
90
|
+
{...props}
|
|
91
|
+
/>
|
|
92
|
+
));
|
|
93
|
+
TableCell.displayName = "TableCell";
|
|
94
|
+
|
|
95
|
+
const TableCaption = React.forwardRef<
|
|
96
|
+
HTMLTableCaptionElement,
|
|
97
|
+
React.HTMLAttributes<HTMLTableCaptionElement>
|
|
98
|
+
>(({ className, ...props }, ref) => (
|
|
99
|
+
<caption
|
|
100
|
+
ref={ref}
|
|
101
|
+
className={cn("mt-4 text-sm text-muted-foreground", className)}
|
|
102
|
+
{...props}
|
|
103
|
+
/>
|
|
104
|
+
));
|
|
105
|
+
TableCaption.displayName = "TableCaption";
|
|
106
|
+
|
|
107
|
+
export {
|
|
108
|
+
Table,
|
|
109
|
+
TableHeader,
|
|
110
|
+
TableBody,
|
|
111
|
+
TableFooter,
|
|
112
|
+
TableHead,
|
|
113
|
+
TableRow,
|
|
114
|
+
TableCell,
|
|
115
|
+
TableCaption,
|
|
116
|
+
};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import * as React from "react"
|
|
4
|
+
import * as TabsPrimitive from "@radix-ui/react-tabs"
|
|
5
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
6
|
+
|
|
7
|
+
import { cn } from "@/lib/utils"
|
|
8
|
+
|
|
9
|
+
function Tabs({
|
|
10
|
+
className,
|
|
11
|
+
orientation = "horizontal",
|
|
12
|
+
...props
|
|
13
|
+
}: React.ComponentProps<typeof TabsPrimitive.Root>) {
|
|
14
|
+
return (
|
|
15
|
+
<TabsPrimitive.Root
|
|
16
|
+
data-slot="tabs"
|
|
17
|
+
data-orientation={orientation}
|
|
18
|
+
orientation={orientation}
|
|
19
|
+
className={cn(
|
|
20
|
+
"group/tabs flex gap-2 data-[orientation=horizontal]:flex-col",
|
|
21
|
+
className
|
|
22
|
+
)}
|
|
23
|
+
{...props}
|
|
24
|
+
/>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const tabsListVariants = cva(
|
|
29
|
+
"rounded-lg p-[3px] group-data-[orientation=horizontal]/tabs:h-9 data-[variant=line]:rounded-none group/tabs-list text-muted-foreground inline-flex w-fit items-center justify-center group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col",
|
|
30
|
+
{
|
|
31
|
+
variants: {
|
|
32
|
+
variant: {
|
|
33
|
+
default: "bg-muted",
|
|
34
|
+
line: "gap-1 bg-transparent",
|
|
35
|
+
},
|
|
36
|
+
},
|
|
37
|
+
defaultVariants: {
|
|
38
|
+
variant: "default",
|
|
39
|
+
},
|
|
40
|
+
}
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
function TabsList({
|
|
44
|
+
className,
|
|
45
|
+
variant = "default",
|
|
46
|
+
...props
|
|
47
|
+
}: React.ComponentProps<typeof TabsPrimitive.List> &
|
|
48
|
+
VariantProps<typeof tabsListVariants>) {
|
|
49
|
+
return (
|
|
50
|
+
<TabsPrimitive.List
|
|
51
|
+
data-slot="tabs-list"
|
|
52
|
+
data-variant={variant}
|
|
53
|
+
className={cn(tabsListVariants({ variant }), className)}
|
|
54
|
+
{...props}
|
|
55
|
+
/>
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function TabsTrigger({
|
|
60
|
+
className,
|
|
61
|
+
...props
|
|
62
|
+
}: React.ComponentProps<typeof TabsPrimitive.Trigger>) {
|
|
63
|
+
return (
|
|
64
|
+
<TabsPrimitive.Trigger
|
|
65
|
+
data-slot="tabs-trigger"
|
|
66
|
+
className={cn(
|
|
67
|
+
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:outline-ring text-foreground/60 hover:text-foreground dark:text-muted-foreground dark:hover:text-foreground relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start focus-visible:ring-[3px] focus-visible:outline-1 disabled:pointer-events-none disabled:opacity-50 group-data-[variant=default]/tabs-list:data-[state=active]:shadow-sm group-data-[variant=line]/tabs-list:data-[state=active]:shadow-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
68
|
+
"group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:border-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent",
|
|
69
|
+
"data-[state=active]:bg-background dark:data-[state=active]:text-foreground dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 data-[state=active]:text-foreground",
|
|
70
|
+
"after:bg-foreground after:absolute after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-[state=active]:after:opacity-100",
|
|
71
|
+
className
|
|
72
|
+
)}
|
|
73
|
+
{...props}
|
|
74
|
+
/>
|
|
75
|
+
)
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
function TabsContent({
|
|
79
|
+
className,
|
|
80
|
+
...props
|
|
81
|
+
}: React.ComponentProps<typeof TabsPrimitive.Content>) {
|
|
82
|
+
return (
|
|
83
|
+
<TabsPrimitive.Content
|
|
84
|
+
data-slot="tabs-content"
|
|
85
|
+
className={cn("flex-1 outline-none", className)}
|
|
86
|
+
{...props}
|
|
87
|
+
/>
|
|
88
|
+
)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export { Tabs, TabsList, TabsTrigger, TabsContent, tabsListVariants }
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Moon02Icon, Sun03Icon } from "hugeicons-react";
|
|
2
|
+
|
|
3
|
+
import { Button } from "@/components/ui/button";
|
|
4
|
+
import { useTheme } from "@/providers/theme-provider";
|
|
5
|
+
|
|
6
|
+
export function ThemeToggle() {
|
|
7
|
+
const { theme, setTheme } = useTheme();
|
|
8
|
+
|
|
9
|
+
const toggleTheme = () => {
|
|
10
|
+
setTheme(theme === "light" ? "dark" : "light");
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
return (
|
|
14
|
+
<Button
|
|
15
|
+
variant="ghost"
|
|
16
|
+
size="icon"
|
|
17
|
+
onClick={toggleTheme}
|
|
18
|
+
className="rounded-full"
|
|
19
|
+
>
|
|
20
|
+
{theme === "light" ? (
|
|
21
|
+
<Sun03Icon className="size-5" />
|
|
22
|
+
) : (
|
|
23
|
+
<Moon02Icon className="size-5" />
|
|
24
|
+
)}
|
|
25
|
+
<span className="sr-only">Toggle theme</span>
|
|
26
|
+
</Button>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Home, Documentation, Demo } from "@/pages";
|
|
2
|
+
import type { ComponentType } from "react";
|
|
3
|
+
|
|
4
|
+
export interface PageConfig {
|
|
5
|
+
id: string;
|
|
6
|
+
title: string;
|
|
7
|
+
component: ComponentType;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const PAGES: Record<string, PageConfig> = {
|
|
11
|
+
home: {
|
|
12
|
+
id: "home",
|
|
13
|
+
title: "Home",
|
|
14
|
+
component: Home,
|
|
15
|
+
},
|
|
16
|
+
documentation: {
|
|
17
|
+
id: "documentation",
|
|
18
|
+
title: "Documentation",
|
|
19
|
+
component: Documentation,
|
|
20
|
+
},
|
|
21
|
+
demo: {
|
|
22
|
+
id: "demo",
|
|
23
|
+
title: "Demo",
|
|
24
|
+
component: Demo,
|
|
25
|
+
},
|
|
26
|
+
// Adding a new page is now super simple:
|
|
27
|
+
// contacts: {
|
|
28
|
+
// id: "contacts",
|
|
29
|
+
// title: "Contacts",
|
|
30
|
+
// component: Contacts,
|
|
31
|
+
// },
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export const DEFAULT_PAGE = PAGES.home;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { DynamicsWebApi } from "dynamics-web-api";
|
|
2
|
+
import { createContext } from "react";
|
|
3
|
+
|
|
4
|
+
export interface DataverseContextProps {
|
|
5
|
+
api: DynamicsWebApi | null;
|
|
6
|
+
isReady: boolean;
|
|
7
|
+
error: string | null;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export const DataverseContext = createContext<
|
|
11
|
+
DataverseContextProps | undefined
|
|
12
|
+
>(undefined);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { createContext } from "react";
|
|
2
|
+
|
|
3
|
+
import type { PageConfig } from "@/config/pages.config";
|
|
4
|
+
|
|
5
|
+
export interface NavigationContextType {
|
|
6
|
+
currentPage: PageConfig;
|
|
7
|
+
navigate: (page: PageConfig) => void;
|
|
8
|
+
canGoBack: boolean;
|
|
9
|
+
goBack: () => void;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const NavigationContext = createContext<
|
|
13
|
+
NavigationContextType | undefined
|
|
14
|
+
>(undefined);
|