@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
|
*/
|
@@ -15,25 +15,6 @@ function getDocument(node) {
|
|
15
15
|
return window.document;
|
16
16
|
}
|
17
17
|
|
18
|
-
/**
|
19
|
-
* A global array of possible `ParentNode`.
|
20
|
-
*/
|
21
|
-
const parentNodes = [Document, Element, HTMLElement];
|
22
|
-
|
23
|
-
/**
|
24
|
-
* Shortcut for `HTMLElement.getElementsByTagName` method. Some `Node` elements
|
25
|
-
* like `ShadowRoot` do not support `getElementsByTagName`.
|
26
|
-
*
|
27
|
-
* @param {string} selector the tag name
|
28
|
-
* @param {(HTMLElement | Element | Document)=} parent optional Element to look into
|
29
|
-
* @return {HTMLCollectionOf<HTMLElement | Element>} the 'HTMLCollection'
|
30
|
-
*/
|
31
|
-
function getElementsByTagName(selector, parent) {
|
32
|
-
const lookUp = parent && parentNodes
|
33
|
-
.some((x) => parent instanceof x) ? parent : getDocument();
|
34
|
-
return lookUp.getElementsByTagName(selector);
|
35
|
-
}
|
36
|
-
|
37
18
|
/**
|
38
19
|
* Shortcut for `Object.assign()` static method.
|
39
20
|
* @param {Record<string, any>} obj a target object
|
@@ -1241,27 +1222,26 @@ const EventRegistry = {};
|
|
1241
1222
|
/**
|
1242
1223
|
* The global event listener.
|
1243
1224
|
*
|
1244
|
-
* @
|
1245
|
-
* @
|
1246
|
-
* @returns {void}
|
1225
|
+
* @type {EventListener}
|
1226
|
+
* @this {EventTarget}
|
1247
1227
|
*/
|
1248
1228
|
function globalListener(e) {
|
1249
1229
|
const that = this;
|
1250
|
-
const { type } = e;
|
1251
|
-
const oneEvMap = EventRegistry[type] ? [...EventRegistry[type]] : [];
|
1230
|
+
const { type, target } = e;
|
1252
1231
|
|
1253
|
-
|
1232
|
+
[...EventRegistry[type]].forEach((elementsMap) => {
|
1254
1233
|
const [element, listenersMap] = elementsMap;
|
1255
|
-
|
1256
|
-
|
1234
|
+
/* istanbul ignore else */
|
1235
|
+
if ([target, that].some((el) => element === el)) {
|
1236
|
+
[...listenersMap].forEach((listenerMap) => {
|
1257
1237
|
const [listener, options] = listenerMap;
|
1258
1238
|
listener.apply(element, [e]);
|
1259
1239
|
|
1260
1240
|
if (options && options.once) {
|
1261
1241
|
removeListener(element, type, listener, options);
|
1262
1242
|
}
|
1263
|
-
}
|
1264
|
-
}
|
1243
|
+
});
|
1244
|
+
}
|
1265
1245
|
});
|
1266
1246
|
}
|
1267
1247
|
|
@@ -1269,10 +1249,7 @@ function globalListener(e) {
|
|
1269
1249
|
* Register a new listener with its options and attach the `globalListener`
|
1270
1250
|
* to the target if this is the first listener.
|
1271
1251
|
*
|
1272
|
-
* @
|
1273
|
-
* @param {string} eventType
|
1274
|
-
* @param {EventListenerObject['handleEvent']} listener
|
1275
|
-
* @param {AddEventListenerOptions=} options
|
1252
|
+
* @type {Listener.ListenerAction<EventTarget>}
|
1276
1253
|
*/
|
1277
1254
|
const addListener = (element, eventType, listener, options) => {
|
1278
1255
|
// get element listeners first
|
@@ -1290,9 +1267,7 @@ const addListener = (element, eventType, listener, options) => {
|
|
1290
1267
|
const { size } = oneElementMap;
|
1291
1268
|
|
1292
1269
|
// register listener with its options
|
1293
|
-
|
1294
|
-
oneElementMap.set(listener, options);
|
1295
|
-
}
|
1270
|
+
oneElementMap.set(listener, options);
|
1296
1271
|
|
1297
1272
|
// add listener last
|
1298
1273
|
if (!size) {
|
@@ -1304,10 +1279,7 @@ const addListener = (element, eventType, listener, options) => {
|
|
1304
1279
|
* Remove a listener from registry and detach the `globalListener`
|
1305
1280
|
* if no listeners are found in the registry.
|
1306
1281
|
*
|
1307
|
-
* @
|
1308
|
-
* @param {string} eventType
|
1309
|
-
* @param {EventListenerObject['handleEvent']} listener
|
1310
|
-
* @param {AddEventListenerOptions=} options
|
1282
|
+
* @type {Listener.ListenerAction<EventTarget>}
|
1311
1283
|
*/
|
1312
1284
|
const removeListener = (element, eventType, listener, options) => {
|
1313
1285
|
// get listener first
|
@@ -1326,6 +1298,7 @@ const removeListener = (element, eventType, listener, options) => {
|
|
1326
1298
|
if (!oneEventMap || !oneEventMap.size) delete EventRegistry[eventType];
|
1327
1299
|
|
1328
1300
|
// remove listener last
|
1301
|
+
/* istanbul ignore else */
|
1329
1302
|
if (!oneElementMap || !oneElementMap.size) {
|
1330
1303
|
element.removeEventListener(eventType, globalListener, eventOptions);
|
1331
1304
|
}
|
@@ -1427,12 +1400,6 @@ const keydownEvent = 'keydown';
|
|
1427
1400
|
*/
|
1428
1401
|
const changeEvent = 'change';
|
1429
1402
|
|
1430
|
-
/**
|
1431
|
-
* A global namespace for `touchstart` event.
|
1432
|
-
* @type {string}
|
1433
|
-
*/
|
1434
|
-
const touchstartEvent = 'touchstart';
|
1435
|
-
|
1436
1403
|
/**
|
1437
1404
|
* A global namespace for `touchmove` event.
|
1438
1405
|
* @type {string}
|
@@ -1440,28 +1407,22 @@ const touchstartEvent = 'touchstart';
|
|
1440
1407
|
const touchmoveEvent = 'touchmove';
|
1441
1408
|
|
1442
1409
|
/**
|
1443
|
-
* A global namespace for `
|
1444
|
-
* @type {string}
|
1445
|
-
*/
|
1446
|
-
const touchendEvent = 'touchend';
|
1447
|
-
|
1448
|
-
/**
|
1449
|
-
* A global namespace for `mousedown` event.
|
1410
|
+
* A global namespace for `pointerdown` event.
|
1450
1411
|
* @type {string}
|
1451
1412
|
*/
|
1452
|
-
const
|
1413
|
+
const pointerdownEvent = 'pointerdown';
|
1453
1414
|
|
1454
1415
|
/**
|
1455
|
-
* A global namespace for `
|
1416
|
+
* A global namespace for `pointermove` event.
|
1456
1417
|
* @type {string}
|
1457
1418
|
*/
|
1458
|
-
const
|
1419
|
+
const pointermoveEvent = 'pointermove';
|
1459
1420
|
|
1460
1421
|
/**
|
1461
|
-
* A global namespace for `
|
1422
|
+
* A global namespace for `pointerup` event.
|
1462
1423
|
* @type {string}
|
1463
1424
|
*/
|
1464
|
-
const
|
1425
|
+
const pointerupEvent = 'pointerup';
|
1465
1426
|
|
1466
1427
|
/**
|
1467
1428
|
* A global namespace for `scroll` event.
|
@@ -1497,27 +1458,6 @@ function getDocumentElement(node) {
|
|
1497
1458
|
return getDocument(node).documentElement;
|
1498
1459
|
}
|
1499
1460
|
|
1500
|
-
/**
|
1501
|
-
* Returns the `Window` object of a target node.
|
1502
|
-
* @see https://github.com/floating-ui/floating-ui
|
1503
|
-
*
|
1504
|
-
* @param {(Node | HTMLElement | Element | Window)=} node target node
|
1505
|
-
* @returns {globalThis}
|
1506
|
-
*/
|
1507
|
-
function getWindow(node) {
|
1508
|
-
if (node == null) {
|
1509
|
-
return window;
|
1510
|
-
}
|
1511
|
-
|
1512
|
-
if (!(node instanceof Window)) {
|
1513
|
-
const { ownerDocument } = node;
|
1514
|
-
return ownerDocument ? ownerDocument.defaultView || window : window;
|
1515
|
-
}
|
1516
|
-
|
1517
|
-
// @ts-ignore
|
1518
|
-
return node;
|
1519
|
-
}
|
1520
|
-
|
1521
1461
|
let elementUID = 0;
|
1522
1462
|
let elementMapUID = 0;
|
1523
1463
|
const elementIDMap = new Map();
|
@@ -1617,6 +1557,11 @@ function getElementTransitionDuration(element) {
|
|
1617
1557
|
return !Number.isNaN(duration) ? duration : 0;
|
1618
1558
|
}
|
1619
1559
|
|
1560
|
+
/**
|
1561
|
+
* A global array of possible `ParentNode`.
|
1562
|
+
*/
|
1563
|
+
const parentNodes = [Document, Element, HTMLElement];
|
1564
|
+
|
1620
1565
|
/**
|
1621
1566
|
* A global array with `Element` | `HTMLElement`.
|
1622
1567
|
*/
|
@@ -2260,17 +2205,16 @@ function getColorMenu(self, colorsSource, menuClass) {
|
|
2260
2205
|
const isOptionsMenu = menuClass === 'color-options';
|
2261
2206
|
const isPalette = colorsSource instanceof ColorPalette;
|
2262
2207
|
const menuLabel = isOptionsMenu ? presetsLabel : defaultsLabel;
|
2263
|
-
|
2264
|
-
colorsArray = colorsArray instanceof Array ? colorsArray : [];
|
2208
|
+
const colorsArray = isPalette ? colorsSource.colors : colorsSource;
|
2265
2209
|
const colorsCount = colorsArray.length;
|
2266
2210
|
const { lightSteps } = isPalette ? colorsSource : { lightSteps: null };
|
2267
|
-
const fit = lightSteps || [9, 10].find((x) => colorsCount
|
2211
|
+
const fit = lightSteps || [9, 10].find((x) => colorsCount >= x * 2 && !(colorsCount % x)) || 5;
|
2268
2212
|
const isMultiLine = isOptionsMenu && colorsCount > fit;
|
2269
2213
|
let rowCountHover = 2;
|
2270
|
-
rowCountHover = isMultiLine && colorsCount
|
2271
|
-
rowCountHover = colorsCount
|
2272
|
-
rowCountHover = colorsCount
|
2273
|
-
const rowCount = rowCountHover - (colorsCount
|
2214
|
+
rowCountHover = isMultiLine && colorsCount > fit * 2 ? 3 : rowCountHover;
|
2215
|
+
rowCountHover = isMultiLine && colorsCount > fit * 3 ? 4 : rowCountHover;
|
2216
|
+
rowCountHover = isMultiLine && colorsCount > fit * 4 ? 5 : rowCountHover;
|
2217
|
+
const rowCount = rowCountHover - (colorsCount <= fit * 3 ? 1 : 2);
|
2274
2218
|
const isScrollable = isMultiLine && colorsCount > rowCount * fit;
|
2275
2219
|
let finalClass = menuClass;
|
2276
2220
|
finalClass += isScrollable ? ' scrollable' : '';
|
@@ -2278,7 +2222,7 @@ function getColorMenu(self, colorsSource, menuClass) {
|
|
2278
2222
|
const gap = isMultiLine ? '1px' : '0.25rem';
|
2279
2223
|
let optionSize = isMultiLine ? 1.75 : 2;
|
2280
2224
|
optionSize = fit > 5 && isMultiLine ? 1.5 : optionSize;
|
2281
|
-
const menuHeight = `${
|
2225
|
+
const menuHeight = `${rowCount * optionSize}rem`;
|
2282
2226
|
const menuHeightHover = `calc(${rowCountHover} * ${optionSize}rem + ${rowCountHover - 1} * ${gap})`;
|
2283
2227
|
/** @type {HTMLUListElement} */
|
2284
2228
|
// @ts-ignore -- <UL> is an `HTMLElement`
|
@@ -2385,16 +2329,14 @@ function setMarkup(self) {
|
|
2385
2329
|
});
|
2386
2330
|
|
2387
2331
|
// color presets
|
2388
|
-
if (
|
2389
|
-
|
2390
|
-
const presetsMenu = getColorMenu(self, colorPresets, 'color-options');
|
2391
|
-
presetsDropdown.append(presetsMenu);
|
2332
|
+
if (colorPresets) {
|
2333
|
+
presetsDropdown.append(getColorMenu(self, colorPresets, 'color-options'));
|
2392
2334
|
}
|
2393
2335
|
|
2394
2336
|
// explicit defaults [reset, initial, inherit, transparent, currentColor]
|
2337
|
+
// also custom defaults [default: #069, complementary: #930]
|
2395
2338
|
if (colorKeywords && colorKeywords.length) {
|
2396
|
-
|
2397
|
-
presetsDropdown.append(keywordsMenu);
|
2339
|
+
presetsDropdown.append(getColorMenu(self, colorKeywords, 'color-defaults'));
|
2398
2340
|
}
|
2399
2341
|
|
2400
2342
|
const presetsBtn = createElement({
|
@@ -2431,7 +2373,7 @@ function setMarkup(self) {
|
|
2431
2373
|
setAttribute(input, tabIndex, '-1');
|
2432
2374
|
}
|
2433
2375
|
|
2434
|
-
var version = "0.0
|
2376
|
+
var version = "1.0.0";
|
2435
2377
|
|
2436
2378
|
// @ts-ignore
|
2437
2379
|
|
@@ -2453,7 +2395,7 @@ const colorPickerDefaults = {
|
|
2453
2395
|
// ColorPicker Static Methods
|
2454
2396
|
// ==========================
|
2455
2397
|
|
2456
|
-
/** @type {CP.GetInstance<ColorPicker>} */
|
2398
|
+
/** @type {CP.GetInstance<ColorPicker, HTMLInputElement>} */
|
2457
2399
|
const getColorPickerInstance = (element) => getInstance(element, colorPickerString);
|
2458
2400
|
|
2459
2401
|
/** @type {CP.InitCallback<ColorPicker>} */
|
@@ -2488,12 +2430,10 @@ function toggleEventsOnShown(self, action) {
|
|
2488
2430
|
const fn = action ? addListener : removeListener;
|
2489
2431
|
const { input, colorMenu, parent } = self;
|
2490
2432
|
const doc = getDocument(input);
|
2491
|
-
const win = getWindow(input);
|
2492
|
-
const
|
2493
|
-
? { down: touchstartEvent, move: touchmoveEvent, up: touchendEvent }
|
2494
|
-
: { down: mousedownEvent, move: mousemoveEvent, up: mouseupEvent };
|
2433
|
+
// const win = getWindow(input);
|
2434
|
+
const win = doc.defaultView;
|
2495
2435
|
|
2496
|
-
fn(self.controls,
|
2436
|
+
fn(self.controls, pointerdownEvent, self.pointerDown);
|
2497
2437
|
self.controlKnobs.forEach((x) => fn(x, keydownEvent, self.handleKnobs));
|
2498
2438
|
|
2499
2439
|
// @ts-ignore -- this is `Window`
|
@@ -2508,8 +2448,8 @@ function toggleEventsOnShown(self, action) {
|
|
2508
2448
|
fn(colorMenu, keydownEvent, self.menuKeyHandler);
|
2509
2449
|
}
|
2510
2450
|
|
2511
|
-
fn(doc,
|
2512
|
-
fn(doc,
|
2451
|
+
fn(doc, pointermoveEvent, self.pointerMove);
|
2452
|
+
fn(doc, pointerupEvent, self.pointerUp);
|
2513
2453
|
fn(parent, focusoutEvent, self.handleFocusOut);
|
2514
2454
|
fn(doc, keyupEvent, self.handleDismiss);
|
2515
2455
|
}
|
@@ -2528,6 +2468,7 @@ function firePickerChange(self) {
|
|
2528
2468
|
* @returns {void}
|
2529
2469
|
*/
|
2530
2470
|
function removePosition(element) {
|
2471
|
+
/* istanbul ignore else */
|
2531
2472
|
if (element) {
|
2532
2473
|
['bottom', 'top'].forEach((x) => removeClass(element, x));
|
2533
2474
|
}
|
@@ -2630,6 +2571,7 @@ class ColorPicker {
|
|
2630
2571
|
} = normalizeOptions(this.isCE ? parent : input, colorPickerDefaults, config || {});
|
2631
2572
|
|
2632
2573
|
let translatedColorLabels = colorNames;
|
2574
|
+
/* istanbul ignore else */
|
2633
2575
|
if (colorLabels instanceof Array && colorLabels.length === 17) {
|
2634
2576
|
translatedColorLabels = colorLabels;
|
2635
2577
|
} else if (colorLabels && colorLabels.split(',').length === 17) {
|
@@ -2646,7 +2588,7 @@ class ColorPicker {
|
|
2646
2588
|
? JSON.parse(componentLabels) : componentLabels;
|
2647
2589
|
|
2648
2590
|
/** @type {Record<string, string>} */
|
2649
|
-
self.componentLabels = ObjectAssign(colorPickerLabels, tempComponentLabels);
|
2591
|
+
self.componentLabels = ObjectAssign({ ...colorPickerLabels }, tempComponentLabels);
|
2650
2592
|
|
2651
2593
|
/** @type {Color} */
|
2652
2594
|
self.color = new Color(input.value || '#fff', format);
|
@@ -2655,14 +2597,14 @@ class ColorPicker {
|
|
2655
2597
|
self.format = format;
|
2656
2598
|
|
2657
2599
|
// set colour defaults
|
2658
|
-
if (colorKeywords instanceof Array) {
|
2600
|
+
if (colorKeywords instanceof Array && colorKeywords.length) {
|
2659
2601
|
self.colorKeywords = colorKeywords;
|
2660
2602
|
} else if (typeof colorKeywords === 'string' && colorKeywords.length) {
|
2661
2603
|
self.colorKeywords = colorKeywords.split(',').map((x) => x.trim());
|
2662
2604
|
}
|
2663
2605
|
|
2664
2606
|
// set colour presets
|
2665
|
-
if (colorPresets instanceof Array) {
|
2607
|
+
if (colorPresets instanceof Array && colorPresets.length) {
|
2666
2608
|
self.colorPresets = colorPresets;
|
2667
2609
|
} else if (typeof colorPresets === 'string' && colorPresets.length) {
|
2668
2610
|
if (isValidJSON(colorPresets)) {
|
@@ -2793,6 +2735,7 @@ class ColorPicker {
|
|
2793
2735
|
let colorName;
|
2794
2736
|
|
2795
2737
|
// determine color appearance
|
2738
|
+
/* istanbul ignore else */
|
2796
2739
|
if (lightness === 100 && saturation === 0) {
|
2797
2740
|
colorName = colorLabels.white;
|
2798
2741
|
} else if (lightness === 0) {
|
@@ -2893,13 +2836,14 @@ class ColorPicker {
|
|
2893
2836
|
const self = this;
|
2894
2837
|
const { activeElement } = getDocument(self.input);
|
2895
2838
|
|
2896
|
-
|
2839
|
+
self.updateDropdownPosition();
|
2840
|
+
|
2841
|
+
/* istanbul ignore next */
|
2842
|
+
if (([pointermoveEvent, touchmoveEvent].includes(e.type) && self.dragElement)
|
2897
2843
|
|| (activeElement && self.controlKnobs.includes(activeElement))) {
|
2898
2844
|
e.stopPropagation();
|
2899
2845
|
e.preventDefault();
|
2900
2846
|
}
|
2901
|
-
|
2902
|
-
self.updateDropdownPosition();
|
2903
2847
|
}
|
2904
2848
|
|
2905
2849
|
/**
|
@@ -2973,7 +2917,9 @@ class ColorPicker {
|
|
2973
2917
|
|
2974
2918
|
self.update();
|
2975
2919
|
|
2920
|
+
/* istanbul ignore else */
|
2976
2921
|
if (currentActive !== target) {
|
2922
|
+
/* istanbul ignore else */
|
2977
2923
|
if (currentActive) {
|
2978
2924
|
removeClass(currentActive, 'active');
|
2979
2925
|
removeAttribute(currentActive, ariaSelected);
|
@@ -2991,15 +2937,13 @@ class ColorPicker {
|
|
2991
2937
|
|
2992
2938
|
/**
|
2993
2939
|
* The `ColorPicker` *touchstart* / *mousedown* events listener for control knobs.
|
2994
|
-
* @param {
|
2940
|
+
* @param {PointerEvent} e
|
2995
2941
|
* @this {ColorPicker}
|
2996
2942
|
*/
|
2997
2943
|
pointerDown(e) {
|
2998
2944
|
const self = this;
|
2999
2945
|
/** @type {*} */
|
3000
|
-
const {
|
3001
|
-
type, target, touches, pageX, pageY,
|
3002
|
-
} = e;
|
2946
|
+
const { target, pageX, pageY } = e;
|
3003
2947
|
const { colorMenu, visuals, controlKnobs } = self;
|
3004
2948
|
const [v1, v2, v3] = visuals;
|
3005
2949
|
const [c1, c2, c3] = controlKnobs;
|
@@ -3007,11 +2951,10 @@ class ColorPicker {
|
|
3007
2951
|
const visual = controlKnobs.includes(target) ? target.previousElementSibling : target;
|
3008
2952
|
const visualRect = getBoundingClientRect(visual);
|
3009
2953
|
const html = getDocumentElement(v1);
|
3010
|
-
const
|
3011
|
-
const
|
3012
|
-
const offsetX = X - html.scrollLeft - visualRect.left;
|
3013
|
-
const offsetY = Y - html.scrollTop - visualRect.top;
|
2954
|
+
const offsetX = pageX - html.scrollLeft - visualRect.left;
|
2955
|
+
const offsetY = pageY - html.scrollTop - visualRect.top;
|
3014
2956
|
|
2957
|
+
/* istanbul ignore else */
|
3015
2958
|
if (target === v1 || target === c1) {
|
3016
2959
|
self.dragElement = visual;
|
3017
2960
|
self.changeControl1(offsetX, offsetY);
|
@@ -3035,7 +2978,7 @@ class ColorPicker {
|
|
3035
2978
|
|
3036
2979
|
/**
|
3037
2980
|
* The `ColorPicker` *touchend* / *mouseup* events listener for control knobs.
|
3038
|
-
* @param {
|
2981
|
+
* @param {PointerEvent} e
|
3039
2982
|
* @this {ColorPicker}
|
3040
2983
|
*/
|
3041
2984
|
pointerUp({ target }) {
|
@@ -3044,9 +2987,8 @@ class ColorPicker {
|
|
3044
2987
|
const doc = getDocument(parent);
|
3045
2988
|
const currentOpen = querySelector(`${colorPickerParentSelector}.open`, doc) !== null;
|
3046
2989
|
const selection = doc.getSelection();
|
3047
|
-
|
2990
|
+
|
3048
2991
|
if (!self.dragElement && !selection.toString().length
|
3049
|
-
// @ts-ignore
|
3050
2992
|
&& !parent.contains(target)) {
|
3051
2993
|
self.hide(currentOpen);
|
3052
2994
|
}
|
@@ -3056,25 +2998,20 @@ class ColorPicker {
|
|
3056
2998
|
|
3057
2999
|
/**
|
3058
3000
|
* The `ColorPicker` *touchmove* / *mousemove* events listener for control knobs.
|
3059
|
-
* @param {
|
3001
|
+
* @param {PointerEvent} e
|
3060
3002
|
*/
|
3061
3003
|
pointerMove(e) {
|
3062
3004
|
const self = this;
|
3063
3005
|
const { dragElement, visuals } = self;
|
3064
3006
|
const [v1, v2, v3] = visuals;
|
3065
|
-
const {
|
3066
|
-
// @ts-ignore
|
3067
|
-
type, touches, pageX, pageY,
|
3068
|
-
} = e;
|
3007
|
+
const { pageX, pageY } = e;
|
3069
3008
|
|
3070
3009
|
if (!dragElement) return;
|
3071
3010
|
|
3072
3011
|
const controlRect = getBoundingClientRect(dragElement);
|
3073
3012
|
const win = getDocumentElement(v1);
|
3074
|
-
const
|
3075
|
-
const
|
3076
|
-
const offsetX = X - win.scrollLeft - controlRect.left;
|
3077
|
-
const offsetY = Y - win.scrollTop - controlRect.top;
|
3013
|
+
const offsetX = pageX - win.scrollLeft - controlRect.left;
|
3014
|
+
const offsetY = pageY - win.scrollTop - controlRect.top;
|
3078
3015
|
|
3079
3016
|
if (dragElement === v1) {
|
3080
3017
|
self.changeControl1(offsetX, offsetY);
|
@@ -3108,13 +3045,16 @@ class ColorPicker {
|
|
3108
3045
|
const currentKnob = controlKnobs.find((x) => x === activeElement);
|
3109
3046
|
const yRatio = offsetHeight / 360;
|
3110
3047
|
|
3048
|
+
/* istanbul ignore else */
|
3111
3049
|
if (currentKnob) {
|
3112
3050
|
let offsetX = 0;
|
3113
3051
|
let offsetY = 0;
|
3114
3052
|
|
3053
|
+
/* istanbul ignore else */
|
3115
3054
|
if (target === c1) {
|
3116
3055
|
const xRatio = offsetWidth / 100;
|
3117
3056
|
|
3057
|
+
/* istanbul ignore else */
|
3118
3058
|
if ([keyArrowLeft, keyArrowRight].includes(code)) {
|
3119
3059
|
self.controlPositions.c1x += code === keyArrowRight ? xRatio : -xRatio;
|
3120
3060
|
} else if ([keyArrowUp, keyArrowDown].includes(code)) {
|
@@ -3160,6 +3100,7 @@ class ColorPicker {
|
|
3160
3100
|
const isNonColorValue = self.hasNonColor && nonColors.includes(currentValue);
|
3161
3101
|
const alpha = i4 ? v4 : (1 - controlPositions.c3y / offsetHeight);
|
3162
3102
|
|
3103
|
+
/* istanbul ignore else */
|
3163
3104
|
if (activeElement === input || (activeElement && inputs.includes(activeElement))) {
|
3164
3105
|
if (activeElement === input) {
|
3165
3106
|
if (isNonColorValue) {
|
@@ -3474,6 +3415,7 @@ class ColorPicker {
|
|
3474
3415
|
const hue = roundPart(hsl.h * 360);
|
3475
3416
|
let newColor;
|
3476
3417
|
|
3418
|
+
/* istanbul ignore else */
|
3477
3419
|
if (format === 'hex') {
|
3478
3420
|
newColor = self.color.toHexString(true);
|
3479
3421
|
i1.value = self.hex;
|
@@ -3574,15 +3516,15 @@ class ColorPicker {
|
|
3574
3516
|
const relatedBtn = openPicker ? pickerToggle : menuToggle;
|
3575
3517
|
const animationDuration = openDropdown && getElementTransitionDuration(openDropdown);
|
3576
3518
|
|
3577
|
-
// if (!self.isValid) {
|
3578
3519
|
self.value = self.color.toString(true);
|
3579
|
-
// }
|
3580
3520
|
|
3521
|
+
/* istanbul ignore else */
|
3581
3522
|
if (openDropdown) {
|
3582
3523
|
removeClass(openDropdown, 'show');
|
3583
3524
|
setAttribute(relatedBtn, ariaExpanded, 'false');
|
3584
3525
|
setTimeout(() => {
|
3585
3526
|
removePosition(openDropdown);
|
3527
|
+
/* istanbul ignore else */
|
3586
3528
|
if (!querySelector('.show', parent)) {
|
3587
3529
|
removeClass(parent, 'open');
|
3588
3530
|
toggleEventsOnShown(self);
|
@@ -3595,7 +3537,7 @@ class ColorPicker {
|
|
3595
3537
|
focus(pickerToggle);
|
3596
3538
|
}
|
3597
3539
|
setAttribute(input, tabIndex, '-1');
|
3598
|
-
if (menuToggle) {
|
3540
|
+
if (relatedBtn === menuToggle) {
|
3599
3541
|
setAttribute(menuToggle, tabIndex, '-1');
|
3600
3542
|
}
|
3601
3543
|
}
|
@@ -3633,14 +3575,76 @@ ObjectAssign(ColorPicker, {
|
|
3633
3575
|
getBoundingClientRect,
|
3634
3576
|
});
|
3635
3577
|
|
3578
|
+
/**
|
3579
|
+
* A small utility to toggle `ColorPickerElement` attributes
|
3580
|
+
* when `connectedCallback` or `disconnectedCallback` methods
|
3581
|
+
* are called and helps the instance keep its value and settings instact.
|
3582
|
+
*
|
3583
|
+
* @param {CP.ColorPickerElement} self ColorPickerElement instance
|
3584
|
+
* @param {Function=} callback when `true`, attributes are added
|
3585
|
+
*
|
3586
|
+
* @example
|
3587
|
+
* const attributes = [
|
3588
|
+
* // essentials
|
3589
|
+
* 'value', 'format',
|
3590
|
+
* // presets menus
|
3591
|
+
* 'color-presets', 'color-keywords',
|
3592
|
+
* // labels
|
3593
|
+
* 'color-labels', 'component-labels',
|
3594
|
+
* ];
|
3595
|
+
*/
|
3596
|
+
function toggleCEAttr(self, callback) {
|
3597
|
+
if (callback) {
|
3598
|
+
const { input, colorPicker } = self;
|
3599
|
+
|
3600
|
+
const {
|
3601
|
+
value, format, colorPresets, colorKeywords, componentLabels, colorLabels,
|
3602
|
+
} = colorPicker;
|
3603
|
+
|
3604
|
+
const { id, placeholder } = input;
|
3605
|
+
|
3606
|
+
setAttribute(self, 'data-id', id);
|
3607
|
+
setAttribute(self, 'data-value', value);
|
3608
|
+
setAttribute(self, 'data-format', format);
|
3609
|
+
setAttribute(self, 'data-placeholder', placeholder);
|
3610
|
+
|
3611
|
+
if (ObjectKeys(colorPickerLabels).some((l) => colorPickerLabels[l] !== componentLabels[l])) {
|
3612
|
+
setAttribute(self, 'data-component-labels', JSON.stringify(componentLabels));
|
3613
|
+
}
|
3614
|
+
if (!colorNames.every((c) => c === colorLabels[c])) {
|
3615
|
+
setAttribute(self, 'data-color-labels', colorNames.map((n) => colorLabels[n]).join(','));
|
3616
|
+
}
|
3617
|
+
if (colorPresets instanceof ColorPalette) {
|
3618
|
+
const { hue, hueSteps, lightSteps } = colorPresets;
|
3619
|
+
setAttribute(self, 'data-color-presets', JSON.stringify({ hue, hueSteps, lightSteps }));
|
3620
|
+
}
|
3621
|
+
if (Array.isArray(colorPresets) && colorPresets.length) {
|
3622
|
+
setAttribute(self, 'data-color-presets', colorPresets.join(','));
|
3623
|
+
}
|
3624
|
+
if (colorKeywords) {
|
3625
|
+
setAttribute(self, 'data-color-keywords', colorKeywords.join(','));
|
3626
|
+
}
|
3627
|
+
setTimeout(callback, 0);
|
3628
|
+
} else {
|
3629
|
+
// keep id
|
3630
|
+
// removeAttribute(self, 'data-id');
|
3631
|
+
removeAttribute(self, 'data-value');
|
3632
|
+
removeAttribute(self, 'data-format');
|
3633
|
+
removeAttribute(self, 'data-placeholder');
|
3634
|
+
removeAttribute(self, 'data-component-labels');
|
3635
|
+
removeAttribute(self, 'data-color-labels');
|
3636
|
+
removeAttribute(self, 'data-color-presets');
|
3637
|
+
removeAttribute(self, 'data-color-keywords');
|
3638
|
+
}
|
3639
|
+
}
|
3640
|
+
|
3636
3641
|
let CPID = 0;
|
3637
3642
|
|
3638
3643
|
/**
|
3639
3644
|
* `ColorPickerElement` Web Component.
|
3640
3645
|
* @example
|
3641
3646
|
* <label for="UNIQUE_ID">Label</label>
|
3642
|
-
* <color-picker>
|
3643
|
-
* <input id="UNIQUE_ID" value="red" format="hex" class="color-preview btn-appearance">
|
3647
|
+
* <color-picker data-id="UNIQUE_ID" data-value="red" data-format="hex">
|
3644
3648
|
* </color-picker>
|
3645
3649
|
* // or
|
3646
3650
|
* <label for="UNIQUE_ID">Label</label>
|
@@ -3659,54 +3663,66 @@ class ColorPickerElement extends HTMLElement {
|
|
3659
3663
|
get value() { return this.input && this.input.value; }
|
3660
3664
|
|
3661
3665
|
connectedCallback() {
|
3662
|
-
|
3666
|
+
const self = this;
|
3667
|
+
if (self.input) return;
|
3663
3668
|
|
3664
|
-
let
|
3665
|
-
const value =
|
3666
|
-
const format =
|
3667
|
-
|
3669
|
+
let id = getAttribute(self, 'data-id');
|
3670
|
+
const value = getAttribute(self, 'data-value') || '#fff';
|
3671
|
+
const format = getAttribute(self, 'data-format') || 'rgb';
|
3672
|
+
const placeholder = getAttribute(self, 'data-placeholder') || '';
|
3668
3673
|
|
3669
3674
|
if (!id) {
|
3670
3675
|
id = `color-picker-${format}-${CPID}`;
|
3671
3676
|
CPID += 1;
|
3672
3677
|
}
|
3673
3678
|
|
3674
|
-
|
3675
|
-
input
|
3676
|
-
|
3677
|
-
|
3678
|
-
|
3679
|
-
|
3679
|
+
const input = createElement({
|
3680
|
+
tagName: 'input',
|
3681
|
+
type: 'text',
|
3682
|
+
className: 'color-preview btn-appearance',
|
3683
|
+
});
|
3684
|
+
|
3685
|
+
setAttribute(input, 'id', id);
|
3686
|
+
setAttribute(input, 'name', id);
|
3687
|
+
setAttribute(input, 'autocomplete', 'off');
|
3688
|
+
setAttribute(input, 'spellcheck', 'false');
|
3689
|
+
setAttribute(input, 'value', value);
|
3690
|
+
setAttribute(input, 'placeholder', placeholder);
|
3691
|
+
self.append(input);
|
3680
3692
|
|
3681
|
-
setAttribute(input, 'id', id);
|
3682
|
-
setAttribute(input, 'name', id);
|
3683
|
-
setAttribute(input, 'autocomplete', 'off');
|
3684
|
-
setAttribute(input, 'spellcheck', 'false');
|
3685
|
-
setAttribute(input, 'value', value);
|
3686
|
-
this.append(input);
|
3687
|
-
}
|
3688
3693
|
/** @type {HTMLInputElement} */
|
3689
3694
|
// @ts-ignore - `HTMLInputElement` is `HTMLElement`
|
3690
|
-
|
3695
|
+
self.input = input;
|
3691
3696
|
|
3692
3697
|
// @ts-ignore - `HTMLInputElement` is `HTMLElement`
|
3693
|
-
|
3698
|
+
self.colorPicker = new ColorPicker(input);
|
3694
3699
|
|
3695
3700
|
// @ts-ignore - `shadowRoot` is defined in the constructor
|
3696
|
-
|
3701
|
+
self.shadowRoot.append(createElement('slot'));
|
3702
|
+
|
3703
|
+
// remove Attributes
|
3704
|
+
toggleCEAttr(self);
|
3697
3705
|
}
|
3698
3706
|
|
3699
3707
|
/** @this {ColorPickerElement} */
|
3700
3708
|
disconnectedCallback() {
|
3701
|
-
const
|
3702
|
-
|
3703
|
-
|
3704
|
-
|
3705
|
-
|
3706
|
-
|
3707
|
-
colorPicker
|
3708
|
-
|
3709
|
-
|
3709
|
+
const self = this;
|
3710
|
+
const { input, colorPicker, shadowRoot } = self;
|
3711
|
+
|
3712
|
+
const callback = () => {
|
3713
|
+
// remove markup
|
3714
|
+
input.remove();
|
3715
|
+
colorPicker.dispose();
|
3716
|
+
shadowRoot.innerHTML = '';
|
3717
|
+
|
3718
|
+
ObjectAssign(self, {
|
3719
|
+
colorPicker: undefined,
|
3720
|
+
input: undefined,
|
3721
|
+
});
|
3722
|
+
};
|
3723
|
+
|
3724
|
+
// re-add Attributes
|
3725
|
+
toggleCEAttr(self, callback);
|
3710
3726
|
}
|
3711
3727
|
}
|
3712
3728
|
|