chroma-panel 0.2.0 → 1.0.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 (92) hide show
  1. package/README.md +46 -8
  2. package/dist/a11y/contrast.cjs +94 -0
  3. package/dist/a11y/contrast.d.cts +8 -0
  4. package/dist/a11y/contrast.d.ts +8 -0
  5. package/dist/a11y/contrast.js +93 -2
  6. package/dist/color/css4.cjs +397 -0
  7. package/dist/color/css4.d.cts +10 -0
  8. package/dist/color/css4.d.ts +10 -0
  9. package/dist/color/css4.js +392 -0
  10. package/dist/color/parse.cjs +3 -1
  11. package/dist/color/parse.js +3 -1
  12. package/dist/color/types.d.cts +16 -0
  13. package/dist/color/types.d.ts +16 -0
  14. package/dist/color/value.cjs +11 -0
  15. package/dist/color/value.d.cts +4 -0
  16. package/dist/color/value.d.ts +4 -0
  17. package/dist/color/value.js +12 -0
  18. package/dist/color.cjs +43 -0
  19. package/dist/color.d.cts +9 -0
  20. package/dist/color.d.ts +9 -0
  21. package/dist/color.js +8 -0
  22. package/dist/components/ChromaPanel.cjs +16 -6
  23. package/dist/components/ChromaPanel.d.cts +4 -2
  24. package/dist/components/ChromaPanel.d.ts +4 -2
  25. package/dist/components/ChromaPanel.js +16 -6
  26. package/dist/components/ColorInput.cjs +1 -1
  27. package/dist/components/ColorInput.js +1 -1
  28. package/dist/components/PanelFooter.cjs +4 -4
  29. package/dist/components/PanelFooter.js +4 -4
  30. package/dist/contrast.cjs +3 -0
  31. package/dist/contrast.d.cts +2 -2
  32. package/dist/contrast.d.ts +2 -2
  33. package/dist/contrast.js +2 -2
  34. package/dist/core/store.cjs +17 -9
  35. package/dist/core/store.d.cts +6 -6
  36. package/dist/core/store.d.ts +6 -6
  37. package/dist/core/store.js +17 -9
  38. package/dist/core.cjs +10 -0
  39. package/dist/core.d.cts +4 -2
  40. package/dist/core.d.ts +4 -2
  41. package/dist/core.js +3 -1
  42. package/dist/export/tokens.cjs +39 -0
  43. package/dist/export/tokens.d.cts +16 -0
  44. package/dist/export/tokens.d.ts +16 -0
  45. package/dist/export/tokens.js +37 -0
  46. package/dist/export.cjs +6 -0
  47. package/dist/export.d.cts +2 -0
  48. package/dist/export.d.ts +2 -0
  49. package/dist/export.js +2 -0
  50. package/dist/gradient/GradientEditor.cjs +196 -0
  51. package/dist/gradient/GradientEditor.d.cts +17 -0
  52. package/dist/gradient/GradientEditor.d.ts +17 -0
  53. package/dist/gradient/GradientEditor.js +195 -0
  54. package/dist/gradient/model.cjs +63 -0
  55. package/dist/gradient/model.d.cts +23 -0
  56. package/dist/gradient/model.d.ts +23 -0
  57. package/dist/gradient/model.js +60 -0
  58. package/dist/gradient.cjs +9 -0
  59. package/dist/gradient.d.cts +3 -0
  60. package/dist/gradient.d.ts +3 -0
  61. package/dist/gradient.js +3 -0
  62. package/dist/index.cjs +13 -0
  63. package/dist/index.d.cts +5 -3
  64. package/dist/index.d.ts +5 -3
  65. package/dist/index.js +4 -2
  66. package/dist/modes/image/index.cjs +65 -4
  67. package/dist/modes/image/index.d.cts +1 -0
  68. package/dist/modes/image/index.d.ts +1 -0
  69. package/dist/modes/image/index.js +65 -4
  70. package/dist/modes/registry.d.cts +1 -1
  71. package/dist/modes/registry.d.ts +1 -1
  72. package/dist/modes.cjs +30 -0
  73. package/dist/modes.d.cts +10 -0
  74. package/dist/modes.d.ts +10 -0
  75. package/dist/modes.js +17 -0
  76. package/dist/panel.cjs +10 -0
  77. package/dist/panel.d.cts +4 -2
  78. package/dist/panel.d.ts +4 -2
  79. package/dist/panel.js +3 -1
  80. package/dist/primitives/ChannelSlider.cjs +4 -4
  81. package/dist/primitives/ChannelSlider.js +4 -4
  82. package/dist/primitives/ColorArea.cjs +6 -6
  83. package/dist/primitives/ColorArea.js +6 -6
  84. package/dist/primitives/ColorDisc.cjs +6 -6
  85. package/dist/primitives/ColorDisc.js +6 -6
  86. package/dist/primitives/ColorField.cjs +2 -2
  87. package/dist/primitives/ColorField.js +2 -2
  88. package/dist/primitives/NumberField.cjs +2 -2
  89. package/dist/primitives/NumberField.js +2 -2
  90. package/dist/primitives/SwatchGrid.cjs +2 -2
  91. package/dist/primitives/SwatchGrid.js +2 -2
  92. package/package.json +46 -2
