react-iro-gradient-picker
Version:
Modern React gradient and solid color picker with complete dark theme support, built with TypeScript and Tailwind CSS
1,395 lines (1,236 loc) • 327 kB
JavaScript
'use strict';
Object.defineProperty(exports, '__esModule', { value: true });
var React = require('react');
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var React__default = /*#__PURE__*/_interopDefaultLegacy(React);
/******************************************************************************
Copyright (c) Microsoft Corporation.
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
var __assign = function() {
__assign = Object.assign || function __assign(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
function __values(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
}
function __read(o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
}
function __spreadArray(to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
}
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
var e = new Error(message);
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
};
var ThemeContext = React.createContext(undefined);
var useTheme = function () {
var context = React.useContext(ThemeContext);
if (context === undefined) {
throw new Error('useTheme must be used within a ThemeProvider');
}
return context;
};
var ThemeProvider = function (_a) {
var children = _a.children, _b = _a.defaultTheme // Dark theme as default
, defaultTheme = _b === void 0 ? 'dark' : _b // Dark theme as default
;
var _c = __read(React.useState(function () {
// Check localStorage first, then use default
if (typeof window !== 'undefined') {
var stored = localStorage.getItem('color-picker-theme');
return stored || defaultTheme;
}
return defaultTheme;
}), 2), theme = _c[0], setTheme = _c[1];
React.useEffect(function () {
// Apply theme to local container instead of document root for better scoping
var containers = document.querySelectorAll('[data-color-picker-theme]');
containers.forEach(function (container) {
// Remove previous theme class
container.classList.remove('light', 'dark');
// Add new theme class
container.classList.add(theme);
});
// Store theme preference
if (typeof window !== 'undefined') {
localStorage.setItem('color-picker-theme', theme);
}
}, [theme]);
var toggleTheme = function () {
setTheme(function (prevTheme) { return (prevTheme === 'light' ? 'dark' : 'light'); });
};
var value = {
theme: theme,
toggleTheme: toggleTheme,
setTheme: setTheme
};
return (React__default["default"].createElement(ThemeContext.Provider, { value: value }, children));
};
// Simple sun and moon icons as SVG components
var SunIcon = function (_a) {
var className = _a.className;
return (React__default["default"].createElement("svg", { className: className, fill: 'currentColor', viewBox: '0 0 20 20' },
React__default["default"].createElement("path", { fillRule: 'evenodd', d: 'M10 2a1 1 0 011 1v1a1 1 0 11-2 0V3a1 1 0 011-1zm4 8a4 4 0 11-8 0 4 4 0 018 0zm-.464 4.95l.707.707a1 1 0 001.414-1.414l-.707-.707a1 1 0 00-1.414 1.414zm2.12-10.607a1 1 0 010 1.414l-.706.707a1 1 0 11-1.414-1.414l.707-.707a1 1 0 011.414 0zM17 11a1 1 0 100-2h-1a1 1 0 100 2h1zm-7 4a1 1 0 011 1v1a1 1 0 11-2 0v-1a1 1 0 011-1zM5.05 6.464A1 1 0 106.465 5.05l-.708-.707a1 1 0 00-1.414 1.414l.707.707zm1.414 8.486l-.707.707a1 1 0 01-1.414-1.414l.707-.707a1 1 0 011.414 1.414zM4 11a1 1 0 100-2H3a1 1 0 000 2h1z', clipRule: 'evenodd' })));
};
var MoonIcon = function (_a) {
var className = _a.className;
return (React__default["default"].createElement("svg", { className: className, fill: 'currentColor', viewBox: '0 0 20 20' },
React__default["default"].createElement("path", { d: 'M17.293 13.293A8 8 0 016.707 2.707a8.001 8.001 0 1010.586 10.586z' })));
};
var ThemeToggle = function (_a) {
var className = _a.className;
var _b = useTheme(), theme = _b.theme, toggleTheme = _b.toggleTheme;
return (React__default["default"].createElement("button", { onClick: toggleTheme, className: "theme-toggle ".concat(className || ''), "aria-label": "Switch to ".concat(theme === 'light' ? 'dark' : 'light', " theme"), title: "Switch to ".concat(theme === 'light' ? 'dark' : 'light', " theme") }, theme === 'light' ? (React__default["default"].createElement(MoonIcon, { className: 'theme-toggle-icon' })) : (React__default["default"].createElement(SunIcon, { className: 'theme-toggle-icon' }))));
};
/*!
* iro.js v5.5.2
* 2016-2021 James Daniel
* Licensed under MPL 2.0
* github.com/jaames/iro.js
*/
var n,u,t,i,r$1,f={},e=[],c=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|^--/i;function s(n,l){for(var u in l){ n[u]=l[u]; }return n}function a(n){var l=n.parentNode;l&&l.removeChild(n);}function h(n,l,u){var t,i,r,o,f=arguments;if(l=s({},l),arguments.length>3){ for(u=[u],t=3;t<arguments.length;t++){ u.push(f[t]); } }if(null!=u&&(l.children=u),null!=n&&null!=n.defaultProps){ for(i in n.defaultProps){ void 0===l[i]&&(l[i]=n.defaultProps[i]); } }return o=l.key,null!=(r=l.ref)&&delete l.ref,null!=o&&delete l.key,v(n,l,o,r)}function v(l,u,t,i){var r={type:l,props:u,key:t,ref:i,__k:null,__p:null,__b:0,__e:null,l:null,__c:null,constructor:void 0};return n.vnode&&n.vnode(r),r}function d(n){return n.children}function y(n){if(null==n||"boolean"==typeof n){ return null; }if("string"==typeof n||"number"==typeof n){ return v(null,n,null,null); }if(null!=n.__e||null!=n.__c){var l=v(n.type,n.props,n.key,null);return l.__e=n.__e,l}return n}function m(n,l){this.props=n,this.context=l;}function w(n,l){if(null==l){ return n.__p?w(n.__p,n.__p.__k.indexOf(n)+1):null; }for(var u;l<n.__k.length;l++){ if(null!=(u=n.__k[l])&&null!=u.__e){ return u.__e; } }return "function"==typeof n.type?w(n):null}function g(n){var l,u;if(null!=(n=n.__p)&&null!=n.__c){for(n.__e=n.__c.base=null,l=0;l<n.__k.length;l++){ if(null!=(u=n.__k[l])&&null!=u.__e){n.__e=n.__c.base=u.__e;break} }return g(n)}}function k(l){(!l.__d&&(l.__d=!0)&&1===u.push(l)||i!==n.debounceRendering)&&(i=n.debounceRendering,(n.debounceRendering||t)(_));}function _(){var n,l,t,i,r,o,f,e;for(u.sort(function(n,l){return l.__v.__b-n.__v.__b});n=u.pop();){ n.__d&&(t=void 0,i=void 0,o=(r=(l=n).__v).__e,f=l.__P,e=l.u,l.u=!1,f&&(t=[],i=$(f,r,s({},r),l.__n,void 0!==f.ownerSVGElement,null,t,e,null==o?w(r):o),j(t,r),i!=o&&g(r))); }}function b(n,l,u,t,i,r,o,c,s){var h,v,p,d,y,m,g,k=u&&u.__k||e,_=k.length;if(c==f&&(c=null!=r?r[0]:_?w(u,0):null),h=0,l.__k=x(l.__k,function(u){if(null!=u){if(u.__p=l,u.__b=l.__b+1,null===(p=k[h])||p&&u.key==p.key&&u.type===p.type){ k[h]=void 0; }else { for(v=0;v<_;v++){if((p=k[v])&&u.key==p.key&&u.type===p.type){k[v]=void 0;break}p=null;} }if(d=$(n,u,p=p||f,t,i,r,o,null,c,s),(v=u.ref)&&p.ref!=v&&(g||(g=[])).push(v,u.__c||d,u),null!=d){if(null==m&&(m=d),null!=u.l){ d=u.l,u.l=null; }else if(r==p||d!=c||null==d.parentNode){n:if(null==c||c.parentNode!==n){ n.appendChild(d); }else {for(y=c,v=0;(y=y.nextSibling)&&v<_;v+=2){ if(y==d){ break n; } }n.insertBefore(d,c);}"option"==l.type&&(n.value="");}c=d.nextSibling,"function"==typeof l.type&&(l.l=d);}}return h++,u}),l.__e=m,null!=r&&"function"!=typeof l.type){ for(h=r.length;h--;){ null!=r[h]&&a(r[h]); } }for(h=_;h--;){ null!=k[h]&&D(k[h],k[h]); }if(g){ for(h=0;h<g.length;h++){ A(g[h],g[++h],g[++h]); } }}function x(n,l,u){if(null==u&&(u=[]),null==n||"boolean"==typeof n){ l&&u.push(l(null)); }else if(Array.isArray(n)){ for(var t=0;t<n.length;t++){ x(n[t],l,u); } }else { u.push(l?l(y(n)):n); }return u}function C(n,l,u,t,i){var r;for(r in u){ r in l||N(n,r,null,u[r],t); }for(r in l){ i&&"function"!=typeof l[r]||"value"===r||"checked"===r||u[r]===l[r]||N(n,r,l[r],u[r],t); }}function P(n,l,u){"-"===l[0]?n.setProperty(l,u):n[l]="number"==typeof u&&!1===c.test(l)?u+"px":null==u?"":u;}function N(n,l,u,t,i){var r,o,f,e,c;if("key"===(l=i?"className"===l?"class":l:"class"===l?"className":l)||"children"===l);else if("style"===l){ if(r=n.style,"string"==typeof u){ r.cssText=u; }else {if("string"==typeof t&&(r.cssText="",t=null),t){ for(o in t){ u&&o in u||P(r,o,""); } }if(u){ for(f in u){ t&&u[f]===t[f]||P(r,f,u[f]); } }} }else { "o"===l[0]&&"n"===l[1]?(e=l!==(l=l.replace(/Capture$/,"")),c=l.toLowerCase(),l=(c in n?c:l).slice(2),u?(t||n.addEventListener(l,T,e),(n.t||(n.t={}))[l]=u):n.removeEventListener(l,T,e)):"list"!==l&&"tagName"!==l&&"form"!==l&&!i&&l in n?n[l]=null==u?"":u:"function"!=typeof u&&"dangerouslySetInnerHTML"!==l&&(l!==(l=l.replace(/^xlink:?/,""))?null==u||!1===u?n.removeAttributeNS("http://www.w3.org/1999/xlink",l.toLowerCase()):n.setAttributeNS("http://www.w3.org/1999/xlink",l.toLowerCase(),u):null==u||!1===u?n.removeAttribute(l):n.setAttribute(l,u)); }}function T(l){return this.t[l.type](n.event?n.event(l):l)}function $(l,u,t,i,r,o,f,e,c,a){var h,v,p,y,w,g,k,_,C,P,N=u.type;if(void 0!==u.constructor){ return null; }(h=n.__b)&&h(u);try{n:if("function"==typeof N){if(_=u.props,C=(h=N.contextType)&&i[h.__c],P=h?C?C.props.value:h.__p:i,t.__c?k=(v=u.__c=t.__c).__p=v.__E:("prototype"in N&&N.prototype.render?u.__c=v=new N(_,P):(u.__c=v=new m(_,P),v.constructor=N,v.render=H),C&&C.sub(v),v.props=_,v.state||(v.state={}),v.context=P,v.__n=i,p=v.__d=!0,v.__h=[]),null==v.__s&&(v.__s=v.state),null!=N.getDerivedStateFromProps&&s(v.__s==v.state?v.__s=s({},v.__s):v.__s,N.getDerivedStateFromProps(_,v.__s)),p){ null==N.getDerivedStateFromProps&&null!=v.componentWillMount&&v.componentWillMount(),null!=v.componentDidMount&&f.push(v); }else {if(null==N.getDerivedStateFromProps&&null==e&&null!=v.componentWillReceiveProps&&v.componentWillReceiveProps(_,P),!e&&null!=v.shouldComponentUpdate&&!1===v.shouldComponentUpdate(_,v.__s,P)){for(v.props=_,v.state=v.__s,v.__d=!1,v.__v=u,u.__e=null!=c?c!==t.__e?c:t.__e:null,u.__k=t.__k,h=0;h<u.__k.length;h++){ u.__k[h]&&(u.__k[h].__p=u); }break n}null!=v.componentWillUpdate&&v.componentWillUpdate(_,v.__s,P);}for(y=v.props,w=v.state,v.context=P,v.props=_,v.state=v.__s,(h=n.__r)&&h(u),v.__d=!1,v.__v=u,v.__P=l,h=v.render(v.props,v.state,v.context),u.__k=x(null!=h&&h.type==d&&null==h.key?h.props.children:h),null!=v.getChildContext&&(i=s(s({},i),v.getChildContext())),p||null==v.getSnapshotBeforeUpdate||(g=v.getSnapshotBeforeUpdate(y,w)),b(l,u,t,i,r,o,f,c,a),v.base=u.__e;h=v.__h.pop();){ v.__s&&(v.state=v.__s),h.call(v); }p||null==y||null==v.componentDidUpdate||v.componentDidUpdate(y,w,g),k&&(v.__E=v.__p=null);}else { u.__e=z(t.__e,u,t,i,r,o,f,a); }(h=n.diffed)&&h(u);}catch(l){n.__e(l,u,t);}return u.__e}function j(l,u){for(var t;t=l.pop();){ try{t.componentDidMount();}catch(l){n.__e(l,t.__v);} }n.__c&&n.__c(u);}function z(n,l,u,t,i,r,o,c){var s,a,h,v,p=u.props,d=l.props;if(i="svg"===l.type||i,null==n&&null!=r){ for(s=0;s<r.length;s++){ if(null!=(a=r[s])&&(null===l.type?3===a.nodeType:a.localName===l.type)){n=a,r[s]=null;break} } }if(null==n){if(null===l.type){ return document.createTextNode(d); }n=i?document.createElementNS("http://www.w3.org/2000/svg",l.type):document.createElement(l.type),r=null;}return null===l.type?p!==d&&(null!=r&&(r[r.indexOf(n)]=null),n.data=d):l!==u&&(null!=r&&(r=e.slice.call(n.childNodes)),h=(p=u.props||f).dangerouslySetInnerHTML,v=d.dangerouslySetInnerHTML,c||(v||h)&&(v&&h&&v.__html==h.__html||(n.innerHTML=v&&v.__html||"")),C(n,d,p,i,c),l.__k=l.props.children,v||b(n,l,u,t,"foreignObject"!==l.type&&i,r,o,f,c),c||("value"in d&&void 0!==d.value&&d.value!==n.value&&(n.value=null==d.value?"":d.value),"checked"in d&&void 0!==d.checked&&d.checked!==n.checked&&(n.checked=d.checked))),n}function A(l,u,t){try{"function"==typeof l?l(u):l.current=u;}catch(l){n.__e(l,t);}}function D(l,u,t){var i,r,o;if(n.unmount&&n.unmount(l),(i=l.ref)&&A(i,null,u),t||"function"==typeof l.type||(t=null!=(r=l.__e)),l.__e=l.l=null,null!=(i=l.__c)){if(i.componentWillUnmount){ try{i.componentWillUnmount();}catch(l){n.__e(l,u);} }i.base=i.__P=null;}if(i=l.__k){ for(o=0;o<i.length;o++){ i[o]&&D(i[o],u,t); } }null!=r&&a(r);}function H(n,l,u){return this.constructor(n,u)}function I(l,u,t){var i,o,c;n.__p&&n.__p(l,u),o=(i=t===r$1)?null:t&&t.__k||u.__k,l=h(d,null,[l]),c=[],$(u,i?u.__k=l:(t||u).__k=l,o||f,f,void 0!==u.ownerSVGElement,t&&!i?[t]:o?null:e.slice.call(u.childNodes),c,!1,t||f,i),j(c,l);}n={},m.prototype.setState=function(n,l){var u=this.__s!==this.state&&this.__s||(this.__s=s({},this.state));("function"!=typeof n||(n=n(u,this.props)))&&s(u,n),null!=n&&this.__v&&(this.u=!1,l&&this.__h.push(l),k(this));},m.prototype.forceUpdate=function(n){this.__v&&(n&&this.__h.push(n),this.u=!0,k(this));},m.prototype.render=d,u=[],t="function"==typeof Promise?Promise.prototype.then.bind(Promise.resolve()):setTimeout,i=n.debounceRendering,n.__e=function(n,l,u){for(var t;l=l.__p;){ if((t=l.__c)&&!t.__p){ try{if(t.constructor&&null!=t.constructor.getDerivedStateFromError){ t.setState(t.constructor.getDerivedStateFromError(n)); }else {if(null==t.componentDidCatch){ continue; }t.componentDidCatch(n);}return k(t.__E=t)}catch(l){n=l;} } }throw n},r$1=f;
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) { descriptor.writable = true; }
Object.defineProperty(target, descriptor.key, descriptor);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) { _defineProperties(Constructor.prototype, protoProps); }
if (staticProps) { _defineProperties(Constructor, staticProps); }
return Constructor;
}
function _extends() {
_extends = Object.assign || function (target) {
var arguments$1 = arguments;
for (var i = 1; i < arguments.length; i++) {
var source = arguments$1[i];
for (var key in source) {
if (Object.prototype.hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
}
return target;
};
return _extends.apply(this, arguments);
}
// Some regular expressions for rgb() and hsl() Colors are borrowed from tinyColor
// https://github.com/bgrins/TinyColor
// Kelvin temperature math borrowed from Neil Barlett's implementation
// from https://github.com/neilbartlett/color-temperature
// https://www.w3.org/TR/css3-values/#integers
var CSS_INTEGER = '[-\\+]?\\d+%?'; // http://www.w3.org/TR/css3-values/#number-value
var CSS_NUMBER = '[-\\+]?\\d*\\.\\d+%?'; // Allow positive/negative integer/number. Don't capture the either/or, just the entire outcome
var CSS_UNIT = '(?:' + CSS_NUMBER + ')|(?:' + CSS_INTEGER + ')'; // Parse function params
// Parens and commas are optional, and this also allows for whitespace between numbers
var PERMISSIVE_MATCH_3 = '[\\s|\\(]+(' + CSS_UNIT + ')[,|\\s]+(' + CSS_UNIT + ')[,|\\s]+(' + CSS_UNIT + ')\\s*\\)?';
var PERMISSIVE_MATCH_4 = '[\\s|\\(]+(' + CSS_UNIT + ')[,|\\s]+(' + CSS_UNIT + ')[,|\\s]+(' + CSS_UNIT + ')[,|\\s]+(' + CSS_UNIT + ')\\s*\\)?'; // Regex patterns for functional color strings
var REGEX_FUNCTIONAL_RGB = new RegExp('rgb' + PERMISSIVE_MATCH_3);
var REGEX_FUNCTIONAL_RGBA = new RegExp('rgba' + PERMISSIVE_MATCH_4);
var REGEX_FUNCTIONAL_HSL = new RegExp('hsl' + PERMISSIVE_MATCH_3);
var REGEX_FUNCTIONAL_HSLA = new RegExp('hsla' + PERMISSIVE_MATCH_4); // Color string parsing regex
var HEX_START = '^(?:#?|0x?)';
var HEX_INT_SINGLE = '([0-9a-fA-F]{1})';
var HEX_INT_DOUBLE = '([0-9a-fA-F]{2})';
var REGEX_HEX_3 = new RegExp(HEX_START + HEX_INT_SINGLE + HEX_INT_SINGLE + HEX_INT_SINGLE + '$');
var REGEX_HEX_4 = new RegExp(HEX_START + HEX_INT_SINGLE + HEX_INT_SINGLE + HEX_INT_SINGLE + HEX_INT_SINGLE + '$');
var REGEX_HEX_6 = new RegExp(HEX_START + HEX_INT_DOUBLE + HEX_INT_DOUBLE + HEX_INT_DOUBLE + '$');
var REGEX_HEX_8 = new RegExp(HEX_START + HEX_INT_DOUBLE + HEX_INT_DOUBLE + HEX_INT_DOUBLE + HEX_INT_DOUBLE + '$'); // Kelvin temperature bounds
var KELVIN_MIN = 2000;
var KELVIN_MAX = 40000; // Math shorthands
var log = Math.log,
round = Math.round,
floor = Math.floor;
/**
* @desc Clamp a number between a min and max value
* @param num - input value
* @param min - min allowed value
* @param max - max allowed value
*/
function clamp(num, min, max) {
return Math.min(Math.max(num, min), max);
}
/**
* @desc Parse a css unit string - either regular int or a percentage number
* @param str - css unit string
* @param max - max unit value, used for calculating percentages
*/
function parseUnit(str, max) {
var isPercentage = str.indexOf('%') > -1;
var num = parseFloat(str);
return isPercentage ? max / 100 * num : num;
}
/**
* @desc Parse hex str to an int
* @param str - hex string to parse
*/
function parseHexInt(str) {
return parseInt(str, 16);
}
/**
* @desc Convert nunber into to 2-digit hex
* @param int - number to convert
*/
function intToHex(_int) {
return _int.toString(16).padStart(2, '0');
}
var IroColor =
/*#__PURE__*/
function () {
/**
* @constructor Color object
* @param value - initial color value
*/
function IroColor(value, onChange) {
// The default Color value
this.$ = {
h: 0,
s: 0,
v: 0,
a: 1
};
if (value) { this.set(value); } // The watch callback function for this Color will be stored here
this.onChange = onChange;
this.initialValue = _extends({}, this.$); // copy initial value
}
/**
* @desc Set the Color from any valid value
* @param value - new color value
*/
var _proto = IroColor.prototype;
_proto.set = function set(value) {
if (typeof value === 'string') {
if (/^(?:#?|0x?)[0-9a-fA-F]{3,8}$/.test(value)) {
this.hexString = value;
} else if (/^rgba?/.test(value)) {
this.rgbString = value;
} else if (/^hsla?/.test(value)) {
this.hslString = value;
}
} else if (typeof value === 'object') {
if (value instanceof IroColor) {
this.hsva = value.hsva;
} else if ('r' in value && 'g' in value && 'b' in value) {
this.rgb = value;
} else if ('h' in value && 's' in value && 'v' in value) {
this.hsv = value;
} else if ('h' in value && 's' in value && 'l' in value) {
this.hsl = value;
} else if ('kelvin' in value) {
this.kelvin = value.kelvin;
}
} else {
throw new Error('Invalid color value');
}
}
/**
* @desc Shortcut to set a specific channel value
* @param format - hsv | hsl | rgb
* @param channel - individual channel to set, for example if model = hsl, chanel = h | s | l
* @param value - new value for the channel
*/
;
_proto.setChannel = function setChannel(format, channel, value) {
var _extends2;
this[format] = _extends({}, this[format], (_extends2 = {}, _extends2[channel] = value, _extends2));
}
/**
* @desc Reset color back to its initial value
*/
;
_proto.reset = function reset() {
this.hsva = this.initialValue;
}
/**
* @desc make new Color instance with the same value as this one
*/
;
_proto.clone = function clone() {
return new IroColor(this);
}
/**
* @desc remove color onChange
*/
;
_proto.unbind = function unbind() {
this.onChange = undefined;
}
/**
* @desc Convert hsv object to rgb
* @param hsv - hsv color object
*/
;
IroColor.hsvToRgb = function hsvToRgb(hsv) {
var h = hsv.h / 60;
var s = hsv.s / 100;
var v = hsv.v / 100;
var i = floor(h);
var f = h - i;
var p = v * (1 - s);
var q = v * (1 - f * s);
var t = v * (1 - (1 - f) * s);
var mod = i % 6;
var r = [v, q, p, p, t, v][mod];
var g = [t, v, v, q, p, p][mod];
var b = [p, p, t, v, v, q][mod];
return {
r: clamp(r * 255, 0, 255),
g: clamp(g * 255, 0, 255),
b: clamp(b * 255, 0, 255)
};
}
/**
* @desc Convert rgb object to hsv
* @param rgb - rgb object
*/
;
IroColor.rgbToHsv = function rgbToHsv(rgb) {
var r = rgb.r / 255;
var g = rgb.g / 255;
var b = rgb.b / 255;
var max = Math.max(r, g, b);
var min = Math.min(r, g, b);
var delta = max - min;
var hue = 0;
var value = max;
var saturation = max === 0 ? 0 : delta / max;
switch (max) {
case min:
hue = 0; // achromatic
break;
case r:
hue = (g - b) / delta + (g < b ? 6 : 0);
break;
case g:
hue = (b - r) / delta + 2;
break;
case b:
hue = (r - g) / delta + 4;
break;
}
return {
h: hue * 60 % 360,
s: clamp(saturation * 100, 0, 100),
v: clamp(value * 100, 0, 100)
};
}
/**
* @desc Convert hsv object to hsl
* @param hsv - hsv object
*/
;
IroColor.hsvToHsl = function hsvToHsl(hsv) {
var s = hsv.s / 100;
var v = hsv.v / 100;
var l = (2 - s) * v;
var divisor = l <= 1 ? l : 2 - l; // Avoid division by zero when lightness is close to zero
var saturation = divisor < 1e-9 ? 0 : s * v / divisor;
return {
h: hsv.h,
s: clamp(saturation * 100, 0, 100),
l: clamp(l * 50, 0, 100)
};
}
/**
* @desc Convert hsl object to hsv
* @param hsl - hsl object
*/
;
IroColor.hslToHsv = function hslToHsv(hsl) {
var l = hsl.l * 2;
var s = hsl.s * (l <= 100 ? l : 200 - l) / 100; // Avoid division by zero when l + s is near 0
var saturation = l + s < 1e-9 ? 0 : 2 * s / (l + s);
return {
h: hsl.h,
s: clamp(saturation * 100, 0, 100),
v: clamp((l + s) / 2, 0, 100)
};
}
/**
* @desc Convert a kelvin temperature to an approx, RGB value
* @param kelvin - kelvin temperature
*/
;
IroColor.kelvinToRgb = function kelvinToRgb(kelvin) {
var temp = kelvin / 100;
var r, g, b;
if (temp < 66) {
r = 255;
g = -155.25485562709179 - 0.44596950469579133 * (g = temp - 2) + 104.49216199393888 * log(g);
b = temp < 20 ? 0 : -254.76935184120902 + 0.8274096064007395 * (b = temp - 10) + 115.67994401066147 * log(b);
} else {
r = 351.97690566805693 + 0.114206453784165 * (r = temp - 55) - 40.25366309332127 * log(r);
g = 325.4494125711974 + 0.07943456536662342 * (g = temp - 50) - 28.0852963507957 * log(g);
b = 255;
}
return {
r: clamp(floor(r), 0, 255),
g: clamp(floor(g), 0, 255),
b: clamp(floor(b), 0, 255)
};
}
/**
* @desc Convert an RGB color to an approximate kelvin temperature
* @param kelvin - kelvin temperature
*/
;
IroColor.rgbToKelvin = function rgbToKelvin(rgb) {
var r = rgb.r,
b = rgb.b;
var eps = 0.4;
var minTemp = KELVIN_MIN;
var maxTemp = KELVIN_MAX;
var temp;
while (maxTemp - minTemp > eps) {
temp = (maxTemp + minTemp) * 0.5;
var _rgb = IroColor.kelvinToRgb(temp);
if (_rgb.b / _rgb.r >= b / r) {
maxTemp = temp;
} else {
minTemp = temp;
}
}
return temp;
};
_createClass(IroColor, [{
key: "hsv",
get: function get() {
// value is cloned to allow changes to be made to the values before passing them back
var value = this.$;
return {
h: value.h,
s: value.s,
v: value.v
};
},
set: function set(newValue) {
var oldValue = this.$;
newValue = _extends({}, oldValue, newValue); // If this Color is being watched for changes we need to compare the new and old values to check the difference
// Otherwise we can just be lazy
if (this.onChange) {
// Compute changed values
var changes = {
h: false,
v: false,
s: false,
a: false
};
for (var key in oldValue) {
changes[key] = newValue[key] != oldValue[key];
}
this.$ = newValue; // If the value has changed, call hook callback
if (changes.h || changes.s || changes.v || changes.a) { this.onChange(this, changes); }
} else {
this.$ = newValue;
}
}
}, {
key: "hsva",
get: function get() {
return _extends({}, this.$);
},
set: function set(value) {
this.hsv = value;
}
}, {
key: "hue",
get: function get() {
return this.$.h;
},
set: function set(value) {
this.hsv = {
h: value
};
}
}, {
key: "saturation",
get: function get() {
return this.$.s;
},
set: function set(value) {
this.hsv = {
s: value
};
}
}, {
key: "value",
get: function get() {
return this.$.v;
},
set: function set(value) {
this.hsv = {
v: value
};
}
}, {
key: "alpha",
get: function get() {
return this.$.a;
},
set: function set(value) {
this.hsv = _extends({}, this.hsv, {
a: value
});
}
}, {
key: "kelvin",
get: function get() {
return IroColor.rgbToKelvin(this.rgb);
},
set: function set(value) {
this.rgb = IroColor.kelvinToRgb(value);
}
}, {
key: "red",
get: function get() {
var rgb = this.rgb;
return rgb.r;
},
set: function set(value) {
this.rgb = _extends({}, this.rgb, {
r: value
});
}
}, {
key: "green",
get: function get() {
var rgb = this.rgb;
return rgb.g;
},
set: function set(value) {
this.rgb = _extends({}, this.rgb, {
g: value
});
}
}, {
key: "blue",
get: function get() {
var rgb = this.rgb;
return rgb.b;
},
set: function set(value) {
this.rgb = _extends({}, this.rgb, {
b: value
});
}
}, {
key: "rgb",
get: function get() {
var _IroColor$hsvToRgb = IroColor.hsvToRgb(this.$),
r = _IroColor$hsvToRgb.r,
g = _IroColor$hsvToRgb.g,
b = _IroColor$hsvToRgb.b;
return {
r: round(r),
g: round(g),
b: round(b)
};
},
set: function set(value) {
this.hsv = _extends({}, IroColor.rgbToHsv(value), {
a: value.a === undefined ? 1 : value.a
});
}
}, {
key: "rgba",
get: function get() {
return _extends({}, this.rgb, {
a: this.alpha
});
},
set: function set(value) {
this.rgb = value;
}
}, {
key: "hsl",
get: function get() {
var _IroColor$hsvToHsl = IroColor.hsvToHsl(this.$),
h = _IroColor$hsvToHsl.h,
s = _IroColor$hsvToHsl.s,
l = _IroColor$hsvToHsl.l;
return {
h: round(h),
s: round(s),
l: round(l)
};
},
set: function set(value) {
this.hsv = _extends({}, IroColor.hslToHsv(value), {
a: value.a === undefined ? 1 : value.a
});
}
}, {
key: "hsla",
get: function get() {
return _extends({}, this.hsl, {
a: this.alpha
});
},
set: function set(value) {
this.hsl = value;
}
}, {
key: "rgbString",
get: function get() {
var rgb = this.rgb;
return "rgb(" + rgb.r + ", " + rgb.g + ", " + rgb.b + ")";
},
set: function set(value) {
var match;
var r,
g,
b,
a = 1;
if (match = REGEX_FUNCTIONAL_RGB.exec(value)) {
r = parseUnit(match[1], 255);
g = parseUnit(match[2], 255);
b = parseUnit(match[3], 255);
} else if (match = REGEX_FUNCTIONAL_RGBA.exec(value)) {
r = parseUnit(match[1], 255);
g = parseUnit(match[2], 255);
b = parseUnit(match[3], 255);
a = parseUnit(match[4], 1);
}
if (match) {
this.rgb = {
r: r,
g: g,
b: b,
a: a
};
} else {
throw new Error('Invalid rgb string');
}
}
}, {
key: "rgbaString",
get: function get() {
var rgba = this.rgba;
return "rgba(" + rgba.r + ", " + rgba.g + ", " + rgba.b + ", " + rgba.a + ")";
},
set: function set(value) {
this.rgbString = value;
}
}, {
key: "hexString",
get: function get() {
var rgb = this.rgb;
return "#" + intToHex(rgb.r) + intToHex(rgb.g) + intToHex(rgb.b);
},
set: function set(value) {
var match;
var r,
g,
b,
a = 255;
if (match = REGEX_HEX_3.exec(value)) {
r = parseHexInt(match[1]) * 17;
g = parseHexInt(match[2]) * 17;
b = parseHexInt(match[3]) * 17;
} else if (match = REGEX_HEX_4.exec(value)) {
r = parseHexInt(match[1]) * 17;
g = parseHexInt(match[2]) * 17;
b = parseHexInt(match[3]) * 17;
a = parseHexInt(match[4]) * 17;
} else if (match = REGEX_HEX_6.exec(value)) {
r = parseHexInt(match[1]);
g = parseHexInt(match[2]);
b = parseHexInt(match[3]);
} else if (match = REGEX_HEX_8.exec(value)) {
r = parseHexInt(match[1]);
g = parseHexInt(match[2]);
b = parseHexInt(match[3]);
a = parseHexInt(match[4]);
}
if (match) {
this.rgb = {
r: r,
g: g,
b: b,
a: a / 255
};
} else {
throw new Error('Invalid hex string');
}
}
}, {
key: "hex8String",
get: function get() {
var rgba = this.rgba;
return "#" + intToHex(rgba.r) + intToHex(rgba.g) + intToHex(rgba.b) + intToHex(floor(rgba.a * 255));
},
set: function set(value) {
this.hexString = value;
}
}, {
key: "hslString",
get: function get() {
var hsl = this.hsl;
return "hsl(" + hsl.h + ", " + hsl.s + "%, " + hsl.l + "%)";
},
set: function set(value) {
var match;
var h,
s,
l,
a = 1;
if (match = REGEX_FUNCTIONAL_HSL.exec(value)) {
h = parseUnit(match[1], 360);
s = parseUnit(match[2], 100);
l = parseUnit(match[3], 100);
} else if (match = REGEX_FUNCTIONAL_HSLA.exec(value)) {
h = parseUnit(match[1], 360);
s = parseUnit(match[2], 100);
l = parseUnit(match[3], 100);
a = parseUnit(match[4], 1);
}
if (match) {
this.hsl = {
h: h,
s: s,
l: l,
a: a
};
} else {
throw new Error('Invalid hsl string');
}
}
}, {
key: "hslaString",
get: function get() {
var hsla = this.hsla;
return "hsla(" + hsla.h + ", " + hsla.s + "%, " + hsla.l + "%, " + hsla.a + ")";
},
set: function set(value) {
this.hslString = value;
}
}]);
return IroColor;
}();
var sliderDefaultOptions = {
sliderShape: 'bar',
sliderType: 'value',
minTemperature: 2200,
maxTemperature: 11000
};
/**
* @desc Get the bounding dimensions of the slider
* @param props - slider props
*/
function getSliderDimensions(props) {
var _sliderSize;
var width = props.width,
sliderSize = props.sliderSize,
borderWidth = props.borderWidth,
handleRadius = props.handleRadius,
padding = props.padding,
sliderShape = props.sliderShape;
var ishorizontal = props.layoutDirection === 'horizontal'; // automatically calculate sliderSize if its not defined
sliderSize = (_sliderSize = sliderSize) != null ? _sliderSize : padding * 2 + handleRadius * 2;
if (sliderShape === 'circle') {
return {
handleStart: props.padding + props.handleRadius,
handleRange: width - padding * 2 - handleRadius * 2,
width: width,
height: width,
cx: width / 2,
cy: width / 2,
radius: width / 2 - borderWidth / 2
};
} else {
return {
handleStart: sliderSize / 2,
handleRange: width - sliderSize,
radius: sliderSize / 2,
x: 0,
y: 0,
width: ishorizontal ? sliderSize : width,
height: ishorizontal ? width : sliderSize
};
}
}
/**
* @desc Get the current slider value for a given color, as a percentage
* @param props - slider props
* @param color
*/
function getCurrentSliderValue(props, color) {
var hsva = color.hsva;
var rgb = color.rgb;
switch (props.sliderType) {
case 'red':
return rgb.r / 2.55;
case 'green':
return rgb.g / 2.55;
case 'blue':
return rgb.b / 2.55;
case 'alpha':
return hsva.a * 100;
case 'kelvin':
var minTemperature = props.minTemperature,
maxTemperature = props.maxTemperature;
var temperatureRange = maxTemperature - minTemperature;
var percent = (color.kelvin - minTemperature) / temperatureRange * 100; // clmap percentage
return Math.max(0, Math.min(percent, 100));
case 'hue':
return hsva.h /= 3.6;
case 'saturation':
return hsva.s;
case 'value':
default:
return hsva.v;
}
}
/**
* @desc Get the current slider value from user input
* @param props - slider props
* @param x - global input x position
* @param y - global input y position
*/
function getSliderValueFromInput(props, x, y) {
var _getSliderDimensions = getSliderDimensions(props),
handleRange = _getSliderDimensions.handleRange,
handleStart = _getSliderDimensions.handleStart;
var handlePos;
if (props.layoutDirection === 'horizontal') {
handlePos = -1 * y + handleRange + handleStart;
} else {
handlePos = x - handleStart;
} // clamp handle position
handlePos = Math.max(Math.min(handlePos, handleRange), 0);
var percent = Math.round(100 / handleRange * handlePos);
switch (props.sliderType) {
case 'kelvin':
var minTemperature = props.minTemperature,
maxTemperature = props.maxTemperature;
var temperatureRange = maxTemperature - minTemperature;
return minTemperature + temperatureRange * (percent / 100);
case 'alpha':
return percent / 100;
case 'hue':
return percent * 3.6;
case 'red':
case 'blue':
case 'green':
return percent * 2.55;
default:
return percent;
}
}
/**
* @desc Get the current handle position for a given color
* @param props - slider props
* @param color
*/
function getSliderHandlePosition(props, color) {
var _getSliderDimensions2 = getSliderDimensions(props),
width = _getSliderDimensions2.width,
height = _getSliderDimensions2.height,
handleRange = _getSliderDimensions2.handleRange,
handleStart = _getSliderDimensions2.handleStart;
var ishorizontal = props.layoutDirection === 'horizontal';
var sliderValue = getCurrentSliderValue(props, color);
var midPoint = ishorizontal ? width / 2 : height / 2;
var handlePos = handleStart + sliderValue / 100 * handleRange;
if (ishorizontal) {
handlePos = -1 * handlePos + handleRange + handleStart * 2;
}
return {
x: ishorizontal ? midPoint : handlePos,
y: ishorizontal ? handlePos : midPoint
};
}
/**
* @desc Get the gradient stops for a slider
* @param props - slider props
* @param color
*/
function getSliderGradient(props, color) {
var hsv = color.hsv;
var rgb = color.rgb;
switch (props.sliderType) {
case 'red':
return [[0, "rgb(" + 0 + "," + rgb.g + "," + rgb.b + ")"], [100, "rgb(" + 255 + "," + rgb.g + "," + rgb.b + ")"]];
case 'green':
return [[0, "rgb(" + rgb.r + "," + 0 + "," + rgb.b + ")"], [100, "rgb(" + rgb.r + "," + 255 + "," + rgb.b + ")"]];
case 'blue':
return [[0, "rgb(" + rgb.r + "," + rgb.g + "," + 0 + ")"], [100, "rgb(" + rgb.r + "," + rgb.g + "," + 255 + ")"]];
case 'alpha':
return [[0, "rgba(" + rgb.r + "," + rgb.g + "," + rgb.b + ",0)"], [100, "rgb(" + rgb.r + "," + rgb.g + "," + rgb.b + ")"]];
case 'kelvin':
var stops = [];
var min = props.minTemperature;
var max = props.maxTemperature;
var numStops = 8;
var range = max - min;
for (var kelvin = min, stop = 0; kelvin < max; kelvin += range / numStops, stop += 1) {
var _IroColor$kelvinToRgb = IroColor.kelvinToRgb(kelvin),
r = _IroColor$kelvinToRgb.r,
g = _IroColor$kelvinToRgb.g,
b = _IroColor$kelvinToRgb.b;
stops.push([100 / numStops * stop, "rgb(" + r + "," + g + "," + b + ")"]);
}
return stops;
case 'hue':
return [[0, '#f00'], [16.666, '#ff0'], [33.333, '#0f0'], [50, '#0ff'], [66.666, '#00f'], [83.333, '#f0f'], [100, '#f00']];
case 'saturation':
var noSat = IroColor.hsvToHsl({
h: hsv.h,
s: 0,
v: hsv.v
});
var fullSat = IroColor.hsvToHsl({
h: hsv.h,
s: 100,
v: hsv.v
});
return [[0, "hsl(" + noSat.h + "," + noSat.s + "%," + noSat.l + "%)"], [100, "hsl(" + fullSat.h + "," + fullSat.s + "%," + fullSat.l + "%)"]];
case 'value':
default:
var hsl = IroColor.hsvToHsl({
h: hsv.h,
s: hsv.s,
v: 100
});
return [[0, '#000'], [100, "hsl(" + hsl.h + "," + hsl.s + "%," + hsl.l + "%)"]];
}
}
var TAU = Math.PI * 2; // javascript's modulo operator doesn't produce positive numbers with negative input
// https://dev.to/maurobringolf/a-neat-trick-to-compute-modulo-of-negative-numbers-111e
var mod = function mod(a, n) {
return (a % n + n) % n;
}; // distance between points (x, y) and (0, 0)
var dist = function dist(x, y) {
return Math.sqrt(x * x + y * y);
};
/**
* @param props - wheel props
* @internal
*/
function getHandleRange(props) {
return props.width / 2 - props.padding - props.handleRadius - props.borderWidth;
}
/**
* Returns true if point (x, y) lands inside the wheel
* @param props - wheel props
* @param x
* @param y
*/
function isInputInsideWheel(props, x, y) {
var _getWheelDimensions = getWheelDimensions(props),
cx = _getWheelDimensions.cx,
cy = _getWheelDimensions.cy;
var r = props.width / 2;
return dist(cx - x, cy - y) < r;
}
/**
* @desc Get the point as the center of the wheel
* @param props - wheel props
*/
function getWheelDimensions(props) {
var r = props.width / 2;
return {
width: props.width,
radius: r - props.borderWidth,
cx: r,
cy: r
};
}
/**
* @desc Translate an angle according to wheelAngle and wheelDirection
* @param props - wheel props
* @param angle - input angle
*/
function translateWheelAngle(props, angle, invert) {
var wheelAngle = props.wheelAngle;
var wheelDirection = props.wheelDirection; // inverted and clockwisee
if (invert && wheelDirection === 'clockwise') { angle = wheelAngle + angle; } // clockwise (input handling)
else if (wheelDirection === 'clockwise') { angle = 360 - wheelAngle + angle; } // inverted and anticlockwise
else if (invert && wheelDirection === 'anticlockwise') { angle = wheelAngle + 180 - angle; } // anticlockwise (input handling)
else if (wheelDirection === 'anticlockwise') { angle = wheelAngle - angle; }
return mod(angle, 360);
}
/**
* @desc Get the current handle position for a given color
* @param props - wheel props
* @param color
*/
function getWheelHandlePosition(props, color) {
var hsv = color.hsv;
var _getWheelDimensions2 = getWheelDimensions(props),
cx = _getWheelDimensions2.cx,
cy = _getWheelDimensions2.cy;
var handleRange = getHandleRange(props);
var handleAngle = (180 + translateWheelAngle(props, hsv.h, true)) * (TAU / 360);
var handleDist = hsv.s / 100 * handleRange;
var direction = props.wheelDirection === 'clockwise' ? -1 : 1;
return {
x: cx + handleDist * Math.cos(handleAngle) * direction,
y: cy + handleDist * Math.sin(handleAngle) * direction
};
}
/**
* @desc Get the current wheel value from user input
* @param props - wheel props
* @param x - global input x position
* @param y - global input y position
*/
function getWheelValueFromInput(props, x, y) {
var _getWheelDimensions3 = getWheelDimensions(props),
cx = _getWheelDimensions3.cx,
cy = _getWheelDimensions3.cy;
var handleRange = getHandleRange(props);
x = cx - x;
y = cy - y; // Calculate the hue by converting the angle to radians
var hue = translateWheelAngle(props, Math.atan2(-y, -x) * (360 / TAU)); // Find the point's distance from the center of the wheel
// This is used to show the saturation level
var handleDist = Math.min(dist(x, y), handleRange);
return {
h: Math.round(hue),
s: Math.round(100 / handleRange * handleDist)
};
}
/**
* @desc Get the bounding dimensions of the box
* @param props - box props
*/
function getBoxDimensions(props) {
var width = props.width,
boxHeight = props.boxHeight,
padding = props.padding,
handleRadius = props.handleRadius;
return {
width: width,
height: boxHeight != null ? boxHeight : width,
radius: padding + handleRadius
};
}
/**
* @desc Get the current box value from user input
* @param props - box props
* @param x - global input x position
* @param y - global input y position
*/
function getBoxValueFromInput(props, x, y) {
var _getBoxDimensions = getBoxDimensions(props),
width = _getBoxDimensions.width,
height = _getBoxDimensions.height,
radius = _getBoxDimensions.radius;
var handleStart = radius;
var handleRangeX = width - radius * 2;
var handleRangeY = height - radius * 2;
var percentX = (x - handleStart) / handleRangeX * 100;
var percentY = (y - handleStart) / handleRangeY * 100;
return {
s: Math.max(0, Math.min(percentX, 100)),
v: Math.max(0, Math.min(100 - percentY, 100))
};
}
/**
* @desc Get the current box handle position for a given color
* @param props - box props
* @param color
*/
function getBoxHandlePosition(props, color) {
var _getBoxDimensions2 = getBoxDimensions(props),
width = _getBoxDimensions2.width,
height = _getBoxDimensions2.height,
radius = _getBoxDimensions2.radius;
var hsv = color.hsv;
var handleStart = radius;
var handleRangeX = width - radius * 2;
var handleRangeY = height - radius * 2;
return {
x: handleStart + hsv.s / 100 * handleRangeX,
y: handleStart + (handleRangeY - hsv.v / 100 * handleRangeY)
};
}
/**
* @desc Get the gradient stops for a box
* @param props - box props
* @param color
*/
function getBoxGradients(props, color) {
var hue = color.hue;
return [// saturation gradient
[[0, '#fff'], [100, "hsl(" + hue + ",100%,50%)"]], // lightness gradient
[[0, 'rgba(0,0,0,0)'], [100, '#000']]];
}
// Keep track of html <base> elements for resolveSvgUrl
// getElementsByTagName returns a live HTMLCollection, which stays in sync with the DOM tree
// So it only needs to be called once
var BASE_ELEMENTS;
/**
* @desc Resolve an SVG reference URL
* This is required to work around how Safari and iOS webviews handle gradient URLS under certain conditions
* If a page is using a client-side routing library which makes use of the HTML <base> tag,
* Safari won't be able to render SVG gradients properly (as they are referenced by URLs)
* More info on the problem:
* https://stackoverflow.com/questions/19742805/angular-and-svg-filters/19753427#19753427
* https://github.com/jaames/iro.js/issues/18
* https://github.com/jaames/iro.js/issues/45
* https://github.com/jaames/iro.js/pull/89
* @props url - SVG reference URL
*/
function resolveSvgUrl(url) {
if (!BASE_ELEMENTS) { BASE_ELEMENTS = document.getElementsByTagName('base'); } // Sniff useragent string to check if the user is running Safari
var ua = window.navigator.userAgent;
var isSafari = /^((?!chrome|android).)*safari/i.test(ua);
var isIos = /iPhone|iPod|iPad/i.test(ua);
var location = window.location;
return (isSafari || isIos) && BASE_ELEMENTS.length > 0 ? location.protocol + "//" + location.host + location.pathname + location.search + url : url;
}
/**
* @desc Given a specifc (x, y) position, test if there's a handle there and return its index, else return null.
* This is used for components like the box and wheel which support multiple handles when multicolor is active
* @props x - point x position
* @props y - point y position
* @props handlePositions - array of {x, y} coords for each handle
*/
function getHandleAtPoint(props, x, y, handlePositions) {
for (var i = 0; i < handlePositions.length; i++) {
var dX = handlePositions[i].x - x;
var dY = handlePositions[i].y - y;
var dist = Math.sqrt(dX * dX + dY * dY);
if (dist < props.handleRadius) {
return i;
}
}
return null;
}
function cssBorderStyles(props) {
return {
boxSizing: 'border-box',
border: props.borderWidth + "px solid " + props.borderColor
};
}
function cssGradient(type, direction, stops) {
return type + "-gradient(" + direction + ", " + stops.map(function (_ref) {
var o = _ref[0],
col = _ref[1];
return col + " " + o + "%";
}).join(',') + ")";
}
function cssValue(value) {
if (typeof value === 'string') { return value; }
return value + "px";
}
var iroColorPickerOptionDefaults = {
width: 300,
height: 300,
color: '#fff',
colors: [],
padding: 6,
layoutDirection: 'vertical',
borderColor: '#fff',
borderWidth: 0,
handleRadius: 8,
activeHandleRadius: null,
handleSvg: null,
handleProps: {
x: 0,
y: 0
},
wheelLightness: true,
wheelAngle: 0,
wheelDirection: 'anticlockwise',
sliderSize: null,
sliderMargin: 12,
boxHeight: null
};
var SECONDARY_EVENTS = ["mousemove" /* MouseMove */, "touchmove" /* TouchMove */, "mouseup" /* MouseUp */, "touchend" /* TouchEnd */];
// Base component class for iro UI components
// This extends the Preact component class to allow them to react to mouse/touch input events by themselves
var IroComponentWrapper = /*@__PURE__*/(function (Component) {
function IroComponentWrapper(props) {
Component.call(this, props);
// Generate unique ID for the component
// This can be used to generate unique IDs for gradients, etc
this.uid = (Math.random() + 1).toString(36).substring(5);
}
if ( Component ) IroComponentWrapper.__proto__ = Component;
IroComponentWrapper.prototype = Object.create( Component && Component.prototype );
IroComponentWrapper.prototype.constructor = IroComponentWrapper;
IroComponentWrapper.prototype.render = function render (props) {
var eventHandler = this.handleEvent.bind(this);
var rootProps = {
onMouseDown: eventHandler,
// https://github.com/jaames/iro.js/issues/126
// https://github.com/preactjs/preact/issues/2113#issuecomment-553408767
ontouchstart: eventHandler,
};
var isHorizontal = props.layoutDirection === 'horizontal';
var margin = props.margin === null ? props.sliderMargin : props.margin;
var rootStyles = {
overflow: 'visible',
display: isHorizontal ? 'inline-block' : 'block'
};
// first component shouldn't have any margin
if (props.index > 0) {
rootStyles[isHorizontal ? 'marginLeft' : 'marginTop'] = margin;
}
return (h(d, null, props.children(this.uid, rootProps, rootStyles)));
};
// More info on handleEvent:
// https://medium.com/@WebReflection/dom-handleevent-a-cross-platform-standard-since-year-2000-5bf17287fd38
// TL;DR this lets us have a single point of entry for multiple events, and we can avoid callback/binding hell
IroComponentWrapper.prototype.handleEvent = function handleEvent (e) {
var this$1$1 = this;
var inputHandler = this.props.onInput;
// Get the screen position of the component
var bounds = this.base.getBoundingClientRect();
// Prefect default browser action
e.preventDefault();
// Detect if the event is a touch event by checking if it has the `touches` property
// If it is a touch event, use the first touch input
var point = e.touches ? e.changedTouches[0] : e;
var x = point.clientX - bounds.left;
var y = point.clientY - bounds.top;
switch (e.ty