@rogieking/figui3 11.6.1 → 11.6.2

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/fig-editor.js CHANGED
@@ -1,7 +1,21 @@
1
1
  /* Copyright (c) 2026 Rogie King. PolyForm Shield 1.0.0. See LICENSE. */
2
2
  import "./fig.js";
3
3
  import "./fig-property.js";
4
+ import {
5
+ figConvertRGB,
6
+ figHexToRGB as figEditorHexToRgb,
7
+ figHslToRGB,
8
+ figHsvToRGB,
9
+ figOklabToOklch as figEditorOklabToOklch,
10
+ figOklabToRGB,
11
+ figOklchToRGB,
12
+ figRGBToHsl as figEditorRgbToHsl,
13
+ figRGBToHsv,
14
+ figRGBToOklab as figEditorRgbToOklab,
15
+ figRGBToOklch,
16
+ } from "./fig-color.js";
4
17
  import { figGradientCSS } from "./fig-gradient-editor.js";
18
+ import "./fig-palette-editor.js";
5
19
  import "./fig-popup-easing.js";
6
20
  import "./fig-popup-gradient.js";
7
21
  import "./fig-popup-palette.js";
@@ -195,73 +209,6 @@ class FigInputPoint extends HTMLElement {
195
209
  }
196
210
  figEditorDefineElement("fig-input-point", FigInputPoint);
197
211
 
198
- function figEditorNormalizePaletteValue(value) {
199
- let entries = value;
200
- if (typeof entries === "string") {
201
- const raw = entries.trim();
202
- if (!raw) return [];
203
- try {
204
- entries = JSON.parse(raw);
205
- } catch {
206
- entries = raw.includes(",") ? raw.split(",") : [raw];
207
- }
208
- }
209
- if (!Array.isArray(entries)) return [];
210
- return entries.map((entry) => {
211
- if (typeof entry === "string") {
212
- const color = entry.trim();
213
- return {
214
- color: color.slice(0, 7) || "#D9D9D9",
215
- alpha:
216
- color.length > 7
217
- ? Math.max(0, Math.min(1, parseInt(color.slice(7, 9), 16) / 255))
218
- : 1,
219
- };
220
- }
221
- if (entry && typeof entry === "object") {
222
- const alpha =
223
- entry.alpha !== undefined
224
- ? Number(entry.alpha)
225
- : entry.opacity !== undefined
226
- ? Number(entry.opacity) / 100
227
- : 1;
228
- return {
229
- color: String(entry.color || "#D9D9D9").slice(0, 7),
230
- alpha: Number.isFinite(alpha) ? Math.max(0, Math.min(1, alpha)) : 1,
231
- };
232
- }
233
- return { color: "#D9D9D9", alpha: 1 };
234
- });
235
- }
236
-
237
- function figEditorPaletteEntryValue(entry) {
238
- const color = String(entry?.color || "#D9D9D9").slice(0, 7);
239
- const alpha = Math.max(0, Math.min(1, Number(entry?.alpha ?? 1)));
240
- if (alpha >= 1) return color;
241
- return `${color}${Math.round(alpha * 255)
242
- .toString(16)
243
- .padStart(2, "0")}`;
244
- }
245
-
246
- function figEditorAveragePaletteEntries(first, second) {
247
- if (!first && !second) return { color: "#D9D9D9", alpha: 1 };
248
- if (!first || !second) return { ...(first || second) };
249
- const firstRgb = figEditorHexToRgb(first.color);
250
- const secondRgb = figEditorHexToRgb(second.color);
251
- const color = `#${["r", "g", "b"]
252
- .map((channel) =>
253
- Math.round((firstRgb[channel] + secondRgb[channel]) / 2)
254
- .toString(16)
255
- .padStart(2, "0"),
256
- )
257
- .join("")
258
- .toUpperCase()}`;
259
- return {
260
- color,
261
- alpha: (Number(first.alpha ?? 1) + Number(second.alpha ?? 1)) / 2,
262
- };
263
- }
264
-
265
212
  const FIG_EDITOR_SVG_NAMESPACE = "http://www.w3.org/2000/svg";
