diff --git a/CHANGELOG.md b/CHANGELOG.md index 48a4a38..18a49a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,24 @@ ### Changelog +#### 5.6.0 + +##### Fixes + +- Fixed an issue where alpha value was reset to 1 after sliding both alpha and +any of the r/g/b sliders (#227). +- Fixed an issue with inaccurate kelvin conversion (replaced with more accurate script). + +##### Additions + +- Added optional label and input elements. Picker color can now be set via input field. +- Added optional `showInput`, `showLabel` and `disabled` slider options for displaying an input field and/or label field next to a slider. +- Added optional `sliderLength` slider option to set each slider's dimension seperately. + +##### Changes +- Utilize display:flex on the entire wrapper component. +- Wrap Slider components in a flex wrapper for easy positioning of elements. +- Add IroColor.raw_rgb getter for kelvin conversion issues (returns float numbers instead of int). + #### 5.5.2 ##### Fixes diff --git a/dist/Input.d.ts b/dist/Input.d.ts new file mode 100644 index 0000000..644d2bb --- /dev/null +++ b/dist/Input.d.ts @@ -0,0 +1,20 @@ +import { h } from 'preact'; +import { LayoutDirection } from '@irojs/iro-core'; +import { IroColor, SliderType } from '@irojs/iro-core'; +interface IroInputProps { + sliderType: SliderType; + sliderSize: number; + activeColor: IroColor; + layoutDirection: LayoutDirection; + handleRadius: number; + disabled: boolean; + minTemperature: number; + maxTemperature: number; +} +export declare function IroInput(props: IroInputProps): h.JSX.Element; +export declare namespace IroInput { + var defaultProps: { + disabled: boolean; + }; +} +export {}; diff --git a/dist/Label.d.ts b/dist/Label.d.ts new file mode 100644 index 0000000..b6105be --- /dev/null +++ b/dist/Label.d.ts @@ -0,0 +1,10 @@ +import { h } from 'preact'; +import { LayoutDirection } from '@irojs/iro-core'; +import { SliderType } from '@irojs/iro-core'; +interface IroLabelProps { + sliderType: SliderType; + layoutDirection: LayoutDirection; + handleRadius: number; +} +export declare function IroLabel(props: IroLabelProps): h.JSX.Element; +export {}; diff --git a/dist/Slider.d.ts b/dist/Slider.d.ts index 1ca0546..79d7f3c 100644 --- a/dist/Slider.d.ts +++ b/dist/Slider.d.ts @@ -4,8 +4,12 @@ import { IroComponentProps } from './ComponentTypes'; interface IroSliderProps extends IroComponentProps { sliderType: SliderType; sliderShape: SliderShape; + sliderSize: number; minTemperature: number; maxTemperature: number; + showInput: boolean; + showLabel: boolean; + disabled: boolean; } export declare function IroSlider(props: IroSliderProps): h.JSX.Element; export declare namespace IroSlider { diff --git a/dist/iro.es.js b/dist/iro.es.js index 8f351a7..91a4f26 100644 --- a/dist/iro.es.js +++ b/dist/iro.es.js @@ -5,7 +5,7 @@ * github.com/jaames/iro.js */ -var n,u,t,i,r,o,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;t2&&(f.children=arguments.length>3?n.call(arguments,2):i),"function"==typeof l&&null!=l.defaultProps){ for(r in l.defaultProps){ void 0===f[r]&&(f[r]=l.defaultProps[r]); } }return y(l,f,t,o,null)}function y(n,i,t,o,r){var f={type:n,props:i,key:t,ref:o,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==r?++u:r};return null==r&&null!=l.vnode&&l.vnode(f),f}function d(n){return n.children}function _(n,l){this.props=n,this.context=l;}function k(n,l){if(null==l){ return n.__?k(n.__,n.__.__k.indexOf(n)+1):null; }for(var u;l0?y(_.type,_.props,_.key,null,_.__v):_)){if(_.__=u,_.__b=u.__b+1,null===(p=w[h])||p&&_.key==p.key&&_.type===p.type){ w[h]=void 0; }else { for(v=0;v 255) { r = 255; } + } + /* Calculate g */ + + + if (temperature < 66.0) { + g = temperature - 2; + g = -155.25485562709179 - 0.44596950469579133 * g + 104.49216199393888 * Math.log(g); + if (g < 0) { g = 0; } + if (g > 255) { g = 255; } + } else { + g = temperature - 50.0; + g = 325.4494125711974 + 0.07943456536662342 * g - 28.0852963507957 * Math.log(g); + if (g < 0) { g = 0; } + if (g > 255) { g = 255; } + } + /* Calculate b */ + + + if (temperature >= 66.0) { b = 255; + } else { + if (temperature <= 20.0) { + b = 0; + } else { + b = temperature - 10; + b = -254.76935184120902 + 0.8274096064007395 * b + 115.67994401066147 * Math.log(b); + if (b < 0) { b = 0; } + if (b > 255) { b = 255; } + } } return { - r: clamp(floor(r), 0, 255), - g: clamp(floor(g), 0, 255), - b: clamp(floor(b), 0, 255) + r: r, + b: b, + g: g }; } /** @@ -344,26 +369,23 @@ function () { ; 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 temperature, testRGB; + var epsilon = 0.4; + var minTemperature = 1000; + var maxTemperature = 40000; - var _rgb = IroColor.kelvinToRgb(temp); + while (maxTemperature - minTemperature > epsilon) { + temperature = (maxTemperature + minTemperature) / 2; + testRGB = IroColor.kelvinToRgb(temperature); - if (_rgb.b / _rgb.r >= b / r) { - maxTemp = temp; + if (testRGB.b / testRGB.r >= rgb.b / rgb.r) { + maxTemperature = temperature; } else { - minTemp = temp; + minTemperature = temperature; } } - return temp; + return temperature; }; _createClass(IroColor, [{ @@ -453,7 +475,7 @@ function () { }, { key: "kelvin", get: function get() { - return IroColor.rgbToKelvin(this.rgb); + return round(IroColor.rgbToKelvin(this.raw_rgb)); }, set: function set(value) { this.rgb = IroColor.kelvinToRgb(value); @@ -507,9 +529,23 @@ function () { }, set: function set(value) { this.hsv = _extends({}, IroColor.rgbToHsv(value), { - a: value.a === undefined ? 1 : value.a + a: value.a === undefined ? this.alpha : value.a }); } + }, { + key: "raw_rgb", + get: function get() { + var _IroColor$hsvToRgb2 = IroColor.hsvToRgb(this.$), + r = _IroColor$hsvToRgb2.r, + g = _IroColor$hsvToRgb2.g, + b = _IroColor$hsvToRgb2.b; + + return { + r: r, + g: g, + b: b + }; + } }, { key: "rgba", get: function get() { @@ -536,7 +572,7 @@ function () { }, set: function set(value) { this.hsv = _extends({}, IroColor.hslToHsv(value), { - a: value.a === undefined ? 1 : value.a + a: value.a === undefined ? this.alpha : value.a }); } }, { @@ -695,6 +731,108 @@ function () { return IroColor; }(); +/** + * @desc Get input field dimensions + * @param props - InputOptions + */ +function getInputDimensions(props) { + var sliderSize = props.sliderSize, + layoutDirection = props.layoutDirection; + var inputWidth; + var fontSize; + + if (layoutDirection === 'vertical') { + inputWidth = 30; + fontSize = 12; + } else { + inputWidth = sliderSize <= 30 ? 26 : sliderSize; + fontSize = sliderSize <= 30 ? 10 : 12; + } + + return { + inputWidth: inputWidth, + inputHeight: 18, + fontSize: fontSize + }; +} +/** + * @desc Clamp slider value between min and max values + * @param type - props.sliderType + * @param value - value to clamp + */ + +function clampSliderValue(props, value) { + function clamp(num, min, max) { + return Math.min(Math.max(num, min), max); + } + + switch (props.sliderType) { + case 'hue': + return clamp(value, 0, 360); + + case 'saturation': + case 'value': + return clamp(value, 0, 100); + + case 'red': + case 'green': + case 'blue': + return clamp(value, 0, 255); + + case 'alpha': + return clamp(value, 0, 1); + + case 'kelvin': + var minTemperature = props.minTemperature, + maxTemperature = props.maxTemperature; + return clamp(value, minTemperature, maxTemperature); + } +} +/** + * @desc Get the current slider value from input field input + * @param props - slider props + * @param e - KeyboardEvent + */ + +function getSliderValueFromInputField(e) { + var target = e.target; + var valueNum = parseInt(target.value); // regex for digit or dot (.) + + if (!/^([0-9]|\.)$/i.test(e.key)) { + e.preventDefault(); + return valueNum; + } + + var valueString = target.value.toString(); + + if (target.selectionStart !== undefined) { + // cursor position + valueString = valueString.substring(0, target.selectionStart) + e.key.toString() + valueString.substring(target.selectionEnd); + } else { + valueString = valueString + e.key.toString(); + } + + return +valueString; +} +/** + * @desc Get the current slider value from clipboard data + * @param props - slider props + * @param e - ClipboardEvent + */ + +function getSliderValueFromClipboard(props, e) { + // allow only whole or decimal numbers + var r = /^[+]?([.]\d+|\d+([.]\d+)?)$/i; + var valueString = e.clipboardData.getData('text'); + + if (!r.test(valueString)) { + return 0; + } + + var valueNum = +valueString; + return clampSliderValue(props, valueNum); +} + var sliderDefaultOptions = { sliderShape: 'bar', sliderType: 'value', @@ -715,7 +853,30 @@ function getSliderDimensions(props) { handleRadius = props.handleRadius, padding = props.padding, sliderShape = props.sliderShape; - var ishorizontal = props.layoutDirection === 'horizontal'; // automatically calculate sliderSize if its not defined + var ishorizontal = props.layoutDirection === 'horizontal'; + var length; + + if (props.sliderLength) { + length = props.sliderLength; + } else { + // automatically calculate slider length + length = width - handleRadius; + + if (props.showInput) { + var _getInputDimensions = getInputDimensions(props), + inputWidth = _getInputDimensions.inputWidth, + inputHeight = _getInputDimensions.inputHeight; + + length -= ishorizontal ? inputHeight : inputWidth; + length -= 3; // padding + } + + if (props.showLabel) { + length -= ishorizontal ? 12 : 10; + length -= 3; // padding + } + } // automatically calculate sliderSize if its not defined + sliderSize = (_sliderSize = sliderSize) != null ? _sliderSize : padding * 2 + handleRadius * 2; @@ -732,12 +893,12 @@ function getSliderDimensions(props) { } else { return { handleStart: sliderSize / 2, - handleRange: width - sliderSize, + handleRange: length - sliderSize, radius: sliderSize / 2, x: 0, y: 0, - width: ishorizontal ? sliderSize : width, - height: ishorizontal ? width : sliderSize + width: ishorizontal ? sliderSize : length, + height: ishorizontal ? length : sliderSize }; } } @@ -768,7 +929,7 @@ function getCurrentSliderValue(props, color) { var minTemperature = props.minTemperature, maxTemperature = props.maxTemperature; var temperatureRange = maxTemperature - minTemperature; - var percent = (color.kelvin - minTemperature) / temperatureRange * 100; // clmap percentage + var percent = (color.kelvin - minTemperature) / temperatureRange * 100; // clamp percentage return Math.max(0, Math.min(percent, 100)); @@ -986,8 +1147,8 @@ function translateWheelAngle(props, angle, invert) { 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; } + else if (invert && wheelDirection === 'anticlockwise') { angle = wheelAngle + 180 - angle; } // anticlockwise (input handling) + else if (wheelDirection === 'anticlockwise') { angle = wheelAngle - angle; } return mod(angle, 360); } /** @@ -1226,13 +1387,13 @@ var IroComponentWrapper = /*@__PURE__*/(function (Component) { var margin = props.margin === null ? props.sliderMargin : props.margin; var rootStyles = { overflow: 'visible', - display: isHorizontal ? 'inline-block' : 'block' + display: isHorizontal ? 'inline-flex' : 'flex' }; // 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))); + return (v(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 @@ -1275,15 +1436,14 @@ var IroComponentWrapper = /*@__PURE__*/(function (Component) { }; return IroComponentWrapper; -}(m)); +}(_)); function IroHandle(props) { var radius = props.r; var url = props.url; var cx = radius; var cy = radius; - return (h("svg", { className: ("IroHandle IroHandle--" + (props.index) + " " + (props.isActive ? 'IroHandle--isActive' : '')), style: { - '-webkit-tap-highlight-color': 'rgba(0, 0, 0, 0);', + return (v("svg", { className: ("IroHandle IroHandle--" + (props.index) + " " + (props.isActive ? 'IroHandle--isActive' : '')), style: { transform: ("translate(" + (cssValue(props.x)) + ", " + (cssValue(props.y)) + ")"), willChange: 'transform', top: cssValue(-radius), @@ -1293,9 +1453,9 @@ function IroHandle(props) { position: 'absolute', overflow: 'visible' } }, - url && (h("use", Object.assign({ xlinkHref: resolveSvgUrl(url) }, props.props))), - !url && (h("circle", { cx: cx, cy: cy, r: radius, fill: "none", "stroke-width": 2, stroke: "#000" })), - !url && (h("circle", { cx: cx, cy: cy, r: radius - 2, fill: props.fill, "stroke-width": 2, stroke: "#fff" })))); + url && (v("use", Object.assign({ xlinkHref: resolveSvgUrl(url) }, props.props))), + !url && (v("circle", { cx: cx, cy: cy, r: radius, fill: "none", "stroke-width": 2, stroke: "#000" })), + !url && (v("circle", { cx: cx, cy: cy, r: radius - 2, fill: props.fill, "stroke-width": 2, stroke: "#fff" })))); } IroHandle.defaultProps = { fill: 'none', @@ -1306,6 +1466,81 @@ IroHandle.defaultProps = { props: { x: 0, y: 0 } }; +var t$1,u$1,r$1,o$1=0,i=[],c$1=l.__b,f$1=l.__r,e$1=l.diffed,a$1=l.__c,v$1=l.unmount;function l$1(t,r){l.__h&&l.__h(u$1,t,o$1||r),o$1=0;var i=u$1.__H||(u$1.__H={__:[],__h:[]});return t>=i.__.length&&i.__.push({}),i.__[t]}function m$1(n){return o$1=1,p(w$1,n)}function p(n,r,o){var i=l$1(t$1++,2);return i.t=n,i.__c||(i.__=[o?o(r):w$1(void 0,r),function(n){var t=i.t(i.__[0],n);i.__[0]!==t&&(i.__=[t,i.__[1]],i.__c.setState({}));}],i.__c=u$1),i.__}function _$1(n,u){var r=l$1(t$1++,7);return k$1(r.__H,u)&&(r.__=n(),r.__H=u,r.__h=n),r.__}function A(n,t){return o$1=8,_$1(function(){return n},t)}function x$1(){for(var t;t=i.shift();){ if(t.__P){ try{t.__H.__h.forEach(g$1),t.__H.__h.forEach(j$1),t.__H.__h=[];}catch(u){t.__H.__h=[],l.__e(u,t.__v);} } }}l.__b=function(n){u$1=null,c$1&&c$1(n);},l.__r=function(n){f$1&&f$1(n),t$1=0;var r=(u$1=n.__c).__H;r&&(r.__h.forEach(g$1),r.__h.forEach(j$1),r.__h=[]);},l.diffed=function(t){e$1&&e$1(t);var o=t.__c;o&&o.__H&&o.__H.__h.length&&(1!==i.push(o)&&r$1===l.requestAnimationFrame||((r$1=l.requestAnimationFrame)||function(n){var t,u=function(){clearTimeout(r),b$1&&cancelAnimationFrame(t),setTimeout(n);},r=setTimeout(u,100);b$1&&(t=requestAnimationFrame(u));})(x$1)),u$1=null;},l.__c=function(t,u){u.some(function(t){try{t.__h.forEach(g$1),t.__h=t.__h.filter(function(n){return !n.__||j$1(n)});}catch(r){u.some(function(n){n.__h&&(n.__h=[]);}),u=[],l.__e(r,t.__v);}}),a$1&&a$1(t,u);},l.unmount=function(t){v$1&&v$1(t);var u,r=t.__c;r&&r.__H&&(r.__H.__.forEach(function(n){try{g$1(n);}catch(n$1){u=n$1;}}),u&&l.__e(u,r.__v));};var b$1="function"==typeof requestAnimationFrame;function g$1(n){var t=u$1,r=n.__c;"function"==typeof r&&(n.__c=void 0,r()),u$1=t;}function j$1(n){var t=u$1;n.__c=n.__(),u$1=t;}function k$1(n,t){return !n||n.length!==t.length||t.some(function(t,u){return t!==n[u]})}function w$1(n,t){return "function"==typeof t?t(n):t} + +function IroInput(props) { + var disabled = props.disabled; + var type = props.sliderType; + var ref = getInputDimensions(props); + var inputWidth = ref.inputWidth; + var fontSize = ref.fontSize; + var activeColor = props.activeColor; + var ref$1 = m$1(activeColor[props.sliderType]); + var sliderValue = ref$1[0]; + var setSliderValue = ref$1[1]; + var val = (type === 'alpha') ? activeColor[props.sliderType].toFixed(2) : Math.round(activeColor[props.sliderType]); + setSliderValue(val); + var onKeypress = A(function (e) { + var value = getSliderValueFromInputField(e); + if (type === 'kelvin') { + var strlen = value.toString().length, minlen = props.minTemperature.toString().length, maxlen = props.maxTemperature.toString().length; + if (strlen > maxlen) { + e.preventDefault(); + activeColor[props.sliderType] = props.maxTemperature; + } + else if (strlen >= minlen) { + if (value < props.minTemperature) { + if (maxlen === minlen) { + e.preventDefault(); + activeColor[props.sliderType] = props.minTemperature; + } + } + else if (value > props.maxTemperature) { + e.preventDefault(); + activeColor[props.sliderType] = props.maxTemperature; + } + else { + e.preventDefault(); + activeColor[props.sliderType] = value; + } + } + } + else { + e.preventDefault(); + activeColor[props.sliderType] = clampSliderValue(props, value); + } + return value; + }, [setSliderValue, props.sliderType]); + var onPaste = A(function (e) { + e.preventDefault(); + var value = getSliderValueFromClipboard(props, e); + activeColor[props.sliderType] = value; + return value; + }, [setSliderValue, props.sliderType]); + return (v("div", { className: "IroSliderValue" }, + v("input", { onKeyPress: onKeypress, onPaste: onPaste, className: "IroSliderInput", style: { + display: 'inline-block', + width: type === 'kelvin' ? cssValue(40) : inputWidth, + height: cssValue(18), + fontSize: fontSize, + padding: cssValue(2) + }, type: "text", disabled: disabled, value: sliderValue }))); +} +IroInput.defaultProps = { + disabled: false +}; + +function IroLabel(props) { + var name = props.sliderType[0].toUpperCase(); + return (v("div", { className: "IroSliderLabel", style: { + display: 'inline-block', + width: cssValue(10), + height: cssValue(12), + lineHeight: cssValue(12), + fontSize: props.layoutDirection === 'horizontal' ? cssValue(12) : cssValue(14) + } }, name)); +} + function IroSlider(props) { var activeIndex = props.activeIndex; var activeColor = (activeIndex !== undefined && activeIndex < props.colors.length) ? props.colors[activeIndex] : props.color; @@ -1319,25 +1554,40 @@ function IroSlider(props) { var value = getSliderValueFromInput(props, x, y); props.parent.inputActive = true; activeColor[props.sliderType] = value; + if (props.sliderType === 'kelvin') { + activeColor._kelvin = value; + } props.onInput(type, props.id); } - return (h(IroComponentWrapper, Object.assign({}, props, { onInput: handleInput }), function (uid, rootProps, rootStyles) { return (h("div", Object.assign({}, rootProps, { className: "IroSlider", style: Object.assign({}, {position: 'relative', - width: cssValue(width), - height: cssValue(height), - borderRadius: cssValue(radius), - // checkered bg to represent alpha - background: "conic-gradient(#ccc 25%, #fff 0 50%, #ccc 0 75%, #fff 0)", - backgroundSize: '8px 8px'}, - rootStyles) }), - h("div", { className: "IroSliderGradient", style: Object.assign({}, {position: 'absolute', - top: 0, - left: 0, - width: "100%", - height: "100%", + return (v(IroComponentWrapper, Object.assign({}, props, { onInput: handleInput }), function (uid, rootProps, rootStyles) { return ( + // add wrapper element + v("div", { className: "IroSliderWrapper", style: Object.assign({}, {width: props.layoutDirection === 'vertical' ? cssValue(props.width) : 'unset', + height: props.layoutDirection === 'horizontal' ? cssValue(props.width) : 'unset', + flexDirection: props.layoutDirection === 'horizontal' ? 'column' : 'row', + alignItems: 'center', + justifyContent: 'space-between'}, + rootStyles) }, + v("div", Object.assign({}, rootProps, { className: "IroSlider", style: { + position: 'relative', + display: 'block', + width: cssValue(width), + height: cssValue(height), borderRadius: cssValue(radius), - background: cssGradient('linear', props.layoutDirection === 'horizontal' ? 'to top' : 'to right', gradient)}, - cssBorderStyles(props)) }), - h(IroHandle, { isActive: true, index: activeColor.index, r: props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePos.x, y: handlePos.y }))); })); + // checkered bg to represent alpha + background: "conic-gradient(#ccc 25%, #fff 0 50%, #ccc 0 75%, #fff 0)", + backgroundSize: '8px 8px', + } }), + v("div", { className: "IroSliderGradient", style: Object.assign({}, {position: 'absolute', + top: 0, + left: 0, + width: "100%", + height: "100%", + borderRadius: cssValue(radius), + background: cssGradient('linear', props.layoutDirection === 'horizontal' ? 'to top' : 'to right', gradient)}, + cssBorderStyles(props)) }), + v(IroHandle, { isActive: true, index: activeColor.index, r: props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePos.x, y: handlePos.y })), + props.showLabel && (v(IroLabel, { sliderType: props.sliderType, layoutDirection: props.layoutDirection, handleRadius: props.handleRadius })), + props.showInput && (v(IroInput, { disabled: props.disabled, sliderType: props.sliderType, sliderSize: props.sliderSize, activeColor: activeColor, handleRadius: props.handleRadius, layoutDirection: props.layoutDirection, minTemperature: props.minTemperature, maxTemperature: props.maxTemperature })))); })); } IroSlider.defaultProps = Object.assign({}, sliderDefaultOptions); @@ -1375,19 +1625,19 @@ function IroBox(props) { // let the color picker fire input:start, input:move or input:end events props.onInput(inputType, props.id); } - return (h(IroComponentWrapper, Object.assign({}, props, { onInput: handleInput }), function (uid, rootProps, rootStyles) { return (h("div", Object.assign({}, rootProps, { className: "IroBox", style: Object.assign({}, {width: cssValue(width), + return (v(IroComponentWrapper, Object.assign({}, props, { onInput: handleInput }), function (uid, rootProps, rootStyles) { return (v("div", Object.assign({}, rootProps, { className: "IroBox", style: Object.assign({}, {width: cssValue(width), height: cssValue(height), position: 'relative'}, rootStyles) }), - h("div", { className: "IroBox", style: Object.assign({}, {width: '100%', + v("div", { className: "IroBox", style: Object.assign({}, {width: '100%', height: '100%', borderRadius: cssValue(radius)}, cssBorderStyles(props), {background: cssGradient('linear', 'to bottom', gradients[1]) + ',' + cssGradient('linear', 'to right', gradients[0])}) }), - colors.filter(function (color) { return color !== activeColor; }).map(function (color) { return (h(IroHandle, { isActive: false, index: color.index, fill: color.hslString, r: props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePositions[color.index].x, y: handlePositions[color.index].y })); }), - h(IroHandle, { isActive: true, index: activeColor.index, fill: activeColor.hslString, r: props.activeHandleRadius || props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePositions[activeColor.index].x, y: handlePositions[activeColor.index].y }))); })); + colors.filter(function (color) { return color !== activeColor; }).map(function (color) { return (v(IroHandle, { isActive: false, index: color.index, fill: color.hslString, r: props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePositions[color.index].x, y: handlePositions[color.index].y })); }), + v(IroHandle, { isActive: true, index: activeColor.index, fill: activeColor.hslString, r: props.activeHandleRadius || props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePositions[activeColor.index].x, y: handlePositions[activeColor.index].y }))); })); } var HUE_GRADIENT_CLOCKWISE = 'conic-gradient(red, yellow, lime, aqua, blue, magenta, red)'; @@ -1439,22 +1689,22 @@ function IroWheel(props) { // let the color picker fire input:start, input:move or input:end events props.onInput(inputType, props.id); } - return (h(IroComponentWrapper, Object.assign({}, props, { onInput: handleInput }), function (uid, rootProps, rootStyles) { return (h("div", Object.assign({}, rootProps, { className: "IroWheel", style: Object.assign({}, {width: cssValue(width), + return (v(IroComponentWrapper, Object.assign({}, props, { onInput: handleInput }), function (uid, rootProps, rootStyles) { return (v("div", Object.assign({}, rootProps, { className: "IroWheel", style: Object.assign({}, {width: cssValue(width), height: cssValue(width), position: 'relative'}, rootStyles) }), - h("div", { className: "IroWheelHue", style: Object.assign({}, circleStyles, + v("div", { className: "IroWheelHue", style: Object.assign({}, circleStyles, {transform: ("rotateZ(" + (props.wheelAngle + 90) + "deg)"), background: props.wheelDirection === 'clockwise' ? HUE_GRADIENT_CLOCKWISE : HUE_GRADIENT_ANTICLOCKWISE}) }), - h("div", { className: "IroWheelSaturation", style: Object.assign({}, circleStyles, + v("div", { className: "IroWheelSaturation", style: Object.assign({}, circleStyles, {background: 'radial-gradient(circle closest-side, #fff, transparent)'}) }), - props.wheelLightness && (h("div", { className: "IroWheelLightness", style: Object.assign({}, circleStyles, + props.wheelLightness && (v("div", { className: "IroWheelLightness", style: Object.assign({}, circleStyles, {background: '#000', opacity: 1 - hsv.v / 100}) })), - h("div", { className: "IroWheelBorder", style: Object.assign({}, circleStyles, + v("div", { className: "IroWheelBorder", style: Object.assign({}, circleStyles, cssBorderStyles(props)) }), - colors.filter(function (color) { return color !== activeColor; }).map(function (color) { return (h(IroHandle, { isActive: false, index: color.index, fill: color.hslString, r: props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePositions[color.index].x, y: handlePositions[color.index].y })); }), - h(IroHandle, { isActive: true, index: activeColor.index, fill: activeColor.hslString, r: props.activeHandleRadius || props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePositions[activeColor.index].x, y: handlePositions[activeColor.index].y }))); })); + colors.filter(function (color) { return color !== activeColor; }).map(function (color) { return (v(IroHandle, { isActive: false, index: color.index, fill: color.hslString, r: props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePositions[color.index].x, y: handlePositions[color.index].y })); }), + v(IroHandle, { isActive: true, index: activeColor.index, fill: activeColor.hslString, r: props.activeHandleRadius || props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePositions[activeColor.index].x, y: handlePositions[activeColor.index].y }))); })); } function createWidget(WidgetComponent) { @@ -1462,7 +1712,7 @@ function createWidget(WidgetComponent) { var widget; // will become an instance of the widget component class var widgetRoot = document.createElement('div'); // Render widget into a temp DOM node - I(h(WidgetComponent, Object.assign({}, {ref: function (ref) { return widget = ref; }}, + S(v(WidgetComponent, Object.assign({}, {ref: function (ref) { return widget = ref; }}, props)), widgetRoot); function mountWidget() { var container = parent instanceof Element ? parent : document.querySelector(parent); @@ -1739,21 +1989,22 @@ var IroColorPicker = /*@__PURE__*/(function (Component) { }); } } - return (h("div", { class: "IroColorPicker", id: state.id, style: { - display: state.display + return (v("div", { class: "IroColorPicker", id: state.id, style: { + display: state.display, + flexDirection: props.layoutDirection === 'horizontal' ? 'row' : 'column' } }, layout.map(function (ref, componentIndex) { var UiComponent = ref.component; var options = ref.options; - return (h(UiComponent, Object.assign({}, state, options, { ref: undefined, onInput: this$1.emitInputEvent.bind(this$1), parent: this$1, index: componentIndex }))); + return (v(UiComponent, Object.assign({}, state, options, { ref: undefined, onInput: this$1.emitInputEvent.bind(this$1), parent: this$1, index: componentIndex }))); }))); }; return IroColorPicker; -}(m)); +}(_)); IroColorPicker.defaultProps = Object.assign({}, iroColorPickerOptionDefaults, {colors: [], - display: 'block', + display: 'flex', id: null, layout: 'default', margin: null}); @@ -1766,7 +2017,7 @@ var iro; iro.ColorPicker = IroColorPickerWidget; var ui; (function (ui) { - ui.h = h; + ui.h = v; ui.ComponentBase = IroComponentWrapper; ui.Handle = IroHandle; ui.Slider = IroSlider; diff --git a/dist/iro.js b/dist/iro.js index 55e7eb4..18bab80 100644 --- a/dist/iro.js +++ b/dist/iro.js @@ -9,9 +9,9 @@ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = global || self, global.iro = factory()); -}(this, function () { 'use strict'; +}(this, (function () { 'use strict'; - var n,u,t,i,r,o,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;t2&&(f.children=arguments.length>3?n.call(arguments,2):i),"function"==typeof l&&null!=l.defaultProps){ for(r in l.defaultProps){ void 0===f[r]&&(f[r]=l.defaultProps[r]); } }return y(l,f,t,o,null)}function y(n,i,t,o,r){var f={type:n,props:i,key:t,ref:o,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==r?++u:r};return null==r&&null!=l.vnode&&l.vnode(f),f}function d(n){return n.children}function _(n,l){this.props=n,this.context=l;}function k(n,l){if(null==l){ return n.__?k(n.__,n.__.__k.indexOf(n)+1):null; }for(var u;l0?y(_.type,_.props,_.key,null,_.__v):_)){if(_.__=u,_.__b=u.__b+1,null===(p=w[h])||p&&_.key==p.key&&_.type===p.type){ w[h]=void 0; }else { for(v=0;v 255) { r = 255; } + } + /* Calculate g */ + + + if (temperature < 66.0) { + g = temperature - 2; + g = -155.25485562709179 - 0.44596950469579133 * g + 104.49216199393888 * Math.log(g); + if (g < 0) { g = 0; } + if (g > 255) { g = 255; } + } else { + g = temperature - 50.0; + g = 325.4494125711974 + 0.07943456536662342 * g - 28.0852963507957 * Math.log(g); + if (g < 0) { g = 0; } + if (g > 255) { g = 255; } + } + /* Calculate b */ + + + if (temperature >= 66.0) { b = 255; + } else { + if (temperature <= 20.0) { + b = 0; + } else { + b = temperature - 10; + b = -254.76935184120902 + 0.8274096064007395 * b + 115.67994401066147 * Math.log(b); + if (b < 0) { b = 0; } + if (b > 255) { b = 255; } + } } return { - r: clamp(floor(r), 0, 255), - g: clamp(floor(g), 0, 255), - b: clamp(floor(b), 0, 255) + r: r, + b: b, + g: g }; } /** @@ -350,26 +375,23 @@ ; 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 temperature, testRGB; + var epsilon = 0.4; + var minTemperature = 1000; + var maxTemperature = 40000; - var _rgb = IroColor.kelvinToRgb(temp); + while (maxTemperature - minTemperature > epsilon) { + temperature = (maxTemperature + minTemperature) / 2; + testRGB = IroColor.kelvinToRgb(temperature); - if (_rgb.b / _rgb.r >= b / r) { - maxTemp = temp; + if (testRGB.b / testRGB.r >= rgb.b / rgb.r) { + maxTemperature = temperature; } else { - minTemp = temp; + minTemperature = temperature; } } - return temp; + return temperature; }; _createClass(IroColor, [{ @@ -459,7 +481,7 @@ }, { key: "kelvin", get: function get() { - return IroColor.rgbToKelvin(this.rgb); + return round(IroColor.rgbToKelvin(this.raw_rgb)); }, set: function set(value) { this.rgb = IroColor.kelvinToRgb(value); @@ -513,9 +535,23 @@ }, set: function set(value) { this.hsv = _extends({}, IroColor.rgbToHsv(value), { - a: value.a === undefined ? 1 : value.a + a: value.a === undefined ? this.alpha : value.a }); } + }, { + key: "raw_rgb", + get: function get() { + var _IroColor$hsvToRgb2 = IroColor.hsvToRgb(this.$), + r = _IroColor$hsvToRgb2.r, + g = _IroColor$hsvToRgb2.g, + b = _IroColor$hsvToRgb2.b; + + return { + r: r, + g: g, + b: b + }; + } }, { key: "rgba", get: function get() { @@ -542,7 +578,7 @@ }, set: function set(value) { this.hsv = _extends({}, IroColor.hslToHsv(value), { - a: value.a === undefined ? 1 : value.a + a: value.a === undefined ? this.alpha : value.a }); } }, { @@ -701,6 +737,108 @@ return IroColor; }(); + /** + * @desc Get input field dimensions + * @param props - InputOptions + */ + function getInputDimensions(props) { + var sliderSize = props.sliderSize, + layoutDirection = props.layoutDirection; + var inputWidth; + var fontSize; + + if (layoutDirection === 'vertical') { + inputWidth = 30; + fontSize = 12; + } else { + inputWidth = sliderSize <= 30 ? 26 : sliderSize; + fontSize = sliderSize <= 30 ? 10 : 12; + } + + return { + inputWidth: inputWidth, + inputHeight: 18, + fontSize: fontSize + }; + } + /** + * @desc Clamp slider value between min and max values + * @param type - props.sliderType + * @param value - value to clamp + */ + + function clampSliderValue(props, value) { + function clamp(num, min, max) { + return Math.min(Math.max(num, min), max); + } + + switch (props.sliderType) { + case 'hue': + return clamp(value, 0, 360); + + case 'saturation': + case 'value': + return clamp(value, 0, 100); + + case 'red': + case 'green': + case 'blue': + return clamp(value, 0, 255); + + case 'alpha': + return clamp(value, 0, 1); + + case 'kelvin': + var minTemperature = props.minTemperature, + maxTemperature = props.maxTemperature; + return clamp(value, minTemperature, maxTemperature); + } + } + /** + * @desc Get the current slider value from input field input + * @param props - slider props + * @param e - KeyboardEvent + */ + + function getSliderValueFromInputField(e) { + var target = e.target; + var valueNum = parseInt(target.value); // regex for digit or dot (.) + + if (!/^([0-9]|\.)$/i.test(e.key)) { + e.preventDefault(); + return valueNum; + } + + var valueString = target.value.toString(); + + if (target.selectionStart !== undefined) { + // cursor position + valueString = valueString.substring(0, target.selectionStart) + e.key.toString() + valueString.substring(target.selectionEnd); + } else { + valueString = valueString + e.key.toString(); + } + + return +valueString; + } + /** + * @desc Get the current slider value from clipboard data + * @param props - slider props + * @param e - ClipboardEvent + */ + + function getSliderValueFromClipboard(props, e) { + // allow only whole or decimal numbers + var r = /^[+]?([.]\d+|\d+([.]\d+)?)$/i; + var valueString = e.clipboardData.getData('text'); + + if (!r.test(valueString)) { + return 0; + } + + var valueNum = +valueString; + return clampSliderValue(props, valueNum); + } + var sliderDefaultOptions = { sliderShape: 'bar', sliderType: 'value', @@ -721,7 +859,30 @@ handleRadius = props.handleRadius, padding = props.padding, sliderShape = props.sliderShape; - var ishorizontal = props.layoutDirection === 'horizontal'; // automatically calculate sliderSize if its not defined + var ishorizontal = props.layoutDirection === 'horizontal'; + var length; + + if (props.sliderLength) { + length = props.sliderLength; + } else { + // automatically calculate slider length + length = width - handleRadius; + + if (props.showInput) { + var _getInputDimensions = getInputDimensions(props), + inputWidth = _getInputDimensions.inputWidth, + inputHeight = _getInputDimensions.inputHeight; + + length -= ishorizontal ? inputHeight : inputWidth; + length -= 3; // padding + } + + if (props.showLabel) { + length -= ishorizontal ? 12 : 10; + length -= 3; // padding + } + } // automatically calculate sliderSize if its not defined + sliderSize = (_sliderSize = sliderSize) != null ? _sliderSize : padding * 2 + handleRadius * 2; @@ -738,12 +899,12 @@ } else { return { handleStart: sliderSize / 2, - handleRange: width - sliderSize, + handleRange: length - sliderSize, radius: sliderSize / 2, x: 0, y: 0, - width: ishorizontal ? sliderSize : width, - height: ishorizontal ? width : sliderSize + width: ishorizontal ? sliderSize : length, + height: ishorizontal ? length : sliderSize }; } } @@ -774,7 +935,7 @@ var minTemperature = props.minTemperature, maxTemperature = props.maxTemperature; var temperatureRange = maxTemperature - minTemperature; - var percent = (color.kelvin - minTemperature) / temperatureRange * 100; // clmap percentage + var percent = (color.kelvin - minTemperature) / temperatureRange * 100; // clamp percentage return Math.max(0, Math.min(percent, 100)); @@ -992,8 +1153,8 @@ 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; } + else if (invert && wheelDirection === 'anticlockwise') { angle = wheelAngle + 180 - angle; } // anticlockwise (input handling) + else if (wheelDirection === 'anticlockwise') { angle = wheelAngle - angle; } return mod(angle, 360); } /** @@ -1232,13 +1393,13 @@ var margin = props.margin === null ? props.sliderMargin : props.margin; var rootStyles = { overflow: 'visible', - display: isHorizontal ? 'inline-block' : 'block' + display: isHorizontal ? 'inline-flex' : 'flex' }; // 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))); + return (v(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 @@ -1281,15 +1442,14 @@ }; return IroComponentWrapper; - }(m)); + }(_)); function IroHandle(props) { var radius = props.r; var url = props.url; var cx = radius; var cy = radius; - return (h("svg", { className: ("IroHandle IroHandle--" + (props.index) + " " + (props.isActive ? 'IroHandle--isActive' : '')), style: { - '-webkit-tap-highlight-color': 'rgba(0, 0, 0, 0);', + return (v("svg", { className: ("IroHandle IroHandle--" + (props.index) + " " + (props.isActive ? 'IroHandle--isActive' : '')), style: { transform: ("translate(" + (cssValue(props.x)) + ", " + (cssValue(props.y)) + ")"), willChange: 'transform', top: cssValue(-radius), @@ -1299,9 +1459,9 @@ position: 'absolute', overflow: 'visible' } }, - url && (h("use", Object.assign({ xlinkHref: resolveSvgUrl(url) }, props.props))), - !url && (h("circle", { cx: cx, cy: cy, r: radius, fill: "none", "stroke-width": 2, stroke: "#000" })), - !url && (h("circle", { cx: cx, cy: cy, r: radius - 2, fill: props.fill, "stroke-width": 2, stroke: "#fff" })))); + url && (v("use", Object.assign({ xlinkHref: resolveSvgUrl(url) }, props.props))), + !url && (v("circle", { cx: cx, cy: cy, r: radius, fill: "none", "stroke-width": 2, stroke: "#000" })), + !url && (v("circle", { cx: cx, cy: cy, r: radius - 2, fill: props.fill, "stroke-width": 2, stroke: "#fff" })))); } IroHandle.defaultProps = { fill: 'none', @@ -1312,6 +1472,81 @@ props: { x: 0, y: 0 } }; + var t$1,u$1,r$1,o$1=0,i=[],c$1=l.__b,f$1=l.__r,e$1=l.diffed,a$1=l.__c,v$1=l.unmount;function l$1(t,r){l.__h&&l.__h(u$1,t,o$1||r),o$1=0;var i=u$1.__H||(u$1.__H={__:[],__h:[]});return t>=i.__.length&&i.__.push({}),i.__[t]}function m$1(n){return o$1=1,p(w$1,n)}function p(n,r,o){var i=l$1(t$1++,2);return i.t=n,i.__c||(i.__=[o?o(r):w$1(void 0,r),function(n){var t=i.t(i.__[0],n);i.__[0]!==t&&(i.__=[t,i.__[1]],i.__c.setState({}));}],i.__c=u$1),i.__}function _$1(n,u){var r=l$1(t$1++,7);return k$1(r.__H,u)&&(r.__=n(),r.__H=u,r.__h=n),r.__}function A(n,t){return o$1=8,_$1(function(){return n},t)}function x$1(){for(var t;t=i.shift();){ if(t.__P){ try{t.__H.__h.forEach(g$1),t.__H.__h.forEach(j$1),t.__H.__h=[];}catch(u){t.__H.__h=[],l.__e(u,t.__v);} } }}l.__b=function(n){u$1=null,c$1&&c$1(n);},l.__r=function(n){f$1&&f$1(n),t$1=0;var r=(u$1=n.__c).__H;r&&(r.__h.forEach(g$1),r.__h.forEach(j$1),r.__h=[]);},l.diffed=function(t){e$1&&e$1(t);var o=t.__c;o&&o.__H&&o.__H.__h.length&&(1!==i.push(o)&&r$1===l.requestAnimationFrame||((r$1=l.requestAnimationFrame)||function(n){var t,u=function(){clearTimeout(r),b$1&&cancelAnimationFrame(t),setTimeout(n);},r=setTimeout(u,100);b$1&&(t=requestAnimationFrame(u));})(x$1)),u$1=null;},l.__c=function(t,u){u.some(function(t){try{t.__h.forEach(g$1),t.__h=t.__h.filter(function(n){return !n.__||j$1(n)});}catch(r){u.some(function(n){n.__h&&(n.__h=[]);}),u=[],l.__e(r,t.__v);}}),a$1&&a$1(t,u);},l.unmount=function(t){v$1&&v$1(t);var u,r=t.__c;r&&r.__H&&(r.__H.__.forEach(function(n){try{g$1(n);}catch(n$1){u=n$1;}}),u&&l.__e(u,r.__v));};var b$1="function"==typeof requestAnimationFrame;function g$1(n){var t=u$1,r=n.__c;"function"==typeof r&&(n.__c=void 0,r()),u$1=t;}function j$1(n){var t=u$1;n.__c=n.__(),u$1=t;}function k$1(n,t){return !n||n.length!==t.length||t.some(function(t,u){return t!==n[u]})}function w$1(n,t){return "function"==typeof t?t(n):t} + + function IroInput(props) { + var disabled = props.disabled; + var type = props.sliderType; + var ref = getInputDimensions(props); + var inputWidth = ref.inputWidth; + var fontSize = ref.fontSize; + var activeColor = props.activeColor; + var ref$1 = m$1(activeColor[props.sliderType]); + var sliderValue = ref$1[0]; + var setSliderValue = ref$1[1]; + var val = (type === 'alpha') ? activeColor[props.sliderType].toFixed(2) : Math.round(activeColor[props.sliderType]); + setSliderValue(val); + var onKeypress = A(function (e) { + var value = getSliderValueFromInputField(e); + if (type === 'kelvin') { + var strlen = value.toString().length, minlen = props.minTemperature.toString().length, maxlen = props.maxTemperature.toString().length; + if (strlen > maxlen) { + e.preventDefault(); + activeColor[props.sliderType] = props.maxTemperature; + } + else if (strlen >= minlen) { + if (value < props.minTemperature) { + if (maxlen === minlen) { + e.preventDefault(); + activeColor[props.sliderType] = props.minTemperature; + } + } + else if (value > props.maxTemperature) { + e.preventDefault(); + activeColor[props.sliderType] = props.maxTemperature; + } + else { + e.preventDefault(); + activeColor[props.sliderType] = value; + } + } + } + else { + e.preventDefault(); + activeColor[props.sliderType] = clampSliderValue(props, value); + } + return value; + }, [setSliderValue, props.sliderType]); + var onPaste = A(function (e) { + e.preventDefault(); + var value = getSliderValueFromClipboard(props, e); + activeColor[props.sliderType] = value; + return value; + }, [setSliderValue, props.sliderType]); + return (v("div", { className: "IroSliderValue" }, + v("input", { onKeyPress: onKeypress, onPaste: onPaste, className: "IroSliderInput", style: { + display: 'inline-block', + width: type === 'kelvin' ? cssValue(40) : inputWidth, + height: cssValue(18), + fontSize: fontSize, + padding: cssValue(2) + }, type: "text", disabled: disabled, value: sliderValue }))); + } + IroInput.defaultProps = { + disabled: false + }; + + function IroLabel(props) { + var name = props.sliderType[0].toUpperCase(); + return (v("div", { className: "IroSliderLabel", style: { + display: 'inline-block', + width: cssValue(10), + height: cssValue(12), + lineHeight: cssValue(12), + fontSize: props.layoutDirection === 'horizontal' ? cssValue(12) : cssValue(14) + } }, name)); + } + function IroSlider(props) { var activeIndex = props.activeIndex; var activeColor = (activeIndex !== undefined && activeIndex < props.colors.length) ? props.colors[activeIndex] : props.color; @@ -1325,25 +1560,40 @@ var value = getSliderValueFromInput(props, x, y); props.parent.inputActive = true; activeColor[props.sliderType] = value; + if (props.sliderType === 'kelvin') { + activeColor._kelvin = value; + } props.onInput(type, props.id); } - return (h(IroComponentWrapper, Object.assign({}, props, { onInput: handleInput }), function (uid, rootProps, rootStyles) { return (h("div", Object.assign({}, rootProps, { className: "IroSlider", style: Object.assign({}, {position: 'relative', - width: cssValue(width), - height: cssValue(height), - borderRadius: cssValue(radius), - // checkered bg to represent alpha - background: "conic-gradient(#ccc 25%, #fff 0 50%, #ccc 0 75%, #fff 0)", - backgroundSize: '8px 8px'}, - rootStyles) }), - h("div", { className: "IroSliderGradient", style: Object.assign({}, {position: 'absolute', - top: 0, - left: 0, - width: "100%", - height: "100%", + return (v(IroComponentWrapper, Object.assign({}, props, { onInput: handleInput }), function (uid, rootProps, rootStyles) { return ( + // add wrapper element + v("div", { className: "IroSliderWrapper", style: Object.assign({}, {width: props.layoutDirection === 'vertical' ? cssValue(props.width) : 'unset', + height: props.layoutDirection === 'horizontal' ? cssValue(props.width) : 'unset', + flexDirection: props.layoutDirection === 'horizontal' ? 'column' : 'row', + alignItems: 'center', + justifyContent: 'space-between'}, + rootStyles) }, + v("div", Object.assign({}, rootProps, { className: "IroSlider", style: { + position: 'relative', + display: 'block', + width: cssValue(width), + height: cssValue(height), borderRadius: cssValue(radius), - background: cssGradient('linear', props.layoutDirection === 'horizontal' ? 'to top' : 'to right', gradient)}, - cssBorderStyles(props)) }), - h(IroHandle, { isActive: true, index: activeColor.index, r: props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePos.x, y: handlePos.y }))); })); + // checkered bg to represent alpha + background: "conic-gradient(#ccc 25%, #fff 0 50%, #ccc 0 75%, #fff 0)", + backgroundSize: '8px 8px', + } }), + v("div", { className: "IroSliderGradient", style: Object.assign({}, {position: 'absolute', + top: 0, + left: 0, + width: "100%", + height: "100%", + borderRadius: cssValue(radius), + background: cssGradient('linear', props.layoutDirection === 'horizontal' ? 'to top' : 'to right', gradient)}, + cssBorderStyles(props)) }), + v(IroHandle, { isActive: true, index: activeColor.index, r: props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePos.x, y: handlePos.y })), + props.showLabel && (v(IroLabel, { sliderType: props.sliderType, layoutDirection: props.layoutDirection, handleRadius: props.handleRadius })), + props.showInput && (v(IroInput, { disabled: props.disabled, sliderType: props.sliderType, sliderSize: props.sliderSize, activeColor: activeColor, handleRadius: props.handleRadius, layoutDirection: props.layoutDirection, minTemperature: props.minTemperature, maxTemperature: props.maxTemperature })))); })); } IroSlider.defaultProps = Object.assign({}, sliderDefaultOptions); @@ -1381,19 +1631,19 @@ // let the color picker fire input:start, input:move or input:end events props.onInput(inputType, props.id); } - return (h(IroComponentWrapper, Object.assign({}, props, { onInput: handleInput }), function (uid, rootProps, rootStyles) { return (h("div", Object.assign({}, rootProps, { className: "IroBox", style: Object.assign({}, {width: cssValue(width), + return (v(IroComponentWrapper, Object.assign({}, props, { onInput: handleInput }), function (uid, rootProps, rootStyles) { return (v("div", Object.assign({}, rootProps, { className: "IroBox", style: Object.assign({}, {width: cssValue(width), height: cssValue(height), position: 'relative'}, rootStyles) }), - h("div", { className: "IroBox", style: Object.assign({}, {width: '100%', + v("div", { className: "IroBox", style: Object.assign({}, {width: '100%', height: '100%', borderRadius: cssValue(radius)}, cssBorderStyles(props), {background: cssGradient('linear', 'to bottom', gradients[1]) + ',' + cssGradient('linear', 'to right', gradients[0])}) }), - colors.filter(function (color) { return color !== activeColor; }).map(function (color) { return (h(IroHandle, { isActive: false, index: color.index, fill: color.hslString, r: props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePositions[color.index].x, y: handlePositions[color.index].y })); }), - h(IroHandle, { isActive: true, index: activeColor.index, fill: activeColor.hslString, r: props.activeHandleRadius || props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePositions[activeColor.index].x, y: handlePositions[activeColor.index].y }))); })); + colors.filter(function (color) { return color !== activeColor; }).map(function (color) { return (v(IroHandle, { isActive: false, index: color.index, fill: color.hslString, r: props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePositions[color.index].x, y: handlePositions[color.index].y })); }), + v(IroHandle, { isActive: true, index: activeColor.index, fill: activeColor.hslString, r: props.activeHandleRadius || props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePositions[activeColor.index].x, y: handlePositions[activeColor.index].y }))); })); } var HUE_GRADIENT_CLOCKWISE = 'conic-gradient(red, yellow, lime, aqua, blue, magenta, red)'; @@ -1445,22 +1695,22 @@ // let the color picker fire input:start, input:move or input:end events props.onInput(inputType, props.id); } - return (h(IroComponentWrapper, Object.assign({}, props, { onInput: handleInput }), function (uid, rootProps, rootStyles) { return (h("div", Object.assign({}, rootProps, { className: "IroWheel", style: Object.assign({}, {width: cssValue(width), + return (v(IroComponentWrapper, Object.assign({}, props, { onInput: handleInput }), function (uid, rootProps, rootStyles) { return (v("div", Object.assign({}, rootProps, { className: "IroWheel", style: Object.assign({}, {width: cssValue(width), height: cssValue(width), position: 'relative'}, rootStyles) }), - h("div", { className: "IroWheelHue", style: Object.assign({}, circleStyles, + v("div", { className: "IroWheelHue", style: Object.assign({}, circleStyles, {transform: ("rotateZ(" + (props.wheelAngle + 90) + "deg)"), background: props.wheelDirection === 'clockwise' ? HUE_GRADIENT_CLOCKWISE : HUE_GRADIENT_ANTICLOCKWISE}) }), - h("div", { className: "IroWheelSaturation", style: Object.assign({}, circleStyles, + v("div", { className: "IroWheelSaturation", style: Object.assign({}, circleStyles, {background: 'radial-gradient(circle closest-side, #fff, transparent)'}) }), - props.wheelLightness && (h("div", { className: "IroWheelLightness", style: Object.assign({}, circleStyles, + props.wheelLightness && (v("div", { className: "IroWheelLightness", style: Object.assign({}, circleStyles, {background: '#000', opacity: 1 - hsv.v / 100}) })), - h("div", { className: "IroWheelBorder", style: Object.assign({}, circleStyles, + v("div", { className: "IroWheelBorder", style: Object.assign({}, circleStyles, cssBorderStyles(props)) }), - colors.filter(function (color) { return color !== activeColor; }).map(function (color) { return (h(IroHandle, { isActive: false, index: color.index, fill: color.hslString, r: props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePositions[color.index].x, y: handlePositions[color.index].y })); }), - h(IroHandle, { isActive: true, index: activeColor.index, fill: activeColor.hslString, r: props.activeHandleRadius || props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePositions[activeColor.index].x, y: handlePositions[activeColor.index].y }))); })); + colors.filter(function (color) { return color !== activeColor; }).map(function (color) { return (v(IroHandle, { isActive: false, index: color.index, fill: color.hslString, r: props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePositions[color.index].x, y: handlePositions[color.index].y })); }), + v(IroHandle, { isActive: true, index: activeColor.index, fill: activeColor.hslString, r: props.activeHandleRadius || props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePositions[activeColor.index].x, y: handlePositions[activeColor.index].y }))); })); } function createWidget(WidgetComponent) { @@ -1468,7 +1718,7 @@ var widget; // will become an instance of the widget component class var widgetRoot = document.createElement('div'); // Render widget into a temp DOM node - I(h(WidgetComponent, Object.assign({}, {ref: function (ref) { return widget = ref; }}, + S(v(WidgetComponent, Object.assign({}, {ref: function (ref) { return widget = ref; }}, props)), widgetRoot); function mountWidget() { var container = parent instanceof Element ? parent : document.querySelector(parent); @@ -1745,21 +1995,22 @@ }); } } - return (h("div", { class: "IroColorPicker", id: state.id, style: { - display: state.display + return (v("div", { class: "IroColorPicker", id: state.id, style: { + display: state.display, + flexDirection: props.layoutDirection === 'horizontal' ? 'row' : 'column' } }, layout.map(function (ref, componentIndex) { var UiComponent = ref.component; var options = ref.options; - return (h(UiComponent, Object.assign({}, state, options, { ref: undefined, onInput: this$1.emitInputEvent.bind(this$1), parent: this$1, index: componentIndex }))); + return (v(UiComponent, Object.assign({}, state, options, { ref: undefined, onInput: this$1.emitInputEvent.bind(this$1), parent: this$1, index: componentIndex }))); }))); }; return IroColorPicker; - }(m)); + }(_)); IroColorPicker.defaultProps = Object.assign({}, iroColorPickerOptionDefaults, {colors: [], - display: 'block', + display: 'flex', id: null, layout: 'default', margin: null}); @@ -1772,7 +2023,7 @@ iro.ColorPicker = IroColorPickerWidget; var ui; (function (ui) { - ui.h = h; + ui.h = v; ui.ComponentBase = IroComponentWrapper; ui.Handle = IroHandle; ui.Slider = IroSlider; @@ -1784,4 +2035,4 @@ return iro$1; -})); +}))); diff --git a/dist/iro.min.js b/dist/iro.min.js index 2d20321..2da823f 100644 --- a/dist/iro.min.js +++ b/dist/iro.min.js @@ -4,4 +4,4 @@ * Licensed under MPL 2.0 * github.com/jaames/iro.js */ -!function(t,n){"object"==typeof exports&&"undefined"!=typeof module?module.exports=n():"function"==typeof define&&define.amd?define(n):(t=t||self).iro=n()}(this,function(){"use strict";var m,s,n,i,o,x={},j=[],r=/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|^--/i;function M(t,n){for(var i in n)t[i]=n[i];return t}function y(t){var n=t.parentNode;n&&n.removeChild(t)}function h(t,n,i){var r,e,u,o,l=arguments;if(n=M({},n),3=r/i?u=n:e=n}return n},function(t,n,i){n&&g(t.prototype,n),i&&g(t,i)}(l,[{key:"hsv",get:function(){var t=this.$;return{h:t.h,s:t.s,v:t.v}},set:function(t){var n=this.$;if(t=b({},n,t),this.onChange){var i={h:!1,v:!1,s:!1,a:!1};for(var r in n)i[r]=t[r]!=n[r];this.$=t,(i.h||i.s||i.v||i.a)&&this.onChange(this,i)}else this.$=t}},{key:"hsva",get:function(){return b({},this.$)},set:function(t){this.hsv=t}},{key:"hue",get:function(){return this.$.h},set:function(t){this.hsv={h:t}}},{key:"saturation",get:function(){return this.$.s},set:function(t){this.hsv={s:t}}},{key:"value",get:function(){return this.$.v},set:function(t){this.hsv={v:t}}},{key:"alpha",get:function(){return this.$.a},set:function(t){this.hsv=b({},this.hsv,{a:t})}},{key:"kelvin",get:function(){return l.rgbToKelvin(this.rgb)},set:function(t){this.rgb=l.kelvinToRgb(t)}},{key:"red",get:function(){return this.rgb.r},set:function(t){this.rgb=b({},this.rgb,{r:t})}},{key:"green",get:function(){return this.rgb.g},set:function(t){this.rgb=b({},this.rgb,{g:t})}},{key:"blue",get:function(){return this.rgb.b},set:function(t){this.rgb=b({},this.rgb,{b:t})}},{key:"rgb",get:function(){var t=l.hsvToRgb(this.$),n=t.r,i=t.g,r=t.b;return{r:G(n),g:G(i),b:G(r)}},set:function(t){this.hsv=b({},l.rgbToHsv(t),{a:void 0===t.a?1:t.a})}},{key:"rgba",get:function(){return b({},this.rgb,{a:this.alpha})},set:function(t){this.rgb=t}},{key:"hsl",get:function(){var t=l.hsvToHsl(this.$),n=t.h,i=t.s,r=t.l;return{h:G(n),s:G(i),l:G(r)}},set:function(t){this.hsv=b({},l.hslToHsv(t),{a:void 0===t.a?1:t.a})}},{key:"hsla",get:function(){return b({},this.hsl,{a:this.alpha})},set:function(t){this.hsl=t}},{key:"rgbString",get:function(){var t=this.rgb;return"rgb("+t.r+", "+t.g+", "+t.b+")"},set:function(t){var n,i,r,e,u=1;if((n=_.exec(t))?(i=K(n[1],255),r=K(n[2],255),e=K(n[3],255)):(n=H.exec(t))&&(i=K(n[1],255),r=K(n[2],255),e=K(n[3],255),u=K(n[4],1)),!n)throw new Error("Invalid rgb string");this.rgb={r:i,g:r,b:e,a:u}}},{key:"rgbaString",get:function(){var t=this.rgba;return"rgba("+t.r+", "+t.g+", "+t.b+", "+t.a+")"},set:function(t){this.rgbString=t}},{key:"hexString",get:function(){var t=this.rgb;return"#"+U(t.r)+U(t.g)+U(t.b)},set:function(t){var n,i,r,e,u=255;if((n=D.exec(t))?(i=17*Q(n[1]),r=17*Q(n[2]),e=17*Q(n[3])):(n=F.exec(t))?(i=17*Q(n[1]),r=17*Q(n[2]),e=17*Q(n[3]),u=17*Q(n[4])):(n=L.exec(t))?(i=Q(n[1]),r=Q(n[2]),e=Q(n[3])):(n=B.exec(t))&&(i=Q(n[1]),r=Q(n[2]),e=Q(n[3]),u=Q(n[4])),!n)throw new Error("Invalid hex string");this.rgb={r:i,g:r,b:e,a:u/255}}},{key:"hex8String",get:function(){var t=this.rgba;return"#"+U(t.r)+U(t.g)+U(t.b)+U(Z(255*t.a))},set:function(t){this.hexString=t}},{key:"hslString",get:function(){var t=this.hsl;return"hsl("+t.h+", "+t.s+"%, "+t.l+"%)"},set:function(t){var n,i,r,e,u=1;if((n=P.exec(t))?(i=K(n[1],360),r=K(n[2],100),e=K(n[3],100)):(n=$.exec(t))&&(i=K(n[1],360),r=K(n[2],100),e=K(n[3],100),u=K(n[4],1)),!n)throw new Error("Invalid hsl string");this.hsl={h:i,s:r,l:e,a:u}}},{key:"hslaString",get:function(){var t=this.hsla;return"hsla("+t.h+", "+t.s+"%, "+t.l+"%, "+t.a+")"},set:function(t){this.hslString=t}}]),l}();function X(t){var n,i=t.width,r=t.sliderSize,e=t.borderWidth,u=t.handleRadius,o=t.padding,l=t.sliderShape,s="horizontal"===t.layoutDirection;return r=null!=(n=r)?n:2*o+2*u,"circle"===l?{handleStart:t.padding+t.handleRadius,handleRange:i-2*o-2*u,width:i,height:i,cx:i/2,cy:i/2,radius:i/2-e/2}:{handleStart:r/2,handleRange:i-r,radius:r/2,x:0,y:0,width:s?r:i,height:s?i:r}}function Y(t,n){var i=X(t),r=i.width,e=i.height,u=i.handleRange,o=i.handleStart,l="horizontal"===t.layoutDirection,s=l?r/2:e/2,c=o+function(t,n){var i=n.hsva,r=n.rgb;switch(t.sliderType){case"red":return r.r/2.55;case"green":return r.g/2.55;case"blue":return r.b/2.55;case"alpha":return 100*i.a;case"kelvin":var e=t.minTemperature,u=t.maxTemperature-e,o=(n.kelvin-e)/u*100;return Math.max(0,Math.min(o,100));case"hue":return i.h/=3.6;case"saturation":return i.s;case"value":default:return i.v}}(t,n)/100*u;return l&&(c=-1*c+u+2*o),{x:l?s:c,y:l?c:s}}var tt,nt=2*Math.PI,it=function(t,n){return(t%n+n)%n},rt=function(t,n){return Math.sqrt(t*t+n*n)};function et(t){return t.width/2-t.padding-t.handleRadius-t.borderWidth}function ut(t){var n=t.width/2;return{width:t.width,radius:n-t.borderWidth,cx:n,cy:n}}function ot(t,n,i){var r=t.wheelAngle,e=t.wheelDirection;return i&&"clockwise"===e?n=r+n:"clockwise"===e?n=360-r+n:i&&"anticlockwise"===e?n=r+180-n:"anticlockwise"===e&&(n=r-n),it(n,360)}function lt(t,n,i){var r=ut(t),e=r.cx,u=r.cy,o=et(t);n=e-n,i=u-i;var l=ot(t,Math.atan2(-i,-n)*(360/nt)),s=Math.min(rt(n,i),o);return{h:Math.round(l),s:Math.round(100/o*s)}}function st(t){var n=t.width,i=t.boxHeight;return{width:n,height:null!=i?i:n,radius:t.padding+t.handleRadius}}function ct(t,n,i){var r=st(t),e=r.width,u=r.height,o=r.radius,l=(n-o)/(e-2*o)*100,s=(i-o)/(u-2*o)*100;return{s:Math.max(0,Math.min(l,100)),v:Math.max(0,Math.min(100-s,100))}}function at(t,n,i,r){for(var e=0;e=t.b/t.r?r=n:e=n;return n},i=o,(t=[{key:"hsv",get:function(){var t=this.$;return{h:t.h,s:t.s,v:t.v}},set:function(t){var n=this.$;if(t=r({},n,t),this.onChange){var i,e={h:!1,v:!1,s:!1,a:!1};for(i in n)e[i]=t[i]!=n[i];this.$=t,(e.h||e.s||e.v||e.a)&&this.onChange(this,e)}else this.$=t}},{key:"hsva",get:function(){return r({},this.$)},set:function(t){this.hsv=t}},{key:"hue",get:function(){return this.$.h},set:function(t){this.hsv={h:t}}},{key:"saturation",get:function(){return this.$.s},set:function(t){this.hsv={s:t}}},{key:"value",get:function(){return this.$.v},set:function(t){this.hsv={v:t}}},{key:"alpha",get:function(){return this.$.a},set:function(t){this.hsv=r({},this.hsv,{a:t})}},{key:"kelvin",get:function(){return u(o.rgbToKelvin(this.raw_rgb))},set:function(t){this.rgb=o.kelvinToRgb(t)}},{key:"red",get:function(){return this.rgb.r},set:function(t){this.rgb=r({},this.rgb,{r:t})}},{key:"green",get:function(){return this.rgb.g},set:function(t){this.rgb=r({},this.rgb,{g:t})}},{key:"blue",get:function(){return this.rgb.b},set:function(t){this.rgb=r({},this.rgb,{b:t})}},{key:"rgb",get:function(){var t=o.hsvToRgb(this.$),n=t.r,i=t.g,t=t.b;return{r:u(n),g:u(i),b:u(t)}},set:function(t){this.hsv=r({},o.rgbToHsv(t),{a:void 0===t.a?this.alpha:t.a})}},{key:"raw_rgb",get:function(){var t=o.hsvToRgb(this.$);return{r:t.r,g:t.g,b:t.b}}},{key:"rgba",get:function(){return r({},this.rgb,{a:this.alpha})},set:function(t){this.rgb=t}},{key:"hsl",get:function(){var t=o.hsvToHsl(this.$),n=t.h,i=t.s,t=t.l;return{h:u(n),s:u(i),l:u(t)}},set:function(t){this.hsv=r({},o.hslToHsv(t),{a:void 0===t.a?this.alpha:t.a})}},{key:"hsla",get:function(){return r({},this.hsl,{a:this.alpha})},set:function(t){this.hsl=t}},{key:"rgbString",get:function(){var t=this.rgb;return"rgb("+t.r+", "+t.g+", "+t.b+")"},set:function(t){var n,i,e,r,o=1;if((n=X.exec(t))?(i=l(n[1],255),e=l(n[2],255),r=l(n[3],255)):(n=Y.exec(t))&&(i=l(n[1],255),e=l(n[2],255),r=l(n[3],255),o=l(n[4],1)),!n)throw new Error("Invalid rgb string");this.rgb={r:i,g:e,b:r,a:o}}},{key:"rgbaString",get:function(){var t=this.rgba;return"rgba("+t.r+", "+t.g+", "+t.b+", "+t.a+")"},set:function(t){this.rgbString=t}},{key:"hexString",get:function(){var t=this.rgb;return"#"+a(t.r)+a(t.g)+a(t.b)},set:function(t){var n,i,e,r,o=255;if((n=it.exec(t))?(i=17*s(n[1]),e=17*s(n[2]),r=17*s(n[3])):(n=et.exec(t))?(i=17*s(n[1]),e=17*s(n[2]),r=17*s(n[3]),o=17*s(n[4])):(n=rt.exec(t))?(i=s(n[1]),e=s(n[2]),r=s(n[3])):(n=ot.exec(t))&&(i=s(n[1]),e=s(n[2]),r=s(n[3]),o=s(n[4])),!n)throw new Error("Invalid hex string");this.rgb={r:i,g:e,b:r,a:o/255}}},{key:"hex8String",get:function(){var t=this.rgba;return"#"+a(t.r)+a(t.g)+a(t.b)+a(ut(255*t.a))},set:function(t){this.hexString=t}},{key:"hslString",get:function(){var t=this.hsl;return"hsl("+t.h+", "+t.s+"%, "+t.l+"%)"},set:function(t){var n,i,e,r,o=1;if((n=tt.exec(t))?(i=l(n[1],360),e=l(n[2],100),r=l(n[3],100)):(n=nt.exec(t))&&(i=l(n[1],360),e=l(n[2],100),r=l(n[3],100),o=l(n[4],1)),!n)throw new Error("Invalid hsl string");this.hsl={h:i,s:e,l:r,a:o}}},{key:"hslaString",get:function(){var t=this.hsla;return"hsla("+t.h+", "+t.s+"%, "+t.l+"%, "+t.a+")"},set:function(t){this.hslString=t}}])&&U(i.prototype,t),n&&U(i,n),Object.defineProperty(i,"prototype",{writable:!1}),o}();function lt(t){var n,i=t.sliderSize,t="vertical"===t.layoutDirection?(n=30,12):(n=i<=30?26:i,i<=30?10:12);return{inputWidth:n,inputHeight:18,fontSize:t}}function st(t,n){function i(t,n,i){return Math.min(Math.max(t,n),i)}switch(t.sliderType){case"hue":return i(n,0,360);case"saturation":case"value":return i(n,0,100);case"red":case"green":case"blue":return i(n,0,255);case"alpha":return i(n,0,1);case"kelvin":return i(n,t.minTemperature,t.maxTemperature)}}function f(t){var n,i,e,r=t.width,o=t.sliderSize,u=t.borderWidth,l=t.handleRadius,s=t.padding,c=t.sliderShape,a="horizontal"===t.layoutDirection;return t.sliderLength?e=t.sliderLength:(e=r-l,t.showInput&&(n=(i=lt(t)).inputWidth,i=i.inputHeight,e=e-(a?i:n)-3),t.showLabel&&(e=e-(a?12:10)-3)),o=null!=o?o:2*s+2*l,"circle"===c?{handleStart:t.padding+t.handleRadius,handleRange:r-2*s-2*l,width:r,height:r,cx:r/2,cy:r/2,radius:r/2-u/2}:{handleStart:o/2,handleRange:e-o,radius:o/2,x:0,y:0,width:a?o:e,height:a?e:o}}function ct(t,n){var i=f(t),e=i.width,r=i.height,o=i.handleRange,i=i.handleStart,u="horizontal"===t.layoutDirection,e=u?e/2:r/2,r=i+function(t,n){var i=n.hsva,e=n.rgb;switch(t.sliderType){case"red":return e.r/2.55;case"green":return e.g/2.55;case"blue":return e.b/2.55;case"alpha":return 100*i.a;case"kelvin":var r=t.minTemperature,o=t.maxTemperature,o=(n.kelvin-r)/(o-r)*100;return Math.max(0,Math.min(o,100));case"hue":return i.h/=3.6;case"saturation":return i.s;default:return i.v}}(t,n)/100*o;return u&&(r=-1*r+o+2*i),{x:u?e:r,y:u?r:e}}function at(t,n){return(t%n+n)%n}var d,ft=2*Math.PI,ht=function(t,n){return Math.sqrt(t*t+n*n)};function dt(t){return t.width/2-t.padding-t.handleRadius-t.borderWidth}function p(t){var n=t.width/2;return{width:t.width,radius:n-t.borderWidth,cx:n,cy:n}}function vt(t,n,i){var e=t.wheelAngle,t=t.wheelDirection;return i&&"clockwise"===t?n=e+n:"clockwise"===t?n=360-e+n:i&&"anticlockwise"===t?n=e+180-n:"anticlockwise"===t&&(n=e-n),at(n,360)}function pt(t,n,i){var e=p(t),r=e.cx,e=e.cy,o=dt(t),r=(n=r-n,i=e-i,vt(t,Math.atan2(-i,-n)*(360/ft))),e=Math.min(ht(n,i),o);return{h:Math.round(r),s:Math.round(100/o*e)}}function g(t){var n=t.width,i=t.boxHeight;return{width:n,height:null!=i?i:n,radius:t.padding+t.handleRadius}}function gt(t,n,i){var t=g(t),e=t.width,r=t.height,t=t.radius,i=(i-t)/(r-2*t)*100;return{s:Math.max(0,Math.min((n-t)/(e-2*t)*100,100)),v:Math.max(0,Math.min(100-i,100))}}function yt(t,n,i,e){for(var r=0;r=n.i.length&&n.i.push({}),n.i[t]}function zt(t){return R=1,n=Ht,t=t,(e=At(kt++,2)).t=n,e.c||(e.i=[i?i(t):Ht(void 0,t),function(t){t=e.t(e.i[0],t);e.i[0]!==t&&(e.i=[t,e.i[1]],e.c.setState({}))}],e.c=z),e.i;var n,i,e}function Rt(t,n){return R=8,i=function(){return t},n=n,o=At(kt++,7),e=o.I,r=n,e&&e.length===r.length&&!r.some(function(t,n){return t!==e[n]})||(o.i=i(),o.I=n,o.f=i),o.i;var i,e,r,o}function Nt(){for(var n;n=Mt.shift();)if(n.m)try{n.I.f.forEach(N),n.I.f.forEach(Tt),n.I.f=[]}catch(t){n.I.f=[],x.o(t,n.d)}}x.e=function(t){z=null,jt&&jt(t)},x.p=function(t){It&&It(t),kt=0;t=(z=t.c).I;t&&(t.f.forEach(N),t.f.forEach(Tt),t.f=[])},x.diffed=function(t){Ot&&Ot(t);t=t.c;t&&t.I&&t.I.f.length&&(1!==Mt.push(t)&&xt===x.requestAnimationFrame||((xt=x.requestAnimationFrame)||function(t){function n(){clearTimeout(e),Et&&cancelAnimationFrame(i),setTimeout(t)}var i,e=setTimeout(n,100);Et&&(i=requestAnimationFrame(n))})(Nt)),z=null},x.c=function(t,i){i.some(function(n){try{n.f.forEach(N),n.f=n.f.filter(function(t){return!t.i||Tt(t)})}catch(t){i.some(function(t){t.f&&(t.f=[])}),i=[],x.o(t,n.d)}}),St&&St(t,i)},x.unmount=function(t){_t&&_t(t);var n,t=t.c;t&&t.I&&(t.I.i.forEach(function(t){try{N(t)}catch(t){n=t}}),n&&x.o(n,t.d))};var Et="function"==typeof requestAnimationFrame;function N(t){var n=z,i=t.c;"function"==typeof i&&(t.c=void 0,i()),z=n}function Tt(t){var n=z;t.c=t.i(),z=n}function Ht(t,n){return"function"==typeof n?n(t):n}function Pt(o){var t=o.disabled,u=o.sliderType,n=lt(o),i=n.inputWidth,n=n.fontSize,l=o.activeColor,e=zt(l[o.sliderType]),r=e[0],e=e[1];return e("alpha"===u?l[o.sliderType].toFixed(2):Math.round(l[o.sliderType])),h("div",{className:"IroSliderValue"},h("input",{onKeyPress:Rt(function(t){r=(n=t).target,i=parseInt(r.value);var n,i,e,r=/^([0-9]|\.)$/i.test(n.key)?(i=r.value.toString(),void 0!==r.selectionStart?i=i.substring(0,r.selectionStart)+n.key.toString()+i.substring(r.selectionEnd):i+=n.key.toString(),+i):(n.preventDefault(),i);return"kelvin"===u?(n=r.toString().length,i=o.minTemperature.toString().length,(e=o.maxTemperature.toString().length)o.maxTemperature?(t.preventDefault(),l[o.sliderType]=o.maxTemperature):(t.preventDefault(),l[o.sliderType]=r))):(t.preventDefault(),l[o.sliderType]=st(o,r)),r},[e,o.sliderType]),onPaste:Rt(function(t){t.preventDefault();n=o,t=(t=t).clipboardData.getData("text");var n=/^[+]?([.]\d+|\d+([.]\d+)?)$/i.test(t)?st(n,+t):0;return l[o.sliderType]=n},[e,o.sliderType]),className:"IroSliderInput",style:{display:"inline-block",width:"kelvin"===u?"40px":i,height:"18px",fontSize:n,padding:"2px"},type:"text",disabled:t,value:r}))}function $t(t){var n=t.sliderType[0].toUpperCase();return h("div",{className:"IroSliderLabel",style:{display:"inline-block",width:"10px",height:"12px",lineHeight:"12px",fontSize:"horizontal"===t.layoutDirection?"12px":"14px"}},n)}function E(e){var t=e.activeIndex,r=void 0!==t&&t3){ for(u=[u],t=3;t2&&(f.children=arguments.length>3?n.call(arguments,2):i),"function"==typeof l&&null!=l.defaultProps){ for(r in l.defaultProps){ void 0===f[r]&&(f[r]=l.defaultProps[r]); } }return y(l,f,t,o,null)}function y(n,i,t,o,r){var f={type:n,props:i,key:t,ref:o,__k:null,__:null,__b:0,__e:null,__d:void 0,__c:null,__h:null,constructor:void 0,__v:null==r?++u:r};return null==r&&null!=l.vnode&&l.vnode(f),f}function d(n){return n.children}function _(n,l){this.props=n,this.context=l;}function k(n,l){if(null==l){ return n.__?k(n.__,n.__.__k.indexOf(n)+1):null; }for(var u;l0?y(_.type,_.props,_.key,null,_.__v):_)){if(_.__=u,_.__b=u.__b+1,null===(p=w[h])||p&&_.key==p.key&&_.type===p.type){ w[h]=void 0; }else { for(v=0;v 255) { r = 255; } + } + /* Calculate g */ + + + if (temperature < 66.0) { + g = temperature - 2; + g = -155.25485562709179 - 0.44596950469579133 * g + 104.49216199393888 * Math.log(g); + if (g < 0) { g = 0; } + if (g > 255) { g = 255; } + } else { + g = temperature - 50.0; + g = 325.4494125711974 + 0.07943456536662342 * g - 28.0852963507957 * Math.log(g); + if (g < 0) { g = 0; } + if (g > 255) { g = 255; } + } + /* Calculate b */ + + + if (temperature >= 66.0) { b = 255; + } else { + if (temperature <= 20.0) { + b = 0; + } else { + b = temperature - 10; + b = -254.76935184120902 + 0.8274096064007395 * b + 115.67994401066147 * Math.log(b); + if (b < 0) { b = 0; } + if (b > 255) { b = 255; } + } } return { - r: clamp(floor(r), 0, 255), - g: clamp(floor(g), 0, 255), - b: clamp(floor(b), 0, 255) + r: r, + b: b, + g: g }; } /** @@ -344,26 +369,23 @@ function () { ; 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 temperature, testRGB; + var epsilon = 0.4; + var minTemperature = 1000; + var maxTemperature = 40000; - var _rgb = IroColor.kelvinToRgb(temp); + while (maxTemperature - minTemperature > epsilon) { + temperature = (maxTemperature + minTemperature) / 2; + testRGB = IroColor.kelvinToRgb(temperature); - if (_rgb.b / _rgb.r >= b / r) { - maxTemp = temp; + if (testRGB.b / testRGB.r >= rgb.b / rgb.r) { + maxTemperature = temperature; } else { - minTemp = temp; + minTemperature = temperature; } } - return temp; + return temperature; }; _createClass(IroColor, [{ @@ -453,7 +475,7 @@ function () { }, { key: "kelvin", get: function get() { - return IroColor.rgbToKelvin(this.rgb); + return round(IroColor.rgbToKelvin(this.raw_rgb)); }, set: function set(value) { this.rgb = IroColor.kelvinToRgb(value); @@ -507,9 +529,23 @@ function () { }, set: function set(value) { this.hsv = _extends({}, IroColor.rgbToHsv(value), { - a: value.a === undefined ? 1 : value.a + a: value.a === undefined ? this.alpha : value.a }); } + }, { + key: "raw_rgb", + get: function get() { + var _IroColor$hsvToRgb2 = IroColor.hsvToRgb(this.$), + r = _IroColor$hsvToRgb2.r, + g = _IroColor$hsvToRgb2.g, + b = _IroColor$hsvToRgb2.b; + + return { + r: r, + g: g, + b: b + }; + } }, { key: "rgba", get: function get() { @@ -536,7 +572,7 @@ function () { }, set: function set(value) { this.hsv = _extends({}, IroColor.hslToHsv(value), { - a: value.a === undefined ? 1 : value.a + a: value.a === undefined ? this.alpha : value.a }); } }, { @@ -695,6 +731,108 @@ function () { return IroColor; }(); +/** + * @desc Get input field dimensions + * @param props - InputOptions + */ +function getInputDimensions(props) { + var sliderSize = props.sliderSize, + layoutDirection = props.layoutDirection; + var inputWidth; + var fontSize; + + if (layoutDirection === 'vertical') { + inputWidth = 30; + fontSize = 12; + } else { + inputWidth = sliderSize <= 30 ? 26 : sliderSize; + fontSize = sliderSize <= 30 ? 10 : 12; + } + + return { + inputWidth: inputWidth, + inputHeight: 18, + fontSize: fontSize + }; +} +/** + * @desc Clamp slider value between min and max values + * @param type - props.sliderType + * @param value - value to clamp + */ + +function clampSliderValue(props, value) { + function clamp(num, min, max) { + return Math.min(Math.max(num, min), max); + } + + switch (props.sliderType) { + case 'hue': + return clamp(value, 0, 360); + + case 'saturation': + case 'value': + return clamp(value, 0, 100); + + case 'red': + case 'green': + case 'blue': + return clamp(value, 0, 255); + + case 'alpha': + return clamp(value, 0, 1); + + case 'kelvin': + var minTemperature = props.minTemperature, + maxTemperature = props.maxTemperature; + return clamp(value, minTemperature, maxTemperature); + } +} +/** + * @desc Get the current slider value from input field input + * @param props - slider props + * @param e - KeyboardEvent + */ + +function getSliderValueFromInputField(e) { + var target = e.target; + var valueNum = parseInt(target.value); // regex for digit or dot (.) + + if (!/^([0-9]|\.)$/i.test(e.key)) { + e.preventDefault(); + return valueNum; + } + + var valueString = target.value.toString(); + + if (target.selectionStart !== undefined) { + // cursor position + valueString = valueString.substring(0, target.selectionStart) + e.key.toString() + valueString.substring(target.selectionEnd); + } else { + valueString = valueString + e.key.toString(); + } + + return +valueString; +} +/** + * @desc Get the current slider value from clipboard data + * @param props - slider props + * @param e - ClipboardEvent + */ + +function getSliderValueFromClipboard(props, e) { + // allow only whole or decimal numbers + var r = /^[+]?([.]\d+|\d+([.]\d+)?)$/i; + var valueString = e.clipboardData.getData('text'); + + if (!r.test(valueString)) { + return 0; + } + + var valueNum = +valueString; + return clampSliderValue(props, valueNum); +} + var sliderDefaultOptions = { sliderShape: 'bar', sliderType: 'value', @@ -715,7 +853,30 @@ function getSliderDimensions(props) { handleRadius = props.handleRadius, padding = props.padding, sliderShape = props.sliderShape; - var ishorizontal = props.layoutDirection === 'horizontal'; // automatically calculate sliderSize if its not defined + var ishorizontal = props.layoutDirection === 'horizontal'; + var length; + + if (props.sliderLength) { + length = props.sliderLength; + } else { + // automatically calculate slider length + length = width - handleRadius; + + if (props.showInput) { + var _getInputDimensions = getInputDimensions(props), + inputWidth = _getInputDimensions.inputWidth, + inputHeight = _getInputDimensions.inputHeight; + + length -= ishorizontal ? inputHeight : inputWidth; + length -= 3; // padding + } + + if (props.showLabel) { + length -= ishorizontal ? 12 : 10; + length -= 3; // padding + } + } // automatically calculate sliderSize if its not defined + sliderSize = (_sliderSize = sliderSize) != null ? _sliderSize : padding * 2 + handleRadius * 2; @@ -732,12 +893,12 @@ function getSliderDimensions(props) { } else { return { handleStart: sliderSize / 2, - handleRange: width - sliderSize, + handleRange: length - sliderSize, radius: sliderSize / 2, x: 0, y: 0, - width: ishorizontal ? sliderSize : width, - height: ishorizontal ? width : sliderSize + width: ishorizontal ? sliderSize : length, + height: ishorizontal ? length : sliderSize }; } } @@ -768,7 +929,7 @@ function getCurrentSliderValue(props, color) { var minTemperature = props.minTemperature, maxTemperature = props.maxTemperature; var temperatureRange = maxTemperature - minTemperature; - var percent = (color.kelvin - minTemperature) / temperatureRange * 100; // clmap percentage + var percent = (color.kelvin - minTemperature) / temperatureRange * 100; // clamp percentage return Math.max(0, Math.min(percent, 100)); @@ -986,8 +1147,8 @@ function translateWheelAngle(props, angle, invert) { 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; } + else if (invert && wheelDirection === 'anticlockwise') { angle = wheelAngle + 180 - angle; } // anticlockwise (input handling) + else if (wheelDirection === 'anticlockwise') { angle = wheelAngle - angle; } return mod(angle, 360); } /** @@ -1226,13 +1387,13 @@ var IroComponentWrapper = /*@__PURE__*/(function (Component) { var margin = props.margin === null ? props.sliderMargin : props.margin; var rootStyles = { overflow: 'visible', - display: isHorizontal ? 'inline-block' : 'block' + display: isHorizontal ? 'inline-flex' : 'flex' }; // 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))); + return (v(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 @@ -1275,15 +1436,14 @@ var IroComponentWrapper = /*@__PURE__*/(function (Component) { }; return IroComponentWrapper; -}(m)); +}(_)); function IroHandle(props) { var radius = props.r; var url = props.url; var cx = radius; var cy = radius; - return (h("svg", { className: ("IroHandle IroHandle--" + (props.index) + " " + (props.isActive ? 'IroHandle--isActive' : '')), style: { - '-webkit-tap-highlight-color': 'rgba(0, 0, 0, 0);', + return (v("svg", { className: ("IroHandle IroHandle--" + (props.index) + " " + (props.isActive ? 'IroHandle--isActive' : '')), style: { transform: ("translate(" + (cssValue(props.x)) + ", " + (cssValue(props.y)) + ")"), willChange: 'transform', top: cssValue(-radius), @@ -1293,9 +1453,9 @@ function IroHandle(props) { position: 'absolute', overflow: 'visible' } }, - url && (h("use", Object.assign({ xlinkHref: resolveSvgUrl(url) }, props.props))), - !url && (h("circle", { cx: cx, cy: cy, r: radius, fill: "none", "stroke-width": 2, stroke: "#000" })), - !url && (h("circle", { cx: cx, cy: cy, r: radius - 2, fill: props.fill, "stroke-width": 2, stroke: "#fff" })))); + url && (v("use", Object.assign({ xlinkHref: resolveSvgUrl(url) }, props.props))), + !url && (v("circle", { cx: cx, cy: cy, r: radius, fill: "none", "stroke-width": 2, stroke: "#000" })), + !url && (v("circle", { cx: cx, cy: cy, r: radius - 2, fill: props.fill, "stroke-width": 2, stroke: "#fff" })))); } IroHandle.defaultProps = { fill: 'none', @@ -1306,6 +1466,81 @@ IroHandle.defaultProps = { props: { x: 0, y: 0 } }; +var t$1,u$1,r$1,o$1=0,i=[],c$1=l.__b,f$1=l.__r,e$1=l.diffed,a$1=l.__c,v$1=l.unmount;function l$1(t,r){l.__h&&l.__h(u$1,t,o$1||r),o$1=0;var i=u$1.__H||(u$1.__H={__:[],__h:[]});return t>=i.__.length&&i.__.push({}),i.__[t]}function m$1(n){return o$1=1,p(w$1,n)}function p(n,r,o){var i=l$1(t$1++,2);return i.t=n,i.__c||(i.__=[o?o(r):w$1(void 0,r),function(n){var t=i.t(i.__[0],n);i.__[0]!==t&&(i.__=[t,i.__[1]],i.__c.setState({}));}],i.__c=u$1),i.__}function _$1(n,u){var r=l$1(t$1++,7);return k$1(r.__H,u)&&(r.__=n(),r.__H=u,r.__h=n),r.__}function A(n,t){return o$1=8,_$1(function(){return n},t)}function x$1(){for(var t;t=i.shift();){ if(t.__P){ try{t.__H.__h.forEach(g$1),t.__H.__h.forEach(j$1),t.__H.__h=[];}catch(u){t.__H.__h=[],l.__e(u,t.__v);} } }}l.__b=function(n){u$1=null,c$1&&c$1(n);},l.__r=function(n){f$1&&f$1(n),t$1=0;var r=(u$1=n.__c).__H;r&&(r.__h.forEach(g$1),r.__h.forEach(j$1),r.__h=[]);},l.diffed=function(t){e$1&&e$1(t);var o=t.__c;o&&o.__H&&o.__H.__h.length&&(1!==i.push(o)&&r$1===l.requestAnimationFrame||((r$1=l.requestAnimationFrame)||function(n){var t,u=function(){clearTimeout(r),b$1&&cancelAnimationFrame(t),setTimeout(n);},r=setTimeout(u,100);b$1&&(t=requestAnimationFrame(u));})(x$1)),u$1=null;},l.__c=function(t,u){u.some(function(t){try{t.__h.forEach(g$1),t.__h=t.__h.filter(function(n){return !n.__||j$1(n)});}catch(r){u.some(function(n){n.__h&&(n.__h=[]);}),u=[],l.__e(r,t.__v);}}),a$1&&a$1(t,u);},l.unmount=function(t){v$1&&v$1(t);var u,r=t.__c;r&&r.__H&&(r.__H.__.forEach(function(n){try{g$1(n);}catch(n$1){u=n$1;}}),u&&l.__e(u,r.__v));};var b$1="function"==typeof requestAnimationFrame;function g$1(n){var t=u$1,r=n.__c;"function"==typeof r&&(n.__c=void 0,r()),u$1=t;}function j$1(n){var t=u$1;n.__c=n.__(),u$1=t;}function k$1(n,t){return !n||n.length!==t.length||t.some(function(t,u){return t!==n[u]})}function w$1(n,t){return "function"==typeof t?t(n):t} + +function IroInput(props) { + var disabled = props.disabled; + var type = props.sliderType; + var ref = getInputDimensions(props); + var inputWidth = ref.inputWidth; + var fontSize = ref.fontSize; + var activeColor = props.activeColor; + var ref$1 = m$1(activeColor[props.sliderType]); + var sliderValue = ref$1[0]; + var setSliderValue = ref$1[1]; + var val = (type === 'alpha') ? activeColor[props.sliderType].toFixed(2) : Math.round(activeColor[props.sliderType]); + setSliderValue(val); + var onKeypress = A(function (e) { + var value = getSliderValueFromInputField(e); + if (type === 'kelvin') { + var strlen = value.toString().length, minlen = props.minTemperature.toString().length, maxlen = props.maxTemperature.toString().length; + if (strlen > maxlen) { + e.preventDefault(); + activeColor[props.sliderType] = props.maxTemperature; + } + else if (strlen >= minlen) { + if (value < props.minTemperature) { + if (maxlen === minlen) { + e.preventDefault(); + activeColor[props.sliderType] = props.minTemperature; + } + } + else if (value > props.maxTemperature) { + e.preventDefault(); + activeColor[props.sliderType] = props.maxTemperature; + } + else { + e.preventDefault(); + activeColor[props.sliderType] = value; + } + } + } + else { + e.preventDefault(); + activeColor[props.sliderType] = clampSliderValue(props, value); + } + return value; + }, [setSliderValue, props.sliderType]); + var onPaste = A(function (e) { + e.preventDefault(); + var value = getSliderValueFromClipboard(props, e); + activeColor[props.sliderType] = value; + return value; + }, [setSliderValue, props.sliderType]); + return (v("div", { className: "IroSliderValue" }, + v("input", { onKeyPress: onKeypress, onPaste: onPaste, className: "IroSliderInput", style: { + display: 'inline-block', + width: type === 'kelvin' ? cssValue(40) : inputWidth, + height: cssValue(18), + fontSize: fontSize, + padding: cssValue(2) + }, type: "text", disabled: disabled, value: sliderValue }))); +} +IroInput.defaultProps = { + disabled: false +}; + +function IroLabel(props) { + var name = props.sliderType[0].toUpperCase(); + return (v("div", { className: "IroSliderLabel", style: { + display: 'inline-block', + width: cssValue(10), + height: cssValue(12), + lineHeight: cssValue(12), + fontSize: props.layoutDirection === 'horizontal' ? cssValue(12) : cssValue(14) + } }, name)); +} + function IroSlider(props) { var activeIndex = props.activeIndex; var activeColor = (activeIndex !== undefined && activeIndex < props.colors.length) ? props.colors[activeIndex] : props.color; @@ -1319,25 +1554,40 @@ function IroSlider(props) { var value = getSliderValueFromInput(props, x, y); props.parent.inputActive = true; activeColor[props.sliderType] = value; + if (props.sliderType === 'kelvin') { + activeColor._kelvin = value; + } props.onInput(type, props.id); } - return (h(IroComponentWrapper, Object.assign({}, props, { onInput: handleInput }), function (uid, rootProps, rootStyles) { return (h("div", Object.assign({}, rootProps, { className: "IroSlider", style: Object.assign({}, {position: 'relative', - width: cssValue(width), - height: cssValue(height), - borderRadius: cssValue(radius), - // checkered bg to represent alpha - background: "conic-gradient(#ccc 25%, #fff 0 50%, #ccc 0 75%, #fff 0)", - backgroundSize: '8px 8px'}, - rootStyles) }), - h("div", { className: "IroSliderGradient", style: Object.assign({}, {position: 'absolute', - top: 0, - left: 0, - width: "100%", - height: "100%", + return (v(IroComponentWrapper, Object.assign({}, props, { onInput: handleInput }), function (uid, rootProps, rootStyles) { return ( + // add wrapper element + v("div", { className: "IroSliderWrapper", style: Object.assign({}, {width: props.layoutDirection === 'vertical' ? cssValue(props.width) : 'unset', + height: props.layoutDirection === 'horizontal' ? cssValue(props.width) : 'unset', + flexDirection: props.layoutDirection === 'horizontal' ? 'column' : 'row', + alignItems: 'center', + justifyContent: 'space-between'}, + rootStyles) }, + v("div", Object.assign({}, rootProps, { className: "IroSlider", style: { + position: 'relative', + display: 'block', + width: cssValue(width), + height: cssValue(height), borderRadius: cssValue(radius), - background: cssGradient('linear', props.layoutDirection === 'horizontal' ? 'to top' : 'to right', gradient)}, - cssBorderStyles(props)) }), - h(IroHandle, { isActive: true, index: activeColor.index, r: props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePos.x, y: handlePos.y }))); })); + // checkered bg to represent alpha + background: "conic-gradient(#ccc 25%, #fff 0 50%, #ccc 0 75%, #fff 0)", + backgroundSize: '8px 8px', + } }), + v("div", { className: "IroSliderGradient", style: Object.assign({}, {position: 'absolute', + top: 0, + left: 0, + width: "100%", + height: "100%", + borderRadius: cssValue(radius), + background: cssGradient('linear', props.layoutDirection === 'horizontal' ? 'to top' : 'to right', gradient)}, + cssBorderStyles(props)) }), + v(IroHandle, { isActive: true, index: activeColor.index, r: props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePos.x, y: handlePos.y })), + props.showLabel && (v(IroLabel, { sliderType: props.sliderType, layoutDirection: props.layoutDirection, handleRadius: props.handleRadius })), + props.showInput && (v(IroInput, { disabled: props.disabled, sliderType: props.sliderType, sliderSize: props.sliderSize, activeColor: activeColor, handleRadius: props.handleRadius, layoutDirection: props.layoutDirection, minTemperature: props.minTemperature, maxTemperature: props.maxTemperature })))); })); } IroSlider.defaultProps = Object.assign({}, sliderDefaultOptions); @@ -1375,19 +1625,19 @@ function IroBox(props) { // let the color picker fire input:start, input:move or input:end events props.onInput(inputType, props.id); } - return (h(IroComponentWrapper, Object.assign({}, props, { onInput: handleInput }), function (uid, rootProps, rootStyles) { return (h("div", Object.assign({}, rootProps, { className: "IroBox", style: Object.assign({}, {width: cssValue(width), + return (v(IroComponentWrapper, Object.assign({}, props, { onInput: handleInput }), function (uid, rootProps, rootStyles) { return (v("div", Object.assign({}, rootProps, { className: "IroBox", style: Object.assign({}, {width: cssValue(width), height: cssValue(height), position: 'relative'}, rootStyles) }), - h("div", { className: "IroBox", style: Object.assign({}, {width: '100%', + v("div", { className: "IroBox", style: Object.assign({}, {width: '100%', height: '100%', borderRadius: cssValue(radius)}, cssBorderStyles(props), {background: cssGradient('linear', 'to bottom', gradients[1]) + ',' + cssGradient('linear', 'to right', gradients[0])}) }), - colors.filter(function (color) { return color !== activeColor; }).map(function (color) { return (h(IroHandle, { isActive: false, index: color.index, fill: color.hslString, r: props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePositions[color.index].x, y: handlePositions[color.index].y })); }), - h(IroHandle, { isActive: true, index: activeColor.index, fill: activeColor.hslString, r: props.activeHandleRadius || props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePositions[activeColor.index].x, y: handlePositions[activeColor.index].y }))); })); + colors.filter(function (color) { return color !== activeColor; }).map(function (color) { return (v(IroHandle, { isActive: false, index: color.index, fill: color.hslString, r: props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePositions[color.index].x, y: handlePositions[color.index].y })); }), + v(IroHandle, { isActive: true, index: activeColor.index, fill: activeColor.hslString, r: props.activeHandleRadius || props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePositions[activeColor.index].x, y: handlePositions[activeColor.index].y }))); })); } var HUE_GRADIENT_CLOCKWISE = 'conic-gradient(red, yellow, lime, aqua, blue, magenta, red)'; @@ -1439,22 +1689,22 @@ function IroWheel(props) { // let the color picker fire input:start, input:move or input:end events props.onInput(inputType, props.id); } - return (h(IroComponentWrapper, Object.assign({}, props, { onInput: handleInput }), function (uid, rootProps, rootStyles) { return (h("div", Object.assign({}, rootProps, { className: "IroWheel", style: Object.assign({}, {width: cssValue(width), + return (v(IroComponentWrapper, Object.assign({}, props, { onInput: handleInput }), function (uid, rootProps, rootStyles) { return (v("div", Object.assign({}, rootProps, { className: "IroWheel", style: Object.assign({}, {width: cssValue(width), height: cssValue(width), position: 'relative'}, rootStyles) }), - h("div", { className: "IroWheelHue", style: Object.assign({}, circleStyles, + v("div", { className: "IroWheelHue", style: Object.assign({}, circleStyles, {transform: ("rotateZ(" + (props.wheelAngle + 90) + "deg)"), background: props.wheelDirection === 'clockwise' ? HUE_GRADIENT_CLOCKWISE : HUE_GRADIENT_ANTICLOCKWISE}) }), - h("div", { className: "IroWheelSaturation", style: Object.assign({}, circleStyles, + v("div", { className: "IroWheelSaturation", style: Object.assign({}, circleStyles, {background: 'radial-gradient(circle closest-side, #fff, transparent)'}) }), - props.wheelLightness && (h("div", { className: "IroWheelLightness", style: Object.assign({}, circleStyles, + props.wheelLightness && (v("div", { className: "IroWheelLightness", style: Object.assign({}, circleStyles, {background: '#000', opacity: 1 - hsv.v / 100}) })), - h("div", { className: "IroWheelBorder", style: Object.assign({}, circleStyles, + v("div", { className: "IroWheelBorder", style: Object.assign({}, circleStyles, cssBorderStyles(props)) }), - colors.filter(function (color) { return color !== activeColor; }).map(function (color) { return (h(IroHandle, { isActive: false, index: color.index, fill: color.hslString, r: props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePositions[color.index].x, y: handlePositions[color.index].y })); }), - h(IroHandle, { isActive: true, index: activeColor.index, fill: activeColor.hslString, r: props.activeHandleRadius || props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePositions[activeColor.index].x, y: handlePositions[activeColor.index].y }))); })); + colors.filter(function (color) { return color !== activeColor; }).map(function (color) { return (v(IroHandle, { isActive: false, index: color.index, fill: color.hslString, r: props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePositions[color.index].x, y: handlePositions[color.index].y })); }), + v(IroHandle, { isActive: true, index: activeColor.index, fill: activeColor.hslString, r: props.activeHandleRadius || props.handleRadius, url: props.handleSvg, props: props.handleProps, x: handlePositions[activeColor.index].x, y: handlePositions[activeColor.index].y }))); })); } function createWidget(WidgetComponent) { @@ -1462,7 +1712,7 @@ function createWidget(WidgetComponent) { var widget; // will become an instance of the widget component class var widgetRoot = document.createElement('div'); // Render widget into a temp DOM node - I(h(WidgetComponent, Object.assign({}, {ref: function (ref) { return widget = ref; }}, + S(v(WidgetComponent, Object.assign({}, {ref: function (ref) { return widget = ref; }}, props)), widgetRoot); function mountWidget() { var container = parent instanceof Element ? parent : document.querySelector(parent); @@ -1739,21 +1989,22 @@ var IroColorPicker = /*@__PURE__*/(function (Component) { }); } } - return (h("div", { class: "IroColorPicker", id: state.id, style: { - display: state.display + return (v("div", { class: "IroColorPicker", id: state.id, style: { + display: state.display, + flexDirection: props.layoutDirection === 'horizontal' ? 'row' : 'column' } }, layout.map(function (ref, componentIndex) { var UiComponent = ref.component; var options = ref.options; - return (h(UiComponent, Object.assign({}, state, options, { ref: undefined, onInput: this$1.emitInputEvent.bind(this$1), parent: this$1, index: componentIndex }))); + return (v(UiComponent, Object.assign({}, state, options, { ref: undefined, onInput: this$1.emitInputEvent.bind(this$1), parent: this$1, index: componentIndex }))); }))); }; return IroColorPicker; -}(m)); +}(_)); IroColorPicker.defaultProps = Object.assign({}, iroColorPickerOptionDefaults, {colors: [], - display: 'block', + display: 'flex', id: null, layout: 'default', margin: null}); @@ -1766,7 +2017,7 @@ var iro; iro.ColorPicker = IroColorPickerWidget; var ui; (function (ui) { - ui.h = h; + ui.h = v; ui.ComponentBase = IroComponentWrapper; ui.Handle = IroHandle; ui.Slider = IroSlider; diff --git a/package.json b/package.json index c40d5b1..0597179 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "main": "dist/iro.js", "types": "dist/index.d.ts", "dependencies": { - "@irojs/iro-core": "^1.2.1", + "@irojs/iro-core": "file:../iro-core", "preact": "^10.0.0" }, "devDependencies": { diff --git a/src/ColorPicker.tsx b/src/ColorPicker.tsx index 0a2279f..11a4e7e 100644 --- a/src/ColorPicker.tsx +++ b/src/ColorPicker.tsx @@ -45,7 +45,7 @@ export class IroColorPicker extends Component { layout.map(({component: UiComponent, options: options }, componentIndex: number) => ( diff --git a/src/ComponentWrapper.tsx b/src/ComponentWrapper.tsx index 83074d4..39f3b09 100644 --- a/src/ComponentWrapper.tsx +++ b/src/ComponentWrapper.tsx @@ -47,7 +47,7 @@ export class IroComponentWrapper extends Component { const rootStyles = { overflow: 'visible', - display: isHorizontal ? 'inline-block' : 'block' + display: isHorizontal ? 'inline-flex' : 'flex' }; // first component shouldn't have any margin diff --git a/src/Input.tsx b/src/Input.tsx new file mode 100644 index 0000000..d7e0a4a --- /dev/null +++ b/src/Input.tsx @@ -0,0 +1,96 @@ +import { h } from 'preact'; +import { cssValue, LayoutDirection } from '@irojs/iro-core'; +import { useCallback, useState } from 'preact/hooks'; +import { + IroColor, + SliderType, + getSliderValueFromInputField, + getSliderValueFromClipboard, + getInputDimensions, + clampSliderValue +} from '@irojs/iro-core'; + +interface IroInputProps { + sliderType: SliderType; + sliderSize: number; + activeColor: IroColor; + layoutDirection: LayoutDirection; + handleRadius: number; + disabled: boolean; + minTemperature: number; + maxTemperature: number; +} + +export function IroInput(props: IroInputProps) { + const disabled = props.disabled; + const type = props.sliderType; + const {inputWidth, fontSize} = getInputDimensions(props); + const activeColor = props.activeColor; + const [sliderValue, setSliderValue] = useState(activeColor[props.sliderType]); + const val = (type === 'alpha') ? activeColor[props.sliderType].toFixed(2) : Math.round(activeColor[props.sliderType]); + setSliderValue(val); + + const onKeypress = useCallback((e: KeyboardEvent) => { + const value = getSliderValueFromInputField(e); + + if (type === 'kelvin') { + let strlen = value.toString().length, + minlen = props.minTemperature.toString().length, + maxlen = props.maxTemperature.toString().length; + + if (strlen > maxlen) { + e.preventDefault(); + activeColor[props.sliderType] = props.maxTemperature; + } else if (strlen >= minlen) { + if (value < props.minTemperature) { + if (maxlen === minlen) { + e.preventDefault(); + activeColor[props.sliderType] = props.minTemperature; + } + } else if (value > props.maxTemperature) { + e.preventDefault(); + activeColor[props.sliderType] = props.maxTemperature; + } else { + e.preventDefault(); + activeColor[props.sliderType] = value; + } + } + } else { + e.preventDefault(); + activeColor[props.sliderType] = clampSliderValue(props, value); + } + return value; + }, [setSliderValue, props.sliderType]); + + const onPaste = useCallback((e: ClipboardEvent) => { + e.preventDefault(); + const value = getSliderValueFromClipboard(props, e); + activeColor[props.sliderType] = value; + return value; + }, [setSliderValue, props.sliderType]); + + return ( +
+ + +
+ ); +} + +IroInput.defaultProps = { + disabled: false +}; \ No newline at end of file diff --git a/src/Label.tsx b/src/Label.tsx new file mode 100644 index 0000000..9551263 --- /dev/null +++ b/src/Label.tsx @@ -0,0 +1,28 @@ +import { h } from 'preact'; +import { cssValue, LayoutDirection } from '@irojs/iro-core'; +import { SliderType } from '@irojs/iro-core'; + +interface IroLabelProps { + sliderType: SliderType; + layoutDirection: LayoutDirection; + handleRadius: number; +} + +export function IroLabel(props: IroLabelProps) { + const name = props.sliderType[0].toUpperCase(); + + return ( +
+ {name} +
+ ); +} diff --git a/src/Slider.tsx b/src/Slider.tsx index 51c510c..98351b3 100644 --- a/src/Slider.tsx +++ b/src/Slider.tsx @@ -1,11 +1,10 @@ import { h } from 'preact'; import { - IroColor, SliderShape, SliderType, sliderDefaultOptions, getSliderDimensions, - getSliderValueFromInput, + getSliderValueFromInput, getSliderHandlePosition, getSliderGradient, cssBorderStyles, @@ -16,12 +15,18 @@ import { import { IroComponentWrapper } from './ComponentWrapper'; import { IroComponentProps, IroInputType } from './ComponentTypes'; import { IroHandle } from './Handle'; +import { IroInput } from './Input'; +import { IroLabel } from './Label'; interface IroSliderProps extends IroComponentProps { sliderType: SliderType; sliderShape: SliderShape; + sliderSize: number; minTemperature: number; maxTemperature: number; + showInput: boolean; // show input fields for manual value input + showLabel: boolean; // show label for slider + disabled: boolean; // enable / disable manual value input }; export function IroSlider(props: IroSliderProps) { @@ -35,52 +40,86 @@ export function IroSlider(props: IroSliderProps) { const value = getSliderValueFromInput(props, x, y); props.parent.inputActive = true; activeColor[props.sliderType] = value; + if (props.sliderType === 'kelvin') { + activeColor._kelvin = value; + } props.onInput(type, props.id); } return ( {(uid, rootProps, rootStyles) => ( + // add wrapper element
- + > +
+ +
+ {props.showLabel && ( + )} + {props.showInput && ( + + )}
)}