clampography 0.9.10 → 2.0.0-beta.2

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/src/index.js ADDED
@@ -0,0 +1,101 @@
1
+ import plugin from "tailwindcss/plugin";
2
+ import { themes as builtInThemes } from "./themes.js";
3
+ import baseStyles from "./base.js";
4
+ import extraStyles from "./extra.js";
5
+
6
+ /**
7
+ * Main plugin function.
8
+ */
9
+ export default plugin.withOptions((options = {}) => {
10
+ return ({ addBase }) => {
11
+ // 1. Load Base and Extra styles
12
+ const includeBase = options.base ?? true;
13
+ const includeExtra = options.extra ?? false;
14
+
15
+ if (includeBase) addBase(baseStyles);
16
+ if (includeExtra) addBase(extraStyles);
17
+
18
+ // 2. Parse themes configuration
19
+ let configThemes = options.themes;
20
+
21
+ // Default values
22
+ let themesToInclude = [];
23
+ let defaultThemeName = "light";
24
+ let prefersDarkTheme = false;
25
+ let rootSelector = options.root ?? ":root";
26
+
27
+ // Normalize input to an array of strings
28
+ // CSS might pass this as a single long string separated by commas
29
+ let rawThemeList = [];
30
+
31
+ if (typeof configThemes === "string") {
32
+ if (configThemes.trim() === "all") {
33
+ // Special case: themes: all
34
+ rawThemeList = Object.keys(builtInThemes);
35
+ } else if (configThemes.trim() === "false") {
36
+ rawThemeList = [];
37
+ } else {
38
+ // Split by comma: "light --default, dark --prefersdark"
39
+ rawThemeList = configThemes.split(",");
40
+ }
41
+ } else if (Array.isArray(configThemes)) {
42
+ rawThemeList = configThemes;
43
+ } else {
44
+ // Default fallback if nothing provided
45
+ rawThemeList = ["light", "dark"];
46
+ }
47
+
48
+ // 3. Process the list and look for flags (--default, --prefersdark)
49
+ // If "all" was used, we don't look for flags (we use default light/dark logic) unless implemented otherwise.
50
+ // Here we focus on the explicit list.
51
+
52
+ rawThemeList.forEach((rawItem) => {
53
+ let themeName = rawItem.trim();
54
+
55
+ // Ignore empty entries
56
+ if (!themeName) return;
57
+
58
+ // Check for --default flag
59
+ if (themeName.includes("--default")) {
60
+ themeName = themeName.replace("--default", "").trim();
61
+ defaultThemeName = themeName;
62
+ }
63
+
64
+ // Check for --prefersdark flag (case insensitive just in case)
65
+ if (themeName.toLowerCase().includes("--prefersdark")) {
66
+ themeName = themeName.replace(/--prefersdark/i, "").trim();
67
+ prefersDarkTheme = themeName;
68
+ }
69
+
70
+ // Check if theme exists in the database
71
+ if (builtInThemes[themeName]) {
72
+ themesToInclude.push(themeName);
73
+ }
74
+ });
75
+
76
+ // If list is empty after filtering, stop here
77
+ if (themesToInclude.length === 0) return;
78
+
79
+ // 4. Generate CSS
80
+ const themeStyles = {};
81
+
82
+ // A. Default theme (:root)
83
+ if (builtInThemes[defaultThemeName]) {
84
+ themeStyles[rootSelector] = builtInThemes[defaultThemeName];
85
+ }
86
+
87
+ // B. Theme for prefers-color-scheme: dark
88
+ if (prefersDarkTheme && builtInThemes[prefersDarkTheme]) {
89
+ themeStyles["@media (prefers-color-scheme: dark)"] = {
90
+ [rootSelector]: builtInThemes[prefersDarkTheme],
91
+ };
92
+ }
93
+
94
+ // C. Scoped styles [data-theme="..."]
95
+ themesToInclude.forEach((themeName) => {
96
+ themeStyles[`[data-theme="${themeName}"]`] = builtInThemes[themeName];
97
+ });
98
+
99
+ addBase(themeStyles);
100
+ };
101
+ });
@@ -0,0 +1,76 @@
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
+ ];
11
+
12
+ export default plugin.withOptions((options = {}) => {
13
+ return ({ addBase }) => {
14
+ // 1. Extract metadata
15
+ const themeName = options.name;
16
+ const isDefault = options.default ?? false;
17
+ const isPrefersDark = options.prefersdark ?? false; // lowercase because CSS might force it
18
+ const rootSelector = options.root ?? ":root";
19
+
20
+ if (!themeName) {
21
+ console.warn("Clampography: Theme definition missing 'name' property.");
22
+ return;
23
+ }
24
+
25
+ // 2. Extract colors from options
26
+ // We iterate over the options object and pick anything that looks like our CSS variable
27
+ // or simply take all known keys.
28
+ const themeColors = {};
29
+
30
+ // You can also support short aliases here if you want (e.g., 'primary' -> '--clampography-primary')
31
+ // For now, let's assume user passes full variable names or mapped keys.
32
+
33
+ // Helper to map simplified keys to full CSS vars (optional convenience)
34
+ const keyMap = {
35
+ "background": "--clampography-background",
36
+ "surface": "--clampography-surface",
37
+ "border": "--clampography-border",
38
+ "heading": "--clampography-heading",
39
+ "text": "--clampography-text",
40
+ "muted": "--clampography-muted",
41
+ "link": "--clampography-link",
42
+ "primary": "--clampography-primary",
43
+ "secondary": "--clampography-secondary",
44
+ };
45
+
46
+ Object.keys(options).forEach((key) => {
47
+ // Check if it's one of our mapped short keys
48
+ if (keyMap[key]) {
49
+ themeColors[keyMap[key]] = options[key];
50
+ } // Or if it is already a custom property key (starts with --)
51
+ else if (key.startsWith("--")) {
52
+ themeColors[key] = options[key];
53
+ }
54
+ });
55
+
56
+ // 3. Generate Styles
57
+ const styles = {};
58
+
59
+ // A. Define the theme as a named data-theme (always available)
60
+ styles[`[data-theme="${themeName}"]`] = themeColors;
61
+
62
+ // B. If marked as default, apply to :root
63
+ if (isDefault) {
64
+ styles[rootSelector] = themeColors;
65
+ }
66
+
67
+ // C. If marked as prefers-dark, apply to media query
68
+ if (isPrefersDark) {
69
+ styles["@media (prefers-color-scheme: dark)"] = {
70
+ [rootSelector]: themeColors,
71
+ };
72
+ }
73
+
74
+ addBase(styles);
75
+ };
76
+ });
package/src/themes.js ADDED
@@ -0,0 +1,48 @@
1
+ export const themes = {
2
+ light: {
3
+ "--clampography-background": "#ffffff",
4
+ "--clampography-surface": "#f3f4f6",
5
+ "--clampography-border": "#e5e7eb",
6
+ "--clampography-heading": "#111827",
7
+ "--clampography-text": "#374151",
8
+ "--clampography-muted": "#6b7280",
9
+ "--clampography-link": "#2563eb",
10
+ "--clampography-primary": "#3b82f6",
11
+ "--clampography-secondary": "#9333ea",
12
+ },
13
+ dark: {
14
+ "--clampography-background": "#0f172a",
15
+ "--clampography-surface": "#1e293b",
16
+ "--clampography-border": "#334155",
17
+ "--clampography-heading": "#f8fafc",
18
+ "--clampography-text": "#cbd5e1",
19
+ "--clampography-muted": "#94a3b8",
20
+ "--clampography-link": "#60a5fa",
21
+ "--clampography-primary": "#3b82f6",
22
+ "--clampography-secondary": "#a855f7",
23
+ },
24
+ retro: {
25
+ "--clampography-background": "#ece3ca",
26
+ "--clampography-surface": "#e0d6b6",
27
+ "--clampography-border": "#cbbd99",
28
+ "--clampography-heading": "#2c2420",
29
+ "--clampography-text": "#4a3b32",
30
+ "--clampography-muted": "#756354",
31
+ "--clampography-link": "#d97757",
32
+ "--clampography-primary": "#e45f2b",
33
+ "--clampography-secondary": "#f6c342",
34
+ },
35
+ cyberpunk: {
36
+ "--clampography-background": "#000b1e",
37
+ "--clampography-surface": "#051630",
38
+ "--clampography-border": "#0f3661",
39
+ "--clampography-heading": "#ffffff",
40
+ "--clampography-text": "#00f0ff",
41
+ "--clampography-muted": "#008f99",
42
+ "--clampography-link": "#ff0099",
43
+ "--clampography-primary": "#fcee0a",
44
+ "--clampography-secondary": "#05ffa1",
45
+ },
46
+ };
47
+
48
+ export const themesList = Object.keys(themes);