266
213
 
267
214
  function figEditorCreateSvgElement(tagName, attributes, children) {
@@ -279,73 +226,6 @@ function figEditorCreateSvgElement(tagName, attributes, children) {
279
226
  return figEditorAppendChildren(element, children);
280
227
  }
281
228
 
282
- function figEditorHexToRgb(hex) {
283
- const h = String(hex || "").replace(/^#/, "");
284
- return {
285
- r: parseInt(h.substring(0, 2), 16) || 0,
286
- g: parseInt(h.substring(2, 4), 16) || 0,
287
- b: parseInt(h.substring(4, 6), 16) || 0,
288
- };
289
- }
290
-
291
- function figEditorRgbToHsl(r, g, b) {
292
- const R = r / 255;
293
- const G = g / 255;
294
- const B = b / 255;
295
- const max = Math.max(R, G, B);
296
- const min = Math.min(R, G, B);
297
- const l = (max + min) / 2;
298
- if (max === min) return { h: 0, s: 0, l: l * 100 };
299
- const d = max - min;
300
- const s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
301
- let h;
302
- switch (max) {
303
- case R:
304
- h = ((G - B) / d + (G < B ? 6 : 0)) / 6;
305
- break;
306
- case G:
307
- h = ((B - R) / d + 2) / 6;
308
- break;
309
- default:
310
- h = ((R - G) / d + 4) / 6;
311
- break;
312
- }
313
- return { h: h * 360, s: s * 100, l: l * 100 };
314
- }
315
-
316
- function figEditorRgbToLinear(c) {
317
- const s = c / 255;
318
- return s <= 0.04045 ? s / 12.92 : Math.pow((s + 0.055) / 1.055, 2.4);
319
- }
320
-
321
- function figEditorRgbToOklab(r, g, b) {
322
- const lr = figEditorRgbToLinear(r);
323
- const lg = figEditorRgbToLinear(g);
324
- const lb = figEditorRgbToLinear(b);
325
- const l_ = Math.cbrt(
326
- 0.4122214708 * lr + 0.5363325363 * lg + 0.0514459929 * lb,
327
- );
328
- const m_ = Math.cbrt(
329
- 0.2119034982 * lr + 0.6806995451 * lg + 0.1073969566 * lb,
330
- );
331
- const s_ = Math.cbrt(
332
- 0.0883024619 * lr + 0.2817188376 * lg + 0.6299787005 * lb,
333
- );
334
- return {
335
- l: 0.2104542553 * l_ + 0.793617785 * m_ - 0.0040720468 * s_,
336
- a: 1.9779984951 * l_ - 2.428592205 * m_ + 0.4505937099 * s_,
337
- b: 0.0259040371 * l_ + 0.7827717662 * m_ - 0.808675766 * s_,
338
- };
339
- }
340
-
341
- function figEditorOklabToOklch(L, a, b) {
342
- return {
343
- l: L,
344
- c: Math.sqrt(a * a + b * b),
345
- h: (Math.atan2(b, a) * 180) / Math.PI,
346
- };
347
- }
348
-
349
229
  function figEditorCreateOverflowButtons({
350
230
  owner,
351
231
  onStart,
@@ -460,262 +340,6 @@ function figEditorScrollElementToCenter(
460
340
  });
461
341
  }
462
342
 
463
-
464
- /**
465
- * A reusable editor for an ordered palette of solid colors.
466
- * @attr {string} value - JSON array of hex strings or {color,alpha} objects, or comma-separated hex
467
- * @attr {number} min - Minimum number of colors (default: 2)
468
- * @attr {number} max - Maximum number of colors (unbounded when omitted)
469
- * @attr {boolean} fixed - Locks palette length while preserving color editing and reordering
470
- * @attr {boolean} disabled - Disables editing and reordering
471
- * @fires input - During color editing or reordering (detail: normalized color array)
472
- * @fires change - On committed color edits, add, remove, or reorder
473
- */
474
- class FigPaletteEditor extends HTMLElement {
475
- #colors = [];
476
- #syncingValueAttribute = false;
477
-
478
- static get observedAttributes() {
479
- return ["value", "min", "max", "fixed", "disabled"];
480
- }
481
-
482
- get #min() {
483
- const value = Number.parseInt(this.getAttribute("min"), 10);
484
- return Number.isFinite(value) ? Math.max(0, value) : 2;
485
- }
486
-
487
- get #max() {
488
- const value = Number.parseInt(this.getAttribute("max"), 10);
489
- return Number.isFinite(value) ? Math.max(this.#min, value) : Infinity;
490
- }
491
-
492
- get #fixed() {
493
- return figEditorBooleanAttribute(this, "fixed");
494
- }
495
-
496
- get #disabled() {
497
- return figEditorBooleanAttribute(this, "disabled");
498
- }
499
-
500
- get value() {
501
- return this.#colors.map((entry) => ({ ...entry }));
502
- }
503
-
504
- set value(value) {
505
- this.setAttribute(
506
- "value",
507
- typeof value === "string" ? value : JSON.stringify(value ?? []),
508
- );
509
- }
510
-
511
- connectedCallback() {
512
- this.#colors = figEditorNormalizePaletteValue(this.getAttribute("value"));
513
- this.#render();
514
- }
515
-
516
- attributeChangedCallback(name, oldValue, newValue) {
517
- if (oldValue === newValue || this.#syncingValueAttribute) return;
518
- if (name === "value") {
519
- this.#colors = figEditorNormalizePaletteValue(newValue);
520
- }
521
- if (this.isConnected) this.#render();
522
- }
523
-
524
- #reflectValue() {
525
- this.#syncingValueAttribute = true;
526
- this.setAttribute("value", JSON.stringify(this.#colors));
527
- this.#syncingValueAttribute = false;
528
- }
529
-
530
- #emit(type) {
531
- this.dispatchEvent(
532
- new CustomEvent(type, {
533
- bubbles: true,
534
- detail: this.value,
535
- }),
536
- );
537
- }
538
-
539
- #commit(type, { rerender = false } = {}) {
540
- this.#reflectValue();
541
- if (rerender) this.#render();
542
- this.#emit(type);
543
- }
544
-
545
- #removeRow(row) {
546
- const currentIndex = Number.parseInt(row?.dataset.index ?? "", 10);
547
- if (
548
- this.#disabled ||
549
- this.#fixed ||
550
- this.#colors.length <= this.#min ||
551
- !Number.isInteger(currentIndex)
552
- ) {
553
- return;
554
- }
555
- this.#colors.splice(currentIndex, 1);
556
- this.#reflectValue();
557
- this.#render();
558
- this.#emit("input");
559
- this.#emit("change");
560
- }
561
-
562
- #createRow(entry, index) {
563
- const colorInput = figEditorCreateElement("fig-input-color", {
564
- className: "fig-palette-editor-color",
565
- slot: "input",
566
- value: figEditorPaletteEntryValue(entry),
567
- text: true,
568
- alpha: true,
569
- full: true,
570
- disabled: this.#disabled || null,
571
- "aria-label": `Palette color ${index + 1}`,
572
- });
573
- const syncColor = (event, type) => {
574
- event.stopPropagation();
575
- const row = colorInput.closest(".fig-palette-editor-color-row");
576
- const currentIndex = Number.parseInt(row?.dataset.index ?? "", 10);
577
- if (!Number.isInteger(currentIndex) || !this.#colors[currentIndex]) return;
578
- this.#colors[currentIndex] = {
579
- color:
580
- colorInput.hexOpaque ||
581
- this.#colors[currentIndex]?.color ||
582
- "#D9D9D9",
583
- alpha:
584
- colorInput.rgba?.a ?? this.#colors[currentIndex]?.alpha ?? 1,
585
- };
586
- this.#commit(type);
587
- };
588
- colorInput.addEventListener("input", (event) =>
589
- syncColor(event, "input"),
590
- );
591
- colorInput.addEventListener("change", (event) =>
592
- syncColor(event, "change"),
593
- );
594
-
595
- const row = figEditorCreateElement(
596
- "fig-property",
597
- {
598
- className: "fig-palette-editor-color-row",
599
- "data-index": index,
600
- leading: "drag",
601
- trailing: this.#fixed ? null : "remove",
602
- "show-trailing": this.#fixed ? null : true,
603
- },
604
- colorInput,
605
- );
606
- row.addEventListener("remove", (event) => {
607
- event.stopPropagation();
608
- this.#removeRow(row);
609
- });
610
- return row;
611
- }
612
-
613
- #handleReorder = (event) => {
614
- const oldIndex = Number(event.detail?.oldIndex);
615
- const newIndex = Number(event.detail?.newIndex);
616
- if (
617
- !Number.isInteger(oldIndex) ||
618
- !Number.isInteger(newIndex) ||
619
- oldIndex === newIndex ||
620
- oldIndex < 0 ||
621
- newIndex < 0 ||
622
- oldIndex >= this.#colors.length ||
623
- newIndex >= this.#colors.length
624
- ) {
625
- return;
626
- }
627
- const [entry] = this.#colors.splice(oldIndex, 1);
628
- this.#colors.splice(newIndex, 0, entry);
629
- this.querySelectorAll(".fig-palette-editor-color-row").forEach(
630
- (row, index) => {
631
- row.dataset.index = String(index);
632
- row
633
- .querySelector(".fig-palette-editor-color")
634
- ?.setAttribute("aria-label", `Palette color ${index + 1}`);
635
- row
636
- .querySelector(".fig-palette-editor-remove")
637
- ?.setAttribute("aria-label", `Remove color ${index + 1}`);
638
- },
639
- );
640
- this.#reflectValue();
641
- this.#emit("input");
642
- this.#emit("change");
643
- };
644
-
645
- #focusColorValue(index) {
646
- requestAnimationFrame(() => {
647
- if (!this.isConnected) return;
648
- const input = this.querySelector(
649
- `.fig-palette-editor-color-row[data-index="${index}"] .fig-palette-editor-color fig-input-text input`,
650
- );
651
- input?.focus();
652
- input?.select();
653
- });
654
- }
655
-
656
- #render() {
657
- const reorder = figEditorCreateElement(
658
- "fig-reorder",
659
- {
660
- axis: "vertical",
661
- items: ".fig-palette-editor-color-row",
662
- "aria-label": "Palette colors",
663
- disabled: this.#disabled || null,
664
- },
665
- this.#colors.map((entry, index) => this.#createRow(entry, index)),
666
- );
667
- reorder.addEventListener("reorder", this.#handleReorder);
668
-
669
- const children = [reorder];
670
- if (!this.#fixed) {
671
- const addButton = figEditorCreateElement(
672
- "fig-button",
673
- {
674
- className: "fig-palette-editor-add",
675
- variant: "secondary",
676
- full: true,
677
- disabled:
678
- this.#disabled || this.#colors.length >= this.#max || null,
679
- },
680
- "Add color",
681
- );
682
- addButton.addEventListener("click", () => {
683
- if (this.#disabled || this.#colors.length >= this.#max) return;
684
- const addedIndex = this.#colors.length;
685
- this.#colors.push(
686
- figEditorAveragePaletteEntries(
687
- this.#colors.at(-2),
688
- this.#colors.at(-1),
689
- ),
690
- );
691
- this.#reflectValue();
692
- this.#render();
693
- this.#emit("input");
694
- this.#emit("change");
695
- this.#focusColorValue(addedIndex);
696
- });
697
- children.push(figEditorCreateElement("fig-field", {}, addButton));
698
- }
699
- this.replaceChildren(...children);
700
- this.querySelectorAll(".fig-palette-editor-color-row").forEach(
701
- (row, index) => {
702
- const remove = row.querySelector(
703
- ':scope > [data-fig-property-action="remove"]',
704
- );
705
- if (!remove) return;
706
- remove.classList.add("fig-palette-editor-remove");
707
- remove.setAttribute("aria-label", `Remove color ${index + 1}`);
708
- remove.toggleAttribute(
709
- "disabled",
710
- this.#disabled || this.#colors.length <= this.#min,
711
- );
712
- },
713
- );
714
- }
715
- }
716
- figEditorDefineElement("fig-palette-editor", FigPaletteEditor);
717
-
718
-
719
343
  /* Select — dropdown-styled trigger + fig-popup listbox */
