@kystverket/styrbord-consent 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/README.md +145 -0
  2. package/dist/src/components/ConsentBanner/ConsentBanner.d.ts +10 -0
  3. package/dist/src/components/ConsentBanner/ConsentBanner.stories.d.ts +16 -0
  4. package/dist/src/components/ConsentPreferencesDialog/ConsentPreferencesDialog.d.ts +13 -0
  5. package/dist/src/components/ConsentPreferencesDialog/ConsentPreferencesDialog.stories.d.ts +13 -0
  6. package/dist/src/components/ConsentProvider/ConsentProvider.d.ts +9 -0
  7. package/dist/src/components/ConsentProvider/ConsentProvider.types.d.ts +13 -0
  8. package/dist/src/components/ConsentSettingsButton/ConsentSettingsButton.d.ts +13 -0
  9. package/dist/src/components/ConsentSettingsButton/ConsentSettingsButton.stories.d.ts +11 -0
  10. package/dist/src/components/CookieConsent/CookieConsent.d.ts +18 -0
  11. package/dist/src/components/CookieConsent/CookieConsent.stories.d.ts +25 -0
  12. package/dist/src/components/shared/Button/Button.d.ts +22 -0
  13. package/dist/src/components/shared/Switch/Switch.d.ts +15 -0
  14. package/dist/src/hooks/useConsent.d.ts +26 -0
  15. package/dist/src/hooks/useStoreValue.d.ts +10 -0
  16. package/dist/src/main.d.ts +19 -0
  17. package/dist/src/utility/consent.types.d.ts +78 -0
  18. package/dist/src/utility/consentContext.d.ts +23 -0
  19. package/dist/src/utility/consentStore.d.ts +40 -0
  20. package/dist/src/utility/dialogRegistry.d.ts +26 -0
  21. package/dist/src/utility/services.d.ts +112 -0
  22. package/dist/src/utility/translations.d.ts +72 -0
  23. package/dist/storybook/ConsentDemo.d.ts +51 -0
  24. package/dist/storybook/styrbordDecorator.d.ts +14 -0
  25. package/dist/style.css +1 -0
  26. package/dist/style.js +447 -0
  27. package/dist/style.umd.cjs +12 -0
  28. package/package.json +54 -0
