@clicktap/ui 0.40.7 → 0.40.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/components/Menu/Menu.js +1 -1
- package/docs/migrations/2026/01/2026-01-14-external-link-detection.md +290 -0
- package/docs/migrations/2026/01/2026-01-14-use-route-hook.md +142 -0
- package/docs/migrations/2026/01/2026-01-15-input-disable-skeleton.md +82 -0
- package/docs/migrations/2026/02/2026-02-16-env-utils-from-clicktap-ui.md +94 -0
- package/docs/migrations/2026/02/2026-02-17-select-popover-portal-container-restored.md +84 -0
- package/docs/migrations/2026/03/2026-03-24-image-dimmed-hidden-onready.md +108 -0
- package/docs/migrations/2026/03/2026-03-24-modal-overlay-backdrop-dismiss.md +81 -0
- package/docs/migrations/2026/04/2026-04-17-select-address-input-onchange-key-or-item.md +182 -0
- package/docs/migrations/2026/04/2026-04-24-image-placeholder-frontend-fallback.md +85 -0
- package/docs/migrations/2026/04/2026-04-30-prune-invalid-pdp-selections.md +166 -0
- package/docs/migrations/2026/04/2026-04-30-top-down-pdp-option-dependency.md +286 -0
- package/docs/migrations/2026/05/2026-05-01-build-pdp-url-util.md +128 -0
- package/docs/migrations/2026/05/2026-05-03-auth-aware-graphql-client.md +278 -0
- package/docs/migrations/2026/05/2026-05-20-framer-motion-11-idioms.md +391 -0
- package/docs/migrations/2026/05/2026-05-21-button-loading-content.md +265 -0
- package/docs/migrations/2026/05/2026-05-21-password-check-hide-on-empty.md +50 -0
- package/docs/migrations/2026/05/2026-05-29-password-check-requirements-variant.md +63 -0
- package/docs/migrations/2026/06/2026-06-17-select-standardization.md +286 -0
- package/docs/migrations/2026/06/2026-06-18-select-hiddenselect-setvalue-crash.md +75 -0
- package/docs/migrations/2026/07/2026-07-31-ui-exports-bundler-resolution.md +50 -0
- package/docs/migrations/README.md +31 -0
- package/package.json +2 -2
package/components/Menu/Menu.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";import{jsx as Oe,jsxs as Ye,Fragment as Ot}from"react/jsx-runtime";import*as g from"react";import{useLayoutEffect as lt,useEffect as Tt,useRef as ut,useState as St,useId as At,cloneElement as Dt}from"react";import{motion as Lt}from"framer-motion";import*as Mt from"react-dom";function ft(e){return at(e)?(e.nodeName||"").toLowerCase():"#document"}function ce(e){var t;return(e==null||(t=e.ownerDocument)==null?void 0:t.defaultView)||window}function kt(e){var t;return(t=(at(e)?e.ownerDocument:e.document)||window.document)==null?void 0:t.documentElement}function at(e){return e instanceof Node||e instanceof ce(e).Node}function _(e){return e instanceof Element||e instanceof ce(e).Element}function Re(e){return e instanceof HTMLElement||e instanceof ce(e).HTMLElement}function ke(e){return typeof ShadowRoot>"u"?!1:e instanceof ShadowRoot||e instanceof ce(e).ShadowRoot}function Ft(e){return["html","body","#document"].includes(ft(e))}function $t(e){return ce(e).getComputedStyle(e)}function It(e){if(ft(e)==="html")return e;const t=e.assignedSlot||e.parentNode||ke(e)&&e.host||kt(e);return ke(t)?t.host:t}function Nt(e){let t=e.activeElement;for(;((n=t)==null||(o=n.shadowRoot)==null?void 0:o.activeElement)!=null;){var n,o;t=t.shadowRoot.activeElement}return t}function se(e,t){if(!e||!t)return!1;const n=t.getRootNode&&t.getRootNode();if(e.contains(t))return!0;if(n&&ke(n)){let o=t;for(;o;){if(e===o)return!0;o=o.parentNode||o.host}}return!1}function _t(){const e=navigator.userAgentData;return e!=null&&e.platform?e.platform:navigator.platform}function Wt(){const e=navigator.userAgentData;return e&&Array.isArray(e.brands)?e.brands.map(t=>{let{brand:n,version:o}=t;return n+"/"+o}).join(" "):navigator.userAgent}function Bt(e){if(e.mozInputSource===0&&e.isTrusted)return!0;const t=/Android/i;return(t.test(_t())||t.test(Wt()))&&e.pointerType?e.type==="click"&&e.buttons===1:e.detail===0&&!e.pointerType}function Vt(e){return e.width===0&&e.height===0||e.width===1&&e.height===1&&e.pressure===0&&e.detail===0&&e.pointerType!=="mouse"||e.width<1&&e.height<1&&e.pressure===0&&e.detail===0}function he(e,t){const n=["mouse","pen"];return t||n.push("",void 0),n.includes(e)}function Ht(e){return"nativeEvent"in e}function Kt(e){return e.matches("html,body")}function X(e){return e?.ownerDocument||document}function de(e,t){if(t==null)return!1;if("composedPath"in e)return e.composedPath().includes(t);const n=e;return n.target!=null&&t.contains(n.target)}function jt(e){return"composedPath"in e?e.composedPath()[0]:e.target}const Xt="input:not([type='hidden']):not([disabled]),[contenteditable]:not([contenteditable='false']),textarea:not([disabled])";function zt(e){return Re(e)&&e.matches(Xt)}const oe=Math.min,Z=Math.max,ve=Math.round,ae=Math.floor,K=e=>({x:e,y:e}),Yt={left:"right",right:"left",bottom:"top",top:"bottom"};function Fe(e,t,n){return Z(e,oe(t,n))}function le(e,t){return typeof e=="function"?e(t):e}function J(e){return e.split("-")[0]}function ue(e){return e.split("-")[1]}function dt(e){return e==="x"?"y":"x"}function We(e){return e==="y"?"height":"width"}function Y(e){const t=e[0];return t==="t"||t==="b"?"y":"x"}function Be(e){return dt(Y(e))}function Ut(e,t,n){n===void 0&&(n=!1);const o=ue(e),r=Be(e),i=We(r);let s=r==="x"?o===(n?"end":"start")?"right":"left":o==="start"?"bottom":"top";return t.reference[i]>t.floating[i]&&(s=ye(s)),[s,ye(s)]}function qt(e){const t=ye(e);return[$e(e),t,$e(t)]}function $e(e){return e.includes("start")?e.replace("start","end"):e.replace("end","start")}const Ue=["left","right"],qe=["right","left"],Gt=["top","bottom"],Qt=["bottom","top"];function Zt(e,t,n){switch(e){case"top":case"bottom":return n?t?qe:Ue:t?Ue:qe;case"left":case"right":return t?Gt:Qt;default:return[]}}function Jt(e,t,n,o){const r=ue(e);let i=Zt(J(e),n==="start",o);return r&&(i=i.map(s=>s+"-"+r),t&&(i=i.concat(i.map($e)))),i}function ye(e){const t=J(e);return Yt[t]+e.slice(t.length)}function en(e){return{top:0,right:0,bottom:0,left:0,...e}}function mt(e){return typeof e!="number"?en(e):{top:e,right:e,bottom:e,left:e}}function we(e){const{x:t,y:n,width:o,height:r}=e;return{width:o,height:r,top:n,left:t,right:t+o,bottom:n+r,x:t,y:n}}function Ge(e,t,n){let{reference:o,floating:r}=e;const i=Y(t),s=Be(t),c=We(s),u=J(t),f=i==="y",d=o.x+o.width/2-r.width/2,a=o.y+o.height/2-r.height/2,m=o[c]/2-r[c]/2;let l;switch(u){case"top":l={x:d,y:o.y-r.height};break;case"bottom":l={x:d,y:o.y+o.height};break;case"right":l={x:o.x+o.width,y:a};break;case"left":l={x:o.x-r.width,y:a};break;default:l={x:o.x,y:o.y}}switch(ue(t)){case"start":l[s]-=m*(n&&f?-1:1);break;case"end":l[s]+=m*(n&&f?-1:1);break}return l}async function tn(e,t){var n;t===void 0&&(t={});const{x:o,y:r,platform:i,rects:s,elements:c,strategy:u}=e,{boundary:f="clippingAncestors",rootBoundary:d="viewport",elementContext:a="floating",altBoundary:m=!1,padding:l=0}=le(t,e),p=mt(l),E=c[m?a==="floating"?"reference":"floating":a],x=we(await i.getClippingRect({element:(n=await(i.isElement==null?void 0:i.isElement(E)))==null||n?E:E.contextElement||await(i.getDocumentElement==null?void 0:i.getDocumentElement(c.floating)),boundary:f,rootBoundary:d,strategy:u})),C=a==="floating"?{x:o,y:r,width:s.floating.width,height:s.floating.height}:s.reference,S=await(i.getOffsetParent==null?void 0:i.getOffsetParent(c.floating)),b=await(i.isElement==null?void 0:i.isElement(S))?await(i.getScale==null?void 0:i.getScale(S))||{x:1,y:1}:{x:1,y:1},O=we(i.convertOffsetParentRelativeRectToViewportRelativeRect?await i.convertOffsetParentRelativeRectToViewportRelativeRect({elements:c,rect:C,offsetParent:S,strategy:u}):C);return{top:(x.top-O.top+p.top)/b.y,bottom:(O.bottom-x.bottom+p.bottom)/b.y,left:(x.left-O.left+p.left)/b.x,right:(O.right-x.right+p.right)/b.x}}const nn=50,on=async(e,t,n)=>{const{placement:o="bottom",strategy:r="absolute",middleware:i=[],platform:s}=n,c=s.detectOverflow?s:{...s,detectOverflow:tn},u=await(s.isRTL==null?void 0:s.isRTL(t));let f=await s.getElementRects({reference:e,floating:t,strategy:r}),{x:d,y:a}=Ge(f,o,u),m=o,l=0;const p={};for(let h=0;h<i.length;h++){const E=i[h];if(!E)continue;const{name:x,fn:C}=E,{x:S,y:b,data:O,reset:P}=await C({x:d,y:a,initialPlacement:o,placement:m,strategy:r,middlewareData:p,rects:f,platform:c,elements:{reference:e,floating:t}});d=S??d,a=b??a,p[x]={...p[x],...O},P&&l<nn&&(l++,typeof P=="object"&&(P.placement&&(m=P.placement),P.rects&&(f=P.rects===!0?await s.getElementRects({reference:e,floating:t,strategy:r}):P.rects),{x:d,y:a}=Ge(f,m,u)),h=-1)}return{x:d,y:a,placement:m,strategy:r,middlewareData:p}},rn=e=>({name:"arrow",options:e,async fn(t){const{x:n,y:o,placement:r,rects:i,platform:s,elements:c,middlewareData:u}=t,{element:f,padding:d=0}=le(e,t)||{};if(f==null)return{};const a=mt(d),m={x:n,y:o},l=Be(r),p=We(l),h=await s.getDimensions(f),E=l==="y",x=E?"top":"left",C=E?"bottom":"right",S=E?"clientHeight":"clientWidth",b=i.reference[p]+i.reference[l]-m[l]-i.floating[p],O=m[l]-i.reference[l],P=await(s.getOffsetParent==null?void 0:s.getOffsetParent(f));let v=P?P[S]:0;(!v||!await(s.isElement==null?void 0:s.isElement(P)))&&(v=c.floating[S]||i.floating[p]);const k=b/2-O/2,I=v/2-h[p]/2-1,$=oe(a[x],I),A=oe(a[C],I),M=$,R=v-h[p]-A,y=v/2-h[p]/2+k,T=Fe(M,y,R),L=!u.arrow&&ue(r)!=null&&y!==T&&i.reference[p]/2-(y<M?$:A)-h[p]/2<0,F=L?y<M?y-M:y-R:0;return{[l]:m[l]+F,data:{[l]:T,centerOffset:y-T-F,...L&&{alignmentOffset:F}},reset:L}}}),sn=function(e){return e===void 0&&(e={}),{name:"flip",options:e,async fn(t){var n,o;const{placement:r,middlewareData:i,rects:s,initialPlacement:c,platform:u,elements:f}=t,{mainAxis:d=!0,crossAxis:a=!0,fallbackPlacements:m,fallbackStrategy:l="bestFit",fallbackAxisSideDirection:p="none",flipAlignment:h=!0,...E}=le(e,t);if((n=i.arrow)!=null&&n.alignmentOffset)return{};const x=J(r),C=Y(c),S=J(c)===c,b=await(u.isRTL==null?void 0:u.isRTL(f.floating)),O=m||(S||!h?[ye(c)]:qt(c)),P=p!=="none";!m&&P&&O.push(...Jt(c,h,p,b));const v=[c,...O],k=await u.detectOverflow(t,E),I=[];let $=((o=i.flip)==null?void 0:o.overflows)||[];if(d&&I.push(k[x]),a){const y=Ut(r,s,b);I.push(k[y[0]],k[y[1]])}if($=[...$,{placement:r,overflows:I}],!I.every(y=>y<=0)){var A,M;const y=(((A=i.flip)==null?void 0:A.index)||0)+1,T=v[y];if(T&&(!(a==="alignment"?C!==Y(T):!1)||$.every(w=>Y(w.placement)===C?w.overflows[0]>0:!0)))return{data:{index:y,overflows:$},reset:{placement:T}};let L=(M=$.filter(F=>F.overflows[0]<=0).sort((F,w)=>F.overflows[1]-w.overflows[1])[0])==null?void 0:M.placement;if(!L)switch(l){case"bestFit":{var R;const F=(R=$.filter(w=>{if(P){const D=Y(w.placement);return D===C||D==="y"}return!0}).map(w=>[w.placement,w.overflows.filter(D=>D>0).reduce((D,N)=>D+N,0)]).sort((w,D)=>w[1]-D[1])[0])==null?void 0:R[0];F&&(L=F);break}case"initialPlacement":L=c;break}if(r!==L)return{reset:{placement:L}}}return{}}}},cn=new Set(["left","top"]);async function ln(e,t){const{placement:n,platform:o,elements:r}=e,i=await(o.isRTL==null?void 0:o.isRTL(r.floating)),s=J(n),c=ue(n),u=Y(n)==="y",f=cn.has(s)?-1:1,d=i&&u?-1:1,a=le(t,e);let{mainAxis:m,crossAxis:l,alignmentAxis:p}=typeof a=="number"?{mainAxis:a,crossAxis:0,alignmentAxis:null}:{mainAxis:a.mainAxis||0,crossAxis:a.crossAxis||0,alignmentAxis:a.alignmentAxis};return c&&typeof p=="number"&&(l=c==="end"?p*-1:p),u?{x:l*d,y:m*f}:{x:m*f,y:l*d}}const un=function(e){return e===void 0&&(e=0),{name:"offset",options:e,async fn(t){var n,o;const{x:r,y:i,placement:s,middlewareData:c}=t,u=await ln(t,e);return s===((n=c.offset)==null?void 0:n.placement)&&(o=c.arrow)!=null&&o.alignmentOffset?{}:{x:r+u.x,y:i+u.y,data:{...u,placement:s}}}}},fn=function(e){return e===void 0&&(e={}),{name:"shift",options:e,async fn(t){const{x:n,y:o,placement:r,platform:i}=t,{mainAxis:s=!0,crossAxis:c=!1,limiter:u={fn:x=>{let{x:C,y:S}=x;return{x:C,y:S}}},...f}=le(e,t),d={x:n,y:o},a=await i.detectOverflow(t,f),m=Y(J(r)),l=dt(m);let p=d[l],h=d[m];if(s){const x=l==="y"?"top":"left",C=l==="y"?"bottom":"right",S=p+a[x],b=p-a[C];p=Fe(S,p,b)}if(c){const x=m==="y"?"top":"left",C=m==="y"?"bottom":"right",S=h+a[x],b=h-a[C];h=Fe(S,h,b)}const E=u.fn({...t,[l]:p,[m]:h});return{...E,data:{x:E.x-n,y:E.y-o,enabled:{[l]:s,[m]:c}}}}}};function be(){return typeof window<"u"}function ie(e){return gt(e)?(e.nodeName||"").toLowerCase():"#document"}function W(e){var t;return(e==null||(t=e.ownerDocument)==null?void 0:t.defaultView)||window}function j(e){var t;return(t=(gt(e)?e.ownerDocument:e.document)||window.document)==null?void 0:t.documentElement}function gt(e){return be()?e instanceof Node||e instanceof W(e).Node:!1}function B(e){return be()?e instanceof Element||e instanceof W(e).Element:!1}function z(e){return be()?e instanceof HTMLElement||e instanceof W(e).HTMLElement:!1}function Qe(e){return!be()||typeof ShadowRoot>"u"?!1:e instanceof ShadowRoot||e instanceof W(e).ShadowRoot}function fe(e){const{overflow:t,overflowX:n,overflowY:o,display:r}=V(e);return/auto|scroll|overlay|hidden|clip/.test(t+o+n)&&r!=="inline"&&r!=="contents"}function an(e){return/^(table|td|th)$/.test(ie(e))}function Ee(e){try{if(e.matches(":popover-open"))return!0}catch{}try{return e.matches(":modal")}catch{return!1}}const dn=/transform|translate|scale|rotate|perspective|filter/,mn=/paint|layout|strict|content/,Q=e=>!!e&&e!=="none";let Te;function Ve(e){const t=B(e)?V(e):e;return Q(t.transform)||Q(t.translate)||Q(t.scale)||Q(t.rotate)||Q(t.perspective)||!He()&&(Q(t.backdropFilter)||Q(t.filter))||dn.test(t.willChange||"")||mn.test(t.contain||"")}function gn(e){let t=G(e);for(;z(t)&&!re(t);){if(Ve(t))return t;if(Ee(t))return null;t=G(t)}return null}function He(){return Te==null&&(Te=typeof CSS<"u"&&CSS.supports&&CSS.supports("-webkit-backdrop-filter","none")),Te}function re(e){return/^(html|body|#document)$/.test(ie(e))}function V(e){return W(e).getComputedStyle(e)}function Ce(e){return B(e)?{scrollLeft:e.scrollLeft,scrollTop:e.scrollTop}:{scrollLeft:e.scrollX,scrollTop:e.scrollY}}function G(e){if(ie(e)==="html")return e;const t=e.assignedSlot||e.parentNode||Qe(e)&&e.host||j(e);return Qe(t)?t.host:t}function pt(e){const t=G(e);return re(t)?e.ownerDocument?e.ownerDocument.body:e.body:z(t)&&fe(t)?t:pt(t)}function U(e,t,n){var o;t===void 0&&(t=[]),n===void 0&&(n=!0);const r=pt(e),i=r===((o=e.ownerDocument)==null?void 0:o.body),s=W(r);if(i){const c=Ie(s);return t.concat(s,s.visualViewport||[],fe(r)?r:[],c&&n?U(c):[])}else return t.concat(r,U(r,[],n))}function Ie(e){return e.parent&&Object.getPrototypeOf(e.parent)?e.frameElement:null}function ht(e){const t=V(e);let n=parseFloat(t.width)||0,o=parseFloat(t.height)||0;const r=z(e),i=r?e.offsetWidth:n,s=r?e.offsetHeight:o,c=ve(n)!==i||ve(o)!==s;return c&&(n=i,o=s),{width:n,height:o,$:c}}function Ke(e){return B(e)?e:e.contextElement}function ne(e){const t=Ke(e);if(!z(t))return K(1);const n=t.getBoundingClientRect(),{width:o,height:r,$:i}=ht(t);let s=(i?ve(n.width):n.width)/o,c=(i?ve(n.height):n.height)/r;return(!s||!Number.isFinite(s))&&(s=1),(!c||!Number.isFinite(c))&&(c=1),{x:s,y:c}}const pn=K(0);function vt(e){const t=W(e);return!He()||!t.visualViewport?pn:{x:t.visualViewport.offsetLeft,y:t.visualViewport.offsetTop}}function hn(e,t,n){return t===void 0&&(t=!1),!n||t&&n!==W(e)?!1:t}function ee(e,t,n,o){t===void 0&&(t=!1),n===void 0&&(n=!1);const r=e.getBoundingClientRect(),i=Ke(e);let s=K(1);t&&(o?B(o)&&(s=ne(o)):s=ne(e));const c=hn(i,n,o)?vt(i):K(0);let u=(r.left+c.x)/s.x,f=(r.top+c.y)/s.y,d=r.width/s.x,a=r.height/s.y;if(i){const m=W(i),l=o&&B(o)?W(o):o;let p=m,h=Ie(p);for(;h&&o&&l!==p;){const E=ne(h),x=h.getBoundingClientRect(),C=V(h),S=x.left+(h.clientLeft+parseFloat(C.paddingLeft))*E.x,b=x.top+(h.clientTop+parseFloat(C.paddingTop))*E.y;u*=E.x,f*=E.y,d*=E.x,a*=E.y,u+=S,f+=b,p=W(h),h=Ie(p)}}return we({width:d,height:a,x:u,y:f})}function Pe(e,t){const n=Ce(e).scrollLeft;return t?t.left+n:ee(j(e)).left+n}function yt(e,t){const n=e.getBoundingClientRect(),o=n.left+t.scrollLeft-Pe(e,n),r=n.top+t.scrollTop;return{x:o,y:r}}function vn(e){let{elements:t,rect:n,offsetParent:o,strategy:r}=e;const i=r==="fixed",s=j(o),c=t?Ee(t.floating):!1;if(o===s||c&&i)return n;let u={scrollLeft:0,scrollTop:0},f=K(1);const d=K(0),a=z(o);if((a||!a&&!i)&&((ie(o)!=="body"||fe(s))&&(u=Ce(o)),a)){const l=ee(o);f=ne(o),d.x=l.x+o.clientLeft,d.y=l.y+o.clientTop}const m=s&&!a&&!i?yt(s,u):K(0);return{width:n.width*f.x,height:n.height*f.y,x:n.x*f.x-u.scrollLeft*f.x+d.x+m.x,y:n.y*f.y-u.scrollTop*f.y+d.y+m.y}}function yn(e){return Array.from(e.getClientRects())}function wn(e){const t=j(e),n=Ce(e),o=e.ownerDocument.body,r=Z(t.scrollWidth,t.clientWidth,o.scrollWidth,o.clientWidth),i=Z(t.scrollHeight,t.clientHeight,o.scrollHeight,o.clientHeight);let s=-n.scrollLeft+Pe(e);const c=-n.scrollTop;return V(o).direction==="rtl"&&(s+=Z(t.clientWidth,o.clientWidth)-r),{width:r,height:i,x:s,y:c}}const Ze=25;function xn(e,t){const n=W(e),o=j(e),r=n.visualViewport;let i=o.clientWidth,s=o.clientHeight,c=0,u=0;if(r){i=r.width,s=r.height;const d=He();(!d||d&&t==="fixed")&&(c=r.offsetLeft,u=r.offsetTop)}const f=Pe(o);if(f<=0){const d=o.ownerDocument,a=d.body,m=getComputedStyle(a),l=d.compatMode==="CSS1Compat"&&parseFloat(m.marginLeft)+parseFloat(m.marginRight)||0,p=Math.abs(o.clientWidth-a.clientWidth-l);p<=Ze&&(i-=p)}else f<=Ze&&(i+=f);return{width:i,height:s,x:c,y:u}}function Rn(e,t){const n=ee(e,!0,t==="fixed"),o=n.top+e.clientTop,r=n.left+e.clientLeft,i=z(e)?ne(e):K(1),s=e.clientWidth*i.x,c=e.clientHeight*i.y,u=r*i.x,f=o*i.y;return{width:s,height:c,x:u,y:f}}function Je(e,t,n){let o;if(t==="viewport")o=xn(e,n);else if(t==="document")o=wn(j(e));else if(B(t))o=Rn(t,n);else{const r=vt(e);o={x:t.x-r.x,y:t.y-r.y,width:t.width,height:t.height}}return we(o)}function wt(e,t){const n=G(e);return n===t||!B(n)||re(n)?!1:V(n).position==="fixed"||wt(n,t)}function bn(e,t){const n=t.get(e);if(n)return n;let o=U(e,[],!1).filter(c=>B(c)&&ie(c)!=="body"),r=null;const i=V(e).position==="fixed";let s=i?G(e):e;for(;B(s)&&!re(s);){const c=V(s),u=Ve(s);!u&&c.position==="fixed"&&(r=null),(i?!u&&!r:!u&&c.position==="static"&&!!r&&(r.position==="absolute"||r.position==="fixed")||fe(s)&&!u&&wt(e,s))?o=o.filter(d=>d!==s):r=c,s=G(s)}return t.set(e,o),o}function En(e){let{element:t,boundary:n,rootBoundary:o,strategy:r}=e;const s=[...n==="clippingAncestors"?Ee(t)?[]:bn(t,this._c):[].concat(n),o],c=Je(t,s[0],r);let u=c.top,f=c.right,d=c.bottom,a=c.left;for(let m=1;m<s.length;m++){const l=Je(t,s[m],r);u=Z(l.top,u),f=oe(l.right,f),d=oe(l.bottom,d),a=Z(l.left,a)}return{width:f-a,height:d-u,x:a,y:u}}function Cn(e){const{width:t,height:n}=ht(e);return{width:t,height:n}}function Pn(e,t,n){const o=z(t),r=j(t),i=n==="fixed",s=ee(e,!0,i,t);let c={scrollLeft:0,scrollTop:0};const u=K(0);function f(){u.x=Pe(r)}if(o||!o&&!i)if((ie(t)!=="body"||fe(r))&&(c=Ce(t)),o){const l=ee(t,!0,i,t);u.x=l.x+t.clientLeft,u.y=l.y+t.clientTop}else r&&f();i&&!o&&r&&f();const d=r&&!o&&!i?yt(r,c):K(0),a=s.left+c.scrollLeft-u.x-d.x,m=s.top+c.scrollTop-u.y-d.y;return{x:a,y:m,width:s.width,height:s.height}}function Se(e){return V(e).position==="static"}function et(e,t){if(!z(e)||V(e).position==="fixed")return null;if(t)return t(e);let n=e.offsetParent;return j(e)===n&&(n=n.ownerDocument.body),n}function xt(e,t){const n=W(e);if(Ee(e))return n;if(!z(e)){let r=G(e);for(;r&&!re(r);){if(B(r)&&!Se(r))return r;r=G(r)}return n}let o=et(e,t);for(;o&&an(o)&&Se(o);)o=et(o,t);return o&&re(o)&&Se(o)&&!Ve(o)?n:o||gn(e)||n}const On=async function(e){const t=this.getOffsetParent||xt,n=this.getDimensions,o=await n(e.floating);return{reference:Pn(e.reference,await t(e.floating),e.strategy),floating:{x:0,y:0,width:o.width,height:o.height}}};function Tn(e){return V(e).direction==="rtl"}const Rt={convertOffsetParentRelativeRectToViewportRelativeRect:vn,getDocumentElement:j,getClippingRect:En,getOffsetParent:xt,getElementRects:On,getClientRects:yn,getDimensions:Cn,getScale:ne,isElement:B,isRTL:Tn};function bt(e,t){return e.x===t.x&&e.y===t.y&&e.width===t.width&&e.height===t.height}function Sn(e,t){let n=null,o;const r=j(e);function i(){var c;clearTimeout(o),(c=n)==null||c.disconnect(),n=null}function s(c,u){c===void 0&&(c=!1),u===void 0&&(u=1),i();const f=e.getBoundingClientRect(),{left:d,top:a,width:m,height:l}=f;if(c||t(),!m||!l)return;const p=ae(a),h=ae(r.clientWidth-(d+m)),E=ae(r.clientHeight-(a+l)),x=ae(d),S={rootMargin:-p+"px "+-h+"px "+-E+"px "+-x+"px",threshold:Z(0,oe(1,u))||1};let b=!0;function O(P){const v=P[0].intersectionRatio;if(v!==u){if(!b)return s();v?s(!1,v):o=setTimeout(()=>{s(!1,1e-7)},1e3)}v===1&&!bt(f,e.getBoundingClientRect())&&s(),b=!1}try{n=new IntersectionObserver(O,{...S,root:r.ownerDocument})}catch{n=new IntersectionObserver(O,S)}n.observe(e)}return s(!0),i}function An(e,t,n,o){o===void 0&&(o={});const{ancestorScroll:r=!0,ancestorResize:i=!0,elementResize:s=typeof ResizeObserver=="function",layoutShift:c=typeof IntersectionObserver=="function",animationFrame:u=!1}=o,f=Ke(e),d=r||i?[...f?U(f):[],...t?U(t):[]]:[];d.forEach(x=>{r&&x.addEventListener("scroll",n,{passive:!0}),i&&x.addEventListener("resize",n)});const a=f&&c?Sn(f,n):null;let m=-1,l=null;s&&(l=new ResizeObserver(x=>{let[C]=x;C&&C.target===f&&l&&t&&(l.unobserve(t),cancelAnimationFrame(m),m=requestAnimationFrame(()=>{var S;(S=l)==null||S.observe(t)})),n()}),f&&!u&&l.observe(f),t&&l.observe(t));let p,h=u?ee(e):null;u&&E();function E(){const x=ee(e);h&&!bt(h,x)&&n(),h=x,p=requestAnimationFrame(E)}return n(),()=>{var x;d.forEach(C=>{r&&C.removeEventListener("scroll",n),i&&C.removeEventListener("resize",n)}),a?.(),(x=l)==null||x.disconnect(),l=null,u&&cancelAnimationFrame(p)}}const Dn=un,Ln=fn,Mn=sn,tt=rn,kn=(e,t,n)=>{const o=new Map,r={platform:Rt,...n},i={...r.platform,_c:o};return on(e,t,{...r,platform:i})};var Fn=typeof document<"u",$n=function(){},me=Fn?lt:$n;function xe(e,t){if(e===t)return!0;if(typeof e!=typeof t)return!1;if(typeof e=="function"&&e.toString()===t.toString())return!0;let n,o,r;if(e&&t&&typeof e=="object"){if(Array.isArray(e)){if(n=e.length,n!==t.length)return!1;for(o=n;o--!==0;)if(!xe(e[o],t[o]))return!1;return!0}if(r=Object.keys(e),n=r.length,n!==Object.keys(t).length)return!1;for(o=n;o--!==0;)if(!{}.hasOwnProperty.call(t,r[o]))return!1;for(o=n;o--!==0;){const i=r[o];if(!(i==="_owner"&&e.$$typeof)&&!xe(e[i],t[i]))return!1}return!0}return e!==e&&t!==t}function Et(e){return typeof window>"u"?1:(e.ownerDocument.defaultView||window).devicePixelRatio||1}function nt(e,t){const n=Et(e);return Math.round(t*n)/n}function Ae(e){const t=g.useRef(e);return me(()=>{t.current=e}),t}function In(e){e===void 0&&(e={});const{placement:t="bottom",strategy:n="absolute",middleware:o=[],platform:r,elements:{reference:i,floating:s}={},transform:c=!0,whileElementsMounted:u,open:f}=e,[d,a]=g.useState({x:0,y:0,strategy:n,placement:t,middlewareData:{},isPositioned:!1}),[m,l]=g.useState(o);xe(m,o)||l(o);const[p,h]=g.useState(null),[E,x]=g.useState(null),C=g.useCallback(w=>{w!==P.current&&(P.current=w,h(w))},[]),S=g.useCallback(w=>{w!==v.current&&(v.current=w,x(w))},[]),b=i||p,O=s||E,P=g.useRef(null),v=g.useRef(null),k=g.useRef(d),I=u!=null,$=Ae(u),A=Ae(r),M=Ae(f),R=g.useCallback(()=>{if(!P.current||!v.current)return;const w={placement:t,strategy:n,middleware:m};A.current&&(w.platform=A.current),kn(P.current,v.current,w).then(D=>{const N={...D,isPositioned:M.current!==!1};y.current&&!xe(k.current,N)&&(k.current=N,Mt.flushSync(()=>{a(N)}))})},[m,t,n,A,M]);me(()=>{f===!1&&k.current.isPositioned&&(k.current.isPositioned=!1,a(w=>({...w,isPositioned:!1})))},[f]);const y=g.useRef(!1);me(()=>(y.current=!0,()=>{y.current=!1}),[]),me(()=>{if(b&&(P.current=b),O&&(v.current=O),b&&O){if($.current)return $.current(b,O,R);R()}},[b,O,R,$,I]);const T=g.useMemo(()=>({reference:P,floating:v,setReference:C,setFloating:S}),[C,S]),L=g.useMemo(()=>({reference:b,floating:O}),[b,O]),F=g.useMemo(()=>{const w={position:n,left:0,top:0};if(!L.floating)return w;const D=nt(L.floating,d.x),N=nt(L.floating,d.y);return c?{...w,transform:"translate("+D+"px, "+N+"px)",...Et(L.floating)>=1.5&&{willChange:"transform"}}:{position:n,left:D,top:N}},[n,c,L.floating,d.x,d.y]);return g.useMemo(()=>({...d,update:R,refs:T,elements:L,floatingStyles:F}),[d,R,T,L,F])}const Nn=e=>{function t(n){return{}.hasOwnProperty.call(n,"current")}return{name:"arrow",options:e,fn(n){const{element:o,padding:r}=typeof e=="function"?e(n):e;return o&&t(o)?o.current!=null?tt({element:o.current,padding:r}).fn(n):{}:o?tt({element:o,padding:r}).fn(n):{}}}},_n=(e,t)=>{const n=Dn(e);return{name:n.name,fn:n.fn,options:[e,t]}},Wn=(e,t)=>{const n=Ln(e);return{name:n.name,fn:n.fn,options:[e,t]}},Bn=(e,t)=>{const n=Mn(e);return{name:n.name,fn:n.fn,options:[e,t]}},Vn=(e,t)=>{const n=Nn(e);return{name:n.name,fn:n.fn,options:[e,t]}};var q=typeof document<"u"?lt:Tt;function Ne(){return Ne=Object.assign?Object.assign.bind():function(e){for(var t=1;t<arguments.length;t++){var n=arguments[t];for(var o in n)Object.prototype.hasOwnProperty.call(n,o)&&(e[o]=n[o])}return e},Ne.apply(this,arguments)}let De=!1,Hn=0;const ot=()=>"floating-ui-"+Hn++;function Kn(){const[e,t]=g.useState(()=>De?ot():void 0);return q(()=>{e==null&&t(ot())},[]),g.useEffect(()=>{De||(De=!0)},[]),e}const jn=g.useId,je=jn||Kn,Xn=g.forwardRef(function(t,n){let{context:{placement:o,elements:{floating:r},middlewareData:{arrow:i}},width:s=14,height:c=7,tipRadius:u=0,strokeWidth:f=0,staticOffset:d,stroke:a,d:m,style:{transform:l,...p}={},...h}=t;process.env.NODE_ENV!=="production"&&(n||console.warn("Floating UI: The `ref` prop is required for the `FloatingArrow`","component."));const E=je();if(!r)return null;f*=2;const x=f/2,C=s/2*(u/-8+1),S=c/2*u/4,[b,O]=o.split("-"),P=Rt.isRTL(r),v=!!m,k=b==="top"||b==="bottom",I=d&&O==="end"?"bottom":"top";let $=d&&O==="end"?"right":"left";d&&P&&($=O==="end"?"left":"right");const A=i?.x!=null?d||i.x:"",M=i?.y!=null?d||i.y:"",R=m||"M0,0"+(" H"+s)+(" L"+(s-C)+","+(c-S))+(" Q"+s/2+","+c+" "+C+","+(c-S))+" Z",y={top:v?"rotate(180deg)":"",left:v?"rotate(90deg)":"rotate(-90deg)",bottom:v?"":"rotate(180deg)",right:v?"rotate(-90deg)":"rotate(90deg)"}[b];return g.createElement("svg",Ne({},h,{"aria-hidden":!0,ref:n,width:v?s:s+f,height:s,viewBox:"0 0 "+s+" "+(c>s?c:s),style:{position:"absolute",pointerEvents:"none",[$]:A,[I]:M,[b]:k||v?"100%":"calc(100% - "+f/2+"px)",transform:""+y+(l??""),...p}}),f>0&&g.createElement("path",{clipPath:"url(#"+E+")",fill:"none",stroke:a,strokeWidth:f+(m?0:1),d:R}),g.createElement("path",{stroke:f&&!m?h.fill:"none",d:R}),g.createElement("clipPath",{id:E},g.createElement("rect",{x:-x,y:x*(v?-1:1),width:s+f,height:s})))});function zn(){const e=new Map;return{emit(t,n){var o;(o=e.get(t))==null||o.forEach(r=>r(n))},on(t,n){e.set(t,[...e.get(t)||[],n])},off(t,n){var o;e.set(t,((o=e.get(t))==null?void 0:o.filter(r=>r!==n))||[])}}}const Yn=g.createContext(null),Un=g.createContext(null),Ct=()=>{var e;return((e=g.useContext(Yn))==null?void 0:e.id)||null},Xe=()=>g.useContext(Un);function ze(e){return"data-floating-ui-"+e}function rt(e){const t=ut(e);return q(()=>{t.current=e}),t}const it=ze("safe-polygon");function ge(e,t,n){return n&&!he(n)?0:typeof e=="number"?e:e?.[t]}function qn(e,t){t===void 0&&(t={});const{open:n,onOpenChange:o,dataRef:r,events:i,elements:{domReference:s,floating:c},refs:u}=e,{enabled:f=!0,delay:d=0,handleClose:a=null,mouseOnly:m=!1,restMs:l=0,move:p=!0}=t,h=Xe(),E=Ct(),x=rt(a),C=rt(d),S=g.useRef(),b=g.useRef(),O=g.useRef(),P=g.useRef(),v=g.useRef(!0),k=g.useRef(!1),I=g.useRef(()=>{}),$=g.useCallback(()=>{var y;const T=(y=r.current.openEvent)==null?void 0:y.type;return T?.includes("mouse")&&T!=="mousedown"},[r]);g.useEffect(()=>{if(!f)return;function y(){clearTimeout(b.current),clearTimeout(P.current),v.current=!0}return i.on("dismiss",y),()=>{i.off("dismiss",y)}},[f,i]),g.useEffect(()=>{if(!f||!x.current||!n)return;function y(L){$()&&o(!1,L)}const T=X(c).documentElement;return T.addEventListener("mouseleave",y),()=>{T.removeEventListener("mouseleave",y)}},[c,n,o,f,x,r,$]);const A=g.useCallback(function(y,T){T===void 0&&(T=!0);const L=ge(C.current,"close",S.current);L&&!O.current?(clearTimeout(b.current),b.current=setTimeout(()=>o(!1,y),L)):T&&(clearTimeout(b.current),o(!1,y))},[C,o]),M=g.useCallback(()=>{I.current(),O.current=void 0},[]),R=g.useCallback(()=>{if(k.current){const y=X(u.floating.current).body;y.style.pointerEvents="",y.removeAttribute(it),k.current=!1}},[u]);return g.useEffect(()=>{if(!f)return;function y(){return r.current.openEvent?["click","mousedown"].includes(r.current.openEvent.type):!1}function T(w){if(clearTimeout(b.current),v.current=!1,m&&!he(S.current)||l>0&&ge(C.current,"open")===0)return;const D=ge(C.current,"open",S.current);D?b.current=setTimeout(()=>{o(!0,w)},D):o(!0,w)}function L(w){if(y())return;I.current();const D=X(c);if(clearTimeout(P.current),x.current){n||clearTimeout(b.current),O.current=x.current({...e,tree:h,x:w.clientX,y:w.clientY,onClose(){R(),M(),A(w)}});const H=O.current;D.addEventListener("mousemove",H),I.current=()=>{D.removeEventListener("mousemove",H)};return}(S.current!=="touch"||!se(c,w.relatedTarget))&&A(w)}function F(w){y()||x.current==null||x.current({...e,tree:h,x:w.clientX,y:w.clientY,onClose(){R(),M(),A(w)}})(w)}if(_(s)){const w=s;return n&&w.addEventListener("mouseleave",F),c?.addEventListener("mouseleave",F),p&&w.addEventListener("mousemove",T,{once:!0}),w.addEventListener("mouseenter",T),w.addEventListener("mouseleave",L),()=>{n&&w.removeEventListener("mouseleave",F),c?.removeEventListener("mouseleave",F),p&&w.removeEventListener("mousemove",T),w.removeEventListener("mouseenter",T),w.removeEventListener("mouseleave",L)}}},[s,c,f,e,m,l,p,A,M,R,o,n,h,C,x,r]),q(()=>{var y;if(f&&n&&(y=x.current)!=null&&y.__options.blockPointerEvents&&$()){const F=X(c).body;if(F.setAttribute(it,""),F.style.pointerEvents="none",k.current=!0,_(s)&&c){var T,L;const w=s,D=h==null||(T=h.nodesRef.current.find(N=>N.id===E))==null||(L=T.context)==null?void 0:L.elements.floating;return D&&(D.style.pointerEvents=""),w.style.pointerEvents="auto",c.style.pointerEvents="auto",()=>{w.style.pointerEvents="",c.style.pointerEvents=""}}}},[f,n,E,c,s,h,x,r,$]),q(()=>{n||(S.current=void 0,M(),R())},[n,M,R]),g.useEffect(()=>()=>{M(),clearTimeout(b.current),clearTimeout(P.current),R()},[f,s,M,R]),g.useMemo(()=>{if(!f)return{};function y(T){S.current=T.pointerType}return{reference:{onPointerDown:y,onPointerEnter:y,onMouseMove(T){n||l===0||(clearTimeout(P.current),P.current=setTimeout(()=>{v.current||o(!0,T.nativeEvent)},l))}},floating:{onMouseEnter(){clearTimeout(b.current)},onMouseLeave(T){i.emit("dismiss",{type:"mouseLeave",data:{returnFocus:!1}}),A(T.nativeEvent,!1)}}}},[i,f,l,n,o,A])}const Gn=g.createContext({delay:0,initialDelay:0,timeoutMs:0,currentId:null,setCurrentId:()=>{},setState:()=>{},isInstantPhase:!1}),Pt=()=>g.useContext(Gn),Qn=(e,t)=>{let{open:n,onOpenChange:o}=e,{id:r}=t;const{currentId:i,setCurrentId:s,initialDelay:c,setState:u,timeoutMs:f}=Pt();q(()=>{i&&(u({delay:{open:1,close:ge(c,"close")}}),i!==r&&o(!1))},[r,o,u,i,c]),q(()=>{function d(){o(!1),u({delay:c,currentId:null})}if(!n&&i===r)if(f){const a=window.setTimeout(d,f);return()=>{clearTimeout(a)}}else d()},[n,u,i,r,o,c,f]),q(()=>{n&&s(r)},[n,s,r])};function Le(e,t){let n=e.filter(r=>{var i;return r.parentId===t&&((i=r.context)==null?void 0:i.open)}),o=n;for(;o.length;)o=e.filter(r=>{var i;return(i=o)==null?void 0:i.some(s=>{var c;return r.parentId===s.id&&((c=r.context)==null?void 0:c.open)})}),n=n.concat(o);return n}function st(e){return Re(e.target)&&e.target.tagName==="BUTTON"}function ct(e){return zt(e)}function Zn(e,t){t===void 0&&(t={});const{open:n,onOpenChange:o,dataRef:r,elements:{domReference:i}}=e,{enabled:s=!0,event:c="click",toggle:u=!0,ignoreMouse:f=!1,keyboardHandlers:d=!0}=t,a=g.useRef(),m=g.useRef(!1);return g.useMemo(()=>s?{reference:{onPointerDown(l){a.current=l.pointerType},onMouseDown(l){l.button===0&&(he(a.current,!0)&&f||c!=="click"&&(n&&u&&(!r.current.openEvent||r.current.openEvent.type==="mousedown")?o(!1,l.nativeEvent):(l.preventDefault(),o(!0,l.nativeEvent))))},onClick(l){if(c==="mousedown"&&a.current){a.current=void 0;return}he(a.current,!0)&&f||(n&&u&&(!r.current.openEvent||r.current.openEvent.type==="click")?o(!1,l.nativeEvent):o(!0,l.nativeEvent))},onKeyDown(l){a.current=void 0,!(l.defaultPrevented||!d||st(l))&&(l.key===" "&&!ct(i)&&(l.preventDefault(),m.current=!0),l.key==="Enter"&&o(!(n&&u),l.nativeEvent))},onKeyUp(l){l.defaultPrevented||!d||st(l)||ct(i)||l.key===" "&&m.current&&(m.current=!1,o(!(n&&u),l.nativeEvent))}}}:{},[s,r,c,f,d,i,u,n,o])}const Jn=g.useInsertionEffect,eo=Jn||(e=>e());function pe(e){const t=g.useRef(()=>{if(process.env.NODE_ENV!=="production")throw new Error("Cannot call an event handler while rendering.")});return eo(()=>{t.current=e}),g.useCallback(function(){for(var n=arguments.length,o=new Array(n),r=0;r<n;r++)o[r]=arguments[r];return t.current==null?void 0:t.current(...o)},[])}const to={pointerdown:"onPointerDown",mousedown:"onMouseDown",click:"onClick"},no={pointerdown:"onPointerDownCapture",mousedown:"onMouseDownCapture",click:"onClickCapture"},oo=e=>{var t,n;return{escapeKeyBubbles:typeof e=="boolean"?e:(t=e?.escapeKey)!=null?t:!1,outsidePressBubbles:typeof e=="boolean"?e:(n=e?.outsidePress)!=null?n:!0}};function ro(e,t){t===void 0&&(t={});const{open:n,onOpenChange:o,events:r,nodeId:i,elements:{reference:s,domReference:c,floating:u},dataRef:f}=e,{enabled:d=!0,escapeKey:a=!0,outsidePress:m=!0,outsidePressEvent:l="pointerdown",referencePress:p=!1,referencePressEvent:h="pointerdown",ancestorScroll:E=!1,bubbles:x}=t,C=Xe(),S=Ct()!=null,b=pe(typeof m=="function"?m:()=>!1),O=typeof m=="function"?b:m,P=g.useRef(!1),{escapeKeyBubbles:v,outsidePressBubbles:k}=oo(x),I=pe(A=>{if(!n||!d||!a||A.key!=="Escape")return;const M=C?Le(C.nodesRef.current,i):[];if(!v&&(A.stopPropagation(),M.length>0)){let R=!0;if(M.forEach(y=>{var T;if((T=y.context)!=null&&T.open&&!y.context.dataRef.current.__escapeKeyBubbles){R=!1;return}}),!R)return}r.emit("dismiss",{type:"escapeKey",data:{returnFocus:{preventScroll:!1}}}),o(!1,Ht(A)?A.nativeEvent:A)}),$=pe(A=>{const M=P.current;if(P.current=!1,M||typeof O=="function"&&!O(A))return;const R=jt(A),y="["+ze("inert")+"]",T=X(u).querySelectorAll(y);let L=_(R)?R:null;for(;L&&!Ft(L);){const D=It(L);if(D===X(u).body||!_(D))break;L=D}if(T.length&&_(R)&&!Kt(R)&&!se(R,u)&&Array.from(T).every(D=>!se(L,D)))return;if(Re(R)&&u){const D=R.clientWidth>0&&R.scrollWidth>R.clientWidth,N=R.clientHeight>0&&R.scrollHeight>R.clientHeight;let H=N&&A.offsetX>R.clientWidth;if(N&&$t(R).direction==="rtl"&&(H=A.offsetX<=R.offsetWidth-R.clientWidth),H||D&&A.offsetY>R.clientHeight)return}const F=C&&Le(C.nodesRef.current,i).some(D=>{var N;return de(A,(N=D.context)==null?void 0:N.elements.floating)});if(de(A,u)||de(A,c)||F)return;const w=C?Le(C.nodesRef.current,i):[];if(w.length>0){let D=!0;if(w.forEach(N=>{var H;if((H=N.context)!=null&&H.open&&!N.context.dataRef.current.__outsidePressBubbles){D=!1;return}}),!D)return}r.emit("dismiss",{type:"outsidePress",data:{returnFocus:S?{preventScroll:!0}:Bt(A)||Vt(A)}}),o(!1,A)});return g.useEffect(()=>{if(!n||!d)return;f.current.__escapeKeyBubbles=v,f.current.__outsidePressBubbles=k;function A(y){o(!1,y)}const M=X(u);a&&M.addEventListener("keydown",I),O&&M.addEventListener(l,$);let R=[];return E&&(_(c)&&(R=U(c)),_(u)&&(R=R.concat(U(u))),!_(s)&&s&&s.contextElement&&(R=R.concat(U(s.contextElement)))),R=R.filter(y=>{var T;return y!==((T=M.defaultView)==null?void 0:T.visualViewport)}),R.forEach(y=>{y.addEventListener("scroll",A,{passive:!0})}),()=>{a&&M.removeEventListener("keydown",I),O&&M.removeEventListener(l,$),R.forEach(y=>{y.removeEventListener("scroll",A)})}},[f,u,c,s,a,O,l,n,o,E,d,v,k,I,$]),g.useEffect(()=>{P.current=!1},[O,l]),g.useMemo(()=>d?{reference:{onKeyDown:I,[to[h]]:A=>{p&&(r.emit("dismiss",{type:"referencePress",data:{returnFocus:!1}}),o(!1,A.nativeEvent))}},floating:{onKeyDown:I,[no[l]]:()=>{P.current=!0}}}:{},[d,r,p,l,h,o,I])}let _e;process.env.NODE_ENV!=="production"&&(_e=new Set);function io(e){var t;e===void 0&&(e={});const{open:n=!1,onOpenChange:o,nodeId:r}=e;if(process.env.NODE_ENV!=="production"){var i;const v="Floating UI: Cannot pass a virtual element to the `elements.reference` option, as it must be a real DOM element. Use `refs.setPositionReference` instead.";if((i=e.elements)!=null&&i.reference&&!_(e.elements.reference)){var s;if(!((s=_e)!=null&&s.has(v))){var c;(c=_e)==null||c.add(v),console.error(v)}}}const[u,f]=g.useState(null),d=((t=e.elements)==null?void 0:t.reference)||u,a=In(e),m=Xe(),l=pe((v,k)=>{v&&(h.current.openEvent=k),o?.(v,k)}),p=g.useRef(null),h=g.useRef({}),E=g.useState(()=>zn())[0],x=je(),C=g.useCallback(v=>{const k=_(v)?{getBoundingClientRect:()=>v.getBoundingClientRect(),contextElement:v}:v;a.refs.setReference(k)},[a.refs]),S=g.useCallback(v=>{(_(v)||v===null)&&(p.current=v,f(v)),(_(a.refs.reference.current)||a.refs.reference.current===null||v!==null&&!_(v))&&a.refs.setReference(v)},[a.refs]),b=g.useMemo(()=>({...a.refs,setReference:S,setPositionReference:C,domReference:p}),[a.refs,S,C]),O=g.useMemo(()=>({...a.elements,domReference:d}),[a.elements,d]),P=g.useMemo(()=>({...a,refs:b,elements:O,dataRef:h,nodeId:r,floatingId:x,events:E,open:n,onOpenChange:l}),[a,r,x,E,n,l,b,O]);return q(()=>{const v=m?.nodesRef.current.find(k=>k.id===r);v&&(v.context=P)}),g.useMemo(()=>({...a,context:P,refs:b,elements:O}),[a,b,O,P])}function so(e,t){t===void 0&&(t={});const{open:n,onOpenChange:o,dataRef:r,events:i,refs:s,elements:{floating:c,domReference:u}}=e,{enabled:f=!0,keyboardOnly:d=!0}=t,a=g.useRef(""),m=g.useRef(!1),l=g.useRef();return g.useEffect(()=>{if(!f)return;const h=X(c).defaultView||window;function E(){!n&&Re(u)&&u===Nt(X(u))&&(m.current=!0)}return h.addEventListener("blur",E),()=>{h.removeEventListener("blur",E)}},[c,u,n,f]),g.useEffect(()=>{if(!f)return;function p(h){(h.type==="referencePress"||h.type==="escapeKey")&&(m.current=!0)}return i.on("dismiss",p),()=>{i.off("dismiss",p)}},[i,f]),g.useEffect(()=>()=>{clearTimeout(l.current)},[]),g.useMemo(()=>f?{reference:{onPointerDown(p){let{pointerType:h}=p;a.current=h,m.current=!!(h&&d)},onMouseLeave(){m.current=!1},onFocus(p){var h;m.current||p.type==="focus"&&((h=r.current.openEvent)==null?void 0:h.type)==="mousedown"&&de(r.current.openEvent,u)||o(!0,p.nativeEvent)},onBlur(p){m.current=!1;const h=p.relatedTarget,E=_(h)&&h.hasAttribute(ze("focus-guard"))&&h.getAttribute("data-type")==="outside";l.current=setTimeout(()=>{se(s.floating.current,h)||se(u,h)||E||o(!1,p.nativeEvent)})}}}:{},[f,d,u,s,r,o])}function Me(e,t,n){const o=new Map;return{...n==="floating"&&{tabIndex:-1},...e,...t.map(r=>r?r[n]:null).concat(e).reduce((r,i)=>(i&&Object.entries(i).forEach(s=>{let[c,u]=s;if(c.indexOf("on")===0){if(o.has(c)||o.set(c,[]),typeof u=="function"){var f;(f=o.get(c))==null||f.push(u),r[c]=function(){for(var d,a=arguments.length,m=new Array(a),l=0;l<a;l++)m[l]=arguments[l];return(d=o.get(c))==null?void 0:d.map(p=>p(...m)).find(p=>p!==void 0)}}}else r[c]=u}),r),{})}}function co(e){e===void 0&&(e=[]);const t=e,n=g.useCallback(i=>Me(i,e,"reference"),t),o=g.useCallback(i=>Me(i,e,"floating"),t),r=g.useCallback(i=>Me(i,e,"item"),e.map(i=>i?.item));return g.useMemo(()=>({getReferenceProps:n,getFloatingProps:o,getItemProps:r}),[n,o,r])}function lo(e,t){t===void 0&&(t={});const{open:n,floatingId:o}=e,{enabled:r=!0,role:i="dialog"}=t,s=je();return g.useMemo(()=>{const c={id:o,role:i};return r?i==="tooltip"?{reference:{"aria-describedby":n?o:void 0},floating:c}:{reference:{"aria-expanded":n?"true":"false","aria-haspopup":i==="alertdialog"?"dialog":i,"aria-controls":n?o:void 0,...i==="listbox"&&{role:"combobox"},...i==="menu"&&{id:s}},floating:{...c,...i==="menu"&&{"aria-labelledby":s}}}:{}},[r,i,n,o,s])}function mo({closeDelay:e=300,offset:t=20,openDelay:n=0,placement:o="bottom-start",slots:r,trigger:i=["hover","focus"],withArrow:s=!0,arrow:c,role:u="dialog",visible:f={},hidden:d={},floatingOptions:a={},isOpen:m,onOpenChange:l}){const[p,h]=St(!1),E=ut(null),x=At(),{x:C,y:S,strategy:b,refs:O,context:P}=io({placement:o,middleware:[_n(t),Bn(),Wn(),Vn({element:E})],open:m||p,onOpenChange:l||h,whileElementsMounted:An,...a}),v=ro(P),k=lo(P,{role:u}),{delay:I}=Pt(),A=qn(P,{delay:I||{open:n,close:e}}),M=so(P),R=Zn(P),y=[i.find(te=>te==="hover")?A:void 0,i.find(te=>te==="click")?R:void 0,i.find(te=>te==="focus")?M:void 0,v,k],{getReferenceProps:T,getFloatingProps:L}=co(y);Qn(P,{id:x});const{onClick:F,...w}=T(),D=String((r?.content?.props).className).includes("pressable")?{onPress:F}:{onClick:F},N=r?.content?Dt(r.content,{...r.content.props,ref:O.setReference,...w,...D}):Oe("div",{ref:O.setReference,...T(),children:"Menu Action"}),H=r?.submenu?Ye(Lt.nav,{ref:O.setFloating,style:{position:b,top:S??0,left:C??0,width:"max-content",zIndex:50},...L(),variants:{hidden:d,visible:f},initial:"hidden",animate:m||p?"visible":"hidden",children:[s&&Oe(Xn,{ref:E,context:P,...c}),r.submenu]}):Oe("nav",{children:"Submenu"});return Ye(Ot,{children:[N,H]})}export{mo as Menu,mo as default};
|
|
1
|
+
"use client";import{jsxs as Be,jsx as oe,Fragment as $t}from"react/jsx-runtime";import*as v from"react";import{useLayoutEffect as vt,useState as Nt,useRef as Wt,useId as Vt,cloneElement as Bt}from"react";import{motion as Ht}from"framer-motion";import*as Kt from"react-dom";function Te(){return typeof window<"u"}function ae(e){return wt(e)?(e.nodeName||"").toLowerCase():"#document"}function K(e){var t;return(e==null||(t=e.ownerDocument)==null?void 0:t.defaultView)||window}function J(e){var t;return(t=(wt(e)?e.ownerDocument:e.document)||window.document)==null?void 0:t.documentElement}function wt(e){return Te()?e instanceof Node||e instanceof K(e).Node:!1}function N(e){return Te()?e instanceof Element||e instanceof K(e).Element:!1}function X(e){return Te()?e instanceof HTMLElement||e instanceof K(e).HTMLElement:!1}function He(e){return!Te()||typeof ShadowRoot>"u"?!1:e instanceof ShadowRoot||e instanceof K(e).ShadowRoot}function Me(e){const{overflow:t,overflowX:n,overflowY:o,display:r}=j(e);return/auto|scroll|overlay|hidden|clip/.test(t+o+n)&&r!=="inline"&&r!=="contents"}function Xt(e){return/^(table|td|th)$/.test(ae(e))}function Se(e){try{if(e.matches(":popover-open"))return!0}catch{}try{return e.matches(":modal")}catch{return!1}}const Ut=/transform|translate|scale|rotate|perspective|filter/,jt=/paint|layout|strict|content/,ne=e=>!!e&&e!=="none";let Ie;function je(e){const t=N(e)?j(e):e;return ne(t.transform)||ne(t.translate)||ne(t.scale)||ne(t.rotate)||ne(t.perspective)||!Le()&&(ne(t.backdropFilter)||ne(t.filter))||Ut.test(t.willChange||"")||jt.test(t.contain||"")}function Yt(e){let t=te(e);for(;X(t)&&!Z(t);){if(je(t))return t;if(Se(t))return null;t=te(t)}return null}function Le(){return Ie==null&&(Ie=typeof CSS<"u"&&CSS.supports&&CSS.supports("-webkit-backdrop-filter","none")),Ie}function Z(e){return/^(html|body|#document)$/.test(ae(e))}function j(e){return K(e).getComputedStyle(e)}function Ae(e){return N(e)?{scrollLeft:e.scrollLeft,scrollTop:e.scrollTop}:{scrollLeft:e.scrollX,scrollTop:e.scrollY}}function te(e){if(ae(e)==="html")return e;const t=e.assignedSlot||e.parentNode||He(e)&&e.host||J(e);return He(t)?t.host:t}function yt(e){const t=te(e);return Z(t)?(e.ownerDocument||e).body:X(t)&&Me(t)?t:yt(t)}function ee(e,t,n){var o;t===void 0&&(t=[]),n===void 0&&(n=!0);const r=yt(e),s=r===((o=e.ownerDocument)==null?void 0:o.body),i=K(r);if(s){const c=Ke(i);return t.concat(i,i.visualViewport||[],Me(r)?r:[],c&&n?ee(c):[])}else return t.concat(r,ee(r,[],n))}function Ke(e){return e.parent&&Object.getPrototypeOf(e.parent)?e.frameElement:null}const ue=Math.min,ie=Math.max,Ee=Math.round,we=Math.floor,G=e=>({x:e,y:e}),zt={left:"right",right:"left",bottom:"top",top:"bottom"};function Rt(e,t,n){return ie(e,ue(t,n))}function he(e,t){return typeof e=="function"?e(t):e}function fe(e){return e.split("-")[0]}function ve(e){return e.split("-")[1]}function xt(e){return e==="x"?"y":"x"}function Ye(e){return e==="y"?"height":"width"}function Q(e){const t=e[0];return t==="t"||t==="b"?"y":"x"}function ze(e){return xt(Q(e))}function qt(e,t,n){n===void 0&&(n=!1);const o=ve(e),r=ze(e),s=Ye(r);let i=r==="x"?o===(n?"end":"start")?"right":"left":o==="start"?"bottom":"top";return t.reference[s]>t.floating[s]&&(i=Ce(i)),[i,Ce(i)]}function Gt(e){const t=Ce(e);return[Xe(e),t,Xe(t)]}function Xe(e){return e.includes("start")?e.replace("start","end"):e.replace("end","start")}const et=["left","right"],tt=["right","left"],Jt=["top","bottom"],Qt=["bottom","top"];function Zt(e,t,n){switch(e){case"top":case"bottom":return n?t?tt:et:t?et:tt;case"left":case"right":return t?Jt:Qt;default:return[]}}function en(e,t,n,o){const r=ve(e);let s=Zt(fe(e),n==="start",o);return r&&(s=s.map(i=>i+"-"+r),t&&(s=s.concat(s.map(Xe)))),s}function Ce(e){const t=fe(e);return zt[t]+e.slice(t.length)}function tn(e){var t,n,o,r;return{top:(t=e.top)!=null?t:0,right:(n=e.right)!=null?n:0,bottom:(o=e.bottom)!=null?o:0,left:(r=e.left)!=null?r:0}}function bt(e){return typeof e!="number"?tn(e):{top:e,right:e,bottom:e,left:e}}function Oe(e){const{x:t,y:n,width:o,height:r}=e;return{width:o,height:r,top:n,left:t,right:t+o,bottom:n+r,x:t,y:n}}function nn(){const e=navigator.userAgentData;return e!=null&&e.platform?e.platform:navigator.platform}function on(){const e=navigator.userAgentData;return e&&Array.isArray(e.brands)?e.brands.map(t=>{let{brand:n,version:o}=t;return n+"/"+o}).join(" "):navigator.userAgent}function rn(){return/apple/i.test(navigator.vendor)}function sn(){return nn().toLowerCase().startsWith("mac")&&!navigator.maxTouchPoints}function cn(){return on().includes("jsdom/")}const nt="data-floating-ui-focusable",ln="input:not([type='hidden']):not([disabled]),[contenteditable]:not([contenteditable='false']),textarea:not([disabled])";function ot(e){let t=e.activeElement;for(;((n=t)==null||(n=n.shadowRoot)==null?void 0:n.activeElement)!=null;){var n;t=t.shadowRoot.activeElement}return t}function me(e,t){if(!e||!t)return!1;const n=t.getRootNode==null?void 0:t.getRootNode();if(e.contains(t))return!0;if(n&&He(n)){let o=t;for(;o;){if(e===o)return!0;o=o.parentNode||o.host}}return!1}function ce(e){return"composedPath"in e?e.composedPath()[0]:e.target}function Fe(e,t){if(t==null)return!1;if("composedPath"in e)return e.composedPath().includes(t);const n=e;return n.target!=null&&t.contains(n.target)}function un(e){return e.matches("html,body")}function re(e){return e?.ownerDocument||document}function Et(e){return X(e)&&e.matches(ln)}function fn(e){if(!e||cn())return!0;try{return e.matches(":focus-visible")}catch{return!0}}function an(e){return e?e.hasAttribute(nt)?e:e.querySelector("["+nt+"]")||e:null}function Re(e,t,n){return n===void 0&&(n=!0),e.filter(r=>{var s;return r.parentId===t&&(!n||((s=r.context)==null?void 0:s.open))}).flatMap(r=>[r,...Re(e,r.id,n)])}function dn(e){return"nativeEvent"in e}function ge(e,t){const n=["mouse","pen"];return t||n.push("",void 0),n.includes(e)}var mn=typeof document<"u",gn=function(){},z=mn?vt:gn;const pn={...v};function ye(e){const t=v.useRef(e);return z(()=>{t.current=e}),t}const hn=pn.useInsertionEffect,vn=hn||(e=>e());function Y(e){const t=v.useRef(()=>{if(process.env.NODE_ENV!=="production")throw new Error("Cannot call an event handler while rendering.")});return vn(()=>{t.current=e}),v.useCallback(function(){for(var n=arguments.length,o=new Array(n),r=0;r<n;r++)o[r]=arguments[r];return t.current==null?void 0:t.current(...o)},[])}function rt(e,t,n){let{reference:o,floating:r}=e;const s=Q(t),i=ze(t),c=Ye(i),u=fe(t),f=s==="y",g=o.x+o.width/2-r.width/2,m=o.y+o.height/2-r.height/2,d=o[c]/2-r[c]/2;let l;switch(u){case"top":l={x:g,y:o.y-r.height};break;case"bottom":l={x:g,y:o.y+o.height};break;case"right":l={x:o.x+o.width,y:m};break;case"left":l={x:o.x-r.width,y:m};break;default:l={x:o.x,y:o.y}}const p=ve(t);return p&&(l[i]+=d*(p==="end"?1:-1)*(n&&f?-1:1)),l}async function wn(e,t){var n;t===void 0&&(t={});const{x:o,y:r,platform:s,rects:i,elements:c,strategy:u}=e,{boundary:f="clippingAncestors",rootBoundary:g="viewport",elementContext:m="floating",altBoundary:d=!1,padding:l=0}=he(t,e),p=bt(l),y=c[d?m==="floating"?"reference":"floating":m],w=Oe(await s.getClippingRect({element:(n=await(s.isElement==null?void 0:s.isElement(y)))==null||n?y:y.contextElement||await(s.getDocumentElement==null?void 0:s.getDocumentElement(c.floating)),boundary:f,rootBoundary:g,strategy:u})),x=m==="floating"?{x:o,y:r,width:i.floating.width,height:i.floating.height}:i.reference,T=await(s.getOffsetParent==null?void 0:s.getOffsetParent(c.floating)),E=await(s.isElement==null?void 0:s.isElement(T))&&await(s.getScale==null?void 0:s.getScale(T))||{x:1,y:1},M=Oe(s.convertOffsetParentRelativeRectToViewportRelativeRect?await s.convertOffsetParentRelativeRectToViewportRelativeRect({elements:c,rect:x,offsetParent:T,strategy:u}):x);return{top:(w.top-M.top+p.top)/E.y,bottom:(M.bottom-w.bottom+p.bottom)/E.y,left:(w.left-M.left+p.left)/E.x,right:(M.right-w.right+p.right)/E.x}}const yn=50,Rn=async(e,t,n)=>{const{placement:o="bottom",strategy:r="absolute",middleware:s=[],platform:i}=n,c=i.detectOverflow?i:{...i,detectOverflow:wn},u=await(i.isRTL==null?void 0:i.isRTL(t));let f=await i.getElementRects({reference:e,floating:t,strategy:r}),{x:g,y:m}=rt(f,o,u),d=o,l=0;const p={};for(let a=0;a<s.length;a++){const y=s[a];if(!y)continue;const{name:w,fn:x}=y,{x:T,y:E,data:M,reset:C}=await x({x:g,y:m,initialPlacement:o,placement:d,strategy:r,middlewareData:p,rects:f,platform:c,elements:{reference:e,floating:t}});g=T??g,m=E??m,p[w]={...p[w],...M},C&&l<yn&&(l++,typeof C=="object"&&(C.placement&&(d=C.placement),C.rects&&(f=C.rects===!0?await i.getElementRects({reference:e,floating:t,strategy:r}):C.rects),{x:g,y:m}=rt(f,d,u)),a=-1)}return{x:g,y:m,placement:d,strategy:r,middlewareData:p}},xn=e=>({name:"arrow",options:e,async fn(t){const{x:n,y:o,placement:r,rects:s,platform:i,elements:c,middlewareData:u}=t,{element:f,padding:g=0}=he(e,t)||{};if(f==null)return{};const m=bt(g),d={x:n,y:o},l=ze(r),p=Ye(l),a=await i.getDimensions(f),y=l==="y",w=y?"top":"left",x=y?"bottom":"right",T=y?"clientHeight":"clientWidth",E=s.reference[p]+s.reference[l]-d[l]-s.floating[p],M=d[l]-s.reference[l],C=await(i.getOffsetParent==null?void 0:i.getOffsetParent(f));let P=C?C[T]:0;(!P||!await(i.isElement==null?void 0:i.isElement(C)))&&(P=c.floating[T]||s.floating[p]);const S=E/2-M/2,$=P/2-a[p]/2-1,I=ue(m[w],$),W=ue(m[x],$),_=P-a[p]-W,F=P/2-a[p]/2+S,R=Rt(I,F,_),L=!u.arrow&&ve(r)!=null&&F!==R&&s.reference[p]/2-(F<I?I:W)-a[p]/2<0,A=L?F<I?F-I:F-_:0;return{[l]:d[l]+A,data:{[l]:R,centerOffset:F-R-A,...L&&{alignmentOffset:A}},reset:L}}}),bn=function(e){return e===void 0&&(e={}),{name:"flip",options:e,async fn(t){var n,o;const{placement:r,middlewareData:s,rects:i,initialPlacement:c,platform:u,elements:f}=t,{mainAxis:g=!0,crossAxis:m=!0,fallbackPlacements:d,fallbackStrategy:l="bestFit",fallbackAxisSideDirection:p="none",flipAlignment:a=!0,...y}=he(e,t);if((n=s.arrow)!=null&&n.alignmentOffset)return{};const w=fe(r),x=Q(c),T=fe(c)===c,E=await(u.isRTL==null?void 0:u.isRTL(f.floating)),M=d||(T||!a?[Ce(c)]:Gt(c)),C=p!=="none";!d&&C&&M.push(...en(c,a,p,E));const P=[c,...M],S=await u.detectOverflow(t,y),$=[];let I=((o=s.flip)==null?void 0:o.overflows)||[];if(g&&$.push(S[w]),m){const R=qt(r,i,E);$.push(S[R[0]],S[R[1]])}if(I=[...I,{placement:r,overflows:$}],!$.every(R=>R<=0)){var W,_;const R=(((W=s.flip)==null?void 0:W.index)||0)+1,L=P[R];if(L&&(!(m==="alignment"?x!==Q(L):!1)||I.every(h=>Q(h.placement)===x?h.overflows[0]>0:!0)))return{data:{index:R,overflows:I},reset:{placement:L}};let A=(_=I.filter(b=>b.overflows[0]<=0).sort((b,h)=>b.overflows[1]-h.overflows[1])[0])==null?void 0:_.placement;if(!A)switch(l){case"bestFit":{var F;const b=(F=I.filter(h=>{if(C){const O=Q(h.placement);return O===x||O==="y"}return!0}).map(h=>[h.placement,h.overflows.filter(O=>O>0).reduce((O,D)=>O+D,0)]).sort((h,O)=>h[1]-O[1])[0])==null?void 0:F[0];b&&(A=b);break}case"initialPlacement":A=c;break}if(r!==A)return{reset:{placement:A}}}return{}}}},En=new Set(["left","top"]);async function Cn(e,t){const{placement:n,platform:o,elements:r}=e,s=await(o.isRTL==null?void 0:o.isRTL(r.floating)),i=fe(n),c=ve(n),u=Q(n)==="y",f=En.has(i)?-1:1,g=s&&u?-1:1,m=he(t,e);let{mainAxis:d,crossAxis:l,alignmentAxis:p}=typeof m=="number"?{mainAxis:m,crossAxis:0,alignmentAxis:null}:{mainAxis:m.mainAxis||0,crossAxis:m.crossAxis||0,alignmentAxis:m.alignmentAxis};return c&&typeof p=="number"&&(l=c==="end"?p*-1:p),u?{x:l*g,y:d*f}:{x:d*f,y:l*g}}const On=function(e){return e===void 0&&(e=0),{name:"offset",options:e,async fn(t){var n,o;const{x:r,y:s,placement:i,middlewareData:c}=t,u=await Cn(t,e);return i===((n=c.offset)==null?void 0:n.placement)&&(o=c.arrow)!=null&&o.alignmentOffset?{}:{x:r+u.x,y:s+u.y,data:{...u,placement:i}}}}},Pn=function(e){return e===void 0&&(e={}),{name:"shift",options:e,async fn(t){const{x:n,y:o,placement:r,platform:s}=t,{mainAxis:i=!0,crossAxis:c=!1,limiter:u={fn:x=>{let{x:T,y:E}=x;return{x:T,y:E}}},...f}=he(e,t),g={x:n,y:o},m=await s.detectOverflow(t,f),d=Q(r),l=xt(d);let p=g[l],a=g[d];const y=(x,T)=>Rt(T+m[x==="y"?"top":"left"],T,T-m[x==="y"?"bottom":"right"]);i&&(p=y(l,p)),c&&(a=y(d,a));const w=u.fn({...t,[l]:p,[d]:a});return{...w,data:{x:w.x-n,y:w.y-o,enabled:{[l]:i,[d]:c}}}}}};function Ct(e){const t=j(e);let n=parseFloat(t.width)||0,o=parseFloat(t.height)||0;const r=X(e),s=r?e.offsetWidth:n,i=r?e.offsetHeight:o,c=Ee(n)!==s||Ee(o)!==i;return c&&(n=s,o=i),{width:n,height:o,$:c}}function qe(e){return N(e)?e:e.contextElement}function le(e){const t=qe(e);if(!X(t))return G(1);const n=t.getBoundingClientRect(),{width:o,height:r,$:s}=Ct(t);let i=(s?Ee(n.width):n.width)/o,c=(s?Ee(n.height):n.height)/r;return(!i||!Number.isFinite(i))&&(i=1),(!c||!Number.isFinite(c))&&(c=1),{x:i,y:c}}const Tn=G(0);function Ot(e){const t=K(e);return!Le()||!t.visualViewport?Tn:{x:t.visualViewport.offsetLeft,y:t.visualViewport.offsetTop}}function Mn(e,t,n){return t===void 0&&(t=!1),!!n&&t&&n===K(e)}function se(e,t,n,o){t===void 0&&(t=!1),n===void 0&&(n=!1);const r=e.getBoundingClientRect(),s=qe(e);let i=G(1);t&&(o?N(o)&&(i=le(o)):i=le(e));const c=Mn(s,n,o)?Ot(s):G(0);let u=(r.left+c.x)/i.x,f=(r.top+c.y)/i.y,g=r.width/i.x,m=r.height/i.y;if(s&&o){const d=K(s),l=N(o)?K(o):o;let p=d,a=Ke(p);for(;a&&l!==p;){const y=le(a),w=a.getBoundingClientRect(),x=j(a),T=w.left+(a.clientLeft+parseFloat(x.paddingLeft))*y.x,E=w.top+(a.clientTop+parseFloat(x.paddingTop))*y.y;u*=y.x,f*=y.y,g*=y.x,m*=y.y,u+=T,f+=E,p=K(a),a=Ke(p)}}return Oe({width:g,height:m,x:u,y:f})}function De(e,t){const n=Ae(e).scrollLeft;return t?t.left+n:se(J(e)).left+n}function Pt(e,t){const n=e.getBoundingClientRect(),o=n.left+t.scrollLeft-De(e,n),r=n.top+t.scrollTop;return{x:o,y:r}}function Sn(e){let{elements:t,rect:n,offsetParent:o,strategy:r}=e;const s=r==="fixed",i=J(o),c=t?Se(t.floating):!1;if(o===i||c&&s)return n;let u={scrollLeft:0,scrollTop:0},f=G(1);const g=G(0),m=X(o);if((m||!s)&&((ae(o)!=="body"||Me(i))&&(u=Ae(o)),m)){const l=se(o);f=le(o),g.x=l.x+o.clientLeft,g.y=l.y+o.clientTop}const d=i&&!m&&!s?Pt(i,u):G(0);return{width:n.width*f.x,height:n.height*f.y,x:n.x*f.x-u.scrollLeft*f.x+g.x+d.x,y:n.y*f.y-u.scrollTop*f.y+g.y+d.y}}function Ln(e){return e.getClientRects?Array.from(e.getClientRects()):[]}function An(e){const t=Ae(e),n=e.ownerDocument.body,o=ie(e.scrollWidth,e.clientWidth,n.scrollWidth,n.clientWidth),r=ie(e.scrollHeight,e.clientHeight,n.scrollHeight,n.clientHeight);let s=-t.scrollLeft+De(e);const i=-t.scrollTop;return j(n).direction==="rtl"&&(s+=ie(e.clientWidth,n.clientWidth)-o),{width:o,height:r,x:s,y:i}}const Dn=25;function kn(e,t,n){n===void 0&&(n="viewport");const o=n==="layoutViewport",r=K(e),s=J(e),i=r.visualViewport;let c=s.clientWidth,u=s.clientHeight,f=0,g=0;if(i){const d=!Le()||t==="fixed";o?d||(f=-i.offsetLeft,g=-i.offsetTop):(c=i.width,u=i.height,d&&(f=i.offsetLeft,g=i.offsetTop))}if(De(s)<=0){const d=s.ownerDocument,l=d.body,p=getComputedStyle(l),a=d.compatMode==="CSS1Compat"&&parseFloat(p.marginLeft)+parseFloat(p.marginRight)||0,y=Math.abs(s.clientWidth-l.clientWidth-a),w=getComputedStyle(s).scrollbarGutter==="stable both-edges"?y/2:y;w<=Dn&&(c-=w)}return{width:c,height:u,x:f,y:g}}function In(e,t){const n=se(e,!0,t==="fixed"),o=n.top+e.clientTop,r=n.left+e.clientLeft,s=le(e),i=e.clientWidth*s.x,c=e.clientHeight*s.y,u=r*s.x,f=o*s.y;return{width:i,height:c,x:u,y:f}}function it(e,t,n){let o;if(t==="viewport"||t==="layoutViewport")o=kn(e,n,t);else if(t==="document")o=An(J(e));else if(N(t))o=In(t,n);else{const r=Ot(e);o={x:t.x-r.x,y:t.y-r.y,width:t.width,height:t.height}}return Oe(o)}function Fn(e,t){const n=t.get(e);if(n)return n;let o=ee(e,[],!1).filter(c=>N(c)&&ae(c)!=="body"),r=null;const s=j(e).position==="fixed";let i=s?te(e):e;for(;N(i)&&!Z(i);){const c=j(i),u=je(i),f=r?r.position:s?"fixed":"";!u&&(f==="fixed"||f==="absolute"&&c.position==="static")?o=o.filter(m=>m!==i):r=c,i=te(i)}return t.set(e,o),o}function _n(e){let{element:t,boundary:n,rootBoundary:o,strategy:r}=e;const i=[...n==="clippingAncestors"?Se(t)?[]:Fn(t,this._c):[].concat(n),o],c=it(t,i[0],r);let u=c.top,f=c.right,g=c.bottom,m=c.left;for(let d=1;d<i.length;d++){const l=it(t,i[d],r);u=ie(l.top,u),f=ue(l.right,f),g=ue(l.bottom,g),m=ie(l.left,m)}return{width:f-m,height:g-u,x:m,y:u}}function $n(e){const{width:t,height:n}=Ct(e);return{width:t,height:n}}function Nn(e,t,n){const o=X(t),r=J(t),s=n==="fixed",i=se(e,!0,s,t);let c={scrollLeft:0,scrollTop:0};const u=G(0);if((o||!s)&&((ae(t)!=="body"||Me(r))&&(c=Ae(t)),o)){const d=se(t,!0,s,t);u.x=d.x+t.clientLeft,u.y=d.y+t.clientTop}!o&&r&&(u.x=De(r));const f=r&&!o&&!s?Pt(r,c):G(0),g=i.left+c.scrollLeft-u.x-f.x,m=i.top+c.scrollTop-u.y-f.y;return{x:g,y:m,width:i.width,height:i.height}}function _e(e){return j(e).position==="static"}function st(e,t){if(!X(e)||j(e).position==="fixed")return null;if(t)return t(e);let n=e.offsetParent;return J(e)===n&&(n=n.ownerDocument.body),n}function Tt(e,t){const n=K(e);if(Se(e))return n;if(!X(e)){let r=te(e);for(;r&&!Z(r);){if(N(r)&&!_e(r))return r;r=te(r)}return n}let o=st(e,t);for(;o&&Xt(o)&&_e(o);)o=st(o,t);return o&&Z(o)&&_e(o)&&!je(o)?n:o||Yt(e)||n}const Wn=async function(e){const t=this.getOffsetParent||Tt,n=this.getDimensions,o=await n(e.floating);return{reference:Nn(e.reference,await t(e.floating),e.strategy),floating:{x:0,y:0,width:o.width,height:o.height}}};function Vn(e){return j(e).direction==="rtl"}const Bn={convertOffsetParentRelativeRectToViewportRelativeRect:Sn,getDocumentElement:J,getClippingRect:_n,getOffsetParent:Tt,getElementRects:Wn,getClientRects:Ln,getDimensions:$n,getScale:le,isElement:N,isRTL:Vn};function Mt(e,t){return e.x===t.x&&e.y===t.y&&e.width===t.width&&e.height===t.height}function Hn(e,t,n){let o=null,r;const s=J(e);function i(){var g;clearTimeout(r),(g=o)==null||g.disconnect(),o=null}function c(g,m){g===void 0&&(g=!1),m===void 0&&(m=1),i();const d=e.getBoundingClientRect(),{left:l,top:p,width:a,height:y}=d;if(g||t(),!a||!y)return;const w=we(p),x=we(s.clientWidth-(l+a)),T=we(s.clientHeight-(p+y)),E=we(l),C={rootMargin:-w+"px "+-x+"px "+-T+"px "+-E+"px",threshold:ie(0,ue(1,m))||1};let P=!0;function S($){const I=$[0].intersectionRatio;if(!Mt(d,e.getBoundingClientRect()))return c();if(I!==m){if(!P)return c();I?c(!1,I):r=setTimeout(()=>{c(!1,1e-7)},1e3)}P=!1}try{o=new IntersectionObserver(S,{...C,root:s.ownerDocument})}catch{o=new IntersectionObserver(S,C)}o.observe(e)}const u=K(e),f=()=>c(n);return u.addEventListener("resize",f),c(!0),()=>{u.removeEventListener("resize",f),i()}}function Kn(e,t,n,o){o===void 0&&(o={});const{ancestorScroll:r=!0,ancestorResize:s=!0,elementResize:i=typeof ResizeObserver=="function",layoutShift:c=typeof IntersectionObserver=="function",animationFrame:u=!1}=o,f=qe(e),g=r||s?[...f?ee(f):[],...t?ee(t):[]]:[];g.forEach(w=>{r&&w.addEventListener("scroll",n),s&&w.addEventListener("resize",n)});const m=f&&c?Hn(f,n,s):null;let d=-1,l=null;i&&(l=new ResizeObserver(w=>{let[x]=w;x&&x.target===f&&l&&t&&(l.unobserve(t),cancelAnimationFrame(d),d=requestAnimationFrame(()=>{var T;(T=l)==null||T.observe(t)})),n()}),f&&!u&&l.observe(f),t&&l.observe(t));let p,a=u?se(e):null;u&&y();function y(){const w=se(e);a&&!Mt(a,w)&&n(),a=w,p=requestAnimationFrame(y)}return n(),()=>{var w;g.forEach(x=>{r&&x.removeEventListener("scroll",n),s&&x.removeEventListener("resize",n)}),m?.(),(w=l)==null||w.disconnect(),l=null,u&&cancelAnimationFrame(p)}}const Xn=On,Un=Pn,jn=bn,ct=xn,Yn=(e,t,n)=>{const o=new Map,r=n??{},s={...Bn,...r.platform,_c:o};return Rn(e,t,{...r,platform:s})};var zn=typeof document<"u",qn=function(){},xe=zn?vt:qn;function Pe(e,t){if(e===t)return!0;if(typeof e!=typeof t)return!1;if(typeof e=="function"&&e.toString()===t.toString())return!0;let n,o,r;if(e&&t&&typeof e=="object"){if(Array.isArray(e)){if(n=e.length,n!==t.length)return!1;for(o=n;o--!==0;)if(!Pe(e[o],t[o]))return!1;return!0}if(r=Object.keys(e),n=r.length,n!==Object.keys(t).length)return!1;for(o=n;o--!==0;)if(!{}.hasOwnProperty.call(t,r[o]))return!1;for(o=n;o--!==0;){const s=r[o];if(!(s==="_owner"&&e.$$typeof)&&!Pe(e[s],t[s]))return!1}return!0}return e!==e&&t!==t}function St(e){return typeof window>"u"?1:(e.ownerDocument.defaultView||window).devicePixelRatio||1}function lt(e,t){const n=St(e);return Math.round(t*n)/n}function $e(e){const t=v.useRef(e);return xe(()=>{t.current=e}),t}function Gn(e){e===void 0&&(e={});const{placement:t="bottom",strategy:n="absolute",middleware:o=[],platform:r,elements:{reference:s,floating:i}={},transform:c=!0,whileElementsMounted:u,open:f}=e,[g,m]=v.useState({x:0,y:0,strategy:n,placement:t,middlewareData:{},isPositioned:!1}),[d,l]=v.useState(o);Pe(d,o)||l(o);const[p,a]=v.useState(null),[y,w]=v.useState(null),x=v.useCallback(h=>{h!==C.current&&(C.current=h,a(h))},[]),T=v.useCallback(h=>{h!==P.current&&(P.current=h,w(h))},[]),E=s||p,M=i||y,C=v.useRef(null),P=v.useRef(null),S=v.useRef(g),$=u!=null,I=$e(u),W=$e(r),_=$e(f),F=v.useCallback(()=>{if(!C.current||!P.current)return;const h={placement:t,strategy:n,middleware:d};W.current&&(h.platform=W.current),Yn(C.current,P.current,h).then(O=>{const D={...O,isPositioned:_.current!==!1};R.current&&!Pe(S.current,D)&&(S.current=D,Kt.flushSync(()=>{m(D)}))})},[d,t,n,W,_]);xe(()=>{f===!1&&S.current.isPositioned&&(S.current.isPositioned=!1,m(h=>({...h,isPositioned:!1})))},[f]);const R=v.useRef(!1);xe(()=>(R.current=!0,()=>{R.current=!1}),[]),xe(()=>{if(E&&(C.current=E),M&&(P.current=M),E&&M){if(I.current)return I.current(E,M,F);F()}},[E,M,F,I,$]);const L=v.useMemo(()=>({reference:C,floating:P,setReference:x,setFloating:T}),[x,T]),A=v.useMemo(()=>({reference:E,floating:M}),[E,M]),b=v.useMemo(()=>{const h={position:n,left:0,top:0};if(!A.floating)return h;const O=lt(A.floating,g.x),D=lt(A.floating,g.y);return c?{...h,transform:"translate("+O+"px, "+D+"px)",...St(A.floating)>=1.5&&{willChange:"transform"}}:{position:n,left:O,top:D}},[n,c,A.floating,g.x,g.y]);return v.useMemo(()=>({...g,update:F,refs:L,elements:A,floatingStyles:b}),[g,F,L,A,b])}const Jn=e=>{function t(n){return{}.hasOwnProperty.call(n,"current")}return{name:"arrow",options:e,fn(n){const{element:o,padding:r}=typeof e=="function"?e(n):e;return o&&t(o)?o.current!=null?ct({element:o.current,padding:r}).fn(n):{}:o?ct({element:o,padding:r}).fn(n):{}}}},Qn=(e,t)=>{const n=Xn(e);return{name:n.name,fn:n.fn,options:[e,t]}},Zn=(e,t)=>{const n=Un(e);return{name:n.name,fn:n.fn,options:[e,t]}},eo=(e,t)=>{const n=jn(e);return{name:n.name,fn:n.fn,options:[e,t]}},to=(e,t)=>{const n=Jn(e);return{name:n.name,fn:n.fn,options:[e,t]}},no="data-floating-ui-focusable",ut="active",ft="selected",oo={...v};let at=!1,ro=0;const dt=()=>"floating-ui-"+Math.random().toString(36).slice(2,6)+ro++;function io(){const[e,t]=v.useState(()=>at?dt():void 0);return z(()=>{e==null&&t(dt())},[]),v.useEffect(()=>{at=!0},[]),e}const so=oo.useId,Ge=so||io;let pe;process.env.NODE_ENV!=="production"&&(pe=new Set);function co(){for(var e,t=arguments.length,n=new Array(t),o=0;o<t;o++)n[o]=arguments[o];const r="Floating UI: "+n.join(" ");if(!((e=pe)!=null&&e.has(r))){var s;(s=pe)==null||s.add(r),console.warn(r)}}function lo(){for(var e,t=arguments.length,n=new Array(t),o=0;o<t;o++)n[o]=arguments[o];const r="Floating UI: "+n.join(" ");if(!((e=pe)!=null&&e.has(r))){var s;(s=pe)==null||s.add(r),console.error(r)}}const uo=v.forwardRef(function(t,n){const{context:{placement:o,elements:{floating:r},middlewareData:{arrow:s,shift:i}},width:c=14,height:u=7,tipRadius:f=0,strokeWidth:g=0,staticOffset:m,stroke:d,d:l,style:{transform:p,...a}={},...y}=t;process.env.NODE_ENV!=="production"&&(n||co("The `ref` prop is required for `FloatingArrow`."));const w=Ge(),[x,T]=v.useState(!1);if(z(()=>{if(!r)return;j(r).direction==="rtl"&&T(!0)},[r]),!r)return null;const[E,M]=o.split("-"),C=E==="top"||E==="bottom";let P=m;(C&&i!=null&&i.x||!C&&i!=null&&i.y)&&(P=null);const S=g*2,$=S/2,I=c/2*(f/-8+1),W=u/2*f/4,_=!!l,F=P&&M==="end"?"bottom":"top";let R=P&&M==="end"?"right":"left";P&&x&&(R=M==="end"?"left":"right");const L=s?.x!=null?P||s.x:"",A=s?.y!=null?P||s.y:"",b=l||"M0,0"+(" H"+c)+(" L"+(c-I)+","+(u-W))+(" Q"+c/2+","+u+" "+I+","+(u-W))+" Z",h={top:_?"rotate(180deg)":"",left:_?"rotate(90deg)":"rotate(-90deg)",bottom:_?"":"rotate(180deg)",right:_?"rotate(-90deg)":"rotate(90deg)"}[E];return Be("svg",{...y,"aria-hidden":!0,ref:n,width:_?c:c+S,height:c,viewBox:"0 0 "+c+" "+(u>c?u:c),style:{position:"absolute",pointerEvents:"none",[R]:L,[F]:A,[E]:C||_?"100%":"calc(100% - "+S/2+"px)",transform:[h,p].filter(O=>!!O).join(" "),...a},children:[S>0&&oe("path",{clipPath:"url(#"+w+")",fill:"none",stroke:d,strokeWidth:S+(l?0:1),d:b}),oe("path",{stroke:S&&!l?y.fill:"none",d:b}),oe("clipPath",{id:w,children:oe("rect",{x:-$,y:$*(_?-1:1),width:c+S,height:c})})]})});function fo(){const e=new Map;return{emit(t,n){var o;(o=e.get(t))==null||o.forEach(r=>r(n))},on(t,n){e.has(t)||e.set(t,new Set),e.get(t).add(n)},off(t,n){var o;(o=e.get(t))==null||o.delete(n)}}}const ao=v.createContext(null),mo=v.createContext(null),Je=()=>{var e;return((e=v.useContext(ao))==null?void 0:e.id)||null},Qe=()=>v.useContext(mo);function Ze(e){return"data-floating-ui-"+e}function U(e){e.current!==-1&&(clearTimeout(e.current),e.current=-1)}const mt=Ze("safe-polygon");function be(e,t,n){if(n&&!ge(n))return 0;if(typeof e=="number")return e;if(typeof e=="function"){const o=e();return typeof o=="number"?o:o?.[t]}return e?.[t]}function Ne(e){return typeof e=="function"?e():e}function go(e,t){t===void 0&&(t={});const{open:n,onOpenChange:o,dataRef:r,events:s,elements:i}=e,{enabled:c=!0,delay:u=0,handleClose:f=null,mouseOnly:g=!1,restMs:m=0,move:d=!0}=t,l=Qe(),p=Je(),a=ye(f),y=ye(u),w=ye(n),x=ye(m),T=v.useRef(),E=v.useRef(-1),M=v.useRef(),C=v.useRef(-1),P=v.useRef(!0),S=v.useRef(!1),$=v.useRef(()=>{}),I=v.useRef(!1),W=Y(()=>{var b;const h=(b=r.current.openEvent)==null?void 0:b.type;return h?.includes("mouse")&&h!=="mousedown"});v.useEffect(()=>{if(!c)return;function b(h){let{open:O}=h;O||(U(E),U(C),P.current=!0,I.current=!1)}return s.on("openchange",b),()=>{s.off("openchange",b)}},[c,s]),v.useEffect(()=>{if(!c||!a.current||!n)return;function b(O){W()&&o(!1,O,"hover")}const h=re(i.floating).documentElement;return h.addEventListener("mouseleave",b),()=>{h.removeEventListener("mouseleave",b)}},[i.floating,n,o,c,a,W]);const _=v.useCallback(function(b,h,O){h===void 0&&(h=!0),O===void 0&&(O="hover");const D=be(y.current,"close",T.current);D&&!M.current?(U(E),E.current=window.setTimeout(()=>o(!1,b,O),D)):h&&(U(E),o(!1,b,O))},[y,o]),F=Y(()=>{$.current(),M.current=void 0}),R=Y(()=>{if(S.current){const b=re(i.floating).body;b.style.pointerEvents="",b.removeAttribute(mt),S.current=!1}}),L=Y(()=>r.current.openEvent?["click","mousedown"].includes(r.current.openEvent.type):!1);v.useEffect(()=>{if(!c)return;function b(k){if(U(E),P.current=!1,g&&!ge(T.current)||Ne(x.current)>0&&!be(y.current,"open"))return;const V=be(y.current,"open",T.current);V?E.current=window.setTimeout(()=>{w.current||o(!0,k,"hover")},V):n||o(!0,k,"hover")}function h(k){if(L()){R();return}$.current();const V=re(i.floating);if(U(C),I.current=!1,a.current&&r.current.floatingContext){n||U(E),M.current=a.current({...r.current.floatingContext,tree:l,x:k.clientX,y:k.clientY,onClose(){R(),F(),L()||_(k,!0,"safe-polygon")}});const H=M.current;V.addEventListener("mousemove",H),$.current=()=>{V.removeEventListener("mousemove",H)};return}(T.current!=="touch"||!me(i.floating,k.relatedTarget))&&_(k)}function O(k){L()||r.current.floatingContext&&(a.current==null||a.current({...r.current.floatingContext,tree:l,x:k.clientX,y:k.clientY,onClose(){R(),F(),L()||_(k)}})(k))}function D(){U(E)}function B(k){L()||_(k,!1)}if(N(i.domReference)){const k=i.domReference,V=i.floating;return n&&k.addEventListener("mouseleave",O),d&&k.addEventListener("mousemove",b,{once:!0}),k.addEventListener("mouseenter",b),k.addEventListener("mouseleave",h),V&&(V.addEventListener("mouseleave",O),V.addEventListener("mouseenter",D),V.addEventListener("mouseleave",B)),()=>{n&&k.removeEventListener("mouseleave",O),d&&k.removeEventListener("mousemove",b),k.removeEventListener("mouseenter",b),k.removeEventListener("mouseleave",h),V&&(V.removeEventListener("mouseleave",O),V.removeEventListener("mouseenter",D),V.removeEventListener("mouseleave",B))}}},[i,c,e,g,d,_,F,R,o,n,w,l,y,a,r,L,x]),z(()=>{var b;if(c&&n&&(b=a.current)!=null&&(b=b.__options)!=null&&b.blockPointerEvents&&W()){S.current=!0;const O=i.floating;if(N(i.domReference)&&O){var h;const D=re(i.floating).body;D.setAttribute(mt,"");const B=i.domReference,k=l==null||(h=l.nodesRef.current.find(V=>V.id===p))==null||(h=h.context)==null?void 0:h.elements.floating;return k&&(k.style.pointerEvents=""),D.style.pointerEvents="none",B.style.pointerEvents="auto",O.style.pointerEvents="auto",()=>{D.style.pointerEvents="",B.style.pointerEvents="",O.style.pointerEvents=""}}}},[c,n,p,i,l,a,W]),z(()=>{n||(T.current=void 0,I.current=!1,F(),R())},[n,F,R]),v.useEffect(()=>()=>{F(),U(E),U(C),R()},[c,i.domReference,F,R]);const A=v.useMemo(()=>{function b(h){T.current=h.pointerType}return{onPointerDown:b,onPointerEnter:b,onMouseMove(h){const{nativeEvent:O}=h;function D(){!P.current&&!w.current&&o(!0,O,"hover")}g&&!ge(T.current)||n||Ne(x.current)===0||I.current&&h.movementX**2+h.movementY**2<2||(U(C),T.current==="touch"?D():(I.current=!0,C.current=window.setTimeout(D,Ne(x.current))))}}},[g,o,n,w,x]);return v.useMemo(()=>c?{reference:A}:{},[c,A])}const Ue=()=>{},po=v.createContext({delay:0,initialDelay:0,timeoutMs:0,currentId:null,setCurrentId:Ue,setState:Ue,isInstantPhase:!1}),ho=()=>v.useContext(po);function vo(e,t){t===void 0&&(t={});const{open:n,onOpenChange:o,floatingId:r}=e,{id:s,enabled:i=!0}=t,c=s??r,u=ho(),{currentId:f,setCurrentId:g,initialDelay:m,setState:d,timeoutMs:l}=u;return z(()=>{i&&f&&(d({delay:{open:1,close:be(m,"close")}}),f!==c&&o(!1))},[i,c,o,d,f,m]),z(()=>{function p(){o(!1),d({delay:m,currentId:null})}if(i&&f&&!n&&f===c){if(l){const a=window.setTimeout(p,l);return()=>{clearTimeout(a)}}p()}},[i,n,d,f,c,o,m,l]),z(()=>{i&&(g===Ue||!n||g(c))},[i,n,g,c]),u}function gt(e){return X(e.target)&&e.target.tagName==="BUTTON"}function wo(e){return X(e.target)&&e.target.tagName==="A"}function pt(e){return Et(e)}function yo(e,t){t===void 0&&(t={});const{open:n,onOpenChange:o,dataRef:r,elements:{domReference:s}}=e,{enabled:i=!0,event:c="click",toggle:u=!0,ignoreMouse:f=!1,keyboardHandlers:g=!0,stickIfOpen:m=!0}=t,d=v.useRef(),l=v.useRef(!1),p=v.useMemo(()=>({onPointerDown(a){d.current=a.pointerType},onMouseDown(a){const y=d.current;a.button===0&&c!=="click"&&(ge(y,!0)&&f||(n&&u&&(!(r.current.openEvent&&m)||r.current.openEvent.type==="mousedown")?o(!1,a.nativeEvent,"click"):(a.preventDefault(),o(!0,a.nativeEvent,"click"))))},onClick(a){const y=d.current;if(c==="mousedown"&&d.current){d.current=void 0;return}ge(y,!0)&&f||(n&&u&&(!(r.current.openEvent&&m)||r.current.openEvent.type==="click")?o(!1,a.nativeEvent,"click"):o(!0,a.nativeEvent,"click"))},onKeyDown(a){d.current=void 0,!(a.defaultPrevented||!g||gt(a))&&(a.key===" "&&!pt(s)&&(a.preventDefault(),l.current=!0),!wo(a)&&a.key==="Enter"&&o(!(n&&u),a.nativeEvent,"click"))},onKeyUp(a){a.defaultPrevented||!g||gt(a)||pt(s)||a.key===" "&&l.current&&(l.current=!1,o(!(n&&u),a.nativeEvent,"click"))}}),[r,s,c,f,g,o,n,m,u]);return v.useMemo(()=>i?{reference:p}:{},[i,p])}const Ro={pointerdown:"onPointerDown",mousedown:"onMouseDown",click:"onClick"},xo={pointerdown:"onPointerDownCapture",mousedown:"onMouseDownCapture",click:"onClickCapture"},ht=e=>{var t,n;return{escapeKey:typeof e=="boolean"?e:(t=e?.escapeKey)!=null?t:!1,outsidePress:typeof e=="boolean"?e:(n=e?.outsidePress)!=null?n:!0}};function bo(e,t){t===void 0&&(t={});const{open:n,onOpenChange:o,elements:r,dataRef:s}=e,{enabled:i=!0,escapeKey:c=!0,outsidePress:u=!0,outsidePressEvent:f="pointerdown",referencePress:g=!1,referencePressEvent:m="pointerdown",ancestorScroll:d=!1,bubbles:l,capture:p}=t,a=Qe(),y=Y(typeof u=="function"?u:()=>!1),w=typeof u=="function"?y:u,x=v.useRef(!1),{escapeKey:T,outsidePress:E}=ht(l),{escapeKey:M,outsidePress:C}=ht(p),P=v.useRef(!1),S=Y(R=>{var L;if(!n||!i||!c||R.key!=="Escape"||P.current)return;const A=(L=s.current.floatingContext)==null?void 0:L.nodeId,b=a?Re(a.nodesRef.current,A):[];if(!T&&(R.stopPropagation(),b.length>0)){let h=!0;if(b.forEach(O=>{var D;if((D=O.context)!=null&&D.open&&!O.context.dataRef.current.__escapeKeyBubbles){h=!1;return}}),!h)return}o(!1,dn(R)?R.nativeEvent:R,"escape-key")}),$=Y(R=>{var L;const A=()=>{var b;S(R),(b=ce(R))==null||b.removeEventListener("keydown",A)};(L=ce(R))==null||L.addEventListener("keydown",A)}),I=Y(R=>{var L;const A=s.current.insideReactTree;s.current.insideReactTree=!1;const b=x.current;if(x.current=!1,f==="click"&&b||A||typeof w=="function"&&!w(R))return;const h=ce(R),O="["+Ze("inert")+"]",D=re(r.floating).querySelectorAll(O);let B=N(h)?h:null;for(;B&&!Z(B);){const H=te(B);if(Z(H)||!N(H))break;B=H}if(D.length&&N(h)&&!un(h)&&!me(h,r.floating)&&Array.from(D).every(H=>!me(B,H)))return;if(X(h)&&F){const H=Z(h),q=j(h),de=/auto|scroll/,Lt=H||de.test(q.overflowX),At=H||de.test(q.overflowY),Dt=Lt&&h.clientWidth>0&&h.scrollWidth>h.clientWidth,kt=At&&h.clientHeight>0&&h.scrollHeight>h.clientHeight,It=q.direction==="rtl",Ft=kt&&(It?R.offsetX<=h.offsetWidth-h.clientWidth:R.offsetX>h.clientWidth),_t=Dt&&R.offsetY>h.clientHeight;if(Ft||_t)return}const k=(L=s.current.floatingContext)==null?void 0:L.nodeId,V=a&&Re(a.nodesRef.current,k).some(H=>{var q;return Fe(R,(q=H.context)==null?void 0:q.elements.floating)});if(Fe(R,r.floating)||Fe(R,r.domReference)||V)return;const ke=a?Re(a.nodesRef.current,k):[];if(ke.length>0){let H=!0;if(ke.forEach(q=>{var de;if((de=q.context)!=null&&de.open&&!q.context.dataRef.current.__outsidePressBubbles){H=!1;return}}),!H)return}o(!1,R,"outside-press")}),W=Y(R=>{var L;const A=()=>{var b;I(R),(b=ce(R))==null||b.removeEventListener(f,A)};(L=ce(R))==null||L.addEventListener(f,A)});v.useEffect(()=>{if(!n||!i)return;s.current.__escapeKeyBubbles=T,s.current.__outsidePressBubbles=E;let R=-1;function L(D){o(!1,D,"ancestor-scroll")}function A(){window.clearTimeout(R),P.current=!0}function b(){R=window.setTimeout(()=>{P.current=!1},Le()?5:0)}const h=re(r.floating);c&&(h.addEventListener("keydown",M?$:S,M),h.addEventListener("compositionstart",A),h.addEventListener("compositionend",b)),w&&h.addEventListener(f,C?W:I,C);let O=[];return d&&(N(r.domReference)&&(O=ee(r.domReference)),N(r.floating)&&(O=O.concat(ee(r.floating))),!N(r.reference)&&r.reference&&r.reference.contextElement&&(O=O.concat(ee(r.reference.contextElement)))),O=O.filter(D=>{var B;return D!==((B=h.defaultView)==null?void 0:B.visualViewport)}),O.forEach(D=>{D.addEventListener("scroll",L)}),()=>{c&&(h.removeEventListener("keydown",M?$:S,M),h.removeEventListener("compositionstart",A),h.removeEventListener("compositionend",b)),w&&h.removeEventListener(f,C?W:I,C),O.forEach(D=>{D.removeEventListener("scroll",L)}),window.clearTimeout(R)}},[s,r,c,w,f,n,o,d,i,T,E,S,M,$,I,C,W]),v.useEffect(()=>{s.current.insideReactTree=!1},[s,w,f]);const _=v.useMemo(()=>({onKeyDown:S,...g&&{[Ro[m]]:R=>{o(!1,R.nativeEvent,"reference-press")},...m!=="click"&&{onClick(R){o(!1,R.nativeEvent,"reference-press")}}}}),[S,o,g,m]),F=v.useMemo(()=>{function R(L){L.button===0&&(x.current=!0)}return{onKeyDown:S,onMouseDown:R,onMouseUp:R,[xo[f]]:()=>{s.current.insideReactTree=!0}}},[S,f,s]);return v.useMemo(()=>i?{reference:_,floating:F}:{},[i,_,F])}function Eo(e){const{open:t=!1,onOpenChange:n,elements:o}=e,r=Ge(),s=v.useRef({}),[i]=v.useState(()=>fo()),c=Je()!=null;if(process.env.NODE_ENV!=="production"){const l=o.reference;l&&!N(l)&&lo("Cannot pass a virtual element to the `elements.reference` option,","as it must be a real DOM element. Use `refs.setPositionReference()`","instead.")}const[u,f]=v.useState(o.reference),g=Y((l,p,a)=>{s.current.openEvent=l?p:void 0,i.emit("openchange",{open:l,event:p,reason:a,nested:c}),n?.(l,p,a)}),m=v.useMemo(()=>({setPositionReference:f}),[]),d=v.useMemo(()=>({reference:u||o.reference||null,floating:o.floating||null,domReference:o.reference}),[u,o.reference,o.floating]);return v.useMemo(()=>({dataRef:s,open:t,onOpenChange:g,elements:d,events:i,floatingId:r,refs:m}),[t,g,d,i,r,m])}function Co(e){var t,n;let{elements:o,...r}=e===void 0?{}:e;const{nodeId:s}=r,i=Eo({...r,elements:{reference:(t=o?.reference)!=null?t:null,floating:(n=o?.floating)!=null?n:null}}),c=r.rootContext||i,u=c.elements,[f,g]=v.useState(null),[m,d]=v.useState(null),p=u?.domReference||f,a=v.useRef(null),y=Qe();z(()=>{p&&(a.current=p)},[p]);const w=Gn({...r,elements:{...u,...m&&{reference:m}}}),x=v.useCallback(P=>{const S=N(P)?{getBoundingClientRect:()=>P.getBoundingClientRect(),getClientRects:()=>P.getClientRects(),contextElement:P}:P;d(S),w.refs.setReference(S)},[w.refs]),T=v.useCallback(P=>{(N(P)||P===null)&&(a.current=P,g(P)),(N(w.refs.reference.current)||w.refs.reference.current===null||P!==null&&!N(P))&&w.refs.setReference(P)},[w.refs]),E=v.useMemo(()=>({...w.refs,setReference:T,setPositionReference:x,domReference:a}),[w.refs,T,x]),M=v.useMemo(()=>({...w.elements,domReference:p}),[w.elements,p]),C=v.useMemo(()=>({...w,...c,refs:E,elements:M,nodeId:s}),[w,E,M,s,c]);return z(()=>{c.dataRef.current.floatingContext=C;const P=y?.nodesRef.current.find(S=>S.id===s);P&&(P.context=C)}),v.useMemo(()=>({...w,context:C,refs:E,elements:M}),[w,E,M,C])}function We(){return sn()&&rn()}function Oo(e,t){t===void 0&&(t={});const{open:n,onOpenChange:o,events:r,dataRef:s,elements:i}=e,{enabled:c=!0,visibleOnly:u=!0}=t,f=v.useRef(!1),g=v.useRef(-1),m=v.useRef(!0);v.useEffect(()=>{if(!c)return;const l=K(i.domReference);function p(){!n&&X(i.domReference)&&i.domReference===ot(re(i.domReference))&&(f.current=!0)}function a(){m.current=!0}function y(){m.current=!1}return l.addEventListener("blur",p),We()&&(l.addEventListener("keydown",a,!0),l.addEventListener("pointerdown",y,!0)),()=>{l.removeEventListener("blur",p),We()&&(l.removeEventListener("keydown",a,!0),l.removeEventListener("pointerdown",y,!0))}},[i.domReference,n,c]),v.useEffect(()=>{if(!c)return;function l(p){let{reason:a}=p;(a==="reference-press"||a==="escape-key")&&(f.current=!0)}return r.on("openchange",l),()=>{r.off("openchange",l)}},[r,c]),v.useEffect(()=>()=>{U(g)},[]);const d=v.useMemo(()=>({onMouseLeave(){f.current=!1},onFocus(l){if(f.current)return;const p=ce(l.nativeEvent);if(u&&N(p)){if(We()&&!l.relatedTarget){if(!m.current&&!Et(p))return}else if(!fn(p))return}o(!0,l.nativeEvent,"focus")},onBlur(l){f.current=!1;const p=l.relatedTarget,a=l.nativeEvent,y=N(p)&&p.hasAttribute(Ze("focus-guard"))&&p.getAttribute("data-type")==="outside";g.current=window.setTimeout(()=>{var w;const x=ot(i.domReference?i.domReference.ownerDocument:document);!p&&x===i.domReference||me((w=s.current.floatingContext)==null?void 0:w.refs.floating.current,x)||me(i.domReference,x)||y||o(!1,a,"focus")})}}),[s,i.domReference,o,u]);return v.useMemo(()=>c?{reference:d}:{},[c,d])}function Ve(e,t,n){const o=new Map,r=n==="item";let s=e;if(r&&e){const{[ut]:i,[ft]:c,...u}=e;s=u}return{...n==="floating"&&{tabIndex:-1,[no]:""},...s,...t.map(i=>{const c=i?i[n]:null;return typeof c=="function"?e?c(e):null:c}).concat(e).reduce((i,c)=>(c&&Object.entries(c).forEach(u=>{let[f,g]=u;if(!(r&&[ut,ft].includes(f)))if(f.indexOf("on")===0){if(o.has(f)||o.set(f,[]),typeof g=="function"){var m;(m=o.get(f))==null||m.push(g),i[f]=function(){for(var d,l=arguments.length,p=new Array(l),a=0;a<l;a++)p[a]=arguments[a];return(d=o.get(f))==null?void 0:d.map(y=>y(...p)).find(y=>y!==void 0)}}}else i[f]=g}),i),{})}}function Po(e){e===void 0&&(e=[]);const t=e.map(c=>c?.reference),n=e.map(c=>c?.floating),o=e.map(c=>c?.item),r=v.useCallback(c=>Ve(c,e,"reference"),t),s=v.useCallback(c=>Ve(c,e,"floating"),n),i=v.useCallback(c=>Ve(c,e,"item"),o);return v.useMemo(()=>({getReferenceProps:r,getFloatingProps:s,getItemProps:i}),[r,s,i])}const To=new Map([["select","listbox"],["combobox","listbox"],["label",!1]]);function Mo(e,t){var n,o;t===void 0&&(t={});const{open:r,elements:s,floatingId:i}=e,{enabled:c=!0,role:u="dialog"}=t,f=Ge(),g=((n=s.domReference)==null?void 0:n.id)||f,m=v.useMemo(()=>{var x;return((x=an(s.floating))==null?void 0:x.id)||i},[s.floating,i]),d=(o=To.get(u))!=null?o:u,p=Je()!=null,a=v.useMemo(()=>d==="tooltip"||u==="label"?{["aria-"+(u==="label"?"labelledby":"describedby")]:r?m:void 0}:{"aria-expanded":r?"true":"false","aria-haspopup":d==="alertdialog"?"dialog":d,"aria-controls":r?m:void 0,...d==="listbox"&&{role:"combobox"},...d==="menu"&&{id:g},...d==="menu"&&p&&{role:"menuitem"},...u==="select"&&{"aria-autocomplete":"none"},...u==="combobox"&&{"aria-autocomplete":"list"}},[d,m,p,r,g,u]),y=v.useMemo(()=>{const x={id:m,...d&&{role:d}};return d==="tooltip"||u==="label"?x:{...x,...d==="menu"&&{"aria-labelledby":g}}},[d,m,g,u]),w=v.useCallback(x=>{let{active:T,selected:E}=x;const M={role:"option",...T&&{id:m+"-fui-option"}};switch(u){case"select":case"combobox":return{...M,"aria-selected":E}}return{}},[m,u]);return v.useMemo(()=>c?{reference:a,floating:y,item:w}:{},[c,a,y,w])}function Do({closeDelay:e=300,offset:t=20,openDelay:n=0,placement:o="bottom-start",slots:r,trigger:s=["hover","focus"],withArrow:i=!0,arrow:c,role:u="dialog",visible:f={},hidden:g={},floatingOptions:m={},isOpen:d,onOpenChange:l}){const[p,a]=Nt(!1),y=Wt(null),w=Vt(),{x,y:T,strategy:E,refs:M,context:C}=Co({placement:o,middleware:[Qn(t),eo(),Zn(),to({element:y})],open:d||p,onOpenChange:l||a,whileElementsMounted:Kn,...m}),P=bo(C),S=Mo(C,{role:u}),{delay:$}=vo(C,{id:w}),W=go(C,{delay:$||{open:n,close:e}}),_=Oo(C),F=yo(C),R=[s.find(k=>k==="hover")?W:void 0,s.find(k=>k==="click")?F:void 0,s.find(k=>k==="focus")?_:void 0,P,S],{getReferenceProps:L,getFloatingProps:A}=Po(R),{onClick:b,...h}=L(),O=String((r?.content?.props).className).includes("pressable")?{onPress:b}:{onClick:b},D=r?.content?Bt(r.content,{...r.content.props,ref:M.setReference,...h,...O}):oe("div",{ref:M.setReference,...L(),children:"Menu Action"}),B=r?.submenu?Be(Ht.nav,{ref:M.setFloating,style:{position:E,top:T??0,left:x??0,width:"max-content",zIndex:50},...A(),variants:{hidden:g,visible:f},initial:"hidden",animate:d||p?"visible":"hidden",children:[i&&oe(uo,{ref:y,context:C,...c}),r.submenu]}):oe("nav",{children:"Submenu"});return Be($t,{children:[D,B]})}export{Do as Menu,Do as default};
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
# External Link Detection Migration
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-01-14
|
|
4
|
+
**Affects:** `@clicktap/ui`, `apps/frontend`
|
|
5
|
+
**Breaking:** No (additive, but requires provider setup for SSR)
|
|
6
|
+
**Classification:** IMPROVEMENT
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
## Dependencies
|
|
10
|
+
|
|
11
|
+
*None*
|
|
12
|
+
|
|
13
|
+
## Summary
|
|
14
|
+
|
|
15
|
+
The `Link` component from `@clicktap/ui` now automatically detects external URLs and applies `target="_blank"` and `rel="noopener noreferrer"` attributes. This requires setting up `LinkProvider` for proper SSR support.
|
|
16
|
+
|
|
17
|
+
## Changes
|
|
18
|
+
|
|
19
|
+
1. `Link` component auto-detects external URLs
|
|
20
|
+
2. New `LinkProvider` for SSR base URL configuration
|
|
21
|
+
3. New `isExternalUrl` utility function
|
|
22
|
+
4. Layout files must pass `baseUrl` from host header
|
|
23
|
+
|
|
24
|
+
## Setup
|
|
25
|
+
|
|
26
|
+
### 1. Update Layouts to Pass baseUrl
|
|
27
|
+
|
|
28
|
+
In your Next.js layout files (Server Components), extract the host header and pass it to Providers:
|
|
29
|
+
|
|
30
|
+
```tsx
|
|
31
|
+
// app/(base)/layout.tsx
|
|
32
|
+
import { headers } from 'next/headers';
|
|
33
|
+
|
|
34
|
+
export default function Layout({ children }) {
|
|
35
|
+
const h = headers();
|
|
36
|
+
const baseUrl = `https://${h.get('host')}`;
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<Providers baseUrl={baseUrl}>
|
|
40
|
+
{children}
|
|
41
|
+
</Providers>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
// app/(checkout)/layout.tsx
|
|
48
|
+
import { headers } from 'next/headers';
|
|
49
|
+
|
|
50
|
+
export default function CheckoutLayout({ children }) {
|
|
51
|
+
const h = headers();
|
|
52
|
+
const baseUrl = `https://${h.get('host')}`;
|
|
53
|
+
|
|
54
|
+
return (
|
|
55
|
+
<Providers baseUrl={baseUrl}>
|
|
56
|
+
{children}
|
|
57
|
+
</Providers>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 2. Update Providers Component
|
|
63
|
+
|
|
64
|
+
Add the `baseUrl` prop and wrap with `LinkProvider`:
|
|
65
|
+
|
|
66
|
+
```tsx
|
|
67
|
+
// providers/Providers.tsx
|
|
68
|
+
import { LinkProvider } from '@clicktap/ui/components/Link';
|
|
69
|
+
|
|
70
|
+
type Props = {
|
|
71
|
+
baseUrl?: string;
|
|
72
|
+
children: ReactNode;
|
|
73
|
+
// ... other props
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export function Providers({ baseUrl, children, ...props }: Props) {
|
|
77
|
+
return (
|
|
78
|
+
<LinkProvider config={{ baseUrl }}>
|
|
79
|
+
{/* other providers */}
|
|
80
|
+
{children}
|
|
81
|
+
</LinkProvider>
|
|
82
|
+
);
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## How It Works
|
|
87
|
+
|
|
88
|
+
### Detection Logic
|
|
89
|
+
|
|
90
|
+
- **Relative URLs** (`/path`, `#anchor`) → Internal (no attributes added)
|
|
91
|
+
- **Absolute URLs** → Compared against current host
|
|
92
|
+
- Same host → Internal
|
|
93
|
+
- Different host → External (adds `target="_blank"` and `rel="noopener noreferrer"`)
|
|
94
|
+
|
|
95
|
+
### Host Detection
|
|
96
|
+
|
|
97
|
+
- **Client-side:** Uses `window.location.host` automatically
|
|
98
|
+
- **Server-side (SSR):** Uses `baseUrl` from `LinkProvider`
|
|
99
|
+
|
|
100
|
+
This ensures external links are correctly identified during both SSR and client-side rendering.
|
|
101
|
+
|
|
102
|
+
## Usage
|
|
103
|
+
|
|
104
|
+
No changes needed in component code. The `Link` component handles detection automatically:
|
|
105
|
+
|
|
106
|
+
```tsx
|
|
107
|
+
import { Link } from '@clicktap/ui/components/Link';
|
|
108
|
+
|
|
109
|
+
// Internal - renders normally
|
|
110
|
+
<Link href="/products">Products</Link>
|
|
111
|
+
|
|
112
|
+
// External - automatically gets target="_blank" rel="noopener noreferrer"
|
|
113
|
+
<Link href="https://google.com">Google</Link>
|
|
114
|
+
|
|
115
|
+
// Anchor - renders normally
|
|
116
|
+
<Link href="#section">Jump to section</Link>
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Override Behavior
|
|
120
|
+
|
|
121
|
+
You can override the automatic behavior if needed:
|
|
122
|
+
|
|
123
|
+
```tsx
|
|
124
|
+
// Force internal link behavior on external URL
|
|
125
|
+
<Link href="https://subdomain.mysite.com" target="_self">
|
|
126
|
+
Subdomain
|
|
127
|
+
</Link>
|
|
128
|
+
|
|
129
|
+
// Force external link behavior on internal URL
|
|
130
|
+
<Link href="/download" target="_blank" rel="noopener noreferrer">
|
|
131
|
+
Download
|
|
132
|
+
</Link>
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
## Utility Function
|
|
136
|
+
|
|
137
|
+
The `isExternalUrl` utility is exported for use outside the Link component:
|
|
138
|
+
|
|
139
|
+
```tsx
|
|
140
|
+
import { isExternalUrl } from '@clicktap/ui/components/Link';
|
|
141
|
+
|
|
142
|
+
const external = isExternalUrl('https://google.com', 'mysite.com');
|
|
143
|
+
// true
|
|
144
|
+
|
|
145
|
+
const internal = isExternalUrl('/products', 'mysite.com');
|
|
146
|
+
// false
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
## Files Changed
|
|
150
|
+
|
|
151
|
+
- `libs/ui/src/components/Link/Link.tsx` - Auto-detection logic
|
|
152
|
+
- `libs/ui/src/components/Link/LinkContext.tsx` - New provider
|
|
153
|
+
- `libs/ui/src/components/Link/utils.ts` - `isExternalUrl` utility
|
|
154
|
+
- `libs/ui/src/components/Link/index.ts` - Updated exports
|
|
155
|
+
- `apps/frontend/app/(base)/layout.tsx` - Pass baseUrl
|
|
156
|
+
- `apps/frontend/app/(checkout)/layout.tsx` - Pass baseUrl
|
|
157
|
+
- `apps/frontend/providers/Providers.tsx` - Add LinkProvider
|
|
158
|
+
|
|
159
|
+
## Migration Checklist
|
|
160
|
+
|
|
161
|
+
1. [ ] Update `libs/ui` to latest version
|
|
162
|
+
2. [ ] Add `baseUrl` prop to Providers component
|
|
163
|
+
3. [ ] Wrap app with `LinkProvider`
|
|
164
|
+
4. [ ] Update all layout files to pass `baseUrl` from host header
|
|
165
|
+
5. [ ] Test external links open in new tab
|
|
166
|
+
6. [ ] Test internal links work normally
|
|
167
|
+
7. [ ] Verify SSR renders correct attributes
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
# LinkAsButton → @clicktap/ui
|
|
172
|
+
|
|
173
|
+
**Date:** 2026-02-06
|
|
174
|
+
|
|
175
|
+
## Summary
|
|
176
|
+
|
|
177
|
+
`LinkAsButton` has been promoted from `apps/frontend/components/LinkAsButton/` into the shared UI library. `Button` also gains `primary`/`secondary`/`tertiary` variant aliases.
|
|
178
|
+
|
|
179
|
+
## Changes
|
|
180
|
+
|
|
181
|
+
### `LinkAsButton` promoted to shared UI library
|
|
182
|
+
|
|
183
|
+
- **Old import:** `import { LinkAsButton } from '../LinkAsButton/LinkAsButton'` (relative, app-level)
|
|
184
|
+
- **New import:** `import { LinkAsButton } from '@clicktap/ui/components/LinkAsButton'`
|
|
185
|
+
- The `[k: string]: any` catch-all type is removed — proper typing via `LinkProps` + `Pick<ButtonProps, 'variant' | 'size'>`
|
|
186
|
+
- Now supports all Button variants (`solid`, `outline`, `ghost`) plus aliases (`primary`, `secondary`, `tertiary`), `size` prop (`sm`, `md`, `lg`), and `isLoading`
|
|
187
|
+
- `apps/frontend/components/LinkAsButton/` has been deleted
|
|
188
|
+
|
|
189
|
+
### Breaking: `LinkAsButton` default behavior changed
|
|
190
|
+
|
|
191
|
+
The old local component had no default variant — it rendered as a transparent link with base layout classes. The new shared component defaults to `variant="solid"` and `size="md"`:
|
|
192
|
+
|
|
193
|
+
| Property | Old (local) | New (`@clicktap/ui`) |
|
|
194
|
+
|----------|-------------|----------------------|
|
|
195
|
+
| `variant` | none (transparent background, transparent border) | `solid` (dark background, white text) |
|
|
196
|
+
| `size` | none (no height constraint) | `md` (`h-10` = 40px height) |
|
|
197
|
+
|
|
198
|
+
**Impact:** Any `<LinkAsButton>` without an explicit `variant` prop now renders as a dark solid button with a 40px height constraint. This is especially problematic when wrapping images — the image gets constrained inside a styled button container.
|
|
199
|
+
|
|
200
|
+
**Fix:** Use `variant="ghost"` for transparent links, or use `<Link>` directly when button styling isn't appropriate (e.g., clickable product images):
|
|
201
|
+
|
|
202
|
+
```tsx
|
|
203
|
+
// Before: image wrapped in default LinkAsButton (was transparent, now solid)
|
|
204
|
+
<LinkAsButton href={url}>
|
|
205
|
+
<Image ... />
|
|
206
|
+
</LinkAsButton>
|
|
207
|
+
|
|
208
|
+
// After: use plain Link for image wrappers
|
|
209
|
+
<Link href={url}>
|
|
210
|
+
<Image ... />
|
|
211
|
+
</Link>
|
|
212
|
+
|
|
213
|
+
// After: use ghost variant if button semantics are needed
|
|
214
|
+
<LinkAsButton variant="ghost" href={url}>
|
|
215
|
+
Text link
|
|
216
|
+
</LinkAsButton>
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Button variant aliases
|
|
220
|
+
|
|
221
|
+
- `Button` now accepts `primary`, `secondary`, and `tertiary` as variant values
|
|
222
|
+
- `primary` → `solid`, `secondary` → `outline`, `tertiary` → `ghost`
|
|
223
|
+
- Existing `solid`, `outline`, `ghost` values continue to work unchanged
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
# Image Component: Remove `width: 'auto'` Auto-Styling
|
|
228
|
+
|
|
229
|
+
**Date:** 2026-02-08
|
|
230
|
+
**Affects:** `@clicktap/ui` Image component, all consumers
|
|
231
|
+
**Breaking:** Yes - images using `width`/`height` props may render differently
|
|
232
|
+
|
|
233
|
+
## Summary
|
|
234
|
+
|
|
235
|
+
The `@clicktap/ui` Image component previously auto-prepended `{ width: 'auto', height: 'auto' }` to the style prop when `width` and `height` props were provided (not `fill`). The `width: 'auto'` has been removed because it overrides the HTML `width` attribute via CSS, causing images to render at their natural intrinsic size instead of the dimensions specified by the props.
|
|
236
|
+
|
|
237
|
+
## What Changed
|
|
238
|
+
|
|
239
|
+
```diff
|
|
240
|
+
const imageStyle = hasSizedProps
|
|
241
|
+
- ? { width: 'auto' as const, height: 'auto' as const, ...style }
|
|
242
|
+
+ ? { height: 'auto' as const, ...style }
|
|
243
|
+
: style;
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
**Before:** Images with `width={100} height={100}` and no explicit `style` rendered at their natural resolution (CSS `width: auto` overrode the HTML attribute).
|
|
247
|
+
|
|
248
|
+
**After:** Images render at the width specified by the `width` prop. `height: 'auto'` preserves the natural aspect ratio.
|
|
249
|
+
|
|
250
|
+
## Migration
|
|
251
|
+
|
|
252
|
+
### Review Image usages without explicit `style` prop
|
|
253
|
+
|
|
254
|
+
Any `<Image>` that passes `width` and `height` props without a `style` override will now render at the `width` prop size instead of the natural image size. In most cases this is the correct behavior.
|
|
255
|
+
|
|
256
|
+
If the natural-size behavior was intentional, restore it with an explicit style:
|
|
257
|
+
|
|
258
|
+
```tsx
|
|
259
|
+
<Image width={100} height={100} style={{ width: 'auto', height: 'auto' }} ... />
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
### Add aspect ratio control where needed
|
|
263
|
+
|
|
264
|
+
If the displayed image needs a specific aspect ratio that differs from the source image's natural ratio, add CSS classes. Use the actual source image dimensions to determine the ratio (e.g., 960x1200 images → `aspect-[4/5]`):
|
|
265
|
+
|
|
266
|
+
```tsx
|
|
267
|
+
// Explicit aspect ratio matching source images (e.g., 960x1200 = 4:5)
|
|
268
|
+
<Image
|
|
269
|
+
width={100} height={125}
|
|
270
|
+
className="aspect-[4/5] object-cover"
|
|
271
|
+
style={{ width: '100%', height: 'auto' }}
|
|
272
|
+
/>
|
|
273
|
+
|
|
274
|
+
// Fill container width, natural aspect ratio (common pattern, no extra classes needed)
|
|
275
|
+
<Image
|
|
276
|
+
width={400} height={300}
|
|
277
|
+
style={{ width: '100%', height: 'auto' }}
|
|
278
|
+
/>
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Affected areas to check
|
|
282
|
+
|
|
283
|
+
Visually inspect any page that displays product images:
|
|
284
|
+
- Cart drawer (mini-cart)
|
|
285
|
+
- Cart page
|
|
286
|
+
- Checkout order summary
|
|
287
|
+
- Checkout success / order confirmation
|
|
288
|
+
- Category listing pages
|
|
289
|
+
- Product collection components
|
|
290
|
+
- Account order history
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
# useRoute Hook Migration
|
|
2
|
+
|
|
3
|
+
**Date:** 2026-01-14
|
|
4
|
+
**Affects:** `@clicktap/ui`, `apps/frontend`
|
|
5
|
+
**Breaking:** No (additive, but recommended migration)
|
|
6
|
+
**Classification:** IMPROVEMENT
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
## Dependencies
|
|
10
|
+
|
|
11
|
+
*None*
|
|
12
|
+
|
|
13
|
+
## Summary
|
|
14
|
+
|
|
15
|
+
Introduces a centralized route configuration system with the `useRoute` hook for generating URLs. Handles dynamic params, protected route redirects, and login-with-return patterns automatically.
|
|
16
|
+
|
|
17
|
+
## New Files
|
|
18
|
+
|
|
19
|
+
- `libs/ui/src/hooks/useRoute/` - Hook and RouteProvider
|
|
20
|
+
- `apps/frontend/config/routes.ts` - Centralized route definitions
|
|
21
|
+
|
|
22
|
+
## Provider Setup
|
|
23
|
+
|
|
24
|
+
Add `RouteProviderWithAuth` inside your `AuthProvider`:
|
|
25
|
+
|
|
26
|
+
```tsx
|
|
27
|
+
import { RouteProvider } from '@clicktap/ui/hooks/useRoute';
|
|
28
|
+
import { useAuth } from '../state/auth/AuthProvider';
|
|
29
|
+
|
|
30
|
+
function RouteProviderWithAuth({ children }: { children: ReactNode }) {
|
|
31
|
+
const { isLoggedIn } = useAuth();
|
|
32
|
+
return <RouteProvider config={{ isLoggedIn }}>{children}</RouteProvider>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// In provider tree:
|
|
36
|
+
<AuthProvider actor={authActor}>
|
|
37
|
+
<RouteProviderWithAuth>
|
|
38
|
+
{children}
|
|
39
|
+
</RouteProviderWithAuth>
|
|
40
|
+
</AuthProvider>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Migration Patterns
|
|
44
|
+
|
|
45
|
+
### Static Routes
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
// Before
|
|
49
|
+
<Link href="/cart">Cart</Link>
|
|
50
|
+
|
|
51
|
+
// After
|
|
52
|
+
import { useRoute } from '@clicktap/ui/hooks/useRoute';
|
|
53
|
+
import { Routes } from '../config/routes';
|
|
54
|
+
|
|
55
|
+
const cartUrl = useRoute(Routes.cart.index);
|
|
56
|
+
<Link href={cartUrl}>Cart</Link>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Dynamic Routes
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
// Before
|
|
63
|
+
<Link href={`/account/orders/${orderId}`}>View Order</Link>
|
|
64
|
+
|
|
65
|
+
// After
|
|
66
|
+
const orderUrl = useRoute(Routes.account.orders.view, { orderId });
|
|
67
|
+
<Link href={orderUrl}>View Order</Link>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Protected Routes
|
|
71
|
+
|
|
72
|
+
Protected routes automatically redirect through auth when logged out:
|
|
73
|
+
|
|
74
|
+
```tsx
|
|
75
|
+
// Before
|
|
76
|
+
const ordersUrl = isLoggedIn
|
|
77
|
+
? '/account/orders'
|
|
78
|
+
: `/account/authenticate?redirect=${encodeURIComponent('/account/orders')}`;
|
|
79
|
+
|
|
80
|
+
// After
|
|
81
|
+
const ordersUrl = useRoute(Routes.account.orders.index);
|
|
82
|
+
// Logged in: '/account/orders'
|
|
83
|
+
// Logged out: '/account/authenticate?redirect=%2Faccount%2Forders'
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Login with Return
|
|
87
|
+
|
|
88
|
+
```tsx
|
|
89
|
+
// Before
|
|
90
|
+
const loginUrl = `/account/authenticate?redirect=${encodeURIComponent(pathname)}`;
|
|
91
|
+
const loginUrl = Routes.account.loginAndReturn(Routes.cart.index);
|
|
92
|
+
|
|
93
|
+
// After
|
|
94
|
+
const loginUrl = useRoute(Routes.account.authenticate, null, { returnHere: true });
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### router.push
|
|
98
|
+
|
|
99
|
+
```tsx
|
|
100
|
+
// Before
|
|
101
|
+
router.push('/checkout');
|
|
102
|
+
router.push(`/checkout/success/${orderId}`);
|
|
103
|
+
|
|
104
|
+
// After
|
|
105
|
+
const checkoutUrl = useRoute(Routes.checkout.index);
|
|
106
|
+
router.push(checkoutUrl);
|
|
107
|
+
|
|
108
|
+
const successUrl = useRoute(Routes.checkout.success, { orderId });
|
|
109
|
+
router.push(successUrl);
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Adding New Routes
|
|
113
|
+
|
|
114
|
+
Add to `apps/frontend/config/routes.ts`:
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
const RawRoutes = {
|
|
118
|
+
// Static route
|
|
119
|
+
newPage: {
|
|
120
|
+
path: '/new-page',
|
|
121
|
+
isProtected: false,
|
|
122
|
+
},
|
|
123
|
+
|
|
124
|
+
// Nested with dynamic param
|
|
125
|
+
feature: {
|
|
126
|
+
index: {
|
|
127
|
+
path: '/feature',
|
|
128
|
+
isProtected: false,
|
|
129
|
+
},
|
|
130
|
+
details: {
|
|
131
|
+
path: '/feature/:featureId',
|
|
132
|
+
isProtected: true,
|
|
133
|
+
},
|
|
134
|
+
},
|
|
135
|
+
} as const;
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
## Deprecated
|
|
139
|
+
|
|
140
|
+
- `Routes.account.loginAndReturn()` - Use `useRoute(route, null, { returnHere: true })`
|
|
141
|
+
- `isProtectedRoute(pathname)` - Use `route.isProtected` directly
|
|
142
|
+
- Direct `.path` access - Use `useRoute()` for all URL generation
|