720
344
  /** Parse options attr — same formats as fig-options. */
721
345
  function figSelectParseOptionsAttribute(raw) {
@@ -3745,8 +3369,15 @@ class FigFillPicker extends HTMLElement {
3745
3369
  const gradH = ctx.createLinearGradient(0, 0, width, 0);
3746
3370
  if (isP3) {
3747
3371
  gradH.addColorStop(0, "color(display-p3 1 1 1)");
3748
- const [r, g, b] = hslToP3(hue, 100, 50);
3749
- gradH.addColorStop(1, `color(display-p3 ${r} ${g} ${b})`);
3372
+ const srgb = figHslToRGB(hue, 100, 50);
3373
+ const p3 = figConvertRGB(srgb.r, srgb.g, srgb.b, {
3374
+ from: "srgb",
3375
+ to: "display-p3",
3376
+ });
3377
+ gradH.addColorStop(
3378
+ 1,
3379
+ `color(display-p3 ${p3.r / 255} ${p3.g / 255} ${p3.b / 255})`,
3380
+ );
3750
3381
  } else {
3751
3382
  gradH.addColorStop(0, "#FFFFFF");
3752
3383
  gradH.addColorStop(1, `hsl(${hue}, 100%, 50%)`);
@@ -5838,91 +5469,11 @@ class FigFillPicker extends HTMLElement {
5838
5469
 
5839
5470
  // ============ COLOR CONVERSION UTILITIES ============
5840
5471
  #hsvToRGB(hsv) {
5841
- const h = hsv.h / 360;
5842
- const s = hsv.s / 100;
5843
- const v = hsv.v / 100;
5844
-
5845
- let r, g, b;
5846
- const i = Math.floor(h * 6);
5847
- const f = h * 6 - i;
5848
- const p = v * (1 - s);
5849
- const q = v * (1 - f * s);
5850
- const t = v * (1 - (1 - f) * s);
5851
-
5852
- switch (i % 6) {
5853
- case 0:
5854
- r = v;
5855
- g = t;
5856
- b = p;
5857
- break;
5858
- case 1:
5859
- r = q;
5860
- g = v;
5861
- b = p;
5862
- break;
5863
- case 2:
5864
- r = p;
5865
- g = v;
5866
- b = t;
5867
- break;
5868
- case 3:
5869
- r = p;
5870
- g = q;
5871
- b = v;
5872
- break;
5873
- case 4:
5874
- r = t;
5875
- g = p;
5876
- b = v;
5877
- break;
5878
- case 5:
5879
- r = v;
5880
- g = p;
5881
- b = q;
5882
- break;
5883
- }
5884
-
5885
- return {
5886
- r: Math.round(r * 255),
5887
- g: Math.round(g * 255),
5888
- b: Math.round(b * 255),
5889
- };
5472
+ return figHsvToRGB(hsv.h, hsv.s, hsv.v);
5890
5473
  }
5891
5474
 
5892
5475
  #rgbToHSV(rgb) {
5893
- const r = rgb.r / 255;
5894
- const g = rgb.g / 255;
5895
- const b = rgb.b / 255;
5896
-
5897
- const max = Math.max(r, g, b);
5898
- const min = Math.min(r, g, b);
5899
- const d = max - min;
5900
-
5901
- let h = 0;
5902
- const s = max === 0 ? 0 : d / max;
5903
- const v = max;
5904
-
5905
- if (max !== min) {
5906
- switch (max) {
5907
- case r:
5908
- h = (g - b) / d + (g < b ? 6 : 0);
5909
- break;
5910
- case g:
5911
- h = (b - r) / d + 2;
5912
- break;
5913
- case b:
5914
- h = (r - g) / d + 4;
5915
- break;
5916
- }
5917
- h /= 6;
5918
- }
5919
-
5920
- return {
5921
- h: h * 360,
5922
- s: s * 100,
5923
- v: v * 100,
5924
- a: 1,
5925
- };
5476
+ return { ...figRGBToHsv(rgb.r, rgb.g, rgb.b), a: 1 };
5926
5477
  }
5927
5478
 
5928
5479
  #hsvToHex(hsv) {
@@ -6007,145 +5558,39 @@ class FigFillPicker extends HTMLElement {
6007
5558
  }
6008
5559
 
6009
5560
  #hexToP3(hex, alpha = 1) {
6010
- const r = +(parseInt(hex.slice(1, 3), 16) / 255).toFixed(4);
6011
- const g = +(parseInt(hex.slice(3, 5), 16) / 255).toFixed(4);
6012
- const b = +(parseInt(hex.slice(5, 7), 16) / 255).toFixed(4);
5561
+ const srgb = figEditorHexToRgb(hex);
5562
+ const p3 = figConvertRGB(srgb.r, srgb.g, srgb.b, {
5563
+ from: "srgb",
5564
+ to: "display-p3",
5565
+ });
5566
+ const r = +(p3.r / 255).toFixed(4);
5567
+ const g = +(p3.g / 255).toFixed(4);
5568
+ const b = +(p3.b / 255).toFixed(4);
6013
5569
  return `color(display-p3 ${r} ${g} ${b} / ${alpha})`;
6014
5570
  }
6015
5571
 
6016
5572
  #rgbToHSL(rgb) {
6017
- const r = rgb.r / 255;
6018
- const g = rgb.g / 255;
6019
- const b = rgb.b / 255;
6020
-
6021
- const max = Math.max(r, g, b);
6022
- const min = Math.min(r, g, b);
6023
- let h, s;
6024
- const l = (max + min) / 2;
6025
-
6026
- if (max === min) {
6027
- h = s = 0;
6028
- } else {
6029
- const d = max - min;
6030
- s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
6031
-
6032
- switch (max) {
6033
- case r:
6034
- h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
6035
- break;
6036
- case g:
6037
- h = ((b - r) / d + 2) / 6;
6038
- break;
6039
- case b:
6040
- h = ((r - g) / d + 4) / 6;
6041
- break;
6042
- }
6043
- }
6044
-
6045
- return { h: h * 360, s: s * 100, l: l * 100 };
5573
+ return figEditorRgbToHsl(rgb.r, rgb.g, rgb.b);
6046
5574
  }
