@seyuna/postcss 1.0.0-canary.37 → 1.0.0-canary.39
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/CHANGELOG.md +26 -0
- package/README.md +444 -156
- package/dist/at-rules/color-scheme.d.ts +3 -2
- package/dist/at-rules/color-scheme.js +6 -7
- package/dist/at-rules/color.d.ts +5 -4
- package/dist/at-rules/color.js +5 -4
- package/dist/at-rules/config.d.ts +2 -1
- package/dist/at-rules/config.js +44 -13
- package/dist/at-rules/container.d.ts +2 -1
- package/dist/at-rules/container.js +4 -6
- package/dist/at-rules/import.d.ts +3 -2
- package/dist/at-rules/import.js +107 -139
- package/dist/at-rules/index.d.ts +2 -1
- package/dist/at-rules/index.js +3 -4
- package/dist/config.js +70 -28
- package/dist/errors.d.ts +3 -5
- package/dist/errors.js +2 -4
- package/dist/functions/color.d.ts +4 -4
- package/dist/functions/color.js +4 -4
- package/dist/functions/index.js +5 -7
- package/dist/helpers.d.ts +4 -6
- package/dist/helpers.js +26 -22
- package/dist/index.d.ts +8 -1
- package/dist/index.js +1 -0
- package/dist/parser.js +36 -49
- package/dist/plugin.d.ts +3 -1
- package/dist/plugin.js +15 -19
- package/dist/types.d.ts +6 -1
- package/dist/types.js +0 -2
- package/package.json +20 -3
- package/.github/workflows/release.yml +0 -41
- package/.vscode/settings.json +0 -4
- package/dist/functions/theme.d.ts +0 -6
- package/dist/functions/theme.js +0 -17
- package/release.config.mjs +0 -37
- package/src/at-rules/color-scheme.ts +0 -54
- package/src/at-rules/color.ts +0 -33
- package/src/at-rules/config.ts +0 -78
- package/src/at-rules/container.ts +0 -58
- package/src/at-rules/import.ts +0 -196
- package/src/at-rules/index.ts +0 -29
- package/src/config.ts +0 -98
- package/src/errors.ts +0 -27
- package/src/functions/color.ts +0 -123
- package/src/functions/index.ts +0 -22
- package/src/functions/theme.ts +0 -20
- package/src/helpers.ts +0 -75
- package/src/index.ts +0 -10
- package/src/parser.ts +0 -81
- package/src/plugin.ts +0 -58
- package/src/styles/seyuna-global.css +0 -94
- package/src/types.ts +0 -71
- package/tests/plugin.test.ts +0 -244
- package/tsconfig.json +0 -14
package/src/at-rules/config.ts
DELETED
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
import { PluginContext } from "../types.js";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Handler for @config "seyuna"
|
|
5
|
-
* Parses the configuration defined directly in CSS.
|
|
6
|
-
*/
|
|
7
|
-
export function handleConfig(atRule: any, context: PluginContext) {
|
|
8
|
-
const params = atRule.params.replace(/['"]/g, "");
|
|
9
|
-
|
|
10
|
-
if (params === "seyuna") {
|
|
11
|
-
const { config } = context;
|
|
12
|
-
if (!config.ui) {
|
|
13
|
-
config.ui = {
|
|
14
|
-
theme: {
|
|
15
|
-
hues: {},
|
|
16
|
-
colors: {},
|
|
17
|
-
light: {
|
|
18
|
-
chroma: 0,
|
|
19
|
-
lightness: 0,
|
|
20
|
-
background: { lightness: 0, chroma: 0, hue: 0 },
|
|
21
|
-
text: { lightness: 0, chroma: 0, hue: 0 },
|
|
22
|
-
colors: {},
|
|
23
|
-
},
|
|
24
|
-
dark: {
|
|
25
|
-
chroma: 0,
|
|
26
|
-
lightness: 0,
|
|
27
|
-
background: { lightness: 0, chroma: 0, hue: 0 },
|
|
28
|
-
text: { lightness: 0, chroma: 0, hue: 0 },
|
|
29
|
-
colors: {},
|
|
30
|
-
},
|
|
31
|
-
},
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const theme = config.ui.theme;
|
|
36
|
-
|
|
37
|
-
atRule.walkDecls((decl: any) => {
|
|
38
|
-
const prop = decl.prop;
|
|
39
|
-
const value = decl.value;
|
|
40
|
-
|
|
41
|
-
// Hues: --hue-alpha: 0;
|
|
42
|
-
if (prop.startsWith("--hue-")) {
|
|
43
|
-
const name = prop.replace("--hue-", "");
|
|
44
|
-
theme.hues[name] = parseFloat(value);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
// Fixed Colors: --color-primary: 0.66 0.26 240;
|
|
48
|
-
else if (prop.startsWith("--color-")) {
|
|
49
|
-
const name = prop.replace("--color-", "");
|
|
50
|
-
const [l, c, h] = value.split(/\s+/).map(parseFloat);
|
|
51
|
-
theme.colors[name] = { lightness: l, chroma: c, hue: h };
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Theme Palettes: --light-lightness: 0.66;
|
|
55
|
-
else if (prop.startsWith("--light-") || prop.startsWith("--dark-")) {
|
|
56
|
-
const isLight = prop.startsWith("--light-");
|
|
57
|
-
const palette = isLight ? theme.light : theme.dark;
|
|
58
|
-
const key = prop.replace(isLight ? "--light-" : "--dark-", "");
|
|
59
|
-
|
|
60
|
-
if (key === "lightness") palette.lightness = parseFloat(value);
|
|
61
|
-
else if (key === "chroma") palette.chroma = parseFloat(value);
|
|
62
|
-
else if (key === "background" || key === "text") {
|
|
63
|
-
const [l, c, h] = value.split(/\s+/).map(parseFloat);
|
|
64
|
-
(palette as any)[key] = { lightness: l, chroma: c, hue: h };
|
|
65
|
-
} else {
|
|
66
|
-
// Custom colors in palette: --light-surface: 1 0 0;
|
|
67
|
-
// Also supports overrides like --light-color-primary: 0.8 0.1 240;
|
|
68
|
-
const cleanKey = key.replace(/^color-/, "");
|
|
69
|
-
const [l, c, h] = value.split(/\s+/).map(parseFloat);
|
|
70
|
-
palette.colors[cleanKey] = { lightness: l, chroma: c, hue: h };
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
// Remove the at-rule from CSS output
|
|
76
|
-
atRule.remove();
|
|
77
|
-
}
|
|
78
|
-
}
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import AtRule from "postcss/lib/at-rule";
|
|
2
|
-
// import type { ChildNode } from "postcss"; // AtRule is now a value import
|
|
3
|
-
import { PluginContext } from "../types.js";
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Custom PostCSS plugin handler for responsive at-rules.
|
|
7
|
-
*
|
|
8
|
-
* Example:
|
|
9
|
-
*
|
|
10
|
-
* @xs {
|
|
11
|
-
* .box { color: red; }
|
|
12
|
-
* }
|
|
13
|
-
*
|
|
14
|
-
* Into:
|
|
15
|
-
*
|
|
16
|
-
* @xs (min-width: 234px) {
|
|
17
|
-
* .box { color: red; }
|
|
18
|
-
* }
|
|
19
|
-
*
|
|
20
|
-
*/
|
|
21
|
-
export default function container(atRule: any, context: PluginContext) {
|
|
22
|
-
const { config } = context;
|
|
23
|
-
|
|
24
|
-
// Default breakpoints
|
|
25
|
-
const defaultBreakpoints: Record<string, string> = {
|
|
26
|
-
xs: "20rem",
|
|
27
|
-
sm: "40rem",
|
|
28
|
-
md: "48rem",
|
|
29
|
-
lg: "64rem",
|
|
30
|
-
xl: "80rem",
|
|
31
|
-
"2xl": "96rem",
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
// Merge with config if available (assuming config.ui.breakpoints exists)
|
|
35
|
-
const breakpoints = {
|
|
36
|
-
...defaultBreakpoints,
|
|
37
|
-
...((config as any).ui?.theme?.breakpoints || {}),
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
if (Object.keys(breakpoints).includes(atRule.name)) {
|
|
41
|
-
const minWidth = breakpoints[atRule.name];
|
|
42
|
-
|
|
43
|
-
const clonedNodes: any[] = [];
|
|
44
|
-
atRule.each((node: any) => {
|
|
45
|
-
clonedNodes.push(node.clone());
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
const containerAtRule = new AtRule({
|
|
49
|
-
name: "container",
|
|
50
|
-
params: `(min-width: ${minWidth})`,
|
|
51
|
-
source: atRule.source,
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
clonedNodes.forEach((node) => containerAtRule.append(node));
|
|
55
|
-
|
|
56
|
-
atRule.replaceWith(containerAtRule);
|
|
57
|
-
}
|
|
58
|
-
}
|
package/src/at-rules/import.ts
DELETED
|
@@ -1,196 +0,0 @@
|
|
|
1
|
-
import Rule from "postcss/lib/rule";
|
|
2
|
-
import Declaration from "postcss/lib/declaration";
|
|
3
|
-
import AtRule from "postcss/lib/at-rule";
|
|
4
|
-
import { PluginContext } from "../types.js";
|
|
5
|
-
import fs from "fs";
|
|
6
|
-
import path from "path";
|
|
7
|
-
import { fileURLToPath } from "url";
|
|
8
|
-
import postcss from "postcss";
|
|
9
|
-
|
|
10
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
11
|
-
const __dirname = path.dirname(__filename);
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Handler for @import "seyuna"
|
|
15
|
-
* Injects the core Seyuna Design System variables and base styles
|
|
16
|
-
*/
|
|
17
|
-
export function handleImport(atRule: any, context: PluginContext) {
|
|
18
|
-
// Support both @seyuna; and the previous @import "seyuna" logic
|
|
19
|
-
// Since this handler is now registered to @seyuna, we just check params or just run it.
|
|
20
|
-
const params = atRule.params.replace(/['"]/g, "").trim();
|
|
21
|
-
|
|
22
|
-
// If it's @seyuna; the params will be empty.
|
|
23
|
-
// If it's @import "seyuna", this handler wouldn't be called unless we kept the name "import".
|
|
24
|
-
// But we want this to run for @seyuna;
|
|
25
|
-
if (atRule.name === "seyuna") {
|
|
26
|
-
const { config, options } = context;
|
|
27
|
-
if (!config.ui) {
|
|
28
|
-
atRule.remove();
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const { theme } = config.ui;
|
|
33
|
-
const modeAttribute = options.modeAttribute;
|
|
34
|
-
const nodes: any[] = [];
|
|
35
|
-
|
|
36
|
-
// 1. Ingest Global Base Styles (Reset, Layers, etc.)
|
|
37
|
-
try {
|
|
38
|
-
const globalStylesPath = path.resolve(
|
|
39
|
-
__dirname,
|
|
40
|
-
"../styles/seyuna-global.css",
|
|
41
|
-
);
|
|
42
|
-
if (fs.existsSync(globalStylesPath)) {
|
|
43
|
-
const globalCss = fs.readFileSync(globalStylesPath, "utf-8");
|
|
44
|
-
const parsed = postcss.parse(globalCss);
|
|
45
|
-
|
|
46
|
-
// Push all nodes from the global styles (reset, layers, etc.)
|
|
47
|
-
parsed.nodes.forEach((node) => {
|
|
48
|
-
nodes.push(node.clone());
|
|
49
|
-
});
|
|
50
|
-
} else {
|
|
51
|
-
nodes.push(
|
|
52
|
-
new AtRule({
|
|
53
|
-
name: "layer",
|
|
54
|
-
params: "reset, base, components, utilities",
|
|
55
|
-
}),
|
|
56
|
-
);
|
|
57
|
-
}
|
|
58
|
-
} catch (e) {
|
|
59
|
-
console.warn("[Seyuna PostCSS] Could not load global base styles:", e);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// 2. Global Hues and Base Colors (:root)
|
|
63
|
-
const rootRule = new Rule({ selector: ":root", source: atRule.source });
|
|
64
|
-
|
|
65
|
-
// Process all hues from config
|
|
66
|
-
if (theme.hues) {
|
|
67
|
-
for (const [name, value] of Object.entries(theme.hues)) {
|
|
68
|
-
rootRule.append(
|
|
69
|
-
new Declaration({ prop: `--${name}-hue`, value: String(value) }),
|
|
70
|
-
);
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Add shared colors from theme.colors
|
|
75
|
-
if (theme.colors) {
|
|
76
|
-
for (const [name, color] of Object.entries(theme.colors)) {
|
|
77
|
-
rootRule.append(
|
|
78
|
-
new Declaration({
|
|
79
|
-
prop: `--${name}-lightness`,
|
|
80
|
-
value: String(color.lightness),
|
|
81
|
-
}),
|
|
82
|
-
);
|
|
83
|
-
rootRule.append(
|
|
84
|
-
new Declaration({
|
|
85
|
-
prop: `--${name}-chroma`,
|
|
86
|
-
value: String(color.chroma),
|
|
87
|
-
}),
|
|
88
|
-
);
|
|
89
|
-
rootRule.append(
|
|
90
|
-
new Declaration({ prop: `--${name}-hue`, value: String(color.hue) }),
|
|
91
|
-
);
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
nodes.push(rootRule);
|
|
95
|
-
|
|
96
|
-
// Helper to generate palette declarations for a specific mode
|
|
97
|
-
const getPaletteDecls = (palette: any) => {
|
|
98
|
-
const decls: Declaration[] = [];
|
|
99
|
-
|
|
100
|
-
if (palette.lightness !== undefined) {
|
|
101
|
-
decls.push(
|
|
102
|
-
new Declaration({
|
|
103
|
-
prop: "--lightness",
|
|
104
|
-
value: String(palette.lightness),
|
|
105
|
-
}),
|
|
106
|
-
);
|
|
107
|
-
}
|
|
108
|
-
if (palette.chroma !== undefined) {
|
|
109
|
-
decls.push(
|
|
110
|
-
new Declaration({ prop: "--chroma", value: String(palette.chroma) }),
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Standard background/text if they exist
|
|
115
|
-
if (palette.background) {
|
|
116
|
-
decls.push(
|
|
117
|
-
new Declaration({
|
|
118
|
-
prop: "--background",
|
|
119
|
-
value: `oklch(${palette.background.lightness} ${palette.background.chroma} ${palette.background.hue})`,
|
|
120
|
-
}),
|
|
121
|
-
);
|
|
122
|
-
}
|
|
123
|
-
if (palette.text) {
|
|
124
|
-
decls.push(
|
|
125
|
-
new Declaration({
|
|
126
|
-
prop: "--text",
|
|
127
|
-
value: `oklch(${palette.text.lightness} ${palette.text.chroma} ${palette.text.hue})`,
|
|
128
|
-
}),
|
|
129
|
-
);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (palette.colors) {
|
|
133
|
-
for (const [name, color] of Object.entries(palette.colors)) {
|
|
134
|
-
const c = color as any;
|
|
135
|
-
decls.push(
|
|
136
|
-
new Declaration({
|
|
137
|
-
prop: `--${name}-lightness`,
|
|
138
|
-
value: String(c.lightness),
|
|
139
|
-
}),
|
|
140
|
-
);
|
|
141
|
-
decls.push(
|
|
142
|
-
new Declaration({
|
|
143
|
-
prop: `--${name}-chroma`,
|
|
144
|
-
value: String(c.chroma),
|
|
145
|
-
}),
|
|
146
|
-
);
|
|
147
|
-
decls.push(
|
|
148
|
-
new Declaration({ prop: `--${name}-hue`, value: String(c.hue) }),
|
|
149
|
-
);
|
|
150
|
-
}
|
|
151
|
-
}
|
|
152
|
-
return decls;
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
// 3. Explicit Mode Selectors ([data-mode="..."])
|
|
156
|
-
if (theme.light) {
|
|
157
|
-
const lightRule = new Rule({
|
|
158
|
-
selector: `[${modeAttribute}="light"]`,
|
|
159
|
-
source: atRule.source,
|
|
160
|
-
});
|
|
161
|
-
lightRule.append(...getPaletteDecls(theme.light));
|
|
162
|
-
nodes.push(lightRule);
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
if (theme.dark) {
|
|
166
|
-
const darkRule = new Rule({
|
|
167
|
-
selector: `[${modeAttribute}="dark"]`,
|
|
168
|
-
source: atRule.source,
|
|
169
|
-
});
|
|
170
|
-
darkRule.append(...getPaletteDecls(theme.dark));
|
|
171
|
-
nodes.push(darkRule);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// 4. System Preference Support
|
|
175
|
-
const createSystemMedia = (scheme: "light" | "dark", palette: any) => {
|
|
176
|
-
const media = new AtRule({
|
|
177
|
-
name: "media",
|
|
178
|
-
params: `(prefers-color-scheme: ${scheme})`,
|
|
179
|
-
source: atRule.source,
|
|
180
|
-
});
|
|
181
|
-
const rule = new Rule({
|
|
182
|
-
selector: `[${modeAttribute}="system"]`,
|
|
183
|
-
source: atRule.source,
|
|
184
|
-
});
|
|
185
|
-
rule.append(...getPaletteDecls(palette));
|
|
186
|
-
media.append(rule);
|
|
187
|
-
return media;
|
|
188
|
-
};
|
|
189
|
-
|
|
190
|
-
if (theme.light) nodes.push(createSystemMedia("light", theme.light));
|
|
191
|
-
if (theme.dark) nodes.push(createSystemMedia("dark", theme.dark));
|
|
192
|
-
|
|
193
|
-
// Replace the @import rule with our generated CSS
|
|
194
|
-
atRule.replaceWith(...nodes);
|
|
195
|
-
}
|
|
196
|
-
}
|
package/src/at-rules/index.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
// import type { AtRule } from "postcss";
|
|
2
|
-
import { eachStandardColor, eachFixedColor } from "./color.js";
|
|
3
|
-
import container from "./container.js";
|
|
4
|
-
import { light, dark } from "./color-scheme.js";
|
|
5
|
-
import { handleImport } from "./import.js";
|
|
6
|
-
import { handleConfig } from "./config.js";
|
|
7
|
-
import { PluginContext } from "../types.js";
|
|
8
|
-
|
|
9
|
-
// Each handler has a name (matches the at-rule) and the function
|
|
10
|
-
export interface AtRuleHandler {
|
|
11
|
-
name: string;
|
|
12
|
-
handler: (atRule: any, context: PluginContext) => void;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
// Ordered array ensures execution order
|
|
16
|
-
export const atRuleHandlers: AtRuleHandler[] = [
|
|
17
|
-
{ name: "config", handler: handleConfig },
|
|
18
|
-
{ name: "seyuna", handler: handleImport },
|
|
19
|
-
{ name: "each-standard-color", handler: eachStandardColor },
|
|
20
|
-
{ name: "each-fixed-color", handler: eachFixedColor },
|
|
21
|
-
{ name: "light", handler: light },
|
|
22
|
-
{ name: "dark", handler: dark },
|
|
23
|
-
{ name: "xs", handler: container },
|
|
24
|
-
{ name: "sm", handler: container },
|
|
25
|
-
{ name: "md", handler: container },
|
|
26
|
-
{ name: "lg", handler: container },
|
|
27
|
-
{ name: "xl", handler: container },
|
|
28
|
-
{ name: "2xl", handler: container },
|
|
29
|
-
];
|
package/src/config.ts
DELETED
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
import path from "path";
|
|
3
|
-
import {
|
|
4
|
-
SeyunaConfig,
|
|
5
|
-
PluginOptions,
|
|
6
|
-
PluginContext,
|
|
7
|
-
FunctionMap,
|
|
8
|
-
} from "./types.js";
|
|
9
|
-
|
|
10
|
-
// Re-export types for backwards compatibility
|
|
11
|
-
export type { PluginOptions, PluginContext, FunctionMap } from "./types.js";
|
|
12
|
-
|
|
13
|
-
const DEFAULT_HUES = {
|
|
14
|
-
alpha: 15,
|
|
15
|
-
beta: 30,
|
|
16
|
-
gamma: 45,
|
|
17
|
-
delta: 60,
|
|
18
|
-
epsilon: 75,
|
|
19
|
-
zeta: 90,
|
|
20
|
-
eta: 105,
|
|
21
|
-
theta: 120,
|
|
22
|
-
iota: 135,
|
|
23
|
-
kappa: 150,
|
|
24
|
-
lambda: 165,
|
|
25
|
-
mu: 180,
|
|
26
|
-
nu: 195,
|
|
27
|
-
xi: 210,
|
|
28
|
-
omicron: 225,
|
|
29
|
-
pi: 240,
|
|
30
|
-
rho: 255,
|
|
31
|
-
sigma: 270,
|
|
32
|
-
tau: 285,
|
|
33
|
-
upsilon: 300,
|
|
34
|
-
phi: 315,
|
|
35
|
-
chi: 330,
|
|
36
|
-
psi: 345,
|
|
37
|
-
omega: 360,
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
const DEFAULT_OPTIONS: Required<PluginOptions> = {
|
|
41
|
-
config: undefined as any,
|
|
42
|
-
functions: undefined as any,
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
export function loadConfig(options: PluginOptions = {}): {
|
|
46
|
-
config: SeyunaConfig;
|
|
47
|
-
options: Required<PluginOptions> & { modeAttribute: string };
|
|
48
|
-
} {
|
|
49
|
-
const mergedOptions = { ...DEFAULT_OPTIONS, ...options };
|
|
50
|
-
|
|
51
|
-
const baseConfig: SeyunaConfig = {
|
|
52
|
-
ui: {
|
|
53
|
-
theme: {
|
|
54
|
-
hues: { ...DEFAULT_HUES },
|
|
55
|
-
colors: {},
|
|
56
|
-
light: {
|
|
57
|
-
chroma: 0,
|
|
58
|
-
lightness: 0,
|
|
59
|
-
background: { lightness: 0, chroma: 0, hue: 0 },
|
|
60
|
-
text: { lightness: 0, chroma: 0, hue: 0 },
|
|
61
|
-
colors: {},
|
|
62
|
-
},
|
|
63
|
-
dark: {
|
|
64
|
-
chroma: 0,
|
|
65
|
-
lightness: 0,
|
|
66
|
-
background: { lightness: 0, chroma: 0, hue: 0 },
|
|
67
|
-
text: { lightness: 0, chroma: 0, hue: 0 },
|
|
68
|
-
colors: {},
|
|
69
|
-
},
|
|
70
|
-
},
|
|
71
|
-
},
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
if (mergedOptions.config) {
|
|
75
|
-
// Deep merge or at least merge hues
|
|
76
|
-
const config = mergedOptions.config;
|
|
77
|
-
if (config.ui?.theme) {
|
|
78
|
-
config.ui.theme.hues = { ...DEFAULT_HUES, ...config.ui.theme.hues };
|
|
79
|
-
}
|
|
80
|
-
return {
|
|
81
|
-
config: config,
|
|
82
|
-
options: { ...mergedOptions, modeAttribute: "data-mode" },
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Return base config with defaults
|
|
87
|
-
return {
|
|
88
|
-
config: baseConfig,
|
|
89
|
-
options: { ...mergedOptions, modeAttribute: "data-mode" },
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export async function loadConfigAsync(options: PluginOptions = {}): Promise<{
|
|
94
|
-
config: SeyunaConfig;
|
|
95
|
-
options: Required<PluginOptions> & { modeAttribute: string };
|
|
96
|
-
}> {
|
|
97
|
-
return loadConfig(options);
|
|
98
|
-
}
|
package/src/errors.ts
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
// import type { Node } from 'postcss';
|
|
2
|
-
import { PluginContext } from "./types.js";
|
|
3
|
-
|
|
4
|
-
export function reportError(
|
|
5
|
-
message: string,
|
|
6
|
-
node: any,
|
|
7
|
-
context: PluginContext,
|
|
8
|
-
options: { word?: string; index?: number } = {},
|
|
9
|
-
) {
|
|
10
|
-
const { options: pluginOptions } = context;
|
|
11
|
-
const formattedMessage = `[Seyuna PostCSS] ${message}`;
|
|
12
|
-
|
|
13
|
-
reportWarning(formattedMessage, node, context);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export function reportWarning(
|
|
17
|
-
message: string,
|
|
18
|
-
node: any,
|
|
19
|
-
context?: PluginContext,
|
|
20
|
-
) {
|
|
21
|
-
if (context?.result) {
|
|
22
|
-
node.warn(context.result, `[Seyuna PostCSS] ${message}`);
|
|
23
|
-
} else {
|
|
24
|
-
// Fallback if no result is available (should not happen in main flow)
|
|
25
|
-
console.warn(`[Seyuna PostCSS Warning] ${message}`);
|
|
26
|
-
}
|
|
27
|
-
}
|
package/src/functions/color.ts
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
import { PluginContext } from "../types.js";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Resolves a color name to its CSS variables based on its type (standard or fixed)
|
|
5
|
-
*/
|
|
6
|
-
function getColorVariables(
|
|
7
|
-
context: PluginContext,
|
|
8
|
-
color: string,
|
|
9
|
-
type?: "sc" | "fc",
|
|
10
|
-
) {
|
|
11
|
-
const { config } = context;
|
|
12
|
-
const hues = config?.ui?.theme?.hues || {};
|
|
13
|
-
const colors = config?.ui?.theme?.colors || {};
|
|
14
|
-
const lightColors = config?.ui?.theme?.light?.colors || {};
|
|
15
|
-
const darkColors = config?.ui?.theme?.dark?.colors || {};
|
|
16
|
-
|
|
17
|
-
// If explicitly typed, trust the type and generate appropriate variables
|
|
18
|
-
if (type === "sc") {
|
|
19
|
-
return {
|
|
20
|
-
l: "var(--lightness)",
|
|
21
|
-
c: "var(--chroma)",
|
|
22
|
-
h: `var(--${color}-hue)`,
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
if (type === "fc") {
|
|
26
|
-
return {
|
|
27
|
-
l: `var(--${color}-lightness)`,
|
|
28
|
-
c: `var(--${color}-chroma)`,
|
|
29
|
-
h: `var(--${color}-hue)`,
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
// Auto-detect based on config
|
|
34
|
-
const isStandard = color in hues;
|
|
35
|
-
const isFixed =
|
|
36
|
-
color in colors || color in lightColors || color in darkColors;
|
|
37
|
-
|
|
38
|
-
if (isStandard && !isFixed) {
|
|
39
|
-
return {
|
|
40
|
-
l: "var(--lightness)",
|
|
41
|
-
c: "var(--chroma)",
|
|
42
|
-
h: `var(--${color}-hue)`,
|
|
43
|
-
};
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (isFixed && !isStandard) {
|
|
47
|
-
return {
|
|
48
|
-
l: `var(--${color}-lightness)`,
|
|
49
|
-
c: `var(--${color}-chroma)`,
|
|
50
|
-
h: `var(--${color}-hue)`,
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
// Resilient fallback (graceful degradation for multi-file scenarios or name collisions)
|
|
55
|
-
// Use specific color variable if it exists, otherwise fall back to theme defaults
|
|
56
|
-
return {
|
|
57
|
-
l: `var(--${color}-lightness, var(--lightness))`,
|
|
58
|
-
c: `var(--${color}-chroma, var(--chroma))`,
|
|
59
|
-
h: `var(--${color}-hue)`,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export function SeyunaStandardColor(
|
|
64
|
-
context: PluginContext,
|
|
65
|
-
name: string,
|
|
66
|
-
alpha?: string,
|
|
67
|
-
lightness?: string,
|
|
68
|
-
chroma?: string,
|
|
69
|
-
) {
|
|
70
|
-
const vars = getColorVariables(context, name, "sc");
|
|
71
|
-
const a = alpha && alpha !== "null" ? alpha : "1";
|
|
72
|
-
const l = lightness && lightness !== "null" ? lightness : vars.l;
|
|
73
|
-
const c = chroma && chroma !== "null" ? chroma : vars.c;
|
|
74
|
-
|
|
75
|
-
return `oklch(${l} ${c} ${vars.h} / ${a})`;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export function SeyunaFixedColor(
|
|
79
|
-
context: PluginContext,
|
|
80
|
-
name: string,
|
|
81
|
-
alpha?: string,
|
|
82
|
-
lightness?: string,
|
|
83
|
-
chroma?: string,
|
|
84
|
-
) {
|
|
85
|
-
const vars = getColorVariables(context, name, "fc");
|
|
86
|
-
const a = alpha && alpha !== "null" ? alpha : "1";
|
|
87
|
-
const l = lightness && lightness !== "null" ? lightness : vars.l;
|
|
88
|
-
const c = chroma && chroma !== "null" ? chroma : vars.c;
|
|
89
|
-
|
|
90
|
-
return `oklch(${l} ${c} ${vars.h} / ${a})`;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
export function SeyunaAlpha(
|
|
94
|
-
context: PluginContext,
|
|
95
|
-
color: string,
|
|
96
|
-
value: string,
|
|
97
|
-
) {
|
|
98
|
-
const { l, c, h } = getColorVariables(context, color);
|
|
99
|
-
return `oklch(${l} ${c} ${h} / ${value})`;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
export function SeyunaLighten(
|
|
103
|
-
context: PluginContext,
|
|
104
|
-
color: string,
|
|
105
|
-
amount: string,
|
|
106
|
-
) {
|
|
107
|
-
const { l, c, h } = getColorVariables(context, color);
|
|
108
|
-
return `oklch(calc(${l} + ${amount}) ${c} ${h} / 1)`;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
export function SeyunaDarken(
|
|
112
|
-
context: PluginContext,
|
|
113
|
-
color: string,
|
|
114
|
-
amount: string,
|
|
115
|
-
) {
|
|
116
|
-
const { l, c, h } = getColorVariables(context, color);
|
|
117
|
-
return `oklch(calc(${l} - ${amount}) ${c} ${h} / 1)`;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
export function SeyunaContrast(context: PluginContext, color: string) {
|
|
121
|
-
const { l } = getColorVariables(context, color);
|
|
122
|
-
return `oklch(calc((${l} - 0.6) * -1000) 0 0)`;
|
|
123
|
-
}
|
package/src/functions/index.ts
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
SeyunaStandardColor,
|
|
3
|
-
SeyunaFixedColor,
|
|
4
|
-
SeyunaAlpha,
|
|
5
|
-
SeyunaLighten,
|
|
6
|
-
SeyunaDarken,
|
|
7
|
-
SeyunaContrast,
|
|
8
|
-
} from "./color.js";
|
|
9
|
-
import { SeyunaTheme } from "./theme.js";
|
|
10
|
-
import { PluginContext } from "../types.js";
|
|
11
|
-
|
|
12
|
-
export type FnHandler = (context: PluginContext, ...args: string[]) => string;
|
|
13
|
-
|
|
14
|
-
export const functions: Record<string, FnHandler> = {
|
|
15
|
-
SeyunaStandardColor,
|
|
16
|
-
SeyunaFixedColor,
|
|
17
|
-
SeyunaAlpha,
|
|
18
|
-
SeyunaLighten,
|
|
19
|
-
SeyunaDarken,
|
|
20
|
-
SeyunaContrast,
|
|
21
|
-
SeyunaTheme,
|
|
22
|
-
};
|
package/src/functions/theme.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { PluginContext } from "../types.js";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Accesses values from the Seyuna configuration using dot notation
|
|
5
|
-
* Example: theme(ui.theme.breakpoints.tablet)
|
|
6
|
-
*/
|
|
7
|
-
export function SeyunaTheme(context: PluginContext, path: string): string {
|
|
8
|
-
const parts = path.split('.');
|
|
9
|
-
let current: any = context.config;
|
|
10
|
-
|
|
11
|
-
for (const part of parts) {
|
|
12
|
-
if (current && typeof current === 'object' && part in current) {
|
|
13
|
-
current = current[part];
|
|
14
|
-
} else {
|
|
15
|
-
return path; // Return original path if not found
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
return String(current);
|
|
20
|
-
}
|