@seyuna/postcss 1.0.0-canary.2 → 1.0.0-canary.20

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.
Files changed (58) hide show
  1. package/.github/workflows/release.yml +1 -1
  2. package/CHANGELOG.md +139 -0
  3. package/README.md +275 -0
  4. package/dist/at-rules/color-scheme.d.ts +4 -0
  5. package/dist/at-rules/color-scheme.js +43 -0
  6. package/dist/at-rules/color.d.ts +10 -0
  7. package/dist/at-rules/color.js +30 -0
  8. package/dist/at-rules/container.d.ts +19 -0
  9. package/dist/at-rules/container.js +48 -0
  10. package/dist/at-rules/index.d.ts +7 -3
  11. package/dist/at-rules/index.js +16 -13
  12. package/dist/config.d.ts +6 -0
  13. package/dist/config.js +47 -0
  14. package/dist/errors.d.ts +7 -0
  15. package/dist/errors.js +14 -0
  16. package/dist/functions/color.d.ts +7 -1
  17. package/dist/functions/color.js +59 -14
  18. package/dist/functions/index.d.ts +2 -1
  19. package/dist/functions/index.js +10 -11
  20. package/dist/functions/theme.d.ts +6 -0
  21. package/dist/functions/theme.js +17 -0
  22. package/dist/helpers.d.ts +11 -0
  23. package/dist/helpers.js +54 -0
  24. package/dist/index.d.ts +3 -3
  25. package/dist/index.js +6 -5
  26. package/dist/parser.d.ts +4 -0
  27. package/dist/parser.js +59 -0
  28. package/dist/plugin.d.ts +1 -3
  29. package/dist/plugin.js +22 -22
  30. package/dist/types.d.ts +59 -0
  31. package/dist/types.js +3 -0
  32. package/package.json +15 -5
  33. package/release.config.mjs +6 -1
  34. package/src/at-rules/color-scheme.ts +52 -0
  35. package/src/at-rules/color.ts +33 -0
  36. package/src/at-rules/container.ts +57 -0
  37. package/src/at-rules/index.ts +23 -9
  38. package/src/config.ts +59 -0
  39. package/src/errors.ts +23 -0
  40. package/src/functions/color.ts +80 -14
  41. package/src/functions/index.ts +11 -5
  42. package/src/functions/theme.ts +20 -0
  43. package/src/helpers.ts +74 -0
  44. package/src/index.ts +5 -3
  45. package/src/parser.ts +81 -0
  46. package/src/plugin.ts +21 -23
  47. package/src/types.ts +72 -0
  48. package/tests/plugin.test.ts +143 -0
  49. package/tsconfig.json +2 -2
  50. package/dist/at-rules/dark.d.ts +0 -2
  51. package/dist/at-rules/dark.js +0 -28
  52. package/dist/at-rules/light.d.ts +0 -2
  53. package/dist/at-rules/light.js +0 -28
  54. package/dist/functions/spacing.d.ts +0 -1
  55. package/dist/functions/spacing.js +0 -6
  56. package/src/at-rules/dark.ts +0 -33
  57. package/src/at-rules/light.ts +0 -33
  58. package/src/functions/spacing.ts +0 -3
@@ -24,7 +24,7 @@ jobs:
24
24
  - name: Setup Node.js with npm auth
25
25
  uses: actions/setup-node@v4
26
26
  with:
27
- node-version: 20
27
+ node-version: 22
28
28
  registry-url: https://registry.npmjs.org/
29
29
  scope: "@seyuna"
30
30
  always-auth: true
