create-astram-app 0.4.0 → 0.6.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/README.md +211 -38
- package/dist/add-frontend.js.map +1 -1
- package/dist/index.js +14 -9
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/template/README.md +51 -20
- package/template/frontend/README.md +21 -11
- package/template/frontend/index.html +16 -0
- package/template/frontend/package.json +1 -1
- package/template/frontend/src/App.jsx +95 -20
- package/template/frontend/src/auth/AuthContext.jsx +145 -21
- package/template/frontend/src/auth/routeGate.js +31 -0
- package/template/frontend/src/auth/routeGate.test.mjs +59 -0
- package/template/frontend/src/auth/sessionFlow.js +27 -0
- package/template/frontend/src/auth/sessionFlow.test.mjs +63 -0
- package/template/frontend/src/components/EntityList.jsx +1 -7
- package/template/frontend/src/components/MultiSelectChecklist.jsx +166 -0
- package/template/frontend/src/components/PageHeader.jsx +5 -4
- package/template/frontend/src/components/ShareDialog.jsx +3 -5
- package/template/frontend/src/components/access/CollapsibleGroup.jsx +4 -1
- package/template/frontend/src/components/ui/alert-dialog.tsx +27 -50
- package/template/frontend/src/components/ui/alert.tsx +17 -23
- package/template/frontend/src/components/ui/avatar.tsx +8 -20
- package/template/frontend/src/components/ui/badge.tsx +17 -26
- package/template/frontend/src/components/ui/button.tsx +22 -24
- package/template/frontend/src/components/ui/card.tsx +19 -36
- package/template/frontend/src/components/ui/checkbox.tsx +7 -10
- package/template/frontend/src/components/ui/date-field.tsx +26 -27
- package/template/frontend/src/components/ui/dialog.tsx +24 -40
- package/template/frontend/src/components/ui/dropdown-menu.tsx +25 -54
- package/template/frontend/src/components/ui/input-otp.tsx +1 -4
- package/template/frontend/src/components/ui/label.tsx +10 -12
- package/template/frontend/src/components/ui/searchable-select.tsx +1 -3
- package/template/frontend/src/components/ui/select.tsx +31 -43
- package/template/frontend/src/components/ui/separator.tsx +6 -6
- package/template/frontend/src/components/ui/sheet.tsx +29 -38
- package/template/frontend/src/components/ui/skeleton.tsx +3 -3
- package/template/frontend/src/components/ui/sonner.tsx +7 -7
- package/template/frontend/src/components/ui/table.tsx +56 -70
- package/template/frontend/src/components/ui/tooltip.tsx +7 -11
- package/template/frontend/src/config/branding.js +1 -4
- package/template/frontend/src/hooks/useMobile.tsx +4 -6
- package/template/frontend/src/index.css +9 -4
- package/template/frontend/src/pages/Dashboard.jsx +13 -7
- package/template/frontend/src/pages/ForgotPassword.jsx +9 -2
- package/template/frontend/src/pages/Login.jsx +85 -70
- package/template/frontend/src/pages/ResetPassword.jsx +9 -2
- package/template/frontend/src/pages/access/AccessForm.jsx +49 -15
- package/template/frontend/src/pages/access/AccessPage.jsx +10 -6
- package/template/frontend/src/pages/access/RecordPoliciesPage.jsx +9 -2
- package/template/frontend/src/pages/account/AccountLayout.jsx +11 -6
- package/template/frontend/src/pages/account/ChangePasswordPage.jsx +2 -2
- package/template/frontend/src/pages/account/ReenrollPage.jsx +3 -5
- package/template/frontend/src/pages/account/TwoFactorPage.jsx +3 -8
- package/template/frontend/src/pages/companies/CompaniesPage.jsx +7 -9
- package/template/frontend/src/pages/cross-tenant/GrantForm.jsx +41 -8
- package/template/frontend/src/pages/cross-tenant/GrantsPage.jsx +30 -7
- package/template/frontend/src/pages/cross-tenant/InboxPage.jsx +12 -3
- package/template/frontend/src/pages/roles/RolesPage.jsx +5 -9
- package/template/frontend/src/pages/service-accounts/KeyRevealDialog.jsx +104 -0
- package/template/frontend/src/pages/service-accounts/ServiceAccountAccessDialog.jsx +231 -0
- package/template/frontend/src/pages/service-accounts/ServiceAccountActionsMenu.jsx +56 -0
- package/template/frontend/src/pages/service-accounts/ServiceAccountsPage.jsx +368 -0
- package/template/frontend/src/pages/service-accounts/accessModel.js +158 -0
- package/template/frontend/src/pages/service-accounts/accessModel.test.mjs +189 -0
- package/template/frontend/src/pages/users/MembershipCard.jsx +3 -1
- package/template/frontend/src/pages/users/PostingRow.jsx +8 -14
- package/template/frontend/src/pages/users/UsersPage.jsx +7 -9
- package/template/frontend/src/platform/httpClient.js +5 -0
- package/template/frontend/src/platform/sessionStore.js +55 -13
- package/template/frontend/src/platform/sessionStore.test.mjs +89 -0
- package/template/frontend/src/platform/shieldTransport.js +6 -0
- package/template/frontend/src/platform/shieldTransport.test.mjs +84 -5
- package/template/frontend/src/shell/AppShell.jsx +10 -12
- package/template/frontend/src/shell/Sidebar.jsx +15 -3
- package/template/frontend/src/shell/nav.js +13 -3
- package/template/frontend/vite.config.js +19 -1
- package/template/server/_env.example +22 -1
- package/template/server/eslint.config.mjs +194 -0
- package/template/server/package.json +11 -11
- package/template/server/scripts/dev.mjs +17 -6
- package/template/server/scripts/sync-astram-guide.mjs +45 -19
- package/template/server/src/app.module.ts +11 -5
- package/template/server/src/health/demo.controller.ts +16 -12
- package/template/server/src/main.ts +23 -1
- package/template/server/test/enforcement.e2e.spec.ts +73 -6
- package/template/server/eslint.config.js +0 -95
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import * as React from
|
|
2
|
-
import { Slot } from
|
|
3
|
-
import { cva, type VariantProps } from
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { Slot } from '@radix-ui/react-slot';
|
|
3
|
+
import { cva, type VariantProps } from 'class-variance-authority';
|
|
4
4
|
|
|
5
|
-
import { cn } from
|
|
5
|
+
import { cn } from '@/lib/utils';
|
|
6
6
|
|
|
7
7
|
const buttonVariants = cva(
|
|
8
8
|
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
|
@@ -13,34 +13,32 @@ const buttonVariants = cva(
|
|
|
13
13
|
// depth (a crisp `shadow-sm` in light; the dark `.dark [data-slot=button].bg-primary`
|
|
14
14
|
// rule in index.css supplies the top-light inset + brand glow in dark),
|
|
15
15
|
// so it reads as a raised, saturated control rather than a flat swatch.
|
|
16
|
-
default:
|
|
16
|
+
default: 'bg-primary text-primary-foreground shadow-sm hover:bg-primary/90',
|
|
17
17
|
destructive:
|
|
18
|
-
|
|
18
|
+
'bg-destructive text-white shadow-sm hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
|
|
19
19
|
outline:
|
|
20
|
-
|
|
21
|
-
secondary:
|
|
22
|
-
|
|
23
|
-
ghost:
|
|
24
|
-
"hover:bg-accent dark:hover:bg-accent/50",
|
|
20
|
+
'border bg-transparent shadow-xs hover:bg-accent dark:bg-transparent dark:border-input dark:hover:bg-input/50',
|
|
21
|
+
secondary: 'bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
|
22
|
+
ghost: 'hover:bg-accent dark:hover:bg-accent/50',
|
|
25
23
|
// Tonal button (OCA `.oca-btn--soft-primary`): a brand-tinted fill with
|
|
26
24
|
// brand-colored text — a lighter-weight primary for secondary actions.
|
|
27
|
-
soft:
|
|
28
|
-
link:
|
|
25
|
+
soft: 'bg-primary/10 text-primary hover:bg-primary/15',
|
|
26
|
+
link: 'text-primary underline-offset-4 hover:underline',
|
|
29
27
|
},
|
|
30
28
|
size: {
|
|
31
|
-
default:
|
|
32
|
-
sm:
|
|
33
|
-
lg:
|
|
34
|
-
icon:
|
|
35
|
-
|
|
36
|
-
|
|
29
|
+
default: 'h-9 px-4 py-2 has-[>svg]:px-3',
|
|
30
|
+
sm: 'h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5',
|
|
31
|
+
lg: 'h-10 rounded-md px-6 has-[>svg]:px-4',
|
|
32
|
+
icon: 'size-9',
|
|
33
|
+
'icon-sm': 'size-8',
|
|
34
|
+
'icon-lg': 'size-10',
|
|
37
35
|
},
|
|
38
36
|
},
|
|
39
37
|
defaultVariants: {
|
|
40
|
-
variant:
|
|
41
|
-
size:
|
|
38
|
+
variant: 'default',
|
|
39
|
+
size: 'default',
|
|
42
40
|
},
|
|
43
|
-
}
|
|
41
|
+
},
|
|
44
42
|
);
|
|
45
43
|
|
|
46
44
|
function Button({
|
|
@@ -49,11 +47,11 @@ function Button({
|
|
|
49
47
|
size,
|
|
50
48
|
asChild = false,
|
|
51
49
|
...props
|
|
52
|
-
}: React.ComponentProps<
|
|
50
|
+
}: React.ComponentProps<'button'> &
|
|
53
51
|
VariantProps<typeof buttonVariants> & {
|
|
54
52
|
asChild?: boolean;
|
|
55
53
|
}) {
|
|
56
|
-
const Comp = asChild ? Slot :
|
|
54
|
+
const Comp = asChild ? Slot : 'button';
|
|
57
55
|
|
|
58
56
|
return (
|
|
59
57
|
<Comp
|
|
@@ -1,92 +1,75 @@
|
|
|
1
|
-
import * as React from
|
|
1
|
+
import * as React from 'react';
|
|
2
2
|
|
|
3
|
-
import { cn } from
|
|
3
|
+
import { cn } from '@/lib/utils';
|
|
4
4
|
|
|
5
|
-
function Card({ className, ...props }: React.ComponentProps<
|
|
5
|
+
function Card({ className, ...props }: React.ComponentProps<'div'>) {
|
|
6
6
|
return (
|
|
7
7
|
<div
|
|
8
8
|
data-slot="card"
|
|
9
9
|
className={cn(
|
|
10
|
-
|
|
11
|
-
className
|
|
10
|
+
'bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm',
|
|
11
|
+
className,
|
|
12
12
|
)}
|
|
13
13
|
{...props}
|
|
14
14
|
/>
|
|
15
15
|
);
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
function CardHeader({ className, ...props }: React.ComponentProps<
|
|
18
|
+
function CardHeader({ className, ...props }: React.ComponentProps<'div'>) {
|
|
19
19
|
return (
|
|
20
20
|
<div
|
|
21
21
|
data-slot="card-header"
|
|
22
22
|
className={cn(
|
|
23
|
-
|
|
24
|
-
className
|
|
23
|
+
'@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6',
|
|
24
|
+
className,
|
|
25
25
|
)}
|
|
26
26
|
{...props}
|
|
27
27
|
/>
|
|
28
28
|
);
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
function CardTitle({ className, ...props }: React.ComponentProps<
|
|
31
|
+
function CardTitle({ className, ...props }: React.ComponentProps<'div'>) {
|
|
32
32
|
return (
|
|
33
33
|
<div
|
|
34
34
|
data-slot="card-title"
|
|
35
|
-
className={cn(
|
|
35
|
+
className={cn('leading-none font-semibold', className)}
|
|
36
36
|
{...props}
|
|
37
37
|
/>
|
|
38
38
|
);
|
|
39
39
|
}
|
|
40
40
|
|
|
41
|
-
function CardDescription({ className, ...props }: React.ComponentProps<
|
|
41
|
+
function CardDescription({ className, ...props }: React.ComponentProps<'div'>) {
|
|
42
42
|
return (
|
|
43
43
|
<div
|
|
44
44
|
data-slot="card-description"
|
|
45
|
-
className={cn(
|
|
45
|
+
className={cn('text-muted-foreground text-sm', className)}
|
|
46
46
|
{...props}
|
|
47
47
|
/>
|
|
48
48
|
);
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
function CardAction({ className, ...props }: React.ComponentProps<
|
|
51
|
+
function CardAction({ className, ...props }: React.ComponentProps<'div'>) {
|
|
52
52
|
return (
|
|
53
53
|
<div
|
|
54
54
|
data-slot="card-action"
|
|
55
|
-
className={cn(
|
|
56
|
-
"col-start-2 row-span-2 row-start-1 self-start justify-self-end",
|
|
57
|
-
className
|
|
58
|
-
)}
|
|
55
|
+
className={cn('col-start-2 row-span-2 row-start-1 self-start justify-self-end', className)}
|
|
59
56
|
{...props}
|
|
60
57
|
/>
|
|
61
58
|
);
|
|
62
59
|
}
|
|
63
60
|
|
|
64
|
-
function CardContent({ className, ...props }: React.ComponentProps<
|
|
65
|
-
return (
|
|
66
|
-
<div
|
|
67
|
-
data-slot="card-content"
|
|
68
|
-
className={cn("px-6", className)}
|
|
69
|
-
{...props}
|
|
70
|
-
/>
|
|
71
|
-
);
|
|
61
|
+
function CardContent({ className, ...props }: React.ComponentProps<'div'>) {
|
|
62
|
+
return <div data-slot="card-content" className={cn('px-6', className)} {...props} />;
|
|
72
63
|
}
|
|
73
64
|
|
|
74
|
-
function CardFooter({ className, ...props }: React.ComponentProps<
|
|
65
|
+
function CardFooter({ className, ...props }: React.ComponentProps<'div'>) {
|
|
75
66
|
return (
|
|
76
67
|
<div
|
|
77
68
|
data-slot="card-footer"
|
|
78
|
-
className={cn(
|
|
69
|
+
className={cn('flex items-center px-6 [.border-t]:pt-6', className)}
|
|
79
70
|
{...props}
|
|
80
71
|
/>
|
|
81
72
|
);
|
|
82
73
|
}
|
|
83
74
|
|
|
84
|
-
export {
|
|
85
|
-
Card,
|
|
86
|
-
CardHeader,
|
|
87
|
-
CardFooter,
|
|
88
|
-
CardTitle,
|
|
89
|
-
CardAction,
|
|
90
|
-
CardDescription,
|
|
91
|
-
CardContent,
|
|
92
|
-
};
|
|
75
|
+
export { Card, CardHeader, CardFooter, CardTitle, CardAction, CardDescription, CardContent };
|
|
@@ -1,19 +1,16 @@
|
|
|
1
|
-
import * as React from
|
|
2
|
-
import * as CheckboxPrimitive from
|
|
3
|
-
import { CheckIcon } from
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import * as CheckboxPrimitive from '@radix-ui/react-checkbox';
|
|
3
|
+
import { CheckIcon } from 'lucide-react';
|
|
4
4
|
|
|
5
|
-
import { cn } from
|
|
5
|
+
import { cn } from '@/lib/utils';
|
|
6
6
|
|
|
7
|
-
function Checkbox({
|
|
8
|
-
className,
|
|
9
|
-
...props
|
|
10
|
-
}: React.ComponentProps<typeof CheckboxPrimitive.Root>) {
|
|
7
|
+
function Checkbox({ className, ...props }: React.ComponentProps<typeof CheckboxPrimitive.Root>) {
|
|
11
8
|
return (
|
|
12
9
|
<CheckboxPrimitive.Root
|
|
13
10
|
data-slot="checkbox"
|
|
14
11
|
className={cn(
|
|
15
|
-
|
|
16
|
-
className
|
|
12
|
+
'peer border-input dark:bg-input/30 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground dark:data-[state=checked]:bg-primary data-[state=checked]:border-primary focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive size-4 shrink-0 rounded-[4px] border shadow-xs transition-shadow outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50',
|
|
13
|
+
className,
|
|
17
14
|
)}
|
|
18
15
|
{...props}
|
|
19
16
|
>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import * as React from
|
|
1
|
+
import * as React from 'react';
|
|
2
2
|
|
|
3
|
-
import { cn } from
|
|
3
|
+
import { cn } from '@/lib/utils';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* DateField — a styled `<input type="date">` wrapper matching the shadcn `Input`
|
|
@@ -18,30 +18,29 @@ import { cn } from "@/lib/utils";
|
|
|
18
18
|
* React 18.3: `React.forwardRef` so a forwarded ref reaches the underlying
|
|
19
19
|
* `<input>` (form libraries / focus management) and never warns.
|
|
20
20
|
*/
|
|
21
|
-
const DateField = React.forwardRef<
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
DateField.displayName = "DateField";
|
|
21
|
+
const DateField = React.forwardRef<HTMLInputElement, React.ComponentPropsWithoutRef<'input'>>(
|
|
22
|
+
({ className, type = 'date', ...props }, ref) => {
|
|
23
|
+
return (
|
|
24
|
+
<input
|
|
25
|
+
ref={ref}
|
|
26
|
+
type={type}
|
|
27
|
+
data-slot="date-field"
|
|
28
|
+
className={cn(
|
|
29
|
+
'border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none tabular-nums md:text-sm',
|
|
30
|
+
'placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground',
|
|
31
|
+
'disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50',
|
|
32
|
+
'focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]',
|
|
33
|
+
'aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive',
|
|
34
|
+
// The native calendar-picker glyph: tint to the muted ink, brighten on
|
|
35
|
+
// hover, and invert in dark mode so it stays visible on the dark field.
|
|
36
|
+
'[&::-webkit-calendar-picker-indicator]:cursor-pointer [&::-webkit-calendar-picker-indicator]:opacity-60 [&::-webkit-calendar-picker-indicator]:hover:opacity-100 dark:[&::-webkit-calendar-picker-indicator]:invert',
|
|
37
|
+
className,
|
|
38
|
+
)}
|
|
39
|
+
{...props}
|
|
40
|
+
/>
|
|
41
|
+
);
|
|
42
|
+
},
|
|
43
|
+
);
|
|
44
|
+
DateField.displayName = 'DateField';
|
|
46
45
|
|
|
47
46
|
export { DateField };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { cn } from
|
|
2
|
-
import * as DialogPrimitive from
|
|
3
|
-
import { XIcon } from
|
|
4
|
-
import * as React from
|
|
1
|
+
import { cn } from '@/lib/utils';
|
|
2
|
+
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
3
|
+
import { XIcon } from 'lucide-react';
|
|
4
|
+
import * as React from 'react';
|
|
5
5
|
|
|
6
6
|
// Context to track composition state across dialog children
|
|
7
7
|
const DialogCompositionContext = React.createContext<{
|
|
@@ -16,12 +16,9 @@ const DialogCompositionContext = React.createContext<{
|
|
|
16
16
|
markCompositionEnd: () => {},
|
|
17
17
|
});
|
|
18
18
|
|
|
19
|
-
export const useDialogComposition = () =>
|
|
20
|
-
React.useContext(DialogCompositionContext);
|
|
19
|
+
export const useDialogComposition = () => React.useContext(DialogCompositionContext);
|
|
21
20
|
|
|
22
|
-
function Dialog({
|
|
23
|
-
...props
|
|
24
|
-
}: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
|
21
|
+
function Dialog({ ...props }: React.ComponentProps<typeof DialogPrimitive.Root>) {
|
|
25
22
|
const composingRef = React.useRef(false);
|
|
26
23
|
const justEndedRef = React.useRef(false);
|
|
27
24
|
const endTimerRef = React.useRef<ReturnType<typeof setTimeout> | null>(null);
|
|
@@ -43,7 +40,7 @@ function Dialog({
|
|
|
43
40
|
}, 150);
|
|
44
41
|
},
|
|
45
42
|
}),
|
|
46
|
-
[]
|
|
43
|
+
[],
|
|
47
44
|
);
|
|
48
45
|
|
|
49
46
|
return (
|
|
@@ -53,21 +50,15 @@ function Dialog({
|
|
|
53
50
|
);
|
|
54
51
|
}
|
|
55
52
|
|
|
56
|
-
function DialogTrigger({
|
|
57
|
-
...props
|
|
58
|
-
}: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
|
|
53
|
+
function DialogTrigger({ ...props }: React.ComponentProps<typeof DialogPrimitive.Trigger>) {
|
|
59
54
|
return <DialogPrimitive.Trigger data-slot="dialog-trigger" {...props} />;
|
|
60
55
|
}
|
|
61
56
|
|
|
62
|
-
function DialogPortal({
|
|
63
|
-
...props
|
|
64
|
-
}: React.ComponentProps<typeof DialogPrimitive.Portal>) {
|
|
57
|
+
function DialogPortal({ ...props }: React.ComponentProps<typeof DialogPrimitive.Portal>) {
|
|
65
58
|
return <DialogPrimitive.Portal data-slot="dialog-portal" {...props} />;
|
|
66
59
|
}
|
|
67
60
|
|
|
68
|
-
function DialogClose({
|
|
69
|
-
...props
|
|
70
|
-
}: React.ComponentProps<typeof DialogPrimitive.Close>) {
|
|
61
|
+
function DialogClose({ ...props }: React.ComponentProps<typeof DialogPrimitive.Close>) {
|
|
71
62
|
return <DialogPrimitive.Close data-slot="dialog-close" {...props} />;
|
|
72
63
|
}
|
|
73
64
|
|
|
@@ -84,15 +75,15 @@ const DialogOverlay = React.forwardRef<
|
|
|
84
75
|
ref={ref}
|
|
85
76
|
data-slot="dialog-overlay"
|
|
86
77
|
className={cn(
|
|
87
|
-
|
|
88
|
-
className
|
|
78
|
+
'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',
|
|
79
|
+
className,
|
|
89
80
|
)}
|
|
90
81
|
{...props}
|
|
91
82
|
/>
|
|
92
83
|
);
|
|
93
84
|
});
|
|
94
85
|
|
|
95
|
-
DialogOverlay.displayName =
|
|
86
|
+
DialogOverlay.displayName = 'DialogOverlay';
|
|
96
87
|
|
|
97
88
|
function DialogContent({
|
|
98
89
|
className,
|
|
@@ -120,7 +111,7 @@ function DialogContent({
|
|
|
120
111
|
// Call user's onEscapeKeyDown if provided
|
|
121
112
|
onEscapeKeyDown?.(e);
|
|
122
113
|
},
|
|
123
|
-
[isComposing, onEscapeKeyDown]
|
|
114
|
+
[isComposing, onEscapeKeyDown],
|
|
124
115
|
);
|
|
125
116
|
|
|
126
117
|
return (
|
|
@@ -129,8 +120,8 @@ function DialogContent({
|
|
|
129
120
|
<DialogPrimitive.Content
|
|
130
121
|
data-slot="dialog-content"
|
|
131
122
|
className={cn(
|
|
132
|
-
|
|
133
|
-
className
|
|
123
|
+
'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(100vw-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg',
|
|
124
|
+
className,
|
|
134
125
|
)}
|
|
135
126
|
onEscapeKeyDown={handleEscapeKeyDown}
|
|
136
127
|
{...props}
|
|
@@ -150,37 +141,31 @@ function DialogContent({
|
|
|
150
141
|
);
|
|
151
142
|
}
|
|
152
143
|
|
|
153
|
-
function DialogHeader({ className, ...props }: React.ComponentProps<
|
|
144
|
+
function DialogHeader({ className, ...props }: React.ComponentProps<'div'>) {
|
|
154
145
|
return (
|
|
155
146
|
<div
|
|
156
147
|
data-slot="dialog-header"
|
|
157
|
-
className={cn(
|
|
148
|
+
className={cn('flex flex-col gap-2 text-center sm:text-left', className)}
|
|
158
149
|
{...props}
|
|
159
150
|
/>
|
|
160
151
|
);
|
|
161
152
|
}
|
|
162
153
|
|
|
163
|
-
function DialogFooter({ className, ...props }: React.ComponentProps<
|
|
154
|
+
function DialogFooter({ className, ...props }: React.ComponentProps<'div'>) {
|
|
164
155
|
return (
|
|
165
156
|
<div
|
|
166
157
|
data-slot="dialog-footer"
|
|
167
|
-
className={cn(
|
|
168
|
-
"flex flex-col-reverse gap-2 sm:flex-row sm:justify-end",
|
|
169
|
-
className
|
|
170
|
-
)}
|
|
158
|
+
className={cn('flex flex-col-reverse gap-2 sm:flex-row sm:justify-end', className)}
|
|
171
159
|
{...props}
|
|
172
160
|
/>
|
|
173
161
|
);
|
|
174
162
|
}
|
|
175
163
|
|
|
176
|
-
function DialogTitle({
|
|
177
|
-
className,
|
|
178
|
-
...props
|
|
179
|
-
}: React.ComponentProps<typeof DialogPrimitive.Title>) {
|
|
164
|
+
function DialogTitle({ className, ...props }: React.ComponentProps<typeof DialogPrimitive.Title>) {
|
|
180
165
|
return (
|
|
181
166
|
<DialogPrimitive.Title
|
|
182
167
|
data-slot="dialog-title"
|
|
183
|
-
className={cn(
|
|
168
|
+
className={cn('text-lg leading-none font-semibold', className)}
|
|
184
169
|
{...props}
|
|
185
170
|
/>
|
|
186
171
|
);
|
|
@@ -193,7 +178,7 @@ function DialogDescription({
|
|
|
193
178
|
return (
|
|
194
179
|
<DialogPrimitive.Description
|
|
195
180
|
data-slot="dialog-description"
|
|
196
|
-
className={cn(
|
|
181
|
+
className={cn('text-muted-foreground text-sm', className)}
|
|
197
182
|
{...props}
|
|
198
183
|
/>
|
|
199
184
|
);
|
|
@@ -209,6 +194,5 @@ export {
|
|
|
209
194
|
DialogOverlay,
|
|
210
195
|
DialogPortal,
|
|
211
196
|
DialogTitle,
|
|
212
|
-
DialogTrigger
|
|
197
|
+
DialogTrigger,
|
|
213
198
|
};
|
|
214
|
-
|
|
@@ -1,32 +1,23 @@
|
|
|
1
|
-
import * as React from
|
|
2
|
-
import * as DropdownMenuPrimitive from
|
|
3
|
-
import { CheckIcon, ChevronRightIcon, CircleIcon } from
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
|
|
3
|
+
import { CheckIcon, ChevronRightIcon, CircleIcon } from 'lucide-react';
|
|
4
4
|
|
|
5
|
-
import { cn } from
|
|
5
|
+
import { cn } from '@/lib/utils';
|
|
6
6
|
|
|
7
|
-
function DropdownMenu({
|
|
8
|
-
...props
|
|
9
|
-
}: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {
|
|
7
|
+
function DropdownMenu({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {
|
|
10
8
|
return <DropdownMenuPrimitive.Root data-slot="dropdown-menu" {...props} />;
|
|
11
9
|
}
|
|
12
10
|
|
|
13
11
|
function DropdownMenuPortal({
|
|
14
12
|
...props
|
|
15
13
|
}: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) {
|
|
16
|
-
return
|
|
17
|
-
<DropdownMenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} />
|
|
18
|
-
);
|
|
14
|
+
return <DropdownMenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} />;
|
|
19
15
|
}
|
|
20
16
|
|
|
21
17
|
function DropdownMenuTrigger({
|
|
22
18
|
...props
|
|
23
19
|
}: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>) {
|
|
24
|
-
return
|
|
25
|
-
<DropdownMenuPrimitive.Trigger
|
|
26
|
-
data-slot="dropdown-menu-trigger"
|
|
27
|
-
{...props}
|
|
28
|
-
/>
|
|
29
|
-
);
|
|
20
|
+
return <DropdownMenuPrimitive.Trigger data-slot="dropdown-menu-trigger" {...props} />;
|
|
30
21
|
}
|
|
31
22
|
|
|
32
23
|
function DropdownMenuContent({
|
|
@@ -40,8 +31,8 @@ function DropdownMenuContent({
|
|
|
40
31
|
data-slot="dropdown-menu-content"
|
|
41
32
|
sideOffset={sideOffset}
|
|
42
33
|
className={cn(
|
|
43
|
-
|
|
44
|
-
className
|
|
34
|
+
'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 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md',
|
|
35
|
+
className,
|
|
45
36
|
)}
|
|
46
37
|
{...props}
|
|
47
38
|
/>
|
|
@@ -49,22 +40,18 @@ function DropdownMenuContent({
|
|
|
49
40
|
);
|
|
50
41
|
}
|
|
51
42
|
|
|
52
|
-
function DropdownMenuGroup({
|
|
53
|
-
...props
|
|
54
|
-
}: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {
|
|
55
|
-
return (
|
|
56
|
-
<DropdownMenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />
|
|
57
|
-
);
|
|
43
|
+
function DropdownMenuGroup({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {
|
|
44
|
+
return <DropdownMenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />;
|
|
58
45
|
}
|
|
59
46
|
|
|
60
47
|
function DropdownMenuItem({
|
|
61
48
|
className,
|
|
62
49
|
inset,
|
|
63
|
-
variant =
|
|
50
|
+
variant = 'default',
|
|
64
51
|
...props
|
|
65
52
|
}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {
|
|
66
53
|
inset?: boolean;
|
|
67
|
-
variant?:
|
|
54
|
+
variant?: 'default' | 'destructive';
|
|
68
55
|
}) {
|
|
69
56
|
return (
|
|
70
57
|
<DropdownMenuPrimitive.Item
|
|
@@ -73,7 +60,7 @@ function DropdownMenuItem({
|
|
|
73
60
|
data-variant={variant}
|
|
74
61
|
className={cn(
|
|
75
62
|
"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",
|
|
76
|
-
className
|
|
63
|
+
className,
|
|
77
64
|
)}
|
|
78
65
|
{...props}
|
|
79
66
|
/>
|
|
@@ -91,7 +78,7 @@ function DropdownMenuCheckboxItem({
|
|
|
91
78
|
data-slot="dropdown-menu-checkbox-item"
|
|
92
79
|
className={cn(
|
|
93
80
|
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm 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",
|
|
94
|
-
className
|
|
81
|
+
className,
|
|
95
82
|
)}
|
|
96
83
|
checked={checked}
|
|
97
84
|
{...props}
|
|
@@ -109,12 +96,7 @@ function DropdownMenuCheckboxItem({
|
|
|
109
96
|
function DropdownMenuRadioGroup({
|
|
110
97
|
...props
|
|
111
98
|
}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>) {
|
|
112
|
-
return
|
|
113
|
-
<DropdownMenuPrimitive.RadioGroup
|
|
114
|
-
data-slot="dropdown-menu-radio-group"
|
|
115
|
-
{...props}
|
|
116
|
-
/>
|
|
117
|
-
);
|
|
99
|
+
return <DropdownMenuPrimitive.RadioGroup data-slot="dropdown-menu-radio-group" {...props} />;
|
|
118
100
|
}
|
|
119
101
|
|
|
120
102
|
function DropdownMenuRadioItem({
|
|
@@ -127,7 +109,7 @@ function DropdownMenuRadioItem({
|
|
|
127
109
|
data-slot="dropdown-menu-radio-item"
|
|
128
110
|
className={cn(
|
|
129
111
|
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm 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",
|
|
130
|
-
className
|
|
112
|
+
className,
|
|
131
113
|
)}
|
|
132
114
|
{...props}
|
|
133
115
|
>
|
|
@@ -152,10 +134,7 @@ function DropdownMenuLabel({
|
|
|
152
134
|
<DropdownMenuPrimitive.Label
|
|
153
135
|
data-slot="dropdown-menu-label"
|
|
154
136
|
data-inset={inset}
|
|
155
|
-
className={cn(
|
|
156
|
-
"px-2 py-1.5 text-sm font-medium data-[inset]:pl-8",
|
|
157
|
-
className
|
|
158
|
-
)}
|
|
137
|
+
className={cn('px-2 py-1.5 text-sm font-medium data-[inset]:pl-8', className)}
|
|
159
138
|
{...props}
|
|
160
139
|
/>
|
|
161
140
|
);
|
|
@@ -168,31 +147,23 @@ function DropdownMenuSeparator({
|
|
|
168
147
|
return (
|
|
169
148
|
<DropdownMenuPrimitive.Separator
|
|
170
149
|
data-slot="dropdown-menu-separator"
|
|
171
|
-
className={cn(
|
|
150
|
+
className={cn('bg-border -mx-1 my-1 h-px', className)}
|
|
172
151
|
{...props}
|
|
173
152
|
/>
|
|
174
153
|
);
|
|
175
154
|
}
|
|
176
155
|
|
|
177
|
-
function DropdownMenuShortcut({
|
|
178
|
-
className,
|
|
179
|
-
...props
|
|
180
|
-
}: React.ComponentProps<"span">) {
|
|
156
|
+
function DropdownMenuShortcut({ className, ...props }: React.ComponentProps<'span'>) {
|
|
181
157
|
return (
|
|
182
158
|
<span
|
|
183
159
|
data-slot="dropdown-menu-shortcut"
|
|
184
|
-
className={cn(
|
|
185
|
-
"text-muted-foreground ml-auto text-xs tracking-widest",
|
|
186
|
-
className
|
|
187
|
-
)}
|
|
160
|
+
className={cn('text-muted-foreground ml-auto text-xs tracking-widest', className)}
|
|
188
161
|
{...props}
|
|
189
162
|
/>
|
|
190
163
|
);
|
|
191
164
|
}
|
|
192
165
|
|
|
193
|
-
function DropdownMenuSub({
|
|
194
|
-
...props
|
|
195
|
-
}: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {
|
|
166
|
+
function DropdownMenuSub({ ...props }: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {
|
|
196
167
|
return <DropdownMenuPrimitive.Sub data-slot="dropdown-menu-sub" {...props} />;
|
|
197
168
|
}
|
|
198
169
|
|
|
@@ -210,7 +181,7 @@ function DropdownMenuSubTrigger({
|
|
|
210
181
|
data-inset={inset}
|
|
211
182
|
className={cn(
|
|
212
183
|
"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
213
|
-
className
|
|
184
|
+
className,
|
|
214
185
|
)}
|
|
215
186
|
{...props}
|
|
216
187
|
>
|
|
@@ -228,8 +199,8 @@ function DropdownMenuSubContent({
|
|
|
228
199
|
<DropdownMenuPrimitive.SubContent
|
|
229
200
|
data-slot="dropdown-menu-sub-content"
|
|
230
201
|
className={cn(
|
|
231
|
-
|
|
232
|
-
className
|
|
202
|
+
'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-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg',
|
|
203
|
+
className,
|
|
233
204
|
)}
|
|
234
205
|
{...props}
|
|
235
206
|
/>
|
|
@@ -16,10 +16,7 @@ const InputOTP = React.forwardRef<
|
|
|
16
16
|
<OTPInput
|
|
17
17
|
ref={ref}
|
|
18
18
|
data-slot="input-otp"
|
|
19
|
-
containerClassName={cn(
|
|
20
|
-
'flex items-center gap-2 has-disabled:opacity-50',
|
|
21
|
-
containerClassName,
|
|
22
|
-
)}
|
|
19
|
+
containerClassName={cn('flex items-center gap-2 has-disabled:opacity-50', containerClassName)}
|
|
23
20
|
className={cn('disabled:cursor-not-allowed', className)}
|
|
24
21
|
{...props}
|
|
25
22
|
/>
|