UNPKG

vue-float-menu

Version:
3 lines (2 loc) 33.9 kB
import{defineComponent as e,createElementBlock as t,openBlock as n,createElementVNode as o,ref as a,computed as r,unref as i,onMounted as l,onUnmounted as s,resolveComponent as u,nextTick as c,watch as d,normalizeStyle as m,Fragment as v,renderList as h,normalizeClass as p,createVNode as f,createCommentVNode as g,renderSlot as y,toDisplayString as b,createBlock as w,Transition as M,withCtx as x,resolveDynamicComponent as C,createSlots as k,mergeProps as S,normalizeProps as T,guardReactiveProps as E,shallowRef as A}from"vue";const $=(e,t,n,o)=>{const{top:a,bottom:r}=e.getBoundingClientRect(),i=Math.round((t.clientWidth-n)/2),l=t.clientHeight;let s="bottom";let u=null;return l>a?(u={top:`${n+15}px`,left:`-${i}px`},s="top"):window.innerHeight-r<l?(u={bottom:`${n+15}px`,left:`-${i}px`},s="bottom"):(u={top:`${n+15}px`,left:`-${i}px`},s="top"),Object.assign({},u,{"min-height":`${o.height}px`,width:`${o.width}px`,newOrientation:s})},I=(e,t,n,o)=>{const{top:a,bottom:r,left:i,right:l}=e.getBoundingClientRect(),{innerWidth:s,innerHeight:u}=window,c=o.clientWidth,d=Math.ceil(c/2);let m=null,v=!1,h=!1;return n&&(v=!1),r>u&&(m={left:t.left,top:t.top-(r-u)},h=!0),a<0&&(m={left:t.left,top:t.top+Math.abs(a)},h=!0),(i<0||i<d)&&(m={left:d,top:t.top},h=!0),(l>s||s-l<c)&&(m={left:s-c,top:t.top},n&&(v=!0),h=!0),{position:m,flip:v,reveal:h}},D=(e,t)=>{const n=15;let o=n,a=n;switch(e){case"top left":o=n,a=n;break;case"top right":o=window.innerWidth-t-n,a=n;break;case"bottom left":o=n,a=window.innerHeight-t-n;break;case"bottom right":o=window.innerWidth-t-n,a=window.innerHeight-t-n}return{left:`${o}px`,top:`${a}px`,width:`${t}px`,height:`${t}px`}};var P=e({name:"MenuIcon"});const O={xmlns:"http://www.w3.org/2000/svg",width:"50%",height:"50%",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round",class:"feather feather-menu"};P.render=function(e,a,r,i,l,s){return n(),t("svg",O,a[0]||(a[0]=[o("line",{x1:"3",y1:"12",x2:"21",y2:"12"},null,-1),o("line",{x1:"3",y1:"6",x2:"21",y2:"6"},null,-1),o("line",{x1:"3",y1:"18",x2:"21",y2:"18"},null,-1)]))},P.__file="src/components/icons/MenuIcon.vue";var _={name:"XIcon"};const B={xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round",class:"feather feather-x"};_.render=function(e,a,r,i,l,s){return n(),t("svg",B,a[0]||(a[0]=[o("line",{x1:"18",y1:"6",x2:"6",y2:"18"},null,-1),o("line",{x1:"6",y1:"6",x2:"18",y2:"18"},null,-1)]))},_.__file="src/components/icons/XIcon.vue";var L=e({name:"ChevronRightIcon"});const j={xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor","stroke-width":"2","stroke-linecap":"round","stroke-linejoin":"round",class:"feather feather-chevron-right"};L.render=function(e,a,r,i,l,s){return n(),t("svg",j,a[0]||(a[0]=[o("polyline",{points:"9 18 15 12 9 6"},null,-1)]))},L.__file="src/components/icons/ChevRightIcon.vue";var z=e({name:"PlusIcon"});const H={xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",class:"feather feather-plus"};z.render=function(e,a,r,i,l,s){return n(),t("svg",H,a[0]||(a[0]=[o("line",{x1:"12",y1:"5",x2:"12",y2:"19"},null,-1),o("line",{x1:"5",y1:"12",x2:"19",y2:"12"},null,-1)]))},z.__file="src/components/icons/PlusIcon.vue";var N=e({name:"PlusIcon"});const R={xmlns:"http://www.w3.org/2000/svg",width:"24",height:"24",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",class:"feather feather-minus"};N.render=function(e,a,r,i,l,s){return n(),t("svg",R,a[0]||(a[0]=[o("line",{x1:"5",y1:"12",x2:"19",y2:"12"},null,-1)]))},N.__file="src/components/icons/MinusIcon.vue";const F={primary:"#4f46e5",textColor:"#374151",menuBgColor:"rgba(255, 255, 255, 0.95)",textSelectedColor:"#1f2937",hoverBackground:"rgba(79, 70, 229, 0.1)"};const q=()=>{const e=a(!1),t=a(!1),n=a(0),o=a({x:0,y:0}),i=a({x:0,y:0});return l((()=>{e.value="ontouchstart"in window||navigator.maxTouchPoints>0||/Android|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),e.value&&document.body.classList.add("touch-device");const t=document.createElement("style");t.textContent="\n .touch-device .menu-list-item {\n min-height: 44px !important;\n padding: 12px 16px !important;\n touch-action: manipulation;\n }\n \n .touch-device .menu-head {\n min-width: 44px !important;\n min-height: 44px !important;\n touch-action: manipulation;\n }\n \n .touch-device .chev-icon {\n min-width: 44px !important;\n min-height: 44px !important;\n display: flex !important;\n align-items: center !important;\n justify-content: center !important;\n }\n \n @media (hover: none) and (pointer: coarse) {\n .menu-list-item:hover {\n background-color: transparent !important;\n }\n \n .menu-list-item:active {\n background-color: var(--hover-background) !important;\n transform: scale(0.98) !important;\n }\n }\n ",document.head.appendChild(t)})),s((()=>{document.body.classList.remove("touch-device")})),{isTouchDevice:r((()=>e.value)),isLongPress:r((()=>t.value)),handleTouchStart:(e,a)=>{const r=e.touches[0];n.value=Date.now(),o.value={x:r.clientX,y:r.clientY},i.value={x:r.clientX,y:r.clientY};const l=setTimeout((()=>{if(t.value)return;t.value=!0;const i={type:"longpress",target:e.target,startPosition:o.value,duration:Date.now()-n.value,force:r.force||1};a?.(i)}),500);e.target._longPressTimer=l},handleTouchMove:e=>{const n=e.touches[0];i.value={x:n.clientX,y:n.clientY};const a=Math.sqrt(Math.pow(i.value.x-o.value.x,2)+Math.pow(i.value.y-o.value.y,2)),r=e.target;a>10&&r._longPressTimer&&(clearTimeout(r._longPressTimer),t.value=!1)},handleTouchEnd:(e,a)=>{const r=Date.now()-n.value,l=e.target;if(l._longPressTimer&&clearTimeout(l._longPressTimer),t.value)return void(t.value=!1);const s=Math.sqrt(Math.pow(i.value.x-o.value.x,2)+Math.pow(i.value.y-o.value.y,2)),u=s/r;let c;c=s<10?{type:"tap",target:e.target,startPosition:o.value,endPosition:i.value,duration:r}:s>50&&u>.3?{type:"swipe",target:e.target,startPosition:o.value,endPosition:i.value,duration:r}:{type:"tap",target:e.target,startPosition:o.value,endPosition:i.value,duration:r},a?.(c)},getSwipeDirection:()=>{const e=i.value.x-o.value.x,t=i.value.y-o.value.y,a=Math.sqrt(e*e+t*t);if(a<50)return null;const r=a/(Date.now()-n.value);return Math.abs(e)>Math.abs(t)?{direction:e>0?"right":"left",velocity:r,distance:a}:{direction:t>0?"down":"up",velocity:r,distance:a}},triggerHapticFeedback:(e="light")=>{if("vibrate"in navigator){const t={light:[10],medium:[20],heavy:[30]};navigator.vibrate(t[e])}},ensureTouchTarget:(e,t=44)=>{const n=e.getBoundingClientRect(),o=Math.min(n.width,n.height);if(o<t){const n=(t-o)/2;e.style.padding=`${n}px`,e.style.minWidth=`${t}px`,e.style.minHeight=`${t}px`}},getOptimalMenuOrientation:(t,n,o)=>{const a=n.getBoundingClientRect(),r=t.getBoundingClientRect();if(e.value&&o.width<768){const e=o.height-a.bottom,t=a.top;return e>=r.height+20?"bottom":t>=r.height+20?"top":"bottom-scroll"}return a.top>o.height/2?"top":"bottom"},enhanceAccessibility:e=>{e.style.touchAction="manipulation",e.hasAttribute("tabindex")||e.setAttribute("tabindex","0"),e.hasAttribute("aria-label")||e.hasAttribute("aria-labelledby")||e.setAttribute("aria-label","Interactive menu item"),e.hasAttribute("role")||e.setAttribute("role","button")}}};var X=Object.freeze({__proto__:null,useTouchOptimizations:q});const W=()=>{const e=a({lazyLoad:!0,treeShaking:!0,codesplitting:!0,compression:!0}),t=async e=>{try{switch(e){case"TouchOptimizations":return await Promise.resolve().then((function(){return X}));case"Animations":return await Promise.resolve().then((function(){return oe}));case"Performance":return await Promise.resolve().then((function(){return ae}));case"ErrorHandling":return await Promise.resolve().then((function(){return re}));default:throw new Error(`Unknown component: ${e}`)}}catch(e){return null}},n=async()=>{const e="ontouchstart"in window||navigator.maxTouchPoints>0,n=window.matchMedia("(prefers-reduced-motion: reduce)").matches,o=navigator.hardwareConcurrency&&navigator.hardwareConcurrency>=4,a=[];e&&a.push(t("TouchOptimizations")),n||a.push(t("Animations")),o&&a.push(t("Performance")),a.push(t("Accessibility"),t("ErrorHandling"),t("KeyboardNavigation"));try{await Promise.all(a)}catch(e){}},o=r((()=>{const e=navigator.userAgent.toLowerCase(),t=/android|iphone|ipad|ipod|blackberry|iemobile|opera mini/i.test(e),n=navigator,o="connection"in navigator&&"slow-2g"===n.connection?.effectiveType||"2g"===n.connection?.effectiveType;return t||o?"aggressive":"standard"})),i=()=>{[{href:"/vue-float-menu.css",as:"style"},{href:"/vue-float-menu.js",as:"script"}].forEach((e=>{const t=document.createElement("link");t.rel="preload",t.href=e.href,t.as=e.as,document.head.appendChild(t)}))};return l((()=>{e.value.lazyLoad&&n(),e.value.compression,import.meta.env&&!import.meta.env.DEV&&i()})),{optimizations:r((()=>e.value)),loadComponent:t,loadComposablesConditionally:n,getBundleInfo:()=>({core:12,touchOptimizations:3,accessibility:2,animations:2,performance:1.5,errorHandling:1,keyboardNavigation:1.5,total:23}),measurePerformance:(e,t)=>{if("performance"in window&&performance.mark){const n=`${e}-start`,o=`${e}-end`,a=`${e}-duration`;performance.mark(n),t(),performance.mark(o);try{performance.measure(a,n,o);performance.getEntriesByName(a)[0]}catch(e){}}else t()},markAsUsed:e=>{import.meta.env},monitorMemoryUsage:()=>{const e=performance;return"memory"in e&&e.memory?{used:e.memory.usedJSHeapSize,total:e.memory.totalJSHeapSize,limit:e.memory.jsHeapSizeLimit}:null},splitStrategy:o,enableCompression:()=>"serviceWorker"in navigator,preloadCriticalResources:i}};var Y=e({name:"FloatMenu",components:{ChevRightIcon:L,PlusIcon:z,MinusIcon:N},props:{data:{type:Array,default:()=>[]},flip:{type:Boolean,default:!1},onSelection:{type:Function,default:null},onClose:{type:Function,default:null,required:!0},theme:{type:Object,required:!1,default:F},menuStyle:{type:String,default:"slide-out",required:!1},isTouchDevice:{type:Boolean,default:!1}},setup(e){const{measurePerformance:t,markAsUsed:n}=W(),{activeIndex:o,menuItems:s,toggleMenu:m,selectMenuItem:v,setActiveIndex:h,closeAllSubMenus:p,updateSelectedItem:f}=function(e){const t=a(-1),n=a(e.map((e=>Object.assign({},e,{id:`menu-item-${Math.random().toString(16)}`,showSubMenu:!1})))),o=(e,t)=>{const o=n.value.find((t=>t.id===e)),a=o?.showSubMenu;a?n.value=n.value.map((t=>t.id===e?Object.assign({},t,{showSubMenu:!1}):t)):(n.value=n.value.map((t=>t.id!==e&&t.showSubMenu?Object.assign({},t,{showSubMenu:!1}):t)),a||setTimeout((()=>{n.value=n.value.map((n=>Object.assign({},n,{showSubMenu:n.id===e?!n.showSubMenu:n.showSubMenu,subMenu:t&&n.id===e?{items:n.subMenu?.items.map(((e,t)=>Object.assign({},e,{selected:0===t})))}:n.subMenu})))}),50))};return{activeIndex:r((()=>i(t))),menuItems:r((()=>i(n))),toggleMenu:o,selectMenuItem:(e,t,n,a,r)=>{n?o(t,a):e&&r&&r(e)},setActiveIndex:e=>{t.value=e},resetActiveIndex:()=>{t.value=-1},updateMenuItems:e=>{n.value=e.map((e=>Object.assign({},e,{id:`menu-item-${Math.random().toString(16)}`,showSubMenu:!1})))},closeAllSubMenus:()=>{setTimeout((()=>{n.value=n.value.map((e=>Object.assign({},e,{showSubMenu:!1})))}),30)},updateSelectedItem:e=>{n.value=n.value.map(((t,n)=>Object.assign({},t,{selected:n===e})))}}}(e.data),g=a(),y=u("FloatMenu"),b=a(!1);l((()=>{const e=window.matchMedia("(prefers-reduced-motion: reduce)");b.value=e.matches;e.addEventListener("change",(e=>{b.value=e.matches})),c((()=>{if(g.value&&(g.value.focus(),s.value.length>0)){const e=s.value.findIndex((e=>!e.divider&&!e.disabled));-1!==e&&h(e)}}))}));const w=r((()=>b.value?0:300)),M=e.isTouchDevice?(()=>{const{triggerHapticFeedback:e}=q();return{triggerHapticFeedback:e}})():null,x=e=>{try{c((()=>{const t=document.querySelector(`[data-submenu-id="${e}"]`);if(t){const e=t.querySelector('[role="menuitem"]:not([aria-disabled="true"]):not(.divider)');if(e){e.focus();const t=document.createElement("div");t.setAttribute("aria-live","polite"),t.className="sr-only",t.textContent="Submenu opened",document.body.appendChild(t),setTimeout((()=>document.body.removeChild(t)),1e3)}}}))}catch(e){}},C=r((()=>({"--background":e.theme.primary,"--menu-background":e.theme.menuBgColor,"--menu-text-color":e.theme.textColor,"--text-selected-color":e.theme.textSelectedColor,"--hover-background":e.theme.hoverBackground}))),k=r((()=>`sub-menu-wrapper ${e.menuStyle}`)),S=r((()=>`menu-item-wrapper ${e.menuStyle}`)),T=r((()=>"accordion"===e.menuStyle));return l((()=>{try{g.value&&g.value.focus(),c((()=>{const t=e.data[0]?.selected;t&&h(0)}))}catch(e){}})),d(o,(e=>{f(e)})),{menuItems:s,handleMenuItemClickWithErrorHandling:(o,a,r,i,l,s,u)=>{t("menuItemClick",(()=>{n("menuItemClick");try{if(o.stopPropagation(),o.preventDefault(),s||u)return;e.isTouchDevice&&M&&M.triggerHapticFeedback("light"),h(l),i?m(a,!1):v(r,a,i,!1,e.onSelection);const t=o.currentTarget;if(t&&(t.style.outline="none",t.style.border="none",setTimeout((()=>{t&&t.classList.contains("selected")&&(t.style.outline="none",t.style.border="none")}),10)),!i&&r){const e=document.createElement("div");e.setAttribute("aria-live","polite"),e.className="sr-only",e.textContent=`Selected ${r}`,document.body.appendChild(e),setTimeout((()=>document.body.removeChild(e)),1e3)}}catch(e){}}))},SubMenuComponent:y,themeStyles:C,menuRef:g,handleKeyUpWithErrorHandling:t=>{try{t.preventDefault(),t.stopPropagation();const n=o.value,a=s.value[n>-1?n:0],r=t.key,i=e.data.length;switch(r){case"ArrowDown":if(n<i-1){let e=n+1;for(;e<i&&(s.value[e]?.divider||s.value[e]?.disabled);)e++;if(e>=i)for(e=0;e<n&&(s.value[e]?.divider||s.value[e]?.disabled);)e++;h(e)}else if(n===i-1){let e=0;for(;e<i&&(s.value[e]?.divider||s.value[e]?.disabled);)e++;e>=i&&(e=n),h(e)}break;case"ArrowUp":if(n>0){let e=n-1;for(;e>=0&&(s.value[e]?.divider||s.value[e]?.disabled);)e--;if(e<0)for(e=i-1;e>n&&(s.value[e]?.divider||s.value[e]?.disabled);)e--;h(e)}else{let e=i-1;for(;e>=0&&(s.value[e]?.divider||s.value[e]?.disabled);)e--;e<0&&(e=n),h(e)}break;case"ArrowLeft":if(a?.disabled)break;e.flip?a.subMenu&&m(a.id,!0):e.onClose("ArrowLeft");break;case"ArrowRight":if(a?.disabled)break;!e.flip&&a?.subMenu?(m(a.id||"",!0),x(a.id||"")):e.flip&&e.onClose?.("ArrowRight");break;case"Enter":if(a?.disabled)break;if(v(a?.name,a?.id||"",Boolean(a?.subMenu),!1,e.onSelection),a?.name){const e=document.createElement("div");e.setAttribute("aria-live","polite"),e.className="sr-only",e.textContent=`Selected ${a.name}`,document.body.appendChild(e),setTimeout((()=>document.body.removeChild(e)),1e3)}break;case"Escape":const t=document.createElement("div");t.setAttribute("aria-live","polite"),t.className="sr-only",t.textContent="Menu closed",document.body.appendChild(t),setTimeout((()=>document.body.removeChild(t)),1e3),e.onClose?.()}}catch(e){}},activeIndex:o,handleSubmenuClose:()=>{try{s.value.filter((e=>e.showSubMenu)).length>0?c((()=>{p(),setTimeout((()=>{g.value&&g.value.focus()}),300)})):g.value&&g.value.focus()}catch(e){}},subMenuClass:k,menuItemClass:S,isAccordion:T,handleMouseEnter:e=>{if(!b.value){const t=e.currentTarget;t&&(t.style.transform="scale(1.02)",t.style.transition="all 150ms cubic-bezier(0.25, 0.46, 0.45, 0.94)",t.style.backgroundColor="var(--hover-background, rgba(0, 0, 0, 0.05))")}},handleMouseLeave:e=>{if(!b.value){const t=e.currentTarget;t&&(t.style.transform="scale(1)",t.style.transition="all 150ms cubic-bezier(0.25, 0.46, 0.45, 0.94)",t.style.backgroundColor="")}},prefersReducedMotion:b,animationDuration:w,handleSubmenuOpen:x,handleBeforeTransitionLeave:e=>{try{if(!b.value){const e=document.createElement("div");e.setAttribute("aria-live","polite"),e.className="sr-only",e.textContent="Submenu closing",document.body.appendChild(e),setTimeout((()=>document.body.removeChild(e)),1e3)}}catch(e){}},handleAfterTransitionEnter:e=>{try{c((()=>{const t=e.querySelector('[role="menuitem"]:not([aria-disabled="true"]):not(.divider)');t&&t.focus()}))}catch(e){}}}}});const K=["aria-setsize","aria-posinset","aria-haspopup","aria-expanded","aria-disabled","onMousedown"],U={key:0,class:"menu-item-icon"},J=["data-submenu-id"],V={key:1,class:"menu-item-divider"};Y.render=function(e,a,r,i,l,s){const c=u("chev-right-icon"),d=u("plus-icon"),T=u("minus-icon");return n(),t("div",{ref:"menuRef",class:"menu-wrapper",role:"menu","aria-label":"Context menu","aria-orientation":"vertical",tabindex:"0",onKeyup:a[3]||(a[3]=(...t)=>e.handleKeyUpWithErrorHandling&&e.handleKeyUpWithErrorHandling(...t))},[o("ul",{class:"menu-list",style:m(e.themeStyles)},[(n(!0),t(v,null,h(e.menuItems,(({id:r,selected:i,name:l,subMenu:s,showSubMenu:u,disabled:E,divider:A,iconSlot:$},I)=>(n(),t("li",{key:r,class:p([{"sub-menu":s,selected:i,disabled:E,flip:e.flip,divider:A},"menu-list-item",e.menuStyle]),style:m(e.themeStyles),role:"menuitem","aria-setsize":e.menuItems.length,"aria-posinset":I+1,"aria-haspopup":s?"menu":void 0,"aria-expanded":s?!!u:void 0,"aria-disabled":!!E,tabindex:-1,onMousedown:t=>e.handleMenuItemClickWithErrorHandling(t,r||"",l||"",!!s,I,!!E,!!A),onMouseenter:a[1]||(a[1]=t=>!e.prefersReducedMotion&&e.handleMouseEnter(t)),onMouseleave:a[2]||(a[2]=t=>!e.prefersReducedMotion&&e.handleMouseLeave(t))},[A?(n(),t("span",V)):(n(),t(v,{key:0},[o("div",{class:p(e.menuItemClass),onClick:a[0]||(a[0]=e=>e.stopPropagation())},[$?(n(),t("span",U,[y(e.$slots,$)])):g("v-if",!0),o("span",{class:p(["name",{disabled:E}])},b(l),3),s?(n(),t("span",{key:1,class:p(["chev-icon",{disabled:E,"show-submenu":u},e.menuStyle])},[e.isAccordion?g("v-if",!0):(n(),w(c,{key:0})),s&&!u&&e.isAccordion?(n(),w(d,{key:1})):g("v-if",!0),s&&u&&e.isAccordion?(n(),w(T,{key:2})):g("v-if",!0)],2)):g("v-if",!0)],2),f(M,{name:e.prefersReducedMotion?"":"submenu",duration:e.animationDuration,onBeforeLeave:e.handleBeforeTransitionLeave,onAfterEnter:e.handleAfterTransitionEnter},{default:x((()=>[!E&&u?(n(),t("div",{key:0,class:p([e.subMenuClass,{"accordion-submenu":e.isAccordion}]),style:m(e.themeStyles),"data-submenu-id":r,role:"menu","aria-label":"Submenu"},[(n(),w(C(e.SubMenuComponent),{data:s?.items||[],"on-selection":e.onSelection,theme:e.theme,"on-close":e.handleSubmenuClose,flip:e.flip,"menu-style":e.menuStyle},k({_:2},[h(Object.keys(e.$slots),(t=>({name:t,fn:x((n=>[y(e.$slots,t,S({ref_for:!0},n))]))})))]),1064,["data","on-selection","theme","on-close","flip","menu-style"]))],14,J)):g("v-if",!0)])),_:2},1032,["name","duration","onBeforeLeave","onAfterEnter"])],64))],46,K)))),128))],4)],544)},Y.__scopeId="data-v-9bcc0be2",Y.__file="src/components/Menu.vue";var G=e({name:"FloatMenu",components:{MenuIcon:P,MenuComponent:Y,XIcon:_},props:{dimension:{type:Number,default:45},position:{type:String,default:"bottom right"},fixed:{type:Boolean,default:!1},menuDimension:{type:Object,default:{height:250,width:250}},menuData:{type:Array,default:[]},useCustomContent:{type:Boolean,default:!1},onSelected:{type:Function,default:null},flipOnEdges:{type:Boolean,default:!1},theme:{type:Object,required:!1,default:F},preserveMenuPosition:{type:Boolean,default:!0},menuStyle:{type:String,default:"slide-out",required:!1}},setup(e,{slots:t}){const{measurePerformance:n,markAsUsed:o}=W(),{isTouchDevice:u,handleTouchStart:d,handleTouchMove:m,handleTouchEnd:v,getSwipeDirection:h,triggerHapticFeedback:p,ensureTouchTarget:f}=q(),g=a(null),y=a(null),b=a(),w=a(),M=a(!1),x=a(),C=a(void 0),k=a("top"),S=a(!1),T=a(!1),E=a(!1),A=a(void 0!==window.ontouchstart),P=r((()=>i(A)?"touchmove":"mousemove")),O=r((()=>"touchmove"===i(P)?"accordion":e.menuStyle)),_=a(!1),B=r((()=>{const t=i(g);return t?{left:`${t.left}px`,top:`${t.top}px`,width:`${e.dimension}px`,height:`${e.dimension}px`}:{}})),L=r((()=>!Object.keys(t).length)),j=e=>{if(M.value){_.value&&(g.value=y.value);if(Array.from(e.target.classList).some((e=>"sub-menu"===e||"disabled"===e)))return;M.value=!1}},z=()=>{const t=D(e.position,e.dimension);g.value={left:Number(t.left.replace(/px/gi,"")),top:Number(t.top.replace(/px/gi,""))}},H=t=>{let n=0,o=0;if(t instanceof MouseEvent?(n=t.clientX,o=t.clientY):t instanceof TouchEvent&&(n=t.touches[0].clientX,o=t.touches[0].clientY),T.value){const t=o-Math.round(e.dimension/2);g.value={left:n-Math.round(e.dimension/2),top:t>0&&t<window.innerHeight-e.dimension?t:t<0?0:t-e.dimension}}};l((()=>{const t=D(e.position,e.dimension),n={left:Number(t.left.replace(/px/gi,"")),top:Number(t.top.replace(/px/gi,""))};g.value=n,y.value=n,window.addEventListener("click",j),window.addEventListener("resize",z),window.addEventListener("mouseup",(e=>{const t=e.target.nodeName;("#document"===t||"HTML"===t)&&(E.value=!1,T.value=!1,y.value=g.value)}),{capture:!0}),!e.fixed&&w.value&&document.addEventListener(P.value,H)})),s((()=>{window.removeEventListener("click",j),window.removeEventListener("resize",z),document.removeEventListener(P.value,H)}));const N=t=>{n("toggleMenu",(()=>{if(o("menuToggle"),T.value)return;t.stopPropagation(),t.preventDefault();if(!Array.from(t.target.classList).some((e=>"menu-list-item"===e)))if(M.value)M.value=!1,_.value&&(g.value=y.value);else{E.value=!1,T.value=!1,(()=>{const t=x.value,n=w.value,{dimension:o}=e;if(!t||!n)return;const a=$(n,t,o,e.menuDimension);k.value=a.newOrientation,C.value=a})(),(t=>{const n=i(g);if(n&&x.value){const o=I(t,n,e.flipOnEdges,x.value);S.value=o.flip,_.value=o.reveal,o.position&&(g.value=o.position)}})(b.value);const t=x.value;t&&t.getAnimations&&t.getAnimations().forEach((e=>e.cancel())),M.value=!0,c((()=>{if(x.value){const e=x.value.querySelector(".menu-wrapper");if(e){e.focus();const t=document.createElement("div");t.setAttribute("aria-live","polite"),t.className="sr-only",t.textContent="Menu opened",document.body.appendChild(t),setTimeout((()=>document.body.removeChild(t)),1e3)}}}))}}))},R=e=>{if("ArrowLeft"===e||"ArrowRight"===e)return;const t=x.value;if(t){const e=t.animate([{opacity:1,transform:"scale(1)"},{opacity:0,transform:"scale(0.95)"}],{duration:250,easing:"cubic-bezier(0.25, 0.46, 0.45, 0.94)",fill:"forwards"});if(t.getAnimations){t.getAnimations().forEach((t=>{t!==e&&t.cancel()}))}e.onfinish=()=>{M.value=!1,_.value&&(g.value=y.value),E.value=!1,T.value=!1,c((()=>{b.value&&b.value.focus()}))}}else M.value=!1,E.value=!1,T.value=!1,_.value&&(g.value=y.value),c((()=>{b.value?.focus()}))},F=r((()=>({"--background":e.theme.primary}))),X=e=>{A.value||e.preventDefault(),E.value=!0},Y=()=>{E.value&&(M.value=!1,T.value=!0)},K=t=>{let n,o;"touches"in t&&t.touches.length>0?(n=t.touches[0].clientX,o=t.touches[0].clientY):"changedTouches"in t&&t.changedTouches.length>0?(n=t.changedTouches[0].clientX,o=t.changedTouches[0].clientY):(n=t.clientX,o=t.clientY),T.value&&(y.value={left:n-Math.round(e.dimension/2),top:o-Math.round(e.dimension/2)},setTimeout((()=>{T.value=!1}),100)),E.value=!1},U=e=>{if(M.value&&("up"===e||"down"===e||"left"===e)){const t=x.value;if(t){const n="up"===e?"translateY(-20px)":"down"===e?"translateY(20px)":"translateX(-20px)";return t.animate([{opacity:1,transform:"scale(1)"},{opacity:0,transform:`scale(0.95) ${n}`}],{duration:250,easing:"cubic-bezier(0.25, 0.46, 0.45, 0.94)",fill:"forwards"}).onfinish=()=>{M.value=!1,_.value&&(g.value=y.value),c((()=>{b.value?.focus()}))},u.value&&p("light"),!0}}return!1};return c((()=>{w.value&&f(w.value)})),{menuHead:b,menuHeadContainer:w,menuContainer:x,position:g,menuActive:M,dragActive:T,isTouchDevice:u,slotsEmpty:L,menuOrientation:k,menuCSS:C,flipMenu:S,style:B,computedMenuStyle:O,getTheme:F,toggleMenu:N,handleMenuClose:R,handleCloseClick:e=>{e.stopPropagation(),e.preventDefault(),u.value&&p("light"),R()},handleMenuItemSelection:t=>{n("menuItemSelection",(()=>{o("menuItemSelection");const n=x.value;if(n){n.animate([{opacity:1,transform:"scale(1)"},{opacity:0,transform:"scale(0.95)"}],{duration:250,easing:"cubic-bezier(0.25, 0.46, 0.45, 0.94)",fill:"forwards"}).onfinish=()=>{M.value=!1,e.onSelected&&e.onSelected(t)}}else M.value=!1,e.onSelected&&e.onSelected(t)}))},handleDragStart:X,handleDragMove:Y,handleDragEnd:K,handleEnhancedTouchStart:e=>{d(e,(t=>{"longpress"===t.type&&(p("medium"),N(e))})),X(e)},handleEnhancedTouchMove:e=>{m(e),Y()},handleEnhancedTouchEnd:e=>{v(e,(t=>{if("tap"===t.type)p("light"),N(e);else if("swipe"===t.type){const e=h();e&&M.value&&U(e.direction)}})),K(e)},handleKeyboardMenuActivation:e=>{"Enter"!==e.key&&" "!==e.key&&"Space"!==e.key||(e.preventDefault(),N(e))},handleSwipeToClose:U}}});const Q=["aria-expanded"],Z={class:"menu-head-icon"};G.render=function(e,a,r,i,l,s){const c=u("MenuIcon"),d=u("XIcon"),v=u("MenuComponent");return n(),t("div",{ref:"menuHeadContainer",class:p([{dragActive:e.dragActive,"touch-device":e.isTouchDevice},"menu-head-wrapper"]),style:m(e.style),onMousedown:a[4]||(a[4]=(...t)=>e.handleDragStart&&e.handleDragStart(...t)),onMouseup:a[5]||(a[5]=(...t)=>e.handleDragEnd&&e.handleDragEnd(...t)),onMousemove:a[6]||(a[6]=(...t)=>e.handleDragMove&&e.handleDragMove(...t)),onTouchstart:a[7]||(a[7]=(...t)=>e.handleEnhancedTouchStart&&e.handleEnhancedTouchStart(...t)),onTouchend:a[8]||(a[8]=(...t)=>e.handleEnhancedTouchEnd&&e.handleEnhancedTouchEnd(...t)),onTouchmove:a[9]||(a[9]=(...t)=>e.handleEnhancedTouchMove&&e.handleEnhancedTouchMove(...t))},[o("div",{ref:"menuHead",tabindex:"0",class:p([{"menu-active":e.menuActive,"drag-active":e.dragActive},"menu-head"]),style:m(e.getTheme),draggable:"false","aria-haspopup":"menu","aria-expanded":e.menuActive,"aria-label":"Menu",onClick:a[0]||(a[0]=(...t)=>e.toggleMenu&&e.toggleMenu(...t)),onKeydown:a[1]||(a[1]=(...t)=>e.handleKeyboardMenuActivation&&e.handleKeyboardMenuActivation(...t))},[o("span",Z,[y(e.$slots,"icon"),y(e.$slots,"default"),e.slotsEmpty?(n(),w(c,{key:0})):g("v-if",!0)])],46,Q),o("div",{ref:"menuContainer",class:p([{"menu-active":e.menuActive},"menu-container"]),style:m(e.menuCSS),draggable:"false"},[o("span",{class:"close-btn",onMousedown:a[2]||(a[2]=(...t)=>e.handleCloseClick&&e.handleCloseClick(...t)),onTouchstart:a[3]||(a[3]=(...t)=>e.handleCloseClick&&e.handleCloseClick(...t))},[f(d)],32),e.menuActive?(n(),w(v,{key:0,data:e.menuData,flip:e.flipMenu,"on-selection":e.handleMenuItemSelection,theme:e.theme,"on-close":e.handleMenuClose,"menu-style":e.computedMenuStyle,"is-touch-device":e.isTouchDevice},k({_:2},[h(Object.keys(e.$slots),(t=>({name:t,fn:x((n=>[y(e.$slots,t,T(E(n)))]))})))]),1032,["data","flip","on-selection","theme","on-close","menu-style","is-touch-device"])):g("v-if",!0)],6)],38)},G.__file="src/components/index.vue";const ee=G;function te(e){e.component("FloatMenu",G)}var ne={install:te,FloatMenu:G};var oe=Object.freeze({__proto__:null,useAnimations:function(){const e=a(!1),t=a([]),n=a(!1);l((()=>{const t=window.matchMedia("(prefers-reduced-motion: reduce)");e.value=t.matches;const n=t=>{e.value=t.matches};t.addEventListener("change",n),s((()=>{t.removeEventListener("change",n)}))}));const o=(t,n=0)=>e.value?n:t,i=(t="ease-out")=>{if(e.value)return"ease";return{ease:"ease","ease-in":"cubic-bezier(0.4, 0, 1, 1)","ease-out":"cubic-bezier(0, 0, 0.2, 1)","ease-in-out":"cubic-bezier(0.4, 0, 0.2, 1)",bounce:"cubic-bezier(0.68, -0.55, 0.265, 1.55)"}[t]},u=(e,t,n={})=>{const{duration:a=300,delay:r=0,easing:l=i("ease-out"),onComplete:s}=n,u=o(a);if(0===u)return Object.entries(t).forEach((([t,n])=>{e.style.setProperty(t,String(n))})),void s?.();const c=`all ${u}ms ${l}`;function d(){Object.entries(t).forEach((([t,n])=>{e.style.setProperty(t,String(n))})),s&&setTimeout((()=>{e.style.transition="",s()}),u)}e.style.transition=c,r>0?setTimeout((()=>d()),r):d()},c=async()=>{if(0===t.value.length)return void(n.value=!1);n.value=!0;const e=t.value.shift();e&&(e(),setTimeout(c,o(100)))},d=r((()=>({"menu-enter-active":`transition-all duration-${o(200)} ${i("ease-out")}`,"menu-leave-active":`transition-all duration-${o(150)} ${i("ease-in")}`,"menu-enter-from":"opacity-0 transform scale-95","menu-enter-to":"opacity-100 transform scale-100","menu-leave-from":"opacity-100 transform scale-100","menu-leave-to":"opacity-0 transform scale-95"})));return{prefersReducedMotion:r((()=>e.value)),getAnimationDuration:o,getTimingFunction:i,animateElement:u,slideIn:(e,t="right",n=200)=>{e.style.transform={left:"translateX(-100%)",right:"translateX(100%)",up:"translateY(-100%)",down:"translateY(100%)"}[t],e.style.opacity="0",requestAnimationFrame((()=>{u(e,{transform:"translateX(0) translateY(0)",opacity:"1"},{duration:o(n),easing:i("ease-out")})}))},fadeIn:(e,t=150)=>{e.style.opacity="0",requestAnimationFrame((()=>{u(e,{opacity:"1"},{duration:o(t),easing:i("ease-out")})}))},fadeOut:(e,t=150,n)=>{u(e,{opacity:"0",transform:"scale(0.95)"},{duration:o(t),easing:i("ease-in"),onComplete:n})},scaleAnimation:(e,t=1.05,n=100)=>{u(e,{transform:`scale(${t})`},{duration:o(n),easing:i("ease-out")})},resetScale:(e,t=100)=>{u(e,{transform:"scale(1)"},{duration:o(t),easing:i("ease-out")})},createRipple:(t,n)=>{if(e.value)return;const o=t.getBoundingClientRect(),a=Math.max(o.width,o.height),r=n.clientX-o.left-a/2,i=n.clientY-o.top-a/2,l=document.createElement("span");if(l.style.cssText=`\n position: absolute;\n border-radius: 50%;\n background: rgba(255, 255, 255, 0.6);\n pointer-events: none;\n left: ${r}px;\n top: ${i}px;\n width: ${a}px;\n height: ${a}px;\n transform: scale(0);\n animation: ripple 600ms ease-out;\n `,!document.querySelector("#ripple-keyframes")){const e=document.createElement("style");e.id="ripple-keyframes",e.textContent="\n @keyframes ripple {\n 0% { transform: scale(0); opacity: 1; }\n 100% { transform: scale(1); opacity: 0; }\n }\n ",document.head.appendChild(e)}t.style.position="relative",t.style.overflow="hidden",t.appendChild(l),setTimeout((()=>{l.parentNode&&l.parentNode.removeChild(l)}),600)},queueAnimation:e=>{t.value.push(e),n.value||c()},transitionClasses:d}}});var ae=Object.freeze({__proto__:null,usePerformanceOptimizations:function(){const e=A(new Map);return{memoize:(t,n)=>(...o)=>{const a=n?n(...o):JSON.stringify(o);if(e.value.has(a))return e.value.get(a);const r=t(...o);return e.value.set(a,r),r},useLazyMenuItems:e=>{const t=a([]),n=a(0),o=()=>{const o=10*n.value,a=o+10,r=e.slice(o,a);t.value.push(...r),n.value++},i=r((()=>t.value.length<e.length));return e.length>0&&o(),{visibleItems:t,loadNextBatch:o,loadAllItems:()=>{t.value=[...e]},hasMoreItems:i}},debounce:(e,t)=>{let n;return(...o)=>{clearTimeout(n),n=window.setTimeout((()=>e(...o)),t)}},throttle:(e,t)=>{let n;return(...o)=>{n||(e(...o),n=!0,setTimeout((()=>n=!1),t))}},clearCache:()=>{e.value.clear()},getCacheSize:()=>e.value.size}}});var re=Object.freeze({__proto__:null,useErrorHandling:function(){const e=a([]),t=(t,n="error",o)=>{const a={id:`error-${Date.now()}-${Math.random().toString(36).substr(2,9)}`,message:t,type:n,timestamp:new Date,context:o};return e.value.unshift(a),e.value.length>10&&(e.value=e.value.slice(0,10)),a.id},n=e=>{if(!Array.isArray(e))return t("Menu data must be an array","error"),!1;for(let o=0;o<e.length;o++){const a=e[o];if(!a||"object"!=typeof a)return t(`Menu item at index ${o} must be an object`,"error"),!1;if(!a.name&&!a.divider)return t(`Menu item at index ${o} must have a name or be a divider`,"error"),!1;if(a.subMenu&&!Array.isArray(a.subMenu.items))return t(`Submenu items at index ${o} must be an array`,"error"),!1;if(a.subMenu?.items){if(!n(a.subMenu.items))return!1}}return!0},o=r((()=>e.value.length>0)),i=r((()=>e.value.length)),l=r((()=>e.value[0]||null)),s=r((()=>({errors:e.value.filter((e=>"error"===e.type)),warnings:e.value.filter((e=>"warning"===e.type)),info:e.value.filter((e=>"info"===e.type))})));return{errors:r((()=>e.value)),hasErrors:o,errorCount:i,latestError:l,errorsByType:s,addError:t,removeError:t=>{const n=e.value.findIndex((e=>e.id===t));n>-1&&e.value.splice(n,1)},clearErrors:()=>{e.value=[]},clearErrorsByType:t=>{e.value=e.value.filter((e=>e.type!==t))},tryAsync:async(e,n,o)=>{try{return await e()}catch(e){const a=n||`An error occurred: ${e instanceof Error?e.message:"Unknown error"}`;return t(a,"error",e),o?.(e instanceof Error?e:new Error(String(e))),null}},trySync:(e,n,o)=>{try{return e()}catch(e){const a=n||`An error occurred: ${e instanceof Error?e.message:"Unknown error"}`;return t(a,"error",e),o?.(e instanceof Error?e:new Error(String(e))),null}},validateMenuData:n,validateTheme:e=>{if(!e||"object"!=typeof e)return t("Theme must be an object","error"),!1;const n=["primary","menuBgColor","textColor","textSelectedColor","hoverBackground"];for(const o of n)o in e||t(`Theme is missing required property: ${o}`,"warning");return!0},handleDOMError:(e,n)=>{t(`DOM operation failed: ${e.message}`,"error",{error:e,element:n?.tagName})},handleKeyboardError:(e,n)=>{t(`Keyboard navigation error: ${e.message}`,"error",{error:e,keyCode:n})},handleAnimationError:(e,n)=>{t(`Animation error: ${e.message}`,"warning",{error:e,animationType:n})},getUserFriendlyMessage:e=>{const t={"Menu data must be an array":"Invalid menu configuration. Please check your menu data.","DOM operation failed":"Interface error occurred. Please try again.","Keyboard navigation error":"Navigation issue detected. Please use mouse or try again.","Animation error":"Display issue occurred. Functionality is not affected."};for(const[n,o]of Object.entries(t))if(e.message.includes(n))return o;return"An unexpected error occurred. Please try again."}}}});export{ee as FloatMenu,F as ThemeDefault,ne as default,te as install}; //# sourceMappingURL=vue-float-menu.js.map