@thednp/color-picker 0.0.2-alpha5 → 1.0.1
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 +21 -19
- 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 +2 -5
- package/dist/js/color-esm.min.js +1 -1
- package/dist/js/color-palette-esm.js +2 -5
- package/dist/js/color-palette-esm.min.js +1 -1
- package/dist/js/color-palette.js +2 -5
- package/dist/js/color-palette.min.js +1 -1
- package/dist/js/color-picker-element-esm.js +184 -189
- package/dist/js/color-picker-element-esm.min.js +2 -2
- package/dist/js/color-picker-element.js +184 -189
- package/dist/js/color-picker-element.min.js +2 -2
- package/dist/js/color-picker-esm.js +77 -134
- package/dist/js/color-picker-esm.min.js +2 -2
- package/dist/js/color-picker.js +77 -134
- package/dist/js/color-picker.min.js +2 -2
- package/dist/js/color.js +2 -5
- package/dist/js/color.min.js +1 -1
- package/package.json +20 -19
- package/src/js/color-picker-element.js +45 -37
- package/src/js/color-picker.js +46 -60
- package/src/js/color.js +1 -4
- package/src/js/index.js +5 -0
- 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/js/util/version.js +0 -1
- package/src/js/version.js +0 -1
- package/src/scss/_variables.scss +7 -0
- package/src/scss/color-picker.scss +86 -45
- package/types/cp.d.ts +31 -17
- package/types/index.d.ts +0 -4
- package/types/source/source.ts +0 -1
- package/types/source/types.d.ts +8 -6
@@ -1,5 +1,5 @@
|
|
1
1
|
/*!
|
2
|
-
* ColorPickerElement
|
2
|
+
* ColorPickerElement v1.0.1 (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
|
@@ -775,7 +756,7 @@
|
|
775
756
|
format = 'hwb';
|
776
757
|
}
|
777
758
|
if (isValidCSSUnit(color.a)) {
|
778
|
-
a = color.a;
|
759
|
+
a = color.a;
|
779
760
|
a = isPercentage(`${a}`) || parseFloat(a) > 1 ? bound01(a, 100) : a;
|
780
761
|
}
|
781
762
|
}
|
@@ -786,9 +767,6 @@
|
|
786
767
|
return {
|
787
768
|
ok,
|
788
769
|
format,
|
789
|
-
// r: Math.min(255, Math.max(rgb.r, 0)),
|
790
|
-
// g: Math.min(255, Math.max(rgb.g, 0)),
|
791
|
-
// b: Math.min(255, Math.max(rgb.b, 0)),
|
792
770
|
r: rgb.r,
|
793
771
|
g: rgb.g,
|
794
772
|
b: rgb.b,
|
@@ -1247,27 +1225,26 @@
|
|
1247
1225
|
/**
|
1248
1226
|
* The global event listener.
|
1249
1227
|
*
|
1250
|
-
* @
|
1251
|
-
* @
|
1252
|
-
* @returns {void}
|
1228
|
+
* @type {EventListener}
|
1229
|
+
* @this {EventTarget}
|
1253
1230
|
*/
|
1254
1231
|
function globalListener(e) {
|
1255
1232
|
const that = this;
|
1256
1233
|
const { type } = e;
|
1257
|
-
const oneEvMap = EventRegistry[type] ? [...EventRegistry[type]] : [];
|
1258
1234
|
|
1259
|
-
|
1235
|
+
[...EventRegistry[type]].forEach((elementsMap) => {
|
1260
1236
|
const [element, listenersMap] = elementsMap;
|
1261
|
-
|
1262
|
-
|
1237
|
+
/* istanbul ignore else */
|
1238
|
+
if (element === that) {
|
1239
|
+
[...listenersMap].forEach((listenerMap) => {
|
1263
1240
|
const [listener, options] = listenerMap;
|
1264
1241
|
listener.apply(element, [e]);
|
1265
1242
|
|
1266
1243
|
if (options && options.once) {
|
1267
1244
|
removeListener(element, type, listener, options);
|
1268
1245
|
}
|
1269
|
-
}
|
1270
|
-
}
|
1246
|
+
});
|
1247
|
+
}
|
1271
1248
|
});
|
1272
1249
|
}
|
1273
1250
|
|
@@ -1275,10 +1252,7 @@
|
|
1275
1252
|
* Register a new listener with its options and attach the `globalListener`
|
1276
1253
|
* to the target if this is the first listener.
|
1277
1254
|
*
|
1278
|
-
* @
|
1279
|
-
* @param {string} eventType
|
1280
|
-
* @param {EventListenerObject['handleEvent']} listener
|
1281
|
-
* @param {AddEventListenerOptions=} options
|
1255
|
+
* @type {Listener.ListenerAction<EventTarget>}
|
1282
1256
|
*/
|
1283
1257
|
const addListener = (element, eventType, listener, options) => {
|
1284
1258
|
// get element listeners first
|
@@ -1296,9 +1270,7 @@
|
|
1296
1270
|
const { size } = oneElementMap;
|
1297
1271
|
|
1298
1272
|
// register listener with its options
|
1299
|
-
|
1300
|
-
oneElementMap.set(listener, options);
|
1301
|
-
}
|
1273
|
+
oneElementMap.set(listener, options);
|
1302
1274
|
|
1303
1275
|
// add listener last
|
1304
1276
|
if (!size) {
|
@@ -1310,10 +1282,7 @@
|
|
1310
1282
|
* Remove a listener from registry and detach the `globalListener`
|
1311
1283
|
* if no listeners are found in the registry.
|
1312
1284
|
*
|
1313
|
-
* @
|
1314
|
-
* @param {string} eventType
|
1315
|
-
* @param {EventListenerObject['handleEvent']} listener
|
1316
|
-
* @param {AddEventListenerOptions=} options
|
1285
|
+
* @type {Listener.ListenerAction<EventTarget>}
|
1317
1286
|
*/
|
1318
1287
|
const removeListener = (element, eventType, listener, options) => {
|
1319
1288
|
// get listener first
|
@@ -1332,6 +1301,7 @@
|
|
1332
1301
|
if (!oneEventMap || !oneEventMap.size) delete EventRegistry[eventType];
|
1333
1302
|
|
1334
1303
|
// remove listener last
|
1304
|
+
/* istanbul ignore else */
|
1335
1305
|
if (!oneElementMap || !oneElementMap.size) {
|
1336
1306
|
element.removeEventListener(eventType, globalListener, eventOptions);
|
1337
1307
|
}
|
@@ -1433,12 +1403,6 @@
|
|
1433
1403
|
*/
|
1434
1404
|
const changeEvent = 'change';
|
1435
1405
|
|
1436
|
-
/**
|
1437
|
-
* A global namespace for `touchstart` event.
|
1438
|
-
* @type {string}
|
1439
|
-
*/
|
1440
|
-
const touchstartEvent = 'touchstart';
|
1441
|
-
|
1442
1406
|
/**
|
1443
1407
|
* A global namespace for `touchmove` event.
|
1444
1408
|
* @type {string}
|
@@ -1446,28 +1410,22 @@
|
|
1446
1410
|
const touchmoveEvent = 'touchmove';
|
1447
1411
|
|
1448
1412
|
/**
|
1449
|
-
* A global namespace for `
|
1413
|
+
* A global namespace for `pointerdown` event.
|
1450
1414
|
* @type {string}
|
1451
1415
|
*/
|
1452
|
-
const
|
1416
|
+
const pointerdownEvent = 'pointerdown';
|
1453
1417
|
|
1454
1418
|
/**
|
1455
|
-
* A global namespace for `
|
1419
|
+
* A global namespace for `pointermove` event.
|
1456
1420
|
* @type {string}
|
1457
1421
|
*/
|
1458
|
-
const
|
1422
|
+
const pointermoveEvent = 'pointermove';
|
1459
1423
|
|
1460
1424
|
/**
|
1461
|
-
* A global namespace for `
|
1425
|
+
* A global namespace for `pointerup` event.
|
1462
1426
|
* @type {string}
|
1463
1427
|
*/
|
1464
|
-
const
|
1465
|
-
|
1466
|
-
/**
|
1467
|
-
* A global namespace for `mouseup` event.
|
1468
|
-
* @type {string}
|
1469
|
-
*/
|
1470
|
-
const mouseupEvent = 'mouseup';
|
1428
|
+
const pointerupEvent = 'pointerup';
|
1471
1429
|
|
1472
1430
|
/**
|
1473
1431
|
* A global namespace for `scroll` event.
|
@@ -1503,27 +1461,6 @@
|
|
1503
1461
|
return getDocument(node).documentElement;
|
1504
1462
|
}
|
1505
1463
|
|
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
1464
|
let elementUID = 0;
|
1528
1465
|
let elementMapUID = 0;
|
1529
1466
|
const elementIDMap = new Map();
|
@@ -1623,6 +1560,11 @@
|
|
1623
1560
|
return !Number.isNaN(duration) ? duration : 0;
|
1624
1561
|
}
|
1625
1562
|
|
1563
|
+
/**
|
1564
|
+
* A global array of possible `ParentNode`.
|
1565
|
+
*/
|
1566
|
+
const parentNodes = [Document, Element, HTMLElement];
|
1567
|
+
|
1626
1568
|
/**
|
1627
1569
|
* A global array with `Element` | `HTMLElement`.
|
1628
1570
|
*/
|
@@ -2266,17 +2208,16 @@
|
|
2266
2208
|
const isOptionsMenu = menuClass === 'color-options';
|
2267
2209
|
const isPalette = colorsSource instanceof ColorPalette;
|
2268
2210
|
const menuLabel = isOptionsMenu ? presetsLabel : defaultsLabel;
|
2269
|
-
|
2270
|
-
colorsArray = colorsArray instanceof Array ? colorsArray : [];
|
2211
|
+
const colorsArray = isPalette ? colorsSource.colors : colorsSource;
|
2271
2212
|
const colorsCount = colorsArray.length;
|
2272
2213
|
const { lightSteps } = isPalette ? colorsSource : { lightSteps: null };
|
2273
|
-
const fit = lightSteps || [9, 10].find((x) => colorsCount
|
2214
|
+
const fit = lightSteps || [9, 10].find((x) => colorsCount >= x * 2 && !(colorsCount % x)) || 5;
|
2274
2215
|
const isMultiLine = isOptionsMenu && colorsCount > fit;
|
2275
2216
|
let rowCountHover = 2;
|
2276
|
-
rowCountHover = isMultiLine && colorsCount
|
2277
|
-
rowCountHover = colorsCount
|
2278
|
-
rowCountHover = colorsCount
|
2279
|
-
const rowCount = rowCountHover - (colorsCount
|
2217
|
+
rowCountHover = isMultiLine && colorsCount > fit * 2 ? 3 : rowCountHover;
|
2218
|
+
rowCountHover = isMultiLine && colorsCount > fit * 3 ? 4 : rowCountHover;
|
2219
|
+
rowCountHover = isMultiLine && colorsCount > fit * 4 ? 5 : rowCountHover;
|
2220
|
+
const rowCount = rowCountHover - (colorsCount <= fit * 3 ? 1 : 2);
|
2280
2221
|
const isScrollable = isMultiLine && colorsCount > rowCount * fit;
|
2281
2222
|
let finalClass = menuClass;
|
2282
2223
|
finalClass += isScrollable ? ' scrollable' : '';
|
@@ -2284,7 +2225,7 @@
|
|
2284
2225
|
const gap = isMultiLine ? '1px' : '0.25rem';
|
2285
2226
|
let optionSize = isMultiLine ? 1.75 : 2;
|
2286
2227
|
optionSize = fit > 5 && isMultiLine ? 1.5 : optionSize;
|
2287
|
-
const menuHeight = `${
|
2228
|
+
const menuHeight = `${rowCount * optionSize}rem`;
|
2288
2229
|
const menuHeightHover = `calc(${rowCountHover} * ${optionSize}rem + ${rowCountHover - 1} * ${gap})`;
|
2289
2230
|
/** @type {HTMLUListElement} */
|
2290
2231
|
// @ts-ignore -- <UL> is an `HTMLElement`
|
@@ -2391,16 +2332,14 @@
|
|
2391
2332
|
});
|
2392
2333
|
|
2393
2334
|
// color presets
|
2394
|
-
if (
|
2395
|
-
|
2396
|
-
const presetsMenu = getColorMenu(self, colorPresets, 'color-options');
|
2397
|
-
presetsDropdown.append(presetsMenu);
|
2335
|
+
if (colorPresets) {
|
2336
|
+
presetsDropdown.append(getColorMenu(self, colorPresets, 'color-options'));
|
2398
2337
|
}
|
2399
2338
|
|
2400
2339
|
// explicit defaults [reset, initial, inherit, transparent, currentColor]
|
2340
|
+
// also custom defaults [default: #069, complementary: #930]
|
2401
2341
|
if (colorKeywords && colorKeywords.length) {
|
2402
|
-
|
2403
|
-
presetsDropdown.append(keywordsMenu);
|
2342
|
+
presetsDropdown.append(getColorMenu(self, colorKeywords, 'color-defaults'));
|
2404
2343
|
}
|
2405
2344
|
|
2406
2345
|
const presetsBtn = createElement({
|
@@ -2437,9 +2376,7 @@
|
|
2437
2376
|
setAttribute(input, tabIndex, '-1');
|
2438
2377
|
}
|
2439
2378
|
|
2440
|
-
var version = "
|
2441
|
-
|
2442
|
-
// @ts-ignore
|
2379
|
+
var version = "1.0.1";
|
2443
2380
|
|
2444
2381
|
const Version = version;
|
2445
2382
|
|
@@ -2459,7 +2396,7 @@
|
|
2459
2396
|
// ColorPicker Static Methods
|
2460
2397
|
// ==========================
|
2461
2398
|
|
2462
|
-
/** @type {CP.GetInstance<ColorPicker>} */
|
2399
|
+
/** @type {CP.GetInstance<ColorPicker, HTMLInputElement>} */
|
2463
2400
|
const getColorPickerInstance = (element) => getInstance(element, colorPickerString);
|
2464
2401
|
|
2465
2402
|
/** @type {CP.InitCallback<ColorPicker>} */
|
@@ -2494,17 +2431,12 @@
|
|
2494
2431
|
const fn = action ? addListener : removeListener;
|
2495
2432
|
const { input, colorMenu, parent } = self;
|
2496
2433
|
const doc = getDocument(input);
|
2497
|
-
const win =
|
2498
|
-
const pointerEvents = `on${touchstartEvent}` in doc
|
2499
|
-
? { down: touchstartEvent, move: touchmoveEvent, up: touchendEvent }
|
2500
|
-
: { down: mousedownEvent, move: mousemoveEvent, up: mouseupEvent };
|
2434
|
+
const win = doc.defaultView;
|
2501
2435
|
|
2502
|
-
fn(self.controls,
|
2436
|
+
fn(self.controls, pointerdownEvent, self.pointerDown);
|
2503
2437
|
self.controlKnobs.forEach((x) => fn(x, keydownEvent, self.handleKnobs));
|
2504
2438
|
|
2505
|
-
// @ts-ignore -- this is `Window`
|
2506
2439
|
fn(win, scrollEvent, self.handleScroll);
|
2507
|
-
// @ts-ignore -- this is `Window`
|
2508
2440
|
fn(win, resizeEvent, self.update);
|
2509
2441
|
|
2510
2442
|
[input, ...self.inputs].forEach((x) => fn(x, changeEvent, self.changeHandler));
|
@@ -2514,8 +2446,8 @@
|
|
2514
2446
|
fn(colorMenu, keydownEvent, self.menuKeyHandler);
|
2515
2447
|
}
|
2516
2448
|
|
2517
|
-
fn(doc,
|
2518
|
-
fn(doc,
|
2449
|
+
fn(doc, pointermoveEvent, self.pointerMove);
|
2450
|
+
fn(doc, pointerupEvent, self.pointerUp);
|
2519
2451
|
fn(parent, focusoutEvent, self.handleFocusOut);
|
2520
2452
|
fn(doc, keyupEvent, self.handleDismiss);
|
2521
2453
|
}
|
@@ -2534,6 +2466,7 @@
|
|
2534
2466
|
* @returns {void}
|
2535
2467
|
*/
|
2536
2468
|
function removePosition(element) {
|
2469
|
+
/* istanbul ignore else */
|
2537
2470
|
if (element) {
|
2538
2471
|
['bottom', 'top'].forEach((x) => removeClass(element, x));
|
2539
2472
|
}
|
@@ -2597,7 +2530,6 @@
|
|
2597
2530
|
constructor(target, config) {
|
2598
2531
|
const self = this;
|
2599
2532
|
/** @type {HTMLInputElement} */
|
2600
|
-
// @ts-ignore
|
2601
2533
|
const input = querySelector(target);
|
2602
2534
|
|
2603
2535
|
// invalidate
|
@@ -2608,7 +2540,6 @@
|
|
2608
2540
|
if (!parent) throw new TypeError('ColorPicker requires a specific markup to work.');
|
2609
2541
|
|
2610
2542
|
/** @type {HTMLElement} */
|
2611
|
-
// @ts-ignore
|
2612
2543
|
self.parent = parent;
|
2613
2544
|
|
2614
2545
|
/** @type {number} */
|
@@ -2636,6 +2567,7 @@
|
|
2636
2567
|
} = normalizeOptions(this.isCE ? parent : input, colorPickerDefaults, config || {});
|
2637
2568
|
|
2638
2569
|
let translatedColorLabels = colorNames;
|
2570
|
+
/* istanbul ignore else */
|
2639
2571
|
if (colorLabels instanceof Array && colorLabels.length === 17) {
|
2640
2572
|
translatedColorLabels = colorLabels;
|
2641
2573
|
} else if (colorLabels && colorLabels.split(',').length === 17) {
|
@@ -2652,7 +2584,7 @@
|
|
2652
2584
|
? JSON.parse(componentLabels) : componentLabels;
|
2653
2585
|
|
2654
2586
|
/** @type {Record<string, string>} */
|
2655
|
-
self.componentLabels = ObjectAssign(colorPickerLabels, tempComponentLabels);
|
2587
|
+
self.componentLabels = ObjectAssign({ ...colorPickerLabels }, tempComponentLabels);
|
2656
2588
|
|
2657
2589
|
/** @type {Color} */
|
2658
2590
|
self.color = new Color(input.value || '#fff', format);
|
@@ -2661,14 +2593,14 @@
|
|
2661
2593
|
self.format = format;
|
2662
2594
|
|
2663
2595
|
// set colour defaults
|
2664
|
-
if (colorKeywords instanceof Array) {
|
2596
|
+
if (colorKeywords instanceof Array && colorKeywords.length) {
|
2665
2597
|
self.colorKeywords = colorKeywords;
|
2666
2598
|
} else if (typeof colorKeywords === 'string' && colorKeywords.length) {
|
2667
2599
|
self.colorKeywords = colorKeywords.split(',').map((x) => x.trim());
|
2668
2600
|
}
|
2669
2601
|
|
2670
2602
|
// set colour presets
|
2671
|
-
if (colorPresets instanceof Array) {
|
2603
|
+
if (colorPresets instanceof Array && colorPresets.length) {
|
2672
2604
|
self.colorPresets = colorPresets;
|
2673
2605
|
} else if (typeof colorPresets === 'string' && colorPresets.length) {
|
2674
2606
|
if (isValidJSON(colorPresets)) {
|
@@ -2701,26 +2633,20 @@
|
|
2701
2633
|
const [colorPicker, colorMenu] = getElementsByClassName('color-dropdown', parent);
|
2702
2634
|
// set main elements
|
2703
2635
|
/** @type {HTMLElement} */
|
2704
|
-
// @ts-ignore
|
2705
2636
|
self.pickerToggle = querySelector('.picker-toggle', parent);
|
2706
2637
|
/** @type {HTMLElement} */
|
2707
|
-
// @ts-ignore
|
2708
2638
|
self.menuToggle = querySelector('.menu-toggle', parent);
|
2709
2639
|
/** @type {HTMLElement} */
|
2710
|
-
// @ts-ignore
|
2711
2640
|
self.colorPicker = colorPicker;
|
2712
2641
|
/** @type {HTMLElement} */
|
2713
|
-
// @ts-ignore
|
2714
2642
|
self.colorMenu = colorMenu;
|
2715
2643
|
/** @type {HTMLInputElement[]} */
|
2716
|
-
// @ts-ignore
|
2717
2644
|
self.inputs = [...getElementsByClassName('color-input', parent)];
|
2718
2645
|
const [controls] = getElementsByClassName('color-controls', parent);
|
2719
2646
|
self.controls = controls;
|
2720
2647
|
/** @type {(HTMLElement | Element)[]} */
|
2721
2648
|
self.controlKnobs = [...getElementsByClassName('knob', controls)];
|
2722
2649
|
/** @type {(HTMLElement)[]} */
|
2723
|
-
// @ts-ignore
|
2724
2650
|
self.visuals = [...getElementsByClassName('visual-control', controls)];
|
2725
2651
|
|
2726
2652
|
// update colour picker controls, inputs and visuals
|
@@ -2799,6 +2725,7 @@
|
|
2799
2725
|
let colorName;
|
2800
2726
|
|
2801
2727
|
// determine color appearance
|
2728
|
+
/* istanbul ignore else */
|
2802
2729
|
if (lightness === 100 && saturation === 0) {
|
2803
2730
|
colorName = colorLabels.white;
|
2804
2731
|
} else if (lightness === 0) {
|
@@ -2872,7 +2799,6 @@
|
|
2872
2799
|
* @this {ColorPicker}
|
2873
2800
|
*/
|
2874
2801
|
handleFocusOut({ relatedTarget }) {
|
2875
|
-
// @ts-ignore
|
2876
2802
|
if (relatedTarget && !this.parent.contains(relatedTarget)) {
|
2877
2803
|
this.hide(true);
|
2878
2804
|
}
|
@@ -2899,13 +2825,14 @@
|
|
2899
2825
|
const self = this;
|
2900
2826
|
const { activeElement } = getDocument(self.input);
|
2901
2827
|
|
2902
|
-
|
2828
|
+
self.updateDropdownPosition();
|
2829
|
+
|
2830
|
+
/* istanbul ignore next */
|
2831
|
+
if (([pointermoveEvent, touchmoveEvent].includes(e.type) && self.dragElement)
|
2903
2832
|
|| (activeElement && self.controlKnobs.includes(activeElement))) {
|
2904
2833
|
e.stopPropagation();
|
2905
2834
|
e.preventDefault();
|
2906
2835
|
}
|
2907
|
-
|
2908
|
-
self.updateDropdownPosition();
|
2909
2836
|
}
|
2910
2837
|
|
2911
2838
|
/**
|
@@ -2915,7 +2842,6 @@
|
|
2915
2842
|
*/
|
2916
2843
|
menuKeyHandler(e) {
|
2917
2844
|
const { target, code } = e;
|
2918
|
-
// @ts-ignore
|
2919
2845
|
const { previousElementSibling, nextElementSibling, parentElement } = target;
|
2920
2846
|
const isColorOptionsMenu = parentElement && hasClass(parentElement, 'color-options');
|
2921
2847
|
const allSiblings = [...parentElement.children];
|
@@ -2954,20 +2880,20 @@
|
|
2954
2880
|
|
2955
2881
|
/**
|
2956
2882
|
* The `ColorPicker` click event listener for the colour menu presets / defaults.
|
2957
|
-
* @param {
|
2883
|
+
* @param {Event} e
|
2958
2884
|
* @this {ColorPicker}
|
2959
2885
|
*/
|
2960
2886
|
menuClickHandler(e) {
|
2961
2887
|
const self = this;
|
2962
|
-
/** @type {*} */
|
2963
2888
|
const { target } = e;
|
2964
2889
|
const { colorMenu } = self;
|
2965
2890
|
const newOption = (getAttribute(target, 'data-value') || '').trim();
|
2966
2891
|
// invalidate for targets other than color options
|
2967
2892
|
if (!newOption.length) return;
|
2968
2893
|
const currentActive = querySelector('li.active', colorMenu);
|
2969
|
-
let newColor =
|
2970
|
-
newColor =
|
2894
|
+
let newColor = newOption;
|
2895
|
+
newColor = nonColors.includes(newColor) ? 'white' : newColor;
|
2896
|
+
newColor = newColor === 'transparent' ? 'rgba(0,0,0,0)' : newColor;
|
2971
2897
|
|
2972
2898
|
const {
|
2973
2899
|
r, g, b, a,
|
@@ -2979,7 +2905,9 @@
|
|
2979
2905
|
|
2980
2906
|
self.update();
|
2981
2907
|
|
2908
|
+
/* istanbul ignore else */
|
2982
2909
|
if (currentActive !== target) {
|
2910
|
+
/* istanbul ignore else */
|
2983
2911
|
if (currentActive) {
|
2984
2912
|
removeClass(currentActive, 'active');
|
2985
2913
|
removeAttribute(currentActive, ariaSelected);
|
@@ -2997,15 +2925,13 @@
|
|
2997
2925
|
|
2998
2926
|
/**
|
2999
2927
|
* The `ColorPicker` *touchstart* / *mousedown* events listener for control knobs.
|
3000
|
-
* @param {
|
2928
|
+
* @param {PointerEvent} e
|
3001
2929
|
* @this {ColorPicker}
|
3002
2930
|
*/
|
3003
2931
|
pointerDown(e) {
|
3004
2932
|
const self = this;
|
3005
2933
|
/** @type {*} */
|
3006
|
-
const {
|
3007
|
-
type, target, touches, pageX, pageY,
|
3008
|
-
} = e;
|
2934
|
+
const { target, pageX, pageY } = e;
|
3009
2935
|
const { colorMenu, visuals, controlKnobs } = self;
|
3010
2936
|
const [v1, v2, v3] = visuals;
|
3011
2937
|
const [c1, c2, c3] = controlKnobs;
|
@@ -3013,11 +2939,10 @@
|
|
3013
2939
|
const visual = controlKnobs.includes(target) ? target.previousElementSibling : target;
|
3014
2940
|
const visualRect = getBoundingClientRect(visual);
|
3015
2941
|
const html = getDocumentElement(v1);
|
3016
|
-
const
|
3017
|
-
const
|
3018
|
-
const offsetX = X - html.scrollLeft - visualRect.left;
|
3019
|
-
const offsetY = Y - html.scrollTop - visualRect.top;
|
2942
|
+
const offsetX = pageX - html.scrollLeft - visualRect.left;
|
2943
|
+
const offsetY = pageY - html.scrollTop - visualRect.top;
|
3020
2944
|
|
2945
|
+
/* istanbul ignore else */
|
3021
2946
|
if (target === v1 || target === c1) {
|
3022
2947
|
self.dragElement = visual;
|
3023
2948
|
self.changeControl1(offsetX, offsetY);
|
@@ -3041,7 +2966,7 @@
|
|
3041
2966
|
|
3042
2967
|
/**
|
3043
2968
|
* The `ColorPicker` *touchend* / *mouseup* events listener for control knobs.
|
3044
|
-
* @param {
|
2969
|
+
* @param {PointerEvent} e
|
3045
2970
|
* @this {ColorPicker}
|
3046
2971
|
*/
|
3047
2972
|
pointerUp({ target }) {
|
@@ -3050,9 +2975,8 @@
|
|
3050
2975
|
const doc = getDocument(parent);
|
3051
2976
|
const currentOpen = querySelector(`${colorPickerParentSelector}.open`, doc) !== null;
|
3052
2977
|
const selection = doc.getSelection();
|
3053
|
-
|
2978
|
+
|
3054
2979
|
if (!self.dragElement && !selection.toString().length
|
3055
|
-
// @ts-ignore
|
3056
2980
|
&& !parent.contains(target)) {
|
3057
2981
|
self.hide(currentOpen);
|
3058
2982
|
}
|
@@ -3062,25 +2986,20 @@
|
|
3062
2986
|
|
3063
2987
|
/**
|
3064
2988
|
* The `ColorPicker` *touchmove* / *mousemove* events listener for control knobs.
|
3065
|
-
* @param {
|
2989
|
+
* @param {PointerEvent} e
|
3066
2990
|
*/
|
3067
2991
|
pointerMove(e) {
|
3068
2992
|
const self = this;
|
3069
2993
|
const { dragElement, visuals } = self;
|
3070
2994
|
const [v1, v2, v3] = visuals;
|
3071
|
-
const {
|
3072
|
-
// @ts-ignore
|
3073
|
-
type, touches, pageX, pageY,
|
3074
|
-
} = e;
|
2995
|
+
const { pageX, pageY } = e;
|
3075
2996
|
|
3076
2997
|
if (!dragElement) return;
|
3077
2998
|
|
3078
2999
|
const controlRect = getBoundingClientRect(dragElement);
|
3079
3000
|
const win = getDocumentElement(v1);
|
3080
|
-
const
|
3081
|
-
const
|
3082
|
-
const offsetX = X - win.scrollLeft - controlRect.left;
|
3083
|
-
const offsetY = Y - win.scrollTop - controlRect.top;
|
3001
|
+
const offsetX = pageX - win.scrollLeft - controlRect.left;
|
3002
|
+
const offsetY = pageY - win.scrollTop - controlRect.top;
|
3084
3003
|
|
3085
3004
|
if (dragElement === v1) {
|
3086
3005
|
self.changeControl1(offsetX, offsetY);
|
@@ -3114,13 +3033,16 @@
|
|
3114
3033
|
const currentKnob = controlKnobs.find((x) => x === activeElement);
|
3115
3034
|
const yRatio = offsetHeight / 360;
|
3116
3035
|
|
3036
|
+
/* istanbul ignore else */
|
3117
3037
|
if (currentKnob) {
|
3118
3038
|
let offsetX = 0;
|
3119
3039
|
let offsetY = 0;
|
3120
3040
|
|
3041
|
+
/* istanbul ignore else */
|
3121
3042
|
if (target === c1) {
|
3122
3043
|
const xRatio = offsetWidth / 100;
|
3123
3044
|
|
3045
|
+
/* istanbul ignore else */
|
3124
3046
|
if ([keyArrowLeft, keyArrowRight].includes(code)) {
|
3125
3047
|
self.controlPositions.c1x += code === keyArrowRight ? xRatio : -xRatio;
|
3126
3048
|
} else if ([keyArrowUp, keyArrowDown].includes(code)) {
|
@@ -3166,6 +3088,7 @@
|
|
3166
3088
|
const isNonColorValue = self.hasNonColor && nonColors.includes(currentValue);
|
3167
3089
|
const alpha = i4 ? v4 : (1 - controlPositions.c3y / offsetHeight);
|
3168
3090
|
|
3091
|
+
/* istanbul ignore else */
|
3169
3092
|
if (activeElement === input || (activeElement && inputs.includes(activeElement))) {
|
3170
3093
|
if (activeElement === input) {
|
3171
3094
|
if (isNonColorValue) {
|
@@ -3480,6 +3403,7 @@
|
|
3480
3403
|
const hue = roundPart(hsl.h * 360);
|
3481
3404
|
let newColor;
|
3482
3405
|
|
3406
|
+
/* istanbul ignore else */
|
3483
3407
|
if (format === 'hex') {
|
3484
3408
|
newColor = self.color.toHexString(true);
|
3485
3409
|
i1.value = self.hex;
|
@@ -3580,15 +3504,15 @@
|
|
3580
3504
|
const relatedBtn = openPicker ? pickerToggle : menuToggle;
|
3581
3505
|
const animationDuration = openDropdown && getElementTransitionDuration(openDropdown);
|
3582
3506
|
|
3583
|
-
// if (!self.isValid) {
|
3584
3507
|
self.value = self.color.toString(true);
|
3585
|
-
// }
|
3586
3508
|
|
3509
|
+
/* istanbul ignore else */
|
3587
3510
|
if (openDropdown) {
|
3588
3511
|
removeClass(openDropdown, 'show');
|
3589
3512
|
setAttribute(relatedBtn, ariaExpanded, 'false');
|
3590
3513
|
setTimeout(() => {
|
3591
3514
|
removePosition(openDropdown);
|
3515
|
+
/* istanbul ignore else */
|
3592
3516
|
if (!querySelector('.show', parent)) {
|
3593
3517
|
removeClass(parent, 'open');
|
3594
3518
|
toggleEventsOnShown(self);
|
@@ -3601,7 +3525,7 @@
|
|
3601
3525
|
focus(pickerToggle);
|
3602
3526
|
}
|
3603
3527
|
setAttribute(input, tabIndex, '-1');
|
3604
|
-
if (menuToggle) {
|
3528
|
+
if (relatedBtn === menuToggle) {
|
3605
3529
|
setAttribute(menuToggle, tabIndex, '-1');
|
3606
3530
|
}
|
3607
3531
|
}
|
@@ -3639,14 +3563,76 @@
|
|
3639
3563
|
getBoundingClientRect,
|
3640
3564
|
});
|
3641
3565
|
|
3566
|
+
/**
|
3567
|
+
* A small utility to toggle `ColorPickerElement` attributes
|
3568
|
+
* when `connectedCallback` or `disconnectedCallback` methods
|
3569
|
+
* are called and helps the instance keep its value and settings instact.
|
3570
|
+
*
|
3571
|
+
* @param {CP.ColorPickerElement} self ColorPickerElement instance
|
3572
|
+
* @param {Function=} callback when `true`, attributes are added
|
3573
|
+
*
|
3574
|
+
* @example
|
3575
|
+
* const attributes = [
|
3576
|
+
* // essentials
|
3577
|
+
* 'value', 'format',
|
3578
|
+
* // presets menus
|
3579
|
+
* 'color-presets', 'color-keywords',
|
3580
|
+
* // labels
|
3581
|
+
* 'color-labels', 'component-labels',
|
3582
|
+
* ];
|
3583
|
+
*/
|
3584
|
+
function toggleCEAttr(self, callback) {
|
3585
|
+
if (callback) {
|
3586
|
+
const { input, colorPicker } = self;
|
3587
|
+
|
3588
|
+
const {
|
3589
|
+
value, format, colorPresets, colorKeywords, componentLabels, colorLabels,
|
3590
|
+
} = colorPicker;
|
3591
|
+
|
3592
|
+
const { id, placeholder } = input;
|
3593
|
+
|
3594
|
+
setAttribute(self, 'data-id', id);
|
3595
|
+
setAttribute(self, 'data-value', value);
|
3596
|
+
setAttribute(self, 'data-format', format);
|
3597
|
+
setAttribute(self, 'data-placeholder', placeholder);
|
3598
|
+
|
3599
|
+
if (ObjectKeys(colorPickerLabels).some((l) => colorPickerLabels[l] !== componentLabels[l])) {
|
3600
|
+
setAttribute(self, 'data-component-labels', JSON.stringify(componentLabels));
|
3601
|
+
}
|
3602
|
+
if (!colorNames.every((c) => c === colorLabels[c])) {
|
3603
|
+
setAttribute(self, 'data-color-labels', colorNames.map((n) => colorLabels[n]).join(','));
|
3604
|
+
}
|
3605
|
+
if (colorPresets instanceof ColorPalette) {
|
3606
|
+
const { hue, hueSteps, lightSteps } = colorPresets;
|
3607
|
+
setAttribute(self, 'data-color-presets', JSON.stringify({ hue, hueSteps, lightSteps }));
|
3608
|
+
}
|
3609
|
+
if (Array.isArray(colorPresets) && colorPresets.length) {
|
3610
|
+
setAttribute(self, 'data-color-presets', colorPresets.join(','));
|
3611
|
+
}
|
3612
|
+
if (colorKeywords) {
|
3613
|
+
setAttribute(self, 'data-color-keywords', colorKeywords.join(','));
|
3614
|
+
}
|
3615
|
+
setTimeout(callback, 0);
|
3616
|
+
} else {
|
3617
|
+
// keep id
|
3618
|
+
// removeAttribute(self, 'data-id');
|
3619
|
+
removeAttribute(self, 'data-value');
|
3620
|
+
removeAttribute(self, 'data-format');
|
3621
|
+
removeAttribute(self, 'data-placeholder');
|
3622
|
+
removeAttribute(self, 'data-component-labels');
|
3623
|
+
removeAttribute(self, 'data-color-labels');
|
3624
|
+
removeAttribute(self, 'data-color-presets');
|
3625
|
+
removeAttribute(self, 'data-color-keywords');
|
3626
|
+
}
|
3627
|
+
}
|
3628
|
+
|
3642
3629
|
let CPID = 0;
|
3643
3630
|
|
3644
3631
|
/**
|
3645
3632
|
* `ColorPickerElement` Web Component.
|
3646
3633
|
* @example
|
3647
3634
|
* <label for="UNIQUE_ID">Label</label>
|
3648
|
-
* <color-picker>
|
3649
|
-
* <input id="UNIQUE_ID" value="red" format="hex" class="color-preview btn-appearance">
|
3635
|
+
* <color-picker data-id="UNIQUE_ID" data-value="red" data-format="hex">
|
3650
3636
|
* </color-picker>
|
3651
3637
|
* // or
|
3652
3638
|
* <label for="UNIQUE_ID">Label</label>
|
@@ -3665,61 +3651,70 @@
|
|
3665
3651
|
get value() { return this.input && this.input.value; }
|
3666
3652
|
|
3667
3653
|
connectedCallback() {
|
3668
|
-
|
3654
|
+
const self = this;
|
3655
|
+
if (self.input) return;
|
3669
3656
|
|
3670
|
-
let
|
3671
|
-
const value =
|
3672
|
-
const format =
|
3673
|
-
|
3657
|
+
let id = getAttribute(self, 'data-id');
|
3658
|
+
const value = getAttribute(self, 'data-value') || '#fff';
|
3659
|
+
const format = getAttribute(self, 'data-format') || 'rgb';
|
3660
|
+
const placeholder = getAttribute(self, 'data-placeholder') || '';
|
3674
3661
|
|
3675
3662
|
if (!id) {
|
3676
3663
|
id = `color-picker-${format}-${CPID}`;
|
3677
3664
|
CPID += 1;
|
3678
3665
|
}
|
3679
3666
|
|
3680
|
-
|
3681
|
-
input
|
3682
|
-
|
3683
|
-
|
3684
|
-
|
3685
|
-
|
3667
|
+
const input = createElement({
|
3668
|
+
tagName: 'input',
|
3669
|
+
type: 'text',
|
3670
|
+
className: 'color-preview btn-appearance',
|
3671
|
+
});
|
3672
|
+
|
3673
|
+
setAttribute(input, 'id', id);
|
3674
|
+
setAttribute(input, 'name', id);
|
3675
|
+
setAttribute(input, 'autocomplete', 'off');
|
3676
|
+
setAttribute(input, 'spellcheck', 'false');
|
3677
|
+
setAttribute(input, 'value', value);
|
3678
|
+
setAttribute(input, 'placeholder', placeholder);
|
3679
|
+
self.append(input);
|
3686
3680
|
|
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
3681
|
/** @type {HTMLInputElement} */
|
3695
|
-
|
3696
|
-
this.input = input;
|
3682
|
+
self.input = input;
|
3697
3683
|
|
3698
|
-
|
3699
|
-
this.colorPicker = new ColorPicker(input);
|
3684
|
+
self.colorPicker = new ColorPicker(input);
|
3700
3685
|
|
3701
|
-
|
3702
|
-
|
3686
|
+
self.shadowRoot.append(createElement('slot'));
|
3687
|
+
|
3688
|
+
// remove Attributes
|
3689
|
+
toggleCEAttr(self);
|
3703
3690
|
}
|
3704
3691
|
|
3705
3692
|
/** @this {ColorPickerElement} */
|
3706
3693
|
disconnectedCallback() {
|
3707
|
-
const
|
3708
|
-
|
3709
|
-
|
3710
|
-
|
3711
|
-
|
3712
|
-
|
3713
|
-
colorPicker
|
3714
|
-
|
3715
|
-
|
3694
|
+
const self = this;
|
3695
|
+
const { input, colorPicker, shadowRoot } = self;
|
3696
|
+
|
3697
|
+
const callback = () => {
|
3698
|
+
// remove markup
|
3699
|
+
input.remove();
|
3700
|
+
colorPicker.dispose();
|
3701
|
+
shadowRoot.innerHTML = '';
|
3702
|
+
|
3703
|
+
ObjectAssign(self, {
|
3704
|
+
colorPicker: undefined,
|
3705
|
+
input: undefined,
|
3706
|
+
});
|
3707
|
+
};
|
3708
|
+
|
3709
|
+
// re-add Attributes
|
3710
|
+
toggleCEAttr(self, callback);
|
3716
3711
|
}
|
3717
3712
|
}
|
3718
3713
|
|
3719
3714
|
ObjectAssign(ColorPickerElement, {
|
3720
3715
|
Color,
|
3721
3716
|
ColorPicker,
|
3722
|
-
ColorPalette,
|
3717
|
+
ColorPalette,
|
3723
3718
|
getInstance: ColorPicker.getInstance,
|
3724
3719
|
Version,
|
3725
3720
|
});
|