@@ -0,0 +1,397 @@
1
+ const require_convert = require("./convert.cjs");
2
+ //#region src/color/css4.ts
3
+ const D50 = [
4
+ .96422,
5
+ 1,
6
+ .82521
7
+ ];
8
+ const D65_TO_D50 = [
9
+ [
10
+ 1.0479298,
11
+ .0229468,
12
+ -.0501922
13
+ ],
14
+ [
15
+ .0296278,
16
+ .9904345,
17
+ -.0170738
18
+ ],
19
+ [
20
+ -.009243,
21
+ .0150552,
22
+ .7518743
23
+ ]
24
+ ];
25
+ const D50_TO_D65 = [
26
+ [
27
+ .9554734,
28
+ -.0230985,
29
+ .0632593
30
+ ],
31
+ [
32
+ -.0283697,
33
+ 1.0099955,
34
+ .0210414
35
+ ],
36
+ [
37
+ .012314,
38
+ -.0205077,
39
+ 1.3303659
40
+ ]
41
+ ];
42
+ function mul(matrix, value) {
43
+ return matrix.map((row) => row[0] * value[0] + row[1] * value[1] + row[2] * value[2]);
44
+ }
45
+ function linear(value) {
46
+ const sign = value < 0 ? -1 : 1;
47
+ const abs = Math.abs(value);
48
+ return sign * (abs <= .04045 ? abs / 12.92 : ((abs + .055) / 1.055) ** 2.4);
49
+ }
50
+ function gamma(value) {
51
+ const sign = value < 0 ? -1 : 1;
52
+ const abs = Math.abs(value);
53
+ return sign * (abs <= .0031308 ? 12.92 * abs : 1.055 * abs ** (1 / 2.4) - .055);
54
+ }
55
+ function rgbToXyz(rgb, space) {
56
+ return mul(space === "srgb" ? [
57
+ [
58
+ .4123908,
59
+ .3575843,
60
+ .1804808
61
+ ],
62
+ [
63
+ .212639,
64
+ .7151687,
65
+ .0721923
66
+ ],
67
+ [
68
+ .0193308,
69
+ .1191948,
70
+ .9505322
71
+ ]
72
+ ] : [
73
+ [
74
+ .4865709,
75
+ .2656677,
76
+ .1982173
77
+ ],
78
+ [
79
+ .2289746,
80
+ .6917385,
81
+ .0792869
82
+ ],
83
+ [
84
+ 0,
85
+ .0451134,
86
+ 1.0439444
87
+ ]
88
+ ], rgb.map(linear));
89
+ }
90
+ function xyzToRgb(xyz, space) {
91
+ return mul(space === "srgb" ? [
92
+ [
93
+ 3.2409699,
94
+ -1.5373832,
95
+ -.4986108
96
+ ],
97
+ [
98
+ -.9692436,
99
+ 1.8759675,
100
+ .0415551
101
+ ],
102
+ [
103
+ .0556301,
104
+ -.203977,
105
+ 1.0569715
106
+ ]
107
+ ] : [
108
+ [
109
+ 2.4934969,
110
+ -.9313836,
111
+ -.4027108
112
+ ],
113
+ [
114
+ -.829489,
115
+ 1.762664,
116
+ .0236247
117
+ ],
118
+ [
119
+ .0358458,
120
+ -.0761724,
121
+ .9568845
122
+ ]
123
+ ], xyz).map(gamma);
124
+ }
125
+ function xyzToOklab(xyz) {
126
+ return mul([
127
+ [
128
+ .2104543,
129
+ .7936178,
130
+ -.004072
131
+ ],
132
+ [
133
+ 1.9779985,
134
+ -2.4285922,
135
+ .4505937
136
+ ],
137
+ [
138
+ .025904,
139
+ .7827718,
140
+ -.8086758
141
+ ]
142
+ ], mul([
143
+ [
144
+ .8190224,
145
+ .3619063,
146
+ -.1288738
147
+ ],
148
+ [
149
+ .0329837,
150
+ .9292868,
151
+ .0361447
152
+ ],
153
+ [
154
+ .0481772,
155
+ .2642395,
156
+ .6335478
157
+ ]
158
+ ], xyz).map(Math.cbrt));
159
+ }
160
+ function oklabToXyz(lab) {
161
+ return mul([
162
+ [
163
+ 1.2268798758,
164
+ -.5578149945,
165
+ .2813910457
166
+ ],
167
+ [
168
+ -.0405757452,
169
+ 1.1122868033,
170
+ -.0717110581
171
+ ],
172
+ [
173
+ -.0763729367,
174
+ -.4214933324,
175
+ 1.5869240198
176
+ ]
177
+ ], mul([
178
+ [
179
+ 1,
180
+ .3963378,
181
+ .2158038
182
+ ],
183
+ [
184
+ 1,
185
+ -.1055613,
186
+ -.0638542
187
+ ],
188
+ [
189
+ 1,
190
+ -.0894842,
191
+ -1.2914855
192
+ ]
193
+ ], lab).map((v) => v ** 3));
194
+ }
195
+ function xyzD50ToLab(xyz) {
196
+ const e = 216 / 24389;
197
+ const k = 24389 / 27;
198
+ const f = xyz.map((v, i) => {
199
+ const n = v / D50[i];
200
+ return n > e ? Math.cbrt(n) : (k * n + 16) / 116;
201
+ });
202
+ return [
203
+ 116 * f[1] - 16,
204
+ 500 * (f[0] - f[1]),
205
+ 200 * (f[1] - f[2])
206
+ ];
207
+ }
208
+ function labToXyzD50(lab) {
209
+ const f = [
210
+ lab[1] / 500 + (lab[0] + 16) / 116,
211
+ (lab[0] + 16) / 116,
212
+ (lab[0] + 16) / 116 - lab[2] / 200
213
+ ];
214
+ const e = 216 / 24389;
215
+ const k = 24389 / 27;
216
+ return f.map((v, i) => D50[i] * (v ** 3 > e ? v ** 3 : (116 * v - 16) / k));
217
+ }
218
+ function polar(value) {
219
+ const r = value[2] * Math.PI / 180;
220
+ return [
221
+ value[0],
222
+ value[1] * Math.cos(r),
223
+ value[1] * Math.sin(r)
224
+ ];
225
+ }
226
+ function cylindrical(value) {
227
+ const c = Math.hypot(value[1], value[2]);
228
+ return [
229
+ value[0],
230
+ c,
231
+ c < 1e-7 ? 0 : (Math.atan2(value[2], value[1]) * 180 / Math.PI + 360) % 360
232
+ ];
233
+ }
234
+ function toXyz(color) {
235
+ switch (color.space) {
236
+ case "srgb":
237
+ case "display-p3": return rgbToXyz([...color.channels], color.space);
238
+ case "oklab": return oklabToXyz([...color.channels]);
239
+ case "oklch": return oklabToXyz(polar([...color.channels]));
240
+ case "lab": return mul(D50_TO_D65, labToXyzD50([...color.channels]));
241
+ case "lch": return mul(D50_TO_D65, labToXyzD50(polar([...color.channels])));
242
+ }
243
+ }
244
+ function convertColor(color, space) {
245
+ if (color.space === space) return {
246
+ ...color,
247
+ channels: [...color.channels]
248
+ };
249
+ const xyz = toXyz(color);
250
+ let channels;
251
+ switch (space) {
252
+ case "srgb":
253
+ case "display-p3":
254
+ channels = xyzToRgb(xyz, space);
255
+ break;
256
+ case "oklab":
257
+ channels = xyzToOklab(xyz);
258
+ break;
259
+ case "oklch":
260
+ channels = cylindrical(xyzToOklab(xyz));
261
+ break;
262
+ case "lab":
263
+ channels = xyzD50ToLab(mul(D65_TO_D50, xyz));
264
+ break;
265
+ case "lch": channels = cylindrical(xyzD50ToLab(mul(D65_TO_D50, xyz)));
266
+ }
267
+ return {
268
+ space,
269
+ channels,
270
+ alpha: color.alpha
271
+ };
272
+ }
273
+ function isInGamut(color, gamut = "srgb") {
274
+ return convertColor(color, gamut).channels.every((v) => v >= -1e-7 && v <= 1 + 1e-7);
275
+ }
276
+ function mapToGamut(color, gamut = "srgb") {
277
+ if (isInGamut(color, gamut)) return convertColor(color, gamut);
278
+ const source = convertColor(color, "oklch");
279
+ let low = 0;
280
+ let high = Math.max(0, source.channels[1]);
281
+ for (let i = 0; i < 24; i++) {
282
+ const c = (low + high) / 2;
283
+ if (isInGamut({
284
+ ...source,
285
+ channels: [
286
+ source.channels[0],
287
+ c,
288
+ source.channels[2]
289
+ ]
290
+ }, gamut)) low = c;
291
+ else high = c;
292
+ }
293
+ const mapped = convertColor({
294
+ ...source,
295
+ channels: [
296
+ source.channels[0],
297
+ low,
298
+ source.channels[2]
299
+ ]
300
+ }, gamut);
301
+ return {
302
+ ...mapped,
303
+ channels: mapped.channels.map((channel) => require_convert.clamp(channel, 0, 1))
304
+ };
305
+ }
306
+ function num(token, percentScale = 1) {
307
+ if (token.toLowerCase() === "none") return 0;
308
+ const percent = token.endsWith("%");
309
+ const value = Number(percent ? token.slice(0, -1) : token);
310
+ return Number.isFinite(value) ? value * (percent ? percentScale / 100 : 1) : null;
311
+ }
312
+ function hue(token) {
313
+ if (token.toLowerCase() === "none") return 0;
314
+ const m = token.match(/^([-+]?(?:\d*\.)?\d+)(deg|grad|rad|turn)?$/i);
315
+ if (m === null) return null;
316
+ const value = Number(m[1]);
317
+ return m[2] === "grad" ? value * .9 : m[2] === "rad" ? value * 180 / Math.PI : m[2] === "turn" ? value * 360 : value;
318
+ }
319
+ function lightness(token, ok) {
320
+ if (token.toLowerCase() === "none") return 0;
321
+ const percent = token.endsWith("%");
322
+ const value = Number(percent ? token.slice(0, -1) : token);
323
+ if (!Number.isFinite(value)) return null;
324
+ return ok && percent ? value / 100 : value;
325
+ }
326
+ function parseCss4Color(input) {
327
+ const rgb = input.trim().match(/^color\((srgb|display-p3)\s+([^/]+?)(?:\s*\/\s*([^\s]+))?\)$/i);
328
+ if (rgb !== null) {
329
+ const values = rgb[2].trim().split(/\s+/).map((v) => num(v, 1));
330
+ const alpha = rgb[3] === void 0 ? 1 : num(rgb[3], 1);
331
+ return values.length === 3 && values.every((v) => v !== null) && alpha !== null ? {
332
+ space: rgb[1].toLowerCase(),
333
+ channels: values,
334
+ alpha: require_convert.clamp(alpha, 0, 1)
335
+ } : null;
336
+ }
337
+ const match = input.trim().match(/^(oklab|oklch|lab|lch)\((.*)\)$/i);
338
+ if (match === null) return null;
339
+ const sections = match[2].split("/");
340
+ const parts = sections[0].trim().split(/\s+/);
341
+ const space = match[1].toLowerCase();
342
+ if (parts.length !== 3 || sections.length > 2) return null;
343
+ const l = lightness(parts[0], space.startsWith("ok"));
344
+ const second = num(parts[1], space.startsWith("ok") ? .4 : space === "lch" ? 150 : 125);
345
+ const third = space.endsWith("ch") ? hue(parts[2]) : num(parts[2], space === "oklab" ? .4 : 125);
346
+ const alpha = sections[1] === void 0 ? 1 : num(sections[1].trim(), 1);
347
+ if (l === null || second === null || third === null || alpha === null) return null;
348
+ return {
349
+ space,
350
+ channels: [
351
+ l,
352
+ space.endsWith("ch") ? Math.max(0, second) : second,
353
+ space.endsWith("ch") ? (third % 360 + 360) % 360 : third
354
+ ],
355
+ alpha: require_convert.clamp(alpha, 0, 1)
356
+ };
357
+ }
358
+ function colorValueToHsva(color) {
359
+ const rgb = mapToGamut(color, "srgb");
360
+ return require_convert.rgbaToHsva({
361
+ r: require_convert.clamp(rgb.channels[0], 0, 1) * 255,
362
+ g: require_convert.clamp(rgb.channels[1], 0, 1) * 255,
363
+ b: require_convert.clamp(rgb.channels[2], 0, 1) * 255,
364
+ a: color.alpha
365
+ });
366
+ }
367
+ function hsvaToColorValue(color) {
368
+ const rgb = require_convert.hsvaToRgba(color);
369
+ return {
370
+ space: "srgb",
371
+ channels: [
372
+ rgb.r / 255,
373
+ rgb.g / 255,
374
+ rgb.b / 255
375
+ ],
376
+ alpha: rgb.a
377
+ };
378
+ }
379
+ const out = (value, precision) => String(Number(value.toFixed(precision)));
380
+ function serializeColor(color, options = {}) {
381
+ const format = options.format ?? color.space;
382
+ const precision = Math.min(8, Math.max(0, options.precision ?? 4));
383
+ const converted = convertColor(options.gamut === void 0 || options.gamut === "preserve" ? color : mapToGamut(color, options.gamut), format);
384
+ const [x, y, z] = converted.channels;
385
+ const alpha = converted.alpha < 1 ? ` / ${out(converted.alpha, precision)}` : "";
386
+ if (format === "srgb" || format === "display-p3") return `color(${format} ${out(x, precision)} ${out(y, precision)} ${out(z, precision)}${alpha})`;
387
+ const lightness = format.startsWith("ok") ? x * 100 : x;
388
+ return `${format}(${out(lightness, precision)}% ${out(y, precision)} ${out(z, precision)}${alpha})`;
389
+ }
390
+ //#endregion
391
+ exports.colorValueToHsva = colorValueToHsva;
392
+ exports.convertColor = convertColor;
393
+ exports.hsvaToColorValue = hsvaToColorValue;
394
+ exports.isInGamut = isInGamut;
395
+ exports.mapToGamut = mapToGamut;
396
+ exports.parseCss4Color = parseCss4Color;
397
+ exports.serializeColor = serializeColor;
@@ -0,0 +1,10 @@
1
+ import { ColorValue, Hsva, ModernColorSpace, SerializeColorOptions } from "./types.cjs";
2
+ //#region src/color/css4.d.ts
3
+ export declare function convertColor(color: ColorValue, space: ModernColorSpace): ColorValue;
4
+ export declare function isInGamut(color: ColorValue, gamut?: "srgb" | "display-p3"): boolean;
5
+ export declare function mapToGamut(color: ColorValue, gamut?: "srgb" | "display-p3"): ColorValue;
6
+ export declare function parseCss4Color(input: string): ColorValue | null;
7
+ export declare function colorValueToHsva(color: ColorValue): Hsva;
8
+ export declare function hsvaToColorValue(color: Hsva): ColorValue;
9
+ export declare function serializeColor(color: ColorValue, options?: SerializeColorOptions): string;
10
+ //#endregion
@@ -0,0 +1,10 @@
1
+ import { ColorValue, Hsva, ModernColorSpace, SerializeColorOptions } from "./types.js";
2
+ //#region src/color/css4.d.ts
3
+ export declare function convertColor(color: ColorValue, space: ModernColorSpace): ColorValue;
4
+ export declare function isInGamut(color: ColorValue, gamut?: "srgb" | "display-p3"): boolean;
5
+ export declare function mapToGamut(color: ColorValue, gamut?: "srgb" | "display-p3"): ColorValue;
6
+ export declare function parseCss4Color(input: string): ColorValue | null;
7
+ export declare function colorValueToHsva(color: ColorValue): Hsva;
8
+ export declare function hsvaToColorValue(color: Hsva): ColorValue;
9
+ export declare function serializeColor(color: ColorValue, options?: SerializeColorOptions): string;
10
+ //#endregion