@flowselections/core 1.0.25 → 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 (53) hide show
  1. package/README.md +21 -6
  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/server/permissions.server.d.ts +6 -1
  49. package/dist/server/permissions.server.d.ts.map +1 -1
  50. package/dist/server/permissions.server.js +38 -14
  51. package/dist/styles/brand-default.css +55 -0
  52. package/dist/styles.css +33 -42
  53. package/package.json +116 -116
@@ -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
  },
@@ -11,8 +11,13 @@ export type PermissionLevel = "none" | "view" | "edit";
11
11
  *
12
12
  * - Ontbreekt de RPC (add-on niet geïnstalleerd) → toegestaan (default-allow).
13
13
  * - Geen geldige sessie → 401. Onvoldoende rechten → 403.
14
+ *
15
+ * `request` is optioneel: geef `getRequest()` mee (uit de code van je eigen
16
+ * shell, die door de Start-compiler wél getransformeerd wordt) als jouw runtime
17
+ * het actuele verzoek niet zelf blootgeeft. Aan het antwoord verandert niets:
18
+ * het token wordt hoe dan ook bij Supabase Auth gevalideerd.
14
19
  */
15
- export declare function requireModulePermission(supabase: SupabaseClient<any, any, any>, moduleId: string, featureId?: string | null, level?: PermissionLevel): Promise<PermissionLevel>;
20
+ export declare function requireModulePermission(supabase: SupabaseClient<any, any, any>, moduleId: string, featureId?: string | null, level?: PermissionLevel, request?: Request | null): Promise<PermissionLevel>;
16
21
  export { getRoleFlags };
17
22
  /**
18
23
  * Sinds 1.0.23. Superadmin? Claims eerst, terugval tabel `user_roles` (RLS:
@@ -1 +1 @@
1
- {"version":3,"file":"permissions.server.d.ts","sourceRoot":"","sources":["../../src/core/server/permissions.server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAEhD,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAuCvD;;;;;;;;;;GAUG;AACH,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EACvC,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,MAAM,GAAG,IAAW,EAC/B,KAAK,GAAE,eAAwB,GAC9B,OAAO,CAAC,eAAe,CAAC,CAyB1B;AAED,OAAO,EAAE,YAAY,EAAE,CAAC;AAExB;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EACvC,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GACtC,OAAO,CAAC,OAAO,CAAC,CAKlB"}
1
+ {"version":3,"file":"permissions.server.d.ts","sourceRoot":"","sources":["../../src/core/server/permissions.server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AA8BhD,MAAM,MAAM,eAAe,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAuCvD;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EACvC,QAAQ,EAAE,MAAM,EAChB,SAAS,GAAE,MAAM,GAAG,IAAW,EAC/B,KAAK,GAAE,eAAwB,EAC/B,OAAO,CAAC,EAAE,OAAO,GAAG,IAAI,GACvB,OAAO,CAAC,eAAe,CAAC,CAyB1B;AAED,OAAO,EAAE,YAAY,EAAE,CAAC;AAExB;;;GAGG;AACH,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EACvC,MAAM,EAAE,MAAM,EACd,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GACtC,OAAO,CAAC,OAAO,CAAC,CAKlB"}
@@ -1,5 +1,28 @@
1
- import { getRequest } from "@tanstack/react-start/server";
2
1
  import { getRoleFlags } from "../auth/roles.js";
2
+ /**
3
+ * `@tanstack/react-start/server` mag hier **niet** statisch geïmporteerd worden
4
+ * (ook niet als letterlijke `import()`): het trekt `@tanstack/start-server-core`
5
+ * (node:async_hooks) in de bundel. Elke shell waarvan een module `./server` in
6
+ * zijn hoofdbarrel her-exporteert, breekt dan op de clientbuild.
7
+ *
8
+ * De specifier wordt pas ter plaatse in mekaar gezet, zodat geen enkele bundler
9
+ * hem statisch kan ontleden. De import draait dus uitsluitend op de server.
10
+ */
11
+ const REACT_START_SERVER = ["@tanstack", "react-start", "server"].join("/");
12
+ /** Het actuele verzoek, voor zover de runtime dat prijsgeeft. */
13
+ async function ambientRequest() {
14
+ try {
15
+ const mod = (await import(/* @vite-ignore */ REACT_START_SERVER));
16
+ return mod.getRequest?.() ?? null;
17
+ }
18
+ catch {
19
+ return null;
20
+ }
21
+ }
22
+ async function readRequestHeader(name, request) {
23
+ const req = request ?? (await ambientRequest());
24
+ return req?.headers?.get(name) ?? null;
25
+ }
3
26
  const RANK = { none: 0, view: 1, edit: 2 };
4
27
  function isMissingRpc(error) {
5
28
  const e = (error ?? {});
@@ -13,21 +36,17 @@ function isMissingRpc(error) {
13
36
  message.includes("could not find the function"));
14
37
  }
15
38
  /** Bearer-token van het huidige verzoek, of null. */
16
- function requestToken() {
17
- try {
18
- const header = getRequest()?.headers?.get("authorization") ?? "";
19
- return header.startsWith("Bearer ") ? header.slice(7) || null : null;
20
- }
21
- catch {
22
- return null;
23
- }
39
+ async function requestToken(request) {
40
+ const header = (await readRequestHeader("authorization", request)) ?? "";
41
+ return header.startsWith("Bearer ") ? header.slice(7) || null : null;
24
42
  }
25
43
  /**
26
44
  * Geverifieerde user-id: uitsluitend uit het token van het verzoek, gevalideerd
27
- * bij Supabase Auth (`getUser(token)`). Geen aanroeper-input.
45
+ * bij Supabase Auth (`getUser(token)`). Geen aanroeper-input: een meegegeven
46
+ * `request` is het verzoek zelf, geen ingevulde user-id.
28
47
  */
29
- async function verifiedUserId(supabase) {
30
- const token = requestToken();
48
+ async function verifiedUserId(supabase, request) {
49
+ const token = await requestToken(request);
31
50
  const { data, error } = token ? await supabase.auth.getUser(token) : await supabase.auth.getUser();
32
51
  if (error || !data?.user?.id)
33
52
  throw new Response("Unauthorized", { status: 401 });
@@ -43,9 +62,14 @@ async function verifiedUserId(supabase) {
43
62
  *
44
63
  * - Ontbreekt de RPC (add-on niet geïnstalleerd) → toegestaan (default-allow).
45
64
  * - Geen geldige sessie → 401. Onvoldoende rechten → 403.
65
+ *
66
+ * `request` is optioneel: geef `getRequest()` mee (uit de code van je eigen
67
+ * shell, die door de Start-compiler wél getransformeerd wordt) als jouw runtime
68
+ * het actuele verzoek niet zelf blootgeeft. Aan het antwoord verandert niets:
69
+ * het token wordt hoe dan ook bij Supabase Auth gevalideerd.
46
70
  */
47
- export async function requireModulePermission(supabase, moduleId, featureId = null, level = "view") {
48
- const userId = await verifiedUserId(supabase);
71
+ export async function requireModulePermission(supabase, moduleId, featureId = null, level = "view", request) {
72
+ const userId = await verifiedUserId(supabase, request);
49
73
  const { data, error } = await supabase.rpc("effective_module_permission", {
50
74
  _user_id: userId,
51
75
  _module_id: moduleId,
@@ -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 {