@dbcdk/react-components 0.0.172 → 0.0.174
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/dist/client.cjs +14 -0
- package/dist/client.d.ts +2 -0
- package/dist/client.js +2 -0
- package/dist/components/app-header/AppHeader.module.css +2 -2
- package/dist/components/button/Button.d.ts +3 -1
- package/dist/components/button/Button.module.css +26 -0
- package/dist/components/color-scheme-button/ColorSchemeButton.cjs +78 -0
- package/dist/components/color-scheme-button/ColorSchemeButton.d.ts +8 -0
- package/dist/components/color-scheme-button/ColorSchemeButton.js +75 -0
- package/dist/components/forms/form-select/FormSelect.d.ts +1 -1
- package/dist/components/forms/form-select/FormSelect.module.css +19 -0
- package/dist/components/forms/input/Input.cjs +1 -1
- package/dist/components/forms/input/Input.d.ts +1 -1
- package/dist/components/forms/input/Input.js +1 -1
- package/dist/components/forms/input/Input.module.css +32 -0
- package/dist/components/forms/typeahead/Typeahead.cjs +1 -0
- package/dist/components/forms/typeahead/Typeahead.js +1 -0
- package/dist/components/grid/Grid.cjs +4 -3
- package/dist/components/grid/Grid.d.ts +3 -3
- package/dist/components/grid/Grid.js +4 -3
- package/dist/components/grid/Grid.module.css +1 -1
- package/dist/components/hyperlink/Hyperlink.cjs +2 -1
- package/dist/components/hyperlink/Hyperlink.d.ts +2 -1
- package/dist/components/hyperlink/Hyperlink.js +2 -1
- package/dist/components/hyperlink/Hyperlink.module.css +16 -0
- package/dist/components/metric-tile/MetricTile.cjs +77 -8
- package/dist/components/metric-tile/MetricTile.d.ts +17 -4
- package/dist/components/metric-tile/MetricTile.js +78 -9
- package/dist/components/metric-tile/MetricTile.module.css +122 -19
- package/dist/components/nav-bar/NavBar.cjs +1 -0
- package/dist/components/nav-bar/NavBar.js +1 -0
- package/dist/components/nav-bar/NavBar.module.css +10 -10
- package/dist/components/page-layout/PageLayout.module.css +1 -1
- package/dist/components/popover/Popover.cjs +4 -2
- package/dist/components/popover/Popover.d.ts +2 -0
- package/dist/components/popover/Popover.js +4 -2
- package/dist/components/popover/Popover.module.css +5 -0
- package/dist/components/theme-button/ThemeButton.cjs +30 -23
- package/dist/components/theme-button/ThemeButton.d.ts +9 -3
- package/dist/components/theme-button/ThemeButton.js +31 -24
- package/dist/components/theme-script/ThemeScript.cjs +50 -12
- package/dist/components/theme-script/ThemeScript.d.ts +35 -12
- package/dist/components/theme-script/ThemeScript.js +51 -13
- package/dist/hooks/useColorScheme.cjs +74 -0
- package/dist/hooks/useColorScheme.d.ts +6 -0
- package/dist/hooks/useColorScheme.js +72 -0
- package/dist/hooks/useTheme.cjs +116 -50
- package/dist/hooks/useTheme.d.ts +17 -5
- package/dist/hooks/useTheme.js +117 -51
- package/dist/index.cjs +14 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2 -0
- package/dist/styles/themes/dbc/colors.css +13 -2
- package/dist/styles/themes/filmstriben/theme.css +55 -0
- package/dist/styles/themes/types.cjs +8 -0
- package/dist/styles/themes/types.d.ts +24 -16
- package/dist/styles/themes/types.js +6 -0
- package/dist/themes/filmstriben.css +4 -0
- package/dist/utils/color-scheme.constants.cjs +11 -0
- package/dist/utils/color-scheme.constants.d.ts +4 -0
- package/dist/utils/color-scheme.constants.js +7 -0
- package/dist/utils/theme.constants.cjs +3 -7
- package/dist/utils/theme.constants.d.ts +2 -4
- package/dist/utils/theme.constants.js +3 -6
- package/package.json +1 -1
- package/dist/styles/themes/filmstriben-budget/theme.css +0 -22
- package/dist/themes/filmstriben-budget.css +0 -3
package/dist/hooks/useTheme.d.ts
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export type {
|
|
3
|
-
export
|
|
4
|
-
theme
|
|
5
|
-
|
|
1
|
+
import type { ThemeHrefs, ThemeId } from '../styles/themes/types';
|
|
2
|
+
export type { ThemeHrefs, ThemeId };
|
|
3
|
+
export interface UseThemeOptions {
|
|
4
|
+
/** The theme the app already loads via a normal static import — never
|
|
5
|
+
* fetched/linked dynamically, just applied via the attribute. */
|
|
6
|
+
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
|
+
storageKey?: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function useTheme(options: UseThemeOptions): {
|
|
16
|
+
theme: ThemeId | null;
|
|
17
|
+
switchTheme: (id: ThemeId) => void;
|
|
6
18
|
};
|
package/dist/hooks/useTheme.js
CHANGED
|
@@ -1,33 +1,58 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { useEffect, useSyncExternalStore } from 'react';
|
|
3
|
-
import {
|
|
3
|
+
import { readCookie, writeCookie } from '../utils/cookie.utils';
|
|
4
|
+
import { readLocalStorage, writeLocalStorage } from '../utils/localStorage.utils';
|
|
5
|
+
import { THEME_STORAGE_KEY, THEME_LINK_ID } from '../utils/theme.constants';
|
|
4
6
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
function persistTheme(id) {
|
|
10
|
-
try {
|
|
11
|
-
localStorage.setItem(THEME_STORAGE_KEY, id);
|
|
12
|
-
} catch {
|
|
13
|
-
console.error("Failed to access localStorage");
|
|
14
|
-
}
|
|
15
|
-
try {
|
|
16
|
-
document.cookie = `${THEME_STORAGE_KEY}=${encodeURIComponent(
|
|
17
|
-
id
|
|
18
|
-
)}; Path=/; Max-Age=${60 * 60 * 24 * 365}`;
|
|
19
|
-
} catch {
|
|
20
|
-
console.error("Failed to set theme cookie");
|
|
21
|
-
}
|
|
7
|
+
const PRELOAD_ID_PREFIX = "dbc-theme-preload-";
|
|
8
|
+
function persistTheme(storageKey, id) {
|
|
9
|
+
writeLocalStorage(storageKey, id);
|
|
10
|
+
writeCookie(storageKey, id);
|
|
22
11
|
}
|
|
23
12
|
function getDomTheme() {
|
|
24
|
-
return document.documentElement.dataset.
|
|
13
|
+
return document.documentElement.dataset.productTheme;
|
|
25
14
|
}
|
|
26
15
|
function applyTheme(id) {
|
|
27
|
-
document.documentElement.dataset.
|
|
16
|
+
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);
|
|
28
52
|
}
|
|
29
53
|
let currentTheme = null;
|
|
30
54
|
let resolved = false;
|
|
55
|
+
let preloadScheduled = false;
|
|
31
56
|
const listeners = /* @__PURE__ */ new Set();
|
|
32
57
|
function notify() {
|
|
33
58
|
listeners.forEach((listener) => listener());
|
|
@@ -44,44 +69,85 @@ function getSnapshot() {
|
|
|
44
69
|
function getServerSnapshot() {
|
|
45
70
|
return null;
|
|
46
71
|
}
|
|
47
|
-
function resolveInitialTheme(
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
const fromCookie =
|
|
51
|
-
if (
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const fromStorage = localStorage.getItem(THEME_STORAGE_KEY);
|
|
56
|
-
if (isThemeVariant(fromStorage)) resolvedTheme = fromStorage;
|
|
57
|
-
} catch {
|
|
58
|
-
console.error("Failed to access localStorage");
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
return resolvedTheme;
|
|
72
|
+
function resolveInitialTheme(storageKey, defaultTheme) {
|
|
73
|
+
const fromDom = getDomTheme();
|
|
74
|
+
if (fromDom) return fromDom;
|
|
75
|
+
const fromCookie = readCookie(storageKey);
|
|
76
|
+
if (fromCookie) return fromCookie;
|
|
77
|
+
const fromStorage = readLocalStorage(storageKey);
|
|
78
|
+
if (fromStorage) return fromStorage;
|
|
79
|
+
return defaultTheme;
|
|
62
80
|
}
|
|
63
|
-
function ensureResolved(
|
|
81
|
+
function ensureResolved(hrefs, defaultTheme, storageKey, linkId) {
|
|
64
82
|
if (resolved) return;
|
|
65
83
|
resolved = true;
|
|
66
|
-
const value = resolveInitialTheme(
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
84
|
+
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);
|
|
71
96
|
}
|
|
72
|
-
function
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
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
|
+
}
|
|
79
120
|
}
|
|
80
|
-
function
|
|
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);
|
|
134
|
+
}
|
|
135
|
+
function useTheme(options) {
|
|
136
|
+
const {
|
|
137
|
+
defaultTheme,
|
|
138
|
+
hrefs = {},
|
|
139
|
+
linkId = THEME_LINK_ID,
|
|
140
|
+
preloadOthers = true,
|
|
141
|
+
storageKey = THEME_STORAGE_KEY
|
|
142
|
+
} = options;
|
|
81
143
|
useEffect(() => {
|
|
82
|
-
ensureResolved(
|
|
83
|
-
|
|
144
|
+
ensureResolved(hrefs, defaultTheme, storageKey, linkId);
|
|
145
|
+
if (preloadOthers) schedulePreload(hrefs, defaultTheme);
|
|
146
|
+
}, []);
|
|
84
147
|
const theme = useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);
|
|
148
|
+
function switchTheme(id) {
|
|
149
|
+
switchThemeInternal(hrefs, defaultTheme, storageKey, linkId, id);
|
|
150
|
+
}
|
|
85
151
|
return { theme, switchTheme };
|
|
86
152
|
}
|
|
87
153
|
|
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var colorScheme_constants = require('./utils/color-scheme.constants');
|
|
3
4
|
var ThemeScript = require('./components/theme-script/ThemeScript');
|
|
4
5
|
var theme_constants = require('./utils/theme.constants');
|
|
6
|
+
var types = require('./styles/themes/types');
|
|
5
7
|
var Icon = require('./components/icon/Icon');
|
|
6
8
|
var UserDisplay = require('./components/user-display/UserDisplay');
|
|
7
9
|
var Headline = require('./components/headline/Headline');
|
|
@@ -46,6 +48,12 @@ var CheckboxGroup = require('./components/forms/checkbox-group/CheckboxGroup');
|
|
|
46
48
|
|
|
47
49
|
|
|
48
50
|
|
|
51
|
+
Object.keys(colorScheme_constants).forEach(function (k) {
|
|
52
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
53
|
+
enumerable: true,
|
|
54
|
+
get: function () { return colorScheme_constants[k]; }
|
|
55
|
+
});
|
|
56
|
+
});
|
|
49
57
|
Object.keys(ThemeScript).forEach(function (k) {
|
|
50
58
|
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
51
59
|
enumerable: true,
|
|
@@ -58,6 +66,12 @@ Object.keys(theme_constants).forEach(function (k) {
|
|
|
58
66
|
get: function () { return theme_constants[k]; }
|
|
59
67
|
});
|
|
60
68
|
});
|
|
69
|
+
Object.keys(types).forEach(function (k) {
|
|
70
|
+
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
71
|
+
enumerable: true,
|
|
72
|
+
get: function () { return types[k]; }
|
|
73
|
+
});
|
|
74
|
+
});
|
|
61
75
|
Object.keys(Icon).forEach(function (k) {
|
|
62
76
|
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
|
|
63
77
|
enumerable: true,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
export * from './utils/color-scheme.constants';
|
|
1
2
|
export * from './components/theme-script/ThemeScript';
|
|
2
3
|
export * from './utils/theme.constants';
|
|
4
|
+
export * from './styles/themes/types';
|
|
3
5
|
export * from './components/icon/Icon';
|
|
4
6
|
export * from './components/user-display/UserDisplay';
|
|
5
7
|
export * from './components/headline/Headline';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
export * from './utils/color-scheme.constants';
|
|
1
2
|
export * from './components/theme-script/ThemeScript';
|
|
2
3
|
export * from './utils/theme.constants';
|
|
4
|
+
export * from './styles/themes/types';
|
|
3
5
|
export * from './components/icon/Icon';
|
|
4
6
|
export * from './components/user-display/UserDisplay';
|
|
5
7
|
export * from './components/headline/Headline';
|
|
@@ -240,11 +240,22 @@ html {
|
|
|
240
240
|
--button-fg-primary: var(--color-fg-on-brand);
|
|
241
241
|
|
|
242
242
|
/* Product / logo lockup — generic defaults; apps with a custom identity
|
|
243
|
-
override these tokens only (see e.g. filmstriben
|
|
244
|
-
--color-logo: var(--color-
|
|
243
|
+
override these tokens only (see e.g. filmstriben/theme.css) */
|
|
244
|
+
--color-logo: var(--color-fg-default);
|
|
245
245
|
--color-logo-bg: color-mix(in srgb, var(--color-logo) 10%, var(--color-bg-surface));
|
|
246
246
|
--color-logo-fg: var(--color-fg-default);
|
|
247
247
|
|
|
248
|
+
/* Navbar */
|
|
249
|
+
--color-navbar-bg: var(--color-bg-surface);
|
|
250
|
+
--color-navbar-fg: var(--color-fg-default);
|
|
251
|
+
--color-navbar-fg-muted: var(--color-fg-muted);
|
|
252
|
+
--color-navbar-border: var(--color-border-default);
|
|
253
|
+
/* Active nav-link accent — deliberately its own token, not --color-logo:
|
|
254
|
+
the two happen to agree in some themes (filmstriben: both yellow) but
|
|
255
|
+
not others (dbc: logo is neutral fg-default, but the active link should
|
|
256
|
+
still read as brand-colored, not the same shade as inactive text) */
|
|
257
|
+
--color-navbar-brand: var(--color-brand);
|
|
258
|
+
|
|
248
259
|
/* Tables */
|
|
249
260
|
--table-header-bg: light-dark(#f3f4f6, #1b2533);
|
|
250
261
|
--table-row-bg: light-dark(#ffffff, #111827);
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/* Filmstriben theme entrypoint.
|
|
2
|
+
*
|
|
3
|
+
* Usage in the consuming app:
|
|
4
|
+
* - Simplest: import the convenience bundle instead of this file directly —
|
|
5
|
+
* @import '@dbcdk/react-components/themes/filmstriben.css';
|
|
6
|
+
* (bundles dbc/base.css + dbc/colors.css + this file + the shared index.css)
|
|
7
|
+
* - Or, for runtime theme switching (see useTheme/ThemeScript), import
|
|
8
|
+
* dbc's base + colors as your permanent foundation, then load this
|
|
9
|
+
* file — just the delta below — only when this theme is actually active:
|
|
10
|
+
* @import '@dbcdk/react-components/styles/themes/dbc/base.css';
|
|
11
|
+
* @import '@dbcdk/react-components/styles/themes/dbc/colors.css';
|
|
12
|
+
* @import '@dbcdk/react-components/styles/themes/filmstriben/theme.css';
|
|
13
|
+
*
|
|
14
|
+
* This file deliberately does NOT import dbc/colors.css itself (unlike a
|
|
15
|
+
* typical single-theme entrypoint) and scopes every override behind
|
|
16
|
+
* [data-product-theme='filmstriben'] instead of a bare :root — both are what
|
|
17
|
+
* let it be safely loaded *alongside* dbc's palette and toggled at runtime by
|
|
18
|
+
* flipping that attribute, without re-declaring or clobbering the whole dbc
|
|
19
|
+
* palette a second time.
|
|
20
|
+
*
|
|
21
|
+
* Only overrides the navbar/header identity (fixed dark bar + logo lockup).
|
|
22
|
+
* General-purpose brand tokens (--color-brand and everything derived from it
|
|
23
|
+
* — buttons, links, tabs, chips, alerts, focus rings, charts) are
|
|
24
|
+
* deliberately left on the shared DBC blue: #ffc107 doesn't have a value
|
|
25
|
+
* that works well both as flat text/borders on white AND as a vivid identity
|
|
26
|
+
* color (see TASK_filmstriben_theme.md for the contrast math and the
|
|
27
|
+
* earlier, abandoned attempt at a mixed "text-safe gold"). Scoping the
|
|
28
|
+
* yellow to the navbar/logo — where it always sits on its own guaranteed
|
|
29
|
+
* background — sidesteps that tradeoff entirely instead of picking a
|
|
30
|
+
* compromise shade.
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
:root[data-product-theme='filmstriben'] {
|
|
34
|
+
--filmstriben-yellow: #ffc107;
|
|
35
|
+
--filmstriben-black: #212529;
|
|
36
|
+
|
|
37
|
+
/* Navbar — fixed dark bar regardless of light/dark color-scheme */
|
|
38
|
+
--color-navbar-bg: var(--filmstriben-black);
|
|
39
|
+
--color-navbar-fg: #ffffff;
|
|
40
|
+
--color-navbar-fg-muted: rgba(255, 255, 255, 0.9);
|
|
41
|
+
/* Softer than full navbar-fg at rest — header components escalate to full
|
|
42
|
+
strength on hover/focus (see Button/Input/FormSelect's .header variant) */
|
|
43
|
+
--color-navbar-border: color-mix(in srgb, var(--color-navbar-fg) 25%, transparent);
|
|
44
|
+
/* Active nav-link accent — the raw vivid yellow is safe here specifically
|
|
45
|
+
because it always sits on this fixed dark bar, unlike --color-brand
|
|
46
|
+
(which follows light-dark() for the page's own background) */
|
|
47
|
+
--color-navbar-brand: var(--filmstriben-yellow);
|
|
48
|
+
|
|
49
|
+
/* Logo lockup — sits on the light page surface (via --color-logo-bg's
|
|
50
|
+
tint) or the dark navbar, never as flat text on a plain white bg, so
|
|
51
|
+
the raw vivid yellow is safe here unlike a general --color-brand value */
|
|
52
|
+
--color-logo: var(--filmstriben-yellow);
|
|
53
|
+
--color-logo-bg: color-mix(in srgb, var(--color-logo) 10%, var(--color-bg-surface));
|
|
54
|
+
--color-logo-fg: var(--filmstriben-black);
|
|
55
|
+
}
|
|
@@ -1,16 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Every product theme this library ships (folders under
|
|
3
|
+
* `src/styles/themes/`). A closed set on purpose, mirroring `ColorScheme`
|
|
4
|
+
* (`'light' | 'dark' | 'system'`) for the color-scheme axis: the library
|
|
5
|
+
* owns which themes exist and what they're called, so consuming apps never
|
|
6
|
+
* need to invent their own labels or types for them — just pass ids.
|
|
7
|
+
* TypeScript-only enforcement; add an id here (and to `THEME_LABELS`)
|
|
8
|
+
* whenever a new theme folder is added.
|
|
9
|
+
*/
|
|
10
|
+
export declare const THEME_IDS: readonly ["dbc", "filmstriben"];
|
|
11
|
+
export type ThemeId = (typeof THEME_IDS)[number];
|
|
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>>;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const COLOR_SCHEMES = ["light", "dark", "system"];
|
|
4
|
+
const COLOR_SCHEME_STORAGE_KEY = "dbc_theme";
|
|
5
|
+
function isColorScheme(x) {
|
|
6
|
+
return !!x && COLOR_SCHEMES.includes(x);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
exports.COLOR_SCHEMES = COLOR_SCHEMES;
|
|
10
|
+
exports.COLOR_SCHEME_STORAGE_KEY = COLOR_SCHEME_STORAGE_KEY;
|
|
11
|
+
exports.isColorScheme = isColorScheme;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const COLOR_SCHEMES: readonly ["light", "dark", "system"];
|
|
2
|
+
export type ColorScheme = (typeof COLOR_SCHEMES)[number];
|
|
3
|
+
export declare const COLOR_SCHEME_STORAGE_KEY = "dbc_theme";
|
|
4
|
+
export declare function isColorScheme(x: string | null | undefined): x is ColorScheme;
|
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
const
|
|
4
|
-
const
|
|
5
|
-
function isThemeVariant(x) {
|
|
6
|
-
return !!x && THEME_VARIANTS.includes(x);
|
|
7
|
-
}
|
|
3
|
+
const THEME_STORAGE_KEY = "dbc_product_theme";
|
|
4
|
+
const THEME_LINK_ID = "dbc-theme-link";
|
|
8
5
|
|
|
6
|
+
exports.THEME_LINK_ID = THEME_LINK_ID;
|
|
9
7
|
exports.THEME_STORAGE_KEY = THEME_STORAGE_KEY;
|
|
10
|
-
exports.THEME_VARIANTS = THEME_VARIANTS;
|
|
11
|
-
exports.isThemeVariant = isThemeVariant;
|
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
export declare const
|
|
2
|
-
export
|
|
3
|
-
export declare const THEME_STORAGE_KEY = "dbc_theme";
|
|
4
|
-
export declare function isThemeVariant(x: string | null | undefined): x is ThemeVariant;
|
|
1
|
+
export declare const THEME_STORAGE_KEY = "dbc_product_theme";
|
|
2
|
+
export declare const THEME_LINK_ID = "dbc-theme-link";
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
const
|
|
2
|
-
const
|
|
3
|
-
function isThemeVariant(x) {
|
|
4
|
-
return !!x && THEME_VARIANTS.includes(x);
|
|
5
|
-
}
|
|
1
|
+
const THEME_STORAGE_KEY = "dbc_product_theme";
|
|
2
|
+
const THEME_LINK_ID = "dbc-theme-link";
|
|
6
3
|
|
|
7
|
-
export {
|
|
4
|
+
export { THEME_LINK_ID, THEME_STORAGE_KEY };
|
package/package.json
CHANGED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/* Filmstriben Budget theme entrypoint.
|
|
2
|
-
*
|
|
3
|
-
* Usage in the consuming app — only two imports needed:
|
|
4
|
-
* @import '@dbcdk/react-components/styles/themes/dbc/base.css';
|
|
5
|
-
* @import '@dbcdk/react-components/styles/themes/filmstriben-budget/theme.css';
|
|
6
|
-
*
|
|
7
|
-
* Pulls in the shared DBC color layer, then overrides only the
|
|
8
|
-
* --color-logo-* tokens. --color-brand and every other semantic/app color
|
|
9
|
-
* stay on the shared DBC palette — buttons, links, focus rings, selected
|
|
10
|
-
* states, charts, and warnings are unaffected.
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
@import '../dbc/colors.css';
|
|
14
|
-
|
|
15
|
-
:root {
|
|
16
|
-
--filmstriben-yellow: #ffc107;
|
|
17
|
-
--filmstriben-black: #212529;
|
|
18
|
-
|
|
19
|
-
--color-logo: var(--filmstriben-yellow);
|
|
20
|
-
--color-logo-bg: color-mix(in srgb, var(--color-logo) 10%, var(--color-bg-surface));
|
|
21
|
-
--color-logo-fg: var(--filmstriben-black);
|
|
22
|
-
}
|