6047
5575
 
6048
5576
  #hslToRGB(hsl) {
6049
- const h = hsl.h / 360;
6050
- const s = hsl.s / 100;
6051
- const l = hsl.l / 100;
6052
-
6053
- let r, g, b;
6054
-
6055
- if (s === 0) {
6056
- r = g = b = l;
6057
- } else {
6058
- const hue2rgb = (p, q, t) => {
6059
- if (t < 0) t += 1;
6060
- if (t > 1) t -= 1;
6061
- if (t < 1 / 6) return p + (q - p) * 6 * t;
6062
- if (t < 1 / 2) return q;
6063
- if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
6064
- return p;
6065
- };
6066
-
6067
- const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
6068
- const p = 2 * l - q;
6069
-
6070
- r = hue2rgb(p, q, h + 1 / 3);
6071
- g = hue2rgb(p, q, h);
6072
- b = hue2rgb(p, q, h - 1 / 3);
6073
- }
6074
-
6075
- return {
6076
- r: Math.round(r * 255),
6077
- g: Math.round(g * 255),
6078
- b: Math.round(b * 255),
6079
- };
5577
+ return figHslToRGB(hsl.h, hsl.s, hsl.l);
6080
5578
  }
6081
5579
 
6082
- // OKLAB/OKLCH conversions (simplified)
6083
5580
  #rgbToOKLAB(rgb) {