package/CHANGELOG.md CHANGED
@@ -1,3 +1,142 @@
1
+ # [1.0.0-canary.20](https://github.com/seyuna-corp/seyuna-postcss/compare/v1.0.0-canary.19...v1.0.0-canary.20) (2026-01-10)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * remove @seyuna/cli dependency to prevent bundler loading Deno polyfills ([544a37e](https://github.com/seyuna-corp/seyuna-postcss/commit/544a37e412fcfd585c1dbcdfe28484ce63bec3c1))
7
+
8
+ # [1.0.0-canary.19](https://github.com/seyuna-corp/seyuna-postcss/compare/v1.0.0-canary.18...v1.0.0-canary.19) (2026-01-10)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * define types locally to avoid @seyuna/cli polyfill side-effects ([acdbcc9](https://github.com/seyuna-corp/seyuna-postcss/commit/acdbcc977fd2a501302d675ff7ffd2c307e25a95))
14
+
15
+ # [1.0.0-canary.18](https://github.com/seyuna-corp/seyuna-postcss/compare/v1.0.0-canary.17...v1.0.0-canary.18) (2026-01-10)
16
+
17
+
18
+ ### Bug Fixes
19
+
20
+ * break circular dependency between config.ts and parser.ts ([88ae984](https://github.com/seyuna-corp/seyuna-postcss/commit/88ae9848ed2eb4d4ca5fb6340cbe5aa1c986f1b8))
21
+
22
+ # [1.0.0-canary.17](https://github.com/seyuna-corp/seyuna-postcss/compare/v1.0.0-canary.16...v1.0.0-canary.17) (2026-01-10)
23
+
24
+
25
+ ### Bug Fixes
26
+
27
+ * transition to proper ESM with correct file extensions ([b330b4f](https://github.com/seyuna-corp/seyuna-postcss/commit/b330b4fcd3394b78ecc39ef5f23f5e993bd425be))
28
+
29
+ # [1.0.0-canary.16](https://github.com/seyuna-corp/seyuna-postcss/compare/v1.0.0-canary.15...v1.0.0-canary.16) (2026-01-10)
30
+
31
+
32
+ ### Bug Fixes
33
+
34
+ * Fixed release configuration. ([3e7f764](https://github.com/seyuna-corp/seyuna-postcss/commit/3e7f76488e109110cbec50cb4c5bdc89397b3b40))
35
+ * release configuration error. ([076eb34](https://github.com/seyuna-corp/seyuna-postcss/commit/076eb348d2ce7ca61bbc1c7a9ad597cadbe59f34))
36
+
37
+ # [1.0.0-canary.15](https://github.com/seyuna-corp/seyuna-postcss/compare/v1.0.0-canary.14...v1.0.0-canary.15) (2026-01-09)
38
+
39
+
40
+ ### Bug Fixes
41
+
42
+ * workflow node version upgrade. ([e98349a](https://github.com/seyuna-corp/seyuna-postcss/commit/e98349af69aab446f0ac4d0790112d5c702c1b36))
43
+
44
+ # [1.0.0-canary.14](https://github.com/seyuna-corp/seyuna-postcss/compare/v1.0.0-canary.13...v1.0.0-canary.14) (2025-10-09)
45
+
46
+
47
+ ### Bug Fixes
48
+
49
+ * bug in generateRules ([d5b66d3](https://github.com/seyuna-corp/seyuna-postcss/commit/d5b66d32786f554c0e4f7ea98ae526e7f7ac82c5))
50
+ * removed pnpm lock file that ([6d87d61](https://github.com/seyuna-corp/seyuna-postcss/commit/6d87d616a79a2a539b09dea26bc907dee1d437e2))
51
+ * updated lock file ([d52dcfb](https://github.com/seyuna-corp/seyuna-postcss/commit/d52dcfb2bccbd502d744ceb09aa83394df4ac057))
52
+
53
+ # [1.0.0-canary.13](https://github.com/seyuna-corp/seyuna-postcss/compare/v1.0.0-canary.12...v1.0.0-canary.13) (2025-10-07)
54
+
55
+
56
+ ### Bug Fixes
57
+
58
+ * safely clone nodes and replace {name} placeholders ([8a68ee6](https://github.com/seyuna-corp/seyuna-postcss/commit/8a68ee6f1ade947639151bdbf365c102aa439d37))
59
+
60
+ # [1.0.0-canary.12](https://github.com/seyuna-corp/seyuna-postcss/compare/v1.0.0-canary.11...v1.0.0-canary.12) (2025-09-15)
61
+
62
+
63
+ ### Bug Fixes
64
+
65
+ * color functions not running when used inside at-each rules ([995fd98](https://github.com/seyuna-corp/seyuna-postcss/commit/995fd9816f2c2d51caa67add4d3172cee41d0c65))
66
+
67
+ # [1.0.0-canary.11](https://github.com/seyuna-corp/seyuna-postcss/compare/v1.0.0-canary.10...v1.0.0-canary.11) (2025-09-15)
68
+
69
+
70
+ ### Bug Fixes
71
+
72
+ * nested rules for at-each-standard-color & at-each-fixed-color ([197a755](https://github.com/seyuna-corp/seyuna-postcss/commit/197a75542798ecacaa071802b2abbf962bcd6538))
73
+
74
+ # [1.0.0-canary.10](https://github.com/seyuna-corp/seyuna-postcss/compare/v1.0.0-canary.9...v1.0.0-canary.10) (2025-09-10)
75
+
76
+
77
+ ### Bug Fixes
78
+
79
+ * registered each breakpoint to the same handler for at-rule `container` ([f3f5b36](https://github.com/seyuna-corp/seyuna-postcss/commit/f3f5b3665291dc94e92f3f7c2b2a576b4bdb4517))
80
+
81
+ # [1.0.0-canary.9](https://github.com/seyuna-corp/seyuna-postcss/compare/v1.0.0-canary.8...v1.0.0-canary.9) (2025-09-10)
82
+
83
+
84
+ ### Bug Fixes
85
+
86
+ * colors selector in at-rule `each-fixed-color` ([31adb28](https://github.com/seyuna-corp/seyuna-postcss/commit/31adb28f3576a0dcfb78a9aadf331ee4b7ef3e0c))
87
+
88
+ # [1.0.0-canary.8](https://github.com/seyuna-corp/seyuna-postcss/compare/v1.0.0-canary.7...v1.0.0-canary.8) (2025-09-10)
89
+
90
+
91
+ ### Features
92
+
93
+ * added at-rule `each-fixed-color` ([699ee0d](https://github.com/seyuna-corp/seyuna-postcss/commit/699ee0defd1fbb0ff91a90c1e13358b1ef9832b2))
94
+
95
+
96
+ ### BREAKING CHANGES
97
+
98
+ * at-rule `each-seyuna-color` renamed to `each-standard-color`
99
+
100
+ # [1.0.0-canary.7](https://github.com/seyuna-corp/seyuna-postcss/compare/v1.0.0-canary.6...v1.0.0-canary.7) (2025-09-10)
101
+
102
+
103
+ ### Features
104
+
105
+ * Added at-rule ([8a08289](https://github.com/seyuna-corp/seyuna-postcss/commit/8a08289023f4aa6f65d56e10697e64d02444f118))
106
+
107
+ # [1.0.0-canary.6](https://github.com/seyuna-corp/seyuna-postcss/compare/v1.0.0-canary.5...v1.0.0-canary.6) (2025-09-09)
108
+
109
+
110
+ ### Features
111
+
112
+ * add new color function 'fc' ([70e961f](https://github.com/seyuna-corp/seyuna-postcss/commit/70e961fb0b0a13e358de15b42a87b7890f3fc5c0))
113
+
114
+
115
+ ### BREAKING CHANGES
116
+
117
+ * changed how 'sc' functions, not backward-compatible
118
+
119
+ # [1.0.0-canary.5](https://github.com/seyuna-corp/seyuna-postcss/compare/v1.0.0-canary.4...v1.0.0-canary.5) (2025-08-25)
120
+
121
+
122
+ ### Bug Fixes
123
+
124
+ * changed color function name to sc to avoid conflicts with the default css color() function ([a46e96c](https://github.com/seyuna-corp/seyuna-postcss/commit/a46e96c74839f930d39a2c273c822a689a942783))
125
+
126
+ # [1.0.0-canary.4](https://github.com/seyuna-corp/seyuna-postcss/compare/v1.0.0-canary.3...v1.0.0-canary.4) (2025-08-24)
127
+
128
+
129
+ ### Bug Fixes
130
+
131
+ * at-rules for mode now ensure that [data-mode=system] before enforcing prefers-color-scheme ([475055d](https://github.com/seyuna-corp/seyuna-postcss/commit/475055db1d5662d25631953af669bf64b2e0468e))
132
+
133
+ # [1.0.0-canary.3](https://github.com/seyuna-corp/seyuna-postcss/compare/v1.0.0-canary.2...v1.0.0-canary.3) (2025-08-24)
134
+
135
+
136
+ ### Bug Fixes
137
+
138
+ * prioritized data-mode over prefers-color-scheme for [@dark](https://github.com/dark) & [@light](https://github.com/light) rules ([1dafbe7](https://github.com/seyuna-corp/seyuna-postcss/commit/1dafbe74c2ceae8faf28f55ac64846e9e752405b))
139
+
1
140
  # [1.0.0-canary.2](https://github.com/seyuna-corp/seyuna-postcss/compare/v1.0.0-canary.1...v1.0.0-canary.2) (2025-08-08)
2
141
 
3
142
 
package/README.md ADDED
@@ -0,0 +1,275 @@
1
+ # @seyuna/postcss
2
+
3
+ [![NPM Version](https://img.shields.io/npm/v/@seyuna/postcss.svg)](https://www.npmjs.com/package/@seyuna/postcss)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ > Build interfaces that transcend resolution.
7
+
8
+ ---
9
+
10
+ ## What is this
11
+
12
+ Seyuna PostCSS is the engine behind the Seyuna design system. It compiles a declarative color configuration into fully functional CSS, handles theme switching, and provides a suite of utilities that make authoring stylesheets faster and more intuitive.
13
+
14
+ The core philosophy is simple: **design once at 1080p, deploy everywhere**. Seyuna UI handles upscaling automatically through viewport-relative font sizing. The result is pixel-perfect consistency from a laptop to a 4K display without breakpoints, without media queries, without you lifting a finger.
15
+
16
+ ```css
17
+ html {
18
+ font-size: max(1rem, 0.833vw);
19
+ }
20
+ ```
21
+
22
+ This single line is the foundation. At 1920px viewport width, `0.833vw` equals exactly `16px`. Everything scales proportionally. No more designing three versions of every component.
23
+
24
+ ---
25
+
26
+ ## Installation
27
+
28
+ ```bash
29
+ npm install @seyuna/postcss postcss-import postcss-advanced-variables postcss-preset-env --save-dev
30
+ ```
31
+
32
+ ---
33
+
34
+ ## Configuration
35
+
36
+ Create a `postcss.config.js` at your project root:
37
+
38
+ ```javascript
39
+ import seyunaPostcss from '@seyuna/postcss';
40
+ import postcssImport from 'postcss-import';
41
+ import postcssAdvancedVariables from 'postcss-advanced-variables';
42
+ import postcssPresetEnv from 'postcss-preset-env';
43
+
44
+ export default {
45
+ plugins: [
46
+ seyunaPostcss({
47
+ configPath: 'seyuna.json',
48
+ modeAttribute: 'data-mode',
49
+ }),
50
+ postcssImport,
51
+ postcssAdvancedVariables,
52
+ postcssPresetEnv({
53
+ stage: 3,
54
+ features: {
55
+ 'nesting-rules': true,
56
+ },
57
+ }),
58
+ ],
59
+ };
60
+ ```
61
+
62
+ The plugin reads from `seyuna.json` at build time. This file is your single source of truth for colors, themes, and any other design tokens you want accessible in CSS.
63
+
64
+ ---
65
+
66
+ ## The Color Model
67
+
68
+ Seyuna operates entirely in the OKLCH color space. Unlike HSL or RGB, OKLCH is perceptually uniform. A lightness of `0.66` looks equally bright across all hues. This makes it possible to build harmonious palettes programmatically.
69
+
70
+ ### Standard Colors
71
+
72
+ Standard colors are hue-only tokens. They inherit the global `--lightness` and `--chroma` values from the current theme mode. When the user switches from light to dark, every standard color adapts automatically.
73
+
74
+ ```css
75
+ .button {
76
+ background: sc(primary);
77
+ }
78
+ ```
79
+
80
+ Compiles to:
81
+
82
+ ```css
83
+ .button {
84
+ background: oklch(var(--lightness) var(--chroma) var(--primary-hue) / 1);
85
+ }
86
+ ```
87
+
88
+ ### Fixed Colors
89
+
90
+ Fixed colors are absolute. They define their own lightness, chroma, and hue. Use these for colors that must remain constant regardless of theme, like brand logos or semantic status indicators.
91
+
92
+ ```css
93
+ .badge {
94
+ background: fc(white);
95
+ }
96
+ ```
97
+
98
+ Compiles to:
99
+
100
+ ```css
101
+ .badge {
102
+ background: oklch(var(--white-lightness) var(--white-chroma) var(--white-hue) / 1);
103
+ }
104
+ ```
105
+
106
+ ---
107
+
108
+ ## Color Manipulation
109
+
110
+ All color functions accept a color name from your configuration.
111
+
112
+ | Function | Purpose | Example |
113
+ |:----------------------|:-----------------------------------------|:----------------------------|
114
+ | `alpha(color, value)` | Adjusts opacity | `alpha(primary, 0.5)` |
115
+ | `lighten(color, amt)` | Increases lightness by `amt` | `lighten(primary, 0.1)` |
116
+ | `darken(color, amt)` | Decreases lightness by `amt` | `darken(primary, 0.1)` |
117
+ | `contrast(color)` | Returns black or white based on lightness| `color: contrast(surface);` |
118
+
119
+ The `contrast()` function uses a dynamic CSS calculation internally. It does not bake in a static value. If `--surface-lightness` changes at runtime, the contrast color updates with it.
120
+
121
+ ---
122
+
123
+ ## Theme Switching
124
+
125
+ Seyuna supports three modes: `light`, `dark`, and `system`. The system mode respects `prefers-color-scheme`. All switching is handled via the `data-mode` attribute on your root element.
126
+
127
+ ```html
128
+ <html data-mode="system">
129
+ ```
130
+
131
+ The compiled CSS contains rules for all three states:
132
+
133
+ ```css
134
+ [data-mode="light"] {
135
+ --lightness: 0.66;
136
+ --chroma: 0.26;
137
+ }
138
+
139
+ @media (prefers-color-scheme: dark) {
140
+ [data-mode="system"] {
141
+ --lightness: 0.66;
142
+ --chroma: 0.26;
143
+ }
144
+ }
145
+ ```
146
+
147
+ ### In-CSS Overrides
148
+
149
+ Need a component to look different in dark mode? Use the `@dark` and `@light` at-rules directly in your stylesheet:
150
+
151
+ ```css
152
+ .card {
153
+ background: fc(white);
154
+
155
+ @dark {
156
+ background: fc(black);
157
+ }
158
+ }
159
+ ```
160
+
161
+ ---
162
+
163
+ ## Container Queries
164
+
165
+ Seyuna ships with shorthand breakpoints that compile to CSS Container Queries instead of traditional media queries. This means components respond to their container size, not the viewport.
166
+
167
+ ```css
168
+ .grid {
169
+ display: grid;
170
+ grid-template-columns: 1fr;
171
+
172
+ @md {
173
+ grid-template-columns: repeat(2, 1fr);
174
+ }
175
+
176
+ @lg {
177
+ grid-template-columns: repeat(3, 1fr);
178
+ }
179
+ }
180
+ ```
181
+
182
+ Available breakpoints:
183
+
184
+ | At-Rule | Container Width |
185
+ |:--------|:----------------|
186
+ | `@xs` | 20rem |
187
+ | `@sm` | 30rem |
188
+ | `@md` | 48rem |
189
+ | `@lg` | 62rem |
190
+ | `@xl` | 80rem |
191
+ | `@2xl` | 96rem |
192
+
193
+ ---
194
+
195
+ ## Configuration Reference
196
+
197
+ ```json
198
+ {
199
+ "ui": {
200
+ "theme": {
201
+ "hues": {
202
+ "primary": 240,
203
+ "secondary": 30,
204
+ "accent": 150
205
+ },
206
+ "colors": {
207
+ "white": { "lightness": 1, "chroma": 0, "hue": 0 },
208
+ "black": { "lightness": 0, "chroma": 0, "hue": 0 }
209
+ },
210
+ "light": {
211
+ "lightness": 0.66,
212
+ "chroma": 0.26,
213
+ "background": { "lightness": 1, "chroma": 0, "hue": 0 },
214
+ "text": { "lightness": 0, "chroma": 0, "hue": 0 }
215
+ },
216
+ "dark": {
217
+ "lightness": 0.66,
218
+ "chroma": 0.26,
219
+ "background": { "lightness": 0, "chroma": 0, "hue": 0 },
220
+ "text": { "lightness": 1, "chroma": 0, "hue": 0 }
221
+ }
222
+ },
223
+ "mode": "system",
224
+ "output_dir": "src/styles"
225
+ }
226
+ }
227
+ ```
228
+
229
+ `hues` defines standard colors. Only the hue angle is specified because lightness and chroma come from the theme mode.
230
+
231
+ `colors` defines fixed colors with explicit lightness, chroma, and hue values.
232
+
233
+ `light` and `dark` set the global lightness and chroma for standard colors, plus any mode-specific fixed colors like background and text.
234
+
235
+ ---
236
+
237
+ ## Palette Iteration
238
+
239
+ Generate utility classes by iterating over your entire color configuration:
240
+
241
+ ```css
242
+ @each-standard-color {
243
+ .bg-{name} {
244
+ background-color: sc({name});
245
+ }
246
+ }
247
+
248
+ @each-fixed-color {
249
+ .text-{name} {
250
+ color: fc({name});
251
+ }
252
+ }
253
+ ```
254
+
255
+ ---
256
+
257
+ ## The Reset Layer
258
+
259
+ Seyuna UI generates a CSS file that includes a minimal, opinionated reset. It zeroes out margins and padding, removes default list styles, and sets sensible defaults for text rendering. The reset is applied to the `reset` layer, so your styles can override it without specificity battles.
260
+
261
+ The upscaling magic happens here:
262
+
263
+ ```css
264
+ html {
265
+ font-size: max(1rem, 0.833vw);
266
+ }
267
+ ```
268
+
269
+ At 1920px, the computed font size is 16px. At 2560px, it becomes roughly 21px. Every `rem` value in your stylesheet scales accordingly. Design at 1080p. Ship at any resolution.
270
+
271
+ ---
272
+
273
+ ## License
274
+
275
+ MIT
@@ -0,0 +1,4 @@
1
+ import { AtRule } from "postcss";
2
+ import { PluginContext } from "../types.js";
3
+ export declare const light: (atRule: AtRule, context: PluginContext) => void;
4
+ export declare const dark: (atRule: AtRule, context: PluginContext) => void;
@@ -0,0 +1,43 @@
1
+ import { Rule, AtRule } from "postcss";
2
+ /**
3
+ * Custom PostCSS plugin handler factory for `@light` and `@dark` at-rules.
4
+ */
5
+ function createColorSchemeHandler(scheme) {
6
+ return (atRule, context) => {
7
+ const { options } = context;
8
+ const modeAttribute = options.modeAttribute;
9
+ const clonedNodes = [];
10
+ // Clone all child nodes inside the block
11
+ atRule.each((node) => {
12
+ clonedNodes.push(node.clone());
13
+ });
14
+ /**
15
+ * Rule 1: [data-mode="scheme"] & { ... } (Explicit mode)
16
+ */
17
+ const explicitRule = new Rule({
18
+ selector: `[${modeAttribute}="${scheme}"] &`,
19
+ source: atRule.source,
20
+ });
21
+ clonedNodes.forEach((node) => explicitRule.append(node.clone()));
22
+ /**
23
+ * Rule 2: @media (prefers-color-scheme: scheme) { [data-mode="system"] & { ... } } (System preference)
24
+ */
25
+ const mediaAtRule = new AtRule({
26
+ name: "media",
27
+ params: `(prefers-color-scheme: ${scheme})`,
28
+ source: atRule.source,
29
+ });
30
+ const systemRule = new Rule({
31
+ selector: `[${modeAttribute}="system"] &`,
32
+ source: atRule.source,
33
+ });
34
+ clonedNodes.forEach((node) => systemRule.append(node.clone()));
35
+ mediaAtRule.append(systemRule);
36
+ /**
37
+ * Replace the original at-rule with the generated rules.
38
+ */
39
+ atRule.replaceWith(mediaAtRule, explicitRule);
40
+ };
41
+ }
42
+ export const light = createColorSchemeHandler('light');
43
+ export const dark = createColorSchemeHandler('dark');
@@ -0,0 +1,10 @@
1
+ import { AtRule } from "postcss";
2
+ import { PluginContext } from "../types.js";
3
+ /**
4
+ * Handler for @each-standard-color
5
+ */
6
+ export declare function eachStandardColor(atRule: AtRule, context: PluginContext): void;
7
+ /**
8
+ * Handler for @each-fixed-color
9
+ */
10
+ export declare function eachFixedColor(atRule: AtRule, context: PluginContext): void;
@@ -0,0 +1,30 @@
1
+ import { generateRules } from "../helpers.js";
2
+ /**
3
+ * Handler for @each-standard-color
4
+ */
5
+ export function eachStandardColor(atRule, context) {
6
+ const { config } = context;
7
+ const hueNames = config.ui ? Object.keys(config.ui.theme.hues) : [];
8
+ const rules = generateRules(hueNames, atRule, context);
9
+ if (rules.length)
10
+ atRule.replaceWith(...rules);
11
+ else
12
+ atRule.remove();
13
+ }
14
+ /**
15
+ * Handler for @each-fixed-color
16
+ */
17
+ export function eachFixedColor(atRule, context) {
18
+ const { config } = context;
19
+ const mergedNames = [
20
+ ...new Set([
21
+ ...(config.ui ? Object.keys(config.ui.theme.light.colors) : []),
22
+ ...(config.ui ? Object.keys(config.ui.theme.dark.colors) : []),
23
+ ]),
24
+ ];
25
+ const rules = generateRules(mergedNames, atRule, context);
26
+ if (rules.length)
27
+ atRule.replaceWith(...rules);
28
+ else
29
+ atRule.remove();
30
+ }
@@ -0,0 +1,19 @@
1
+ import { AtRule } from "postcss";
2
+ import { PluginContext } from "../types.js";
3
+ /**
4
+ * Custom PostCSS plugin handler for responsive at-rules.
5
+ *
6
+ * Example:
7
+ *
8
+ * @xs {
9
+ * .box { color: red; }
10
+ * }
11
+ *
12
+ * Into:
13
+ *
14
+ * @xs (min-width: 234px) {
15
+ * .box { color: red; }
16
+ * }
17
+ *
18
+ */
19
+ export default function container(atRule: AtRule, context: PluginContext): void;
@@ -0,0 +1,48 @@
1
+ import { AtRule } from "postcss";
2
+ /**
3
+ * Custom PostCSS plugin handler for responsive at-rules.
4
+ *
5
+ * Example:
6
+ *
7
+ * @xs {
8
+ * .box { color: red; }
9
+ * }
10
+ *
11
+ * Into:
12
+ *
13
+ * @xs (min-width: 234px) {
14
+ * .box { color: red; }
15
+ * }
16
+ *
17
+ */
18
+ export default function container(atRule, context) {
19
+ const { config } = context;
20
+ // Default breakpoints
21
+ const defaultBreakpoints = {
22
+ xs: "20rem",
23
+ sm: "40rem",
24
+ md: "48rem",
25
+ lg: "64rem",
26
+ xl: "80rem",
27
+ "2xl": "96rem",
28
+ };
29
+ // Merge with config if available (assuming config.ui.breakpoints exists)
30
+ const breakpoints = {
31
+ ...defaultBreakpoints,
32
+ ...(config.ui?.theme?.breakpoints || {}),
33
+ };
34
+ if (Object.keys(breakpoints).includes(atRule.name)) {
35
+ const minWidth = breakpoints[atRule.name];
36
+ const clonedNodes = [];
37
+ atRule.each((node) => {
38
+ clonedNodes.push(node.clone());
39
+ });
40
+ const containerAtRule = new AtRule({
41
+ name: "container",
42
+ params: `(min-width: ${minWidth})`,
43
+ source: atRule.source,
44
+ });
45
+ clonedNodes.forEach((node) => containerAtRule.append(node));
46
+ atRule.replaceWith(containerAtRule);
47
+ }
48
+ }
@@ -1,3 +1,7 @@
1
- import type { AtRule } from "postcss";
2
- export type AtRuleHandler = (atRule: AtRule) => void;
3
- export declare const atRuleHandlers: Record<string, AtRuleHandler>;
1
+ import { AtRule } from "postcss";
2
+ import { PluginContext } from "../types.js";
3
+ export interface AtRuleHandler {
4
+ name: string;
5
+ handler: (atRule: AtRule, context: PluginContext) => void;
6
+ }
7
+ export declare const atRuleHandlers: AtRuleHandler[];
@@ -1,13 +1,16 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.atRuleHandlers = void 0;
7
- const dark_1 = __importDefault(require("./dark"));
8
- const light_1 = __importDefault(require("./light"));
9
- exports.atRuleHandlers = {
10
- light: light_1.default,
11
- dark: dark_1.default,
12
- // add more handlers here as needed
13
- };
1
+ import { eachStandardColor, eachFixedColor } from "./color.js";
2
+ import container from "./container.js";
3
+ import { light, dark } from "./color-scheme.js";
4
+ // Ordered array ensures execution order
5
+ export const atRuleHandlers = [
6
+ { name: "each-standard-color", handler: eachStandardColor },
7
+ { name: "each-fixed-color", handler: eachFixedColor },
8
+ { name: "light", handler: light },
9
+ { name: "dark", handler: dark },
10
+ { name: "xs", handler: container },
11
+ { name: "sm", handler: container },
12
+ { name: "md", handler: container },
13
+ { name: "lg", handler: container },
14
+ { name: "xl", handler: container },
15
+ { name: "2xl", handler: container },
16
+ ];
@@ -0,0 +1,6 @@
1
+ import { SeyunaConfig, PluginOptions } from './types.js';
2
+ export type { PluginOptions, PluginContext, FunctionMap } from './types.js';
3
+ export declare function loadConfig(options?: PluginOptions): {
4
+ config: SeyunaConfig;
5
+ options: Required<PluginOptions>;
6
+ };
package/dist/config.js ADDED
@@ -0,0 +1,47 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ const DEFAULT_OPTIONS = {
4
+ configPath: 'seyuna.json',
5
+ modeAttribute: 'data-mode',
6
+ strict: false,
7
+ config: undefined,
8
+ functions: undefined,
9
+ };
10
+ let cachedConfig = null;
11
+ let cachedConfigPath = null;
12
+ export function loadConfig(options = {}) {
13
+ const mergedOptions = { ...DEFAULT_OPTIONS, ...options };
14
+ if (mergedOptions.config) {
15
+ return { config: mergedOptions.config, options: mergedOptions };
16
+ }
17
+ const configPath = path.resolve(process.cwd(), mergedOptions.configPath);
18
+ // Cache config if it's the same path
19
+ if (cachedConfig && cachedConfigPath === configPath) {
20
+ return { config: cachedConfig, options: mergedOptions };
21
+ }
22
+ try {
23
+ if (!fs.existsSync(configPath)) {
24
+ if (mergedOptions.strict) {
25
+ throw new Error(`Seyuna config not found at ${configPath}`);
26
+ }
27
+ return {
28
+ config: { ui: { theme: { hues: {}, light: { colors: {} }, dark: { colors: {} } } } },
29
+ options: mergedOptions,
30
+ };
31
+ }
32
+ const data = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
33
+ cachedConfig = data;
34
+ cachedConfigPath = configPath;
35
+ return { config: data, options: mergedOptions };
36
+ }
37
+ catch (error) {
38
+ if (mergedOptions.strict) {
39
+ throw error;
40
+ }
41
+ console.warn(`[Seyuna PostCSS] Warning: Failed to load config: ${error instanceof Error ? error.message : String(error)}`);
42
+ return {
43
+ config: { ui: { theme: { hues: {}, light: { colors: {} }, dark: { colors: {} } } } },
44
+ options: mergedOptions,
45
+ };
46
+ }
47
+ }