vueless 1.5.1-beta.3 → 1.5.1-beta.5
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/index.d.ts +9 -1
- package/index.ts +9 -1
- package/modules.d.ts +1 -0
- package/package.json +2 -2
- package/plugin-vite.js +5 -0
- package/types.ts +5 -0
- package/utils/node/helper.d.ts +1 -0
- package/utils/node/helper.js +13 -1
- package/utils/node/vuelessConfig.d.ts +1 -1
- package/utils/node/vuelessConfig.js +3 -1
- package/utils/tests/theme.test.ts +124 -0
- package/utils/theme.ts +46 -48
- package/utils/ui.ts +10 -2
package/index.d.ts
CHANGED
|
@@ -27,7 +27,15 @@ export {
|
|
|
27
27
|
} from "./utils/ui";
|
|
28
28
|
export { addToRequestQueue, removeFromRequestQueue } from "./utils/requestQueue";
|
|
29
29
|
export { isMac, isPWA, isIOS, isAndroid, isMobileApp, isWindows } from "./utils/platform";
|
|
30
|
-
export {
|
|
30
|
+
export {
|
|
31
|
+
getTheme,
|
|
32
|
+
setTheme,
|
|
33
|
+
resetTheme,
|
|
34
|
+
getThemeCookieName,
|
|
35
|
+
normalizeThemeConfig,
|
|
36
|
+
cssVar,
|
|
37
|
+
setRootCSSVariables,
|
|
38
|
+
} from "./utils/theme";
|
|
31
39
|
export { getArgs, getArgTypes, getSlotNames, getSlotsFragment, getSource, getDocsDescription } from "./utils/storybook";
|
|
32
40
|
/* adapters */
|
|
33
41
|
export { default as defaultEnLocale } from "./adapter.locale/locales/en";
|
package/index.ts
CHANGED
|
@@ -33,7 +33,15 @@ export {
|
|
|
33
33
|
} from "./utils/ui";
|
|
34
34
|
export { addToRequestQueue, removeFromRequestQueue } from "./utils/requestQueue";
|
|
35
35
|
export { isMac, isPWA, isIOS, isAndroid, isMobileApp, isWindows } from "./utils/platform";
|
|
36
|
-
export {
|
|
36
|
+
export {
|
|
37
|
+
getTheme,
|
|
38
|
+
setTheme,
|
|
39
|
+
resetTheme,
|
|
40
|
+
getThemeCookieName,
|
|
41
|
+
normalizeThemeConfig,
|
|
42
|
+
cssVar,
|
|
43
|
+
setRootCSSVariables,
|
|
44
|
+
} from "./utils/theme";
|
|
37
45
|
export { getArgs, getArgTypes, getSlotNames, getSlotsFragment, getSource, getDocsDescription } from "./utils/storybook";
|
|
38
46
|
/* adapters */
|
|
39
47
|
export { default as defaultEnLocale } from "./adapter.locale/locales/en";
|
package/modules.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vueless",
|
|
3
|
-
"version": "1.5.1-beta.
|
|
3
|
+
"version": "1.5.1-beta.5",
|
|
4
4
|
"description": "Vue Styleless UI Component Library, powered by Tailwind CSS.",
|
|
5
5
|
"author": "Johnny Grid <hello@vueless.com> (https://vueless.com)",
|
|
6
6
|
"homepage": "https://vueless.com",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"@tailwindcss/postcss": "^4.2.4",
|
|
36
36
|
"@tailwindcss/vite": "^4.2.4",
|
|
37
37
|
"@types/lodash-es": "^4.17.12",
|
|
38
|
-
"cva": "
|
|
38
|
+
"cva": "1.0.0-beta.10",
|
|
39
39
|
"lodash-es": "^4.18.1",
|
|
40
40
|
"rolldown": "^1.1.5",
|
|
41
41
|
"svgo": "^4.0.1",
|
package/plugin-vite.js
CHANGED
|
@@ -24,6 +24,7 @@ import { overrideComponents, restoreComponents } from "./utils/node/componentOve
|
|
|
24
24
|
import {
|
|
25
25
|
getNuxtDirs,
|
|
26
26
|
getVueDirs,
|
|
27
|
+
getAppName,
|
|
27
28
|
getVuelessAppDirs,
|
|
28
29
|
cacheMergedConfigs,
|
|
29
30
|
autoImportUserConfigs,
|
|
@@ -74,6 +75,9 @@ export const Vueless = function (options = {}) {
|
|
|
74
75
|
|
|
75
76
|
const vuelessSrcDir = isInternalEnv ? VUELESS_LOCAL_DIR : VUELESS_PACKAGE_DIR;
|
|
76
77
|
|
|
78
|
+
/* app name for theme cookie prefixing */
|
|
79
|
+
const appName = getAppName();
|
|
80
|
+
|
|
77
81
|
// Cache to store previous icon content for change detection
|
|
78
82
|
const iconContentCache = new Map();
|
|
79
83
|
|
|
@@ -109,6 +113,7 @@ export const Vueless = function (options = {}) {
|
|
|
109
113
|
define: {
|
|
110
114
|
"process.env": {},
|
|
111
115
|
__VUELESS_DEV__: process.argv.includes("--watch") || process.argv.includes("-w"),
|
|
116
|
+
__VUELESS_APP_NAME__: JSON.stringify(appName),
|
|
112
117
|
},
|
|
113
118
|
optimizeDeps: {
|
|
114
119
|
include: isInternalEnv
|
package/types.ts
CHANGED
|
@@ -183,6 +183,11 @@ export interface Config extends ThemeConfig {
|
|
|
183
183
|
*/
|
|
184
184
|
directives?: Partial<Directives>;
|
|
185
185
|
|
|
186
|
+
/**
|
|
187
|
+
* Theme cookie name prefix (defaults to the app `package.json` name, `""` disables prefixing).
|
|
188
|
+
*/
|
|
189
|
+
cookiePrefix?: string;
|
|
190
|
+
|
|
186
191
|
/**
|
|
187
192
|
* Tailwind CSS theme config.
|
|
188
193
|
* https://tailwindcss.com/docs/theme
|
package/utils/node/helper.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export function cacheMergedConfigs({ vuelessSrcDir, basePath }?: {
|
|
|
13
13
|
}): Promise<void>;
|
|
14
14
|
export function buildTSFile(entryPath: string, configOutFile: string): Promise<void>;
|
|
15
15
|
export function removeFolderIfEmpty(dirPath: string): Promise<void>;
|
|
16
|
+
export function getAppName(): string;
|
|
16
17
|
export function detectTypeScript(): Promise<boolean>;
|
|
17
18
|
export function autoImportUserConfigs(basePath?: string): Promise<void>;
|
|
18
19
|
export function generateConfigIndexContent(imports?: string[], componentEntries?: string[]): Promise<string>;
|
package/utils/node/helper.js
CHANGED
|
@@ -2,7 +2,7 @@ import { build as rolldownBuild } from "rolldown";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { cwd } from "node:process";
|
|
4
4
|
import { pathToFileURL } from "node:url";
|
|
5
|
-
import { existsSync, statSync } from "node:fs";
|
|
5
|
+
import { existsSync, statSync, readFileSync } from "node:fs";
|
|
6
6
|
import { mkdir, readdir, rmdir, readFile, writeFile } from "node:fs/promises";
|
|
7
7
|
|
|
8
8
|
import { getMergedConfig, getVuelessConfig } from "./vuelessConfig.js";
|
|
@@ -226,6 +226,18 @@ export async function removeFolderIfEmpty(dirPath) {
|
|
|
226
226
|
}
|
|
227
227
|
}
|
|
228
228
|
|
|
229
|
+
/**
|
|
230
|
+
* Reads the app name from the project's package.json (used to prefix theme cookies).
|
|
231
|
+
* @returns {string} The package name, or an empty string if unavailable.
|
|
232
|
+
*/
|
|
233
|
+
export function getAppName() {
|
|
234
|
+
try {
|
|
235
|
+
return JSON.parse(readFileSync(path.join(cwd(), "package.json"), "utf-8")).name || "";
|
|
236
|
+
} catch {
|
|
237
|
+
return "";
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
229
241
|
/**
|
|
230
242
|
* Detects if TypeScript is a dependency in the project's package.json
|
|
231
243
|
* @returns {Promise<boolean>} True if TypeScript is found in dependencies or devDependencies
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export function getVuelessConfig(basePath?: string): Promise<Object>;
|
|
2
2
|
export let vuelessConfig: {};
|
|
3
|
-
export const cx: import("cva").CX
|
|
3
|
+
export const cx: import("cva").CX<import("cva").ClassValue>;
|
|
4
4
|
export const getMergedConfig: ({ defaultConfig, globalConfig, propsConfig, unstyled }: {
|
|
5
5
|
defaultConfig: any;
|
|
6
6
|
globalConfig: any;
|
|
@@ -2,7 +2,8 @@ import fs from "node:fs";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { cwd } from "node:process";
|
|
4
4
|
import { pathToFileURL } from "node:url";
|
|
5
|
-
import {
|
|
5
|
+
import { cx as cvaCx } from "cva";
|
|
6
|
+
import { defineConfig } from "cva/config";
|
|
6
7
|
import { merge } from "lodash-es";
|
|
7
8
|
import { extendTailwindMerge } from "tailwind-merge";
|
|
8
9
|
|
|
@@ -57,6 +58,7 @@ const twMerge = extendTailwindMerge(
|
|
|
57
58
|
* – remove all Vueless nested component names ({U...} strings) from the class list string.
|
|
58
59
|
*/
|
|
59
60
|
export const { cx } = defineConfig({
|
|
61
|
+
cx: cvaCx,
|
|
60
62
|
hooks: {
|
|
61
63
|
onComplete: (classNames) => twMerge(classNames).replace(NESTED_COMPONENT_PATTERN_REG_EXP, ""),
|
|
62
64
|
},
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
|
|
3
|
+
import { AUTO_MODE_KEY, COLOR_MODE_KEY } from "../../constants.js";
|
|
4
|
+
import { ColorMode } from "../../types";
|
|
5
|
+
import type { Config } from "../../types";
|
|
6
|
+
|
|
7
|
+
const mockVuelessConfig: Config = {};
|
|
8
|
+
|
|
9
|
+
vi.mock("../ui", () => ({ vuelessConfig: mockVuelessConfig }));
|
|
10
|
+
|
|
11
|
+
/* jsdom doesn't implement matchMedia, which theme.ts evaluates on import. */
|
|
12
|
+
const prefersDark = { matches: false, addEventListener: vi.fn(), removeEventListener: vi.fn() };
|
|
13
|
+
|
|
14
|
+
window.matchMedia = vi.fn(() => prefersDark) as unknown as typeof window.matchMedia;
|
|
15
|
+
|
|
16
|
+
const { getTheme, getThemeCookieName, resetTheme } = await import("../theme");
|
|
17
|
+
|
|
18
|
+
function setConfig(config: Config) {
|
|
19
|
+
Object.keys(mockVuelessConfig).forEach((key) => delete mockVuelessConfig[key as keyof Config]);
|
|
20
|
+
Object.assign(mockVuelessConfig, config);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function clearCookies() {
|
|
24
|
+
document.cookie.split("; ").forEach((cookie) => {
|
|
25
|
+
const name = cookie.split("=")[0];
|
|
26
|
+
|
|
27
|
+
if (name) document.cookie = `${name}=; max-age=-1; path=/`;
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
beforeEach(() => {
|
|
32
|
+
localStorage.clear();
|
|
33
|
+
clearCookies();
|
|
34
|
+
setConfig({});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
describe("getThemeCookieName", () => {
|
|
38
|
+
it("prefixes a key with the app name from package.json", () => {
|
|
39
|
+
expect(getThemeCookieName(COLOR_MODE_KEY)).toBe(`vueless-${COLOR_MODE_KEY}`);
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("makes the prefix cookie-safe", () => {
|
|
43
|
+
setConfig({ cookiePrefix: "@acme/Back_Office!" });
|
|
44
|
+
|
|
45
|
+
expect(getThemeCookieName(COLOR_MODE_KEY)).toBe(`acme-back_office-${COLOR_MODE_KEY}`);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("lets cookiePrefix override the app name", () => {
|
|
49
|
+
setConfig({ cookiePrefix: "app-a" });
|
|
50
|
+
|
|
51
|
+
expect(getThemeCookieName(COLOR_MODE_KEY)).toBe(`app-a-${COLOR_MODE_KEY}`);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("returns the legacy name when cookiePrefix is an empty string", () => {
|
|
55
|
+
setConfig({ cookiePrefix: "" });
|
|
56
|
+
|
|
57
|
+
expect(getThemeCookieName(COLOR_MODE_KEY)).toBe(COLOR_MODE_KEY);
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe("theme value storage", () => {
|
|
62
|
+
it("writes the cookie prefixed and the localStorage key raw", () => {
|
|
63
|
+
setConfig({ cookiePrefix: "app-a" });
|
|
64
|
+
|
|
65
|
+
getTheme({ colorMode: ColorMode.Dark });
|
|
66
|
+
|
|
67
|
+
expect(localStorage.getItem(COLOR_MODE_KEY)).toBe(ColorMode.Dark);
|
|
68
|
+
expect(document.cookie).toContain(`app-a-${COLOR_MODE_KEY}=${ColorMode.Dark}`);
|
|
69
|
+
expect(document.cookie.split("; ")).not.toContain(`${COLOR_MODE_KEY}=${ColorMode.Dark}`);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("deletes the prefixed cookies on resetTheme", () => {
|
|
73
|
+
setConfig({ cookiePrefix: "app-a" });
|
|
74
|
+
|
|
75
|
+
getTheme({ colorMode: ColorMode.Dark });
|
|
76
|
+
resetTheme();
|
|
77
|
+
|
|
78
|
+
expect(localStorage.getItem(COLOR_MODE_KEY)).toBeNull();
|
|
79
|
+
expect(document.cookie).not.toContain(`app-a-${COLOR_MODE_KEY}=${ColorMode.Dark}`);
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
describe("CSR color mode precedence", () => {
|
|
84
|
+
it("prefers the explicit mode over everything else", () => {
|
|
85
|
+
localStorage.setItem(COLOR_MODE_KEY, ColorMode.Light);
|
|
86
|
+
setConfig({ colorMode: ColorMode.Light });
|
|
87
|
+
|
|
88
|
+
expect(getTheme({ colorMode: ColorMode.Dark }).colorMode).toBe(ColorMode.Dark);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it("falls back to localStorage when no mode is passed", () => {
|
|
92
|
+
localStorage.setItem(COLOR_MODE_KEY, ColorMode.Dark);
|
|
93
|
+
setConfig({ colorMode: ColorMode.Light });
|
|
94
|
+
|
|
95
|
+
expect(getTheme().colorMode).toBe(ColorMode.Dark);
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
it("ignores cookies when localStorage is empty", () => {
|
|
99
|
+
document.cookie = `${COLOR_MODE_KEY}=${ColorMode.Dark}; path=/`;
|
|
100
|
+
document.cookie = `vueless-${COLOR_MODE_KEY}=${ColorMode.Dark}; path=/`;
|
|
101
|
+
setConfig({ colorMode: ColorMode.Light });
|
|
102
|
+
|
|
103
|
+
expect(getTheme().colorMode).toBe(ColorMode.Light);
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
it("falls back to vuelessConfig.colorMode", () => {
|
|
107
|
+
setConfig({ colorMode: ColorMode.Dark });
|
|
108
|
+
|
|
109
|
+
expect(getTheme().colorMode).toBe(ColorMode.Dark);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("falls back to light when nothing is set", () => {
|
|
113
|
+
expect(getTheme().colorMode).toBe(ColorMode.Light);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
describe("auto color mode", () => {
|
|
118
|
+
it("reports auto mode from the cached localStorage flag", () => {
|
|
119
|
+
localStorage.setItem(AUTO_MODE_KEY, "1");
|
|
120
|
+
localStorage.setItem(COLOR_MODE_KEY, ColorMode.Dark);
|
|
121
|
+
|
|
122
|
+
expect(getTheme().isColorModeAuto).toBe(true);
|
|
123
|
+
});
|
|
124
|
+
});
|
package/utils/theme.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { cloneDeep, merge } from "lodash-es";
|
|
2
2
|
|
|
3
3
|
import { vuelessConfig } from "./ui";
|
|
4
|
-
import { isCSR, getStored,
|
|
4
|
+
import { isCSR, getStored, setCookie, deleteCookie, toNumber } from "./helper";
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
7
|
PX_IN_REM,
|
|
@@ -63,14 +63,33 @@ declare interface SetColorMode {
|
|
|
63
63
|
/* Creates a media query that checks if the user's system color scheme is set to the dark. */
|
|
64
64
|
const prefersColorSchemeDark = isCSR && window.matchMedia("(prefers-color-scheme: dark)");
|
|
65
65
|
|
|
66
|
+
/* Prefixes theme cookie names, so apps sharing a host (cookies ignore the port) don't collide. */
|
|
67
|
+
export function getThemeCookieName(key: string) {
|
|
68
|
+
const appName = typeof __VUELESS_APP_NAME__ === "undefined" ? "" : __VUELESS_APP_NAME__;
|
|
69
|
+
const prefix = (vuelessConfig.cookiePrefix ?? appName)
|
|
70
|
+
.toLowerCase()
|
|
71
|
+
.replace(/[^a-z0-9_-]/g, "-")
|
|
72
|
+
.replace(/^-+|-+$/g, "");
|
|
73
|
+
|
|
74
|
+
return prefix ? `${prefix}-${key}` : key;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* Saves a theme value under the raw key in local storage (client) and the prefixed cookie (SSR). */
|
|
78
|
+
function storeThemeValue(key: string, value: string) {
|
|
79
|
+
if (!isCSR) return;
|
|
80
|
+
|
|
81
|
+
localStorage.setItem(key, value);
|
|
82
|
+
setCookie(getThemeCookieName(key), value);
|
|
83
|
+
}
|
|
84
|
+
|
|
66
85
|
function toggleColorModeClass() {
|
|
67
86
|
if (!prefersColorSchemeDark) return;
|
|
68
87
|
|
|
69
88
|
const isDarkMode = prefersColorSchemeDark.matches;
|
|
70
89
|
const colorMode = isDarkMode ? ColorMode.Dark : ColorMode.Light;
|
|
71
90
|
|
|
72
|
-
|
|
73
|
-
|
|
91
|
+
storeThemeValue(COLOR_MODE_KEY, colorMode);
|
|
92
|
+
storeThemeValue(AUTO_MODE_KEY, String(Number(true)));
|
|
74
93
|
|
|
75
94
|
document.documentElement.classList.toggle(DARK_MODE_CLASS, isDarkMode);
|
|
76
95
|
document.documentElement.classList.toggle(LIGHT_MODE_CLASS, !isDarkMode);
|
|
@@ -90,8 +109,9 @@ function toggleColorModeClass() {
|
|
|
90
109
|
* - `isColorModeAuto` {boolean}: Indicates whether the color mode is set to auto.
|
|
91
110
|
*/
|
|
92
111
|
function setCSRColorMode(mode: `${ColorMode}`): SetColorMode {
|
|
93
|
-
const colorMode = mode ||
|
|
94
|
-
const
|
|
112
|
+
const colorMode = mode || getStored(COLOR_MODE_KEY) || vuelessConfig.colorMode || ColorMode.Light;
|
|
113
|
+
const storedAutoMode = getStored(AUTO_MODE_KEY);
|
|
114
|
+
const isCachedAutoMode = !!Number(storedAutoMode ?? 0);
|
|
95
115
|
|
|
96
116
|
const isAutoMode = colorMode === ColorMode.Auto;
|
|
97
117
|
const isSystemDarkMode = isAutoMode && prefersColorSchemeDark && prefersColorSchemeDark?.matches;
|
|
@@ -114,17 +134,15 @@ function setCSRColorMode(mode: `${ColorMode}`): SetColorMode {
|
|
|
114
134
|
/* Dispatching custom event for the useDarkMode composable. */
|
|
115
135
|
window.dispatchEvent(new CustomEvent("darkModeChange", { detail: isDarkMode }));
|
|
116
136
|
|
|
117
|
-
/* Saving color mode value into cookies (server) and local storage (client). */
|
|
118
137
|
let currentColorMode = colorMode;
|
|
119
138
|
|
|
120
139
|
if (isAutoMode) {
|
|
121
140
|
currentColorMode = isDarkMode ? ColorMode.Dark : ColorMode.Light;
|
|
122
141
|
}
|
|
123
142
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
setCookie(AUTO_MODE_KEY, String(Number(isAutoMode)));
|
|
143
|
+
if (mode || storedAutoMode === undefined) {
|
|
144
|
+
storeThemeValue(COLOR_MODE_KEY, currentColorMode);
|
|
145
|
+
storeThemeValue(AUTO_MODE_KEY, String(Number(isAutoMode)));
|
|
128
146
|
|
|
129
147
|
if (mode !== ColorMode.Auto && prefersColorSchemeDark) {
|
|
130
148
|
prefersColorSchemeDark.removeEventListener("change", toggleColorModeClass);
|
|
@@ -196,7 +214,7 @@ export function resetTheme() {
|
|
|
196
214
|
|
|
197
215
|
themeKeys.forEach((key) => {
|
|
198
216
|
localStorage.removeItem(key);
|
|
199
|
-
deleteCookie(key);
|
|
217
|
+
deleteCookie(getThemeCookieName(key));
|
|
200
218
|
});
|
|
201
219
|
}
|
|
202
220
|
|
|
@@ -436,8 +454,7 @@ function getPrimaryColor(primary?: PrimaryColors) {
|
|
|
436
454
|
validateColorShades(primaryColor, PRIMARY_COLOR);
|
|
437
455
|
|
|
438
456
|
if (isCSR && primary) {
|
|
439
|
-
|
|
440
|
-
localStorage.setItem(storageKey, JSON.stringify(primaryColor));
|
|
457
|
+
storeThemeValue(storageKey, JSON.stringify(primaryColor));
|
|
441
458
|
}
|
|
442
459
|
|
|
443
460
|
return primaryColor;
|
|
@@ -454,8 +471,7 @@ function getPrimaryColor(primary?: PrimaryColors) {
|
|
|
454
471
|
}
|
|
455
472
|
|
|
456
473
|
if (isCSR && primary) {
|
|
457
|
-
|
|
458
|
-
localStorage.setItem(storageKey, String(primaryColor));
|
|
474
|
+
storeThemeValue(storageKey, String(primaryColor));
|
|
459
475
|
}
|
|
460
476
|
|
|
461
477
|
return primaryColor;
|
|
@@ -486,8 +502,7 @@ function getNeutralColor(neutral?: NeutralColors) {
|
|
|
486
502
|
validateColorShades(neutralColor, NEUTRAL_COLOR);
|
|
487
503
|
|
|
488
504
|
if (isCSR && neutral) {
|
|
489
|
-
|
|
490
|
-
localStorage.setItem(storageKey, JSON.stringify(neutralColor));
|
|
505
|
+
storeThemeValue(storageKey, JSON.stringify(neutralColor));
|
|
491
506
|
}
|
|
492
507
|
|
|
493
508
|
return neutralColor;
|
|
@@ -503,8 +518,7 @@ function getNeutralColor(neutral?: NeutralColors) {
|
|
|
503
518
|
}
|
|
504
519
|
|
|
505
520
|
if (isCSR && neutral) {
|
|
506
|
-
|
|
507
|
-
localStorage.setItem(storageKey, String(neutralColor));
|
|
521
|
+
storeThemeValue(storageKey, String(neutralColor));
|
|
508
522
|
}
|
|
509
523
|
|
|
510
524
|
return neutralColor;
|
|
@@ -553,15 +567,10 @@ function getText(text?: ThemeConfig["text"]) {
|
|
|
553
567
|
/* eslint-enable prettier/prettier,vue/max-len */
|
|
554
568
|
|
|
555
569
|
if (isCSR && text !== undefined) {
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
localStorage.setItem(storageKey.xs, String(mergedText.xs));
|
|
562
|
-
localStorage.setItem(storageKey.sm, String(mergedText.sm));
|
|
563
|
-
localStorage.setItem(storageKey.md, String(mergedText.md));
|
|
564
|
-
localStorage.setItem(storageKey.lg, String(mergedText.lg));
|
|
570
|
+
storeThemeValue(storageKey.xs, String(mergedText.xs));
|
|
571
|
+
storeThemeValue(storageKey.sm, String(mergedText.sm));
|
|
572
|
+
storeThemeValue(storageKey.md, String(mergedText.md));
|
|
573
|
+
storeThemeValue(storageKey.lg, String(mergedText.lg));
|
|
565
574
|
}
|
|
566
575
|
|
|
567
576
|
return mergedText;
|
|
@@ -609,13 +618,9 @@ function getOutlines(outline?: ThemeConfig["outline"]) {
|
|
|
609
618
|
/* eslint-enable prettier/prettier,vue/max-len */
|
|
610
619
|
|
|
611
620
|
if (isCSR && outline !== undefined) {
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
localStorage.setItem(storageKey.sm, String(mergedOutline.sm));
|
|
617
|
-
localStorage.setItem(storageKey.md, String(mergedOutline.md));
|
|
618
|
-
localStorage.setItem(storageKey.lg, String(mergedOutline.lg));
|
|
621
|
+
storeThemeValue(storageKey.sm, String(mergedOutline.sm));
|
|
622
|
+
storeThemeValue(storageKey.md, String(mergedOutline.md));
|
|
623
|
+
storeThemeValue(storageKey.lg, String(mergedOutline.lg));
|
|
619
624
|
}
|
|
620
625
|
|
|
621
626
|
return mergedOutline;
|
|
@@ -672,13 +677,9 @@ function getRoundings(rounding?: ThemeConfig["rounding"]) {
|
|
|
672
677
|
/* eslint-enable prettier/prettier,vue/max-len */
|
|
673
678
|
|
|
674
679
|
if (isCSR && rounding !== undefined) {
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
localStorage.setItem(storageKey.sm, String(mergedRounding.sm));
|
|
680
|
-
localStorage.setItem(storageKey.md, String(mergedRounding.md));
|
|
681
|
-
localStorage.setItem(storageKey.lg, String(mergedRounding.lg));
|
|
680
|
+
storeThemeValue(storageKey.sm, String(mergedRounding.sm));
|
|
681
|
+
storeThemeValue(storageKey.md, String(mergedRounding.md));
|
|
682
|
+
storeThemeValue(storageKey.lg, String(mergedRounding.lg));
|
|
682
683
|
}
|
|
683
684
|
|
|
684
685
|
return mergedRounding;
|
|
@@ -695,8 +696,7 @@ function getSpacing(spacing?: ThemeConfig["spacing"]) {
|
|
|
695
696
|
const mergedSpacing = Number(storedSpacing ?? DEFAULT_SPACING);
|
|
696
697
|
|
|
697
698
|
if (isCSR && spacing !== undefined) {
|
|
698
|
-
|
|
699
|
-
localStorage.setItem(storageKey, String(mergedSpacing));
|
|
699
|
+
storeThemeValue(storageKey, String(mergedSpacing));
|
|
700
700
|
}
|
|
701
701
|
|
|
702
702
|
return mergedSpacing;
|
|
@@ -713,8 +713,7 @@ function getLetterSpacing(letterSpacing?: ThemeConfig["letterSpacing"]) {
|
|
|
713
713
|
const mergedSpacing = Number(spacing ?? DEFAULT_LETTER_SPACING);
|
|
714
714
|
|
|
715
715
|
if (isCSR && letterSpacing !== undefined) {
|
|
716
|
-
|
|
717
|
-
localStorage.setItem(storageKey, String(mergedSpacing));
|
|
716
|
+
storeThemeValue(storageKey, String(mergedSpacing));
|
|
718
717
|
}
|
|
719
718
|
|
|
720
719
|
return mergedSpacing;
|
|
@@ -731,8 +730,7 @@ function getDisabledOpacity(disabledOpacity?: ThemeConfig["disabledOpacity"]) {
|
|
|
731
730
|
const mergedOpacity = Math.max(0, Number(opacity ?? DEFAULT_DISABLED_OPACITY));
|
|
732
731
|
|
|
733
732
|
if (isCSR && disabledOpacity !== undefined) {
|
|
734
|
-
|
|
735
|
-
localStorage.setItem(storageKey, String(mergedOpacity));
|
|
733
|
+
storeThemeValue(storageKey, String(mergedOpacity));
|
|
736
734
|
}
|
|
737
735
|
|
|
738
736
|
return mergedOpacity;
|
package/utils/ui.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { merge } from "lodash-es";
|
|
2
|
-
import {
|
|
2
|
+
import { cx as cvaCx } from "cva";
|
|
3
|
+
import { defineConfig } from "cva/config";
|
|
3
4
|
import { extendTailwindMerge } from "tailwind-merge";
|
|
4
5
|
|
|
5
6
|
import { isCSR, isSSR } from "./helper";
|
|
@@ -7,6 +8,7 @@ import { createGetMergedConfig } from "./node/mergeConfigs";
|
|
|
7
8
|
import { COMPONENT_NAME as U_ICON } from "../ui.image-icon/constants";
|
|
8
9
|
import { ICON_NON_PROPS_DEFAULTS, TAILWIND_MERGE_EXTENSION } from "../constants";
|
|
9
10
|
|
|
11
|
+
import type { CVAVariantShape } from "cva";
|
|
10
12
|
import type {
|
|
11
13
|
Config,
|
|
12
14
|
UnknownObject,
|
|
@@ -75,6 +77,7 @@ export const {
|
|
|
75
77
|
compose,
|
|
76
78
|
cva: classVarianceAuthority,
|
|
77
79
|
} = defineConfig({
|
|
80
|
+
cx: cvaCx,
|
|
78
81
|
hooks: {
|
|
79
82
|
onComplete: (classNames) => twMerge(classNames),
|
|
80
83
|
},
|
|
@@ -83,7 +86,12 @@ export const {
|
|
|
83
86
|
export const getMergedConfig = createGetMergedConfig(cx) as GetMergedConfig;
|
|
84
87
|
|
|
85
88
|
/* This allows skipping some CVA config keys in vueless config. */
|
|
86
|
-
export const cva = ({
|
|
89
|
+
export const cva = ({
|
|
90
|
+
base = "",
|
|
91
|
+
variants = {} as CVAVariantShape,
|
|
92
|
+
compoundVariants = [],
|
|
93
|
+
defaultVariants = {},
|
|
94
|
+
}) =>
|
|
87
95
|
classVarianceAuthority({
|
|
88
96
|
base,
|
|
89
97
|
variants,
|