@statsbygg/layout 0.1.11 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -63,26 +63,97 @@ src/
63
63
 
64
64
  ## Usage
65
65
 
66
- ### Basic Setup
66
+ ### 1. Defining Your Route Tree
67
67
 
68
- In your Next.js zone's root layout file (`app/layout.tsx`):
68
+ The routing system uses **URL-Driven Logic**. You define a single `RouteNode` tree passed to `RootLayout`.
69
+
70
+ - **External Links**: Any path starting with `http` or `https` is treated as an external parent.
71
+ - **Internal Links**: Any relative path (e.g., `/`, `/about`) is treated as internal to your application (relative to your `basePath`).
72
+
73
+ #### Scenario A: Standard Application
74
+ *This app sits directly under the main Statsbygg site.*
69
75
 
70
76
  ```tsx
71
- import { RootLayout } from '@statsbygg/layout';
72
- import '@digdir/designsystemet-theme';
73
- import '@digdir/designsystemet-css';
77
+ // app/layout.tsx
78
+ import { RootLayout, RouteNode } from '@statsbygg/layout';
79
+
80
+ const ROUTES: RouteNode = {
81
+ label: 'Hjem',
82
+ path: 'https://statsbygg.no', // External Parent
83
+ children: [
84
+ {
85
+ label: 'My App',
86
+ path: '/', // App Root (relative to basePath)
87
+ children: [
88
+ { label: 'Page 1', path: '/page-1' },
89
+ { label: 'Page 2', path: '/page-2' },
90
+ ],
91
+ },
92
+ ],
93
+ };
74
94
 
75
95
  export default function Layout({ children }: { children: React.ReactNode }) {
76
96
  return (
77
97
  <html lang="no">
78
98
  <body>
79
- <RootLayout zoneName="your-app-zone">
80
- {children}
81
- </RootLayout>
99
+ <RootLayout routes={ROUTES}>{children}</RootLayout>
82
100
  </body>
83
101
  </html>
84
102
  );
85
103
  }
104
+
105
+ ```
106
+
107
+ #### Scenario B: Deeply Nested Microfrontend
108
+
109
+ *This app sits deep within a hierarchy of other applications.*
110
+
111
+ ```tsx
112
+ // app/layout.tsx
113
+ const ROUTES: RouteNode = {
114
+ label: 'Hjem',
115
+ path: 'https://statsbygg.no',
116
+ children: [
117
+ {
118
+ label: 'Parent Route',
119
+ path: 'https://statsbygg.no/parent-route', // External Parent 2
120
+ children: [
121
+ {
122
+ label: 'Your App Name',
123
+ path: '/', // Your App Root
124
+ children: [
125
+ { label: 'Your App Route', path: '/your-app-route' }
126
+ ]
127
+ }
128
+ ]
129
+ }
130
+ ]
131
+ };
132
+
133
+ ```
134
+
135
+ ### 2. Handling Dynamic Routes
136
+
137
+ For pages with dynamic IDs (e.g., `/properties/[id]`), use the `useBreadcrumbs` hook.
138
+
139
+ **Note:** You only need to define the *dynamic* portion of the path. The layout package automatically prepends the static parents (Home, App Root, etc.) defined in your `ROUTES` tree.
140
+
141
+ ```tsx
142
+ // app/properties/[id]/page.tsx
143
+ 'use client';
144
+ import { useBreadcrumbs } from '@statsbygg/layout';
145
+
146
+ export default function PropertyPage({ params, propertyName }) {
147
+
148
+ useBreadcrumbs([
149
+ { label: 'Properties', href: '/properties' },
150
+ { label: propertyName, href: `/properties/${params.id}` },
151
+ ]);
152
+
153
+ return <div>...</div>;
154
+ }
155
+ // Resulting Breadcrumbs: Home > My App > Properties > [Property Name]
156
+
86
157
  ```
87
158
 
88
159
  ### Using the Global Store
@@ -121,7 +192,7 @@ Main layout component that orchestrates the entire layout structure.
121
192
  ```tsx
122
193
  interface RootLayoutProps {
123
194
  children: React.ReactNode;
124
- zoneName: string;
195
+ routes: RouteNode;
125
196
  className?: string;
126
197
  }
127
198
  ```
@@ -69,6 +69,26 @@
69
69
  color: var(--ds-color-accent-text-default);
70
70
  }
71
71
 
