@activecollab/components 2.0.379 → 2.0.381
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/utils/themes.js +37 -7
- package/dist/cjs/utils/themes.js.map +1 -1
- package/dist/cjs/utils/themes.swatch.test.js +47 -0
- package/dist/cjs/utils/themes.swatch.test.js.map +1 -0
- package/dist/cjs/utils/themes.test.js +60 -0
- package/dist/cjs/utils/themes.test.js.map +1 -0
- package/dist/esm/utils/themes.d.ts +13 -0
- package/dist/esm/utils/themes.d.ts.map +1 -1
- package/dist/esm/utils/themes.js +30 -6
- package/dist/esm/utils/themes.js.map +1 -1
- package/dist/esm/utils/themes.swatch.test.d.ts +2 -0
- package/dist/esm/utils/themes.swatch.test.d.ts.map +1 -0
- package/dist/esm/utils/themes.swatch.test.js +39 -0
- package/dist/esm/utils/themes.swatch.test.js.map +1 -0
- package/dist/esm/utils/themes.test.d.ts +2 -0
- package/dist/esm/utils/themes.test.d.ts.map +1 -0
- package/dist/esm/utils/themes.test.js +58 -0
- package/dist/esm/utils/themes.test.js.map +1 -0
- package/dist/index.js +42 -6
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/package.json +1 -1
package/dist/cjs/utils/themes.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.isDarkTheme = exports.THEME_NAMES = exports.THEMES = exports.DARK_THEME_SELECTOR = exports.DARK_THEME_NAMES = exports.DARK_THEME_MATCH = void 0;
|
|
6
|
+
exports.resolveTheme = exports.isDarkTheme = exports.THEME_NAMES = exports.THEME_MODE_SYSTEM = exports.THEME_MODE_SINGLE = exports.THEMES = exports.LIGHT_THEME_NAMES = exports.DEFAULT_THEME = exports.DEFAULT_DARK_THEME = exports.DARK_THEME_SELECTOR = exports.DARK_THEME_NAMES = exports.DARK_THEME_MATCH = void 0;
|
|
7
7
|
// Single source of truth for theme identity. The theme name is the only class put on <html>;
|
|
8
8
|
// styling that targets "any dark theme" uses DARK_THEME_SELECTOR, which is derived from this list
|
|
9
9
|
// so a new theme never needs the selector updating by hand.
|
|
@@ -11,27 +11,33 @@ exports.isDarkTheme = exports.THEME_NAMES = exports.THEMES = exports.DARK_THEME_
|
|
|
11
11
|
var THEMES = exports.THEMES = [{
|
|
12
12
|
name: "indigo",
|
|
13
13
|
title: "Indigo",
|
|
14
|
-
dark: false
|
|
14
|
+
dark: false,
|
|
15
|
+
swatch: ["#5d2bff", "#5d2bff", "#f4f5f7"]
|
|
15
16
|
}, {
|
|
16
17
|
name: "cupcake",
|
|
17
18
|
title: "Cupcake",
|
|
18
|
-
dark: false
|
|
19
|
+
dark: false,
|
|
20
|
+
swatch: ["#fe6fa7", "#29bcdd", "#f4f5f7"]
|
|
19
21
|
}, {
|
|
20
22
|
name: "classic",
|
|
21
23
|
title: "Classic",
|
|
22
|
-
dark: false
|
|
24
|
+
dark: false,
|
|
25
|
+
swatch: ["#4182f2", "#4182f2", "#f4f5f7"]
|
|
23
26
|
}, {
|
|
24
27
|
name: "neon",
|
|
25
28
|
title: "Neon",
|
|
26
|
-
dark: true
|
|
29
|
+
dark: true,
|
|
30
|
+
swatch: ["#67ffc8", "#67ffc8", "#2c2e38"]
|
|
27
31
|
}, {
|
|
28
32
|
name: "dracula",
|
|
29
33
|
title: "Dracula",
|
|
30
|
-
dark: true
|
|
34
|
+
dark: true,
|
|
35
|
+
swatch: ["#ff79c6", "#bd93f9", "#282a36"]
|
|
31
36
|
}, {
|
|
32
37
|
name: "one-dark",
|
|
33
38
|
title: "One Dark",
|
|
34
|
-
dark: true
|
|
39
|
+
dark: true,
|
|
40
|
+
swatch: ["#c678dd", "#61afef", "#282c34"]
|
|
35
41
|
}];
|
|
36
42
|
var THEME_NAMES = exports.THEME_NAMES = THEMES.map(function (theme) {
|
|
37
43
|
return theme.name;
|
|
@@ -41,9 +47,33 @@ var DARK_THEME_NAMES = exports.DARK_THEME_NAMES = THEMES.filter(function (theme)
|
|
|
41
47
|
}).map(function (theme) {
|
|
42
48
|
return theme.name;
|
|
43
49
|
});
|
|
50
|
+
var LIGHT_THEME_NAMES = exports.LIGHT_THEME_NAMES = THEMES.filter(function (theme) {
|
|
51
|
+
return !theme.dark;
|
|
52
|
+
}).map(function (theme) {
|
|
53
|
+
return theme.name;
|
|
54
|
+
});
|
|
55
|
+
var DEFAULT_THEME = exports.DEFAULT_THEME = "indigo";
|
|
56
|
+
var DEFAULT_DARK_THEME = exports.DEFAULT_DARK_THEME = "neon";
|
|
57
|
+
var THEME_MODE_SINGLE = exports.THEME_MODE_SINGLE = "single";
|
|
58
|
+
var THEME_MODE_SYSTEM = exports.THEME_MODE_SYSTEM = "system";
|
|
44
59
|
var isDarkTheme = exports.isDarkTheme = function isDarkTheme(name) {
|
|
45
60
|
return Boolean(name) && DARK_THEME_NAMES.includes(name);
|
|
46
61
|
};
|
|
62
|
+
var knownTheme = function knownTheme(name, fallback) {
|
|
63
|
+
return name && THEME_NAMES.includes(name) ? name : fallback;
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
// Resolution is derived per render, never persisted — writing it back would destroy the user's pick.
|
|
67
|
+
var resolveTheme = exports.resolveTheme = function resolveTheme(_ref, prefersDark) {
|
|
68
|
+
var mode = _ref.mode,
|
|
69
|
+
theme = _ref.theme,
|
|
70
|
+
themeLight = _ref.themeLight,
|
|
71
|
+
themeDark = _ref.themeDark;
|
|
72
|
+
if (mode !== THEME_MODE_SYSTEM) {
|
|
73
|
+
return knownTheme(theme, DEFAULT_THEME);
|
|
74
|
+
}
|
|
75
|
+
return prefersDark ? knownTheme(themeDark, DEFAULT_DARK_THEME) : knownTheme(themeLight, DEFAULT_THEME);
|
|
76
|
+
};
|
|
47
77
|
|
|
48
78
|
// :is() and not :where() — :where() is zero-specificity and would silently lose to the light
|
|
49
79
|
// declarations it is meant to override.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"themes.js","names":["THEMES","exports","name","title","dark","THEME_NAMES","map","theme","DARK_THEME_NAMES","filter","isDarkTheme","Boolean","includes","DARK_THEME_MATCH","concat","join","DARK_THEME_SELECTOR"],"sources":["../../../src/utils/themes.ts"],"sourcesContent":["// Single source of truth for theme identity. The theme name is the only class put on <html>;\n// styling that targets \"any dark theme\" uses DARK_THEME_SELECTOR, which is derived from this list\n// so a new theme never needs the selector updating by hand.\nexport interface ThemeDescriptor {\n name: string;\n title: string;\n dark: boolean;\n}\n\nexport const THEMES: ThemeDescriptor[] = [\n {
|
|
1
|
+
{"version":3,"file":"themes.js","names":["THEMES","exports","name","title","dark","swatch","THEME_NAMES","map","theme","DARK_THEME_NAMES","filter","LIGHT_THEME_NAMES","DEFAULT_THEME","DEFAULT_DARK_THEME","THEME_MODE_SINGLE","THEME_MODE_SYSTEM","isDarkTheme","Boolean","includes","knownTheme","fallback","resolveTheme","_ref","prefersDark","mode","themeLight","themeDark","DARK_THEME_MATCH","concat","join","DARK_THEME_SELECTOR"],"sources":["../../../src/utils/themes.ts"],"sourcesContent":["// Single source of truth for theme identity. The theme name is the only class put on <html>;\n// styling that targets \"any dark theme\" uses DARK_THEME_SELECTOR, which is derived from this list\n// so a new theme never needs the selector updating by hand.\nexport interface ThemeDescriptor {\n name: string;\n title: string;\n dark: boolean;\n // [secondary, primary, page background] — accents lead so the swatch reads as the theme's colour.\n // Mirrors GlobalStyle; themes.swatch.test.ts fails if the two drift apart.\n swatch: [string, string, string];\n}\n\nexport const THEMES: ThemeDescriptor[] = [\n {\n name: \"indigo\",\n title: \"Indigo\",\n dark: false,\n swatch: [\"#5d2bff\", \"#5d2bff\", \"#f4f5f7\"],\n },\n {\n name: \"cupcake\",\n title: \"Cupcake\",\n dark: false,\n swatch: [\"#fe6fa7\", \"#29bcdd\", \"#f4f5f7\"],\n },\n {\n name: \"classic\",\n title: \"Classic\",\n dark: false,\n swatch: [\"#4182f2\", \"#4182f2\", \"#f4f5f7\"],\n },\n {\n name: \"neon\",\n title: \"Neon\",\n dark: true,\n swatch: [\"#67ffc8\", \"#67ffc8\", \"#2c2e38\"],\n },\n {\n name: \"dracula\",\n title: \"Dracula\",\n dark: true,\n swatch: [\"#ff79c6\", \"#bd93f9\", \"#282a36\"],\n },\n {\n name: \"one-dark\",\n title: \"One Dark\",\n dark: true,\n swatch: [\"#c678dd\", \"#61afef\", \"#282c34\"],\n },\n];\n\nexport const THEME_NAMES = THEMES.map((theme) => theme.name);\n\nexport const DARK_THEME_NAMES = THEMES.filter((theme) => theme.dark).map(\n (theme) => theme.name\n);\n\nexport const LIGHT_THEME_NAMES = THEMES.filter((theme) => !theme.dark).map(\n (theme) => theme.name\n);\n\nexport const DEFAULT_THEME = \"indigo\";\nexport const DEFAULT_DARK_THEME = \"neon\";\n\nexport const THEME_MODE_SINGLE = \"single\";\nexport const THEME_MODE_SYSTEM = \"system\";\n\nexport interface ThemeSelection {\n mode?: string | null;\n theme?: string | null;\n themeLight?: string | null;\n themeDark?: string | null;\n}\n\nexport const isDarkTheme = (name?: string | null): boolean =>\n Boolean(name) && DARK_THEME_NAMES.includes(name as string);\n\nconst knownTheme = (\n name: string | null | undefined,\n fallback: string\n): string => (name && THEME_NAMES.includes(name) ? name : fallback);\n\n// Resolution is derived per render, never persisted — writing it back would destroy the user's pick.\nexport const resolveTheme = (\n { mode, theme, themeLight, themeDark }: ThemeSelection,\n prefersDark: boolean\n): string => {\n if (mode !== THEME_MODE_SYSTEM) {\n return knownTheme(theme, DEFAULT_THEME);\n }\n\n return prefersDark\n ? knownTheme(themeDark, DEFAULT_DARK_THEME)\n : knownTheme(themeLight, DEFAULT_THEME);\n};\n\n// :is() and not :where() — :where() is zero-specificity and would silently lose to the light\n// declarations it is meant to override.\n\n// Compound onto an element that carries the theme class itself: `html${DARK_THEME_MATCH}`.\nexport const DARK_THEME_MATCH = `:is(${DARK_THEME_NAMES.map(\n (name) => `.${name}`\n).join(\", \")})`;\n\n// Stand-alone ancestor selector: `${DARK_THEME_SELECTOR} &`. The leading `*` adds no specificity\n// but stops stylis from reading a leading `:` as \"attach to the parent\" and gluing it onto `&`.\nexport const DARK_THEME_SELECTOR = `*${DARK_THEME_MATCH}`;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _fs = require("fs");
|
|
4
|
+
var _path = require("path");
|
|
5
|
+
var _themes = require("./themes");
|
|
6
|
+
var GLOBAL_STYLE = (0, _fs.readFileSync)((0, _path.join)(__dirname, "../components/GlobalStyle.ts"), "utf-8");
|
|
7
|
+
var SWATCH_VARS = ["color-secondary", "color-primary", "body-bg-main"];
|
|
8
|
+
var collectBlocks = function collectBlocks(selector) {
|
|
9
|
+
var re = new RegExp("".concat(selector, "\\s*\\{([^}]*)\\}"), "g");
|
|
10
|
+
var declarations = "";
|
|
11
|
+
var match;
|
|
12
|
+
while (match = re.exec(GLOBAL_STYLE)) declarations += "".concat(match[1], ";");
|
|
13
|
+
return declarations;
|
|
14
|
+
};
|
|
15
|
+
var readVar = function readVar(block, name) {
|
|
16
|
+
var _block$match;
|
|
17
|
+
return (_block$match = block.match(new RegExp("--".concat(name, "\\s*:\\s*([^;}]+)")))) === null || _block$match === void 0 ? void 0 : _block$match[1].trim();
|
|
18
|
+
};
|
|
19
|
+
var toHex = function toHex(value) {
|
|
20
|
+
var rgb = value.match(/rgb\(\s*(\d+)[,\s]+(\d+)[,\s]+(\d+)\s*\)/);
|
|
21
|
+
if (!rgb) return value.toLowerCase();
|
|
22
|
+
return "#".concat(rgb.slice(1).map(function (channel) {
|
|
23
|
+
return Number(channel).toString(16).padStart(2, "0");
|
|
24
|
+
}).join(""));
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// indigo has no class block of its own — it is the :root default every other theme overrides.
|
|
28
|
+
var declarationsFor = function declarationsFor(name) {
|
|
29
|
+
return (name === "indigo" ? "" : collectBlocks("\\.".concat(name))) + collectBlocks(":root");
|
|
30
|
+
};
|
|
31
|
+
describe("theme swatches", function () {
|
|
32
|
+
it("should match the colours GlobalStyle defines for each theme", function () {
|
|
33
|
+
var fromStylesheet = _themes.THEMES.map(function (_ref) {
|
|
34
|
+
var name = _ref.name;
|
|
35
|
+
var block = declarationsFor(name);
|
|
36
|
+
return [name, SWATCH_VARS.map(function (cssVar) {
|
|
37
|
+
return toHex(readVar(block, cssVar));
|
|
38
|
+
})];
|
|
39
|
+
});
|
|
40
|
+
expect(fromStylesheet).toEqual(_themes.THEMES.map(function (_ref2) {
|
|
41
|
+
var name = _ref2.name,
|
|
42
|
+
swatch = _ref2.swatch;
|
|
43
|
+
return [name, swatch];
|
|
44
|
+
}));
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
//# sourceMappingURL=themes.swatch.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"themes.swatch.test.js","names":["_fs","require","_path","_themes","GLOBAL_STYLE","readFileSync","join","__dirname","SWATCH_VARS","collectBlocks","selector","re","RegExp","concat","declarations","match","exec","readVar","block","name","_block$match","trim","toHex","value","rgb","toLowerCase","slice","map","channel","Number","toString","padStart","declarationsFor","describe","it","fromStylesheet","THEMES","_ref","cssVar","expect","toEqual","_ref2","swatch"],"sources":["../../../src/utils/themes.swatch.test.ts"],"sourcesContent":["import { readFileSync } from \"fs\";\nimport { join } from \"path\";\n\nimport { THEMES } from \"./themes\";\n\nconst GLOBAL_STYLE = readFileSync(\n join(__dirname, \"../components/GlobalStyle.ts\"),\n \"utf-8\"\n);\n\nconst SWATCH_VARS = [\"color-secondary\", \"color-primary\", \"body-bg-main\"];\n\nconst collectBlocks = (selector: string): string => {\n const re = new RegExp(`${selector}\\\\s*\\\\{([^}]*)\\\\}`, \"g\");\n let declarations = \"\";\n let match;\n while ((match = re.exec(GLOBAL_STYLE))) declarations += `${match[1]};`;\n return declarations;\n};\n\nconst readVar = (block: string, name: string): string | undefined =>\n block.match(new RegExp(`--${name}\\\\s*:\\\\s*([^;}]+)`))?.[1].trim();\n\nconst toHex = (value: string): string => {\n const rgb = value.match(/rgb\\(\\s*(\\d+)[,\\s]+(\\d+)[,\\s]+(\\d+)\\s*\\)/);\n if (!rgb) return value.toLowerCase();\n return `#${rgb\n .slice(1)\n .map((channel) => Number(channel).toString(16).padStart(2, \"0\"))\n .join(\"\")}`;\n};\n\n// indigo has no class block of its own — it is the :root default every other theme overrides.\nconst declarationsFor = (name: string): string =>\n (name === \"indigo\" ? \"\" : collectBlocks(`\\\\.${name}`)) +\n collectBlocks(\":root\");\n\ndescribe(\"theme swatches\", () => {\n it(\"should match the colours GlobalStyle defines for each theme\", () => {\n const fromStylesheet = THEMES.map(({ name }) => {\n const block = declarationsFor(name);\n return [\n name,\n SWATCH_VARS.map((cssVar) => toHex(readVar(block, cssVar) as string)),\n ];\n });\n\n expect(fromStylesheet).toEqual(\n THEMES.map(({ name, swatch }) => [name, swatch])\n );\n });\n});\n"],"mappings":";;AAAA,IAAAA,GAAA,GAAAC,OAAA;AACA,IAAAC,KAAA,GAAAD,OAAA;AAEA,IAAAE,OAAA,GAAAF,OAAA;AAEA,IAAMG,YAAY,GAAG,IAAAC,gBAAY,EAC/B,IAAAC,UAAI,EAACC,SAAS,EAAE,8BAA8B,CAAC,EAC/C,OACF,CAAC;AAED,IAAMC,WAAW,GAAG,CAAC,iBAAiB,EAAE,eAAe,EAAE,cAAc,CAAC;AAExE,IAAMC,aAAa,GAAG,SAAhBA,aAAaA,CAAIC,QAAgB,EAAa;EAClD,IAAMC,EAAE,GAAG,IAAIC,MAAM,IAAAC,MAAA,CAAIH,QAAQ,wBAAqB,GAAG,CAAC;EAC1D,IAAII,YAAY,GAAG,EAAE;EACrB,IAAIC,KAAK;EACT,OAAQA,KAAK,GAAGJ,EAAE,CAACK,IAAI,CAACZ,YAAY,CAAC,EAAGU,YAAY,OAAAD,MAAA,CAAOE,KAAK,CAAC,CAAC,CAAC,MAAG;EACtE,OAAOD,YAAY;AACrB,CAAC;AAED,IAAMG,OAAO,GAAG,SAAVA,OAAOA,CAAIC,KAAa,EAAEC,IAAY;EAAA,IAAAC,YAAA;EAAA,QAAAA,YAAA,GAC1CF,KAAK,CAACH,KAAK,CAAC,IAAIH,MAAM,MAAAC,MAAA,CAAMM,IAAI,sBAAmB,CAAC,CAAC,cAAAC,YAAA,uBAArDA,YAAA,CAAwD,CAAC,CAAC,CAACC,IAAI,CAAC,CAAC;AAAA;AAEnE,IAAMC,KAAK,GAAG,SAARA,KAAKA,CAAIC,KAAa,EAAa;EACvC,IAAMC,GAAG,GAAGD,KAAK,CAACR,KAAK,CAAC,0CAA0C,CAAC;EACnE,IAAI,CAACS,GAAG,EAAE,OAAOD,KAAK,CAACE,WAAW,CAAC,CAAC;EACpC,WAAAZ,MAAA,CAAWW,GAAG,CACXE,KAAK,CAAC,CAAC,CAAC,CACRC,GAAG,CAAC,UAACC,OAAO;IAAA,OAAKC,MAAM,CAACD,OAAO,CAAC,CAACE,QAAQ,CAAC,EAAE,CAAC,CAACC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC;EAAA,EAAC,CAC/DzB,IAAI,CAAC,EAAE,CAAC;AACb,CAAC;;AAED;AACA,IAAM0B,eAAe,GAAG,SAAlBA,eAAeA,CAAIb,IAAY;EAAA,OACnC,CAACA,IAAI,KAAK,QAAQ,GAAG,EAAE,GAAGV,aAAa,OAAAI,MAAA,CAAOM,IAAI,CAAE,CAAC,IACrDV,aAAa,CAAC,OAAO,CAAC;AAAA;AAExBwB,QAAQ,CAAC,gBAAgB,EAAE,YAAM;EAC/BC,EAAE,CAAC,6DAA6D,EAAE,YAAM;IACtE,IAAMC,cAAc,GAAGC,cAAM,CAACT,GAAG,CAAC,UAAAU,IAAA,EAAc;MAAA,IAAXlB,IAAI,GAAAkB,IAAA,CAAJlB,IAAI;MACvC,IAAMD,KAAK,GAAGc,eAAe,CAACb,IAAI,CAAC;MACnC,OAAO,CACLA,IAAI,EACJX,WAAW,CAACmB,GAAG,CAAC,UAACW,MAAM;QAAA,OAAKhB,KAAK,CAACL,OAAO,CAACC,KAAK,EAAEoB,MAAM,CAAW,CAAC;MAAA,EAAC,CACrE;IACH,CAAC,CAAC;IAEFC,MAAM,CAACJ,cAAc,CAAC,CAACK,OAAO,CAC5BJ,cAAM,CAACT,GAAG,CAAC,UAAAc,KAAA;MAAA,IAAGtB,IAAI,GAAAsB,KAAA,CAAJtB,IAAI;QAAEuB,MAAM,GAAAD,KAAA,CAANC,MAAM;MAAA,OAAO,CAACvB,IAAI,EAAEuB,MAAM,CAAC;IAAA,EACjD,CAAC;EACH,CAAC,CAAC;AACJ,CAAC,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
var _themes = require("./themes");
|
|
4
|
+
describe("resolveTheme", function () {
|
|
5
|
+
it("should split the theme list into light and dark without overlap", function () {
|
|
6
|
+
expect(_themes.LIGHT_THEME_NAMES).toEqual(["indigo", "cupcake", "classic"]);
|
|
7
|
+
expect(_themes.DARK_THEME_NAMES).toEqual(["neon", "dracula", "one-dark"]);
|
|
8
|
+
});
|
|
9
|
+
it("should ignore the system appearance in single mode", function () {
|
|
10
|
+
var selection = {
|
|
11
|
+
mode: _themes.THEME_MODE_SINGLE,
|
|
12
|
+
theme: "dracula",
|
|
13
|
+
themeLight: "cupcake",
|
|
14
|
+
themeDark: "one-dark"
|
|
15
|
+
};
|
|
16
|
+
expect((0, _themes.resolveTheme)(selection, false)).toBe("dracula");
|
|
17
|
+
expect((0, _themes.resolveTheme)(selection, true)).toBe("dracula");
|
|
18
|
+
});
|
|
19
|
+
it("should follow the system appearance in system mode", function () {
|
|
20
|
+
var selection = {
|
|
21
|
+
mode: _themes.THEME_MODE_SYSTEM,
|
|
22
|
+
theme: "dracula",
|
|
23
|
+
themeLight: "cupcake",
|
|
24
|
+
themeDark: "one-dark"
|
|
25
|
+
};
|
|
26
|
+
expect((0, _themes.resolveTheme)(selection, false)).toBe("cupcake");
|
|
27
|
+
expect((0, _themes.resolveTheme)(selection, true)).toBe("one-dark");
|
|
28
|
+
});
|
|
29
|
+
it("should fall back to the defaults when a slot is missing or unknown", function () {
|
|
30
|
+
expect((0, _themes.resolveTheme)({
|
|
31
|
+
mode: _themes.THEME_MODE_SYSTEM
|
|
32
|
+
}, false)).toBe(_themes.DEFAULT_THEME);
|
|
33
|
+
expect((0, _themes.resolveTheme)({
|
|
34
|
+
mode: _themes.THEME_MODE_SYSTEM
|
|
35
|
+
}, true)).toBe(_themes.DEFAULT_DARK_THEME);
|
|
36
|
+
expect((0, _themes.resolveTheme)({
|
|
37
|
+
mode: _themes.THEME_MODE_SYSTEM,
|
|
38
|
+
themeLight: "solarized",
|
|
39
|
+
themeDark: "solarized"
|
|
40
|
+
}, false)).toBe(_themes.DEFAULT_THEME);
|
|
41
|
+
expect((0, _themes.resolveTheme)({
|
|
42
|
+
mode: _themes.THEME_MODE_SYSTEM,
|
|
43
|
+
themeLight: "solarized",
|
|
44
|
+
themeDark: "solarized"
|
|
45
|
+
}, true)).toBe(_themes.DEFAULT_DARK_THEME);
|
|
46
|
+
expect((0, _themes.resolveTheme)({
|
|
47
|
+
theme: "solarized"
|
|
48
|
+
}, false)).toBe(_themes.DEFAULT_THEME);
|
|
49
|
+
});
|
|
50
|
+
it("should treat an absent or unrecognised mode as single", function () {
|
|
51
|
+
expect((0, _themes.resolveTheme)({
|
|
52
|
+
theme: "neon"
|
|
53
|
+
}, false)).toBe("neon");
|
|
54
|
+
expect((0, _themes.resolveTheme)({
|
|
55
|
+
mode: "auto",
|
|
56
|
+
theme: "neon"
|
|
57
|
+
}, true)).toBe("neon");
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
//# sourceMappingURL=themes.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"themes.test.js","names":["_themes","require","describe","it","expect","LIGHT_THEME_NAMES","toEqual","DARK_THEME_NAMES","selection","mode","THEME_MODE_SINGLE","theme","themeLight","themeDark","resolveTheme","toBe","THEME_MODE_SYSTEM","DEFAULT_THEME","DEFAULT_DARK_THEME"],"sources":["../../../src/utils/themes.test.ts"],"sourcesContent":["import {\n DEFAULT_DARK_THEME,\n DEFAULT_THEME,\n DARK_THEME_NAMES,\n LIGHT_THEME_NAMES,\n THEME_MODE_SINGLE,\n THEME_MODE_SYSTEM,\n resolveTheme,\n} from \"./themes\";\n\ndescribe(\"resolveTheme\", () => {\n it(\"should split the theme list into light and dark without overlap\", () => {\n expect(LIGHT_THEME_NAMES).toEqual([\"indigo\", \"cupcake\", \"classic\"]);\n expect(DARK_THEME_NAMES).toEqual([\"neon\", \"dracula\", \"one-dark\"]);\n });\n\n it(\"should ignore the system appearance in single mode\", () => {\n const selection = {\n mode: THEME_MODE_SINGLE,\n theme: \"dracula\",\n themeLight: \"cupcake\",\n themeDark: \"one-dark\",\n };\n\n expect(resolveTheme(selection, false)).toBe(\"dracula\");\n expect(resolveTheme(selection, true)).toBe(\"dracula\");\n });\n\n it(\"should follow the system appearance in system mode\", () => {\n const selection = {\n mode: THEME_MODE_SYSTEM,\n theme: \"dracula\",\n themeLight: \"cupcake\",\n themeDark: \"one-dark\",\n };\n\n expect(resolveTheme(selection, false)).toBe(\"cupcake\");\n expect(resolveTheme(selection, true)).toBe(\"one-dark\");\n });\n\n it(\"should fall back to the defaults when a slot is missing or unknown\", () => {\n expect(resolveTheme({ mode: THEME_MODE_SYSTEM }, false)).toBe(\n DEFAULT_THEME\n );\n expect(resolveTheme({ mode: THEME_MODE_SYSTEM }, true)).toBe(\n DEFAULT_DARK_THEME\n );\n expect(\n resolveTheme(\n {\n mode: THEME_MODE_SYSTEM,\n themeLight: \"solarized\",\n themeDark: \"solarized\",\n },\n false\n )\n ).toBe(DEFAULT_THEME);\n expect(\n resolveTheme(\n {\n mode: THEME_MODE_SYSTEM,\n themeLight: \"solarized\",\n themeDark: \"solarized\",\n },\n true\n )\n ).toBe(DEFAULT_DARK_THEME);\n expect(resolveTheme({ theme: \"solarized\" }, false)).toBe(DEFAULT_THEME);\n });\n\n it(\"should treat an absent or unrecognised mode as single\", () => {\n expect(resolveTheme({ theme: \"neon\" }, false)).toBe(\"neon\");\n expect(resolveTheme({ mode: \"auto\", theme: \"neon\" }, true)).toBe(\"neon\");\n });\n});\n"],"mappings":";;AAAA,IAAAA,OAAA,GAAAC,OAAA;AAUAC,QAAQ,CAAC,cAAc,EAAE,YAAM;EAC7BC,EAAE,CAAC,iEAAiE,EAAE,YAAM;IAC1EC,MAAM,CAACC,yBAAiB,CAAC,CAACC,OAAO,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;IACnEF,MAAM,CAACG,wBAAgB,CAAC,CAACD,OAAO,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;EACnE,CAAC,CAAC;EAEFH,EAAE,CAAC,oDAAoD,EAAE,YAAM;IAC7D,IAAMK,SAAS,GAAG;MAChBC,IAAI,EAAEC,yBAAiB;MACvBC,KAAK,EAAE,SAAS;MAChBC,UAAU,EAAE,SAAS;MACrBC,SAAS,EAAE;IACb,CAAC;IAEDT,MAAM,CAAC,IAAAU,oBAAY,EAACN,SAAS,EAAE,KAAK,CAAC,CAAC,CAACO,IAAI,CAAC,SAAS,CAAC;IACtDX,MAAM,CAAC,IAAAU,oBAAY,EAACN,SAAS,EAAE,IAAI,CAAC,CAAC,CAACO,IAAI,CAAC,SAAS,CAAC;EACvD,CAAC,CAAC;EAEFZ,EAAE,CAAC,oDAAoD,EAAE,YAAM;IAC7D,IAAMK,SAAS,GAAG;MAChBC,IAAI,EAAEO,yBAAiB;MACvBL,KAAK,EAAE,SAAS;MAChBC,UAAU,EAAE,SAAS;MACrBC,SAAS,EAAE;IACb,CAAC;IAEDT,MAAM,CAAC,IAAAU,oBAAY,EAACN,SAAS,EAAE,KAAK,CAAC,CAAC,CAACO,IAAI,CAAC,SAAS,CAAC;IACtDX,MAAM,CAAC,IAAAU,oBAAY,EAACN,SAAS,EAAE,IAAI,CAAC,CAAC,CAACO,IAAI,CAAC,UAAU,CAAC;EACxD,CAAC,CAAC;EAEFZ,EAAE,CAAC,oEAAoE,EAAE,YAAM;IAC7EC,MAAM,CAAC,IAAAU,oBAAY,EAAC;MAAEL,IAAI,EAAEO;IAAkB,CAAC,EAAE,KAAK,CAAC,CAAC,CAACD,IAAI,CAC3DE,qBACF,CAAC;IACDb,MAAM,CAAC,IAAAU,oBAAY,EAAC;MAAEL,IAAI,EAAEO;IAAkB,CAAC,EAAE,IAAI,CAAC,CAAC,CAACD,IAAI,CAC1DG,0BACF,CAAC;IACDd,MAAM,CACJ,IAAAU,oBAAY,EACV;MACEL,IAAI,EAAEO,yBAAiB;MACvBJ,UAAU,EAAE,WAAW;MACvBC,SAAS,EAAE;IACb,CAAC,EACD,KACF,CACF,CAAC,CAACE,IAAI,CAACE,qBAAa,CAAC;IACrBb,MAAM,CACJ,IAAAU,oBAAY,EACV;MACEL,IAAI,EAAEO,yBAAiB;MACvBJ,UAAU,EAAE,WAAW;MACvBC,SAAS,EAAE;IACb,CAAC,EACD,IACF,CACF,CAAC,CAACE,IAAI,CAACG,0BAAkB,CAAC;IAC1Bd,MAAM,CAAC,IAAAU,oBAAY,EAAC;MAAEH,KAAK,EAAE;IAAY,CAAC,EAAE,KAAK,CAAC,CAAC,CAACI,IAAI,CAACE,qBAAa,CAAC;EACzE,CAAC,CAAC;EAEFd,EAAE,CAAC,uDAAuD,EAAE,YAAM;IAChEC,MAAM,CAAC,IAAAU,oBAAY,EAAC;MAAEH,KAAK,EAAE;IAAO,CAAC,EAAE,KAAK,CAAC,CAAC,CAACI,IAAI,CAAC,MAAM,CAAC;IAC3DX,MAAM,CAAC,IAAAU,oBAAY,EAAC;MAAEL,IAAI,EAAE,MAAM;MAAEE,KAAK,EAAE;IAAO,CAAC,EAAE,IAAI,CAAC,CAAC,CAACI,IAAI,CAAC,MAAM,CAAC;EAC1E,CAAC,CAAC;AACJ,CAAC,CAAC","ignoreList":[]}
|
|
@@ -2,11 +2,24 @@ export interface ThemeDescriptor {
|
|
|
2
2
|
name: string;
|
|
3
3
|
title: string;
|
|
4
4
|
dark: boolean;
|
|
5
|
+
swatch: [string, string, string];
|
|
5
6
|
}
|
|
6
7
|
export declare const THEMES: ThemeDescriptor[];
|
|
7
8
|
export declare const THEME_NAMES: string[];
|
|
8
9
|
export declare const DARK_THEME_NAMES: string[];
|
|
10
|
+
export declare const LIGHT_THEME_NAMES: string[];
|
|
11
|
+
export declare const DEFAULT_THEME = "indigo";
|
|
12
|
+
export declare const DEFAULT_DARK_THEME = "neon";
|
|
13
|
+
export declare const THEME_MODE_SINGLE = "single";
|
|
14
|
+
export declare const THEME_MODE_SYSTEM = "system";
|
|
15
|
+
export interface ThemeSelection {
|
|
16
|
+
mode?: string | null;
|
|
17
|
+
theme?: string | null;
|
|
18
|
+
themeLight?: string | null;
|
|
19
|
+
themeDark?: string | null;
|
|
20
|
+
}
|
|
9
21
|
export declare const isDarkTheme: (name?: string | null) => boolean;
|
|
22
|
+
export declare const resolveTheme: ({ mode, theme, themeLight, themeDark }: ThemeSelection, prefersDark: boolean) => string;
|
|
10
23
|
export declare const DARK_THEME_MATCH: string;
|
|
11
24
|
export declare const DARK_THEME_SELECTOR: string;
|
|
12
25
|
//# sourceMappingURL=themes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"themes.d.ts","sourceRoot":"","sources":["../../../src/utils/themes.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"themes.d.ts","sourceRoot":"","sources":["../../../src/utils/themes.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IAGd,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,eAAO,MAAM,MAAM,EAAE,eAAe,EAqCnC,CAAC;AAEF,eAAO,MAAM,WAAW,UAAoC,CAAC;AAE7D,eAAO,MAAM,gBAAgB,UAE5B,CAAC;AAEF,eAAO,MAAM,iBAAiB,UAE7B,CAAC;AAEF,eAAO,MAAM,aAAa,WAAW,CAAC;AACtC,eAAO,MAAM,kBAAkB,SAAS,CAAC;AAEzC,eAAO,MAAM,iBAAiB,WAAW,CAAC;AAC1C,eAAO,MAAM,iBAAiB,WAAW,CAAC;AAE1C,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAED,eAAO,MAAM,WAAW,GAAI,OAAO,MAAM,GAAG,IAAI,KAAG,OACS,CAAC;AAQ7D,eAAO,MAAM,YAAY,GACvB,wCAAwC,cAAc,EACtD,aAAa,OAAO,KACnB,MAQF,CAAC;AAMF,eAAO,MAAM,gBAAgB,QAEd,CAAC;AAIhB,eAAO,MAAM,mBAAmB,QAAyB,CAAC"}
|
package/dist/esm/utils/themes.js
CHANGED
|
@@ -5,31 +5,55 @@
|
|
|
5
5
|
export const THEMES = [{
|
|
6
6
|
name: "indigo",
|
|
7
7
|
title: "Indigo",
|
|
8
|
-
dark: false
|
|
8
|
+
dark: false,
|
|
9
|
+
swatch: ["#5d2bff", "#5d2bff", "#f4f5f7"]
|
|
9
10
|
}, {
|
|
10
11
|
name: "cupcake",
|
|
11
12
|
title: "Cupcake",
|
|
12
|
-
dark: false
|
|
13
|
+
dark: false,
|
|
14
|
+
swatch: ["#fe6fa7", "#29bcdd", "#f4f5f7"]
|
|
13
15
|
}, {
|
|
14
16
|
name: "classic",
|
|
15
17
|
title: "Classic",
|
|
16
|
-
dark: false
|
|
18
|
+
dark: false,
|
|
19
|
+
swatch: ["#4182f2", "#4182f2", "#f4f5f7"]
|
|
17
20
|
}, {
|
|
18
21
|
name: "neon",
|
|
19
22
|
title: "Neon",
|
|
20
|
-
dark: true
|
|
23
|
+
dark: true,
|
|
24
|
+
swatch: ["#67ffc8", "#67ffc8", "#2c2e38"]
|
|
21
25
|
}, {
|
|
22
26
|
name: "dracula",
|
|
23
27
|
title: "Dracula",
|
|
24
|
-
dark: true
|
|
28
|
+
dark: true,
|
|
29
|
+
swatch: ["#ff79c6", "#bd93f9", "#282a36"]
|
|
25
30
|
}, {
|
|
26
31
|
name: "one-dark",
|
|
27
32
|
title: "One Dark",
|
|
28
|
-
dark: true
|
|
33
|
+
dark: true,
|
|
34
|
+
swatch: ["#c678dd", "#61afef", "#282c34"]
|
|
29
35
|
}];
|
|
30
36
|
export const THEME_NAMES = THEMES.map(theme => theme.name);
|
|
31
37
|
export const DARK_THEME_NAMES = THEMES.filter(theme => theme.dark).map(theme => theme.name);
|
|
38
|
+
export const LIGHT_THEME_NAMES = THEMES.filter(theme => !theme.dark).map(theme => theme.name);
|
|
39
|
+
export const DEFAULT_THEME = "indigo";
|
|
40
|
+
export const DEFAULT_DARK_THEME = "neon";
|
|
41
|
+
export const THEME_MODE_SINGLE = "single";
|
|
42
|
+
export const THEME_MODE_SYSTEM = "system";
|
|
32
43
|
export const isDarkTheme = name => Boolean(name) && DARK_THEME_NAMES.includes(name);
|
|
44
|
+
const knownTheme = (name, fallback) => name && THEME_NAMES.includes(name) ? name : fallback;
|
|
45
|
+
|
|
46
|
+
// Resolution is derived per render, never persisted — writing it back would destroy the user's pick.
|
|
47
|
+
export const resolveTheme = (_ref, prefersDark) => {
|
|
48
|
+
let mode = _ref.mode,
|
|
49
|
+
theme = _ref.theme,
|
|
50
|
+
themeLight = _ref.themeLight,
|
|
51
|
+
themeDark = _ref.themeDark;
|
|
52
|
+
if (mode !== THEME_MODE_SYSTEM) {
|
|
53
|
+
return knownTheme(theme, DEFAULT_THEME);
|
|
54
|
+
}
|
|
55
|
+
return prefersDark ? knownTheme(themeDark, DEFAULT_DARK_THEME) : knownTheme(themeLight, DEFAULT_THEME);
|
|
56
|
+
};
|
|
33
57
|
|
|
34
58
|
// :is() and not :where() — :where() is zero-specificity and would silently lose to the light
|
|
35
59
|
// declarations it is meant to override.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"themes.js","names":["THEMES","name","title","dark","THEME_NAMES","map","theme","DARK_THEME_NAMES","filter","isDarkTheme","Boolean","includes","DARK_THEME_MATCH","join","DARK_THEME_SELECTOR"],"sources":["../../../src/utils/themes.ts"],"sourcesContent":["// Single source of truth for theme identity. The theme name is the only class put on <html>;\n// styling that targets \"any dark theme\" uses DARK_THEME_SELECTOR, which is derived from this list\n// so a new theme never needs the selector updating by hand.\nexport interface ThemeDescriptor {\n name: string;\n title: string;\n dark: boolean;\n}\n\nexport const THEMES: ThemeDescriptor[] = [\n {
|
|
1
|
+
{"version":3,"file":"themes.js","names":["THEMES","name","title","dark","swatch","THEME_NAMES","map","theme","DARK_THEME_NAMES","filter","LIGHT_THEME_NAMES","DEFAULT_THEME","DEFAULT_DARK_THEME","THEME_MODE_SINGLE","THEME_MODE_SYSTEM","isDarkTheme","Boolean","includes","knownTheme","fallback","resolveTheme","_ref","prefersDark","mode","themeLight","themeDark","DARK_THEME_MATCH","join","DARK_THEME_SELECTOR"],"sources":["../../../src/utils/themes.ts"],"sourcesContent":["// Single source of truth for theme identity. The theme name is the only class put on <html>;\n// styling that targets \"any dark theme\" uses DARK_THEME_SELECTOR, which is derived from this list\n// so a new theme never needs the selector updating by hand.\nexport interface ThemeDescriptor {\n name: string;\n title: string;\n dark: boolean;\n // [secondary, primary, page background] — accents lead so the swatch reads as the theme's colour.\n // Mirrors GlobalStyle; themes.swatch.test.ts fails if the two drift apart.\n swatch: [string, string, string];\n}\n\nexport const THEMES: ThemeDescriptor[] = [\n {\n name: \"indigo\",\n title: \"Indigo\",\n dark: false,\n swatch: [\"#5d2bff\", \"#5d2bff\", \"#f4f5f7\"],\n },\n {\n name: \"cupcake\",\n title: \"Cupcake\",\n dark: false,\n swatch: [\"#fe6fa7\", \"#29bcdd\", \"#f4f5f7\"],\n },\n {\n name: \"classic\",\n title: \"Classic\",\n dark: false,\n swatch: [\"#4182f2\", \"#4182f2\", \"#f4f5f7\"],\n },\n {\n name: \"neon\",\n title: \"Neon\",\n dark: true,\n swatch: [\"#67ffc8\", \"#67ffc8\", \"#2c2e38\"],\n },\n {\n name: \"dracula\",\n title: \"Dracula\",\n dark: true,\n swatch: [\"#ff79c6\", \"#bd93f9\", \"#282a36\"],\n },\n {\n name: \"one-dark\",\n title: \"One Dark\",\n dark: true,\n swatch: [\"#c678dd\", \"#61afef\", \"#282c34\"],\n },\n];\n\nexport const THEME_NAMES = THEMES.map((theme) => theme.name);\n\nexport const DARK_THEME_NAMES = THEMES.filter((theme) => theme.dark).map(\n (theme) => theme.name\n);\n\nexport const LIGHT_THEME_NAMES = THEMES.filter((theme) => !theme.dark).map(\n (theme) => theme.name\n);\n\nexport const DEFAULT_THEME = \"indigo\";\nexport const DEFAULT_DARK_THEME = \"neon\";\n\nexport const THEME_MODE_SINGLE = \"single\";\nexport const THEME_MODE_SYSTEM = \"system\";\n\nexport interface ThemeSelection {\n mode?: string | null;\n theme?: string | null;\n themeLight?: string | null;\n themeDark?: string | null;\n}\n\nexport const isDarkTheme = (name?: string | null): boolean =>\n Boolean(name) && DARK_THEME_NAMES.includes(name as string);\n\nconst knownTheme = (\n name: string | null | undefined,\n fallback: string\n): string => (name && THEME_NAMES.includes(name) ? name : fallback);\n\n// Resolution is derived per render, never persisted — writing it back would destroy the user's pick.\nexport const resolveTheme = (\n { mode, theme, themeLight, themeDark }: ThemeSelection,\n prefersDark: boolean\n): string => {\n if (mode !== THEME_MODE_SYSTEM) {\n return knownTheme(theme, DEFAULT_THEME);\n }\n\n return prefersDark\n ? knownTheme(themeDark, DEFAULT_DARK_THEME)\n : knownTheme(themeLight, DEFAULT_THEME);\n};\n\n// :is() and not :where() — :where() is zero-specificity and would silently lose to the light\n// declarations it is meant to override.\n\n// Compound onto an element that carries the theme class itself: `html${DARK_THEME_MATCH}`.\nexport const DARK_THEME_MATCH = `:is(${DARK_THEME_NAMES.map(\n (name) => `.${name}`\n).join(\", \")})`;\n\n// Stand-alone ancestor selector: `${DARK_THEME_SELECTOR} &`. The leading `*` adds no specificity\n// but stops stylis from reading a leading `:` as \"attach to the parent\" and gluing it onto `&`.\nexport const DARK_THEME_SELECTOR = `*${DARK_THEME_MATCH}`;\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"themes.swatch.test.d.ts","sourceRoot":"","sources":["../../../src/utils/themes.swatch.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { readFileSync } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
import { THEMES } from "./themes";
|
|
4
|
+
const GLOBAL_STYLE = readFileSync(join(__dirname, "../components/GlobalStyle.ts"), "utf-8");
|
|
5
|
+
const SWATCH_VARS = ["color-secondary", "color-primary", "body-bg-main"];
|
|
6
|
+
const collectBlocks = selector => {
|
|
7
|
+
const re = new RegExp(selector + "\\s*\\{([^}]*)\\}", "g");
|
|
8
|
+
let declarations = "";
|
|
9
|
+
let match;
|
|
10
|
+
while (match = re.exec(GLOBAL_STYLE)) declarations += match[1] + ";";
|
|
11
|
+
return declarations;
|
|
12
|
+
};
|
|
13
|
+
const readVar = (block, name) => {
|
|
14
|
+
var _block$match;
|
|
15
|
+
return (_block$match = block.match(new RegExp("--" + name + "\\s*:\\s*([^;}]+)"))) == null ? void 0 : _block$match[1].trim();
|
|
16
|
+
};
|
|
17
|
+
const toHex = value => {
|
|
18
|
+
const rgb = value.match(/rgb\(\s*(\d+)[,\s]+(\d+)[,\s]+(\d+)\s*\)/);
|
|
19
|
+
if (!rgb) return value.toLowerCase();
|
|
20
|
+
return "#" + rgb.slice(1).map(channel => Number(channel).toString(16).padStart(2, "0")).join("");
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
// indigo has no class block of its own — it is the :root default every other theme overrides.
|
|
24
|
+
const declarationsFor = name => (name === "indigo" ? "" : collectBlocks("\\." + name)) + collectBlocks(":root");
|
|
25
|
+
describe("theme swatches", () => {
|
|
26
|
+
it("should match the colours GlobalStyle defines for each theme", () => {
|
|
27
|
+
const fromStylesheet = THEMES.map(_ref => {
|
|
28
|
+
let name = _ref.name;
|
|
29
|
+
const block = declarationsFor(name);
|
|
30
|
+
return [name, SWATCH_VARS.map(cssVar => toHex(readVar(block, cssVar)))];
|
|
31
|
+
});
|
|
32
|
+
expect(fromStylesheet).toEqual(THEMES.map(_ref2 => {
|
|
33
|
+
let name = _ref2.name,
|
|
34
|
+
swatch = _ref2.swatch;
|
|
35
|
+
return [name, swatch];
|
|
36
|
+
}));
|
|
37
|
+
});
|
|
38
|
+
});
|
|
39
|
+
//# sourceMappingURL=themes.swatch.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"themes.swatch.test.js","names":["readFileSync","join","THEMES","GLOBAL_STYLE","__dirname","SWATCH_VARS","collectBlocks","selector","re","RegExp","declarations","match","exec","readVar","block","name","_block$match","trim","toHex","value","rgb","toLowerCase","slice","map","channel","Number","toString","padStart","declarationsFor","describe","it","fromStylesheet","_ref","cssVar","expect","toEqual","_ref2","swatch"],"sources":["../../../src/utils/themes.swatch.test.ts"],"sourcesContent":["import { readFileSync } from \"fs\";\nimport { join } from \"path\";\n\nimport { THEMES } from \"./themes\";\n\nconst GLOBAL_STYLE = readFileSync(\n join(__dirname, \"../components/GlobalStyle.ts\"),\n \"utf-8\"\n);\n\nconst SWATCH_VARS = [\"color-secondary\", \"color-primary\", \"body-bg-main\"];\n\nconst collectBlocks = (selector: string): string => {\n const re = new RegExp(`${selector}\\\\s*\\\\{([^}]*)\\\\}`, \"g\");\n let declarations = \"\";\n let match;\n while ((match = re.exec(GLOBAL_STYLE))) declarations += `${match[1]};`;\n return declarations;\n};\n\nconst readVar = (block: string, name: string): string | undefined =>\n block.match(new RegExp(`--${name}\\\\s*:\\\\s*([^;}]+)`))?.[1].trim();\n\nconst toHex = (value: string): string => {\n const rgb = value.match(/rgb\\(\\s*(\\d+)[,\\s]+(\\d+)[,\\s]+(\\d+)\\s*\\)/);\n if (!rgb) return value.toLowerCase();\n return `#${rgb\n .slice(1)\n .map((channel) => Number(channel).toString(16).padStart(2, \"0\"))\n .join(\"\")}`;\n};\n\n// indigo has no class block of its own — it is the :root default every other theme overrides.\nconst declarationsFor = (name: string): string =>\n (name === \"indigo\" ? \"\" : collectBlocks(`\\\\.${name}`)) +\n collectBlocks(\":root\");\n\ndescribe(\"theme swatches\", () => {\n it(\"should match the colours GlobalStyle defines for each theme\", () => {\n const fromStylesheet = THEMES.map(({ name }) => {\n const block = declarationsFor(name);\n return [\n name,\n SWATCH_VARS.map((cssVar) => toHex(readVar(block, cssVar) as string)),\n ];\n });\n\n expect(fromStylesheet).toEqual(\n THEMES.map(({ name, swatch }) => [name, swatch])\n );\n });\n});\n"],"mappings":"AAAA,SAASA,YAAY,QAAQ,IAAI;AACjC,SAASC,IAAI,QAAQ,MAAM;AAE3B,SAASC,MAAM,QAAQ,UAAU;AAEjC,MAAMC,YAAY,GAAGH,YAAY,CAC/BC,IAAI,CAACG,SAAS,EAAE,8BAA8B,CAAC,EAC/C,OACF,CAAC;AAED,MAAMC,WAAW,GAAG,CAAC,iBAAiB,EAAE,eAAe,EAAE,cAAc,CAAC;AAExE,MAAMC,aAAa,GAAIC,QAAgB,IAAa;EAClD,MAAMC,EAAE,GAAG,IAAIC,MAAM,CAAIF,QAAQ,wBAAqB,GAAG,CAAC;EAC1D,IAAIG,YAAY,GAAG,EAAE;EACrB,IAAIC,KAAK;EACT,OAAQA,KAAK,GAAGH,EAAE,CAACI,IAAI,CAACT,YAAY,CAAC,EAAGO,YAAY,IAAOC,KAAK,CAAC,CAAC,CAAC,MAAG;EACtE,OAAOD,YAAY;AACrB,CAAC;AAED,MAAMG,OAAO,GAAGA,CAACC,KAAa,EAAEC,IAAY;EAAA,IAAAC,YAAA;EAAA,QAAAA,YAAA,GAC1CF,KAAK,CAACH,KAAK,CAAC,IAAIF,MAAM,QAAMM,IAAI,sBAAmB,CAAC,CAAC,qBAArDC,YAAA,CAAwD,CAAC,CAAC,CAACC,IAAI,CAAC,CAAC;AAAA;AAEnE,MAAMC,KAAK,GAAIC,KAAa,IAAa;EACvC,MAAMC,GAAG,GAAGD,KAAK,CAACR,KAAK,CAAC,0CAA0C,CAAC;EACnE,IAAI,CAACS,GAAG,EAAE,OAAOD,KAAK,CAACE,WAAW,CAAC,CAAC;EACpC,aAAWD,GAAG,CACXE,KAAK,CAAC,CAAC,CAAC,CACRC,GAAG,CAAEC,OAAO,IAAKC,MAAM,CAACD,OAAO,CAAC,CAACE,QAAQ,CAAC,EAAE,CAAC,CAACC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAC/D1B,IAAI,CAAC,EAAE,CAAC;AACb,CAAC;;AAED;AACA,MAAM2B,eAAe,GAAIb,IAAY,IACnC,CAACA,IAAI,KAAK,QAAQ,GAAG,EAAE,GAAGT,aAAa,SAAOS,IAAM,CAAC,IACrDT,aAAa,CAAC,OAAO,CAAC;AAExBuB,QAAQ,CAAC,gBAAgB,EAAE,MAAM;EAC/BC,EAAE,CAAC,6DAA6D,EAAE,MAAM;IACtE,MAAMC,cAAc,GAAG7B,MAAM,CAACqB,GAAG,CAACS,IAAA,IAAc;MAAA,IAAXjB,IAAI,GAAAiB,IAAA,CAAJjB,IAAI;MACvC,MAAMD,KAAK,GAAGc,eAAe,CAACb,IAAI,CAAC;MACnC,OAAO,CACLA,IAAI,EACJV,WAAW,CAACkB,GAAG,CAAEU,MAAM,IAAKf,KAAK,CAACL,OAAO,CAACC,KAAK,EAAEmB,MAAM,CAAW,CAAC,CAAC,CACrE;IACH,CAAC,CAAC;IAEFC,MAAM,CAACH,cAAc,CAAC,CAACI,OAAO,CAC5BjC,MAAM,CAACqB,GAAG,CAACa,KAAA;MAAA,IAAGrB,IAAI,GAAAqB,KAAA,CAAJrB,IAAI;QAAEsB,MAAM,GAAAD,KAAA,CAANC,MAAM;MAAA,OAAO,CAACtB,IAAI,EAAEsB,MAAM,CAAC;IAAA,EACjD,CAAC;EACH,CAAC,CAAC;AACJ,CAAC,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"themes.test.d.ts","sourceRoot":"","sources":["../../../src/utils/themes.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { DEFAULT_DARK_THEME, DEFAULT_THEME, DARK_THEME_NAMES, LIGHT_THEME_NAMES, THEME_MODE_SINGLE, THEME_MODE_SYSTEM, resolveTheme } from "./themes";
|
|
2
|
+
describe("resolveTheme", () => {
|
|
3
|
+
it("should split the theme list into light and dark without overlap", () => {
|
|
4
|
+
expect(LIGHT_THEME_NAMES).toEqual(["indigo", "cupcake", "classic"]);
|
|
5
|
+
expect(DARK_THEME_NAMES).toEqual(["neon", "dracula", "one-dark"]);
|
|
6
|
+
});
|
|
7
|
+
it("should ignore the system appearance in single mode", () => {
|
|
8
|
+
const selection = {
|
|
9
|
+
mode: THEME_MODE_SINGLE,
|
|
10
|
+
theme: "dracula",
|
|
11
|
+
themeLight: "cupcake",
|
|
12
|
+
themeDark: "one-dark"
|
|
13
|
+
};
|
|
14
|
+
expect(resolveTheme(selection, false)).toBe("dracula");
|
|
15
|
+
expect(resolveTheme(selection, true)).toBe("dracula");
|
|
16
|
+
});
|
|
17
|
+
it("should follow the system appearance in system mode", () => {
|
|
18
|
+
const selection = {
|
|
19
|
+
mode: THEME_MODE_SYSTEM,
|
|
20
|
+
theme: "dracula",
|
|
21
|
+
themeLight: "cupcake",
|
|
22
|
+
themeDark: "one-dark"
|
|
23
|
+
};
|
|
24
|
+
expect(resolveTheme(selection, false)).toBe("cupcake");
|
|
25
|
+
expect(resolveTheme(selection, true)).toBe("one-dark");
|
|
26
|
+
});
|
|
27
|
+
it("should fall back to the defaults when a slot is missing or unknown", () => {
|
|
28
|
+
expect(resolveTheme({
|
|
29
|
+
mode: THEME_MODE_SYSTEM
|
|
30
|
+
}, false)).toBe(DEFAULT_THEME);
|
|
31
|
+
expect(resolveTheme({
|
|
32
|
+
mode: THEME_MODE_SYSTEM
|
|
33
|
+
}, true)).toBe(DEFAULT_DARK_THEME);
|
|
34
|
+
expect(resolveTheme({
|
|
35
|
+
mode: THEME_MODE_SYSTEM,
|
|
36
|
+
themeLight: "solarized",
|
|
37
|
+
themeDark: "solarized"
|
|
38
|
+
}, false)).toBe(DEFAULT_THEME);
|
|
39
|
+
expect(resolveTheme({
|
|
40
|
+
mode: THEME_MODE_SYSTEM,
|
|
41
|
+
themeLight: "solarized",
|
|
42
|
+
themeDark: "solarized"
|
|
43
|
+
}, true)).toBe(DEFAULT_DARK_THEME);
|
|
44
|
+
expect(resolveTheme({
|
|
45
|
+
theme: "solarized"
|
|
46
|
+
}, false)).toBe(DEFAULT_THEME);
|
|
47
|
+
});
|
|
48
|
+
it("should treat an absent or unrecognised mode as single", () => {
|
|
49
|
+
expect(resolveTheme({
|
|
50
|
+
theme: "neon"
|
|
51
|
+
}, false)).toBe("neon");
|
|
52
|
+
expect(resolveTheme({
|
|
53
|
+
mode: "auto",
|
|
54
|
+
theme: "neon"
|
|
55
|
+
}, true)).toBe("neon");
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
//# sourceMappingURL=themes.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"themes.test.js","names":["DEFAULT_DARK_THEME","DEFAULT_THEME","DARK_THEME_NAMES","LIGHT_THEME_NAMES","THEME_MODE_SINGLE","THEME_MODE_SYSTEM","resolveTheme","describe","it","expect","toEqual","selection","mode","theme","themeLight","themeDark","toBe"],"sources":["../../../src/utils/themes.test.ts"],"sourcesContent":["import {\n DEFAULT_DARK_THEME,\n DEFAULT_THEME,\n DARK_THEME_NAMES,\n LIGHT_THEME_NAMES,\n THEME_MODE_SINGLE,\n THEME_MODE_SYSTEM,\n resolveTheme,\n} from \"./themes\";\n\ndescribe(\"resolveTheme\", () => {\n it(\"should split the theme list into light and dark without overlap\", () => {\n expect(LIGHT_THEME_NAMES).toEqual([\"indigo\", \"cupcake\", \"classic\"]);\n expect(DARK_THEME_NAMES).toEqual([\"neon\", \"dracula\", \"one-dark\"]);\n });\n\n it(\"should ignore the system appearance in single mode\", () => {\n const selection = {\n mode: THEME_MODE_SINGLE,\n theme: \"dracula\",\n themeLight: \"cupcake\",\n themeDark: \"one-dark\",\n };\n\n expect(resolveTheme(selection, false)).toBe(\"dracula\");\n expect(resolveTheme(selection, true)).toBe(\"dracula\");\n });\n\n it(\"should follow the system appearance in system mode\", () => {\n const selection = {\n mode: THEME_MODE_SYSTEM,\n theme: \"dracula\",\n themeLight: \"cupcake\",\n themeDark: \"one-dark\",\n };\n\n expect(resolveTheme(selection, false)).toBe(\"cupcake\");\n expect(resolveTheme(selection, true)).toBe(\"one-dark\");\n });\n\n it(\"should fall back to the defaults when a slot is missing or unknown\", () => {\n expect(resolveTheme({ mode: THEME_MODE_SYSTEM }, false)).toBe(\n DEFAULT_THEME\n );\n expect(resolveTheme({ mode: THEME_MODE_SYSTEM }, true)).toBe(\n DEFAULT_DARK_THEME\n );\n expect(\n resolveTheme(\n {\n mode: THEME_MODE_SYSTEM,\n themeLight: \"solarized\",\n themeDark: \"solarized\",\n },\n false\n )\n ).toBe(DEFAULT_THEME);\n expect(\n resolveTheme(\n {\n mode: THEME_MODE_SYSTEM,\n themeLight: \"solarized\",\n themeDark: \"solarized\",\n },\n true\n )\n ).toBe(DEFAULT_DARK_THEME);\n expect(resolveTheme({ theme: \"solarized\" }, false)).toBe(DEFAULT_THEME);\n });\n\n it(\"should treat an absent or unrecognised mode as single\", () => {\n expect(resolveTheme({ theme: \"neon\" }, false)).toBe(\"neon\");\n expect(resolveTheme({ mode: \"auto\", theme: \"neon\" }, true)).toBe(\"neon\");\n });\n});\n"],"mappings":"AAAA,SACEA,kBAAkB,EAClBC,aAAa,EACbC,gBAAgB,EAChBC,iBAAiB,EACjBC,iBAAiB,EACjBC,iBAAiB,EACjBC,YAAY,QACP,UAAU;AAEjBC,QAAQ,CAAC,cAAc,EAAE,MAAM;EAC7BC,EAAE,CAAC,iEAAiE,EAAE,MAAM;IAC1EC,MAAM,CAACN,iBAAiB,CAAC,CAACO,OAAO,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;IACnED,MAAM,CAACP,gBAAgB,CAAC,CAACQ,OAAO,CAAC,CAAC,MAAM,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;EACnE,CAAC,CAAC;EAEFF,EAAE,CAAC,oDAAoD,EAAE,MAAM;IAC7D,MAAMG,SAAS,GAAG;MAChBC,IAAI,EAAER,iBAAiB;MACvBS,KAAK,EAAE,SAAS;MAChBC,UAAU,EAAE,SAAS;MACrBC,SAAS,EAAE;IACb,CAAC;IAEDN,MAAM,CAACH,YAAY,CAACK,SAAS,EAAE,KAAK,CAAC,CAAC,CAACK,IAAI,CAAC,SAAS,CAAC;IACtDP,MAAM,CAACH,YAAY,CAACK,SAAS,EAAE,IAAI,CAAC,CAAC,CAACK,IAAI,CAAC,SAAS,CAAC;EACvD,CAAC,CAAC;EAEFR,EAAE,CAAC,oDAAoD,EAAE,MAAM;IAC7D,MAAMG,SAAS,GAAG;MAChBC,IAAI,EAAEP,iBAAiB;MACvBQ,KAAK,EAAE,SAAS;MAChBC,UAAU,EAAE,SAAS;MACrBC,SAAS,EAAE;IACb,CAAC;IAEDN,MAAM,CAACH,YAAY,CAACK,SAAS,EAAE,KAAK,CAAC,CAAC,CAACK,IAAI,CAAC,SAAS,CAAC;IACtDP,MAAM,CAACH,YAAY,CAACK,SAAS,EAAE,IAAI,CAAC,CAAC,CAACK,IAAI,CAAC,UAAU,CAAC;EACxD,CAAC,CAAC;EAEFR,EAAE,CAAC,oEAAoE,EAAE,MAAM;IAC7EC,MAAM,CAACH,YAAY,CAAC;MAAEM,IAAI,EAAEP;IAAkB,CAAC,EAAE,KAAK,CAAC,CAAC,CAACW,IAAI,CAC3Df,aACF,CAAC;IACDQ,MAAM,CAACH,YAAY,CAAC;MAAEM,IAAI,EAAEP;IAAkB,CAAC,EAAE,IAAI,CAAC,CAAC,CAACW,IAAI,CAC1DhB,kBACF,CAAC;IACDS,MAAM,CACJH,YAAY,CACV;MACEM,IAAI,EAAEP,iBAAiB;MACvBS,UAAU,EAAE,WAAW;MACvBC,SAAS,EAAE;IACb,CAAC,EACD,KACF,CACF,CAAC,CAACC,IAAI,CAACf,aAAa,CAAC;IACrBQ,MAAM,CACJH,YAAY,CACV;MACEM,IAAI,EAAEP,iBAAiB;MACvBS,UAAU,EAAE,WAAW;MACvBC,SAAS,EAAE;IACb,CAAC,EACD,IACF,CACF,CAAC,CAACC,IAAI,CAAChB,kBAAkB,CAAC;IAC1BS,MAAM,CAACH,YAAY,CAAC;MAAEO,KAAK,EAAE;IAAY,CAAC,EAAE,KAAK,CAAC,CAAC,CAACG,IAAI,CAACf,aAAa,CAAC;EACzE,CAAC,CAAC;EAEFO,EAAE,CAAC,uDAAuD,EAAE,MAAM;IAChEC,MAAM,CAACH,YAAY,CAAC;MAAEO,KAAK,EAAE;IAAO,CAAC,EAAE,KAAK,CAAC,CAAC,CAACG,IAAI,CAAC,MAAM,CAAC;IAC3DP,MAAM,CAACH,YAAY,CAAC;MAAEM,IAAI,EAAE,MAAM;MAAEC,KAAK,EAAE;IAAO,CAAC,EAAE,IAAI,CAAC,CAAC,CAACG,IAAI,CAAC,MAAM,CAAC;EAC1E,CAAC,CAAC;AACJ,CAAC,CAAC","ignoreList":[]}
|
package/dist/index.js
CHANGED
|
@@ -626,27 +626,33 @@
|
|
|
626
626
|
var THEMES = [{
|
|
627
627
|
name: "indigo",
|
|
628
628
|
title: "Indigo",
|
|
629
|
-
dark: false
|
|
629
|
+
dark: false,
|
|
630
|
+
swatch: ["#5d2bff", "#5d2bff", "#f4f5f7"]
|
|
630
631
|
}, {
|
|
631
632
|
name: "cupcake",
|
|
632
633
|
title: "Cupcake",
|
|
633
|
-
dark: false
|
|
634
|
+
dark: false,
|
|
635
|
+
swatch: ["#fe6fa7", "#29bcdd", "#f4f5f7"]
|
|
634
636
|
}, {
|
|
635
637
|
name: "classic",
|
|
636
638
|
title: "Classic",
|
|
637
|
-
dark: false
|
|
639
|
+
dark: false,
|
|
640
|
+
swatch: ["#4182f2", "#4182f2", "#f4f5f7"]
|
|
638
641
|
}, {
|
|
639
642
|
name: "neon",
|
|
640
643
|
title: "Neon",
|
|
641
|
-
dark: true
|
|
644
|
+
dark: true,
|
|
645
|
+
swatch: ["#67ffc8", "#67ffc8", "#2c2e38"]
|
|
642
646
|
}, {
|
|
643
647
|
name: "dracula",
|
|
644
648
|
title: "Dracula",
|
|
645
|
-
dark: true
|
|
649
|
+
dark: true,
|
|
650
|
+
swatch: ["#ff79c6", "#bd93f9", "#282a36"]
|
|
646
651
|
}, {
|
|
647
652
|
name: "one-dark",
|
|
648
653
|
title: "One Dark",
|
|
649
|
-
dark: true
|
|
654
|
+
dark: true,
|
|
655
|
+
swatch: ["#c678dd", "#61afef", "#282c34"]
|
|
650
656
|
}];
|
|
651
657
|
var THEME_NAMES = THEMES.map(function (theme) {
|
|
652
658
|
return theme.name;
|
|
@@ -656,9 +662,33 @@
|
|
|
656
662
|
}).map(function (theme) {
|
|
657
663
|
return theme.name;
|
|
658
664
|
});
|
|
665
|
+
var LIGHT_THEME_NAMES = THEMES.filter(function (theme) {
|
|
666
|
+
return !theme.dark;
|
|
667
|
+
}).map(function (theme) {
|
|
668
|
+
return theme.name;
|
|
669
|
+
});
|
|
670
|
+
var DEFAULT_THEME = "indigo";
|
|
671
|
+
var DEFAULT_DARK_THEME = "neon";
|
|
672
|
+
var THEME_MODE_SINGLE = "single";
|
|
673
|
+
var THEME_MODE_SYSTEM = "system";
|
|
659
674
|
var isDarkTheme = function isDarkTheme(name) {
|
|
660
675
|
return Boolean(name) && DARK_THEME_NAMES.includes(name);
|
|
661
676
|
};
|
|
677
|
+
var knownTheme = function knownTheme(name, fallback) {
|
|
678
|
+
return name && THEME_NAMES.includes(name) ? name : fallback;
|
|
679
|
+
};
|
|
680
|
+
|
|
681
|
+
// Resolution is derived per render, never persisted — writing it back would destroy the user's pick.
|
|
682
|
+
var resolveTheme = function resolveTheme(_ref, prefersDark) {
|
|
683
|
+
var mode = _ref.mode,
|
|
684
|
+
theme = _ref.theme,
|
|
685
|
+
themeLight = _ref.themeLight,
|
|
686
|
+
themeDark = _ref.themeDark;
|
|
687
|
+
if (mode !== THEME_MODE_SYSTEM) {
|
|
688
|
+
return knownTheme(theme, DEFAULT_THEME);
|
|
689
|
+
}
|
|
690
|
+
return prefersDark ? knownTheme(themeDark, DEFAULT_DARK_THEME) : knownTheme(themeLight, DEFAULT_THEME);
|
|
691
|
+
};
|
|
662
692
|
|
|
663
693
|
// :is() and not :where() — :where() is zero-specificity and would silently lose to the light
|
|
664
694
|
// declarations it is meant to override.
|
|
@@ -28821,7 +28851,9 @@
|
|
|
28821
28851
|
exports.DARK_THEME_MATCH = DARK_THEME_MATCH;
|
|
28822
28852
|
exports.DARK_THEME_NAMES = DARK_THEME_NAMES;
|
|
28823
28853
|
exports.DARK_THEME_SELECTOR = DARK_THEME_SELECTOR;
|
|
28854
|
+
exports.DEFAULT_DARK_THEME = DEFAULT_DARK_THEME;
|
|
28824
28855
|
exports.DEFAULT_KEYBOARD_STEP = DEFAULT_KEYBOARD_STEP;
|
|
28856
|
+
exports.DEFAULT_THEME = DEFAULT_THEME;
|
|
28825
28857
|
exports.DataTable = DataTable;
|
|
28826
28858
|
exports.DatePicker = DatePicker;
|
|
28827
28859
|
exports.DateStepper = DateStepper;
|
|
@@ -28926,6 +28958,7 @@
|
|
|
28926
28958
|
exports.Item = Item;
|
|
28927
28959
|
exports.ItemContext = ItemContext;
|
|
28928
28960
|
exports.KeyIcon = KeyIcon$1;
|
|
28961
|
+
exports.LIGHT_THEME_NAMES = LIGHT_THEME_NAMES;
|
|
28929
28962
|
exports.Label = Label;
|
|
28930
28963
|
exports.LabelsIcon = LabelsIcon$1;
|
|
28931
28964
|
exports.LayerBackIcon = LayerBackIcon$1;
|
|
@@ -29099,6 +29132,8 @@
|
|
|
29099
29132
|
exports.SunIcon = SunIcon$1;
|
|
29100
29133
|
exports.SystemSettingsIcon = SystemSettingsIcon$1;
|
|
29101
29134
|
exports.THEMES = THEMES;
|
|
29135
|
+
exports.THEME_MODE_SINGLE = THEME_MODE_SINGLE;
|
|
29136
|
+
exports.THEME_MODE_SYSTEM = THEME_MODE_SYSTEM;
|
|
29102
29137
|
exports.THEME_NAMES = THEME_NAMES;
|
|
29103
29138
|
exports.Table = Table;
|
|
29104
29139
|
exports.Tag = Tag;
|
|
@@ -29166,6 +29201,7 @@
|
|
|
29166
29201
|
exports.makeStart = makeStart;
|
|
29167
29202
|
exports.measurePercent = measurePercent;
|
|
29168
29203
|
exports.numberWithSeparator = numberWithSeparator;
|
|
29204
|
+
exports.resolveTheme = resolveTheme;
|
|
29169
29205
|
exports.signifierTypes = signifierTypes;
|
|
29170
29206
|
exports.snap = snap;
|
|
29171
29207
|
exports.toMoment = toMoment;
|