@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.
Files changed (50) hide show
  1. package/README.md +18 -3
  2. package/dist/components/layout/BrandLogo.d.ts +9 -0
  3. package/dist/components/layout/BrandLogo.d.ts.map +1 -0
  4. package/dist/components/layout/BrandLogo.js +12 -0
  5. package/dist/components/layout/BugsDialog.js +4 -4
  6. package/dist/components/layout/LoginPage.d.ts +6 -1
  7. package/dist/components/layout/LoginPage.d.ts.map +1 -1
  8. package/dist/components/layout/LoginPage.js +11 -5
  9. package/dist/components/layout/NotificationBell.js +1 -1
  10. package/dist/components/layout/ResetWachtwoordPage.js +1 -1
  11. package/dist/components/layout/Sidebar.d.ts +1 -1
  12. package/dist/components/layout/Sidebar.d.ts.map +1 -1
  13. package/dist/components/layout/Sidebar.js +4 -3
  14. package/dist/components/ui/alert.js +1 -1
  15. package/dist/components/ui/badge.d.ts +1 -1
  16. package/dist/components/ui/badge.d.ts.map +1 -1
  17. package/dist/components/ui/badge.js +5 -2
  18. package/dist/components/ui/button.js +5 -5
  19. package/dist/components/ui/calendar.js +1 -1
  20. package/dist/components/ui/card.js +1 -1
  21. package/dist/components/ui/checkbox.js +1 -1
  22. package/dist/components/ui/input-otp.js +1 -1
  23. package/dist/components/ui/input.js +1 -1
  24. package/dist/components/ui/menubar.js +1 -1
  25. package/dist/components/ui/navigation-menu.js +1 -1
  26. package/dist/components/ui/radio-group.js +1 -1
  27. package/dist/components/ui/resizable.js +1 -1
  28. package/dist/components/ui/select.js +1 -1
  29. package/dist/components/ui/sidebar.js +3 -3
  30. package/dist/components/ui/slider.js +1 -1
  31. package/dist/components/ui/sonner.js +1 -1
  32. package/dist/components/ui/switch.js +1 -1
  33. package/dist/components/ui/tabs.js +1 -1
  34. package/dist/components/ui/textarea.js +1 -1
  35. package/dist/components/ui/toggle.js +2 -2
  36. package/dist/extensions/ShellExtensions.d.ts +15 -4
  37. package/dist/extensions/ShellExtensions.d.ts.map +1 -1
  38. package/dist/extensions/ShellExtensions.js +6 -3
  39. package/dist/hooks/useLogoSrc.d.ts +3 -3
  40. package/dist/hooks/useLogoSrc.d.ts.map +1 -1
  41. package/dist/hooks/useLogoSrc.js +4 -25
  42. package/dist/index.d.ts +1 -1
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/permissions/ModuleAccessGuard.js +1 -1
  45. package/dist/routes/index.d.ts +63 -6
  46. package/dist/routes/index.d.ts.map +1 -1
  47. package/dist/routes/index.js +17 -4
  48. package/dist/styles/brand-default.css +55 -0
  49. package/dist/styles.css +33 -42
  50. 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
