diff --git a/.eslintignore b/.eslintignore index 4c92c7fa..4feee441 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1,5 +1,5 @@ _locales icons modules/noto-sans/* -modules/color-picker/* +modules/internal/color-picker/* resources diff --git a/modules/internal/color-picker/color-picker.css b/modules/internal/color-picker/color-picker.css index c9a20555..c3f3d96e 100644 --- a/modules/internal/color-picker/color-picker.css +++ b/modules/internal/color-picker/color-picker.css @@ -6,40 +6,47 @@ .color-picker *::after { box-sizing: border-box; } + .color-picker { position: absolute; top: 0; left: 0; z-index: 9999; - box-shadow: 1px 3px 6px rgba(0, 0, 0, .5); + box-shadow: 1px 3px 6px rgba(0, 0, 0, 0.5); } + .color-picker > div { display: flex; height: 10em; border: 1px solid #000; color: #000; } + .color-picker > div * { border-color: inherit; color: inherit; } + .color-picker i { font: inherit; - font-size: 12px; /* Measure the color picker control size by measuring the text size */ + font-size: 12px; + /* Measure the color picker control size by measuring the text size */ } + .color-picker\:a, .color-picker\:h, .color-picker\:sv { background-size: 100% 100%; position: relative; + -webkit-touch-callout: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + -webkit-tap-highlight-color: rgba(0, 0, 0, 0); + -webkit-tap-highlight-color: transparent; } -.color-picker\:a, -.color-picker\:h { - width: 1.5em; - border-left: 1px solid; - cursor: ns-resize; - overflow: hidden; -} + .color-picker\:a div, .color-picker\:h div, .color-picker\:sv div { @@ -49,6 +56,15 @@ bottom: 0; left: 0; } + +.color-picker\:a, +.color-picker\:h { + width: 1.5em; + border-left: 1px solid; + cursor: ns-resize; + overflow: hidden; +} + .color-picker\:a i, .color-picker\:h i { display: block; @@ -59,6 +75,7 @@ left: 0; z-index: 2; } + .color-picker\:a i::before, .color-picker\:h i::before { display: block; @@ -68,15 +85,40 @@ right: 0; bottom: 0; left: 0; - border:.25em solid; + border: .25em solid; border-top-color: transparent; border-bottom-color: transparent; } + +.color-picker\:a div { + z-index: 2; +} + +.color-picker\:a div + div { + background-image: linear-gradient(45deg, #ddd 25%, transparent 25%, transparent 75%, #ddd 75%, #ddd 100%), linear-gradient(45deg, #ddd 25%, #fff 25%, #fff 75%, #ddd 75%, #ddd 100%); + background-size: .5em .5em; + background-position: 0 0, .25em .25em; + z-index: 1; +} + +.color-picker\:h div { + background-image: linear-gradient(to top, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%); +} + .color-picker\:sv { width: 10em; cursor: crosshair; overflow: hidden; } + +.color-picker\:sv div + div { + background-image: linear-gradient(to right, #fff, rgba(255, 255, 255, 0)); +} + +.color-picker\:sv div + div + div { + background-image: linear-gradient(to top, #000, rgba(0, 0, 0, 0)); +} + .color-picker\:sv i { display: block; width: .75em; @@ -86,6 +128,7 @@ right: -.375em; z-index: 2; } + .color-picker\:sv i::before { display: block; content: ""; @@ -98,32 +141,3 @@ border-radius: 100%; box-shadow: 0 0 2px #000; } -.color-picker\:a div { - z-index: 2; -} -.color-picker\:a div + div { - background-image: linear-gradient(45deg, #ddd 25%, transparent 25%, transparent 75%, #ddd 75%, #ddd 100%), linear-gradient(45deg, #ddd 25%, #fff 25%, #fff 75%, #ddd 75%, #ddd 100%); - background-size: .5em .5em; - background-position: 0 0, .25em .25em; - z-index: 1; -} -.color-picker\:h div { - background-image: linear-gradient(to top, #f00 0%, #ff0 17%, #0f0 33%, #0ff 50%, #00f 67%, #f0f 83%, #f00 100%); -} -.color-picker\:sv div + div { - background-image: linear-gradient(to right, #fff, rgba(255, 255, 255, 0)); -} -.color-picker\:sv div + div + div { - background-image: linear-gradient(to top, #000, rgba(0, 0, 0, 0)); -} -.color-picker\:a, -.color-picker\:h, -.color-picker\:sv { - -webkit-touch-callout: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); - -webkit-tap-highlight-color: transparent; -} diff --git a/modules/internal/color-picker/color-picker.js b/modules/internal/color-picker/color-picker.js index 746f36b1..4ae04fe5 100644 --- a/modules/internal/color-picker/color-picker.js +++ b/modules/internal/color-picker/color-picker.js @@ -1,594 +1,834 @@ -/*! - * ============================================================== - * COLOR PICKER 2.1.4 - * ============================================================== - * Author: Taufik Nurrohman - * License: MIT - * -------------------------------------------------------------- - */ - -(function(win, doc, name) { - - var html = doc.documentElement, - HEX = 'HEX', - top = 'top', - right = 'right', - left = 'left', - px = 'px', - delay = win.setTimeout, - instances = 'instances', - - downEvents = ['touchstart', 'mousedown'], - moveEvents = ['touchmove', 'mousemove'], - resizeEvents = ['orientationchange', 'resize'], - upEvents = ['touchend', 'mouseup']; - - // Convert cursor position to RGBA - function P2RGB(a) { - var h = +a[0], - s = +a[1], - v = +a[2], - r, g, b, i, f, p, q, t; - i = Math.floor(h * 6); - f = h * 6 - i; - p = v * (1 - s); - q = v * (1 - f * s); - t = v * (1 - (1 - f) * s); - i = i || 0; - q = q || 0; - t = t || 0; - switch (i % 6) { - case 0: - r = v, g = t, b = p; - break; - case 1: - r = q, g = v, b = p; - break; - case 2: - r = p, g = v, b = t; - break; - case 3: - r = p, g = q, b = v; - break; - case 4: - r = t, g = p, b = v; - break; - case 5: - r = v, g = p, b = q; - break; - } - return [toRound(r * 255), toRound(g * 255), toRound(b * 255), isSet(a[3]) ? +a[3] : 1]; - } - - // Convert RGBA to HSVA - function RGB2HSV(a) { - var r = +a[0] / 255, - g = +a[1] / 255, - b = +a[2] / 255, - max = Math.max(r, g, b), - min = Math.min(r, g, b), - h, s, v = max, - d = max - min, - s = max === 0 ? 0 : d / max; - if (max === min) { - h = 0; // Achromatic - } else { - switch (max) { - case r: - h = (g - b) / d + (g < b ? 6 : 0); - break; - case g: - h = (b - r) / d + 2; - break; - case b: - h = (r - g) / d + 4; - break; - } - h /= 6; - } - return [h, s, v, isSet(a[3]) ? +a[3] : 1]; - } - - function axixGet(el, e) { - var touches = 'touches', - clientX = 'clientX', - clientY = 'clientY', - x = !!e[touches] ? e[touches][0][clientX] : e[clientX], - y = !!e[touches] ? e[touches][0][clientY] : e[clientY], - offset = offsetGet(el); - return [x - offset[0], y - offset[1]]; - } - - function closestGet(a, b) { - if (a === b) { - return a; - } - while ((a = a.parentElement) && a !== b); - return a; - } - - function offsetGet(el) { - var x, y, rect; - if (el === win) { - x = win.pageXOffset || html.scrollLeft; - y = win.pageYOffset || html.scrollTop; - } else { - rect = el.getBoundingClientRect(); - x = rect.left; - y = rect.top; - } - return [x, y]; - } - - function sizeGet(el) { - return el === win ? [win.innerWidth, win.innerHeight] : [el.offsetWidth, el.offsetHeight]; - } - - function doPreventDefault(e) { - e && e.preventDefault(); - } - - function isFunction(x) { - return 'function' === typeof x; - } - - function isObject(x) { - return 'object' === typeof x; - } - - function isSet(x) { - return 'undefined' !== typeof x && null !== x; - } - - function isString(x) { - return 'string' === typeof x; - } - - function toEdge(a, b) { - if (a < b[0]) return b[0]; - if (a > b[1]) return b[1]; - return a; - } - - function toInt(a, b) { - return parseInt(a, b || 10); - } - - function toNode(a, b, c) { - a = doc.createElement(a); - b && b.appendChild(a); - c && (a.className = c); - return a; - } - - function toRound(a) { - return Math.round(a); - } - - function toString(a, b) { - return a.toString(b); - } - - function eventsLet(to, events, fn) { - for (var i = 0, j = events.length; i < j; ++i) { - to.removeEventListener(events[i], fn, false); - } - } - - function eventsSet(to, events, fn) { - for (var i = 0, j = events.length; i < j; ++i) { - to.addEventListener(events[i], fn, false); - } - } - - function styleSet(to, prop, value) { - to.style[prop] = value; - } - - (function($$) { - - $$.version = '2.1.4'; - - $$.state = { - 'class': 'color-picker', - 'color': HEX, - 'parent': null - }; - - // Collect all instance(s) - $$[instances] = {}; - - $$[HEX] = function(x) { - if (isString(x)) { - var count = (x = x.trim()).length; - if ((4 === count || 7 === count) && '#' === x[0]) { - if (/^#([a-f\d]{3}){1,2}$/i.test(x)) { - if (4 === count) { - return [toInt(x[1] + x[1], 16), toInt(x[2] + x[2], 16), toInt(x[3] + x[3], 16), 1]; - } - return [toInt(x[1] + x[2], 16), toInt(x[3] + x[4], 16), toInt(x[5] + x[6], 16), 1]; - } - } else if ((5 === count || 9 === count) && '#' === x[0]) { - if (/^#([a-f\d]{3,4}){1,2}$/i.test(x)) { - if (5 === count) { - return [toInt(x[1] + x[1], 16), toInt(x[2] + x[2], 16), toInt(x[3] + x[3], 16), toInt(x[4] + x[4], 16) / 255]; - } - return [toInt(x[1] + x[2], 16), toInt(x[3] + x[4], 16), toInt(x[5] + x[6], 16), toInt(x[7] + x[8], 16) / 255]; - } - } - return [0, 0, 0, 1]; // Default to black - } - return '#' + ('000000' + toString(+x[2] | (+x[1] << 8) | (+x[0] << 16), 16)).slice(-6) + (isSet(x[3]) && x[3] < 1 ? toString(toRound(x[3] * 255) + 0x10000, 16).substr(-2) : ""); - }; - - })(win[name] = function(source, o) { - - if (!source) return; - - var $ = this, - $$ = win[name], - hooks = {}, - state = Object.assign({}, $$.state, isString(o) ? { - 'color': o - } : (o || {})), - cn = state['class'], - self = toNode('div', 0, cn); - - // Already instantiated, skip! - if (source[name]) { - return $; - } - - // Return new instance if `CP` was called without the `new` operator - if (!($ instanceof $$)) { - return new $$(source, o); - } - - // Store color picker instance to `CP.instances` - $$[instances][source.id || source.name || Object.keys($$[instances]).length] = $; - - // Mark current DOM as active color picker to prevent duplicate instance - source[name] = 1; - - $.visible = false; - - function value(a) { - var to = $$[isFunction($$[state.color]) ? state.color : HEX], - color; - if (color = source.dataset.color) { - if (isSet(a)) { - return (source.dataset.color = to(color)); - } - return to(color); - } - if (color = source.value) { - if (isSet(a)) { - return (source.value = to(color)); - } - return to(color); - } - if (color = source.textContent) { - if (isSet(a)) { - return (source.textContent = to(color)); - } - return to(color); - } - if (isSet(a)) { - return; // Do nothing - } - return [0, 0, 0, 1]; // Default to black - } - - function hookLet(name, fn) { - if (!isSet(name)) { - return (hooks = {}), $; - } - if (isSet(hooks[name])) { - if (isSet(fn)) { - for (var i = 0, j = hooks[name].length; i < j; ++i) { - if (fn === hooks[name][i]) { - hooks[name].splice(i, 1); - } - } - // Clean-up empty hook(s) - if (0 === j) { - delete hooks[name]; - } - } else { - delete hooks[name]; - } - } - return $; - } - - function hookSet(name, fn) { - if (!isSet(hooks[name])) { - hooks[name] = []; - } - if (isSet(fn)) { - hooks[name].push(fn); - } - return $; - } - - function hookFire(name, lot) { - if (!isSet(hooks[name])) { - return $; - } - for (var i = 0, j = hooks[name].length; i < j; ++i) { - hooks[name][i].apply($, lot); - } - return $; - } - - var doEnter, - doExit, - doFit, - doFitTo, - body = doc.body, - color = value(), - data = RGB2HSV(color), - C = toNode('div', self), - SV = toNode('div', C, cn + ':sv'), - H = toNode('div', C, cn + ':h'), - A = toNode('div', C, cn + ':a'), - - SVColor = toNode('div', SV), - SVSaturation = toNode('div', SV), - SVValue = toNode('div', SV), - SVCursor = toNode('i', SV), - - HColor = toNode('div', H), - HCursor = toNode('i', H), - - AColor = toNode('div', A), - APattern = toNode('div', A), - ACursor = toNode('i', A), - - SVStarting = 0, - HStarting = 0, - AStarting = 0, - - SVDragging = 0, - HDragging = 0, - ADragging = 0; - - function isVisible() { - return self.parentNode; - } - - function doClick(e) { - if (hooks.focus) { - hookFire('focus', color); - } else { - var t = e.target, - isSource = source === closestGet(t, source); - if (isSource) { - !isVisible() && doEnter(state.parent); - } else { - doExit(); - } - } - } - - function doApply(isFirst, to) { - - // Refresh value - data = RGB2HSV(color = value()); - - if (!isFirst) { - (to || state.parent || body).appendChild(self), ($.visible = true); - } - - doEnter = function(to) { - return doApply(0, to), hookFire('enter', color), $; - }; - - doExit = function() { - var exist = isVisible(); - if (exist) { - exist.removeChild(self); - $.current = null; - $.visible = false; - } - eventsLet(SV, downEvents, doDownSV); - eventsLet(H, downEvents, doDownH); - eventsLet(A, downEvents, doDownA); - eventsLet(doc, moveEvents, doMove); - eventsLet(doc, upEvents, doStop); - eventsLet(win, resizeEvents, doFitTo); - return hookFire('exit', color), $; - }; - - doFit = function(to) { - var winSize = sizeGet(win), - htmlSize = sizeGet(html), - scrollBarSizeV = winSize[0] - htmlSize[0], // Vertical scroll bar - scrollBarSizeH = winSize[1] - html.clientHeight, // Horizontal scroll bar - winOffset = offsetGet(win), - sourceOffset = offsetGet(source), - selfSize = sizeGet(self), - selfSizeWidth = selfSize[0], - selfSizeHeight = selfSize[1], - selfOffsetLeft = sourceOffset[0] + winOffset[0], - selfOffsetTop = sourceOffset[1] + winOffset[1] + sizeGet(source)[1]; // Drop! - if (isObject(to)) { - isSet(to[0]) && (selfOffsetLeft = to[0]); - isSet(to[1]) && (selfOffsetTop = to[1]); - } else { - var minX = winOffset[0], - minY = winOffset[1], - maxX = winOffset[0] + winSize[0] - selfSizeWidth - scrollBarSizeV, - maxY = winOffset[1] + winSize[1] - selfSizeHeight - scrollBarSizeH; - selfOffsetLeft = toEdge(selfOffsetLeft, [minX, maxX]) >> 0; - selfOffsetTop = toEdge(selfOffsetTop, [minY, maxY]) >> 0; - } - styleSet(self, left, selfOffsetLeft + px); - styleSet(self, top, selfOffsetTop + px); - return hookFire('fit', color), $; - }; - - doFitTo = function() { - return doFit(); - }; - - var SVSize = sizeGet(SV), - SVSizeWidth = SVSize[0], - SVSizeHeight = SVSize[1], - SVCursorSize = sizeGet(SVCursor), - SVCursorSizeWidth = SVCursorSize[0], - SVCursorSizeHeight = SVCursorSize[1], - HSizeHeight = sizeGet(H)[1], - HCursorSizeHeight = sizeGet(HCursor)[1], - ASizeHeight = sizeGet(A)[1], - ACursorSizeHeight = sizeGet(ACursor)[1]; - - if (isFirst) { - eventsSet(source, downEvents, doClick); - delay(function() { - hookFire('change', color); - }, 1); - } else { - eventsSet(SV, downEvents, doDownSV); - eventsSet(H, downEvents, doDownH); - eventsSet(A, downEvents, doDownA); - eventsSet(doc, moveEvents, doMove); - eventsSet(doc, upEvents, doStop); - eventsSet(win, resizeEvents, doFitTo); - doFit(); - } - - function doMove(e) { - SVDragging && cursorSVSet(e); - HDragging && cursorHSet(e); - ADragging && cursorASet(e); - color = P2RGB(data); - if (SVDragging || HDragging || ADragging) { - hookFire((SVStarting || HStarting || AStarting ? 'start' : 'drag'), color); - hookFire('change', color); - } - SVStarting = HStarting = AStarting = 0; - } - - function doStop(e) { - color = P2RGB(data); - var t = e.target, - isSource = source === closestGet(t, source), - isSelf = self === closestGet(t, self); - $.current = null; - if (!isSource && !isSelf) { - if (hooks.blur) { - hookFire('blur', color); - } else { - // Click outside the source or picker element to exit - isVisible() && doExit(); - } - } else { - if (isSelf) { - if (SVDragging || HDragging || ADragging) { - hookFire('stop', color); - } - } - } - SVDragging = HDragging = ADragging = 0; - } - - function doDownSV(e) { - $.current = SV; - SVStarting = SVDragging = 1; - doMove(e); - doPreventDefault(e); - } - - function doDownH(e) { - $.current = H; - HStarting = HDragging = 1; - doMove(e); - doPreventDefault(e); - } - - function doDownA(e) { - $.current = A; - AStarting = ADragging = 1; - doMove(e); - doPreventDefault(e); - } - - function cursorSet(x) { - isSet(x[1]) && styleSet(SVCursor, right, (SVSizeWidth - (SVCursorSizeWidth / 2) - (SVSizeWidth * +x[1])) + px); - isSet(x[2]) && styleSet(SVCursor, top, (SVSizeHeight - (SVCursorSizeHeight / 2) - (SVSizeHeight * +x[2])) + px); - isSet(x[0]) && styleSet(HCursor, top, (HSizeHeight - (HCursorSizeHeight / 2) - (HSizeHeight * +x[0])) + px); - isSet(x[3]) && styleSet(ACursor, top, (ASizeHeight - (ACursorSizeHeight / 2) - (ASizeHeight * +x[3])) + px); - } - - $.get = function() { - return value(); - }; - - $.set = function(r, g, b, a) { - data = RGB2HSV([r, g, b, a]); - return colorSet(), $; - }; - - function cursorSVSet(e) { - var SVPoint = axixGet(SV, e), - x = toEdge(SVPoint[0], [0, SVSizeWidth]), - y = toEdge(SVPoint[1], [0, SVSizeHeight]); - data[1] = 1 - ((SVSizeWidth - x) / SVSizeWidth); - data[2] = (SVSizeHeight - y) / SVSizeHeight; - colorSet(); - } - - function cursorHSet(e) { - data[0] = (HSizeHeight - toEdge(axixGet(H, e)[1], [0, HSizeHeight])) / HSizeHeight; - colorSet(); - } - - function cursorASet(e) { - data[3] = (ASizeHeight - toEdge(axixGet(A, e)[1], [0, ASizeHeight])) / ASizeHeight; - colorSet(); - } - - function colorSet() { - cursorSet(data); - var a = P2RGB(data), - b = P2RGB([data[0], 1, 1]); - styleSet(SVColor, 'backgroundColor', 'rgb(' + b[0] + ',' + b[1] + ',' + b[2] + ')'); - styleSet(AColor, 'backgroundImage', 'linear-gradient(rgb(' + a[0] + ',' + a[1] + ',' + a[2] + '),transparent)'); - } colorSet(); - - } doApply(1); - - $.color = function(r, g, b, a) { - return $$[isFunction($$[state.color]) ? state.color : HEX]([r, g, b, a]); - }; - - $.current = null; - $.enter = doEnter; - $.exit = doExit; - $.fire = hookFire; - $.fit = doFit; - $.hooks = hooks; - $.off = hookLet; - $.on = hookSet; - - $.pop = function() { - if (!source[name]) { - return $; // Already ejected - } - delete source[name]; - eventsLet(source, downEvents, doClick); - return doExit(), hookFire('pop', color); - }; - - $.value = function(r, g, b, a) { - return $.set(r, g, b, a), hookFire('change', [r, g, b, a]); - }; - - $.self = self; - $.source = source; - $.state = state; - - }); - -})(window, document, 'CP'); \ No newline at end of file + /*! + * + * The MIT License (MIT) + * + * Copyright © 2021 Taufik Nurrohman + * + * + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the “Software”), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + + (function(global, factory) { + typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.CP = factory()); + })(this, function() { + 'use strict'; + var isArray = function isArray(x) { + return Array.isArray(x); + }; + var isDefined = function isDefined(x) { + return 'undefined' !== typeof x; + }; + var isFunction = function isFunction(x) { + return 'function' === typeof x; + }; + var isInstance = function isInstance(x, of ) { + return x && isSet( of ) && x instanceof of ; + }; + var isNull = function isNull(x) { + return null === x; + }; + var isNumber = function isNumber(x) { + return 'number' === typeof x; + }; + var isNumeric = function isNumeric(x) { + return /^-?(?:\d*.)?\d+$/.test(x + ""); + }; + var isObject = function isObject(x, isPlain) { + if (isPlain === void 0) { + isPlain = true; + } + if ('object' !== typeof x) { + return false; + } + return isPlain ? isInstance(x, Object) : true; + }; + var isSet = function isSet(x) { + return isDefined(x) && !isNull(x); + }; + var isString = function isString(x) { + return 'string' === typeof x; + }; + var fromJSON = function fromJSON(x) { + var value = null; + try { + value = JSON.parse(x); + } catch (e) {} + return value; + }; + var fromStates = function fromStates() { + for (var _len = arguments.length, lot = new Array(_len), _key = 0; _key < _len; _key++) { + lot[_key] = arguments[_key]; + } + return Object.assign.apply(Object, [{}].concat(lot)); + }; + var fromValue = function fromValue(x) { + if (isArray(x)) { + return x.map(function(v) { + return fromValue(x); + }); + } + if (isObject(x)) { + for (var k in x) { + x[k] = fromValue(x[k]); + } + return x; + } + if (false === x) { + return 'false'; + } + if (null === x) { + return 'null'; + } + if (true === x) { + return 'true'; + } + return "" + x; + }; + var toCaseCamel = function toCaseCamel(x) { + return x.replace(/[-_.](\w)/g, function(m0, m1) { + return toCaseUpper(m1); + }); + }; + var toCaseUpper = function toCaseUpper(x) { + return x.toUpperCase(); + }; + var toCount = function toCount(x) { + return x.length; + }; + var toEdge = function toEdge(x, edges) { + if (isSet(edges[0]) && x < edges[0]) { + return edges[0]; + } + if (isSet(edges[1]) && x > edges[1]) { + return edges[1]; + } + return x; + }; + var toJSON = function toJSON(x) { + return JSON.stringify(x); + }; + var toNumber = function toNumber(x, base) { + if (base === void 0) { + base = 10; + } + return base ? parseInt(x, base) : parseFloat(x); + }; + var toObjectCount = function toObjectCount(x) { + return toCount(toObjectKeys(x)); + }; + var toObjectKeys = function toObjectKeys(x) { + return Object.keys(x); + }; + var toRound = function toRound(x) { + return isNumber(x) ? Math.round(x) : null; + }; + var toString = function toString(x, base) { + if (base === void 0) { + base = 10; + } + return isNumber(x) ? x.toString(base) : "" + x; + }; + var toValue = function toValue(x) { + if (isArray(x)) { + return x.map(function(v) { + return toValue(v); + }); + } + if (isNumeric(x)) { + return toNumber(x); + } + if (isObject(x)) { + for (var k in x) { + x[k] = toValue(x[k]); + } + return x; + } + if ('false' === x) { + return false; + } + if ('null' === x) { + return null; + } + if ('true' === x) { + return true; + } + return x; + }; + var D = document; + var W = window; + var B = D.body; + var R = D.documentElement; + var getAttribute = function getAttribute(node, attribute, parseValue) { + if (parseValue === void 0) { + parseValue = true; + } + if (!hasAttribute(node, attribute)) { + return null; + } + var value = node.getAttribute(attribute); + return parseValue ? toValue(value) : value; + }; + var getDatum = function getDatum(node, datum, parseValue) { + if (parseValue === void 0) { + parseValue = true; + } + var value = getAttribute(node, 'data-' + datum, parseValue), + v = (value + "").trim(); + if (parseValue && v && ('[' === v[0] && ']' === v.slice(-1) || '{' === v[0] && '}' === v.slice(-1)) && null !== (v = fromJSON(value))) { + return v; + } + return value; + }; + var getParent = function getParent(node) { + return node.parentNode || null; + }; + var getState = function getState(node, state) { + return hasState(node, state) && node[state] || null; + }; + var getText = function getText(node, trim) { + if (trim === void 0) { + trim = true; + } + var state = 'textContent'; + if (!hasState(node, state)) { + return false; + } + var content = node[state]; + content = trim ? content.trim() : content; + return "" !== content ? content : null; + }; + var hasAttribute = function hasAttribute(node, attribute) { + return node.hasAttribute(attribute); + }; + var hasState = function hasState(node, state) { + return state in node; + }; + var isWindow = function isWindow(node) { + return node === W; + }; + var letAttribute = function letAttribute(node, attribute) { + return node.removeAttribute(attribute), node; + }; + var letElement = function letElement(node) { + var parent = getParent(node); + return node.remove(), parent; + }; + var setAttribute = function setAttribute(node, attribute, value) { + if (true === value) { + value = attribute; + } + return node.setAttribute(attribute, fromValue(value)), node; + }; + var setAttributes = function setAttributes(node, attributes) { + var value; + for (var attribute in attributes) { + value = attributes[attribute]; + if (value || "" === value || 0 === value) { + setAttribute(node, attribute, value); + } else { + letAttribute(node, attribute); + } + } + return node; + }; + var setChildLast = function setChildLast(parent, node) { + return parent.append(node), node; + }; + var setDatum = function setDatum(node, datum, value) { + if (isArray(value) || isObject(value)) { + value = toJSON(value); + } + return setAttribute(node, 'data-' + datum, value); + }; + var setElement = function setElement(node, content, attributes) { + node = isString(node) ? D.createElement(node) : node; + if (isObject(content)) { + attributes = content; + content = false; + } + if (isString(content)) { + setHTML(node, content); + } + if (isObject(attributes)) { + setAttributes(node, attributes); + } + return node; + }; + var setHTML = function setHTML(node, content, trim) { + if (trim === void 0) { + trim = true; + } + if (null === content) { + return node; + } + var state = 'innerHTML'; + return hasState(node, state) && (node[state] = trim ? content.trim() : content), node; + }; + var setState = function setState(node, key, value) { + return node[key] = value, node; + }; + var setStyle = function setStyle(node, style, value) { + if (isNumber(value)) { + value += 'px'; + } + return node.style[toCaseCamel(style)] = fromValue(value), node; + }; + var setText = function setText(node, content, trim) { + if (trim === void 0) { + trim = true; + } + if (null === content) { + return node; + } + var state = 'textContent'; + return hasState(node, state) && (node[state] = trim ? content.trim() : content), node; + }; + var offEvent = function offEvent(name, node, then) { + node.removeEventListener(name, then); + }; + var offEventDefault = function offEventDefault(e) { + return e && e.preventDefault(); + }; + var offEvents = function offEvents(names, node, then) { + names.forEach(function(name) { + return offEvent(name, node, then); + }); + }; + var onEvent = function onEvent(name, node, then, options) { + if (options === void 0) { + options = false; + } + node.addEventListener(name, then, options); + }; + var onEvents = function onEvents(names, node, then, options) { + if (options === void 0) { + options = false; + } + names.forEach(function(name) { + return onEvent(name, node, then, options); + }); + }; + + function hook($) { + var hooks = {}; + + function fire(name, data) { + if (!isSet(hooks[name])) { + return $; + } + hooks[name].forEach(function(then) { + return then.apply($, data); + }); + return $; + } + + function off(name, then) { + if (!isSet(name)) { + return hooks = {}, $; + } + if (isSet(hooks[name])) { + if (isSet(then)) { + for (var i = 0, _j = hooks[name].length; i < _j; ++i) { + if (then === hooks[name][i]) { + hooks[name].splice(i, 1); + break; + } + } // Clean-up empty hook(s) + if (0 === j) { + delete hooks[name]; + } + } else { + delete hooks[name]; + } + } + return $; + } + + function on(name, then) { + if (!isSet(hooks[name])) { + hooks[name] = []; + } + if (isSet(then)) { + hooks[name].push(then); + } + return $; + } + $.hooks = hooks; + $.fire = fire; + $.off = off; + $.on = on; + return $; + } + var getAxis = function getAxis(event, node) { + var touches = event.touches, + x = touches ? touches[0].clientX : event.clientX, + y = touches ? touches[0].clientY : event.clientY; + if (node) { + var rect = getRect(node); + return [x - rect[0], y - rect[1], rect[0], rect[1]]; + } + return [x, y]; + }; + var getRect = function getRect(node) { + var h, rect, w, x, y, X, Y; + if (isWindow(node)) { + x = node.pageXOffset || R.scrollLeft || B.scrollLeft; + y = node.pageYOffset || R.scrollTop || B.scrollTop; + w = node.innerWidth; + h = node.innerHeight; + } else { + rect = node.getBoundingClientRect(); + x = rect.left; + y = rect.top; + w = rect.width; + h = rect.height; + X = rect.right; + Y = rect.bottom; + } + return [x, y, w, h, X, Y]; + }; + let name = 'CP', + delay = W.setTimeout, + hex = 'HEX'; + + function getClosest(a, b) { + if (a === b) { + return a; + } + while ((a = a.parentElement) && a !== b); + return a; + } // Convert cursor position to RGBA + function P2RGB(a) { + let h = +a[0], + s = +a[1], + v = +a[2], + r, + g, + b, + i, + f, + p, + q, + t; + i = Math.floor(h * 6); + f = h * 6 - i; + p = v * (1 - s); + q = v * (1 - f * s); + t = v * (1 - (1 - f) * s); + i = i || 0; + q = q || 0; + t = t || 0; + switch (i % 6) { + case 0: + r = v, g = t, b = p; + break; + case 1: + r = q, g = v, b = p; + break; + case 2: + r = p, g = v, b = t; + break; + case 3: + r = p, g = q, b = v; + break; + case 4: + r = t, g = p, b = v; + break; + case 5: + r = v, g = p, b = q; + break; + } + return [toRound(r * 255), toRound(g * 255), toRound(b * 255), isSet(a[3]) ? +a[3] : 1]; + } // Convert RGBA to HSVA + function RGB2HSV(a) { + let r = +a[0] / 255, + g = +a[1] / 255, + b = +a[2] / 255, + max = Math.max(r, g, b), + min = Math.min(r, g, b), + h, + s, + v = max, + d = max - min; + s = max === 0 ? 0 : d / max; + if (max === min) { + h = 0; // Achromatic + } else { + switch (max) { + case r: + h = (g - b) / d + (g < b ? 6 : 0); + break; + case g: + h = (b - r) / d + 2; + break; + case b: + h = (r - g) / d + 4; + break; + } + h /= 6; + } + return [h, s, v, isSet(a[3]) ? +a[3] : 1]; + } + const EVENTS_DOWN = ['touchstart', 'mousedown']; + const EVENTS_MOVE = ['touchmove', 'mousemove']; + const EVENTS_RESIZE = ['orientationchange', 'resize']; + const EVENTS_UP = ['touchend', 'mouseup']; + + function CP(source, state = {}) { + if (!source) return; + const $ = this; // Return new instance if `CP` was called without the `new` operator + if (!isInstance($, CP)) { + return new CP(source, state); + } // Already instantiated, skip! + if (source[name]) { + return; + } + let { + fire, + hooks + } = hook($); + $.state = state = fromStates(CP.state, isString(state) ? { + color: state + } : state || {}); + $.source = source; + $.visible = false; // Store current instance to `CP.instances` + CP.instances[source.id || source.name || toObjectCount(CP.instances)] = $; // Mark current DOM as active color picker to prevent duplicate instance + source[name] = 1; + + function theValue(from) { + let to = CP[isFunction(CP[state.color]) ? state.color : hex], + theColor; // Get value from `data-color` attribute + if (theColor = getDatum(source, 'color')) { + if (isSet(from)) { + return setDatum(source, 'color', to(from)); + } + return to(theColor); + } // Get value from `value` attribute + if (theColor = getState(source, 'value')) { + if (isSet(from)) { + return setState(source, 'value', to(from)); + } + return to(theColor); + } // Get value from content + if (theColor = getText(source)) { + if (isSet(from)) { + return setText(source, to(from)); + } + return to(theColor); + } + if (isSet(from)) { + return; // Do nothing + } + return [0, 0, 0, 1]; // Default to black + } + let className = state['class'], + doEnter, + doExit, + doFit, + doResize, + theColor = theValue(), + theData = RGB2HSV(theColor), + self = setElement('div', { + 'class': className + }), + C = setElement('div'), + SV = setElement('div', { + 'class': className + ':sv' + }), + H = setElement('div', { + 'class': className + ':h' + }), + A = setElement('div', { + 'class': className + ':a' + }), + SVColor = setElement('div'), + SVSaturation = setElement('div'), + SVValue = setElement('div'), + SVCursor = setElement('i'), + HColor = setElement('div'), + HCursor = setElement('i'), + AColor = setElement('div'), + APattern = setElement('div'), + ACursor = setElement('i'), + SVStarting = 0, + HStarting = 0, + AStarting = 0, + SVDragging = 0, + HDragging = 0, + ADragging = 0; + setChildLast(self, C); + setChildLast(C, SV); + setChildLast(C, H); + setChildLast(C, A); + setChildLast(SV, SVColor); + setChildLast(SV, SVSaturation); + setChildLast(SV, SVValue); + setChildLast(SV, SVCursor); + setChildLast(H, HColor); + setChildLast(H, HCursor); + setChildLast(A, AColor); + setChildLast(A, APattern); + setChildLast(A, ACursor); + + function doApply(isFirst, toParent) { + // Refresh data + theData = RGB2HSV(theColor = theValue()); + if (!isFirst) { + setChildLast(toParent || state.parent || B, self); + $.visible = true; + } + doEnter = toParent => { + return doApply(0, toParent), fire('enter', theColor), $; + }; + doExit = () => { + if (getParent(self)) { + letElement(self); + $.current = null; + $.visible = false; + } + offEvents(EVENTS_DOWN, SV, doDownSV); + offEvents(EVENTS_DOWN, H, doDownH); + offEvents(EVENTS_DOWN, A, doDownA); + offEvents(EVENTS_MOVE, D, doMove); + offEvents(EVENTS_UP, D, doStop); + offEvents(EVENTS_RESIZE, W, doResize); + return fire('exit', theColor); + }; + doFit = to => { + let rootRect = getRect(R), + sourceRect = getRect(source), + winRect = getRect(W), + scrollBarHeight = winRect[3] - R.clientHeight, + // Horizontal scroll bar + scrollBarWidth = winRect[2] - rootRect[2], + // Vertical scroll bar + selfRect = getRect(self), + selfHeight = selfRect[3], + selfWidth = selfRect[2], + selfLeft = sourceRect[0] + winRect[0], + selfTop = sourceRect[1] + winRect[1] + sourceRect[3]; // Drop! + if (isObject(to)) { + isSet(to[0]) && (selfLeft = to[0]); + isSet(to[1]) && (selfTop = to[1]); + } else { + let minX = winRect[0], + minY = winRect[1], + maxX = winRect[0] + winRect[2] - selfWidth - scrollBarWidth, + maxY = winRect[1] + winRect[3] - selfHeight - scrollBarHeight; + selfLeft = toEdge(selfLeft, [minX, maxX]) >> 0; + selfTop = toEdge(selfTop, [minY, maxY]) >> 0; + } + setStyle(self, 'left', selfLeft); + setStyle(self, 'top', selfTop); + return fire('fit', theColor); + }; + doResize = () => doFit(); + + function doDownA(e) { + $.current = A; + AStarting = ADragging = 1; + doMove(e); + offEventDefault(e); + } + + function doDownH(e) { + $.current = H; + HStarting = HDragging = 1; + doMove(e); + offEventDefault(e); + } + + function doDownSV(e) { + $.current = SV; + SVStarting = SVDragging = 1; + doMove(e); + offEventDefault(e); + } + + function doMove(e) { + SVDragging && doSetSVCursor(e); + HDragging && doSetHCursor(e); + ADragging && doSetACursor(e); + theColor = P2RGB(theData); + if (SVDragging || HDragging || ADragging) { + fire(SVStarting || HStarting || AStarting ? 'start' : 'drag', theColor); + fire('change', theColor); + } + SVStarting = HStarting = AStarting = 0; + } + + function doSetColor() { + doSetCursor(theData); + let a = P2RGB(theData), + b = P2RGB([theData[0], 1, 1]); + setStyle(SVColor, 'background-color', 'rgb(' + b[0] + ',' + b[1] + ',' + b[2] + ')'); + setStyle(AColor, 'background-image', 'linear-gradient(rgb(' + a[0] + ',' + a[1] + ',' + a[2] + '),transparent)'); + } + + function doSetCursor(x) { + isSet(x[1]) && setStyle(SVCursor, 'right', SVWidth - SVWidthCursor / 2 - SVWidth * +x[1]); + isSet(x[2]) && setStyle(SVCursor, 'top', SVHeight - SVHeightCursor / 2 - SVHeight * +x[2]); + isSet(x[0]) && setStyle(HCursor, 'top', HHeight - HHeightCursor / 2 - HHeight * +x[0]); + isSet(x[3]) && setStyle(ACursor, 'top', AHeight - AHeightCursor / 2 - AHeight * +x[3]); + } + + function doSetACursor(e) { + theData[3] = (AHeight - toEdge(getAxis(e, A)[1], [0, AHeight])) / AHeight; + doSetColor(); + } + + function doSetHCursor(e) { + theData[0] = (HHeight - toEdge(getAxis(e, H)[1], [0, HHeight])) / HHeight; + doSetColor(); + } + + function doSetSVCursor(e) { + let SVPoint = getAxis(e, SV), + x = toEdge(SVPoint[0], [0, SVWidth]), + y = toEdge(SVPoint[1], [0, SVHeight]); + theData[1] = 1 - (SVWidth - x) / SVWidth; + theData[2] = (SVHeight - y) / SVHeight; + doSetColor(); + } + + function doStop(e) { + theColor = P2RGB(theData); + let t = e.target, + isSource = source === getClosest(t, source), + isSelf = self === getClosest(t, self); + $.current = null; + if (!isSource && !isSelf) { + if (hooks.blur) { + fire('blur', theColor); + } else { + // Click outside the source or picker element to exit + if (SVDragging || HDragging || ADragging); + else { + getParent(self) && doExit(); + } + } + } else { + if (isSelf) { + if (SVDragging || HDragging || ADragging) { + fire('stop', theColor); + } + } + } + SVDragging = HDragging = ADragging = 0; + } + let SVRect = getRect(SV), + SVRectCursor = getRect(SVCursor), + HRect = getRect(H), + HRectCursor = getRect(HCursor), + ARect = getRect(A), + ARectCursor = getRect(ACursor), + SVHeight = SVRect[3], + SVHeightCursor = SVRectCursor[3], + SVWidth = SVRect[2], + SVWidthCursor = SVRectCursor[2], + HHeight = HRect[3], + HHeightCursor = HRectCursor[3], + AHeight = ARect[3], + AHeightCursor = ARectCursor[3]; + if (isFirst) { + onEvents(EVENTS_DOWN, source, doClick); + delay(() => { + fire('change', theColor); + }, 1); + } else { + onEvents(EVENTS_DOWN, SV, doDownSV); + onEvents(EVENTS_DOWN, H, doDownH); + onEvents(EVENTS_DOWN, A, doDownA); + onEvents(EVENTS_MOVE, D, doMove); + onEvents(EVENTS_UP, D, doStop); + onEvents(EVENTS_RESIZE, W, doResize); + doFit(); + } + doSetColor(); + $.color = (r, g, b, a) => CP[isFunction(CP[state.color]) ? state.color : hex]([r, g, b, a]); + $.current = null; + $.enter = doEnter; + $.exit = doExit; + $.fit = doFit; + $.get = () => theValue(); + $.pop = () => { + if (!source[name]) { + return $; // Already ejected + } + delete source[name]; + offEvents(EVENTS_DOWN, source, doClick); + return doExit(), fire('pop', theColor); + }; + $.set = (r, g, b, a) => { + theData = RGB2HSV([r, g, b, a]); + return doSetColor(), $; + }; + $.self = self; + $.value = (r, g, b, a) => ($.set(r, g, b, a), fire('change', [r, g, b, a])); + } + doApply(1); + + function doClick(e) { + if (hooks.focus) { + fire('focus', theColor); + } else { + let t = e.target, + isSource = source === getClosest(t, source); + if (isSource) { + !getParent(self) && doEnter(state.parent); + } else { + doExit(); + } + } + } + return $; + } + CP[hex] = x => { + if (isString(x)) { + let count = (x = x.trim()).length; + if ((4 === count || 7 === count) && '#' === x[0]) { + if (/^#([a-f\d]{3}){1,2}$/i.test(x)) { + if (4 === count) { + return [toNumber(x[1] + x[1], 16), toNumber(x[2] + x[2], 16), toNumber(x[3] + x[3], 16), 1]; + } + return [toNumber(x[1] + x[2], 16), toNumber(x[3] + x[4], 16), toNumber(x[5] + x[6], 16), 1]; + } + } else if ((5 === count || 9 === count) && '#' === x[0]) { + if (/^#([a-f\d]{3,4}){1,2}$/i.test(x)) { + if (5 === count) { + return [toNumber(x[1] + x[1], 16), toNumber(x[2] + x[2], 16), toNumber(x[3] + x[3], 16), toNumber(x[4] + x[4], 16) / 255]; + } + return [toNumber(x[1] + x[2], 16), toNumber(x[3] + x[4], 16), toNumber(x[5] + x[6], 16), toNumber(x[7] + x[8], 16) / 255]; + } + } + return [0, 0, 0, 1]; // Default to black + } + return '#' + ('000000' + toString(+x[2] | +x[1] << 8 | +x[0] << 16, 16)).slice(-6) + (isSet(x[3]) && x[3] < 1 ? toString(toRound(x[3] * 255) + 0x10000, 16).substr(-2) : ""); + }; + CP.instances = {}; + CP.state = { + 'class': 'color-picker', + 'color': hex, + 'parent': null + }; + CP.version = '2.2.0'; + return CP; + }); diff --git a/pages/updates/updates.html b/pages/updates/updates.html index a344274c..587aeb5e 100644 --- a/pages/updates/updates.html +++ b/pages/updates/updates.html @@ -58,6 +58,7 @@
  • Updated: angular-material v1.2.1 -> v1.2.2 (#363)
  • Updated: vue-i18n v8.24.2 -> v8.24.3 (#366)
  • Updated: angular-ui-select v0.19.8 (#367)
  • +
  • Updated: Internal module "Color Picker" v2.1.4 -> v2.2.0