@thednp/color-picker 0.0.2 → 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.
- package/README.md +2 -1
- package/dist/css/color-picker.css +82 -46
- package/dist/css/color-picker.min.css +2 -2
- package/dist/css/color-picker.rtl.css +82 -46
- package/dist/css/color-picker.rtl.min.css +2 -2
- package/dist/js/color-esm.js +1 -1
- package/dist/js/color-esm.min.js +1 -1
- package/dist/js/color-palette-esm.js +1 -1
- package/dist/js/color-palette-esm.min.js +1 -1
- package/dist/js/color-palette.js +1 -1
- package/dist/js/color-palette.min.js +1 -1
- package/dist/js/color-picker-element-esm.js +180 -164
- package/dist/js/color-picker-element-esm.min.js +2 -2
- package/dist/js/color-picker-element.js +180 -164
- package/dist/js/color-picker-element.min.js +2 -2
- package/dist/js/color-picker-esm.js +69 -113
- package/dist/js/color-picker-esm.min.js +2 -2
- package/dist/js/color-picker.js +69 -113
- package/dist/js/color-picker.min.js +2 -2
- package/dist/js/color.js +1 -1
- package/dist/js/color.min.js +1 -1
- package/package.json +17 -14
- package/src/js/color-picker-element.js +44 -33
- package/src/js/color-picker.js +43 -44
- package/src/js/util/getColorMenu.js +7 -8
- package/src/js/util/setMarkup.js +4 -7
- package/src/js/util/toggleCEAttr.js +70 -0
- package/src/scss/_variables.scss +7 -0
- package/src/scss/color-picker.scss +86 -45
- package/types/index.d.ts +1 -1
- package/types/source/types.d.ts +8 -6
@@ -1,5 +1,5 @@
|
|
1
1
|
/*!
|
2
|
-
* ColorPickerElement
|
2
|
+
* ColorPickerElement v1.0.0 (http://thednp.github.io/color-picker)
|
3
3
|
* Copyright 2022 © thednp
|
4
4
|
* Licensed under MIT (https://github.com/thednp/color-picker/blob/master/LICENSE)
|
5
5
|
*/
|
@@ -21,25 +21,6 @@
|
|
21
21
|
return window.document;
|
22
22
|
}
|
23
23
|
|
24
|
-
/**
|
25
|
-
* A global array of possible `ParentNode`.
|
26
|
-
*/
|
27
|
-
const parentNodes = [Document, Element, HTMLElement];
|
28
|
-
|
29
|
-
/**
|
30
|
-
* Shortcut for `HTMLElement.getElementsByTagName` method. Some `Node` elements
|
31
|
-
* like `ShadowRoot` do not support `getElementsByTagName`.
|
32
|
-
*
|
33
|
-
* @param {string} selector the tag name
|
34
|
-
* @param {(HTMLElement | Element | Document)=} parent optional Element to look into
|
35
|
-
* @return {HTMLCollectionOf<HTMLElement | Element>} the 'HTMLCollection'
|
36
|
-
*/
|
37
|
-
function getElementsByTagName(selector, parent) {
|
38
|
-
const lookUp = parent && parentNodes
|
39
|
-
.some((x) => parent instanceof x) ? parent : getDocument();
|
40
|
-
return lookUp.getElementsByTagName(selector);
|
41
|
-
}
|
42
|
-
|
43
24
|
/**
|
44
25
|
* Shortcut for `Object.assign()` static method.
|
45
26
|
* @param {Record<string, any>} obj a target object
|
@@ -1247,27 +1228,26 @@
|
|
1247
1228
|
/**
|
1248
1229
|
* The global event listener.
|
1249
1230
|
*
|
1250
|
-
* @
|
1251
|
-
* @
|
1252
|
-
* @returns {void}
|
1231
|
+
* @type {EventListener}
|
1232
|
+
* @this {EventTarget}
|
1253
1233
|
*/
|
1254
1234
|
function globalListener(e) {
|
1255
1235
|
const that = this;
|
1256
|
-
const { type } = e;
|
1257
|
-
const oneEvMap = EventRegistry[type] ? [...EventRegistry[type]] : [];
|
1236
|
+
const { type, target } = e;
|
1258
1237
|
|
1259
|
-
|
1238
|
+
[...EventRegistry[type]].forEach((elementsMap) => {
|
1260
1239
|
const [element, listenersMap] = elementsMap;
|
1261
|
-
|
1262
|
-
|
1240
|
+
/* istanbul ignore else */
|
1241
|
+
if ([target, that].some((el) => element === el)) {
|
1242
|
+
[...listenersMap].forEach((listenerMap) => {
|
1263
1243
|
const [listener, options] = listenerMap;
|
1264
1244
|
listener.apply(element, [e]);
|
1265
1245
|
|
1266
1246
|
if (options && options.once) {
|
1267
1247
|
removeListener(element, type, listener, options);
|
1268
1248
|
}
|
1269
|
-
}
|
1270
|
-
}
|
1249
|
+
});
|
1250
|
+
}
|
1271
1251
|
});
|
1272
1252
|
}
|
1273
1253
|
|
@@ -1275,10 +1255,7 @@
|
|
1275
1255
|
* Register a new listener with its options and attach the `globalListener`
|
1276
1256
|
* to the target if this is the first listener.
|
1277
1257
|
*
|
1278
|
-
* @
|
1279
|
-
* @param {string} eventType
|
1280
|
-
* @param {EventListenerObject['handleEvent']} listener
|
1281
|
-
* @param {AddEventListenerOptions=} options
|
1258
|
+
* @type {Listener.ListenerAction<EventTarget>}
|
1282
1259
|
*/
|
1283
1260
|
const addListener = (element, eventType, listener, options) => {
|
1284
1261
|
// get element listeners first
|
@@ -1296,9 +1273,7 @@
|
|
1296
1273
|
const { size } = oneElementMap;
|
1297
1274
|
|
1298
1275
|
// register listener with its options
|
1299
|
-
|
1300
|
-
oneElementMap.set(listener, options);
|
1301
|
-
}
|
1276
|
+
oneElementMap.set(listener, options);
|
1302
1277
|
|
1303
1278
|
// add listener last
|
1304
1279
|
if (!size) {
|
@@ -1310,10 +1285,7 @@
|
|
1310
1285
|
* Remove a listener from registry and detach the `globalListener`
|
1311
1286
|
* if no listeners are found in the registry.
|
1312
1287
|
*
|
1313
|
-
* @
|
1314
|
-
* @param {string} eventType
|
1315
|
-
* @param {EventListenerObject['handleEvent']} listener
|
1316
|
-
* @param {AddEventListenerOptions=} options
|
1288
|
+
* @type {Listener.ListenerAction<EventTarget>}
|
1317
1289
|
*/
|
1318
1290
|
const removeListener = (element, eventType, listener, options) => {
|
1319
1291
|
// get listener first
|
@@ -1332,6 +1304,7 @@
|
|
1332
1304
|
if (!oneEventMap || !oneEventMap.size) delete EventRegistry[eventType];
|
1333
1305
|
|
1334
1306
|
// remove listener last
|
1307
|
+
/* istanbul ignore else */
|
1335
1308
|
if (!oneElementMap || !oneElementMap.size) {
|
1336
1309
|
element.removeEventListener(eventType, globalListener, eventOptions);
|
1337
1310
|
}
|
@@ -1433,12 +1406,6 @@
|
|
1433
1406
|
*/
|
1434
1407
|
const changeEvent = 'change';
|
1435
1408
|
|
1436
|
-
/**
|
1437
|
-
* A global namespace for `touchstart` event.
|
1438
|
-
* @type {string}
|
1439
|
-
*/
|
1440
|
-
const touchstartEvent = 'touchstart';
|
1441
|
-
|
1442
1409
|
/**
|
1443
1410
|
* A global namespace for `touchmove` event.
|
1444
1411
|
* @type {string}
|
@@ -1446,28 +1413,22 @@
|
|
1446
1413
|
const touchmoveEvent = 'touchmove';
|
1447
1414
|
|
1448
1415
|
/**
|
1449
|
-
* A global namespace for `
|
1450
|
-
* @type {string}
|
1451
|
-
*/
|
1452
|
-
const touchendEvent = 'touchend';
|
1453
|
-
|
1454
|
-
/**
|
1455
|
-
* A global namespace for `mousedown` event.
|
1416
|
+
* A global namespace for `pointerdown` event.
|
1456
1417
|
* @type {string}
|
1457
1418
|
*/
|
1458
|
-
const
|
1419
|
+
const pointerdownEvent = 'pointerdown';
|
1459
1420
|
|
1460
1421
|
/**
|
1461
|
-
* A global namespace for `
|
1422
|
+
* A global namespace for `pointermove` event.
|
1462
1423
|
* @type {string}
|
1463
1424
|
*/
|
1464
|
-
const
|
1425
|
+
const pointermoveEvent = 'pointermove';
|
1465
1426
|
|
1466
1427
|
/**
|
1467
|
-
* A global namespace for `
|
1428
|
+
* A global namespace for `pointerup` event.
|
1468
1429
|
* @type {string}
|
1469
1430
|
*/
|
1470
|
-
const
|
1431
|
+
const pointerupEvent = 'pointerup';
|
1471
1432
|
|
1472
1433
|
/**
|
1473
1434
|
* A global namespace for `scroll` event.
|
@@ -1503,27 +1464,6 @@
|
|
1503
1464
|
return getDocument(node).documentElement;
|
1504
1465
|
}
|
1505
1466
|
|
1506
|
-
/**
|
1507
|
-
* Returns the `Window` object of a target node.
|
1508
|
-
* @see https://github.com/floating-ui/floating-ui
|
1509
|
-
*
|
1510
|
-
* @param {(Node | HTMLElement | Element | Window)=} node target node
|
1511
|
-
* @returns {globalThis}
|
1512
|
-
*/
|
1513
|
-
function getWindow(node) {
|
1514
|
-
if (node == null) {
|
1515
|
-
return window;
|
1516
|
-
}
|
1517
|
-
|
1518
|
-
if (!(node instanceof Window)) {
|
1519
|
-
const { ownerDocument } = node;
|
1520
|
-
return ownerDocument ? ownerDocument.defaultView || window : window;
|
1521
|
-
}
|
1522
|
-
|
1523
|
-
// @ts-ignore
|
1524
|
-
return node;
|
1525
|
-
}
|
1526
|
-
|
1527
1467
|
let elementUID = 0;
|
1528
1468
|
let elementMapUID = 0;
|
1529
1469
|
const elementIDMap = new Map();
|
@@ -1623,6 +1563,11 @@
|
|
1623
1563
|
return !Number.isNaN(duration) ? duration : 0;
|
1624
1564
|
}
|
1625
1565
|
|
1566
|
+
/**
|
1567
|
+
* A global array of possible `ParentNode`.
|
1568
|
+
*/
|
1569
|
+
const parentNodes = [Document, Element, HTMLElement];
|
1570
|
+
|
1626
1571
|
/**
|
1627
1572
|
* A global array with `Element` | `HTMLElement`.
|
1628
1573
|
*/
|
@@ -2266,17 +2211,16 @@
|
|
2266
2211
|
const isOptionsMenu = menuClass === 'color-options';
|
2267
2212
|
const isPalette = colorsSource instanceof ColorPalette;
|
2268
2213
|
const menuLabel = isOptionsMenu ? presetsLabel : defaultsLabel;
|
2269
|
-
|
2270
|
-
colorsArray = colorsArray instanceof Array ? colorsArray : [];
|
2214
|
+
const colorsArray = isPalette ? colorsSource.colors : colorsSource;
|
2271
2215
|
const colorsCount = colorsArray.length;
|
2272
2216
|
const { lightSteps } = isPalette ? colorsSource : { lightSteps: null };
|
2273
|
-
const fit = lightSteps || [9, 10].find((x) => colorsCount
|
2217
|
+
const fit = lightSteps || [9, 10].find((x) => colorsCount >= x * 2 && !(colorsCount % x)) || 5;
|
2274
2218
|
const isMultiLine = isOptionsMenu && colorsCount > fit;
|
2275
2219
|
let rowCountHover = 2;
|
2276
|
-
rowCountHover = isMultiLine && colorsCount
|
2277
|
-
rowCountHover = colorsCount
|
2278
|
-
rowCountHover = colorsCount
|
2279
|
-
const rowCount = rowCountHover - (colorsCount
|
2220
|
+
rowCountHover = isMultiLine && colorsCount > fit * 2 ? 3 : rowCountHover;
|
2221
|
+
rowCountHover = isMultiLine && colorsCount > fit * 3 ? 4 : rowCountHover;
|
2222
|
+
rowCountHover = isMultiLine && colorsCount > fit * 4 ? 5 : rowCountHover;
|
2223
|
+
const rowCount = rowCountHover - (colorsCount <= fit * 3 ? 1 : 2);
|
2280
2224
|
const isScrollable = isMultiLine && colorsCount > rowCount * fit;
|
2281
2225
|
let finalClass = menuClass;
|
2282
2226
|
finalClass += isScrollable ? ' scrollable' : '';
|
@@ -2284,7 +2228,7 @@
|
|
2284
2228
|
const gap = isMultiLine ? '1px' : '0.25rem';
|
2285
2229
|
let optionSize = isMultiLine ? 1.75 : 2;
|
2286
2230
|
optionSize = fit > 5 && isMultiLine ? 1.5 : optionSize;
|
2287
|
-
const menuHeight = `${
|
2231
|
+
const menuHeight = `${rowCount * optionSize}rem`;
|
2288
2232
|
const menuHeightHover = `calc(${rowCountHover} * ${optionSize}rem + ${rowCountHover - 1} * ${gap})`;
|
2289
2233
|
/** @type {HTMLUListElement} */
|
2290
2234
|
// @ts-ignore -- <UL> is an `HTMLElement`
|
@@ -2391,16 +2335,14 @@
|
|
2391
2335
|
});
|
2392
2336
|
|
2393
2337
|
// color presets
|
2394
|
-
if (
|
2395
|
-
|
2396
|
-
const presetsMenu = getColorMenu(self, colorPresets, 'color-options');
|
2397
|
-
presetsDropdown.append(presetsMenu);
|
2338
|
+
if (colorPresets) {
|
2339
|
+
presetsDropdown.append(getColorMenu(self, colorPresets, 'color-options'));
|
2398
2340
|
}
|
2399
2341
|
|
2400
2342
|
// explicit defaults [reset, initial, inherit, transparent, currentColor]
|
2343
|
+
// also custom defaults [default: #069, complementary: #930]
|
2401
2344
|
if (colorKeywords && colorKeywords.length) {
|
2402
|
-
|
2403
|
-
presetsDropdown.append(keywordsMenu);
|
2345
|
+
presetsDropdown.append(getColorMenu(self, colorKeywords, 'color-defaults'));
|
2404
2346
|
}
|
2405
2347
|
|
2406
2348
|
const presetsBtn = createElement({
|
@@ -2437,7 +2379,7 @@
|
|
2437
2379
|
setAttribute(input, tabIndex, '-1');
|
2438
2380
|
}
|
2439
2381
|
|
2440
|
-
var version = "0.0
|
2382
|
+
var version = "1.0.0";
|
2441
2383
|
|
2442
2384
|
// @ts-ignore
|
2443
2385
|
|
@@ -2459,7 +2401,7 @@
|
|
2459
2401
|
// ColorPicker Static Methods
|
2460
2402
|
// ==========================
|
2461
2403
|
|
2462
|
-
/** @type {CP.GetInstance<ColorPicker>} */
|
2404
|
+
/** @type {CP.GetInstance<ColorPicker, HTMLInputElement>} */
|
2463
2405
|
const getColorPickerInstance = (element) => getInstance(element, colorPickerString);
|
2464
2406
|
|
2465
2407
|
/** @type {CP.InitCallback<ColorPicker>} */
|
@@ -2494,12 +2436,10 @@
|
|
2494
2436
|
const fn = action ? addListener : removeListener;
|
2495
2437
|
const { input, colorMenu, parent } = self;
|
2496
2438
|
const doc = getDocument(input);
|
2497
|
-
const win = getWindow(input);
|
2498
|
-
const
|
2499
|
-
? { down: touchstartEvent, move: touchmoveEvent, up: touchendEvent }
|
2500
|
-
: { down: mousedownEvent, move: mousemoveEvent, up: mouseupEvent };
|
2439
|
+
// const win = getWindow(input);
|
2440
|
+
const win = doc.defaultView;
|
2501
2441
|
|
2502
|
-
fn(self.controls,
|
2442
|
+
fn(self.controls, pointerdownEvent, self.pointerDown);
|
2503
2443
|
self.controlKnobs.forEach((x) => fn(x, keydownEvent, self.handleKnobs));
|
2504
2444
|
|
2505
2445
|
// @ts-ignore -- this is `Window`
|
@@ -2514,8 +2454,8 @@
|
|
2514
2454
|
fn(colorMenu, keydownEvent, self.menuKeyHandler);
|
2515
2455
|
}
|
2516
2456
|
|
2517
|
-
fn(doc,
|
2518
|
-
fn(doc,
|
2457
|
+
fn(doc, pointermoveEvent, self.pointerMove);
|
2458
|
+
fn(doc, pointerupEvent, self.pointerUp);
|
2519
2459
|
fn(parent, focusoutEvent, self.handleFocusOut);
|
2520
2460
|
fn(doc, keyupEvent, self.handleDismiss);
|
2521
2461
|
}
|
@@ -2534,6 +2474,7 @@
|
|
2534
2474
|
* @returns {void}
|
2535
2475
|
*/
|
2536
2476
|
function removePosition(element) {
|
2477
|
+
/* istanbul ignore else */
|
2537
2478
|
if (element) {
|
2538
2479
|
['bottom', 'top'].forEach((x) => removeClass(element, x));
|
2539
2480
|
}
|
@@ -2636,6 +2577,7 @@
|
|
2636
2577
|
} = normalizeOptions(this.isCE ? parent : input, colorPickerDefaults, config || {});
|
2637
2578
|
|
2638
2579
|
let translatedColorLabels = colorNames;
|
2580
|
+
/* istanbul ignore else */
|
2639
2581
|
if (colorLabels instanceof Array && colorLabels.length === 17) {
|
2640
2582
|
translatedColorLabels = colorLabels;
|
2641
2583
|
} else if (colorLabels && colorLabels.split(',').length === 17) {
|
@@ -2652,7 +2594,7 @@
|
|
2652
2594
|
? JSON.parse(componentLabels) : componentLabels;
|
2653
2595
|
|
2654
2596
|
/** @type {Record<string, string>} */
|
2655
|
-
self.componentLabels = ObjectAssign(colorPickerLabels, tempComponentLabels);
|
2597
|
+
self.componentLabels = ObjectAssign({ ...colorPickerLabels }, tempComponentLabels);
|
2656
2598
|
|
2657
2599
|
/** @type {Color} */
|
2658
2600
|
self.color = new Color(input.value || '#fff', format);
|
@@ -2661,14 +2603,14 @@
|
|
2661
2603
|
self.format = format;
|
2662
2604
|
|
2663
2605
|
// set colour defaults
|
2664
|
-
if (colorKeywords instanceof Array) {
|
2606
|
+
if (colorKeywords instanceof Array && colorKeywords.length) {
|
2665
2607
|
self.colorKeywords = colorKeywords;
|
2666
2608
|
} else if (typeof colorKeywords === 'string' && colorKeywords.length) {
|
2667
2609
|
self.colorKeywords = colorKeywords.split(',').map((x) => x.trim());
|
2668
2610
|
}
|
2669
2611
|
|
2670
2612
|
// set colour presets
|
2671
|
-
if (colorPresets instanceof Array) {
|
2613
|
+
if (colorPresets instanceof Array && colorPresets.length) {
|
2672
2614
|
self.colorPresets = colorPresets;
|
2673
2615
|
} else if (typeof colorPresets === 'string' && colorPresets.length) {
|
2674
2616
|
if (isValidJSON(colorPresets)) {
|
@@ -2799,6 +2741,7 @@
|
|
2799
2741
|
let colorName;
|
2800
2742
|
|
2801
2743
|
// determine color appearance
|
2744
|
+
/* istanbul ignore else */
|
2802
2745
|
if (lightness === 100 && saturation === 0) {
|
2803
2746
|
colorName = colorLabels.white;
|
2804
2747
|
} else if (lightness === 0) {
|
@@ -2899,13 +2842,14 @@
|
|
2899
2842
|
const self = this;
|
2900
2843
|
const { activeElement } = getDocument(self.input);
|
2901
2844
|
|
2902
|
-
|
2845
|
+
self.updateDropdownPosition();
|
2846
|
+
|
2847
|
+
/* istanbul ignore next */
|
2848
|
+
if (([pointermoveEvent, touchmoveEvent].includes(e.type) && self.dragElement)
|
2903
2849
|
|| (activeElement && self.controlKnobs.includes(activeElement))) {
|
2904
2850
|
e.stopPropagation();
|
2905
2851
|
e.preventDefault();
|
2906
2852
|
}
|
2907
|
-
|
2908
|
-
self.updateDropdownPosition();
|
2909
2853
|
}
|
2910
2854
|
|
2911
2855
|
/**
|
@@ -2979,7 +2923,9 @@
|
|
2979
2923
|
|
2980
2924
|
self.update();
|
2981
2925
|
|
2926
|
+
/* istanbul ignore else */
|
2982
2927
|
if (currentActive !== target) {
|
2928
|
+
/* istanbul ignore else */
|
2983
2929
|
if (currentActive) {
|
2984
2930
|
removeClass(currentActive, 'active');
|
2985
2931
|
removeAttribute(currentActive, ariaSelected);
|
@@ -2997,15 +2943,13 @@
|
|
2997
2943
|
|
2998
2944
|
/**
|
2999
2945
|
* The `ColorPicker` *touchstart* / *mousedown* events listener for control knobs.
|
3000
|
-
* @param {
|
2946
|
+
* @param {PointerEvent} e
|
3001
2947
|
* @this {ColorPicker}
|
3002
2948
|
*/
|
3003
2949
|
pointerDown(e) {
|
3004
2950
|
const self = this;
|
3005
2951
|
/** @type {*} */
|
3006
|
-
const {
|
3007
|
-
type, target, touches, pageX, pageY,
|
3008
|
-
} = e;
|
2952
|
+
const { target, pageX, pageY } = e;
|
3009
2953
|
const { colorMenu, visuals, controlKnobs } = self;
|
3010
2954
|
const [v1, v2, v3] = visuals;
|
3011
2955
|
const [c1, c2, c3] = controlKnobs;
|
@@ -3013,11 +2957,10 @@
|
|
3013
2957
|
const visual = controlKnobs.includes(target) ? target.previousElementSibling : target;
|
3014
2958
|
const visualRect = getBoundingClientRect(visual);
|
3015
2959
|
const html = getDocumentElement(v1);
|
3016
|
-
const
|
3017
|
-
const
|
3018
|
-
const offsetX = X - html.scrollLeft - visualRect.left;
|
3019
|
-
const offsetY = Y - html.scrollTop - visualRect.top;
|
2960
|
+
const offsetX = pageX - html.scrollLeft - visualRect.left;
|
2961
|
+
const offsetY = pageY - html.scrollTop - visualRect.top;
|
3020
2962
|
|
2963
|
+
/* istanbul ignore else */
|
3021
2964
|
if (target === v1 || target === c1) {
|
3022
2965
|
self.dragElement = visual;
|
3023
2966
|
self.changeControl1(offsetX, offsetY);
|
@@ -3041,7 +2984,7 @@
|
|
3041
2984
|
|
3042
2985
|
/**
|
3043
2986
|
* The `ColorPicker` *touchend* / *mouseup* events listener for control knobs.
|
3044
|
-
* @param {
|
2987
|
+
* @param {PointerEvent} e
|
3045
2988
|
* @this {ColorPicker}
|
3046
2989
|
*/
|
3047
2990
|
pointerUp({ target }) {
|
@@ -3050,9 +2993,8 @@
|
|
3050
2993
|
const doc = getDocument(parent);
|
3051
2994
|
const currentOpen = querySelector(`${colorPickerParentSelector}.open`, doc) !== null;
|
3052
2995
|
const selection = doc.getSelection();
|
3053
|
-
|
2996
|
+
|
3054
2997
|
if (!self.dragElement && !selection.toString().length
|
3055
|
-
// @ts-ignore
|
3056
2998
|
&& !parent.contains(target)) {
|
3057
2999
|
self.hide(currentOpen);
|
3058
3000
|
}
|
@@ -3062,25 +3004,20 @@
|
|
3062
3004
|
|
3063
3005
|
/**
|
3064
3006
|
* The `ColorPicker` *touchmove* / *mousemove* events listener for control knobs.
|
3065
|
-
* @param {
|
3007
|
+
* @param {PointerEvent} e
|
3066
3008
|
*/
|
3067
3009
|
pointerMove(e) {
|
3068
3010
|
const self = this;
|
3069
3011
|
const { dragElement, visuals } = self;
|
3070
3012
|
const [v1, v2, v3] = visuals;
|
3071
|
-
const {
|
3072
|
-
// @ts-ignore
|
3073
|
-
type, touches, pageX, pageY,
|
3074
|
-
} = e;
|
3013
|
+
const { pageX, pageY } = e;
|
3075
3014
|
|
3076
3015
|
if (!dragElement) return;
|
3077
3016
|
|
3078
3017
|
const controlRect = getBoundingClientRect(dragElement);
|
3079
3018
|
const win = getDocumentElement(v1);
|
3080
|
-
const
|
3081
|
-
const
|
3082
|
-
const offsetX = X - win.scrollLeft - controlRect.left;
|
3083
|
-
const offsetY = Y - win.scrollTop - controlRect.top;
|
3019
|
+
const offsetX = pageX - win.scrollLeft - controlRect.left;
|
3020
|
+
const offsetY = pageY - win.scrollTop - controlRect.top;
|
3084
3021
|
|
3085
3022
|
if (dragElement === v1) {
|
3086
3023
|
self.changeControl1(offsetX, offsetY);
|
@@ -3114,13 +3051,16 @@
|
|
3114
3051
|
const currentKnob = controlKnobs.find((x) => x === activeElement);
|
3115
3052
|
const yRatio = offsetHeight / 360;
|
3116
3053
|
|
3054
|
+
/* istanbul ignore else */
|
3117
3055
|
if (currentKnob) {
|
3118
3056
|
let offsetX = 0;
|
3119
3057
|
let offsetY = 0;
|
3120
3058
|
|
3059
|
+
/* istanbul ignore else */
|
3121
3060
|
if (target === c1) {
|
3122
3061
|
const xRatio = offsetWidth / 100;
|
3123
3062
|
|
3063
|
+
/* istanbul ignore else */
|
3124
3064
|
if ([keyArrowLeft, keyArrowRight].includes(code)) {
|
3125
3065
|
self.controlPositions.c1x += code === keyArrowRight ? xRatio : -xRatio;
|
3126
3066
|
} else if ([keyArrowUp, keyArrowDown].includes(code)) {
|
@@ -3166,6 +3106,7 @@
|
|
3166
3106
|
const isNonColorValue = self.hasNonColor && nonColors.includes(currentValue);
|
3167
3107
|
const alpha = i4 ? v4 : (1 - controlPositions.c3y / offsetHeight);
|
3168
3108
|
|
3109
|
+
/* istanbul ignore else */
|
3169
3110
|
if (activeElement === input || (activeElement && inputs.includes(activeElement))) {
|
3170
3111
|
if (activeElement === input) {
|
3171
3112
|
if (isNonColorValue) {
|
@@ -3480,6 +3421,7 @@
|
|
3480
3421
|
const hue = roundPart(hsl.h * 360);
|
3481
3422
|
let newColor;
|
3482
3423
|
|
3424
|
+
/* istanbul ignore else */
|
3483
3425
|
if (format === 'hex') {
|
3484
3426
|
newColor = self.color.toHexString(true);
|
3485
3427
|
i1.value = self.hex;
|
@@ -3580,15 +3522,15 @@
|
|
3580
3522
|
const relatedBtn = openPicker ? pickerToggle : menuToggle;
|
3581
3523
|
const animationDuration = openDropdown && getElementTransitionDuration(openDropdown);
|
3582
3524
|
|
3583
|
-
// if (!self.isValid) {
|
3584
3525
|
self.value = self.color.toString(true);
|
3585
|
-
// }
|
3586
3526
|
|
3527
|
+
/* istanbul ignore else */
|
3587
3528
|
if (openDropdown) {
|
3588
3529
|
removeClass(openDropdown, 'show');
|
3589
3530
|
setAttribute(relatedBtn, ariaExpanded, 'false');
|
3590
3531
|
setTimeout(() => {
|
3591
3532
|
removePosition(openDropdown);
|
3533
|
+
/* istanbul ignore else */
|
3592
3534
|
if (!querySelector('.show', parent)) {
|
3593
3535
|
removeClass(parent, 'open');
|
3594
3536
|
toggleEventsOnShown(self);
|
@@ -3601,7 +3543,7 @@
|
|
3601
3543
|
focus(pickerToggle);
|
3602
3544
|
}
|
3603
3545
|
setAttribute(input, tabIndex, '-1');
|
3604
|
-
if (menuToggle) {
|
3546
|
+
if (relatedBtn === menuToggle) {
|
3605
3547
|
setAttribute(menuToggle, tabIndex, '-1');
|
3606
3548
|
}
|
3607
3549
|
}
|
@@ -3639,14 +3581,76 @@
|
|
3639
3581
|
getBoundingClientRect,
|
3640
3582
|
});
|
3641
3583
|
|
3584
|
+
/**
|
3585
|
+
* A small utility to toggle `ColorPickerElement` attributes
|
3586
|
+
* when `connectedCallback` or `disconnectedCallback` methods
|
3587
|
+
* are called and helps the instance keep its value and settings instact.
|
3588
|
+
*
|
3589
|
+
* @param {CP.ColorPickerElement} self ColorPickerElement instance
|
3590
|
+
* @param {Function=} callback when `true`, attributes are added
|
3591
|
+
*
|
3592
|
+
* @example
|
3593
|
+
* const attributes = [
|
3594
|
+
* // essentials
|
3595
|
+
* 'value', 'format',
|
3596
|
+
* // presets menus
|
3597
|
+
* 'color-presets', 'color-keywords',
|
3598
|
+
* // labels
|
3599
|
+
* 'color-labels', 'component-labels',
|
3600
|
+
* ];
|
3601
|
+
*/
|
3602
|
+
function toggleCEAttr(self, callback) {
|
3603
|
+
if (callback) {
|
3604
|
+
const { input, colorPicker } = self;
|
3605
|
+
|
3606
|
+
const {
|
3607
|
+
value, format, colorPresets, colorKeywords, componentLabels, colorLabels,
|
3608
|
+
} = colorPicker;
|
3609
|
+
|
3610
|
+
const { id, placeholder } = input;
|
3611
|
+
|
3612
|
+
setAttribute(self, 'data-id', id);
|
3613
|
+
setAttribute(self, 'data-value', value);
|
3614
|
+
setAttribute(self, 'data-format', format);
|
3615
|
+
setAttribute(self, 'data-placeholder', placeholder);
|
3616
|
+
|
3617
|
+
if (ObjectKeys(colorPickerLabels).some((l) => colorPickerLabels[l] !== componentLabels[l])) {
|
3618
|
+
setAttribute(self, 'data-component-labels', JSON.stringify(componentLabels));
|
3619
|
+
}
|
3620
|
+
if (!colorNames.every((c) => c === colorLabels[c])) {
|
3621
|
+
setAttribute(self, 'data-color-labels', colorNames.map((n) => colorLabels[n]).join(','));
|
3622
|
+
}
|
3623
|
+
if (colorPresets instanceof ColorPalette) {
|
3624
|
+
const { hue, hueSteps, lightSteps } = colorPresets;
|
3625
|
+
setAttribute(self, 'data-color-presets', JSON.stringify({ hue, hueSteps, lightSteps }));
|
3626
|
+
}
|
3627
|
+
if (Array.isArray(colorPresets) && colorPresets.length) {
|
3628
|
+
setAttribute(self, 'data-color-presets', colorPresets.join(','));
|
3629
|
+
}
|
3630
|
+
if (colorKeywords) {
|
3631
|
+
setAttribute(self, 'data-color-keywords', colorKeywords.join(','));
|
3632
|
+
}
|
3633
|
+
setTimeout(callback, 0);
|
3634
|
+
} else {
|
3635
|
+
// keep id
|
3636
|
+
// removeAttribute(self, 'data-id');
|
3637
|
+
removeAttribute(self, 'data-value');
|
3638
|
+
removeAttribute(self, 'data-format');
|
3639
|
+
removeAttribute(self, 'data-placeholder');
|
3640
|
+
removeAttribute(self, 'data-component-labels');
|
3641
|
+
removeAttribute(self, 'data-color-labels');
|
3642
|
+
removeAttribute(self, 'data-color-presets');
|
3643
|
+
removeAttribute(self, 'data-color-keywords');
|
3644
|
+
}
|
3645
|
+
}
|
3646
|
+
|
3642
3647
|
let CPID = 0;
|
3643
3648
|
|
3644
3649
|
/**
|
3645
3650
|
* `ColorPickerElement` Web Component.
|
3646
3651
|
* @example
|
3647
3652
|
* <label for="UNIQUE_ID">Label</label>
|
3648
|
-
* <color-picker>
|
3649
|
-
* <input id="UNIQUE_ID" value="red" format="hex" class="color-preview btn-appearance">
|
3653
|
+
* <color-picker data-id="UNIQUE_ID" data-value="red" data-format="hex">
|
3650
3654
|
* </color-picker>
|
3651
3655
|
* // or
|
3652
3656
|
* <label for="UNIQUE_ID">Label</label>
|
@@ -3665,54 +3669,66 @@
|
|
3665
3669
|
get value() { return this.input && this.input.value; }
|
3666
3670
|
|
3667
3671
|
connectedCallback() {
|
3668
|
-
|
3672
|
+
const self = this;
|
3673
|
+
if (self.input) return;
|
3669
3674
|
|
3670
|
-
let
|
3671
|
-
const value =
|
3672
|
-
const format =
|
3673
|
-
|
3675
|
+
let id = getAttribute(self, 'data-id');
|
3676
|
+
const value = getAttribute(self, 'data-value') || '#fff';
|
3677
|
+
const format = getAttribute(self, 'data-format') || 'rgb';
|
3678
|
+
const placeholder = getAttribute(self, 'data-placeholder') || '';
|
3674
3679
|
|
3675
3680
|
if (!id) {
|
3676
3681
|
id = `color-picker-${format}-${CPID}`;
|
3677
3682
|
CPID += 1;
|
3678
3683
|
}
|
3679
3684
|
|
3680
|
-
|
3681
|
-
input
|
3682
|
-
|
3683
|
-
|
3684
|
-
|
3685
|
-
|
3685
|
+
const input = createElement({
|
3686
|
+
tagName: 'input',
|
3687
|
+
type: 'text',
|
3688
|
+
className: 'color-preview btn-appearance',
|
3689
|
+
});
|
3690
|
+
|
3691
|
+
setAttribute(input, 'id', id);
|
3692
|
+
setAttribute(input, 'name', id);
|
3693
|
+
setAttribute(input, 'autocomplete', 'off');
|
3694
|
+
setAttribute(input, 'spellcheck', 'false');
|
3695
|
+
setAttribute(input, 'value', value);
|
3696
|
+
setAttribute(input, 'placeholder', placeholder);
|
3697
|
+
self.append(input);
|
3686
3698
|
|
3687
|
-
setAttribute(input, 'id', id);
|
3688
|
-
setAttribute(input, 'name', id);
|
3689
|
-
setAttribute(input, 'autocomplete', 'off');
|
3690
|
-
setAttribute(input, 'spellcheck', 'false');
|
3691
|
-
setAttribute(input, 'value', value);
|
3692
|
-
this.append(input);
|
3693
|
-
}
|
3694
3699
|
/** @type {HTMLInputElement} */
|
3695
3700
|
// @ts-ignore - `HTMLInputElement` is `HTMLElement`
|
3696
|
-
|
3701
|
+
self.input = input;
|
3697
3702
|
|
3698
3703
|
// @ts-ignore - `HTMLInputElement` is `HTMLElement`
|
3699
|
-
|
3704
|
+
self.colorPicker = new ColorPicker(input);
|
3700
3705
|
|
3701
3706
|
// @ts-ignore - `shadowRoot` is defined in the constructor
|
3702
|
-
|
3707
|
+
self.shadowRoot.append(createElement('slot'));
|
3708
|
+
|
3709
|
+
// remove Attributes
|
3710
|
+
toggleCEAttr(self);
|
3703
3711
|
}
|
3704
3712
|
|
3705
3713
|
/** @this {ColorPickerElement} */
|
3706
3714
|
disconnectedCallback() {
|
3707
|
-
const
|
3708
|
-
|
3709
|
-
|
3710
|
-
|
3711
|
-
|
3712
|
-
|
3713
|
-
colorPicker
|
3714
|
-
|
3715
|
-
|
3715
|
+
const self = this;
|
3716
|
+
const { input, colorPicker, shadowRoot } = self;
|
3717
|
+
|
3718
|
+
const callback = () => {
|
3719
|
+
// remove markup
|
3720
|
+
input.remove();
|
3721
|
+
colorPicker.dispose();
|
3722
|
+
shadowRoot.innerHTML = '';
|
3723
|
+
|
3724
|
+
ObjectAssign(self, {
|
3725
|
+
colorPicker: undefined,
|
3726
|
+
input: undefined,
|
3727
|
+
});
|
3728
|
+
};
|
3729
|
+
|
3730
|
+
// re-add Attributes
|
3731
|
+
toggleCEAttr(self, callback);
|
3716
3732
|
}
|
3717
3733
|
}
|
3718
3734
|
|