react-color-strip
Version:
🎨 A minimal horizontal color picker strip component for React with draggable pointer support.
3 lines (2 loc) • 5.29 kB
JavaScript
import{jsxs as t,jsx as e}from"react/jsx-runtime";import{useRef as r,useState as n,useEffect as a}from"react";function o(t,e,r){t/=360,r/=100;const n=(t,e,r)=>(r<0&&(r+=1),r>1&&(r-=1),r<1/6?t+6*(e-t)*r:r<.5?e:r<2/3?t+(e-t)*(2/3-r)*6:t);let a,o,s;if(0===(e/=100))a=o=s=r;else{const i=r<.5?r*(1+e):r+e-r*e,l=2*r-i;a=n(l,i,t+1/3),o=n(l,i,t),s=n(l,i,t-1/3)}return{r:Math.round(255*a),g:Math.round(255*o),b:Math.round(255*s)}}function s(t,e,r){t/=255,e/=255,r/=255;const n=Math.max(t,e,r),a=Math.min(t,e,r);let o=0,s=0;const i=(n+a)/2;if(n===a)o=s=0;else{const l=n-a;switch(s=i>.5?l/(2-n-a):l/(n+a),n){case t:o=(e-r)/l+(e<r?6:0);break;case e:o=(r-t)/l+2;break;case r:o=(t-e)/l+4}o/=6}return{h:Math.round(360*o),s:Math.round(100*s),l:Math.round(100*i)}}function i(t,e,r){const n=t=>{const e=Math.round(t).toString(16);return 1===e.length?"0"+e:e};return`#${n(t)}${n(e)}${n(r)}`}function l(t){const e=/^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(t);return e?{r:parseInt(e[1],16),g:parseInt(e[2],16),b:parseInt(e[3],16)}:null}function c(t){const e=o(t,100,50);return{hex:i(e.r,e.g,e.b),rgb:e,hsl:{h:t,s:100,l:50}}}function u(t){const e=function(t){if(t.startsWith("#"))return l(t);const e=t.match(/rgb\((\d+),\s*(\d+),\s*(\d+)\)/);if(e)return{r:parseInt(e[1]),g:parseInt(e[2]),b:parseInt(e[3])};const r=t.match(/hsl\((\d+),\s*(\d+)%,\s*(\d+)%\)/);if(r)return o(parseInt(r[1]),parseInt(r[2]),parseInt(r[3]));return null}(t);if(!e)return 0;return s(e.r,e.g,e.b).h}function d(t,e,r){const n=l(t),a=l(e);if(!n||!a)return t;return i(n.r+(a.r-n.r)*r,n.g+(a.g-n.g)*r,n.b+(a.b-n.b)*r)}!function(t,e){void 0===e&&(e={});var r=e.insertAt;if("undefined"!=typeof document){var n=document.head||document.getElementsByTagName("head")[0],a=document.createElement("style");a.type="text/css","top"===r&&n.firstChild?n.insertBefore(a,n.firstChild):n.appendChild(a),a.styleSheet?a.styleSheet.cssText=t:a.appendChild(document.createTextNode(t))}}(".stripStyle {\r\n position: relative;\r\n display: inline-block;\r\n border: 1px solid #D1D5DB;\r\n}\r\n\r\n.canvasStyle {\r\n display: block;\r\n}\r\n\r\n.pointer {\r\n position: absolute;\r\n top: 50%;\r\n transition: transform 0.15s ease-in-out;\r\n}");const f=({value:o="#000000ff",width:i=300,height:f=20,disabled:h=!1,pointer:p={},style:b={},customColor:g,rounded:m=0,onChange:x,onChangeComplete:v})=>{const{width:y=12,height:M=f,backgroundColor:C="white",border:w="none",borderRadius:k="2px",boxShadow:D="0 4px 6px -1px rgba(0, 0, 0, 0.1)",scaleOnDrag:S=!0,dragScale:I=1.1}=p,R=r(null),$=r(null),[B,A]=n(!1),[E,N]=n(()=>u(o)),[P,L]=n(()=>g?.5:u(o)/360);a(()=>{const t=$.current;if(!t)return;const e=t.getContext("2d");if(!e)return;t.width=i,t.height=f;const r=e.createLinearGradient(0,0,i,0);if(g)r.addColorStop(0,"#ffffff"),r.addColorStop(.5,g),r.addColorStop(1,"#000000");else for(let t=0;t<=360;t+=30){const e=t%360;r.addColorStop(t/360,`hsl(${e}, 100%, 50%)`)}e.fillStyle=r,e.fillRect(0,0,i,f)},[i,f,g]),a(()=>{g&&L(.5)},[g]),a(()=>{if(!g){const t=u(o);N(t),L(t/360)}},[o,g]);const T=t=>{const e=Math.max(0,Math.min(1,t/i));if(g){const t=.5,r=e<t?d("#ffffff",g,e/t):d(g,"#000000",(e-t)/t),n=l(r);return{hex:r,rgb:n,hsl:s(n.r,n.g,n.b)}}return c(360*e)},X={left:`${g?P*i:E/360*i}px`,width:`${y}px`,height:`${M}px`,backgroundColor:C,border:w,borderRadius:k,boxShadow:D,transform:["translate(-50%, -50%)",B&&S?`scale(${I})`:null].filter(Boolean).join(" "),pointerEvents:"none",opacity:h?"0.5":""};return t("div",{ref:R,className:"stripStyle",style:{width:i,height:f,...{opacity:h?"0.5":"",cursor:h?"not-allowed":B?"grabbing":"grab",borderRadius:m},...b},onPointerDown:t=>{if(h)return;t.preventDefault(),A(!0);const e=R.current?.getBoundingClientRect();if(!e)return;const r=t.clientX-e.left,n=Math.max(0,Math.min(1,r/i));L(n);const a=T(r);g||N(a.hsl.h),x?.(a),t.target.setPointerCapture(t.pointerId)},onPointerMove:t=>{if(!B||h)return;t.preventDefault();const e=R.current?.getBoundingClientRect();if(!e)return;const r=t.clientX-e.left,n=Math.max(0,Math.min(1,r/i));L(n);const a=T(r);g||N(a.hsl.h),x?.(a)},onPointerUp:t=>{if(!B)return;A(!1);const e=R.current?.getBoundingClientRect();if(!e)return;const r=t.clientX-e.left,n=Math.max(0,Math.min(1,r/i));L(n);const a=T(r);g||N(a.hsl.h),v?.(a),t.target.releasePointerCapture(t.pointerId)},onKeyDown:t=>{if(!h)if(g){let e=P;switch(t.key){case"ArrowLeft":t.preventDefault(),e=Math.max(0,P-.01);break;case"ArrowRight":t.preventDefault(),e=Math.min(1,P+.01);break;case"Home":t.preventDefault(),e=0;break;case"End":t.preventDefault(),e=1;break;default:return}L(e);const r=.5,n=e<r?d("#ffffff",g,e/r):d(g,"#000000",(e-r)/r),a=l(n),o={hex:n,rgb:a,hsl:s(a.r,a.g,a.b)};x?.(o),v?.(o)}else{let e=E;switch(t.key){case"ArrowLeft":t.preventDefault(),e=Math.max(0,E-1);break;case"ArrowRight":t.preventDefault(),e=Math.min(360,E+1);break;case"Home":t.preventDefault(),e=0;break;case"End":t.preventDefault(),e=360;break;default:return}const r=c(e);N(e),x?.(r),v?.(r)}},tabIndex:h?-1:0,role:"slider","aria-label":"Color hue selector","aria-valuemin":0,"aria-valuemax":360,"aria-valuenow":E,"aria-disabled":h,children:[e("canvas",{ref:$,className:"canvasStyle",style:{width:"100%",height:"100%",borderRadius:m}}),e("div",{className:"pointer",style:X})]})};export{f as ColorStrip,f as default};
//# sourceMappingURL=index.mjs.map