@zenithui/light-box
Version:
A Light Box is React component that displays a light box with a content area and a close button from the ZenithUI ecosystem.
5 lines • 9.59 kB
JavaScript
import*as e from"react/jsx-runtime";import*as t from"@radix-ui/react-dialog";import*as n from"@zenithui/utils";import*as i from"react";import*as a from"@use-gesture/react";let o=()=>(0,e.jsx)("div",{style:{position:"absolute",top:"50%",left:"50%",transform:"translate(-50%, -50%)",width:"40px",height:"40px",border:"3px solid rgba(255,255,255,0.3)",borderRadius:"50%",borderTopColor:"#fff",animation:"spin 1s ease-in-out infinite"}}),r=()=>(0,e.jsxs)("div",{style:{position:"absolute",top:"50%",left:"50%",transform:"translate(-50%, -50%)",color:"white",textAlign:"center",padding:"1rem",borderRadius:"4px"},children:[(0,e.jsx)("div",{style:{fontSize:"2rem"},children:"⚠️"}),(0,e.jsx)("div",{children:"Failed to load image"})]});function s({open:s,onOpenChange:h,images:m,initialIndex:g=0,showCloseButton:p=!0,showDeleteButton:x=!1,showPagination:f=!0,showCaption:v=!1,animation:b="slide",animationDuration:y=500,closeOnBackdropClick:j=!0,closeOnEscape:C=!0,swipeToNavigate:B=!0,zoomable:N=!1,maxZoom:k=4,minZoom:D=1,onImageDelete:w,classNames:I,components:$}){let[M,R]=i.useState(g),[E,S]=i.useState({}),[L,z]=i.useState({}),[O,A]=i.useState(1),[Y,T]=i.useState({x:0,y:0}),[X,F]=i.useState(!1),P=i.useRef(null),K=i.useRef(null),G=(0,n.useDeviceType)();i.useEffect(()=>{let e={},t={};m.forEach((n,i)=>{e[i]=!1,t[i]=!1}),S(e),z(t)},[m]),i.useEffect(()=>{A(D),T({x:0,y:0})},[M,s]);let U=e=>{S(t=>({...t,[e]:!0}))},H=e=>{z(t=>({...t,[e]:!0}))},W=i.useCallback(()=>{R(e=>e>=m.length-1?0:e+1)},[m.length]),q=i.useCallback(()=>{R(e=>e<=0?m.length-1:e-1)},[m.length]),J=i.useCallback(()=>{if(!P.current||!K.current)return{minX:0,maxX:0,minY:0,maxY:0};let e=P.current.getBoundingClientRect(),t=K.current.getBoundingClientRect(),n=t.width*O,i=t.height*O,a=Math.max(0,(n-e.width)/2),o=Math.max(0,(i-e.height)/2);return{minX:-a,maxX:a,minY:-o,maxY:o}},[O]),Q=i.useCallback((e,t)=>{let{minX:n,maxX:i,minY:a,maxY:o}=J();return{x:Math.min(Math.max(e,n),i),y:Math.min(Math.max(t,a),o)}},[J]),V=(0,a.useGesture)({onDrag:({movement:[e,t],memo:n,event:i})=>{if(N&&!(O<=1))return i?.preventDefault(),n||(n=Y),T(Q(n.x+e,n.y+t)),F(!0),P.current&&(P.current.style.cursor="grabbing"),n},onDragEnd:({swipe:[e],direction:[t],velocity:[n]})=>{F(!1),["smallMobile","largeMobile"].includes(G)&&B&&!(O>1)&&1===Math.abs(e)&&n>.3&&(t<0?W():t>0&&q())},onPinch:({origin:e,da:[t],memo:n,event:i})=>{if(!N||!P.current)return;i.preventDefault();let a=P.current.getBoundingClientRect(),[o,r]=e,s=o-a.left-Y.x,l=r-a.top-Y.y,c=Math.min(Math.max(O+.01*(t-(n?.lastDistance??t)),D),k),u=c/O,d=Q(Y.x-s*(u-1),Y.y-l*(u-1));return A(c),T(d),{lastDistance:t}},onWheel:({event:e,delta:[t,n]})=>{if(!N||!P.current)return;if(O<=D&&n>=0)return void T(Q(Y.x,Y.y));let i=O+(n>0?-.1:.1);if((i=Math.round(100*Math.min(Math.max(i,D),k))/100)<=D){A(D),T(Q(Y.x,Y.y));return}if(.01>Math.abs(i-O))return;let a=P.current.getBoundingClientRect(),o=(e.clientX-a.left-Y.x)/O,r=(e.clientY-a.top-Y.y)/O,s=i/O;T(Q(Y.x-o*(s-1),Y.y-r*(s-1))),A(i)},onDoubleClick:({event:e})=>{N&&(e.preventDefault(),A(1),T({x:0,y:0}))}},{drag:{filterTaps:!0,bounds:()=>{let{minX:e,maxX:t,minY:n,maxY:i}=J();return{left:e,right:t,top:n,bottom:i}},rubberband:.2},pinch:{distanceBounds:{min:D,max:k},rubberband:.2},wheel:{rubberband:.2},eventOptions:{passive:!0}});i.useEffect(()=>{if(!P.current)return;P.current.style.cursor=O>D?"grab":"auto";let e=e=>{O>1&&e.preventDefault()};return["smallMobile","largeMobile"].includes(G)&&P.current.addEventListener("touchmove",e,{passive:!1}),()=>{P.current?.removeEventListener("touchmove",e)}},[O,D,G]);let Z=e=>"string"!=typeof e?e.src:e,_=(t,n)=>{let i=Z(t),a=!E[n]&&!L[n],s=L[n];return(0,e.jsxs)("div",{ref:n===M?K:null,style:{position:"relative",width:"100%",height:"100%",overflow:"hidden",touchAction:N?"none":void 0},children:[(0,e.jsx)("img",{src:i,alt:"",style:{position:"absolute",top:"0",left:"0",objectFit:"cover",width:"100%",height:"100%",transform:N?`translate(${Y.x}px, ${Y.y}px) scale(${O})`:void 0,transition:X?"none":`transform ${y}ms ease-out`,opacity:+(!a&&!s),willChange:"transform, opacity",pointerEvents:"none",userSelect:"none",touchAction:"none",MozUserSelect:"none"},onLoad:()=>U(n),onError:()=>H(n)}),a&&(0,e.jsx)(o,{}),s&&(0,e.jsx)(r,{})]})},ee=()=>(0,e.jsx)("div",{style:{position:"absolute",top:0,left:0,display:"flex",height:"100%",width:"100%",zIndex:-1,transform:`translateX(-${100*M}%)`,transition:`transform ${y}ms ease-in-out`},children:m.map((t,n)=>(0,e.jsx)("div",{style:{flex:"0 0 100%",position:"relative",overflow:"hidden"},children:_(t,n)},`slide-${n.toString()}`))}),et=()=>(0,e.jsx)(e.Fragment,{children:m.map((t,n)=>(0,e.jsx)("div",{style:{position:"absolute",top:0,left:0,width:"100%",height:"100%",zIndex:-1,opacity:+(M===n),transition:`opacity ${y}ms ease-in-out`,pointerEvents:M===n?"auto":"none"},children:_(t,n)},`fade-${n.toString()}`))}),en=()=>(0,e.jsx)("div",{style:{position:"absolute",top:0,left:0,width:"100%",height:"100%",zIndex:-1,transform:`${M%2==0?"rotateY(180deg)":"rotateY(0deg)"}`,transition:`transform ${y}ms ease-in-out`},children:_(m[M],M)}),ei=()=>(0,e.jsx)(e.Fragment,{children:m.map((t,n)=>(0,e.jsx)("div",{style:{position:"absolute",top:0,left:0,width:"100%",height:"100%",zIndex:-1,filter:M===n?"blur(0)":"blur(10px)",transition:`filter ${y}ms ease-in-out, opacity ${y}ms ease-in-out`,opacity:+(M===n),pointerEvents:M===n?"auto":"none"},children:_(t,n)},`blur-${n.toString()}`))}),ea=()=>(0,e.jsx)("div",{style:{position:"absolute",top:0,left:0,width:"100%",height:"100%",zIndex:-1,backgroundImage:`url(${Z(m[M])})`,backgroundSize:"cover",backgroundRepeat:"no-repeat",backgroundPosition:"center"},children:_(m[M],M)});return(0,e.jsx)(t.Root,{open:s,onOpenChange:h,children:(0,e.jsxs)(t.DialogPortal,{children:[(0,e.jsx)("style",{children:`
@keyframes spin {
to { transform: translate(-50%, -50%) rotate(360deg); }
}
`}),(0,e.jsx)(t.Overlay,{className:(0,n.cn)(I?.overLay)}),(0,e.jsxs)(t.Content,{ref:P,style:{"--animation-duration":`${y}ms`,..."stretch"===b?{overflow:"hidden"}:{}},onEscapeKeyDown:e=>{C||e.preventDefault()},onPointerDownOutside:e=>{j||e.preventDefault()},"aria-modal":"true","aria-labelledby":"lightbox-title","aria-describedby":"lightbox-description",className:(0,n.cn)(I?.lightBox),"data-animation":b,onKeyDown:e=>{C&&"Escape"===e.key&&h(!1),"ArrowLeft"===e.key&&q(),"ArrowRight"===e.key&&W(),"Home"===e.key&&R(0),"End"===e.key&&R(m.length-1)},...V(),children:[(0,e.jsx)(t.Title,{style:{display:"none"},children:"Title"}),(()=>{switch(b){case"slide":default:return ee();case"fade":return et();case"flip":return en();case"blur":return ei();case"stretch":return ea()}})(),(0,e.jsxs)("div",{className:(0,n.cn)(I?.controls),"data-animation":b,children:[x&&($?.DeleteButton?(0,e.jsx)($.DeleteButton,{onImageDelete:w,currentIndex:M,images:m,onOpenChange:h,setCurrentIndex:R,className:I?.deleteButton}):(0,e.jsx)(c,{onImageDelete:w,currentIndex:M,images:m,onOpenChange:h,setCurrentIndex:R,className:I?.deleteButton,children:$?.DeleteButtonIcon})),p&&($?.CloseButton?(0,e.jsx)($.CloseButton,{onOpenChange:h,className:I?.closeButton,children:$?.CloseButtonIcon}):(0,e.jsx)(l,{onOpenChange:h,className:I?.closeButton,children:$?.CloseButtonIcon}))]}),(0,e.jsxs)("div",{className:(0,n.cn)(I?.navigation),"data-animation":b,children:[$?.NavigationButtonLeft?(0,e.jsx)($.NavigationButtonLeft,{direction:"left",onClick:q,className:(0,n.cn)(I?.navigateButton,I?.navigateButtonLeft)}):(0,e.jsx)(u,{direction:"left",onClick:q,className:(0,n.cn)(I?.navigateButton,I?.navigateButtonLeft),children:$?.NavigationButtonLeftIcon}),$?.NavigationButtonRight?(0,e.jsx)($.NavigationButtonRight,{direction:"right",onClick:W,className:(0,n.cn)(I?.navigateButton,I?.navigateButtonRight)}):(0,e.jsx)(u,{direction:"right",onClick:W,className:(0,n.cn)(I?.navigateButton,I?.navigateButtonRight),children:$?.NavigationButtonRightIcon})]}),(0,e.jsxs)("div",{className:(0,n.cn)(I?.footer),"data-animation":b,children:[v&&(0,e.jsxs)("div",{style:{display:"flex",flexDirection:"column",paddingInline:"1rem",gap:"0.5rem",width:"100%"},className:(0,n.cn)(I?.captionContainer),children:[(0,e.jsx)("span",{className:(0,n.cn)(I?.caption),children:("string"!=typeof m[M]&&m[M].caption)??""}),(0,e.jsx)("span",{className:(0,n.cn)(I?.captionDescription),children:("string"!=typeof m[M]&&m[M].captionDescription)??""})]}),f&&(0,e.jsx)("div",{className:(0,n.cn)(I?.pagination),children:Array.from({length:m.length}).map((t,n)=>(0,e.jsx)(d,{active:M===n,onClick:()=>{R(n)},className:I?.paginationButton,activeClassName:I?.paginationButtonActive},`pagination-${n.toString()}`))})]})]})]})})}let l=i.memo(({onOpenChange:t,className:i,children:a})=>(0,e.jsx)("button",{type:"button",className:(0,n.cn)(i),onClick:()=>t(!1),children:a})),c=i.memo(({currentIndex:t,images:a,onOpenChange:o,setCurrentIndex:r,className:s,onImageDelete:l,children:c})=>{let u=i.useCallback(()=>{l&&(l(t),1===a.length?o(!1):t===a.length-1&&r(t-1))},[t,a.length,l,o,r]);return(0,e.jsx)("button",{type:"button",className:(0,n.cn)(s),tabIndex:0,onClick:u,"aria-label":"Delete current image",children:c})}),u=i.memo(({direction:t,onClick:i,className:a,children:o})=>(0,e.jsx)("button",{type:"button",className:(0,n.cn)(a),onClick:i,"aria-label":`Navigate ${t}`,children:o})),d=i.memo(({active:t,onClick:i,activeClassName:a,className:o})=>(0,e.jsx)("div",{"data-active":t,className:(0,n.cn)(o,t&&(a||"")),onClick:i,onKeyUp:e=>{("Enter"===e.key||" "===e.key)&&i()},tabIndex:0,role:"button","aria-pressed":t,"aria-label":`Go to image ${t?"(current)":""}`}));export{s as LightBox};