@ldrender/gradient-picker
Advanced tools
Comparing version 2.0.2 to 2.0.3
@@ -1,2 +0,2 @@ | ||
class t{static isNamedColor(t){return t.toLowerCase()in this.namedColors}static getNamedColorHex(t){const e=t.toLowerCase();return this.namedColors[e]||null}}t.namedColors={indianred:"#CD5C5C",lightcoral:"#F08080",salmon:"#FA8072",darksalmon:"#E9967A",lightsalmon:"#FFA07A",crimson:"#DC143C",red:"#FF0000",firebrick:"#B22222",darkred:"#8B0000",pink:"#FFC0CB",lightpink:"#FFB6C1",hotpink:"#FF69B4",deeppink:"#FF1493",mediumvioletred:"#C71585",palevioletred:"#DB7093",coral:"#FF7F50",tomato:"#FF6347",orangered:"#FF4500",darkorange:"#FF8C00",orange:"#FFA500",gold:"#FFD700",yellow:"#FFFF00",lightyellow:"#FFFFE0",lemonchiffon:"#FFFACD",lightgoldenrodyellow:"#FAFAD2",papayawhip:"#FFEFD5",moccasin:"#FFE4B5",peachpuff:"#FFDAB9",palegoldenrod:"#EEE8AA",khaki:"#F0E68C",darkkhaki:"#BDB76B",lavender:"#E6E6FA",thistle:"#D8BFD8",plum:"#DDA0DD",violet:"#EE82EE",orchid:"#DA70D6",fuchsia:"#FF00FF",magenta:"#FF00FF",mediumorchid:"#BA55D3",mediumpurple:"#9370DB",rebeccapurple:"#663399",blueviolet:"#8A2BE2",darkviolet:"#9400D3",darkorchid:"#9932CC",darkmagenta:"#8B008B",purple:"#800080",indigo:"#4B0082",slateblue:"#6A5ACD",darkslateblue:"#483D8B",mediumslateblue:"#7B68EE",greenyellow:"#ADFF2F",chartreuse:"#7FFF00",lawngreen:"#7CFC00",lime:"#00FF00",limegreen:"#32CD32",palegreen:"#98FB98",lightgreen:"#90EE90",mediumspringgreen:"#00FA9A",springgreen:"#00FF7F",mediumseagreen:"#3CB371",seagreen:"#2E8B57",forestgreen:"#228B22",green:"#008000",darkgreen:"#006400",yellowgreen:"#9ACD32",olivedrab:"#6B8E23",olive:"#808000",darkolivegreen:"#556B2F",mediumaquamarine:"#66CDAA",darkseagreen:"#8FBC8B",lightseagreen:"#20B2AA",darkcyan:"#008B8B",teal:"#008080",aqua:"#00FFFF",cyan:"#00FFFF",lightcyan:"#E0FFFF",paleturquoise:"#AFEEEE",aquamarine:"#7FFFD4",turquoise:"#40E0D0",mediumturquoise:"#48D1CC",darkturquoise:"#00CED1",cadetblue:"#5F9EA0",steelblue:"#4682B4",lightsteelblue:"#B0C4DE",powderblue:"#B0E0E6",lightblue:"#ADD8E6",skyblue:"#87CEEB",lightskyblue:"#87CEFA",deepskyblue:"#00BFFF",dodgerblue:"#1E90FF",cornflowerblue:"#6495ED",royalblue:"#4169E1",blue:"#0000FF",mediumblue:"#0000CD",darkblue:"#00008B",navy:"#000080",midnightblue:"#191970",cornsilk:"#FFF8DC",blanchedalmond:"#FFEBCD",bisque:"#FFE4C4",navajowhite:"#FFDEAD",wheat:"#F5DEB3",burlywood:"#DEB887",tan:"#D2B48C",rosybrown:"#BC8F8F",sandybrown:"#F4A460",goldenrod:"#DAA520",darkgoldenrod:"#B8860B",peru:"#CD853F",chocolate:"#D2691E",saddlebrown:"#8B4513",sienna:"#A0522D",brown:"#A52A2A",maroon:"#800000",white:"#FFFFFF",snow:"#FFFAFA",honeydew:"#F0FFF0",mintcream:"#F5FFFA",azure:"#F0FFFF",aliceblue:"#F0F8FF",ghostwhite:"#F8F8FF",whitesmoke:"#F5F5F5",seashell:"#FFF5EE",beige:"#F5F5DC",oldlace:"#FDF5E6",floralwhite:"#FFFAF0",ivory:"#FFFFF0",antiquewhite:"#FAEBD7",linen:"#FAF0E6",lavenderblush:"#FFF0F5",mistyrose:"#FFE4E1",gainsboro:"#DCDCDC",lightgray:"#D3D3D3",silver:"#C0C0C0",darkgray:"#A9A9A9",gray:"#808080",dimgray:"#696969",lightslategray:"#778899",slategray:"#708090",darkslategray:"#2F4F4F",black:"#000000"};class e{static rgbToHex({r:t,g:e,b:i}){const r=t=>{const e=Math.max(0,Math.min(255,t)).toString(16);return 1===e.length?"0"+e:e};return`#${r(t)}${r(e)}${r(i)}`}static parseRGB(t){const e=t.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)$/);return e?{r:parseInt(e[1],10),g:parseInt(e[2],10),b:parseInt(e[3],10),a:e[4]?parseFloat(e[4]):void 0}:null}static parseHSL(t){const e=t.match(/^hsla?\((\d+),\s*(\d+)%,\s*(\d+)%(?:,\s*([\d.]+))?\)$/);return e?{h:parseInt(e[1],10),s:parseInt(e[2],10),l:parseInt(e[3],10),a:e[4]?parseFloat(e[4]):void 0}:null}static hslToRGB({h:t,s:e,l:i}){i/=100;const r=e=>(e+t/30)%12,n=(e/=100)*Math.min(i,1-i),s=t=>i-n*Math.max(-1,Math.min(r(t)-3,Math.min(9-r(t),1)));return{r:Math.round(255*s(0)),g:Math.round(255*s(8)),b:Math.round(255*s(4))}}static normalizeColor(t){if(this.colorCache.has(t))return this.colorCache.get(t);const e=(()=>{if(t.startsWith("#"))return t;const e=this.parseRGB(t);if(e)return this.rgbToHex(e);const i=this.parseHSL(t);if(i){const t=this.hslToRGB(i);return this.rgbToHex(t)}const r=this.ColorTypes.getNamedColorHex(t);return r||t})();return this.colorCache.set(t,e),e}}function i(t,e,i){const r=document.createElement(t);for(const t in e)r.setAttribute(t,e[t]);for(const t in i)r.style.setProperty(t,i[t]);return r}function r(t,e="gradient-picker"){const r=i("div",{class:e});return t.append(r),r}function n(t,e,r="gradient-picker__select"){const n=i("select",{class:r});return e.forEach((t=>{const e=document.createElement("option");e.value=t,e.text=t,n.append(e)})),t.append(n),n}e.colorCache=new Map,e.ColorTypes=t;class s{static validateStops(t){if(t.some((t=>t.offset<0||t.offset>100)))throw new Error("Stop offsets must be between 0 and 100");t.forEach((t=>{if(!s.isValidColor(t.color))throw new Error(`Invalid color format: ${t.color}`)}))}static isValidColor(e){return!!/^#([A-Fa-f0-9]{3}){1,2}$/.test(e)||(!!/^rgba?\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*(?:,\s*[\d.]+\s*)?\)$/.test(e)||(!!/^hsla?\(\s*\d+\s*,\s*\d+%\s*,\s*\d+%\s*(?:,\s*[\d.]+\s*)?\)$/.test(e)||t.isNamedColor(e)))}}class o{static getGradientString(t,e,i,r){s.validateStops(t);const n=[...t].sort(((t,e)=>t.offset-e.offset)).map((t=>{return`${t.color} ${e=t.offset,Math.round(100*e)/100}%`;var e})).join(","),o=this.getDirectionValue(e,i,r);return"radial"===e?`radial-gradient(circle ${o}, ${n})`:`linear-gradient(${o},${n})`}static getDirectionValue(t,e,i){return"select"===i?this.getSelectDirectionValue(t,e):this.getPercentDirectionValue(t,e)}static getSelectDirectionValue(t,e){if("radial"===t){return{bottom:"at center bottom",center:"",left:"at left center",right:"at center right",top:"at center top"}[e]}return`to ${e}`}static getPercentDirectionValue(t,e){return"radial"===t?e>=360?"at center top":e>=270?"at center left":e>=180?"at center bottom":e>=90?"at center right":"at center top":`${e}deg`}static isFloat(t){return t===+t&&t!==(0|t)}static getPercentage(t,e){return(t-e.getBoundingClientRect().x)/parseInt(getComputedStyle(e).width)*100}}class a{constructor(t,e,i,r){this.stops=t,this.sliderEl=e,this.colorHandlersEl=i,this.updateCallback=r}createHandler(t){const e=this.stops.findIndex((e=>e.id===t)),i=this.stops[e],r=Math.ceil(i.offset).toString(),n=this.createHandlerElement(t,r,i.color),s=this.createHandlerButtons(t,r,i.color);this.sliderEl.append(n),this.colorHandlersEl.append(s)}createHandlerElement(t,e,r){return i("div",{class:"gradient-picker__slider-handler","data-index":t.toString()},{"--handler-position":`${e}%`,"--handler-color":r})}createHandlerButtons(t,e,r){const n=i("div",{class:"gradient-picker__colors-variation","data-index":t.toString()},{"--color-order":e}),s=this.createColorInputs(t,r),o=this.createPositionInput(t,e),a=this.createRemoveButton(t);return n.append(s,o,a),n}createColorInputs(t,e){const r=i("div",{class:"gradient-picker__colors-picker"}),n=i("input",{type:"color",class:"gradient-picker__colors-picker-input","data-index-color":t.toString(),value:e},{"--color-value":e}),s=i("input",{type:"text",class:"gradient-picker__colors-picker-input","data-index-color":t.toString(),value:e},{"--color-value":e});return n.addEventListener("input",(e=>this.onColorChange(e,t))),s.addEventListener("input",(e=>this.onColorChange(e,t))),r.append(n,s),r}createPositionInput(t,e){const r=i("div",{class:"gradient-picker__colors-position"}),n=i("input",{type:"number",class:"gradient-picker__colors-position-input","data-index-position":t.toString(),value:e});return n.addEventListener("input",(e=>this.onPositionChange(e,t))),r.append(n),r}createRemoveButton(t){const e=i("div",{class:"gradient-picker__colors-remover"});return e.addEventListener("click",(()=>{if(this.stops.length<=2)throw new Error("Gradient must have at least 2 color stops");const e=this.stops.findIndex((e=>e.id===t));this.stops.splice(e,1),this.sliderEl.querySelector(`[data-index="${t}"]`)?.remove(),this.colorHandlersEl.querySelector(`[data-index="${t}"]`)?.remove(),this.updateCallback()})),e}onColorChange(t,e){const i=t.target.value,r=this.stops.findIndex((t=>t.id===e));this.stops[r].color=i,this.colorHandlersEl.querySelectorAll(`input[data-index-color='${e}']`).forEach((t=>t.value=i)),this.sliderEl.querySelectorAll(`div.gradient-picker__slider-handler[data-index='${e}']`).forEach((t=>t.style.setProperty("--handler-color",i))),this.updateCallback()}onPositionChange(t,e){const i=parseInt(t.target.value),r=this.stops.findIndex((t=>t.id===e)),n=Math.ceil(i);this.stops[r].offset=n,this.sliderEl.querySelectorAll(`div.gradient-picker__slider-handler[data-index='${e}']`).forEach((t=>t.style.setProperty("--handler-position",i+"%"))),this.colorHandlersEl.querySelectorAll(`div.gradient-picker__colors-variation[data-index='${e}']`).forEach((t=>t.style.setProperty("--color-order",n.toString()))),this.colorHandlersEl.querySelectorAll(`input.gradient-picker__colors-position-input[data-index-position='${e}']`).forEach((t=>t.value=n.toString())),this.updateCallback()}}class l{static parseGradientString(t){const e=t.match(/^linear-gradient\((.*)\)$/);if(e)return this.parseLinearGradient(e[1]);const i=t.match(/^radial-gradient\((.*)\)$/);return i?this.parseRadialGradient(i[1]):null}static parseLinearGradient(t){const i=t.split(",").map((t=>t.trim()));let r="right",n=[];return i[0].startsWith("to ")?(r=i[0].replace("to ",""),i.shift()):i[0].endsWith("deg")&&(r=parseInt(i[0]),i.shift()),n=i.map((t=>{const[i,r]=t.split(/\s+/);return{color:e.normalizeColor(i),offset:parseFloat(r)}})),{type:"linear",direction:r,stops:n}}static parseRadialGradient(t){const i=t.split(",").map((t=>t.trim()));let r="center",n=[];if(i[0].includes("at ")){const t=i[0].match(/at\s+((?:center|top|bottom|left|right)(?:\s+(?:center|top|bottom|left|right))?)/i);if(t){r={"center center":"center","center top":"top","center bottom":"bottom","left center":"left","center right":"right",center:"center",top:"top",bottom:"bottom",left:"left",right:"right"}[t[1].toLowerCase()]||"center",i.shift()}}return n=i.map((t=>{const i=t.match(/((?:#[0-9a-f]{3,8}|(?:rgb|hsl)a?\([^)]+\)|[a-z]+))\s*([0-9.]+)?%?/i);if(i){const[,t,r="0"]=i;return{color:e.normalizeColor(t),offset:parseFloat(r)}}return{color:"#000000",offset:0}})),n.length<2&&(n=[{color:"#ffffff",offset:0},{color:"#000000",offset:100}]),{type:"radial",direction:r,stops:n}}}class d{constructor({el:t,stops:e=[],directionType:i="percent",returnType:r="string",direction:n,type:a,preview:l=!1}){this.preview=!1,this.direction="right",this.directionType="select",this.directionInput=null,this.type="linear",this.typeInput=null,this.stops=[],this.isDragging=!1,this.isEventAttached=!1,this.debounceTimeout=null,this.DEBOUNCE_DELAY=16,this.currentPointer=null,this.handlePointerDown=t=>{const e=t.target;e.classList.contains("gradient-picker__slider-handler")&&(this.currentPointer=t.pointerId,e.setPointerCapture(t.pointerId),e.classList.add("active"),this.isDragging=!0)},this.handlePointerMove=t=>{this.isDragging&&this.currentPointer===t.pointerId&&(this.rafId&&cancelAnimationFrame(this.rafId),this.rafId=requestAnimationFrame((()=>{const e=this.sliderEl.querySelector(".gradient-picker__slider-handler.active");if(!(e&&e instanceof HTMLElement))return;const i=o.getPercentage(t.clientX,this.sliderEl);if(i<-1||i>100)return;const r=parseInt(e.getAttribute("data-index")||"0",10);this.updateHandlerPosition(r,i)})))},this.handlePointerUp=t=>{if(this.currentPointer!==t.pointerId)return;this.isDragging=!1,this.currentPointer=null;const e=this.sliderEl.querySelector(".gradient-picker__slider-handler.active");e&&(e.classList.remove("active"),e instanceof HTMLElement&&e.releasePointerCapture(t.pointerId))};const d=document.querySelector(t);if(!d)throw new Error(`Element with selector "${t}" not found`);e.length&&s.validateStops(e),this.defaultElement=d,this.direction=n||"right",this.type=a||"linear",this.returnType=r,this.preview=l,this.initializeElements(),this.initializeHandlerManager(),this.initDirection(i),this.initializeGradient(e),this.setupEventListeners()}initializeElements(){this.containerPicker=r(this.defaultElement,"gradient-picker"),this.inputReturn=this.createInputReturn(),this.preview&&(this.previewEl=r(this.containerPicker,"gradient-picker__preview")),this.optionsEl=r(this.containerPicker,"gradient-picker__options"),this.sliderEl=r(this.containerPicker,"gradient-picker__slider"),this.colorHandlersEl=r(this.containerPicker,"gradient-picker__colors"),this.typeInput=n(this.optionsEl,["linear","radial"],"gradient-picker__select"),this.defaultElement.replaceWith(this.containerPicker)}createInputReturn(){const t=i("input",{type:"hidden",class:"gradient-picker__return",name:"gradientInput",id:this.defaultElement.id,value:""});return this.containerPicker.append(t),t}initializeHandlerManager(){this.handlerManager=new a(this.stops,this.sliderEl,this.colorHandlersEl,(()=>this.updateGradient()))}initDirection(t="select"){this.directionType=t,this.directionInput?.remove(),"select"===t?(this.directionInput=n(this.optionsEl,["top","left","center","bottom","right"],"gradient-picker__select"),this.direction="right"):(this.directionInput=i("input",{class:"gradient-picker__input",type:"number",value:"0",min:"0",max:"360"}),this.optionsEl.append(this.directionInput),this.direction=0),this.directionInput.addEventListener("input",(()=>{this.direction=this.directionInput?.value,this.updateGradient()}))}initializeGradient(t){const e=this.defaultElement.getAttribute("value");if(e)try{const t=JSON.parse(e);if(this.isValidGradient(t))return void this.loadGradientFromObject(t)}catch(t){}this.initDefaultStops(t)}initDefaultStops(t){if(!t.length)return this.addColorStop("#af68fe",9.3),void this.addColorStop("#65dfff",75.1);t.forEach((({color:t,offset:e})=>this.addColorStop(t,e)))}importFromCSSString(t){const e=l.parseGradientString(t);if(!e)throw new Error("Invalid gradient string format");this.loadGradientFromObject(e)}addColorStop(t,i){const r=e.normalizeColor(t),n=this.stops[this.stops.length-1]?.id+1||0;this.stops.push({id:n,color:r,offset:i}),this.handlerManager.createHandler(n),this.updateGradient()}isValidGradient(t){return t&&"object"==typeof t&&"type"in t&&"direction"in t&&"stops"in t}loadGradientFromObject(t){this.type=t.type,this.direction=t.direction,this.stops=[],t.stops.forEach((({color:t,offset:e})=>{const i=!o.isFloat(e)||e>1?e:100*e;this.addColorStop(t,i)})),this.updateGradient()}setupEventListeners(){this.isEventAttached||(this.isEventAttached=!0,this.setupSliderListeners(),this.setupInputListeners())}setupSliderListeners(){this.sliderEl.addEventListener("pointerdown",this.handlePointerDown),this.sliderEl.addEventListener("pointermove",this.handlePointerMove),this.sliderEl.addEventListener("pointerup",this.handlePointerUp),this.sliderEl.addEventListener("pointercancel",this.handlePointerUp),this.sliderEl.style.touchAction="none"}updateHandlerPosition(t,e){const i=this.stops.findIndex((e=>e.id===t));if(-1===i)return;const r=Math.ceil(e);this.stops[i].offset=r;const n=new Map;n.set(`.gradient-picker__slider-handler[data-index='${t}']`,{"--handler-position":`${r}%`}),n.set(`input[data-index-position='${t}']`,{value:r.toString()}),this.batchDOMUpdates(n),this.updateGradient()}batchDOMUpdates(t){requestAnimationFrame((()=>{t.forEach(((t,e)=>{this.containerPicker.querySelectorAll(e).forEach((e=>{Object.entries(t).forEach((([t,i])=>{"value"===t&&e instanceof HTMLInputElement?e.value=i:e instanceof HTMLElement&&e.style.setProperty(t,i)}))}))}))}))}setupInputListeners(){this.typeInput?.addEventListener("input",(()=>{this.type=this.typeInput?.value,this.updateGradient()}))}getGradient(){const t=[...this.stops].sort(((t,e)=>t.offset-e.offset)).map((({color:t,offset:e})=>({color:t,offset:e})));return{type:this.type,direction:this.direction,stops:t}}getStops(){return[...this.stops].sort(((t,e)=>t.offset-e.offset)).map((({color:t,offset:e})=>({color:t,offset:e})))}updateGradient(){this.debounceTimeout&&clearTimeout(this.debounceTimeout),this.debounceTimeout=window.setTimeout((()=>{const t=o.getGradientString(this.stops,"linear","right","select");if(this.sliderEl.style.backgroundImage=t,this.preview&&this.previewEl){const t=o.getGradientString(this.stops,this.type,this.direction,this.directionType);this.previewEl.style.backgroundImage=t}this.updateReturnValue()}),this.DEBOUNCE_DELAY)}updateReturnValue(){let t="";switch(this.returnType){case"string":t=o.getGradientString(this.stops,this.type,this.direction,this.directionType);break;case"object":t=JSON.stringify(this.getGradient());break;case"stops-list":t=JSON.stringify(this.getStops())}this.inputReturn.value=t,this.inputReturn.dispatchEvent(new Event("change"))}}export{d as GradientPicker}; | ||
class t{static isNamedColor(t){return t.toLowerCase()in this.namedColors}static getNamedColorHex(t){const e=t.toLowerCase();return this.namedColors[e]||null}}t.namedColors={indianred:"#CD5C5C",lightcoral:"#F08080",salmon:"#FA8072",darksalmon:"#E9967A",lightsalmon:"#FFA07A",crimson:"#DC143C",red:"#FF0000",firebrick:"#B22222",darkred:"#8B0000",pink:"#FFC0CB",lightpink:"#FFB6C1",hotpink:"#FF69B4",deeppink:"#FF1493",mediumvioletred:"#C71585",palevioletred:"#DB7093",coral:"#FF7F50",tomato:"#FF6347",orangered:"#FF4500",darkorange:"#FF8C00",orange:"#FFA500",gold:"#FFD700",yellow:"#FFFF00",lightyellow:"#FFFFE0",lemonchiffon:"#FFFACD",lightgoldenrodyellow:"#FAFAD2",papayawhip:"#FFEFD5",moccasin:"#FFE4B5",peachpuff:"#FFDAB9",palegoldenrod:"#EEE8AA",khaki:"#F0E68C",darkkhaki:"#BDB76B",lavender:"#E6E6FA",thistle:"#D8BFD8",plum:"#DDA0DD",violet:"#EE82EE",orchid:"#DA70D6",fuchsia:"#FF00FF",magenta:"#FF00FF",mediumorchid:"#BA55D3",mediumpurple:"#9370DB",rebeccapurple:"#663399",blueviolet:"#8A2BE2",darkviolet:"#9400D3",darkorchid:"#9932CC",darkmagenta:"#8B008B",purple:"#800080",indigo:"#4B0082",slateblue:"#6A5ACD",darkslateblue:"#483D8B",mediumslateblue:"#7B68EE",greenyellow:"#ADFF2F",chartreuse:"#7FFF00",lawngreen:"#7CFC00",lime:"#00FF00",limegreen:"#32CD32",palegreen:"#98FB98",lightgreen:"#90EE90",mediumspringgreen:"#00FA9A",springgreen:"#00FF7F",mediumseagreen:"#3CB371",seagreen:"#2E8B57",forestgreen:"#228B22",green:"#008000",darkgreen:"#006400",yellowgreen:"#9ACD32",olivedrab:"#6B8E23",olive:"#808000",darkolivegreen:"#556B2F",mediumaquamarine:"#66CDAA",darkseagreen:"#8FBC8B",lightseagreen:"#20B2AA",darkcyan:"#008B8B",teal:"#008080",aqua:"#00FFFF",cyan:"#00FFFF",lightcyan:"#E0FFFF",paleturquoise:"#AFEEEE",aquamarine:"#7FFFD4",turquoise:"#40E0D0",mediumturquoise:"#48D1CC",darkturquoise:"#00CED1",cadetblue:"#5F9EA0",steelblue:"#4682B4",lightsteelblue:"#B0C4DE",powderblue:"#B0E0E6",lightblue:"#ADD8E6",skyblue:"#87CEEB",lightskyblue:"#87CEFA",deepskyblue:"#00BFFF",dodgerblue:"#1E90FF",cornflowerblue:"#6495ED",royalblue:"#4169E1",blue:"#0000FF",mediumblue:"#0000CD",darkblue:"#00008B",navy:"#000080",midnightblue:"#191970",cornsilk:"#FFF8DC",blanchedalmond:"#FFEBCD",bisque:"#FFE4C4",navajowhite:"#FFDEAD",wheat:"#F5DEB3",burlywood:"#DEB887",tan:"#D2B48C",rosybrown:"#BC8F8F",sandybrown:"#F4A460",goldenrod:"#DAA520",darkgoldenrod:"#B8860B",peru:"#CD853F",chocolate:"#D2691E",saddlebrown:"#8B4513",sienna:"#A0522D",brown:"#A52A2A",maroon:"#800000",white:"#FFFFFF",snow:"#FFFAFA",honeydew:"#F0FFF0",mintcream:"#F5FFFA",azure:"#F0FFFF",aliceblue:"#F0F8FF",ghostwhite:"#F8F8FF",whitesmoke:"#F5F5F5",seashell:"#FFF5EE",beige:"#F5F5DC",oldlace:"#FDF5E6",floralwhite:"#FFFAF0",ivory:"#FFFFF0",antiquewhite:"#FAEBD7",linen:"#FAF0E6",lavenderblush:"#FFF0F5",mistyrose:"#FFE4E1",gainsboro:"#DCDCDC",lightgray:"#D3D3D3",silver:"#C0C0C0",darkgray:"#A9A9A9",gray:"#808080",dimgray:"#696969",lightslategray:"#778899",slategray:"#708090",darkslategray:"#2F4F4F",black:"#000000"};class e{static rgbToHex({r:t,g:e,b:i}){const r=t=>{const e=Math.max(0,Math.min(255,t)).toString(16);return 1===e.length?"0"+e:e};return`#${r(t)}${r(e)}${r(i)}`}static parseRGB(t){const e=t.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)$/);return e?{r:parseInt(e[1],10),g:parseInt(e[2],10),b:parseInt(e[3],10),a:e[4]?parseFloat(e[4]):void 0}:null}static parseHSL(t){const e=t.match(/^hsla?\((\d+),\s*(\d+)%,\s*(\d+)%(?:,\s*([\d.]+))?\)$/);return e?{h:parseInt(e[1],10),s:parseInt(e[2],10),l:parseInt(e[3],10),a:e[4]?parseFloat(e[4]):void 0}:null}static hslToRGB({h:t,s:e,l:i}){i/=100;const r=e=>(e+t/30)%12,n=(e/=100)*Math.min(i,1-i),s=t=>i-n*Math.max(-1,Math.min(r(t)-3,Math.min(9-r(t),1)));return{r:Math.round(255*s(0)),g:Math.round(255*s(8)),b:Math.round(255*s(4))}}static normalizeColor(t){if(this.colorCache.has(t))return this.colorCache.get(t);const e=(()=>{if(t.startsWith("#"))return t;const e=this.parseRGB(t);if(e)return this.rgbToHex(e);const i=this.parseHSL(t);if(i){const t=this.hslToRGB(i);return this.rgbToHex(t)}const r=this.ColorTypes.getNamedColorHex(t);return r||t})();return this.colorCache.set(t,e),e}}function i(t,e,i){const r=document.createElement(t);for(const t in e)r.setAttribute(t,e[t]);for(const t in i)r.style.setProperty(t,i[t]);return r}function r(t,e="gradient-picker"){const r=i("div",{class:e});return t.append(r),r}function n(t,e,r="gradient-picker__select"){const n=i("select",{class:r});return e.forEach((t=>{const e=document.createElement("option");e.value=t,e.text=t,n.append(e)})),t.append(n),n}e.colorCache=new Map,e.ColorTypes=t;class s{static validateStops(t){if(t.some((t=>t.offset<0||t.offset>100)))throw new Error("Stop offsets must be between 0 and 100");t.forEach((t=>{if(!s.isValidColor(t.color))throw new Error(`Invalid color format: ${t.color}`)}))}static isValidColor(e){return!!/^#([A-Fa-f0-9]{3}){1,2}$/.test(e)||(!!/^rgba?\(\s*\d+\s*,\s*\d+\s*,\s*\d+\s*(?:,\s*[\d.]+\s*)?\)$/.test(e)||(!!/^hsla?\(\s*\d+\s*,\s*\d+%\s*,\s*\d+%\s*(?:,\s*[\d.]+\s*)?\)$/.test(e)||t.isNamedColor(e)))}}class o{static getGradientString(t,e,i,r){s.validateStops(t);const n=[...t].sort(((t,e)=>t.offset-e.offset)).map((t=>{return`${t.color} ${e=t.offset,Math.round(100*e)/100}%`;var e})).join(","),o=this.getDirectionValue(e,i,r);return"radial"===e?`radial-gradient(circle ${o}, ${n})`:`linear-gradient(${o},${n})`}static getDirectionValue(t,e,i){return"select"===i?this.getSelectDirectionValue(t,e):this.getPercentDirectionValue(t,e)}static getSelectDirectionValue(t,e){if("radial"===t){return{bottom:"at center bottom",center:"at center",left:"at left center",right:"at center right",top:"at center top"}[e]}return`to ${e}`}static getPercentDirectionValue(t,e){return"radial"===t?e>=360?"at center top":e>=270?"at center left":e>=180?"at center bottom":e>=90?"at center right":"at center top":`${e}deg`}static isFloat(t){return t===+t&&t!==(0|t)}static getPercentage(t,e){return(t-e.getBoundingClientRect().x)/parseInt(getComputedStyle(e).width)*100}}class a{constructor(t,e,i,r){this.stops=t,this.sliderEl=e,this.colorHandlersEl=i,this.updateCallback=r}createHandler(t){const e=this.stops.findIndex((e=>e.id===t)),i=this.stops[e],r=Math.ceil(i.offset).toString(),n=this.createHandlerElement(t,r,i.color),s=this.createHandlerButtons(t,r,i.color);this.sliderEl.append(n),this.colorHandlersEl.append(s)}createHandlerElement(t,e,r){return i("div",{class:"gradient-picker__slider-handler","data-index":t.toString()},{"--handler-position":`${e}%`,"--handler-color":r})}createHandlerButtons(t,e,r){const n=i("div",{class:"gradient-picker__colors-variation","data-index":t.toString()},{"--color-order":e}),s=this.createColorInputs(t,r),o=this.createPositionInput(t,e),a=this.createRemoveButton(t);return n.append(s,o,a),n}createColorInputs(t,e){const r=i("div",{class:"gradient-picker__colors-picker"}),n=i("input",{type:"color",class:"gradient-picker__colors-picker-input","data-index-color":t.toString(),value:e},{"--color-value":e}),s=i("input",{type:"text",class:"gradient-picker__colors-picker-input","data-index-color":t.toString(),value:e},{"--color-value":e});return n.addEventListener("input",(e=>this.onColorChange(e,t))),s.addEventListener("input",(e=>this.onColorChange(e,t))),r.append(n,s),r}createPositionInput(t,e){const r=i("div",{class:"gradient-picker__colors-position"}),n=i("input",{type:"number",class:"gradient-picker__colors-position-input","data-index-position":t.toString(),value:e});return n.addEventListener("input",(e=>this.onPositionChange(e,t))),r.append(n),r}createRemoveButton(t){const e=i("div",{class:"gradient-picker__colors-remover"});return e.addEventListener("click",(()=>{if(this.stops.length<=2)throw new Error("Gradient must have at least 2 color stops");const e=this.stops.findIndex((e=>e.id===t));this.stops.splice(e,1),this.sliderEl.querySelector(`[data-index="${t}"]`)?.remove(),this.colorHandlersEl.querySelector(`[data-index="${t}"]`)?.remove(),this.updateCallback()})),e}onColorChange(t,e){const i=t.target.value,r=this.stops.findIndex((t=>t.id===e));this.stops[r].color=i,this.colorHandlersEl.querySelectorAll(`input[data-index-color='${e}']`).forEach((t=>t.value=i)),this.sliderEl.querySelectorAll(`div.gradient-picker__slider-handler[data-index='${e}']`).forEach((t=>t.style.setProperty("--handler-color",i))),this.updateCallback()}onPositionChange(t,e){const i=parseInt(t.target.value),r=this.stops.findIndex((t=>t.id===e)),n=Math.ceil(i);this.stops[r].offset=n,this.sliderEl.querySelectorAll(`div.gradient-picker__slider-handler[data-index='${e}']`).forEach((t=>t.style.setProperty("--handler-position",i+"%"))),this.colorHandlersEl.querySelectorAll(`div.gradient-picker__colors-variation[data-index='${e}']`).forEach((t=>t.style.setProperty("--color-order",n.toString()))),this.colorHandlersEl.querySelectorAll(`input.gradient-picker__colors-position-input[data-index-position='${e}']`).forEach((t=>t.value=n.toString())),this.updateCallback()}}class l{static parseGradientString(t){const e=t.match(/^linear-gradient\((.*)\)$/);if(e)return this.parseLinearGradient(e[1]);const i=t.match(/^radial-gradient\((.*)\)$/);return i?this.parseRadialGradient(i[1]):null}static parseLinearGradient(t){const i=t.split(",").map((t=>t.trim()));let r="right",n=[];return i[0].startsWith("to ")?(r=i[0].replace("to ",""),i.shift()):i[0].endsWith("deg")&&(r=parseInt(i[0]),i.shift()),n=i.map((t=>{const[i,r]=t.split(/\s+/);return{color:e.normalizeColor(i),offset:parseFloat(r)}})),{type:"linear",direction:r,stops:n}}static parseRadialGradient(t){const i=t.split(",").map((t=>t.trim()));let r="center",n=[];if(i[0].includes("at ")){const t=i[0].match(/at\s+((?:center|top|bottom|left|right)(?:\s+(?:center|top|bottom|left|right))?)/i);if(t){r={"center center":"center","center top":"top","center bottom":"bottom","left center":"left","center right":"right",center:"center",top:"top",bottom:"bottom",left:"left",right:"right"}[t[1].toLowerCase()]||"center",i.shift()}}return n=i.map((t=>{const i=t.match(/((?:#[0-9a-f]{3,8}|(?:rgb|hsl)a?\([^)]+\)|[a-z]+))\s*([0-9.]+)?%?/i);if(i){const[,t,r="0"]=i;return{color:e.normalizeColor(t),offset:parseFloat(r)}}return{color:"#000000",offset:0}})),n.length<2&&(n=[{color:"#ffffff",offset:0},{color:"#000000",offset:100}]),{type:"radial",direction:r,stops:n}}}class d{constructor({el:t,stops:e=[],direction:i,directionType:r="percent",directionRadial:n=!0,returnType:a="string",type:l,preview:d=!1}){this.preview=!1,this.direction="right",this.directionType="select",this.directionTypeDefault="select",this.directionInput=null,this.directionRadial=!0,this.type="linear",this.typeInput=null,this.stops=[],this.isDragging=!1,this.isEventAttached=!1,this.debounceTimeout=null,this.DEBOUNCE_DELAY=16,this.currentPointer=null,this.handlePointerDown=t=>{const e=t.target;e.classList.contains("gradient-picker__slider-handler")&&(this.currentPointer=t.pointerId,e.setPointerCapture(t.pointerId),e.classList.add("active"),this.isDragging=!0)},this.handlePointerMove=t=>{this.isDragging&&this.currentPointer===t.pointerId&&(this.rafId&&cancelAnimationFrame(this.rafId),this.rafId=requestAnimationFrame((()=>{const e=this.sliderEl.querySelector(".gradient-picker__slider-handler.active");if(!(e&&e instanceof HTMLElement))return;const i=o.getPercentage(t.clientX,this.sliderEl);if(i<-1||i>100)return;const r=parseInt(e.getAttribute("data-index")||"0",10);this.updateHandlerPosition(r,i)})))},this.handlePointerUp=t=>{if(this.currentPointer!==t.pointerId)return;this.isDragging=!1,this.currentPointer=null;const e=this.sliderEl.querySelector(".gradient-picker__slider-handler.active");e&&(e.classList.remove("active"),e instanceof HTMLElement&&e.releasePointerCapture(t.pointerId))};const c=document.querySelector(t);if(!c)throw new Error(`Element with selector "${t}" not found`);e.length&&s.validateStops(e),this.defaultElement=c,this.direction=i||"right",this.type=l||"linear",this.returnType=a,this.preview=d,this.directionRadial=n,this.initializeElements(),this.initializeHandlerManager(),this.initDirection(r),this.initializeGradient(e),this.setupEventListeners()}initializeElements(){this.containerPicker=r(this.defaultElement,"gradient-picker"),this.inputReturn=this.createInputReturn(),this.preview&&(this.previewEl=r(this.containerPicker,"gradient-picker__preview")),this.optionsEl=r(this.containerPicker,"gradient-picker__options"),this.sliderEl=r(this.containerPicker,"gradient-picker__slider"),this.colorHandlersEl=r(this.containerPicker,"gradient-picker__colors"),this.typeInput=n(this.optionsEl,["linear","radial"],"gradient-picker__select"),this.defaultElement.replaceWith(this.containerPicker)}createInputReturn(){const t=i("input",{type:"hidden",class:"gradient-picker__return",name:"gradientInput",id:this.defaultElement.id,value:""});return this.containerPicker.append(t),t}initializeHandlerManager(){this.handlerManager=new a(this.stops,this.sliderEl,this.colorHandlersEl,(()=>this.updateGradient()))}initDirection(t="select"){this.directionType=t,this.directionTypeDefault=t,this.directionInput?.remove(),"select"===t?(this.directionInput=n(this.optionsEl,["top","left","center","bottom","right"],"gradient-picker__select"),this.direction="right"):(this.directionInput=i("input",{class:"gradient-picker__input",type:"number",value:"0",min:"0",max:"360"}),this.optionsEl.append(this.directionInput),this.direction=0),this.directionInput.addEventListener("input",(()=>{this.direction=this.directionInput?.value,this.updateGradient()}))}initializeGradient(t){const e=this.defaultElement.getAttribute("value");if(e)try{const t=JSON.parse(e);if(this.isValidGradient(t))return void this.loadGradientFromObject(t)}catch(t){}this.initDefaultStops(t)}initDefaultStops(t){if(!t.length)return this.addColorStop("#af68fe",9.3),void this.addColorStop("#65dfff",75.1);t.forEach((({color:t,offset:e})=>this.addColorStop(t,e)))}importFromCSSString(t){const e=l.parseGradientString(t);if(!e)throw new Error("Invalid gradient string format");this.loadGradientFromObject(e)}addColorStop(t,i){const r=e.normalizeColor(t),n=this.stops[this.stops.length-1]?.id+1||0;this.stops.push({id:n,color:r,offset:i}),this.handlerManager.createHandler(n),this.updateGradient()}isValidGradient(t){return t&&"object"==typeof t&&"type"in t&&"direction"in t&&"stops"in t}loadGradientFromObject(t){this.type=t.type,this.direction=t.direction,this.stops=[],t.stops.forEach((({color:t,offset:e})=>{const i=!o.isFloat(e)||e>1?e:100*e;this.addColorStop(t,i)})),this.updateGradient()}setupEventListeners(){this.isEventAttached||(this.isEventAttached=!0,this.setupSliderListeners(),this.setupInputListeners())}setupSliderListeners(){this.sliderEl.addEventListener("pointerdown",this.handlePointerDown),this.sliderEl.addEventListener("pointermove",this.handlePointerMove),this.sliderEl.addEventListener("pointerup",this.handlePointerUp),this.sliderEl.addEventListener("pointercancel",this.handlePointerUp),this.sliderEl.style.touchAction="none"}updateHandlerPosition(t,e){const i=this.stops.findIndex((e=>e.id===t));if(-1===i)return;const r=Math.ceil(e);this.stops[i].offset=r;const n=new Map;n.set(`.gradient-picker__slider-handler[data-index='${t}']`,{"--handler-position":`${r}%`}),n.set(`input[data-index-position='${t}']`,{value:r.toString()}),this.batchDOMUpdates(n),this.updateGradient()}batchDOMUpdates(t){requestAnimationFrame((()=>{t.forEach(((t,e)=>{this.containerPicker.querySelectorAll(e).forEach((e=>{Object.entries(t).forEach((([t,i])=>{"value"===t&&e instanceof HTMLInputElement?e.value=i:e instanceof HTMLElement&&e.style.setProperty(t,i)}))}))}))}))}setupInputListeners(){this.typeInput?.addEventListener("input",(()=>{this.type=this.typeInput?.value,this.directionInput&&!this.directionRadial&&("radial"===this.type?(this.directionInput.style.display="none",this.directionType="select",this.direction="center"):(this.directionInput.style.display="",this.directionType=this.directionTypeDefault,this.direction=this.directionInput.value)),this.updateGradient()}))}getGradient(){const t=[...this.stops].sort(((t,e)=>t.offset-e.offset)).map((({color:t,offset:e})=>({color:t,offset:e})));return{type:this.type,direction:this.direction,stops:t}}getStops(){return[...this.stops].sort(((t,e)=>t.offset-e.offset)).map((({color:t,offset:e})=>({color:t,offset:e})))}updateGradient(){this.debounceTimeout&&clearTimeout(this.debounceTimeout),this.debounceTimeout=window.setTimeout((()=>{const t=o.getGradientString(this.stops,"linear","right","select");if(this.sliderEl.style.backgroundImage=t,this.preview&&this.previewEl){const t=o.getGradientString(this.stops,this.type,this.direction,this.directionType);this.previewEl.style.backgroundImage=t}this.updateReturnValue()}),this.DEBOUNCE_DELAY)}updateReturnValue(){let t="";switch(this.returnType){case"string":t=o.getGradientString(this.stops,this.type,this.direction,this.directionType);break;case"object":t=JSON.stringify(this.getGradient());break;case"stops-list":t=JSON.stringify(this.getStops())}this.inputReturn.value=t,this.inputReturn.dispatchEvent(new Event("change"))}}export{d as GradientPicker}; | ||
//# sourceMappingURL=gradient-picker.js.map |
@@ -15,3 +15,5 @@ import { GradientDirectionType, GradientPickerProps, GradientStop, GradientObject } from './types/gradient'; | ||
private directionType; | ||
private directionTypeDefault; | ||
private directionInput; | ||
private directionRadial; | ||
private type; | ||
@@ -26,3 +28,3 @@ private typeInput; | ||
private currentPointer; | ||
constructor({ el, stops, directionType, returnType, direction, type, preview }: GradientPickerProps); | ||
constructor({ el, stops, direction, directionType, directionRadial, returnType, type, preview }: GradientPickerProps); | ||
private initializeElements; | ||
@@ -29,0 +31,0 @@ private createInputReturn; |
@@ -13,5 +13,7 @@ export type GradientDirectionType = "select" | "percent"; | ||
stops?: GradientStop[]; | ||
direction?: GradientDirection | number; | ||
directionType?: GradientDirectionType; | ||
directionRadial?: boolean; | ||
directionRadialType?: GradientDirectionType; | ||
returnType?: "string" | "object"; | ||
direction?: GradientDirection | number; | ||
type?: GradientType; | ||
@@ -18,0 +20,0 @@ preview?: boolean; |
{ | ||
"name": "@ldrender/gradient-picker", | ||
"version": "2.0.2", | ||
"version": "2.0.3", | ||
"description": "A gradient picker component", | ||
@@ -5,0 +5,0 @@ "type": "module", |
@@ -67,4 +67,5 @@ <h1 align="center">Gradient Picker</h1> | ||
type?: 'linear' | 'radial'; // Gradient type (default: 'linear') | ||
direction?: string | number; // Gradient direction (default: 'right') | ||
directionType?: 'select' | 'percent'; // Direction input type (default: 'select') | ||
direction?: string | number; // Gradient direction (default: 'right') | ||
directionRadial?: boolean; // For gradient type 'radial', select if direction input is displayed (default: true) | ||
returnType?: 'string' | 'object' | 'stops-list'; // Output format (default: 'string') | ||
@@ -148,2 +149,18 @@ preview?: boolean; // Enable preview window (default: false) | ||
## Gradient Type Support | ||
### Linear Gradients | ||
- integer: `0 - 360` | ||
- string: `top`, `right`, `bottom`, `left` | ||
### Radial Gradients | ||
- string: `top`, `right`, `bottom`, `left`, `center` | ||
- integer: 0 - 89 = `at center top` | ||
- integer: 90 - 179 = `at center right`, | ||
- integer: 180 - 269 = `at center bottom`, | ||
- integer: 270 - 359 = `at center left` | ||
- integer: 360 = `at center top` | ||
## Color Support | ||
@@ -150,0 +167,0 @@ |
Sorry, the diff of this file is not supported yet
95722
329
230