72
+ .parentLink.active {
73
+ color: var(--ds-color-accent-text-default);
74
+ font-weight: 600;
75
+ text-decoration: none;
76
+ }
77
+
78
+ .childLink.active {
79
+ color: var(--ds-color-accent-text-default);
80
+ font-weight: 500;
81
+ text-decoration: none;
82
+ border-left: 2px solid var(--ds-color-accent-text-default);
83
+ padding-left: calc(var(--ds-size-2) - 2px); /* Adjust padding to prevent layout shift */
84
+ }
85
+
86
+ .compactLink.active {
87
+ color: var(--ds-color-accent-text-default);
88
+ font-weight: 600;
89
+ text-decoration: none;
90
+ }
91
+
72
92
  @keyframes fadeIn {
73
93
  from {
74
94
  opacity: 0;
@@ -0,0 +1,3 @@
1
+ .container {
2
+ /* Add your styles here */
3
+ }
package/dist/index.d.ts CHANGED
@@ -1,20 +1,34 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as zustand_middleware from 'zustand/middleware';
3
3
  import * as zustand from 'zustand';
4
+ import { ReactNode } from 'react';
5
+
6
+ type RouteNode = {
7
+ path: string;
8
+ label: string;
9
+ children?: RouteNode[];
10
+ };
11
+ type BreadcrumbItem = {
12
+ label: string;
13
+ href: string;
14
+ };
15
+ type AncestorChain = {
16
+ externalAncestors: RouteNode[];
17
+ appRoot: RouteNode | null;
18
+ };
19
+ declare function findAppRootWithAncestors(node: RouteNode, ancestors?: RouteNode[]): AncestorChain;
20
+ declare function getBreadcrumbs(routes: RouteNode, pathname: string): BreadcrumbItem[];
4
21
 
5
22
  type RootLayoutProps = {
6
23
  children: React.ReactNode;
7
- zone: string;
24
+ routes: RouteNode;
25
+ appBasePath?: string;
8
26
  className?: string;
9
27
  };
10
28
 
11
- declare function RootLayout({ children, zone, className, }: RootLayoutProps): react_jsx_runtime.JSX.Element;
29
+ declare function RootLayout({ children, routes, appBasePath, className }: RootLayoutProps): react_jsx_runtime.JSX.Element;
12
30
 
13
31
  type Theme = 'light' | 'dark' | 'system';
14
- type BreadcrumbItem = {
15
- label: string;
16
- href: string;
17
- };
18
32
  type GlobalState = {
19
33
  user?: {
20
34
  id: string;
@@ -30,7 +44,7 @@ type GlobalState = {
30
44
  setIsMenuOpen: (isOpen: boolean) => void;
31
45
  toggleMenu: () => void;
32
46
  setBreadcrumbs: (breadcrumbs: BreadcrumbItem[] | null) => void;
33
- initialize: () => void | Promise<void>;
47
+ initialize: () => void;
34
48
  };
35
49
  declare const useGlobalStore: zustand.UseBoundStore<Omit<zustand.StoreApi<GlobalState>, "setState" | "persist"> & {
36
50
  setState(partial: GlobalState | Partial<GlobalState> | ((state: GlobalState) => GlobalState | Partial<GlobalState>), replace?: false | undefined): unknown;
@@ -47,25 +61,41 @@ declare const useGlobalStore: zustand.UseBoundStore<Omit<zustand.StoreApi<Global
47
61
  }>;
48
62
 
49
63
  /**
50
- * Custom hook to override the default breadcrumb generation for a specific page.
51
- * Automatically resets breadcrumbs to null on unmount to restore default behavior
52
- * for subsequent pages.
53
- *
54
- * @param breadcrumbs - Array of breadcrumb items to display
55
- *
56
- * @example
57
- * ```tsx
58
- * function MyPage({ data }) {
59
- * useBreadcrumbs([
60
- * { label: 'Hjem', href: '/' },
61
- * { label: 'Parent', href: '/parent' },
62
- * { label: data.name, href: '#' }
63
- * ]);
64
+ * Hook for manually setting breadcrumbs on dynamic routes.
65
+ * Overrides automatic breadcrumb generation, preserving external ancestors.
64
66
  *
65
- * return <div>Page content</div>;
66
- * }
67
- * ```
67
+ * @param breadcrumbs - Array of breadcrumb items for the current dynamic route
68
68
  */
69
69
  declare function useBreadcrumbs(breadcrumbs: BreadcrumbItem[]): void;
70
70
 
71
- export { type GlobalState, RootLayout, type RootLayoutProps, useBreadcrumbs, useGlobalStore };
71
+ type SmartLinkProps = {
72
+ href: string;
73
+ appBasePath?: string;
74
+ external?: boolean;
75
+ className?: string;
76
+ children: ReactNode;
77
+ };
78
+
79
+ /**
80
+ * Determines if a given href belongs to the current zone, another zone or should be external
81
+ */
82
+ declare function SmartLink({ href, appBasePath, external, className, children, }: SmartLinkProps): react_jsx_runtime.JSX.Element;
83
+
84
+ type MenuItem = {
85
+ label: string;
86
+ href: string;
87
+ external?: boolean;
88
+ children?: MenuItem[];
89
+ };
90
+ type MenuSubsection = {
91
+ title: string;
92
+ items: MenuItem[];
93
+ };
94
+ type MenuSection = {
95
+ title: string;
96
+ layout?: 'columns' | 'subsections';
97
+ items?: MenuItem[];
98
+ subsections?: MenuSubsection[];
99
+ };
100
+
101
+ export { type BreadcrumbItem, type GlobalState, type MenuItem, type MenuSection, type MenuSubsection, RootLayout, type RootLayoutProps, type RouteNode, SmartLink, type SmartLinkProps, findAppRootWithAncestors, getBreadcrumbs, useBreadcrumbs, useGlobalStore };
package/dist/index.js CHANGED
@@ -2,154 +2,113 @@
2
2
 
3
3
  // src/components/RootLayout/RootLayout.tsx
4
4
  import { useEffect as useEffect2 } from "react";
5
- import clsx4 from "clsx";
5
+ import clsx5 from "clsx";
6
+ import { SkipLink } from "@digdir/designsystemet-react";
6
7
 
7
8
  // src/components/GlobalHeader/GlobalHeader.tsx
8
9
  import { Button as Button2, Link as Link2 } from "@digdir/designsystemet-react";
9
- import clsx2 from "clsx";
10
+ import { Search as Search2 } from "lucide-react";
11
+ import clsx3 from "clsx";
10
12
 
11
13
  // src/components/Breadcrumbs/Breadcrumbs.tsx
14
+ import { useMemo } from "react";
12
15
  import { usePathname } from "next/navigation";
13
16
  import { Breadcrumbs } from "@digdir/designsystemet-react";
14
17
  import clsx from "clsx";
15
- import styles from "./Breadcrumbs.module.css";
16
18
 
17
19
  // src/routes.ts
18
- var ZONE_TREES_INPUT = {
19
- sbno: {
20
- segment: "",
21
- // primary root route, no breadcrumb
22
- label: "Hjem",
23
- children: [
24
- { segment: "nyheter", label: "Nyheter" }
25
- ]
26
- },
27
- lokaler: {
28
- segment: "lokaler",
29
- label: "Statens eide og leide lokaler",
30
- children: [
31
- {
32
- segment: "lokalbruk",
33
- label: "Lokalbruk"
34
- },
35
- { segment: "veiledning", label: "Veiledning" },
36
- { segment: "statlige-eiendommer", label: "Statlige eiendommer" },
37
- { segment: "ledig-for-fremleie", label: "Ledig for fremleie" },
38
- { segment: "statistikk", label: "Statistikk" }
39
- ]
40
- }
41
- };
42
- var ROUTES_INDEX = {};
43
- var PARENT_INDEX = /* @__PURE__ */ new Map();
44
- var ZONE_TREES = {};
45
- function isSegmentNode(n) {
46
- return n.segment !== void 0 && n.path === void 0;
47
- }
48
- function isPathNode(n) {
49
- return n.path !== void 0;
20
+ function isExternalPath(path) {
21
+ return path.startsWith("http://") || path.startsWith("https://");
50
22
  }
51
- function joinPath(base, seg) {
52
- if (!base) return seg ? `/${seg}` : "/";
53
- return seg ? `${base.replace(/\/+$/, "")}/${seg.replace(/^\/+/, "")}` : base || "/";
23
+ function normalizePath(path) {
24
+ if (path === "/") return "/";
25
+ return path.replace(/\/+$/, "");
54
26
  }
55
- function normalizeToAbsolute(node, base = "") {
56
- var _a;
57
- const path = isSegmentNode(node) ? joinPath(base, node.segment) : isPathNode(node) ? node.path === "" ? "/" : node.path : "/";
58
- const children = ((_a = node.children) != null ? _a : []).map((c) => normalizeToAbsolute(c, path));
59
- return { path, label: node.label, children: children.length ? children : void 0 };
27
+ function formatSegmentLabel(segment) {
28
+ try {
29
+ const decoded = decodeURIComponent(segment).replace(/[-_]+/g, " ").trim();
30
+ return decoded ? decoded.charAt(0).toUpperCase() + decoded.slice(1) : segment;
31
+ } catch (e) {
32
+ return segment;
33
+ }
60
34
  }
61
- (function buildAll() {
62
- Object.keys(ZONE_TREES_INPUT).forEach((zone) => {
63
- ZONE_TREES[zone] = normalizeToAbsolute(ZONE_TREES_INPUT[zone]);
64
- });
65
- function walk(zone, node, parentKey) {
66
- var _a;
67
- const def = { zone, path: node.path, label: node.label };
68
- const key = `${zone}:${node.path}`;
69
- ROUTES_INDEX[zone].push(def);
70
- PARENT_INDEX.set(key, parentKey);
71
- for (const child of (_a = node.children) != null ? _a : []) {
72
- walk(zone, child, key);
73
- }
35
+ function findAppRootWithAncestors(node, ancestors = []) {
36
+ if (!isExternalPath(node.path)) {
37
+ return {
38
+ externalAncestors: ancestors,
39
+ appRoot: node
40
+ };
74
41
  }
75
- Object.keys(ZONE_TREES).forEach((zone) => {
76
- ROUTES_INDEX[zone] = [];
77
- walk(zone, ZONE_TREES[zone], null);
78
- });
79
- })();
80
- function findBestMatch(zone, pathname) {
81
- var _a;
82
- const list = (_a = ROUTES_INDEX[zone]) != null ? _a : [];
83
- let best;
84
- for (const r of list) {
85
- if (pathname === r.path) {
86
- best = r;
87
- break;
42
+ if (node.children) {
43
+ for (const child of node.children) {
44
+ const result = findAppRootWithAncestors(child, [...ancestors, node]);
45
+ if (result.appRoot) return result;
88
46
  }
89
- if (pathname.startsWith(r.path.endsWith("/") ? r.path : r.path + "/")) {
90
- if (!best || r.path.length > best.path.length) best = r;
91
- }
92
- }
93
- return best != null ? best : list.find((r) => {
94
- var _a2;
95
- return r.path === ((_a2 = ZONE_TREES[zone]) == null ? void 0 : _a2.path);
96
- });
97
- }
98
- function getZoneRoot(zone) {
99
- var _a;
100
- return ((_a = ZONE_TREES[zone]) == null ? void 0 : _a.path) || "/";
101
- }
102
- function labelFromSlug(slug) {
103
- try {
104
- const s = decodeURIComponent(slug).replace(/[-_]+/g, " ").trim();
105
- return s ? s.charAt(0).toUpperCase() + s.slice(1) : slug;
106
- } catch (e) {
107
- return slug;
108
47
  }
48
+ return { externalAncestors: ancestors, appRoot: null };
109
49
  }
110
- function getBreadcrumbs(zone, pathname) {
111
- var _a, _b;
112
- const normalizedPathname = pathname === "/" ? pathname : pathname.replace(/\/+$/, "");
113
- if (zone === "sbno" && normalizedPathname === "/") return [];
114
- const match = findBestMatch(zone, normalizedPathname);
115
- if (!match) return [];
116
- const chain = [];
117
- let key = `${zone}:${match.path}`;
118
- while (key) {
119
- const parentKey = PARENT_INDEX.get(key);
120
- const [z, p] = key.split(":");
121
- const def = ((_a = ROUTES_INDEX[z]) != null ? _a : []).find((r) => r.path === p);
122
- if (def) chain.unshift(def);
123
- key = parentKey != null ? parentKey : void 0;
50
+ function findInternalMatch(node, pathname, ancestors = []) {
51
+ const nodePath = normalizePath(node.path);
52
+ if (pathname === nodePath) {
53
+ return { node, ancestors };
124
54
  }
125
- const homeRoute = ((_b = ROUTES_INDEX.sbno) != null ? _b : []).find((r) => r.path === "/");
126
- if (homeRoute && !(chain.length === 1 && chain[0].zone === "sbno" && chain[0].path === "/") && (chain.length === 0 || chain[0].path !== homeRoute.path)) {
127
- chain.unshift(homeRoute);
55
+ if (node.children) {
56
+ for (const child of node.children) {
57
+ if (isExternalPath(child.path)) continue;
58
+ const result = findInternalMatch(child, pathname, [...ancestors, node]);
59
+ if (result) return result;
60
+ }
128
61
  }
129
- const last = chain[chain.length - 1];
130
- if (last && normalizedPathname !== last.path && normalizedPathname.startsWith(last.path.endsWith("/") ? last.path : last.path + "/")) {
131
- const segments = normalizedPathname.split("/").filter(Boolean);
132
- const tail = segments[segments.length - 1];
133
- chain.push({ zone, path: normalizedPathname, label: labelFromSlug(tail) });
62
+ const pathPrefix = nodePath === "/" ? "/" : nodePath + "/";
63
+ if (pathname.startsWith(pathPrefix) || pathname === nodePath) {
64
+ return { node, ancestors };
134
65
  }
135
- return chain.map((r) => ({ label: r.label, href: r.path }));
66
+ return null;
136
67
  }
137
- function transformHrefForZone(targetPath, currentZone, options) {
138
- const { isDev, prodUrl } = options;
139
- const targetZone = getZoneFromPathname(targetPath);
140
- const isCrossZone = targetZone !== currentZone;
141
- if (isCrossZone && isDev && prodUrl) {
142
- return `${prodUrl}${targetPath}`;
68
+ function getBreadcrumbs(routes, pathname) {
69
+ const normalizedPathname = normalizePath(pathname);
70
+ const { externalAncestors, appRoot } = findAppRootWithAncestors(routes);
71
+ if (!appRoot) {
72
+ return externalAncestors.map((node) => ({
73
+ label: node.label,
74
+ href: node.path
75
+ }));
143
76
  }
144
- const currentZoneRoot = getZoneRoot(currentZone);
145
- if (!isCrossZone && isDev && currentZoneRoot !== "/") {
146
- return targetPath.replace(currentZoneRoot, "") || "/";
77
+ const breadcrumbs = externalAncestors.map((node) => ({
78
+ label: node.label,
79
+ href: node.path
80
+ }));
81
+ const internalMatch = findInternalMatch(appRoot, normalizedPathname);
82
+ if (!internalMatch) {
83
+ breadcrumbs.push({ label: appRoot.label, href: appRoot.path });
84
+ return breadcrumbs;
147
85
  }
148
- return targetPath;
149
- }
150
- function getZoneFromPathname(pathname) {
151
- if (pathname.startsWith("/lokaler")) return "lokaler";
152
- return "sbno";
86
+ for (const ancestor of internalMatch.ancestors) {
87
+ breadcrumbs.push({
88
+ label: ancestor.label,
89
+ href: ancestor.path
90
+ });
91
+ }
92
+ breadcrumbs.push({
93
+ label: internalMatch.node.label,
94
+ href: internalMatch.node.path
95
+ });
96
+ const matchedPath = normalizePath(internalMatch.node.path);
97
+ if (normalizedPathname !== matchedPath) {
98
+ const remainingPath = normalizedPathname.slice(
99
+ matchedPath === "/" ? 1 : matchedPath.length + 1
100
+ );
101
+ const dynamicSegments = remainingPath.split("/").filter(Boolean);
102
+ let accumulatedPath = matchedPath;
103
+ for (const segment of dynamicSegments) {
104
+ accumulatedPath = accumulatedPath === "/" ? `/${segment}` : `${accumulatedPath}/${segment}`;
105
+ breadcrumbs.push({
106
+ label: formatSegmentLabel(segment),
107
+ href: accumulatedPath
108
+ });
109
+ }
110
+ }
111
+ return breadcrumbs;
153
112
  }
154
113
 
155
114
  // src/store/globalState.ts
@@ -191,32 +150,76 @@ var useGlobalStore = create()(
191
150
  })
192
151
  );
193
152
 
153
+ // src/locales/translations.ts
154
+ var translations = {
155
+ no: {
156
+ "common.menu": "Meny",
157
+ "common.close": "Lukk",
158
+ "common.search": "S\xF8k",
159
+ "common.searchLabel": "S\xF8k",
160
+ "common.youAreHere": "Du er her:",
161
+ "common.skipLink": "Hopp til hovedinnhold",
162
+ "common.home": "Hjem",
163
+ "footer.content": "Statsbygg Footer",
164
+ "menu.helpTitle": "Hva kan vi hjelpe deg med?",
165
+ "menu.mainMenuLabel": "Hovedmeny",
166
+ "menu.closeMenu": "Lukk meny",
167
+ "menu.openMenu": "\xC5pne meny"
168
+ }
169
+ };
170
+
171
+ // src/hooks/use-layout-translation.ts
172
+ function useLayoutTranslation() {
173
+ const locale = useGlobalStore((state) => state.locale);
174
+ const languageMap = translations[locale] || translations.no;
175
+ function t(key) {
176
+ return languageMap[key] || key;
177
+ }
178
+ return { t, locale };
179
+ }
180
+
194
181
  // src/components/Breadcrumbs/Breadcrumbs.tsx
182
+ import styles from "./Breadcrumbs.module.css";
195
183
  import { jsx } from "react/jsx-runtime";
196
- function SbBreadcrumbs({ className, zone }) {
184
+ function SbBreadcrumbs({ className, routes }) {
197
185
  const pathname = usePathname();
198
186
  const manualBreadcrumbs = useGlobalStore((state) => state.breadcrumbs);
199
- const isDev = process.env.NODE_ENV === "development";
200
- const prodUrl = "https://www.statsbygg.no";
201
- const zoneRoot = getZoneRoot(zone);
202
- const fullPath = isDev && zoneRoot !== "/" && !pathname.startsWith(zoneRoot) ? `${zoneRoot}${pathname}` : pathname;
203
- const breadcrumbs = manualBreadcrumbs != null ? manualBreadcrumbs : getBreadcrumbs(zone, fullPath);
204
- if (breadcrumbs.length <= 1) {
187
+ const { t } = useLayoutTranslation();
188
+ const breadcrumbs = useMemo(() => {
189
+ if (manualBreadcrumbs) {
190
+ const { externalAncestors } = findAppRootWithAncestors(routes);
191
+ const baseBreadcrumbs = externalAncestors.map((node) => ({
192
+ label: node.label,
193
+ href: node.path
194
+ }));
195
+ const manualHrefs = new Set(manualBreadcrumbs.map((b) => b.href));
196
+ const uniqueBase = baseBreadcrumbs.filter((b) => !manualHrefs.has(b.href));
197
+ return [...uniqueBase, ...manualBreadcrumbs];
198
+ }
199
+ return getBreadcrumbs(routes, pathname);
200
+ }, [routes, pathname, manualBreadcrumbs]);
201
+ if (breadcrumbs.length === 0) {
205
202
  return null;
206
203
  }
207
- return /* @__PURE__ */ jsx(Breadcrumbs, { "aria-label": "Du er her:", className: clsx(styles.breadcrumbs, className), children: /* @__PURE__ */ jsx(Breadcrumbs.List, { children: breadcrumbs.map((crumb, index) => {
208
- const isLast = index === breadcrumbs.length - 1;
209
- const href = manualBreadcrumbs ? crumb.href : transformHrefForZone(crumb.href, zone, { isDev, prodUrl });
210
- return /* @__PURE__ */ jsx(Breadcrumbs.Item, { children: /* @__PURE__ */ jsx(
211
- Breadcrumbs.Link,
212
- {
213
- href,
214
- "aria-current": isLast ? "page" : void 0,
215
- className: isLast ? styles.currentLink : styles.link,
216
- children: crumb.label
217
- }
218
- ) }, crumb.href);
219
- }) }) });
204
+ return /* @__PURE__ */ jsx(
205
+ Breadcrumbs,
206
+ {
207
+ "aria-label": t("common.youAreHere"),
208
+ className: clsx(styles.breadcrumbs, className),
209
+ children: /* @__PURE__ */ jsx(Breadcrumbs.List, { children: breadcrumbs.map((crumb, index) => {
210
+ const isLast = index === breadcrumbs.length - 1;
211
+ return /* @__PURE__ */ jsx(Breadcrumbs.Item, { children: /* @__PURE__ */ jsx(
212
+ Breadcrumbs.Link,
213
+ {
214
+ href: crumb.href,
215
+ "aria-current": isLast ? "page" : void 0,
216
+ className: isLast ? styles.currentLink : styles.link,
217
+ children: crumb.label
218
+ }
219
+ ) }, `${crumb.href}-${index}`);
220
+ }) })
221
+ }
222
+ );
220
223
  }
221
224
 
222
225
  // src/components/MenuButton/MenuButton.tsx
@@ -248,9 +251,7 @@ var NAVIGATION_MENU = [
248
251
  label: "For leietakere",
249
252
  href: "/for-leietakere",
250
253
  children: [
251
- { label: "Leieveileder", href: "/leietakere/leieveileder" },
252
- { label: "Lenke til underside", href: "/leietakere/lenke1" },
253
- { label: "Lenke til underside", href: "/leietakere/lenke2" }
254
+ { label: "Leieveileder", href: "/for-leietakere/leieveileder" }
254
255
  ]
255
256
  },
256
257
  {
@@ -259,8 +260,7 @@ var NAVIGATION_MENU = [
259
260
  children: [
260
261
  { label: "V\xE5re krav", href: "/byggebransjen/vare-krav" },
261
262
  { label: "BIM", href: "/byggebransjen/bim" },
262
- { label: "ByggBoks", href: "/byggebransjen/byggboks" },
263
- { label: "Lenke til underside", href: "/byggebransjen/lenke" }
263
+ { label: "ByggBoks", href: "/byggebransjen/byggboks" }
264
264
  ]
265
265
  },
266
266
  {
@@ -343,27 +343,74 @@ var NAVIGATION_MENU = [
343
343
  ];
344
344
 
345
345
  // src/components/NavigationMenuItem/NavigationMenuItem.tsx
346
- import { Link, List } from "@digdir/designsystemet-react";
346
+ import { List } from "@digdir/designsystemet-react";
347
347
  import { ExternalLink } from "lucide-react";
348
+ import { usePathname as usePathname2 } from "next/navigation";
349
+ import clsx2 from "clsx";
350
+
351
+ // src/components/SmartLink/SmartLink.tsx
352
+ import Link from "next/link";
353
+ import { Link as DsLink } from "@digdir/designsystemet-react";
354
+ import { jsx as jsx2 } from "react/jsx-runtime";
355
+ function SmartLink({
356
+ href,
357
+ appBasePath,
358
+ external = false,
359
+ className,
360
+ children
361
+ }) {
362
+ const isExternalUrl = href.startsWith("http://") || href.startsWith("https://");
363
+ const isLocalRoute = appBasePath && !isExternalUrl && (href === appBasePath || href.startsWith(`${appBasePath}/`));
364
+ if (isExternalUrl || external) {
365
+ return /* @__PURE__ */ jsx2(
366
+ DsLink,
367
+ {
368
+ href,
369
+ className,
370
+ target: "_blank",
371
+ rel: "noopener noreferrer",
372
+ children
373
+ }
374
+ );
375
+ }
376
+ if (isLocalRoute) {
377
+ const localHref = href.replace(appBasePath, "") || "/";
378
+ return /* @__PURE__ */ jsx2(Link, { href: localHref, className, children });
379
+ }
380
+ return /* @__PURE__ */ jsx2(DsLink, { href, className, children });
381
+ }
382
+
383
+ // src/components/NavigationMenuItem/NavigationMenuItem.tsx
348
384
  import styles2 from "./NavigationMenuItem.module.css";
349
- import { jsx as jsx2, jsxs } from "react/jsx-runtime";
350
- function NavigationMenuItem({ item, animationDelay, compact = false }) {
385
+ import { jsx as jsx3, jsxs } from "react/jsx-runtime";
386
+ function NavigationMenuItem({
387
+ item,
388
+ animationDelay,
389
+ compact = false,
390
+ appBasePath
391
+ }) {
392
+ const pathname = usePathname2();
393
+ const isActive = (href) => {
394
+ if (href === "/") return pathname === "/";
395
+ return pathname == null ? void 0 : pathname.startsWith(href);
396
+ };
397
+ const isParentActive = isActive(item.href);
351
398
  if (compact) {
352
- return /* @__PURE__ */ jsx2(
399
+ return /* @__PURE__ */ jsx3(
353
400
  "div",
354
401
  {
355
402
  className: styles2.itemColumn,
356
403
  style: { animationDelay: `${animationDelay}ms` },
357
404
  children: /* @__PURE__ */ jsxs(
358
- Link,
405
+ SmartLink,
359
406
  {
360
407
  href: item.href,
361
- className: styles2.compactLink,
362
- target: item.external ? "_blank" : void 0,
363
- rel: item.external ? "noopener noreferrer" : void 0,
408
+ appBasePath,
409
+ external: item.external,
410
+ className: clsx2(styles2.compactLink, isParentActive && styles2.active),
364
411
  children: [
365
412
  item.label,
366
- item.external && /* @__PURE__ */ jsx2(ExternalLink, { size: 16, "aria-hidden": "true" })
413
+ item.external && /* @__PURE__ */ jsx3(ExternalLink, { size: 16, "aria-hidden": "true" })
367
414
  ]
368
415
  }
369
416
  )
@@ -377,39 +424,42 @@ function NavigationMenuItem({ item, animationDelay, compact = false }) {
377
424
  style: { animationDelay: `${animationDelay}ms` },
378
425
  children: [
379
426
  /* @__PURE__ */ jsxs(
380
- Link,
427
+ SmartLink,
381
428
  {
382
429
  href: item.href,
383
- className: styles2.parentLink,
384
- target: item.external ? "_blank" : void 0,
385
- rel: item.external ? "noopener noreferrer" : void 0,
430
+ appBasePath,
431
+ external: item.external,
432
+ className: clsx2(styles2.parentLink, isParentActive && styles2.active),
386
433
  children: [
387
434
  item.label,
388
- item.external && /* @__PURE__ */ jsx2(ExternalLink, { size: 20, "aria-hidden": "true" })
435
+ item.external && /* @__PURE__ */ jsx3(ExternalLink, { size: 20, "aria-hidden": "true" })
389
436
  ]
390
437
  }
391
438
  ),
392
- item.children && item.children.length > 0 && /* @__PURE__ */ jsx2(List.Unordered, { className: styles2.childItems, children: item.children.map((child, childIndex) => /* @__PURE__ */ jsx2(
393
- List.Item,
394
- {
395
- className: styles2.childItem,
396
- style: { animationDelay: `${animationDelay + 30 + childIndex * 15}ms` },
397
- children: /* @__PURE__ */ jsxs(
398
- Link,
399
- {
400
- href: child.href,
401
- className: styles2.childLink,
402
- target: child.external ? "_blank" : void 0,
403
- rel: child.external ? "noopener noreferrer" : void 0,
404
- children: [
405
- child.label,
406
- child.external && /* @__PURE__ */ jsx2(ExternalLink, { size: 20, "aria-hidden": "true" })
407
- ]
408
- }
409
- )
410
- },
411
- childIndex
412
- )) })
439
+ item.children && item.children.length > 0 && /* @__PURE__ */ jsx3(List.Unordered, { className: styles2.childItems, children: item.children.map((child, childIndex) => {
440
+ const isChildActive = isActive(child.href);
441
+ return /* @__PURE__ */ jsx3(
442
+ List.Item,
443
+ {
444
+ className: styles2.childItem,
445
+ style: { animationDelay: `${animationDelay + 30 + childIndex * 15}ms` },
446
+ children: /* @__PURE__ */ jsxs(
447
+ SmartLink,
448
+ {
449
+ href: child.href,
450
+ appBasePath,
451
+ external: child.external,
452
+ className: clsx2(styles2.childLink, isChildActive && styles2.active),
453
+ children: [
454
+ child.label,
455
+ child.external && /* @__PURE__ */ jsx3(ExternalLink, { size: 16, "aria-hidden": "true" })
456
+ ]
457
+ }
458
+ )
459
+ },
460
+ childIndex
461
+ );
462
+ }) })
413
463
  ]
414
464
  }
415
465
  );
@@ -417,27 +467,26 @@ function NavigationMenuItem({ item, animationDelay, compact = false }) {
417
467
 
418
468
  // src/components/NavigationMenu/NavigationMenu.tsx
419
469
  import styles3 from "./NavigationMenu.module.css";
420
- import { Fragment, jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
421
- function NavigationMenu({ zone }) {
470
+ import { Fragment, jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
471
+ function NavigationMenu({ className, appBasePath }) {
422
472
  const [searchValue, setSearchValue] = useState("");
423
473
  const isMenuOpen = useGlobalStore((state) => state.isMenuOpen);
424
474
  const setIsMenuOpen = useGlobalStore((state) => state.setIsMenuOpen);
425
475
  const searchInputRef = useRef(null);
476
+ const { t } = useLayoutTranslation();
426
477
  useEffect(() => {
427
478
  if (!isMenuOpen) return;
428
- const handleEscape = (event) => {
479
+ function handleEscape(event) {
429
480
  if (event.key === "Escape") {
430
481
  setIsMenuOpen(false);
431
482
  }
432
- };
483
+ }
433
484
  setTimeout(() => {
434
485
  var _a;
435
486
  (_a = searchInputRef.current) == null ? void 0 : _a.focus();
436
487
  }, 100);
437
488
  document.addEventListener("keydown", handleEscape);
438
- return () => {
439
- document.removeEventListener("keydown", handleEscape);
440
- };
489
+ return () => document.removeEventListener("keydown", handleEscape);
441
490
  }, [setIsMenuOpen, isMenuOpen]);
442
491
  function handleBackdropClick(e) {
443
492
  if (e.target === e.currentTarget) {
@@ -445,26 +494,26 @@ function NavigationMenu({ zone }) {
445
494
  }
446
495
  }
447
496
  return /* @__PURE__ */ jsxs2(Fragment, { children: [
448
- isMenuOpen && /* @__PURE__ */ jsx3("div", { className: styles3.backdrop, onClick: handleBackdropClick }),
449
- /* @__PURE__ */ jsx3("div", { className: `${styles3.menuOverlay} ${!isMenuOpen ? styles3.hidden : ""}`, children: /* @__PURE__ */ jsxs2("div", { className: styles3.container, children: [
497
+ isMenuOpen && /* @__PURE__ */ jsx4("div", { className: styles3.backdrop, onClick: handleBackdropClick }),
498
+ /* @__PURE__ */ jsx4("div", { className: `${styles3.menuOverlay} ${!isMenuOpen ? styles3.hidden : ""} ${className != null ? className : ""}`, children: /* @__PURE__ */ jsxs2("div", { className: styles3.container, children: [
450
499
  /* @__PURE__ */ jsxs2("div", { className: styles3.searchSection, children: [
451
- /* @__PURE__ */ jsx3(Heading, { level: 1, children: "Hva kan vi hjelpe deg med?" }),
500
+ /* @__PURE__ */ jsx4(Heading, { level: 1, children: t("menu.helpTitle") }),
452
501
  /* @__PURE__ */ jsxs2(Search, { children: [
453
- /* @__PURE__ */ jsx3(
502
+ /* @__PURE__ */ jsx4(
454
503
  Search.Input,
455
504
  {
456
- "aria-label": "S\xF8k",
505
+ "aria-label": t("common.search"),
457
506
  ref: searchInputRef,
458
507
  value: searchValue,
459
508
  onChange: (e) => setSearchValue(e.target.value),
460
- placeholder: "S\xF8k",
509
+ placeholder: t("common.search"),
461
510
  className: styles3.searchField
462
511
  }
463
512
  ),
464
- /* @__PURE__ */ jsx3(Search.Clear, {})
513
+ /* @__PURE__ */ jsx4(Search.Clear, {})
465
514
  ] })
466
515
  ] }),
467
- /* @__PURE__ */ jsx3("nav", { className: styles3.menuSections, "aria-label": "Hovedmeny", children: NAVIGATION_MENU.map((section, sectionIndex) => {
516
+ /* @__PURE__ */ jsx4("nav", { className: styles3.menuSections, "aria-label": t("menu.mainMenuLabel"), children: NAVIGATION_MENU.map((section, sectionIndex) => {
468
517
  var _a;
469
518
  return /* @__PURE__ */ jsxs2(
470
519
  "section",
@@ -472,23 +521,25 @@ function NavigationMenu({ zone }) {
472
521
  className: styles3.section,
473
522
  style: { animationDelay: `${0.15 + sectionIndex * 0.06}s` },
474
523
  children: [
475
- section.layout !== "subsections" && /* @__PURE__ */ jsx3(Heading, { level: 2, className: styles3.sectionHeader, children: section.title }),
476
- section.layout === "subsections" && section.subsections ? /* @__PURE__ */ jsx3("div", { className: styles3.subsectionsGrid, children: section.subsections.map((subsection, subsectionIndex) => /* @__PURE__ */ jsxs2("div", { className: styles3.subsection, children: [
477
- /* @__PURE__ */ jsx3(Heading, { level: 2, className: styles3.subsectionHeader, children: subsection.title }),
478
- /* @__PURE__ */ jsx3("div", { className: styles3.subsectionItems, children: subsection.items.map((item, itemIndex) => /* @__PURE__ */ jsx3(
524
+ section.layout !== "subsections" && /* @__PURE__ */ jsx4(Heading, { level: 2, className: styles3.sectionHeader, children: section.title }),
525
+ section.layout === "subsections" && section.subsections ? /* @__PURE__ */ jsx4("div", { className: styles3.subsectionsGrid, children: section.subsections.map((subsection, subsectionIndex) => /* @__PURE__ */ jsxs2("div", { className: styles3.subsection, children: [
526
+ /* @__PURE__ */ jsx4(Heading, { level: 2, className: styles3.subsectionHeader, children: subsection.title }),
527
+ /* @__PURE__ */ jsx4("div", { className: styles3.subsectionItems, children: subsection.items.map((item, itemIndex) => /* @__PURE__ */ jsx4(
479
528
  NavigationMenuItem,
480
529
  {
481
530
  item,
482
531
  animationDelay: 150 + sectionIndex * 60 + subsectionIndex * 40 + itemIndex * 25,
532
+ appBasePath,
483
533
  compact: true
484
534
  },
485
535
  itemIndex
486
536
  )) })
487
- ] }, subsectionIndex)) }) : /* @__PURE__ */ jsx3("div", { className: sectionIndex === 2 ? styles3.itemsGridThreeCol : styles3.itemsGrid, children: (_a = section.items) == null ? void 0 : _a.map((item, itemIndex) => /* @__PURE__ */ jsx3(
537
+ ] }, subsectionIndex)) }) : /* @__PURE__ */ jsx4("div", { className: sectionIndex === 2 ? styles3.itemsGridThreeCol : styles3.itemsGrid, children: (_a = section.items) == null ? void 0 : _a.map((item, itemIndex) => /* @__PURE__ */ jsx4(
488
538
  NavigationMenuItem,
489
539
  {
490
540
  item,
491
- animationDelay: 150 + sectionIndex * 60 + itemIndex * 25
541
+ animationDelay: 150 + sectionIndex * 60 + itemIndex * 25,
542
+ appBasePath
492
543
  },
493
544
  itemIndex
494
545
  )) })
@@ -502,10 +553,11 @@ function NavigationMenu({ zone }) {
502
553
  }
503
554
 
504
555
  // src/components/MenuButton/MenuButton.tsx
505
- import { Fragment as Fragment2, jsx as jsx4, jsxs as jsxs3 } from "react/jsx-runtime";
506
- function MenuButton({ zone }) {
556
+ import { Fragment as Fragment2, jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
557
+ function MenuButton({ className, appBasePath }) {
507
558
  const isMenuOpen = useGlobalStore((state) => state.isMenuOpen);
508
559
  const toggleMenu = useGlobalStore((state) => state.toggleMenu);
560
+ const { t } = useLayoutTranslation();
509
561
  return /* @__PURE__ */ jsxs3(Fragment2, { children: [
510
562
  /* @__PURE__ */ jsxs3(
511
563
  Button,
@@ -513,93 +565,89 @@ function MenuButton({ zone }) {
513
565
  variant: "primary",
514
566
  onClick: toggleMenu,
515
567
  "aria-expanded": isMenuOpen,
516
- "aria-label": isMenuOpen ? "Lukk meny" : "\xC5pne meny",
568
+ "aria-label": isMenuOpen ? t("menu.closeMenu") : t("menu.openMenu"),
569
+ className,
517
570
  children: [
518
- isMenuOpen ? /* @__PURE__ */ jsx4(X, { size: 20, "aria-hidden": "true" }) : /* @__PURE__ */ jsx4(Menu, { size: 20, "aria-hidden": "true" }),
519
- isMenuOpen ? "Lukk" : "Meny"
571
+ isMenuOpen ? /* @__PURE__ */ jsx5(X, { size: 20, "aria-hidden": "true" }) : /* @__PURE__ */ jsx5(Menu, { size: 20, "aria-hidden": "true" }),
572
+ isMenuOpen ? t("common.close") : t("common.menu")
520
573
  ]
521
574
  }
522
575
  ),
523
- /* @__PURE__ */ jsx4(NavigationMenu, { zone })
576
+ /* @__PURE__ */ jsx5(NavigationMenu, { appBasePath })
524
577
  ] });
525
578
  }
526
579
 
527
580
  // src/components/GlobalHeader/GlobalHeader.tsx
528
581
  import styles4 from "./GlobalHeader.module.css";
529
- import { Search as Search2 } from "lucide-react";
530
- import { Fragment as Fragment3, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
531
- function GlobalHeader({ className, zone }) {
582
+ import { Fragment as Fragment3, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
583
+ function GlobalHeader({ className, routes, appBasePath }) {
532
584
  const isMenuOpen = useGlobalStore((state) => state.isMenuOpen);
533
585
  const setIsMenuOpen = useGlobalStore((state) => state.setIsMenuOpen);
534
586
  const setTheme = useGlobalStore((state) => state.setTheme);
535
587
  const theme = useGlobalStore((state) => state.theme);
588
+ const { t } = useLayoutTranslation();
536
589
  function toggleDarkMode() {
537
590
  setTheme(theme === "dark" ? "light" : "dark");
538
591
  }
539
- return /* @__PURE__ */ jsx5("header", { className: clsx2(styles4.header, isMenuOpen && styles4.menuOpen, className), children: /* @__PURE__ */ jsxs4("div", { className: styles4.headerContainer, children: [
592
+ return /* @__PURE__ */ jsx6("header", { className: clsx3(styles4.header, isMenuOpen && styles4.menuOpen, className), children: /* @__PURE__ */ jsxs4("div", { className: styles4.headerContainer, children: [
540
593
  /* @__PURE__ */ jsxs4("div", { className: styles4.topBarContainer, children: [
541
- /* @__PURE__ */ jsx5(Link2, { href: "https://www.statsbygg.no", children: /* @__PURE__ */ jsx5("img", { src: "https://dok.statsbygg.no/wp-content/uploads/2025/11/Statsbygg_logo.svg", alt: "Logo", className: styles4.logo }) }),
594
+ /* @__PURE__ */ jsx6(Link2, { href: "https://www.statsbygg.no", children: /* @__PURE__ */ jsx6(
595
+ "img",
596
+ {
597
+ src: "https://dok.statsbygg.no/wp-content/uploads/2025/11/Statsbygg_logo.svg",
598
+ alt: "Logo",
599
+ className: styles4.logo
600
+ }
601
+ ) }),
542
602
  /* @__PURE__ */ jsxs4("div", { className: styles4.actionsContainer, children: [
543
603
  !isMenuOpen && /* @__PURE__ */ jsxs4(Fragment3, { children: [
544
- ALLOW_DARK_THEME && /* @__PURE__ */ jsx5(Button2, { onClick: toggleDarkMode, className: styles4.themeToggleButton, children: theme === "dark" ? "\u2600\uFE0F" : "\u{1F319}" }),
604
+ ALLOW_DARK_THEME && /* @__PURE__ */ jsx6(Button2, { onClick: toggleDarkMode, className: styles4.themeToggleButton, children: theme === "dark" ? "\u2600\uFE0F" : "\u{1F319}" }),
545
605
  /* @__PURE__ */ jsxs4(
546
606
  Button2,
547
607
  {
548
608
  variant: "secondary",
549
609
  onClick: () => setIsMenuOpen(true),
550
610
  className: styles4.searchButton,
551
- "aria-label": "S\xF8k",
611
+ "aria-label": t("common.search"),
552
612
  children: [
553
- /* @__PURE__ */ jsx5(Search2, { size: 20, "aria-hidden": "true" }),
554
- "S\xF8k"
613
+ /* @__PURE__ */ jsx6(Search2, { size: 20, "aria-hidden": "true" }),
614
+ t("common.search")
555
615
  ]
556
616
  }
557
617
  )
558
618
  ] }),
559
- /* @__PURE__ */ jsx5(MenuButton, { zone })
619
+ /* @__PURE__ */ jsx6(MenuButton, { appBasePath })
560
620
  ] })
561
621
  ] }),
562
- /* @__PURE__ */ jsx5(SbBreadcrumbs, { zone })
622
+ /* @__PURE__ */ jsx6(SbBreadcrumbs, { routes })
563
623
  ] }) });
564
624
  }
565
625
 
566
626
  // src/components/GlobalFooter/GlobalFooter.tsx
567
627
  import { Paragraph } from "@digdir/designsystemet-react";
568
- import clsx3 from "clsx";
628
+ import clsx4 from "clsx";
569
629
  import styles5 from "./GlobalFooter.module.css";
570
- import { jsx as jsx6 } from "react/jsx-runtime";
630
+ import { jsx as jsx7 } from "react/jsx-runtime";
571
631
  function GlobalFooter({ className }) {
572
- return /* @__PURE__ */ jsx6("footer", { className: clsx3(styles5.footer, className), children: /* @__PURE__ */ jsx6("div", { className: styles5.container, children: /* @__PURE__ */ jsx6("div", { className: styles5.content, children: /* @__PURE__ */ jsx6(Paragraph, { children: "Statsbygg Footer" }) }) }) });
632
+ const { t } = useLayoutTranslation();
633
+ return /* @__PURE__ */ jsx7("footer", { className: clsx4(styles5.footer, className), children: /* @__PURE__ */ jsx7("div", { className: styles5.container, children: /* @__PURE__ */ jsx7("div", { className: styles5.content, children: /* @__PURE__ */ jsx7(Paragraph, { children: t("footer.content") }) }) }) });
573
634
  }
574
635
 
575
636
  // src/components/RootLayout/RootLayout.tsx
576
637
  import styles6 from "./RootLayout.module.css";
577
- import { SkipLink } from "@digdir/designsystemet-react";
578
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
579
- function RootLayout({
580
- children,
581
- zone,
582
- className
583
- }) {
638
+ import { jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
639
+ function RootLayout({ children, routes, appBasePath, className }) {
584
640
  const initialize = useGlobalStore((state) => state.initialize);
585
641
  const isMenuOpen = useGlobalStore((state) => state.isMenuOpen);
642
+ const { t } = useLayoutTranslation();
586
643
  useEffect2(() => {
587
- try {
588
- const maybe = initialize();
589
- if (maybe && typeof maybe.then === "function") {
590
- maybe.catch((error) => {
591
- console.error("Failed to initialize global state:", error);
592
- });
593
- }
594
- } catch (error) {
595
- console.error("Failed to initialize global state:", error);
596
- }
644
+ initialize();
597
645
  }, [initialize]);
598
- return /* @__PURE__ */ jsxs5("div", { className: clsx4(styles6.root, isMenuOpen && styles6.menuOpen, className), "data-zone": zone, children: [
599
- /* @__PURE__ */ jsx7(SkipLink, { className: styles6.skipLink, href: "#main-content", children: "Hopp til hovedinnhold" }),
600
- /* @__PURE__ */ jsx7(GlobalHeader, { zone }),
601
- /* @__PURE__ */ jsx7("main", { id: "main-content", tabIndex: -1, className: styles6.main, children }),
602
- /* @__PURE__ */ jsx7(GlobalFooter, {})
646
+ return /* @__PURE__ */ jsxs5("div", { className: clsx5(styles6.root, isMenuOpen && styles6.menuOpen, className), children: [
647
+ /* @__PURE__ */ jsx8(SkipLink, { className: styles6.skipLink, href: "#main-content", children: t("common.skipLink") }),
648
+ /* @__PURE__ */ jsx8(GlobalHeader, { routes, appBasePath }),
649
+ /* @__PURE__ */ jsx8("main", { id: "main-content", tabIndex: -1, className: styles6.main, children }),
650
+ /* @__PURE__ */ jsx8(GlobalFooter, {})
603
651
  ] });
604
652
  }
605
653
 
@@ -607,15 +655,19 @@ function RootLayout({
607
655
  import { useEffect as useEffect3 } from "react";
608
656
  function useBreadcrumbs(breadcrumbs) {
609
657
  const setBreadcrumbs = useGlobalStore((state) => state.setBreadcrumbs);
658
+ const serialized = JSON.stringify(breadcrumbs);
610
659
  useEffect3(() => {
611
- setBreadcrumbs(breadcrumbs);
660
+ setBreadcrumbs(JSON.parse(serialized));
612
661
  return () => {
613
662
  setBreadcrumbs(null);
614
663
  };
615
- }, [breadcrumbs, setBreadcrumbs]);
664
+ }, [serialized, setBreadcrumbs]);
616
665
  }
617
666
  export {
618
667
  RootLayout,
668
+ SmartLink,
669
+ findAppRootWithAncestors,
670
+ getBreadcrumbs,
619
671
  useBreadcrumbs,
620
672
  useGlobalStore
621
673
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/RootLayout/RootLayout.tsx","../src/components/GlobalHeader/GlobalHeader.tsx","../src/components/Breadcrumbs/Breadcrumbs.tsx","../src/routes.ts","../src/store/globalState.ts","../src/components/MenuButton/MenuButton.tsx","../src/components/NavigationMenu/NavigationMenu.tsx","../src/navigationMenu.ts","../src/components/NavigationMenuItem/NavigationMenuItem.tsx","../src/components/GlobalFooter/GlobalFooter.tsx","../src/hooks/use-breadcrumbs.ts"],"sourcesContent":["'use client';\n\nimport { useEffect } from 'react';\nimport clsx from 'clsx';\nimport { GlobalHeader } from '../GlobalHeader';\nimport { GlobalFooter } from '../GlobalFooter';\nimport type { RootLayoutProps } from './RootLayout.types';\nimport styles from './RootLayout.module.css';\nimport { useGlobalStore } from '@/store/globalState';\nimport { SkipLink } from '@digdir/designsystemet-react';\n\nexport function RootLayout({\n children,\n zone, \n className,\n}: RootLayoutProps) {\n const initialize = useGlobalStore((state) => state.initialize);\n const isMenuOpen = useGlobalStore((state) => state.isMenuOpen); \n\n useEffect(() => {\n try {\n const maybe = initialize();\n if (maybe && typeof (maybe as Promise<void>).then === 'function') {\n (maybe as Promise<void>).catch((error) => {\n console.error('Failed to initialize global state:', error);\n });\n }\n } catch (error) {\n console.error('Failed to initialize global state:', error);\n }\n }, [initialize]);\n\n\n return (\n <div className={clsx(styles.root, isMenuOpen && styles.menuOpen, className)} data-zone={zone}>\n <SkipLink className={styles.skipLink} href='#main-content'>Hopp til hovedinnhold</SkipLink>\n <GlobalHeader zone={zone}/>\n <main id=\"main-content\" tabIndex={-1} className={styles.main}>{children}</main>\n <GlobalFooter />\n </div>\n );\n}\n","'use client';\n\nimport { Button, Link } from '@digdir/designsystemet-react';\nimport clsx from 'clsx';\nimport { Breadcrumbs } from '../Breadcrumbs';\nimport { MenuButton } from '../MenuButton';\nimport type { GlobalHeaderProps } from './GlobalHeader.types';\nimport styles from './GlobalHeader.module.css';\nimport { ALLOW_DARK_THEME, useGlobalStore } from '@/store/globalState';\nimport { Search } from 'lucide-react';\n\nexport function GlobalHeader({ className, zone }: GlobalHeaderProps) {\n const isMenuOpen = useGlobalStore((state) => state.isMenuOpen);\n const setIsMenuOpen = useGlobalStore((state) => state.setIsMenuOpen);\n const setTheme = useGlobalStore((state) => state.setTheme);\n const theme = useGlobalStore((state) => state.theme);\n \n // function for toggling darkmode lightmode with zustand store\n function toggleDarkMode() {\n setTheme(theme === 'dark' ? 'light' : 'dark');\n }\n\n\n return (\n <header className={clsx(styles.header, isMenuOpen && styles.menuOpen, className)}>\n <div className={styles.headerContainer}>\n <div className={styles.topBarContainer}>\n <Link href=\"https://www.statsbygg.no\">\n <img src={'https://dok.statsbygg.no/wp-content/uploads/2025/11/Statsbygg_logo.svg'} alt=\"Logo\" className={styles.logo} />\n </Link>\n <div className={styles.actionsContainer}>\n {!isMenuOpen && (\n <>\n {ALLOW_DARK_THEME && <Button onClick={toggleDarkMode} className={styles.themeToggleButton}>\n {theme === 'dark' ? '☀️' : '🌙'}\n </Button>}\n <Button\n variant=\"secondary\"\n onClick={() => setIsMenuOpen(true)}\n className={styles.searchButton}\n aria-label=\"Søk\"\n >\n <Search size={20} aria-hidden=\"true\" />\n Søk\n </Button></>\n )}\n <MenuButton zone={zone} />\n </div>\n </div>\n <Breadcrumbs zone={zone} />\n </div>\n </header>\n );\n}","'use client';\n\nimport { usePathname } from 'next/navigation';\nimport { Breadcrumbs } from '@digdir/designsystemet-react';\nimport clsx from 'clsx';\nimport type { BreadcrumbsProps } from './Breadcrumbs.types';\nimport styles from './Breadcrumbs.module.css';\nimport { getBreadcrumbs, getZoneRoot, transformHrefForZone } from '@/routes';\nimport { useGlobalStore } from '@/store/globalState';\n\nexport function SbBreadcrumbs({ className, zone }: BreadcrumbsProps) {\n const pathname = usePathname();\n const manualBreadcrumbs = useGlobalStore((state) => state.breadcrumbs);\n const isDev = process.env.NODE_ENV === 'development';\n const prodUrl = 'https://www.statsbygg.no';\n const zoneRoot = getZoneRoot(zone);\n \n const fullPath = isDev && zoneRoot !== '/' && !pathname.startsWith(zoneRoot)\n ? `${zoneRoot}${pathname}`\n : pathname;\n \n const breadcrumbs = manualBreadcrumbs ?? getBreadcrumbs(zone, fullPath);\n\n if (breadcrumbs.length <= 1) {\n return null;\n }\n\n return (\n <Breadcrumbs aria-label=\"Du er her:\" className={clsx(styles.breadcrumbs, className)}>\n <Breadcrumbs.List>\n {breadcrumbs.map((crumb, index) => {\n const isLast = index === breadcrumbs.length - 1;\n const href = manualBreadcrumbs \n ? crumb.href \n : transformHrefForZone(crumb.href, zone, { isDev, prodUrl });\n \n return (\n <Breadcrumbs.Item key={crumb.href}>\n <Breadcrumbs.Link\n href={href}\n aria-current={isLast ? 'page' : undefined}\n className={isLast ? styles.currentLink : styles.link}\n >\n {crumb.label}\n </Breadcrumbs.Link>\n </Breadcrumbs.Item>\n );\n })}\n </Breadcrumbs.List>\n </Breadcrumbs>\n );\n}","export type RouteNodeInput =\n | { segment: string; label: string; children?: RouteNodeInput[] }\n | { path: string; label: string; children?: RouteNodeInput[] };\n\nexport type RouteNode = {\n path: string;\n label: string;\n children?: RouteNode[];\n};\n\nexport type RouteDefinition = {\n path: string;\n label: string;\n zone: string;\n};\n\nconst ZONE_TREES_INPUT: Record<string, RouteNodeInput> = {\n sbno: {\n segment: '',// primary root route, no breadcrumb\n label: 'Hjem',\n children: [\n { segment: 'nyheter', label: 'Nyheter' },\n ],\n },\n lokaler: {\n segment: 'lokaler',\n label: 'Statens eide og leide lokaler',\n children: [\n {\n segment: 'lokalbruk', label: 'Lokalbruk'\n },\n { segment: 'veiledning', label: 'Veiledning' },\n { segment: 'statlige-eiendommer', label: 'Statlige eiendommer' },\n { segment: 'ledig-for-fremleie', label: 'Ledig for fremleie' },\n { segment: 'statistikk', label: 'Statistikk' },\n ],\n },\n};\n\n\ntype Key = `${string}:${string}`; // `${zone}:${absolutePath}`\n\nconst ROUTES_INDEX: Record<string, RouteDefinition[]> = {};\nconst PARENT_INDEX = new Map<Key, Key | null>(); // child -> parent\nconst ZONE_TREES: Record<string, RouteNode> = {}; // normalized absolute trees\n\nfunction isSegmentNode(n: RouteNodeInput): n is Extract<RouteNodeInput, { segment: string }> {\n return (n as any).segment !== undefined && (n as any).path === undefined;\n}\nfunction isPathNode(n: RouteNodeInput): n is Extract<RouteNodeInput, { path: string }> {\n return (n as any).path !== undefined;\n}\n\nfunction joinPath(base: string, seg: string): string {\n if (!base) return seg ? `/${seg}` : '/';\n return seg ? `${base.replace(/\\/+$/, '')}/${seg.replace(/^\\/+/, '')}` : base || '/';\n}\n\nfunction normalizeToAbsolute(node: RouteNodeInput, base = ''): RouteNode {\n const path = isSegmentNode(node)\n ? joinPath(base, node.segment)\n : isPathNode(node)\n ? (node.path === '' ? '/' : node.path)\n : '/';\n\n const children = (node.children ?? []).map((c) => normalizeToAbsolute(c, path));\n return { path, label: (node as any).label, children: children.length ? children : undefined };\n}\n\n(function buildAll() {\n // Normalize each zone tree to absolute paths\n Object.keys(ZONE_TREES_INPUT).forEach((zone) => {\n ZONE_TREES[zone] = normalizeToAbsolute(ZONE_TREES_INPUT[zone]);\n });\n\n // Build flat indexes + parent relationships\n function walk(zone: string, node: RouteNode, parentKey: Key | null) {\n const def: RouteDefinition = { zone, path: node.path, label: node.label };\n const key: Key = `${zone}:${node.path}`;\n ROUTES_INDEX[zone].push(def);\n PARENT_INDEX.set(key, parentKey);\n for (const child of node.children ?? []) {\n walk(zone, child, key);\n }\n }\n\n (Object.keys(ZONE_TREES) as string[]).forEach((zone) => {\n ROUTES_INDEX[zone] = [];\n walk(zone, ZONE_TREES[zone], null);\n });\n})();\n\n\nfunction findBestMatch(zone: string, pathname: string): RouteDefinition | undefined {\n const list = ROUTES_INDEX[zone] ?? [];\n let best: RouteDefinition | undefined;\n\n for (const r of list) {\n if (pathname === r.path) {\n best = r; // exact wins\n break;\n }\n if (pathname.startsWith(r.path.endsWith('/') ? r.path : r.path + '/')) {\n if (!best || r.path.length > best.path.length) best = r;\n }\n }\n // fallback: zone root\n return best ?? list.find((r) => r.path === ZONE_TREES[zone]?.path);\n}\n\nexport function getZoneRoutes(zone: string): RouteDefinition[] {\n return ROUTES_INDEX[zone] ?? [];\n}\n\n// Top-level links for a zone’s menu (children of the zone root)\nexport function getZoneMenuRoutes(zone: string): RouteDefinition[] {\n const root = ZONE_TREES[zone];\n const children = root?.children ?? [];\n return children.map((c) => ({ zone, path: c.path, label: c.label }));\n}\n\nexport function getAllZones(): string[] {\n return Object.keys(ZONE_TREES);\n}\n\nexport function getZoneRoot(zone: string): string {\n return ZONE_TREES[zone]?.path || '/';\n}\n\n// prettify dynamic slug labels\nfunction labelFromSlug(slug: string): string {\n try {\n const s = decodeURIComponent(slug).replace(/[-_]+/g, ' ').trim();\n return s ? s.charAt(0).toUpperCase() + s.slice(1) : slug;\n } catch {\n return slug;\n }\n}\n\nexport function getBreadcrumbs(\n zone: string,\n pathname: string\n): Array<{ label: string; href: string }> {\n\n const normalizedPathname = pathname === '/' ? pathname : pathname.replace(/\\/+$/, '');\n\n // sbno root has no crumbs\n if (zone === 'sbno' && normalizedPathname === '/') return [];\n\n const match = findBestMatch(zone, normalizedPathname);\n if (!match) return [];\n\n const chain: RouteDefinition[] = [];\n let key: Key | undefined = `${zone}:${match.path}`;\n while (key) {\n const parentKey = PARENT_INDEX.get(key);\n const [z, p] = key.split(':') as [string, string];\n const def = (ROUTES_INDEX[z] ?? []).find((r) => r.path === p);\n if (def) chain.unshift(def);\n key = parentKey ?? undefined;\n }\n\n const homeRoute = (ROUTES_INDEX.sbno ?? []).find((r) => r.path === '/');\n if (\n homeRoute &&\n !(chain.length === 1 && chain[0].zone === 'sbno' && chain[0].path === '/') &&\n (chain.length === 0 || chain[0].path !== homeRoute.path)\n ) {\n chain.unshift(homeRoute);\n }\n\n // If the pathname is deeper than the best static match, add a dynamic tail\n const last = chain[chain.length - 1];\n if (last && normalizedPathname !== last.path && normalizedPathname.startsWith(last.path.endsWith('/') ? last.path : last.path + '/')) {\n const segments = normalizedPathname.split('/').filter(Boolean);\n const tail = segments[segments.length - 1];\n chain.push({ zone, path: normalizedPathname, label: labelFromSlug(tail) });\n }\n\n return chain.map((r) => ({ label: r.label, href: r.path }));\n}\n\nexport function transformHrefForZone(\n targetPath: string,\n currentZone: string,\n options: {\n isDev: boolean;\n prodUrl?: string;\n }\n): string {\n const { isDev, prodUrl } = options;\n\n const targetZone = getZoneFromPathname(targetPath);\n const isCrossZone = targetZone !== currentZone;\n\n if (isCrossZone && isDev && prodUrl) {\n return `${prodUrl}${targetPath}`;\n }\n\n const currentZoneRoot = getZoneRoot(currentZone);\n if (!isCrossZone && isDev && currentZoneRoot !== '/') {\n return targetPath.replace(currentZoneRoot, '') || '/';\n }\n\n return targetPath;\n}\n\nexport function getZoneFromPathname(pathname: string): string {\n if (pathname.startsWith('/lokaler')) return 'lokaler';\n return 'sbno';\n}","import { create, StateCreator } from 'zustand';\nimport { persist, createJSONStorage } from 'zustand/middleware';\n\nexport type Theme = 'light' | 'dark' | 'system';\n\nexport const ALLOW_DARK_THEME = false;\n\nexport type BreadcrumbItem = {\n label: string;\n href: string;\n};\n\nexport type GlobalState = {\n user?: { id: string; name?: string } | null;\n theme: Theme;\n locale: string;\n isMenuOpen: boolean;\n breadcrumbs: BreadcrumbItem[] | null;\n setUser: (user: GlobalState['user']) => void;\n setTheme: (theme: Theme) => void;\n setLocale: (locale: string) => void;\n setIsMenuOpen: (isOpen: boolean) => void;\n toggleMenu: () => void;\n setBreadcrumbs: (breadcrumbs: BreadcrumbItem[] | null) => void;\n initialize: () => void | Promise<void>;\n};\n\nconst creator: StateCreator<GlobalState, [['zustand/persist', unknown]]> = (set, get) => ({\n user: null,\n theme: 'light',\n locale: 'no',\n isMenuOpen: false,\n breadcrumbs: null,\n setUser: (user) => set({ user }),\n setTheme: (theme) => {\n set({ theme: ALLOW_DARK_THEME ? theme : 'light' });\n if (typeof document !== 'undefined' && ALLOW_DARK_THEME) {\n document.documentElement.setAttribute('data-color-scheme', theme);\n }\n },\n setLocale: (locale) => set({ locale }),\n setIsMenuOpen: (isMenuOpen) => set({ isMenuOpen }),\n toggleMenu: () => set((state) => ({ isMenuOpen: !state.isMenuOpen })),\n setBreadcrumbs: (breadcrumbs) => set({ breadcrumbs }),\n initialize: () => {\n if (typeof document !== 'undefined' && ALLOW_DARK_THEME) {\n document.documentElement.setAttribute('data-color-scheme', get().theme);\n }\n },\n});\n\nexport const useGlobalStore = create<GlobalState>()(\n persist(creator, {\n name: 'statsbygg-global-state',\n storage: createJSONStorage(() => localStorage),\n partialize: (state) => ({\n user: state.user,\n theme: ALLOW_DARK_THEME ? state.theme : 'light',\n locale: state.locale,\n }),\n })\n);","'use client';\n\nimport { Button } from '@digdir/designsystemet-react';\nimport { Menu, X } from 'lucide-react';\nimport { useGlobalStore } from '@/store/globalState';\nimport { NavigationMenu } from '../NavigationMenu';\nimport type { MenuButtonProps } from './MenuButton.types';\n\nexport function MenuButton({ zone }: MenuButtonProps) {\n const isMenuOpen = useGlobalStore((state) => state.isMenuOpen);\n const toggleMenu = useGlobalStore((state) => state.toggleMenu);\n\n return (\n <>\n <Button\n variant='primary'\n onClick={toggleMenu}\n aria-expanded={isMenuOpen}\n aria-label={isMenuOpen ? 'Lukk meny' : 'Åpne meny'}\n >\n {isMenuOpen ? <X size={20} aria-hidden=\"true\" /> : <Menu size={20} aria-hidden=\"true\" />}\n {isMenuOpen ? 'Lukk' : 'Meny'}\n </Button>\n <NavigationMenu zone={zone} />\n </>\n );\n}","'use client';\nimport { useState, useEffect, useRef } from 'react';\nimport { Heading, Search, Textfield } from '@digdir/designsystemet-react';\nimport { NAVIGATION_MENU } from '../../navigationMenu';\nimport { NavigationMenuItem } from '../NavigationMenuItem/NavigationMenuItem';\nimport { useGlobalStore } from '../../store/globalState';\nimport styles from './NavigationMenu.module.css';\nimport { MenuSection, NavigationMenuProps } from './NavigationMenu.types';\n\nexport function NavigationMenu({ zone }: NavigationMenuProps) {\n const [searchValue, setSearchValue] = useState('');\n const isMenuOpen = useGlobalStore((state) => state.isMenuOpen);\n const setIsMenuOpen = useGlobalStore((state) => state.setIsMenuOpen);\n const searchInputRef = useRef<HTMLInputElement>(null);\n\nuseEffect(() => {\n if (!isMenuOpen) return;\n\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === 'Escape') {\n setIsMenuOpen(false);\n }\n };\n\n setTimeout(() => {\n searchInputRef.current?.focus();\n }, 100);\n\n document.addEventListener('keydown', handleEscape);\n\n return () => {\n document.removeEventListener('keydown', handleEscape);\n };\n}, [setIsMenuOpen, isMenuOpen]);\n\n function handleBackdropClick(e: React.MouseEvent<HTMLDivElement>) {\n if (e.target === e.currentTarget) {\n setIsMenuOpen(false);\n }\n }\n\n return (\n <>\n {isMenuOpen && <div className={styles.backdrop} onClick={handleBackdropClick} />}\n <div className={`${styles.menuOverlay} ${!isMenuOpen ? styles.hidden : ''}`}>\n <div className={styles.container}>\n <div className={styles.searchSection}>\n <Heading level={1}>\n Hva kan vi hjelpe deg med?\n </Heading>\n <Search>\n <Search.Input aria-label='Søk' ref={searchInputRef}\n value={searchValue}\n onChange={(e) => setSearchValue(e.target.value)}\n placeholder=\"Søk\"\n className={styles.searchField}\n />\n <Search.Clear />\n </Search>\n </div>\n\n <nav className={styles.menuSections} aria-label=\"Hovedmeny\">\n {NAVIGATION_MENU.map((section: MenuSection, sectionIndex: number) => (\n <section\n key={sectionIndex}\n className={styles.section}\n style={{ animationDelay: `${0.15 + (sectionIndex * 0.06)}s` }}\n >\n {/* Only show section header for non-subsection layouts */}\n {section.layout !== 'subsections' && (\n <Heading level={2} className={styles.sectionHeader}>\n {section.title}\n </Heading>\n )}\n\n {section.layout === 'subsections' && section.subsections ? (\n <div className={styles.subsectionsGrid}>\n {section.subsections.map((subsection, subsectionIndex) => (\n <div key={subsectionIndex} className={styles.subsection}>\n <Heading level={2} className={styles.subsectionHeader}>\n {subsection.title}\n </Heading>\n <div className={styles.subsectionItems}>\n {subsection.items.map((item, itemIndex) => (\n <NavigationMenuItem\n key={itemIndex}\n item={item}\n animationDelay={(150 + (sectionIndex * 60)) + (subsectionIndex * 40) + (itemIndex * 25)}\n compact\n />\n ))}\n </div>\n </div>\n ))}\n </div>\n ) : (\n <div className={sectionIndex === 2 ? styles.itemsGridThreeCol : styles.itemsGrid}>\n {section.items?.map((item, itemIndex) => (\n <NavigationMenuItem\n key={itemIndex}\n item={item}\n animationDelay={(150 + (sectionIndex * 60)) + (itemIndex * 25)}\n />\n ))}\n </div>\n )}\n </section>\n ))}\n </nav>\n </div>\n </div>\n </>\n );\n}","export interface MenuItem {\n label: string;\n href: string;\n external?: boolean;\n children?: MenuItem[];\n}\n\nexport interface MenuSubsection {\n title: string;\n items: MenuItem[];\n}\n\nexport interface MenuSection {\n title: string;\n layout?: 'columns' | 'subsections';\n items?: MenuItem[];\n subsections?: MenuSubsection[];\n}\n\nexport const NAVIGATION_MENU: MenuSection[] = [\n {\n title: 'Våre tjenester',\n layout: 'columns',\n items: [\n {\n label: 'Statens eide og leide lokaler',\n href: '/lokaler',\n children: [\n { label: 'Lokalbruk', href: '/lokaler/lokalbruk' },\n { label: 'Statlige eiendommer', href: '/lokaler/statlige-eiendommer' },\n { label: 'Ledig for fremleie', href: '/lokaler/ledig-for-fremleie' },\n { label: 'Statistikk for lokalbruk', href: '/lokaler/statistikk' },\n { label: 'Veiledning', href: '/lokaler/veiledning' },\n ],\n },\n {\n label: 'For leietakere',\n href: '/for-leietakere',\n children: [\n { label: 'Leieveileder', href: '/leietakere/leieveileder' },\n { label: 'Lenke til underside', href: '/leietakere/lenke1' },\n { label: 'Lenke til underside', href: '/leietakere/lenke2' },\n ],\n },\n {\n label: 'For byggebransjen',\n href: '/byggebransjen',\n children: [\n { label: 'Våre krav', href: '/byggebransjen/vare-krav' },\n { label: 'BIM', href: '/byggebransjen/bim' },\n { label: 'ByggBoks', href: '/byggebransjen/byggboks' },\n { label: 'Lenke til underside', href: '/byggebransjen/lenke' },\n ],\n },\n {\n label: 'Karriere',\n href: '/karriere',\n children: [\n { label: 'Ledige stillinger', href: '/karriere/ledige-stillinger' },\n { label: 'Å jobbe hos oss', href: '/karriere/jobbe-hos-oss' },\n { label: 'Møt en statsbygger', href: '/karriere/mot-en-statsbygger' },\n { label: 'Summer internship', href: '/karriere/summer-internship' },\n { label: 'Studenter og lærlinger', href: '/karriere/studenter-og-laerlinger' },\n ],\n },\n ],\n },\n {\n title: 'Informasjon om statsbygg',\n layout: 'subsections',\n subsections: [\n {\n title: 'Informasjon om statsbygg',\n items: [\n { label: 'Om Statsbygg', href: '/om-statsbygg' },\n { label: 'Samfunnsansvar', href: '/samfunnsansvar' },\n { label: 'Tilgjengelighet', href: '/tilgjengelighet' },\n { label: 'About Statsbygg', href: '/about-statsbygg' },\n { label: 'Statsbygg birra', href: '/statsbygg-birra' },\n ],\n },\n {\n title: 'Kontakt oss',\n items: [\n { label: 'Kontakt oss', href: '/kontakt' },\n { label: 'Ansattsøk', href: '/ansattsok' },\n { label: 'For pressen', href: '/for-pressen' },\n { label: 'Varsling', href: '/varsling' },\n ],\n },\n {\n title: 'Arkiv',\n items: [\n { label: 'Nyheter', href: '/nyheter' },\n { label: 'Artikler om bygg', href: '/artikler-om-bygg' },\n { label: 'Dokumenter', href: '/dokumenter' },\n ],\n },\n ],\n },\n {\n title: 'Eksterne lenker',\n layout: 'columns',\n items: [\n {\n label: 'Statens lokaler',\n href: 'https://statensinnleie.no',\n external: true,\n },\n {\n label: 'Statens innleie',\n href: 'https://statensinnleie.no',\n external: true,\n },\n {\n label: 'MainManager FM',\n href: 'https://mainmanager.no',\n external: true,\n },\n {\n label: 'Offentlig postjournal',\n href: 'https://postjournal.no',\n external: true,\n },\n {\n label: 'SIMBA (BIM)',\n href: 'https://bim.statsbygg.no',\n external: true,\n },\n ],\n },\n];","import { Link, List } from '@digdir/designsystemet-react';\nimport { ExternalLink } from 'lucide-react';\nimport { MenuItem } from '../../navigationMenu';\nimport styles from './NavigationMenuItem.module.css';\nimport { NavigationMenuItemProps } from './NavigationMenuItem.types';\n\nexport function NavigationMenuItem({ item, animationDelay, compact = false }: NavigationMenuItemProps) {\n if (compact) {\n return (\n <div\n className={styles.itemColumn}\n style={{ animationDelay: `${animationDelay}ms` }}\n >\n <Link\n href={item.href}\n className={styles.compactLink}\n target={item.external ? '_blank' : undefined}\n rel={item.external ? 'noopener noreferrer' : undefined}\n >\n {item.label}\n {item.external && (\n <ExternalLink size={16} aria-hidden=\"true\" />\n )}\n </Link>\n </div>\n );\n }\n\n return (\n <div\n className={styles.itemColumn}\n style={{ animationDelay: `${animationDelay}ms` }}\n >\n <Link\n href={item.href}\n className={styles.parentLink}\n target={item.external ? '_blank' : undefined}\n rel={item.external ? 'noopener noreferrer' : undefined}\n >\n {item.label}\n {item.external && (\n <ExternalLink size={20} aria-hidden=\"true\" />\n )}\n </Link>\n\n {item.children && item.children.length > 0 && (\n <List.Unordered className={styles.childItems}>\n {item.children.map((child, childIndex) => (\n <List.Item\n key={childIndex}\n className={styles.childItem}\n style={{ animationDelay: `${animationDelay + 30 + (childIndex * 15)}ms` }}\n >\n <Link\n href={child.href}\n className={styles.childLink}\n target={child.external ? '_blank' : undefined}\n rel={child.external ? 'noopener noreferrer' : undefined}\n >\n {child.label}\n {child.external && (\n <ExternalLink size={20} aria-hidden=\"true\" />\n )}\n </Link>\n </List.Item>\n ))}\n </List.Unordered>\n )}\n </div>\n );\n}","'use client';\n\nimport { Paragraph } from '@digdir/designsystemet-react';\nimport clsx from 'clsx';\nimport type { GlobalFooterProps } from './GlobalFooter.types';\nimport styles from './GlobalFooter.module.css';\n\nexport function GlobalFooter({ className }: GlobalFooterProps) {\n\n return (\n <footer className={clsx(styles.footer, className)}>\n <div className={styles.container}>\n <div className={styles.content}>\n <Paragraph>\n Statsbygg Footer\n </Paragraph>\n\n\n </div>\n </div>\n </footer>\n );\n}","import { useEffect } from 'react';\nimport { useGlobalStore, BreadcrumbItem } from '../store/globalState';\n\n/**\n * Custom hook to override the default breadcrumb generation for a specific page.\n * Automatically resets breadcrumbs to null on unmount to restore default behavior\n * for subsequent pages.\n *\n * @param breadcrumbs - Array of breadcrumb items to display\n *\n * @example\n * ```tsx\n * function MyPage({ data }) {\n * useBreadcrumbs([\n * { label: 'Hjem', href: '/' },\n * { label: 'Parent', href: '/parent' },\n * { label: data.name, href: '#' }\n * ]);\n *\n * return <div>Page content</div>;\n * }\n * ```\n */\nexport function useBreadcrumbs(breadcrumbs: BreadcrumbItem[]): void {\n const setBreadcrumbs = useGlobalStore((state) => state.setBreadcrumbs);\n\n useEffect(() => {\n setBreadcrumbs(breadcrumbs);\n\n return () => {\n setBreadcrumbs(null);\n };\n }, [breadcrumbs, setBreadcrumbs]);\n}"],"mappings":"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","names":["useEffect","clsx","Button","Link","clsx","_a","styles","jsx","styles","jsx","jsxs","Fragment","jsx","jsxs","styles","Search","Fragment","jsx","jsxs","clsx","styles","Link","Button","clsx","styles","jsx","styles","jsx","jsxs","useEffect","clsx","styles","useEffect","useEffect"]}
1
+ {"version":3,"sources":["../src/components/RootLayout/RootLayout.tsx","../src/components/GlobalHeader/GlobalHeader.tsx","../src/components/Breadcrumbs/Breadcrumbs.tsx","../src/routes.ts","../src/store/globalState.ts","../src/locales/translations.ts","../src/hooks/use-layout-translation.ts","../src/components/MenuButton/MenuButton.tsx","../src/components/NavigationMenu/NavigationMenu.tsx","../src/navigationMenu.ts","../src/components/NavigationMenuItem/NavigationMenuItem.tsx","../src/components/SmartLink/SmartLink.tsx","../src/components/GlobalFooter/GlobalFooter.tsx","../src/hooks/use-breadcrumbs.ts"],"sourcesContent":["'use client';\n\nimport { useEffect } from 'react';\nimport clsx from 'clsx';\nimport { SkipLink } from '@digdir/designsystemet-react';\nimport { GlobalHeader } from '../GlobalHeader';\nimport { GlobalFooter } from '../GlobalFooter';\nimport { useGlobalStore } from '@/store/globalState';\nimport { useLayoutTranslation } from '@/hooks/use-layout-translation';\nimport type { RootLayoutProps } from './RootLayout.types';\nimport styles from './RootLayout.module.css';\n\nexport function RootLayout({ children, routes, appBasePath, className }: RootLayoutProps) {\n const initialize = useGlobalStore((state) => state.initialize);\n const isMenuOpen = useGlobalStore((state) => state.isMenuOpen);\n const { t } = useLayoutTranslation();\n\n useEffect(() => {\n initialize();\n }, [initialize]);\n\n return (\n <div className={clsx(styles.root, isMenuOpen && styles.menuOpen, className)}>\n <SkipLink className={styles.skipLink} href=\"#main-content\">\n {t('common.skipLink')}\n </SkipLink>\n <GlobalHeader routes={routes} appBasePath={appBasePath} />\n <main id=\"main-content\" tabIndex={-1} className={styles.main}>\n {children}\n </main>\n <GlobalFooter />\n </div>\n );\n}","'use client';\n\nimport { Button, Link } from '@digdir/designsystemet-react';\nimport { Search } from 'lucide-react';\nimport clsx from 'clsx';\nimport { Breadcrumbs } from '../Breadcrumbs';\nimport { MenuButton } from '../MenuButton';\nimport { ALLOW_DARK_THEME, useGlobalStore } from '@/store/globalState';\nimport { useLayoutTranslation } from '@/hooks/use-layout-translation';\nimport type { GlobalHeaderProps } from './GlobalHeader.types';\nimport styles from './GlobalHeader.module.css';\n\nexport function GlobalHeader({ className, routes, appBasePath }: GlobalHeaderProps) {\n const isMenuOpen = useGlobalStore((state) => state.isMenuOpen);\n const setIsMenuOpen = useGlobalStore((state) => state.setIsMenuOpen);\n const setTheme = useGlobalStore((state) => state.setTheme);\n const theme = useGlobalStore((state) => state.theme);\n const { t } = useLayoutTranslation();\n\n function toggleDarkMode() {\n setTheme(theme === 'dark' ? 'light' : 'dark');\n }\n\n return (\n <header className={clsx(styles.header, isMenuOpen && styles.menuOpen, className)}>\n <div className={styles.headerContainer}>\n <div className={styles.topBarContainer}>\n <Link href=\"https://www.statsbygg.no\">\n <img\n src=\"https://dok.statsbygg.no/wp-content/uploads/2025/11/Statsbygg_logo.svg\"\n alt=\"Logo\"\n className={styles.logo}\n />\n </Link>\n <div className={styles.actionsContainer}>\n {!isMenuOpen && (\n <>\n {ALLOW_DARK_THEME && (\n <Button onClick={toggleDarkMode} className={styles.themeToggleButton}>\n {theme === 'dark' ? '☀️' : '🌙'}\n </Button>\n )}\n <Button\n variant=\"secondary\"\n onClick={() => setIsMenuOpen(true)}\n className={styles.searchButton}\n aria-label={t('common.search')}\n >\n <Search size={20} aria-hidden=\"true\" />\n {t('common.search')}\n </Button>\n </>\n )}\n <MenuButton appBasePath={appBasePath} />\n </div>\n </div>\n <Breadcrumbs routes={routes} />\n </div>\n </header>\n );\n}","'use client';\n\nimport { useMemo } from 'react';\nimport { usePathname } from 'next/navigation';\nimport { Breadcrumbs } from '@digdir/designsystemet-react';\nimport clsx from 'clsx';\nimport { getBreadcrumbs, findAppRootWithAncestors, BreadcrumbItem } from '@/routes';\nimport { useGlobalStore } from '@/store/globalState';\nimport { useLayoutTranslation } from '@/hooks/use-layout-translation';\nimport type { BreadcrumbsProps } from './Breadcrumbs.types';\nimport styles from './Breadcrumbs.module.css';\n\nexport function SbBreadcrumbs({ className, routes }: BreadcrumbsProps) {\n const pathname = usePathname();\n const manualBreadcrumbs = useGlobalStore((state) => state.breadcrumbs);\n const { t } = useLayoutTranslation();\n\n const breadcrumbs = useMemo((): BreadcrumbItem[] => {\n if (manualBreadcrumbs) {\n const { externalAncestors } = findAppRootWithAncestors(routes);\n const baseBreadcrumbs = externalAncestors.map((node) => ({\n label: node.label,\n href: node.path,\n }));\n const manualHrefs = new Set(manualBreadcrumbs.map((b) => b.href));\n const uniqueBase = baseBreadcrumbs.filter((b) => !manualHrefs.has(b.href));\n return [...uniqueBase, ...manualBreadcrumbs];\n }\n return getBreadcrumbs(routes, pathname);\n }, [routes, pathname, manualBreadcrumbs]);\n\n if (breadcrumbs.length === 0) {\n return null;\n }\n\n return (\n <Breadcrumbs\n aria-label={t('common.youAreHere')}\n className={clsx(styles.breadcrumbs, className)}\n >\n <Breadcrumbs.List>\n {breadcrumbs.map((crumb, index) => {\n const isLast = index === breadcrumbs.length - 1;\n\n return (\n <Breadcrumbs.Item key={`${crumb.href}-${index}`}>\n <Breadcrumbs.Link\n href={crumb.href}\n aria-current={isLast ? 'page' : undefined}\n className={isLast ? styles.currentLink : styles.link}\n >\n {crumb.label}\n </Breadcrumbs.Link>\n </Breadcrumbs.Item>\n );\n })}\n </Breadcrumbs.List>\n </Breadcrumbs>\n );\n}","export type RouteNode = {\n path: string;\n label: string;\n children?: RouteNode[];\n};\n\nexport type BreadcrumbItem = {\n label: string;\n href: string;\n};\n\nfunction isExternalPath(path: string): boolean {\n return path.startsWith('http://') || path.startsWith('https://');\n}\n\nfunction normalizePath(path: string): string {\n if (path === '/') return '/';\n return path.replace(/\\/+$/, '');\n}\n\nfunction formatSegmentLabel(segment: string): string {\n try {\n const decoded = decodeURIComponent(segment).replace(/[-_]+/g, ' ').trim();\n return decoded ? decoded.charAt(0).toUpperCase() + decoded.slice(1) : segment;\n } catch {\n return segment;\n }\n}\n\ntype AncestorChain = {\n externalAncestors: RouteNode[];\n appRoot: RouteNode | null;\n};\n\nexport function findAppRootWithAncestors(node: RouteNode, ancestors: RouteNode[] = []): AncestorChain {\n if (!isExternalPath(node.path)) {\n return {\n externalAncestors: ancestors,\n appRoot: node,\n };\n }\n\n if (node.children) {\n for (const child of node.children) {\n const result = findAppRootWithAncestors(child, [...ancestors, node]);\n if (result.appRoot) return result;\n }\n }\n\n return { externalAncestors: ancestors, appRoot: null };\n}\n\ntype InternalMatch = {\n node: RouteNode;\n ancestors: RouteNode[];\n};\n\nfunction findInternalMatch(\n node: RouteNode,\n pathname: string,\n ancestors: RouteNode[] = []\n): InternalMatch | null {\n const nodePath = normalizePath(node.path);\n\n if (pathname === nodePath) {\n return { node, ancestors };\n }\n\n if (node.children) {\n for (const child of node.children) {\n if (isExternalPath(child.path)) continue;\n\n const result = findInternalMatch(child, pathname, [...ancestors, node]);\n if (result) return result;\n }\n }\n\n const pathPrefix = nodePath === '/' ? '/' : nodePath + '/';\n if (pathname.startsWith(pathPrefix) || pathname === nodePath) {\n return { node, ancestors };\n }\n\n return null;\n}\n\nexport function getBreadcrumbs(routes: RouteNode, pathname: string): BreadcrumbItem[] {\n const normalizedPathname = normalizePath(pathname);\n const { externalAncestors, appRoot } = findAppRootWithAncestors(routes);\n\n if (!appRoot) {\n return externalAncestors.map((node) => ({\n label: node.label,\n href: node.path,\n }));\n }\n\n const breadcrumbs: BreadcrumbItem[] = externalAncestors.map((node) => ({\n label: node.label,\n href: node.path,\n }));\n\n const internalMatch = findInternalMatch(appRoot, normalizedPathname);\n\n if (!internalMatch) {\n breadcrumbs.push({ label: appRoot.label, href: appRoot.path });\n return breadcrumbs;\n }\n\n for (const ancestor of internalMatch.ancestors) {\n breadcrumbs.push({\n label: ancestor.label,\n href: ancestor.path,\n });\n }\n\n breadcrumbs.push({\n label: internalMatch.node.label,\n href: internalMatch.node.path,\n });\n\n const matchedPath = normalizePath(internalMatch.node.path);\n if (normalizedPathname !== matchedPath) {\n const remainingPath = normalizedPathname.slice(\n matchedPath === '/' ? 1 : matchedPath.length + 1\n );\n const dynamicSegments = remainingPath.split('/').filter(Boolean);\n\n let accumulatedPath = matchedPath;\n for (const segment of dynamicSegments) {\n accumulatedPath = accumulatedPath === '/' ? `/${segment}` : `${accumulatedPath}/${segment}`;\n breadcrumbs.push({\n label: formatSegmentLabel(segment),\n href: accumulatedPath,\n });\n }\n }\n\n return breadcrumbs;\n}","import { create, StateCreator } from 'zustand';\nimport { persist, createJSONStorage } from 'zustand/middleware';\nimport type { BreadcrumbItem } from '../routes';\n\nexport type Theme = 'light' | 'dark' | 'system';\n\nexport const ALLOW_DARK_THEME = false;\n\nexport type GlobalState = {\n user?: { id: string; name?: string } | null;\n theme: Theme;\n locale: string;\n isMenuOpen: boolean;\n breadcrumbs: BreadcrumbItem[] | null;\n setUser: (user: GlobalState['user']) => void;\n setTheme: (theme: Theme) => void;\n setLocale: (locale: string) => void;\n setIsMenuOpen: (isOpen: boolean) => void;\n toggleMenu: () => void;\n setBreadcrumbs: (breadcrumbs: BreadcrumbItem[] | null) => void;\n initialize: () => void;\n};\n\nconst creator: StateCreator<GlobalState, [['zustand/persist', unknown]]> = (set, get) => ({\n user: null,\n theme: 'light',\n locale: 'no',\n isMenuOpen: false,\n breadcrumbs: null,\n setUser: (user) => set({ user }),\n setTheme: (theme) => {\n set({ theme: ALLOW_DARK_THEME ? theme : 'light' });\n if (typeof document !== 'undefined' && ALLOW_DARK_THEME) {\n document.documentElement.setAttribute('data-color-scheme', theme);\n }\n },\n setLocale: (locale) => set({ locale }),\n setIsMenuOpen: (isMenuOpen) => set({ isMenuOpen }),\n toggleMenu: () => set((state) => ({ isMenuOpen: !state.isMenuOpen })),\n setBreadcrumbs: (breadcrumbs) => set({ breadcrumbs }),\n initialize: () => {\n if (typeof document !== 'undefined' && ALLOW_DARK_THEME) {\n document.documentElement.setAttribute('data-color-scheme', get().theme);\n }\n },\n});\n\nexport const useGlobalStore = create<GlobalState>()(\n persist(creator, {\n name: 'statsbygg-global-state',\n storage: createJSONStorage(() => localStorage),\n partialize: (state) => ({\n user: state.user,\n theme: ALLOW_DARK_THEME ? state.theme : 'light',\n locale: state.locale,\n }),\n })\n);","export const translations = {\n no: {\n 'common.menu': 'Meny',\n 'common.close': 'Lukk',\n 'common.search': 'Søk',\n 'common.searchLabel': 'Søk',\n 'common.youAreHere': 'Du er her:',\n 'common.skipLink': 'Hopp til hovedinnhold',\n 'common.home': 'Hjem',\n 'footer.content': 'Statsbygg Footer',\n 'menu.helpTitle': 'Hva kan vi hjelpe deg med?',\n 'menu.mainMenuLabel': 'Hovedmeny',\n 'menu.closeMenu': 'Lukk meny',\n 'menu.openMenu': 'Åpne meny',\n }\n};\n\nexport type TranslationKey = keyof typeof translations.no;","import { TranslationKey, translations } from '@/locales/translations';\nimport { useGlobalStore } from '@/store/globalState';\n\nexport function useLayoutTranslation() {\n const locale = useGlobalStore((state) => state.locale) as keyof typeof translations;\n \n const languageMap = translations[locale] || translations.no;\n\n function t(key: TranslationKey): string {\n return languageMap[key] || key;\n }\n\n return { t, locale };\n}","'use client';\n\nimport { Button } from '@digdir/designsystemet-react';\nimport { Menu, X } from 'lucide-react';\nimport { useGlobalStore } from '@/store/globalState';\nimport { NavigationMenu } from '../NavigationMenu';\nimport { useLayoutTranslation } from '@/hooks/use-layout-translation';\nimport type { MenuButtonProps } from './MenuButton.types';\n\nexport function MenuButton({ className, appBasePath }: MenuButtonProps) {\n const isMenuOpen = useGlobalStore((state) => state.isMenuOpen);\n const toggleMenu = useGlobalStore((state) => state.toggleMenu);\n const { t } = useLayoutTranslation();\n\n return (\n <>\n <Button\n variant=\"primary\"\n onClick={toggleMenu}\n aria-expanded={isMenuOpen}\n aria-label={isMenuOpen ? t('menu.closeMenu') : t('menu.openMenu')}\n className={className}\n >\n {isMenuOpen ? <X size={20} aria-hidden=\"true\" /> : <Menu size={20} aria-hidden=\"true\" />}\n {isMenuOpen ? t('common.close') : t('common.menu')}\n </Button>\n <NavigationMenu appBasePath={appBasePath} />\n </>\n );\n}","'use client';\n\nimport { useState, useEffect, useRef } from 'react';\nimport { Heading, Search } from '@digdir/designsystemet-react';\nimport { NAVIGATION_MENU, MenuSection } from '../../navigationMenu';\nimport { NavigationMenuItem } from '../NavigationMenuItem/NavigationMenuItem';\nimport { useGlobalStore } from '../../store/globalState';\nimport { useLayoutTranslation } from '@/hooks/use-layout-translation';\nimport type { NavigationMenuProps } from './NavigationMenu.types';\nimport styles from './NavigationMenu.module.css';\n\nexport function NavigationMenu({ className, appBasePath }: NavigationMenuProps) {\n const [searchValue, setSearchValue] = useState('');\n const isMenuOpen = useGlobalStore((state) => state.isMenuOpen);\n const setIsMenuOpen = useGlobalStore((state) => state.setIsMenuOpen);\n const searchInputRef = useRef<HTMLInputElement>(null);\n const { t } = useLayoutTranslation();\n\n useEffect(() => {\n if (!isMenuOpen) return;\n\n function handleEscape(event: KeyboardEvent) {\n if (event.key === 'Escape') {\n setIsMenuOpen(false);\n }\n }\n\n setTimeout(() => {\n searchInputRef.current?.focus();\n }, 100);\n\n document.addEventListener('keydown', handleEscape);\n return () => document.removeEventListener('keydown', handleEscape);\n }, [setIsMenuOpen, isMenuOpen]);\n\n function handleBackdropClick(e: React.MouseEvent<HTMLDivElement>) {\n if (e.target === e.currentTarget) {\n setIsMenuOpen(false);\n }\n }\n\n return (\n <>\n {isMenuOpen && <div className={styles.backdrop} onClick={handleBackdropClick} />}\n <div className={`${styles.menuOverlay} ${!isMenuOpen ? styles.hidden : ''} ${className ?? ''}`}>\n <div className={styles.container}>\n <div className={styles.searchSection}>\n <Heading level={1}>{t('menu.helpTitle')}</Heading>\n <Search>\n <Search.Input\n aria-label={t('common.search')}\n ref={searchInputRef}\n value={searchValue}\n onChange={(e) => setSearchValue(e.target.value)}\n placeholder={t('common.search')}\n className={styles.searchField}\n />\n <Search.Clear />\n </Search>\n </div>\n\n <nav className={styles.menuSections} aria-label={t('menu.mainMenuLabel')}>\n {NAVIGATION_MENU.map((section: MenuSection, sectionIndex: number) => (\n <section\n key={sectionIndex}\n className={styles.section}\n style={{ animationDelay: `${0.15 + sectionIndex * 0.06}s` }}\n >\n {section.layout !== 'subsections' && (\n <Heading level={2} className={styles.sectionHeader}>\n {section.title}\n </Heading>\n )}\n\n {section.layout === 'subsections' && section.subsections ? (\n <div className={styles.subsectionsGrid}>\n {section.subsections.map((subsection, subsectionIndex) => (\n <div key={subsectionIndex} className={styles.subsection}>\n <Heading level={2} className={styles.subsectionHeader}>\n {subsection.title}\n </Heading>\n <div className={styles.subsectionItems}>\n {subsection.items.map((item, itemIndex) => (\n <NavigationMenuItem\n key={itemIndex}\n item={item}\n animationDelay={\n 150 + sectionIndex * 60 + subsectionIndex * 40 + itemIndex * 25\n }\n appBasePath={appBasePath}\n compact\n />\n ))}\n </div>\n </div>\n ))}\n </div>\n ) : (\n <div className={sectionIndex === 2 ? styles.itemsGridThreeCol : styles.itemsGrid}>\n {section.items?.map((item, itemIndex) => (\n <NavigationMenuItem\n key={itemIndex}\n item={item}\n animationDelay={150 + sectionIndex * 60 + itemIndex * 25}\n appBasePath={appBasePath}\n />\n ))}\n </div>\n )}\n </section>\n ))}\n </nav>\n </div>\n </div>\n </>\n );\n}","export type MenuItem = {\n label: string;\n href: string;\n external?: boolean;\n children?: MenuItem[];\n};\n\nexport type MenuSubsection = {\n title: string;\n items: MenuItem[];\n};\n\nexport type MenuSection = {\n title: string;\n layout?: 'columns' | 'subsections';\n items?: MenuItem[];\n subsections?: MenuSubsection[];\n};\n\nexport const NAVIGATION_MENU: MenuSection[] = [\n {\n title: 'Våre tjenester',\n layout: 'columns',\n items: [\n {\n label: 'Statens eide og leide lokaler',\n href: '/lokaler',\n children: [\n { label: 'Lokalbruk', href: '/lokaler/lokalbruk' },\n { label: 'Statlige eiendommer', href: '/lokaler/statlige-eiendommer' },\n { label: 'Ledig for fremleie', href: '/lokaler/ledig-for-fremleie' },\n { label: 'Statistikk for lokalbruk', href: '/lokaler/statistikk' },\n { label: 'Veiledning', href: '/lokaler/veiledning' },\n ],\n },\n {\n label: 'For leietakere',\n href: '/for-leietakere',\n children: [\n { label: 'Leieveileder', href: '/for-leietakere/leieveileder' },\n ],\n },\n {\n label: 'For byggebransjen',\n href: '/byggebransjen',\n children: [\n { label: 'Våre krav', href: '/byggebransjen/vare-krav' },\n { label: 'BIM', href: '/byggebransjen/bim' },\n { label: 'ByggBoks', href: '/byggebransjen/byggboks' },\n ],\n },\n {\n label: 'Karriere',\n href: '/karriere',\n children: [\n { label: 'Ledige stillinger', href: '/karriere/ledige-stillinger' },\n { label: 'Å jobbe hos oss', href: '/karriere/jobbe-hos-oss' },\n { label: 'Møt en statsbygger', href: '/karriere/mot-en-statsbygger' },\n { label: 'Summer internship', href: '/karriere/summer-internship' },\n { label: 'Studenter og lærlinger', href: '/karriere/studenter-og-laerlinger' },\n ],\n },\n ],\n },\n {\n title: 'Informasjon om statsbygg',\n layout: 'subsections',\n subsections: [\n {\n title: 'Informasjon om statsbygg',\n items: [\n { label: 'Om Statsbygg', href: '/om-statsbygg' },\n { label: 'Samfunnsansvar', href: '/samfunnsansvar' },\n { label: 'Tilgjengelighet', href: '/tilgjengelighet' },\n { label: 'About Statsbygg', href: '/about-statsbygg' },\n { label: 'Statsbygg birra', href: '/statsbygg-birra' },\n ],\n },\n {\n title: 'Kontakt oss',\n items: [\n { label: 'Kontakt oss', href: '/kontakt' },\n { label: 'Ansattsøk', href: '/ansattsok' },\n { label: 'For pressen', href: '/for-pressen' },\n { label: 'Varsling', href: '/varsling' },\n ],\n },\n {\n title: 'Arkiv',\n items: [\n { label: 'Nyheter', href: '/nyheter' },\n { label: 'Artikler om bygg', href: '/artikler-om-bygg' },\n { label: 'Dokumenter', href: '/dokumenter' },\n ],\n },\n ],\n },\n {\n title: 'Eksterne lenker',\n layout: 'columns',\n items: [\n {\n label: 'Statens lokaler',\n href: 'https://statensinnleie.no',\n external: true,\n },\n {\n label: 'Statens innleie',\n href: 'https://statensinnleie.no',\n external: true,\n },\n {\n label: 'MainManager FM',\n href: 'https://mainmanager.no',\n external: true,\n },\n {\n label: 'Offentlig postjournal',\n href: 'https://postjournal.no',\n external: true,\n },\n {\n label: 'SIMBA (BIM)',\n href: 'https://bim.statsbygg.no',\n external: true,\n },\n ],\n },\n];","'use client';\n\nimport { List } from '@digdir/designsystemet-react';\nimport { ExternalLink } from 'lucide-react';\nimport { usePathname } from 'next/navigation';\nimport clsx from 'clsx';\nimport { SmartLink } from '../SmartLink';\nimport type { MenuItem } from '../../navigationMenu';\nimport type { NavigationMenuItemProps } from './NavigationMenuItem.types';\nimport styles from './NavigationMenuItem.module.css';\n\nexport function NavigationMenuItem({\n item,\n animationDelay,\n compact = false,\n appBasePath,\n}: NavigationMenuItemProps) {\n const pathname = usePathname();\n\n const isActive = (href: string) => {\n if (href === '/') return pathname === '/';\n return pathname?.startsWith(href);\n };\n\n const isParentActive = isActive(item.href);\n\n if (compact) {\n return (\n <div\n className={styles.itemColumn}\n style={{ animationDelay: `${animationDelay}ms` }}\n >\n <SmartLink\n href={item.href}\n appBasePath={appBasePath}\n external={item.external}\n className={clsx(styles.compactLink, isParentActive && styles.active)}\n >\n {item.label}\n {item.external && <ExternalLink size={16} aria-hidden=\"true\" />}\n </SmartLink>\n </div>\n );\n }\n\n return (\n <div\n className={styles.itemColumn}\n style={{ animationDelay: `${animationDelay}ms` }}\n >\n <SmartLink\n href={item.href}\n appBasePath={appBasePath}\n external={item.external}\n className={clsx(styles.parentLink, isParentActive && styles.active)}\n >\n {item.label}\n {item.external && <ExternalLink size={20} aria-hidden=\"true\" />}\n </SmartLink>\n\n {item.children && item.children.length > 0 && (\n <List.Unordered className={styles.childItems}>\n {item.children.map((child: MenuItem, childIndex: number) => {\n const isChildActive = isActive(child.href);\n\n return (\n <List.Item\n key={childIndex}\n className={styles.childItem}\n style={{ animationDelay: `${animationDelay + 30 + childIndex * 15}ms` }}\n >\n <SmartLink\n href={child.href}\n appBasePath={appBasePath}\n external={child.external}\n className={clsx(styles.childLink, isChildActive && styles.active)}\n >\n {child.label}\n {child.external && <ExternalLink size={16} aria-hidden=\"true\" />}\n </SmartLink>\n </List.Item>\n );\n })}\n </List.Unordered>\n )}\n </div>\n );\n}","'use client';\n\nimport Link from 'next/link';\nimport { Link as DsLink } from '@digdir/designsystemet-react';\nimport type { SmartLinkProps } from './SmartLink.types';\n\n/**\n * Determines if a given href belongs to the current zone, another zone or should be external\n */\nexport function SmartLink({\n href,\n appBasePath,\n external = false,\n className,\n children,\n}: SmartLinkProps) {\n const isExternalUrl = href.startsWith('http://') || href.startsWith('https://');\n const isLocalRoute =\n appBasePath &&\n !isExternalUrl &&\n (href === appBasePath || href.startsWith(`${appBasePath}/`));\n\n if (isExternalUrl || external) {\n return (\n <DsLink\n href={href}\n className={className}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n {children}\n </DsLink>\n );\n }\n\n if (isLocalRoute) {\n // Strip the basePath\n const localHref = href.replace(appBasePath, '') || '/';\n\n return (\n <Link href={localHref} className={className}>\n {children}\n </Link>\n );\n }\n\n // Cross-zone navigation: use standard anchor for full page load\n return (\n <DsLink href={href} className={className}>\n {children}\n </DsLink>\n );\n}","'use client';\n\nimport { Paragraph } from '@digdir/designsystemet-react';\nimport clsx from 'clsx';\nimport type { GlobalFooterProps } from './GlobalFooter.types';\nimport styles from './GlobalFooter.module.css';\nimport { useLayoutTranslation } from '@/hooks/use-layout-translation';\n\nexport function GlobalFooter({ className }: GlobalFooterProps) {\n const { t } = useLayoutTranslation();\n\n return (\n <footer className={clsx(styles.footer, className)}>\n <div className={styles.container}>\n <div className={styles.content}>\n <Paragraph>\n {t('footer.content')}\n </Paragraph>\n\n\n </div>\n </div>\n </footer>\n );\n}","import { useEffect } from 'react';\nimport { useGlobalStore } from '../store/globalState';\nimport type { BreadcrumbItem } from '../routes';\n\n/**\n * Hook for manually setting breadcrumbs on dynamic routes.\n * Overrides automatic breadcrumb generation, preserving external ancestors.\n *\n * @param breadcrumbs - Array of breadcrumb items for the current dynamic route\n */\nexport function useBreadcrumbs(breadcrumbs: BreadcrumbItem[]): void {\n const setBreadcrumbs = useGlobalStore((state) => state.setBreadcrumbs);\n const serialized = JSON.stringify(breadcrumbs);\n\n useEffect(() => {\n setBreadcrumbs(JSON.parse(serialized));\n\n return () => {\n setBreadcrumbs(null);\n };\n }, [serialized, setBreadcrumbs]);\n}"],"mappings":"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","names":["useEffect","clsx","Button","Link","Search","clsx","usePathname","clsx","jsx","styles","jsx","usePathname","clsx","styles","jsx","jsxs","Fragment","jsx","jsxs","styles","Fragment","jsx","jsxs","clsx","Link","Button","Search","clsx","styles","jsx","clsx","styles","styles","jsx","jsxs","useEffect","clsx","useEffect","useEffect"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@statsbygg/layout",
3
- "version": "0.1.11",
3
+ "version": "0.1.13",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },