@thednp/color-picker 0.0.1-alpha2 → 0.0.1-alpha3
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 +31 -15
- package/dist/css/color-picker.css +37 -15
- package/dist/css/color-picker.min.css +2 -2
- package/dist/css/color-picker.rtl.css +37 -15
- package/dist/css/color-picker.rtl.min.css +2 -2
- package/dist/js/color-picker-element-esm.js +164 -135
- package/dist/js/color-picker-element-esm.min.js +2 -2
- package/dist/js/color-picker-element.js +164 -135
- package/dist/js/color-picker-element.min.js +2 -2
- package/dist/js/color-picker-esm.js +159 -133
- package/dist/js/color-picker-esm.min.js +2 -2
- package/dist/js/color-picker.js +159 -133
- package/dist/js/color-picker.min.js +2 -2
- package/package.json +1 -1
- package/src/js/color-palette.js +18 -9
- package/src/js/color-picker-element.js +7 -3
- package/src/js/color-picker.js +59 -48
- package/src/js/color.js +33 -34
- package/src/js/util/getColorControls.js +3 -3
- package/src/js/util/getColorForm.js +0 -1
- package/src/js/util/getColorMenu.js +21 -28
- package/src/js/util/roundPart.js +9 -0
- package/src/js/util/setCSSProperties.js +12 -0
- package/src/js/util/tabindex.js +3 -0
- package/src/scss/color-picker.scss +35 -12
- package/types/cp.d.ts +1 -3
@@ -1,5 +1,5 @@
|
|
1
1
|
/*!
|
2
|
-
* ColorPicker v0.0.
|
2
|
+
* ColorPicker v0.0.1alpha3 (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
|
*/
|
@@ -661,13 +661,20 @@ const Data = {
|
|
661
661
|
*/
|
662
662
|
const getInstance = (target, component) => Data.get(target, component);
|
663
663
|
|
664
|
+
/**
|
665
|
+
* Shortcut for `Object.keys()` static method.
|
666
|
+
* @param {Record<string, any>} obj a target object
|
667
|
+
* @returns {string[]}
|
668
|
+
*/
|
669
|
+
const ObjectKeys = (obj) => Object.keys(obj);
|
670
|
+
|
664
671
|
/**
|
665
672
|
* Shortcut for multiple uses of `HTMLElement.style.propertyName` method.
|
666
673
|
* @param {HTMLElement | Element} element target element
|
667
674
|
* @param {Partial<CSSStyleDeclaration>} styles attribute value
|
668
675
|
*/
|
669
676
|
// @ts-ignore
|
670
|
-
const setElementStyle = (element, styles) =>
|
677
|
+
const setElementStyle = (element, styles) => ObjectAssign(element.style, styles);
|
671
678
|
|
672
679
|
/**
|
673
680
|
* Shortcut for `HTMLElement.getAttribute()` method.
|
@@ -710,13 +717,6 @@ function normalizeValue(value) {
|
|
710
717
|
return value;
|
711
718
|
}
|
712
719
|
|
713
|
-
/**
|
714
|
-
* Shortcut for `Object.keys()` static method.
|
715
|
-
* @param {Record<string, any>} obj a target object
|
716
|
-
* @returns {string[]}
|
717
|
-
*/
|
718
|
-
const ObjectKeys = (obj) => Object.keys(obj);
|
719
|
-
|
720
720
|
/**
|
721
721
|
* Shortcut for `String.toLowerCase()`.
|
722
722
|
*
|
@@ -933,7 +933,6 @@ function getColorForm(self) {
|
|
933
933
|
max,
|
934
934
|
step,
|
935
935
|
});
|
936
|
-
// }
|
937
936
|
colorForm.append(cInputLabel, cInput);
|
938
937
|
});
|
939
938
|
return colorForm;
|
@@ -957,6 +956,8 @@ const ariaValueMin = 'aria-valuemin';
|
|
957
956
|
*/
|
958
957
|
const ariaValueMax = 'aria-valuemax';
|
959
958
|
|
959
|
+
const tabIndex = 'tabindex';
|
960
|
+
|
960
961
|
/**
|
961
962
|
* Returns all color controls for `ColorPicker`.
|
962
963
|
*
|
@@ -1022,10 +1023,8 @@ function getColorControls(self) {
|
|
1022
1023
|
const {
|
1023
1024
|
i, c, l, min, max,
|
1024
1025
|
} = template;
|
1025
|
-
// const hidden = i === 2 && format === 'hwb' ? ' v-hidden' : '';
|
1026
1026
|
const control = createElement({
|
1027
1027
|
tagName: 'div',
|
1028
|
-
// className: `color-control${hidden}`,
|
1029
1028
|
className: 'color-control',
|
1030
1029
|
});
|
1031
1030
|
setAttribute(control, 'role', 'presentation');
|
@@ -1045,7 +1044,7 @@ function getColorControls(self) {
|
|
1045
1044
|
|
1046
1045
|
setAttribute(knob, ariaLabel, l);
|
1047
1046
|
setAttribute(knob, 'role', 'slider');
|
1048
|
-
setAttribute(knob,
|
1047
|
+
setAttribute(knob, tabIndex, '0');
|
1049
1048
|
setAttribute(knob, ariaValueMin, `${min}`);
|
1050
1049
|
setAttribute(knob, ariaValueMax, `${max}`);
|
1051
1050
|
control.append(knob);
|
@@ -1055,6 +1054,17 @@ function getColorControls(self) {
|
|
1055
1054
|
return colorControls;
|
1056
1055
|
}
|
1057
1056
|
|
1057
|
+
/**
|
1058
|
+
* Helps setting CSS variables to the color-menu.
|
1059
|
+
* @param {HTMLElement} element
|
1060
|
+
* @param {Record<string,any>} props
|
1061
|
+
*/
|
1062
|
+
function setCSSProperties(element, props) {
|
1063
|
+
ObjectKeys(props).forEach((prop) => {
|
1064
|
+
element.style.setProperty(prop, props[prop]);
|
1065
|
+
});
|
1066
|
+
}
|
1067
|
+
|
1058
1068
|
/**
|
1059
1069
|
* Returns the `document.head` or the `<head>` element.
|
1060
1070
|
*
|
@@ -1065,6 +1075,16 @@ function getDocumentHead(node) {
|
|
1065
1075
|
return getDocument(node).head;
|
1066
1076
|
}
|
1067
1077
|
|
1078
|
+
/**
|
1079
|
+
* Round colour components, for all formats except HEX.
|
1080
|
+
* @param {number} v one of the colour components
|
1081
|
+
* @returns {number} the rounded number
|
1082
|
+
*/
|
1083
|
+
function roundPart(v) {
|
1084
|
+
const floor = Math.floor(v);
|
1085
|
+
return v - floor < 0.5 ? floor : Math.round(v);
|
1086
|
+
}
|
1087
|
+
|
1068
1088
|
// Color supported formats
|
1069
1089
|
const COLOR_FORMAT = ['rgb', 'hex', 'hsl', 'hsb', 'hwb'];
|
1070
1090
|
|
@@ -1232,7 +1252,7 @@ function getRGBFromName(name) {
|
|
1232
1252
|
* @returns {string} - the hexadecimal value
|
1233
1253
|
*/
|
1234
1254
|
function convertDecimalToHex(d) {
|
1235
|
-
return
|
1255
|
+
return roundPart(d * 255).toString(16);
|
1236
1256
|
}
|
1237
1257
|
|
1238
1258
|
/**
|
@@ -1484,9 +1504,9 @@ function hsvToRgb(H, S, V) {
|
|
1484
1504
|
*/
|
1485
1505
|
function rgbToHex(r, g, b, allow3Char) {
|
1486
1506
|
const hex = [
|
1487
|
-
pad2(
|
1488
|
-
pad2(
|
1489
|
-
pad2(
|
1507
|
+
pad2(roundPart(r).toString(16)),
|
1508
|
+
pad2(roundPart(g).toString(16)),
|
1509
|
+
pad2(roundPart(b).toString(16)),
|
1490
1510
|
];
|
1491
1511
|
|
1492
1512
|
// Return a 3 character hex if possible
|
@@ -1511,9 +1531,9 @@ function rgbToHex(r, g, b, allow3Char) {
|
|
1511
1531
|
*/
|
1512
1532
|
function rgbaToHex(r, g, b, a, allow4Char) {
|
1513
1533
|
const hex = [
|
1514
|
-
pad2(
|
1515
|
-
pad2(
|
1516
|
-
pad2(
|
1534
|
+
pad2(roundPart(r).toString(16)),
|
1535
|
+
pad2(roundPart(g).toString(16)),
|
1536
|
+
pad2(roundPart(b).toString(16)),
|
1517
1537
|
pad2(convertDecimalToHex(a)),
|
1518
1538
|
];
|
1519
1539
|
|
@@ -1675,6 +1695,8 @@ function inputToRGB(input) {
|
|
1675
1695
|
let w = null;
|
1676
1696
|
let b = null;
|
1677
1697
|
let h = null;
|
1698
|
+
let r = null;
|
1699
|
+
let g = null;
|
1678
1700
|
let ok = false;
|
1679
1701
|
let format = 'hex';
|
1680
1702
|
|
@@ -1685,7 +1707,10 @@ function inputToRGB(input) {
|
|
1685
1707
|
}
|
1686
1708
|
if (typeof color === 'object') {
|
1687
1709
|
if (isValidCSSUnit(color.r) && isValidCSSUnit(color.g) && isValidCSSUnit(color.b)) {
|
1688
|
-
|
1710
|
+
({ r, g, b } = color);
|
1711
|
+
[r, g, b] = [...[r, g, b]]
|
1712
|
+
.map((n) => bound01(n, isPercentage(n) ? 100 : 255) * 255).map(roundPart);
|
1713
|
+
rgb = { r, g, b }; // RGB values now are all in [0, 255] range
|
1689
1714
|
ok = true;
|
1690
1715
|
format = 'rgb';
|
1691
1716
|
} else if (isValidCSSUnit(color.h) && isValidCSSUnit(color.s) && isValidCSSUnit(color.v)) {
|
@@ -1773,14 +1798,6 @@ class Color {
|
|
1773
1798
|
self.ok = ok;
|
1774
1799
|
/** @type {CP.ColorFormats} */
|
1775
1800
|
self.format = configFormat || format;
|
1776
|
-
|
1777
|
-
// Don't let the range of [0,255] come back in [0,1].
|
1778
|
-
// Potentially lose a little bit of precision here, but will fix issues where
|
1779
|
-
// .5 gets interpreted as half of the total, instead of half of 1
|
1780
|
-
// If it was supposed to be 128, this was already taken care of by `inputToRgb`
|
1781
|
-
if (r < 1) self.r = Math.round(r);
|
1782
|
-
if (g < 1) self.g = Math.round(g);
|
1783
|
-
if (b < 1) self.b = Math.round(b);
|
1784
1801
|
}
|
1785
1802
|
|
1786
1803
|
/**
|
@@ -1796,7 +1813,7 @@ class Color {
|
|
1796
1813
|
* @returns {boolean} the query result
|
1797
1814
|
*/
|
1798
1815
|
get isDark() {
|
1799
|
-
return this.brightness <
|
1816
|
+
return this.brightness < 120;
|
1800
1817
|
}
|
1801
1818
|
|
1802
1819
|
/**
|
@@ -1848,13 +1865,13 @@ class Color {
|
|
1848
1865
|
const {
|
1849
1866
|
r, g, b, a,
|
1850
1867
|
} = this;
|
1851
|
-
const [R, G, B] = [r, g, b].map((x) =>
|
1868
|
+
const [R, G, B] = [r, g, b].map((x) => roundPart(x));
|
1852
1869
|
|
1853
1870
|
return {
|
1854
1871
|
r: R,
|
1855
1872
|
g: G,
|
1856
1873
|
b: B,
|
1857
|
-
a:
|
1874
|
+
a: roundPart(a * 100) / 100,
|
1858
1875
|
};
|
1859
1876
|
}
|
1860
1877
|
|
@@ -1884,7 +1901,7 @@ class Color {
|
|
1884
1901
|
const {
|
1885
1902
|
r, g, b, a,
|
1886
1903
|
} = this.toRgb();
|
1887
|
-
const A = a === 1 ? '' : ` / ${
|
1904
|
+
const A = a === 1 ? '' : ` / ${roundPart(a * 100)}%`;
|
1888
1905
|
|
1889
1906
|
return `rgb(${r} ${g} ${b}${A})`;
|
1890
1907
|
}
|
@@ -1979,10 +1996,10 @@ class Color {
|
|
1979
1996
|
let {
|
1980
1997
|
h, s, l, a,
|
1981
1998
|
} = this.toHsl();
|
1982
|
-
h =
|
1983
|
-
s =
|
1984
|
-
l =
|
1985
|
-
a =
|
1999
|
+
h = roundPart(h * 360);
|
2000
|
+
s = roundPart(s * 100);
|
2001
|
+
l = roundPart(l * 100);
|
2002
|
+
a = roundPart(a * 100) / 100;
|
1986
2003
|
|
1987
2004
|
return a === 1
|
1988
2005
|
? `hsl(${h}, ${s}%, ${l}%)`
|
@@ -1999,11 +2016,11 @@ class Color {
|
|
1999
2016
|
let {
|
2000
2017
|
h, s, l, a,
|
2001
2018
|
} = this.toHsl();
|
2002
|
-
h =
|
2003
|
-
s =
|
2004
|
-
l =
|
2005
|
-
a =
|
2006
|
-
const A = a < 100 ? ` / ${
|
2019
|
+
h = roundPart(h * 360);
|
2020
|
+
s = roundPart(s * 100);
|
2021
|
+
l = roundPart(l * 100);
|
2022
|
+
a = roundPart(a * 100);
|
2023
|
+
const A = a < 100 ? ` / ${roundPart(a)}%` : '';
|
2007
2024
|
|
2008
2025
|
return `hsl(${h}deg ${s}% ${l}%${A})`;
|
2009
2026
|
}
|
@@ -2030,11 +2047,11 @@ class Color {
|
|
2030
2047
|
let {
|
2031
2048
|
h, w, b, a,
|
2032
2049
|
} = this.toHwb();
|
2033
|
-
h =
|
2034
|
-
w =
|
2035
|
-
b =
|
2036
|
-
a =
|
2037
|
-
const A = a < 100 ? ` / ${
|
2050
|
+
h = roundPart(h * 360);
|
2051
|
+
w = roundPart(w * 100);
|
2052
|
+
b = roundPart(b * 100);
|
2053
|
+
a = roundPart(a * 100);
|
2054
|
+
const A = a < 100 ? ` / ${roundPart(a)}%` : '';
|
2038
2055
|
|
2039
2056
|
return `hwb(${h}deg ${w}% ${b}%${A})`;
|
2040
2057
|
}
|
@@ -2180,6 +2197,7 @@ ObjectAssign(Color, {
|
|
2180
2197
|
numberInputToObject,
|
2181
2198
|
stringInputToObject,
|
2182
2199
|
inputToRGB,
|
2200
|
+
roundPart,
|
2183
2201
|
ObjectAssign,
|
2184
2202
|
});
|
2185
2203
|
|
@@ -2195,8 +2213,8 @@ class ColorPalette {
|
|
2195
2213
|
* The `hue` parameter is optional, which would be set to 0.
|
2196
2214
|
* @param {number[]} args represeinting hue, hueSteps, lightSteps
|
2197
2215
|
* * `args.hue` the starting Hue [0, 360]
|
2198
|
-
* * `args.hueSteps` Hue Steps Count [5,
|
2199
|
-
* * `args.lightSteps` Lightness Steps Count [
|
2216
|
+
* * `args.hueSteps` Hue Steps Count [5, 24]
|
2217
|
+
* * `args.lightSteps` Lightness Steps Count [5, 12]
|
2200
2218
|
*/
|
2201
2219
|
constructor(...args) {
|
2202
2220
|
let hue = 0;
|
@@ -2209,24 +2227,32 @@ class ColorPalette {
|
|
2209
2227
|
} else if (args.length === 2) {
|
2210
2228
|
[hueSteps, lightSteps] = args;
|
2211
2229
|
} else {
|
2212
|
-
throw TypeError('
|
2230
|
+
throw TypeError('ColorPalette requires minimum 2 arguments');
|
2213
2231
|
}
|
2214
2232
|
|
2215
2233
|
/** @type {string[]} */
|
2216
2234
|
const colors = [];
|
2217
2235
|
|
2218
2236
|
const hueStep = 360 / hueSteps;
|
2219
|
-
const
|
2220
|
-
const
|
2237
|
+
const half = roundPart((lightSteps - (lightSteps % 2 ? 1 : 0)) / 2);
|
2238
|
+
const estimatedStep = 100 / (lightSteps + (lightSteps % 2 ? 0 : 1)) / 100;
|
2239
|
+
|
2240
|
+
let lightStep = 0.25;
|
2241
|
+
lightStep = [4, 5].includes(lightSteps) ? 0.2 : lightStep;
|
2242
|
+
lightStep = [6, 7].includes(lightSteps) ? 0.15 : lightStep;
|
2243
|
+
lightStep = [8, 9].includes(lightSteps) ? 0.11 : lightStep;
|
2244
|
+
lightStep = [10, 11].includes(lightSteps) ? 0.09 : lightStep;
|
2245
|
+
lightStep = [12, 13].includes(lightSteps) ? 0.075 : lightStep;
|
2246
|
+
lightStep = lightSteps > 13 ? estimatedStep : lightStep;
|
2221
2247
|
|
2222
2248
|
// light tints
|
2223
|
-
for (let i =
|
2224
|
-
lightnessArray = [...lightnessArray, (0.5 + lightStep * (i
|
2249
|
+
for (let i = 1; i < half + 1; i += 1) {
|
2250
|
+
lightnessArray = [...lightnessArray, (0.5 + lightStep * (i))];
|
2225
2251
|
}
|
2226
2252
|
|
2227
2253
|
// dark tints
|
2228
|
-
for (let i =
|
2229
|
-
lightnessArray = [(0.5 - lightStep * (i
|
2254
|
+
for (let i = 1; i < lightSteps - half; i += 1) {
|
2255
|
+
lightnessArray = [(0.5 - lightStep * (i)), ...lightnessArray];
|
2230
2256
|
}
|
2231
2257
|
|
2232
2258
|
// feed `colors` Array
|
@@ -2261,45 +2287,38 @@ function getColorMenu(self, colorsSource, menuClass) {
|
|
2261
2287
|
colorsArray = colorsArray instanceof Array ? colorsArray : [];
|
2262
2288
|
const colorsCount = colorsArray.length;
|
2263
2289
|
const { lightSteps } = isPalette ? colorsSource : { lightSteps: null };
|
2264
|
-
|
2265
|
-
|| Math.max(...[5, 6, 7, 8, 9, 10].filter((x) => colorsCount > (x * 2) && !(colorsCount % x)));
|
2266
|
-
fit = Number.isFinite(fit) ? fit : 5;
|
2290
|
+
const fit = lightSteps || [9, 10].find((x) => colorsCount > x * 2 && !(colorsCount % x)) || 5;
|
2267
2291
|
const isMultiLine = isOptionsMenu && colorsCount > fit;
|
2268
|
-
let rowCountHover =
|
2269
|
-
rowCountHover = isMultiLine && colorsCount
|
2270
|
-
rowCountHover = colorsCount >=
|
2271
|
-
rowCountHover = colorsCount >=
|
2272
|
-
|
2273
|
-
const
|
2274
|
-
const isScrollable = isMultiLine && colorsCount > rowCountHover * fit;
|
2292
|
+
let rowCountHover = 2;
|
2293
|
+
rowCountHover = isMultiLine && colorsCount >= fit * 2 ? 3 : rowCountHover;
|
2294
|
+
rowCountHover = colorsCount >= fit * 3 ? 4 : rowCountHover;
|
2295
|
+
rowCountHover = colorsCount >= fit * 4 ? 5 : rowCountHover;
|
2296
|
+
const rowCount = rowCountHover - (colorsCount < fit * 3 ? 1 : 2);
|
2297
|
+
const isScrollable = isMultiLine && colorsCount > rowCount * fit;
|
2275
2298
|
let finalClass = menuClass;
|
2276
2299
|
finalClass += isScrollable ? ' scrollable' : '';
|
2277
2300
|
finalClass += isMultiLine ? ' multiline' : '';
|
2278
2301
|
const gap = isMultiLine ? '1px' : '0.25rem';
|
2279
2302
|
let optionSize = isMultiLine ? 1.75 : 2;
|
2280
|
-
optionSize =
|
2303
|
+
optionSize = fit > 5 && isMultiLine ? 1.5 : optionSize;
|
2281
2304
|
const menuHeight = `${(rowCount || 1) * optionSize}rem`;
|
2282
2305
|
const menuHeightHover = `calc(${rowCountHover} * ${optionSize}rem + ${rowCountHover - 1} * ${gap})`;
|
2283
|
-
const gridTemplateColumns = `repeat(${fit}, ${optionSize}rem)`;
|
2284
|
-
const gridTemplateRows = `repeat(auto-fill, ${optionSize}rem)`;
|
2285
2306
|
|
2286
2307
|
const menu = createElement({
|
2287
2308
|
tagName: 'ul',
|
2288
2309
|
className: finalClass,
|
2289
2310
|
});
|
2290
2311
|
setAttribute(menu, 'role', 'listbox');
|
2291
|
-
setAttribute(menu, ariaLabel,
|
2292
|
-
|
2293
|
-
if (
|
2294
|
-
|
2295
|
-
|
2296
|
-
|
2297
|
-
|
2298
|
-
|
2299
|
-
|
2300
|
-
|
2301
|
-
};
|
2302
|
-
setElementStyle(menu, menuStyle);
|
2312
|
+
setAttribute(menu, ariaLabel, menuLabel);
|
2313
|
+
|
2314
|
+
if (isScrollable) { // @ts-ignore
|
2315
|
+
setCSSProperties(menu, {
|
2316
|
+
'--grid-item-size': `${optionSize}rem`,
|
2317
|
+
'--grid-fit': fit,
|
2318
|
+
'--grid-gap': gap,
|
2319
|
+
'--grid-height': menuHeight,
|
2320
|
+
'--grid-hover-height': menuHeightHover,
|
2321
|
+
});
|
2303
2322
|
}
|
2304
2323
|
|
2305
2324
|
colorsArray.forEach((x) => {
|
@@ -2314,15 +2333,13 @@ function getColorMenu(self, colorsSource, menuClass) {
|
|
2314
2333
|
innerText: `${label || x}`,
|
2315
2334
|
});
|
2316
2335
|
|
2317
|
-
setAttribute(option,
|
2336
|
+
setAttribute(option, tabIndex, '0');
|
2318
2337
|
setAttribute(option, 'data-value', `${value}`);
|
2319
2338
|
setAttribute(option, 'role', 'option');
|
2320
2339
|
setAttribute(option, ariaSelected, isActive ? 'true' : 'false');
|
2321
2340
|
|
2322
2341
|
if (isOptionsMenu) {
|
2323
|
-
setElementStyle(option, {
|
2324
|
-
width: `${optionSize}rem`, height: `${optionSize}rem`, backgroundColor: x,
|
2325
|
-
});
|
2342
|
+
setElementStyle(option, { backgroundColor: x });
|
2326
2343
|
}
|
2327
2344
|
|
2328
2345
|
menu.append(option);
|
@@ -2344,7 +2361,7 @@ function isValidJSON(str) {
|
|
2344
2361
|
return true;
|
2345
2362
|
}
|
2346
2363
|
|
2347
|
-
var version = "0.0.
|
2364
|
+
var version = "0.0.1alpha3";
|
2348
2365
|
|
2349
2366
|
// @ts-ignore
|
2350
2367
|
|
@@ -2359,8 +2376,8 @@ const colorPickerDefaults = {
|
|
2359
2376
|
componentLabels: colorPickerLabels,
|
2360
2377
|
colorLabels: colorNames,
|
2361
2378
|
format: 'rgb',
|
2362
|
-
colorPresets:
|
2363
|
-
colorKeywords:
|
2379
|
+
colorPresets: false,
|
2380
|
+
colorKeywords: false,
|
2364
2381
|
};
|
2365
2382
|
|
2366
2383
|
// ColorPicker Static Methods
|
@@ -2449,7 +2466,7 @@ function initCallback(self) {
|
|
2449
2466
|
tagName: 'button',
|
2450
2467
|
className: 'menu-toggle btn-appearance',
|
2451
2468
|
});
|
2452
|
-
setAttribute(presetsBtn,
|
2469
|
+
setAttribute(presetsBtn, tabIndex, '-1');
|
2453
2470
|
setAttribute(presetsBtn, ariaExpanded, 'false');
|
2454
2471
|
setAttribute(presetsBtn, ariaHasPopup, 'true');
|
2455
2472
|
|
@@ -2476,7 +2493,7 @@ function initCallback(self) {
|
|
2476
2493
|
if (colorKeywords && nonColors.includes(colorValue)) {
|
2477
2494
|
self.value = colorValue;
|
2478
2495
|
}
|
2479
|
-
setAttribute(input,
|
2496
|
+
setAttribute(input, tabIndex, '-1');
|
2480
2497
|
}
|
2481
2498
|
|
2482
2499
|
/**
|
@@ -2577,8 +2594,19 @@ function showDropdown(self, dropdown) {
|
|
2577
2594
|
addClass(dropdown, 'bottom');
|
2578
2595
|
reflow(dropdown);
|
2579
2596
|
addClass(dropdown, 'show');
|
2597
|
+
|
2580
2598
|
if (isPicker) self.update();
|
2581
|
-
|
2599
|
+
|
2600
|
+
if (!self.isOpen) {
|
2601
|
+
toggleEventsOnShown(self, true);
|
2602
|
+
self.updateDropdownPosition();
|
2603
|
+
self.isOpen = true;
|
2604
|
+
setAttribute(self.input, tabIndex, '0');
|
2605
|
+
if (menuToggle) {
|
2606
|
+
setAttribute(menuToggle, tabIndex, '0');
|
2607
|
+
}
|
2608
|
+
}
|
2609
|
+
|
2582
2610
|
setAttribute(nextBtn, ariaExpanded, 'true');
|
2583
2611
|
if (activeBtn) {
|
2584
2612
|
setAttribute(activeBtn, ariaExpanded, 'false');
|
@@ -2748,7 +2776,7 @@ class ColorPicker {
|
|
2748
2776
|
set value(v) { this.input.value = v; }
|
2749
2777
|
|
2750
2778
|
/** Check if the colour presets include any non-colour. */
|
2751
|
-
get
|
2779
|
+
get hasNonColor() {
|
2752
2780
|
return this.colorKeywords instanceof Array
|
2753
2781
|
&& this.colorKeywords.some((x) => nonColors.includes(x));
|
2754
2782
|
}
|
@@ -2804,7 +2832,7 @@ class ColorPicker {
|
|
2804
2832
|
const { r, g, b } = Color.hslToRgb(hue, 1, 0.5);
|
2805
2833
|
const whiteGrad = 'linear-gradient(rgb(255,255,255) 0%, rgb(255,255,255) 100%)';
|
2806
2834
|
const alpha = 1 - controlPositions.c3y / offsetHeight;
|
2807
|
-
const roundA =
|
2835
|
+
const roundA = roundPart((alpha * 100)) / 100;
|
2808
2836
|
|
2809
2837
|
if (format !== 'hsl') {
|
2810
2838
|
const fill = new Color({
|
@@ -2822,7 +2850,7 @@ class ColorPicker {
|
|
2822
2850
|
});
|
2823
2851
|
setElementStyle(v2, { background: hueGradient });
|
2824
2852
|
} else {
|
2825
|
-
const saturation =
|
2853
|
+
const saturation = roundPart((controlPositions.c2y / offsetHeight) * 100);
|
2826
2854
|
const fill0 = new Color({
|
2827
2855
|
r: 255, g: 0, b: 0, a: alpha,
|
2828
2856
|
}).saturate(-saturation).toRgbString();
|
@@ -2977,12 +3005,12 @@ class ColorPicker {
|
|
2977
3005
|
|
2978
3006
|
self.update();
|
2979
3007
|
|
2980
|
-
if (currentActive) {
|
2981
|
-
removeClass(currentActive, 'active');
|
2982
|
-
removeAttribute(currentActive, ariaSelected);
|
2983
|
-
}
|
2984
|
-
|
2985
3008
|
if (currentActive !== target) {
|
3009
|
+
if (currentActive) {
|
3010
|
+
removeClass(currentActive, 'active');
|
3011
|
+
removeAttribute(currentActive, ariaSelected);
|
3012
|
+
}
|
3013
|
+
|
2986
3014
|
addClass(target, 'active');
|
2987
3015
|
setAttribute(target, ariaSelected, 'true');
|
2988
3016
|
|
@@ -3149,7 +3177,7 @@ class ColorPicker {
|
|
3149
3177
|
const [v1, v2, v3, v4] = format === 'rgb'
|
3150
3178
|
? inputs.map((i) => parseFloat(i.value) / (i === i4 ? 100 : 1))
|
3151
3179
|
: inputs.map((i) => parseFloat(i.value) / (i !== i1 ? 100 : 360));
|
3152
|
-
const isNonColorValue = self.
|
3180
|
+
const isNonColorValue = self.hasNonColor && nonColors.includes(currentValue);
|
3153
3181
|
const alpha = i4 ? v4 : (1 - controlPositions.c3y / offsetHeight);
|
3154
3182
|
|
3155
3183
|
if (activeElement === input || (activeElement && inputs.includes(activeElement))) {
|
@@ -3408,11 +3436,11 @@ class ColorPicker {
|
|
3408
3436
|
} = componentLabels;
|
3409
3437
|
const { r, g, b } = color.toRgb();
|
3410
3438
|
const [knob1, knob2, knob3] = controlKnobs;
|
3411
|
-
const hue =
|
3439
|
+
const hue = roundPart(hsl.h * 360);
|
3412
3440
|
const alpha = color.a;
|
3413
3441
|
const saturationSource = format === 'hsl' ? hsl.s : hsv.s;
|
3414
|
-
const saturation =
|
3415
|
-
const lightness =
|
3442
|
+
const saturation = roundPart(saturationSource * 100);
|
3443
|
+
const lightness = roundPart(hsl.l * 100);
|
3416
3444
|
const hsvl = hsv.v * 100;
|
3417
3445
|
let colorName;
|
3418
3446
|
|
@@ -3459,8 +3487,8 @@ class ColorPicker {
|
|
3459
3487
|
setAttribute(knob2, ariaValueNow, `${saturation}`);
|
3460
3488
|
} else if (format === 'hwb') {
|
3461
3489
|
const { hwb } = self;
|
3462
|
-
const whiteness =
|
3463
|
-
const blackness =
|
3490
|
+
const whiteness = roundPart(hwb.w * 100);
|
3491
|
+
const blackness = roundPart(hwb.b * 100);
|
3464
3492
|
colorLabel = `HWB: ${hue}°, ${whiteness}%, ${blackness}%`;
|
3465
3493
|
setAttribute(knob1, ariaDescription, `${valueLabel}: ${colorLabel}. ${appearanceLabel}: ${colorName}.`);
|
3466
3494
|
setAttribute(knob1, ariaValueText, `${whiteness}% & ${blackness}%`);
|
@@ -3476,7 +3504,7 @@ class ColorPicker {
|
|
3476
3504
|
setAttribute(knob2, ariaValueNow, `${hue}`);
|
3477
3505
|
}
|
3478
3506
|
|
3479
|
-
const alphaValue =
|
3507
|
+
const alphaValue = roundPart(alpha * 100);
|
3480
3508
|
setAttribute(knob3, ariaValueText, `${alphaValue}%`);
|
3481
3509
|
setAttribute(knob3, ariaValueNow, `${alphaValue}`);
|
3482
3510
|
|
@@ -3499,10 +3527,14 @@ class ColorPicker {
|
|
3499
3527
|
/** Updates the control knobs actual positions. */
|
3500
3528
|
updateControls() {
|
3501
3529
|
const { controlKnobs, controlPositions } = this;
|
3530
|
+
const {
|
3531
|
+
c1x, c1y, c2y, c3y,
|
3532
|
+
} = controlPositions;
|
3502
3533
|
const [control1, control2, control3] = controlKnobs;
|
3503
|
-
|
3504
|
-
setElementStyle(
|
3505
|
-
setElementStyle(
|
3534
|
+
|
3535
|
+
setElementStyle(control1, { transform: `translate3d(${c1x - 4}px,${c1y - 4}px,0)` });
|
3536
|
+
setElementStyle(control2, { transform: `translate3d(0,${c2y - 4}px,0)` });
|
3537
|
+
setElementStyle(control3, { transform: `translate3d(0,${c3y - 4}px,0)` });
|
3506
3538
|
}
|
3507
3539
|
|
3508
3540
|
/**
|
@@ -3515,16 +3547,16 @@ class ColorPicker {
|
|
3515
3547
|
value: oldColor, format, inputs, color, hsl,
|
3516
3548
|
} = self;
|
3517
3549
|
const [i1, i2, i3, i4] = inputs;
|
3518
|
-
const alpha =
|
3519
|
-
const hue =
|
3550
|
+
const alpha = roundPart(color.a * 100);
|
3551
|
+
const hue = roundPart(hsl.h * 360);
|
3520
3552
|
let newColor;
|
3521
3553
|
|
3522
3554
|
if (format === 'hex') {
|
3523
3555
|
newColor = self.color.toHexString(true);
|
3524
3556
|
i1.value = self.hex;
|
3525
3557
|
} else if (format === 'hsl') {
|
3526
|
-
const lightness =
|
3527
|
-
const saturation =
|
3558
|
+
const lightness = roundPart(hsl.l * 100);
|
3559
|
+
const saturation = roundPart(hsl.s * 100);
|
3528
3560
|
newColor = self.color.toHslString();
|
3529
3561
|
i1.value = `${hue}`;
|
3530
3562
|
i2.value = `${saturation}`;
|
@@ -3532,8 +3564,8 @@ class ColorPicker {
|
|
3532
3564
|
i4.value = `${alpha}`;
|
3533
3565
|
} else if (format === 'hwb') {
|
3534
3566
|
const { w, b } = self.hwb;
|
3535
|
-
const whiteness =
|
3536
|
-
const blackness =
|
3567
|
+
const whiteness = roundPart(w * 100);
|
3568
|
+
const blackness = roundPart(b * 100);
|
3537
3569
|
|
3538
3570
|
newColor = self.color.toHwbString();
|
3539
3571
|
i1.value = `${hue}`;
|
@@ -3605,7 +3637,7 @@ class ColorPicker {
|
|
3605
3637
|
const self = this;
|
3606
3638
|
const { colorPicker } = self;
|
3607
3639
|
|
3608
|
-
if (!hasClass(colorPicker,
|
3640
|
+
if (!['top', 'bottom'].some((c) => hasClass(colorPicker, c))) {
|
3609
3641
|
showDropdown(self, colorPicker);
|
3610
3642
|
}
|
3611
3643
|
}
|
@@ -3622,21 +3654,6 @@ class ColorPicker {
|
|
3622
3654
|
}
|
3623
3655
|
}
|
3624
3656
|
|
3625
|
-
/** Shows the `ColorPicker` dropdown or the presets menu. */
|
3626
|
-
show() {
|
3627
|
-
const self = this;
|
3628
|
-
const { menuToggle } = self;
|
3629
|
-
if (!self.isOpen) {
|
3630
|
-
toggleEventsOnShown(self, true);
|
3631
|
-
self.updateDropdownPosition();
|
3632
|
-
self.isOpen = true;
|
3633
|
-
setAttribute(self.input, 'tabindex', '0');
|
3634
|
-
if (menuToggle) {
|
3635
|
-
setAttribute(menuToggle, 'tabindex', '0');
|
3636
|
-
}
|
3637
|
-
}
|
3638
|
-
}
|
3639
|
-
|
3640
3657
|
/**
|
3641
3658
|
* Hides the currently open `ColorPicker` dropdown.
|
3642
3659
|
* @param {boolean=} focusPrevented
|
@@ -3671,9 +3688,9 @@ class ColorPicker {
|
|
3671
3688
|
if (!focusPrevented) {
|
3672
3689
|
focus(pickerToggle);
|
3673
3690
|
}
|
3674
|
-
setAttribute(input,
|
3691
|
+
setAttribute(input, tabIndex, '-1');
|
3675
3692
|
if (menuToggle) {
|
3676
|
-
setAttribute(menuToggle,
|
3693
|
+
setAttribute(menuToggle, tabIndex, '-1');
|
3677
3694
|
}
|
3678
3695
|
}
|
3679
3696
|
}
|
@@ -3687,7 +3704,10 @@ class ColorPicker {
|
|
3687
3704
|
[...parent.children].forEach((el) => {
|
3688
3705
|
if (el !== input) el.remove();
|
3689
3706
|
});
|
3707
|
+
|
3708
|
+
removeAttribute(input, tabIndex);
|
3690
3709
|
setElementStyle(input, { backgroundColor: '' });
|
3710
|
+
|
3691
3711
|
['txt-light', 'txt-dark'].forEach((c) => removeClass(parent, c));
|
3692
3712
|
Data.remove(input, colorPickerString);
|
3693
3713
|
}
|
@@ -3695,10 +3715,16 @@ class ColorPicker {
|
|
3695
3715
|
|
3696
3716
|
ObjectAssign(ColorPicker, {
|
3697
3717
|
Color,
|
3718
|
+
ColorPalette,
|
3698
3719
|
Version,
|
3699
3720
|
getInstance: getColorPickerInstance,
|
3700
3721
|
init: initColorPicker,
|
3701
3722
|
selector: colorPickerSelector,
|
3723
|
+
// utils important for render
|
3724
|
+
roundPart,
|
3725
|
+
setElementStyle,
|
3726
|
+
setAttribute,
|
3727
|
+
getBoundingClientRect,
|
3702
3728
|
});
|
3703
3729
|
|
3704
3730
|
export default ColorPicker;
|