clampography 2.0.0-beta.2 → 2.0.0-beta.21
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/README.md +115 -27
- package/package.json +15 -4
- package/src/base.js +491 -421
- package/src/convert.js +264 -0
- package/src/css/base.css +444 -0
- package/src/css/base.css.min +1 -0
- package/src/css/extra.css +145 -0
- package/src/css/extra.css.min +1 -0
- package/src/extra.js +197 -137
- package/src/index.js +240 -92
- package/src/theme-plugin.js +93 -33
- package/src/themes.js +56 -36
- package/src/types/index.d.ts +14 -0
- package/src/types/theme-plugin.d.ts +32 -0
- package/src/types/themes.d.ts +18 -0
package/src/index.js
CHANGED
|
@@ -3,99 +3,247 @@ import { themes as builtInThemes } from "./themes.js";
|
|
|
3
3
|
import baseStyles from "./base.js";
|
|
4
4
|
import extraStyles from "./extra.js";
|
|
5
5
|
|
|
6
|
+
// Import version from package.json
|
|
7
|
+
import { version } from "../package.json" with { type: "json" };
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Helper to resolve boolean options from CSS configuration.
|
|
11
|
+
* CSS values often come as strings ("true"/"false"), which are both truthy in JS.
|
|
12
|
+
*/
|
|
13
|
+
const resolveBool = (value, defaultValue) => {
|
|
14
|
+
if (
|
|
15
|
+
value === "false" || value === false || value === "no" || value === "none"
|
|
16
|
+
) return false;
|
|
17
|
+
if (value === "true" || value === true || value === "yes") return true;
|
|
18
|
+
return defaultValue;
|
|
19
|
+
};
|
|
20
|
+
|
|
6
21
|
/**
|
|
7
22
|
* Main plugin function.
|
|
8
23
|
*/
|
|
9
|
-
export default plugin.withOptions(
|
|
10
|
-
|
|
11
|
-
//
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
24
|
+
export default plugin.withOptions(
|
|
25
|
+
(() => {
|
|
26
|
+
let firstRun = true; // Track first run for logging
|
|
27
|
+
|
|
28
|
+
return (options = {}) => {
|
|
29
|
+
return ({ addBase }) => {
|
|
30
|
+
// Extract logs option (default: true)
|
|
31
|
+
const showLogs = resolveBool(options.logs, true);
|
|
32
|
+
|
|
33
|
+
// Show startup log only once
|
|
34
|
+
if (showLogs && firstRun) {
|
|
35
|
+
console.log(`🍀 Clampography v${version} loaded successfully`);
|
|
36
|
+
firstRun = false;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// 1. Load Base and Extra styles
|
|
40
|
+
// We use the helper to correctly parse "false" string from CSS
|
|
41
|
+
const includeBase = resolveBool(options.base, true); // Default: true
|
|
42
|
+
const includeExtra = resolveBool(options.extra, false); // Default: false
|
|
43
|
+
|
|
44
|
+
// Pass options to the style functions to enable scoping
|
|
45
|
+
includeBase && addBase(baseStyles(options));
|
|
46
|
+
includeExtra && addBase(extraStyles(options));
|
|
47
|
+
|
|
48
|
+
// 2. Parse themes configuration
|
|
49
|
+
let configThemes = options.themes;
|
|
50
|
+
let themesToInclude = [];
|
|
51
|
+
let defaultThemeName = null;
|
|
52
|
+
let prefersDarkTheme = false;
|
|
53
|
+
let rootSelector = options.root || ":root";
|
|
54
|
+
let isAllThemes = false; // Track if user specified "all"
|
|
55
|
+
|
|
56
|
+
// Normalize input to an array of strings
|
|
57
|
+
let rawThemeList = [];
|
|
58
|
+
if (typeof configThemes === "string") {
|
|
59
|
+
if (["all", "true", "yes"].includes(configThemes.trim())) {
|
|
60
|
+
// Special case: themes: all
|
|
61
|
+
isAllThemes = true;
|
|
62
|
+
rawThemeList = Object.keys(builtInThemes);
|
|
63
|
+
} else if (["false", "none", "no"].includes(configThemes.trim())) {
|
|
64
|
+
// Explicitly disabled themes
|
|
65
|
+
rawThemeList = [];
|
|
66
|
+
} else {
|
|
67
|
+
rawThemeList = configThemes.split(",");
|
|
68
|
+
}
|
|
69
|
+
} else if (Array.isArray(configThemes)) {
|
|
70
|
+
rawThemeList = configThemes;
|
|
71
|
+
} else {
|
|
72
|
+
// Default behavior: NO themes loaded automatically.
|
|
73
|
+
// User must specify themes to load them.
|
|
74
|
+
rawThemeList = [];
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// 3. Process the list and look for flags (--default, --prefersdark)
|
|
78
|
+
rawThemeList.forEach((rawItem) => {
|
|
79
|
+
let themeName = rawItem.trim();
|
|
80
|
+
|
|
81
|
+
// Ignore empty entries
|
|
82
|
+
if (!themeName) return;
|
|
83
|
+
|
|
84
|
+
// Check for --default flag
|
|
85
|
+
if (themeName.includes("--default")) {
|
|
86
|
+
themeName = themeName.replace("--default", "").trim();
|
|
87
|
+
defaultThemeName = themeName;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// Check for --prefersdark flag
|
|
91
|
+
if (themeName.toLowerCase().includes("--prefersdark")) {
|
|
92
|
+
themeName = themeName.replace(/--prefersdark/i, "").trim();
|
|
93
|
+
prefersDarkTheme = themeName;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Check if theme exists in the database
|
|
97
|
+
if (builtInThemes[themeName]) {
|
|
98
|
+
themesToInclude.push(themeName);
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// 4. Auto-configure defaults for "themes: all"
|
|
103
|
+
if (isAllThemes) {
|
|
104
|
+
if (!defaultThemeName) {
|
|
105
|
+
if (themesToInclude.includes("light")) {
|
|
106
|
+
defaultThemeName = "light";
|
|
107
|
+
} else if (themesToInclude.length > 0) {
|
|
108
|
+
defaultThemeName = themesToInclude[0];
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (!prefersDarkTheme && themesToInclude.includes("dark")) {
|
|
112
|
+
prefersDarkTheme = "dark";
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// LOGGING: Built-in themes summary
|
|
117
|
+
if (showLogs) {
|
|
118
|
+
const explicitlyDisabled = ["false", "no", "none"].includes(
|
|
119
|
+
String(options.themes).trim(),
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
if (themesToInclude.length > 0) {
|
|
123
|
+
const themesList = themesToInclude.map((theme) => {
|
|
124
|
+
const flags = [];
|
|
125
|
+
if (theme === defaultThemeName) flags.push("default");
|
|
126
|
+
if (theme === prefersDarkTheme) flags.push("prefersdark");
|
|
127
|
+
|
|
128
|
+
const flagStr = flags.length > 0 ? ` (${flags.join(", ")})` : "";
|
|
129
|
+
return `${theme}${flagStr}`;
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
console.log(
|
|
133
|
+
`🍀 Clampography: Loaded ${themesToInclude.length} built-in themes: ${
|
|
134
|
+
themesList.join(", ")
|
|
135
|
+
}`,
|
|
136
|
+
);
|
|
137
|
+
} else if (!explicitlyDisabled) {
|
|
138
|
+
console.info("ℹ️ Clampography: No built-in themes loaded.");
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
// Final check before generating CSS
|
|
143
|
+
if (
|
|
144
|
+
themesToInclude.length === 0 && !defaultThemeName && !prefersDarkTheme
|
|
145
|
+
) return;
|
|
146
|
+
|
|
147
|
+
// 5. Generate CSS
|
|
148
|
+
const themeStyles = {};
|
|
149
|
+
|
|
150
|
+
// A. Default theme - uses :where() for lower specificity
|
|
151
|
+
// Helper to combine root and data-theme
|
|
152
|
+
// If root is ":root", we use "html[data-theme...]" for backwards compatibility.
|
|
153
|
+
// If root is custom (e.g. "#morda"), we generate "#morda[data-theme...]"
|
|
154
|
+
const getThemeSelector = (themeName) => {
|
|
155
|
+
if (rootSelector === ":root") {
|
|
156
|
+
return `html[data-theme="${themeName}"], [data-theme="${themeName}"]`;
|
|
157
|
+
}
|
|
158
|
+
// For custom root, attach data-theme directly to it
|
|
159
|
+
// AND allow a nested data-theme inside it (optional, but good for nesting)
|
|
160
|
+
return `${rootSelector}[data-theme="${themeName}"], ${rootSelector} [data-theme="${themeName}"]`;
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
// A. Default theme
|
|
164
|
+
if (defaultThemeName && builtInThemes[defaultThemeName]) {
|
|
165
|
+
// Default variables applied to the root element itself without data-theme attribute
|
|
166
|
+
// uses :where() for lower specificity so it can be overridden
|
|
167
|
+
const defaultSelector = `:where(${rootSelector})`;
|
|
168
|
+
|
|
169
|
+
// Also apply if explicitly selected
|
|
170
|
+
const explicitSelector = getThemeSelector(defaultThemeName);
|
|
171
|
+
|
|
172
|
+
themeStyles[`${defaultSelector}, ${explicitSelector}`] =
|
|
173
|
+
builtInThemes[defaultThemeName];
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// B. Theme for prefers-color-scheme: dark
|
|
177
|
+
if (prefersDarkTheme && builtInThemes[prefersDarkTheme]) {
|
|
178
|
+
themeStyles["@media (prefers-color-scheme: dark)"] = {
|
|
179
|
+
[rootSelector]: builtInThemes[prefersDarkTheme],
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// C. All themes available via [data-theme] attribute
|
|
184
|
+
themesToInclude.forEach((themeName) => {
|
|
185
|
+
if (themeName === defaultThemeName) return;
|
|
186
|
+
const selector = getThemeSelector(themeName);
|
|
187
|
+
themeStyles[selector] = builtInThemes[themeName];
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
// D. Override media query with data-theme selectors
|
|
191
|
+
if (prefersDarkTheme) {
|
|
192
|
+
themeStyles["@media (prefers-color-scheme: dark)"] = {
|
|
193
|
+
...themeStyles["@media (prefers-color-scheme: dark)"],
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
themesToInclude.forEach((themeName) => {
|
|
197
|
+
if (themeName === prefersDarkTheme) return;
|
|
198
|
+
const selector = getThemeSelector(themeName);
|
|
199
|
+
|
|
200
|
+
if (!themeStyles["@media (prefers-color-scheme: dark)"][selector]) {
|
|
201
|
+
themeStyles["@media (prefers-color-scheme: dark)"][selector] =
|
|
202
|
+
builtInThemes[themeName];
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
addBase(themeStyles);
|
|
91
208
|
};
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
209
|
+
};
|
|
210
|
+
})(),
|
|
211
|
+
// Theme extension - enables utilities like bg-surface, text-heading, etc.
|
|
212
|
+
(options = {}) => {
|
|
213
|
+
// ✅ Extract prefix option (default: "clampography")
|
|
214
|
+
// This prefix is ONLY used for Tailwind utility classes (e.g., bg-clampography-primary)
|
|
215
|
+
// CSS variables remain unchanged (always --clampography-*)
|
|
216
|
+
const prefixEnabled = resolveBool(options.prefix, true);
|
|
217
|
+
const prefix = prefixEnabled
|
|
218
|
+
? (typeof options.prefix === "string" &&
|
|
219
|
+
!["false", "no", "none", "true"].includes(options.prefix)
|
|
220
|
+
? options.prefix
|
|
221
|
+
: "clampography")
|
|
222
|
+
: "";
|
|
223
|
+
|
|
224
|
+
// Helper to add prefix with separator
|
|
225
|
+
const addPrefix = (name) => prefix ? `${prefix}-${name}` : name;
|
|
226
|
+
|
|
227
|
+
return {
|
|
228
|
+
theme: {
|
|
229
|
+
extend: {
|
|
230
|
+
colors: {
|
|
231
|
+
[addPrefix("background")]: "var(--clampography-background)",
|
|
232
|
+
[addPrefix("border")]: "var(--clampography-border)",
|
|
233
|
+
[addPrefix("error")]: "var(--clampography-error)",
|
|
234
|
+
[addPrefix("heading")]: "var(--clampography-heading)",
|
|
235
|
+
[addPrefix("info")]: "var(--clampography-info)",
|
|
236
|
+
[addPrefix("link")]: "var(--clampography-link)",
|
|
237
|
+
[addPrefix("muted")]: "var(--clampography-muted)",
|
|
238
|
+
[addPrefix("primary")]: "var(--clampography-primary)",
|
|
239
|
+
[addPrefix("secondary")]: "var(--clampography-secondary)",
|
|
240
|
+
[addPrefix("success")]: "var(--clampography-success)",
|
|
241
|
+
[addPrefix("surface")]: "var(--clampography-surface)",
|
|
242
|
+
[addPrefix("text")]: "var(--clampography-text)",
|
|
243
|
+
[addPrefix("warning")]: "var(--clampography-warning)",
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
};
|
|
248
|
+
},
|
|
249
|
+
);
|
package/src/theme-plugin.js
CHANGED
|
@@ -1,70 +1,130 @@
|
|
|
1
1
|
import plugin from "tailwindcss/plugin";
|
|
2
|
-
|
|
3
|
-
// List of required color keys for validation (optional but good practice)
|
|
4
|
-
const REQUIRED_KEYS = [
|
|
5
|
-
"--clampography-background",
|
|
6
|
-
"--clampography-text",
|
|
7
|
-
"--clampography-link",
|
|
8
|
-
"--clampography-primary",
|
|
9
|
-
"--clampography-secondary",
|
|
10
|
-
];
|
|
2
|
+
import { themes as builtInThemes } from "./themes.js";
|
|
11
3
|
|
|
12
4
|
export default plugin.withOptions((options = {}) => {
|
|
13
5
|
return ({ addBase }) => {
|
|
14
6
|
// 1. Extract metadata
|
|
15
7
|
const themeName = options.name;
|
|
16
8
|
const isDefault = options.default ?? false;
|
|
17
|
-
const isPrefersDark = options.prefersdark ?? false;
|
|
18
|
-
const rootSelector = options.root
|
|
9
|
+
const isPrefersDark = options.prefersdark ?? false;
|
|
10
|
+
const rootSelector = options.root || ":root";
|
|
11
|
+
const colorScheme = options["color-scheme"] ?? "light";
|
|
12
|
+
|
|
13
|
+
// This option is completely separate from the main plugin's logs option
|
|
14
|
+
const showLogs = options.logs !== false;
|
|
19
15
|
|
|
20
16
|
if (!themeName) {
|
|
21
|
-
|
|
17
|
+
if (showLogs) {
|
|
18
|
+
console.warn(
|
|
19
|
+
"🍀 Clampography: Theme definition missing 'name' property.",
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
22
|
return;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
//
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
25
|
+
// LOGGING: Custom theme loaded
|
|
26
|
+
if (showLogs) {
|
|
27
|
+
const flags = [];
|
|
28
|
+
if (isDefault) flags.push("Default");
|
|
29
|
+
if (isPrefersDark) flags.push("Dark Pref");
|
|
30
|
+
const flagStr = flags.length > 0 ? ` (${flags.join(", ")})` : "";
|
|
31
|
+
|
|
32
|
+
console.log(
|
|
33
|
+
`✨ Clampography: Loaded custom theme "${themeName}"${flagStr}`,
|
|
34
|
+
);
|
|
35
|
+
}
|
|
29
36
|
|
|
30
|
-
//
|
|
31
|
-
//
|
|
37
|
+
// 2. Prepare Base Colors (Fallback)
|
|
38
|
+
// We fetch the full palette of the requested color scheme (light/dark)
|
|
39
|
+
// to fill in any missing gaps in the user's definition.
|
|
40
|
+
const fallbackTheme = builtInThemes[colorScheme] || builtInThemes["light"];
|
|
32
41
|
|
|
33
|
-
//
|
|
42
|
+
// 3. Extract & Merge Colors
|
|
43
|
+
const themeColors = {};
|
|
44
|
+
|
|
45
|
+
// Mapping of simplified keys to full CSS variable names
|
|
34
46
|
const keyMap = {
|
|
35
47
|
"background": "--clampography-background",
|
|
36
|
-
"surface": "--clampography-surface",
|
|
37
48
|
"border": "--clampography-border",
|
|
49
|
+
"error": "--clampography-error",
|
|
38
50
|
"heading": "--clampography-heading",
|
|
39
|
-
"
|
|
40
|
-
"muted": "--clampography-muted",
|
|
51
|
+
"info": "--clampography-info",
|
|
41
52
|
"link": "--clampography-link",
|
|
53
|
+
"muted": "--clampography-muted",
|
|
42
54
|
"primary": "--clampography-primary",
|
|
43
55
|
"secondary": "--clampography-secondary",
|
|
56
|
+
"success": "--clampography-success",
|
|
57
|
+
"surface": "--clampography-surface",
|
|
58
|
+
"text": "--clampography-text",
|
|
59
|
+
"warning": "--clampography-warning",
|
|
44
60
|
};
|
|
45
61
|
|
|
62
|
+
// First, populate with fallback colors
|
|
63
|
+
Object.keys(fallbackTheme).forEach((key) => {
|
|
64
|
+
themeColors[key] = fallbackTheme[key];
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
// Then override with user provided values
|
|
46
68
|
Object.keys(options).forEach((key) => {
|
|
47
|
-
//
|
|
69
|
+
// Ignore metadata keys
|
|
70
|
+
if (
|
|
71
|
+
["name", "default", "prefersdark", "root", "color-scheme", "logs"]
|
|
72
|
+
.includes(key)
|
|
73
|
+
) return;
|
|
74
|
+
|
|
75
|
+
const value = options[key];
|
|
76
|
+
|
|
48
77
|
if (keyMap[key]) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
78
|
+
// Validate color format (only if logs enabled)
|
|
79
|
+
if (showLogs && value && typeof value === "string") {
|
|
80
|
+
// Check if value starts with oklch() or is a valid CSS color
|
|
81
|
+
const isOklch = value.trim().startsWith("oklch(");
|
|
82
|
+
const isHex = /^#[0-9A-Fa-f]{3,8}$/.test(value.trim());
|
|
83
|
+
const isRgb = value.trim().startsWith("rgb(") ||
|
|
84
|
+
value.trim().startsWith("rgba(");
|
|
85
|
+
|
|
86
|
+
if (!isOklch && !isHex && !isRgb) {
|
|
87
|
+
console.warn(
|
|
88
|
+
`Clampography (${themeName}): Color "${key}" has value "${value}" which may not be a valid color format. ` +
|
|
89
|
+
`For best compatibility with opacity modifiers (e.g., bg-${key}/20), use full OKLCH format: ` +
|
|
90
|
+
`oklch(70% 0.2 180) or oklch(0.7 0.2 180)`,
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (isHex || isRgb) {
|
|
95
|
+
console.info(
|
|
96
|
+
`🍀 Clampography (${themeName}): Color "${key}" uses ${
|
|
97
|
+
isHex ? "HEX" : "RGB"
|
|
98
|
+
} format. ` +
|
|
99
|
+
`Consider using OKLCH format for better color space support and smoother gradients.`,
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
themeColors[keyMap[key]] = value;
|
|
105
|
+
} else if (key.startsWith("--")) {
|
|
106
|
+
themeColors[key] = value;
|
|
53
107
|
}
|
|
54
108
|
});
|
|
55
109
|
|
|
56
|
-
//
|
|
110
|
+
// Add the CSS property 'color-scheme' for browser UI adaptation (scrollbars, etc.)
|
|
111
|
+
themeColors["color-scheme"] = colorScheme;
|
|
112
|
+
|
|
113
|
+
// 4. Generate Styles
|
|
57
114
|
const styles = {};
|
|
58
115
|
|
|
59
|
-
//
|
|
60
|
-
|
|
116
|
+
// Build selector based on flags
|
|
117
|
+
let selector = `[data-theme="${themeName}"]`;
|
|
61
118
|
|
|
62
|
-
//
|
|
119
|
+
// If default, prepend :where(root) with lower specificity
|
|
63
120
|
if (isDefault) {
|
|
64
|
-
|
|
121
|
+
selector = `:where(${rootSelector}),${selector}`;
|
|
65
122
|
}
|
|
66
123
|
|
|
67
|
-
//
|
|
124
|
+
// Apply theme to the constructed selector
|
|
125
|
+
styles[selector] = themeColors;
|
|
126
|
+
|
|
127
|
+
// If prefers-dark, apply only to root selector in media query
|
|
68
128
|
if (isPrefersDark) {
|
|
69
129
|
styles["@media (prefers-color-scheme: dark)"] = {
|
|
70
130
|
[rootSelector]: themeColors,
|
package/src/themes.js
CHANGED
|
@@ -1,47 +1,67 @@
|
|
|
1
1
|
export const themes = {
|
|
2
2
|
light: {
|
|
3
|
-
"
|
|
4
|
-
"--clampography-
|
|
5
|
-
"--clampography-border": "
|
|
6
|
-
"--clampography-
|
|
7
|
-
"--clampography-
|
|
8
|
-
"--clampography-
|
|
9
|
-
"--clampography-link": "
|
|
10
|
-
"--clampography-
|
|
11
|
-
"--clampography-
|
|
3
|
+
"color-scheme": "light",
|
|
4
|
+
"--clampography-background": "oklch(100% 0 0)",
|
|
5
|
+
"--clampography-border": "oklch(92% 0.003 264)",
|
|
6
|
+
"--clampography-error": "oklch(63% 0.22 27)",
|
|
7
|
+
"--clampography-heading": "oklch(15% 0.02 264)",
|
|
8
|
+
"--clampography-info": "oklch(63% 0.258 262)",
|
|
9
|
+
"--clampography-link": "oklch(43% 0.19 264)",
|
|
10
|
+
"--clampography-muted": "oklch(52% 0.014 258)",
|
|
11
|
+
"--clampography-primary": "oklch(63% 0.258 262)",
|
|
12
|
+
"--clampography-secondary": "oklch(55% 0.28 300)",
|
|
13
|
+
"--clampography-success": "oklch(65% 0.17 165)",
|
|
14
|
+
"--clampography-surface": "oklch(96% 0.003 264)",
|
|
15
|
+
"--clampography-text": "oklch(31% 0.02 257)",
|
|
16
|
+
"--clampography-warning": "oklch(72% 0.17 65)",
|
|
12
17
|
},
|
|
13
18
|
dark: {
|
|
14
|
-
"
|
|
15
|
-
"--clampography-
|
|
16
|
-
"--clampography-border": "
|
|
17
|
-
"--clampography-
|
|
18
|
-
"--clampography-
|
|
19
|
-
"--clampography-
|
|
20
|
-
"--clampography-link": "
|
|
21
|
-
"--clampography-
|
|
22
|
-
"--clampography-
|
|
19
|
+
"color-scheme": "dark",
|
|
20
|
+
"--clampography-background": "oklch(10% 0 0)",
|
|
21
|
+
"--clampography-border": "oklch(31% 0.03 254)",
|
|
22
|
+
"--clampography-error": "oklch(63% 0.22 27)",
|
|
23
|
+
"--clampography-heading": "oklch(98% 0.003 264)",
|
|
24
|
+
"--clampography-info": "oklch(72% 0.17 254)",
|
|
25
|
+
"--clampography-link": "oklch(72% 0.17 254)",
|
|
26
|
+
"--clampography-muted": "oklch(68% 0.024 254)",
|
|
27
|
+
"--clampography-primary": "oklch(63% 0.258 262)",
|
|
28
|
+
"--clampography-secondary": "oklch(63% 0.25 300)",
|
|
29
|
+
"--clampography-success": "oklch(65% 0.17 165)",
|
|
30
|
+
"--clampography-surface": "oklch(12% 0 0)",
|
|
31
|
+
"--clampography-text": "oklch(95% 0 0)",
|
|
32
|
+
"--clampography-warning": "oklch(72% 0.17 65)",
|
|
23
33
|
},
|
|
24
34
|
retro: {
|
|
25
|
-
"
|
|
26
|
-
"--clampography-
|
|
27
|
-
"--clampography-border": "
|
|
28
|
-
"--clampography-
|
|
29
|
-
"--clampography-
|
|
30
|
-
"--clampography-
|
|
31
|
-
"--clampography-link": "
|
|
32
|
-
"--clampography-
|
|
33
|
-
"--clampography-
|
|
35
|
+
"color-scheme": "light",
|
|
36
|
+
"--clampography-background": "oklch(91% 0.03 85)",
|
|
37
|
+
"--clampography-border": "oklch(78% 0.05 85)",
|
|
38
|
+
"--clampography-error": "oklch(52% 0.15 35)",
|
|
39
|
+
"--clampography-heading": "oklch(18% 0.02 35)",
|
|
40
|
+
"--clampography-info": "oklch(60% 0.06 230)",
|
|
41
|
+
"--clampography-link": "oklch(63% 0.13 40)",
|
|
42
|
+
"--clampography-muted": "oklch(44% 0.03 45)",
|
|
43
|
+
"--clampography-primary": "oklch(60% 0.19 35)",
|
|
44
|
+
"--clampography-secondary": "oklch(80% 0.14 85)",
|
|
45
|
+
"--clampography-success": "oklch(62% 0.10 130)",
|
|
46
|
+
"--clampography-surface": "oklch(87% 0.04 85)",
|
|
47
|
+
"--clampography-text": "oklch(28% 0.03 40)",
|
|
48
|
+
"--clampography-warning": "oklch(80% 0.14 85)",
|
|
34
49
|
},
|
|
35
50
|
cyberpunk: {
|
|
36
|
-
"
|
|
37
|
-
"--clampography-
|
|
38
|
-
"--clampography-border": "
|
|
39
|
-
"--clampography-
|
|
40
|
-
"--clampography-
|
|
41
|
-
"--clampography-
|
|
42
|
-
"--clampography-link": "
|
|
43
|
-
"--clampography-
|
|
44
|
-
"--clampography-
|
|
51
|
+
"color-scheme": "dark",
|
|
52
|
+
"--clampography-background": "oklch(8% 0.04 264)",
|
|
53
|
+
"--clampography-border": "oklch(27% 0.09 254)",
|
|
54
|
+
"--clampography-error": "oklch(60% 0.29 340)",
|
|
55
|
+
"--clampography-heading": "oklch(100% 0 0)",
|
|
56
|
+
"--clampography-info": "oklch(88% 0.16 195)",
|
|
57
|
+
"--clampography-link": "oklch(60% 0.29 340)",
|
|
58
|
+
"--clampography-muted": "oklch(55% 0.07 200)",
|
|
59
|
+
"--clampography-primary": "oklch(93% 0.22 105)",
|
|
60
|
+
"--clampography-secondary": "oklch(87% 0.20 165)",
|
|
61
|
+
"--clampography-success": "oklch(87% 0.20 165)",
|
|
62
|
+
"--clampography-surface": "oklch(12% 0.05 264)",
|
|
63
|
+
"--clampography-text": "oklch(88% 0.16 195)",
|
|
64
|
+
"--clampography-warning": "oklch(93% 0.22 105)",
|
|
45
65
|
},
|
|
46
66
|
};
|
|
47
67
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Config, PluginCreator } from "tailwindcss/types/config";
|
|
2
|
+
|
|
3
|
+
interface ClampographyOptions {
|
|
4
|
+
themes?: string | string[] | boolean;
|
|
5
|
+
base?: boolean;
|
|
6
|
+
extra?: boolean;
|
|
7
|
+
root?: string;
|
|
8
|
+
prefix?: string | boolean;
|
|
9
|
+
logs?: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
declare const clampographyPlugin: PluginCreator<ClampographyOptions>;
|
|
13
|
+
|
|
14
|
+
export default clampographyPlugin;
|