tailwind-oklch 0.4.0 → 0.5.0

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 (3) hide show
  1. package/index.css +2 -0
  2. package/package.json +1 -1
  3. package/plugin.js +171 -1
package/index.css CHANGED
@@ -98,6 +98,7 @@
98
98
 
99
99
  :root:not(.dark) {
100
100
  --lc-dir: -1;
101
+ --lc-flip: 0;
101
102
  --lc-range-start: 0.95;
102
103
  --lc-range-end: 0.15;
103
104
 
@@ -127,6 +128,7 @@
127
128
 
128
129
  :root {
129
130
  --lc-dir: 1;
131
+ --lc-flip: 1;
130
132
 
131
133
  --bg-l: var(--l-5);
132
134
  --bg-c: var(--c-lo);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tailwind-oklch",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "OKLCH color composition system for Tailwind CSS v4",
5
5
  "style": "index.css",
6
6
  "main": "index.css",
package/plugin.js CHANGED
@@ -17,7 +17,7 @@
17
17
  * Load via: @plugin "tailwind-oklch/plugin";
18
18
  */
19
19
 
20
- module.exports = function ({ addUtilities }) {
20
+ module.exports = function ({ addUtilities, matchUtilities }) {
21
21
  const luminances = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', 'base', 'fore', 'none', 'full'];
22
22
  const chromas = ['lo', 'mlo', 'mid', 'mhi', 'hi'];
23
23
  const hues = ['primary', 'accent', 'success', 'warning', 'danger', 'info', 'neutral'];
@@ -97,4 +97,174 @@ module.exports = function ({ addUtilities }) {
97
97
  }
98
98
 
99
99
  addUtilities(utilities);
100
+
101
+ // ── Arbitrary hue values ────────────────────────────────────────────────
102
+ // hue-[180] → sets all hue properties to 180 (degrees).
103
+ // bg-h-[280] → sets only background hue to 280.
104
+
105
+ const hueVars = ['--bg-h', '--tx-h', '--bd-h', '--bdb-h', '--ac-h', '--gf-h', '--gt-h', '--sh-h'];
106
+
107
+ matchUtilities(
108
+ {
109
+ hue: (value) => Object.fromEntries(hueVars.map((v) => [v, value])),
110
+ },
111
+ { type: ['integer'] },
112
+ );
113
+
114
+ for (const prop of properties) {
115
+ matchUtilities(
116
+ {
117
+ [`${prop.prefix}-h`]: (value) => ({
118
+ [prop.vars[2]]: value,
119
+ [prop.css]: `oklch(var(${prop.vars[0]}) var(${prop.vars[1]}) var(${prop.vars[2]}))`,
120
+ }),
121
+ },
122
+ { type: ['integer'] },
123
+ );
124
+ }
125
+
126
+ // Gradient from/to arbitrary hue
127
+ matchUtilities(
128
+ {
129
+ 'from-h': (value) => ({
130
+ '--gf-h': value,
131
+ '--tw-gradient-from': 'oklch(var(--gf-l) var(--gf-c) var(--gf-h))',
132
+ '--tw-gradient-stops': stopsExpr,
133
+ }),
134
+ 'to-h': (value) => ({
135
+ '--gt-h': value,
136
+ '--tw-gradient-to': 'oklch(var(--gt-l) var(--gt-c) var(--gt-h))',
137
+ '--tw-gradient-stops': stopsExpr,
138
+ }),
139
+ },
140
+ { type: ['integer'] },
141
+ );
142
+
143
+ // Shadow arbitrary hue
144
+ matchUtilities(
145
+ {
146
+ 'shadow-h': (value) => ({
147
+ '--sh-h': value,
148
+ '--tw-shadow-color': 'oklch(var(--sh-l) var(--sh-c) var(--sh-h))',
149
+ }),
150
+ },
151
+ { type: ['integer'] },
152
+ );
153
+
154
+ // ── Arbitrary chroma values ───────────────────────────────────────────
155
+ // chroma-[15] → sets all chroma properties to 0.15.
156
+ // bg-c-[20] → sets only background chroma to 0.20.
157
+
158
+ const chromaVars = ['--bg-c', '--tx-c', '--bd-c', '--bdb-c', '--ac-c', '--gf-c', '--gt-c', '--sh-c'];
159
+
160
+ const chromaValue = (value) => {
161
+ const v = Number(value) / 100;
162
+ return `${Math.round(v * 1e6) / 1e6}`;
163
+ };
164
+
165
+ matchUtilities(
166
+ {
167
+ chroma: (value) => {
168
+ const c = chromaValue(value);
169
+ return Object.fromEntries(chromaVars.map((v) => [v, c]));
170
+ },
171
+ },
172
+ { type: ['integer'] },
173
+ );
174
+
175
+ for (const prop of properties) {
176
+ matchUtilities(
177
+ {
178
+ [`${prop.prefix}-c`]: (value) => ({
179
+ [prop.vars[1]]: chromaValue(value),
180
+ [prop.css]: `oklch(var(${prop.vars[0]}) var(${prop.vars[1]}) var(${prop.vars[2]}))`,
181
+ }),
182
+ },
183
+ { type: ['integer'] },
184
+ );
185
+ }
186
+
187
+ // Gradient from/to arbitrary chroma
188
+ matchUtilities(
189
+ {
190
+ 'from-c': (value) => ({
191
+ '--gf-c': chromaValue(value),
192
+ '--tw-gradient-from': 'oklch(var(--gf-l) var(--gf-c) var(--gf-h))',
193
+ '--tw-gradient-stops': stopsExpr,
194
+ }),
195
+ 'to-c': (value) => ({
196
+ '--gt-c': chromaValue(value),
197
+ '--tw-gradient-to': 'oklch(var(--gt-l) var(--gt-c) var(--gt-h))',
198
+ '--tw-gradient-stops': stopsExpr,
199
+ }),
200
+ },
201
+ { type: ['integer'] },
202
+ );
203
+
204
+ // Shadow arbitrary chroma
205
+ matchUtilities(
206
+ {
207
+ 'shadow-c': (value) => ({
208
+ '--sh-c': chromaValue(value),
209
+ '--tw-shadow-color': 'oklch(var(--sh-l) var(--sh-c) var(--sh-h))',
210
+ }),
211
+ },
212
+ { type: ['integer'] },
213
+ );
214
+
215
+ // ── Auto-flip luminance for arbitrary values ──────────────────────────
216
+ // bg-lc-[60] → light mode L=0.60, dark mode L=0.40 (simple 1−x flip).
217
+ // Uses --lc-flip (0 in light, 1 in dark) so the transform is pure CSS.
218
+ // Formula: L = v + flip × (1 − 2v) where v = input / 100
219
+ // flip=0 → v (light: use value as-is)
220
+ // flip=1 → 1−v (dark: reflect around 0.5)
221
+
222
+ const lcFlipValue = (value) => {
223
+ const v = Number(value) / 100;
224
+ const delta = 1 - 2 * v;
225
+ // Round to avoid floating-point noise in the CSS output
226
+ const vR = Math.round(v * 1e6) / 1e6;
227
+ const dR = Math.round(delta * 1e6) / 1e6;
228
+ return `calc(${vR} + var(--lc-flip) * ${dR})`;
229
+ };
230
+
231
+ for (const prop of properties) {
232
+ matchUtilities(
233
+ {
234
+ [`${prop.prefix}-lc`]: (value) => ({
235
+ [prop.vars[0]]: lcFlipValue(value),
236
+ [prop.css]: `oklch(var(${prop.vars[0]}) var(${prop.vars[1]}) var(${prop.vars[2]}))`,
237
+ }),
238
+ },
239
+ { type: ['integer'] },
240
+ );
241
+ }
242
+
243
+ // Gradient from/to auto-flip luminance
244
+ matchUtilities(
245
+ {
246
+ 'from-lc': (value) => ({
247
+ '--gf-l': lcFlipValue(value),
248
+ '--tw-gradient-from': 'oklch(var(--gf-l) var(--gf-c) var(--gf-h))',
249
+ '--tw-gradient-stops': stopsExpr,
250
+ }),
251
+ 'to-lc': (value) => ({
252
+ '--gt-l': lcFlipValue(value),
253
+ '--tw-gradient-to': 'oklch(var(--gt-l) var(--gt-c) var(--gt-h))',
254
+ '--tw-gradient-stops': stopsExpr,
255
+ }),
256
+ },
257
+ { type: ['integer'] },
258
+ );
259
+
260
+ // Shadow auto-flip luminance
261
+ matchUtilities(
262
+ {
263
+ 'shadow-lc': (value) => ({
264
+ '--sh-l': lcFlipValue(value),
265
+ '--tw-shadow-color': 'oklch(var(--sh-l) var(--sh-c) var(--sh-h))',
266
+ }),
267
+ },
268
+ { type: ['integer'] },
269
+ );
100
270
  };