pickit-color 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.
@@ -0,0 +1,929 @@
1
+ /* Pickit Color v1.0.0, @license Donationware */
2
+ (function (global, factory) {
3
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
4
+ typeof define === 'function' && define.amd ? define(['exports'], factory) :
5
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.colorpicker = {}));
6
+ }(this, (function (exports) { 'use strict';
7
+
8
+ /******************************************************************************
9
+ Copyright (c) Microsoft Corporation.
10
+
11
+ Permission to use, copy, modify, and/or distribute this software for any
12
+ purpose with or without fee is hereby granted.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
15
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
16
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
17
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
18
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
19
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20
+ PERFORMANCE OF THIS SOFTWARE.
21
+ ***************************************************************************** */
22
+
23
+ function __awaiter(thisArg, _arguments, P, generator) {
24
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
25
+ return new (P || (P = Promise))(function (resolve, reject) {
26
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
27
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
28
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
29
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
30
+ });
31
+ }
32
+
33
+ function __generator(thisArg, body) {
34
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
35
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
36
+ function verb(n) { return function (v) { return step([n, v]); }; }
37
+ function step(op) {
38
+ if (f) throw new TypeError("Generator is already executing.");
39
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
40
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
41
+ if (y = 0, t) op = [op[0] & 2, t.value];
42
+ switch (op[0]) {
43
+ case 0: case 1: t = op; break;
44
+ case 4: _.label++; return { value: op[1], done: false };
45
+ case 5: _.label++; y = op[1]; op = [0]; continue;
46
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
47
+ default:
48
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
49
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
50
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
51
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
52
+ if (t[2]) _.ops.pop();
53
+ _.trys.pop(); continue;
54
+ }
55
+ op = body.call(thisArg, _);
56
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
57
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
58
+ }
59
+ }
60
+
61
+ var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
62
+ var e = new Error(message);
63
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
64
+ };
65
+
66
+ /**
67
+ * Pickit Color Picker
68
+ * An accessible, lightweight color picker inspired by flatpickr
69
+ * Supports HSL, RGB, HEX formats with keyboard navigation
70
+ */
71
+ var ColorPicker = /** @class */ (function () {
72
+ function ColorPicker(element, options) {
73
+ if (options === void 0) { options = {}; }
74
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
75
+ this.container = null;
76
+ this.colorBox = null;
77
+ this.hueSlider = null;
78
+ this.saturationSlider = null;
79
+ this.lightnessSlider = null;
80
+ this.alphaSlider = null;
81
+ this.hexInput = null;
82
+ this.currentColor = { h: 0, s: 100, l: 50, a: 1 };
83
+ this.isOpen = false;
84
+ this.saturationPointer = null;
85
+ this.compactButton = null;
86
+ this.inputPreview = null;
87
+ this.announceTimeout = null;
88
+ this.input =
89
+ typeof element === "string"
90
+ ? document.querySelector(element)
91
+ : element;
92
+ if (!this.input) {
93
+ throw new Error("ColorPicker: Invalid element selector");
94
+ }
95
+ // Read preset colors from data attribute if available
96
+ var dataPresets = this.input.getAttribute("data-preset-colors");
97
+ var presetsFromAttr = dataPresets ? dataPresets.split(",").map(function (c) { return c.trim(); }) : null;
98
+ this.options = {
99
+ defaultColor: options.defaultColor || "#3b82f6",
100
+ format: options.format || "hex",
101
+ showAlpha: (_a = options.showAlpha) !== null && _a !== void 0 ? _a : false,
102
+ sliderMode: (_b = options.sliderMode) !== null && _b !== void 0 ? _b : false,
103
+ eyeDropper: (_c = options.eyeDropper) !== null && _c !== void 0 ? _c : false,
104
+ presetColors: options.presetColors || presetsFromAttr || [
105
+ "#ef4444",
106
+ "#f59e0b",
107
+ "#10b981",
108
+ "#3b82f6",
109
+ "#8b5cf6",
110
+ "#ec4899",
111
+ "#000000",
112
+ "#ffffff",
113
+ ],
114
+ presetLabels: options.presetLabels || [],
115
+ presetsOnly: (_d = options.presetsOnly) !== null && _d !== void 0 ? _d : false,
116
+ listView: (_e = options.listView) !== null && _e !== void 0 ? _e : false,
117
+ inline: (_f = options.inline) !== null && _f !== void 0 ? _f : false,
118
+ compact: (_g = options.compact) !== null && _g !== void 0 ? _g : false,
119
+ inputPreview: (_h = options.inputPreview) !== null && _h !== void 0 ? _h : false,
120
+ onChange: options.onChange || (function () { }),
121
+ onOpen: options.onOpen || (function () { }),
122
+ onClose: options.onClose || (function () { }),
123
+ appendTo: options.appendTo || document.body,
124
+ position: options.position || "auto",
125
+ closeOnSelect: (_j = options.closeOnSelect) !== null && _j !== void 0 ? _j : true,
126
+ ariaLabels: {
127
+ hue: ((_k = options.ariaLabels) === null || _k === void 0 ? void 0 : _k.hue) || "Hue",
128
+ saturation: ((_l = options.ariaLabels) === null || _l === void 0 ? void 0 : _l.saturation) || "Saturation and Lightness",
129
+ lightness: ((_m = options.ariaLabels) === null || _m === void 0 ? void 0 : _m.lightness) || "Lightness",
130
+ alpha: ((_o = options.ariaLabels) === null || _o === void 0 ? void 0 : _o.alpha) || "Alpha",
131
+ presets: ((_p = options.ariaLabels) === null || _p === void 0 ? void 0 : _p.presets) || "Preset colors",
132
+ },
133
+ };
134
+ this.init();
135
+ ColorPicker.instances.set(this.input, this);
136
+ }
137
+ ColorPicker.prototype.init = function () {
138
+ // Parse initial color
139
+ var initialColor = this.input.value || this.options.defaultColor;
140
+ this.currentColor = this.parseColor(initialColor);
141
+ // Create compact button if needed
142
+ if (this.options.compact) {
143
+ this.createCompactButton();
144
+ }
145
+ // Create input preview if needed
146
+ if (this.options.inputPreview && !this.options.compact) {
147
+ this.createInputPreview();
148
+ }
149
+ // Build UI
150
+ this.buildColorPicker();
151
+ // Setup event listeners
152
+ this.setupEventListeners();
153
+ // Update display
154
+ this.updateColorDisplay();
155
+ // Open if inline
156
+ if (this.options.inline) {
157
+ this.open();
158
+ }
159
+ };
160
+ ColorPicker.prototype.buildColorPicker = function () {
161
+ var _this = this;
162
+ var _a;
163
+ this.container = document.createElement("div");
164
+ this.container.className = "colorpicker-container";
165
+ if (this.options.presetsOnly) {
166
+ this.container.classList.add("colorpicker-presets-only");
167
+ }
168
+ if (this.options.inline) {
169
+ this.container.classList.add("colorpicker-inline");
170
+ }
171
+ this.container.setAttribute("role", "dialog");
172
+ this.container.setAttribute("aria-label", "Color picker");
173
+ this.container.style.display = "none";
174
+ var content = "\n <div class=\"colorpicker-content\">\n ".concat(!this.options.presetsOnly ? "\n ".concat(!this.options.sliderMode ? "\n <div class=\"colorpicker-saturation\" \n role=\"slider\" \n aria-label=\"".concat(this.options.ariaLabels.saturation, "\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n aria-valuenow=\"").concat(this.currentColor.s, "\"\n tabindex=\"0\">\n <div class=\"colorpicker-saturation-overlay\"></div>\n <div class=\"colorpicker-saturation-pointer\" role=\"presentation\"></div>\n </div>\n ") : '', "\n \n <div class=\"colorpicker-controls\">\n <div class=\"colorpicker-sliders").concat(this.options.sliderMode ? ' colorpicker-sliders-only' : '', "\">\n <div class=\"colorpicker-slider-group\">\n <label for=\"colorpicker-hue\">\n <span class=\"colorpicker-label\">").concat(this.options.ariaLabels.hue, "</span>\n </label>\n <input \n type=\"range\" \n id=\"colorpicker-hue\"\n class=\"colorpicker-slider colorpicker-hue-slider\"\n min=\"0\" \n max=\"360\" \n value=\"").concat(this.currentColor.h, "\"\n aria-label=\"").concat(this.options.ariaLabels.hue, "\"\n />\n </div>\n ").concat(this.options.sliderMode
175
+ ? "\n <div class=\"colorpicker-slider-group\">\n <label for=\"colorpicker-saturation\">\n <span class=\"colorpicker-label\">".concat(this.options.ariaLabels.saturation, "</span>\n </label>\n <input \n type=\"range\" \n id=\"colorpicker-saturation\"\n class=\"colorpicker-slider colorpicker-saturation-slider\"\n min=\"0\" \n max=\"100\" \n value=\"").concat(this.currentColor.s, "\"\n aria-label=\"").concat(this.options.ariaLabels.saturation, "\"\n />\n </div>\n <div class=\"colorpicker-slider-group\">\n <label for=\"colorpicker-lightness\">\n <span class=\"colorpicker-label\">").concat(this.options.ariaLabels.lightness, "</span>\n </label>\n <input \n type=\"range\" \n id=\"colorpicker-lightness\"\n class=\"colorpicker-slider colorpicker-lightness-slider\"\n min=\"0\" \n max=\"100\" \n value=\"").concat(this.currentColor.l, "\"\n aria-label=\"").concat(this.options.ariaLabels.lightness, "\"\n />\n </div>\n ")
176
+ : "", "\n ").concat(this.options.showAlpha
177
+ ? "\n <div class=\"colorpicker-slider-group\">\n <label for=\"colorpicker-alpha\">\n <span class=\"colorpicker-label\">".concat(this.options.ariaLabels.alpha, "</span>\n </label>\n <input \n type=\"range\" \n id=\"colorpicker-alpha\"\n class=\"colorpicker-slider colorpicker-alpha-slider\"\n min=\"0\" \n max=\"100\" \n value=\"").concat(this.currentColor.a * 100, "\"\n aria-label=\"").concat(this.options.ariaLabels.alpha, "\"\n />\n </div>\n ")
178
+ : "", "\n </div>\n \n <div class=\"colorpicker-preview\">\n <div class=\"colorpicker-preview-color\" role=\"presentation\"></div>\n </div>\n </div>\n \n <div class=\"colorpicker-input-wrapper\">\n <label for=\"colorpicker-hex\">\n <span class=\"colorpicker-sr-only\">Color value</span>\n </label>\n <div class=\"colorpicker-input-row\">\n <input \n type=\"text\" \n id=\"colorpicker-hex\"\n class=\"colorpicker-input\"\n placeholder=\"").concat(this.getPlaceholder(), "\"\n aria-label=\"Color value in ").concat(this.options.format, " format\"\n />\n ").concat(this.options.eyeDropper
179
+ ? "\n ".concat(this.supportsEyeDropper() ? "\n <button \n type=\"button\"\n class=\"colorpicker-eyedropper-btn\"\n aria-label=\"Pick color from screen\"\n title=\"Pick color from screen\"\n >\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M2 22l1-1\"/>\n <path d=\"M8.5 16.5l-1-1\"/>\n <path d=\"M17 3l4 4\"/>\n <path d=\"M12 8l4 4\"/>\n <path d=\"M3 21l9-9\"/>\n <path d=\"M14.5 9.5l-1 1\"/>\n <path d=\"M20 14l-8 8\"/>\n </svg>\n </button>\n " : '', "\n <button \n type=\"button\"\n class=\"colorpicker-system-picker-btn\"\n aria-label=\"Open system color picker\"\n title=\"Open system color picker\"\n >\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <circle cx=\"12\" cy=\"12\" r=\"10\"/>\n <path d=\"M12 2v20\"/>\n <path d=\"M2 12h20\"/>\n <circle cx=\"12\" cy=\"12\" r=\"3\"/>\n </svg>\n </button>\n <input \n type=\"color\"\n class=\"colorpicker-system-picker-input\"\n style=\"position: absolute; opacity: 0; pointer-events: none; width: 0; height: 0;\"\n />\n ")
180
+ : "", "\n </div>\n </div>\n ") : '', "\n \n ").concat(this.options.presetColors.length > 0
181
+ ? "\n <div class=\"colorpicker-presets".concat(this.options.listView ? ' colorpicker-presets-list' : '', "\" role=\"group\" aria-label=\"").concat(this.options.ariaLabels.presets, "\">\n ").concat(this.options.presetColors
182
+ .map(function (color, index) {
183
+ var label = _this.options.presetLabels[index] || '';
184
+ return _this.options.listView && label
185
+ ? "\n <button \n type=\"button\"\n class=\"colorpicker-preset colorpicker-preset-list-item\" \n data-color=\"".concat(color, "\"\n aria-label=\"Select color ").concat(label, "\"\n >\n <span class=\"colorpicker-preset-color\" style=\"background-color: ").concat(color, "\"></span>\n <span class=\"colorpicker-preset-label\">").concat(label, "</span>\n </button>\n ")
186
+ : "\n <button \n type=\"button\"\n class=\"colorpicker-preset\" \n style=\"background-color: ".concat(color, "\"\n data-color=\"").concat(color, "\"\n aria-label=\"Select color ").concat(label || color, "\"\n ></button>\n ");
187
+ })
188
+ .join(""), "\n </div>\n ")
189
+ : "", "\n </div>\n ");
190
+ this.container.innerHTML = content;
191
+ // Cache element references
192
+ this.colorBox = this.container.querySelector(".colorpicker-saturation");
193
+ this.saturationPointer = this.container.querySelector(".colorpicker-saturation-pointer");
194
+ this.hueSlider = this.container.querySelector(".colorpicker-hue-slider");
195
+ this.saturationSlider = this.container.querySelector(".colorpicker-saturation-slider");
196
+ this.lightnessSlider = this.container.querySelector(".colorpicker-lightness-slider");
197
+ this.alphaSlider = this.container.querySelector(".colorpicker-alpha-slider");
198
+ this.hexInput = this.container.querySelector(".colorpicker-input");
199
+ // Append to DOM
200
+ if (this.options.inline) {
201
+ // For inline mode, insert after the input
202
+ (_a = this.input.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(this.container, this.input.nextSibling);
203
+ // Hide the original input
204
+ this.input.style.display = "none";
205
+ }
206
+ else {
207
+ // For popup mode, append to specified container
208
+ this.options.appendTo.appendChild(this.container);
209
+ }
210
+ };
211
+ ColorPicker.prototype.createCompactButton = function () {
212
+ var _this = this;
213
+ var _a;
214
+ // Hide the original input
215
+ this.input.style.position = "absolute";
216
+ this.input.style.opacity = "0";
217
+ this.input.style.pointerEvents = "none";
218
+ this.input.style.width = "0";
219
+ this.input.style.height = "0";
220
+ // Create compact button
221
+ this.compactButton = document.createElement("button");
222
+ this.compactButton.type = "button";
223
+ this.compactButton.className = "colorpicker-compact-button";
224
+ this.compactButton.setAttribute("aria-label", "Select color");
225
+ this.compactButton.tabIndex = 0;
226
+ // Compact Mode: Immer Farbvorschau
227
+ var preview = document.createElement("span");
228
+ preview.className = "colorpicker-compact-preview";
229
+ preview.style.backgroundColor = this.input.value || this.options.defaultColor;
230
+ this.compactButton.appendChild(preview);
231
+ // Insert after input
232
+ (_a = this.input.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(this.compactButton, this.input.nextSibling);
233
+ // Click handler
234
+ this.compactButton.addEventListener("click", function (e) {
235
+ e.preventDefault();
236
+ e.stopPropagation();
237
+ _this.toggle();
238
+ });
239
+ // Keyboard handler
240
+ this.compactButton.addEventListener("keydown", function (e) {
241
+ if (e.key === "Enter" || e.key === " ") {
242
+ e.preventDefault();
243
+ e.stopPropagation();
244
+ _this.toggle();
245
+ }
246
+ });
247
+ };
248
+ ColorPicker.prototype.createInputPreview = function () {
249
+ var _a;
250
+ // Create wrapper
251
+ var wrapper = document.createElement("div");
252
+ wrapper.className = "colorpicker-input-group";
253
+ // Create preview element
254
+ this.inputPreview = document.createElement("span");
255
+ this.inputPreview.className = "colorpicker-input-preview";
256
+ this.inputPreview.style.backgroundColor = this.input.value || this.options.defaultColor;
257
+ // Wrap input
258
+ (_a = this.input.parentNode) === null || _a === void 0 ? void 0 : _a.insertBefore(wrapper, this.input);
259
+ wrapper.appendChild(this.inputPreview);
260
+ wrapper.appendChild(this.input);
261
+ // Add class to input for styling
262
+ this.input.classList.add("colorpicker-has-preview");
263
+ };
264
+ ColorPicker.prototype.supportsEyeDropper = function () {
265
+ return typeof window !== 'undefined' && 'EyeDropper' in window;
266
+ };
267
+ ColorPicker.prototype.openEyeDropper = function () {
268
+ return __awaiter(this, void 0, Promise, function () {
269
+ var eyeDropper, result, error_1;
270
+ return __generator(this, function (_a) {
271
+ switch (_a.label) {
272
+ case 0:
273
+ if (!this.supportsEyeDropper()) {
274
+ return [2 /*return*/]; // Silently fail if not supported
275
+ }
276
+ _a.label = 1;
277
+ case 1:
278
+ _a.trys.push([1, 3, , 4]);
279
+ eyeDropper = new EyeDropper();
280
+ return [4 /*yield*/, eyeDropper.open()];
281
+ case 2:
282
+ result = _a.sent();
283
+ if (result.sRGBHex) {
284
+ this.currentColor = this.parseColor(result.sRGBHex);
285
+ this.input.value = result.sRGBHex;
286
+ this.updateColorDisplay();
287
+ this.options.onChange(result.sRGBHex);
288
+ }
289
+ return [3 /*break*/, 4];
290
+ case 3:
291
+ error_1 = _a.sent();
292
+ // User cancelled - do nothing
293
+ if (error_1.name !== 'AbortError') {
294
+ console.error('EyeDropper error:', error_1);
295
+ }
296
+ return [3 /*break*/, 4];
297
+ case 4: return [2 /*return*/];
298
+ }
299
+ });
300
+ });
301
+ };
302
+ ColorPicker.prototype.setupEventListeners = function () {
303
+ var _this = this;
304
+ var _a, _b, _c, _d;
305
+ // Input click/keyboard to open (not in compact mode)
306
+ if (!this.options.compact) {
307
+ this.input.addEventListener("click", function () {
308
+ if (!_this.options.inline) {
309
+ _this.toggle();
310
+ }
311
+ });
312
+ this.input.addEventListener("keydown", function (e) {
313
+ if ((e.key === "Enter" || e.key === " ") && !_this.options.inline) {
314
+ e.preventDefault();
315
+ _this.toggle();
316
+ }
317
+ });
318
+ }
319
+ // Input change
320
+ this.input.addEventListener("change", function () {
321
+ _this.currentColor = _this.parseColor(_this.input.value);
322
+ _this.updateColorDisplay();
323
+ });
324
+ // Hue slider
325
+ if (this.hueSlider) {
326
+ this.hueSlider.addEventListener("input", function (e) {
327
+ _this.currentColor.h = parseInt(e.target.value);
328
+ _this.updateColorDisplay();
329
+ _this.announceColorChange();
330
+ });
331
+ }
332
+ // Saturation slider (sliderMode only)
333
+ if (this.saturationSlider) {
334
+ this.saturationSlider.addEventListener("input", function (e) {
335
+ _this.currentColor.s = parseInt(e.target.value);
336
+ _this.updateColorDisplay();
337
+ _this.announceColorChange();
338
+ });
339
+ }
340
+ // Lightness slider (sliderMode only)
341
+ if (this.lightnessSlider) {
342
+ this.lightnessSlider.addEventListener("input", function (e) {
343
+ _this.currentColor.l = parseInt(e.target.value);
344
+ _this.updateColorDisplay();
345
+ _this.announceColorChange();
346
+ });
347
+ }
348
+ // Alpha slider
349
+ if (this.alphaSlider) {
350
+ this.alphaSlider.addEventListener("input", function (e) {
351
+ _this.currentColor.a =
352
+ parseInt(e.target.value) / 100;
353
+ _this.updateColorDisplay();
354
+ _this.announceColorChange();
355
+ });
356
+ }
357
+ // Saturation box
358
+ if (this.colorBox) {
359
+ this.colorBox.addEventListener("mousedown", function (e) {
360
+ return _this.onSaturationMouseDown(e);
361
+ });
362
+ this.colorBox.addEventListener("keydown", function (e) {
363
+ return _this.onSaturationKeyDown(e);
364
+ });
365
+ }
366
+ // Color value input (accepts all formats)
367
+ if (this.hexInput) {
368
+ this.hexInput.addEventListener("input", function (e) {
369
+ var value = e.target.value.trim();
370
+ if (_this.isValidColor(value)) {
371
+ _this.currentColor = _this.parseColor(value);
372
+ _this.updateColorDisplay(false);
373
+ }
374
+ });
375
+ }
376
+ // Preset colors
377
+ var presets = (_a = this.container) === null || _a === void 0 ? void 0 : _a.querySelectorAll(".colorpicker-preset");
378
+ presets === null || presets === void 0 ? void 0 : presets.forEach(function (preset) {
379
+ preset.addEventListener("click", function (e) {
380
+ var color = e.currentTarget.dataset.color;
381
+ _this.currentColor = _this.parseColor(color);
382
+ _this.updateColorDisplay();
383
+ if (_this.options.closeOnSelect) {
384
+ _this.close();
385
+ }
386
+ });
387
+ });
388
+ // EyeDropper button
389
+ var eyeDropperBtn = (_b = this.container) === null || _b === void 0 ? void 0 : _b.querySelector(".colorpicker-eyedropper-btn");
390
+ if (eyeDropperBtn) {
391
+ eyeDropperBtn.addEventListener("click", function (e) { return __awaiter(_this, void 0, void 0, function () {
392
+ return __generator(this, function (_a) {
393
+ switch (_a.label) {
394
+ case 0:
395
+ e.preventDefault();
396
+ e.stopPropagation();
397
+ return [4 /*yield*/, this.openEyeDropper()];
398
+ case 1:
399
+ _a.sent();
400
+ return [2 /*return*/];
401
+ }
402
+ });
403
+ }); });
404
+ }
405
+ // System Color Picker button (Safari fallback)
406
+ var systemPickerBtn = (_c = this.container) === null || _c === void 0 ? void 0 : _c.querySelector(".colorpicker-system-picker-btn");
407
+ var systemPickerInput = (_d = this.container) === null || _d === void 0 ? void 0 : _d.querySelector(".colorpicker-system-picker-input");
408
+ if (systemPickerBtn && systemPickerInput) {
409
+ // Set current color to system picker
410
+ systemPickerInput.value = this.formatColor(this.currentColor).substring(0, 7); // HEX only
411
+ systemPickerBtn.addEventListener("click", function (e) {
412
+ e.preventDefault();
413
+ e.stopPropagation();
414
+ systemPickerInput.click();
415
+ });
416
+ systemPickerInput.addEventListener("change", function () {
417
+ var color = systemPickerInput.value;
418
+ _this.currentColor = _this.parseColor(color);
419
+ _this.input.value = color;
420
+ _this.updateColorDisplay();
421
+ _this.options.onChange(color);
422
+ });
423
+ }
424
+ // Close on outside click
425
+ if (!this.options.inline) {
426
+ document.addEventListener("mousedown", function (e) {
427
+ var _a;
428
+ if (_this.isOpen &&
429
+ !((_a = _this.container) === null || _a === void 0 ? void 0 : _a.contains(e.target)) &&
430
+ e.target !== _this.input) {
431
+ _this.close();
432
+ }
433
+ });
434
+ }
435
+ // Escape key to close
436
+ document.addEventListener("keydown", function (e) {
437
+ if (e.key === "Escape" && _this.isOpen && !_this.options.inline) {
438
+ _this.close();
439
+ _this.input.focus();
440
+ }
441
+ });
442
+ };
443
+ ColorPicker.prototype.onSaturationMouseDown = function (e) {
444
+ var _this = this;
445
+ e.preventDefault();
446
+ this.updateSaturationFromMouse(e);
447
+ var onMouseMove = function (e) {
448
+ _this.updateSaturationFromMouse(e);
449
+ };
450
+ var onMouseUp = function () {
451
+ document.removeEventListener("mousemove", onMouseMove);
452
+ document.removeEventListener("mouseup", onMouseUp);
453
+ };
454
+ document.addEventListener("mousemove", onMouseMove);
455
+ document.addEventListener("mouseup", onMouseUp);
456
+ };
457
+ ColorPicker.prototype.updateSaturationFromMouse = function (e) {
458
+ if (!this.colorBox)
459
+ return;
460
+ var rect = this.colorBox.getBoundingClientRect();
461
+ var x = Math.max(0, Math.min(e.clientX - rect.left, rect.width));
462
+ var y = Math.max(0, Math.min(e.clientY - rect.top, rect.height));
463
+ this.currentColor.s = (x / rect.width) * 100;
464
+ this.currentColor.l = 100 - (y / rect.height) * 100;
465
+ this.updateColorDisplay();
466
+ this.announceColorChange();
467
+ };
468
+ ColorPicker.prototype.onSaturationKeyDown = function (e) {
469
+ var step = e.shiftKey ? 10 : 1;
470
+ var handled = false;
471
+ switch (e.key) {
472
+ case "ArrowRight":
473
+ this.currentColor.s = Math.min(100, this.currentColor.s + step);
474
+ handled = true;
475
+ break;
476
+ case "ArrowLeft":
477
+ this.currentColor.s = Math.max(0, this.currentColor.s - step);
478
+ handled = true;
479
+ break;
480
+ case "ArrowUp":
481
+ this.currentColor.l = Math.min(100, this.currentColor.l + step);
482
+ handled = true;
483
+ break;
484
+ case "ArrowDown":
485
+ this.currentColor.l = Math.max(0, this.currentColor.l - step);
486
+ handled = true;
487
+ break;
488
+ }
489
+ if (handled) {
490
+ e.preventDefault();
491
+ this.updateColorDisplay();
492
+ this.announceColorChange();
493
+ }
494
+ };
495
+ ColorPicker.prototype.updateColorDisplay = function (updateInput) {
496
+ var _a;
497
+ if (updateInput === void 0) { updateInput = true; }
498
+ // Update saturation box background
499
+ if (this.colorBox) {
500
+ this.colorBox.style.backgroundColor = "hsl(".concat(this.currentColor.h, ", 100%, 50%)");
501
+ }
502
+ // Update saturation pointer position
503
+ if (this.saturationPointer && this.colorBox) {
504
+ var x = (this.currentColor.s / 100) * 100;
505
+ var y = (1 - this.currentColor.l / 100) * 100;
506
+ this.saturationPointer.style.left = "".concat(x, "%");
507
+ this.saturationPointer.style.top = "".concat(y, "%");
508
+ }
509
+ // Update slider backgrounds (sliderMode)
510
+ if (this.saturationSlider) {
511
+ this.saturationSlider.style.background = "linear-gradient(to right, hsl(".concat(this.currentColor.h, ", 0%, 50%), hsl(").concat(this.currentColor.h, ", 100%, 50%))");
512
+ }
513
+ if (this.lightnessSlider) {
514
+ this.lightnessSlider.style.background = "linear-gradient(to right, hsl(".concat(this.currentColor.h, ", ").concat(this.currentColor.s, "%, 0%), hsl(").concat(this.currentColor.h, ", ").concat(this.currentColor.s, "%, 50%), hsl(").concat(this.currentColor.h, ", ").concat(this.currentColor.s, "%, 100%))");
515
+ }
516
+ // Update preview
517
+ var preview = (_a = this.container) === null || _a === void 0 ? void 0 : _a.querySelector(".colorpicker-preview-color");
518
+ if (preview) {
519
+ preview.style.backgroundColor = this.toHSLString(this.currentColor);
520
+ }
521
+ // Update color value input (shows current format)
522
+ if (this.hexInput && updateInput) {
523
+ this.hexInput.value = this.formatColor(this.currentColor);
524
+ }
525
+ // Update sliders
526
+ if (this.hueSlider) {
527
+ this.hueSlider.value = String(this.currentColor.h);
528
+ }
529
+ if (this.saturationSlider) {
530
+ this.saturationSlider.value = String(this.currentColor.s);
531
+ }
532
+ if (this.lightnessSlider) {
533
+ this.lightnessSlider.value = String(this.currentColor.l);
534
+ }
535
+ if (this.alphaSlider) {
536
+ this.alphaSlider.value = String(this.currentColor.a * 100);
537
+ }
538
+ // Update input field
539
+ if (updateInput) {
540
+ this.input.value = this.formatColor(this.currentColor);
541
+ this.options.onChange(this.input.value);
542
+ // Update compact button preview
543
+ if (this.compactButton) {
544
+ var preview_1 = this.compactButton.querySelector('.colorpicker-compact-preview');
545
+ if (preview_1) {
546
+ preview_1.style.backgroundColor = this.toHSLString(this.currentColor);
547
+ }
548
+ }
549
+ // Update input preview
550
+ if (this.inputPreview) {
551
+ this.inputPreview.style.backgroundColor = this.toHSLString(this.currentColor);
552
+ }
553
+ }
554
+ };
555
+ ColorPicker.prototype.formatColor = function (color) {
556
+ switch (this.options.format) {
557
+ case "hsl":
558
+ return this.toHSLString(color);
559
+ case "rgb":
560
+ return this.toRGBString(this.hslToRgb(color));
561
+ case "hex":
562
+ default:
563
+ return this.toHex(color);
564
+ }
565
+ };
566
+ ColorPicker.prototype.getPlaceholder = function () {
567
+ switch (this.options.format) {
568
+ case "hsl":
569
+ return this.options.showAlpha ? "hsla(0, 0%, 0%, 1)" : "hsl(0, 0%, 0%)";
570
+ case "rgb":
571
+ return this.options.showAlpha ? "rgba(0, 0, 0, 1)" : "rgb(0, 0, 0)";
572
+ case "hex":
573
+ default:
574
+ return "#000000";
575
+ }
576
+ };
577
+ ColorPicker.prototype.parseColor = function (colorString) {
578
+ colorString = colorString.trim();
579
+ // Try hex
580
+ if (colorString.startsWith("#")) {
581
+ return this.hexToHsl(colorString);
582
+ }
583
+ // Try rgb/rgba
584
+ var rgbMatch = colorString.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);
585
+ if (rgbMatch) {
586
+ var rgb = {
587
+ r: parseInt(rgbMatch[1]),
588
+ g: parseInt(rgbMatch[2]),
589
+ b: parseInt(rgbMatch[3]),
590
+ a: rgbMatch[4] ? parseFloat(rgbMatch[4]) : 1,
591
+ };
592
+ return this.rgbToHsl(rgb);
593
+ }
594
+ // Try hsl/hsla
595
+ var hslMatch = colorString.match(/hsla?\((\d+),\s*(\d+)%,\s*(\d+)%(?:,\s*([\d.]+))?\)/);
596
+ if (hslMatch) {
597
+ return {
598
+ h: parseInt(hslMatch[1]),
599
+ s: parseInt(hslMatch[2]),
600
+ l: parseInt(hslMatch[3]),
601
+ a: hslMatch[4] ? parseFloat(hslMatch[4]) : 1,
602
+ };
603
+ }
604
+ // Default to current color
605
+ return this.currentColor;
606
+ };
607
+ ColorPicker.prototype.hexToHsl = function (hex) {
608
+ hex = hex.replace("#", "");
609
+ var r = parseInt(hex.substring(0, 2), 16) / 255;
610
+ var g = parseInt(hex.substring(2, 4), 16) / 255;
611
+ var b = parseInt(hex.substring(4, 6), 16) / 255;
612
+ var a = hex.length === 8 ? parseInt(hex.substring(6, 8), 16) / 255 : 1;
613
+ return this.rgbToHsl({ r: r * 255, g: g * 255, b: b * 255, a: a });
614
+ };
615
+ ColorPicker.prototype.rgbToHsl = function (rgb) {
616
+ var r = rgb.r / 255;
617
+ var g = rgb.g / 255;
618
+ var b = rgb.b / 255;
619
+ var max = Math.max(r, g, b);
620
+ var min = Math.min(r, g, b);
621
+ var h = 0;
622
+ var s = 0;
623
+ var l = (max + min) / 2;
624
+ if (max !== min) {
625
+ var d = max - min;
626
+ s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
627
+ switch (max) {
628
+ case r:
629
+ h = ((g - b) / d + (g < b ? 6 : 0)) / 6;
630
+ break;
631
+ case g:
632
+ h = ((b - r) / d + 2) / 6;
633
+ break;
634
+ case b:
635
+ h = ((r - g) / d + 4) / 6;
636
+ break;
637
+ }
638
+ }
639
+ return {
640
+ h: Math.round(h * 360),
641
+ s: Math.round(s * 100),
642
+ l: Math.round(l * 100),
643
+ a: rgb.a,
644
+ };
645
+ };
646
+ ColorPicker.prototype.hslToRgb = function (hsl) {
647
+ var h = hsl.h / 360;
648
+ var s = hsl.s / 100;
649
+ var l = hsl.l / 100;
650
+ var r, g, b;
651
+ if (s === 0) {
652
+ r = g = b = l;
653
+ }
654
+ else {
655
+ var hue2rgb = function (p, q, t) {
656
+ if (t < 0)
657
+ t += 1;
658
+ if (t > 1)
659
+ t -= 1;
660
+ if (t < 1 / 6)
661
+ return p + (q - p) * 6 * t;
662
+ if (t < 1 / 2)
663
+ return q;
664
+ if (t < 2 / 3)
665
+ return p + (q - p) * (2 / 3 - t) * 6;
666
+ return p;
667
+ };
668
+ var q = l < 0.5 ? l * (1 + s) : l + s - l * s;
669
+ var p = 2 * l - q;
670
+ r = hue2rgb(p, q, h + 1 / 3);
671
+ g = hue2rgb(p, q, h);
672
+ b = hue2rgb(p, q, h - 1 / 3);
673
+ }
674
+ return {
675
+ r: Math.round(r * 255),
676
+ g: Math.round(g * 255),
677
+ b: Math.round(b * 255),
678
+ a: hsl.a,
679
+ };
680
+ };
681
+ ColorPicker.prototype.toHex = function (hsl) {
682
+ var rgb = this.hslToRgb(hsl);
683
+ var toHex = function (n) { return n.toString(16).padStart(2, "0"); };
684
+ // Include alpha channel if showAlpha is enabled and alpha < 1
685
+ if (this.options.showAlpha && hsl.a < 1) {
686
+ var alpha = Math.round(hsl.a * 255);
687
+ return "#".concat(toHex(rgb.r)).concat(toHex(rgb.g)).concat(toHex(rgb.b)).concat(toHex(alpha));
688
+ }
689
+ return "#".concat(toHex(rgb.r)).concat(toHex(rgb.g)).concat(toHex(rgb.b));
690
+ };
691
+ ColorPicker.prototype.toHSLString = function (hsl) {
692
+ if (this.options.showAlpha && hsl.a < 1) {
693
+ return "hsla(".concat(hsl.h, ", ").concat(hsl.s, "%, ").concat(hsl.l, "%, ").concat(hsl.a, ")");
694
+ }
695
+ return "hsl(".concat(hsl.h, ", ").concat(hsl.s, "%, ").concat(hsl.l, "%)");
696
+ };
697
+ ColorPicker.prototype.toRGBString = function (rgb) {
698
+ if (this.options.showAlpha && rgb.a < 1) {
699
+ return "rgba(".concat(rgb.r, ", ").concat(rgb.g, ", ").concat(rgb.b, ", ").concat(rgb.a, ")");
700
+ }
701
+ return "rgb(".concat(rgb.r, ", ").concat(rgb.g, ", ").concat(rgb.b, ")");
702
+ };
703
+ ColorPicker.prototype.isValidHex = function (hex) {
704
+ return /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{8})$/.test(hex);
705
+ };
706
+ ColorPicker.prototype.isValidColor = function (value) {
707
+ // Check if valid HEX
708
+ if (this.isValidHex(value))
709
+ return true;
710
+ // Check if valid RGB/RGBA
711
+ if (/^rgba?\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*(,\s*[\d.]+\s*)?\)$/.test(value))
712
+ return true;
713
+ // Check if valid HSL/HSLA
714
+ if (/^hsla?\(\s*\d+\s*,\s*\d+%\s*,\s*\d+%\s*(,\s*[\d.]+\s*)?\)$/.test(value))
715
+ return true;
716
+ return false;
717
+ };
718
+ ColorPicker.prototype.announceColorChange = function () {
719
+ var _this = this;
720
+ // Throttled ARIA live region announcement
721
+ if (!this.announceTimeout) {
722
+ this.announceTimeout = setTimeout(function () {
723
+ var _a;
724
+ var announcement = document.createElement("div");
725
+ announcement.setAttribute("role", "status");
726
+ announcement.setAttribute("aria-live", "polite");
727
+ announcement.className = "colorpicker-sr-only";
728
+ announcement.textContent = "Color changed to ".concat(_this.formatColor(_this.currentColor));
729
+ (_a = _this.container) === null || _a === void 0 ? void 0 : _a.appendChild(announcement);
730
+ setTimeout(function () { return announcement.remove(); }, 1000);
731
+ _this.announceTimeout = null;
732
+ }, 500);
733
+ }
734
+ };
735
+ ColorPicker.prototype.open = function () {
736
+ var _this = this;
737
+ if (this.isOpen || !this.container)
738
+ return;
739
+ this.isOpen = true;
740
+ this.container.style.display = "block";
741
+ if (!this.options.inline) {
742
+ this.positionPicker();
743
+ }
744
+ this.options.onOpen();
745
+ // Focus first interactive element
746
+ setTimeout(function () {
747
+ var _a;
748
+ (_a = _this.colorBox) === null || _a === void 0 ? void 0 : _a.focus();
749
+ }, 0);
750
+ };
751
+ ColorPicker.prototype.close = function () {
752
+ if (!this.isOpen || !this.container)
753
+ return;
754
+ this.isOpen = false;
755
+ if (!this.options.inline) {
756
+ this.container.style.display = "none";
757
+ }
758
+ this.options.onClose();
759
+ };
760
+ ColorPicker.prototype.toggle = function () {
761
+ if (this.isOpen) {
762
+ this.close();
763
+ }
764
+ else {
765
+ this.open();
766
+ }
767
+ };
768
+ ColorPicker.prototype.positionPicker = function () {
769
+ if (!this.container)
770
+ return;
771
+ var inputRect = this.input.getBoundingClientRect();
772
+ var containerRect = this.container.getBoundingClientRect();
773
+ var viewportHeight = window.innerHeight;
774
+ var top = inputRect.bottom + window.scrollY + 4;
775
+ var left = inputRect.left + window.scrollX;
776
+ // Check if there's enough space below
777
+ if (this.options.position === "auto") {
778
+ var spaceBelow = viewportHeight - inputRect.bottom;
779
+ var spaceAbove = inputRect.top;
780
+ if (spaceBelow < containerRect.height && spaceAbove > spaceBelow) {
781
+ top = inputRect.top + window.scrollY - containerRect.height - 4;
782
+ }
783
+ }
784
+ else if (this.options.position === "above") {
785
+ top = inputRect.top + window.scrollY - containerRect.height - 4;
786
+ }
787
+ this.container.style.position = "absolute";
788
+ this.container.style.top = "".concat(top, "px");
789
+ this.container.style.left = "".concat(left, "px");
790
+ this.container.style.zIndex = "9999";
791
+ };
792
+ ColorPicker.prototype.setColor = function (color) {
793
+ this.currentColor = this.parseColor(color);
794
+ this.updateColorDisplay();
795
+ };
796
+ ColorPicker.prototype.getColor = function () {
797
+ return this.formatColor(this.currentColor);
798
+ };
799
+ ColorPicker.prototype.destroy = function () {
800
+ var _a, _b, _c;
801
+ (_a = this.container) === null || _a === void 0 ? void 0 : _a.remove();
802
+ (_b = this.compactButton) === null || _b === void 0 ? void 0 : _b.remove();
803
+ // Restore input if it was hidden for compact mode
804
+ if (this.options.compact && this.input) {
805
+ this.input.style.position = "";
806
+ this.input.style.opacity = "";
807
+ this.input.style.pointerEvents = "";
808
+ this.input.style.width = "";
809
+ this.input.style.height = "";
810
+ }
811
+ // Restore input if it had preview
812
+ if (this.options.inputPreview && this.input) {
813
+ this.input.classList.remove("colorpicker-has-preview");
814
+ var wrapper = this.input.parentElement;
815
+ if (wrapper && wrapper.classList.contains("colorpicker-input-group")) {
816
+ (_c = wrapper.parentNode) === null || _c === void 0 ? void 0 : _c.insertBefore(this.input, wrapper);
817
+ wrapper.remove();
818
+ }
819
+ }
820
+ ColorPicker.instances.delete(this.input);
821
+ };
822
+ ColorPicker.getInstance = function (element) {
823
+ return ColorPicker.instances.get(element);
824
+ };
825
+ ColorPicker.instances = new Map();
826
+ return ColorPicker;
827
+ }());
828
+ // Factory function
829
+ function colorpicker(selector, options) {
830
+ return new ColorPicker(selector, options);
831
+ }
832
+ // Auto-initialization helper
833
+ function initColorPickers(root) {
834
+ if (root === void 0) { root = document; }
835
+ var pickers = [];
836
+ var elements = root.querySelectorAll('[data-colorpicker], .colorpicker, input[type="color"][data-format]');
837
+ elements.forEach(function (element) {
838
+ // Skip if already initialized
839
+ if (ColorPicker.getInstance(element)) {
840
+ return;
841
+ }
842
+ var dataset = element.dataset;
843
+ var options = {};
844
+ // Parse data-colorpicker attribute
845
+ if (dataset.colorpicker) {
846
+ var config = dataset.colorpicker;
847
+ var parts = config.split(/[,;]/);
848
+ parts.forEach(function (part) {
849
+ var _a = part.split(':').map(function (s) { return s.trim(); }), key = _a[0], value = _a[1];
850
+ switch (key) {
851
+ case 'format':
852
+ if (value === 'hex' || value === 'rgb' || value === 'hsl') {
853
+ options.format = value;
854
+ }
855
+ break;
856
+ case 'alpha':
857
+ case 'showAlpha':
858
+ options.showAlpha = value === 'true' || value === '1';
859
+ break;
860
+ case 'compact':
861
+ options.compact = value === 'true' || value === '1';
862
+ break;
863
+ case 'inline':
864
+ options.inline = value === 'true' || value === '1';
865
+ break;
866
+ case 'presets':
867
+ options.presetsOnly = value === 'true' || value === '1';
868
+ break;
869
+ case 'list':
870
+ options.listView = value === 'true' || value === '1';
871
+ break;
872
+ case 'sliderMode':
873
+ options.sliderMode = value === 'true' || value === '1';
874
+ break;
875
+ case 'eyeDropper':
876
+ options.eyeDropper = value === 'true' || value === '1';
877
+ break;
878
+ case 'inputPreview':
879
+ options.inputPreview = value === 'true' || value === '1';
880
+ break;
881
+ }
882
+ });
883
+ }
884
+ // Parse individual data attributes
885
+ if (dataset.format && (dataset.format === 'hex' || dataset.format === 'rgb' || dataset.format === 'hsl')) {
886
+ options.format = dataset.format;
887
+ }
888
+ if (dataset.alpha !== undefined) {
889
+ options.showAlpha = dataset.alpha === 'true' || dataset.alpha === '1';
890
+ }
891
+ if (dataset.compact !== undefined) {
892
+ options.compact = dataset.compact === 'true' || dataset.compact === '1';
893
+ }
894
+ if (dataset.inline !== undefined) {
895
+ options.inline = dataset.inline === 'true' || dataset.inline === '1';
896
+ }
897
+ if (dataset.presetsOnly !== undefined) {
898
+ options.presetsOnly = dataset.presetsOnly === 'true' || dataset.presetsOnly === '1';
899
+ }
900
+ if (dataset.listView !== undefined) {
901
+ options.listView = dataset.listView === 'true' || dataset.listView === '1';
902
+ }
903
+ if (dataset.defaultColor) {
904
+ options.defaultColor = dataset.defaultColor;
905
+ }
906
+ // Create picker instance
907
+ var picker = new ColorPicker(element, options);
908
+ pickers.push(picker);
909
+ });
910
+ return pickers;
911
+ }
912
+ // Auto-init on DOMContentLoaded
913
+ if (typeof window !== 'undefined' && typeof document !== 'undefined') {
914
+ if (document.readyState === 'loading') {
915
+ document.addEventListener('DOMContentLoaded', function () { return initColorPickers(); });
916
+ }
917
+ else {
918
+ // DOM already loaded
919
+ initColorPickers();
920
+ }
921
+ }
922
+
923
+ exports.ColorPicker = ColorPicker;
924
+ exports.default = colorpicker;
925
+ exports.initColorPickers = initColorPickers;
926
+
927
+ Object.defineProperty(exports, '__esModule', { value: true });
928
+
929
+ })));