vue-multiple-themes 3.0.1 → 4.2.0

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/style.css ADDED
@@ -0,0 +1,39 @@
1
+
2
+ .vmt-root {
3
+ display: inline-flex;
4
+ align-items: center;
5
+ gap: 0.5rem;
6
+ position: relative;
7
+ }
8
+ .vmt-toggle {
9
+ display: inline-flex;
10
+ align-items: center;
11
+ gap: 0.4rem;
12
+ padding: 0.4rem 0.6rem;
13
+ border-radius: 0.5rem;
14
+ border: 1px solid var(--vmt-border, #e5e7eb);
15
+ background: var(--vmt-surface, transparent);
16
+ color: var(--vmt-foreground, inherit);
17
+ cursor: pointer;
18
+ transition: background 0.2s, border-color 0.2s;
19
+ outline: none;
20
+ }
21
+ .vmt-toggle:hover {
22
+ background: var(--vmt-surface-elevated, rgba(0, 0, 0, 0.05));
23
+ }
24
+ .vmt-toggle:focus-visible {
25
+ outline: 2px solid var(--vmt-ring, #4f46e5);
26
+ outline-offset: 2px;
27
+ }
28
+ .vmt-icon {
29
+ display: inline-flex;
30
+ align-items: center;
31
+ color: var(--vmt-icon-color, var(--vmt-foreground, currentColor));
32
+ flex-shrink: 0;
33
+ }
34
+ .vmt-label {
35
+ font-size: 0.875rem;
36
+ font-weight: 500;
37
+ white-space: nowrap;
38
+ color: var(--vmt-foreground, inherit);
39
+ }
@@ -0,0 +1,86 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ function toKebab(str) {
4
+ return str.replace(/([A-Z])/g, (_, c) => `-${c.toLowerCase()}`);
5
+ }
6
+ function buildCssVarRecord(theme, prefix) {
7
+ const record = {};
8
+ for (const [key, value] of Object.entries(theme.colors)) {
9
+ if (value !== void 0) {
10
+ record[`${prefix}${toKebab(key)}`] = value;
11
+ }
12
+ }
13
+ return record;
14
+ }
15
+ function resolveSelectors(themeName, strategy, isFirst) {
16
+ const selectors = [];
17
+ if (isFirst) selectors.push(":root");
18
+ if (strategy === "attribute" || strategy === "both") {
19
+ selectors.push(`:root[data-theme="${themeName}"]`);
20
+ selectors.push(`[data-theme="${themeName}"]`);
21
+ }
22
+ if (strategy === "class" || strategy === "both") {
23
+ selectors.push(`:root.theme-${themeName}`);
24
+ selectors.push(`.theme-${themeName}`);
25
+ }
26
+ return [...new Set(selectors)];
27
+ }
28
+ function vmtTailwindPlugin(opts) {
29
+ const {
30
+ themes,
31
+ cssVarPrefix = "--vmt-",
32
+ strategy = "both",
33
+ generateUtils = true
34
+ } = opts;
35
+ return ({ addBase, addUtilities }) => {
36
+ const baseStyles = {};
37
+ for (let i = 0; i < themes.length; i++) {
38
+ const theme = themes[i];
39
+ const selectors = resolveSelectors(theme.name, strategy, i === 0);
40
+ const vars = buildCssVarRecord(theme, cssVarPrefix);
41
+ for (const selector of selectors) {
42
+ if (baseStyles[selector]) {
43
+ Object.assign(baseStyles[selector], vars);
44
+ } else {
45
+ baseStyles[selector] = { ...vars };
46
+ }
47
+ }
48
+ }
49
+ baseStyles[":root"] = {
50
+ ...baseStyles[":root"],
51
+ [`${cssVarPrefix}icon-color`]: `var(${cssVarPrefix}text, currentColor)`
52
+ };
53
+ addBase(baseStyles);
54
+ if (!generateUtils) return;
55
+ const allKeys = /* @__PURE__ */ new Set();
56
+ for (const theme of themes) {
57
+ for (const key of Object.keys(theme.colors)) {
58
+ allKeys.add(key);
59
+ }
60
+ }
61
+ const utilities = {};
62
+ for (const key of allKeys) {
63
+ const cssVar = `var(${cssVarPrefix}${toKebab(key)})`;
64
+ utilities[`.bg-vmt-${toKebab(key)}`] = { backgroundColor: cssVar };
65
+ utilities[`.text-vmt-${toKebab(key)}`] = { color: cssVar };
66
+ utilities[`.border-vmt-${toKebab(key)}`] = { borderColor: cssVar };
67
+ utilities[`.ring-vmt-${toKebab(key)}`] = {
68
+ "--tw-ring-color": cssVar
69
+ };
70
+ utilities[`.fill-vmt-${toKebab(key)}`] = { fill: cssVar };
71
+ utilities[`.stroke-vmt-${toKebab(key)}`] = { stroke: cssVar };
72
+ }
73
+ addUtilities(utilities);
74
+ };
75
+ }
76
+ function createVmtPlugin(opts) {
77
+ try {
78
+ const plugin = require("tailwindcss/plugin");
79
+ return plugin(vmtTailwindPlugin(opts));
80
+ } catch {
81
+ return vmtTailwindPlugin(opts);
82
+ }
83
+ }
84
+ exports.createVmtPlugin = createVmtPlugin;
85
+ exports.vmtTailwindPlugin = vmtTailwindPlugin;
86
+ //# sourceMappingURL=tailwind-plugin.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tailwind-plugin.cjs","sources":["../src/tailwind-plugin.ts"],"sourcesContent":["/**\n * TailwindCSS plugin for vue-multiple-themes.\n *\n * Generates:\n * 1. CSS custom-property declarations under `[data-theme=\"...\"]` and / or\n * `.theme-...` selectors.\n * 2. (optional) Semantic utility classes:\n * `bg-vmt-background`, `text-vmt-primary`, `border-vmt-border`, etc.\n * using `rgb(var(--vmt-<token>) / <alpha>)` format for full opacity support.\n *\n * @example tailwind.config.js / ts:\n * ```ts\n * import { vmtTailwindPlugin } from 'vue-multiple-themes/tailwind'\n * export default {\n * plugins: [\n * vmtTailwindPlugin({\n * themes: myThemes,\n * cssVarPrefix: '--vmt-',\n * strategy: 'both',\n * generateUtils: true,\n * }),\n * ],\n * }\n * ```\n */\n\nimport type { TailwindPluginOptions, ThemeDefinition } from './types'\n\ntype PluginFn = (helpers: {\n addBase: (styles: Record<string, unknown>) => void\n addUtilities: (utilities: Record<string, unknown>) => void\n addComponents: (components: Record<string, unknown>) => void\n e: (className: string) => string\n}) => void\n\n/** camelCase → kebab-case */\nfunction toKebab(str: string): string {\n return str.replace(/([A-Z])/g, (_, c: string) => `-${c.toLowerCase()}`)\n}\n\nfunction buildCssVarRecord(\n theme: ThemeDefinition,\n prefix: string,\n): Record<string, string> {\n const record: Record<string, string> = {}\n for (const [key, value] of Object.entries(theme.colors)) {\n if (value !== undefined) {\n record[`${prefix}${toKebab(key)}`] = value\n }\n }\n return record\n}\n\nfunction resolveSelectors(\n themeName: string,\n strategy: TailwindPluginOptions['strategy'],\n isFirst: boolean,\n): string[] {\n const selectors: string[] = []\n if (isFirst) selectors.push(':root')\n\n if (strategy === 'attribute' || strategy === 'both') {\n selectors.push(`:root[data-theme=\"${themeName}\"]`)\n selectors.push(`[data-theme=\"${themeName}\"]`)\n }\n\n if (strategy === 'class' || strategy === 'both') {\n selectors.push(`:root.theme-${themeName}`)\n selectors.push(`.theme-${themeName}`)\n }\n\n // Remove duplicates\n return [...new Set(selectors)]\n}\n\n/**\n * Build the Tailwind plugin function.\n * Compatible with both `plugin()` factory and the older function-export form.\n */\nexport function vmtTailwindPlugin(opts: TailwindPluginOptions): PluginFn {\n const {\n themes,\n cssVarPrefix = '--vmt-',\n strategy = 'both',\n generateUtils = true,\n } = opts\n\n return ({ addBase, addUtilities }) => {\n // ─── 1. CSS variable declarations ──────────────────────────────────────\n const baseStyles: Record<string, Record<string, string>> = {}\n\n for (let i = 0; i < themes.length; i++) {\n const theme = themes[i]\n const selectors = resolveSelectors(theme.name, strategy, i === 0)\n const vars = buildCssVarRecord(theme, cssVarPrefix)\n\n for (const selector of selectors) {\n if (baseStyles[selector]) {\n Object.assign(baseStyles[selector], vars)\n } else {\n baseStyles[selector] = { ...vars }\n }\n }\n }\n\n // Add icon-color convenience var\n baseStyles[':root'] = {\n ...baseStyles[':root'],\n [`${cssVarPrefix}icon-color`]: `var(${cssVarPrefix}text, currentColor)`,\n }\n\n addBase(baseStyles as Parameters<typeof addBase>[0])\n\n // ─── 2. Semantic utilities ────────────────────────────────────────────\n if (!generateUtils) return\n\n // Collect all unique color keys across all themes\n const allKeys = new Set<string>()\n for (const theme of themes) {\n for (const key of Object.keys(theme.colors)) {\n allKeys.add(key)\n }\n }\n\n const utilities: Record<string, Record<string, string>> = {}\n\n for (const key of allKeys) {\n const cssVar = `var(${cssVarPrefix}${toKebab(key)})`\n\n // Background color\n utilities[`.bg-vmt-${toKebab(key)}`] = { backgroundColor: cssVar }\n // Text color\n utilities[`.text-vmt-${toKebab(key)}`] = { color: cssVar }\n // Border color\n utilities[`.border-vmt-${toKebab(key)}`] = { borderColor: cssVar }\n // Ring color\n utilities[`.ring-vmt-${toKebab(key)}`] = {\n '--tw-ring-color': cssVar,\n }\n // Fill (for SVG)\n utilities[`.fill-vmt-${toKebab(key)}`] = { fill: cssVar }\n // Stroke (for SVG)\n utilities[`.stroke-vmt-${toKebab(key)}`] = { stroke: cssVar }\n }\n\n addUtilities(utilities as Parameters<typeof addUtilities>[0])\n }\n}\n\n/**\n * Convenience wrapper that returns a Tailwind plugin object\n * compatible with the `plugins: []` array in tailwind.config.ts.\n */\nexport function createVmtPlugin(opts: TailwindPluginOptions) {\n // Support both `require('tailwindcss/plugin')` and flat export\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const plugin = require('tailwindcss/plugin') as (fn: PluginFn) => unknown\n return plugin(vmtTailwindPlugin(opts))\n } catch {\n // In environments without tailwindcss installed, return raw fn\n return vmtTailwindPlugin(opts)\n }\n}\n"],"names":[],"mappings":"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"}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * Convenience wrapper that returns a Tailwind plugin object
3
+ * compatible with the `plugins: []` array in tailwind.config.ts.
4
+ */
5
+ export declare function createVmtPlugin(opts: TailwindPluginOptions): unknown;
6
+
7
+ declare type PluginFn = (helpers: {
8
+ addBase: (styles: Record<string, unknown>) => void;
9
+ addUtilities: (utilities: Record<string, unknown>) => void;
10
+ addComponents: (components: Record<string, unknown>) => void;
11
+ e: (className: string) => string;
12
+ }) => void;
13
+
14
+ declare interface TailwindPluginOptions {
15
+ themes: ThemeDefinition[];
16
+ /** CSS variable prefix – default: `'--vmt-'` */
17
+ cssVarPrefix?: string;
18
+ /**
19
+ * `'attribute'` → `[data-theme="name"]` selectors
20
+ * `'class'` → `.theme-name` selectors
21
+ * `'both'` → both (default)
22
+ */
23
+ strategy?: 'attribute' | 'class' | 'both';
24
+ /**
25
+ * When true (default), the plugin also registers semantic Tailwind utilities:
26
+ * `bg-vmt-background`, `text-vmt-primary`, `border-vmt-border`, etc.
27
+ */
28
+ generateUtils?: boolean;
29
+ }
30
+
31
+ /**
32
+ * Mapping of semantic color tokens to CSS values.
33
+ * Values can be hex, hsl, rgb, or channel-only (for Tailwind RGB opacity support).
34
+ *
35
+ * @example { primary: '#3b82f6', background: '#ffffff', text: '#111827' }
36
+ * @example { primary: '59 130 246' } // Tailwind RGB-channel format
37
+ */
38
+ declare interface ThemeColors {
39
+ primary?: string;
40
+ primaryLight?: string;
41
+ primaryDark?: string;
42
+ secondary?: string;
43
+ accent?: string;
44
+ background?: string;
45
+ surface?: string;
46
+ surfaceElevated?: string;
47
+ text?: string;
48
+ textMuted?: string;
49
+ textInverse?: string;
50
+ border?: string;
51
+ ring?: string;
52
+ success?: string;
53
+ warning?: string;
54
+ error?: string;
55
+ info?: string;
56
+ /** Any additional custom token */
57
+ [key: string]: string | undefined;
58
+ }
59
+
60
+ /**
61
+ * A single theme configuration object.
62
+ */
63
+ declare interface ThemeDefinition {
64
+ /** Unique slug used as the value of `data-theme` / CSS class suffix */
65
+ name: string;
66
+ /** Human-readable display name */
67
+ label?: string;
68
+ /**
69
+ * Name of the Lucide icon to show in the toggle button while this theme is
70
+ * active. Uses `currentColor` so it inherits `--vmt-icon-color`.
71
+ *
72
+ * Supported names: 'sun' | 'moon' | 'sunset' | 'sunrise' | 'monitor' |
73
+ * 'laptop' | 'coffee' | 'leaf' | 'droplets' | 'flame' | 'snowflake' |
74
+ * 'palette' | 'eye' | 'star' | 'zap'
75
+ */
76
+ icon?: string;
77
+ /** Color tokens for this theme */
78
+ colors: ThemeColors;
79
+ /** Extra CSS classes added to the target element alongside the theme class */
80
+ extraClasses?: string[];
81
+ }
82
+
83
+ /**
84
+ * Build the Tailwind plugin function.
85
+ * Compatible with both `plugin()` factory and the older function-export form.
86
+ */
87
+ export declare function vmtTailwindPlugin(opts: TailwindPluginOptions): PluginFn;
88
+
89
+ export { }
@@ -0,0 +1,86 @@
1
+ function toKebab(str) {
2
+ return str.replace(/([A-Z])/g, (_, c) => `-${c.toLowerCase()}`);
3
+ }
4
+ function buildCssVarRecord(theme, prefix) {
5
+ const record = {};
6
+ for (const [key, value] of Object.entries(theme.colors)) {
7
+ if (value !== void 0) {
8
+ record[`${prefix}${toKebab(key)}`] = value;
9
+ }
10
+ }
11
+ return record;
12
+ }
13
+ function resolveSelectors(themeName, strategy, isFirst) {
14
+ const selectors = [];
15
+ if (isFirst) selectors.push(":root");
16
+ if (strategy === "attribute" || strategy === "both") {
17
+ selectors.push(`:root[data-theme="${themeName}"]`);
18
+ selectors.push(`[data-theme="${themeName}"]`);
19
+ }
20
+ if (strategy === "class" || strategy === "both") {
21
+ selectors.push(`:root.theme-${themeName}`);
22
+ selectors.push(`.theme-${themeName}`);
23
+ }
24
+ return [...new Set(selectors)];
25
+ }
26
+ function vmtTailwindPlugin(opts) {
27
+ const {
28
+ themes,
29
+ cssVarPrefix = "--vmt-",
30
+ strategy = "both",
31
+ generateUtils = true
32
+ } = opts;
33
+ return ({ addBase, addUtilities }) => {
34
+ const baseStyles = {};
35
+ for (let i = 0; i < themes.length; i++) {
36
+ const theme = themes[i];
37
+ const selectors = resolveSelectors(theme.name, strategy, i === 0);
38
+ const vars = buildCssVarRecord(theme, cssVarPrefix);
39
+ for (const selector of selectors) {
40
+ if (baseStyles[selector]) {
41
+ Object.assign(baseStyles[selector], vars);
42
+ } else {
43
+ baseStyles[selector] = { ...vars };
44
+ }
45
+ }
46
+ }
47
+ baseStyles[":root"] = {
48
+ ...baseStyles[":root"],
49
+ [`${cssVarPrefix}icon-color`]: `var(${cssVarPrefix}text, currentColor)`
50
+ };
51
+ addBase(baseStyles);
52
+ if (!generateUtils) return;
53
+ const allKeys = /* @__PURE__ */ new Set();
54
+ for (const theme of themes) {
55
+ for (const key of Object.keys(theme.colors)) {
56
+ allKeys.add(key);
57
+ }
58
+ }
59
+ const utilities = {};
60
+ for (const key of allKeys) {
61
+ const cssVar = `var(${cssVarPrefix}${toKebab(key)})`;
62
+ utilities[`.bg-vmt-${toKebab(key)}`] = { backgroundColor: cssVar };
63
+ utilities[`.text-vmt-${toKebab(key)}`] = { color: cssVar };
64
+ utilities[`.border-vmt-${toKebab(key)}`] = { borderColor: cssVar };
65
+ utilities[`.ring-vmt-${toKebab(key)}`] = {
66
+ "--tw-ring-color": cssVar
67
+ };
68
+ utilities[`.fill-vmt-${toKebab(key)}`] = { fill: cssVar };
69
+ utilities[`.stroke-vmt-${toKebab(key)}`] = { stroke: cssVar };
70
+ }
71
+ addUtilities(utilities);
72
+ };
73
+ }
74
+ function createVmtPlugin(opts) {
75
+ try {
76
+ const plugin = require("tailwindcss/plugin");
77
+ return plugin(vmtTailwindPlugin(opts));
78
+ } catch {
79
+ return vmtTailwindPlugin(opts);
80
+ }
81
+ }
82
+ export {
83
+ createVmtPlugin,
84
+ vmtTailwindPlugin
85
+ };
86
+ //# sourceMappingURL=tailwind-plugin.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tailwind-plugin.js","sources":["../src/tailwind-plugin.ts"],"sourcesContent":["/**\n * TailwindCSS plugin for vue-multiple-themes.\n *\n * Generates:\n * 1. CSS custom-property declarations under `[data-theme=\"...\"]` and / or\n * `.theme-...` selectors.\n * 2. (optional) Semantic utility classes:\n * `bg-vmt-background`, `text-vmt-primary`, `border-vmt-border`, etc.\n * using `rgb(var(--vmt-<token>) / <alpha>)` format for full opacity support.\n *\n * @example tailwind.config.js / ts:\n * ```ts\n * import { vmtTailwindPlugin } from 'vue-multiple-themes/tailwind'\n * export default {\n * plugins: [\n * vmtTailwindPlugin({\n * themes: myThemes,\n * cssVarPrefix: '--vmt-',\n * strategy: 'both',\n * generateUtils: true,\n * }),\n * ],\n * }\n * ```\n */\n\nimport type { TailwindPluginOptions, ThemeDefinition } from './types'\n\ntype PluginFn = (helpers: {\n addBase: (styles: Record<string, unknown>) => void\n addUtilities: (utilities: Record<string, unknown>) => void\n addComponents: (components: Record<string, unknown>) => void\n e: (className: string) => string\n}) => void\n\n/** camelCase → kebab-case */\nfunction toKebab(str: string): string {\n return str.replace(/([A-Z])/g, (_, c: string) => `-${c.toLowerCase()}`)\n}\n\nfunction buildCssVarRecord(\n theme: ThemeDefinition,\n prefix: string,\n): Record<string, string> {\n const record: Record<string, string> = {}\n for (const [key, value] of Object.entries(theme.colors)) {\n if (value !== undefined) {\n record[`${prefix}${toKebab(key)}`] = value\n }\n }\n return record\n}\n\nfunction resolveSelectors(\n themeName: string,\n strategy: TailwindPluginOptions['strategy'],\n isFirst: boolean,\n): string[] {\n const selectors: string[] = []\n if (isFirst) selectors.push(':root')\n\n if (strategy === 'attribute' || strategy === 'both') {\n selectors.push(`:root[data-theme=\"${themeName}\"]`)\n selectors.push(`[data-theme=\"${themeName}\"]`)\n }\n\n if (strategy === 'class' || strategy === 'both') {\n selectors.push(`:root.theme-${themeName}`)\n selectors.push(`.theme-${themeName}`)\n }\n\n // Remove duplicates\n return [...new Set(selectors)]\n}\n\n/**\n * Build the Tailwind plugin function.\n * Compatible with both `plugin()` factory and the older function-export form.\n */\nexport function vmtTailwindPlugin(opts: TailwindPluginOptions): PluginFn {\n const {\n themes,\n cssVarPrefix = '--vmt-',\n strategy = 'both',\n generateUtils = true,\n } = opts\n\n return ({ addBase, addUtilities }) => {\n // ─── 1. CSS variable declarations ──────────────────────────────────────\n const baseStyles: Record<string, Record<string, string>> = {}\n\n for (let i = 0; i < themes.length; i++) {\n const theme = themes[i]\n const selectors = resolveSelectors(theme.name, strategy, i === 0)\n const vars = buildCssVarRecord(theme, cssVarPrefix)\n\n for (const selector of selectors) {\n if (baseStyles[selector]) {\n Object.assign(baseStyles[selector], vars)\n } else {\n baseStyles[selector] = { ...vars }\n }\n }\n }\n\n // Add icon-color convenience var\n baseStyles[':root'] = {\n ...baseStyles[':root'],\n [`${cssVarPrefix}icon-color`]: `var(${cssVarPrefix}text, currentColor)`,\n }\n\n addBase(baseStyles as Parameters<typeof addBase>[0])\n\n // ─── 2. Semantic utilities ────────────────────────────────────────────\n if (!generateUtils) return\n\n // Collect all unique color keys across all themes\n const allKeys = new Set<string>()\n for (const theme of themes) {\n for (const key of Object.keys(theme.colors)) {\n allKeys.add(key)\n }\n }\n\n const utilities: Record<string, Record<string, string>> = {}\n\n for (const key of allKeys) {\n const cssVar = `var(${cssVarPrefix}${toKebab(key)})`\n\n // Background color\n utilities[`.bg-vmt-${toKebab(key)}`] = { backgroundColor: cssVar }\n // Text color\n utilities[`.text-vmt-${toKebab(key)}`] = { color: cssVar }\n // Border color\n utilities[`.border-vmt-${toKebab(key)}`] = { borderColor: cssVar }\n // Ring color\n utilities[`.ring-vmt-${toKebab(key)}`] = {\n '--tw-ring-color': cssVar,\n }\n // Fill (for SVG)\n utilities[`.fill-vmt-${toKebab(key)}`] = { fill: cssVar }\n // Stroke (for SVG)\n utilities[`.stroke-vmt-${toKebab(key)}`] = { stroke: cssVar }\n }\n\n addUtilities(utilities as Parameters<typeof addUtilities>[0])\n }\n}\n\n/**\n * Convenience wrapper that returns a Tailwind plugin object\n * compatible with the `plugins: []` array in tailwind.config.ts.\n */\nexport function createVmtPlugin(opts: TailwindPluginOptions) {\n // Support both `require('tailwindcss/plugin')` and flat export\n try {\n // eslint-disable-next-line @typescript-eslint/no-var-requires\n const plugin = require('tailwindcss/plugin') as (fn: PluginFn) => unknown\n return plugin(vmtTailwindPlugin(opts))\n } catch {\n // In environments without tailwindcss installed, return raw fn\n return vmtTailwindPlugin(opts)\n }\n}\n"],"names":[],"mappings":"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"}