@datalayer/primer-addons 1.0.12 → 1.0.13

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/App.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  import "@primer/primitives/dist/css/base/typography/typography.css";
2
+ import "@primer/primitives/dist/css/base/motion/motion.css";
2
3
  import "@primer/primitives/dist/css/functional/themes/light.css";
3
4
  import "@primer/primitives/dist/css/functional/size/border.css";
4
5
  import "@primer/primitives/dist/css/functional/size/breakpoints.css";
package/lib/App.js CHANGED
@@ -5,6 +5,7 @@ import { KebabHorizontalIcon } from "@primer/octicons-react";
5
5
  import { DatalayerIcon, LogOutIcon, SettingsIcon } from "@datalayer/icons-react";
6
6
  import { Slider, Overlay } from ".";
7
7
  import "@primer/primitives/dist/css/base/typography/typography.css";
8
+ import "@primer/primitives/dist/css/base/motion/motion.css";
8
9
  import "@primer/primitives/dist/css/functional/themes/light.css";
9
10
  import "@primer/primitives/dist/css/functional/size/border.css";
10
11
  import "@primer/primitives/dist/css/functional/size/breakpoints.css";
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { SegmentedControl } from '@primer/react';
2
+ import { SegmentedControl, Tooltip } from '@primer/react';
3
3
  import { MoonIcon, SunIcon, DeviceDesktopIcon, } from '@primer/octicons-react';
4
4
  import { Box } from '../box/Box';
5
5
  import { themeVariants, themeConfigs, } from '../../theme';
@@ -16,27 +16,27 @@ export function AppearanceControls({ colorMode, themeVariant, onColorModeChange,
16
16
  }, children: themeVariants.map((variant) => {
17
17
  const cfg = themeConfigs[variant];
18
18
  const isSelected = themeVariant === variant;
19
- return (_jsx(Box, { as: "button", "aria-label": cfg.label, "aria-pressed": isSelected, onClick: () => onThemeChange(variant), sx: {
20
- width: 24,
21
- height: 24,
22
- borderRadius: '50%',
23
- backgroundColor: cfg.brandColor,
24
- border: '2px solid',
25
- borderColor: isSelected ? 'accent.fg' : 'border.default',
26
- cursor: 'pointer',
27
- padding: 0,
28
- outline: 'none',
29
- transition: 'border-color 0.15s ease',
30
- boxShadow: isSelected
31
- ? '0 0 0 2px var(--bgColor-accent-muted, rgba(9,105,218,0.3))'
32
- : 'none',
33
- '&:hover': {
34
- borderColor: 'accent.fg',
35
- },
36
- '&:focus-visible': {
37
- boxShadow: '0 0 0 2px var(--bgColor-accent-muted, rgba(9,105,218,0.3))',
38
- },
39
- } }, variant));
19
+ return (_jsx(Tooltip, { text: cfg.label, direction: "s", children: _jsx(Box, { as: "button", "aria-label": cfg.label, "aria-pressed": isSelected, onClick: () => onThemeChange(variant), sx: {
20
+ width: 24,
21
+ height: 24,
22
+ borderRadius: '50%',
23
+ backgroundColor: cfg.brandColor,
24
+ border: '2px solid',
25
+ borderColor: isSelected ? 'accent.fg' : 'border.default',
26
+ cursor: 'pointer',
27
+ padding: 0,
28
+ outline: 'none',
29
+ transition: 'border-color 0.15s ease',
30
+ boxShadow: isSelected
31
+ ? '0 0 0 2px var(--bgColor-accent-muted, rgba(9,105,218,0.3))'
32
+ : 'none',
33
+ '&:hover': {
34
+ borderColor: 'accent.fg',
35
+ },
36
+ '&:focus-visible': {
37
+ boxShadow: '0 0 0 2px var(--bgColor-accent-muted, rgba(9,105,218,0.3))',
38
+ },
39
+ } }) }, variant));
40
40
  }) })] }));
41
41
  }
42
42
  export default AppearanceControls;
@@ -3,7 +3,20 @@ import { type ThemeVariant } from '../../theme';
3
3
  export interface LogoColorPair {
4
4
  primary: string;
5
5
  secondary: string;
6
+ /** Colour for the "DATA" part of the wordmark (gray in the original brand logo). */
7
+ textColor: string;
8
+ /** Gradient [start, end] for primary (left) bars. */
9
+ primaryGradient: [start: string, end: string];
10
+ /** Gradient [start, end] for secondary (right) bars. */
11
+ secondaryGradient: [start: string, end: string];
6
12
  }
