@thednp/color-picker 0.0.1 → 0.0.2-alpha1
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 +1 -0
- package/dist/css/color-picker.css +1 -1
- package/dist/css/color-picker.min.css +1 -1
- package/dist/css/color-picker.rtl.css +1 -1
- package/dist/css/color-picker.rtl.min.css +1 -1
- package/dist/js/color-esm.js +1178 -0
- package/dist/js/color-esm.min.js +2 -0
- package/dist/js/color-palette-esm.js +1252 -0
- package/dist/js/color-palette-esm.min.js +2 -0
- package/dist/js/color-palette.js +1260 -0
- package/dist/js/color-palette.min.js +2 -0
- package/dist/js/color-picker-element-esm.js +287 -319
- package/dist/js/color-picker-element-esm.min.js +2 -2
- package/dist/js/color-picker-element.js +289 -321
- package/dist/js/color-picker-element.min.js +2 -2
- package/dist/js/color-picker-esm.js +520 -552
- package/dist/js/color-picker-esm.min.js +2 -2
- package/dist/js/color-picker.js +522 -554
- package/dist/js/color-picker.min.js +2 -2
- package/dist/js/color.js +1186 -0
- package/dist/js/color.min.js +2 -0
- package/package.json +19 -3
- package/src/js/color-palette.js +10 -3
- package/src/js/color-picker-element.js +1 -1
- package/src/js/color-picker.js +7 -120
- package/src/js/color.js +88 -91
- package/src/js/util/getColorMenu.js +12 -7
- package/src/js/util/setMarkup.js +122 -0
- package/src/js/util/version.js +6 -0
- package/types/cp.d.ts +47 -17
- package/src/js/util/templates.js +0 -10
    
        package/dist/js/color-picker.js
    CHANGED
    
    | @@ -1,13 +1,13 @@ | |
| 1 1 | 
             
            /*!
         | 
| 2 | 
            -
            * ColorPicker v0.0. | 
| 2 | 
            +
            * ColorPicker v0.0.2alpha1 (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 | 
             
            */
         | 
