@node-projects/web-component-designer 0.2.22 → 0.2.24

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 (118) hide show
  1. package/dist/elements/controls/ColorEditor.d.ts +82 -0
  2. package/dist/elements/controls/ColorEditor.js +972 -0
  3. package/dist/elements/controls/ColorEditor.js.map +1 -0
  4. package/dist/elements/controls/MetricsEditor.d.ts +26 -4
  5. package/dist/elements/controls/MetricsEditor.js +376 -130
  6. package/dist/elements/controls/MetricsEditor.js.map +1 -1
  7. package/dist/elements/helper/CssAttributeParser.d.ts +3 -1
  8. package/dist/elements/helper/CssAttributeParser.js +12 -3
  9. package/dist/elements/helper/CssAttributeParser.js.map +1 -1
  10. package/dist/elements/helper/CssImportant.d.ts +5 -0
  11. package/dist/elements/helper/CssImportant.js +12 -0
  12. package/dist/elements/helper/CssImportant.js.map +1 -0
  13. package/dist/elements/helper/DesignerStylesheetPatcher.d.ts +9 -0
  14. package/dist/elements/helper/DesignerStylesheetPatcher.js +11 -0
  15. package/dist/elements/helper/DesignerStylesheetPatcher.js.map +1 -0
  16. package/dist/elements/helper/LayoutHelper.d.ts +1 -0
  17. package/dist/elements/helper/LayoutHelper.js +11 -1
  18. package/dist/elements/helper/LayoutHelper.js.map +1 -1
  19. package/dist/elements/helper/PathDataPolyfill.d.ts +1 -0
  20. package/dist/elements/helper/PathDataPolyfill.js +20 -0
  21. package/dist/elements/helper/PathDataPolyfill.js.map +1 -1
  22. package/dist/elements/item/DesignItem.d.ts +6 -3
  23. package/dist/elements/item/DesignItem.js +51 -28
  24. package/dist/elements/item/DesignItem.js.map +1 -1
  25. package/dist/elements/item/IDesignItem.d.ts +3 -1
  26. package/dist/elements/services/DefaultServiceBootstrap.js +3 -1
  27. package/dist/elements/services/DefaultServiceBootstrap.js.map +1 -1
  28. package/dist/elements/services/ServiceContainer.d.ts +3 -0
  29. package/dist/elements/services/ServiceContainer.js +3 -0
  30. package/dist/elements/services/ServiceContainer.js.map +1 -1
  31. package/dist/elements/services/elementsService/IElementsService.d.ts +3 -0
  32. package/dist/elements/services/htmlWriterService/AbstractHtmlWriterService.js +9 -5
  33. package/dist/elements/services/htmlWriterService/AbstractHtmlWriterService.js.map +1 -1
  34. package/dist/elements/services/htmlWriterService/FormatingHtmlWriterService.js +7 -4
  35. package/dist/elements/services/htmlWriterService/FormatingHtmlWriterService.js.map +1 -1
  36. package/dist/elements/services/htmlWriterService/IHtmlWriterService.d.ts +7 -0
  37. package/dist/elements/services/htmlWriterService/SimpleHtmlWriterService.js +7 -4
  38. package/dist/elements/services/htmlWriterService/SimpleHtmlWriterService.js.map +1 -1
  39. package/dist/elements/services/placementService/AbsolutePlacementService.js +6 -2
  40. package/dist/elements/services/placementService/AbsolutePlacementService.js.map +1 -1
  41. package/dist/elements/services/placementService/DefaultPlacementService.js +6 -2
  42. package/dist/elements/services/placementService/DefaultPlacementService.js.map +1 -1
  43. package/dist/elements/services/propertiesService/DefaultEditorTypeService.js +3 -4
  44. package/dist/elements/services/propertiesService/DefaultEditorTypeService.js.map +1 -1
  45. package/dist/elements/services/propertiesService/DefaultPropertyEditorTypesService.d.ts +1 -0
  46. package/dist/elements/services/propertiesService/DefaultPropertyEditorTypesService.js +7 -0
  47. package/dist/elements/services/propertiesService/DefaultPropertyEditorTypesService.js.map +1 -1
  48. package/dist/elements/services/propertiesService/IProperty.d.ts +1 -0
  49. package/dist/elements/services/propertiesService/propertyEditors/ColorPropertyEditor.d.ts +2 -1
  50. package/dist/elements/services/propertiesService/propertyEditors/ColorPropertyEditor.js +6 -12
  51. package/dist/elements/services/propertiesService/propertyEditors/ColorPropertyEditor.js.map +1 -1
  52. package/dist/elements/services/propertiesService/propertyEditors/CssPropertyEditor.d.ts +22 -0
  53. package/dist/elements/services/propertiesService/propertyEditors/CssPropertyEditor.js +101 -0
  54. package/dist/elements/services/propertiesService/propertyEditors/CssPropertyEditor.js.map +1 -0
  55. package/dist/elements/services/propertiesService/propertyEditors/special/MetricsPropertyEditor.d.ts +1 -0
  56. package/dist/elements/services/propertiesService/propertyEditors/special/MetricsPropertyEditor.js +24 -2
  57. package/dist/elements/services/propertiesService/propertyEditors/special/MetricsPropertyEditor.js.map +1 -1
  58. package/dist/elements/services/propertiesService/services/AbstractCssPropertiesService.js +4 -2
  59. package/dist/elements/services/propertiesService/services/AbstractCssPropertiesService.js.map +1 -1
  60. package/dist/elements/services/propertiesService/services/AbstractPropertiesService.js +4 -2
  61. package/dist/elements/services/propertiesService/services/AbstractPropertiesService.js.map +1 -1
  62. package/dist/elements/services/propertiesService/services/CssCurrentPropertiesService.js +7 -5
  63. package/dist/elements/services/propertiesService/services/CssCurrentPropertiesService.js.map +1 -1
  64. package/dist/elements/services/propertiesService/services/CssCustomPropertiesService.js +2 -1
  65. package/dist/elements/services/propertiesService/services/CssCustomPropertiesService.js.map +1 -1
  66. package/dist/elements/services/propertiesService/services/CssPropertiesService.js +1 -1
  67. package/dist/elements/services/propertiesService/services/CssPropertiesService.js.map +1 -1
  68. package/dist/elements/services/renderedDesignItemService/IRenderedDesignItemService.d.ts +5 -0
  69. package/dist/elements/services/renderedDesignItemService/IRenderedDesignItemService.js +2 -0
  70. package/dist/elements/services/renderedDesignItemService/IRenderedDesignItemService.js.map +1 -0
  71. package/dist/elements/services/renderedDesignItemService/StyleElementRenderedDesignItemService.d.ts +11 -0
  72. package/dist/elements/services/renderedDesignItemService/StyleElementRenderedDesignItemService.js +73 -0
  73. package/dist/elements/services/renderedDesignItemService/StyleElementRenderedDesignItemService.js.map +1 -0
  74. package/dist/elements/services/stylesheetService/AbstractStylesheetService.js +12 -8
  75. package/dist/elements/services/stylesheetService/AbstractStylesheetService.js.map +1 -1
  76. package/dist/elements/services/undoService/transactionItems/CssStyleChangeAction.d.ts +3 -1
  77. package/dist/elements/services/undoService/transactionItems/CssStyleChangeAction.js +9 -15
  78. package/dist/elements/services/undoService/transactionItems/CssStyleChangeAction.js.map +1 -1
  79. package/dist/elements/services/undoService/transactionItems/TextContentChangeAction.js +2 -0
  80. package/dist/elements/services/undoService/transactionItems/TextContentChangeAction.js.map +1 -1
  81. package/dist/elements/widgets/designerView/DomConverter.d.ts +1 -1
  82. package/dist/elements/widgets/designerView/designerView.js +4 -1
  83. package/dist/elements/widgets/designerView/designerView.js.map +1 -1
  84. package/dist/elements/widgets/designerView/extensions/svg/UnifiedGeometryExtension.d.ts +3 -0
  85. package/dist/elements/widgets/designerView/extensions/svg/UnifiedGeometryExtension.js +102 -16
  86. package/dist/elements/widgets/designerView/extensions/svg/UnifiedGeometryExtension.js.map +1 -1
  87. package/dist/elements/widgets/designerView/extensions/svg/geometry/GeometryWriteHelper.d.ts +4 -1
  88. package/dist/elements/widgets/designerView/extensions/svg/geometry/GeometryWriteHelper.js +26 -3
  89. package/dist/elements/widgets/designerView/extensions/svg/geometry/GeometryWriteHelper.js.map +1 -1
  90. package/dist/elements/widgets/designerView/tools/DrawEllipsisTool.js +8 -4
  91. package/dist/elements/widgets/designerView/tools/DrawEllipsisTool.js.map +1 -1
  92. package/dist/elements/widgets/designerView/tools/DrawLineTool.js +8 -6
  93. package/dist/elements/widgets/designerView/tools/DrawLineTool.js.map +1 -1
  94. package/dist/elements/widgets/designerView/tools/DrawPathTool.d.ts +2 -0
  95. package/dist/elements/widgets/designerView/tools/DrawPathTool.js +15 -6
  96. package/dist/elements/widgets/designerView/tools/DrawPathTool.js.map +1 -1
  97. package/dist/elements/widgets/designerView/tools/DrawRectTool.js +8 -4
  98. package/dist/elements/widgets/designerView/tools/DrawRectTool.js.map +1 -1
  99. package/dist/elements/widgets/designerView/tools/toolBar/popups/DrawToolPopup.js +3 -0
  100. package/dist/elements/widgets/designerView/tools/toolBar/popups/DrawToolPopup.js.map +1 -1
  101. package/dist/elements/widgets/layerDepthView/ILayerDepthView.d.ts +2 -0
  102. package/dist/elements/widgets/layerDepthView/ILayerDepthView.js +2 -0
  103. package/dist/elements/widgets/layerDepthView/ILayerDepthView.js.map +1 -0
  104. package/dist/elements/widgets/layerDepthView/layerDepthView.d.ts +46 -0
  105. package/dist/elements/widgets/layerDepthView/layerDepthView.js +341 -0
  106. package/dist/elements/widgets/layerDepthView/layerDepthView.js.map +1 -0
  107. package/dist/elements/widgets/paletteView/paletteElements.js +1 -0
  108. package/dist/elements/widgets/paletteView/paletteElements.js.map +1 -1
  109. package/dist/elements/widgets/paletteView/paletteView.js +3 -0
  110. package/dist/elements/widgets/paletteView/paletteView.js.map +1 -1
  111. package/dist/elements/widgets/propertyGrid/PropertyGridPropertyList.js +6 -1
  112. package/dist/elements/widgets/propertyGrid/PropertyGridPropertyList.js.map +1 -1
  113. package/dist/index-min.js +16 -13
  114. package/dist/index-min.js.map +4 -4
  115. package/dist/index.d.ts +8 -0
  116. package/dist/index.js +6 -0
  117. package/dist/index.js.map +1 -1
  118. package/package.json +1 -1