13
+ /**
14
+ * Gradient pattern derived from the original brand logo SVG:
15
+ * - Left bars: accent → brand (bright → mid)
16
+ * - Right bars: hover → text (dark → mid)
17
+ *
18
+ * This mapping is consistent across all four themes.
19
+ */
7
20
  export declare const THEME_LOGO_COLORS: Record<ThemeVariant, {
8
21
  light: LogoColorPair;
9
22
  dark: LogoColorPair;
@@ -11,8 +24,16 @@ export declare const THEME_LOGO_COLORS: Record<ThemeVariant, {
11
24
  export declare function getLogoColors(variant?: ThemeVariant, colorMode?: 'light' | 'dark' | 'auto'): LogoColorPair;
12
25
  export interface DatalayerLogoProps extends Omit<SVGProps<SVGSVGElement>, 'ref'> {
13
26
  size?: number;
27
+ variant?: ThemeVariant;
28
+ colorMode?: 'light' | 'dark' | 'auto';
14
29
  primaryColor?: string;
15
30
  secondaryColor?: string;
31
+ /** Explicit gradient [start, end] for primary (left) bars. */
32
+ primaryGradient?: [start: string, end: string];
33
+ /** Explicit gradient [start, end] for secondary (right) bars. */
34
+ secondaryGradient?: [start: string, end: string];
35
+ /** Enable horizontal gradients matching the original brand logo. Default `true`. */
36
+ gradient?: boolean;
16
37
  }
17
38
  export declare const DatalayerLogo: import("react").ForwardRefExoticComponent<DatalayerLogoProps & import("react").RefAttributes<SVGSVGElement>>;
18
39
  export default DatalayerLogo;
@@ -3,47 +3,94 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  * Copyright (c) 2023-2025 Datalayer, Inc.
4
4
  * Distributed under the terms of the Modified BSD License.
5
5
  */
6
- import { forwardRef } from 'react';
7
- import { datalayerColors, spatialColors, lovelyColors, matrixColors, } from '../../theme';
6
+ import { forwardRef, useId } from 'react';
7
+ import { datalayerColors, spatialColors, lovelyColors, matrixColors, earthColors, } from '../../theme';
8
+ /**
9
+ * Gradient pattern derived from the original brand logo SVG:
10
+ * - Left bars: accent → brand (bright → mid)
11
+ * - Right bars: hover → text (dark → mid)
12
+ *
13
+ * This mapping is consistent across all four themes.
14
+ */
8
15
  export const THEME_LOGO_COLORS = {
9
16
  datalayer: {
10
17
  light: {
11
- primary: datalayerColors.greenBrand,
18
+ primary: datalayerColors.greenAccent,
12
19
  secondary: datalayerColors.greenText,
20
+ textColor: datalayerColors.gray,
21
+ primaryGradient: [datalayerColors.greenAccent, datalayerColors.greenBrand],
22
+ secondaryGradient: [datalayerColors.greenHover, datalayerColors.greenBrand],
13
23
  },
14
24
  dark: {
15
25
  primary: datalayerColors.greenBright,
16
26
  secondary: datalayerColors.greenAccent,
27
+ textColor: datalayerColors.gray,
28
+ primaryGradient: [datalayerColors.greenAccent, datalayerColors.greenBrand],
29
+ secondaryGradient: [datalayerColors.greenHover, datalayerColors.greenText],
17
30
  },
18
31
  },
19
32
  spatial: {
20
33
  light: {
21
34
  primary: spatialColors.indigoBrand,
22
35
  secondary: spatialColors.indigoText,
36
+ textColor: spatialColors.gray,
37
+ primaryGradient: [spatialColors.indigoBright, spatialColors.indigoBrand],
38
+ secondaryGradient: [spatialColors.indigoHover, spatialColors.indigoAccent],
23
39
  },
24
40
  dark: {
25
41
  primary: spatialColors.indigoBright,
26
42
  secondary: spatialColors.indigoAccent,
43
+ textColor: spatialColors.gray,
44
+ primaryGradient: [spatialColors.indigoBright, spatialColors.indigoBrand],
45
+ secondaryGradient: [spatialColors.indigoHover, spatialColors.indigoAccent],
27
46
  },
28
47
  },
29
48
  lovely: {
30
49
  light: {
31
50
  primary: lovelyColors.roseBrand,
32
51
  secondary: lovelyColors.roseText,
52
+ textColor: lovelyColors.gray,
53
+ primaryGradient: [lovelyColors.roseBright, lovelyColors.roseBrand],
54
+ secondaryGradient: [lovelyColors.roseHover, lovelyColors.roseAccent],
33
55
  },
34
56
  dark: {
35
57
  primary: lovelyColors.roseBright,
36
58
  secondary: lovelyColors.roseAccent,
59
+ textColor: lovelyColors.gray,
60
+ primaryGradient: [lovelyColors.roseBright, lovelyColors.roseBrand],
61
+ secondaryGradient: [lovelyColors.roseHover, lovelyColors.roseAccent],
37
62
  },
38
63
  },
39
64
  matrix: {
40
65
  light: {
41
66
  primary: matrixColors.greenBrand,
42
67
  secondary: matrixColors.greenText,
68
+ textColor: matrixColors.gray,
69
+ primaryGradient: [matrixColors.greenGlow, matrixColors.greenBrand],
70
+ secondaryGradient: [matrixColors.greenHover, matrixColors.greenAccent],
43
71
  },
44
72
  dark: {
45
73
  primary: matrixColors.greenGlow,
46
74
  secondary: matrixColors.greenPhosphor,
75
+ textColor: matrixColors.gray,
76
+ primaryGradient: [matrixColors.greenGlow, matrixColors.greenBrand],
77
+ secondaryGradient: [matrixColors.greenHover, matrixColors.greenAccent],
78
+ },
79
+ },
80
+ earth: {
81
+ light: {
82
+ primary: earthColors.oceanBrand,
83
+ secondary: earthColors.oceanText,
84
+ textColor: earthColors.gray,
85
+ primaryGradient: [earthColors.oceanAccent, earthColors.oceanBrand],
86
+ secondaryGradient: [earthColors.oceanHover, earthColors.oceanText],
87
+ },
88
+ dark: {
89
+ primary: earthColors.oceanBright,
90
+ secondary: earthColors.oceanAccent,
91
+ textColor: earthColors.gray,
92
+ primaryGradient: [earthColors.oceanBright, earthColors.oceanBrand],
93
+ secondaryGradient: [earthColors.oceanHover, earthColors.oceanAccent],
47
94
  },
48
95
  },
49
96
  };
@@ -57,7 +104,13 @@ const BARS = [
57
104
  { y: 37.5, secondaryWidth: 50, primaryWidth: 50 },
58
105
  { y: 75, secondaryWidth: 70, primaryWidth: 30 },
59
106
  ];
60
- export const DatalayerLogo = forwardRef(function DatalayerLogo({ size = 16, primaryColor = 'currentColor', secondaryColor = 'currentColor', ...svgProps }, ref) {
61
- return (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 100 100", width: size, height: size, "aria-hidden": "true", ref: ref, ...svgProps, children: BARS.map(({ y, secondaryWidth, primaryWidth }) => (_jsxs("g", { children: [_jsx("rect", { x: 0, y: y, width: secondaryWidth, height: BAR_HEIGHT, fill: secondaryColor }), _jsx("rect", { x: secondaryWidth, y: y, width: primaryWidth, height: BAR_HEIGHT, fill: primaryColor })] }, y))) }));
107
+ export const DatalayerLogo = forwardRef(function DatalayerLogo({ size = 16, variant = 'datalayer', colorMode = 'light', primaryColor, secondaryColor, primaryGradient, secondaryGradient, gradient = true, ...svgProps }, ref) {
108
+ const themed = getLogoColors(variant, colorMode);
109
+ const resolvedPrimary = primaryColor ?? themed.primary;
110
+ const resolvedSecondary = secondaryColor ?? themed.secondary;
111
+ const uid = useId().replace(/:/g, '');
112
+ const [primaryStart, primaryEnd] = primaryGradient ?? themed.primaryGradient;
113
+ const [secondaryStart, secondaryEnd] = secondaryGradient ?? themed.secondaryGradient;
114
+ return (_jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 100 100", width: size, height: size, "aria-hidden": "true", ref: ref, ...svgProps, children: [gradient && (_jsxs("defs", { children: [_jsxs("linearGradient", { id: `${uid}-p`, x1: "0", y1: "0", x2: "1", y2: "0", children: [_jsx("stop", { offset: "0", stopColor: primaryStart }), _jsx("stop", { offset: "1", stopColor: primaryEnd })] }), _jsxs("linearGradient", { id: `${uid}-s`, x1: "0", y1: "0", x2: "1", y2: "0", children: [_jsx("stop", { offset: "0", stopColor: secondaryStart }), _jsx("stop", { offset: "1", stopColor: secondaryEnd })] })] })), BARS.map(({ y, secondaryWidth, primaryWidth }) => (_jsxs("g", { children: [_jsx("rect", { x: 0, y: y, width: secondaryWidth, height: BAR_HEIGHT, fill: gradient ? `url(#${uid}-p)` : resolvedPrimary }), _jsx("rect", { x: secondaryWidth, y: y, width: primaryWidth, height: BAR_HEIGHT, fill: gradient ? `url(#${uid}-s)` : resolvedSecondary })] }, y)))] }));
62
115
  });
63
116
  export default DatalayerLogo;
@@ -1,5 +1,5 @@
1
1
  import { type SVGProps } from 'react';
2
- import type { ThemeVariant } from '../../theme';
2
+ import { type ThemeVariant } from '../../theme';
3
3
  export interface DatalayerLogoTextProps extends Omit<SVGProps<SVGSVGElement>, 'ref'> {
4
4
  size?: number;
5
5
  scale?: number;
@@ -7,6 +7,14 @@ export interface DatalayerLogoTextProps extends Omit<SVGProps<SVGSVGElement>, 'r
7
7
  variant?: ThemeVariant;
8
8
  primaryColor?: string;
9
9
  secondaryColor?: string;
10
+ /** Explicit gradient [start, end] for primary (left) bars. */
11
+ primaryGradient?: [start: string, end: string];
12
+ /** Explicit gradient [start, end] for secondary (right) bars. */
13
+ secondaryGradient?: [start: string, end: string];
14
+ /** Enable horizontal gradients matching the original brand logo. Default `true`. */
15
+ gradient?: boolean;
16
+ /** Colour for the "DATA" part of the wordmark (defaults to theme gray). */
17
+ textColor?: string;
10
18
  textSizeMultiplier?: number;
11
19
  /**
12
20
  * When true, render logo mark first then text.
@@ -1,29 +1,30 @@
1
- import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  /*
3
3
  * Copyright (c) 2023-2026 Datalayer, Inc.
4
4
  * Distributed under the terms of the Modified BSD License.
5
5
  */
6
6
  import { forwardRef } from 'react';
7
- import { getLogoColors } from './DatalayerLogo';
7
+ import { DatalayerLogo, getLogoColors } from './DatalayerLogo';
8
8
  import { DatalayerText } from './DatalayerText';
9
9
  /**
10
10
  * Datalayer icon + wordmark based on official brand proportions.
11
11
  * Uses themed colors by default and allows explicit color overrides.
12
12
  */
13
- export const DatalayerLogoText = forwardRef(function DatalayerLogoText({ size = 25, scale = 1, colorMode = 'light', variant = 'datalayer', primaryColor, secondaryColor,
13
+ export const DatalayerLogoText = forwardRef(function DatalayerLogoText({ size = 25, scale = 1, colorMode = 'light', variant = 'datalayer', primaryColor, secondaryColor, primaryGradient, secondaryGradient, gradient = true, textColor,
14
14
  // 2.380655 ~= 25 / (0.7 * 15.00187)
15
15
  // This makes the wordmark glyph height match the 25-unit icon height.
16
16
  textSizeMultiplier = 2.380655, inverse = false, ...svgProps }, ref) {
17
17
  const themed = getLogoColors(variant, colorMode);
18
18
  const primary = primaryColor ?? themed.primary;
19
19
  const secondary = secondaryColor ?? themed.secondary;
20
+ // "DATA" part of the wordmark defaults to the themed gray.
21
+ const dataTextColor = textColor ?? themed.textColor;
20
22
  const baseHeight = size;
21
- const baseWidth = (149.672 / 25) * size;
23
+ const baseWidth = (161.672 / 25) * size;
22
24
  const height = baseHeight * scale;
23
25
  const width = baseWidth * scale;
24
- const iconGroup = (_jsxs("g", { transform: "translate(0 0)", children: [_jsx("rect", { x: "0", y: "0", width: "10", height: "6.25", fill: secondary }), _jsx("rect", { x: "10", y: "0", width: "15", height: "6.25", fill: primary }), _jsx("rect", { x: "0", y: "9.375", width: "15", height: "6.25", fill: secondary }), _jsx("rect", { x: "15", y: "9.375", width: "10", height: "6.25", fill: primary }), _jsx("rect", { x: "0", y: "18.75", width: "20", height: "6.25", fill: secondary }), _jsx("rect", { x: "20", y: "18.75", width: "5", height: "6.25", fill: primary })] }));
25
- const logoFirst = (_jsxs(_Fragment, { children: [iconGroup, _jsx(DatalayerText, { primaryColor: primary, secondaryColor: secondary, sizeMultiplier: textSizeMultiplier, x: 16 })] }));
26
- const textFirst = (_jsxs(_Fragment, { children: [_jsx(DatalayerText, { primaryColor: primary, secondaryColor: secondary, sizeMultiplier: textSizeMultiplier, x: 0 }), _jsxs("g", { transform: "translate(124.672 0)", children: [_jsx("rect", { x: "0", y: "0", width: "10", height: "6.25", fill: secondary }), _jsx("rect", { x: "10", y: "0", width: "15", height: "6.25", fill: primary }), _jsx("rect", { x: "0", y: "9.375", width: "15", height: "6.25", fill: secondary }), _jsx("rect", { x: "15", y: "9.375", width: "10", height: "6.25", fill: primary }), _jsx("rect", { x: "0", y: "18.75", width: "20", height: "6.25", fill: secondary }), _jsx("rect", { x: "20", y: "18.75", width: "5", height: "6.25", fill: primary })] })] }));
27
- return (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 149.672 25", width: width, height: height, role: "img", "aria-label": "Datalayer", ref: ref, ...svgProps, children: inverse ? logoFirst : textFirst }));
26
+ 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: 0 }), _jsx(DatalayerLogo, { size: 25, x: 136.672, y: 0, variant: variant, colorMode: colorMode, primaryColor: primary, secondaryColor: secondary, primaryGradient: primaryGradient, secondaryGradient: secondaryGradient, gradient: gradient })] }));
28
+ return (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", viewBox: "0 0 161.672 25", width: width, height: height, role: "img", "aria-label": "Datalayer", ref: ref, ...svgProps, children: inverse ? logoFirst : textFirst }));
28
29
  });
29
30
  export default DatalayerLogoText;
@@ -1,6 +1,8 @@
1
1
  import type { SVGProps } from 'react';
2
2
  export interface DatalayerTextProps extends Omit<SVGProps<SVGGElement>, 'ref'> {
3
+ /** Colour for the "LAYER" part of the wordmark. */
3
4
  primaryColor?: string;
5
+ /** Colour for the "DATA" part of the wordmark (gray in the original brand logo). */
4
6
  secondaryColor?: string;
5
7
  /** Multiplies the base wordmark size. 1.0 keeps current dimensions. */
6
8
  sizeMultiplier?: number;
@@ -11,6 +13,10 @@ export interface DatalayerTextProps extends Omit<SVGProps<SVGGElement>, 'ref'> {
11
13
  }
12
14
  /**
13
15
  * Official Datalayer wordmark outlines (BebasNeue converted to paths).
16
+ *
17
+ * Colour mapping matches the original brand logo SVG:
18
+ * - "DATA" = secondaryColor (gray in the original)
19
+ * - "LAYER" = primaryColor (green accent in the original)
14
20
  */
15
21
  export declare const DatalayerText: ({ primaryColor, secondaryColor, sizeMultiplier, x, y, ...groupProps }: DatalayerTextProps) => JSX.Element;
16
22
  export default DatalayerText;
@@ -1,8 +1,13 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { datalayerColors } from '../../theme';
2
3
  /**
3
4
  * Official Datalayer wordmark outlines (BebasNeue converted to paths).
5
+ *
6
+ * Colour mapping matches the original brand logo SVG:
7
+ * - "DATA" = secondaryColor (gray in the original)
8
+ * - "LAYER" = primaryColor (green accent in the original)
4
9
  */
5
- export const DatalayerText = ({ primaryColor = 'currentColor', secondaryColor = 'currentColor', sizeMultiplier = 1, x = 20, y = -190.15, ...groupProps }) => {
10
+ export const DatalayerText = ({ primaryColor = datalayerColors.greenAccent, secondaryColor = datalayerColors.gray, sizeMultiplier = 1, x = 20, y = -190.15, ...groupProps }) => {
6
11
  const baseScale = 0.7;
7
12
  const scale = baseScale * sizeMultiplier;
8
13
  // Keep the wordmark anchored when scaling so larger multipliers do not
@@ -9,7 +9,7 @@
9
9
  export const datalayerColors = {
10
10
  // Core Neutrals
11
11
  black: '#000000', // Primary text - AAA on white
12
- gray: '#59595C', // Secondary text - AA on white
12
+ gray: '#595A5C', // Secondary text - AA on white (matches original brand SVG)
13
13
  white: '#FFFFFF', // Background
14
14
  // Greens (Brand & Accessibility)
15
15
  greenBrand: '#16A085', // Brand accent, icons, dividers, headings
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Earth Color System – The Blue Planet
3
+ * Ocean blues (sea), forest greens (plants), golden yellows (sun)
4
+ * WCAG AA/AAA compliant
5
+ */
6
+ export declare const earthColors: {
7
+ black: string;
8
+ gray: string;
9
+ white: string;
10
+ oceanBrand: string;
11
+ oceanAccent: string;
12
+ oceanText: string;
13
+ oceanTint: string;
14
+ oceanBright: string;
15
+ oceanHover: string;
16
+ forestBrand: string;
17
+ forestAccent: string;
18
+ forestTint: string;
19
+ sunBrand: string;
20
+ sunAccent: string;
21
+ sunTint: string;
22
+ earthWarm: string;
23
+ earthSand: string;
24
+ earthClay: string;
25
+ brightGlow: string;
26
+ brightPop: string;
27
+ brightSpark: string;
28
+ brightBlaze: string;
29
+ brightSurge: string;
30
+ brightFlame: string;
31
+ brightGold: string;
32
+ brightLightGlow: string;
33
+ brightLightPop: string;
34
+ brightLightSpark: string;
35
+ brightLightBlaze: string;
36
+ brightLightSurge: string;
37
+ brightLightFlame: string;
38
+ brightLightGold: string;
39
+ };
@@ -0,0 +1,51 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ /**
6
+ * Earth Color System – The Blue Planet
7
+ * Ocean blues (sea), forest greens (plants), golden yellows (sun)
8
+ * WCAG AA/AAA compliant
9
+ */
10
+ export const earthColors = {
11
+ // Core Neutrals
12
+ black: '#0A1628', // Deep ocean night — primary dark background
13
+ gray: '#5B6B7A', // Slate — secondary text
14
+ white: '#F7FAFC', // Morning sky — primary light background
15
+ // Ocean Blue palette (Brand) — the blue planet
16
+ oceanBrand: '#0369A1', // Deep ocean — headings, icons, dividers
17
+ oceanAccent: '#0EA5E9', // Bright sky blue — charts, highlights on dark surfaces
18
+ oceanText: '#075985', // Accessible ocean blue for text & buttons (AA+ on white)
19
+ oceanTint: '#E0F2FE', // Pale sky — soft background for callouts
20
+ oceanBright: '#38BDF8', // Vivid sky blue — highlights on dark backgrounds
21
+ oceanHover: '#0C4A6E', // Abyss navy — primary button hover
22
+ // Forest / Canopy (Secondary — green like plants)
23
+ forestBrand: '#15803D', // Dense canopy green
24
+ forestAccent: '#22C55E', // Sunlit leaf green
25
+ forestTint: '#DCFCE7', // Morning dew
26
+ // Sun / Warmth (Tertiary — yellow like sun)
27
+ sunBrand: '#CA8A04', // Deep golden sun
28
+ sunAccent: '#EAB308', // Vivid sunflower
29
+ sunTint: '#FEF9C3', // Pale sunshine
30
+ // Earth / Soil tones
31
+ earthWarm: '#92400E', // Red earth / laterite
32
+ earthSand: '#D97706', // Sandstone / amber
33
+ earthClay: '#B45309', // Terracotta
34
+ // Bright / vivid colours for SVG illustrations
35
+ brightGlow: '#0EA5E9', // Vivid ocean blue — primary glow (sea)
36
+ brightPop: '#22C55E', // Vivid green — contrasting accent (vegetation)
37
+ brightSpark: '#EAB308', // Vivid gold — sparkle (sunlight)
38
+ brightBlaze: '#EF4444', // Vivid red — warm accent (wildfire / alerts)
39
+ brightSurge: '#3B82F6', // Deep blue — cool accent (deep water)
40
+ // Warm vivid colours — earth & sun accents
41
+ brightFlame: '#F59E0B', // Amber gold — warm energy (solar)
42
+ brightGold: '#FACC15', // Bright sunflower — golden highlight
43
+ // Vivid brights for light backgrounds
44
+ brightLightGlow: '#0284C7', // Deep ocean blue
45
+ brightLightPop: '#16A34A', // Vivid forest green
46
+ brightLightSpark: '#CA8A04', // Deep golden sun
47
+ brightLightBlaze: '#DC2626', // Deep red
48
+ brightLightSurge: '#2563EB', // Deep ocean blue
49
+ brightLightFlame: '#D97706', // Deep amber
50
+ brightLightGold: '#A16207', // Deep gold
51
+ };
@@ -2,4 +2,17 @@ export { datalayerColors } from './datalayerColors';
2
2
  export { spatialColors } from './spatialColors';
3
3
  export { lovelyColors } from './lovelyColors';
4
4
  export { matrixColors } from './matrixColors';
5
+ export { earthColors } from './earthColors';
5
6
  export { indicatorColors, defaultIndicatorColors, type IndicatorColors, } from './indicatorColors';
7
+ import type { ThemeVariant } from '../themeRegistry';
8
+ /**
9
+ * Themed color palettes — maps each `ThemeVariant` to its corresponding
10
+ * color object so consumers can pick the right palette at runtime.
11
+ *
12
+ * Usage:
13
+ * ```ts
14
+ * import { themedColors } from '@datalayer/primer-addons/lib/theme';
15
+ * const colors = themedColors[themeVariant]; // Record<string, string>
16
+ * ```
17
+ */
18
+ export declare const themedColors: Record<ThemeVariant, Record<string, string>>;
@@ -6,4 +6,27 @@ export { datalayerColors } from './datalayerColors';
6
6
  export { spatialColors } from './spatialColors';
7
7
  export { lovelyColors } from './lovelyColors';
8
8
  export { matrixColors } from './matrixColors';
9
+ export { earthColors } from './earthColors';
9
10
  export { indicatorColors, defaultIndicatorColors, } from './indicatorColors';
11
+ import { datalayerColors } from './datalayerColors';
12
+ import { spatialColors } from './spatialColors';
13
+ import { lovelyColors } from './lovelyColors';
14
+ import { matrixColors } from './matrixColors';
15
+ import { earthColors } from './earthColors';
16
+ /**
17
+ * Themed color palettes — maps each `ThemeVariant` to its corresponding
18
+ * color object so consumers can pick the right palette at runtime.
19
+ *
20
+ * Usage:
21
+ * ```ts
22
+ * import { themedColors } from '@datalayer/primer-addons/lib/theme';
23
+ * const colors = themedColors[themeVariant]; // Record<string, string>
24
+ * ```
25
+ */
26
+ export const themedColors = {
27
+ datalayer: datalayerColors,
28
+ spatial: spatialColors,
29
+ lovely: lovelyColors,
30
+ matrix: matrixColors,
31
+ earth: earthColors,
32
+ };
@@ -6,9 +6,9 @@ export * from './DatalayerBrandThemeProvider';
6
6
  export * from './themes/spatialTheme';
7
7
  export * from './themes/lovelyTheme';
8
8
  export * from './themes/matrixTheme';
9
+ export * from './themes/earthTheme';
9
10
  export * from './themes-brand/spatialBrandTheme';
10
11
  export * from './themeRegistry';
11
- export * from './Palette';
12
12
  export * from './useSystemColorMode';
13
13
  export * from './useThemeStore';
14
14
  export * from './ThemedProvider';
@@ -10,9 +10,9 @@ export * from './DatalayerBrandThemeProvider';
10
10
  export * from './themes/spatialTheme';
11
11
  export * from './themes/lovelyTheme';
12
12
  export * from './themes/matrixTheme';
13
+ export * from './themes/earthTheme';
13
14
  export * from './themes-brand/spatialBrandTheme';
14
15
  export * from './themeRegistry';
15
- export * from './Palette';
16
16
  export * from './useSystemColorMode';
17
17
  export * from './useThemeStore';
18
18
  export * from './ThemedProvider';
@@ -1,7 +1,7 @@
1
1
  import { type CSSProperties } from 'react';
2
2
  import { type ColorMode } from './DatalayerBrandThemeProvider';
3
3
  /** Available theme variants. */
4
- export type ThemeVariant = 'datalayer' | 'spatial' | 'lovely' | 'matrix';
4
+ export type ThemeVariant = 'datalayer' | 'spatial' | 'lovely' | 'matrix' | 'earth';
5
5
  /** A pair of colours for a two-stop gradient. */
6
6
  export interface GradientPair {
7
7
  /** Start colour (brighter / brand). */
@@ -6,10 +6,12 @@ import { datalayerTheme, datalayerThemeStyles } from './themes/datalayerTheme';
6
6
  import { spatialTheme, spatialThemeStyles } from './themes/spatialTheme';
7
7
  import { lovelyTheme, lovelyThemeStyles } from './themes/lovelyTheme';
8
8
  import { matrixTheme, matrixThemeStyles } from './themes/matrixTheme';
9
+ import { earthTheme, earthThemeStyles } from './themes/earthTheme';
9
10
  import { datalayerColors } from './colors/datalayerColors';
10
11
  import { spatialColors } from './colors/spatialColors';
11
12
  import { lovelyColors } from './colors/lovelyColors';
12
13
  import { matrixColors } from './colors/matrixColors';
14
+ import { earthColors } from './colors/earthColors';
13
15
  /* ─── Registry ────────────────────────────────────────────────────────── */
14
16
  export const themeConfigs = {
15
17
  datalayer: {
@@ -140,9 +142,41 @@ export const themeConfigs = {
140
142
  gold: matrixColors.brightLightGold, // #FFAB00 — vivid amber
141
143
  },
142
144
  },
145
+ earth: {
146
+ label: 'Earth',
147
+ description: 'Ocean blues, forest greens & golden sun — the Blue Planet.',
148
+ brandColor: earthColors.oceanBrand,
149
+ defaultColorMode: 'auto',
150
+ primerTheme: earthTheme,
151
+ themeStyles: earthThemeStyles,
152
+ cardGradient: {
153
+ light: { from: earthColors.oceanBrand, to: earthColors.oceanText }, // #0369A1 → #075985
154
+ dark: { from: earthColors.oceanAccent, to: earthColors.oceanBrand }, // #0EA5E9 → #0369A1
155
+ },
156
+ brightPalette: {
157
+ glow: earthColors.brightGlow, // #0EA5E9 — vivid ocean blue
158
+ onGlow: '#ffffff', // white text on ocean blue
159
+ pop: earthColors.brightPop, // #22C55E — vivid green
160
+ spark: earthColors.brightSpark, // #EAB308 — vivid gold
161
+ blaze: earthColors.brightBlaze, // #EF4444 — vivid red
162
+ surge: earthColors.brightSurge, // #3B82F6 — deep blue
163
+ flame: earthColors.brightFlame, // #F59E0B — amber gold
164
+ gold: earthColors.brightGold, // #FACC15 — sunflower
165
+ },
166
+ brightPaletteLight: {
167
+ glow: earthColors.brightLightGlow, // #0284C7 — deep ocean blue
168
+ onGlow: '#ffffff', // white text on deep ocean
169
+ pop: earthColors.brightLightPop, // #16A34A — vivid forest green
170
+ spark: earthColors.brightLightSpark, // #CA8A04 — deep golden sun
171
+ blaze: earthColors.brightLightBlaze, // #DC2626 — deep red
172
+ surge: earthColors.brightLightSurge, // #2563EB — deep ocean blue
173
+ flame: earthColors.brightLightFlame, // #D97706 — deep amber
174
+ gold: earthColors.brightLightGold, // #A16207 — deep gold
175
+ },
176
+ },
143
177
  };
144
178
  /** All available theme variants in display order. */
145
- export const themeVariants = ['datalayer', 'spatial', 'lovely', 'matrix'];
179
+ export const themeVariants = ['datalayer', 'spatial', 'lovely', 'matrix', 'earth'];
146
180
  /** Look up a theme config by variant name. */
147
181
  export function getThemeConfig(variant) {
148
182
  return themeConfigs[variant];
@@ -263,6 +297,22 @@ const avatarColorPalettes = {
263
297
  matrixColors.brightSurge, // #00E5FF — electric blue
264
298
  ],
265
299
  },
300
+ earth: {
301
+ light: [
302
+ earthColors.oceanText, // #075985 — deep ocean blue
303
+ earthColors.oceanBrand, // #0369A1 — brand ocean
304
+ earthColors.brightLightPop, // #16A34A — vivid forest green
305
+ earthColors.brightLightSpark, // #CA8A04 — deep golden sun
306
+ earthColors.gray, // #5B6B7A — slate
307
+ ],
308
+ dark: [
309
+ earthColors.oceanAccent, // #0EA5E9 — bright sky blue
310
+ earthColors.oceanBright, // #38BDF8 — vivid sky blue
311
+ earthColors.brightPop, // #22C55E — vivid green
312
+ earthColors.brightSpark, // #EAB308 — vivid gold
313
+ earthColors.brightFlame, // #F59E0B — amber gold
314
+ ],
315
+ },
266
316
  };
267
317
  /**
268
318
  * Get a 5-colour avatar palette for the given theme variant and colour mode.
@@ -1,5 +1,3 @@
1
- import { datalayerColors } from '../colors';
2
- export { datalayerColors };
3
1
  /**
4
2
  * The Primer theme object.
5
3
  *
@@ -12,8 +12,6 @@
12
12
  import { theme as primerTheme } from '@primer/react';
13
13
  import { datalayerColors } from '../colors';
14
14
  import { buildThemeStyles } from './createThemeCSSVars';
15
- // Re-export so existing consumers keep working.
16
- export { datalayerColors };
17
15
  /* ── Light-mode colour definitions ───────────────────────────────────── */
18
16
  const datalayerLight = {
19
17
  canvas: {