- Tokens staan op één plek: `src/core/styles.css`, ook als
170
- `@flowselections/core/styles.css`. Logo: `logoSrc`-prop, anders `logo` uit
171
- `/huisstijl.json`, anders `/logo.png`.
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: "default" },
18
- resolved: { label: "Opgelost", variant: "secondary" },
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: "default", children: "In behandeling" }) }), _jsx(SelectItem, { value: "resolved", children: _jsx(Badge, { variant: "secondary", children: "Opgelost" }) })] })] }), _jsx("span", { className: "text-xs text-muted-foreground", children: formatDate(bug.created_at) })] })] }, bug.id));
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":"AAWA,UAAU,cAAc;IACtB,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,SAAS,CAAC,EAAE,UAA4B,EAAE,EAAE,cAAc,2CA+HzE"}
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
- export function LoginPage({ redirectTo = "/instellingen" }) {
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
- const target = readRedirectParam(redirectTo);
50
- await router.navigate({ href: target, replace: true });
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
- /** Sinds 1.0.23. Logopad; anders `logo` uit /huisstijl.json, anders /logo.png. */
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;AAOjE,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,kFAAkF;IAClF,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;AAmKD;;;GAGG;AACH,wBAAgB,OAAO,CAAC,EACtB,IAAI,EACJ,OAAO,EACP,OAAO,EACP,WAAmB,EACnB,OAAO,EACP,YAAmB,EACnB,cAAc,EACd,OAAO,GACR,EAAE,YAAY,2CA2Dd"}
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("img", { src: logoSrc, alt: "Logo", className: "max-h-24 w-auto max-w-full object-contain" }) }), _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
+ 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("img", { src: logo, alt: "Logo", className: "h-8 w-auto max-w-[10rem] object-contain" })] }), _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
+ 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 text-destructive dark:border-destructive [&>svg]:text-destructive",
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;;8EAkBlB,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"}
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 shadow hover:bg-primary/80",
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 shadow hover:bg-destructive/80",
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-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", {
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 shadow hover:bg-primary/90",
10
- destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
11
- outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
12
- secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
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 shadow-xs has-focus:ring-ring/50 has-focus:ring-[3px] relative rounded-md border", defaultClassNames.dropdown_root),
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-xl border bg-card text-card-foreground shadow", className), ...props })));
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 shadow focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring 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" }) }) })));
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 shadow-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" }) }))] }));
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 shadow-sm 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-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", className), ref: ref, ...props }));
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 shadow-sm", className), ...props })));
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 bg-border shadow-md" }) })));
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 shadow focus:outline-none focus-visible:ring-1 focus-visible:ring-ring 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" }) }) }));
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-1 focus-visible:ring-ring focus-visible:ring-offset-1 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" }) })) }));
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 shadow-sm ring-offset-background data-[placeholder]:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring 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" }) })] })));
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 group-data-[variant=floating]:shadow", children: children }) })] }));
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-xl md:peer-data-[variant=inset]:shadow", className), ...props }));
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: "bg-background shadow-[0_0_0_1px_var(--sidebar-border)] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_var(--sidebar-accent)]",
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 shadow transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50" })] })));
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 group-[.toaster]:shadow-lg",
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-transparent shadow-sm 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]: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 bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0") }) })));
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]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow", className), ...props })));
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 shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 md:text-sm", className), ref: ref, ...props }));
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-1 focus-visible:ring-ring 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", {
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 shadow-sm hover:bg-accent hover:text-accent-foreground",
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
- /** Transformeert de modulelijst (filteren en/of sorteren). Puur, geen side effects. */
4
- export type ModuleListTransform = (modules: FlowModule[]) => FlowModule[];
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. Zonder provider, tijdens laden of bij
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,uFAAuF;AACvF,MAAM,MAAM,mBAAmB,GAAG,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,UAAU,EAAE,CAAC;AAE1E,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;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,UAAU,EAAE,CAuB1E"}
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. Zonder provider, tijdens laden of bij
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.png";
1
+ export declare const DEFAULT_LOGO_SRC = "/brand/logo-wit.svg";
2
2
  /**
3
- * Sinds 1.0.23. Logopad: prop wint, dan `logo` uit `/huisstijl.json`, dan
4
- * `/logo.png`.
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":"AAEA,eAAO,MAAM,gBAAgB,cAAc,CAAC;AAa5C;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,CAWhD"}
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"}
@@ -1,29 +1,8 @@
1
- import { useEffect, useState } from "react";
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
- * Sinds 1.0.23. Logopad: prop wint, dan `logo` uit `/huisstijl.json`, dan
15
- * `/logo.png`.
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
- const [fromFile, setFromFile] = useState(null);
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";
@@ -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
  }
@@ -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":"AAeA,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;sBAEzD,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"}
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"}
@@ -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: () => ({ meta: [{ title: "Inloggen" }] }),
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: () => ({ meta: [{ title: "Nieuw wachtwoord instellen" }] }),
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: () => ({ meta: [{ title: "Aanmelden" }] }),
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 {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowselections/core",
3
- "version": "1.0.26",
3
+ "version": "1.0.27",
4
4
  "private": false,
5
5
  "sideEffects": false,
6
6
  "type": "module",