| 6 6 | 
             
            (function (global, factory) {
         | 
| 7 7 | 
             
              typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
         | 
| 8 8 | 
             
              typeof define === 'function' && define.amd ? define(factory) :
         | 
| 9 | 
            -
              (global = global || self, global.ColorPicker = factory());
         | 
| 10 | 
            -
            }(this, (function () { 'use strict';
         | 
| 9 | 
            +
              (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.ColorPicker = factory());
         | 
| 10 | 
            +
            })(this, (function () { 'use strict';
         | 
| 11 11 |  | 
| 12 12 | 
             
              /** @type {Record<string, any>} */
         | 
| 13 13 | 
             
              const EventRegistry = {};
         | 
| @@ -135,24 +135,6 @@ | |
| 135 135 | 
             
               */
         | 
| 136 136 | 
             
              const ariaValueNow = 'aria-valuenow';
         | 
| 137 137 |  | 
| 138 | 
            -
              /**
         | 
| 139 | 
            -
               * A global namespace for aria-haspopup.
         | 
| 140 | 
            -
               * @type {string}
         | 
| 141 | 
            -
               */
         | 
| 142 | 
            -
              const ariaHasPopup = 'aria-haspopup';
         | 
| 143 | 
            -
             | 
| 144 | 
            -
              /**
         | 
| 145 | 
            -
               * A global namespace for aria-hidden.
         | 
| 146 | 
            -
               * @type {string}
         | 
| 147 | 
            -
               */
         | 
| 148 | 
            -
              const ariaHidden = 'aria-hidden';
         | 
| 149 | 
            -
             | 
| 150 | 
            -
              /**
         | 
| 151 | 
            -
               * A global namespace for aria-labelledby.
         | 
| 152 | 
            -
               * @type {string}
         | 
| 153 | 
            -
               */
         | 
| 154 | 
            -
              const ariaLabelledBy = 'aria-labelledby';
         | 
| 155 | 
            -
             | 
| 156 138 | 
             
              /**
         | 
| 157 139 | 
             
               * A global namespace for `ArrowDown` key.
         | 
| 158 140 | 
             
               * @type {string} e.which = 40 equivalent
         | 
| @@ -279,37 +261,6 @@ | |
| 279 261 | 
             
               */
         | 
| 280 262 | 
             
              const focusoutEvent = 'focusout';
         | 
| 281 263 |  | 
| 282 | 
            -
              // @ts-ignore
         | 
| 283 | 
            -
              const { userAgentData: uaDATA } = navigator;
         | 
| 284 | 
            -
             | 
| 285 | 
            -
              /**
         | 
| 286 | 
            -
               * A global namespace for `userAgentData` object.
         | 
| 287 | 
            -
               */
         | 
| 288 | 
            -
              const userAgentData = uaDATA;
         | 
| 289 | 
            -
             | 
| 290 | 
            -
              const { userAgent: userAgentString } = navigator;
         | 
| 291 | 
            -
             | 
| 292 | 
            -
              /**
         | 
| 293 | 
            -
               * A global namespace for `navigator.userAgent` string.
         | 
| 294 | 
            -
               */
         | 
| 295 | 
            -
              const userAgent = userAgentString;
         | 
| 296 | 
            -
             | 
| 297 | 
            -
              const mobileBrands = /iPhone|iPad|iPod|Android/i;
         | 
| 298 | 
            -
              let isMobileCheck = false;
         | 
| 299 | 
            -
             | 
| 300 | 
            -
              if (userAgentData) {
         | 
| 301 | 
            -
                isMobileCheck = userAgentData.brands
         | 
| 302 | 
            -
                  .some((/** @type {Record<String, any>} */x) => mobileBrands.test(x.brand));
         | 
| 303 | 
            -
              } else {
         | 
| 304 | 
            -
                isMobileCheck = mobileBrands.test(userAgent);
         | 
| 305 | 
            -
              }
         | 
| 306 | 
            -
             | 
| 307 | 
            -
              /**
         | 
| 308 | 
            -
               * A global `boolean` for mobile detection.
         | 
| 309 | 
            -
               * @type {boolean}
         | 
| 310 | 
            -
               */
         | 
| 311 | 
            -
              const isMobile = isMobileCheck;
         | 
| 312 | 
            -
             | 
| 313 264 | 
             
              /**
         | 
| 314 265 | 
             
               * Returns the `document` or the `#document` element.
         | 
| 315 266 | 
             
               * @see https://github.com/floating-ui/floating-ui
         | 
| @@ -530,60 +481,6 @@ | |
| 530 481 | 
             
                return lookUp.getElementsByClassName(selector);
         | 
| 531 482 | 
             
              }
         | 
| 532 483 |  | 
| 533 | 
            -
              /**
         | 
| 534 | 
            -
               * Shortcut for `Object.assign()` static method.
         | 
| 535 | 
            -
               * @param  {Record<string, any>} obj a target object
         | 
| 536 | 
            -
               * @param  {Record<string, any>} source a source object
         | 
| 537 | 
            -
               */
         | 
| 538 | 
            -
              const ObjectAssign = (obj, source) => Object.assign(obj, source);
         | 
| 539 | 
            -
             | 
| 540 | 
            -
              /**
         | 
| 541 | 
            -
               * This is a shortie for `document.createElement` method
         | 
| 542 | 
            -
               * which allows you to create a new `HTMLElement` for a given `tagName`
         | 
| 543 | 
            -
               * or based on an object with specific non-readonly attributes:
         | 
| 544 | 
            -
               * `id`, `className`, `textContent`, `style`, etc.
         | 
| 545 | 
            -
               * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement
         | 
| 546 | 
            -
               *
         | 
| 547 | 
            -
               * @param {Record<string, string> | string} param `tagName` or object
         | 
| 548 | 
            -
               * @return {HTMLElement | Element} a new `HTMLElement` or `Element`
         | 
| 549 | 
            -
               */
         | 
| 550 | 
            -
              function createElement(param) {
         | 
| 551 | 
            -
                if (typeof param === 'string') {
         | 
| 552 | 
            -
                  return getDocument().createElement(param);
         | 
| 553 | 
            -
                }
         | 
| 554 | 
            -
             | 
| 555 | 
            -
                const { tagName } = param;
         | 
| 556 | 
            -
                const attr = { ...param };
         | 
| 557 | 
            -
                const newElement = createElement(tagName);
         | 
| 558 | 
            -
                delete attr.tagName;
         | 
| 559 | 
            -
                ObjectAssign(newElement, attr);
         | 
| 560 | 
            -
                return newElement;
         | 
| 561 | 
            -
              }
         | 
| 562 | 
            -
             | 
| 563 | 
            -
              /**
         | 
| 564 | 
            -
               * This is a shortie for `document.createElementNS` method
         | 
| 565 | 
            -
               * which allows you to create a new `HTMLElement` for a given `tagName`
         | 
| 566 | 
            -
               * or based on an object with specific non-readonly attributes:
         | 
| 567 | 
            -
               * `id`, `className`, `textContent`, `style`, etc.
         | 
| 568 | 
            -
               * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/createElementNS
         | 
| 569 | 
            -
               *
         | 
| 570 | 
            -
               * @param {string} namespace `namespaceURI` to associate with the new `HTMLElement`
         | 
| 571 | 
            -
               * @param {Record<string, string> | string} param `tagName` or object
         | 
| 572 | 
            -
               * @return {HTMLElement | Element} a new `HTMLElement` or `Element`
         | 
| 573 | 
            -
               */
         | 
| 574 | 
            -
              function createElementNS(namespace, param) {
         | 
| 575 | 
            -
                if (typeof param === 'string') {
         | 
| 576 | 
            -
                  return getDocument().createElementNS(namespace, param);
         | 
| 577 | 
            -
                }
         | 
| 578 | 
            -
             | 
| 579 | 
            -
                const { tagName } = param;
         | 
| 580 | 
            -
                const attr = { ...param };
         | 
| 581 | 
            -
                const newElement = createElementNS(namespace, tagName);
         | 
| 582 | 
            -
                delete attr.tagName;
         | 
| 583 | 
            -
                ObjectAssign(newElement, attr);
         | 
| 584 | 
            -
                return newElement;
         | 
| 585 | 
            -
              }
         | 
| 586 | 
            -
             | 
| 587 484 | 
             
              /**
         | 
| 588 485 | 
             
               * Shortcut for the `Element.dispatchEvent(Event)` method.
         | 
| 589 486 | 
             
               *
         | 
| @@ -592,6 +489,13 @@ | |
| 592 489 | 
             
               */
         | 
| 593 490 | 
             
              const dispatchEvent = (element, event) => element.dispatchEvent(event);
         | 
| 594 491 |  | 
| 492 | 
            +
              /**
         | 
| 493 | 
            +
               * Shortcut for `Object.assign()` static method.
         | 
| 494 | 
            +
               * @param  {Record<string, any>} obj a target object
         | 
| 495 | 
            +
               * @param  {Record<string, any>} source a source object
         | 
| 496 | 
            +
               */
         | 
| 497 | 
            +
              const ObjectAssign = (obj, source) => Object.assign(obj, source);
         | 
| 498 | 
            +
             | 
| 595 499 | 
             
              /** @type {Map<string, Map<HTMLElement | Element, Record<string, any>>>} */
         | 
| 596 500 | 
             
              const componentData = new Map();
         | 
| 597 501 | 
             
              /**
         | 
| @@ -667,20 +571,13 @@ | |
| 667 571 | 
             
               */
         | 
| 668 572 | 
             
              const getInstance = (target, component) => Data.get(target, component);
         | 
| 669 573 |  | 
| 670 | 
            -
              /**
         | 
| 671 | 
            -
               * Shortcut for `Object.keys()` static method.
         | 
| 672 | 
            -
               * @param  {Record<string, any>} obj a target object
         | 
| 673 | 
            -
               * @returns {string[]}
         | 
| 674 | 
            -
               */
         | 
| 675 | 
            -
              const ObjectKeys = (obj) => Object.keys(obj);
         | 
| 676 | 
            -
             | 
| 677 574 | 
             
              /**
         | 
| 678 575 | 
             
               * Shortcut for multiple uses of `HTMLElement.style.propertyName` method.
         | 
| 679 576 | 
             
               * @param  {HTMLElement | Element} element target element
         | 
| 680 577 | 
             
               * @param  {Partial<CSSStyleDeclaration>} styles attribute value
         | 
| 681 578 | 
             
               */
         | 
| 682 579 | 
             
              // @ts-ignore
         | 
| 683 | 
            -
              const setElementStyle = (element, styles) => ObjectAssign(element.style, styles);
         | 
| 580 | 
            +
              const setElementStyle = (element, styles) => { ObjectAssign(element.style, styles); };
         | 
| 684 581 |  | 
| 685 582 | 
             
              /**
         | 
| 686 583 | 
             
               * Shortcut for `HTMLElement.getAttribute()` method.
         | 
| @@ -723,6 +620,13 @@ | |
| 723 620 | 
             
                return value;
         | 
| 724 621 | 
             
              }
         | 
| 725 622 |  | 
| 623 | 
            +
              /**
         | 
| 624 | 
            +
               * Shortcut for `Object.keys()` static method.
         | 
| 625 | 
            +
               * @param  {Record<string, any>} obj a target object
         | 
| 626 | 
            +
               * @returns {string[]}
         | 
| 627 | 
            +
               */
         | 
| 628 | 
            +
              const ObjectKeys = (obj) => Object.keys(obj);
         | 
| 629 | 
            +
             | 
| 726 630 | 
             
              /**
         | 
| 727 631 | 
             
               * Shortcut for `String.toLowerCase()`.
         | 
| 728 632 | 
             
               *
         | 
| @@ -843,32 +747,10 @@ | |
| 843 747 | 
             
               */
         | 
| 844 748 | 
             
              const removeAttribute = (element, attribute) => element.removeAttribute(attribute);
         | 
| 845 749 |  | 
| 846 | 
            -
              /** @type {Record<string, string>} */
         | 
| 847 | 
            -
              const colorPickerLabels = {
         | 
| 848 | 
            -
                pickerLabel: 'Colour Picker',
         | 
| 849 | 
            -
                appearanceLabel: 'Colour Appearance',
         | 
| 850 | 
            -
                valueLabel: 'Colour Value',
         | 
| 851 | 
            -
                toggleLabel: 'Select Colour',
         | 
| 852 | 
            -
                presetsLabel: 'Colour Presets',
         | 
| 853 | 
            -
                defaultsLabel: 'Colour Defaults',
         | 
| 854 | 
            -
                formatLabel: 'Format',
         | 
| 855 | 
            -
                alphaLabel: 'Alpha',
         | 
| 856 | 
            -
                hexLabel: 'Hexadecimal',
         | 
| 857 | 
            -
                hueLabel: 'Hue',
         | 
| 858 | 
            -
                whitenessLabel: 'Whiteness',
         | 
| 859 | 
            -
                blacknessLabel: 'Blackness',
         | 
| 860 | 
            -
                saturationLabel: 'Saturation',
         | 
| 861 | 
            -
                lightnessLabel: 'Lightness',
         | 
| 862 | 
            -
                redLabel: 'Red',
         | 
| 863 | 
            -
                greenLabel: 'Green',
         | 
| 864 | 
            -
                blueLabel: 'Blue',
         | 
| 865 | 
            -
              };
         | 
| 866 | 
            -
             | 
| 867 750 | 
             
              /**
         | 
| 868 | 
            -
               * A  | 
| 869 | 
            -
               * @type {string[]}
         | 
| 751 | 
            +
               * A global namespace for `document.head`.
         | 
| 870 752 | 
             
               */
         | 
| 871 | 
            -
              const  | 
| 753 | 
            +
              const { head: documentHead } = document;
         | 
| 872 754 |  | 
| 873 755 | 
             
              /**
         | 
| 874 756 | 
             
               * A list of explicit default non-color values.
         | 
| @@ -876,297 +758,97 @@ | |
| 876 758 | 
             
              const nonColors = ['transparent', 'currentColor', 'inherit', 'revert', 'initial'];
         | 
| 877 759 |  | 
| 878 760 | 
             
              /**
         | 
| 879 | 
            -
               *  | 
| 880 | 
            -
               *
         | 
| 881 | 
            -
               * @ | 
| 882 | 
            -
               * @returns {string} uppercase output string
         | 
| 761 | 
            +
               * Round colour components, for all formats except HEX.
         | 
| 762 | 
            +
               * @param {number} v one of the colour components
         | 
| 763 | 
            +
               * @returns {number} the rounded number
         | 
| 883 764 | 
             
               */
         | 
| 884 | 
            -
               | 
| 765 | 
            +
              function roundPart(v) {
         | 
| 766 | 
            +
                const floor = Math.floor(v);
         | 
| 767 | 
            +
                return v - floor < 0.5 ? floor : Math.round(v);
         | 
| 768 | 
            +
              }
         | 
| 885 769 |  | 
| 886 | 
            -
               | 
| 770 | 
            +
              // Color supported formats
         | 
| 771 | 
            +
              const COLOR_FORMAT = ['rgb', 'hex', 'hsl', 'hsv', 'hwb'];
         | 
| 887 772 |  | 
| 888 | 
            -
               | 
| 889 | 
            -
             | 
| 890 | 
            -
               *
         | 
| 891 | 
            -
               * @param {CP.ColorPicker} self the `ColorPicker` instance
         | 
| 892 | 
            -
               * @returns {HTMLElement | Element} a new `<div>` element with color component `<input>`
         | 
| 893 | 
            -
               */
         | 
| 894 | 
            -
              function getColorForm(self) {
         | 
| 895 | 
            -
                const { format, id, componentLabels } = self;
         | 
| 896 | 
            -
                const colorForm = createElement({
         | 
| 897 | 
            -
                  tagName: 'div',
         | 
| 898 | 
            -
                  className: `color-form ${format}`,
         | 
| 899 | 
            -
                });
         | 
| 773 | 
            +
              // Hue angles
         | 
| 774 | 
            +
              const ANGLES = 'deg|rad|grad|turn';
         | 
| 900 775 |  | 
| 901 | 
            -
             | 
| 902 | 
            -
             | 
| 903 | 
            -
                else if (format === 'hsl') components = ['hue', 'saturation', 'lightness', 'alpha'];
         | 
| 904 | 
            -
                else if (format === 'hwb') components = ['hue', 'whiteness', 'blackness', 'alpha'];
         | 
| 776 | 
            +
              // <http://www.w3.org/TR/css3-values/#integers>
         | 
| 777 | 
            +
              const CSS_INTEGER = '[-\\+]?\\d+%?';
         | 
| 905 778 |  | 
| 906 | 
            -
             | 
| 907 | 
            -
             | 
| 908 | 
            -
             | 
| 909 | 
            -
                  const formatLabel = componentLabels[`${c}Label`];
         | 
| 910 | 
            -
                  const cInputLabel = createElement({ tagName: 'label' });
         | 
| 911 | 
            -
                  setAttribute(cInputLabel, 'for', cID);
         | 
| 912 | 
            -
                  cInputLabel.append(
         | 
| 913 | 
            -
                    createElement({ tagName: 'span', ariaHidden: 'true', innerText: `${C}:` }),
         | 
| 914 | 
            -
                    createElement({ tagName: 'span', className: vHidden, innerText: formatLabel }),
         | 
| 915 | 
            -
                  );
         | 
| 916 | 
            -
                  const cInput = createElement({
         | 
| 917 | 
            -
                    tagName: 'input',
         | 
| 918 | 
            -
                    id: cID,
         | 
| 919 | 
            -
                    // name: cID, - prevent saving the value to a form
         | 
| 920 | 
            -
                    type: format === 'hex' ? 'text' : 'number',
         | 
| 921 | 
            -
                    value: c === 'alpha' ? '100' : '0',
         | 
| 922 | 
            -
                    className: `color-input ${c}`,
         | 
| 923 | 
            -
                  });
         | 
| 924 | 
            -
                  setAttribute(cInput, 'autocomplete', 'off');
         | 
| 925 | 
            -
                  setAttribute(cInput, 'spellcheck', 'false');
         | 
| 779 | 
            +
              // Include CSS3 Module
         | 
| 780 | 
            +
              // <http://www.w3.org/TR/css3-values/#number-value>
         | 
| 781 | 
            +
              const CSS_NUMBER = '[-\\+]?\\d*\\.\\d+%?';
         | 
| 926 782 |  | 
| 927 | 
            -
             | 
| 928 | 
            -
             | 
| 929 | 
            -
             | 
| 930 | 
            -
             | 
| 931 | 
            -
             | 
| 932 | 
            -
             | 
| 933 | 
            -
             | 
| 934 | 
            -
             | 
| 935 | 
            -
             | 
| 936 | 
            -
             | 
| 937 | 
            -
             | 
| 938 | 
            -
             | 
| 939 | 
            -
             | 
| 940 | 
            -
             | 
| 941 | 
            -
             | 
| 942 | 
            -
             | 
| 943 | 
            -
             | 
| 944 | 
            -
             | 
| 945 | 
            -
               | 
| 783 | 
            +
              // Include CSS4 Module Hue degrees unit
         | 
| 784 | 
            +
              // <https://www.w3.org/TR/css3-values/#angle-value>
         | 
| 785 | 
            +
              const CSS_ANGLE = `[-\\+]?\\d*\\.?\\d+(?:${ANGLES})?`;
         | 
| 786 | 
            +
             | 
| 787 | 
            +
              // Allow positive/negative integer/number.  Don't capture the either/or, just the entire outcome.
         | 
| 788 | 
            +
              const CSS_UNIT = `(?:${CSS_NUMBER})|(?:${CSS_INTEGER})`;
         | 
| 789 | 
            +
             | 
| 790 | 
            +
              // Add angles to the mix
         | 
| 791 | 
            +
              const CSS_UNIT2 = `(?:${CSS_UNIT})|(?:${CSS_ANGLE})`;
         | 
| 792 | 
            +
             | 
| 793 | 
            +
              // Start & end
         | 
| 794 | 
            +
              const START_MATCH = '(?:[\\s|\\(\\s|\\s\\(\\s]+)?';
         | 
| 795 | 
            +
              const END_MATCH = '(?:[\\s|\\)\\s]+)?';
         | 
| 796 | 
            +
              // Components separation
         | 
| 797 | 
            +
              const SEP = '(?:[,|\\s]+)';
         | 
| 798 | 
            +
              const SEP2 = '(?:[,|\\/\\s]*)?';
         | 
| 799 | 
            +
             | 
| 800 | 
            +
              // Actual matching.
         | 
| 801 | 
            +
              // Parentheses and commas are optional, but not required.
         | 
| 802 | 
            +
              // Whitespace can take the place of commas or opening paren
         | 
| 803 | 
            +
              const PERMISSIVE_MATCH = `${START_MATCH}(${CSS_UNIT2})${SEP}(${CSS_UNIT})${SEP}(${CSS_UNIT})${SEP2}(${CSS_UNIT})?${END_MATCH}`;
         | 
| 804 | 
            +
             | 
| 805 | 
            +
              const matchers = {
         | 
| 806 | 
            +
                CSS_UNIT: new RegExp(CSS_UNIT2),
         | 
| 807 | 
            +
                hwb: new RegExp(`hwb${PERMISSIVE_MATCH}`),
         | 
| 808 | 
            +
                rgb: new RegExp(`rgb(?:a)?${PERMISSIVE_MATCH}`),
         | 
| 809 | 
            +
                hsl: new RegExp(`hsl(?:a)?${PERMISSIVE_MATCH}`),
         | 
| 810 | 
            +
                hsv: new RegExp(`hsv(?:a)?${PERMISSIVE_MATCH}`),
         | 
| 811 | 
            +
                hex3: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
         | 
| 812 | 
            +
                hex6: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,
         | 
| 813 | 
            +
                hex4: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
         | 
| 814 | 
            +
                hex8: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,
         | 
| 815 | 
            +
              };
         | 
| 946 816 |  | 
| 947 817 | 
             
              /**
         | 
| 948 | 
            -
               *  | 
| 949 | 
            -
               *  | 
| 818 | 
            +
               * Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
         | 
| 819 | 
            +
               * <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>
         | 
| 820 | 
            +
               * @param {string} n testing number
         | 
| 821 | 
            +
               * @returns {boolean} the query result
         | 
| 950 822 | 
             
               */
         | 
| 951 | 
            -
               | 
| 823 | 
            +
              function isOnePointZero(n) {
         | 
| 824 | 
            +
                return `${n}`.includes('.') && parseFloat(n) === 1;
         | 
| 825 | 
            +
              }
         | 
| 952 826 |  | 
| 953 827 | 
             
              /**
         | 
| 954 | 
            -
               *  | 
| 955 | 
            -
               * @ | 
| 828 | 
            +
               * Check to see if string passed in is a percentage
         | 
| 829 | 
            +
               * @param {string} n testing number
         | 
| 830 | 
            +
               * @returns {boolean} the query result
         | 
| 956 831 | 
             
               */
         | 
| 957 | 
            -
               | 
| 958 | 
            -
             | 
| 959 | 
            -
               | 
| 960 | 
            -
               * A global namespace for aria-valuemax.
         | 
| 961 | 
            -
               * @type {string}
         | 
| 962 | 
            -
               */
         | 
| 963 | 
            -
              const ariaValueMax = 'aria-valuemax';
         | 
| 964 | 
            -
             | 
| 965 | 
            -
              const tabIndex = 'tabindex';
         | 
| 966 | 
            -
             | 
| 967 | 
            -
              /**
         | 
| 968 | 
            -
               * Returns all color controls for `ColorPicker`.
         | 
| 969 | 
            -
               *
         | 
| 970 | 
            -
               * @param {CP.ColorPicker} self the `ColorPicker` instance
         | 
| 971 | 
            -
               * @returns {HTMLElement | Element} color controls
         | 
| 972 | 
            -
               */
         | 
| 973 | 
            -
              function getColorControls(self) {
         | 
| 974 | 
            -
                const { format, componentLabels } = self;
         | 
| 975 | 
            -
                const {
         | 
| 976 | 
            -
                  hueLabel, alphaLabel, lightnessLabel, saturationLabel,
         | 
| 977 | 
            -
                  whitenessLabel, blacknessLabel,
         | 
| 978 | 
            -
                } = componentLabels;
         | 
| 979 | 
            -
             | 
| 980 | 
            -
                const max1 = format === 'hsl' ? 360 : 100;
         | 
| 981 | 
            -
                const max2 = format === 'hsl' ? 100 : 360;
         | 
| 982 | 
            -
                const max3 = 100;
         | 
| 983 | 
            -
             | 
| 984 | 
            -
                let ctrl1Label = format === 'hsl'
         | 
| 985 | 
            -
                  ? `${hueLabel} & ${lightnessLabel}`
         | 
| 986 | 
            -
                  : `${lightnessLabel} & ${saturationLabel}`;
         | 
| 987 | 
            -
             | 
| 988 | 
            -
                ctrl1Label = format === 'hwb'
         | 
| 989 | 
            -
                  ? `${whitenessLabel} & ${blacknessLabel}`
         | 
| 990 | 
            -
                  : ctrl1Label;
         | 
| 991 | 
            -
             | 
| 992 | 
            -
                const ctrl2Label = format === 'hsl'
         | 
| 993 | 
            -
                  ? `${saturationLabel}`
         | 
| 994 | 
            -
                  : `${hueLabel}`;
         | 
| 995 | 
            -
             | 
| 996 | 
            -
                const colorControls = createElement({
         | 
| 997 | 
            -
                  tagName: 'div',
         | 
| 998 | 
            -
                  className: `color-controls ${format}`,
         | 
| 999 | 
            -
                });
         | 
| 1000 | 
            -
             | 
| 1001 | 
            -
                const colorPointer = 'color-pointer';
         | 
| 1002 | 
            -
                const colorSlider = 'color-slider';
         | 
| 1003 | 
            -
             | 
| 1004 | 
            -
                const controls = [
         | 
| 1005 | 
            -
                  {
         | 
| 1006 | 
            -
                    i: 1,
         | 
| 1007 | 
            -
                    c: colorPointer,
         | 
| 1008 | 
            -
                    l: ctrl1Label,
         | 
| 1009 | 
            -
                    min: 0,
         | 
| 1010 | 
            -
                    max: max1,
         | 
| 1011 | 
            -
                  },
         | 
| 1012 | 
            -
                  {
         | 
| 1013 | 
            -
                    i: 2,
         | 
| 1014 | 
            -
                    c: colorSlider,
         | 
| 1015 | 
            -
                    l: ctrl2Label,
         | 
| 1016 | 
            -
                    min: 0,
         | 
| 1017 | 
            -
                    max: max2,
         | 
| 1018 | 
            -
                  },
         | 
| 1019 | 
            -
                  {
         | 
| 1020 | 
            -
                    i: 3,
         | 
| 1021 | 
            -
                    c: colorSlider,
         | 
| 1022 | 
            -
                    l: alphaLabel,
         | 
| 1023 | 
            -
                    min: 0,
         | 
| 1024 | 
            -
                    max: max3,
         | 
| 1025 | 
            -
                  },
         | 
| 1026 | 
            -
                ];
         | 
| 1027 | 
            -
             | 
| 1028 | 
            -
                controls.forEach((template) => {
         | 
| 1029 | 
            -
                  const {
         | 
| 1030 | 
            -
                    i, c, l, min, max,
         | 
| 1031 | 
            -
                  } = template;
         | 
| 1032 | 
            -
                  const control = createElement({
         | 
| 1033 | 
            -
                    tagName: 'div',
         | 
| 1034 | 
            -
                    className: 'color-control',
         | 
| 1035 | 
            -
                  });
         | 
| 1036 | 
            -
                  setAttribute(control, 'role', 'presentation');
         | 
| 1037 | 
            -
             | 
| 1038 | 
            -
                  control.append(
         | 
| 1039 | 
            -
                    createElement({
         | 
| 1040 | 
            -
                      tagName: 'div',
         | 
| 1041 | 
            -
                      className: `visual-control visual-control${i}`,
         | 
| 1042 | 
            -
                    }),
         | 
| 1043 | 
            -
                  );
         | 
| 1044 | 
            -
             | 
| 1045 | 
            -
                  const knob = createElement({
         | 
| 1046 | 
            -
                    tagName: 'div',
         | 
| 1047 | 
            -
                    className: `${c} knob`,
         | 
| 1048 | 
            -
                    ariaLive: 'polite',
         | 
| 1049 | 
            -
                  });
         | 
| 1050 | 
            -
             | 
| 1051 | 
            -
                  setAttribute(knob, ariaLabel, l);
         | 
| 1052 | 
            -
                  setAttribute(knob, 'role', 'slider');
         | 
| 1053 | 
            -
                  setAttribute(knob, tabIndex, '0');
         | 
| 1054 | 
            -
                  setAttribute(knob, ariaValueMin, `${min}`);
         | 
| 1055 | 
            -
                  setAttribute(knob, ariaValueMax, `${max}`);
         | 
| 1056 | 
            -
                  control.append(knob);
         | 
| 1057 | 
            -
                  colorControls.append(control);
         | 
| 1058 | 
            -
                });
         | 
| 1059 | 
            -
             | 
| 1060 | 
            -
                return colorControls;
         | 
| 1061 | 
            -
              }
         | 
| 1062 | 
            -
             | 
| 1063 | 
            -
              /**
         | 
| 1064 | 
            -
               * Helps setting CSS variables to the color-menu.
         | 
| 1065 | 
            -
               * @param {HTMLElement} element
         | 
| 1066 | 
            -
               * @param {Record<string,any>} props
         | 
| 1067 | 
            -
               */
         | 
| 1068 | 
            -
              function setCSSProperties(element, props) {
         | 
| 1069 | 
            -
                ObjectKeys(props).forEach((prop) => {
         | 
| 1070 | 
            -
                  element.style.setProperty(prop, props[prop]);
         | 
| 1071 | 
            -
                });
         | 
| 1072 | 
            -
              }
         | 
| 1073 | 
            -
             | 
| 1074 | 
            -
              /**
         | 
| 1075 | 
            -
               * Returns the `document.head` or the `<head>` element.
         | 
| 1076 | 
            -
               *
         | 
| 1077 | 
            -
               * @param {(Node | HTMLElement | Element | globalThis)=} node
         | 
| 1078 | 
            -
               * @returns {HTMLElement | HTMLHeadElement}
         | 
| 1079 | 
            -
               */
         | 
| 1080 | 
            -
              function getDocumentHead(node) {
         | 
| 1081 | 
            -
                return getDocument(node).head;
         | 
| 1082 | 
            -
              }
         | 
| 1083 | 
            -
             | 
| 1084 | 
            -
              /**
         | 
| 1085 | 
            -
               * Round colour components, for all formats except HEX.
         | 
| 1086 | 
            -
               * @param {number} v one of the colour components
         | 
| 1087 | 
            -
               * @returns {number} the rounded number
         | 
| 1088 | 
            -
               */
         | 
| 1089 | 
            -
              function roundPart(v) {
         | 
| 1090 | 
            -
                const floor = Math.floor(v);
         | 
| 1091 | 
            -
                return v - floor < 0.5 ? floor : Math.round(v);
         | 
| 1092 | 
            -
              }
         | 
| 1093 | 
            -
             | 
| 1094 | 
            -
              // Color supported formats
         | 
| 1095 | 
            -
              const COLOR_FORMAT = ['rgb', 'hex', 'hsl', 'hsb', 'hwb'];
         | 
| 1096 | 
            -
             | 
| 1097 | 
            -
              // Hue angles
         | 
| 1098 | 
            -
              const ANGLES = 'deg|rad|grad|turn';
         | 
| 1099 | 
            -
             | 
| 1100 | 
            -
              // <http://www.w3.org/TR/css3-values/#integers>
         | 
| 1101 | 
            -
              const CSS_INTEGER = '[-\\+]?\\d+%?';
         | 
| 1102 | 
            -
             | 
| 1103 | 
            -
              // Include CSS3 Module
         | 
| 1104 | 
            -
              // <http://www.w3.org/TR/css3-values/#number-value>
         | 
| 1105 | 
            -
              const CSS_NUMBER = '[-\\+]?\\d*\\.\\d+%?';
         | 
| 1106 | 
            -
             | 
| 1107 | 
            -
              // Include CSS4 Module Hue degrees unit
         | 
| 1108 | 
            -
              // <https://www.w3.org/TR/css3-values/#angle-value>
         | 
| 1109 | 
            -
              const CSS_ANGLE = `[-\\+]?\\d*\\.?\\d+(?:${ANGLES})?`;
         | 
| 1110 | 
            -
             | 
| 1111 | 
            -
              // Allow positive/negative integer/number.  Don't capture the either/or, just the entire outcome.
         | 
| 1112 | 
            -
              const CSS_UNIT = `(?:${CSS_NUMBER})|(?:${CSS_INTEGER})`;
         | 
| 1113 | 
            -
             | 
| 1114 | 
            -
              // Add angles to the mix
         | 
| 1115 | 
            -
              const CSS_UNIT2 = `(?:${CSS_UNIT})|(?:${CSS_ANGLE})`;
         | 
| 1116 | 
            -
             | 
| 1117 | 
            -
              // Actual matching.
         | 
| 1118 | 
            -
              // Parentheses and commas are optional, but not required.
         | 
| 1119 | 
            -
              // Whitespace can take the place of commas or opening paren
         | 
| 1120 | 
            -
              const PERMISSIVE_MATCH = `[\\s|\\(]+(${CSS_UNIT2})[,|\\s]+(${CSS_UNIT})[,|\\s]+(${CSS_UNIT})[,|\\s|\\/\\s]*(${CSS_UNIT})?\\s*\\)?`;
         | 
| 1121 | 
            -
             | 
| 1122 | 
            -
              const matchers = {
         | 
| 1123 | 
            -
                CSS_UNIT: new RegExp(CSS_UNIT2),
         | 
| 1124 | 
            -
                hwb: new RegExp(`hwb${PERMISSIVE_MATCH}`),
         | 
| 1125 | 
            -
                rgb: new RegExp(`rgb(?:a)?${PERMISSIVE_MATCH}`),
         | 
| 1126 | 
            -
                hsl: new RegExp(`hsl(?:a)?${PERMISSIVE_MATCH}`),
         | 
| 1127 | 
            -
                hsv: new RegExp(`hsv(?:a)?${PERMISSIVE_MATCH}`),
         | 
| 1128 | 
            -
                hex3: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
         | 
| 1129 | 
            -
                hex6: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,
         | 
| 1130 | 
            -
                hex4: /^#?([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})([0-9a-fA-F]{1})$/,
         | 
| 1131 | 
            -
                hex8: /^#?([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/,
         | 
| 1132 | 
            -
              };
         | 
| 1133 | 
            -
             | 
| 1134 | 
            -
              /**
         | 
| 1135 | 
            -
               * Need to handle 1.0 as 100%, since once it is a number, there is no difference between it and 1
         | 
| 1136 | 
            -
               * <http://stackoverflow.com/questions/7422072/javascript-how-to-detect-number-as-a-decimal-including-1-0>
         | 
| 1137 | 
            -
               * @param {string} n testing number
         | 
| 1138 | 
            -
               * @returns {boolean} the query result
         | 
| 1139 | 
            -
               */
         | 
| 1140 | 
            -
              function isOnePointZero(n) {
         | 
| 1141 | 
            -
                return `${n}`.includes('.') && parseFloat(n) === 1;
         | 
| 1142 | 
            -
              }
         | 
| 1143 | 
            -
             | 
| 1144 | 
            -
              /**
         | 
| 1145 | 
            -
               * Check to see if string passed in is a percentage
         | 
| 1146 | 
            -
               * @param {string} n testing number
         | 
| 1147 | 
            -
               * @returns {boolean} the query result
         | 
| 1148 | 
            -
               */
         | 
| 1149 | 
            -
              function isPercentage(n) {
         | 
| 1150 | 
            -
                return `${n}`.includes('%');
         | 
| 1151 | 
            -
              }
         | 
| 1152 | 
            -
             | 
| 1153 | 
            -
              /**
         | 
| 1154 | 
            -
               * Check to see if string passed in is an angle
         | 
| 1155 | 
            -
               * @param {string} n testing string
         | 
| 1156 | 
            -
               * @returns {boolean} the query result
         | 
| 1157 | 
            -
               */
         | 
| 1158 | 
            -
              function isAngle(n) {
         | 
| 1159 | 
            -
                return ANGLES.split('|').some((a) => `${n}`.includes(a));
         | 
| 1160 | 
            -
              }
         | 
| 832 | 
            +
              function isPercentage(n) {
         | 
| 833 | 
            +
                return `${n}`.includes('%');
         | 
| 834 | 
            +
              }
         | 
| 1161 835 |  | 
| 1162 836 | 
             
              /**
         | 
| 1163 837 | 
             
               * Check to see if string passed is a web safe colour.
         | 
| 838 | 
            +
               * @see https://stackoverflow.com/a/16994164
         | 
| 1164 839 | 
             
               * @param {string} color a colour name, EG: *red*
         | 
| 1165 840 | 
             
               * @returns {boolean} the query result
         | 
| 1166 841 | 
             
               */
         | 
| 1167 842 | 
             
              function isColorName(color) {
         | 
| 1168 | 
            -
                 | 
| 1169 | 
            -
                   | 
| 843 | 
            +
                if (nonColors.includes(color)
         | 
| 844 | 
            +
                  || ['#', ...COLOR_FORMAT].some((f) => color.includes(f))) return false;
         | 
| 845 | 
            +
             | 
| 846 | 
            +
                return ['rgb(255, 255, 255)', 'rgb(0, 0, 0)'].every((c) => {
         | 
| 847 | 
            +
                  setElementStyle(documentHead, { color });
         | 
| 848 | 
            +
                  const computedColor = getElementStyle(documentHead, 'color');
         | 
| 849 | 
            +
                  setElementStyle(documentHead, { color: '' });
         | 
| 850 | 
            +
                  return computedColor !== c;
         | 
| 851 | 
            +
                });
         | 
| 1170 852 | 
             
              }
         | 
| 1171 853 |  | 
| 1172 854 | 
             
              /**
         | 
| @@ -1187,15 +869,15 @@ | |
| 1187 869 | 
             
               */
         | 
| 1188 870 | 
             
              function bound01(N, max) {
         | 
| 1189 871 | 
             
                let n = N;
         | 
| 1190 | 
            -
                if (isOnePointZero( | 
| 1191 | 
            -
             | 
| 1192 | 
            -
                n = max === 360 ? n : Math.min(max, Math.max(0, parseFloat(n)));
         | 
| 872 | 
            +
                if (isOnePointZero(N)) n = '100%';
         | 
| 1193 873 |  | 
| 1194 | 
            -
                 | 
| 1195 | 
            -
                 | 
| 874 | 
            +
                const processPercent = isPercentage(n);
         | 
| 875 | 
            +
                n = max === 360
         | 
| 876 | 
            +
                  ? parseFloat(n)
         | 
| 877 | 
            +
                  : Math.min(max, Math.max(0, parseFloat(n)));
         | 
| 1196 878 |  | 
| 1197 879 | 
             
                // Automatically convert percentage into number
         | 
| 1198 | 
            -
                if ( | 
| 880 | 
            +
                if (processPercent) n = (n * max) / 100;
         | 
| 1199 881 |  | 
| 1200 882 | 
             
                // Handle floating point rounding errors
         | 
| 1201 883 | 
             
                if (Math.abs(n - max) < 0.000001) {
         | 
| @@ -1206,11 +888,11 @@ | |
| 1206 888 | 
             
                  // If n is a hue given in degrees,
         | 
| 1207 889 | 
             
                  // wrap around out-of-range values into [0, 360] range
         | 
| 1208 890 | 
             
                  // then convert into [0, 1].
         | 
| 1209 | 
            -
                  n = (n < 0 ? (n % max) + max : n % max) /  | 
| 891 | 
            +
                  n = (n < 0 ? (n % max) + max : n % max) / max;
         | 
| 1210 892 | 
             
                } else {
         | 
| 1211 893 | 
             
                  // If n not a hue given in degrees
         | 
| 1212 894 | 
             
                  // Convert into [0, 1] range if it isn't already.
         | 
| 1213 | 
            -
                  n = (n % max) /  | 
| 895 | 
            +
                  n = (n % max) / max;
         | 
| 1214 896 | 
             
                }
         | 
| 1215 897 | 
             
                return n;
         | 
| 1216 898 | 
             
              }
         | 
| @@ -1245,7 +927,6 @@ | |
| 1245 927 | 
             
               * @returns {string}
         | 
| 1246 928 | 
             
               */
         | 
| 1247 929 | 
             
              function getRGBFromName(name) {
         | 
| 1248 | 
            -
                const documentHead = getDocumentHead();
         | 
| 1249 930 | 
             
                setElementStyle(documentHead, { color: name });
         | 
| 1250 931 | 
             
                const colorName = getElementStyle(documentHead, 'color');
         | 
| 1251 932 | 
             
                setElementStyle(documentHead, { color: '' });
         | 
| @@ -1344,6 +1025,36 @@ | |
| 1344 1025 | 
             
                return p;
         | 
| 1345 1026 | 
             
              }
         | 
| 1346 1027 |  | 
| 1028 | 
            +
              /**
         | 
| 1029 | 
            +
               * Converts an HSL colour value to RGB.
         | 
| 1030 | 
            +
               *
         | 
| 1031 | 
            +
               * @param {number} h Hue Angle [0, 1]
         | 
| 1032 | 
            +
               * @param {number} s Saturation [0, 1]
         | 
| 1033 | 
            +
               * @param {number} l Lightness Angle [0, 1]
         | 
| 1034 | 
            +
               * @returns {CP.RGB} {r,g,b} object with [0, 255] ranged values
         | 
| 1035 | 
            +
               */
         | 
| 1036 | 
            +
              function hslToRgb(h, s, l) {
         | 
| 1037 | 
            +
                let r = 0;
         | 
| 1038 | 
            +
                let g = 0;
         | 
| 1039 | 
            +
                let b = 0;
         | 
| 1040 | 
            +
             | 
| 1041 | 
            +
                if (s === 0) {
         | 
| 1042 | 
            +
                  // achromatic
         | 
| 1043 | 
            +
                  g = l;
         | 
| 1044 | 
            +
                  b = l;
         | 
| 1045 | 
            +
                  r = l;
         | 
| 1046 | 
            +
                } else {
         | 
| 1047 | 
            +
                  const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
         | 
| 1048 | 
            +
                  const p = 2 * l - q;
         | 
| 1049 | 
            +
                  r = hueToRgb(p, q, h + 1 / 3);
         | 
| 1050 | 
            +
                  g = hueToRgb(p, q, h);
         | 
| 1051 | 
            +
                  b = hueToRgb(p, q, h - 1 / 3);
         | 
| 1052 | 
            +
                }
         | 
| 1053 | 
            +
                [r, g, b] = [r, g, b].map((x) => x * 255);
         | 
| 1054 | 
            +
             | 
| 1055 | 
            +
                return { r, g, b };
         | 
| 1056 | 
            +
              }
         | 
| 1057 | 
            +
             | 
| 1347 1058 | 
             
              /**
         | 
| 1348 1059 | 
             
              * Returns an HWB colour object from an RGB colour object.
         | 
| 1349 1060 | 
             
              * @link https://www.w3.org/TR/css-color-4/#hwb-to-rgb
         | 
| @@ -1406,36 +1117,6 @@ | |
| 1406 1117 | 
             
                return { r, g, b };
         | 
| 1407 1118 | 
             
              }
         | 
| 1408 1119 |  | 
| 1409 | 
            -
              /**
         | 
| 1410 | 
            -
               * Converts an HSL colour value to RGB.
         | 
| 1411 | 
            -
               *
         | 
| 1412 | 
            -
               * @param {number} h Hue Angle [0, 1]
         | 
| 1413 | 
            -
               * @param {number} s Saturation [0, 1]
         | 
| 1414 | 
            -
               * @param {number} l Lightness Angle [0, 1]
         | 
| 1415 | 
            -
               * @returns {CP.RGB} {r,g,b} object with [0, 255] ranged values
         | 
| 1416 | 
            -
               */
         | 
| 1417 | 
            -
              function hslToRgb(h, s, l) {
         | 
| 1418 | 
            -
                let r = 0;
         | 
| 1419 | 
            -
                let g = 0;
         | 
| 1420 | 
            -
                let b = 0;
         | 
| 1421 | 
            -
             | 
| 1422 | 
            -
                if (s === 0) {
         | 
| 1423 | 
            -
                  // achromatic
         | 
| 1424 | 
            -
                  g = l;
         | 
| 1425 | 
            -
                  b = l;
         | 
| 1426 | 
            -
                  r = l;
         | 
| 1427 | 
            -
                } else {
         | 
| 1428 | 
            -
                  const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
         | 
| 1429 | 
            -
                  const p = 2 * l - q;
         | 
| 1430 | 
            -
                  r = hueToRgb(p, q, h + 1 / 3);
         | 
| 1431 | 
            -
                  g = hueToRgb(p, q, h);
         | 
| 1432 | 
            -
                  b = hueToRgb(p, q, h - 1 / 3);
         | 
| 1433 | 
            -
                }
         | 
| 1434 | 
            -
                [r, g, b] = [r, g, b].map((x) => x * 255);
         | 
| 1435 | 
            -
             | 
| 1436 | 
            -
                return { r, g, b };
         | 
| 1437 | 
            -
              }
         | 
| 1438 | 
            -
             | 
| 1439 1120 | 
             
              /**
         | 
| 1440 1121 | 
             
               * Converts an RGB colour value to HSV.
         | 
| 1441 1122 | 
             
               *
         | 
| @@ -1491,10 +1172,11 @@ | |
| 1491 1172 | 
             
                const q = v * (1 - f * s);
         | 
| 1492 1173 | 
             
                const t = v * (1 - (1 - f) * s);
         | 
| 1493 1174 | 
             
                const mod = i % 6;
         | 
| 1494 | 
            -
                 | 
| 1495 | 
            -
                 | 
| 1496 | 
            -
                 | 
| 1497 | 
            -
                 | 
| 1175 | 
            +
                let r = [v, q, p, p, t, v][mod];
         | 
| 1176 | 
            +
                let g = [t, v, v, q, p, p][mod];
         | 
| 1177 | 
            +
                let b = [p, p, t, v, v, q][mod];
         | 
| 1178 | 
            +
                [r, g, b] = [r, g, b].map((n) => n * 255);
         | 
| 1179 | 
            +
                return { r, g, b };
         | 
| 1498 1180 | 
             
              }
         | 
| 1499 1181 |  | 
| 1500 1182 | 
             
              /**
         | 
| @@ -1518,7 +1200,7 @@ | |
| 1518 1200 | 
             
                // Return a 3 character hex if possible
         | 
| 1519 1201 | 
             
                if (allow3Char && hex[0].charAt(0) === hex[0].charAt(1)
         | 
| 1520 1202 | 
             
                  && hex[1].charAt(0) === hex[1].charAt(1)
         | 
| 1521 | 
            -
             | 
| 1203 | 
            +
                  && hex[2].charAt(0) === hex[2].charAt(1)) {
         | 
| 1522 1204 | 
             
                  return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0);
         | 
| 1523 1205 | 
             
                }
         | 
| 1524 1206 |  | 
| @@ -1546,39 +1228,24 @@ | |
| 1546 1228 | 
             
                // Return a 4 character hex if possible
         | 
| 1547 1229 | 
             
                if (allow4Char && hex[0].charAt(0) === hex[0].charAt(1)
         | 
| 1548 1230 | 
             
                  && hex[1].charAt(0) === hex[1].charAt(1)
         | 
| 1549 | 
            -
             | 
| 1550 | 
            -
             | 
| 1231 | 
            +
                  && hex[2].charAt(0) === hex[2].charAt(1)
         | 
| 1232 | 
            +
                  && hex[3].charAt(0) === hex[3].charAt(1)) {
         | 
| 1551 1233 | 
             
                  return hex[0].charAt(0) + hex[1].charAt(0) + hex[2].charAt(0) + hex[3].charAt(0);
         | 
| 1552 1234 | 
             
                }
         | 
| 1553 1235 | 
             
                return hex.join('');
         | 
| 1554 1236 | 
             
              }
         | 
| 1555 1237 |  | 
| 1556 | 
            -
              /**
         | 
| 1557 | 
            -
               * Returns a colour object corresponding to a given number.
         | 
| 1558 | 
            -
               * @param {number} color input number
         | 
| 1559 | 
            -
               * @returns {CP.RGB} {r,g,b} object with [0, 255] ranged values
         | 
| 1560 | 
            -
               */
         | 
| 1561 | 
            -
              function numberInputToObject(color) {
         | 
| 1562 | 
            -
                /* eslint-disable no-bitwise */
         | 
| 1563 | 
            -
                return {
         | 
| 1564 | 
            -
                  r: color >> 16,
         | 
| 1565 | 
            -
                  g: (color & 0xff00) >> 8,
         | 
| 1566 | 
            -
                  b: color & 0xff,
         | 
| 1567 | 
            -
                };
         | 
| 1568 | 
            -
                /* eslint-enable no-bitwise */
         | 
| 1569 | 
            -
              }
         | 
| 1570 | 
            -
             | 
| 1571 1238 | 
             
              /**
         | 
| 1572 1239 | 
             
               * Permissive string parsing. Take in a number of formats, and output an object
         | 
| 1573 1240 | 
             
               * based on detected format. Returns {r,g,b} or {h,s,l} or {h,s,v}
         | 
| 1574 1241 | 
             
               * @param {string} input colour value in any format
         | 
| 1575 | 
            -
               * @returns {Record<string, (number | string)> | false} an object matching the RegExp
         | 
| 1242 | 
            +
               * @returns {Record<string, (number | string | boolean)> | false} an object matching the RegExp
         | 
| 1576 1243 | 
             
               */
         | 
| 1577 1244 | 
             
              function stringInputToObject(input) {
         | 
| 1578 | 
            -
                let color = input.trim() | 
| 1245 | 
            +
                let color = toLowerCase(input.trim());
         | 
| 1579 1246 | 
             
                if (color.length === 0) {
         | 
| 1580 1247 | 
             
                  return {
         | 
| 1581 | 
            -
                    r: 0, g: 0, b: 0, a:  | 
| 1248 | 
            +
                    r: 0, g: 0, b: 0, a: 1,
         | 
| 1582 1249 | 
             
                  };
         | 
| 1583 1250 | 
             
                }
         | 
| 1584 1251 | 
             
                let named = false;
         | 
| @@ -1586,11 +1253,9 @@ | |
| 1586 1253 | 
             
                  color = getRGBFromName(color);
         | 
| 1587 1254 | 
             
                  named = true;
         | 
| 1588 1255 | 
             
                } else if (nonColors.includes(color)) {
         | 
| 1589 | 
            -
                  const  | 
| 1590 | 
            -
                  const rgb = isTransparent ? 0 : 255;
         | 
| 1591 | 
            -
                  const a = isTransparent ? 0 : 1;
         | 
| 1256 | 
            +
                  const a = color === 'transparent' ? 0 : 1;
         | 
| 1592 1257 | 
             
                  return {
         | 
| 1593 | 
            -
                    r:  | 
| 1258 | 
            +
                    r: 0, g: 0, b: 0, a, format: 'rgb', ok: true,
         | 
| 1594 1259 | 
             
                  };
         | 
| 1595 1260 | 
             
                }
         | 
| 1596 1261 |  | 
| @@ -1630,7 +1295,6 @@ | |
| 1630 1295 | 
             
                    g: parseIntFromHex(m2),
         | 
| 1631 1296 | 
             
                    b: parseIntFromHex(m3),
         | 
| 1632 1297 | 
             
                    a: convertHexToDecimal(m4),
         | 
| 1633 | 
            -
                    // format: named ? 'rgb' : 'hex8',
         | 
| 1634 1298 | 
             
                    format: named ? 'rgb' : 'hex',
         | 
| 1635 1299 | 
             
                  };
         | 
| 1636 1300 | 
             
                }
         | 
| @@ -1694,6 +1358,7 @@ | |
| 1694 1358 | 
             
              function inputToRGB(input) {
         | 
| 1695 1359 | 
             
                let rgb = { r: 0, g: 0, b: 0 };
         | 
| 1696 1360 | 
             
                let color = input;
         | 
| 1361 | 
            +
                /** @type {string | number} */
         | 
| 1697 1362 | 
             
                let a = 1;
         | 
| 1698 1363 | 
             
                let s = null;
         | 
| 1699 1364 | 
             
                let v = null;
         | 
| @@ -1704,7 +1369,8 @@ | |
| 1704 1369 | 
             
                let r = null;
         | 
| 1705 1370 | 
             
                let g = null;
         | 
| 1706 1371 | 
             
                let ok = false;
         | 
| 1707 | 
            -
                 | 
| 1372 | 
            +
                const inputFormat = typeof color === 'object' && color.format;
         | 
| 1373 | 
            +
                let format = inputFormat && COLOR_FORMAT.includes(inputFormat) ? inputFormat : 'rgb';
         | 
| 1708 1374 |  | 
| 1709 1375 | 
             
                if (typeof input === 'string') {
         | 
| 1710 1376 | 
             
                  // @ts-ignore -- this now is converted to object
         | 
| @@ -1745,14 +1411,17 @@ | |
| 1745 1411 | 
             
                    format = 'hwb';
         | 
| 1746 1412 | 
             
                  }
         | 
| 1747 1413 | 
             
                  if (isValidCSSUnit(color.a)) {
         | 
| 1748 | 
            -
                    a = color.a;
         | 
| 1749 | 
            -
                    a = isPercentage(`${a}`) ? bound01(a, 100) : a;
         | 
| 1414 | 
            +
                    a = color.a; // @ts-ignore -- `parseFloat` works with numbers too
         | 
| 1415 | 
            +
                    a = isPercentage(`${a}`) || parseFloat(a) > 1 ? bound01(a, 100) : a;
         | 
| 1750 1416 | 
             
                  }
         | 
| 1751 1417 | 
             
                }
         | 
| 1418 | 
            +
                if (typeof color === 'undefined') {
         | 
| 1419 | 
            +
                  ok = true;
         | 
| 1420 | 
            +
                }
         | 
| 1752 1421 |  | 
| 1753 1422 | 
             
                return {
         | 
| 1754 | 
            -
                  ok, | 
| 1755 | 
            -
                  format | 
| 1423 | 
            +
                  ok,
         | 
| 1424 | 
            +
                  format,
         | 
| 1756 1425 | 
             
                  r: Math.min(255, Math.max(rgb.r, 0)),
         | 
| 1757 1426 | 
             
                  g: Math.min(255, Math.max(rgb.g, 0)),
         | 
| 1758 1427 | 
             
                  b: Math.min(255, Math.max(rgb.b, 0)),
         | 
| @@ -1781,7 +1450,8 @@ | |
| 1781 1450 | 
             
                    color = inputToRGB(color);
         | 
| 1782 1451 | 
             
                  }
         | 
| 1783 1452 | 
             
                  if (typeof color === 'number') {
         | 
| 1784 | 
            -
                     | 
| 1453 | 
            +
                    const len = `${color}`.length;
         | 
| 1454 | 
            +
                    color = `#${(len === 2 ? '0' : '00')}${color}`;
         | 
| 1785 1455 | 
             
                  }
         | 
| 1786 1456 | 
             
                  const {
         | 
| 1787 1457 | 
             
                    r, g, b, a, ok, format,
         | 
| @@ -1791,7 +1461,7 @@ | |
| 1791 1461 | 
             
                  const self = this;
         | 
| 1792 1462 |  | 
| 1793 1463 | 
             
                  /** @type {CP.ColorInput} */
         | 
| 1794 | 
            -
                  self.originalInput =  | 
| 1464 | 
            +
                  self.originalInput = input;
         | 
| 1795 1465 | 
             
                  /** @type {number} */
         | 
| 1796 1466 | 
             
                  self.r = r;
         | 
| 1797 1467 | 
             
                  /** @type {number} */
         | 
| @@ -2181,6 +1851,7 @@ | |
| 2181 1851 | 
             
                isOnePointZero,
         | 
| 2182 1852 | 
             
                isPercentage,
         | 
| 2183 1853 | 
             
                isValidCSSUnit,
         | 
| 1854 | 
            +
                isColorName,
         | 
| 2184 1855 | 
             
                pad2,
         | 
| 2185 1856 | 
             
                clamp01,
         | 
| 2186 1857 | 
             
                bound01,
         | 
| @@ -2198,10 +1869,11 @@ | |
| 2198 1869 | 
             
                hueToRgb,
         | 
| 2199 1870 | 
             
                hwbToRgb,
         | 
| 2200 1871 | 
             
                parseIntFromHex,
         | 
| 2201 | 
            -
                numberInputToObject,
         | 
| 2202 1872 | 
             
                stringInputToObject,
         | 
| 2203 1873 | 
             
                inputToRGB,
         | 
| 2204 1874 | 
             
                roundPart,
         | 
| 1875 | 
            +
                getElementStyle,
         | 
| 1876 | 
            +
                setElementStyle,
         | 
| 2205 1877 | 
             
                ObjectAssign,
         | 
| 2206 1878 | 
             
              });
         | 
| 2207 1879 |  | 
| @@ -2210,7 +1882,7 @@ | |
| 2210 1882 | 
             
               * Returns a color palette with a given set of parameters.
         | 
| 2211 1883 | 
             
               * @example
         | 
| 2212 1884 | 
             
               * new ColorPalette(0, 12, 10);
         | 
| 2213 | 
            -
               * // => { hue: 0, hueSteps: 12, lightSteps: 10, colors:  | 
| 1885 | 
            +
               * // => { hue: 0, hueSteps: 12, lightSteps: 10, colors: Array<Color> }
         | 
| 2214 1886 | 
             
               */
         | 
| 2215 1887 | 
             
              class ColorPalette {
         | 
| 2216 1888 | 
             
                /**
         | 
| @@ -2230,11 +1902,14 @@ | |
| 2230 1902 | 
             
                    [hue, hueSteps, lightSteps] = args;
         | 
| 2231 1903 | 
             
                  } else if (args.length === 2) {
         | 
| 2232 1904 | 
             
                    [hueSteps, lightSteps] = args;
         | 
| 1905 | 
            +
                    if ([hueSteps, lightSteps].some((n) => n < 1)) {
         | 
| 1906 | 
            +
                      throw TypeError('ColorPalette: when 2 arguments used, both must be larger than 0.');
         | 
| 1907 | 
            +
                    }
         | 
| 2233 1908 | 
             
                  } else {
         | 
| 2234 1909 | 
             
                    throw TypeError('ColorPalette requires minimum 2 arguments');
         | 
| 2235 1910 | 
             
                  }
         | 
| 2236 1911 |  | 
| 2237 | 
            -
                  /** @type { | 
| 1912 | 
            +
                  /** @type {Color[]} */
         | 
| 2238 1913 | 
             
                  const colors = [];
         | 
| 2239 1914 |  | 
| 2240 1915 | 
             
                  const hueStep = 360 / hueSteps;
         | 
| @@ -2263,7 +1938,7 @@ | |
| 2263 1938 | 
             
                  for (let i = 0; i < hueSteps; i += 1) {
         | 
| 2264 1939 | 
             
                    const currentHue = ((hue + i * hueStep) % 360) / 360;
         | 
| 2265 1940 | 
             
                    lightnessArray.forEach((l) => {
         | 
| 2266 | 
            -
                      colors.push(new Color({ h: currentHue, s: 1, l }) | 
| 1941 | 
            +
                      colors.push(new Color({ h: currentHue, s: 1, l }));
         | 
| 2267 1942 | 
             
                    });
         | 
| 2268 1943 | 
             
                  }
         | 
| 2269 1944 |  | 
| @@ -2274,6 +1949,310 @@ | |
| 2274 1949 | 
             
                }
         | 
| 2275 1950 | 
             
              }
         | 
| 2276 1951 |  | 
| 1952 | 
            +
              ObjectAssign(ColorPalette, { Color });
         | 
| 1953 | 
            +
             | 
| 1954 | 
            +
              /** @type {Record<string, string>} */
         | 
| 1955 | 
            +
              const colorPickerLabels = {
         | 
| 1956 | 
            +
                pickerLabel: 'Colour Picker',
         | 
| 1957 | 
            +
                appearanceLabel: 'Colour Appearance',
         | 
| 1958 | 
            +
                valueLabel: 'Colour Value',
         | 
| 1959 | 
            +
                toggleLabel: 'Select Colour',
         | 
| 1960 | 
            +
                presetsLabel: 'Colour Presets',
         | 
| 1961 | 
            +
                defaultsLabel: 'Colour Defaults',
         | 
| 1962 | 
            +
                formatLabel: 'Format',
         | 
| 1963 | 
            +
                alphaLabel: 'Alpha',
         | 
| 1964 | 
            +
                hexLabel: 'Hexadecimal',
         | 
| 1965 | 
            +
                hueLabel: 'Hue',
         | 
| 1966 | 
            +
                whitenessLabel: 'Whiteness',
         | 
| 1967 | 
            +
                blacknessLabel: 'Blackness',
         | 
| 1968 | 
            +
                saturationLabel: 'Saturation',
         | 
| 1969 | 
            +
                lightnessLabel: 'Lightness',
         | 
| 1970 | 
            +
                redLabel: 'Red',
         | 
| 1971 | 
            +
                greenLabel: 'Green',
         | 
| 1972 | 
            +
                blueLabel: 'Blue',
         | 
| 1973 | 
            +
              };
         | 
| 1974 | 
            +
             | 
| 1975 | 
            +
              /**
         | 
| 1976 | 
            +
               * A list of 17 color names used for WAI-ARIA compliance.
         | 
| 1977 | 
            +
               * @type {string[]}
         | 
| 1978 | 
            +
               */
         | 
| 1979 | 
            +
              const colorNames = ['white', 'black', 'grey', 'red', 'orange', 'brown', 'gold', 'olive', 'yellow', 'lime', 'green', 'teal', 'cyan', 'blue', 'violet', 'magenta', 'pink'];
         | 
| 1980 | 
            +
             | 
| 1981 | 
            +
              const tabIndex = 'tabindex';
         | 
| 1982 | 
            +
             | 
| 1983 | 
            +
              /**
         | 
| 1984 | 
            +
               * Check if a string is valid JSON string.
         | 
| 1985 | 
            +
               * @param {string} str the string input
         | 
| 1986 | 
            +
               * @returns {boolean} the query result
         | 
| 1987 | 
            +
               */
         | 
| 1988 | 
            +
              function isValidJSON(str) {
         | 
| 1989 | 
            +
                try {
         | 
| 1990 | 
            +
                  JSON.parse(str);
         | 
| 1991 | 
            +
                } catch (e) {
         | 
| 1992 | 
            +
                  return false;
         | 
| 1993 | 
            +
                }
         | 
| 1994 | 
            +
                return true;
         | 
| 1995 | 
            +
              }
         | 
| 1996 | 
            +
             | 
| 1997 | 
            +
              /**
         | 
| 1998 | 
            +
               * Shortcut for `String.toUpperCase()`.
         | 
| 1999 | 
            +
               *
         | 
| 2000 | 
            +
               * @param {string} source input string
         | 
| 2001 | 
            +
               * @returns {string} uppercase output string
         | 
| 2002 | 
            +
               */
         | 
| 2003 | 
            +
              const toUpperCase = (source) => source.toUpperCase();
         | 
| 2004 | 
            +
             | 
| 2005 | 
            +
              /**
         | 
| 2006 | 
            +
               * A global namespace for aria-haspopup.
         | 
| 2007 | 
            +
               * @type {string}
         | 
| 2008 | 
            +
               */
         | 
| 2009 | 
            +
              const ariaHasPopup = 'aria-haspopup';
         | 
| 2010 | 
            +
             | 
| 2011 | 
            +
              /**
         | 
| 2012 | 
            +
               * A global namespace for aria-hidden.
         | 
| 2013 | 
            +
               * @type {string}
         | 
| 2014 | 
            +
               */
         | 
| 2015 | 
            +
              const ariaHidden = 'aria-hidden';
         | 
| 2016 | 
            +
             | 
| 2017 | 
            +
              /**
         | 
| 2018 | 
            +
               * A global namespace for aria-labelledby.
         | 
| 2019 | 
            +
               * @type {string}
         | 
| 2020 | 
            +
               */
         | 
| 2021 | 
            +
              const ariaLabelledBy = 'aria-labelledby';
         | 
| 2022 | 
            +
             | 
| 2023 | 
            +
              /**
         | 
| 2024 | 
            +
               * This is a shortie for `document.createElement` method
         | 
| 2025 | 
            +
               * which allows you to create a new `HTMLElement` for a given `tagName`
         | 
| 2026 | 
            +
               * or based on an object with specific non-readonly attributes:
         | 
| 2027 | 
            +
               * `id`, `className`, `textContent`, `style`, etc.
         | 
| 2028 | 
            +
               * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/createElement
         | 
| 2029 | 
            +
               *
         | 
| 2030 | 
            +
               * @param {Record<string, string> | string} param `tagName` or object
         | 
| 2031 | 
            +
               * @return {HTMLElement | Element} a new `HTMLElement` or `Element`
         | 
| 2032 | 
            +
               */
         | 
| 2033 | 
            +
              function createElement(param) {
         | 
| 2034 | 
            +
                if (typeof param === 'string') {
         | 
| 2035 | 
            +
                  return getDocument().createElement(param);
         | 
| 2036 | 
            +
                }
         | 
| 2037 | 
            +
             | 
| 2038 | 
            +
                const { tagName } = param;
         | 
| 2039 | 
            +
                const attr = { ...param };
         | 
| 2040 | 
            +
                const newElement = createElement(tagName);
         | 
| 2041 | 
            +
                delete attr.tagName;
         | 
| 2042 | 
            +
                ObjectAssign(newElement, attr);
         | 
| 2043 | 
            +
                return newElement;
         | 
| 2044 | 
            +
              }
         | 
| 2045 | 
            +
             | 
| 2046 | 
            +
              /**
         | 
| 2047 | 
            +
               * This is a shortie for `document.createElementNS` method
         | 
| 2048 | 
            +
               * which allows you to create a new `HTMLElement` for a given `tagName`
         | 
| 2049 | 
            +
               * or based on an object with specific non-readonly attributes:
         | 
| 2050 | 
            +
               * `id`, `className`, `textContent`, `style`, etc.
         | 
| 2051 | 
            +
               * @see https://developer.mozilla.org/en-US/docs/Web/API/Document/createElementNS
         | 
| 2052 | 
            +
               *
         | 
| 2053 | 
            +
               * @param {string} namespace `namespaceURI` to associate with the new `HTMLElement`
         | 
| 2054 | 
            +
               * @param {Record<string, string> | string} param `tagName` or object
         | 
| 2055 | 
            +
               * @return {HTMLElement | Element} a new `HTMLElement` or `Element`
         | 
| 2056 | 
            +
               */
         | 
| 2057 | 
            +
              function createElementNS(namespace, param) {
         | 
| 2058 | 
            +
                if (typeof param === 'string') {
         | 
| 2059 | 
            +
                  return getDocument().createElementNS(namespace, param);
         | 
| 2060 | 
            +
                }
         | 
| 2061 | 
            +
             | 
| 2062 | 
            +
                const { tagName } = param;
         | 
| 2063 | 
            +
                const attr = { ...param };
         | 
| 2064 | 
            +
                const newElement = createElementNS(namespace, tagName);
         | 
| 2065 | 
            +
                delete attr.tagName;
         | 
| 2066 | 
            +
                ObjectAssign(newElement, attr);
         | 
| 2067 | 
            +
                return newElement;
         | 
| 2068 | 
            +
              }
         | 
| 2069 | 
            +
             | 
| 2070 | 
            +
              const vHidden = 'v-hidden';
         | 
| 2071 | 
            +
             | 
| 2072 | 
            +
              /**
         | 
| 2073 | 
            +
               * Returns the color form for `ColorPicker`.
         | 
| 2074 | 
            +
               *
         | 
| 2075 | 
            +
               * @param {CP.ColorPicker} self the `ColorPicker` instance
         | 
| 2076 | 
            +
               * @returns {HTMLElement | Element} a new `<div>` element with color component `<input>`
         | 
| 2077 | 
            +
               */
         | 
| 2078 | 
            +
              function getColorForm(self) {
         | 
| 2079 | 
            +
                const { format, id, componentLabels } = self;
         | 
| 2080 | 
            +
                const colorForm = createElement({
         | 
| 2081 | 
            +
                  tagName: 'div',
         | 
| 2082 | 
            +
                  className: `color-form ${format}`,
         | 
| 2083 | 
            +
                });
         | 
| 2084 | 
            +
             | 
| 2085 | 
            +
                let components = ['hex'];
         | 
| 2086 | 
            +
                if (format === 'rgb') components = ['red', 'green', 'blue', 'alpha'];
         | 
| 2087 | 
            +
                else if (format === 'hsl') components = ['hue', 'saturation', 'lightness', 'alpha'];
         | 
| 2088 | 
            +
                else if (format === 'hwb') components = ['hue', 'whiteness', 'blackness', 'alpha'];
         | 
| 2089 | 
            +
             | 
| 2090 | 
            +
                components.forEach((c) => {
         | 
| 2091 | 
            +
                  const [C] = format === 'hex' ? ['#'] : toUpperCase(c).split('');
         | 
| 2092 | 
            +
                  const cID = `color_${format}_${c}_${id}`;
         | 
| 2093 | 
            +
                  const formatLabel = componentLabels[`${c}Label`];
         | 
| 2094 | 
            +
                  const cInputLabel = createElement({ tagName: 'label' });
         | 
| 2095 | 
            +
                  setAttribute(cInputLabel, 'for', cID);
         | 
| 2096 | 
            +
                  cInputLabel.append(
         | 
| 2097 | 
            +
                    createElement({ tagName: 'span', ariaHidden: 'true', innerText: `${C}:` }),
         | 
| 2098 | 
            +
                    createElement({ tagName: 'span', className: vHidden, innerText: formatLabel }),
         | 
| 2099 | 
            +
                  );
         | 
| 2100 | 
            +
                  const cInput = createElement({
         | 
| 2101 | 
            +
                    tagName: 'input',
         | 
| 2102 | 
            +
                    id: cID,
         | 
| 2103 | 
            +
                    // name: cID, - prevent saving the value to a form
         | 
| 2104 | 
            +
                    type: format === 'hex' ? 'text' : 'number',
         | 
| 2105 | 
            +
                    value: c === 'alpha' ? '100' : '0',
         | 
| 2106 | 
            +
                    className: `color-input ${c}`,
         | 
| 2107 | 
            +
                  });
         | 
| 2108 | 
            +
                  setAttribute(cInput, 'autocomplete', 'off');
         | 
| 2109 | 
            +
                  setAttribute(cInput, 'spellcheck', 'false');
         | 
| 2110 | 
            +
             | 
| 2111 | 
            +
                  // alpha
         | 
| 2112 | 
            +
                  let max = '100';
         | 
| 2113 | 
            +
                  let step = '1';
         | 
| 2114 | 
            +
                  if (c !== 'alpha') {
         | 
| 2115 | 
            +
                    if (format === 'rgb') {
         | 
| 2116 | 
            +
                      max = '255'; step = '1';
         | 
| 2117 | 
            +
                    } else if (c === 'hue') {
         | 
| 2118 | 
            +
                      max = '360'; step = '1';
         | 
| 2119 | 
            +
                    }
         | 
| 2120 | 
            +
                  }
         | 
| 2121 | 
            +
                  ObjectAssign(cInput, {
         | 
| 2122 | 
            +
                    min: '0',
         | 
| 2123 | 
            +
                    max,
         | 
| 2124 | 
            +
                    step,
         | 
| 2125 | 
            +
                  });
         | 
| 2126 | 
            +
                  colorForm.append(cInputLabel, cInput);
         | 
| 2127 | 
            +
                });
         | 
| 2128 | 
            +
                return colorForm;
         | 
| 2129 | 
            +
              }
         | 
| 2130 | 
            +
             | 
| 2131 | 
            +
              /**
         | 
| 2132 | 
            +
               * A global namespace for aria-label.
         | 
| 2133 | 
            +
               * @type {string}
         | 
| 2134 | 
            +
               */
         | 
| 2135 | 
            +
              const ariaLabel = 'aria-label';
         | 
| 2136 | 
            +
             | 
| 2137 | 
            +
              /**
         | 
| 2138 | 
            +
               * A global namespace for aria-valuemin.
         | 
| 2139 | 
            +
               * @type {string}
         | 
| 2140 | 
            +
               */
         | 
| 2141 | 
            +
              const ariaValueMin = 'aria-valuemin';
         | 
| 2142 | 
            +
             | 
| 2143 | 
            +
              /**
         | 
| 2144 | 
            +
               * A global namespace for aria-valuemax.
         | 
| 2145 | 
            +
               * @type {string}
         | 
| 2146 | 
            +
               */
         | 
| 2147 | 
            +
              const ariaValueMax = 'aria-valuemax';
         | 
| 2148 | 
            +
             | 
| 2149 | 
            +
              /**
         | 
| 2150 | 
            +
               * Returns all color controls for `ColorPicker`.
         | 
| 2151 | 
            +
               *
         | 
| 2152 | 
            +
               * @param {CP.ColorPicker} self the `ColorPicker` instance
         | 
| 2153 | 
            +
               * @returns {HTMLElement | Element} color controls
         | 
| 2154 | 
            +
               */
         | 
| 2155 | 
            +
              function getColorControls(self) {
         | 
| 2156 | 
            +
                const { format, componentLabels } = self;
         | 
| 2157 | 
            +
                const {
         | 
| 2158 | 
            +
                  hueLabel, alphaLabel, lightnessLabel, saturationLabel,
         | 
| 2159 | 
            +
                  whitenessLabel, blacknessLabel,
         | 
| 2160 | 
            +
                } = componentLabels;
         | 
| 2161 | 
            +
             | 
| 2162 | 
            +
                const max1 = format === 'hsl' ? 360 : 100;
         | 
| 2163 | 
            +
                const max2 = format === 'hsl' ? 100 : 360;
         | 
| 2164 | 
            +
                const max3 = 100;
         | 
| 2165 | 
            +
             | 
| 2166 | 
            +
                let ctrl1Label = format === 'hsl'
         | 
| 2167 | 
            +
                  ? `${hueLabel} & ${lightnessLabel}`
         | 
| 2168 | 
            +
                  : `${lightnessLabel} & ${saturationLabel}`;
         | 
| 2169 | 
            +
             | 
| 2170 | 
            +
                ctrl1Label = format === 'hwb'
         | 
| 2171 | 
            +
                  ? `${whitenessLabel} & ${blacknessLabel}`
         | 
| 2172 | 
            +
                  : ctrl1Label;
         | 
| 2173 | 
            +
             | 
| 2174 | 
            +
                const ctrl2Label = format === 'hsl'
         | 
| 2175 | 
            +
                  ? `${saturationLabel}`
         | 
| 2176 | 
            +
                  : `${hueLabel}`;
         | 
| 2177 | 
            +
             | 
| 2178 | 
            +
                const colorControls = createElement({
         | 
| 2179 | 
            +
                  tagName: 'div',
         | 
| 2180 | 
            +
                  className: `color-controls ${format}`,
         | 
| 2181 | 
            +
                });
         | 
| 2182 | 
            +
             | 
| 2183 | 
            +
                const colorPointer = 'color-pointer';
         | 
| 2184 | 
            +
                const colorSlider = 'color-slider';
         | 
| 2185 | 
            +
             | 
| 2186 | 
            +
                const controls = [
         | 
| 2187 | 
            +
                  {
         | 
| 2188 | 
            +
                    i: 1,
         | 
| 2189 | 
            +
                    c: colorPointer,
         | 
| 2190 | 
            +
                    l: ctrl1Label,
         | 
| 2191 | 
            +
                    min: 0,
         | 
| 2192 | 
            +
                    max: max1,
         | 
| 2193 | 
            +
                  },
         | 
| 2194 | 
            +
                  {
         | 
| 2195 | 
            +
                    i: 2,
         | 
| 2196 | 
            +
                    c: colorSlider,
         | 
| 2197 | 
            +
                    l: ctrl2Label,
         | 
| 2198 | 
            +
                    min: 0,
         | 
| 2199 | 
            +
                    max: max2,
         | 
| 2200 | 
            +
                  },
         | 
| 2201 | 
            +
                  {
         | 
| 2202 | 
            +
                    i: 3,
         | 
| 2203 | 
            +
                    c: colorSlider,
         | 
| 2204 | 
            +
                    l: alphaLabel,
         | 
| 2205 | 
            +
                    min: 0,
         | 
| 2206 | 
            +
                    max: max3,
         | 
| 2207 | 
            +
                  },
         | 
| 2208 | 
            +
                ];
         | 
| 2209 | 
            +
             | 
| 2210 | 
            +
                controls.forEach((template) => {
         | 
| 2211 | 
            +
                  const {
         | 
| 2212 | 
            +
                    i, c, l, min, max,
         | 
| 2213 | 
            +
                  } = template;
         | 
| 2214 | 
            +
                  const control = createElement({
         | 
| 2215 | 
            +
                    tagName: 'div',
         | 
| 2216 | 
            +
                    className: 'color-control',
         | 
| 2217 | 
            +
                  });
         | 
| 2218 | 
            +
                  setAttribute(control, 'role', 'presentation');
         | 
| 2219 | 
            +
             | 
| 2220 | 
            +
                  control.append(
         | 
| 2221 | 
            +
                    createElement({
         | 
| 2222 | 
            +
                      tagName: 'div',
         | 
| 2223 | 
            +
                      className: `visual-control visual-control${i}`,
         | 
| 2224 | 
            +
                    }),
         | 
| 2225 | 
            +
                  );
         | 
| 2226 | 
            +
             | 
| 2227 | 
            +
                  const knob = createElement({
         | 
| 2228 | 
            +
                    tagName: 'div',
         | 
| 2229 | 
            +
                    className: `${c} knob`,
         | 
| 2230 | 
            +
                    ariaLive: 'polite',
         | 
| 2231 | 
            +
                  });
         | 
| 2232 | 
            +
             | 
| 2233 | 
            +
                  setAttribute(knob, ariaLabel, l);
         | 
| 2234 | 
            +
                  setAttribute(knob, 'role', 'slider');
         | 
| 2235 | 
            +
                  setAttribute(knob, tabIndex, '0');
         | 
| 2236 | 
            +
                  setAttribute(knob, ariaValueMin, `${min}`);
         | 
| 2237 | 
            +
                  setAttribute(knob, ariaValueMax, `${max}`);
         | 
| 2238 | 
            +
                  control.append(knob);
         | 
| 2239 | 
            +
                  colorControls.append(control);
         | 
| 2240 | 
            +
                });
         | 
| 2241 | 
            +
             | 
| 2242 | 
            +
                return colorControls;
         | 
| 2243 | 
            +
              }
         | 
| 2244 | 
            +
             | 
| 2245 | 
            +
              /**
         | 
| 2246 | 
            +
               * Helps setting CSS variables to the color-menu.
         | 
| 2247 | 
            +
               * @param {HTMLElement} element
         | 
| 2248 | 
            +
               * @param {Record<string,any>} props
         | 
| 2249 | 
            +
               */
         | 
| 2250 | 
            +
              function setCSSProperties(element, props) {
         | 
| 2251 | 
            +
                ObjectKeys(props).forEach((prop) => {
         | 
| 2252 | 
            +
                  element.style.setProperty(prop, props[prop]);
         | 
| 2253 | 
            +
                });
         | 
| 2254 | 
            +
              }
         | 
| 2255 | 
            +
             | 
| 2277 2256 | 
             
              /**
         | 
| 2278 2257 | 
             
               * Returns a color-defaults with given values and class.
         | 
| 2279 2258 | 
             
               * @param {CP.ColorPicker} self
         | 
| @@ -2307,7 +2286,8 @@ | |
| 2307 2286 | 
             
                optionSize = fit > 5 && isMultiLine ? 1.5 : optionSize;
         | 
| 2308 2287 | 
             
                const menuHeight = `${(rowCount || 1) * optionSize}rem`;
         | 
| 2309 2288 | 
             
                const menuHeightHover = `calc(${rowCountHover} * ${optionSize}rem + ${rowCountHover - 1} * ${gap})`;
         | 
| 2310 | 
            -
             | 
| 2289 | 
            +
                /** @type {HTMLUListElement} */
         | 
| 2290 | 
            +
                // @ts-ignore -- <UL> is an `HTMLElement`
         | 
| 2311 2291 | 
             
                const menu = createElement({
         | 
| 2312 2292 | 
             
                  tagName: 'ul',
         | 
| 2313 2293 | 
             
                  className: finalClass,
         | 
| @@ -2315,7 +2295,7 @@ | |
| 2315 2295 | 
             
                setAttribute(menu, 'role', 'listbox');
         | 
| 2316 2296 | 
             
                setAttribute(menu, ariaLabel, menuLabel);
         | 
| 2317 2297 |  | 
| 2318 | 
            -
                if (isScrollable) { | 
| 2298 | 
            +
                if (isScrollable) {
         | 
| 2319 2299 | 
             
                  setCSSProperties(menu, {
         | 
| 2320 2300 | 
             
                    '--grid-item-size': `${optionSize}rem`,
         | 
| 2321 2301 | 
             
                    '--grid-fit': fit,
         | 
| @@ -2326,15 +2306,19 @@ | |
| 2326 2306 | 
             
                }
         | 
| 2327 2307 |  | 
| 2328 2308 | 
             
                colorsArray.forEach((x) => {
         | 
| 2329 | 
            -
                   | 
| 2330 | 
            -
                   | 
| 2331 | 
            -
             | 
| 2309 | 
            +
                  let [value, label] = typeof x === 'string' ? x.trim().split(':') : [];
         | 
| 2310 | 
            +
                  if (x instanceof Color) {
         | 
| 2311 | 
            +
                    value = x.toHexString();
         | 
| 2312 | 
            +
                    label = value;
         | 
| 2313 | 
            +
                  }
         | 
| 2314 | 
            +
                  const color = new Color(x instanceof Color ? x : value, format);
         | 
| 2315 | 
            +
                  const isActive = color.toString() === getAttribute(input, 'value');
         | 
| 2332 2316 | 
             
                  const active = isActive ? ' active' : '';
         | 
| 2333 2317 |  | 
| 2334 2318 | 
             
                  const option = createElement({
         | 
| 2335 2319 | 
             
                    tagName: 'li',
         | 
| 2336 2320 | 
             
                    className: `color-option${active}`,
         | 
| 2337 | 
            -
                    innerText: `${label ||  | 
| 2321 | 
            +
                    innerText: `${label || value}`,
         | 
| 2338 2322 | 
             
                  });
         | 
| 2339 2323 |  | 
| 2340 2324 | 
             
                  setAttribute(option, tabIndex, '0');
         | 
| @@ -2343,7 +2327,7 @@ | |
| 2343 2327 | 
             
                  setAttribute(option, ariaSelected, isActive ? 'true' : 'false');
         | 
| 2344 2328 |  | 
| 2345 2329 | 
             
                  if (isOptionsMenu) {
         | 
| 2346 | 
            -
                    setElementStyle(option, { backgroundColor:  | 
| 2330 | 
            +
                    setElementStyle(option, { backgroundColor: value });
         | 
| 2347 2331 | 
             
                  }
         | 
| 2348 2332 |  | 
| 2349 2333 | 
             
                  menu.append(option);
         | 
| @@ -2352,55 +2336,10 @@ | |
| 2352 2336 | 
             
              }
         | 
| 2353 2337 |  | 
| 2354 2338 | 
             
              /**
         | 
| 2355 | 
            -
             | 
| 2356 | 
            -
             | 
| 2357 | 
            -
             | 
| 2358 | 
            -
             | 
| 2359 | 
            -
              function isValidJSON(str) {
         | 
| 2360 | 
            -
                try {
         | 
| 2361 | 
            -
                  JSON.parse(str);
         | 
| 2362 | 
            -
                } catch (e) {
         | 
| 2363 | 
            -
                  return false;
         | 
| 2364 | 
            -
                }
         | 
| 2365 | 
            -
                return true;
         | 
| 2366 | 
            -
              }
         | 
| 2367 | 
            -
             | 
| 2368 | 
            -
              var version = "0.0.1";
         | 
| 2369 | 
            -
             | 
| 2370 | 
            -
              // @ts-ignore
         | 
| 2371 | 
            -
             | 
| 2372 | 
            -
              const Version = version;
         | 
| 2373 | 
            -
             | 
| 2374 | 
            -
              // ColorPicker GC
         | 
| 2375 | 
            -
              // ==============
         | 
| 2376 | 
            -
              const colorPickerString = 'color-picker';
         | 
| 2377 | 
            -
              const colorPickerSelector = `[data-function="${colorPickerString}"]`;
         | 
| 2378 | 
            -
              const colorPickerParentSelector = `.${colorPickerString},${colorPickerString}`;
         | 
| 2379 | 
            -
              const colorPickerDefaults = {
         | 
| 2380 | 
            -
                componentLabels: colorPickerLabels,
         | 
| 2381 | 
            -
                colorLabels: colorNames,
         | 
| 2382 | 
            -
                format: 'rgb',
         | 
| 2383 | 
            -
                colorPresets: false,
         | 
| 2384 | 
            -
                colorKeywords: false,
         | 
| 2385 | 
            -
              };
         | 
| 2386 | 
            -
             | 
| 2387 | 
            -
              // ColorPicker Static Methods
         | 
| 2388 | 
            -
              // ==========================
         | 
| 2389 | 
            -
             | 
| 2390 | 
            -
              /** @type {CP.GetInstance<ColorPicker>} */
         | 
| 2391 | 
            -
              const getColorPickerInstance = (element) => getInstance(element, colorPickerString);
         | 
| 2392 | 
            -
             | 
| 2393 | 
            -
              /** @type {CP.InitCallback<ColorPicker>} */
         | 
| 2394 | 
            -
              const initColorPicker = (element) => new ColorPicker(element);
         | 
| 2395 | 
            -
             | 
| 2396 | 
            -
              // ColorPicker Private Methods
         | 
| 2397 | 
            -
              // ===========================
         | 
| 2398 | 
            -
             | 
| 2399 | 
            -
              /**
         | 
| 2400 | 
            -
               * Generate HTML markup and update instance properties.
         | 
| 2401 | 
            -
               * @param {ColorPicker} self
         | 
| 2402 | 
            -
               */
         | 
| 2403 | 
            -
              function initCallback(self) {
         | 
| 2339 | 
            +
              * Generate HTML markup and update instance properties.
         | 
| 2340 | 
            +
              * @param {CP.ColorPicker} self
         | 
| 2341 | 
            +
              */
         | 
| 2342 | 
            +
              function setMarkup(self) {
         | 
| 2404 2343 | 
             
                const {
         | 
| 2405 2344 | 
             
                  input, parent, format, id, componentLabels, colorKeywords, colorPresets,
         | 
| 2406 2345 | 
             
                } = self;
         | 
| @@ -2415,9 +2354,7 @@ | |
| 2415 2354 | 
             
                self.color = new Color(color, format);
         | 
| 2416 2355 |  | 
| 2417 2356 | 
             
                // set initial controls dimensions
         | 
| 2418 | 
            -
                 | 
| 2419 | 
            -
                const dropClass = isMobile ? ' mobile' : '';
         | 
| 2420 | 
            -
                const formatString = format === 'hex' ? hexLabel : format.toUpperCase();
         | 
| 2357 | 
            +
                const formatString = format === 'hex' ? hexLabel : toUpperCase(format);
         | 
| 2421 2358 |  | 
| 2422 2359 | 
             
                const pickerBtn = createElement({
         | 
| 2423 2360 | 
             
                  id: `picker-btn-${id}`,
         | 
| @@ -2434,7 +2371,7 @@ | |
| 2434 2371 |  | 
| 2435 2372 | 
             
                const pickerDropdown = createElement({
         | 
| 2436 2373 | 
             
                  tagName: 'div',
         | 
| 2437 | 
            -
                  className:  | 
| 2374 | 
            +
                  className: 'color-dropdown picker',
         | 
| 2438 2375 | 
             
                });
         | 
| 2439 2376 | 
             
                setAttribute(pickerDropdown, ariaLabelledBy, `picker-btn-${id}`);
         | 
| 2440 2377 | 
             
                setAttribute(pickerDropdown, 'role', 'group');
         | 
| @@ -2450,7 +2387,7 @@ | |
| 2450 2387 | 
             
                if (colorKeywords || colorPresets) {
         | 
| 2451 2388 | 
             
                  const presetsDropdown = createElement({
         | 
| 2452 2389 | 
             
                    tagName: 'div',
         | 
| 2453 | 
            -
                    className:  | 
| 2390 | 
            +
                    className: 'color-dropdown scrollable menu',
         | 
| 2454 2391 | 
             
                  });
         | 
| 2455 2392 |  | 
| 2456 2393 | 
             
                  // color presets
         | 
| @@ -2500,6 +2437,37 @@ | |
| 2500 2437 | 
             
                setAttribute(input, tabIndex, '-1');
         | 
| 2501 2438 | 
             
              }
         | 
| 2502 2439 |  | 
| 2440 | 
            +
              var version = "0.0.2alpha1";
         | 
| 2441 | 
            +
             | 
| 2442 | 
            +
              // @ts-ignore
         | 
| 2443 | 
            +
             | 
| 2444 | 
            +
              const Version = version;
         | 
| 2445 | 
            +
             | 
| 2446 | 
            +
              // ColorPicker GC
         | 
| 2447 | 
            +
              // ==============
         | 
| 2448 | 
            +
              const colorPickerString = 'color-picker';
         | 
| 2449 | 
            +
              const colorPickerSelector = `[data-function="${colorPickerString}"]`;
         | 
| 2450 | 
            +
              const colorPickerParentSelector = `.${colorPickerString},${colorPickerString}`;
         | 
| 2451 | 
            +
              const colorPickerDefaults = {
         | 
| 2452 | 
            +
                componentLabels: colorPickerLabels,
         | 
| 2453 | 
            +
                colorLabels: colorNames,
         | 
| 2454 | 
            +
                format: 'rgb',
         | 
| 2455 | 
            +
                colorPresets: false,
         | 
| 2456 | 
            +
                colorKeywords: false,
         | 
| 2457 | 
            +
              };
         | 
| 2458 | 
            +
             | 
| 2459 | 
            +
              // ColorPicker Static Methods
         | 
| 2460 | 
            +
              // ==========================
         | 
| 2461 | 
            +
             | 
| 2462 | 
            +
              /** @type {CP.GetInstance<ColorPicker>} */
         | 
| 2463 | 
            +
              const getColorPickerInstance = (element) => getInstance(element, colorPickerString);
         | 
| 2464 | 
            +
             | 
| 2465 | 
            +
              /** @type {CP.InitCallback<ColorPicker>} */
         | 
| 2466 | 
            +
              const initColorPicker = (element) => new ColorPicker(element);
         | 
| 2467 | 
            +
             | 
| 2468 | 
            +
              // ColorPicker Private Methods
         | 
| 2469 | 
            +
              // ===========================
         | 
| 2470 | 
            +
             | 
| 2503 2471 | 
             
              /**
         | 
| 2504 2472 | 
             
               * Add / remove `ColorPicker` main event listeners.
         | 
| 2505 2473 | 
             
               * @param {ColorPicker} self
         | 
| @@ -2733,7 +2701,7 @@ | |
| 2733 2701 | 
             
                  self.handleKnobs = self.handleKnobs.bind(self);
         | 
| 2734 2702 |  | 
| 2735 2703 | 
             
                  // generate markup
         | 
| 2736 | 
            -
                   | 
| 2704 | 
            +
                  setMarkup(self);
         | 
| 2737 2705 |  | 
| 2738 2706 | 
             
                  const [colorPicker, colorMenu] = getElementsByClassName('color-dropdown', parent);
         | 
| 2739 2707 | 
             
                  // set main elements
         | 
| @@ -2929,7 +2897,7 @@ | |
| 2929 2897 | 
             
                  const self = this;
         | 
| 2930 2898 | 
             
                  const { activeElement } = getDocument(self.input);
         | 
| 2931 2899 |  | 
| 2932 | 
            -
                  if (( | 
| 2900 | 
            +
                  if ((e.type === touchmoveEvent && self.dragElement)
         | 
| 2933 2901 | 
             
                    || (activeElement && self.controlKnobs.includes(activeElement))) {
         | 
| 2934 2902 | 
             
                    e.stopPropagation();
         | 
| 2935 2903 | 
             
                    e.preventDefault();
         | 
| @@ -3747,4 +3715,4 @@ | |
| 3747 3715 |  | 
| 3748 3716 | 
             
              return ColorPicker;
         | 
| 3749 3717 |  | 
| 3750 | 
            -
            })) | 
| 3718 | 
            +
            }));
         |