@dbcdk/react-components 0.0.175 → 0.0.177

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 (35) hide show
  1. package/README.md +17 -18
  2. package/dist/components/menu/Menu.module.css +2 -4
  3. package/dist/components/theme-button/ThemeButton.cjs +4 -15
  4. package/dist/components/theme-button/ThemeButton.d.ts +3 -4
  5. package/dist/components/theme-button/ThemeButton.js +4 -15
  6. package/dist/components/theme-script/ThemeScript.cjs +23 -16
  7. package/dist/components/theme-script/ThemeScript.d.ts +2 -6
  8. package/dist/components/theme-script/ThemeScript.js +24 -17
  9. package/dist/hooks/usePersistentState.cjs +6 -1
  10. package/dist/hooks/usePersistentState.d.ts +1 -1
  11. package/dist/hooks/usePersistentState.js +6 -1
  12. package/dist/hooks/useTheme.cjs +33 -96
  13. package/dist/hooks/useTheme.d.ts +3 -10
  14. package/dist/hooks/useTheme.js +34 -97
  15. package/dist/styles/themes/apply-product-theme.cjs +20 -0
  16. package/dist/styles/themes/apply-product-theme.d.ts +3 -0
  17. package/dist/styles/themes/apply-product-theme.js +18 -0
  18. package/dist/styles/themes/dbc/colors.css +1 -1
  19. package/dist/styles/themes/product-theme-tokens.cjs +39 -0
  20. package/dist/styles/themes/product-theme-tokens.d.ts +3 -0
  21. package/dist/styles/themes/product-theme-tokens.js +37 -0
  22. package/dist/styles/themes/product-themes.cjs +143 -0
  23. package/dist/styles/themes/product-themes.d.ts +11 -0
  24. package/dist/styles/themes/product-themes.js +140 -0
  25. package/dist/styles/themes/types.cjs +3 -2
  26. package/dist/styles/themes/types.d.ts +1 -13
  27. package/dist/styles/themes/types.js +3 -2
  28. package/dist/utils/sessionStorage.utils.cjs +53 -0
  29. package/dist/utils/sessionStorage.utils.d.ts +19 -0
  30. package/dist/utils/sessionStorage.utils.js +49 -0
  31. package/package.json +1 -1
  32. package/dist/styles/themes/filmstriben/theme.css +0 -108
  33. package/dist/themes/filmstriben.css +0 -4
  34. package/dist/types/assets.d.cjs +0 -2
  35. package/dist/types/assets.d.js +0 -1
@@ -1,10 +1,10 @@
1
1
  'use client';
2
2
  import { useEffect, useSyncExternalStore } from 'react';
3
+ import { applyProductTheme } from '../styles/themes/apply-product-theme';
3
4
  import { readCookie, writeCookie } from '../utils/cookie.utils';
4
5
  import { readLocalStorage, writeLocalStorage } from '../utils/localStorage.utils';
5
- import { THEME_STORAGE_KEY, THEME_LINK_ID } from '../utils/theme.constants';
6
+ import { THEME_STORAGE_KEY } from '../utils/theme.constants';
6
7
 