6084
- // Convert to linear sRGB
6085
- const toLinear = (c) => {
6086
- c = c / 255;
6087
- return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
6088
- };
6089
-
6090
- const r = toLinear(rgb.r);
6091
- const g = toLinear(rgb.g);
6092
- const b = toLinear(rgb.b);
6093
-
6094
- // Convert to LMS
6095
- const l = 0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b;
6096
- const m = 0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b;
6097
- const s = 0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b;
6098
-
6099
- // Convert to Oklab
6100
- const l_ = Math.cbrt(l);
6101
- const m_ = Math.cbrt(m);
6102
- const s_ = Math.cbrt(s);
6103
-
6104
- return {
6105
- l: 0.2104542553 * l_ + 0.793617785 * m_ - 0.0040720468 * s_,
6106
- a: 1.9779984951 * l_ - 2.428592205 * m_ + 0.4505937099 * s_,
6107
- b: 0.0259040371 * l_ + 0.7827717662 * m_ - 0.808675766 * s_,
6108
- };
5581
+ return figEditorRgbToOklab(rgb.r, rgb.g, rgb.b);
6109
5582
  }
6110
5583
 
6111
5584
  #rgbToOKLCH(rgb) {
6112
- const lab = this.#rgbToOKLAB(rgb);
6113
- return {
6114
- l: lab.l,
6115
- c: Math.sqrt(lab.a * lab.a + lab.b * lab.b),
6116
- h: ((Math.atan2(lab.b, lab.a) * 180) / Math.PI + 360) % 360,
6117
- };
5585
+ return figRGBToOklch(rgb.r, rgb.g, rgb.b);
6118
5586
  }
