@datalayer/primer-addons 1.0.14 → 1.0.17
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/AI.d.ts +17 -0
- package/lib/components/logo/AI.js +18 -0
- package/lib/components/logo/DatalayerTextAI.d.ts +25 -0
- package/lib/components/logo/DatalayerTextAI.js +40 -0
- package/lib/components/logo/index.d.ts +2 -0
- package/lib/components/logo/index.js +2 -0
- package/lib/theme/DatalayerThemeProvider.d.ts +1 -1
- package/lib/theme/colors/index.d.ts +0 -1
- package/lib/theme/colors/index.js +0 -1
- package/lib/theme/{themes → css}/createThemeCSSVars.js +1 -0
- package/lib/theme/index.d.ts +2 -1
- package/lib/theme/index.js +2 -1
- package/lib/theme/indicators/index.d.ts +1 -0
- package/lib/theme/indicators/index.js +5 -0
- package/lib/theme/palettes/{SvgPalette.d.ts → ColorPalette.d.ts} +8 -6
- package/lib/theme/palettes/{SvgPalette.js → ColorPalette.js} +9 -6
- package/lib/theme/palettes/index.d.ts +1 -1
- package/lib/theme/palettes/index.js +1 -1
- package/lib/theme/themes/datalayerTheme.d.ts +1 -1
- package/lib/theme/themes/datalayerTheme.js +1 -1
- package/lib/theme/themes/earthTheme.d.ts +1 -1
- package/lib/theme/themes/earthTheme.js +1 -1
- package/lib/theme/themes/lovelyTheme.d.ts +1 -1
- package/lib/theme/themes/lovelyTheme.js +1 -1
- package/lib/theme/themes/matrixTheme.d.ts +1 -1
- package/lib/theme/themes/matrixTheme.js +1 -1
- package/lib/theme/themes/spatialTheme.d.ts +1 -1
- package/lib/theme/themes/spatialTheme.js +1 -1
- package/lib/theme/useThemeStore.d.ts +36 -2
- package/lib/theme/useThemeStore.js +116 -14
- package/package.json +1 -1
- /package/lib/theme/{themes → css}/createThemeCSSVars.d.ts +0 -0
- /package/lib/theme/{colors → indicators}/indicatorColors.d.ts +0 -0
- /package/lib/theme/{colors → indicators}/indicatorColors.js +0 -0
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type SVGProps } from 'react';
|
|
2
|
+
import { type ThemeVariant } from '../../theme';
|
|
3
|
+
export interface AIProps extends Omit<SVGProps<SVGSVGElement>, 'ref'> {
|
|
4
|
+
size?: number;
|
|
5
|
+
variant?: ThemeVariant;
|
|
6
|
+
colorMode?: 'light' | 'dark' | 'auto';
|
|
7
|
+
/** Colour of the "I" glyph. */
|
|
8
|
+
primaryColor?: string;
|
|
9
|
+
/** Colour of the "A" glyph. */
|
|
10
|
+
secondaryColor?: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* AI glyph mark from the official brand source SVG.
|
|
14
|
+
* Defaults to themed logo colors and supports explicit overrides.
|
|
15
|
+
*/
|
|
16
|
+
export declare const AI: import("react").ForwardRefExoticComponent<AIProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
17
|
+
export default AI;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2023-2026 Datalayer, Inc.
|
|
4
|
+
* Distributed under the terms of the Modified BSD License.
|
|
5
|
+
*/
|
|
6
|
+
import { forwardRef } from 'react';
|
|
7
|
+
import { getLogoColors } from './DatalayerLogo';
|
|
8
|
+
/**
|
|
9
|
+
* AI glyph mark from the official brand source SVG.
|
|
10
|
+
* Defaults to themed logo colors and supports explicit overrides.
|
|
11
|
+
*/
|
|
12
|
+
export const AI = forwardRef(function AI({ size = 24, variant = 'datalayer', colorMode = 'light', primaryColor, secondaryColor, ...svgProps }, ref) {
|
|
13
|
+
const themed = getLogoColors(variant, colorMode);
|
|
14
|
+
const resolvedPrimary = primaryColor ?? themed.primary;
|
|
15
|
+
const resolvedSecondary = secondaryColor ?? themed.textColor;
|
|
16
|
+
return (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", width: size, height: size, role: "img", "aria-label": "AI", ref: ref, ...svgProps, children: [_jsx("path", { d: "m13.788825 3.932 6.43325 16.136075h3.5279L17.316725 3.932H13.788825Z", fill: resolvedPrimary, strokeWidth: 0.25 }), _jsx("path", { d: "m6.325375 13.682775 2.20125 -5.67065 2.201275 5.67065H6.325375ZM6.68225 3.932 0.25 20.068075h3.596525l1.3155 -3.3886h6.729425l1.315275 3.3886h3.59655L10.371 3.932H6.68225Z", fill: resolvedSecondary, fillRule: "evenodd", clipRule: "evenodd", strokeWidth: 0.25 })] }));
|
|
17
|
+
});
|
|
18
|
+
export default AI;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type SVGProps } from 'react';
|
|
2
|
+
import { type ThemeVariant } from '../../theme';
|
|
3
|
+
export interface DatalayerTextAIProps extends Omit<SVGProps<SVGSVGElement>, 'ref'> {
|
|
4
|
+
size?: number;
|
|
5
|
+
scale?: number;
|
|
6
|
+
colorMode?: 'light' | 'dark' | 'auto';
|
|
7
|
+
variant?: ThemeVariant;
|
|
8
|
+
/** Colour for the "LAYER" part of the wordmark. */
|
|
9
|
+
primaryColor?: string;
|
|
10
|
+
/** Secondary accent colour used by the AI glyph. */
|
|
11
|
+
secondaryColor?: string;
|
|
12
|
+
/** Colour for the "DATA" part of the wordmark. */
|
|
13
|
+
textColor?: string;
|
|
14
|
+
textSizeMultiplier?: number;
|
|
15
|
+
aiPrimaryColor?: string;
|
|
16
|
+
aiSecondaryColor?: string;
|
|
17
|
+
/** Gap between wordmark and AI glyph in viewBox units. */
|
|
18
|
+
aiGap?: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Datalayer wordmark followed by AI glyph on one line.
|
|
22
|
+
* Both elements are aligned to the same 25-unit cap height.
|
|
23
|
+
*/
|
|
24
|
+
export declare const DatalayerTextAI: import("react").ForwardRefExoticComponent<DatalayerTextAIProps & import("react").RefAttributes<SVGSVGElement>>;
|
|
25
|
+
export default DatalayerTextAI;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright (c) 2023-2026 Datalayer, Inc.
|
|
4
|
+
* Distributed under the terms of the Modified BSD License.
|
|
5
|
+
*/
|
|
6
|
+
import { forwardRef } from 'react';
|
|
7
|
+
import { AI } from './AI';
|
|
8
|
+
import { DatalayerText } from './DatalayerText';
|
|
9
|
+
import { getLogoColors } from './DatalayerLogo';
|
|
10
|
+
const TEXT_LEFT_TRIM = 12;
|
|
11
|
+
const TEXT_END_X = 136.672 - TEXT_LEFT_TRIM;
|
|
12
|
+
const AI_SIZE = 24;
|
|
13
|
+
const AI_VISIBLE_TOP = 3.932;
|
|
14
|
+
const AI_VISIBLE_LEFT = 0.25;
|
|
15
|
+
const AI_VISIBLE_HEIGHT = 16.136075;
|
|
16
|
+
const AI_SCALE_TO_TEXT_HEIGHT = 25 / AI_VISIBLE_HEIGHT;
|
|
17
|
+
const AI_RENDER_SIZE = AI_SIZE * AI_SCALE_TO_TEXT_HEIGHT;
|
|
18
|
+
const AI_X_TRIM = AI_VISIBLE_LEFT * AI_SCALE_TO_TEXT_HEIGHT;
|
|
19
|
+
const AI_Y_TRIM = AI_VISIBLE_TOP * AI_SCALE_TO_TEXT_HEIGHT;
|
|
20
|
+
/**
|
|
21
|
+
* Datalayer wordmark followed by AI glyph on one line.
|
|
22
|
+
* Both elements are aligned to the same 25-unit cap height.
|
|
23
|
+
*/
|
|
24
|
+
export const DatalayerTextAI = forwardRef(function DatalayerTextAI({ size = 25, scale = 1, colorMode = 'light', variant = 'datalayer', primaryColor, secondaryColor, textColor,
|
|
25
|
+
// 2.380655 ~= 25 / (0.7 * 15.00187)
|
|
26
|
+
textSizeMultiplier = 2.380655, aiPrimaryColor, aiSecondaryColor, aiGap = 6, ...svgProps }, ref) {
|
|
27
|
+
const themed = getLogoColors(variant, colorMode);
|
|
28
|
+
const layerColor = primaryColor ?? themed.primary;
|
|
29
|
+
const accentColor = secondaryColor ?? themed.secondary;
|
|
30
|
+
const dataTextColor = textColor ?? themed.textColor;
|
|
31
|
+
const resolvedAiPrimary = aiPrimaryColor ?? layerColor;
|
|
32
|
+
const resolvedAiSecondary = aiSecondaryColor ?? accentColor;
|
|
33
|
+
const viewBoxWidth = TEXT_END_X + aiGap + AI_RENDER_SIZE - AI_X_TRIM;
|
|
34
|
+
const baseHeight = size;
|
|
35
|
+
const baseWidth = (viewBoxWidth / 25) * size;
|
|
36
|
+
const height = baseHeight * scale;
|
|
37
|
+
const width = baseWidth * scale;
|
|
38
|
+
return (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: `0 0 ${viewBoxWidth} 25`, width: width, height: height, role: "img", "aria-label": "Datalayer AI", ref: ref, ...svgProps, children: [_jsx(DatalayerText, { primaryColor: layerColor, secondaryColor: dataTextColor, sizeMultiplier: textSizeMultiplier, x: -TEXT_LEFT_TRIM }), _jsx(AI, { size: AI_RENDER_SIZE, x: TEXT_END_X + aiGap - AI_X_TRIM, y: -AI_Y_TRIM, variant: variant, colorMode: colorMode, primaryColor: resolvedAiPrimary, secondaryColor: resolvedAiSecondary })] }));
|
|
39
|
+
});
|
|
40
|
+
export default DatalayerTextAI;
|
|
@@ -25,7 +25,7 @@ export interface IDatalayerThemeProviderProps extends Omit<ThemeProviderProps, '
|
|
|
25
25
|
* When provided, these replace the built-in datalayer styles entirely.
|
|
26
26
|
* The `baseStyles` prop is still merged on top.
|
|
27
27
|
*
|
|
28
|
-
* Use the `buildThemeStyles` helper from `./
|
|
28
|
+
* Use the `buildThemeStyles` helper from `./css/createThemeCSSVars`
|
|
29
29
|
* to generate comprehensive overrides from a `ThemeColorDefs` pair.
|
|
30
30
|
*/
|
|
31
31
|
themeStyles?: {
|
|
@@ -3,7 +3,6 @@ export { spatialColors } from './spatialColors';
|
|
|
3
3
|
export { lovelyColors } from './lovelyColors';
|
|
4
4
|
export { matrixColors } from './matrixColors';
|
|
5
5
|
export { earthColors } from './earthColors';
|
|
6
|
-
export { indicatorColors, defaultIndicatorColors, type IndicatorColors, } from './indicatorColors';
|
|
7
6
|
import type { ThemeVariant } from '../themeRegistry';
|
|
8
7
|
/**
|
|
9
8
|
* Themed color palettes — maps each `ThemeVariant` to its corresponding
|
|
@@ -7,7 +7,6 @@ export { spatialColors } from './spatialColors';
|
|
|
7
7
|
export { lovelyColors } from './lovelyColors';
|
|
8
8
|
export { matrixColors } from './matrixColors';
|
|
9
9
|
export { earthColors } from './earthColors';
|
|
10
|
-
export { indicatorColors, defaultIndicatorColors, } from './indicatorColors';
|
|
11
10
|
import { datalayerColors } from './datalayerColors';
|
|
12
11
|
import { spatialColors } from './spatialColors';
|
|
13
12
|
import { lovelyColors } from './lovelyColors';
|
|
@@ -174,6 +174,7 @@ export function colorDefsToCSS(defs) {
|
|
|
174
174
|
/* ── Datalayer brand tokens (consumed by custom components) ─── */
|
|
175
175
|
'--brand-color-canvas-default': defs.canvas.default,
|
|
176
176
|
'--brand-color-text-default': defs.fg.default,
|
|
177
|
+
'--datalayer-icon-fg': defs.accent.fg,
|
|
177
178
|
};
|
|
178
179
|
}
|
|
179
180
|
/**
|
package/lib/theme/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from './colors';
|
|
2
|
-
export * from './
|
|
2
|
+
export * from './indicators';
|
|
3
|
+
export * from './css/createThemeCSSVars';
|
|
3
4
|
export * from './themes/datalayerTheme';
|
|
4
5
|
export * from './DatalayerThemeProvider';
|
|
5
6
|
export * from './DatalayerBrandThemeProvider';
|
package/lib/theme/index.js
CHANGED
|
@@ -3,7 +3,8 @@
|
|
|
3
3
|
* Distributed under the terms of the Modified BSD License.
|
|
4
4
|
*/
|
|
5
5
|
export * from './colors';
|
|
6
|
-
export * from './
|
|
6
|
+
export * from './indicators';
|
|
7
|
+
export * from './css/createThemeCSSVars';
|
|
7
8
|
export * from './themes/datalayerTheme';
|
|
8
9
|
export * from './DatalayerThemeProvider';
|
|
9
10
|
export * from './DatalayerBrandThemeProvider';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { indicatorColors, defaultIndicatorColors, type IndicatorColors, } from './indicatorColors';
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
import { type ThemeVariant } from '../themeRegistry';
|
|
2
|
+
export interface ColorPalette {
|
|
2
3
|
bg: string;
|
|
3
4
|
bgPanel: string;
|
|
4
5
|
bgAlt: string;
|
|
@@ -16,14 +17,15 @@ export interface SvgPalette {
|
|
|
16
17
|
textMuted: string;
|
|
17
18
|
isLight: boolean;
|
|
18
19
|
}
|
|
19
|
-
export declare function
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
export declare function getColorPalette(theme?: ThemeVariant, colorMode?: 'light' | 'dark' | 'auto'): ColorPalette;
|
|
21
|
+
export declare function useColorPalette(): ColorPalette;
|
|
22
|
+
/** @deprecated Use `useColorPalette` instead. */
|
|
23
|
+
export declare const useBlogColorPalette: typeof useColorPalette;
|
|
22
24
|
export declare const LightBoostFilter: () => import("react/jsx-runtime").JSX.Element;
|
|
23
25
|
export declare const SharedDefs: ({ p }: {
|
|
24
|
-
p:
|
|
26
|
+
p: ColorPalette;
|
|
25
27
|
}) => import("react/jsx-runtime").JSX.Element;
|
|
26
|
-
export declare const svgLightFilter: (p:
|
|
28
|
+
export declare const svgLightFilter: (p: ColorPalette) => "url(#svgLightBoost)" | undefined;
|
|
27
29
|
export declare const BgGrid: ({ w, h }: {
|
|
28
30
|
w?: number;
|
|
29
31
|
h?: number;
|
|
@@ -5,8 +5,8 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
5
5
|
* Datalayer License
|
|
6
6
|
*/
|
|
7
7
|
/**
|
|
8
|
-
* Shared
|
|
9
|
-
* gradient / grid definitions
|
|
8
|
+
* Shared palette types, theme-aware colour resolution, and reusable
|
|
9
|
+
* gradient / grid definitions.
|
|
10
10
|
*/
|
|
11
11
|
import { datalayerColors, spatialColors, lovelyColors, matrixColors, earthColors, } from '../colors';
|
|
12
12
|
import { getBrightPalette, } from '../themeRegistry';
|
|
@@ -213,8 +213,7 @@ const palettes = {
|
|
|
213
213
|
},
|
|
214
214
|
},
|
|
215
215
|
};
|
|
216
|
-
export function
|
|
217
|
-
const { colorMode, theme } = useThemeStore();
|
|
216
|
+
export function getColorPalette(theme = 'datalayer', colorMode = 'auto') {
|
|
218
217
|
const mode = colorMode === 'auto'
|
|
219
218
|
? typeof window !== 'undefined' &&
|
|
220
219
|
window.matchMedia('(prefers-color-scheme: dark)').matches
|
|
@@ -223,8 +222,12 @@ export function useSvgPalette() {
|
|
|
223
222
|
: colorMode;
|
|
224
223
|
return palettes[theme]?.[mode] ?? palettes.datalayer.dark;
|
|
225
224
|
}
|
|
226
|
-
|
|
227
|
-
|
|
225
|
+
export function useColorPalette() {
|
|
226
|
+
const { colorMode, theme } = useThemeStore();
|
|
227
|
+
return getColorPalette(theme, colorMode);
|
|
228
|
+
}
|
|
229
|
+
/** @deprecated Use `useColorPalette` instead. */
|
|
230
|
+
export const useBlogColorPalette = useColorPalette;
|
|
228
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" }) }) }));
|
|
229
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" }) })] }));
|
|
230
233
|
export const svgLightFilter = (p) => p.isLight ? 'url(#svgLightBoost)' : undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export * from './
|
|
1
|
+
export * from './ColorPalette';
|
|
@@ -1087,5 +1087,5 @@ export declare const datalayerTheme: {
|
|
|
1087
1087
|
}>;
|
|
1088
1088
|
};
|
|
1089
1089
|
/** Comprehensive Primer CSS-variable overrides for light & dark mode. */
|
|
1090
|
-
export declare const datalayerThemeStyles: import("
|
|
1090
|
+
export declare const datalayerThemeStyles: import("../css/createThemeCSSVars").ThemeStyles;
|
|
1091
1091
|
export default datalayerTheme;
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { theme as primerTheme } from '@primer/react';
|
|
13
13
|
import { datalayerColors } from '../colors';
|
|
14
|
-
import { buildThemeStyles } from '
|
|
14
|
+
import { buildThemeStyles } from '../css/createThemeCSSVars';
|
|
15
15
|
/* ── Light-mode colour definitions ───────────────────────────────────── */
|
|
16
16
|
const datalayerLight = {
|
|
17
17
|
canvas: {
|
|
@@ -1087,5 +1087,5 @@ export declare const earthTheme: {
|
|
|
1087
1087
|
}>;
|
|
1088
1088
|
};
|
|
1089
1089
|
/** Comprehensive Primer CSS-variable overrides for light & dark mode. */
|
|
1090
|
-
export declare const earthThemeStyles: import("
|
|
1090
|
+
export declare const earthThemeStyles: import("../css/createThemeCSSVars").ThemeStyles;
|
|
1091
1091
|
export default earthTheme;
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { theme as primerTheme } from '@primer/react';
|
|
13
13
|
import { earthColors } from '../colors/earthColors';
|
|
14
|
-
import { buildThemeStyles } from '
|
|
14
|
+
import { buildThemeStyles } from '../css/createThemeCSSVars';
|
|
15
15
|
/* ── Light-mode colour definitions ───────────────────────────────────── */
|
|
16
16
|
const earthLight = {
|
|
17
17
|
canvas: {
|
|
@@ -1087,5 +1087,5 @@ export declare const lovelyTheme: {
|
|
|
1087
1087
|
}>;
|
|
1088
1088
|
};
|
|
1089
1089
|
/** Comprehensive Primer CSS-variable overrides for light & dark mode. */
|
|
1090
|
-
export declare const lovelyThemeStyles: import("
|
|
1090
|
+
export declare const lovelyThemeStyles: import("../css/createThemeCSSVars").ThemeStyles;
|
|
1091
1091
|
export default lovelyTheme;
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { theme as primerTheme } from '@primer/react';
|
|
12
12
|
import { lovelyColors } from '../colors';
|
|
13
|
-
import { buildThemeStyles } from '
|
|
13
|
+
import { buildThemeStyles } from '../css/createThemeCSSVars';
|
|
14
14
|
/* ── Light-mode colour definitions ───────────────────────────────────── */
|
|
15
15
|
const lovelyLight = {
|
|
16
16
|
canvas: {
|
|
@@ -1087,5 +1087,5 @@ export declare const matrixTheme: {
|
|
|
1087
1087
|
}>;
|
|
1088
1088
|
};
|
|
1089
1089
|
/** Comprehensive Primer CSS-variable overrides for light & dark mode. */
|
|
1090
|
-
export declare const matrixThemeStyles: import("
|
|
1090
|
+
export declare const matrixThemeStyles: import("../css/createThemeCSSVars").ThemeStyles;
|
|
1091
1091
|
export default matrixTheme;
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { theme as primerTheme } from '@primer/react';
|
|
12
12
|
import { matrixColors } from '../colors';
|
|
13
|
-
import { buildThemeStyles } from '
|
|
13
|
+
import { buildThemeStyles } from '../css/createThemeCSSVars';
|
|
14
14
|
/* ── Light-mode colour definitions ───────────────────────────────────── */
|
|
15
15
|
const matrixLight = {
|
|
16
16
|
canvas: {
|
|
@@ -1087,5 +1087,5 @@ export declare const spatialTheme: {
|
|
|
1087
1087
|
}>;
|
|
1088
1088
|
};
|
|
1089
1089
|
/** Comprehensive Primer CSS-variable overrides for light & dark mode. */
|
|
1090
|
-
export declare const spatialThemeStyles: import("
|
|
1090
|
+
export declare const spatialThemeStyles: import("../css/createThemeCSSVars").ThemeStyles;
|
|
1091
1091
|
export default spatialTheme;
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { theme as primerTheme } from '@primer/react';
|
|
12
12
|
import { spatialColors } from '../colors';
|
|
13
|
-
import { buildThemeStyles } from '
|
|
13
|
+
import { buildThemeStyles } from '../css/createThemeCSSVars';
|
|
14
14
|
/* ── Light-mode colour definitions ───────────────────────────────────── */
|
|
15
15
|
const spatialLight = {
|
|
16
16
|
canvas: {
|
|
@@ -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
|
/**
|
package/package.json
CHANGED
|
File without changes
|
|
File without changes
|
|
File without changes
|