package/dist/style.js ADDED
@@ -0,0 +1,447 @@
1
+ 'use client';
2
+ import { jsx as o, jsxs as l, Fragment as V } from "react/jsx-runtime";
3
+ import { createContext as B, useContext as T, useEffect as w, useRef as N, useState as F, useMemo as G, useSyncExternalStore as Z, useId as Q } from "react";
4
+ import { deleteCookie as x, configureConsentManager as W, createConsentManagerStore as Y } from "c15t";
5
+ const U = B(null);
6
+ function C() {
7
+ const e = T(U);
8
+ if (!e)
9
+ throw new Error("useConsentStore må brukes innenfor en <ConsentProvider>.");
10
+ return e;
11
+ }
12
+ const O = "kystverket_consent", M = 182;
13
+ function A(e) {
14
+ const n = e.filter((t) => !t.alwaysLoad).map((t) => t.category).filter((t) => typeof t == "string").filter((t) => t !== "necessary");
15
+ return [...new Set(n)];
16
+ }
17
+ function z(e) {
18
+ return A(e).length > 0;
19
+ }
20
+ function X(e, n, t) {
21
+ if (typeof document > "u")
22
+ return;
23
+ const a = e.filter((s) => s.alwaysLoad || typeof s.category != "string" ? !1 : n[s.category] !== !0).flatMap((s) => s.clearCookiePrefixes ?? []);
24
+ if (a.length === 0)
25
+ return;
26
+ const i = document.cookie.split(";").map((s) => {
27
+ var d;
28
+ return (d = s.split("=")[0]) == null ? void 0 : d.trim();
29
+ }).filter((s) => !!s);
30
+ for (const s of i)
31
+ a.some((d) => s.startsWith(d)) && (x(s), x(s, { domain: window.location.hostname }), t && x(s, { domain: t }));
32
+ }
33
+ function J(e) {
34
+ return {
35
+ storageKey: e.storageKey ?? O,
36
+ defaultExpiryDays: e.expiryDays ?? M,
37
+ // Bevisst ikke `crossSubdomain: true` — se kommentaren på ConsentConfig.cookieDomain.
38
+ ...e.cookieDomain ? { defaultDomain: e.cookieDomain } : {}
39
+ };
40
+ }
41
+ function ee(e) {
42
+ const n = J(e), t = W({
43
+ mode: "offline",
44
+ storageConfig: n
45
+ });
46
+ return Y(t, {
47
+ storageConfig: n,
48
+ scripts: e.services,
49
+ initialConsentCategories: A(e.services),
50
+ debug: e.debug ?? !1,
51
+ // Laster siden på nytt når samtykke trekkes tilbake. Nødvendig fordi et skript som
52
+ // Hotjar ikke lar seg stoppe når det først kjører.
53
+ reloadOnConsentRevoked: !0,
54
+ callbacks: {
55
+ onConsentSet: ({ preferences: a }) => X(e.services, a, e.cookieDomain)
56
+ }
57
+ });
58
+ }
59
+ const $ = B(null), ne = $.Provider;
60
+ function te() {
61
+ return N({ count: 0 }).current;
62
+ }
63
+ function se() {
64
+ const e = T($);
65
+ w(() => {
66
+ if (e)
67
+ return e.count += 1, () => {
68
+ e.count -= 1;
69
+ };
70
+ }, [e]);
71
+ }
72
+ const L = /* @__PURE__ */ new Set();
73
+ function H(e, n) {
74
+ const t = T($);
75
+ w(() => {
76
+ if (!n || !t || L.has(e))
77
+ return;
78
+ const a = setTimeout(() => {
79
+ t.count > 0 || L.has(e) || (L.add(e), console.warn(`<${e}> is shown without a <ConsentPreferencesDialog> mounted. Opening the consent settings will hide it with nothing to replace it, leaving the user unable to give or withdraw consent. Mount <ConsentPreferencesDialog> alongside it, or use <CookieConsent>, which mounts all three surfaces.`));
80
+ }, 0);
81
+ return () => clearTimeout(a);
82
+ }, [n, e, t]);
83
+ }
84
+ const oe = { heading: "Cookies", body: "We use cookies to understand how this service is used, so that we can improve it. You decide what you consent to.", acceptAll: "Accept all", rejectAll: "Necessary only", managePreferences: "Choose yourself" }, ie = { heading: "Cookie settings", body: "Necessary cookies are always on, because the service does not work without them. The rest is up to you.", savePreferences: "Save choices", acceptAll: "Accept all", rejectAll: "Necessary only", close: "Close", servicesLabel: "Services", showCookies: "Show cookies", noCookies: "Sets no cookies", alwaysOnHeading: "Always on", alwaysOnBody: "These store nothing on your device and cannot be used to recognise you. They therefore do not require consent, and are always on.", cookieName: "Name", cookieProvider: "Provided by", cookieDuration: "Duration" }, ae = { session: "Until you close your browser", day: "{{count}} day", days: "{{count}} days", month: "{{count}} month", months: "{{count}} months", year: "{{count}} year", years: "{{count}} years" }, re = { necessary: { title: "Necessary", description: "Required for the service to work, including sign-in and security. These cannot be turned off." }, functionality: { title: "Functionality", description: "Remembers your choices, such as language and other settings." }, measurement: { title: "Statistics", description: "Lets us count visits and see which pages are used, so we can prioritise correctly." }, experience: { title: "User experience", description: "Lets us see how the pages are actually used, through anonymised recordings and heatmaps, so we can fix what is difficult." }, marketing: { title: "Marketing", description: "Used to tailor advertising. Kystverket does not use this today." } }, ce = "Manage cookies", le = {
85
+ banner: oe,
86
+ dialog: ie,
87
+ durations: ae,
88
+ categories: re,
89
+ manageLink: ce
90
+ }, de = { heading: "Informasjonskapsler", body: "Vi bruker informasjonskapsler for å forstå hvordan tjenesten brukes, slik at vi kan gjøre den bedre. Du velger selv hva du samtykker til.", acceptAll: "Godta alle", rejectAll: "Kun nødvendige", managePreferences: "Velg selv" }, ue = { heading: "Innstillinger for informasjonskapsler", body: "Nødvendige informasjonskapsler er alltid på, fordi tjenesten ikke fungerer uten dem. De øvrige velger du selv.", savePreferences: "Lagre valg", acceptAll: "Godta alle", rejectAll: "Kun nødvendige", close: "Lukk", servicesLabel: "Tjenester", showCookies: "Vis informasjonskapsler", noCookies: "Setter ingen informasjonskapsler", alwaysOnHeading: "Alltid på", alwaysOnBody: "Disse lagrer ingenting på enheten din og kan ikke brukes til å kjenne deg igjen. De krever derfor ikke samtykke, og er alltid på.", cookieName: "Navn", cookieProvider: "Levert av", cookieDuration: "Varighet" }, ge = { session: "Til du lukker nettleseren", day: "{{count}} dag", days: "{{count}} dager", month: "{{count}} måned", months: "{{count}} måneder", year: "{{count}} år", years: "{{count}} år" }, he = { necessary: { title: "Nødvendige", description: "Kreves for at tjenesten skal fungere, blant annet for innlogging og sikkerhet. Disse kan ikke slås av." }, functionality: { title: "Funksjonalitet", description: "Husker valgene dine, som språk og andre innstillinger." }, measurement: { title: "Statistikk", description: "Lar oss telle besøk og se hvilke sider som brukes, slik at vi kan prioritere riktig." }, experience: { title: "Brukeropplevelse", description: "Lar oss se hvordan sidene faktisk brukes, gjennom anonymiserte opptak og varmekart, slik at vi kan rette opp det som er vanskelig." }, marketing: { title: "Markedsføring", description: "Brukes til å tilpasse annonser. Kystverket bruker ikke dette i dag." } }, ke = "Administrer informasjonskapsler", me = {
91
+ banner: de,
92
+ dialog: ue,
93
+ durations: ge,
94
+ categories: he,
95
+ manageLink: ke
96
+ }, ye = { heading: "Informasjonskapslar", body: "Vi brukar informasjonskapslar for å forstå korleis tenesta blir brukt, slik at vi kan gjere henne betre. Du vel sjølv kva du samtykkjer til.", acceptAll: "Godta alle", rejectAll: "Berre nødvendige", managePreferences: "Vel sjølv" }, pe = { heading: "Innstillingar for informasjonskapslar", body: "Nødvendige informasjonskapslar er alltid på, fordi tenesta ikkje fungerer utan dei. Dei andre vel du sjølv.", savePreferences: "Lagre val", acceptAll: "Godta alle", rejectAll: "Berre nødvendige", close: "Lukk", servicesLabel: "Tenester", showCookies: "Vis informasjonskapslar", noCookies: "Set ingen informasjonskapslar", alwaysOnHeading: "Alltid på", alwaysOnBody: "Desse lagrar ingenting på eininga di og kan ikkje brukast til å kjenne deg att. Dei krev difor ikkje samtykke, og er alltid på.", cookieName: "Namn", cookieProvider: "Levert av", cookieDuration: "Varigheit" }, fe = { session: "Til du lukkar nettlesaren", day: "{{count}} dag", days: "{{count}} dagar", month: "{{count}} månad", months: "{{count}} månader", year: "{{count}} år", years: "{{count}} år" }, ve = { necessary: { title: "Nødvendige", description: "Krevst for at tenesta skal fungere, mellom anna for innlogging og tryggleik. Desse kan ikkje slåast av." }, functionality: { title: "Funksjonalitet", description: "Hugsar vala dine, som språk og andre innstillingar." }, measurement: { title: "Statistikk", description: "Lèt oss telje besøk og sjå kva sider som blir brukte, slik at vi kan prioritere rett." }, experience: { title: "Brukaroppleving", description: "Lèt oss sjå korleis sidene faktisk blir brukte, gjennom anonymiserte opptak og varmekart, slik at vi kan rette opp det som er vanskeleg." }, marketing: { title: "Marknadsføring", description: "Blir brukt til å tilpasse annonsar. Kystverket brukar ikkje dette i dag." } }, be = "Administrer informasjonskapslar", _e = {
97
+ banner: ye,
98
+ dialog: pe,
99
+ durations: fe,
100
+ categories: ve,
101
+ manageLink: be
102
+ }, _ = {
103
+ "nb-NO": me,
104
+ "nn-NO": _e,
105
+ "en-US": le
106
+ }, P = "nb-NO";
107
+ function Ce(e) {
108
+ var i;
109
+ if (!e)
110
+ return _[P];
111
+ const n = _[e];
112
+ if (n)
113
+ return n;
114
+ const t = (i = e.split("-")[0]) == null ? void 0 : i.toLowerCase(), a = Object.keys(_).find((s) => s.split("-")[0].toLowerCase() === t);
115
+ return a ? _[a] : _[P];
116
+ }
117
+ function je(e, n) {
118
+ const { durations: t } = n;
119
+ if (e === "session")
120
+ return t.session;
121
+ const a = (i, s) => i.replace("{{count}}", String(s));
122
+ if (e >= 365 && e % 365 === 0) {
123
+ const i = e / 365;
124
+ return a(i === 1 ? t.year : t.years, i);
125
+ }
126
+ if (e >= 28) {
127
+ const i = Math.round(e / 30.4);
128
+ if (i >= 1)
129
+ return a(i === 1 ? t.month : t.months, i);
130
+ }
131
+ return a(e === 1 ? t.day : t.days, e);
132
+ }
133
+ function we(e, n) {
134
+ return n ? {
135
+ banner: { ...e.banner, ...n.banner },
136
+ dialog: { ...e.dialog, ...n.dialog },
137
+ durations: { ...e.durations, ...n.durations },
138
+ categories: { ...e.categories, ...n.categories },
139
+ manageLink: n.manageLink ?? e.manageLink
140
+ } : e;
141
+ }
142
+ function hn({ children: e, language: n, translations: t, ...a }) {
143
+ const i = N(null);
144
+ i.current ?? (i.current = ee(a));
145
+ const s = i.current, { services: d } = a, g = d.map((h) => h.id).join(","), [m, p] = F(!1);
146
+ w(() => p(!0), []);
147
+ const y = te(), u = G(
148
+ () => ({
149
+ store: s,
150
+ translations: we(Ce(n), t),
151
+ showsBanner: z(d),
152
+ mounted: m
153
+ }),
154
+ // `serviceIds` står her med vilje i stedet for `services`: lista bygges som regel inline
155
+ // hos kallstedet og har ny identitet ved hver render, mens innholdet er det samme.
156
+ [s, n, t, g, m]
157
+ );
158
+ return /* @__PURE__ */ o(U.Provider, { value: u, children: /* @__PURE__ */ o(ne, { value: y, children: e }) });
159
+ }
160
+ function k(e, n) {
161
+ const t = N(null);
162
+ return Z(e.subscribe, () => n(e.getState()), () => (t.current ?? (t.current = { value: n(e.getState()) }), t.current.value));
163
+ }
164
+ function Ne() {
165
+ const { store: e } = C(), n = k(e, (s) => s.consents), t = k(e, (s) => s.activeUI), a = k(e, (s) => s.consentInfo), i = k(e, (s) => s.isLoadingConsentInfo);
166
+ return {
167
+ hasConsent: (s) => e.getState().has(s),
168
+ consents: n,
169
+ needsDecision: !i && a === null,
170
+ showPreferences: () => e.getState().setActiveUI("dialog"),
171
+ close: () => e.getState().setActiveUI("none"),
172
+ activeUI: t
173
+ };
174
+ }
175
+ const Se = "_button_ax4nf_2", xe = "_filled_ax4nf_29", Le = "_outline_ax4nf_42", De = "_ghost_ax4nf_48", q = {
176
+ button: Se,
177
+ filled: xe,
178
+ outline: Le,
179
+ ghost: De
180
+ };
181
+ function v({ variant: e = "filled", className: n, type: t = "button", ...a }) {
182
+ return /* @__PURE__ */ o("button", { ...a, type: t, className: [q.button, q[e], n].filter(Boolean).join(" ") });
183
+ }
184
+ const Te = "_banner_hahjv_2", Ae = "_inner_hahjv_15", $e = "_text_hahjv_23", Pe = "_heading_hahjv_29", qe = "_body_hahjv_38", Ie = "_actions_hahjv_45", f = {
185
+ banner: Te,
186
+ inner: Ae,
187
+ text: $e,
188
+ heading: Pe,
189
+ body: qe,
190
+ actions: Ie
191
+ };
192
+ function Be() {
193
+ const { store: e, translations: n, showsBanner: t, mounted: a } = C(), i = k(e, (m) => m.activeUI), s = a && t && i === "banner";
194
+ if (H("ConsentBanner", s), !s)
195
+ return null;
196
+ const { saveConsents: d, setActiveUI: g } = e.getState();
197
+ return /* @__PURE__ */ o("section", { className: f.banner, "data-color": "primary", "aria-labelledby": "styrbord-consent-banner-heading", children: /* @__PURE__ */ l("div", { className: f.inner, children: [
198
+ /* @__PURE__ */ l("div", { className: f.text, children: [
199
+ /* @__PURE__ */ o("h2", { id: "styrbord-consent-banner-heading", className: f.heading, children: n.banner.heading }),
200
+ /* @__PURE__ */ o("p", { className: f.body, children: n.banner.body })
201
+ ] }),
202
+ /* @__PURE__ */ l("div", { className: f.actions, children: [
203
+ /* @__PURE__ */ o(v, { variant: "filled", onClick: () => d("all"), children: n.banner.acceptAll }),
204
+ /* @__PURE__ */ o(v, { variant: "outline", onClick: () => d("necessary"), children: n.banner.rejectAll }),
205
+ /* @__PURE__ */ o(v, { variant: "ghost", onClick: () => g("dialog"), children: n.banner.managePreferences })
206
+ ] })
207
+ ] }) });
208
+ }
209
+ const Ue = "_input_oxxbn_10", Oe = "_label_oxxbn_53", Me = "_description_oxxbn_62", j = {
210
+ switch: "_switch_oxxbn_2",
211
+ input: Ue,
212
+ label: Oe,
213
+ description: Me
214
+ };
215
+ function He({ label: e, description: n, checked: t, onChange: a }) {
216
+ const i = Q(), s = `${i}-description`;
217
+ return /* @__PURE__ */ l("div", { className: j.switch, children: [
218
+ /* @__PURE__ */ o("input", { id: i, type: "checkbox", role: "switch", className: j.input, checked: t, onChange: a, "aria-describedby": n ? s : void 0 }),
219
+ /* @__PURE__ */ o("label", { className: j.label, htmlFor: i, children: e }),
220
+ n && /* @__PURE__ */ o("p", { id: s, className: j.description, children: n })
221
+ ] });
222
+ }
223
+ const Re = "_dialog_1y45s_2", Ee = "_content_1y45s_26", Ke = "_header_1y45s_34", Ve = "_heading_1y45s_41", Fe = "_close_1y45s_50", Ge = "_summary_1y45s_75", Ze = "_body_1y45s_80", Qe = "_fineprint_1y45s_87", We = "_categories_1y45s_95", Ye = "_category_1y45s_101", ze = "_categoryHeading_1y45s_114", Xe = "_services_1y45s_122", Je = "_details_1y45s_129", en = "_table_1y45s_142", nn = "_buttons_1y45s_162", c = {
224
+ dialog: Re,
225
+ content: Ee,
226
+ header: Ke,
227
+ heading: Ve,
228
+ close: Fe,
229
+ summary: Ge,
230
+ body: Ze,
231
+ fineprint: Qe,
232
+ categories: We,
233
+ category: Ye,
234
+ categoryHeading: ze,
235
+ services: Xe,
236
+ details: Je,
237
+ table: en,
238
+ buttons: nn
239
+ };
240
+ function D({ services: e, translations: n }) {
241
+ if (!e.some((i) => i.cookies !== void 0))
242
+ return null;
243
+ const a = e.flatMap((i) => (i.cookies ?? []).map((s) => ({ ...s, provider: i.displayName ?? i.id })));
244
+ return a.length === 0 ? /* @__PURE__ */ o("p", { className: c.fineprint, children: n.dialog.noCookies }) : /* @__PURE__ */ l("details", { className: c.details, children: [
245
+ /* @__PURE__ */ o("summary", { className: c.summary, children: n.dialog.showCookies }),
246
+ /* @__PURE__ */ l("table", { className: c.table, children: [
247
+ /* @__PURE__ */ o("thead", { children: /* @__PURE__ */ l("tr", { children: [
248
+ /* @__PURE__ */ o("th", { scope: "col", children: n.dialog.cookieName }),
249
+ /* @__PURE__ */ o("th", { scope: "col", children: n.dialog.cookieProvider }),
250
+ /* @__PURE__ */ o("th", { scope: "col", children: n.dialog.cookieDuration })
251
+ ] }) }),
252
+ /* @__PURE__ */ o("tbody", { children: a.map((i) => /* @__PURE__ */ l("tr", { children: [
253
+ /* @__PURE__ */ o("td", { children: /* @__PURE__ */ o("code", { children: i.name }) }),
254
+ /* @__PURE__ */ o("td", { children: i.provider }),
255
+ /* @__PURE__ */ o("td", { children: je(i.duration, n) })
256
+ ] }, `${i.provider}-${i.name}`)) })
257
+ ] })
258
+ ] });
259
+ }
260
+ function I({ services: e, translations: n }) {
261
+ return e.length === 0 ? null : /* @__PURE__ */ l("p", { className: c.fineprint, children: [
262
+ n.dialog.servicesLabel,
263
+ ": ",
264
+ e.map((t) => t.displayName ?? t.id).join(", ")
265
+ ] });
266
+ }
267
+ function tn() {
268
+ const { store: e, translations: n, mounted: t } = C(), a = k(e, (r) => r.activeUI), i = k(e, (r) => r.selectedConsents), s = k(e, (r) => r.scripts), d = N(null), g = a === "dialog";
269
+ se(), w(() => {
270
+ const r = d.current;
271
+ r && (g && !r.open ? r.showModal() : !g && r.open && r.close());
272
+ }, [g]);
273
+ const m = A(s), { setSelectedConsent: p, saveConsents: y, setActiveUI: u } = e.getState();
274
+ if (!t)
275
+ return null;
276
+ const h = s.filter((r) => r.category === "necessary"), S = s.filter((r) => r.alwaysLoad && r.category !== "necessary"), R = (r) => s.filter((b) => !b.alwaysLoad && b.category === r), E = (r) => {
277
+ r.target === d.current && u("none");
278
+ };
279
+ return /* @__PURE__ */ l("dialog", { ref: d, className: c.dialog, "data-color": "primary", "aria-labelledby": "styrbord-consent-dialog-heading", onClose: () => u("none"), onClick: E, children: [
280
+ /* @__PURE__ */ l("div", { className: c.content, children: [
281
+ /* @__PURE__ */ l("div", { className: c.header, children: [
282
+ /* @__PURE__ */ o("h2", { id: "styrbord-consent-dialog-heading", className: c.heading, children: n.dialog.heading }),
283
+ /* @__PURE__ */ o("button", { type: "button", className: c.close, "aria-label": n.dialog.close, onClick: () => u("none"), children: /* @__PURE__ */ o("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": !0, focusable: "false", children: /* @__PURE__ */ o("path", { d: "m6 6 12 12M18 6 6 18", strokeLinecap: "round" }) }) })
284
+ ] }),
285
+ /* @__PURE__ */ o("p", { className: c.body, children: n.dialog.body }),
286
+ /* @__PURE__ */ l("div", { className: c.categories, children: [
287
+ /* @__PURE__ */ l("section", { className: c.category, children: [
288
+ /* @__PURE__ */ o("h3", { className: c.categoryHeading, children: n.categories.necessary.title }),
289
+ /* @__PURE__ */ o("p", { className: c.body, children: n.categories.necessary.description }),
290
+ /* @__PURE__ */ o(D, { services: h, translations: n })
291
+ ] }),
292
+ S.length > 0 && /* @__PURE__ */ l("section", { className: c.category, children: [
293
+ /* @__PURE__ */ o("h3", { className: c.categoryHeading, children: n.dialog.alwaysOnHeading }),
294
+ /* @__PURE__ */ o("p", { className: c.body, children: n.dialog.alwaysOnBody }),
295
+ /* @__PURE__ */ o(I, { services: S, translations: n }),
296
+ /* @__PURE__ */ o(D, { services: S, translations: n })
297
+ ] }),
298
+ m.map((r) => {
299
+ const b = R(r);
300
+ return /* @__PURE__ */ l("section", { className: c.category, children: [
301
+ /* @__PURE__ */ o(He, { label: n.categories[r].title, description: n.categories[r].description, checked: i[r] === !0, onChange: (K) => p(r, K.target.checked) }),
302
+ /* @__PURE__ */ l("div", { className: c.services, children: [
303
+ /* @__PURE__ */ o(I, { services: b, translations: n }),
304
+ /* @__PURE__ */ o(D, { services: b, translations: n })
305
+ ] })
306
+ ] }, r);
307
+ })
308
+ ] })
309
+ ] }),
310
+ /* @__PURE__ */ l("div", { className: c.buttons, children: [
311
+ /* @__PURE__ */ o(v, { variant: "filled", onClick: () => y("custom"), children: n.dialog.savePreferences }),
312
+ /* @__PURE__ */ o(v, { variant: "outline", onClick: () => y("all"), children: n.dialog.acceptAll }),
313
+ /* @__PURE__ */ o(v, { variant: "ghost", onClick: () => y("necessary"), children: n.dialog.rejectAll })
314
+ ] })
315
+ ] });
316
+ }
317
+ const sn = "_button_zo1st_2", on = {
318
+ button: sn
319
+ };
320
+ function an() {
321
+ return /* @__PURE__ */ o("svg", { xmlns: "http://www.w3.org/2000/svg", height: "20px", viewBox: "0 -960 960 960", width: "20px", children: /* @__PURE__ */ o("path", { color: "currentColor", d: "M480-96q-79.38 0-149.19-30T208.5-208.5Q156-261 126-330.81T96-480q0-81 31-151.5t82.5-123Q261-807 329-837.5T470-868q23 0 45 3t45 9q-8 45 5.5 82t42.03 60.96q28.53 23.96 68 33T759-681q-24 57 8.01 108.5 32.01 51.49 95.08 53.4.95 10.49 1.43 19.55T864-480q0 78-30.24 147.98-30.24 69.99-82.08 122.6t-121.92 83.01Q559.68-96 480-96Zm-60-456q25 0 42.5-17.5T480-612q0-25-17.5-42.5T420-672q-25 0-42.5 17.5T360-612q0 25 17.5 42.5T420-552Zm-96 192q25 0 42.5-17.5T384-420q0-25-17.5-42.5T324-480q-25 0-42.5 17.5T264-420q0 25 17.5 42.5T324-360Zm275.79 36q15.21 0 25.71-10.29t10.5-25.5q0-15.21-10.29-25.71t-25.5-10.5q-15.21 0-25.71 10.29t-10.5 25.5q0 15.21 10.29 25.71t25.5 10.5ZM480-168q125 0 214.5-84.5T792-462q-45-18-75-55.5T679-603q-76-11-129-63t-63-126q-63-4-120.5 19.5t-102 66.5Q220-663 194-604.5T168-480q0 129.67 91.16 220.84Q350.33-168 480-168Zm0-311Z" }) });
322
+ }
323
+ function rn() {
324
+ const { store: e, translations: n, showsBanner: t, mounted: a } = C(), i = k(e, (d) => d.activeUI), s = a && t && i === "none";
325
+ return H("ConsentSettingsButton", s), s ? /* @__PURE__ */ o("button", { type: "button", className: on.button, "data-color": "neutral", "aria-label": n.manageLink, title: n.manageLink, onClick: () => e.getState().setActiveUI("dialog"), children: /* @__PURE__ */ o(an, {}) }) : null;
326
+ }
327
+ const cn = "_link_6z1zn_4", ln = {
328
+ link: cn
329
+ };
330
+ function kn() {
331
+ return /* @__PURE__ */ l(V, { children: [
332
+ /* @__PURE__ */ o(Be, {}),
333
+ /* @__PURE__ */ o(tn, {}),
334
+ /* @__PURE__ */ o(rn, {})
335
+ ] });
336
+ }
337
+ function mn({ className: e }) {
338
+ const { translations: n } = C(), { showPreferences: t } = Ne();
339
+ return /* @__PURE__ */ o("button", { type: "button", className: [ln.link, e].filter(Boolean).join(" "), onClick: t, children: n.manageLink });
340
+ }
341
+ function yn({ domain: e, requireConsent: n = !1, scriptSrc: t = "https://plausible.io/js/script.js" }) {
342
+ return {
343
+ id: "plausible",
344
+ displayName: "Plausible",
345
+ src: t,
346
+ category: "measurement",
347
+ alwaysLoad: !n,
348
+ defer: !0,
349
+ attributes: { "data-domain": e },
350
+ // Tom liste, ikke utelatt: dialogen skiller mellom «setter ingen kapsler» og «vi har
351
+ // ikke oppgitt noe», og det kapselfrie er hele grunnen til at Plausible går usamtykket.
352
+ cookies: []
353
+ };
354
+ }
355
+ function pn({ siteId: e }) {
356
+ return {
357
+ id: "hotjar",
358
+ displayName: "Hotjar",
359
+ category: "experience",
360
+ clearCookiePrefixes: ["_hj"],
361
+ cookies: [
362
+ { name: "_hjSessionUser_*", duration: 365 },
363
+ { name: "_hjSession_*", duration: 1 },
364
+ { name: "_hjIncludedInSessionSample_*", duration: 1 }
365
+ ],
366
+ textContent: `
367
+ (function (h, o, t, j, a, r) {
368
+ h.hj = h.hj || function () { (h.hj.q = h.hj.q || []).push(arguments); };
369
+ h._hjSettings = { hjid: ${Number(e)}, hjsv: 6 };
370
+ a = o.getElementsByTagName('head')[0];
371
+ r = o.createElement('script');
372
+ r.async = 1;
373
+ r.src = t + h._hjSettings.hjid + j + h._hjSettings.hjsv;
374
+ a.appendChild(r);
375
+ })(window, document, 'https://static.hotjar.com/c/hotjar-', '.js?sv=');
376
+ `
377
+ };
378
+ }
379
+ function fn({ apiKey: e, apiHost: n = "https://eu.i.posthog.com", assetHost: t, sessionReplay: a = !1, capturePageview: i = !0, personProfiles: s = "identified_only", defaults: d = "2026-05-30" }) {
380
+ const g = n.replace(/\/$/, ""), m = (t ?? g.replace(".i.posthog.com", "-assets.i.posthog.com")).replace(/\/$/, ""), p = () => window.posthog, y = (u) => {
381
+ if (!a)
382
+ return;
383
+ const h = p();
384
+ h && (u.experience === !0 ? h.startSessionRecording() : h.stopSessionRecording());
385
+ };
386
+ return {
387
+ id: "posthog",
388
+ displayName: "PostHog",
389
+ category: "measurement",
390
+ clearCookiePrefixes: ["ph_"],
391
+ // Kapselen heter `ph_<nøkkel>_posthog`. Nøkkelen er kjent her, så brukeren får se det
392
+ // faktiske navnet framfor et jokertegn. PostHog speiler den samme verdien til localStorage,
393
+ // som dialogen foreløpig ikke har noen måte å vise.
394
+ cookies: [{ name: `ph_${e}_posthog`, duration: 365 }],
395
+ src: `${m}/static/array.js`,
396
+ onLoad: ({ consents: u }) => {
397
+ var h;
398
+ (h = p()) == null || h.init(e, {
399
+ api_host: g,
400
+ person_profiles: s,
401
+ capture_pageview: i,
402
+ defaults: d,
403
+ // PostHog setter denne til `true` selv, som legger kapselen på toppdomenet. Samme felle
404
+ // som c15t sin `crossSubdomain` — se kommentaren på `ConsentConfig.cookieDomain`.
405
+ cross_subdomain_cookie: !1,
406
+ disable_session_recording: !0,
407
+ capture_heatmaps: a && u.experience === !0
408
+ }), y(u);
409
+ },
410
+ onConsentChange: ({ consents: u }) => y(u)
411
+ };
412
+ }
413
+ function vn(e = O, n = M) {
414
+ return {
415
+ id: "consent",
416
+ displayName: "Kystverket",
417
+ category: "necessary",
418
+ callbackOnly: !0,
419
+ alwaysLoad: !0,
420
+ cookies: [{ name: e, duration: n }]
421
+ };
422
+ }
423
+ export {
424
+ Be as ConsentBanner,
425
+ tn as ConsentPreferencesDialog,
426
+ hn as ConsentProvider,
427
+ rn as ConsentSettingsButton,
428
+ kn as CookieConsent,
429
+ M as DEFAULT_EXPIRY_DAYS,
430
+ O as DEFAULT_STORAGE_KEY,
431
+ mn as ManageConsentLink,
432
+ X as clearServiceCookies,
433
+ vn as consentCookieService,
434
+ _ as consentTranslations,
435
+ ee as createConsentStore,
436
+ P as defaultConsentLanguage,
437
+ je as formatCookieDuration,
438
+ Ce as getConsentTranslations,
439
+ A as getSelectableCategories,
440
+ z as hasGatedServices,
441
+ pn as hotjarService,
442
+ yn as plausibleService,
443
+ fn as postHogService,
444
+ Ne as useConsent,
445
+ C as useConsentStore,
446
+ k as useStoreValue
447
+ };
@@ -0,0 +1,12 @@
1
+ 'use client';
2
+ (function(r,t){typeof exports=="object"&&typeof module<"u"?t(exports,require("react/jsx-runtime"),require("react"),require("c15t")):typeof define=="function"&&define.amd?define(["exports","react/jsx-runtime","react","c15t"],t):(r=typeof globalThis<"u"?globalThis:r||self,t(r.Styrbord={},r.jsxRuntime,r.React,r.c15t))})(this,(function(r,t,g,j){"use strict";const x=g.createContext(null);function v(){const e=g.useContext(x);if(!e)throw new Error("useConsentStore må brukes innenfor en <ConsentProvider>.");return e}const L="kystverket_consent",$=182;function w(e){const n=e.filter(s=>!s.alwaysLoad).map(s=>s.category).filter(s=>typeof s=="string").filter(s=>s!=="necessary");return[...new Set(n)]}function I(e){return w(e).length>0}function B(e,n,s){if(typeof document>"u")return;const i=e.filter(o=>o.alwaysLoad||typeof o.category!="string"?!1:n[o.category]!==!0).flatMap(o=>o.clearCookiePrefixes??[]);if(i.length===0)return;const a=document.cookie.split(";").map(o=>{var d;return(d=o.split("=")[0])==null?void 0:d.trim()}).filter(o=>!!o);for(const o of a)i.some(d=>o.startsWith(d))&&(j.deleteCookie(o),j.deleteCookie(o,{domain:window.location.hostname}),s&&j.deleteCookie(o,{domain:s}))}function Z(e){return{storageKey:e.storageKey??L,defaultExpiryDays:e.expiryDays??$,...e.cookieDomain?{defaultDomain:e.cookieDomain}:{}}}function U(e){const n=Z(e),s=j.configureConsentManager({mode:"offline",storageConfig:n});return j.createConsentManagerStore(s,{storageConfig:n,scripts:e.services,initialConsentCategories:w(e.services),debug:e.debug??!1,reloadOnConsentRevoked:!0,callbacks:{onConsentSet:({preferences:i})=>B(e.services,i,e.cookieDomain)}})}const T=g.createContext(null),Q=T.Provider;function W(){return g.useRef({count:0}).current}function z(){const e=g.useContext(T);g.useEffect(()=>{if(e)return e.count+=1,()=>{e.count-=1}},[e])}const D=new Set;function O(e,n){const s=g.useContext(T);g.useEffect(()=>{if(!n||!s||D.has(e))return;const i=setTimeout(()=>{s.count>0||D.has(e)||(D.add(e),console.warn(`<${e}> is shown without a <ConsentPreferencesDialog> mounted. Opening the consent settings will hide it with nothing to replace it, leaving the user unable to give or withdraw consent. Mount <ConsentPreferencesDialog> alongside it, or use <CookieConsent>, which mounts all three surfaces.`))},0);return()=>clearTimeout(i)},[n,e,s])}const b={"nb-NO":{banner:{heading:"Informasjonskapsler",body:"Vi bruker informasjonskapsler for å forstå hvordan tjenesten brukes, slik at vi kan gjøre den bedre. Du velger selv hva du samtykker til.",acceptAll:"Godta alle",rejectAll:"Kun nødvendige",managePreferences:"Velg selv"},dialog:{heading:"Innstillinger for informasjonskapsler",body:"Nødvendige informasjonskapsler er alltid på, fordi tjenesten ikke fungerer uten dem. De øvrige velger du selv.",savePreferences:"Lagre valg",acceptAll:"Godta alle",rejectAll:"Kun nødvendige",close:"Lukk",servicesLabel:"Tjenester",showCookies:"Vis informasjonskapsler",noCookies:"Setter ingen informasjonskapsler",alwaysOnHeading:"Alltid på",alwaysOnBody:"Disse lagrer ingenting på enheten din og kan ikke brukes til å kjenne deg igjen. De krever derfor ikke samtykke, og er alltid på.",cookieName:"Navn",cookieProvider:"Levert av",cookieDuration:"Varighet"},durations:{session:"Til du lukker nettleseren",day:"{{count}} dag",days:"{{count}} dager",month:"{{count}} måned",months:"{{count}} måneder",year:"{{count}} år",years:"{{count}} år"},categories:{necessary:{title:"Nødvendige",description:"Kreves for at tjenesten skal fungere, blant annet for innlogging og sikkerhet. Disse kan ikke slås av."},functionality:{title:"Funksjonalitet",description:"Husker valgene dine, som språk og andre innstillinger."},measurement:{title:"Statistikk",description:"Lar oss telle besøk og se hvilke sider som brukes, slik at vi kan prioritere riktig."},experience:{title:"Brukeropplevelse",description:"Lar oss se hvordan sidene faktisk brukes, gjennom anonymiserte opptak og varmekart, slik at vi kan rette opp det som er vanskelig."},marketing:{title:"Markedsføring",description:"Brukes til å tilpasse annonser. Kystverket bruker ikke dette i dag."}},manageLink:"Administrer informasjonskapsler"},"nn-NO":{banner:{heading:"Informasjonskapslar",body:"Vi brukar informasjonskapslar for å forstå korleis tenesta blir brukt, slik at vi kan gjere henne betre. Du vel sjølv kva du samtykkjer til.",acceptAll:"Godta alle",rejectAll:"Berre nødvendige",managePreferences:"Vel sjølv"},dialog:{heading:"Innstillingar for informasjonskapslar",body:"Nødvendige informasjonskapslar er alltid på, fordi tenesta ikkje fungerer utan dei. Dei andre vel du sjølv.",savePreferences:"Lagre val",acceptAll:"Godta alle",rejectAll:"Berre nødvendige",close:"Lukk",servicesLabel:"Tenester",showCookies:"Vis informasjonskapslar",noCookies:"Set ingen informasjonskapslar",alwaysOnHeading:"Alltid på",alwaysOnBody:"Desse lagrar ingenting på eininga di og kan ikkje brukast til å kjenne deg att. Dei krev difor ikkje samtykke, og er alltid på.",cookieName:"Namn",cookieProvider:"Levert av",cookieDuration:"Varigheit"},durations:{session:"Til du lukkar nettlesaren",day:"{{count}} dag",days:"{{count}} dagar",month:"{{count}} månad",months:"{{count}} månader",year:"{{count}} år",years:"{{count}} år"},categories:{necessary:{title:"Nødvendige",description:"Krevst for at tenesta skal fungere, mellom anna for innlogging og tryggleik. Desse kan ikkje slåast av."},functionality:{title:"Funksjonalitet",description:"Hugsar vala dine, som språk og andre innstillingar."},measurement:{title:"Statistikk",description:"Lèt oss telje besøk og sjå kva sider som blir brukte, slik at vi kan prioritere rett."},experience:{title:"Brukaroppleving",description:"Lèt oss sjå korleis sidene faktisk blir brukte, gjennom anonymiserte opptak og varmekart, slik at vi kan rette opp det som er vanskeleg."},marketing:{title:"Marknadsføring",description:"Blir brukt til å tilpasse annonsar. Kystverket brukar ikkje dette i dag."}},manageLink:"Administrer informasjonskapslar"},"en-US":{banner:{heading:"Cookies",body:"We use cookies to understand how this service is used, so that we can improve it. You decide what you consent to.",acceptAll:"Accept all",rejectAll:"Necessary only",managePreferences:"Choose yourself"},dialog:{heading:"Cookie settings",body:"Necessary cookies are always on, because the service does not work without them. The rest is up to you.",savePreferences:"Save choices",acceptAll:"Accept all",rejectAll:"Necessary only",close:"Close",servicesLabel:"Services",showCookies:"Show cookies",noCookies:"Sets no cookies",alwaysOnHeading:"Always on",alwaysOnBody:"These store nothing on your device and cannot be used to recognise you. They therefore do not require consent, and are always on.",cookieName:"Name",cookieProvider:"Provided by",cookieDuration:"Duration"},durations:{session:"Until you close your browser",day:"{{count}} day",days:"{{count}} days",month:"{{count}} month",months:"{{count}} months",year:"{{count}} year",years:"{{count}} years"},categories:{necessary:{title:"Necessary",description:"Required for the service to work, including sign-in and security. These cannot be turned off."},functionality:{title:"Functionality",description:"Remembers your choices, such as language and other settings."},measurement:{title:"Statistics",description:"Lets us count visits and see which pages are used, so we can prioritise correctly."},experience:{title:"User experience",description:"Lets us see how the pages are actually used, through anonymised recordings and heatmaps, so we can fix what is difficult."},marketing:{title:"Marketing",description:"Used to tailor advertising. Kystverket does not use this today."}},manageLink:"Manage cookies"}},A="nb-NO";function M(e){var a;if(!e)return b[A];const n=b[e];if(n)return n;const s=(a=e.split("-")[0])==null?void 0:a.toLowerCase(),i=Object.keys(b).find(o=>o.split("-")[0].toLowerCase()===s);return i?b[i]:b[A]}function E(e,n){const{durations:s}=n;if(e==="session")return s.session;const i=(a,o)=>a.replace("{{count}}",String(o));if(e>=365&&e%365===0){const a=e/365;return i(a===1?s.year:s.years,a)}if(e>=28){const a=Math.round(e/30.4);if(a>=1)return i(a===1?s.month:s.months,a)}return i(e===1?s.day:s.days,e)}function X(e,n){return n?{banner:{...e.banner,...n.banner},dialog:{...e.dialog,...n.dialog},durations:{...e.durations,...n.durations},categories:{...e.categories,...n.categories},manageLink:n.manageLink??e.manageLink}:e}function J({children:e,language:n,translations:s,...i}){const a=g.useRef(null);a.current??(a.current=U(i));const o=a.current,{services:d}=i,k=d.map(f=>f.id).join(","),[y,C]=g.useState(!1);g.useEffect(()=>C(!0),[]);const p=W(),u=g.useMemo(()=>({store:o,translations:X(M(n),s),showsBanner:I(d),mounted:y}),[o,n,s,k,y]);return t.jsx(x.Provider,{value:u,children:t.jsx(Q,{value:p,children:e})})}function h(e,n){const s=g.useRef(null);return g.useSyncExternalStore(e.subscribe,()=>n(e.getState()),()=>(s.current??(s.current={value:n(e.getState())}),s.current.value))}function H(){const{store:e}=v(),n=h(e,o=>o.consents),s=h(e,o=>o.activeUI),i=h(e,o=>o.consentInfo),a=h(e,o=>o.isLoadingConsentInfo);return{hasConsent:o=>e.getState().has(o),consents:n,needsDecision:!a&&i===null,showPreferences:()=>e.getState().setActiveUI("dialog"),close:()=>e.getState().setActiveUI("none"),activeUI:s}}const K={button:"_button_ax4nf_2",filled:"_filled_ax4nf_29",outline:"_outline_ax4nf_42",ghost:"_ghost_ax4nf_48"};function m({variant:e="filled",className:n,type:s="button",...i}){return t.jsx("button",{...i,type:s,className:[K.button,K[e],n].filter(Boolean).join(" ")})}const _={banner:"_banner_hahjv_2",inner:"_inner_hahjv_15",text:"_text_hahjv_23",heading:"_heading_hahjv_29",body:"_body_hahjv_38",actions:"_actions_hahjv_45"};function V(){const{store:e,translations:n,showsBanner:s,mounted:i}=v(),a=h(e,y=>y.activeUI),o=i&&s&&a==="banner";if(O("ConsentBanner",o),!o)return null;const{saveConsents:d,setActiveUI:k}=e.getState();return t.jsx("section",{className:_.banner,"data-color":"primary","aria-labelledby":"styrbord-consent-banner-heading",children:t.jsxs("div",{className:_.inner,children:[t.jsxs("div",{className:_.text,children:[t.jsx("h2",{id:"styrbord-consent-banner-heading",className:_.heading,children:n.banner.heading}),t.jsx("p",{className:_.body,children:n.banner.body})]}),t.jsxs("div",{className:_.actions,children:[t.jsx(m,{variant:"filled",onClick:()=>d("all"),children:n.banner.acceptAll}),t.jsx(m,{variant:"outline",onClick:()=>d("necessary"),children:n.banner.rejectAll}),t.jsx(m,{variant:"ghost",onClick:()=>k("dialog"),children:n.banner.managePreferences})]})]})})}const N={switch:"_switch_oxxbn_2",input:"_input_oxxbn_10",label:"_label_oxxbn_53",description:"_description_oxxbn_62"};function R({label:e,description:n,checked:s,onChange:i}){const a=g.useId(),o=`${a}-description`;return t.jsxs("div",{className:N.switch,children:[t.jsx("input",{id:a,type:"checkbox",role:"switch",className:N.input,checked:s,onChange:i,"aria-describedby":n?o:void 0}),t.jsx("label",{className:N.label,htmlFor:a,children:e}),n&&t.jsx("p",{id:o,className:N.description,children:n})]})}const l={dialog:"_dialog_1y45s_2",content:"_content_1y45s_26",header:"_header_1y45s_34",heading:"_heading_1y45s_41",close:"_close_1y45s_50",summary:"_summary_1y45s_75",body:"_body_1y45s_80",fineprint:"_fineprint_1y45s_87",categories:"_categories_1y45s_95",category:"_category_1y45s_101",categoryHeading:"_categoryHeading_1y45s_114",services:"_services_1y45s_122",details:"_details_1y45s_129",table:"_table_1y45s_142",buttons:"_buttons_1y45s_162"};function P({services:e,translations:n}){if(!e.some(a=>a.cookies!==void 0))return null;const i=e.flatMap(a=>(a.cookies??[]).map(o=>({...o,provider:a.displayName??a.id})));return i.length===0?t.jsx("p",{className:l.fineprint,children:n.dialog.noCookies}):t.jsxs("details",{className:l.details,children:[t.jsx("summary",{className:l.summary,children:n.dialog.showCookies}),t.jsxs("table",{className:l.table,children:[t.jsx("thead",{children:t.jsxs("tr",{children:[t.jsx("th",{scope:"col",children:n.dialog.cookieName}),t.jsx("th",{scope:"col",children:n.dialog.cookieProvider}),t.jsx("th",{scope:"col",children:n.dialog.cookieDuration})]})}),t.jsx("tbody",{children:i.map(a=>t.jsxs("tr",{children:[t.jsx("td",{children:t.jsx("code",{children:a.name})}),t.jsx("td",{children:a.provider}),t.jsx("td",{children:E(a.duration,n)})]},`${a.provider}-${a.name}`))})]})]})}function F({services:e,translations:n}){return e.length===0?null:t.jsxs("p",{className:l.fineprint,children:[n.dialog.servicesLabel,": ",e.map(s=>s.displayName??s.id).join(", ")]})}function G(){const{store:e,translations:n,mounted:s}=v(),i=h(e,c=>c.activeUI),a=h(e,c=>c.selectedConsents),o=h(e,c=>c.scripts),d=g.useRef(null),k=i==="dialog";z(),g.useEffect(()=>{const c=d.current;c&&(k&&!c.open?c.showModal():!k&&c.open&&c.close())},[k]);const y=w(o),{setSelectedConsent:C,saveConsents:p,setActiveUI:u}=e.getState();if(!s)return null;const f=o.filter(c=>c.category==="necessary"),q=o.filter(c=>c.alwaysLoad&&c.category!=="necessary"),le=c=>o.filter(S=>!S.alwaysLoad&&S.category===c),de=c=>{c.target===d.current&&u("none")};return t.jsxs("dialog",{ref:d,className:l.dialog,"data-color":"primary","aria-labelledby":"styrbord-consent-dialog-heading",onClose:()=>u("none"),onClick:de,children:[t.jsxs("div",{className:l.content,children:[t.jsxs("div",{className:l.header,children:[t.jsx("h2",{id:"styrbord-consent-dialog-heading",className:l.heading,children:n.dialog.heading}),t.jsx("button",{type:"button",className:l.close,"aria-label":n.dialog.close,onClick:()=>u("none"),children:t.jsx("svg",{viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2","aria-hidden":!0,focusable:"false",children:t.jsx("path",{d:"m6 6 12 12M18 6 6 18",strokeLinecap:"round"})})})]}),t.jsx("p",{className:l.body,children:n.dialog.body}),t.jsxs("div",{className:l.categories,children:[t.jsxs("section",{className:l.category,children:[t.jsx("h3",{className:l.categoryHeading,children:n.categories.necessary.title}),t.jsx("p",{className:l.body,children:n.categories.necessary.description}),t.jsx(P,{services:f,translations:n})]}),q.length>0&&t.jsxs("section",{className:l.category,children:[t.jsx("h3",{className:l.categoryHeading,children:n.dialog.alwaysOnHeading}),t.jsx("p",{className:l.body,children:n.dialog.alwaysOnBody}),t.jsx(F,{services:q,translations:n}),t.jsx(P,{services:q,translations:n})]}),y.map(c=>{const S=le(c);return t.jsxs("section",{className:l.category,children:[t.jsx(R,{label:n.categories[c].title,description:n.categories[c].description,checked:a[c]===!0,onChange:ge=>C(c,ge.target.checked)}),t.jsxs("div",{className:l.services,children:[t.jsx(F,{services:S,translations:n}),t.jsx(P,{services:S,translations:n})]})]},c)})]})]}),t.jsxs("div",{className:l.buttons,children:[t.jsx(m,{variant:"filled",onClick:()=>p("custom"),children:n.dialog.savePreferences}),t.jsx(m,{variant:"outline",onClick:()=>p("all"),children:n.dialog.acceptAll}),t.jsx(m,{variant:"ghost",onClick:()=>p("necessary"),children:n.dialog.rejectAll})]})]})}const ee={button:"_button_zo1st_2"};function ne(){return t.jsx("svg",{xmlns:"http://www.w3.org/2000/svg",height:"20px",viewBox:"0 -960 960 960",width:"20px",children:t.jsx("path",{color:"currentColor",d:"M480-96q-79.38 0-149.19-30T208.5-208.5Q156-261 126-330.81T96-480q0-81 31-151.5t82.5-123Q261-807 329-837.5T470-868q23 0 45 3t45 9q-8 45 5.5 82t42.03 60.96q28.53 23.96 68 33T759-681q-24 57 8.01 108.5 32.01 51.49 95.08 53.4.95 10.49 1.43 19.55T864-480q0 78-30.24 147.98-30.24 69.99-82.08 122.6t-121.92 83.01Q559.68-96 480-96Zm-60-456q25 0 42.5-17.5T480-612q0-25-17.5-42.5T420-672q-25 0-42.5 17.5T360-612q0 25 17.5 42.5T420-552Zm-96 192q25 0 42.5-17.5T384-420q0-25-17.5-42.5T324-480q-25 0-42.5 17.5T264-420q0 25 17.5 42.5T324-360Zm275.79 36q15.21 0 25.71-10.29t10.5-25.5q0-15.21-10.29-25.71t-25.5-10.5q-15.21 0-25.71 10.29t-10.5 25.5q0 15.21 10.29 25.71t25.5 10.5ZM480-168q125 0 214.5-84.5T792-462q-45-18-75-55.5T679-603q-76-11-129-63t-63-126q-63-4-120.5 19.5t-102 66.5Q220-663 194-604.5T168-480q0 129.67 91.16 220.84Q350.33-168 480-168Zm0-311Z"})})}function Y(){const{store:e,translations:n,showsBanner:s,mounted:i}=v(),a=h(e,d=>d.activeUI),o=i&&s&&a==="none";return O("ConsentSettingsButton",o),o?t.jsx("button",{type:"button",className:ee.button,"data-color":"neutral","aria-label":n.manageLink,title:n.manageLink,onClick:()=>e.getState().setActiveUI("dialog"),children:t.jsx(ne,{})}):null}const te={link:"_link_6z1zn_4"};function se(){return t.jsxs(t.Fragment,{children:[t.jsx(V,{}),t.jsx(G,{}),t.jsx(Y,{})]})}function oe({className:e}){const{translations:n}=v(),{showPreferences:s}=H();return t.jsx("button",{type:"button",className:[te.link,e].filter(Boolean).join(" "),onClick:s,children:n.manageLink})}function ae({domain:e,requireConsent:n=!1,scriptSrc:s="https://plausible.io/js/script.js"}){return{id:"plausible",displayName:"Plausible",src:s,category:"measurement",alwaysLoad:!n,defer:!0,attributes:{"data-domain":e},cookies:[]}}function ie({siteId:e}){return{id:"hotjar",displayName:"Hotjar",category:"experience",clearCookiePrefixes:["_hj"],cookies:[{name:"_hjSessionUser_*",duration:365},{name:"_hjSession_*",duration:1},{name:"_hjIncludedInSessionSample_*",duration:1}],textContent:`
3
+ (function (h, o, t, j, a, r) {
4
+ h.hj = h.hj || function () { (h.hj.q = h.hj.q || []).push(arguments); };
5
+ h._hjSettings = { hjid: ${Number(e)}, hjsv: 6 };
6
+ a = o.getElementsByTagName('head')[0];
7
+ r = o.createElement('script');
8
+ r.async = 1;
9
+ r.src = t + h._hjSettings.hjid + j + h._hjSettings.hjsv;
10
+ a.appendChild(r);
11
+ })(window, document, 'https://static.hotjar.com/c/hotjar-', '.js?sv=');
12
+ `}}function re({apiKey:e,apiHost:n="https://eu.i.posthog.com",assetHost:s,sessionReplay:i=!1,capturePageview:a=!0,personProfiles:o="identified_only",defaults:d="2026-05-30"}){const k=n.replace(/\/$/,""),y=(s??k.replace(".i.posthog.com","-assets.i.posthog.com")).replace(/\/$/,""),C=()=>window.posthog,p=u=>{if(!i)return;const f=C();f&&(u.experience===!0?f.startSessionRecording():f.stopSessionRecording())};return{id:"posthog",displayName:"PostHog",category:"measurement",clearCookiePrefixes:["ph_"],cookies:[{name:`ph_${e}_posthog`,duration:365}],src:`${y}/static/array.js`,onLoad:({consents:u})=>{var f;(f=C())==null||f.init(e,{api_host:k,person_profiles:o,capture_pageview:a,defaults:d,cross_subdomain_cookie:!1,disable_session_recording:!0,capture_heatmaps:i&&u.experience===!0}),p(u)},onConsentChange:({consents:u})=>p(u)}}function ce(e=L,n=$){return{id:"consent",displayName:"Kystverket",category:"necessary",callbackOnly:!0,alwaysLoad:!0,cookies:[{name:e,duration:n}]}}r.ConsentBanner=V,r.ConsentPreferencesDialog=G,r.ConsentProvider=J,r.ConsentSettingsButton=Y,r.CookieConsent=se,r.DEFAULT_EXPIRY_DAYS=$,r.DEFAULT_STORAGE_KEY=L,r.ManageConsentLink=oe,r.clearServiceCookies=B,r.consentCookieService=ce,r.consentTranslations=b,r.createConsentStore=U,r.defaultConsentLanguage=A,r.formatCookieDuration=E,r.getConsentTranslations=M,r.getSelectableCategories=w,r.hasGatedServices=I,r.hotjarService=ie,r.plausibleService=ae,r.postHogService=re,r.useConsent=H,r.useConsentStore=v,r.useStoreValue=h,Object.defineProperty(r,Symbol.toStringTag,{value:"Module"})}));
package/package.json ADDED
@@ -0,0 +1,54 @@
1
+ {
2
+ "name": "@kystverket/styrbord-consent",
3
+ "version": "0.0.0",
4
+ "description": "Samtykke-komponenter for Kystverkets applikasjoner",
5
+ "type": "module",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/Kystverket/styrbord.git"
9
+ },
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/src/main.d.ts",
13
+ "style": "./dist/style.css",
14
+ "import": "./dist/style.js"
15
+ },
16
+ "./*.css": {
17
+ "import": "./dist/*.css",
18
+ "require": "./dist/*.css"
19
+ }
20
+ },
21
+ "main": "./dist/style.js",
22
+ "typings": "./dist/src/main.d.ts",
23
+ "files": [
24
+ "dist/**/*"
25
+ ],
26
+ "scripts": {
27
+ "build": "tsc && vite build",
28
+ "test": "echo \"Warning: no test specified\" && exit 0",
29
+ "storybook": "storybook dev -p 6007",
30
+ "storybook:build": "storybook build",
31
+ "pretty:check": "npx prettier . --check",
32
+ "pretty:fix": "npx prettier . --write",
33
+ "lint:check": "npx eslint .",
34
+ "lint:fix": "npx eslint --fix ."
35
+ },
36
+ "author": "",
37
+ "license": "ISC",
38
+ "peerDependencies": {
39
+ "react": ">=18.2.0",
40
+ "react-dom": ">=18.2.0"
41
+ },
42
+ "dependencies": {
43
+ "@kystverket/styrbord-tokens": "^1.1.0",
44
+ "c15t": "^2.2.1"
45
+ },
46
+ "devDependencies": {
47
+ "@chromatic-com/storybook": "^5.0.1",
48
+ "@storybook/addon-docs": "^10.2.13",
49
+ "@storybook/addon-links": "^10.2.13",
50
+ "@storybook/addon-onboarding": "^10.2.13",
51
+ "@storybook/react-vite": "^10.2.13",
52
+ "storybook-addon-tag-badges": "^3.0.6"
53
+ }
54
+ }