@seyuna/postcss 1.0.0-canary.15 → 1.0.0-canary.17

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 (50) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/README.md +168 -72
  3. package/dist/at-rules/color-scheme.d.ts +1 -1
  4. package/dist/at-rules/color.d.ts +1 -1
  5. package/dist/at-rules/color.js +1 -1
  6. package/dist/at-rules/container.d.ts +1 -1
  7. package/dist/at-rules/index.d.ts +1 -1
  8. package/dist/at-rules/index.js +4 -13
  9. package/dist/config.d.ts +2 -4
  10. package/dist/errors.d.ts +1 -1
  11. package/dist/functions/color.d.ts +1 -1
  12. package/dist/functions/color.js +27 -74
  13. package/dist/functions/index.d.ts +1 -1
  14. package/dist/functions/index.js +2 -2
  15. package/dist/functions/theme.d.ts +1 -1
  16. package/dist/helpers.d.ts +1 -1
  17. package/dist/helpers.js +1 -1
  18. package/dist/index.d.ts +2 -2
  19. package/dist/index.js +2 -2
  20. package/dist/parser.d.ts +1 -1
  21. package/dist/parser.js +1 -1
  22. package/dist/plugin.d.ts +1 -1
  23. package/dist/plugin.js +4 -5
  24. package/package.json +3 -1
  25. package/release.config.mjs +6 -1
  26. package/src/at-rules/color-scheme.ts +1 -1
  27. package/src/at-rules/color.ts +2 -2
  28. package/src/at-rules/container.ts +1 -1
  29. package/src/at-rules/index.ts +5 -14
  30. package/src/config.ts +2 -5
  31. package/src/errors.ts +1 -1
  32. package/src/functions/color.ts +46 -99
  33. package/src/functions/index.ts +3 -3
  34. package/src/functions/theme.ts +1 -1
  35. package/src/helpers.ts +2 -2
  36. package/src/index.ts +2 -2
  37. package/src/parser.ts +2 -2
  38. package/src/plugin.ts +4 -5
  39. package/test-import.mjs +2 -0
  40. package/tests/plugin.test.ts +36 -144
  41. package/tsconfig.json +2 -2
  42. package/dist/at-rules/conditional.d.ts +0 -6
  43. package/dist/at-rules/conditional.js +0 -29
  44. package/dist/at-rules/custom-media.d.ts +0 -15
  45. package/dist/at-rules/custom-media.js +0 -40
  46. package/dist/at-rules/mixin.d.ts +0 -10
  47. package/dist/at-rules/mixin.js +0 -37
  48. package/src/at-rules/conditional.ts +0 -34
  49. package/src/at-rules/custom-media.ts +0 -50
  50. package/src/at-rules/mixin.ts +0 -46
