primevue
Version: 
[](https://opensource.org/licenses/MIT) [](https://badge.fury.io/js/primevue) [ • 26.2 kB
JavaScript
this.primevue = this.primevue || {};
this.primevue.colorpicker = (function (utils, OverlayEventBus, vue) {
    'use strict';
    function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
    var OverlayEventBus__default = /*#__PURE__*/_interopDefaultLegacy(OverlayEventBus);
    var script = {
        name: 'ColorPicker',
        emits: ['update:modelValue'],
        props: {
            modelValue: {
                type: null,
                default: null
            },
            defaultColor: {
                type: null,
                default: 'ff0000'
            },
            inline: {
                type: Boolean,
                default: false
            },
            format: {
                type: String,
                default: 'hex'
            },
            disabled: {
                type: Boolean,
                default: false
            },
            tabindex: {
                type: String,
                default: null
            },
            autoZIndex: {
                type: Boolean,
                default: true
            },
            baseZIndex: {
                type: Number,
                default: 0
            },
            ariaLabelledBy: {
                type: String,
                default: null
            },
            appendTo: {
                type: String,
                default: 'body'
            },
            panelClass: null
        },
        data() {
            return {
                overlayVisible: false
            };
        },
        hsbValue: null,
        outsideClickListener: null,
        documentMouseMoveListener: null,
        documentMouseUpListener: null,
        scrollHandler: null,
        resizeListener: null,
        hueDragging: null,
        colorDragging: null,
        selfUpdate: null,
        picker: null,
        colorSelector: null,
        colorHandle: null,
        hueView: null,
        hueHandle: null,
        beforeUnmount() {
            this.unbindOutsideClickListener();
            this.unbindDragListeners();
            this.unbindResizeListener();
            if (this.scrollHandler) {
                this.scrollHandler.destroy();
                this.scrollHandler = null;
            }
            if (this.picker && this.autoZIndex) {
                utils.ZIndexUtils.clear(this.picker);
            }
            this.clearRefs();
        },
        mounted() {
            this.updateUI();
        },
        watch: {
            modelValue: {
                immediate: true,
                handler(newValue) {
                    this.hsbValue = this.toHSB(newValue);
                    if (this.selfUpdate)
                        this.selfUpdate = false;
                    else
                        this.updateUI();
                }
            }
        },
        methods: {
            pickColor(event) {
                let rect = this.colorSelector.getBoundingClientRect();
                let top = rect.top + (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0);
                let left = rect.left + document.body.scrollLeft;
                let saturation = Math.floor(100 * (Math.max(0, Math.min(150, ((event.pageX || event.changedTouches[0].pageX)- left)))) / 150);
                let brightness = Math.floor(100 * (150 - Math.max(0, Math.min(150, ((event.pageY || event.changedTouches[0].pageY) - top)))) / 150);
                this.hsbValue = this.validateHSB({
                    h: this.hsbValue.h,
                    s: saturation,
                    b: brightness
                });
                this.selfUpdate = true;
                this.updateColorHandle();
                this.updateInput();
                this.updateModel();
            },
            pickHue(event) {
                let top = this.hueView.getBoundingClientRect().top + (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0);
                this.hsbValue = this.validateHSB({
                    h: Math.floor(360 * (150 - Math.max(0, Math.min(150, ((event.pageY || event.changedTouches[0].pageY) - top)))) / 150),
                    s: 100,
                    b: 100
                });
                this.selfUpdate = true;
                this.updateColorSelector();
                this.updateHue();
                this.updateModel();
                this.updateInput();
            },
            updateModel() {
                switch(this.format) {
                    case 'hex':
                        this.$emit('update:modelValue', this.HSBtoHEX(this.hsbValue));
                    break;
                    case 'rgb':
                        this.$emit('update:modelValue', this.HSBtoRGB(this.hsbValue));
                    break;
                    case 'hsb':
                        this.$emit('update:modelValue', this.hsbValue);
                    break;
                }
            },
            updateColorSelector() {
                if (this.colorSelector) {
                    let hsbValue = this.validateHSB({
                        h: this.hsbValue.h,
                        s: 100,
                        b: 100
                    });
                    this.colorSelector.style.backgroundColor = '#' + this.HSBtoHEX(hsbValue);
                }
            },
            updateColorHandle() {
                if (this.colorHandle) {
                    this.colorHandle.style.left = Math.floor(150 * this.hsbValue.s / 100) + 'px';
                    this.colorHandle.style.top = Math.floor(150 * (100 - this.hsbValue.b) / 100) + 'px';
                }
            },
            updateHue() {
                if (this.hueHandle) {
                    this.hueHandle.style.top = Math.floor(150 - (150 * this.hsbValue.h / 360)) + 'px';
                }
            },
            updateInput() {
                if (this.$refs.input) {
                    this.$refs.input.style.backgroundColor = '#' + this.HSBtoHEX(this.hsbValue);
                }
            },
            updateUI() {
                this.updateHue();
                this.updateColorHandle();
                this.updateInput();
                this.updateColorSelector();
            },
            validateHSB(hsb) {
                return {
                    h: Math.min(360, Math.max(0, hsb.h)),
                    s: Math.min(100, Math.max(0, hsb.s)),
                    b: Math.min(100, Math.max(0, hsb.b))
                };
            },
            validateRGB(rgb) {
                return {
                    r: Math.min(255, Math.max(0, rgb.r)),
                    g: Math.min(255, Math.max(0, rgb.g)),
                    b: Math.min(255, Math.max(0, rgb.b))
                };
            },
            validateHEX(hex) {
                var len = 6 - hex.length;
                if (len > 0) {
                    var o = [];
                    for (var i=0; i<len; i++) {
                        o.push('0');
                    }
                    o.push(hex);
                    hex = o.join('');
                }
                return hex;
            },
            HEXtoRGB(hex) {
                let hexValue = parseInt(((hex.indexOf('#') > -1) ? hex.substring(1) : hex), 16);
                return {r: hexValue >> 16, g: (hexValue & 0x00FF00) >> 8, b: (hexValue & 0x0000FF)};
            },
            HEXtoHSB(hex) {
                return this.RGBtoHSB(this.HEXtoRGB(hex));
            },
            RGBtoHSB(rgb) {
                var hsb = {
                    h: 0,
                    s: 0,
                    b: 0
                };
                var min = Math.min(rgb.r, rgb.g, rgb.b);
                var max = Math.max(rgb.r, rgb.g, rgb.b);
                var delta = max - min;
                hsb.b = max;
                hsb.s = max !== 0 ? 255 * delta / max : 0;
                if (hsb.s !== 0) {
                    if (rgb.r === max) {
                        hsb.h = (rgb.g - rgb.b) / delta;
                    } else if (rgb.g === max) {
                        hsb.h = 2 + (rgb.b - rgb.r) / delta;
                    } else {
                        hsb.h = 4 + (rgb.r - rgb.g) / delta;
                    }
                } else {
                    hsb.h = -1;
                }
                hsb.h *= 60;
                if (hsb.h < 0) {
                    hsb.h += 360;
                }
                hsb.s *= 100/255;
                hsb.b *= 100/255;
                return hsb;
            },
            HSBtoRGB(hsb) {
                var rgb = {
                    r: null, g: null, b: null
                };
                var h = Math.round(hsb.h);
                var s = Math.round(hsb.s*255/100);
                var v = Math.round(hsb.b*255/100);
                if (s === 0) {
                    rgb = {
                        r: v,
                        g: v,
                        b: v
                    };
                }
                else {
                    var t1 = v;
                    var t2 = (255-s)*v/255;
                    var t3 = (t1-t2)*(h%60)/60;
                    if (h===360) h = 0;
                    if (h<60) {rgb.r=t1;	rgb.b=t2; rgb.g=t2+t3;}
                    else if (h<120) {rgb.g=t1; rgb.b=t2;	rgb.r=t1-t3;}
                    else if (h<180) {rgb.g=t1; rgb.r=t2;	rgb.b=t2+t3;}
                    else if (h<240) {rgb.b=t1; rgb.r=t2;	rgb.g=t1-t3;}
                    else if (h<300) {rgb.b=t1; rgb.g=t2;	rgb.r=t2+t3;}
                    else if (h<360) {rgb.r=t1; rgb.g=t2;	rgb.b=t1-t3;}
                    else {rgb.r=0; rgb.g=0;	rgb.b=0;}
                }
                return {r:Math.round(rgb.r), g:Math.round(rgb.g), b:Math.round(rgb.b)};
            },
            RGBtoHEX(rgb) {
                var hex = [
                    rgb.r.toString(16),
                    rgb.g.toString(16),
                    rgb.b.toString(16)
                ];
                for (var key in hex) {
                    if (hex[key].length === 1) {
                        hex[key] = '0' + hex[key];
                    }
                }
                return hex.join('');
            },
            HSBtoHEX(hsb) {
                return this.RGBtoHEX(this.HSBtoRGB(hsb));
            },
            toHSB(value) {
                let hsb;
                if (value) {
                    switch (this.format) {
                        case 'hex':
                            hsb = this.HEXtoHSB(value);
                        break;
                        case 'rgb':
                            hsb = this.RGBtoHSB(value);
                        break;
                        case 'hsb':
                            hsb = value;
                        break;
                    }
                }
                else {
                    hsb = this.HEXtoHSB(this.defaultColor);
                }
                return hsb;
            },
            onOverlayEnter(el) {
                this.updateUI();
                this.alignOverlay();
                this.bindOutsideClickListener();
                this.bindScrollListener();
                this.bindResizeListener();
                if (this.autoZIndex) {
                    utils.ZIndexUtils.set('overlay', el, this.$primevue.config.zIndex.overlay);
                }
            },
            onOverlayLeave() {
                this.unbindOutsideClickListener();
                this.unbindScrollListener();
                this.unbindResizeListener();
                this.clearRefs();
            },
            onOverlayAfterLeave(el) {
                if (this.autoZIndex) {
                    utils.ZIndexUtils.clear(el);
                }
            },
            alignOverlay() {
                if (this.appendDisabled)
                    utils.DomHandler.relativePosition(this.picker, this.$refs.input);
                else
                    utils.DomHandler.absolutePosition(this.picker, this.$refs.input);
            },
            onInputClick() {
                if (this.disabled) {
                    return;
                }
                this.overlayVisible = !this.overlayVisible;
            },
            onInputKeydown(event) {
                switch(event.which) {
                    //space
                    case 32:
                        this.overlayVisible = !this.overlayVisible;
                        event.preventDefault();
                    break;
                    //escape and tab
                    case 27:
                    case 9:
                        this.overlayVisible = false;
                    break;
                }
            },
            onColorMousedown(event) {
                if (this.disabled) {
                    return;
                }
                this.bindDragListeners();
                this.onColorDragStart(event);
            },
            onColorDragStart(event) {
                if (this.disabled) {
                    return;
                }
                this.colorDragging = true;
                this.pickColor(event);
                utils.DomHandler.addClass(this.$el, 'p-colorpicker-dragging');
                event.preventDefault();
            },
            onDrag(event) {
                if (this.colorDragging) {
                    this.pickColor(event);
                    event.preventDefault();
                }
                if (this.hueDragging) {
                    this.pickHue(event);
                    event.preventDefault();
                }
            },
            onDragEnd() {
                this.colorDragging = false;
                this.hueDragging = false;
                utils.DomHandler.removeClass(this.$el, 'p-colorpicker-dragging');
                this.unbindDragListeners();
            },
            onHueMousedown(event) {
                if (this.disabled) {
                    return;
                }
                this.bindDragListeners();
                this.onHueDragStart(event);
            },
            onHueDragStart(event) {
                if (this.disabled) {
                    return;
                }
                this.hueDragging = true;
                this.pickHue(event);
                utils.DomHandler.addClass(this.$el, 'p-colorpicker-dragging');
            },
            isInputClicked(event) {
                return this.$refs.input && this.$refs.input.isSameNode(event.target);
            },
            bindDragListeners() {
                this.bindDocumentMouseMoveListener();
                this.bindDocumentMouseUpListener();
            },
            unbindDragListeners() {
                this.unbindDocumentMouseMoveListener();
                this.unbindDocumentMouseUpListener();
            },
            bindOutsideClickListener() {
                if (!this.outsideClickListener) {
                    this.outsideClickListener = (event) => {
                        if (this.overlayVisible && this.picker && !this.picker.contains(event.target) && !this.isInputClicked(event)) {
                            this.overlayVisible = false;
                        }
                    };
                    document.addEventListener('click', this.outsideClickListener);
                }
            },
            unbindOutsideClickListener() {
                if (this.outsideClickListener) {
                    document.removeEventListener('click', this.outsideClickListener);
                    this.outsideClickListener = null;
                }
            },
            bindScrollListener() {
                if (!this.scrollHandler) {
                    this.scrollHandler = new utils.ConnectedOverlayScrollHandler(this.$refs.container, () => {
                        if (this.overlayVisible) {
                            this.overlayVisible = false;
                        }
                    });
                }
                this.scrollHandler.bindScrollListener();
            },
            unbindScrollListener() {
                if (this.scrollHandler) {
                    this.scrollHandler.unbindScrollListener();
                }
            },
            bindResizeListener() {
                if (!this.resizeListener) {
                    this.resizeListener = () => {
                        if (this.overlayVisible) {
                            this.overlayVisible = false;
                        }
                    };
                    window.addEventListener('resize', this.resizeListener);
                }
            },
            unbindResizeListener() {
                if (this.resizeListener) {
                    window.removeEventListener('resize', this.resizeListener);
                    this.resizeListener = null;
                }
            },
            bindDocumentMouseMoveListener() {
                if (!this.documentMouseMoveListener) {
                    this.documentMouseMoveListener = this.onDrag.bind(this);
                    document.addEventListener('mousemove', this.documentMouseMoveListener);
                }
            },
            unbindDocumentMouseMoveListener() {
                if (this.documentMouseMoveListener) {
                    document.removeEventListener('mousemove', this.documentMouseMoveListener);
                    this.documentMouseMoveListener = null;
                }
            },
            bindDocumentMouseUpListener() {
                if (!this.documentMouseUpListener) {
                    this.documentMouseUpListener = this.onDragEnd.bind(this);
                    document.addEventListener('mouseup', this.documentMouseUpListener);
                }
            },
            unbindDocumentMouseUpListener() {
                if (this.documentMouseUpListener) {
                    document.removeEventListener('mouseup', this.documentMouseUpListener);
                    this.documentMouseUpListener = null;
                }
            },
            pickerRef(el) {
                this.picker = el;
            },
            colorSelectorRef(el) {
                this.colorSelector = el;
            },
            colorHandleRef(el) {
                this.colorHandle = el;
            },
            hueViewRef(el) {
                this.hueView = el;
            },
            hueHandleRef(el) {
                this.hueHandle = el;
            },
            clearRefs() {
                this.picker = null;
                this.colorSelector = null;
                this.colorHandle = null;
                this.hueView = null;
                this.hueHandle = null;
            },
            onOverlayClick(event) {
                OverlayEventBus__default['default'].emit('overlay-click', {
                    originalEvent: event,
                    target: this.$el
                });
            }
        },
        computed: {
            containerClass() {
                return ['p-colorpicker p-component', {'p-colorpicker-overlay': !this.inline}];
            },
            inputClass() {
                return ['p-colorpicker-preview p-inputtext', {'p-disabled': this.disabled}];
            },
            pickerClass() {
                return ['p-colorpicker-panel', this.panelClass, {
                    'p-colorpicker-overlay-panel': !this.inline, 'p-disabled': this.disabled,
                    'p-input-filled': this.$primevue.config.inputStyle === 'filled',
                    'p-ripple-disabled': this.$primevue.config.ripple === false
                }];
            },
            appendDisabled() {
                return this.appendTo === 'self' || this.inline;
            },
            appendTarget() {
                return this.appendDisabled ? null : this.appendTo;
            }
        }
    };
    const _hoisted_1 = { class: "p-colorpicker-content" };
    const _hoisted_2 = { class: "p-colorpicker-color" };
    function render(_ctx, _cache, $props, $setup, $data, $options) {
      return (vue.openBlock(), vue.createBlock("div", {
        ref: "container",
        class: $options.containerClass
      }, [
        (!$props.inline)
          ? (vue.openBlock(), vue.createBlock("input", {
              key: 0,
              ref: "input",
              type: "text",
              class: $options.inputClass,
              readonly: "readonly",
              tabindex: $props.tabindex,
              disabled: $props.disabled,
              onClick: _cache[1] || (_cache[1] = (...args) => ($options.onInputClick && $options.onInputClick(...args))),
              onKeydown: _cache[2] || (_cache[2] = (...args) => ($options.onInputKeydown && $options.onInputKeydown(...args))),
              "aria-labelledby": $props.ariaLabelledBy
            }, null, 42, ["tabindex", "disabled", "aria-labelledby"]))
          : vue.createCommentVNode("", true),
        (vue.openBlock(), vue.createBlock(vue.Teleport, {
          to: $options.appendTarget,
          disabled: $options.appendDisabled
        }, [
          vue.createVNode(vue.Transition, {
            name: "p-connected-overlay",
            onEnter: $options.onOverlayEnter,
            onLeave: $options.onOverlayLeave,
            onAfterLeave: $options.onOverlayAfterLeave
          }, {
            default: vue.withCtx(() => [
              ($props.inline ? true : $data.overlayVisible)
                ? (vue.openBlock(), vue.createBlock("div", {
                    key: 0,
                    ref: $options.pickerRef,
                    class: $options.pickerClass,
                    onClick: _cache[11] || (_cache[11] = (...args) => ($options.onOverlayClick && $options.onOverlayClick(...args)))
                  }, [
                    vue.createVNode("div", _hoisted_1, [
                      vue.createVNode("div", {
                        ref: $options.colorSelectorRef,
                        class: "p-colorpicker-color-selector",
                        onMousedown: _cache[3] || (_cache[3] = $event => ($options.onColorMousedown($event))),
                        onTouchstart: _cache[4] || (_cache[4] = $event => ($options.onColorDragStart($event))),
                        onTouchmove: _cache[5] || (_cache[5] = $event => ($options.onDrag($event))),
                        onTouchend: _cache[6] || (_cache[6] = $event => ($options.onDragEnd()))
                      }, [
                        vue.createVNode("div", _hoisted_2, [
                          vue.createVNode("div", {
                            ref: $options.colorHandleRef,
                            class: "p-colorpicker-color-handle"
                          }, null, 512)
                        ])
                      ], 544),
                      vue.createVNode("div", {
                        ref: $options.hueViewRef,
                        class: "p-colorpicker-hue",
                        onMousedown: _cache[7] || (_cache[7] = $event => ($options.onHueMousedown($event))),
                        onTouchstart: _cache[8] || (_cache[8] = $event => ($options.onHueDragStart($event))),
                        onTouchmove: _cache[9] || (_cache[9] = $event => ($options.onDrag($event))),
                        onTouchend: _cache[10] || (_cache[10] = $event => ($options.onDragEnd()))
                      }, [
                        vue.createVNode("div", {
                          ref: $options.hueHandleRef,
                          class: "p-colorpicker-hue-handle"
                        }, null, 512)
                      ], 544)
                    ])
                  ], 2))
                : vue.createCommentVNode("", true)
            ]),
            _: 1
          }, 8, ["onEnter", "onLeave", "onAfterLeave"])
        ], 8, ["to", "disabled"]))
      ], 2))
    }
    function styleInject(css, ref) {
      if ( ref === void 0 ) ref = {};
      var insertAt = ref.insertAt;
      if (!css || typeof document === 'undefined') { return; }
      var head = document.head || document.getElementsByTagName('head')[0];
      var style = document.createElement('style');
      style.type = 'text/css';
      if (insertAt === 'top') {
        if (head.firstChild) {
          head.insertBefore(style, head.firstChild);
        } else {
          head.appendChild(style);
        }
      } else {
        head.appendChild(style);
      }
      if (style.styleSheet) {
        style.styleSheet.cssText = css;
      } else {
        style.appendChild(document.createTextNode(css));
      }
    }
    var css_248z = "\n.p-colorpicker {\n    display: inline-block;\n}\n.p-colorpicker-dragging {\n    cursor: pointer;\n}\n.p-colorpicker-overlay {\n    position: relative;\n}\n.p-colorpicker-panel {\n    position: relative;\n    width: 193px;\n    height: 166px;\n}\n.p-colorpicker-overlay-panel {\n    position: absolute;\n}\n.p-colorpicker-preview {\n    cursor: pointer;\n}\n.p-colorpicker-panel .p-colorpicker-content {\n    position: relative;\n}\n.p-colorpicker-panel .p-colorpicker-color-selector {\n    width: 150px;\n    height: 150px;\n    top: 8px;\n    left: 8px;\n    position: absolute;\n}\n.p-colorpicker-panel .p-colorpicker-color {\n     width: 150px;\n     height: 150px;\n}\n.p-colorpicker-panel .p-colorpicker-color-handle {\n     position: absolute;\n     top: 0px;\n     left: 150px;\n     border-radius: 100%;\n     width: 10px;\n     height: 10px;\n     border-width: 1px;\n     border-style: solid;\n     margin: -5px 0 0 -5px;\n     cursor: pointer;\n     opacity: .85;\n}\n.p-colorpicker-panel .p-colorpicker-hue {\n    width: 17px;\n    height: 150px;\n    top: 8px;\n    left: 167px;\n    position: absolute;\n    opacity: .85;\n}\n.p-colorpicker-panel .p-colorpicker-hue-handle {\n     position: absolute;\n     top: 150px;\n     left: 0px;\n     width: 21px;\n     margin-left: -2px;\n     margin-top: -5px;\n     height: 10px;\n     border-width: 2px;\n     border-style: solid;\n     opacity: .85;\n     cursor: pointer;\n}\n";
    styleInject(css_248z);
    script.render = render;
    return script;
}(primevue.utils, primevue.overlayeventbus, Vue));