react-compare-slider
Version:
A slider component to compare any two React components in landscape or portrait orientation. It supports custom images, videos... and everything else.
3 lines • 7.17 kB
JavaScript
"use client"
import{forwardRef as we,useCallback as S,useEffect as U,useImperativeHandle as Le,useRef as w,useState as G}from"react";import{forwardRef as Z}from"react";import{jsx as ee}from"react/jsx-runtime";var z=Z(({transition:e,...i},r)=>{let a={position:"absolute",top:0,left:0,width:"100%",height:"100%",transition:e?`clip-path ${e}`:void 0,userSelect:"none",willChange:"clip-path, transition",KhtmlUserSelect:"none",MozUserSelect:"none",WebkitUserSelect:"none"};return ee("div",{...i,style:a,"data-rcs":"clip-item",ref:r})});z.displayName="ContainerClip";var I=Z(({children:e,disabled:i,portrait:r,position:a,transition:n},d)=>{let m={position:"absolute",top:0,width:r?"100%":void 0,height:r?void 0:"100%",background:"none",border:0,padding:0,pointerEvents:"all",appearance:"none",WebkitAppearance:"none",MozAppearance:"none",outline:0,transform:r?"translate3d(0, -50% ,0)":"translate3d(-50%, 0, 0)",transition:n?`${r?"top":"left"} ${n}`:void 0};return ee("button",{ref:d,"aria-orientation":r?"vertical":"horizontal","aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":a,"data-rcs":"handle-container",disabled:i,role:"slider",style:m,children:e})});I.displayName="ThisHandleContainer";import{jsx as b,jsxs as re}from"react/jsx-runtime";var te=({flip:e})=>b("div",{className:"__rcs-handle-arrow",style:{width:0,height:0,borderTop:"8px solid transparent",borderRight:"10px solid",borderBottom:"8px solid transparent",transform:e?"rotate(180deg)":void 0}}),B=({className:e="__rcs-handle-root",disabled:i,buttonStyle:r,linesStyle:a,portrait:n,style:d,...o})=>{let m={display:"flex",flexDirection:n?"row":"column",placeItems:"center",height:"100%",cursor:i?"not-allowed":n?"ns-resize":"ew-resize",pointerEvents:"none",color:"#fff",...d},v={flexGrow:1,height:n?2:"100%",width:n?"100%":2,backgroundColor:"currentColor",pointerEvents:"auto",boxShadow:"0 0 4px rgba(0,0,0,.5)",...a},L={display:"grid",gridAutoFlow:"column",gap:8,placeContent:"center",flexShrink:0,width:56,height:56,borderRadius:"50%",borderStyle:"solid",borderWidth:2,pointerEvents:"auto",backdropFilter:"blur(7px)",WebkitBackdropFilter:"blur(7px)",backgroundColor:"rgba(0, 0, 0, 0.125)",boxShadow:"0 0 4px rgba(0,0,0,.35)",transform:n?"rotate(90deg)":void 0,...r};return re("div",{...o,"aria-label":o["aria-label"]||"Drag to move",className:e,style:m,children:[b("div",{className:"__rcs-handle-line",style:v}),re("div",{className:"__rcs-handle-button",style:L,children:[b(te,{}),b(te,{flip:!0})]}),b("div",{className:"__rcs-handle-line",style:v})]})};import{useCallback as ye,useEffect as _,useLayoutEffect as ge,useRef as F}from"react";var N=(n=>(n.ARROW_LEFT="ArrowLeft",n.ARROW_RIGHT="ArrowRight",n.ARROW_UP="ArrowUp",n.ARROW_DOWN="ArrowDown",n))(N||{}),$=({boxSizing:e="border-box",objectFit:i="cover",objectPosition:r="center center",...a}={})=>({display:"block",width:"100%",height:"100%",maxWidth:"100%",boxSizing:e,objectFit:i,objectPosition:r,...a}),ne=e=>{let i=F(e);return _(()=>{i.current=e}),i.current},O=(e,i,r,a)=>{let n=F();_(()=>{n.current=i},[i]),_(()=>{if(!(r&&r.addEventListener))return;let d=o=>n.current&&n.current(o);return r.addEventListener(e,d,a),()=>{r.removeEventListener(e,d,a)}},[e,r,a])},be=typeof window<"u"&&typeof window.document<"u"&&typeof window.document.createElement<"u"?ge:_,oe=(e,i)=>{let r=F(),a=ye(()=>{e.current&&r.current&&r.current.observe(e.current)},[e]);be(()=>(r.current=new ResizeObserver(([n])=>i(n.contentRect)),a(),()=>{r.current&&r.current.disconnect()}),[i,a])};import{jsx as X,jsxs as He}from"react/jsx-runtime";var k={capture:!1,passive:!0},V={capture:!0,passive:!1},ie=we(({disabled:e=!1,handle:i,itemOne:r,itemTwo:a,onlyHandleDraggable:n=!1,onPositionChange:d,portrait:o=!1,position:m=50,boundsPadding:v=0,changePositionOnHover:L=!1,keyboardIncrement:H="5%",style:se,transition:ae,...le},ce)=>{let p=w(null),Y=w(null),f=w(null),u=w(m),[E,j]=G(!1),[de,T]=G(!0),x=w(!1),[pe,me]=G(),q=ne(m),l=S(function({x:s,y:c,isOffset:R}){let g=p.current,M=f.current,A=Y.current,{width:h,height:C,left:Pe,top:he}=g.getBoundingClientRect();if(h===0||C===0)return;let Ee=o?R?c-he-window.scrollY:c:R?s-Pe-window.scrollX:s,K=Math.min(Math.max(Ee/(o?C:h)*100,0),100),W=o?C/(g.offsetHeight||1):h/(g.offsetWidth||1),Q=v*W/(o?C:h)*100,D=Math.min(Math.max(K,Q*W),100-Q*W);u.current=K,M.setAttribute("aria-valuenow",`${Math.round(u.current)}`),M.style.top=o?`${D}%`:"0",M.style.left=o?"0":`${D}%`,A.style.clipPath=o?`inset(${D}% 0 0 0)`:`inset(0 0 0 ${D}%)`,d&&d(u.current)},[v,d,o]);U(()=>{let{width:t,height:s}=p.current.getBoundingClientRect(),c=m===q?u.current:m;l({x:t/100*c,y:s/100*c})},[v,m,o,q,l]);let ue=S(t=>{t.preventDefault(),!(e||t.button!==0)&&(l({isOffset:!0,x:t.pageX,y:t.pageY}),j(!0),T(!0))},[e,l]),P=S(function(s){l({isOffset:!0,x:s.pageX,y:s.pageY}),T(!1)},[l]),y=S(()=>{j(!1),T(!0)},[]),fe=S(({width:t,height:s})=>{let{width:c,height:R}=p.current.getBoundingClientRect();l({x:t/100*u.current*c/t,y:s/100*u.current*R/s})},[l]),Re=S(t=>{t.preventDefault(),f.current.focus()},[]),Ce=S(t=>{if(!Object.values(N).includes(t.key))return;t.preventDefault(),T(!0);let{top:s,left:c}=f.current.getBoundingClientRect(),{width:R,height:g}=p.current.getBoundingClientRect(),A=typeof H=="string"?parseFloat(H):H/R*100,h=o?t.key==="ArrowLeft"||t.key==="ArrowDown":t.key==="ArrowRight"||t.key==="ArrowUp",C=Math.min(Math.max(h?u.current+A:u.current-A,0),100);l({x:o?c:R*C/100,y:o?g*C/100:s})},[H,o,l]);U(()=>{me(n?f.current:p.current)},[n]),U(()=>{let t=p.current,s=()=>{E||y()};return L&&(t.addEventListener("pointermove",P,k),t.addEventListener("pointerleave",s,k)),()=>{t.removeEventListener("pointermove",P),t.removeEventListener("pointerleave",s)}},[L,P,y,E]),U(()=>(E&&!x.current&&(window.addEventListener("pointermove",P,k),window.addEventListener("pointerup",y,k),x.current=!0),()=>{x.current&&(window.removeEventListener("pointermove",P),window.removeEventListener("pointerup",y),x.current=!1)}),[P,y,E]),Le(ce,()=>({rootContainer:p.current,setPosition(t){let{width:s,height:c}=p.current.getBoundingClientRect();l({x:s/100*t,y:c/100*t})}}),[l]),oe(p,fe),O("keydown",Ce,f.current,V),O("click",Re,f.current,V),O("pointerdown",ue,pe,V);let Se=i||X(B,{disabled:e,portrait:o}),J=de?ae:void 0,ve={position:"relative",display:"flex",overflow:"hidden",cursor:E?o?"ns-resize":"ew-resize":void 0,touchAction:"none",userSelect:"none",KhtmlUserSelect:"none",msUserSelect:"none",MozUserSelect:"none",WebkitUserSelect:"none",...se};return He("div",{...le,ref:p,style:ve,"data-rcs":"root",children:[r,X(z,{ref:Y,transition:J,children:a}),X(I,{disabled:e,portrait:o,position:Math.round(u.current),ref:f,transition:J,children:Se})]})});ie.displayName="ReactCompareSlider";import{jsx as xe}from"react/jsx-runtime";var Te=({style:e,...i})=>{let r=$(e);return xe("img",{...i,style:r,"data-rcs":"image"})};import{useRef as Me}from"react";var Ae=()=>Me({rootContainer:null,setPosition:()=>console.warn("[react-compare-slider] `setPosition` cannot be used until the component has mounted.")});export{ie as ReactCompareSlider,B as ReactCompareSliderHandle,Te as ReactCompareSliderImage,$ as styleFitContainer,Ae as useReactCompareSliderRef};
//# sourceMappingURL=index.mjs.map