@gooddata/sdk-ui-theme-provider 11.42.0-alpha.3 → 11.42.0-alpha.4
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/esm/ThemeProvider/ThemeProvider.d.ts.map +1 -1
- package/esm/ThemeProvider/ThemeProvider.js +40 -14
- package/esm/ThemeProvider/prepareTheme.d.ts +12 -0
- package/esm/ThemeProvider/prepareTheme.d.ts.map +1 -1
- package/esm/ThemeProvider/prepareTheme.js +72 -11
- package/esm/colorValidation.d.ts +35 -0
- package/esm/colorValidation.d.ts.map +1 -0
- package/esm/colorValidation.js +66 -0
- package/esm/index.d.ts +1 -0
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +1 -0
- package/esm/sdk-ui-theme-provider.d.ts +36 -0
- package/esm/variablesSpec/internal/geo.d.ts.map +1 -1
- package/esm/variablesSpec/internal/geo.js +14 -1
- package/package.json +9 -9
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThemeProvider.d.ts","sourceRoot":"","sources":["../../src/ThemeProvider/ThemeProvider.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAA+B,MAAM,OAAO,CAAC;AAEpE,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAWlD;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;AAEtD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAChC;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAE7B;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,QAAQ,CAAC,EAAE,aAAa,CAAC;IAEzB;;;;;;OAMG;IACH,0BAA0B,CAAC,EAAE,OAAO,CAAC;IAErC;;;;OAIG;IACH,0BAA0B,CAAC,EAAE,OAAO,CAAC;IAErC;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACxB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,EAC1B,QAAQ,EACR,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,YAAY,EACrB,SAAS,EAAE,cAAc,EACzB,QAAmB,EACnB,0BAAiC,EACjC,0BAAiC,EACpC,EAAE,mBAAmB,
|
|
1
|
+
{"version":3,"file":"ThemeProvider.d.ts","sourceRoot":"","sources":["../../src/ThemeProvider/ThemeProvider.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAA+B,MAAM,OAAO,CAAC;AAEpE,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AACpE,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAWlD;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;AAEtD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAChC;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,kBAAkB,CAAC;IAE7B;;;;;;OAMG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,QAAQ,CAAC,EAAE,aAAa,CAAC;IAEzB;;;;;;OAMG;IACH,0BAA0B,CAAC,EAAE,OAAO,CAAC;IAErC;;;;OAIG;IACH,0BAA0B,CAAC,EAAE,OAAO,CAAC;IAErC;;OAEG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;CACxB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,EAC1B,QAAQ,EACR,KAAK,EAAE,UAAU,EACjB,OAAO,EAAE,YAAY,EACrB,SAAS,EAAE,cAAc,EACzB,QAAmB,EACnB,0BAAiC,EACjC,0BAAiC,EACpC,EAAE,mBAAmB,2CAoFrB"}
|
|
@@ -27,13 +27,31 @@ export function ThemeProvider({ children, theme: themeParam, backend: backendPar
|
|
|
27
27
|
const lastWorkspace = useRef(undefined);
|
|
28
28
|
lastWorkspace.current = workspace;
|
|
29
29
|
useEffect(() => {
|
|
30
|
+
// A malformed theme (e.g. an unparseable color) must never block rendering. Preparing and
|
|
31
|
+
// applying the theme is wrapped so any failure falls back to the default theme and always
|
|
32
|
+
// resolves the loading state, instead of leaving the app stuck on the loading screen.
|
|
33
|
+
const applyTheme = (themeToApply) => {
|
|
34
|
+
try {
|
|
35
|
+
const preparedTheme = prepareTheme(themeToApply, enableComplementaryPalette);
|
|
36
|
+
setTheme(preparedTheme);
|
|
37
|
+
clearCssProperties();
|
|
38
|
+
setCssProperties(preparedTheme, isDarkTheme(preparedTheme));
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
console.error("Failed to apply the theme, falling back to the default theme.", error);
|
|
42
|
+
// reset both channels (context theme and global CSS) to the default theme so
|
|
43
|
+
// context consumers stay consistent with the cleared CSS variables
|
|
44
|
+
setTheme({});
|
|
45
|
+
clearCssProperties();
|
|
46
|
+
}
|
|
47
|
+
finally {
|
|
48
|
+
setIsLoading(false);
|
|
49
|
+
setStatus("success");
|
|
50
|
+
}
|
|
51
|
+
};
|
|
30
52
|
// no need to load anything if the themeParam is present
|
|
31
53
|
if (themeParam) {
|
|
32
|
-
|
|
33
|
-
setTheme(preparedTheme);
|
|
34
|
-
setStatus("success");
|
|
35
|
-
clearCssProperties();
|
|
36
|
-
setCssProperties(preparedTheme, isDarkTheme(preparedTheme));
|
|
54
|
+
applyTheme(themeParam);
|
|
37
55
|
return;
|
|
38
56
|
}
|
|
39
57
|
const fetchData = async () => {
|
|
@@ -43,15 +61,23 @@ export function ThemeProvider({ children, theme: themeParam, backend: backendPar
|
|
|
43
61
|
}
|
|
44
62
|
setIsLoading(true);
|
|
45
63
|
setStatus("loading");
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
64
|
+
try {
|
|
65
|
+
const selectedTheme = await backend.workspace(workspace).styling().getTheme();
|
|
66
|
+
if (lastWorkspace.current === workspace) {
|
|
67
|
+
applyTheme(modifier(selectedTheme));
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
if (lastWorkspace.current === workspace) {
|
|
72
|
+
// covers both the backend fetch and the modifier transformation of the theme
|
|
73
|
+
console.error("Failed to load or process the theme from the backend.", error);
|
|
74
|
+
// reset both channels (context theme and global CSS) to the default theme so
|
|
75
|
+
// context consumers stay consistent with the cleared CSS variables
|
|
76
|
+
setTheme({});
|
|
77
|
+
clearCssProperties();
|
|
78
|
+
setIsLoading(false);
|
|
79
|
+
setStatus("success");
|
|
80
|
+
}
|
|
55
81
|
}
|
|
56
82
|
};
|
|
57
83
|
void fetchData();
|
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
import { type ITheme } from "@gooddata/sdk-model";
|
|
2
|
+
/**
|
|
3
|
+
* Drops palette colors that the `polished` color functions cannot parse.
|
|
4
|
+
*
|
|
5
|
+
* @remarks
|
|
6
|
+
* A single invalid color (e.g. a typo like "#1616D") would otherwise make theme application throw.
|
|
7
|
+
* An invalid color is treated exactly like an omitted one: it is removed so the standard default
|
|
8
|
+
* applies (missing shades are interpolated, missing family/complementary colors fall back to the
|
|
9
|
+
* default theme), while every other valid color is preserved. A color family whose base is invalid
|
|
10
|
+
* is dropped as a whole, since the family is meaningless without a base. The try/catch in
|
|
11
|
+
* ThemeProvider remains the hard backstop for any color path not covered here.
|
|
12
|
+
*/
|
|
13
|
+
export declare const sanitizePalette: (theme: ITheme) => ITheme;
|
|
2
14
|
export declare const prepareComplementaryPalette: (theme: ITheme) => ITheme;
|
|
3
15
|
export declare const prepareBaseColors: (theme: ITheme) => ITheme;
|
|
4
16
|
export declare const stripComplementaryPalette: (theme: ITheme) => ITheme;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prepareTheme.d.ts","sourceRoot":"","sources":["../../src/ThemeProvider/prepareTheme.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"prepareTheme.d.ts","sourceRoot":"","sources":["../../src/ThemeProvider/prepareTheme.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,MAAM,EAA2D,MAAM,qBAAqB,CAAC;AAmD3G;;;;;;;;;;GAUG;AACH,eAAO,MAAM,eAAe,2BA0B3B,CAAC;AAEF,eAAO,MAAM,2BAA2B,2BAYvC,CAAC;AAEF,eAAO,MAAM,iBAAiB,2BAe7B,CAAC;AAEF,eAAO,MAAM,yBAAyB,2BAgBrC,CAAC;AAEF,eAAO,MAAM,mBAAmB,2BAsB/B,CAAC;AAEF,eAAO,MAAM,YAAY,iEAUxB,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
// (C) 2021-
|
|
1
|
+
// (C) 2021-2026 GoodData Corporation
|
|
2
2
|
import { getContrast, shade } from "polished";
|
|
3
|
+
import { isValidThemeColor } from "../colorValidation.js";
|
|
3
4
|
import { getComplementaryPalette } from "../complementaryPalette.js";
|
|
4
5
|
/**
|
|
5
6
|
* Minimum contrast ratio n:1 recommended by W3C
|
|
@@ -7,6 +8,69 @@ import { getComplementaryPalette } from "../complementaryPalette.js";
|
|
|
7
8
|
*/
|
|
8
9
|
const MIN_CONTRAST_RATIO = 3;
|
|
9
10
|
const DEFAULT_BACKGROUND_COLOR = "#fff";
|
|
11
|
+
const DEFAULT_PRIMARY = "#14b2e2";
|
|
12
|
+
const DEFAULT_SUCCESS = "#00c18d";
|
|
13
|
+
const DEFAULT_ERROR = "#e54d42";
|
|
14
|
+
const DEFAULT_WARNING = "#f18600";
|
|
15
|
+
const sanitizeColorFamily = (family) => {
|
|
16
|
+
// without a usable base the whole family is dropped, so a default base is supplied downstream
|
|
17
|
+
if (!isValidThemeColor(family.base)) {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
const sanitized = { base: family.base };
|
|
21
|
+
["light", "dark", "contrast"].forEach((key) => {
|
|
22
|
+
const value = family[key];
|
|
23
|
+
if (value !== undefined && isValidThemeColor(value)) {
|
|
24
|
+
sanitized[key] = value;
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
return sanitized;
|
|
28
|
+
};
|
|
29
|
+
const sanitizeComplementaryPalette = (complementary) => {
|
|
30
|
+
const sanitized = {};
|
|
31
|
+
Object.keys(complementary).forEach((key) => {
|
|
32
|
+
const value = complementary[key];
|
|
33
|
+
if (value !== undefined && isValidThemeColor(value)) {
|
|
34
|
+
sanitized[key] = value;
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
return sanitized;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Drops palette colors that the `polished` color functions cannot parse.
|
|
41
|
+
*
|
|
42
|
+
* @remarks
|
|
43
|
+
* A single invalid color (e.g. a typo like "#1616D") would otherwise make theme application throw.
|
|
44
|
+
* An invalid color is treated exactly like an omitted one: it is removed so the standard default
|
|
45
|
+
* applies (missing shades are interpolated, missing family/complementary colors fall back to the
|
|
46
|
+
* default theme), while every other valid color is preserved. A color family whose base is invalid
|
|
47
|
+
* is dropped as a whole, since the family is meaningless without a base. The try/catch in
|
|
48
|
+
* ThemeProvider remains the hard backstop for any color path not covered here.
|
|
49
|
+
*/
|
|
50
|
+
export const sanitizePalette = (theme) => {
|
|
51
|
+
if (!theme?.palette) {
|
|
52
|
+
return theme;
|
|
53
|
+
}
|
|
54
|
+
const palette = { ...theme.palette };
|
|
55
|
+
const families = ["primary", "error", "warning", "success", "info"];
|
|
56
|
+
families.forEach((key) => {
|
|
57
|
+
const family = palette[key];
|
|
58
|
+
if (family === undefined) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
const sanitized = sanitizeColorFamily(family);
|
|
62
|
+
if (sanitized) {
|
|
63
|
+
palette[key] = sanitized;
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
delete palette[key];
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
if (palette.complementary) {
|
|
70
|
+
palette.complementary = sanitizeComplementaryPalette(palette.complementary);
|
|
71
|
+
}
|
|
72
|
+
return { ...theme, palette };
|
|
73
|
+
};
|
|
10
74
|
export const prepareComplementaryPalette = (theme) => {
|
|
11
75
|
if (theme?.palette?.complementary) {
|
|
12
76
|
return {
|
|
@@ -20,19 +84,15 @@ export const prepareComplementaryPalette = (theme) => {
|
|
|
20
84
|
return theme;
|
|
21
85
|
};
|
|
22
86
|
export const prepareBaseColors = (theme) => {
|
|
23
|
-
const defaultPrimary = "#14b2e2";
|
|
24
|
-
const defaultSuccess = "#00c18d";
|
|
25
|
-
const defaultError = "#e54d42";
|
|
26
|
-
const defaultWarning = "#f18600";
|
|
27
87
|
if (theme?.palette?.complementary) {
|
|
28
88
|
return {
|
|
29
89
|
...theme,
|
|
30
90
|
palette: {
|
|
31
91
|
...theme.palette,
|
|
32
|
-
...(theme.palette.primary ? {} : { primary: { base:
|
|
33
|
-
...(theme.palette.success ? {} : { success: { base:
|
|
34
|
-
...(theme.palette.error ? {} : { error: { base:
|
|
35
|
-
...(theme.palette.warning ? {} : { warning: { base:
|
|
92
|
+
...(theme.palette.primary ? {} : { primary: { base: DEFAULT_PRIMARY } }),
|
|
93
|
+
...(theme.palette.success ? {} : { success: { base: DEFAULT_SUCCESS } }),
|
|
94
|
+
...(theme.palette.error ? {} : { error: { base: DEFAULT_ERROR } }),
|
|
95
|
+
...(theme.palette.warning ? {} : { warning: { base: DEFAULT_WARNING } }),
|
|
36
96
|
},
|
|
37
97
|
};
|
|
38
98
|
}
|
|
@@ -74,10 +134,11 @@ export const preparePrimaryColor = (theme) => {
|
|
|
74
134
|
};
|
|
75
135
|
};
|
|
76
136
|
export const prepareTheme = (theme, enableComplementaryPalette = true) => {
|
|
137
|
+
const sanitizedTheme = sanitizePalette(theme);
|
|
77
138
|
if (!enableComplementaryPalette) {
|
|
78
|
-
const themeWithContrastPrimaryColor = preparePrimaryColor(
|
|
139
|
+
const themeWithContrastPrimaryColor = preparePrimaryColor(sanitizedTheme);
|
|
79
140
|
return stripComplementaryPalette(themeWithContrastPrimaryColor);
|
|
80
141
|
}
|
|
81
|
-
const themeWithComplementaryPalette = prepareComplementaryPalette(
|
|
142
|
+
const themeWithComplementaryPalette = prepareComplementaryPalette(sanitizedTheme);
|
|
82
143
|
return prepareBaseColors(themeWithComplementaryPalette);
|
|
83
144
|
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type ITheme } from "@gooddata/sdk-model";
|
|
2
|
+
/**
|
|
3
|
+
* Returns true if the provided value is a color string that the `polished` library can parse
|
|
4
|
+
* (hex, rgb(a), hsl(a) or a named color).
|
|
5
|
+
*
|
|
6
|
+
* @remarks
|
|
7
|
+
* `polished` is the single source of truth for what the theme application code can consume:
|
|
8
|
+
* the same parser (`parseToRgb`) backs `mix`, `getContrast`, `shade`, `transparentize` and
|
|
9
|
+
* `getLuminance`. Validating with it guarantees this check agrees exactly with the functions
|
|
10
|
+
* that would otherwise throw on an unparseable color.
|
|
11
|
+
*
|
|
12
|
+
* @internal
|
|
13
|
+
*/
|
|
14
|
+
export declare const isValidThemeColor: (color: unknown) => boolean;
|
|
15
|
+
/**
|
|
16
|
+
* A palette color that cannot be parsed, together with its dot-separated location in the palette
|
|
17
|
+
* (e.g. `complementary.c9` or `primary.base`).
|
|
18
|
+
*
|
|
19
|
+
* @internal
|
|
20
|
+
*/
|
|
21
|
+
export interface IInvalidThemeColor {
|
|
22
|
+
path: string;
|
|
23
|
+
value: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Walks the theme palette and returns the colors that cannot be parsed, each with its location.
|
|
27
|
+
*
|
|
28
|
+
* @remarks
|
|
29
|
+
* Only palette colors are inspected, as those are the values fed into the `polished` color
|
|
30
|
+
* functions during theme application. An empty array means every palette color is valid.
|
|
31
|
+
*
|
|
32
|
+
* @internal
|
|
33
|
+
*/
|
|
34
|
+
export declare const findInvalidThemeColors: (theme: ITheme | undefined) => IInvalidThemeColor[];
|
|
35
|
+
//# sourceMappingURL=colorValidation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"colorValidation.d.ts","sourceRoot":"","sources":["../src/colorValidation.ts"],"names":[],"mappings":"AAIA,OAAO,EACH,KAAK,MAAM,EAId,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iBAAiB,6BAW7B,CAAC;AAEF;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACjB;AA6BD;;;;;;;;GAQG;AACH,eAAO,MAAM,sBAAsB,qDAelC,CAAC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { parseToRgb } from "polished";
|
|
3
|
+
/**
|
|
4
|
+
* Returns true if the provided value is a color string that the `polished` library can parse
|
|
5
|
+
* (hex, rgb(a), hsl(a) or a named color).
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* `polished` is the single source of truth for what the theme application code can consume:
|
|
9
|
+
* the same parser (`parseToRgb`) backs `mix`, `getContrast`, `shade`, `transparentize` and
|
|
10
|
+
* `getLuminance`. Validating with it guarantees this check agrees exactly with the functions
|
|
11
|
+
* that would otherwise throw on an unparseable color.
|
|
12
|
+
*
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
export const isValidThemeColor = (color) => {
|
|
16
|
+
if (typeof color !== "string" || color.trim() === "") {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
try {
|
|
20
|
+
parseToRgb(color);
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
const colorFamilyKeys = ["base", "light", "dark", "contrast"];
|
|
28
|
+
const collectInvalidFamilyColors = (family, familyKey) => {
|
|
29
|
+
if (!family) {
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
return colorFamilyKeys
|
|
33
|
+
.filter((key) => family[key] !== undefined && !isValidThemeColor(family[key]))
|
|
34
|
+
.map((key) => ({ path: `${familyKey}.${key}`, value: family[key] }));
|
|
35
|
+
};
|
|
36
|
+
const collectInvalidComplementaryColors = (complementary) => {
|
|
37
|
+
if (!complementary) {
|
|
38
|
+
return [];
|
|
39
|
+
}
|
|
40
|
+
return Object.keys(complementary)
|
|
41
|
+
.filter((key) => complementary[key] !== undefined && !isValidThemeColor(complementary[key]))
|
|
42
|
+
.map((key) => ({ path: `complementary.${key}`, value: complementary[key] }));
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Walks the theme palette and returns the colors that cannot be parsed, each with its location.
|
|
46
|
+
*
|
|
47
|
+
* @remarks
|
|
48
|
+
* Only palette colors are inspected, as those are the values fed into the `polished` color
|
|
49
|
+
* functions during theme application. An empty array means every palette color is valid.
|
|
50
|
+
*
|
|
51
|
+
* @internal
|
|
52
|
+
*/
|
|
53
|
+
export const findInvalidThemeColors = (theme) => {
|
|
54
|
+
const palette = theme?.palette;
|
|
55
|
+
if (!palette) {
|
|
56
|
+
return [];
|
|
57
|
+
}
|
|
58
|
+
return [
|
|
59
|
+
...collectInvalidFamilyColors(palette.primary, "primary"),
|
|
60
|
+
...collectInvalidFamilyColors(palette.error, "error"),
|
|
61
|
+
...collectInvalidFamilyColors(palette.warning, "warning"),
|
|
62
|
+
...collectInvalidFamilyColors(palette.success, "success"),
|
|
63
|
+
...collectInvalidFamilyColors(palette.info, "info"),
|
|
64
|
+
...collectInvalidComplementaryColors(palette.complementary),
|
|
65
|
+
];
|
|
66
|
+
};
|
package/esm/index.d.ts
CHANGED
|
@@ -14,4 +14,5 @@ export { ScopedThemeProvider, type IScopedThemeProviderProps } from "./ThemeProv
|
|
|
14
14
|
export { ConditionalScopedThemeProvider } from "./ThemeProvider/ConditionalScopedThemeProvider.js";
|
|
15
15
|
export { isDarkTheme } from "./ThemeProvider/isDarkTheme.js";
|
|
16
16
|
export { withTheme, useTheme, useThemeIsLoading, useIsScopeThemed, useThemeStatus, useIsDarkTheme, ThemeContextProvider, type IThemeContextProviderProps, type ThemeStatus, } from "./ThemeProvider/Context.js";
|
|
17
|
+
export { isValidThemeColor, findInvalidThemeColors, type IInvalidThemeColor } from "./colorValidation.js";
|
|
17
18
|
//# sourceMappingURL=index.d.ts.map
|
package/esm/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AACH,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EACH,aAAa,EACb,KAAK,mBAAmB,EACxB,KAAK,aAAa,GACrB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,KAAK,yBAAyB,EAAE,MAAM,wCAAwC,CAAC;AAC7G,OAAO,EAAE,8BAA8B,EAAE,MAAM,mDAAmD,CAAC;AACnG,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EACH,SAAS,EACT,QAAQ,EACR,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,KAAK,0BAA0B,EAC/B,KAAK,WAAW,GACnB,MAAM,4BAA4B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AACH,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EACH,aAAa,EACb,KAAK,mBAAmB,EACxB,KAAK,aAAa,GACrB,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,mBAAmB,EAAE,KAAK,yBAAyB,EAAE,MAAM,wCAAwC,CAAC;AAC7G,OAAO,EAAE,8BAA8B,EAAE,MAAM,mDAAmD,CAAC;AACnG,OAAO,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAC7D,OAAO,EACH,SAAS,EACT,QAAQ,EACR,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,KAAK,0BAA0B,EAC/B,KAAK,WAAW,GACnB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,iBAAiB,EAAE,sBAAsB,EAAE,KAAK,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}
|
package/esm/index.js
CHANGED
|
@@ -16,3 +16,4 @@ export { ScopedThemeProvider } from "./ThemeProvider/ScopedThemeProvider.js";
|
|
|
16
16
|
export { ConditionalScopedThemeProvider } from "./ThemeProvider/ConditionalScopedThemeProvider.js";
|
|
17
17
|
export { isDarkTheme } from "./ThemeProvider/isDarkTheme.js";
|
|
18
18
|
export { withTheme, useTheme, useThemeIsLoading, useIsScopeThemed, useThemeStatus, useIsDarkTheme, ThemeContextProvider, } from "./ThemeProvider/Context.js";
|
|
19
|
+
export { isValidThemeColor, findInvalidThemeColors } from "./colorValidation.js";
|
|
@@ -37,6 +37,28 @@ export declare function ConditionalScopedThemeProvider({ children }: {
|
|
|
37
37
|
*/
|
|
38
38
|
export declare const defaultHeaderTheme: IThemeHeader;
|
|
39
39
|
|
|
40
|
+
/**
|
|
41
|
+
* Walks the theme palette and returns the colors that cannot be parsed, each with its location.
|
|
42
|
+
*
|
|
43
|
+
* @remarks
|
|
44
|
+
* Only palette colors are inspected, as those are the values fed into the `polished` color
|
|
45
|
+
* functions during theme application. An empty array means every palette color is valid.
|
|
46
|
+
*
|
|
47
|
+
* @internal
|
|
48
|
+
*/
|
|
49
|
+
export declare const findInvalidThemeColors: (theme: ITheme | undefined) => IInvalidThemeColor[];
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* A palette color that cannot be parsed, together with its dot-separated location in the palette
|
|
53
|
+
* (e.g. `complementary.c9` or `primary.base`).
|
|
54
|
+
*
|
|
55
|
+
* @internal
|
|
56
|
+
*/
|
|
57
|
+
export declare interface IInvalidThemeColor {
|
|
58
|
+
path: string;
|
|
59
|
+
value: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
40
62
|
/**
|
|
41
63
|
* @internal
|
|
42
64
|
*/
|
|
@@ -95,6 +117,20 @@ export declare interface IScopedThemeProviderProps {
|
|
|
95
117
|
*/
|
|
96
118
|
export declare const isDarkTheme: (theme: ITheme | undefined) => boolean;
|
|
97
119
|
|
|
120
|
+
/**
|
|
121
|
+
* Returns true if the provided value is a color string that the `polished` library can parse
|
|
122
|
+
* (hex, rgb(a), hsl(a) or a named color).
|
|
123
|
+
*
|
|
124
|
+
* @remarks
|
|
125
|
+
* `polished` is the single source of truth for what the theme application code can consume:
|
|
126
|
+
* the same parser (`parseToRgb`) backs `mix`, `getContrast`, `shade`, `transparentize` and
|
|
127
|
+
* `getLuminance`. Validating with it guarantees this check agrees exactly with the functions
|
|
128
|
+
* that would otherwise throw on an unparseable color.
|
|
129
|
+
*
|
|
130
|
+
* @internal
|
|
131
|
+
*/
|
|
132
|
+
export declare const isValidThemeColor: (color: unknown) => boolean;
|
|
133
|
+
|
|
98
134
|
/**
|
|
99
135
|
* @public
|
|
100
136
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"geo.d.ts","sourceRoot":"","sources":["../../../src/variablesSpec/internal/geo.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAE5D,eAAO,MAAM,yBAAyB,EAAE,wBAAwB,
|
|
1
|
+
{"version":3,"file":"geo.d.ts","sourceRoot":"","sources":["../../../src/variablesSpec/internal/geo.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAE5D,eAAO,MAAM,yBAAyB,EAAE,wBAAwB,EAwB/D,CAAC"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// (C) 2025 GoodData Corporation
|
|
1
|
+
// (C) 2025-2026 GoodData Corporation
|
|
2
2
|
export const internalGeoThemeVariables = [
|
|
3
3
|
{
|
|
4
4
|
type: "internal",
|
|
@@ -10,4 +10,17 @@ export const internalGeoThemeVariables = [
|
|
|
10
10
|
variableName: "--gd-geo-multi-layer-legend__toggle-duration",
|
|
11
11
|
defaultValue: "0.2s",
|
|
12
12
|
},
|
|
13
|
+
// Tooltip background, shared between the card and its clipped-content fade; referenced without a
|
|
14
|
+
// fallback, so no default value to validate.
|
|
15
|
+
{
|
|
16
|
+
type: "internal",
|
|
17
|
+
variableName: "--gd-viz-tooltip-bg",
|
|
18
|
+
defaultValue: null,
|
|
19
|
+
},
|
|
20
|
+
// Dynamic height cap fed from JS; unset (none) means no clamp.
|
|
21
|
+
{
|
|
22
|
+
type: "internal",
|
|
23
|
+
variableName: "--gd-viz-tooltip-max-height",
|
|
24
|
+
defaultValue: "none",
|
|
25
|
+
},
|
|
13
26
|
];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gooddata/sdk-ui-theme-provider",
|
|
3
|
-
"version": "11.42.0-alpha.
|
|
3
|
+
"version": "11.42.0-alpha.4",
|
|
4
4
|
"description": "GoodData SDK - Theme provider",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "GoodData Corporation",
|
|
@@ -32,10 +32,10 @@
|
|
|
32
32
|
"postcss-value-parser": "^4.2.0",
|
|
33
33
|
"ts-invariant": "0.10.3",
|
|
34
34
|
"tslib": "2.8.1",
|
|
35
|
-
"@gooddata/sdk-
|
|
36
|
-
"@gooddata/
|
|
37
|
-
"@gooddata/sdk-
|
|
38
|
-
"@gooddata/
|
|
35
|
+
"@gooddata/sdk-backend-spi": "11.42.0-alpha.4",
|
|
36
|
+
"@gooddata/sdk-model": "11.42.0-alpha.4",
|
|
37
|
+
"@gooddata/sdk-ui": "11.42.0-alpha.4",
|
|
38
|
+
"@gooddata/util": "11.42.0-alpha.4"
|
|
39
39
|
},
|
|
40
40
|
"devDependencies": {
|
|
41
41
|
"@microsoft/api-documenter": "^7.17.0",
|
|
@@ -73,10 +73,10 @@
|
|
|
73
73
|
"react-dom": "19.1.1",
|
|
74
74
|
"typescript": "5.9.3",
|
|
75
75
|
"vitest": "4.1.8",
|
|
76
|
-
"@gooddata/eslint-config": "11.42.0-alpha.
|
|
77
|
-
"@gooddata/oxlint-config": "11.42.0-alpha.
|
|
78
|
-
"@gooddata/reference-workspace": "11.42.0-alpha.
|
|
79
|
-
"@gooddata/sdk-backend-mockingbird": "11.42.0-alpha.
|
|
76
|
+
"@gooddata/eslint-config": "11.42.0-alpha.4",
|
|
77
|
+
"@gooddata/oxlint-config": "11.42.0-alpha.4",
|
|
78
|
+
"@gooddata/reference-workspace": "11.42.0-alpha.4",
|
|
79
|
+
"@gooddata/sdk-backend-mockingbird": "11.42.0-alpha.4"
|
|
80
80
|
},
|
|
81
81
|
"peerDependencies": {
|
|
82
82
|
"react": "^18.0.0 || ^19.0.0",
|