6119
5587
 
6120
5588
  #oklabToRGB(lab) {
6121
- const l_ = lab.l + 0.3963377774 * lab.a + 0.2158037573 * lab.b;
6122
- const m_ = lab.l - 0.1055613458 * lab.a - 0.0638541728 * lab.b;
6123
- const s_ = lab.l - 0.0894841775 * lab.a - 1.291485548 * lab.b;
6124
-
6125
- const l = l_ * l_ * l_;
6126
- const m = m_ * m_ * m_;
6127
- const s = s_ * s_ * s_;
6128
-
6129
- const toSRGB = (c) => {
6130
- const v =
6131
- c <= 0.0031308 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055;
6132
- return Math.round(Math.max(0, Math.min(1, v)) * 255);
6133
- };
6134
-
6135
- return {
6136
- r: toSRGB(+4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s),
6137
- g: toSRGB(-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s),
6138
- b: toSRGB(-0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s),
6139
- };
5589
+ return figOklabToRGB(lab.l, lab.a, lab.b);
6140
5590
  }
6141
5591
 
6142
5592
  #oklchToRGB(lch) {
6143
- const hRad = (lch.h * Math.PI) / 180;
6144
- return this.#oklabToRGB({
6145
- l: lch.l,
6146
- a: lch.c * Math.cos(hRad),
6147
- b: lch.c * Math.sin(hRad),
6148
- });
5593
+ return figOklchToRGB(lch.l, lch.c, lch.h);
6149
5594
  }
6150
5595
 
6151
5596
  // ============ EVENT EMITTERS ============