@datalayer/primer-addons 1.0.13 → 1.0.15
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/lib/components/logo/DatalayerLogoText.js +7 -3
- package/lib/theme/index.d.ts +1 -0
- package/lib/theme/index.js +1 -0
- package/lib/theme/palettes/SvgPalette.d.ts +32 -0
- package/lib/theme/palettes/SvgPalette.js +234 -0
- package/lib/theme/palettes/index.d.ts +1 -0
- package/lib/theme/palettes/index.js +6 -0
- package/lib/theme/useThemeStore.d.ts +36 -2
- package/lib/theme/useThemeStore.js +116 -14
- package/package.json +1 -1
|
@@ -19,12 +19,16 @@ textSizeMultiplier = 2.380655, inverse = false, ...svgProps }, ref) {
|
|
|
19
19
|
const secondary = secondaryColor ?? themed.secondary;
|
|
20
20
|
// "DATA" part of the wordmark defaults to the themed gray.
|
|
21
21
|
const dataTextColor = textColor ?? themed.textColor;
|
|
22
|
+
// The text-first arrangement has an intrinsic leading gutter from the
|
|
23
|
+
// original outline coordinates. Trim it at the source geometry level.
|
|
24
|
+
const textFirstLeftTrim = 12;
|
|
25
|
+
const viewBoxWidth = inverse ? 161.672 : 161.672 - textFirstLeftTrim;
|
|
22
26
|
const baseHeight = size;
|
|
23
|
-
const baseWidth = (
|
|
27
|
+
const baseWidth = (viewBoxWidth / 25) * size;
|
|
24
28
|
const height = baseHeight * scale;
|
|
25
29
|
const width = baseWidth * scale;
|
|
26
30
|
const logoFirst = (_jsxs(_Fragment, { children: [_jsx(DatalayerLogo, { size: 25, x: 0, y: 0, variant: variant, colorMode: colorMode, primaryColor: primary, secondaryColor: secondary, primaryGradient: primaryGradient, secondaryGradient: secondaryGradient, gradient: gradient }), _jsx(DatalayerText, { primaryColor: primary, secondaryColor: dataTextColor, sizeMultiplier: textSizeMultiplier, x: 16 })] }));
|
|
27
|
-
const textFirst = (_jsxs(_Fragment, { children: [_jsx(DatalayerText, { primaryColor: primary, secondaryColor: dataTextColor, sizeMultiplier: textSizeMultiplier, x:
|
|
28
|
-
return (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox:
|
|
31
|
+
const textFirst = (_jsxs(_Fragment, { children: [_jsx(DatalayerText, { primaryColor: primary, secondaryColor: dataTextColor, sizeMultiplier: textSizeMultiplier, x: -textFirstLeftTrim }), _jsx(DatalayerLogo, { size: 25, x: 136.672 - textFirstLeftTrim, y: 0, variant: variant, colorMode: colorMode, primaryColor: primary, secondaryColor: secondary, primaryGradient: primaryGradient, secondaryGradient: secondaryGradient, gradient: gradient })] }));
|
|
32
|
+
return (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: `0 0 ${viewBoxWidth} 25`, width: width, height: height, role: "img", "aria-label": "Datalayer", ref: ref, ...svgProps, children: inverse ? logoFirst : textFirst }));
|
|
29
33
|
});
|
|
30
34
|
export default DatalayerLogoText;
|
package/lib/theme/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export * from './themes/matrixTheme';
|
|
|
9
9
|
export * from './themes/earthTheme';
|
|
10
10
|
export * from './themes-brand/spatialBrandTheme';
|
|
11
11
|
export * from './themeRegistry';
|
|
12
|
+
export * from './palettes';
|
|
12
13
|
export * from './useSystemColorMode';
|
|
13
14
|
export * from './useThemeStore';
|
|
14
15
|
export * from './ThemedProvider';
|
package/lib/theme/index.js
CHANGED
|
@@ -13,6 +13,7 @@ export * from './themes/matrixTheme';
|
|
|
13
13
|
export * from './themes/earthTheme';
|
|
14
14
|
export * from './themes-brand/spatialBrandTheme';
|
|
15
15
|
export * from './themeRegistry';
|
|
16
|
+
export * from './palettes';
|
|
16
17
|
export * from './useSystemColorMode';
|
|
17
18
|
export * from './useThemeStore';
|
|
18
19
|
export * from './ThemedProvider';
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type ThemeVariant } from '../themeRegistry';
|
|
2
|
+
export interface SvgPalette {
|
|
3
|
+
bg: string;
|
|
4
|
+
bgPanel: string;
|
|
5
|
+
bgAlt: string;
|
|
6
|
+
primary: string;
|
|
7
|
+
secondary: string;
|
|
8
|
+
accent: string;
|
|
9
|
+
glow: string;
|
|
10
|
+
pop: string;
|
|
11
|
+
spark: string;
|
|
12
|
+
blaze: string;
|
|
13
|
+
surge: string;
|
|
14
|
+
flame: string;
|
|
15
|
+
gold: string;
|
|
16
|
+
textLight: string;
|
|
17
|
+
textMuted: string;
|
|
18
|
+
isLight: boolean;
|
|
19
|
+
}
|
|
20
|
+
export declare function getSvgPalette(theme?: ThemeVariant, colorMode?: 'light' | 'dark' | 'auto'): SvgPalette;
|
|
21
|
+
export declare function useSvgPalette(): SvgPalette;
|
|
22
|
+
/** @deprecated Use `useSvgPalette` instead. */
|
|
23
|
+
export declare const useBlogSvgPalette: typeof useSvgPalette;
|
|
24
|
+
export declare const LightBoostFilter: () => import("react/jsx-runtime").JSX.Element;
|
|
25
|
+
export declare const SharedDefs: ({ p }: {
|
|
26
|
+
p: SvgPalette;
|
|
27
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
28
|
+
export declare const svgLightFilter: (p: SvgPalette) => "url(#svgLightBoost)" | undefined;
|
|
29
|
+
export declare const BgGrid: ({ w, h }: {
|
|
30
|
+
w?: number;
|
|
31
|
+
h?: number;
|
|
32
|
+
}) => import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2021-2024 Datalayer, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Datalayer License
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Shared SVG palette types, theme-aware colour resolution, and reusable
|
|
9
|
+
* gradient / grid definitions consumed by SVG illustrations.
|
|
10
|
+
*/
|
|
11
|
+
import { datalayerColors, spatialColors, lovelyColors, matrixColors, earthColors, } from '../colors';
|
|
12
|
+
import { getBrightPalette, } from '../themeRegistry';
|
|
13
|
+
import { useThemeStore } from '../useThemeStore';
|
|
14
|
+
const dlBrightDark = getBrightPalette('datalayer');
|
|
15
|
+
const dlBrightLight = getBrightPalette('datalayer', 'light');
|
|
16
|
+
const spBrightDark = getBrightPalette('spatial');
|
|
17
|
+
const spBrightLight = getBrightPalette('spatial', 'light');
|
|
18
|
+
const lvBrightDark = getBrightPalette('lovely');
|
|
19
|
+
const lvBrightLight = getBrightPalette('lovely', 'light');
|
|
20
|
+
const mxBrightDark = getBrightPalette('matrix');
|
|
21
|
+
const mxBrightLight = getBrightPalette('matrix', 'light');
|
|
22
|
+
const eaBrightDark = getBrightPalette('earth');
|
|
23
|
+
const eaBrightLight = getBrightPalette('earth', 'light');
|
|
24
|
+
const palettes = {
|
|
25
|
+
datalayer: {
|
|
26
|
+
light: {
|
|
27
|
+
bg: '#f6f8fa',
|
|
28
|
+
bgPanel: '#ffffff',
|
|
29
|
+
bgAlt: '#f0f3f6',
|
|
30
|
+
primary: datalayerColors.greenBrand,
|
|
31
|
+
secondary: datalayerColors.greenText,
|
|
32
|
+
accent: datalayerColors.greenBright,
|
|
33
|
+
glow: dlBrightLight.glow,
|
|
34
|
+
pop: dlBrightLight.pop,
|
|
35
|
+
spark: dlBrightLight.spark,
|
|
36
|
+
blaze: dlBrightLight.blaze,
|
|
37
|
+
surge: dlBrightLight.surge,
|
|
38
|
+
flame: dlBrightLight.flame,
|
|
39
|
+
gold: dlBrightLight.gold,
|
|
40
|
+
textLight: '#1f2328',
|
|
41
|
+
textMuted: '#656d76',
|
|
42
|
+
isLight: true,
|
|
43
|
+
},
|
|
44
|
+
dark: {
|
|
45
|
+
bg: '#0d1117',
|
|
46
|
+
bgPanel: '#161b22',
|
|
47
|
+
bgAlt: '#1c2128',
|
|
48
|
+
primary: datalayerColors.greenAccent,
|
|
49
|
+
secondary: datalayerColors.greenBrand,
|
|
50
|
+
accent: datalayerColors.greenBright,
|
|
51
|
+
glow: dlBrightDark.glow,
|
|
52
|
+
pop: dlBrightDark.pop,
|
|
53
|
+
spark: dlBrightDark.spark,
|
|
54
|
+
blaze: dlBrightDark.blaze,
|
|
55
|
+
surge: dlBrightDark.surge,
|
|
56
|
+
flame: dlBrightDark.flame,
|
|
57
|
+
gold: dlBrightDark.gold,
|
|
58
|
+
textLight: '#f0f6fc',
|
|
59
|
+
textMuted: '#8b949e',
|
|
60
|
+
isLight: false,
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
spatial: {
|
|
64
|
+
light: {
|
|
65
|
+
bg: '#f0f2ff',
|
|
66
|
+
bgPanel: '#ffffff',
|
|
67
|
+
bgAlt: '#eef2ff',
|
|
68
|
+
primary: spatialColors.indigoBrand,
|
|
69
|
+
secondary: spatialColors.indigoText,
|
|
70
|
+
accent: spatialColors.indigoBright,
|
|
71
|
+
glow: spBrightLight.glow,
|
|
72
|
+
pop: spBrightLight.pop,
|
|
73
|
+
spark: spBrightLight.spark,
|
|
74
|
+
blaze: spBrightLight.blaze,
|
|
75
|
+
surge: spBrightLight.surge,
|
|
76
|
+
flame: spBrightLight.flame,
|
|
77
|
+
gold: spBrightLight.gold,
|
|
78
|
+
textLight: '#1E1E3F',
|
|
79
|
+
textMuted: spatialColors.gray,
|
|
80
|
+
isLight: true,
|
|
81
|
+
},
|
|
82
|
+
dark: {
|
|
83
|
+
bg: spatialColors.black,
|
|
84
|
+
bgPanel: '#111827',
|
|
85
|
+
bgAlt: '#1E293B',
|
|
86
|
+
primary: spatialColors.indigoAccent,
|
|
87
|
+
secondary: spatialColors.indigoBrand,
|
|
88
|
+
accent: spatialColors.indigoBright,
|
|
89
|
+
glow: spBrightDark.glow,
|
|
90
|
+
pop: spBrightDark.pop,
|
|
91
|
+
spark: spBrightDark.spark,
|
|
92
|
+
blaze: spBrightDark.blaze,
|
|
93
|
+
surge: spBrightDark.surge,
|
|
94
|
+
flame: spBrightDark.flame,
|
|
95
|
+
gold: spBrightDark.gold,
|
|
96
|
+
textLight: '#E0E7FF',
|
|
97
|
+
textMuted: '#94A3B8',
|
|
98
|
+
isLight: false,
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
lovely: {
|
|
102
|
+
light: {
|
|
103
|
+
bg: '#fff5f7',
|
|
104
|
+
bgPanel: '#ffffff',
|
|
105
|
+
bgAlt: lovelyColors.roseTint,
|
|
106
|
+
primary: lovelyColors.roseBrand,
|
|
107
|
+
secondary: lovelyColors.roseText,
|
|
108
|
+
accent: lovelyColors.roseBright,
|
|
109
|
+
glow: lvBrightLight.glow,
|
|
110
|
+
pop: lvBrightLight.pop,
|
|
111
|
+
spark: lvBrightLight.spark,
|
|
112
|
+
blaze: lvBrightLight.blaze,
|
|
113
|
+
surge: lvBrightLight.surge,
|
|
114
|
+
flame: lvBrightLight.flame,
|
|
115
|
+
gold: lvBrightLight.gold,
|
|
116
|
+
textLight: '#2D1B28',
|
|
117
|
+
textMuted: lovelyColors.gray,
|
|
118
|
+
isLight: true,
|
|
119
|
+
},
|
|
120
|
+
dark: {
|
|
121
|
+
bg: lovelyColors.black,
|
|
122
|
+
bgPanel: '#250E1D',
|
|
123
|
+
bgAlt: '#3D1530',
|
|
124
|
+
primary: lovelyColors.roseAccent,
|
|
125
|
+
secondary: lovelyColors.roseBrand,
|
|
126
|
+
accent: lovelyColors.roseBright,
|
|
127
|
+
glow: lvBrightDark.glow,
|
|
128
|
+
pop: lvBrightDark.pop,
|
|
129
|
+
spark: lvBrightDark.spark,
|
|
130
|
+
blaze: lvBrightDark.blaze,
|
|
131
|
+
surge: lvBrightDark.surge,
|
|
132
|
+
flame: lvBrightDark.flame,
|
|
133
|
+
gold: lvBrightDark.gold,
|
|
134
|
+
textLight: '#FCE7F3',
|
|
135
|
+
textMuted: '#D4A5BD',
|
|
136
|
+
isLight: false,
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
matrix: {
|
|
140
|
+
light: {
|
|
141
|
+
bg: '#f0fff0',
|
|
142
|
+
bgPanel: '#ffffff',
|
|
143
|
+
bgAlt: matrixColors.greenTint,
|
|
144
|
+
primary: matrixColors.greenBrand,
|
|
145
|
+
secondary: matrixColors.greenText,
|
|
146
|
+
accent: matrixColors.greenAccent,
|
|
147
|
+
glow: mxBrightLight.glow,
|
|
148
|
+
pop: mxBrightLight.pop,
|
|
149
|
+
spark: mxBrightLight.spark,
|
|
150
|
+
blaze: mxBrightLight.blaze,
|
|
151
|
+
surge: mxBrightLight.surge,
|
|
152
|
+
flame: mxBrightLight.flame,
|
|
153
|
+
gold: mxBrightLight.gold,
|
|
154
|
+
textLight: '#0A2E1A',
|
|
155
|
+
textMuted: matrixColors.gray,
|
|
156
|
+
isLight: true,
|
|
157
|
+
},
|
|
158
|
+
dark: {
|
|
159
|
+
bg: matrixColors.black,
|
|
160
|
+
bgPanel: '#0A1F0A',
|
|
161
|
+
bgAlt: '#122812',
|
|
162
|
+
primary: matrixColors.greenPhosphor,
|
|
163
|
+
secondary: matrixColors.greenGlow,
|
|
164
|
+
accent: matrixColors.greenGlow,
|
|
165
|
+
glow: mxBrightDark.glow,
|
|
166
|
+
pop: mxBrightDark.pop,
|
|
167
|
+
spark: mxBrightDark.spark,
|
|
168
|
+
blaze: mxBrightDark.blaze,
|
|
169
|
+
surge: mxBrightDark.surge,
|
|
170
|
+
flame: mxBrightDark.flame,
|
|
171
|
+
gold: mxBrightDark.gold,
|
|
172
|
+
textLight: '#C8E6C9',
|
|
173
|
+
textMuted: '#66BB6A',
|
|
174
|
+
isLight: false,
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
earth: {
|
|
178
|
+
light: {
|
|
179
|
+
bg: '#F0F5FA',
|
|
180
|
+
bgPanel: '#ffffff',
|
|
181
|
+
bgAlt: earthColors.oceanTint,
|
|
182
|
+
primary: earthColors.oceanBrand,
|
|
183
|
+
secondary: earthColors.oceanText,
|
|
184
|
+
accent: earthColors.oceanAccent,
|
|
185
|
+
glow: eaBrightLight.glow,
|
|
186
|
+
pop: eaBrightLight.pop,
|
|
187
|
+
spark: eaBrightLight.spark,
|
|
188
|
+
blaze: eaBrightLight.blaze,
|
|
189
|
+
surge: eaBrightLight.surge,
|
|
190
|
+
flame: eaBrightLight.flame,
|
|
191
|
+
gold: eaBrightLight.gold,
|
|
192
|
+
textLight: '#1A2332',
|
|
193
|
+
textMuted: earthColors.gray,
|
|
194
|
+
isLight: true,
|
|
195
|
+
},
|
|
196
|
+
dark: {
|
|
197
|
+
bg: earthColors.black,
|
|
198
|
+
bgPanel: '#0E1D30',
|
|
199
|
+
bgAlt: '#132840',
|
|
200
|
+
primary: earthColors.oceanAccent,
|
|
201
|
+
secondary: earthColors.oceanBrand,
|
|
202
|
+
accent: earthColors.oceanBright,
|
|
203
|
+
glow: eaBrightDark.glow,
|
|
204
|
+
pop: eaBrightDark.pop,
|
|
205
|
+
spark: eaBrightDark.spark,
|
|
206
|
+
blaze: eaBrightDark.blaze,
|
|
207
|
+
surge: eaBrightDark.surge,
|
|
208
|
+
flame: eaBrightDark.flame,
|
|
209
|
+
gold: eaBrightDark.gold,
|
|
210
|
+
textLight: '#D4E4DC',
|
|
211
|
+
textMuted: '#8A9BA8',
|
|
212
|
+
isLight: false,
|
|
213
|
+
},
|
|
214
|
+
},
|
|
215
|
+
};
|
|
216
|
+
export function getSvgPalette(theme = 'datalayer', colorMode = 'auto') {
|
|
217
|
+
const mode = colorMode === 'auto'
|
|
218
|
+
? typeof window !== 'undefined' &&
|
|
219
|
+
window.matchMedia('(prefers-color-scheme: dark)').matches
|
|
220
|
+
? 'dark'
|
|
221
|
+
: 'light'
|
|
222
|
+
: colorMode;
|
|
223
|
+
return palettes[theme]?.[mode] ?? palettes.datalayer.dark;
|
|
224
|
+
}
|
|
225
|
+
export function useSvgPalette() {
|
|
226
|
+
const { colorMode, theme } = useThemeStore();
|
|
227
|
+
return getSvgPalette(theme, colorMode);
|
|
228
|
+
}
|
|
229
|
+
/** @deprecated Use `useSvgPalette` instead. */
|
|
230
|
+
export const useBlogSvgPalette = useSvgPalette;
|
|
231
|
+
export const LightBoostFilter = () => (_jsx("filter", { id: "svgLightBoost", colorInterpolationFilters: "sRGB", children: _jsx("feComponentTransfer", { children: _jsx("feFuncA", { type: "gamma", exponent: "0.45", amplitude: "1", offset: "0" }) }) }));
|
|
232
|
+
export const SharedDefs = ({ p }) => (_jsxs("defs", { children: [_jsx(LightBoostFilter, {}), _jsxs("linearGradient", { id: "fadeGreen", x1: "0", y1: "0", x2: "1", y2: "1", children: [_jsx("stop", { offset: "0%", stopColor: p.primary, stopOpacity: "0.7" }), _jsx("stop", { offset: "100%", stopColor: p.secondary, stopOpacity: "0" })] }), _jsxs("linearGradient", { id: "fadeGreenH", x1: "0", y1: "0", x2: "1", y2: "0", children: [_jsx("stop", { offset: "0%", stopColor: p.primary, stopOpacity: "0.5" }), _jsx("stop", { offset: "50%", stopColor: p.secondary, stopOpacity: "0.25" }), _jsx("stop", { offset: "100%", stopColor: p.secondary, stopOpacity: "0" })] }), _jsxs("linearGradient", { id: "fadeBright", x1: "0", y1: "0", x2: "0", y2: "1", children: [_jsx("stop", { offset: "0%", stopColor: p.accent, stopOpacity: "0.4" }), _jsx("stop", { offset: "100%", stopColor: p.accent, stopOpacity: "0" })] }), _jsxs("linearGradient", { id: "fadeVivid", x1: "0", y1: "0", x2: "1", y2: "1", children: [_jsx("stop", { offset: "0%", stopColor: p.glow, stopOpacity: "0.8" }), _jsx("stop", { offset: "50%", stopColor: p.pop, stopOpacity: "0.5" }), _jsx("stop", { offset: "100%", stopColor: p.spark, stopOpacity: "0" })] }), _jsxs("linearGradient", { id: "fadeVividH", x1: "0", y1: "0", x2: "1", y2: "0", children: [_jsx("stop", { offset: "0%", stopColor: p.glow, stopOpacity: "0.6" }), _jsx("stop", { offset: "100%", stopColor: p.pop, stopOpacity: "0.15" })] }), _jsxs("radialGradient", { id: "glowGreen", children: [_jsx("stop", { offset: "0%", stopColor: p.primary, stopOpacity: "0.6" }), _jsx("stop", { offset: "100%", stopColor: p.primary, stopOpacity: "0" })] }), _jsxs("radialGradient", { id: "glowBright", children: [_jsx("stop", { offset: "0%", stopColor: p.accent, stopOpacity: "0.45" }), _jsx("stop", { offset: "100%", stopColor: p.accent, stopOpacity: "0" })] }), _jsxs("radialGradient", { id: "glowVivid", children: [_jsx("stop", { offset: "0%", stopColor: p.glow, stopOpacity: "0.7" }), _jsx("stop", { offset: "60%", stopColor: p.glow, stopOpacity: "0.2" }), _jsx("stop", { offset: "100%", stopColor: p.glow, stopOpacity: "0" })] }), _jsxs("radialGradient", { id: "glowPop", children: [_jsx("stop", { offset: "0%", stopColor: p.pop, stopOpacity: "0.65" }), _jsx("stop", { offset: "60%", stopColor: p.pop, stopOpacity: "0.15" }), _jsx("stop", { offset: "100%", stopColor: p.pop, stopOpacity: "0" })] }), _jsxs("radialGradient", { id: "glowSpark", children: [_jsx("stop", { offset: "0%", stopColor: p.spark, stopOpacity: "0.6" }), _jsx("stop", { offset: "60%", stopColor: p.spark, stopOpacity: "0.15" }), _jsx("stop", { offset: "100%", stopColor: p.spark, stopOpacity: "0" })] }), _jsxs("radialGradient", { id: "glowBlaze", children: [_jsx("stop", { offset: "0%", stopColor: p.blaze, stopOpacity: "0.7" }), _jsx("stop", { offset: "55%", stopColor: p.blaze, stopOpacity: "0.2" }), _jsx("stop", { offset: "100%", stopColor: p.blaze, stopOpacity: "0" })] }), _jsxs("radialGradient", { id: "glowSurge", children: [_jsx("stop", { offset: "0%", stopColor: p.surge, stopOpacity: "0.7" }), _jsx("stop", { offset: "55%", stopColor: p.surge, stopOpacity: "0.2" }), _jsx("stop", { offset: "100%", stopColor: p.surge, stopOpacity: "0" })] }), _jsxs("radialGradient", { id: "glowFlame", children: [_jsx("stop", { offset: "0%", stopColor: p.flame, stopOpacity: "0.7" }), _jsx("stop", { offset: "55%", stopColor: p.flame, stopOpacity: "0.2" }), _jsx("stop", { offset: "100%", stopColor: p.flame, stopOpacity: "0" })] }), _jsxs("radialGradient", { id: "glowGold", children: [_jsx("stop", { offset: "0%", stopColor: p.gold, stopOpacity: "0.7" }), _jsx("stop", { offset: "55%", stopColor: p.gold, stopOpacity: "0.2" }), _jsx("stop", { offset: "100%", stopColor: p.gold, stopOpacity: "0" })] }), _jsxs("linearGradient", { id: "fadeBlazeToSurge", x1: "0", y1: "0", x2: "1", y2: "0", children: [_jsx("stop", { offset: "0%", stopColor: p.blaze, stopOpacity: "0.7" }), _jsx("stop", { offset: "50%", stopColor: p.spark, stopOpacity: "0.3" }), _jsx("stop", { offset: "100%", stopColor: p.surge, stopOpacity: "0.7" })] }), _jsx("pattern", { id: "gridDots", width: "24", height: "24", patternUnits: "userSpaceOnUse", children: _jsx("circle", { cx: "1", cy: "1", r: "0.7", fill: p.primary, opacity: "0.06" }) })] }));
|
|
233
|
+
export const svgLightFilter = (p) => p.isLight ? 'url(#svgLightBoost)' : undefined;
|
|
234
|
+
export const BgGrid = ({ w = 800, h = 400 }) => (_jsx("rect", { width: w, height: h, fill: "url(#gridDots)" }));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './SvgPalette';
|
|
@@ -1,14 +1,32 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Zustand store for theme preferences – reusable across Datalayer apps.
|
|
3
3
|
*
|
|
4
|
-
* Persists `colorMode` and `theme` to localStorage.
|
|
4
|
+
* Persists `colorMode` and `theme` to localStorage. The store key is
|
|
5
5
|
* configurable so that different apps can maintain independent prefs.
|
|
6
6
|
*
|
|
7
|
+
* ## Variants
|
|
8
|
+
*
|
|
9
|
+
* A *variant* is a named set of theme/colorMode defaults (e.g. `anonymous`,
|
|
10
|
+
* `authenticated`). When a variant is active, `setTheme`, `setColorMode`,
|
|
11
|
+
* and `toggleColorMode` automatically update the active variant's stored
|
|
12
|
+
* preferences. Calling `setVariant(name)` switches theme/colorMode to
|
|
13
|
+
* that variant's prefs in one step.
|
|
14
|
+
*
|
|
15
|
+
* Variants can be registered at build time (via defaults) or at runtime
|
|
16
|
+
* (via `registerVariants`). `registerVariants` only sets defaults for
|
|
17
|
+
* variants that don't already exist, preserving user-customised prefs
|
|
18
|
+
* across page loads.
|
|
19
|
+
*
|
|
7
20
|
* @module theme/useThemeStore
|
|
8
21
|
*/
|
|
9
22
|
import { type StoreApi, type UseBoundStore } from 'zustand';
|
|
10
23
|
import type { ThemeVariant } from './themeRegistry';
|
|
11
24
|
import type { ColorMode } from './DatalayerBrandThemeProvider';
|
|
25
|
+
/** Per-variant theme + colorMode preferences. */
|
|
26
|
+
export type VariantDefaults = Record<string, {
|
|
27
|
+
theme: ThemeVariant;
|
|
28
|
+
colorMode: ColorMode;
|
|
29
|
+
}>;
|
|
12
30
|
export interface ThemeState {
|
|
13
31
|
/** Current color mode (light, dark, or auto = follow OS). */
|
|
14
32
|
colorMode: ColorMode;
|
|
@@ -24,6 +42,21 @@ export interface ThemeState {
|
|
|
24
42
|
* color mode to the theme's configured default.
|
|
25
43
|
*/
|
|
26
44
|
setTheme: (theme: ThemeVariant, applyDefaultColorMode?: boolean) => void;
|
|
45
|
+
/** The currently active variant (`null` when no variant is active). */
|
|
46
|
+
activeVariant: string | null;
|
|
47
|
+
/** Per-variant stored preferences. */
|
|
48
|
+
variants: VariantDefaults;
|
|
49
|
+
/**
|
|
50
|
+
* Register variant definitions. Only sets defaults for variants that
|
|
51
|
+
* don't already exist — existing (possibly user-customised) variants
|
|
52
|
+
* are preserved.
|
|
53
|
+
*/
|
|
54
|
+
registerVariants: (defs: VariantDefaults) => void;
|
|
55
|
+
/**
|
|
56
|
+
* Activate a named variant. Sets `theme` / `colorMode` to the
|
|
57
|
+
* variant's stored prefs in one step.
|
|
58
|
+
*/
|
|
59
|
+
setVariant: (variant: string) => void;
|
|
27
60
|
}
|
|
28
61
|
/**
|
|
29
62
|
* Create a theme store bound to a specific localStorage key.
|
|
@@ -34,11 +67,12 @@ export interface ThemeState {
|
|
|
34
67
|
* ```
|
|
35
68
|
*
|
|
36
69
|
* @param storageKey localStorage key for persistence (e.g. `'otel-example-theme'`)
|
|
37
|
-
* @param defaults Optional overrides for the initial colorMode / theme
|
|
70
|
+
* @param defaults Optional overrides for the initial colorMode / theme / variants
|
|
38
71
|
*/
|
|
39
72
|
export declare function createThemeStore(storageKey: string, defaults?: {
|
|
40
73
|
colorMode?: ColorMode;
|
|
41
74
|
theme?: ThemeVariant;
|
|
75
|
+
variants?: VariantDefaults;
|
|
42
76
|
}): UseBoundStore<StoreApi<ThemeState>>;
|
|
43
77
|
/**
|
|
44
78
|
* Default theme store for Datalayer applications.
|
|
@@ -5,14 +5,33 @@
|
|
|
5
5
|
/**
|
|
6
6
|
* Zustand store for theme preferences – reusable across Datalayer apps.
|
|
7
7
|
*
|
|
8
|
-
* Persists `colorMode` and `theme` to localStorage.
|
|
8
|
+
* Persists `colorMode` and `theme` to localStorage. The store key is
|
|
9
9
|
* configurable so that different apps can maintain independent prefs.
|
|
10
10
|
*
|
|
11
|
+
* ## Variants
|
|
12
|
+
*
|
|
13
|
+
* A *variant* is a named set of theme/colorMode defaults (e.g. `anonymous`,
|
|
14
|
+
* `authenticated`). When a variant is active, `setTheme`, `setColorMode`,
|
|
15
|
+
* and `toggleColorMode` automatically update the active variant's stored
|
|
16
|
+
* preferences. Calling `setVariant(name)` switches theme/colorMode to
|
|
17
|
+
* that variant's prefs in one step.
|
|
18
|
+
*
|
|
19
|
+
* Variants can be registered at build time (via defaults) or at runtime
|
|
20
|
+
* (via `registerVariants`). `registerVariants` only sets defaults for
|
|
21
|
+
* variants that don't already exist, preserving user-customised prefs
|
|
22
|
+
* across page loads.
|
|
23
|
+
*
|
|
11
24
|
* @module theme/useThemeStore
|
|
12
25
|
*/
|
|
13
26
|
import { create } from 'zustand';
|
|
14
27
|
import { persist, createJSONStorage } from 'zustand/middleware';
|
|
15
28
|
import { themeConfigs } from './themeRegistry';
|
|
29
|
+
/* ── Helpers ─────────────────────────────────────────────────────── */
|
|
30
|
+
const colorModeCycle = {
|
|
31
|
+
light: 'dark',
|
|
32
|
+
dark: 'auto',
|
|
33
|
+
auto: 'light',
|
|
34
|
+
};
|
|
16
35
|
/**
|
|
17
36
|
* Create a theme store bound to a specific localStorage key.
|
|
18
37
|
*
|
|
@@ -22,35 +41,118 @@ import { themeConfigs } from './themeRegistry';
|
|
|
22
41
|
* ```
|
|
23
42
|
*
|
|
24
43
|
* @param storageKey localStorage key for persistence (e.g. `'otel-example-theme'`)
|
|
25
|
-
* @param defaults Optional overrides for the initial colorMode / theme
|
|
44
|
+
* @param defaults Optional overrides for the initial colorMode / theme / variants
|
|
26
45
|
*/
|
|
27
46
|
export function createThemeStore(storageKey, defaults) {
|
|
28
47
|
return create()(persist(set => ({
|
|
29
48
|
colorMode: defaults?.colorMode ?? 'dark',
|
|
30
49
|
theme: defaults?.theme ?? 'matrix',
|
|
50
|
+
/* ── variant state ──────────────────────────────────── */
|
|
51
|
+
activeVariant: null,
|
|
52
|
+
variants: defaults?.variants ?? {},
|
|
53
|
+
/* ── actions ────────────────────────────────────────── */
|
|
31
54
|
toggleColorMode: () => set(state => {
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
55
|
+
const next = colorModeCycle[state.colorMode];
|
|
56
|
+
if (state.activeVariant && state.variants[state.activeVariant]) {
|
|
57
|
+
return {
|
|
58
|
+
colorMode: next,
|
|
59
|
+
variants: {
|
|
60
|
+
...state.variants,
|
|
61
|
+
[state.activeVariant]: { ...state.variants[state.activeVariant], colorMode: next },
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
return { colorMode: next };
|
|
66
|
+
}),
|
|
67
|
+
setColorMode: (mode) => set(state => {
|
|
68
|
+
if (state.activeVariant && state.variants[state.activeVariant]) {
|
|
69
|
+
return {
|
|
70
|
+
colorMode: mode,
|
|
71
|
+
variants: {
|
|
72
|
+
...state.variants,
|
|
73
|
+
[state.activeVariant]: { ...state.variants[state.activeVariant], colorMode: mode },
|
|
74
|
+
},
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return { colorMode: mode };
|
|
38
78
|
}),
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
79
|
+
setTheme: (theme, applyDefaultColorMode = true) => set(state => {
|
|
80
|
+
const nextColorMode = applyDefaultColorMode
|
|
81
|
+
? themeConfigs[theme].defaultColorMode
|
|
82
|
+
: state.colorMode;
|
|
83
|
+
if (state.activeVariant && state.variants[state.activeVariant]) {
|
|
84
|
+
return {
|
|
85
|
+
theme,
|
|
86
|
+
colorMode: nextColorMode,
|
|
87
|
+
variants: {
|
|
88
|
+
...state.variants,
|
|
89
|
+
[state.activeVariant]: { theme, colorMode: nextColorMode },
|
|
90
|
+
},
|
|
91
|
+
};
|
|
44
92
|
}
|
|
45
|
-
return
|
|
93
|
+
return { theme, colorMode: nextColorMode };
|
|
94
|
+
}),
|
|
95
|
+
registerVariants: (defs) => set(state => {
|
|
96
|
+
const merged = { ...state.variants };
|
|
97
|
+
for (const [key, val] of Object.entries(defs)) {
|
|
98
|
+
if (!merged[key]) {
|
|
99
|
+
merged[key] = val;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
return { variants: merged };
|
|
103
|
+
}),
|
|
104
|
+
setVariant: (variant) => set(state => {
|
|
105
|
+
const v = state.variants[variant];
|
|
106
|
+
if (!v) {
|
|
107
|
+
return { activeVariant: variant };
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
activeVariant: variant,
|
|
111
|
+
theme: v.theme,
|
|
112
|
+
colorMode: v.colorMode,
|
|
113
|
+
};
|
|
46
114
|
}),
|
|
47
115
|
}), {
|
|
48
116
|
name: storageKey,
|
|
117
|
+
version: 2,
|
|
49
118
|
storage: createJSONStorage(() => localStorage),
|
|
50
119
|
partialize: state => ({
|
|
51
120
|
colorMode: state.colorMode,
|
|
52
121
|
theme: state.theme,
|
|
122
|
+
activeVariant: state.activeVariant,
|
|
123
|
+
variants: state.variants,
|
|
53
124
|
}),
|
|
125
|
+
/**
|
|
126
|
+
* Migration: when `version` is missing or differs from the current
|
|
127
|
+
* value the persisted state is discarded and the store starts fresh
|
|
128
|
+
* from code-defined defaults.
|
|
129
|
+
*/
|
|
130
|
+
migrate: () => ({}),
|
|
131
|
+
/**
|
|
132
|
+
* Deep-merge variants during hydration so that:
|
|
133
|
+
* - Code-defined variants (from defaults or registerVariants) are
|
|
134
|
+
* always present even when localStorage has an older snapshot.
|
|
135
|
+
* - Per-variant prefs that the user customised (persisted) win over
|
|
136
|
+
* code defaults for each variant key.
|
|
137
|
+
*/
|
|
138
|
+
merge: (persisted, current) => {
|
|
139
|
+
const p = (persisted ?? {});
|
|
140
|
+
// Build merged variants: start from code-defined, then overlay
|
|
141
|
+
// any persisted variant whose prefs differ (user customisations).
|
|
142
|
+
const mergedVariants = { ...current.variants };
|
|
143
|
+
if (p.variants) {
|
|
144
|
+
for (const [key, val] of Object.entries(p.variants)) {
|
|
145
|
+
if (val && typeof val === 'object' && 'theme' in val) {
|
|
146
|
+
mergedVariants[key] = val;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return {
|
|
151
|
+
...current,
|
|
152
|
+
...p,
|
|
153
|
+
variants: mergedVariants,
|
|
154
|
+
};
|
|
155
|
+
},
|
|
54
156
|
}));
|
|
55
157
|
}
|
|
56
158
|
/**
|