7
- const PRELOAD_ID_PREFIX = "dbc-theme-preload-";
8
8
  function persistTheme(storageKey, id) {
9
9
  writeLocalStorage(storageKey, id);
10
10
  writeCookie(storageKey, id);
@@ -12,47 +12,16 @@ function persistTheme(storageKey, id) {
12
12
  function getDomTheme() {
13
13
  return document.documentElement.dataset.productTheme;
14
14
  }
15
+ function getDomColorScheme() {
16
+ return document.documentElement.dataset.theme;
17
+ }
15
18
  function applyTheme(id) {
16
19
  document.documentElement.dataset.productTheme = id;
17
- }
18
- function findLink(linkId) {
19
- return document.getElementById(linkId);
20
- }
21
- function findPreloadLink(id) {
22
- return document.getElementById(`${PRELOAD_ID_PREFIX}${id}`);
23
- }
24
- function ensureStylesheet(id, href, linkId, onReady) {
25
- var _a;
26
- if (!href) {
27
- onReady();
28
- return;
29
- }
30
- const active = findLink(linkId);
31
- if (active && active.getAttribute("href") === href && active.rel === "stylesheet") {
32
- onReady();
33
- return;
34
- }
35
- const preload = findPreloadLink(id);
36
- const link = (_a = active != null ? active : preload) != null ? _a : document.createElement("link");
37
- const wasConnected = link.isConnected;
38
- link.id = linkId;
39
- link.rel = "stylesheet";
40
- link.removeAttribute("as");
41
- link.href = href;
42
- if (preload && preload !== link) preload.remove();
43
- let settled = false;
44
- const finish = () => {
45
- if (settled) return;
46
- settled = true;
47
- onReady();
48
- };
49
- link.addEventListener("load", finish, { once: true });
50
- link.addEventListener("error", finish, { once: true });
51
- if (!wasConnected) document.head.appendChild(link);
20
+ applyProductTheme(id, getDomColorScheme());
52
21
  }
53
22
  let currentTheme = null;
54
23
  let resolved = false;
55
- let preloadScheduled = false;
24
+ let observerAttached = false;
56
25
  const listeners = /* @__PURE__ */ new Set();
57
26
  function notify() {
58
27
  listeners.forEach((listener) => listener());
@@ -78,75 +47,43 @@ function resolveInitialTheme(storageKey, defaultTheme) {
78
47
  if (fromStorage) return fromStorage;
79
48
  return defaultTheme;
80
49
  }
81
- function ensureResolved(hrefs, defaultTheme, storageKey, linkId) {
50
+ function ensureResolved(defaultTheme, storageKey) {
82
51
  if (resolved) return;
83
52
  resolved = true;
84
53
  const value = resolveInitialTheme(storageKey, defaultTheme);
85
- const finish = () => {
86
- applyTheme(value);
87
- persistTheme(storageKey, value);
88
- currentTheme = value;
89
- notify();
90
- };
91
- if (value === defaultTheme) {
92
- finish();
93
- return;
94
- }
95
- ensureStylesheet(value, hrefs[value], linkId, finish);
54
+ applyTheme(value);
55
+ persistTheme(storageKey, value);
56
+ currentTheme = value;
57
+ notify();
96
58
  }
97
- function schedulePreload(hrefs, defaultTheme) {
98
- if (preloadScheduled) return;
99
- preloadScheduled = true;
100
- const run = () => {
101
- var _a;
102
- for (const [id, href] of Object.entries(hrefs)) {
103
- if (id === defaultTheme || !href) continue;
104
- if (((_a = findLink(THEME_LINK_ID)) == null ? void 0 : _a.getAttribute("href")) === href) continue;
105
- if (findPreloadLink(id)) continue;
106
- const link = document.createElement("link");
107
- link.id = `${PRELOAD_ID_PREFIX}${id}`;
108
- link.rel = "preload";
109
- link.as = "style";
110
- link.href = href;
111
- document.head.appendChild(link);
112
- }
113
- };
114
- const requestIdle = window.requestIdleCallback;
115
- if (typeof requestIdle === "function") {
116
- requestIdle(run);
117
- } else {
118
- setTimeout(run, 1);
119
- }
59
+ function ensureColorSchemeObserver() {
60
+ if (observerAttached) return;
61
+ observerAttached = true;
62
+ const observer = new MutationObserver(() => {
63
+ if (!currentTheme) return;
64
+ applyProductTheme(currentTheme, getDomColorScheme());
65
+ });
66
+ observer.observe(document.documentElement, {
67
+ attributes: true,
68
+ attributeFilter: ["data-theme"]
69
+ });
120
70
  }
121
- function switchThemeInternal(hrefs, defaultTheme, storageKey, linkId, id) {
122
- const finish = () => {
123
- applyTheme(id);
124
- persistTheme(storageKey, id);
125
- currentTheme = id;
126
- resolved = true;
127
- notify();
128
- };
129
- if (id === defaultTheme) {
130
- finish();
131
- return;
132
- }
133
- ensureStylesheet(id, hrefs[id], linkId, finish);
71
+ function switchThemeInternal(storageKey, id) {
72
+ applyTheme(id);
73
+ persistTheme(storageKey, id);
74
+ currentTheme = id;
75
+ resolved = true;
76
+ notify();
134
77
  }
135
78
  function useTheme(options) {
136
- const {
137
- defaultTheme,
138
- hrefs = {},
139
- linkId = THEME_LINK_ID,
140
- preloadOthers = true,
141
- storageKey = THEME_STORAGE_KEY
142
- } = options;
79
+ const { defaultTheme, storageKey = THEME_STORAGE_KEY } = options;
143
80
  useEffect(() => {
144
- ensureResolved(hrefs, defaultTheme, storageKey, linkId);
145
- if (preloadOthers) schedulePreload(hrefs, defaultTheme);
146
- }, []);
81
+ ensureColorSchemeObserver();
82
+ ensureResolved(defaultTheme, storageKey);
83
+ }, [defaultTheme, storageKey]);
147
84
  const theme = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
148
85
  function switchTheme(id) {
149
- switchThemeInternal(hrefs, defaultTheme, storageKey, linkId, id);
86
+ switchThemeInternal(storageKey, id);
150
87
  }
151
88
  return { theme, switchTheme };
152
89
  }
@@ -0,0 +1,20 @@
1
+ 'use strict';
2
+
3
+ var productThemeTokens = require('./product-theme-tokens');
4
+ var productThemes = require('./product-themes');
5
+
6
+ function clearProductThemeTokens(target) {
7
+ for (const token of productThemeTokens.PRODUCT_THEME_TOKEN_NAMES) {
8
+ target.style.removeProperty(token);
9
+ }
10
+ }
11
+ function applyProductTheme(themeId, colorScheme, target = document.documentElement) {
12
+ clearProductThemeTokens(target);
13
+ const tokens = productThemes.getProductThemeTokens(themeId, colorScheme);
14
+ for (const [token, value] of Object.entries(tokens)) {
15
+ if (!value) continue;
16
+ target.style.setProperty(token, value);
17
+ }
18
+ }
19
+
20
+ exports.applyProductTheme = applyProductTheme;
@@ -0,0 +1,3 @@
1
+ import type { ColorScheme } from '../../utils/color-scheme.constants';
2
+ import type { ThemeId } from './types';
3
+ export declare function applyProductTheme(themeId: ThemeId, colorScheme: ColorScheme | undefined, target?: HTMLElement): void;
@@ -0,0 +1,18 @@
1
+ import { PRODUCT_THEME_TOKEN_NAMES } from './product-theme-tokens';
2
+ import { getProductThemeTokens } from './product-themes';
3
+
4
+ function clearProductThemeTokens(target) {
5
+ for (const token of PRODUCT_THEME_TOKEN_NAMES) {
6
+ target.style.removeProperty(token);
7
+ }
8
+ }
9
+ function applyProductTheme(themeId, colorScheme, target = document.documentElement) {
10
+ clearProductThemeTokens(target);
11
+ const tokens = getProductThemeTokens(themeId, colorScheme);
12
+ for (const [token, value] of Object.entries(tokens)) {
13
+ if (!value) continue;
14
+ target.style.setProperty(token, value);
15
+ }
16
+ }
17
+
18
+ export { applyProductTheme };
@@ -241,7 +241,7 @@ html {
241
241
  --button-fg-primary: var(--color-fg-on-brand);
242
242
 
243
243
  /* Product / logo lockup — generic defaults; apps with a custom identity
244
- override these tokens only (see e.g. filmstriben/theme.css) */
244
+ override these tokens only via the product-theme token registry. */
245
245
  --color-logo: var(--color-fg-default);
246
246
  --color-logo-bg: color-mix(in srgb, var(--color-logo) 10%, var(--color-bg-surface));
247
247
  --color-logo-fg: var(--color-fg-default);
@@ -0,0 +1,39 @@
1
+ 'use strict';
2
+
3
+ const PRODUCT_THEME_TOKEN_NAMES = [
4
+ "--color-brand",
5
+ "--color-brand-hover",
6
+ "--color-brand-strong",
7
+ "--color-fg-on-brand",
8
+ "--color-border-selected",
9
+ "--color-link",
10
+ "--color-link-hover",
11
+ "--color-bg-selected",
12
+ "--color-bg-selected-hover",
13
+ "--color-chart-primary",
14
+ "--color-chart-brand",
15
+ "--color-navbar-bg",
16
+ "--color-navbar-fg",
17
+ "--color-navbar-fg-muted",
18
+ "--color-navbar-border",
19
+ "--color-navbar-brand",
20
+ "--color-logo",
21
+ "--color-logo-bg",
22
+ "--color-logo-fg",
23
+ "--color-field-focus",
24
+ "--color-focus-ring",
25
+ "--focus-ring",
26
+ "--color-bg-page",
27
+ "--color-bg-surface",
28
+ "--color-bg-surface-subtle",
29
+ "--color-bg-surface-strong",
30
+ "--color-bg-inverse",
31
+ "--color-bg-toolbar",
32
+ "--color-bg-toolbar-hover",
33
+ "--table-header-bg",
34
+ "--table-row-bg",
35
+ "--table-row-bg-alt",
36
+ "--table-row-bg-hover"
37
+ ];
38
+
39
+ exports.PRODUCT_THEME_TOKEN_NAMES = PRODUCT_THEME_TOKEN_NAMES;
@@ -0,0 +1,3 @@
1
+ export declare const PRODUCT_THEME_TOKEN_NAMES: readonly ["--color-brand", "--color-brand-hover", "--color-brand-strong", "--color-fg-on-brand", "--color-border-selected", "--color-link", "--color-link-hover", "--color-bg-selected", "--color-bg-selected-hover", "--color-chart-primary", "--color-chart-brand", "--color-navbar-bg", "--color-navbar-fg", "--color-navbar-fg-muted", "--color-navbar-border", "--color-navbar-brand", "--color-logo", "--color-logo-bg", "--color-logo-fg", "--color-field-focus", "--color-focus-ring", "--focus-ring", "--color-bg-page", "--color-bg-surface", "--color-bg-surface-subtle", "--color-bg-surface-strong", "--color-bg-inverse", "--color-bg-toolbar", "--color-bg-toolbar-hover", "--table-header-bg", "--table-row-bg", "--table-row-bg-alt", "--table-row-bg-hover"];
2
+ export type ProductThemeTokenName = (typeof PRODUCT_THEME_TOKEN_NAMES)[number];
3
+ export type ProductThemeTokens = Partial<Record<ProductThemeTokenName, string>>;
@@ -0,0 +1,37 @@
1
+ const PRODUCT_THEME_TOKEN_NAMES = [
2
+ "--color-brand",
3
+ "--color-brand-hover",
4
+ "--color-brand-strong",
5
+ "--color-fg-on-brand",
6
+ "--color-border-selected",
7
+ "--color-link",
8
+ "--color-link-hover",
9
+ "--color-bg-selected",
10
+ "--color-bg-selected-hover",
11
+ "--color-chart-primary",
12
+ "--color-chart-brand",
13
+ "--color-navbar-bg",
14
+ "--color-navbar-fg",
15
+ "--color-navbar-fg-muted",
16
+ "--color-navbar-border",
17
+ "--color-navbar-brand",
18
+ "--color-logo",
19
+ "--color-logo-bg",
20
+ "--color-logo-fg",
21
+ "--color-field-focus",
22
+ "--color-focus-ring",
23
+ "--focus-ring",
24
+ "--color-bg-page",
25
+ "--color-bg-surface",
26
+ "--color-bg-surface-subtle",
27
+ "--color-bg-surface-strong",
28
+ "--color-bg-inverse",
29
+ "--color-bg-toolbar",
30
+ "--color-bg-toolbar-hover",
31
+ "--table-header-bg",
32
+ "--table-row-bg",
33
+ "--table-row-bg-alt",
34
+ "--table-row-bg-hover"
35
+ ];
36
+
37
+ export { PRODUCT_THEME_TOKEN_NAMES };
@@ -0,0 +1,143 @@
1
+ 'use strict';
2
+
3
+ const PRODUCT_THEMES = {
4
+ dbc: {
5
+ label: "DBC"
6
+ },
7
+ filmstriben: {
8
+ label: "Filmstriben",
9
+ base: {
10
+ "--color-navbar-bg": "#212529",
11
+ "--color-navbar-fg": "#ffffff",
12
+ "--color-navbar-fg-muted": "rgba(255, 255, 255, 0.9)",
13
+ "--color-navbar-border": "color-mix(in srgb, var(--color-navbar-fg) 25%, transparent)",
14
+ "--color-navbar-brand": "#ffc107",
15
+ "--color-logo": "#ffc107",
16
+ "--color-logo-bg": "color-mix(in srgb, var(--color-logo) 10%, var(--color-bg-surface))",
17
+ "--color-logo-fg": "#212529"
18
+ },
19
+ light: {
20
+ "--color-brand": "var(--dbc-blue-500)",
21
+ "--color-brand-hover": "var(--dbc-blue-600)",
22
+ "--color-brand-strong": "var(--dbc-blue-600)",
23
+ "--color-fg-on-brand": "#ffffff",
24
+ "--color-border-selected": "var(--color-brand)",
25
+ "--color-field-focus": "var(--dbc-blue-500)",
26
+ "--color-focus-ring": "var(--dbc-blue-300)",
27
+ "--focus-ring": "0 0 0 3px rgba(12, 62, 227, 0.25)",
28
+ "--color-link": "var(--dbc-blue-500)",
29
+ "--color-link-hover": "var(--dbc-blue-600)",
30
+ "--color-bg-selected": "var(--dbc-blue-100)",
31
+ "--color-bg-selected-hover": "var(--dbc-blue-150)",
32
+ "--color-chart-primary": "color-mix(in srgb, var(--color-brand) 75%, rgb(255 255 255 / 0))"
33
+ },
34
+ dark: {
35
+ "--color-bg-page": "#212529",
36
+ "--color-bg-surface": "#212529",
37
+ "--color-bg-surface-subtle": "#2a2f34",
38
+ "--color-bg-surface-strong": "#161a1d",
39
+ "--color-bg-inverse": "#34393f",
40
+ "--color-bg-toolbar": "#2a2f34",
41
+ "--color-bg-toolbar-hover": "#343a40",
42
+ "--table-header-bg": "#2a2f34",
43
+ "--table-row-bg": "#212529",
44
+ "--table-row-bg-alt": "#1c2024",
45
+ "--table-row-bg-hover": "#2a2f34",
46
+ "--color-brand": "#ffc107",
47
+ "--color-brand-hover": "#ffca2c",
48
+ "--color-brand-strong": "#ffcd39",
49
+ "--color-fg-on-brand": "#212529",
50
+ "--color-border-selected": "var(--color-brand)",
51
+ "--color-field-focus": "var(--dbc-blue-300)",
52
+ "--color-focus-ring": "#ffc107",
53
+ "--focus-ring": "0 0 0 3px color-mix(in srgb, #ffc107 35%, transparent)",
54
+ "--color-bg-selected": "#4a3a06",
55
+ "--color-bg-selected-hover": "#5b4707",
56
+ "--color-chart-primary": "color-mix(in srgb, var(--color-brand) 75%, rgb(255 255 255 / 0))"
57
+ }
58
+ },
59
+ valentines: {
60
+ label: "Valentines",
61
+ light: {
62
+ "--color-navbar-bg": "linear-gradient(90deg, #fff1f5 0%, #ffe4ec 52%, #f5ecff 100%)",
63
+ "--color-navbar-fg": "#3f1d2e",
64
+ "--color-navbar-fg-muted": "color-mix(in srgb, #3f1d2e 72%, white)",
65
+ "--color-navbar-border": "color-mix(in srgb, #e11d48 18%, transparent)",
66
+ "--color-navbar-brand": "#e11d48",
67
+ "--color-logo": "#e11d48",
68
+ "--color-logo-bg": "color-mix(in srgb, #e11d48 16%, white)",
69
+ "--color-logo-fg": "#ffffff",
70
+ "--color-bg-page": "#fff5f8",
71
+ "--color-bg-surface": "#fff0f5",
72
+ "--color-bg-surface-subtle": "#fff8fb",
73
+ "--color-bg-surface-strong": "#ffe2eb",
74
+ "--color-bg-inverse": "#3f1d2e",
75
+ "--color-bg-toolbar": "#ffdce8",
76
+ "--color-bg-toolbar-hover": "#ffcddd",
77
+ "--table-header-bg": "#ffe2eb",
78
+ "--table-row-bg": "#fff0f5",
79
+ "--table-row-bg-alt": "#fff7fa",
80
+ "--table-row-bg-hover": "#ffe8f0",
81
+ "--color-brand": "#e11d48",
82
+ "--color-brand-hover": "#be123c",
83
+ "--color-brand-strong": "#9f1239",
84
+ "--color-fg-on-brand": "#ffffff",
85
+ "--color-border-selected": "var(--color-brand)",
86
+ "--color-field-focus": "#4c1d95",
87
+ "--color-focus-ring": "#4c1d95",
88
+ "--focus-ring": "0 0 0 3px color-mix(in srgb, #4c1d95 28%, transparent)",
89
+ "--color-link": "#4c1d95",
90
+ "--color-link-hover": "color-mix(in srgb, #4c1d95 86%, black)",
91
+ "--color-bg-selected": "#ffe4ec",
92
+ "--color-bg-selected-hover": "#ffd3e0",
93
+ "--color-chart-primary": "color-mix(in srgb, var(--color-brand) 78%, rgb(255 255 255 / 0))",
94
+ "--color-chart-brand": "color-mix(in srgb, #4c1d95 76%, rgb(255 255 255 / 0))"
95
+ },
96
+ dark: {
97
+ "--color-navbar-bg": "linear-gradient(90deg, #4c1d95 0%, #7e22ce 35%, #be185d 100%)",
98
+ "--color-navbar-fg": "#fff7fb",
99
+ "--color-navbar-fg-muted": "rgba(255, 247, 251, 0.82)",
100
+ "--color-navbar-border": "rgba(255, 247, 251, 0.18)",
101
+ "--color-navbar-brand": "#ffd6e7",
102
+ "--color-logo": "#ffd6e7",
103
+ "--color-logo-bg": "color-mix(in srgb, #ffd6e7 18%, var(--color-bg-surface))",
104
+ "--color-logo-fg": "#4c1d95",
105
+ "--color-bg-page": "#241326",
106
+ "--color-bg-surface": "#241326",
107
+ "--color-bg-surface-subtle": "#301836",
108
+ "--color-bg-surface-strong": "#1a0d1d",
109
+ "--color-bg-inverse": "#fdf2f8",
110
+ "--color-bg-toolbar": "#301836",
111
+ "--color-bg-toolbar-hover": "#43204b",
112
+ "--table-header-bg": "#301836",
113
+ "--table-row-bg": "#241326",
114
+ "--table-row-bg-alt": "#2a142f",
115
+ "--table-row-bg-hover": "#301836",
116
+ "--color-brand": "#fb7185",
117
+ "--color-brand-hover": "#f43f5e",
118
+ "--color-brand-strong": "#e11d48",
119
+ "--color-fg-on-brand": "#2c1022",
120
+ "--color-border-selected": "var(--color-brand)",
121
+ "--color-field-focus": "#c4b5fd",
122
+ "--color-focus-ring": "#f9a8d4",
123
+ "--focus-ring": "0 0 0 3px color-mix(in srgb, #f9a8d4 36%, transparent)",
124
+ "--color-link": "#f9a8d4",
125
+ "--color-link-hover": "#fbcfe8",
126
+ "--color-bg-selected": "#4a1730",
127
+ "--color-bg-selected-hover": "#5a1c3a",
128
+ "--color-chart-primary": "color-mix(in srgb, var(--color-brand) 78%, rgb(255 255 255 / 0))",
129
+ "--color-chart-brand": "color-mix(in srgb, #c4b5fd 76%, rgb(255 255 255 / 0))"
130
+ }
131
+ }
132
+ };
133
+ function getProductThemeTokens(themeId, colorScheme) {
134
+ const definition = PRODUCT_THEMES[themeId];
135
+ if (!definition) return {};
136
+ return {
137
+ ...definition.base,
138
+ ...colorScheme === "dark" ? definition.dark : definition.light
139
+ };
140
+ }
141
+
142
+ exports.PRODUCT_THEMES = PRODUCT_THEMES;
143
+ exports.getProductThemeTokens = getProductThemeTokens;
@@ -0,0 +1,11 @@
1
+ import type { ColorScheme } from '../../utils/color-scheme.constants';
2
+ import type { ProductThemeTokens } from './product-theme-tokens';
3
+ import type { ThemeId } from './types';
4
+ export interface ProductThemeDefinition {
5
+ label: string;
6
+ base?: ProductThemeTokens;
7
+ light?: ProductThemeTokens;
8
+ dark?: ProductThemeTokens;
9
+ }
10
+ export declare const PRODUCT_THEMES: Record<ThemeId, ProductThemeDefinition>;
11
+ export declare function getProductThemeTokens(themeId: ThemeId, colorScheme: ColorScheme | undefined): ProductThemeTokens;
@@ -0,0 +1,140 @@
1
+ const PRODUCT_THEMES = {
2
+ dbc: {
3
+ label: "DBC"
4
+ },
5
+ filmstriben: {
6
+ label: "Filmstriben",
7
+ base: {
8
+ "--color-navbar-bg": "#212529",
9
+ "--color-navbar-fg": "#ffffff",
10
+ "--color-navbar-fg-muted": "rgba(255, 255, 255, 0.9)",
11
+ "--color-navbar-border": "color-mix(in srgb, var(--color-navbar-fg) 25%, transparent)",
12
+ "--color-navbar-brand": "#ffc107",
13
+ "--color-logo": "#ffc107",
14
+ "--color-logo-bg": "color-mix(in srgb, var(--color-logo) 10%, var(--color-bg-surface))",
15
+ "--color-logo-fg": "#212529"
16
+ },
17
+ light: {
18
+ "--color-brand": "var(--dbc-blue-500)",
19
+ "--color-brand-hover": "var(--dbc-blue-600)",
20
+ "--color-brand-strong": "var(--dbc-blue-600)",
21
+ "--color-fg-on-brand": "#ffffff",
22
+ "--color-border-selected": "var(--color-brand)",
23
+ "--color-field-focus": "var(--dbc-blue-500)",
24
+ "--color-focus-ring": "var(--dbc-blue-300)",
25
+ "--focus-ring": "0 0 0 3px rgba(12, 62, 227, 0.25)",
26
+ "--color-link": "var(--dbc-blue-500)",
27
+ "--color-link-hover": "var(--dbc-blue-600)",
28
+ "--color-bg-selected": "var(--dbc-blue-100)",
29
+ "--color-bg-selected-hover": "var(--dbc-blue-150)",
30
+ "--color-chart-primary": "color-mix(in srgb, var(--color-brand) 75%, rgb(255 255 255 / 0))"
31
+ },
32
+ dark: {
33
+ "--color-bg-page": "#212529",
34
+ "--color-bg-surface": "#212529",
35
+ "--color-bg-surface-subtle": "#2a2f34",
36
+ "--color-bg-surface-strong": "#161a1d",
37
+ "--color-bg-inverse": "#34393f",
38
+ "--color-bg-toolbar": "#2a2f34",
39
+ "--color-bg-toolbar-hover": "#343a40",
40
+ "--table-header-bg": "#2a2f34",
41
+ "--table-row-bg": "#212529",
42
+ "--table-row-bg-alt": "#1c2024",
43
+ "--table-row-bg-hover": "#2a2f34",
44
+ "--color-brand": "#ffc107",
45
+ "--color-brand-hover": "#ffca2c",
46
+ "--color-brand-strong": "#ffcd39",
47
+ "--color-fg-on-brand": "#212529",
48
+ "--color-border-selected": "var(--color-brand)",
49
+ "--color-field-focus": "var(--dbc-blue-300)",
50
+ "--color-focus-ring": "#ffc107",
51
+ "--focus-ring": "0 0 0 3px color-mix(in srgb, #ffc107 35%, transparent)",
52
+ "--color-bg-selected": "#4a3a06",
53
+ "--color-bg-selected-hover": "#5b4707",
54
+ "--color-chart-primary": "color-mix(in srgb, var(--color-brand) 75%, rgb(255 255 255 / 0))"
55
+ }
56
+ },
57
+ valentines: {
58
+ label: "Valentines",
59
+ light: {
60
+ "--color-navbar-bg": "linear-gradient(90deg, #fff1f5 0%, #ffe4ec 52%, #f5ecff 100%)",
61
+ "--color-navbar-fg": "#3f1d2e",
62
+ "--color-navbar-fg-muted": "color-mix(in srgb, #3f1d2e 72%, white)",
63
+ "--color-navbar-border": "color-mix(in srgb, #e11d48 18%, transparent)",
64
+ "--color-navbar-brand": "#e11d48",
65
+ "--color-logo": "#e11d48",
66
+ "--color-logo-bg": "color-mix(in srgb, #e11d48 16%, white)",
67
+ "--color-logo-fg": "#ffffff",
68
+ "--color-bg-page": "#fff5f8",
69
+ "--color-bg-surface": "#fff0f5",
70
+ "--color-bg-surface-subtle": "#fff8fb",
71
+ "--color-bg-surface-strong": "#ffe2eb",
72
+ "--color-bg-inverse": "#3f1d2e",
73
+ "--color-bg-toolbar": "#ffdce8",
74
+ "--color-bg-toolbar-hover": "#ffcddd",
75
+ "--table-header-bg": "#ffe2eb",
76
+ "--table-row-bg": "#fff0f5",
77
+ "--table-row-bg-alt": "#fff7fa",
78
+ "--table-row-bg-hover": "#ffe8f0",
79
+ "--color-brand": "#e11d48",
80
+ "--color-brand-hover": "#be123c",
81
+ "--color-brand-strong": "#9f1239",
82
+ "--color-fg-on-brand": "#ffffff",
83
+ "--color-border-selected": "var(--color-brand)",
84
+ "--color-field-focus": "#4c1d95",
85
+ "--color-focus-ring": "#4c1d95",
86
+ "--focus-ring": "0 0 0 3px color-mix(in srgb, #4c1d95 28%, transparent)",
87
+ "--color-link": "#4c1d95",
88
+ "--color-link-hover": "color-mix(in srgb, #4c1d95 86%, black)",
89
+ "--color-bg-selected": "#ffe4ec",
90
+ "--color-bg-selected-hover": "#ffd3e0",
91
+ "--color-chart-primary": "color-mix(in srgb, var(--color-brand) 78%, rgb(255 255 255 / 0))",
92
+ "--color-chart-brand": "color-mix(in srgb, #4c1d95 76%, rgb(255 255 255 / 0))"
93
+ },
94
+ dark: {
95
+ "--color-navbar-bg": "linear-gradient(90deg, #4c1d95 0%, #7e22ce 35%, #be185d 100%)",
96
+ "--color-navbar-fg": "#fff7fb",
97
+ "--color-navbar-fg-muted": "rgba(255, 247, 251, 0.82)",
98
+ "--color-navbar-border": "rgba(255, 247, 251, 0.18)",
99
+ "--color-navbar-brand": "#ffd6e7",
100
+ "--color-logo": "#ffd6e7",
101
+ "--color-logo-bg": "color-mix(in srgb, #ffd6e7 18%, var(--color-bg-surface))",
102
+ "--color-logo-fg": "#4c1d95",
103
+ "--color-bg-page": "#241326",
104
+ "--color-bg-surface": "#241326",
105
+ "--color-bg-surface-subtle": "#301836",
106
+ "--color-bg-surface-strong": "#1a0d1d",
107
+ "--color-bg-inverse": "#fdf2f8",
108
+ "--color-bg-toolbar": "#301836",
109
+ "--color-bg-toolbar-hover": "#43204b",
110
+ "--table-header-bg": "#301836",
111
+ "--table-row-bg": "#241326",
112
+ "--table-row-bg-alt": "#2a142f",
113
+ "--table-row-bg-hover": "#301836",
114
+ "--color-brand": "#fb7185",
115
+ "--color-brand-hover": "#f43f5e",
116
+ "--color-brand-strong": "#e11d48",
117
+ "--color-fg-on-brand": "#2c1022",
118
+ "--color-border-selected": "var(--color-brand)",
119
+ "--color-field-focus": "#c4b5fd",
120
+ "--color-focus-ring": "#f9a8d4",
121
+ "--focus-ring": "0 0 0 3px color-mix(in srgb, #f9a8d4 36%, transparent)",
122
+ "--color-link": "#f9a8d4",
123
+ "--color-link-hover": "#fbcfe8",
124
+ "--color-bg-selected": "#4a1730",
125
+ "--color-bg-selected-hover": "#5a1c3a",
126
+ "--color-chart-primary": "color-mix(in srgb, var(--color-brand) 78%, rgb(255 255 255 / 0))",
127
+ "--color-chart-brand": "color-mix(in srgb, #c4b5fd 76%, rgb(255 255 255 / 0))"
128
+ }
129
+ }
130
+ };
131
+ function getProductThemeTokens(themeId, colorScheme) {
132
+ const definition = PRODUCT_THEMES[themeId];
133
+ if (!definition) return {};
134
+ return {
135
+ ...definition.base,
136
+ ...colorScheme === "dark" ? definition.dark : definition.light
137
+ };
138
+ }
139
+
140
+ export { PRODUCT_THEMES, getProductThemeTokens };
@@ -1,9 +1,10 @@
1
1
  'use strict';
2
2
 
3
- const THEME_IDS = ["dbc", "filmstriben"];
3
+ const THEME_IDS = ["dbc", "filmstriben", "valentines"];
4
4
  const THEME_LABELS = {
5
5
  dbc: "DBC",
6
- filmstriben: "Filmstriben"
6
+ filmstriben: "Filmstriben",
7
+ valentines: "Valentines"
7
8
  };
8
9
 
9
10
  exports.THEME_IDS = THEME_IDS;
@@ -7,18 +7,6 @@
7
7
  * TypeScript-only enforcement; add an id here (and to `THEME_LABELS`)
8
8
  * whenever a new theme folder is added.
9
9
  */
10
- export declare const THEME_IDS: readonly ["dbc", "filmstriben"];
10
+ export declare const THEME_IDS: readonly ["dbc", "filmstriben", "valentines"];
11
11
  export type ThemeId = (typeof THEME_IDS)[number];
12
12
  export declare const THEME_LABELS: Record<ThemeId, string>;
13
- /**
14
- * Per-theme override for where to fetch its CSS from at runtime. Only
15
- * needed for a theme whose CSS isn't already loaded some other way by the
16
- * app — omit an id (or leave its value `''`/unset) for a theme that's
17
- * already bundled statically alongside whatever the app already imports.
18
- *
19
- * This is the only piece of theme data `ThemeScript`/`useTheme` actually
20
- * need at runtime (which id to inject a `<link>` for, and its URL) — they
21
- * don't need the full enumerated id list or labels, only whichever UI
22
- * renders the switcher (`ThemeButton`/`ThemeMenuSection`) does.
23
- */
24
- export type ThemeHrefs = Partial<Record<ThemeId, string>>;
@@ -1,7 +1,8 @@
1
- const THEME_IDS = ["dbc", "filmstriben"];
1
+ const THEME_IDS = ["dbc", "filmstriben", "valentines"];
2
2
  const THEME_LABELS = {
3
3
  dbc: "DBC",
4
- filmstriben: "Filmstriben"
4
+ filmstriben: "Filmstriben",
5
+ valentines: "Valentines"
5
6
  };
6
7
 
7
8
  export { THEME_IDS, THEME_LABELS };