@flowselections/core 1.0.26 → 1.0.27
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 +18 -3
- package/dist/components/layout/BrandLogo.d.ts +9 -0
- package/dist/components/layout/BrandLogo.d.ts.map +1 -0
- package/dist/components/layout/BrandLogo.js +12 -0
- package/dist/components/layout/BugsDialog.js +4 -4
- package/dist/components/layout/LoginPage.d.ts +6 -1
- package/dist/components/layout/LoginPage.d.ts.map +1 -1
- package/dist/components/layout/LoginPage.js +11 -5
- package/dist/components/layout/NotificationBell.js +1 -1
- package/dist/components/layout/ResetWachtwoordPage.js +1 -1
- package/dist/components/layout/Sidebar.d.ts +1 -1
- package/dist/components/layout/Sidebar.d.ts.map +1 -1
- package/dist/components/layout/Sidebar.js +4 -3
- package/dist/components/ui/alert.js +1 -1
- package/dist/components/ui/badge.d.ts +1 -1
- package/dist/components/ui/badge.d.ts.map +1 -1
- package/dist/components/ui/badge.js +5 -2
- package/dist/components/ui/button.js +5 -5
- package/dist/components/ui/calendar.js +1 -1
- package/dist/components/ui/card.js +1 -1
- package/dist/components/ui/checkbox.js +1 -1
- package/dist/components/ui/input-otp.js +1 -1
- package/dist/components/ui/input.js +1 -1
- package/dist/components/ui/menubar.js +1 -1
- package/dist/components/ui/navigation-menu.js +1 -1
- package/dist/components/ui/radio-group.js +1 -1
- package/dist/components/ui/resizable.js +1 -1
- package/dist/components/ui/select.js +1 -1
- package/dist/components/ui/sidebar.js +3 -3
- package/dist/components/ui/slider.js +1 -1
- package/dist/components/ui/sonner.js +1 -1
- package/dist/components/ui/switch.js +1 -1
- package/dist/components/ui/tabs.js +1 -1
- package/dist/components/ui/textarea.js +1 -1
- package/dist/components/ui/toggle.js +2 -2
- package/dist/extensions/ShellExtensions.d.ts +15 -4
- package/dist/extensions/ShellExtensions.d.ts.map +1 -1
- package/dist/extensions/ShellExtensions.js +6 -3
- package/dist/hooks/useLogoSrc.d.ts +3 -3
- package/dist/hooks/useLogoSrc.d.ts.map +1 -1
- package/dist/hooks/useLogoSrc.js +4 -25
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/permissions/ModuleAccessGuard.js +1 -1
- package/dist/routes/index.d.ts +63 -6
- package/dist/routes/index.d.ts.map +1 -1
- package/dist/routes/index.js +17 -4
- package/dist/styles/brand-default.css +55 -0
- package/dist/styles.css +33 -42
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -80,6 +80,12 @@ Pipeline-volgorde is de array-volgorde: **eerst rechten filteren, dan sorteren.*
|
|
|
80
80
|
Meegegeven hooks moeten stabiele referenties zijn (module-scope functies, geen
|
|
81
81
|
inline lambdas), zodat de hook-volgorde tussen renders nooit verandert.
|
|
82
82
|
|
|
83
|
+
Elke transform ontvangt `(modules, { allModules })`: `modules` is de actuele
|
|
84
|
+
pipeline-uitkomst en `allModules` is altijd de ongefilterde shell-lijst. Een
|
|
85
|
+
transform moet puur op basis van deze input werken en mag geen side-effects
|
|
86
|
+
hebben: geen synchronisatie, schrijfacties of andere mutaties buiten zijn
|
|
87
|
+
retourwaarde.
|
|
88
|
+
|
|
83
89
|
Bij laden, een ontbrekende tabel/RPC of een fout in een transform komt de lijst
|
|
84
90
|
**ongewijzigd** terug. Een lege zijbalk is nooit een geldige uitkomst.
|
|
85
91
|
|
|
@@ -166,9 +172,18 @@ erop leunen: ze kunnen nu echt 403 geven.
|
|
|
166
172
|
|
|
167
173
|
### Huisstijl
|
|
168
174
|
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
175
|
+
Flora Select is de standaardhuisstijl. De tokens staan in
|
|
176
|
+
`src/core/styles/brand-default.css` en worden via `@flowselections/core/styles.css`
|
|
177
|
+
geladen; een latere `src/brand.generated.css` van de shell overschrijft dezelfde
|
|
178
|
+
variabelen. Alle statuskleuren hebben een vol en zacht paar. Inter is de
|
|
179
|
+
interfaceletter, Fraunces is voor login en lege toestanden en JetBrains Mono voor
|
|
180
|
+
codes. Logo: `logoSrc`-prop, anders `/brand/logo-wit.svg`; login gebruikt
|
|
181
|
+
`/brand/logo.svg`. Een ontbrekend bestand valt terug op het tekstlogo.
|
|
182
|
+
Shells laden de fontstylesheet in hun root head:
|
|
183
|
+
|
|
184
|
+
```text
|
|
185
|
+
https://fonts.googleapis.com/css2?family=Fraunces:opsz,wght,SOFT@9..144,600..800,0..100&family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@400;500&display=swap
|
|
186
|
+
```
|
|
172
187
|
|
|
173
188
|
## Systeemroutes (`@flowselections/core/routes`, vanaf 1.0.23)
|
|
174
189
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
interface BrandLogoProps {
|
|
2
|
+
src: string;
|
|
3
|
+
className?: string;
|
|
4
|
+
fallbackClassName?: string;
|
|
5
|
+
}
|
|
6
|
+
/** Toont nooit een kapotte afbeelding: bij een ontbrekend shell-logo verschijnt het tekstlogo. */
|
|
7
|
+
export declare function BrandLogo({ src, className, fallbackClassName }: BrandLogoProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=BrandLogo.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BrandLogo.d.ts","sourceRoot":"","sources":["../../../src/core/components/layout/BrandLogo.tsx"],"names":[],"mappings":"AAGA,UAAU,cAAc;IACtB,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,kGAAkG;AAClG,wBAAgB,SAAS,CAAC,EAAE,GAAG,EAAE,SAAS,EAAE,iBAAiB,EAAE,EAAE,cAAc,2CAa9E"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from "react";
|
|
3
|
+
import { cn } from "../../lib/utils.js";
|
|
4
|
+
/** Toont nooit een kapotte afbeelding: bij een ontbrekend shell-logo verschijnt het tekstlogo. */
|
|
5
|
+
export function BrandLogo({ src, className, fallbackClassName }) {
|
|
6
|
+
const [failedSrc, setFailedSrc] = useState(null);
|
|
7
|
+
const failed = failedSrc === src;
|
|
8
|
+
if (failed) {
|
|
9
|
+
return (_jsx("span", { className: cn("text-xl font-bold", fallbackClassName), children: "Flora Select" }));
|
|
10
|
+
}
|
|
11
|
+
return _jsx("img", { src: src, alt: "Flora Select", className: className, onError: () => setFailedSrc(src) });
|
|
12
|
+
}
|
|
@@ -14,8 +14,8 @@ import { toast } from "sonner";
|
|
|
14
14
|
import { bugReportSchema, validateFileUpload, ALLOWED_FILE_TYPES } from "../../lib/validationSchemas.js";
|
|
15
15
|
const statusConfig = {
|
|
16
16
|
open: { label: "Open", variant: "destructive" },
|
|
17
|
-
in_progress: { label: "In behandeling", variant: "
|
|
18
|
-
resolved: { label: "Opgelost", variant: "
|
|
17
|
+
in_progress: { label: "In behandeling", variant: "info" },
|
|
18
|
+
resolved: { label: "Opgelost", variant: "success" },
|
|
19
19
|
};
|
|
20
20
|
export function BugsDialog({ open, onOpenChange }) {
|
|
21
21
|
const [bugs, setBugs] = useState([]);
|
|
@@ -141,8 +141,8 @@ export function BugsDialog({ open, onOpenChange }) {
|
|
|
141
141
|
});
|
|
142
142
|
};
|
|
143
143
|
const acceptString = ALLOWED_FILE_TYPES.join(",");
|
|
144
|
-
return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { className: "max-w-2xl max-h-[85vh] overflow-hidden flex flex-col", children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: "Bugs" }) }), _jsxs(Tabs, { value: activeTab, onValueChange: setActiveTab, className: "flex-1 flex flex-col overflow-hidden", children: [_jsxs(TabsList, { className: "grid w-full grid-cols-2", children: [_jsxs(TabsTrigger, { value: "list", children: ["Overzicht (", bugs.filter(b => b.status !== "resolved").length, ")"] }), _jsxs(TabsTrigger, { value: "new", children: [_jsx(Plus, { className: "mr-2 h-4 w-4" }), "Nieuwe Bug"] })] }), _jsx(TabsContent, { value: "list", className: "flex-1 overflow-y-auto mt-4", children: loading ? (_jsx("div", { className: "flex items-center justify-center py-8", children: _jsx(Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" }) })) : bugs.length === 0 ? (_jsx("div", { className: "text-center py-8 text-muted-foreground", children: "Geen bugs gemeld \uD83C\uDF89" })) : (_jsx("div", { className: "space-y-3", children: bugs.map((bug) => {
|
|
144
|
+
return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { className: "max-w-2xl max-h-[85vh] overflow-hidden flex flex-col", children: [_jsx(DialogHeader, { children: _jsx(DialogTitle, { children: "Bugs" }) }), _jsxs(Tabs, { value: activeTab, onValueChange: setActiveTab, className: "flex-1 flex flex-col overflow-hidden", children: [_jsxs(TabsList, { className: "grid w-full grid-cols-2", children: [_jsxs(TabsTrigger, { value: "list", children: ["Overzicht (", bugs.filter(b => b.status !== "resolved").length, ")"] }), _jsxs(TabsTrigger, { value: "new", children: [_jsx(Plus, { className: "mr-2 h-4 w-4" }), "Nieuwe Bug"] })] }), _jsx(TabsContent, { value: "list", className: "flex-1 overflow-y-auto mt-4", children: loading ? (_jsx("div", { className: "flex items-center justify-center py-8", children: _jsx(Loader2, { className: "h-6 w-6 animate-spin text-muted-foreground" }) })) : bugs.length === 0 ? (_jsx("div", { "data-empty-state": true, className: "text-center py-8 text-muted-foreground", children: "Geen bugs gemeld \uD83C\uDF89" })) : (_jsx("div", { className: "space-y-3", children: bugs.map((bug) => {
|
|
145
145
|
const status = statusConfig[bug.status] || statusConfig.open;
|
|
146
|
-
return (_jsxs("div", { className: "rounded-lg border border-border p-4 space-y-2", children: [_jsxs("div", { className: "flex items-start justify-between gap-2", children: [_jsxs("div", { className: "flex-1", children: [_jsx("h4", { className: "font-medium", children: bug.title }), _jsx("p", { className: "text-sm text-muted-foreground mt-1", children: bug.description }), bug.attachment_url && (_jsxs("a", { href: bug.attachment_url, target: "_blank", rel: "noopener noreferrer", className: "inline-flex items-center gap-1 text-xs text-primary hover:underline mt-2", children: [_jsx(FileText, { className: "h-3 w-3" }), "Bijlage bekijken"] }))] }), _jsx(Button, { variant: "ghost", size: "icon", className: "shrink-0", onClick: () => handleDelete(bug.id), children: _jsx(Trash2, { className: "h-4 w-4" }) })] }), _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs(Select, { value: bug.status, onValueChange: (value) => handleUpdateStatus(bug.id, value), children: [_jsx(SelectTrigger, { className: "h-7 w-auto", children: _jsx(Badge, { variant: status.variant, children: status.label }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "open", children: _jsx(Badge, { variant: "destructive", children: "Open" }) }), _jsx(SelectItem, { value: "in_progress", children: _jsx(Badge, { variant: "
|
|
146
|
+
return (_jsxs("div", { className: "rounded-lg border border-border p-4 space-y-2", children: [_jsxs("div", { className: "flex items-start justify-between gap-2", children: [_jsxs("div", { className: "flex-1", children: [_jsx("h4", { className: "font-medium", children: bug.title }), _jsx("p", { className: "text-sm text-muted-foreground mt-1", children: bug.description }), bug.attachment_url && (_jsxs("a", { href: bug.attachment_url, target: "_blank", rel: "noopener noreferrer", className: "inline-flex items-center gap-1 text-xs text-primary hover:underline mt-2", children: [_jsx(FileText, { className: "h-3 w-3" }), "Bijlage bekijken"] }))] }), _jsx(Button, { variant: "ghost", size: "icon", className: "shrink-0", onClick: () => handleDelete(bug.id), children: _jsx(Trash2, { className: "h-4 w-4" }) })] }), _jsxs("div", { className: "flex items-center justify-between", children: [_jsxs(Select, { value: bug.status, onValueChange: (value) => handleUpdateStatus(bug.id, value), children: [_jsx(SelectTrigger, { className: "h-7 w-auto", children: _jsx(Badge, { variant: status.variant, children: status.label }) }), _jsxs(SelectContent, { children: [_jsx(SelectItem, { value: "open", children: _jsx(Badge, { variant: "destructive", children: "Open" }) }), _jsx(SelectItem, { value: "in_progress", children: _jsx(Badge, { variant: "info", children: "In behandeling" }) }), _jsx(SelectItem, { value: "resolved", children: _jsx(Badge, { variant: "success", children: "Opgelost" }) })] })] }), _jsx("span", { className: "text-xs text-muted-foreground", children: formatDate(bug.created_at) })] })] }, bug.id));
|
|
147
147
|
}) })) }), _jsx(TabsContent, { value: "new", className: "flex-1 overflow-y-auto mt-4", children: _jsxs("div", { className: "space-y-4", children: [_jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "bug-title", children: "Titel" }), _jsx(Input, { id: "bug-title", placeholder: "Korte beschrijving van de bug...", value: title, onChange: (e) => setTitle(e.target.value), maxLength: 200 })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "bug-description", children: "Beschrijving" }), _jsx(Textarea, { id: "bug-description", placeholder: "Beschrijf de bug in detail. Wat ging er mis? Wat verwachtte je?", value: description, onChange: (e) => setDescription(e.target.value), rows: 4, maxLength: 5000 })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { children: "Bijlage (optioneel)" }), _jsx("input", { type: "file", ref: fileInputRef, onChange: handleFileChange, className: "hidden", accept: acceptString }), attachment ? (_jsxs("div", { className: "flex items-center gap-2 p-2 border rounded-md bg-muted/50", children: [_jsx(FileText, { className: "h-4 w-4 text-muted-foreground" }), _jsx("span", { className: "text-sm flex-1 truncate", children: attachment.name }), _jsx(Button, { type: "button", variant: "ghost", size: "icon", className: "h-6 w-6", onClick: removeAttachment, children: _jsx(X, { className: "h-4 w-4" }) })] })) : (_jsxs(Button, { type: "button", variant: "outline", className: "w-full", onClick: () => fileInputRef.current?.click(), children: [_jsx(Paperclip, { className: "mr-2 h-4 w-4" }), "Document toevoegen (max 10MB)"] })), _jsx("p", { className: "text-xs text-muted-foreground", children: "Toegestane bestandstypen: PNG, JPEG, GIF, PDF" })] }), _jsx(Button, { onClick: handleSubmit, disabled: submitting || !title.trim() || !description.trim(), className: "w-full", children: submitting ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), "Melden..."] })) : (_jsxs(_Fragment, { children: [_jsx(CheckCircle, { className: "mr-2 h-4 w-4" }), "Bug Melden"] })) })] }) })] })] }) }));
|
|
148
148
|
}
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
interface LoginPageProps {
|
|
2
2
|
/** Pad waarnaar wordt genavigeerd na succesvol inloggen. */
|
|
3
3
|
redirectTo?: string;
|
|
4
|
+
/**
|
|
5
|
+
* De route-factory handelt de redirect af via `beforeLoad`. Eigen loginroutes
|
|
6
|
+
* laten dit weg en gebruiken de veilige fallback van deze pagina.
|
|
7
|
+
*/
|
|
8
|
+
routeHandlesRedirect?: boolean;
|
|
4
9
|
}
|
|
5
|
-
export declare function LoginPage({ redirectTo }: LoginPageProps): import("react/jsx-runtime").JSX.Element;
|
|
10
|
+
export declare function LoginPage({ redirectTo, routeHandlesRedirect }: LoginPageProps): import("react/jsx-runtime").JSX.Element;
|
|
6
11
|
export {};
|
|
7
12
|
//# sourceMappingURL=LoginPage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LoginPage.d.ts","sourceRoot":"","sources":["../../../src/core/components/layout/LoginPage.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"LoginPage.d.ts","sourceRoot":"","sources":["../../../src/core/components/layout/LoginPage.tsx"],"names":[],"mappings":"AAYA,UAAU,cAAc;IACtB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;OAGG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAED,wBAAgB,SAAS,CAAC,EAAE,UAA4B,EAAE,oBAA4B,EAAE,EAAE,cAAc,2CAsIvG"}
|
|
@@ -9,7 +9,8 @@ import { toast } from "sonner";
|
|
|
9
9
|
import { loginSchema } from "../../lib/validationSchemas.js";
|
|
10
10
|
import { supabase } from "../../supabase/client.js";
|
|
11
11
|
import { readRedirectParam } from "../../auth/redirect.js";
|
|
12
|
-
|
|
12
|
+
import { BrandLogo } from "./BrandLogo.js";
|
|
13
|
+
export function LoginPage({ redirectTo = "/instellingen", routeHandlesRedirect = false }) {
|
|
13
14
|
const router = useRouter();
|
|
14
15
|
const [email, setEmail] = useState("");
|
|
15
16
|
const [password, setPassword] = useState("");
|
|
@@ -34,6 +35,8 @@ export function LoginPage({ redirectTo = "/instellingen" }) {
|
|
|
34
35
|
toast.error(validation.error.issues[0].message);
|
|
35
36
|
return;
|
|
36
37
|
}
|
|
38
|
+
// Vóór signIn lezen: de root-invalidate kan de login-search meteen opruimen.
|
|
39
|
+
const target = readRedirectParam(redirectTo);
|
|
37
40
|
setIsLoading(true);
|
|
38
41
|
const { error } = await supabase.auth.signInWithPassword({ email, password });
|
|
39
42
|
if (error) {
|
|
@@ -46,8 +49,11 @@ export function LoginPage({ redirectTo = "/instellingen" }) {
|
|
|
46
49
|
// Geen window.location.href-fallback: een volledige load laat de guard
|
|
47
50
|
// opnieuw beslissen; de root-invalidate pakt de sessie alsnog op.
|
|
48
51
|
await waitForAuthContext();
|
|
49
|
-
|
|
50
|
-
|
|
52
|
+
// loginRoute.beforeLoad is leidend en voorkomt een tweede, concurrerende
|
|
53
|
+
// navigatie. Alleen een eigen loginroute krijgt deze compatibiliteitsfallback.
|
|
54
|
+
if (!routeHandlesRedirect && router.state.location.pathname === "/login") {
|
|
55
|
+
await router.navigate({ href: target, replace: true });
|
|
56
|
+
}
|
|
51
57
|
setIsLoading(false);
|
|
52
58
|
};
|
|
53
59
|
const handleForgotPassword = async (e) => {
|
|
@@ -70,7 +76,7 @@ export function LoginPage({ redirectTo = "/instellingen" }) {
|
|
|
70
76
|
}
|
|
71
77
|
};
|
|
72
78
|
if (showForgot) {
|
|
73
|
-
return (_jsx("div", { className: "min-h-screen flex items-center justify-center bg-background p-4", children: _jsxs(Card, { className: "w-full max-w-md", children: [_jsxs(CardHeader, { className: "text-center", children: [_jsx(CardTitle, { className: "text-2xl", children: "Wachtwoord vergeten" }), _jsx(CardDescription, { children: "Vul je e-mailadres in om een reset-link te ontvangen" })] }), _jsxs("form", { onSubmit: handleForgotPassword, children: [_jsx(CardContent, { className: "space-y-4", children: _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "forgot-email", children: "E-mailadres" }), _jsx(Input, { id: "forgot-email", type: "email", placeholder: "naam@bedrijf.nl", value: forgotEmail, onChange: (e) => setForgotEmail(e.target.value), required: true, maxLength: 255 })] }) }), _jsxs(CardFooter, { className: "flex flex-col gap-4", children: [_jsx(Button, { type: "submit", className: "w-full", disabled: forgotLoading, children: forgotLoading ? "Versturen..." : "Reset-link versturen" }), _jsx("button", { type: "button", onClick: () => setShowForgot(false), className: "text-sm text-primary hover:underline", children: "Terug naar inloggen" })] })] })] }) }));
|
|
79
|
+
return (_jsx("div", { className: "min-h-screen flex items-center justify-center bg-background p-4", children: _jsxs(Card, { className: "w-full max-w-md", children: [_jsxs(CardHeader, { className: "text-center", children: [_jsx(BrandLogo, { src: "/brand/logo.svg", className: "mx-auto mb-4 max-h-16 max-w-52 object-contain", fallbackClassName: "mb-4 font-display text-primary" }), _jsx(CardTitle, { className: "font-display text-2xl", children: "Wachtwoord vergeten" }), _jsx(CardDescription, { children: "Vul je e-mailadres in om een reset-link te ontvangen" })] }), _jsxs("form", { onSubmit: handleForgotPassword, children: [_jsx(CardContent, { className: "space-y-4", children: _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "forgot-email", children: "E-mailadres" }), _jsx(Input, { id: "forgot-email", type: "email", placeholder: "naam@bedrijf.nl", value: forgotEmail, onChange: (e) => setForgotEmail(e.target.value), required: true, maxLength: 255 })] }) }), _jsxs(CardFooter, { className: "flex flex-col gap-4", children: [_jsx(Button, { type: "submit", className: "w-full", disabled: forgotLoading, children: forgotLoading ? "Versturen..." : "Reset-link versturen" }), _jsx("button", { type: "button", onClick: () => setShowForgot(false), className: "text-sm text-primary hover:underline", children: "Terug naar inloggen" })] })] })] }) }));
|
|
74
80
|
}
|
|
75
|
-
return (_jsx("div", { className: "min-h-screen flex items-center justify-center bg-background p-4", children: _jsxs(Card, { className: "w-full max-w-md", children: [_jsxs(CardHeader, { className: "text-center", children: [_jsx(CardTitle, { className: "text-2xl", children: "Inloggen" }), _jsx(CardDescription, { children: "Voer je gegevens in om toegang te krijgen tot het systeem" })] }), _jsxs("form", { onSubmit: handleSubmit, children: [_jsxs(CardContent, { className: "space-y-4", children: [_jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "email", children: "E-mailadres" }), _jsx(Input, { id: "email", type: "email", placeholder: "naam@bedrijf.nl", value: email, onChange: (e) => setEmail(e.target.value), required: true, maxLength: 255 })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "password", children: "Wachtwoord" }), _jsx(Input, { id: "password", type: "password", placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", value: password, onChange: (e) => setPassword(e.target.value), required: true, maxLength: 128 })] })] }), _jsxs(CardFooter, { className: "flex flex-col gap-4", children: [_jsx(Button, { type: "submit", className: "w-full", disabled: isLoading, children: isLoading ? "Bezig met inloggen..." : "Inloggen" }), _jsx("button", { type: "button", onClick: () => setShowForgot(true), className: "text-sm text-muted-foreground hover:text-primary hover:underline", children: "Wachtwoord vergeten?" })] })] })] }) }));
|
|
81
|
+
return (_jsx("div", { className: "min-h-screen flex items-center justify-center bg-background p-4", children: _jsxs(Card, { className: "w-full max-w-md", children: [_jsxs(CardHeader, { className: "text-center", children: [_jsx(BrandLogo, { src: "/brand/logo.svg", className: "mx-auto mb-4 max-h-16 max-w-52 object-contain", fallbackClassName: "mb-4 font-display text-primary" }), _jsx(CardTitle, { className: "font-display text-2xl", children: "Inloggen" }), _jsx(CardDescription, { children: "Voer je gegevens in om toegang te krijgen tot het systeem" })] }), _jsxs("form", { onSubmit: handleSubmit, children: [_jsxs(CardContent, { className: "space-y-4", children: [_jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "email", children: "E-mailadres" }), _jsx(Input, { id: "email", type: "email", placeholder: "naam@bedrijf.nl", value: email, onChange: (e) => setEmail(e.target.value), required: true, maxLength: 255 })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "password", children: "Wachtwoord" }), _jsx(Input, { id: "password", type: "password", placeholder: "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022", value: password, onChange: (e) => setPassword(e.target.value), required: true, maxLength: 128 })] })] }), _jsxs(CardFooter, { className: "flex flex-col gap-4", children: [_jsx(Button, { type: "submit", className: "w-full", disabled: isLoading, children: isLoading ? "Bezig met inloggen..." : "Inloggen" }), _jsx("button", { type: "button", onClick: () => setShowForgot(true), className: "text-sm text-muted-foreground hover:text-primary hover:underline", children: "Wachtwoord vergeten?" })] })] })] }) }));
|
|
76
82
|
}
|
|
@@ -41,5 +41,5 @@ export function NotificationBell() {
|
|
|
41
41
|
day: "2-digit", month: "2-digit", hour: "2-digit", minute: "2-digit",
|
|
42
42
|
});
|
|
43
43
|
};
|
|
44
|
-
return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { variant: "ghost", size: "icon", className: "relative", children: [_jsx(Bell, { className: "h-5 w-5" }), unreadCount > 0 && (_jsx("span", { className: "absolute -top-1 -right-1 flex h-5 w-5 items-center justify-center rounded-full bg-destructive text-[10px] font-bold text-destructive-foreground", children: unreadCount > 9 ? "9+" : unreadCount }))] }) }), _jsxs(PopoverContent, { className: "w-80 p-0", align: "end", children: [_jsx("div", { className: "border-b p-3", children: _jsx("h4", { className: "font-semibold text-sm", children: "Notificaties" }) }), _jsx("div", { className: "max-h-80 overflow-y-auto", children: notifications.length === 0 ? (_jsx("div", { className: "p-4 text-center text-sm text-muted-foreground", children: "Geen notificaties" })) : (notifications.map((n) => (_jsxs("div", { className: cn("flex items-start gap-2 border-b p-3 cursor-pointer hover:bg-muted/50 transition-colors", !n.read && "bg-accent/30"), onClick: () => markAsRead(n.id), children: [_jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("p", { className: cn("text-sm", !n.read && "font-medium"), children: n.title }), n.message && _jsx("p", { className: "text-xs text-muted-foreground mt-0.5 truncate", children: n.message }), _jsx("p", { className: "text-xs text-muted-foreground mt-1", children: formatDate(n.created_at) })] }), _jsx(Button, { variant: "ghost", size: "icon", className: "h-6 w-6 shrink-0", onClick: (e) => { e.stopPropagation(); dismissNotification(n.id); }, children: _jsx("span", { className: "text-xs", children: "\u2715" }) })] }, n.id)))) })] })] }));
|
|
44
|
+
return (_jsxs(Popover, { open: open, onOpenChange: setOpen, children: [_jsx(PopoverTrigger, { asChild: true, children: _jsxs(Button, { variant: "ghost", size: "icon", className: "relative", children: [_jsx(Bell, { className: "h-5 w-5" }), unreadCount > 0 && (_jsx("span", { className: "absolute -top-1 -right-1 flex h-5 w-5 items-center justify-center rounded-full bg-destructive-soft text-[10px] font-bold text-destructive-soft-foreground ring-1 ring-destructive/30", children: unreadCount > 9 ? "9+" : unreadCount }))] }) }), _jsxs(PopoverContent, { className: "w-80 p-0", align: "end", children: [_jsx("div", { className: "border-b p-3", children: _jsx("h4", { className: "font-semibold text-sm", children: "Notificaties" }) }), _jsx("div", { className: "max-h-80 overflow-y-auto", children: notifications.length === 0 ? (_jsx("div", { "data-empty-state": true, className: "p-4 text-center text-sm text-muted-foreground", children: "Geen notificaties" })) : (notifications.map((n) => (_jsxs("div", { className: cn("flex items-start gap-2 border-b p-3 cursor-pointer hover:bg-muted/50 transition-colors", !n.read && "bg-accent/30"), onClick: () => markAsRead(n.id), children: [_jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("p", { className: cn("text-sm", !n.read && "font-medium"), children: n.title }), n.message && _jsx("p", { className: "text-xs text-muted-foreground mt-0.5 truncate", children: n.message }), _jsx("p", { className: "text-xs text-muted-foreground mt-1", children: formatDate(n.created_at) })] }), _jsx(Button, { variant: "ghost", size: "icon", className: "h-6 w-6 shrink-0", onClick: (e) => { e.stopPropagation(); dismissNotification(n.id); }, children: _jsx("span", { className: "text-xs", children: "\u2715" }) })] }, n.id)))) })] })] }));
|
|
45
45
|
}
|
|
@@ -47,7 +47,7 @@ export function ResetWachtwoordPage({ redirectTo, loginPath = "/login" }) {
|
|
|
47
47
|
}
|
|
48
48
|
};
|
|
49
49
|
if (!isReady) {
|
|
50
|
-
return (_jsx("div", { className: "min-h-screen flex items-center justify-center bg-background p-4", children: _jsxs(Card, { className: "w-full max-w-md", children: [_jsxs(CardHeader, { className: "text-center", children: [_jsx(CardTitle, { className: "text-2xl", children: "Ongeldige link" }), _jsx(CardDescription, { children: "Deze reset-link is ongeldig of verlopen. Vraag een nieuwe aan via de inlogpagina." })] }), _jsx(CardFooter, { className: "justify-center", children: _jsx(Button, { onClick: () => router.navigate({ href: loginPath }), children: "Naar inlogpagina" }) })] }) }));
|
|
50
|
+
return (_jsx("div", { className: "min-h-screen flex items-center justify-center bg-background p-4", children: _jsxs(Card, { className: "w-full max-w-md", children: [_jsxs(CardHeader, { className: "text-center", children: [_jsx(CardTitle, { "data-empty-state": true, className: "text-2xl", children: "Ongeldige link" }), _jsx(CardDescription, { children: "Deze reset-link is ongeldig of verlopen. Vraag een nieuwe aan via de inlogpagina." })] }), _jsx(CardFooter, { className: "justify-center", children: _jsx(Button, { onClick: () => router.navigate({ href: loginPath }), children: "Naar inlogpagina" }) })] }) }));
|
|
51
51
|
}
|
|
52
52
|
return (_jsx("div", { className: "min-h-screen flex items-center justify-center bg-background p-4", children: _jsxs(Card, { className: "w-full max-w-md", children: [_jsxs(CardHeader, { className: "text-center", children: [_jsx(CardTitle, { className: "text-2xl", children: "Nieuw wachtwoord instellen" }), _jsx(CardDescription, { children: "Kies een nieuw wachtwoord voor je account" })] }), _jsxs("form", { onSubmit: handleSubmit, children: [_jsxs(CardContent, { className: "space-y-4", children: [_jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "password", children: "Nieuw wachtwoord" }), _jsx(Input, { id: "password", type: "password", value: password, onChange: (e) => setPassword(e.target.value), required: true, minLength: 6, maxLength: 128 })] }), _jsxs("div", { className: "space-y-2", children: [_jsx(Label, { htmlFor: "confirmPassword", children: "Bevestig wachtwoord" }), _jsx(Input, { id: "confirmPassword", type: "password", value: confirmPassword, onChange: (e) => setConfirmPassword(e.target.value), required: true, minLength: 6, maxLength: 128 })] })] }), _jsx(CardFooter, { children: _jsx(Button, { type: "submit", className: "w-full", disabled: isLoading, children: isLoading ? "Opslaan..." : "Wachtwoord opslaan" }) })] })] }) }));
|
|
53
53
|
}
|
|
@@ -15,7 +15,7 @@ export interface SidebarProps {
|
|
|
15
15
|
* Zichtbaarheid, geen beveiliging.
|
|
16
16
|
*/
|
|
17
17
|
permissions?: boolean;
|
|
18
|
-
/**
|
|
18
|
+
/** Logopad; standaard het door het dashboard beheerde /brand/logo-wit.svg. */
|
|
19
19
|
logoSrc?: string;
|
|
20
20
|
/** Sinds 1.0.23. Instellingen tonen (standaard true). Uitloggen is nooit te verbergen. */
|
|
21
21
|
showSettings?: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sidebar.d.ts","sourceRoot":"","sources":["../../../src/core/components/layout/Sidebar.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAW,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"Sidebar.d.ts","sourceRoot":"","sources":["../../../src/core/components/layout/Sidebar.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACzD,OAAO,KAAK,EAAE,UAAU,EAAW,MAAM,uBAAuB,CAAC;AAQjE,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,8EAA8E;IAC9E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,0FAA0F;IAC1F,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB;;;OAGG;IACH,cAAc,CAAC,EAAE,UAAU,EAAE,CAAC;IAC9B,8EAA8E;IAC9E,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,UAAU,EAAE,EAAE,WAAW,EAAE,OAAO;;;EAI5E;AAuKD;;;GAGG;AACH,wBAAgB,OAAO,CAAC,EACtB,IAAI,EACJ,OAAO,EACP,OAAO,EACP,WAAmB,EACnB,OAAO,EACP,YAAmB,EACnB,cAAc,EACd,OAAO,GACR,EAAE,YAAY,2CA+Dd"}
|
|
@@ -8,13 +8,14 @@ import { cn } from "../../lib/utils.js";
|
|
|
8
8
|
import { useFooterItems, useModuleListTransform } from "../../extensions/ShellExtensions.js";
|
|
9
9
|
import { usePermissionFilteredModules } from "../../permissions/useModulePermission.js";
|
|
10
10
|
import { useLogoSrc } from "../../hooks/useLogoSrc.js";
|
|
11
|
+
import { BrandLogo } from "./BrandLogo.js";
|
|
11
12
|
/**
|
|
12
13
|
* Sinds 1.0.23. Pipeline: eerst rechten, dan extensie-transforms (ordening).
|
|
13
14
|
* Zichtbaarheid, geen beveiliging.
|
|
14
15
|
*/
|
|
15
16
|
export function useSidebarModules(modules, permissions) {
|
|
16
17
|
const filtered = usePermissionFilteredModules(modules, permissions);
|
|
17
|
-
const visible = useModuleListTransform(filtered.modules);
|
|
18
|
+
const visible = useModuleListTransform(filtered.modules, modules);
|
|
18
19
|
return { visibleModules: visible, loading: filtered.loading };
|
|
19
20
|
}
|
|
20
21
|
// ─── Single flat nav link ─────────────────────────────────────────────────────
|
|
@@ -38,7 +39,7 @@ function SidebarContent({ auth, visibleModules, loading, logoSrc, showSettings,
|
|
|
38
39
|
onNavigate?.();
|
|
39
40
|
await auth.signOut();
|
|
40
41
|
};
|
|
41
|
-
return (_jsxs("div", { className: "flex h-full min-h-0 flex-col", children: [_jsx("div", { className: "flex shrink-0 items-center justify-center px-12 py-0 border-b border-sidebar-border", children: _jsx(
|
|
42
|
+
return (_jsxs("div", { className: "flex h-full min-h-0 flex-col", children: [_jsx("div", { className: "flex shrink-0 items-center justify-center px-12 py-0 border-b border-sidebar-border", children: _jsx(BrandLogo, { src: logoSrc, className: "max-h-24 w-auto max-w-full object-contain", fallbackClassName: "text-sidebar-foreground" }) }), _jsx("nav", { className: "min-h-0 flex-1 space-y-1 px-3 py-4 overflow-y-auto sidebar-scroll", "aria-busy": loading || undefined, children: loading ? (_jsx("div", { "data-testid": "sidebar-skeleton", className: "space-y-2", children: [0, 1, 2, 3].map((i) => (_jsx(Skeleton, { className: "h-9 w-full bg-sidebar-accent" }, i))) })) : (visibleModules.map((mod) => mod.nav.children?.length ? (_jsx(SidebarGroup, { item: mod.nav, pathname: pathname, onNavigate: onNavigate }, mod.id)) : (_jsx(SidebarLink, { item: mod.nav, pathname: pathname, onNavigate: onNavigate }, mod.id)))) }), _jsxs("div", { className: "shrink-0 border-t border-sidebar-border px-3 py-4", children: [showSettings && (_jsx(SidebarLink, { item: { label: "Instellingen", href: "/instellingen", icon: Settings }, pathname: pathname, onNavigate: onNavigate })), _jsxs("button", { onClick: handleSignOut, className: "flex w-full items-center gap-3 rounded-lg px-3 py-2.5 text-sm font-medium transition-colors text-sidebar-muted hover:bg-sidebar-accent hover:text-sidebar-accent-foreground mt-1 cursor-pointer", children: [_jsx(LogOut, { className: "h-5 w-5" }), "Uitloggen"] })] })] }));
|
|
42
43
|
}
|
|
43
44
|
// ─── Main Sidebar ─────────────────────────────────────────────────────────────
|
|
44
45
|
/**
|
|
@@ -67,5 +68,5 @@ export function Sidebar({ auth, modules, shellId, permissions = false, logoSrc,
|
|
|
67
68
|
showSettings: footer.settings,
|
|
68
69
|
pathname,
|
|
69
70
|
};
|
|
70
|
-
return (_jsxs(_Fragment, { children: [_jsx("aside", { "data-shell": shellId, className: "fixed left-0 top-0 z-40 hidden h-screen h-dvh w-64 bg-sidebar md:block", children: _jsx(SidebarContent, { ...contentProps }) }), _jsxs("div", { className: "fixed inset-x-0 top-0 z-40 flex h-14 items-center gap-3 border-b border-sidebar-border bg-sidebar px-3 md:hidden", children: [_jsx("button", { type: "button", onClick: () => setMobileOpen(true), "aria-label": "Menu openen", className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-lg text-sidebar-muted hover:bg-sidebar-accent hover:text-sidebar-accent-foreground", children: _jsx(Menu, { className: "h-5 w-5" }) }), _jsx(
|
|
71
|
+
return (_jsxs(_Fragment, { children: [_jsx("aside", { "data-shell": shellId, className: "fixed left-0 top-0 z-40 hidden h-screen h-dvh w-64 bg-sidebar md:block", children: _jsx(SidebarContent, { ...contentProps }) }), _jsxs("div", { className: "fixed inset-x-0 top-0 z-40 flex h-14 items-center gap-3 border-b border-sidebar-border bg-sidebar px-3 md:hidden", children: [_jsx("button", { type: "button", onClick: () => setMobileOpen(true), "aria-label": "Menu openen", className: "flex h-10 w-10 shrink-0 items-center justify-center rounded-lg text-sidebar-muted hover:bg-sidebar-accent hover:text-sidebar-accent-foreground", children: _jsx(Menu, { className: "h-5 w-5" }) }), _jsx(BrandLogo, { src: logo, className: "h-8 w-auto max-w-[10rem] object-contain", fallbackClassName: "text-sidebar-foreground" })] }), _jsx(Sheet, { open: mobileOpen, onOpenChange: setMobileOpen, children: _jsxs(SheetContent, { side: "left", "data-shell": shellId, className: "w-64 max-w-[85vw] border-sidebar-border bg-sidebar p-0 md:hidden", children: [_jsx(SheetTitle, { className: "sr-only", children: "Navigatie" }), _jsx(SidebarContent, { ...contentProps, onNavigate: close })] }) })] }));
|
|
71
72
|
}
|
|
@@ -6,7 +6,7 @@ const alertVariants = cva("relative w-full rounded-lg border px-4 py-3 text-sm [
|
|
|
6
6
|
variants: {
|
|
7
7
|
variant: {
|
|
8
8
|
default: "bg-background text-foreground",
|
|
9
|
-
destructive: "border-destructive/50
|
|
9
|
+
destructive: "border-destructive/50 bg-destructive-soft text-destructive-soft-foreground [&>svg]:text-destructive-soft-foreground",
|
|
10
10
|
},
|
|
11
11
|
},
|
|
12
12
|
defaultVariants: {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import { type VariantProps } from "class-variance-authority";
|
|
3
3
|
declare const badgeVariants: (props?: ({
|
|
4
|
-
variant?: "default" | "destructive" | "outline" | "secondary" | null | undefined;
|
|
4
|
+
variant?: "default" | "destructive" | "outline" | "secondary" | "success" | "warning" | "info" | null | undefined;
|
|
5
5
|
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
6
6
|
export interface BadgeProps extends React.HTMLAttributes<HTMLDivElement>, VariantProps<typeof badgeVariants> {
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"badge.d.ts","sourceRoot":"","sources":["../../../src/core/components/ui/badge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAIjE,QAAA,MAAM,aAAa;;
|
|
1
|
+
{"version":3,"file":"badge.d.ts","sourceRoot":"","sources":["../../../src/core/components/ui/badge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAA;AAIjE,QAAA,MAAM,aAAa;;8EAwBlB,CAAA;AAED,MAAM,WAAW,UACf,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC,EAC1C,YAAY,CAAC,OAAO,aAAa,CAAC;CAAG;AAEzC,iBAAS,KAAK,CAAC,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,KAAK,EAAE,EAAE,UAAU,2CAI1D;AAED,OAAO,EAAE,KAAK,EAAE,aAAa,EAAE,CAAA"}
|
|
@@ -4,9 +4,12 @@ import { cn } from "../../lib/utils.js";
|
|
|
4
4
|
const badgeVariants = cva("inline-flex items-center rounded-md border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2", {
|
|
5
5
|
variants: {
|
|
6
6
|
variant: {
|
|
7
|
-
default: "border-transparent bg-primary text-primary-foreground
|
|
7
|
+
default: "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
|
|
8
8
|
secondary: "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
9
|
-
destructive: "border-transparent bg-destructive text-destructive-foreground
|
|
9
|
+
destructive: "border-transparent bg-destructive-soft text-destructive-soft-foreground hover:bg-destructive-soft/80",
|
|
10
|
+
success: "border-transparent bg-success-soft text-success-soft-foreground hover:bg-success-soft/80",
|
|
11
|
+
warning: "border-transparent bg-warning-soft text-warning-soft-foreground hover:bg-warning-soft/80",
|
|
12
|
+
info: "border-transparent bg-info-soft text-info-soft-foreground hover:bg-info-soft/80",
|
|
10
13
|
outline: "text-foreground",
|
|
11
14
|
},
|
|
12
15
|
},
|
|
@@ -3,13 +3,13 @@ import * as React from "react";
|
|
|
3
3
|
import { Slot } from "@radix-ui/react-slot";
|
|
4
4
|
import { cva } from "class-variance-authority";
|
|
5
5
|
import { cn } from "../../lib/utils.js";
|
|
6
|
-
const buttonVariants = cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-
|
|
6
|
+
const buttonVariants = cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", {
|
|
7
7
|
variants: {
|
|
8
8
|
variant: {
|
|
9
|
-
default: "bg-primary text-primary-foreground
|
|
10
|
-
destructive: "bg-destructive text-destructive-foreground
|
|
11
|
-
outline: "border border-input bg-background
|
|
12
|
-
secondary: "bg-secondary text-secondary-foreground
|
|
9
|
+
default: "bg-primary text-primary-foreground hover:bg-primary/90",
|
|
10
|
+
destructive: "bg-destructive text-destructive-foreground hover:bg-destructive/90",
|
|
11
|
+
outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
|
|
12
|
+
secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
|
|
13
13
|
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
14
14
|
link: "text-primary underline-offset-4 hover:underline",
|
|
15
15
|
},
|
|
@@ -19,7 +19,7 @@ function Calendar({ className, classNames, showOutsideDays = true, captionLayout
|
|
|
19
19
|
button_next: cn(buttonVariants({ variant: buttonVariant }), "h-(--cell-size) w-(--cell-size) select-none p-0 aria-disabled:opacity-50", defaultClassNames.button_next),
|
|
20
20
|
month_caption: cn("flex h-(--cell-size) w-full items-center justify-center px-(--cell-size)", defaultClassNames.month_caption),
|
|
21
21
|
dropdowns: cn("flex h-(--cell-size) w-full items-center justify-center gap-1.5 text-sm font-medium", defaultClassNames.dropdowns),
|
|
22
|
-
dropdown_root: cn("has-focus:border-ring border-input
|
|
22
|
+
dropdown_root: cn("has-focus:border-ring border-input has-focus:ring-ring relative rounded-md border has-focus:ring-2 has-focus:ring-offset-2", defaultClassNames.dropdown_root),
|
|
23
23
|
dropdown: cn("bg-popover absolute inset-0 opacity-0", defaultClassNames.dropdown),
|
|
24
24
|
caption_label: cn("select-none font-medium", captionLayout === "label"
|
|
25
25
|
? "text-sm"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import { cn } from "../../lib/utils.js";
|
|
4
|
-
const Card = React.forwardRef(({ className, ...props }, ref) => (_jsx("div", { ref: ref, className: cn("rounded-
|
|
4
|
+
const Card = React.forwardRef(({ className, ...props }, ref) => (_jsx("div", { ref: ref, className: cn("rounded-lg border bg-card text-card-foreground", className), ...props })));
|
|
5
5
|
Card.displayName = "Card";
|
|
6
6
|
const CardHeader = React.forwardRef(({ className, ...props }, ref) => (_jsx("div", { ref: ref, className: cn("flex flex-col space-y-1.5 p-6", className), ...props })));
|
|
7
7
|
CardHeader.displayName = "CardHeader";
|
|
@@ -3,6 +3,6 @@ import * as React from "react";
|
|
|
3
3
|
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
|
|
4
4
|
import { Check } from "lucide-react";
|
|
5
5
|
import { cn } from "../../lib/utils.js";
|
|
6
|
-
const Checkbox = React.forwardRef(({ className, ...props }, ref) => (_jsx(CheckboxPrimitive.Root, { ref: ref, className: cn("grid place-content-center peer h-4 w-4 shrink-0 rounded-sm border border-primary
|
|
6
|
+
const Checkbox = React.forwardRef(({ className, ...props }, ref) => (_jsx(CheckboxPrimitive.Root, { ref: ref, className: cn("grid place-content-center peer h-4 w-4 shrink-0 rounded-sm border border-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground", className), ...props, children: _jsx(CheckboxPrimitive.Indicator, { className: cn("grid place-content-center text-current"), children: _jsx(Check, { className: "h-4 w-4" }) }) })));
|
|
7
7
|
Checkbox.displayName = CheckboxPrimitive.Root.displayName;
|
|
8
8
|
export { Checkbox };
|
|
@@ -10,7 +10,7 @@ InputOTPGroup.displayName = "InputOTPGroup";
|
|
|
10
10
|
const InputOTPSlot = React.forwardRef(({ index, className, ...props }, ref) => {
|
|
11
11
|
const inputOTPContext = React.useContext(OTPInputContext);
|
|
12
12
|
const { char, hasFakeCaret, isActive } = inputOTPContext.slots[index];
|
|
13
|
-
return (_jsxs("div", { ref: ref, className: cn("relative flex h-9 w-9 items-center justify-center border-y border-r border-input text-sm
|
|
13
|
+
return (_jsxs("div", { ref: ref, className: cn("relative flex h-9 w-9 items-center justify-center border-y border-r border-input text-sm transition-all first:rounded-l-md first:border-l last:rounded-r-md", isActive && "z-10 ring-1 ring-ring", className), ...props, children: [char, hasFakeCaret && (_jsx("div", { className: "pointer-events-none absolute inset-0 flex items-center justify-center", children: _jsx("div", { className: "h-4 w-px animate-caret-blink bg-foreground duration-1000" }) }))] }));
|
|
14
14
|
});
|
|
15
15
|
InputOTPSlot.displayName = "InputOTPSlot";
|
|
16
16
|
const InputOTPSeparator = React.forwardRef(({ ...props }, ref) => (_jsx("div", { ref: ref, role: "separator", ...props, children: _jsx(Minus, {}) })));
|
|
@@ -2,7 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import { cn } from "../../lib/utils.js";
|
|
4
4
|
const Input = React.forwardRef(({ className, type, ...props }, ref) => {
|
|
5
|
-
return (_jsx("input", { type: type, className: cn("flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base
|
|
5
|
+
return (_jsx("input", { type: type, className: cn("flex h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-base transition-colors file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground 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 md:text-sm", className), ref: ref, ...props }));
|
|
6
6
|
});
|
|
7
7
|
Input.displayName = "Input";
|
|
8
8
|
export { Input };
|
|
@@ -18,7 +18,7 @@ function MenubarRadioGroup({ ...props }) {
|
|
|
18
18
|
function MenubarSub({ ...props }) {
|
|
19
19
|
return _jsx(MenubarPrimitive.Sub, { "data-slot": "menubar-sub", ...props });
|
|
20
20
|
}
|
|
21
|
-
const Menubar = React.forwardRef(({ className, ...props }, ref) => (_jsx(MenubarPrimitive.Root, { ref: ref, className: cn("flex h-9 items-center space-x-1 rounded-md border bg-background p-1
|
|
21
|
+
const Menubar = React.forwardRef(({ className, ...props }, ref) => (_jsx(MenubarPrimitive.Root, { ref: ref, className: cn("flex h-9 items-center space-x-1 rounded-md border bg-background p-1", className), ...props })));
|
|
22
22
|
Menubar.displayName = MenubarPrimitive.Root.displayName;
|
|
23
23
|
const MenubarTrigger = React.forwardRef(({ className, ...props }, ref) => (_jsx(MenubarPrimitive.Trigger, { ref: ref, className: cn("flex cursor-default select-none items-center rounded-sm px-3 py-1 text-sm font-medium outline-none focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground", className), ...props })));
|
|
24
24
|
MenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName;
|
|
@@ -18,7 +18,7 @@ const NavigationMenuLink = NavigationMenuPrimitive.Link;
|
|
|
18
18
|
const NavigationMenuViewport = React.forwardRef(({ className, ...props }, ref) => (_jsx("div", { className: cn("absolute left-0 top-full flex justify-center"), children: _jsx(NavigationMenuPrimitive.Viewport, { className: cn("origin-top-center relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border bg-popover text-popover-foreground shadow data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 md:w-[var(--radix-navigation-menu-viewport-width)]", className), ref: ref, ...props }) })));
|
|
19
19
|
NavigationMenuViewport.displayName =
|
|
20
20
|
NavigationMenuPrimitive.Viewport.displayName;
|
|
21
|
-
const NavigationMenuIndicator = React.forwardRef(({ className, ...props }, ref) => (_jsx(NavigationMenuPrimitive.Indicator, { ref: ref, className: cn("top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in", className), ...props, children: _jsx("div", { className: "relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm
|
|
21
|
+
const NavigationMenuIndicator = React.forwardRef(({ className, ...props }, ref) => (_jsx(NavigationMenuPrimitive.Indicator, { ref: ref, className: cn("top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in", className), ...props, children: _jsx("div", { className: "relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm border-l border-t bg-popover" }) })));
|
|
22
22
|
NavigationMenuIndicator.displayName =
|
|
23
23
|
NavigationMenuPrimitive.Indicator.displayName;
|
|
24
24
|
export { navigationMenuTriggerStyle, NavigationMenu, NavigationMenuList, NavigationMenuItem, NavigationMenuContent, NavigationMenuTrigger, NavigationMenuLink, NavigationMenuIndicator, NavigationMenuViewport, };
|
|
@@ -8,7 +8,7 @@ const RadioGroup = React.forwardRef(({ className, ...props }, ref) => {
|
|
|
8
8
|
});
|
|
9
9
|
RadioGroup.displayName = RadioGroupPrimitive.Root.displayName;
|
|
10
10
|
const RadioGroupItem = React.forwardRef(({ className, ...props }, ref) => {
|
|
11
|
-
return (_jsx(RadioGroupPrimitive.Item, { ref: ref, className: cn("aspect-square h-4 w-4 rounded-full border border-primary text-primary
|
|
11
|
+
return (_jsx(RadioGroupPrimitive.Item, { ref: ref, className: cn("aspect-square h-4 w-4 rounded-full border border-primary text-primary focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", className), ...props, children: _jsx(RadioGroupPrimitive.Indicator, { className: "flex items-center justify-center", children: _jsx(Circle, { className: "h-3.5 w-3.5 fill-primary" }) }) }));
|
|
12
12
|
});
|
|
13
13
|
RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName;
|
|
14
14
|
export { RadioGroup, RadioGroupItem };
|
|
@@ -4,5 +4,5 @@ import { Group, Panel, Separator } from "react-resizable-panels";
|
|
|
4
4
|
import { cn } from "../../lib/utils.js";
|
|
5
5
|
const ResizablePanelGroup = ({ className, ...props }) => (_jsx(Group, { className: cn("flex h-full w-full data-[panel-group-direction=vertical]:flex-col", className), ...props }));
|
|
6
6
|
const ResizablePanel = Panel;
|
|
7
|
-
const ResizableHandle = ({ withHandle, className, ...props }) => (_jsx(Separator, { className: cn("relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-
|
|
7
|
+
const ResizableHandle = ({ withHandle, className, ...props }) => (_jsx(Separator, { className: cn("relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 [&[data-panel-group-direction=vertical]>div]:rotate-90", className), ...props, children: withHandle && (_jsx("div", { className: "z-10 flex h-4 w-3 items-center justify-center rounded-sm border bg-border", children: _jsx(GripVertical, { className: "h-2.5 w-2.5" }) })) }));
|
|
8
8
|
export { ResizablePanelGroup, ResizablePanel, ResizableHandle };
|
|
@@ -7,7 +7,7 @@ import { cn } from "../../lib/utils.js";
|
|
|
7
7
|
const Select = SelectPrimitive.Root;
|
|
8
8
|
const SelectGroup = SelectPrimitive.Group;
|
|
9
9
|
const SelectValue = SelectPrimitive.Value;
|
|
10
|
-
const SelectTrigger = React.forwardRef(({ className, children, ...props }, ref) => (_jsxs(SelectPrimitive.Trigger, { ref: ref, className: cn("flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm
|
|
10
|
+
const SelectTrigger = React.forwardRef(({ className, children, ...props }, ref) => (_jsxs(SelectPrimitive.Trigger, { ref: ref, className: cn("flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm ring-offset-background data-[placeholder]:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1", className), ...props, children: [children, _jsx(SelectPrimitive.Icon, { asChild: true, children: _jsx(ChevronDown, { className: "h-4 w-4 opacity-50" }) })] })));
|
|
11
11
|
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
|
|
12
12
|
const SelectScrollUpButton = React.forwardRef(({ className, ...props }, ref) => (_jsx(SelectPrimitive.ScrollUpButton, { ref: ref, className: cn("flex cursor-default items-center justify-center py-1", className), ...props, children: _jsx(ChevronUp, { className: "h-4 w-4" }) })));
|
|
13
13
|
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
|
|
@@ -98,7 +98,7 @@ const Sidebar = React.forwardRef(({ side = "left", variant = "sidebar", collapsi
|
|
|
98
98
|
// Adjust the padding for floating and inset variants.
|
|
99
99
|
variant === "floating" || variant === "inset"
|
|
100
100
|
? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4)_+2px)]"
|
|
101
|
-
: "group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l", className), ...props, children: _jsx("div", { "data-sidebar": "sidebar", className: "flex h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border
|
|
101
|
+
: "group-data-[collapsible=icon]:w-(--sidebar-width-icon) group-data-[side=left]:border-r group-data-[side=right]:border-l", className), ...props, children: _jsx("div", { "data-sidebar": "sidebar", className: "flex h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border", children: children }) })] }));
|
|
102
102
|
});
|
|
103
103
|
Sidebar.displayName = "Sidebar";
|
|
104
104
|
const SidebarTrigger = React.forwardRef(({ className, onClick, ...props }, ref) => {
|
|
@@ -115,7 +115,7 @@ const SidebarRail = React.forwardRef(({ className, ...props }, ref) => {
|
|
|
115
115
|
});
|
|
116
116
|
SidebarRail.displayName = "SidebarRail";
|
|
117
117
|
const SidebarInset = React.forwardRef(({ className, ...props }, ref) => {
|
|
118
|
-
return (_jsx("main", { ref: ref, className: cn("relative flex w-full flex-1 flex-col bg-background", "md:peer-data-[variant=inset]:m-2 md:peer-data-[state=collapsed]:peer-data-[variant=inset]:ml-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-
|
|
118
|
+
return (_jsx("main", { ref: ref, className: cn("relative flex w-full flex-1 flex-col bg-background", "md:peer-data-[variant=inset]:m-2 md:peer-data-[state=collapsed]:peer-data-[variant=inset]:ml-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-lg md:peer-data-[variant=inset]:border", className), ...props }));
|
|
119
119
|
});
|
|
120
120
|
SidebarInset.displayName = "SidebarInset";
|
|
121
121
|
const SidebarInput = React.forwardRef(({ className, ...props }, ref) => {
|
|
@@ -164,7 +164,7 @@ const sidebarMenuButtonVariants = cva("peer/menu-button flex w-full items-center
|
|
|
164
164
|
variants: {
|
|
165
165
|
variant: {
|
|
166
166
|
default: "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
|
|
167
|
-
outline: "
|
|
167
|
+
outline: "border border-sidebar-border bg-background hover:border-sidebar-accent hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
|
|
168
168
|
},
|
|
169
169
|
size: {
|
|
170
170
|
default: "h-8 text-sm",
|
|
@@ -2,6 +2,6 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import * as SliderPrimitive from "@radix-ui/react-slider";
|
|
4
4
|
import { cn } from "../../lib/utils.js";
|
|
5
|
-
const Slider = React.forwardRef(({ className, ...props }, ref) => (_jsxs(SliderPrimitive.Root, { ref: ref, className: cn("relative flex w-full touch-none select-none items-center", className), ...props, children: [_jsx(SliderPrimitive.Track, { className: "relative h-1.5 w-full grow overflow-hidden rounded-full bg-primary/20", children: _jsx(SliderPrimitive.Range, { className: "absolute h-full bg-primary" }) }), _jsx(SliderPrimitive.Thumb, { className: "block h-4 w-4 rounded-full border border-primary/50 bg-background
|
|
5
|
+
const Slider = React.forwardRef(({ className, ...props }, ref) => (_jsxs(SliderPrimitive.Root, { ref: ref, className: cn("relative flex w-full touch-none select-none items-center", className), ...props, children: [_jsx(SliderPrimitive.Track, { className: "relative h-1.5 w-full grow overflow-hidden rounded-full bg-primary/20", children: _jsx(SliderPrimitive.Range, { className: "absolute h-full bg-primary" }) }), _jsx(SliderPrimitive.Thumb, { className: "block h-4 w-4 rounded-full border border-primary/50 bg-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50" })] })));
|
|
6
6
|
Slider.displayName = SliderPrimitive.Root.displayName;
|
|
7
7
|
export { Slider };
|
|
@@ -3,7 +3,7 @@ import { Toaster as Sonner } from "sonner";
|
|
|
3
3
|
const Toaster = ({ ...props }) => {
|
|
4
4
|
return (_jsx(Sonner, { className: "toaster group", toastOptions: {
|
|
5
5
|
classNames: {
|
|
6
|
-
toast: "group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border
|
|
6
|
+
toast: "group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border",
|
|
7
7
|
description: "group-[.toast]:text-muted-foreground",
|
|
8
8
|
actionButton: "group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
|
|
9
9
|
cancelButton: "group-[.toast]:bg-muted group-[.toast]:text-muted-foreground",
|
|
@@ -2,6 +2,6 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import * as SwitchPrimitives from "@radix-ui/react-switch";
|
|
4
4
|
import { cn } from "../../lib/utils.js";
|
|
5
|
-
const Switch = React.forwardRef(({ className, ...props }, ref) => (_jsx(SwitchPrimitives.Root, { className: cn("peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-
|
|
5
|
+
const Switch = React.forwardRef(({ className, ...props }, ref) => (_jsx(SwitchPrimitives.Root, { className: cn("peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-input transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:border-primary data-[state=checked]:bg-primary data-[state=unchecked]:bg-input", className), ...props, ref: ref, children: _jsx(SwitchPrimitives.Thumb, { className: cn("pointer-events-none block h-4 w-4 rounded-full border border-border bg-background ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0") }) })));
|
|
6
6
|
Switch.displayName = SwitchPrimitives.Root.displayName;
|
|
7
7
|
export { Switch };
|
|
@@ -5,7 +5,7 @@ import { cn } from "../../lib/utils.js";
|
|
|
5
5
|
const Tabs = TabsPrimitive.Root;
|
|
6
6
|
const TabsList = React.forwardRef(({ className, ...props }, ref) => (_jsx(TabsPrimitive.List, { ref: ref, className: cn("inline-flex h-9 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground", className), ...props })));
|
|
7
7
|
TabsList.displayName = TabsPrimitive.List.displayName;
|
|
8
|
-
const TabsTrigger = React.forwardRef(({ className, ...props }, ref) => (_jsx(TabsPrimitive.Trigger, { ref: ref, className: cn("inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:
|
|
8
|
+
const TabsTrigger = React.forwardRef(({ className, ...props }, ref) => (_jsx(TabsPrimitive.Trigger, { ref: ref, className: cn("inline-flex items-center justify-center whitespace-nowrap rounded-md border border-transparent px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:border-border data-[state=active]:bg-background data-[state=active]:text-foreground", className), ...props })));
|
|
9
9
|
TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
|
|
10
10
|
const TabsContent = React.forwardRef(({ className, ...props }, ref) => (_jsx(TabsPrimitive.Content, { ref: ref, className: cn("mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2", className), ...props })));
|
|
11
11
|
TabsContent.displayName = TabsPrimitive.Content.displayName;
|
|
@@ -2,7 +2,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
2
2
|
import * as React from "react";
|
|
3
3
|
import { cn } from "../../lib/utils.js";
|
|
4
4
|
const Textarea = React.forwardRef(({ className, ...props }, ref) => {
|
|
5
|
-
return (_jsx("textarea", { className: cn("flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base
|
|
5
|
+
return (_jsx("textarea", { className: cn("flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-base 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 md:text-sm", className), ref: ref, ...props }));
|
|
6
6
|
});
|
|
7
7
|
Textarea.displayName = "Textarea";
|
|
8
8
|
export { Textarea };
|
|
@@ -3,11 +3,11 @@ import * as React from "react";
|
|
|
3
3
|
import * as TogglePrimitive from "@radix-ui/react-toggle";
|
|
4
4
|
import { cva } from "class-variance-authority";
|
|
5
5
|
import { cn } from "../../lib/utils.js";
|
|
6
|
-
const toggleVariants = cva("inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-
|
|
6
|
+
const toggleVariants = cva("inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium transition-colors hover:bg-muted hover:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", {
|
|
7
7
|
variants: {
|
|
8
8
|
variant: {
|
|
9
9
|
default: "bg-transparent",
|
|
10
|
-
outline: "border border-input bg-transparent
|
|
10
|
+
outline: "border border-input bg-transparent hover:bg-accent hover:text-accent-foreground",
|
|
11
11
|
},
|
|
12
12
|
size: {
|
|
13
13
|
default: "h-9 px-2 min-w-9",
|
|
@@ -1,7 +1,15 @@
|
|
|
1
1
|
import type { ComponentType, ReactNode } from "react";
|
|
2
2
|
import type { FlowModule } from "../types/module.js";
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
export interface ModuleListTransformContext {
|
|
4
|
+
/** De ongefilterde modulelijst die de shell aan de core-layout gaf. */
|
|
5
|
+
allModules: FlowModule[];
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Transformeert de actuele modulelijst (filteren en/of sorteren).
|
|
9
|
+
* Het tweede argument bevat altijd de ongefilterde shell-lijst.
|
|
10
|
+
* Puur op basis van input: geen synchronisatie, schrijfacties of andere side-effects.
|
|
11
|
+
*/
|
|
12
|
+
export type ModuleListTransform = (modules: FlowModule[], context: ModuleListTransformContext) => FlowModule[];
|
|
5
13
|
export type UseModuleListTransform = () => ModuleListTransform;
|
|
6
14
|
/**
|
|
7
15
|
* Sinds 1.0.23. Footer-items van de zijbalk. Uitloggen staat bewust NIET in dit
|
|
@@ -36,9 +44,12 @@ export declare function useShellGuard(): ComponentType<{
|
|
|
36
44
|
children: ReactNode;
|
|
37
45
|
}> | undefined;
|
|
38
46
|
/**
|
|
39
|
-
* Past de geregistreerde transforms toe.
|
|
47
|
+
* Past de geregistreerde transforms toe. `allModules` is de ongefilterde
|
|
48
|
+
* shell-lijst en blijft voor de hele pipeline gelijk. Transforms zijn puur op
|
|
49
|
+
* basis van hun input: geen synchronisatie, schrijfacties of andere side-effects.
|
|
50
|
+
* Zonder provider, tijdens laden of bij
|
|
40
51
|
* een fout in een transform komt de lijst ONGEWIJZIGD terug — nooit een lege
|
|
41
52
|
* zijbalk.
|
|
42
53
|
*/
|
|
43
|
-
export declare function useModuleListTransform(modules: FlowModule[]): FlowModule[];
|
|
54
|
+
export declare function useModuleListTransform(modules: FlowModule[], allModules?: FlowModule[]): FlowModule[];
|
|
44
55
|
//# sourceMappingURL=ShellExtensions.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ShellExtensions.d.ts","sourceRoot":"","sources":["../../src/core/extensions/ShellExtensions.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,
|
|
1
|
+
{"version":3,"file":"ShellExtensions.d.ts","sourceRoot":"","sources":["../../src/core/extensions/ShellExtensions.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACtD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,MAAM,WAAW,0BAA0B;IACzC,uEAAuE;IACvE,UAAU,EAAE,UAAU,EAAE,CAAC;CAC1B;AAED;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,CAChC,OAAO,EAAE,UAAU,EAAE,EACrB,OAAO,EAAE,0BAA0B,KAChC,UAAU,EAAE,CAAC;AAElB,MAAM,MAAM,sBAAsB,GAAG,MAAM,mBAAmB,CAAC;AAE/D;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,OAAO,CAAC;CACnB;AACD,MAAM,MAAM,eAAe,GAAG,CAAC,KAAK,EAAE,WAAW,KAAK,WAAW,CAAC;AAClE,MAAM,MAAM,kBAAkB,GAAG,MAAM,eAAe,CAAC;AAYvD,uGAAuG;AACvG,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW,CAc7D;AAED,MAAM,WAAW,4BAA4B;IAC3C;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,sBAAsB,GAAG,sBAAsB,EAAE,CAAC;IAClE,kFAAkF;IAClF,KAAK,CAAC,EAAE,aAAa,CAAC;QAAE,QAAQ,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;IAC/C,+FAA+F;IAC/F,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,wBAAgB,uBAAuB,CAAC,EACtC,aAAa,EACb,KAAK,EACL,SAAS,EACT,QAAQ,GACT,EAAE,4BAA4B,2CAY9B;AAED,wBAAgB,aAAa,IAAI,aAAa,CAAC;IAAE,QAAQ,EAAE,SAAS,CAAA;CAAE,CAAC,GAAG,SAAS,CAElF;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,UAAU,EAAE,EACrB,UAAU,GAAE,UAAU,EAAY,GACjC,UAAU,EAAE,CAuBd"}
|
|
@@ -33,11 +33,14 @@ export function useShellGuard() {
|
|
|
33
33
|
return useContext(ShellExtensionsContext).guard;
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
36
|
-
* Past de geregistreerde transforms toe.
|
|
36
|
+
* Past de geregistreerde transforms toe. `allModules` is de ongefilterde
|
|
37
|
+
* shell-lijst en blijft voor de hele pipeline gelijk. Transforms zijn puur op
|
|
38
|
+
* basis van hun input: geen synchronisatie, schrijfacties of andere side-effects.
|
|
39
|
+
* Zonder provider, tijdens laden of bij
|
|
37
40
|
* een fout in een transform komt de lijst ONGEWIJZIGD terug — nooit een lege
|
|
38
41
|
* zijbalk.
|
|
39
42
|
*/
|
|
40
|
-
export function useModuleListTransform(modules) {
|
|
43
|
+
export function useModuleListTransform(modules, allModules = modules) {
|
|
41
44
|
const { transforms } = useContext(ShellExtensionsContext);
|
|
42
45
|
// Onvoorwaardelijk en in vaste volgorde: geen hook-order-problemen.
|
|
43
46
|
const applied = [];
|
|
@@ -52,7 +55,7 @@ export function useModuleListTransform(modules) {
|
|
|
52
55
|
let result = modules;
|
|
53
56
|
for (const transform of applied) {
|
|
54
57
|
try {
|
|
55
|
-
const next = transform(result);
|
|
58
|
+
const next = transform(result, { allModules });
|
|
56
59
|
if (Array.isArray(next))
|
|
57
60
|
result = next;
|
|
58
61
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export declare const DEFAULT_LOGO_SRC = "/logo.
|
|
1
|
+
export declare const DEFAULT_LOGO_SRC = "/brand/logo-wit.svg";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
* `/logo.
|
|
3
|
+
* Logopad: een expliciete shell-prop wint, anders het door het dashboard
|
|
4
|
+
* beheerde `/brand/logo-wit.svg`.
|
|
5
5
|
*/
|
|
6
6
|
export declare function useLogoSrc(prop?: string): string;
|
|
7
7
|
//# sourceMappingURL=useLogoSrc.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLogoSrc.d.ts","sourceRoot":"","sources":["../../src/core/hooks/useLogoSrc.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useLogoSrc.d.ts","sourceRoot":"","sources":["../../src/core/hooks/useLogoSrc.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,gBAAgB,wBAAwB,CAAC;AAEtD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAEhD"}
|
package/dist/hooks/useLogoSrc.js
CHANGED
|
@@ -1,29 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
export const DEFAULT_LOGO_SRC = "/logo.png";
|
|
3
|
-
let huisstijlLogo = null;
|
|
4
|
-
function loadHuisstijlLogo() {
|
|
5
|
-
if (!huisstijlLogo) {
|
|
6
|
-
huisstijlLogo = fetch("/huisstijl.json")
|
|
7
|
-
.then((r) => (r.ok ? r.json() : null))
|
|
8
|
-
.then((j) => (j && typeof j.logo === "string" && j.logo ? j.logo : null))
|
|
9
|
-
.catch(() => null);
|
|
10
|
-
}
|
|
11
|
-
return huisstijlLogo;
|
|
12
|
-
}
|
|
1
|
+
export const DEFAULT_LOGO_SRC = "/brand/logo-wit.svg";
|
|
13
2
|
/**
|
|
14
|
-
*
|
|
15
|
-
* `/logo.
|
|
3
|
+
* Logopad: een expliciete shell-prop wint, anders het door het dashboard
|
|
4
|
+
* beheerde `/brand/logo-wit.svg`.
|
|
16
5
|
*/
|
|
17
6
|
export function useLogoSrc(prop) {
|
|
18
|
-
|
|
19
|
-
useEffect(() => {
|
|
20
|
-
if (prop || typeof window === "undefined")
|
|
21
|
-
return;
|
|
22
|
-
let alive = true;
|
|
23
|
-
loadHuisstijlLogo().then((v) => alive && setFromFile(v));
|
|
24
|
-
return () => {
|
|
25
|
-
alive = false;
|
|
26
|
-
};
|
|
27
|
-
}, [prop]);
|
|
28
|
-
return prop || fromFile || DEFAULT_LOGO_SRC;
|
|
7
|
+
return prop || DEFAULT_LOGO_SRC;
|
|
29
8
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -46,7 +46,7 @@ export { useHuisstijl } from "./hooks/useHuisstijl.js";
|
|
|
46
46
|
export type { FlowModule, NavItem, SettingsCard, FeatureDefinition } from "./types/module.js";
|
|
47
47
|
export { moduleKey, navKey, featureKey, moduleFeatures } from "./types/module.js";
|
|
48
48
|
export { ShellExtensionsProvider, useModuleListTransform, useFooterItems } from "./extensions/ShellExtensions.js";
|
|
49
|
-
export type { ModuleListTransform, UseModuleListTransform, ShellExtensionsProviderProps, FooterItems, FooterTransform, UseFooterTransform, } from "./extensions/ShellExtensions.js";
|
|
49
|
+
export type { ModuleListTransform, ModuleListTransformContext, UseModuleListTransform, ShellExtensionsProviderProps, FooterItems, FooterTransform, UseFooterTransform, } from "./extensions/ShellExtensions.js";
|
|
50
50
|
export { ModuleGuardSlot } from "./extensions/ModuleGuardSlot.js";
|
|
51
51
|
export { useMyModulePermissions, useModulePermission, useModulePermissionTransform, useCan, Can, usePermissionFilteredModules, } from "./permissions/useModulePermission.js";
|
|
52
52
|
export type { PermissionLevel, ModulePermissionRow, CanProps } from "./permissions/useModulePermission.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/core/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/core/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -16,5 +16,5 @@ export function ModuleAccessGuard({ children, fallback, moduleId, featureId, })
|
|
|
16
16
|
const { canView } = useModulePermission(key, featureId ?? null);
|
|
17
17
|
if (canView)
|
|
18
18
|
return _jsx(_Fragment, { children: children });
|
|
19
|
-
return (_jsx(_Fragment, { children: fallback ?? (_jsx("div", { className: "flex min-h-[60vh] items-center justify-center p-8", children: _jsxs("div", { className: "max-w-md text-center", children: [_jsx("h1", { className: "text-lg font-semibold text-foreground", children: "Geen toegang" }), _jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: "Je hebt geen rechten voor deze module. Vraag een beheerder om toegang." })] }) })) }));
|
|
19
|
+
return (_jsx(_Fragment, { children: fallback ?? (_jsx("div", { className: "flex min-h-[60vh] items-center justify-center p-8", children: _jsxs("div", { "data-empty-state": true, className: "max-w-md text-center", children: [_jsx("h1", { className: "text-lg font-semibold text-foreground", children: "Geen toegang" }), _jsx("p", { className: "mt-2 text-sm text-muted-foreground", children: "Je hebt geen rechten voor deze module. Vraag een beheerder om toegang." })] }) })) }));
|
|
20
20
|
}
|
package/dist/routes/index.d.ts
CHANGED
|
@@ -15,23 +15,67 @@ export declare function loginRoute({ landing }: SystemRouteOptions): {
|
|
|
15
15
|
search: LoginSearch;
|
|
16
16
|
}) => void;
|
|
17
17
|
head: () => {
|
|
18
|
-
meta: {
|
|
18
|
+
meta: ({
|
|
19
19
|
title: string;
|
|
20
|
-
|
|
20
|
+
name?: undefined;
|
|
21
|
+
content?: undefined;
|
|
22
|
+
property?: undefined;
|
|
23
|
+
} | {
|
|
24
|
+
name: string;
|
|
25
|
+
content: string;
|
|
26
|
+
title?: undefined;
|
|
27
|
+
property?: undefined;
|
|
28
|
+
} | {
|
|
29
|
+
property: string;
|
|
30
|
+
content: string;
|
|
31
|
+
title?: undefined;
|
|
32
|
+
name?: undefined;
|
|
33
|
+
})[];
|
|
21
34
|
};
|
|
22
35
|
component: () => import("react/jsx-runtime").JSX.Element;
|
|
23
36
|
};
|
|
24
37
|
/** `/reset-wachtwoord`: de core-pagina, daarna naar `landing`. */
|
|
25
38
|
export declare function resetPasswordRoute({ landing, loginPath }: SystemRouteOptions): {
|
|
26
39
|
head: () => {
|
|
27
|
-
meta: {
|
|
40
|
+
meta: ({
|
|
28
41
|
title: string;
|
|
29
|
-
|
|
42
|
+
name?: undefined;
|
|
43
|
+
content?: undefined;
|
|
44
|
+
property?: undefined;
|
|
45
|
+
} | {
|
|
46
|
+
name: string;
|
|
47
|
+
content: string;
|
|
48
|
+
title?: undefined;
|
|
49
|
+
property?: undefined;
|
|
50
|
+
} | {
|
|
51
|
+
property: string;
|
|
52
|
+
content: string;
|
|
53
|
+
title?: undefined;
|
|
54
|
+
name?: undefined;
|
|
55
|
+
})[];
|
|
30
56
|
};
|
|
31
57
|
component: () => import("react/jsx-runtime").JSX.Element;
|
|
32
58
|
};
|
|
33
59
|
/** `/`: redirect in beforeLoad, dus er wordt niets gerenderd (geen flits). */
|
|
34
60
|
export declare function landingRoute({ landing }: Pick<SystemRouteOptions, "landing">): {
|
|
61
|
+
head: () => {
|
|
62
|
+
meta: ({
|
|
63
|
+
title: string;
|
|
64
|
+
name?: undefined;
|
|
65
|
+
content?: undefined;
|
|
66
|
+
property?: undefined;
|
|
67
|
+
} | {
|
|
68
|
+
name: string;
|
|
69
|
+
content: string;
|
|
70
|
+
title?: undefined;
|
|
71
|
+
property?: undefined;
|
|
72
|
+
} | {
|
|
73
|
+
property: string;
|
|
74
|
+
content: string;
|
|
75
|
+
title?: undefined;
|
|
76
|
+
name?: undefined;
|
|
77
|
+
})[];
|
|
78
|
+
};
|
|
35
79
|
beforeLoad: () => never;
|
|
36
80
|
component: () => null;
|
|
37
81
|
};
|
|
@@ -41,9 +85,22 @@ export declare function handoverRoute({ landing, loginPath, exchangePath, }: Sys
|
|
|
41
85
|
}): {
|
|
42
86
|
ssr: false;
|
|
43
87
|
head: () => {
|
|
44
|
-
meta: {
|
|
88
|
+
meta: ({
|
|
45
89
|
title: string;
|
|
46
|
-
|
|
90
|
+
name?: undefined;
|
|
91
|
+
content?: undefined;
|
|
92
|
+
property?: undefined;
|
|
93
|
+
} | {
|
|
94
|
+
name: string;
|
|
95
|
+
content: string;
|
|
96
|
+
title?: undefined;
|
|
97
|
+
property?: undefined;
|
|
98
|
+
} | {
|
|
99
|
+
property: string;
|
|
100
|
+
content: string;
|
|
101
|
+
title?: undefined;
|
|
102
|
+
name?: undefined;
|
|
103
|
+
})[];
|
|
47
104
|
};
|
|
48
105
|
component: () => import("react/jsx-runtime").JSX.Element;
|
|
49
106
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/routes/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/routes/index.tsx"],"names":[],"mappings":"AA4BA,MAAM,WAAW,kBAAkB;IACjC,4EAA4E;IAC5E,OAAO,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAMD,8EAA8E;AAC9E,wBAAgB,UAAU,CAAC,EAAE,OAAO,EAAE,EAAE,kBAAkB;6BAE7B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,WAAW;sCAE5B;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,WAAW,CAAA;KAAE;;;;;;;;;;;;;;;;;;;;EAU9E;AAED,kEAAkE;AAClE,wBAAgB,kBAAkB,CAAC,EAAE,OAAO,EAAE,SAAoB,EAAE,EAAE,kBAAkB;;;;;;;;;;;;;;;;;;;;EAOvF;AAED,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,EAAE,OAAO,EAAE,EAAE,IAAI,CAAC,kBAAkB,EAAE,SAAS,CAAC;;;;;;;;;;;;;;;;;;;sBAGzD,KAAK;;EAOxB;AAED,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,EAC5B,OAAO,EACP,SAAoB,EACpB,YAAY,GACb,EAAE,kBAAkB,GAAG;IAAE,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;;;;;;;;;;;;EAQhD"}
|
package/dist/routes/index.js
CHANGED
|
@@ -13,6 +13,18 @@ import { LoginPage } from "../components/layout/LoginPage.js";
|
|
|
13
13
|
import { ResetWachtwoordPage } from "../components/layout/ResetWachtwoordPage.js";
|
|
14
14
|
import { HandoverPage } from "../components/layout/HandoverPage.js";
|
|
15
15
|
import { safeRedirectPath } from "../auth/redirect.js";
|
|
16
|
+
function pageHead(title, description) {
|
|
17
|
+
return {
|
|
18
|
+
meta: [
|
|
19
|
+
{ title },
|
|
20
|
+
{ name: "description", content: description },
|
|
21
|
+
{ property: "og:title", content: title },
|
|
22
|
+
{ property: "og:description", content: description },
|
|
23
|
+
{ property: "og:type", content: "website" },
|
|
24
|
+
{ name: "twitter:card", content: "summary" },
|
|
25
|
+
],
|
|
26
|
+
};
|
|
27
|
+
}
|
|
16
28
|
function isAuthenticated(context) {
|
|
17
29
|
return Boolean(context?.auth?.isAuthenticated);
|
|
18
30
|
}
|
|
@@ -25,16 +37,16 @@ export function loginRoute({ landing }) {
|
|
|
25
37
|
throw redirect({ href: safeRedirectPath(search?.redirect, landing) });
|
|
26
38
|
}
|
|
27
39
|
},
|
|
28
|
-
head: () => (
|
|
40
|
+
head: () => pageHead("Inloggen | Flora Select", "Log veilig in bij Flora Select."),
|
|
29
41
|
component: function LoginRouteComponent() {
|
|
30
|
-
return _jsx(LoginPage, { redirectTo: landing });
|
|
42
|
+
return _jsx(LoginPage, { redirectTo: landing, routeHandlesRedirect: true });
|
|
31
43
|
},
|
|
32
44
|
};
|
|
33
45
|
}
|
|
34
46
|
/** `/reset-wachtwoord`: de core-pagina, daarna naar `landing`. */
|
|
35
47
|
export function resetPasswordRoute({ landing, loginPath = "/login" }) {
|
|
36
48
|
return {
|
|
37
|
-
head: () => (
|
|
49
|
+
head: () => pageHead("Nieuw wachtwoord | Flora Select", "Stel een nieuw wachtwoord in voor Flora Select."),
|
|
38
50
|
component: function ResetPasswordRouteComponent() {
|
|
39
51
|
return _jsx(ResetWachtwoordPage, { redirectTo: landing, loginPath: loginPath });
|
|
40
52
|
},
|
|
@@ -43,6 +55,7 @@ export function resetPasswordRoute({ landing, loginPath = "/login" }) {
|
|
|
43
55
|
/** `/`: redirect in beforeLoad, dus er wordt niets gerenderd (geen flits). */
|
|
44
56
|
export function landingRoute({ landing }) {
|
|
45
57
|
return {
|
|
58
|
+
head: () => pageHead("Flora Select", "Open de Flora Select-omgeving."),
|
|
46
59
|
beforeLoad: () => {
|
|
47
60
|
throw redirect({ href: landing });
|
|
48
61
|
},
|
|
@@ -55,7 +68,7 @@ export function landingRoute({ landing }) {
|
|
|
55
68
|
export function handoverRoute({ landing, loginPath = "/login", exchangePath, }) {
|
|
56
69
|
return {
|
|
57
70
|
ssr: false,
|
|
58
|
-
head: () => (
|
|
71
|
+
head: () => pageHead("Aanmelden | Flora Select", "Rond de veilige aanmelding bij Flora Select af."),
|
|
59
72
|
component: function HandoverRouteComponent() {
|
|
60
73
|
return _jsx(HandoverPage, { redirectTo: landing, loginPath: loginPath, exchangePath: exchangePath });
|
|
61
74
|
},
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/* Flora Select — standaardhuisstijl van core. Afgeleid uit tokens.json.
|
|
2
|
+
Shells met src/brand.generated.css (update-dashboard) overschrijven dit. */
|
|
3
|
+
:root {
|
|
4
|
+
--radius: 8px;
|
|
5
|
+
--background: #F6F7F5; --foreground: #21221F;
|
|
6
|
+
--card: #FFFFFF; --card-foreground: #21221F;
|
|
7
|
+
--popover: #FFFFFF; --popover-foreground: #21221F;
|
|
8
|
+
--primary: #426F14; --primary-foreground: #FFFFFF;
|
|
9
|
+
--secondary: #EEEFEC; --secondary-foreground: #21221F;
|
|
10
|
+
--muted: #EEEFEC; --muted-foreground: #5F625A;
|
|
11
|
+
--accent: #F0FBE9; --accent-foreground: #426F14;
|
|
12
|
+
--destructive: #C64B36; --destructive-foreground: #FFFFFF;
|
|
13
|
+
--destructive-soft: #FFF4F2; --destructive-soft-foreground: #A23725;
|
|
14
|
+
--success: #426F14; --success-foreground: #FFFFFF;
|
|
15
|
+
--success-soft: #F0FBE9; --success-soft-foreground: #426F14;
|
|
16
|
+
--warning: #F4B854; --warning-foreground: #2F1E00;
|
|
17
|
+
--warning-soft: #FFF5E7; --warning-soft-foreground: #805800;
|
|
18
|
+
--info: #166B82; --info-foreground: #FFFFFF;
|
|
19
|
+
--info-soft: #EBFAFF; --info-soft-foreground: #166B82;
|
|
20
|
+
--brand: #6DA43F;
|
|
21
|
+
--border: #DEE0DB; --input: #90938A; --ring: #558A25;
|
|
22
|
+
--chart-1: #6DA43F; --chart-2: #449FBB; --chart-3: #E1A01D;
|
|
23
|
+
--chart-4: #D75841; --chart-5: #C7787E;
|
|
24
|
+
--sidebar: #244008; --sidebar-foreground: #F0FBE9;
|
|
25
|
+
--sidebar-primary: #426F14; --sidebar-primary-foreground: #F0FBE9;
|
|
26
|
+
--sidebar-accent: #426F14; --sidebar-accent-foreground: #F0FBE9;
|
|
27
|
+
--sidebar-border: #31560A; --sidebar-ring: #558A25;
|
|
28
|
+
--sidebar-muted: #BFD7AA;
|
|
29
|
+
}
|
|
30
|
+
.dark {
|
|
31
|
+
--background: #181A16; --foreground: #F6F7F5;
|
|
32
|
+
--card: #21221F; --card-foreground: #F6F7F5;
|
|
33
|
+
--popover: #21221F; --popover-foreground: #F6F7F5;
|
|
34
|
+
--primary: #8EC168; --primary-foreground: #142803;
|
|
35
|
+
--secondary: #121410; --secondary-foreground: #F6F7F5;
|
|
36
|
+
--muted: #121410; --muted-foreground: #ADB1A8;
|
|
37
|
+
--accent: #142803; --accent-foreground: #8EC168;
|
|
38
|
+
--destructive: #FF8972; --destructive-foreground: #3E1008;
|
|
39
|
+
--destructive-soft: #3E1008; --destructive-soft-foreground: #FFB6A6;
|
|
40
|
+
--success: #B0DA93; --success-foreground: #142803;
|
|
41
|
+
--success-soft: #142803; --success-soft-foreground: #B0DA93;
|
|
42
|
+
--warning: #F4B854; --warning-foreground: #2F1E00;
|
|
43
|
+
--warning-soft: #2F1E00; --warning-soft-foreground: #FFCF83;
|
|
44
|
+
--info: #99D5EB; --info-foreground: #142803;
|
|
45
|
+
--info-soft: #042630; --info-soft-foreground: #99D5EB;
|
|
46
|
+
--brand: #6DA43F;
|
|
47
|
+
--border: #494B45; --input: #777A72; --ring: #8EC168;
|
|
48
|
+
--chart-1: #6DA43F; --chart-2: #449FBB; --chart-3: #E1A01D;
|
|
49
|
+
--chart-4: #D75841; --chart-5: #C7787E;
|
|
50
|
+
--sidebar: #142803; --sidebar-foreground: #F0FBE9;
|
|
51
|
+
--sidebar-primary: #31560A; --sidebar-primary-foreground: #F0FBE9;
|
|
52
|
+
--sidebar-accent: #31560A; --sidebar-accent-foreground: #F0FBE9;
|
|
53
|
+
--sidebar-border: #244008; --sidebar-ring: #8EC168;
|
|
54
|
+
--sidebar-muted: #BFD7AA;
|
|
55
|
+
}
|
package/dist/styles.css
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
@import "tailwindcss";
|
|
2
2
|
@import "tw-animate-css";
|
|
3
|
-
|
|
3
|
+
@import "./styles/brand-default.css";
|
|
4
4
|
|
|
5
5
|
@custom-variant dark (&:is(.dark *));
|
|
6
6
|
|
|
@@ -34,10 +34,21 @@
|
|
|
34
34
|
--color-accent-foreground: var(--accent-foreground);
|
|
35
35
|
--color-destructive: var(--destructive);
|
|
36
36
|
--color-destructive-foreground: var(--destructive-foreground);
|
|
37
|
+
--color-destructive-soft: var(--destructive-soft);
|
|
38
|
+
--color-destructive-soft-foreground: var(--destructive-soft-foreground);
|
|
37
39
|
--color-success: var(--success);
|
|
38
40
|
--color-success-foreground: var(--success-foreground);
|
|
41
|
+
--color-success-soft: var(--success-soft);
|
|
42
|
+
--color-success-soft-foreground: var(--success-soft-foreground);
|
|
39
43
|
--color-warning: var(--warning);
|
|
40
44
|
--color-warning-foreground: var(--warning-foreground);
|
|
45
|
+
--color-warning-soft: var(--warning-soft);
|
|
46
|
+
--color-warning-soft-foreground: var(--warning-soft-foreground);
|
|
47
|
+
--color-info: var(--info);
|
|
48
|
+
--color-info-foreground: var(--info-foreground);
|
|
49
|
+
--color-info-soft: var(--info-soft);
|
|
50
|
+
--color-info-soft-foreground: var(--info-soft-foreground);
|
|
51
|
+
--color-brand: var(--brand);
|
|
41
52
|
--color-border: var(--border);
|
|
42
53
|
--color-input: var(--input);
|
|
43
54
|
--color-ring: var(--ring);
|
|
@@ -56,47 +67,8 @@
|
|
|
56
67
|
--color-sidebar-ring: var(--sidebar-ring);
|
|
57
68
|
--color-sidebar-muted: var(--sidebar-muted);
|
|
58
69
|
--font-sans: 'Inter', ui-sans-serif, system-ui, sans-serif;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
:root {
|
|
62
|
-
--radius: 0.5rem;
|
|
63
|
-
--background: hsl(210 20% 98%);
|
|
64
|
-
--foreground: hsl(214 79% 15%);
|
|
65
|
-
--card: hsl(0 0% 100%);
|
|
66
|
-
--card-foreground: hsl(214 79% 15%);
|
|
67
|
-
--popover: hsl(0 0% 100%);
|
|
68
|
-
--popover-foreground: hsl(214 79% 15%);
|
|
69
|
-
--primary: hsl(214 79% 33%);
|
|
70
|
-
--primary-foreground: hsl(0 0% 100%);
|
|
71
|
-
--secondary: hsl(214 30% 93%);
|
|
72
|
-
--secondary-foreground: hsl(214 79% 33%);
|
|
73
|
-
--muted: hsl(210 20% 96%);
|
|
74
|
-
--muted-foreground: hsl(214 20% 46%);
|
|
75
|
-
--accent: hsl(214 60% 90%);
|
|
76
|
-
--accent-foreground: hsl(214 79% 25%);
|
|
77
|
-
--destructive: hsl(0 72% 51%);
|
|
78
|
-
--destructive-foreground: hsl(0 0% 100%);
|
|
79
|
-
--success: hsl(142 71% 45%);
|
|
80
|
-
--success-foreground: hsl(0 0% 100%);
|
|
81
|
-
--warning: hsl(38 92% 50%);
|
|
82
|
-
--warning-foreground: hsl(0 0% 100%);
|
|
83
|
-
--border: hsl(214 20% 88%);
|
|
84
|
-
--input: hsl(214 20% 88%);
|
|
85
|
-
--ring: hsl(214 79% 33%);
|
|
86
|
-
--chart-1: hsl(214 79% 33%);
|
|
87
|
-
--chart-2: hsl(142 71% 45%);
|
|
88
|
-
--chart-3: hsl(38 92% 50%);
|
|
89
|
-
--chart-4: hsl(0 72% 51%);
|
|
90
|
-
--chart-5: hsl(280 60% 50%);
|
|
91
|
-
--sidebar: hsl(214 79% 33%);
|
|
92
|
-
--sidebar-foreground: hsl(0 0% 100%);
|
|
93
|
-
--sidebar-primary: hsl(0 0% 100%);
|
|
94
|
-
--sidebar-primary-foreground: hsl(214 79% 33%);
|
|
95
|
-
--sidebar-accent: hsl(214 79% 40%);
|
|
96
|
-
--sidebar-accent-foreground: hsl(0 0% 100%);
|
|
97
|
-
--sidebar-border: hsl(214 79% 45%);
|
|
98
|
-
--sidebar-ring: hsl(0 0% 100%);
|
|
99
|
-
--sidebar-muted: hsl(214 60% 70%);
|
|
70
|
+
--font-display: 'Fraunces', ui-serif, Georgia, serif;
|
|
71
|
+
--font-mono: 'JetBrains Mono', ui-monospace, monospace;
|
|
100
72
|
}
|
|
101
73
|
|
|
102
74
|
@layer base {
|
|
@@ -108,6 +80,25 @@
|
|
|
108
80
|
background-color: var(--color-background);
|
|
109
81
|
color: var(--color-foreground);
|
|
110
82
|
font-family: var(--font-sans);
|
|
83
|
+
font-size: 14px;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
:focus-visible {
|
|
87
|
+
outline: 2px solid var(--color-ring) !important;
|
|
88
|
+
outline-offset: 2px !important;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
code, kbd, pre, .font-mono {
|
|
92
|
+
font-family: var(--font-mono);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.font-display, [data-empty-state] {
|
|
96
|
+
font-family: var(--font-display);
|
|
97
|
+
font-variation-settings: 'SOFT' 100;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
table td, table th {
|
|
101
|
+
font-variant-numeric: tabular-nums;
|
|
111
102
|
}
|
|
112
103
|
|
|
113
104
|
.sidebar-scroll::-webkit-scrollbar {
|