@@ -0,0 +1,972 @@
1
+ import { BaseCustomWebComponentConstructorAppend, css, html, TypedEvent } from '@node-projects/base-custom-webcomponent';
2
+ import { w3color } from '../helper/w3color.js';
3
+ const modes = ['rgb', 'hsl', 'cmyk', 'oklab', 'oklch'];
4
+ const epsilon = 0.000001;
5
+ export class ColorEditor extends BaseCustomWebComponentConstructorAppend {
6
+ static style = css `
7
+ :host {
8
+ display: block;
9
+ box-sizing: border-box;
10
+ width: 280px;
11
+ color: var(--property-grid-text-color, #e8edf2);
12
+ font: 12px system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
13
+ }
14
+
15
+ #editor {
16
+ display: grid;
17
+ gap: 10px;
18
+ box-sizing: border-box;
19
+ padding: 12px;
20
+ border: 1px solid rgba(255, 255, 255, .14);
21
+ border-radius: 8px;
22
+ background: var(--color-editor-background, #20252b);
23
+ box-shadow: 0 14px 38px rgba(0, 0, 0, .36);
24
+ }
25
+
26
+ #plane {
27
+ position: relative;
28
+ height: 150px;
29
+ border-radius: 6px;
30
+ overflow: hidden;
31
+ cursor: crosshair;
32
+ background:
33
+ linear-gradient(to top, #000, transparent),
34
+ linear-gradient(to right, #fff, transparent),
35
+ hsl(var(--hue, 0) 100% 50%);
36
+ box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .12);
37
+ touch-action: none;
38
+ }
39
+
40
+ #plane-handle {
41
+ position: absolute;
42
+ width: 12px;
43
+ height: 12px;
44
+ box-sizing: border-box;
45
+ border: 2px solid white;
46
+ border-radius: 50%;
47
+ transform: translate(-6px, -6px);
48
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, .85), 0 1px 4px rgba(0, 0, 0, .55);
49
+ pointer-events: none;
50
+ }
51
+
52
+ .slider-row {
53
+ display: grid;
54
+ grid-template-columns: 18px minmax(0, 1fr) 42px;
55
+ gap: 8px;
56
+ align-items: center;
57
+ }
58
+
59
+ .slider-row span {
60
+ color: rgba(232, 237, 242, .68);
61
+ font-size: 11px;
62
+ text-transform: uppercase;
63
+ }
64
+
65
+ input[type="range"] {
66
+ --slider-background: #79b8ff;
67
+ -webkit-appearance: none;
68
+ appearance: none;
69
+ width: 100%;
70
+ height: 16px;
71
+ margin: 0;
72
+ background: transparent;
73
+ outline: none;
74
+ }
75
+
76
+ #hue {
77
+ --slider-background: linear-gradient(to right, #f00, #ff0, #0f0, #0ff, #00f, #f0f, #f00);
78
+ }
79
+
80
+ #alpha {
81
+ --slider-background:
82
+ linear-gradient(to right, rgba(var(--rgb-color, 0, 0, 0), 0), var(--opaque-color, #000)),
83
+ linear-gradient(45deg, rgba(255, 255, 255, .24) 25%, transparent 25% 75%, rgba(255, 255, 255, .24) 75%),
84
+ linear-gradient(45deg, rgba(255, 255, 255, .24) 25%, transparent 25% 75%, rgba(255, 255, 255, .24) 75%),
85
+ #2a3037;
86
+ --slider-background-position: 0 0, 0 0, 5px 5px, 0 0;
87
+ --slider-background-size: auto, 10px 10px, 10px 10px, auto;
88
+ }
89
+
90
+ input[type="range"]::-webkit-slider-runnable-track {
91
+ height: 7px;
92
+ border-radius: 999px;
93
+ background: var(--slider-background);
94
+ background-position: var(--slider-background-position, 0 0);
95
+ background-size: var(--slider-background-size, auto);
96
+ box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .22);
97
+ }
98
+
99
+ input[type="range"]::-moz-range-track {
100
+ height: 7px;
101
+ border-radius: 999px;
102
+ background: var(--slider-background);
103
+ background-position: var(--slider-background-position, 0 0);
104
+ background-size: var(--slider-background-size, auto);
105
+ box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .22);
106
+ }
107
+
108
+ input[type="range"]::-webkit-slider-thumb {
109
+ -webkit-appearance: none;
110
+ appearance: none;
111
+ width: 14px;
112
+ height: 14px;
113
+ margin-top: -3.5px;
114
+ border: 2px solid white;
115
+ border-radius: 50%;
116
+ background: hsl(var(--hue, 0) 100% 50%);
117
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, .75), 0 1px 3px rgba(0, 0, 0, .45);
118
+ }
119
+
120
+ input[type="range"]::-moz-range-thumb {
121
+ width: 10px;
122
+ height: 10px;
123
+ border: 2px solid white;
124
+ border-radius: 50%;
125
+ background: hsl(var(--hue, 0) 100% 50%);
126
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, .75), 0 1px 3px rgba(0, 0, 0, .45);
127
+ }
128
+
129
+ #alpha::-webkit-slider-thumb {
130
+ background: var(--color, #000);
131
+ }
132
+
133
+ #alpha::-moz-range-thumb {
134
+ background: var(--color, #000);
135
+ }
136
+
137
+ .swatch {
138
+ width: 42px;
139
+ height: 22px;
140
+ border-radius: 5px;
141
+ background:
142
+ linear-gradient(var(--color, #000), var(--color, #000)),
143
+ linear-gradient(45deg, rgba(255, 255, 255, .22) 25%, transparent 25% 75%, rgba(255, 255, 255, .22) 75%),
144
+ linear-gradient(45deg, rgba(255, 255, 255, .22) 25%, transparent 25% 75%, rgba(255, 255, 255, .22) 75%);
145
+ background-position: 0 0, 0 0, 5px 5px;
146
+ background-size: auto, 10px 10px, 10px 10px;
147
+ box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .16);
148
+ }
149
+
150
+ #mode {
151
+ height: 26px;
152
+ min-width: 0;
153
+ border: 1px solid rgba(255, 255, 255, .14);
154
+ border-radius: 5px;
155
+ background: #161a1f;
156
+ color: inherit;
157
+ font: inherit;
158
+ outline: none;
159
+ }
160
+
161
+ #channels {
162
+ display: grid;
163
+ grid-template-columns: repeat(4, minmax(0, 1fr));
164
+ gap: 6px;
165
+ }
166
+
167
+ label {
168
+ display: grid;
169
+ gap: 3px;
170
+ min-width: 0;
171
+ color: rgba(232, 237, 242, .68);
172
+ font-size: 10px;
173
+ text-transform: uppercase;
174
+ }
175
+
176
+ input[type="number"],
177
+ #text {
178
+ box-sizing: border-box;
179
+ width: 100%;
180
+ min-width: 0;
181
+ height: 26px;
182
+ border: 1px solid rgba(255, 255, 255, .14);
183
+ border-radius: 5px;
184
+ background: #161a1f;
185
+ color: inherit;
186
+ font: inherit;
187
+ outline: none;
188
+ }
189
+
190
+ input[type="number"] {
191
+ padding: 0 4px;
192
+ }
193
+
194
+ #text {
195
+ padding: 0 8px;
196
+ font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
197
+ text-transform: none;
198
+ }
199
+
200
+ #text.invalid {
201
+ border-color: #e66b6b;
202
+ box-shadow: 0 0 0 1px rgba(230, 107, 107, .35);
203
+ }
204
+
205
+ input:focus,
206
+ select:focus {
207
+ border-color: #79b8ff;
208
+ box-shadow: 0 0 0 1px rgba(121, 184, 255, .28);
209
+ }
210
+
211
+ :host([readonly]) input,
212
+ :host([readonly]) select,
213
+ :host([readonly]) #plane,
214
+ :host([disabled]) input,
215
+ :host([disabled]) select,
216
+ :host([disabled]) #plane {
217
+ opacity: .65;
218
+ pointer-events: none;
219
+ }
220
+ `;
221
+ static template = html `
222
+ <div id="editor">
223
+ <div id="plane"><div id="plane-handle"></div></div>
224
+ <div class="slider-row">
225
+ <span>Hue</span>
226
+ <input id="hue" type="range" min="0" max="360" step="1">
227
+ <div id="preview" class="swatch"></div>
228
+ </div>
229
+ <div class="slider-row">
230
+ <span>Alpha</span>
231
+ <input id="alpha" type="range" min="0" max="100" step="1">
232
+ <span id="alpha-label"></span>
233
+ </div>
234
+ <select id="mode" aria-label="Color mode">
235
+ <option value="rgb">RGB</option>
236
+ <option value="hsl">HSL</option>
237
+ <option value="cmyk">CMYK</option>
238
+ <option value="oklab">OKLab</option>
239
+ <option value="oklch">OKLCH</option>
240
+ </select>
241
+ <div id="channels"></div>
242
+ <input id="text" type="text" spellcheck="false" aria-label="Color text">
243
+ </div>
244
+ `;
245
+ valueChanged = new TypedEvent();
246
+ valuePreviewChanged = new TypedEvent();
247
+ _value = '#000000';
248
+ _color = { r: 0, g: 0, b: 0, a: 1 };
249
+ _mode = 'rgb';
250
+ _hue = 0;
251
+ _plane;
252
+ _planeHandle;
253
+ _hueInput;
254
+ _alphaInput;
255
+ _alphaLabel;
256
+ _modeSelect;
257
+ _channels;
258
+ _textInput;
259
+ _dragPointerId = null;
260
+ get value() {
261
+ return this._value;
262
+ }
263
+ set value(value) {
264
+ const parsed = parseColor(value);
265
+ if (parsed) {
266
+ this._color = parsed;
267
+ this._mode = inferColorMode(value) ?? this._mode;
268
+ this._syncHueFromColor();
269
+ this._value = this._formatColor();
270
+ this._render();
271
+ return;
272
+ }
273
+ this._value = value ?? '';
274
+ this._render();
275
+ }
276
+ get mode() {
277
+ return this._mode;
278
+ }
279
+ set mode(value) {
280
+ if (modes.includes(value)) {
281
+ this._mode = value;
282
+ this._value = this._formatColor();
283
+ this._render();
284
+ }
285
+ }
286
+ get readOnly() {
287
+ return this.hasAttribute('readonly');
288
+ }
289
+ set readOnly(value) {
290
+ this.toggleAttribute('readonly', value);
291
+ }
292
+ get disabled() {
293
+ return this.hasAttribute('disabled');
294
+ }
295
+ set disabled(value) {
296
+ this.toggleAttribute('disabled', value);
297
+ }
298
+ constructor() {
299
+ super();
300
+ this._plane = this._getDomElement('plane');
301
+ this._planeHandle = this._getDomElement('plane-handle');
302
+ this._hueInput = this._getDomElement('hue');
303
+ this._alphaInput = this._getDomElement('alpha');
304
+ this._alphaLabel = this._getDomElement('alpha-label');
305
+ this._modeSelect = this._getDomElement('mode');
306
+ this._channels = this._getDomElement('channels');
307
+ this._textInput = this._getDomElement('text');
308
+ }
309
+ ready() {
310
+ this._wireEvents();
311
+ const attributeValue = this.getAttribute('value');
312
+ if (attributeValue != null)
313
+ this.value = attributeValue;
314
+ const attributeMode = this.getAttribute('mode');
315
+ if (modes.includes(attributeMode)) {
316
+ this._mode = attributeMode;
317
+ this._value = this._formatColor();
318
+ }
319
+ this._render();
320
+ }
321
+ _wireEvents() {
322
+ this._plane.addEventListener('pointerdown', e => this._startPlaneDrag(e));
323
+ this._hueInput.addEventListener('input', () => this._applyHue(true));
324
+ this._hueInput.addEventListener('change', () => this._commitCurrentValue());
325
+ this._alphaInput.addEventListener('input', () => this._applyAlpha(true));
326
+ this._alphaInput.addEventListener('change', () => this._commitCurrentValue());
327
+ this._modeSelect.addEventListener('change', () => {
328
+ this.mode = this._modeSelect.value;
329
+ this._commitCurrentValue();
330
+ });
331
+ this._channels.addEventListener('input', () => this._applyChannelInputs(true));
332
+ this._channels.addEventListener('change', () => this._commitCurrentValue());
333
+ this._textInput.addEventListener('input', () => this._validateTextInput());
334
+ this._textInput.addEventListener('change', () => this._applyText());
335
+ this._textInput.addEventListener('keydown', e => {
336
+ if (e.key === 'Enter') {
337
+ this._applyText();
338
+ this._textInput.blur();
339
+ }
340
+ });
341
+ }
342
+ _startPlaneDrag(event) {
343
+ if (this.readOnly || this.disabled)
344
+ return;
345
+ this._dragPointerId = event.pointerId;
346
+ this._plane.setPointerCapture(event.pointerId);
347
+ this._applyPlanePointer(event, true);
348
+ this._plane.addEventListener('pointermove', this._planePointerMove);
349
+ this._plane.addEventListener('pointerup', this._finishPlaneDrag);
350
+ this._plane.addEventListener('pointercancel', this._finishPlaneDrag);
351
+ event.preventDefault();
352
+ }
353
+ _planePointerMove = (event) => {
354
+ if (event.pointerId === this._dragPointerId)
355
+ this._applyPlanePointer(event, true);
356
+ };
357
+ _finishPlaneDrag = (event) => {
358
+ if (event.pointerId !== this._dragPointerId)
359
+ return;
360
+ this._dragPointerId = null;
361
+ this._plane.removeEventListener('pointermove', this._planePointerMove);
362
+ this._plane.removeEventListener('pointerup', this._finishPlaneDrag);
363
+ this._plane.removeEventListener('pointercancel', this._finishPlaneDrag);
364
+ this._commitCurrentValue();
365
+ };
366
+ _applyPlanePointer(event, preview) {
367
+ const rect = this._plane.getBoundingClientRect();
368
+ const s = clamp((event.clientX - rect.left) / rect.width, 0, 1);
369
+ const v = clamp(1 - ((event.clientY - rect.top) / rect.height), 0, 1);
370
+ const hue = Number(this._hueInput.value) || 0;
371
+ this._hue = normalizeHue(hue);
372
+ this._setColor({ ...hsvToRgb(hue, s, v), a: this._color.a }, preview);
373
+ }
374
+ _applyHue(preview) {
375
+ const hsv = rgbToHsv(this._color);
376
+ const hue = Number(this._hueInput.value) || 0;
377
+ this._hue = normalizeHue(hue);
378
+ this._setColor({ ...hsvToRgb(hue, hsv.s || 1, hsv.v || 1), a: this._color.a }, preview);
379
+ }
380
+ _applyAlpha(preview) {
381
+ this._setColor({ ...this._color, a: clamp(Number(this._alphaInput.value) / 100, 0, 1) }, preview);
382
+ }
383
+ _applyChannelInputs(preview) {
384
+ const values = [...this._channels.querySelectorAll('input')].reduce((map, input) => {
385
+ map[input.name] = Number(input.value);
386
+ return map;
387
+ }, {});
388
+ let color;
389
+ if (this._mode === 'rgb')
390
+ color = { r: values.r, g: values.g, b: values.b, a: values.a / 100 };
391
+ else if (this._mode === 'hsl')
392
+ color = { ...hslToRgb(values.h, values.s / 100, values.l / 100), a: values.a / 100 };
393
+ else if (this._mode === 'cmyk')
394
+ color = { ...cmykToRgb(values.c / 100, values.m / 100, values.y / 100, values.k / 100), a: values.a / 100 };
395
+ else if (this._mode === 'oklab')
396
+ color = { ...oklabToRgb(values.l / 100, values.a1, values.b1), a: values.alpha / 100 };
397
+ else
398
+ color = { ...oklchToRgb(values.l / 100, values.c, values.h), a: values.a / 100 };
399
+ this._setColor(normalizeColor(color), preview, false, true);
400
+ }
401
+ _validateTextInput() {
402
+ const text = this._textInput.value.trim();
403
+ this._textInput.classList.toggle('invalid', text.length > 0 && !parseColor(text));
404
+ }
405
+ _applyText() {
406
+ const parsed = parseColor(this._textInput.value);
407
+ this._textInput.classList.toggle('invalid', !parsed);
408
+ if (!parsed)
409
+ return;
410
+ this._mode = inferColorMode(this._textInput.value) ?? this._mode;
411
+ this._setColor(parsed, false, true, true);
412
+ }
413
+ _setColor(color, preview, renderChannels = true, syncHue = false) {
414
+ const oldValue = this._value;
415
+ this._color = normalizeColor(color);
416
+ if (syncHue)
417
+ this._syncHueFromColor();
418
+ this._value = this._formatColor();
419
+ this._render(renderChannels);
420
+ if (preview)
421
+ this.valuePreviewChanged.emit({ newValue: this._value, oldValue });
422
+ else
423
+ this.valueChanged.emit({ newValue: this._value, oldValue });
424
+ }
425
+ _commitCurrentValue() {
426
+ const oldValue = this._value;
427
+ this._value = this._formatColor();
428
+ this.valueChanged.emit({ newValue: this._value, oldValue });
429
+ }
430
+ _render(renderChannels = true) {
431
+ if (!this._textInput)
432
+ return;
433
+ const hsv = rgbToHsv(this._color);
434
+ this.style.setProperty('--hue', String(Math.round(this._hue)));
435
+ this.style.setProperty('--color', toCssRgb(this._color));
436
+ this.style.setProperty('--opaque-color', `rgb(${this._color.r}, ${this._color.g}, ${this._color.b})`);
437
+ this.style.setProperty('--rgb-color', `${this._color.r}, ${this._color.g}, ${this._color.b}`);
438
+ this._planeHandle.style.left = `${hsv.s * 100}%`;
439
+ this._planeHandle.style.top = `${(1 - hsv.v) * 100}%`;
440
+ this._hueInput.value = String(Math.round(this._hue));
441
+ this._alphaInput.value = String(Math.round(this._color.a * 100));
442
+ this._alphaLabel.textContent = `${Math.round(this._color.a * 100)}%`;
443
+ this._modeSelect.value = this._mode;
444
+ if (renderChannels)
445
+ this._renderChannelInputs();
446
+ if (document.activeElement !== this._textInput)
447
+ this._textInput.value = this._value;
448
+ this._textInput.classList.remove('invalid');
449
+ }
450
+ _renderChannelInputs() {
451
+ const channels = getChannelValues(this._color, this._mode);
452
+ this._channels.innerHTML = channels.map(channel => `
453
+ <label>${channel.label}
454
+ <input type="number" name="${channel.name}" min="${channel.min}" max="${channel.max}" step="${channel.step}" value="${channel.value}">
455
+ </label>`).join('');
456
+ }
457
+ _formatColor() {
458
+ return formatColor(this._color, this._mode);
459
+ }
460
+ _syncHueFromColor() {
461
+ const hsv = rgbToHsv(this._color);
462
+ if (hsv.s > epsilon && hsv.v > epsilon)
463
+ this._hue = normalizeHue(hsv.h);
464
+ }
465
+ }
466
+ export class ColorInput extends BaseCustomWebComponentConstructorAppend {
467
+ static style = css `
468
+ :host {
469
+ display: inline-block;
470
+ box-sizing: border-box;
471
+ width: 100%;
472
+ height: 100%;
473
+ padding: 2px;
474
+ }
475
+
476
+ button {
477
+ display: block;
478
+ box-sizing: border-box;
479
+ width: 100%;
480
+ height: 100%;
481
+ padding: 3px;
482
+ border: 1px solid var(--input-border-color, #596c7a);
483
+ border-radius: 4px;
484
+ background: var(--input-background-color, #1d2228);
485
+ cursor: pointer;
486
+ outline: none;
487
+ }
488
+
489
+ button:focus {
490
+ border-color: #79b8ff;
491
+ box-shadow: 0 0 0 1px rgba(121, 184, 255, .28);
492
+ }
493
+
494
+ #swatch {
495
+ display: block;
496
+ width: 100%;
497
+ height: 100%;
498
+ border-radius: 2px;
499
+ background:
500
+ linear-gradient(var(--color, #000), var(--color, #000)),
501
+ linear-gradient(45deg, rgba(255, 255, 255, .25) 25%, transparent 25% 75%, rgba(255, 255, 255, .25) 75%),
502
+ linear-gradient(45deg, rgba(255, 255, 255, .25) 25%, transparent 25% 75%, rgba(255, 255, 255, .25) 75%);
503
+ background-position: 0 0, 0 0, 5px 5px;
504
+ background-size: auto, 10px 10px, 10px 10px;
505
+ box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .28);
506
+ }
507
+
508
+ :host([readonly]) button,
509
+ :host([disabled]) button {
510
+ cursor: default;
511
+ opacity: .65;
512
+ }
513
+ `;
514
+ static template = html `
515
+ <button id="button" type="button" aria-label="Edit color"><span id="swatch"></span></button>
516
+ `;
517
+ _value = '#000000';
518
+ _button;
519
+ _popup;
520
+ _editor;
521
+ _ignoreNextClick = false;
522
+ _outsidePointerHandler = (event) => this._handleOutsidePointer(event);
523
+ _windowKeyHandler = (event) => this._handleWindowKey(event);
524
+ get value() {
525
+ return this._value;
526
+ }
527
+ set value(value) {
528
+ this._setValue(value, false);
529
+ }
530
+ get readOnly() {
531
+ return this.hasAttribute('readonly');
532
+ }
533
+ set readOnly(value) {
534
+ this.toggleAttribute('readonly', value);
535
+ }
536
+ get disabled() {
537
+ return this.hasAttribute('disabled');
538
+ }
539
+ set disabled(value) {
540
+ this.toggleAttribute('disabled', value);
541
+ if (this._button)
542
+ this._button.disabled = value;
543
+ }
544
+ constructor() {
545
+ super();
546
+ this._button = this._getDomElement('button');
547
+ }
548
+ ready() {
549
+ const attributeValue = this.getAttribute('value');
550
+ if (attributeValue != null)
551
+ this._setValue(attributeValue, false);
552
+ this._button.disabled = this.disabled;
553
+ this._button.addEventListener('pointerdown', e => this._handleButtonPointerDown(e));
554
+ this._button.addEventListener('click', e => this._handleButtonClick(e));
555
+ this._button.addEventListener('keydown', e => this._handleButtonKeyDown(e));
556
+ this._renderSwatch();
557
+ }
558
+ disconnectedCallback() {
559
+ this._closePopup();
560
+ }
561
+ _togglePopup() {
562
+ if (this.readOnly || this.disabled)
563
+ return;
564
+ if (this._popup)
565
+ this._closePopup();
566
+ else
567
+ this._openPopup();
568
+ }
569
+ _handleButtonPointerDown(event) {
570
+ if (event.button !== 0)
571
+ return;
572
+ this._ignoreNextClick = true;
573
+ this._togglePopup();
574
+ event.preventDefault();
575
+ event.stopPropagation();
576
+ }
577
+ _handleButtonClick(event) {
578
+ if (this._ignoreNextClick) {
579
+ this._ignoreNextClick = false;
580
+ event.preventDefault();
581
+ event.stopPropagation();
582
+ return;
583
+ }
584
+ this._togglePopup();
585
+ }
586
+ _handleButtonKeyDown(event) {
587
+ if (event.key !== 'Enter' && event.key !== ' ')
588
+ return;
589
+ this._togglePopup();
590
+ event.preventDefault();
591
+ event.stopPropagation();
592
+ }
593
+ _openPopup() {
594
+ this._popup = document.createElement('div');
595
+ this._popup.style.position = 'fixed';
596
+ this._popup.style.zIndex = '100000';
597
+ this._popup.style.width = '280px';
598
+ this._editor = document.createElement('node-projects-color-editor');
599
+ this._editor.value = this._value;
600
+ this._editor.valuePreviewChanged.on(e => {
601
+ this._setValue(e.newValue, true);
602
+ this.dispatchEvent(new Event('input', { bubbles: true, composed: true }));
603
+ });
604
+ this._editor.valueChanged.on(e => {
605
+ this._setValue(e.newValue, true);
606
+ this.dispatchEvent(new Event('change', { bubbles: true, composed: true }));
607
+ });
608
+ this._popup.appendChild(this._editor);
609
+ document.body.appendChild(this._popup);
610
+ this._positionPopup();
611
+ window.addEventListener('resize', () => this._positionPopup(), { once: true });
612
+ window.addEventListener('scroll', () => this._positionPopup(), { once: true, capture: true });
613
+ window.addEventListener('keydown', this._windowKeyHandler);
614
+ requestAnimationFrame(() => window.addEventListener('pointerdown', this._outsidePointerHandler, true));
615
+ }
616
+ _positionPopup() {
617
+ if (!this._popup)
618
+ return;
619
+ const rect = this.getBoundingClientRect();
620
+ const width = this._popup.offsetWidth || 280;
621
+ const height = this._popup.offsetHeight || 360;
622
+ let left = rect.left;
623
+ let top = rect.bottom + 4;
624
+ if (left + width > window.innerWidth - 8)
625
+ left = window.innerWidth - width - 8;
626
+ if (top + height > window.innerHeight - 8)
627
+ top = rect.top - height - 4;
628
+ this._popup.style.left = `${Math.max(8, left)}px`;
629
+ this._popup.style.top = `${Math.max(8, top)}px`;
630
+ }
631
+ _handleOutsidePointer(event) {
632
+ const path = event.composedPath();
633
+ if (path.includes(this) || (this._popup && path.includes(this._popup)))
634
+ return;
635
+ this._closePopup();
636
+ }
637
+ _handleWindowKey(event) {
638
+ if (event.key === 'Escape')
639
+ this._closePopup();
640
+ }
641
+ _closePopup() {
642
+ window.removeEventListener('pointerdown', this._outsidePointerHandler, true);
643
+ window.removeEventListener('keydown', this._windowKeyHandler);
644
+ this._popup?.remove();
645
+ this._popup = null;
646
+ this._editor = null;
647
+ }
648
+ _setValue(value, updateAttribute) {
649
+ this._value = value ?? '';
650
+ if (updateAttribute)
651
+ this.setAttribute('value', this._value);
652
+ this._renderSwatch();
653
+ }
654
+ _renderSwatch() {
655
+ const parsed = parseColor(this._value) ?? { r: 0, g: 0, b: 0, a: 1 };
656
+ this.style.setProperty('--color', toCssRgb(parsed));
657
+ }
658
+ }
659
+ function parseColor(value) {
660
+ if (!value)
661
+ return null;
662
+ const text = value.trim();
663
+ if (text.toLowerCase() === 'transparent')
664
+ return { r: 0, g: 0, b: 0, a: 0 };
665
+ const hex = parseHexColor(text);
666
+ if (hex)
667
+ return hex;
668
+ const oklab = parseOklabColor(text);
669
+ if (oklab)
670
+ return oklab;
671
+ const normalized = normalizeModernColorSyntax(text);
672
+ const color = w3color.toColorObject(normalized);
673
+ if (color?.valid)
674
+ return normalizeColor({ r: color.red, g: color.green, b: color.blue, a: color.opacity });
675
+ return null;
676
+ }
677
+ function inferColorMode(value) {
678
+ const match = /^\s*(rgba?|hsla?|cmyk|oklab|oklch)\s*\(/i.exec(value ?? '');
679
+ const colorFunction = match?.[1]?.toLowerCase();
680
+ if (colorFunction === 'rgb' || colorFunction === 'rgba')
681
+ return 'rgb';
682
+ if (colorFunction === 'hsl' || colorFunction === 'hsla')
683
+ return 'hsl';
684
+ if (colorFunction === 'cmyk')
685
+ return 'cmyk';
686
+ if (colorFunction === 'oklab')
687
+ return 'oklab';
688
+ if (colorFunction === 'oklch')
689
+ return 'oklch';
690
+ return null;
691
+ }
692
+ function normalizeModernColorSyntax(value) {
693
+ return value
694
+ .replace(/,\s*/g, ',')
695
+ .replace(/rgba?\(([^)]*)\)/i, (_, body) => normalizeFunctionBody('rgb', body))
696
+ .replace(/hsla?\(([^)]*)\)/i, (_, body) => normalizeFunctionBody('hsl', body));
697
+ }
698
+ function normalizeFunctionBody(name, body) {
699
+ if (body.includes(',')) {
700
+ const parts = body.split(',').map(x => x.trim());
701
+ if (parts.length === 4 && parts[3].endsWith('%'))
702
+ parts[3] = String(Number(parts[3].slice(0, -1)) / 100);
703
+ return `${name}${parts.length === 4 ? 'a' : ''}(${parts.join(',')})`;
704
+ }
705
+ const [channels, alpha] = body.split('/').map(x => x.trim());
706
+ const parts = channels.split(/\s+/).filter(Boolean);
707
+ if (alpha)
708
+ parts.push(alpha.endsWith('%') ? String(Number(alpha.slice(0, -1)) / 100) : alpha);
709
+ return `${name}${parts.length === 4 ? 'a' : ''}(${parts.join(',')})`;
710
+ }
711
+ function parseHexColor(value) {
712
+ const match = /^#([0-9a-f]{3,8})$/i.exec(value);
713
+ if (!match)
714
+ return null;
715
+ const hex = match[1];
716
+ const read = (part) => parseInt(part.length === 1 ? part + part : part, 16);
717
+ if (hex.length === 3 || hex.length === 4)
718
+ return normalizeColor({ r: read(hex[0]), g: read(hex[1]), b: read(hex[2]), a: hex.length === 4 ? read(hex[3]) / 255 : 1 });
719
+ if (hex.length === 6 || hex.length === 8)
720
+ return normalizeColor({ r: read(hex.slice(0, 2)), g: read(hex.slice(2, 4)), b: read(hex.slice(4, 6)), a: hex.length === 8 ? read(hex.slice(6, 8)) / 255 : 1 });
721
+ return null;
722
+ }
723
+ function parseOklabColor(value) {
724
+ const match = /^(oklab|oklch)\((.*)\)$/i.exec(value);
725
+ if (!match)
726
+ return null;
727
+ const mode = match[1].toLowerCase();
728
+ const [channels, alphaText] = match[2].split('/').map(x => x.trim());
729
+ const parts = channels.replace(/,/g, ' ').split(/\s+/).filter(Boolean);
730
+ if (parts.length !== 3)
731
+ return null;
732
+ const alpha = alphaText ? parseNumberOrPercent(alphaText, 1) : 1;
733
+ if (mode === 'oklab')
734
+ return normalizeColor({ ...oklabToRgb(parseNumberOrPercent(parts[0], 1), Number(parts[1]), Number(parts[2])), a: alpha });
735
+ return normalizeColor({ ...oklchToRgb(parseNumberOrPercent(parts[0], 1), Number(parts[1]), Number(parts[2])), a: alpha });
736
+ }
737
+ function formatColor(color, mode) {
738
+ const alpha = round(color.a, 3);
739
+ if (mode === 'rgb')
740
+ return color.a >= 1 ? `rgb(${color.r}, ${color.g}, ${color.b})` : `rgba(${color.r}, ${color.g}, ${color.b}, ${alpha})`;
741
+ if (mode === 'hsl') {
742
+ const hsl = rgbToHsl(color);
743
+ return color.a >= 1
744
+ ? `hsl(${Math.round(hsl.h)}, ${Math.round(hsl.s * 100)}%, ${Math.round(hsl.l * 100)}%)`
745
+ : `hsla(${Math.round(hsl.h)}, ${Math.round(hsl.s * 100)}%, ${Math.round(hsl.l * 100)}%, ${alpha})`;
746
+ }
747
+ if (mode === 'cmyk') {
748
+ const cmyk = rgbToCmyk(color);
749
+ const body = `${Math.round(cmyk.c * 100)}%, ${Math.round(cmyk.m * 100)}%, ${Math.round(cmyk.y * 100)}%, ${Math.round(cmyk.k * 100)}%`;
750
+ return color.a >= 1 ? `cmyk(${body})` : `cmyk(${body}, ${alpha})`;
751
+ }
752
+ if (mode === 'oklab') {
753
+ const lab = rgbToOklab(color);
754
+ return `oklab(${round(lab.l * 100, 2)}% ${round(lab.a, 4)} ${round(lab.b, 4)}${color.a >= 1 ? '' : ` / ${alpha}`})`;
755
+ }
756
+ const lch = rgbToOklch(color);
757
+ return `oklch(${round(lch.l * 100, 2)}% ${round(lch.c, 4)} ${round(lch.h, 2)}${color.a >= 1 ? '' : ` / ${alpha}`})`;
758
+ }
759
+ function getChannelValues(color, mode) {
760
+ if (mode === 'rgb')
761
+ return [
762
+ { label: 'R', name: 'r', value: color.r, min: 0, max: 255, step: 1 },
763
+ { label: 'G', name: 'g', value: color.g, min: 0, max: 255, step: 1 },
764
+ { label: 'B', name: 'b', value: color.b, min: 0, max: 255, step: 1 },
765
+ { label: 'A', name: 'a', value: Math.round(color.a * 100), min: 0, max: 100, step: 1 }
766
+ ];
767
+ if (mode === 'hsl') {
768
+ const hsl = rgbToHsl(color);
769
+ return [
770
+ { label: 'H', name: 'h', value: Math.round(hsl.h), min: 0, max: 360, step: 1 },
771
+ { label: 'S', name: 's', value: Math.round(hsl.s * 100), min: 0, max: 100, step: 1 },
772
+ { label: 'L', name: 'l', value: Math.round(hsl.l * 100), min: 0, max: 100, step: 1 },
773
+ { label: 'A', name: 'a', value: Math.round(color.a * 100), min: 0, max: 100, step: 1 }
774
+ ];
775
+ }
776
+ if (mode === 'cmyk') {
777
+ const cmyk = rgbToCmyk(color);
778
+ return [
779
+ { label: 'C', name: 'c', value: Math.round(cmyk.c * 100), min: 0, max: 100, step: 1 },
780
+ { label: 'M', name: 'm', value: Math.round(cmyk.m * 100), min: 0, max: 100, step: 1 },
781
+ { label: 'Y', name: 'y', value: Math.round(cmyk.y * 100), min: 0, max: 100, step: 1 },
782
+ { label: 'K', name: 'k', value: Math.round(cmyk.k * 100), min: 0, max: 100, step: 1 },
783
+ { label: 'A', name: 'a', value: Math.round(color.a * 100), min: 0, max: 100, step: 1 }
784
+ ];
785
+ }
786
+ if (mode === 'oklab') {
787
+ const lab = rgbToOklab(color);
788
+ return [
789
+ { label: 'L', name: 'l', value: round(lab.l * 100, 2), min: 0, max: 100, step: .1 },
790
+ { label: 'A', name: 'a1', value: round(lab.a, 4), min: -1, max: 1, step: .001 },
791
+ { label: 'B', name: 'b1', value: round(lab.b, 4), min: -1, max: 1, step: .001 },
792
+ { label: 'Alpha', name: 'alpha', value: Math.round(color.a * 100), min: 0, max: 100, step: 1 }
793
+ ];
794
+ }
795
+ const lch = rgbToOklch(color);
796
+ return [
797
+ { label: 'L', name: 'l', value: round(lch.l * 100, 2), min: 0, max: 100, step: .1 },
798
+ { label: 'C', name: 'c', value: round(lch.c, 4), min: 0, max: 1, step: .001 },
799
+ { label: 'H', name: 'h', value: round(lch.h, 2), min: 0, max: 360, step: .1 },
800
+ { label: 'A', name: 'a', value: Math.round(color.a * 100), min: 0, max: 100, step: 1 }
801
+ ];
802
+ }
803
+ function normalizeColor(color) {
804
+ return {
805
+ r: Math.round(clamp(color.r, 0, 255)),
806
+ g: Math.round(clamp(color.g, 0, 255)),
807
+ b: Math.round(clamp(color.b, 0, 255)),
808
+ a: clamp(Number.isFinite(color.a) ? color.a : 1, 0, 1)
809
+ };
810
+ }
811
+ function toCssRgb(color) {
812
+ return `rgba(${color.r}, ${color.g}, ${color.b}, ${round(color.a, 3)})`;
813
+ }
814
+ function rgbToHsv(color) {
815
+ const r = color.r / 255;
816
+ const g = color.g / 255;
817
+ const b = color.b / 255;
818
+ const max = Math.max(r, g, b);
819
+ const min = Math.min(r, g, b);
820
+ const d = max - min;
821
+ let h = 0;
822
+ if (d !== 0) {
823
+ if (max === r)
824
+ h = ((g - b) / d) % 6;
825
+ else if (max === g)
826
+ h = (b - r) / d + 2;
827
+ else
828
+ h = (r - g) / d + 4;
829
+ h *= 60;
830
+ }
831
+ return { h: (h + 360) % 360, s: max === 0 ? 0 : d / max, v: max };
832
+ }
833
+ function hsvToRgb(h, s, v) {
834
+ const c = v * s;
835
+ const x = c * (1 - Math.abs((h / 60) % 2 - 1));
836
+ const m = v - c;
837
+ let r = 0;
838
+ let g = 0;
839
+ let b = 0;
840
+ if (h < 60)
841
+ [r, g, b] = [c, x, 0];
842
+ else if (h < 120)
843
+ [r, g, b] = [x, c, 0];
844
+ else if (h < 180)
845
+ [r, g, b] = [0, c, x];
846
+ else if (h < 240)
847
+ [r, g, b] = [0, x, c];
848
+ else if (h < 300)
849
+ [r, g, b] = [x, 0, c];
850
+ else
851
+ [r, g, b] = [c, 0, x];
852
+ return { r: (r + m) * 255, g: (g + m) * 255, b: (b + m) * 255 };
853
+ }
854
+ function rgbToHsl(color) {
855
+ const r = color.r / 255;
856
+ const g = color.g / 255;
857
+ const b = color.b / 255;
858
+ const max = Math.max(r, g, b);
859
+ const min = Math.min(r, g, b);
860
+ const l = (max + min) / 2;
861
+ const d = max - min;
862
+ let h = 0;
863
+ let s = 0;
864
+ if (d !== 0) {
865
+ s = d / (1 - Math.abs(2 * l - 1));
866
+ if (max === r)
867
+ h = ((g - b) / d) % 6;
868
+ else if (max === g)
869
+ h = (b - r) / d + 2;
870
+ else
871
+ h = (r - g) / d + 4;
872
+ h *= 60;
873
+ }
874
+ return { h: (h + 360) % 360, s, l };
875
+ }
876
+ function hslToRgb(h, s, l) {
877
+ const c = (1 - Math.abs(2 * l - 1)) * s;
878
+ const x = c * (1 - Math.abs((h / 60) % 2 - 1));
879
+ const m = l - c / 2;
880
+ let r = 0;
881
+ let g = 0;
882
+ let b = 0;
883
+ if (h < 60)
884
+ [r, g, b] = [c, x, 0];
885
+ else if (h < 120)
886
+ [r, g, b] = [x, c, 0];
887
+ else if (h < 180)
888
+ [r, g, b] = [0, c, x];
889
+ else if (h < 240)
890
+ [r, g, b] = [0, x, c];
891
+ else if (h < 300)
892
+ [r, g, b] = [x, 0, c];
893
+ else
894
+ [r, g, b] = [c, 0, x];
895
+ return { r: (r + m) * 255, g: (g + m) * 255, b: (b + m) * 255 };
896
+ }
897
+ function rgbToCmyk(color) {
898
+ const r = color.r / 255;
899
+ const g = color.g / 255;
900
+ const b = color.b / 255;
901
+ const k = 1 - Math.max(r, g, b);
902
+ if (k >= 1 - epsilon)
903
+ return { c: 0, m: 0, y: 0, k: 1 };
904
+ return {
905
+ c: (1 - r - k) / (1 - k),
906
+ m: (1 - g - k) / (1 - k),
907
+ y: (1 - b - k) / (1 - k),
908
+ k
909
+ };
910
+ }
911
+ function cmykToRgb(c, m, y, k) {
912
+ return {
913
+ r: 255 * (1 - c) * (1 - k),
914
+ g: 255 * (1 - m) * (1 - k),
915
+ b: 255 * (1 - y) * (1 - k)
916
+ };
917
+ }
918
+ function rgbToOklab(color) {
919
+ const r = srgbToLinear(color.r / 255);
920
+ const g = srgbToLinear(color.g / 255);
921
+ const b = srgbToLinear(color.b / 255);
922
+ const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);
923
+ const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);
924
+ const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);
925
+ return {
926
+ l: 0.2104542553 * l + 0.7936177850 * m - 0.0040720468 * s,
927
+ a: 1.9779984951 * l - 2.4285922050 * m + 0.4505937099 * s,
928
+ b: 0.0259040371 * l + 0.7827717662 * m - 0.8086757660 * s
929
+ };
930
+ }
931
+ function oklabToRgb(lValue, aValue, bValue) {
932
+ const l = Math.pow(lValue + 0.3963377774 * aValue + 0.2158037573 * bValue, 3);
933
+ const m = Math.pow(lValue - 0.1055613458 * aValue - 0.0638541728 * bValue, 3);
934
+ const s = Math.pow(lValue - 0.0894841775 * aValue - 1.2914855480 * bValue, 3);
935
+ return {
936
+ r: 255 * linearToSrgb(4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s),
937
+ g: 255 * linearToSrgb(-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s),
938
+ b: 255 * linearToSrgb(-0.0041960863 * l - 0.7034186147 * m + 1.7076147010 * s)
939
+ };
940
+ }
941
+ function rgbToOklch(color) {
942
+ const lab = rgbToOklab(color);
943
+ const c = Math.sqrt(lab.a * lab.a + lab.b * lab.b);
944
+ const h = c < epsilon ? 0 : (Math.atan2(lab.b, lab.a) * 180 / Math.PI + 360) % 360;
945
+ return { l: lab.l, c, h };
946
+ }
947
+ function oklchToRgb(l, c, h) {
948
+ const radians = h * Math.PI / 180;
949
+ return oklabToRgb(l, c * Math.cos(radians), c * Math.sin(radians));
950
+ }
951
+ function srgbToLinear(value) {
952
+ return value <= 0.04045 ? value / 12.92 : Math.pow((value + 0.055) / 1.055, 2.4);
953
+ }
954
+ function linearToSrgb(value) {
955
+ return value <= 0.0031308 ? 12.92 * value : 1.055 * Math.pow(value, 1 / 2.4) - 0.055;
956
+ }
957
+ function parseNumberOrPercent(value, percentBase) {
958
+ return value.endsWith('%') ? Number(value.slice(0, -1)) / 100 * percentBase : Number(value);
959
+ }
960
+ function clamp(value, min, max) {
961
+ return Math.min(max, Math.max(min, Number.isFinite(value) ? value : min));
962
+ }
963
+ function normalizeHue(value) {
964
+ return clamp(value, 0, 360);
965
+ }
966
+ function round(value, decimals) {
967
+ const factor = Math.pow(10, decimals);
968
+ return Math.round(value * factor) / factor;
969
+ }
970
+ customElements.define('node-projects-color-editor', ColorEditor);
971
+ customElements.define('node-projects-color-input', ColorInput);
972
+ //# sourceMappingURL=ColorEditor.js.map