package/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
1
+ # [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)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * transition to proper ESM with correct file extensions ([b330b4f](https://github.com/seyuna-corp/seyuna-postcss/commit/b330b4fcd3394b78ecc39ef5f23f5e993bd425be))
7
+
8
+ # [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)
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * Fixed release configuration. ([3e7f764](https://github.com/seyuna-corp/seyuna-postcss/commit/3e7f76488e109110cbec50cb4c5bdc89397b3b40))
14
+ * release configuration error. ([076eb34](https://github.com/seyuna-corp/seyuna-postcss/commit/076eb348d2ce7ca61bbc1c7a9ad597cadbe59f34))
15
+
1
16
  # [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)
2
17
 
3
18
 
package/README.md CHANGED
@@ -3,25 +3,37 @@
3
3
  [![NPM Version](https://img.shields.io/npm/v/@seyuna/postcss.svg)](https://www.npmjs.com/package/@seyuna/postcss)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
5
 
6
- > The official PostCSS plugin for the Seyuna UI framework.
6
+ > Build interfaces that transcend resolution.
7
7
 
8
8
  ---
9
9
 
10
- ## 🚀 Overview
10
+ ## What is this
11
11
 
12
- `@seyuna/postcss` is a powerful PostCSS plugin that brings the Seyuna design system to your CSS. It leverages the modern **OKLCH** color space, CSS Container Queries, and configuration-driven styling to provide a premium developer experience.
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.
13
23
 
14
24
  ---
15
25
 
16
- ## 📦 Installation
26
+ ## Installation
17
27
 
18
28
  ```bash
19
29
  npm install @seyuna/postcss postcss-import postcss-advanced-variables postcss-preset-env --save-dev
20
30
  ```
21
31
 
22
- ## Usage
32
+ ---
33
+
34
+ ## Configuration
23
35
 
24
- Add the plugin to your `postcss.config.js` (ESM):
36
+ Create a `postcss.config.js` at your project root:
25
37
 
26
38
  ```javascript
27
39
  import seyunaPostcss from '@seyuna/postcss';
@@ -32,121 +44,155 @@ import postcssPresetEnv from 'postcss-preset-env';
32
44
  export default {
33
45
  plugins: [
34
46
  seyunaPostcss({
35
- configPath: 'seyuna.json', // Path to your Seyuna config
36
- modeAttribute: 'data-mode', // Attribute used for theme switching
47
+ configPath: 'seyuna.json',
48
+ modeAttribute: 'data-mode',
37
49
  }),
38
50
  postcssImport,
39
51
  postcssAdvancedVariables,
40
52
  postcssPresetEnv({
41
- stage: 3, // Enables features that are in the CSS spec pipeline
53
+ stage: 3,
42
54
  features: {
43
- "nesting-rules": true, // Uses postcss-nesting internally
55
+ 'nesting-rules': true,
44
56
  },
45
57
  }),
46
58
  ],
47
59
  };
48
60
  ```
49
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
+
50
64
  ---
51
65
 
52
- ## 🎨 The Color System
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
+ ```
53
87
 
54
- Seyuna distinguishes between two types of colors to maximize flexibility and maintain consistency.
88
+ ### Fixed Colors
55
89
 
56
- ### 1. Standard Colors (`sc`)
57
- Standard colors are "hue-only" tokens. They automatically inherit the **lightness** and **chroma** variables assigned to the current mode (light or dark).
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.
58
91
 
59
- - **Usage**: `sc(primary)`
60
- - **Compiled**: `oklch(var(--lightness) var(--chroma) var(--primary-hue) / 1)`
92
+ ```css
93
+ .badge {
94
+ background: fc(white);
95
+ }
96
+ ```
61
97
 
62
- ### 2. Fixed Colors (`fc`)
63
- Fixed colors ignore the global lightness/chroma context and use their own pre-defined values.
98
+ Compiles to:
64
99
 
65
- - **Usage**: `fc(white)`
66
- - **Compiled**: `oklch(var(--white-lightness) var(--white-chroma) var(--white-hue) / 1)`
100
+ ```css
101
+ .badge {
102
+ background: oklch(var(--white-lightness) var(--white-chroma) var(--white-hue) / 1);
103
+ }
104
+ ```
67
105
 
68
106
  ---
69
107
 
70
- ## 🛠️ Custom Functions
108
+ ## Color Manipulation
71
109
 
72
- ### Color Manipulation
73
- All color functions support both raw `oklch()` strings and color names from your `seyuna.json`.
110
+ All color functions accept a color name from your configuration.
74
111
 
75
- | Function | Description | Example |
76
- | :--- | :--- | :--- |
77
- | `alpha(color, value)` | Sets the opacity of a color. | `alpha(primary, 0.5)` |
78
- | `lighten(color, amt)` | Increases lightness. | `lighten(primary, 0.1)` |
79
- | `darken(color, amt)` | Decreases lightness. | `darken(primary, 0.1)` |
80
- | `contrast(color)` | Returns `black` or `white`. | `color: contrast(primary)` |
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);` |
81
118
 
82
- ### Utilities
83
- - **`theme(path)`**: Access any value in `seyuna.json` using dot notation.
84
- ```css
85
- padding: theme(ui.spacing.medium);
86
- ```
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.
87
120
 
88
121
  ---
89
122
 
90
- ## 🏗️ Powerful At-Rules
123
+ ## Theme Switching
91
124
 
92
- ### Palette Iterators
93
- Generate utility classes by iterating over your configuration.
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:
94
132
 
95
133
  ```css
96
- @each-standard-color {
97
- .bg-{name} { background-color: sc({name}); }
134
+ [data-mode="light"] {
135
+ --lightness: 0.66;
136
+ --chroma: 0.26;
98
137
  }
99
138
 
100
- @each-fixed-color {
101
- .text-{name} { color: fc({name}); }
139
+ @media (prefers-color-scheme: dark) {
140
+ [data-mode="system"] {
141
+ --lightness: 0.66;
142
+ --chroma: 0.26;
143
+ }
102
144
  }
103
145
  ```
104
146
 
105
- ### Theme Wrappers
106
- Simplified syntax for light and dark mode overrides.
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:
107
150
 
108
151
  ```css
109
152
  .card {
110
- background: white;
153
+ background: fc(white);
154
+
111
155
  @dark {
112
- background: black;
156
+ background: fc(black);
113
157
  }
114
158
  }
115
159
  ```
116
160
 
117
- ### Breakpoint Shortcuts
118
- These generate modern CSS Container Queries. Ensure your parent element has `container-type: inline-size`.
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.
119
166
 
120
167
  ```css
121
168
  .grid {
169
+ display: grid;
122
170
  grid-template-columns: 1fr;
171
+
123
172
  @md {
124
- grid-template-columns: 1fr 1fr;
173
+ grid-template-columns: repeat(2, 1fr);
125
174
  }
126
- }
127
- ```
128
- *Supported: `@xs`, `@sm`, `@md`, `@lg`, `@xl`, `@xxl`.*
129
175
 
130
- ### Mixins & Conditionals
131
- ```css
132
- @define-mixin flex-center {
133
- display: flex;
134
- align-items: center;
135
- justify-content: center;
136
- }
137
-
138
- .button {
139
- @apply flex-center;
140
-
141
- @if (theme(ui.features.glass)) {
142
- backdrop-filter: blur(10px);
176
+ @lg {
177
+ grid-template-columns: repeat(3, 1fr);
143
178
  }
144
179
  }
145
180
  ```
146
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
+
147
193
  ---
148
194
 
149
- ## ⚙️ Configuration (`seyuna.json`)
195
+ ## Configuration Reference
150
196
 
151
197
  ```json
152
198
  {
@@ -154,26 +200,76 @@ These generate modern CSS Container Queries. Ensure your parent element has `con
154
200
  "theme": {
155
201
  "hues": {
156
202
  "primary": 240,
157
- "secondary": 30
203
+ "secondary": 30,
204
+ "accent": 150
158
205
  },
159
206
  "colors": {
160
- "white": { "lightness": 1, "chroma": 0, "hue": 0 }
207
+ "white": { "lightness": 1, "chroma": 0, "hue": 0 },
208
+ "black": { "lightness": 0, "chroma": 0, "hue": 0 }
161
209
  },
162
210
  "light": {
211
+ "lightness": 0.66,
163
212
  "chroma": 0.26,
164
- "lightness": 0.66
213
+ "background": { "lightness": 1, "chroma": 0, "hue": 0 },
214
+ "text": { "lightness": 0, "chroma": 0, "hue": 0 }
165
215
  },
166
216
  "dark": {
217
+ "lightness": 0.66,
167
218
  "chroma": 0.26,
168
- "lightness": 0.66
219
+ "background": { "lightness": 0, "chroma": 0, "hue": 0 },
220
+ "text": { "lightness": 1, "chroma": 0, "hue": 0 }
169
221
  }
170
- }
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});
171
251
  }
172
252
  }
173
253
  ```
174
254
 
175
255
  ---
176
256
 
177
- ## 📜 License
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
178
274
 
179
- MIT © [Seyuna](https://seyuna.com)
275
+ MIT
@@ -1,4 +1,4 @@
1
1
  import { AtRule } from "postcss";
2
- import { PluginContext } from "../config";
2
+ import { PluginContext } from "../config.js";
3
3
  export declare const light: (atRule: AtRule, context: PluginContext) => void;
4
4
  export declare const dark: (atRule: AtRule, context: PluginContext) => void;
@@ -1,5 +1,5 @@
1
1
  import { AtRule } from "postcss";
2
- import { PluginContext } from "../config";
2
+ import { PluginContext } from "../config.js";
3
3
  /**
4
4
  * Handler for @each-standard-color
5
5
  */
@@ -1,4 +1,4 @@
1
- import { generateRules } from "../helpers";
1
+ import { generateRules } from "../helpers.js";
2
2
  /**
3
3
  * Handler for @each-standard-color
4
4
  */
@@ -1,5 +1,5 @@
1
1
  import { AtRule } from "postcss";
2
- import { PluginContext } from "../config";
2
+ import { PluginContext } from "../config.js";
3
3
  /**
4
4
  * Custom PostCSS plugin handler for responsive at-rules.
5
5
  *
@@ -1,5 +1,5 @@
1
1
  import { AtRule } from "postcss";
2
- import { PluginContext } from "../config";
2
+ import { PluginContext } from "../config.js";
3
3
  export interface AtRuleHandler {
4
4
  name: string;
5
5
  handler: (atRule: AtRule, context: PluginContext) => void;
@@ -1,17 +1,9 @@
1
- import { eachStandardColor, eachFixedColor } from "./color";
2
- import container from "./container";
3
- import { light, dark } from "./color-scheme";
4
- import { defineMixin, applyMixin } from "./mixin";
5
- import { conditional } from "./conditional";
6
- import { resolveCustomMedia, defineCustomMedia } from "./custom-media";
1
+ import { eachStandardColor, eachFixedColor } from "./color.js";
2
+ import container from "./container.js";
3
+ import { light, dark } from "./color-scheme.js";
7
4
  // Ordered array ensures execution order
8
5
  export const atRuleHandlers = [
9
- { name: "define-mixin", handler: defineMixin },
10
- { name: "custom-media", handler: defineCustomMedia },
11
- { name: "apply", handler: applyMixin },
12
- { name: "if", handler: conditional },
13
- { name: "media", handler: resolveCustomMedia },
14
- { name: "each-standard-color", handler: eachStandardColor }, // first
6
+ { name: "each-standard-color", handler: eachStandardColor },
15
7
  { name: "each-fixed-color", handler: eachFixedColor },
16
8
  { name: "light", handler: light },
17
9
  { name: "dark", handler: dark },
@@ -21,5 +13,4 @@ export const atRuleHandlers = [
21
13
  { name: "lg", handler: container },
22
14
  { name: "xl", handler: container },
23
15
  { name: "2xl", handler: container },
24
- // add more handlers here as needed
25
16
  ];
package/dist/config.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { SeyunaConfig } from './types';
2
- import { FunctionMap } from './parser';
1
+ import { SeyunaConfig } from './types.js';
2
+ import { FunctionMap } from './parser.js';
3
3
  export interface PluginOptions {
4
4
  configPath?: string;
5
5
  modeAttribute?: string;
@@ -7,12 +7,10 @@ export interface PluginOptions {
7
7
  config?: SeyunaConfig;
8
8
  functions?: FunctionMap;
9
9
  }
10
- import { ChildNode } from 'postcss';
11
10
  export interface PluginContext {
12
11
  config: SeyunaConfig;
13
12
  options: Required<PluginOptions>;
14
13
  functions: FunctionMap;
15
- mixins: Record<string, ChildNode[]>;
16
14
  }
17
15
  export declare function loadConfig(options?: PluginOptions): {
18
16
  config: SeyunaConfig;
package/dist/errors.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Node } from 'postcss';
2
- import { PluginContext } from './config';
2
+ import { PluginContext } from "./config.js";
3
3
  export declare function reportError(message: string, node: Node, context: PluginContext, options?: {
4
4
  word?: string;
5
5
  index?: number;
@@ -1,4 +1,4 @@
1
- import { PluginContext } from "../config";
1
+ import { PluginContext } from "../config.js";
2
2
  export declare function sc(context: PluginContext, name: string, alpha?: string, lightness?: string, chroma?: string): string;
3
3
  export declare function fc(context: PluginContext, name: string, alpha?: string, lightness?: string, chroma?: string): string;
4
4
  export declare function alpha(context: PluginContext, color: string, value: string): string;
@@ -1,110 +1,63 @@
1
- /**
2
- * Utility to parse an oklch string and return its parts
3
- */
4
- function parseOklch(color) {
5
- const match = color.match(/oklch\(([^ ]+) ([^ ]+) ([^ /]+)(?: \/ ([^)]+))?\)/);
6
- if (!match)
7
- return null;
8
- return {
9
- l: match[1],
10
- c: match[2],
11
- h: match[3],
12
- a: match[4] || "1",
13
- };
14
- }
15
- export function sc(context, name, alpha, lightness, chroma) {
16
- let a = alpha && alpha !== "null" ? alpha : "1";
17
- let l = lightness && lightness !== "null" ? lightness : "var(--lightness)";
18
- let c = chroma && chroma !== "null" ? chroma : "var(--chroma)";
19
- let h = `var(--${name}-hue)`;
20
- return `oklch(${l} ${c} ${h} / ${a})`;
21
- }
22
- export function fc(context, name, alpha, lightness, chroma) {
23
- let a = alpha && alpha !== "null" ? alpha : "1";
24
- let l = lightness && lightness !== "null" ? lightness : `var(--${name}-lightness)`;
25
- let c = chroma && chroma !== "null" ? chroma : `var(--${name}-chroma)`;
26
- let h = `var(--${name}-hue)`;
27
- return `oklch(${l} ${c} ${h} / ${a})`;
28
- }
29
1
  /**
30
2
  * Resolves a color name to its CSS variables based on its type (standard or fixed)
31
3
  */
32
- function getColorVariables(context, color) {
4
+ function getColorVariables(context, color, type) {
33
5
  const { config } = context;
34
6
  const hues = config?.ui?.theme?.hues || {};
35
7
  const colors = config?.ui?.theme?.colors || {};
36
8
  const lightColors = config?.ui?.theme?.light?.colors || {};
37
9
  const darkColors = config?.ui?.theme?.dark?.colors || {};
38
- // Check if it's a standard color (sc)
39
- if (color in hues) {
10
+ const isStandard = color in hues;
11
+ const isFixed = color in colors || color in lightColors || color in darkColors;
12
+ if (type === 'sc' && !isStandard) {
13
+ throw new Error(`Standard color '${color}' not found in seyuna.json hues`);
14
+ }
15
+ if (type === 'fc' && !isFixed) {
16
+ throw new Error(`Fixed color '${color}' not found in seyuna.json colors`);
17
+ }
18
+ if (isStandard) {
40
19
  return {
41
20
  l: "var(--lightness)",
42
21
  c: "var(--chroma)",
43
22
  h: `var(--${color}-hue)`,
44
23
  };
45
24
  }
46
- // Check if it's a fixed color (fc)
47
- if (color in colors || color in lightColors || color in darkColors) {
25
+ if (isFixed) {
48
26
  return {
49
27
  l: `var(--${color}-lightness)`,
50
28
  c: `var(--${color}-chroma)`,
51
29
  h: `var(--${color}-hue)`,
52
30
  };
53
31
  }
54
- // Fallback to assume it's a fixed color if unknown but used as a name
55
- return {
56
- l: `var(--${color}-lightness)`,
57
- c: `var(--${color}-chroma)`,
58
- h: `var(--${color}-hue)`,
59
- };
32
+ throw new Error(`Color '${color}' not found in seyuna.json`);
33
+ }
34
+ export function sc(context, name, alpha, lightness, chroma) {
35
+ const vars = getColorVariables(context, name, 'sc');
36
+ const a = alpha && alpha !== "null" ? alpha : "1";
37
+ const l = lightness && lightness !== "null" ? lightness : vars.l;
38
+ const c = chroma && chroma !== "null" ? chroma : vars.c;
39
+ return `oklch(${l} ${c} ${vars.h} / ${a})`;
40
+ }
41
+ export function fc(context, name, alpha, lightness, chroma) {
42
+ const vars = getColorVariables(context, name, 'fc');
43
+ const a = alpha && alpha !== "null" ? alpha : "1";
44
+ const l = lightness && lightness !== "null" ? lightness : vars.l;
45
+ const c = chroma && chroma !== "null" ? chroma : vars.c;
46
+ return `oklch(${l} ${c} ${vars.h} / ${a})`;
60
47
  }
61
48
  export function alpha(context, color, value) {
62
- const parsed = parseOklch(color);
63
- if (parsed) {
64
- return `oklch(${parsed.l} ${parsed.c} ${parsed.h} / ${value})`;
65
- }
66
49
  const { l, c, h } = getColorVariables(context, color);
67
50
  return `oklch(${l} ${c} ${h} / ${value})`;
68
51
  }
69
52
  export function lighten(context, color, amount) {
70
- const parsed = parseOklch(color);
71
- if (parsed) {
72
- if (parsed.l.startsWith('var(')) {
73
- return `oklch(calc(${parsed.l} + ${amount}) ${parsed.c} ${parsed.h} / ${parsed.a})`;
74
- }
75
- const lValue = parseFloat(parsed.l);
76
- const amtValue = parseFloat(amount);
77
- return `oklch(${Math.min(1, lValue + amtValue)} ${parsed.c} ${parsed.h} / ${parsed.a})`;
78
- }
79
53
  const { l, c, h } = getColorVariables(context, color);
80
54
  return `oklch(calc(${l} + ${amount}) ${c} ${h} / 1)`;
81
55
  }
82
56
  export function darken(context, color, amount) {
83
- const parsed = parseOklch(color);
84
- if (parsed) {
85
- if (parsed.l.startsWith('var(')) {
86
- return `oklch(calc(${parsed.l} - ${amount}) ${parsed.c} ${parsed.h} / ${parsed.a})`;
87
- }
88
- const lValue = parseFloat(parsed.l);
89
- const amtValue = parseFloat(amount);
90
- return `oklch(${Math.max(0, lValue - amtValue)} ${parsed.c} ${parsed.h} / ${parsed.a})`;
91
- }
92
57
  const { l, c, h } = getColorVariables(context, color);
93
58
  return `oklch(calc(${l} - ${amount}) ${c} ${h} / 1)`;
94
59
  }
95
60
  export function contrast(context, color) {
96
- const parsed = parseOklch(color);
97
- let l;
98
- if (parsed) {
99
- l = parsed.l;
100
- }
101
- else {
102
- const vars = getColorVariables(context, color);
103
- l = vars.l;
104
- }
105
- // Dynamic CSS contrast logic:
106
- // (L - 0.6) * -1000 will be:
107
- // - very negative if L > 0.6 (clamped to 0 / black)
108
- // - very positive if L < 0.6 (clamped to 1 / white)
61
+ const { l } = getColorVariables(context, color);
109
62
  return `oklch(calc((${l} - 0.6) * -1000) 0 0)`;
110
63
  }
@@ -1,3 +1,3 @@
1
- import { PluginContext } from "../config";
1
+ import { PluginContext } from "../config.js";
2
2
  export type FnHandler = (context: PluginContext, ...args: string[]) => string;
3
3
  export declare const functions: Record<string, FnHandler>;
@@ -1,5 +1,5 @@
1
- import { sc, fc, alpha, lighten, darken, contrast } from "./color";
2
- import { theme } from "./theme";
1
+ import { sc, fc, alpha, lighten, darken, contrast } from "./color.js";
2
+ import { theme } from "./theme.js";
3
3
  export const functions = {
4
4
  sc,
5
5
  fc,
@@ -1,4 +1,4 @@
1
- import { PluginContext } from "../config";
1
+ import { PluginContext } from "../config.js";
2
2
  /**
3
3
  * Accesses values from the Seyuna configuration using dot notation
4
4
  * Example: theme(ui.theme.breakpoints.tablet)
package/dist/helpers.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Rule, ChildNode, AtRule } from "postcss";
2
- import { PluginContext } from "./config";
2
+ import { PluginContext } from "./config.js";
3
3
  /**
4
4
  * Helper: clone nodes and replace {name} placeholders safely
5
5
  * Returns only valid Rules or Declarations (never raw AtRules)
package/dist/helpers.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Rule } from "postcss";
2
- import { processFunctions } from "./parser";
2
+ import { processFunctions } from "./parser.js";
3
3
  /**
4
4
  * Helper: clone nodes and replace {name} placeholders safely
5
5
  * Returns only valid Rules or Declarations (never raw AtRules)
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- declare const plugin: import("postcss").PluginCreator<import("./config").PluginOptions> & {
1
+ declare const plugin: import("postcss").PluginCreator<import("./config.js").PluginOptions> & {
2
2
  postcss: boolean;
3
- functions: Record<string, import("./functions").FnHandler>;
3
+ functions: Record<string, import("./functions/index.js").FnHandler>;
4
4
  };
5
5
  export default plugin;
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { dynamicFunctionsPlugin } from './plugin';
2
- import { functions } from './functions';
1
+ import { dynamicFunctionsPlugin } from './plugin.js';
2
+ import { functions } from './functions/index.js';
3
3
  // CommonJS-friendly export
4
4
  const plugin = Object.assign(dynamicFunctionsPlugin, {
5
5
  postcss: true,