@dbcdk/react-components 0.0.174 → 0.0.176
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 +17 -18
- package/dist/components/filter-field/FilterField.module.css +2 -2
- package/dist/components/forms/file-upload/FileUpload.module.css +3 -3
- package/dist/components/forms/form-select/FormSelect.module.css +1 -1
- package/dist/components/forms/input/Input.module.css +8 -8
- package/dist/components/forms/text-area/Textarea.module.css +2 -1
- package/dist/components/nav-bar/NavBar.module.css +1 -1
- package/dist/components/theme-button/ThemeButton.cjs +4 -15
- package/dist/components/theme-button/ThemeButton.d.ts +3 -4
- package/dist/components/theme-button/ThemeButton.js +4 -15
- package/dist/components/theme-script/ThemeScript.cjs +23 -16
- package/dist/components/theme-script/ThemeScript.d.ts +2 -6
- package/dist/components/theme-script/ThemeScript.js +24 -17
- package/dist/hooks/usePersistentState.cjs +6 -1
- package/dist/hooks/usePersistentState.d.ts +1 -1
- package/dist/hooks/usePersistentState.js +6 -1
- package/dist/hooks/useTheme.cjs +33 -96
- package/dist/hooks/useTheme.d.ts +3 -10
- package/dist/hooks/useTheme.js +34 -97
- package/dist/styles/themes/apply-product-theme.cjs +20 -0
- package/dist/styles/themes/apply-product-theme.d.ts +3 -0
- package/dist/styles/themes/apply-product-theme.js +18 -0
- package/dist/styles/themes/dbc/colors.css +2 -1
- package/dist/styles/themes/product-theme-tokens.cjs +39 -0
- package/dist/styles/themes/product-theme-tokens.d.ts +3 -0
- package/dist/styles/themes/product-theme-tokens.js +37 -0
- package/dist/styles/themes/product-themes.cjs +143 -0
- package/dist/styles/themes/product-themes.d.ts +11 -0
- package/dist/styles/themes/product-themes.js +140 -0
- package/dist/styles/themes/types.cjs +3 -2
- package/dist/styles/themes/types.d.ts +1 -13
- package/dist/styles/themes/types.js +3 -2
- package/dist/utils/sessionStorage.utils.cjs +53 -0
- package/dist/utils/sessionStorage.utils.d.ts +19 -0
- package/dist/utils/sessionStorage.utils.js +49 -0
- package/package.json +1 -1
- package/dist/styles/themes/filmstriben/theme.css +0 -55
- package/dist/themes/filmstriben.css +0 -4
- package/dist/types/assets.d.cjs +0 -2
- package/dist/types/assets.d.js +0 -1
package/dist/hooks/useTheme.d.ts
CHANGED
|
@@ -1,15 +1,8 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export type {
|
|
1
|
+
import type { ThemeId } from '../styles/themes/types';
|
|
2
|
+
export type { ThemeId };
|
|
3
3
|
export interface UseThemeOptions {
|
|
4
|
-
/** The theme the app
|
|
5
|
-
* fetched/linked dynamically, just applied via the attribute. */
|
|
4
|
+
/** The theme the app should fall back to when nothing is stored yet. */
|
|
6
5
|
defaultTheme: ThemeId;
|
|
7
|
-
/** Per-theme CSS URL, for any theme not already loaded some other way. */
|
|
8
|
-
hrefs?: ThemeHrefs;
|
|
9
|
-
/** DOM id for the `<link>` element used for the currently active non-default theme. */
|
|
10
|
-
linkId?: string;
|
|
11
|
-
/** Warm the browser cache for every other theme at idle time. Default true. */
|
|
12
|
-
preloadOthers?: boolean;
|
|
13
6
|
storageKey?: string;
|
|
14
7
|
}
|
|
15
8
|
export declare function useTheme(options: UseThemeOptions): {
|
package/dist/hooks/useTheme.js
CHANGED
|
@@ -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
|
|
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
|
|
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(
|
|
50
|
+
function ensureResolved(defaultTheme, storageKey) {
|
|
82
51
|
if (resolved) return;
|
|
83
52
|
resolved = true;
|
|
84
53
|
const value = resolveInitialTheme(storageKey, defaultTheme);
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
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
|
|
98
|
-
if (
|
|
99
|
-
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
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(
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
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
|
-
|
|
145
|
-
|
|
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(
|
|
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,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 };
|
|
@@ -215,6 +215,7 @@ html {
|
|
|
215
215
|
/* Focus */
|
|
216
216
|
--color-focus-ring: var(--dbc-blue-300);
|
|
217
217
|
--focus-ring: 0 0 0 3px light-dark(rgba(12, 62, 227, 0.25), rgba(59, 130, 246, 0.35));
|
|
218
|
+
--color-field-focus: var(--color-brand);
|
|
218
219
|
|
|
219
220
|
/* Syntax (JSON viewer) */
|
|
220
221
|
--color-syntax-accent: var(--dbc-blue-300);
|
|
@@ -240,7 +241,7 @@ html {
|
|
|
240
241
|
--button-fg-primary: var(--color-fg-on-brand);
|
|
241
242
|
|
|
242
243
|
/* Product / logo lockup — generic defaults; apps with a custom identity
|
|
243
|
-
override these tokens only
|
|
244
|
+
override these tokens only via the product-theme token registry. */
|
|
244
245
|
--color-logo: var(--color-fg-default);
|
|
245
246
|
--color-logo-bg: color-mix(in srgb, var(--color-logo) 10%, var(--color-bg-surface));
|
|
246
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>>;
|