@featherk/composables 0.6.5 → 0.6.7

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.
@@ -1 +1 @@
1
- (function(te,t){typeof exports=="object"&&typeof module<"u"?t(exports,require("vue"),require("@vueuse/integrations/useFocusTrap")):typeof define=="function"&&define.amd?define(["exports","vue","@vueuse/integrations/useFocusTrap"],t):(te=typeof globalThis<"u"?globalThis:te||self,t(te.FeatherKComposables={},te.Vue,te.useFocusTrap))})(this,(function(te,t,Ee){"use strict";const xe=e=>{const n=t.ref(null);let d=!1,P=null,L=null;const B=[],N=".k-table-row[data-grid-row-index] [tabindex]",k=()=>e?.value?.columns,b=l=>{const p=l.key||l.code;[" ","Spacebar","Space","Enter"].includes(p)&&(l.preventDefault(),l.stopPropagation(),n.value=l.target,l.target.click())},v=l=>{if(!n.value)return;if(l.code==="Escape"){l.preventDefault(),l.stopPropagation(),n.value&&n.value.focus();return}const p=Array.from(document.querySelectorAll(".k-animation-container .k-popup .k-column-menu .k-columnmenu-item-wrapper .k-columnmenu-item")),i=document.querySelector(".k-filter-menu-container");if(i){if(l.code==="Tab"){const s=[".k-filter-menu-container .k-dropdownlist[tabindex='0']",".k-filter-menu-container input.k-input-inner:not([tabindex='-1']):not([disabled])",".k-filter-menu-container button:not([tabindex='-1']):not([disabled])"],y=Array.from(i.querySelectorAll(s.join(",")));if(y.length===0)return;const A=y.findIndex($=>$===document.activeElement);let S;A===-1?S=0:l.shiftKey?S=(A-1+y.length)%y.length:S=(A+1)%y.length,l.preventDefault(),l.stopPropagation(),y[S]?.focus();return}}else if(l.code==="ArrowUp"||l.code==="ArrowDown"){l.preventDefault(),l.stopPropagation();const s=p.findIndex(A=>A===document.activeElement);let y=s;l.code==="ArrowUp"?y=s>0?s-1:p.length-1:l.code==="ArrowDown"&&(y=s<p.length-1?s+1:0),p[y]?.focus();return}l.code==="Tab"&&(l.preventDefault(),l.stopPropagation(),l.shiftKey?(n.value?.previousElementSibling).focus():(n.value?.nextElementSibling).focus())},w=()=>{P=new MutationObserver(l=>{l.forEach(p=>{p.addedNodes.forEach(i=>{if(i.nodeType===Node.ELEMENT_NODE){const s=i;if(s.classList.contains("k-animation-container")){const A=n.value;A&&(A.dataset.featherKSortable==="true"||t.nextTick(()=>{s.querySelectorAll(".k-columnmenu-item-wrapper").forEach(H=>{H.textContent?.toLowerCase().includes("sort")&&H.remove()})})),s.addEventListener("keydown",v),t.nextTick(()=>{const S=()=>{const $=Array.from(s.querySelectorAll(".k-animation-container .k-popup .k-column-menu .k-columnmenu-item-wrapper .k-columnmenu-item"));if($.length===1)$[0].focus(),$[0].click(),S.attempts=0;else if($.length>1){S.attempts=0;return}else S.attempts===void 0&&(S.attempts=0),S.attempts++<3&&setTimeout(S,200)};S()})}s.querySelectorAll(".k-animation-container").forEach(A=>{A.addEventListener("keydown",v)})}}),p.removedNodes.forEach(i=>{if(i.nodeType===Node.ELEMENT_NODE){const s=i;s.classList.contains("k-animation-container")&&s.removeEventListener("keydown",v),s.querySelectorAll(".k-animation-container").forEach(A=>{A.removeEventListener("keydown",v)})}})})}),P.observe(document.body,{childList:!0,subtree:!0})},C=l=>{if(!l.type||!l)return;const p=l.target;if(p){if(l.code==="Escape"){const i=document.activeElement?.closest(".k-table-row[data-grid-row-index]");if(i){l.preventDefault(),l.stopPropagation();try{Array.from(e?.value.$el.querySelectorAll(".k-table-row[data-grid-row-index]")).forEach(y=>y.setAttribute("tabindex","-1"))}catch{}i.setAttribute("tabindex","0"),i.focus();return}}if(["ArrowDown","ArrowLeft","ArrowRight","ArrowUp","Enter","Space"].includes(l.code)){if(l.preventDefault(),p.classList.contains("k-grid-header-menu")&&p.classList.contains("k-grid-column-menu")){n.value=p;return}const i=p.closest(".k-table-row[data-grid-row-index]");if(i){if(["ArrowDown","ArrowUp"].includes(l.code)){const s=(A,S)=>{let $=S==="next"?A.nextElementSibling:A.previousElementSibling;for(;$;){const H=$;try{if(H.hasAttribute&&H.classList.contains("k-table-row"))return H}catch{}$=S==="next"?$.nextElementSibling:$.previousElementSibling}return null},y=l.code==="ArrowDown"?s(i,"next"):s(i,"previous");y&&(i.setAttribute("tabindex","-1"),y.setAttribute("tabindex","0"),y.focus());return}if(["ArrowLeft","ArrowRight"].includes(l.code)){l.preventDefault();const s=i.querySelectorAll(N);if(s.length===0)return;let y=Array.from(s).findIndex(A=>A===document.activeElement);if(y===-1&&document.activeElement===i){s[0].focus();return}l.code==="ArrowRight"?y=y===s.length-1?0:y+1:l.code==="ArrowLeft"&&(y=y===s.length-1?y-1:s.length-1),s[y].focus();return}}}}},D=()=>{t.nextTick(()=>{const l=e.value.$el.closest(".k-grid");l&&l.classList.add("fk-grid")})},x=()=>{if(!L)try{const l=()=>{try{const s=Array.from(e.value.$el.querySelectorAll(".k-table-row[data-grid-row-index]"));if(!s||s.length===0||s.filter(S=>S.getAttribute("tabindex")==="0").length===1)return;const A=s.find(S=>S===document.activeElement||S.contains(document.activeElement));if(s.forEach(S=>S.setAttribute("tabindex","-1")),A){A.setAttribute("tabindex","0");return}s[0].setAttribute("tabindex","0")}catch(s){console.error("ensureSingleTabindex error:",s)}},p=Array.from(e.value.$el.querySelectorAll(".k-table-row[data-grid-row-index]"));p.length>0&&p.forEach((s,y)=>{s.setAttribute("tabindex",y===0?"0":"-1")});const i=e.value.$el.querySelector(".k-table-tbody");i&&(L=new MutationObserver(()=>{l()}),L.observe(i,{childList:!0,subtree:!0}))}catch(l){console.error("Error setting up row navigation:",l)}},T=()=>{t.nextTick(()=>{const p=document.querySelectorAll(".k-grid-header .k-grid-header-menu.k-grid-column-menu");p&&p.forEach(i=>{i.setAttribute("role","button"),i.addEventListener("keydown",b)}),w(),m()})},q=()=>{const p=document.querySelectorAll(".k-grid-header .k-grid-header-menu.k-grid-column-menu");p&&p.forEach(i=>{i.removeEventListener("keydown",b)}),P&&(P.disconnect(),P=null),L&&(L.disconnect(),L=null),B.forEach(i=>i()),B.length=0},m=()=>{document.querySelectorAll(".k-grid-header .k-table-thead th").forEach((i,s)=>{const y=i.querySelector(".k-grid-header-menu.k-grid-column-menu");if(!y)return;const A=k();if(A&&A[s]){const Y=A[s].field??"";i.setAttribute("data-feather-k-field",Y),i.setAttribute("data-feather-k-filterable",A[s].filterable===!1?"false":"true"),i.setAttribute("data-feather-k-sortable",A[s].sortable===!1?"false":"true")}const S=i.dataset.featherKFilterable!=="false",$=i.dataset.featherKSortable!=="false";y.setAttribute("tabindex","-1"),S||$?i.style.cursor="pointer":i.style.cursor="default",S?(i.setAttribute("tabindex","0"),i.setAttribute("role","button"),i.setAttribute("aria-haspopup","menu")):(i.setAttribute("tabindex","0"),i.setAttribute("role","columnheader"),i.removeAttribute("aria-haspopup"));const H=Y=>{Y.target?.closest(".k-column-resizer")||(n.value=i,y.click())},re=Y=>{if(S)n.value=i,Y.preventDefault(),Y.stopPropagation(),H(Y);else if($){n.value=i;const _=new KeyboardEvent("keydown",{key:"Enter",code:"Enter",keyCode:13,which:13,bubbles:!0,cancelable:!0});i.dispatchEvent(_)}};i.addEventListener("click",re),B.push(()=>{i.removeEventListener("click",re)});const z=Y=>{if((Y.code==="Enter"||Y.code==="Space")&&(S||$)){if(n.value=i,n.value.focus(),S)Y.preventDefault(),Y.stopPropagation(),H(Y);else if($){const _=i.querySelector(".k-link");_&&_.click()}}};i.addEventListener("keydown",z,!0),B.push(()=>{i.removeEventListener("keydown",z,!0)})});const p=document.querySelector(".k-grid-header .k-table-thead");if(p){const i=s=>{const y=s.target.closest("th");y&&(s.code==="Enter"||s.code==="Space")&&y.dataset.featherKFilterable==="false"&&y.dataset.featherKSortable==="false"&&(s.preventDefault(),s.stopImmediatePropagation())};p.addEventListener("keydown",i,!0),B.push(()=>{p.removeEventListener("keydown",i,!0)})}},h=function(l,p){const i=l?.event.event.target,s=k();if(!i||!s)return;const y=i.classList.contains("k-link"),A=i.classList.contains("k-columnmenu-item"),S=s.find($=>$.field===l.event.field)?.sortable&&!0;if(!y){if(A&&!S){(l.event.sort&&void 0)?.filter(H=>H.field!==l.event.field);return}typeof p=="function"&&t.nextTick(()=>{n.value&&n.value.focus(),p(l)})}},F=()=>{if(!d)try{D(),x(),T(),d=!0}catch(l){console.error("initA11y failed:",l),q()}};return t.onBeforeUnmount(()=>{q()}),{activeFilterButton:n,handleGridKeyDown:C,handleSortChange:h,initA11y:F}};function Me(e){const n=t.ref(""),d=t.ref(void 0),P=t.ref(!!e.debug),L=t.ref(e.dateFormat??"mm/dd/yyyy"),B=t.computed(()=>!!e.required),N=t.ref(!1),k=["ArrowUp","ArrowDown"],b=["ArrowLeft","ArrowRight"],v=t.computed(()=>(n.value??"").replace(/\D/g,"")),w=a=>a<=2?"mm":a<=5?"dd":v.value.length<=10?"yyyy":"mm",C=t.computed(()=>{const a=n.value&&n.value.substring(0,2).replace(/\D/g,"0")||"0";return parseInt(a).toString().padStart(2,"0")}),D=t.computed(()=>{const a=n.value&&n.value.substring(3,5).replace(/\D/g,"0")||"0";return parseInt(a).toString().padStart(2,"0")}),x=t.computed(()=>{const a=n.value&&n.value.substring(6,10).replace(/\D/g,"0")||"0";return parseInt(a).toString().padStart(4,"0")}),T=a=>{if(v.value.length===0){e.onChange({value:null,event:a});return}if(v.value.length<8){e.onChange({value:null,event:a});return}if((n.value??"").length===10&&v.value.length===8){const[f,I,Q]=n.value.split("/"),o=parseInt(f),u=parseInt(I),g=parseInt(Q);if(l(g,o,u)){const M=new Date(g,o-1,u);q(M)?e.onChange({value:M,event:a}):e.onChange({value:null,event:a})}else e.onChange({value:null,event:a})}},q=a=>{const f=e.min??void 0,I=e.max??void 0;return!(f&&a<f||I&&a>I)},m=t.computed(()=>{if((n.value??"").length===10&&v.value.length===8){const[a,f,I]=(n.value??"").split("/"),Q=parseInt(a),o=parseInt(f),u=parseInt(I);if(l(u,Q,o))return new Date(u,Q-1,o)}return null}),h=t.computed(()=>(n.value??"").length===10&&v.value.length===8),F=(a,f)=>new Date(a,f,0).getDate(),l=(a,f,I)=>f>=1&&f<=12&&a>=1900&&I>=1&&I<=F(a,f),p=a=>{n.value=a.value;const f=a.event?.target;d.value=f?.selectionStart??0,T(a)},i=a=>{d.value=a.target.selectionStart??0},s=(a,f,I)=>{const Q=f?.selectionStart??d.value??0;d.value=Q;let o=parseInt(C.value),u=parseInt(D.value),g=parseInt(x.value);if(!(v.value.length>=8)||!l(g,o,u)){const j=e.defaultValue??new Date;o=j.getMonth()+1,u=j.getDate(),g=j.getFullYear(),n.value=`${String(o).padStart(2,"0")}/${String(u).padStart(2,"0")}/${String(g)}`;const U=new Date(g,o-1,u);e.onChange({value:q(U)?U:null,event:I}),t.nextTick(()=>{requestAnimationFrame(()=>{const G=document.getElementById(e.id),X=d.value??0;G&&(G.focus(),G.setSelectionRange(X,X))})});return}const O=w(Q);if(O==="mm")o=a==="ArrowUp"?o<12?o+1:1:o>1?o-1:12;else if(O==="dd"){const j=new Date(g,o,0).getDate();u=a==="ArrowUp"?u<j?u+1:1:u>1?u-1:j}else O==="yyyy"&&(g=a==="ArrowUp"?g+1:Math.max(1,g-1));n.value=`${String(o).padStart(2,"0")}/${String(u).padStart(2,"0")}/${String(g)}`;const[ne,W,K]=n.value.split("/"),ae=new Date(parseInt(K),parseInt(ne)-1,parseInt(W));ae.toString()!=="Invalid Date"&&parseInt(K)>=1e3?e.onChange({value:q(ae)?ae:null,event:I}):e.onChange({value:null,event:I}),t.nextTick(()=>{requestAnimationFrame(()=>{const j=document.getElementById(e.id),U=d.value??0;j&&(j.focus(),j.setSelectionRange(U,U))})})},y=a=>{if(a.code==="Space"||a.key===" "){e.onShowCalendar(a);return}if(k.includes(a.key)){a.preventDefault();const f=a.target;s(a.key,f,a)}},A=a=>{a.preventDefault();const f=a.deltaY<0?"ArrowUp":"ArrowDown";s(f,a.target,a)},S=a=>{const f=a.target;if(b.includes(a.key)){d.value=f?.selectionStart??0;return}k.includes(a.key)&&(a.preventDefault(),d.value=f?.selectionStart??0)},$=a=>{N.value=!0,B.value&&!e.defaultValue&&e.externalValue&&e.externalValue.value===void 0&&v.value.length===0&&(e.externalValue.value="");const f=a.target;f&&(d.value=f.selectionStart??0)};e.externalValue&&t.watch(e.externalValue,a=>{if(a){const f=new Date(a);if(f.toString()!=="Invalid Date"){const I=(f.getMonth()+1).toString().padStart(2,"0"),Q=f.getDate().toString().padStart(2,"0"),o=f.getFullYear().toString();n.value=`${I}/${Q}/${o}`;return}}},{immediate:!0});const H=t.computed(()=>[["Date",`${C.value} / ${D.value} / ${x.value}`],["Digits only",v.value],["min",e.min?.toLocaleDateString("en-US",{year:"numeric",month:"2-digit",day:"2-digit"})??null],["max",e.max?.toLocaleDateString("en-US",{year:"numeric",month:"2-digit",day:"2-digit"})??null]]),re=t.computed(()=>{if(!B.value){if(!h.value)return!0;const f=m.value;return f?q(f):!1}if(!N.value)return!0;const a=m.value;return!h.value||!a?!1:q(a)}),z=t.computed(()=>{if(!B.value){if(!h.value)return;const f=m.value;return f?q(f)?"valid":"out-of-bounds":"invalid-date"}if(!N.value)return;if(v.value.length===0||!h.value)return"incomplete";const a=m.value;return a?q(a)?"valid":"out-of-bounds":"invalid-date"}),Y=t.computed(()=>{const a=z.value;if(!a||a==="valid")return"";if(a==="incomplete")return"Required";if(a==="invalid-date")return`Must be in ${L.value} format.`;const f=e.min?e.min.toLocaleDateString("en-US",{year:"numeric",month:"2-digit",day:"2-digit"}):null,I=e.max?e.max.toLocaleDateString("en-US",{year:"numeric",month:"2-digit",day:"2-digit"}):null;if(a==="out-of-bounds"){if(f&&I)return`Must be between ${f} and ${I}.`;if(f)return`Must be on or after ${f}.`;if(I)return`Must be on or before ${I}.`}return""}),_=()=>{t.nextTick(()=>{const a=document.getElementById(e.id);if(!a){console.warn(`ID (#${e.id}) not found for styling.`);return}const f=a.closest(".k-datepicker");if(f){const I=f.parentElement;I?I.classList.add("fk-datepicker"):console.warn(`Parent of .k-datepicker not found for #${e.id} styling.`)}else{console.warn(`.k-datepicker parent not found for #${e.id} styling.`);return}})};return t.onMounted(()=>{_()}),{raw:n,cursorPos:d,debugEnabled:P,debugLines:H,placeholder:L,isValid:re,reason:t.readonly(z),validationMessage:Y,digitsOnly:v,month:t.readonly(C),day:t.readonly(D),year:t.readonly(x),datePart:w,handleChange:p,handleKeyDown:y,handleWheel:A,handleKeyUp:S,handleClick:i,handleBlur:$}}function Te(e){const n=t.ref(""),d=t.ref(void 0),P=t.ref(!!e.debug),L=t.ref(!1),N=365*(1440*60*1e3),k=new Date,b=new Date(k.getTime()-N),v=new Date(k.getTime()+N);e.min=e.min??b,e.max=e.max??v;const w=t.computed(()=>(n.value??"").replace(/\D/g,"")),C=(r,c)=>new Date(r,c,0).getDate(),D=(r,c,E)=>c>=1&&c<=12&&r>=1e3&&E>=1&&E<=C(r,c),x=r=>Date.UTC(r.getFullYear(),r.getMonth(),r.getDate()),T=r=>{if(!r)return null;const c=e.min,E=e.max,R=x(r);return R<x(c)||R>x(E)?null:r},q=(r,c)=>e.allowReverse??!1?!0:r<=c,m=t.computed(()=>(n.value?.length??0)>=23&&w.value.length>=16),h=r=>{if((r??"").length<23||w.value.length<16)return{start:null,end:null};const c=r.substring(0,10),E=r.substring(13,23),[R,Z,oe]=c.split("/").map(ie=>parseInt(ie||"0",10)),[pe,ue,ce]=E.split("/").map(ie=>parseInt(ie||"0",10)),de=new Date(oe,R-1,Z),ye=new Date(ce,pe-1,ue),Se=D(oe,R,Z)&&de.toString()!=="Invalid Date",be=D(ce,pe,ue)&&ye.toString()!=="Invalid Date";return{start:Se?de:null,end:be?ye:null}},F=e.externalValid??t.ref(!0),l=t.computed(()=>h(n.value)),p=t.computed(()=>{const r=T(l.value.start),c=T(l.value.end);return{start:r,end:c}}),i=t.computed(()=>{if(!m.value)return;const r=p.value.start,c=p.value.end;if(!r||!c)return;const E=Math.abs(x(c)-x(r));return Math.round(E/864e5+1)}),s=t.computed(()=>{if(!m.value)return!1;const{start:r,end:c}=l.value;if(!r||!c||!p.value.start||!p.value.end)return!1;const E=p.value.start,R=p.value.end;return!(!q(E,R)||typeof e.maxSpanDays=="number"&&i.value!==void 0&&i.value>e.maxSpanDays)}),y=t.computed(()=>{const{start:r,end:c}=l.value;if(!m.value)return"incomplete";if(!r||!c)return"invalid-date";if(!p.value.start||!p.value.end)return"out-of-bounds";const E=p.value.start,R=p.value.end;return q(E,R)?typeof e.maxSpanDays=="number"&&i.value!==void 0&&i.value>e.maxSpanDays?"span-exceeds-limit":"valid":"reversed-range"}),A=t.ref(void 0),S=t.computed(()=>{if(F.value!==!1)return"";const{min:r,max:c}=e,E=A.value;if(!E)return"";switch(E){case"incomplete":return"Required";case"invalid-date":return"One or both dates invalid.";case"reversed-range":return"End Date must be on or after Start Date.";case"out-of-bounds":return r&&c?`Dates must be between ${z(r)} and ${z(c)}.`:"Dates must be within the allowed range.";case"span-exceeds-limit":return typeof e.maxSpanDays=="number"?`Date range exceeds ${e.maxSpanDays} days.`:"Date range exceeds maximum allowed span.";case"valid":default:return""}}),$=["ArrowUp","ArrowDown"],H=["ArrowLeft","ArrowRight"],re=(r,c)=>String(r).padStart(c,"0"),z=r=>`${re(r.getMonth()+1,2)}/${re(r.getDate(),2)}/${re(r.getFullYear(),4)}`,Y=r=>r<=2?{side:"start",part:"mm"}:r<=5?{side:"start",part:(r<=3,"dd")}:r<=11?{side:"start",part:"yyyy"}:r<=15?{side:"end",part:"mm"}:r<=18?{side:"end",part:"dd"}:{side:"end",part:"yyyy"},_=(r,c,E)=>{const R=c?.selectionStart??d.value??0;d.value=R;const{start:Z,end:oe}=h(n.value);if(!Z&&!oe){const V=new Date,le=z(V);n.value=`${le} - ${le}`,e.onChange({value:{start:V,end:V},event:E}),t.nextTick(()=>{requestAnimationFrame(()=>{const J=document.getElementById(e.id),ee=d.value??0;J&&(J.focus(),J.setSelectionRange(ee,ee))})});return}const pe=new Date,ue=Y(R);let ce=Z?new Date(Z):new Date(pe),de=oe?new Date(oe):new Date(pe);const ye=(V,le)=>{if(le==="mm"){const J=V.getMonth()+1,ee=r==="ArrowUp"?J<12?J+1:1:J>1?J-1:12;V.setMonth(ee-1);const ge=C(V.getFullYear(),ee);V.getDate()>ge&&V.setDate(ge)}else if(le==="dd"){const J=C(V.getFullYear(),V.getMonth()+1),ee=V.getDate(),ge=r==="ArrowUp"?ee<J?ee+1:1:ee>1?ee-1:J;V.setDate(ge)}else if(le==="yyyy"){const J=V.getFullYear();V.setFullYear(r==="ArrowUp"?J+1:Math.max(1,J-1));const ee=C(V.getFullYear(),V.getMonth()+1);V.getDate()>ee&&V.setDate(ee)}};ue.side==="start"?ye(ce,ue.part):ye(de,ue.part);const Se=z(ce),be=z(de);n.value=`${Se} - ${be}`;const ie=T(ce),we=T(de);ie&&we&&q(ie,we)?e.onChange({value:{start:ie,end:we},event:E}):e.onChange({value:null,event:E}),t.nextTick(()=>{requestAnimationFrame(()=>{const V=document.getElementById(e.id),le=d.value??0;V&&(V.focus(),V.setSelectionRange(le,le))})})},a=r=>{const{start:c,end:E}=h(n.value);if(!c||!E){e.onChange({value:null,event:r});return}const R=T(c),Z=T(E);if(!R||!Z){e.onChange({value:null,event:r});return}if(!q(R,Z)){e.onChange({value:null,event:r});return}e.onChange({value:{start:R,end:Z},event:r})},f=r=>{const c=r.value??"",E=r.event;if(!c&&E&&E.type==="click"){O(E);return}n.value=c;const R=E?.target;d.value=R?.selectionStart??0,a(r)},I=r=>{d.value=r.target.selectionStart??0},Q=r=>{if(r.code==="Space"||r.key===" "){r.preventDefault(),e.onShowCalendar(r);return}if(r.key==="ArrowDown"&&r.altKey){r.preventDefault(),e.onShowCalendar(r);return}if($.includes(r.key)){r.preventDefault();const c=r.target;_(r.key,c,r)}},o=r=>{r.preventDefault();const c=r.deltaY<0?"ArrowUp":"ArrowDown";_(c,r.target,r)},u=r=>{if(H.includes(r.key)||$.includes(r.key)){r.preventDefault();const c=r.target;d.value=c?.selectionStart??0}},g=()=>{A.value=y.value,(e.manageValid??!0)&&(F.value=s.value)},M=r=>{g()},O=r=>{console.log("Clear event:",r),n.value="",d.value=0,e.onChange({value:null,event:r}),g(),t.nextTick(()=>{const c=document.getElementById(e.id);c&&(c.focus(),c.setSelectionRange(0,0))})};e.externalValue&&t.watch(e.externalValue,r=>{const c=r?.start??null,E=r?.end??null;if(c&&E){if(n.value=`${z(c)} - ${z(E)}`,e.isOpen?.value&&L.value&&e.onRequestClose){const R=typeof e.closeDelay=="number"?e.closeDelay:e.closeDelay?.value??0;setTimeout(()=>{e.onRequestClose?.(),L.value=!1,g()},R)}return}},{immediate:!0});const ne=t.computed(()=>n.value&&n.value.substring(0,2).replace(/\D/g,"0")||"0"),W=t.computed(()=>n.value&&n.value.substring(3,5).replace(/\D/g,"0")||"0"),K=t.computed(()=>n.value&&n.value.substring(6,10).replace(/\D/g,"0")||"0"),ae=t.computed(()=>n.value&&n.value.substring(13,15).replace(/\D/g,"0")||"0"),j=t.computed(()=>n.value&&n.value.substring(16,18).replace(/\D/g,"0")||"0"),U=t.computed(()=>n.value&&n.value.substring(19,23).replace(/\D/g,"0")||"0"),G=t.computed(()=>{const{start:r,end:c}=h(n.value);return[{label:"Raw",value:n.value},{label:"Min Date",value:`${e.min?e.min.toDateString():"-"}`},{label:"Max Date",value:`${e.max?e.max.toDateString():"-"}`},{label:"Start",value:`${String(ne.value).padStart(2,"0")} / ${String(W.value).padStart(2,"0")} / ${String(K.value).padStart(4,"0")}`},{label:"End",value:`${String(ae.value).padStart(2,"0")} / ${String(j.value).padStart(2,"0")} / ${String(U.value).padStart(4,"0")}`},{label:"Digits only",value:w.value},{label:"Mask complete",value:`${m.value}`},{label:"Parsed",value:`${r?r.toDateString():"-"} | ${c?c.toDateString():"-"}`},{label:"Valid (managed)",value:`${F.value??"-"}`},{label:"Span (days)",value:`${i.value??"-"}`},{label:"Reason",value:`${y.value??"-"}`},{label:"Cursor in",value:`${d.value??"-"} (${(()=>{const E=d.value??0,R=Y(E);return`${R.side}.${R.part}`})()})`}]}),X=()=>{t.nextTick(()=>{const r=document.getElementById(e.id);if(!r){console.warn(`#${e.id} not found for styling.`);return}const c=r.closest("div");c?c.classList.add("fk-daterangepicker"):console.warn(`Parent div of #${e.id} not found for styling.`)})};t.onMounted(()=>{X()});const me=()=>{t.nextTick(()=>{try{const r=Array.from(document.querySelectorAll(".k-animation-container"));if(!r.length)return;const E=[...r].reverse().find(oe=>oe.querySelector(".k-calendar"))?.querySelector(".k-calendar");if(!E)return;const R=E.querySelectorAll(".k-calendar-table");let Z=!1;R.forEach(oe=>{oe.tabIndex===0&&(Z?oe.tabIndex=-1:Z=!0)})}catch(r){console.warn(r)}})};return e.isOpen&&t.watch(e.isOpen,r=>{r&&setTimeout(()=>me(),0)},{immediate:!1}),{raw:n,cursorPos:d,debugEnabled:P,debugLines:G,digitsOnly:w,valid:F,validComputed:t.readonly(s),reason:t.readonly(y),validationMessage:t.readonly(S),spanDays:t.readonly(i),month1:t.readonly(ne),day1:t.readonly(W),year1:t.readonly(K),month2:t.readonly(ae),day2:t.readonly(j),year2:t.readonly(U),handleChange:f,handleKeyDown:Q,handleWheel:o,handleKeyUp:u,handleClick:I,handleBlur:M,handleClear:O,onCalendarChange:()=>{L.value=!0}}}function $e(e){const n=t.ref(""),d=t.ref(void 0),P=t.ref(!!e.debug),L=t.ref(e.timeFormat??"hh:mm AM"),B=t.computed(()=>!!e.required),N=t.ref(!1),k=["ArrowUp","ArrowDown"],b=["ArrowLeft","ArrowRight"],v=t.computed(()=>(n.value??"").replace(/\D/g,"")),w={H:/[0-9]/,h:/[0-9]/,M:/[0-9]/,m:/[0-9]/,A:/[AaPp]/,a:/[Mm]/},C=o=>o<=2?"hh":o<=5?"mm":"ampm",D=t.computed(()=>{const o=n.value&&n.value.substring(0,2).replace(/\D/g,"0")||"0",u=parseInt(o);return Math.min(Math.max(u,0),23)}),x=t.computed(()=>{const o=n.value&&n.value.substring(3,5).replace(/\D/g,"0")||"0",u=parseInt(o);return Math.min(Math.max(u,0),59)}),T=t.computed(()=>(n.value?.substring(6,8)||"AM").toUpperCase().startsWith("P")?"PM":"AM"),q=t.computed(()=>{const o=parseInt(n.value?.substring(0,2).replace(/\D/g,"0")||"0"),u=T.value;return o===12?u==="AM"?0:12:u==="PM"?o+12:o}),m=t.computed(()=>h.value?`${String(q.value).padStart(2,"0")}:${String(x.value).padStart(2,"0")}:00`:null),h=t.computed(()=>/^(\d{2}):(\d{2})\s([AP]M)$/i.test(n.value??"")),F=(o,u,g)=>{let M=o%12;return M===0&&(M=12),`${String(M).padStart(2,"0")}:${String(u).padStart(2,"0")} ${g}`},l=o=>{const u=o.match(/^(\d{2}):(\d{2})\s([AP]M)$/i);if(!u)return null;const g=parseInt(u[1]),M=parseInt(u[2]),O=u[3].toUpperCase();if(g<1||g>12||M<0||M>59)return null;let ne=g%12;O==="PM"&&(ne+=12);const W=new Date;return W.setSeconds(0,0),W.setHours(ne),W.setMinutes(M),W},p=o=>{if(v.value.length===0){e.onChange({value:null,event:o});return}if(!h.value){e.onChange({value:null,event:o});return}const u=l(n.value);u&&s(u)?e.onChange({value:u,event:o}):e.onChange({value:null,event:o})},i=o=>o.getHours()*60+o.getMinutes(),s=o=>{const u=e.min??void 0,g=e.max??void 0,M=i(o);if(u){const O=i(u);if(M<O)return!1}if(g){const O=i(g);if(M>O)return!1}return!0},y=o=>{n.value=o.value;const u=o.event?.target;d.value=u?.selectionStart??0;try{const g=d.value??0;if(C(g)==="ampm"&&(n.value??"").length>=8){const M=n.value.charAt(6);/[Aa]/.test(M)?(n.value=`${n.value.slice(0,6)}AM${n.value.slice(8)}`,t.nextTick(()=>{requestAnimationFrame(()=>{const O=document.getElementById(e.id);O&&(O.focus(),O.setSelectionRange(8,8))})})):/[Pp]/.test(M)&&(n.value=`${n.value.slice(0,6)}PM${n.value.slice(8)}`,t.nextTick(()=>{requestAnimationFrame(()=>{const O=document.getElementById(e.id);O&&(O.focus(),O.setSelectionRange(8,8))})}))}}catch{}p(o)},A=o=>{d.value=o.target.selectionStart??0},S=(o,u,g)=>{const M=u?.selectionStart??d.value??0;d.value=M;const O=C(M),ne=(n.value??"").match(/^(\d{2}):(\d{2})\s([AP]M)$/i);if(!ne){if((n.value??"").length===0||v.value.length===0){const U=new Date,G=U.getHours(),X=G>=12?"PM":"AM";n.value=F(G,U.getMinutes(),X);const me=l(n.value);me&&s(me)?e.onChange({value:me,event:g}):e.onChange({value:null,event:g}),t.nextTick(()=>{requestAnimationFrame(()=>{const r=document.getElementById(e.id),c=d.value??0;r&&(r.focus(),r.setSelectionRange(c,c))})})}return}let W=parseInt(ne[1]),K=parseInt(ne[2]),ae=ne[3].toUpperCase();if(O==="hh")o==="ArrowUp"?W=W<12?W+1:1:W=W>1?W-1:12;else if(O==="mm"){const U=e.minuteStepRef?.value??e.minuteStep??1;if(U===1)o==="ArrowUp"?K=K<59?K+1:0:K=K>0?K-1:59;else if(o==="ArrowUp"){const G=K%U;let X=G===0?K+U:K+(U-G);X>=60&&(X=0),K=X}else{const G=K%U;let X=G===0?K-U:K-G;X<0&&(X=60-U),K=X}}else O==="ampm"&&(ae=ae==="AM"?"PM":"AM");n.value=`${String(W).padStart(2,"0")}:${String(K).padStart(2,"0")} ${ae}`;const j=l(n.value);j&&s(j)?e.onChange({value:j,event:g}):e.onChange({value:null,event:g}),t.nextTick(()=>{requestAnimationFrame(()=>{const U=document.getElementById(e.id),G=d.value??0;U&&(U.focus(),U.setSelectionRange(G,G))})})},$=o=>{if(o.code==="Space"||o.key===" "){e.onShowPicker(o);return}if(k.includes(o.key)){o.preventDefault();const u=o.target;S(o.key,u,o)}},H=o=>{o.preventDefault();const u=o.deltaY<0?"ArrowUp":"ArrowDown";S(u,o.target,o)},re=o=>{const u=o.target;if(b.includes(o.key)){d.value=u?.selectionStart??0;return}k.includes(o.key)&&(o.preventDefault(),d.value=u?.selectionStart??0)},z=o=>{N.value=!0,B.value&&e.externalValue&&e.externalValue.value===void 0&&v.value.length===0&&(e.externalValue.value="");const u=o.target;u&&(d.value=u.selectionStart??0)};e.externalValue&&t.watch(e.externalValue,o=>{if(o){const u=new Date(o);if(u.toString()!=="Invalid Date"){const g=u.getHours(),M=g>=12?"PM":"AM";n.value=F(g,u.getMinutes(),M);return}}},{immediate:!0});const Y=t.computed(()=>[["Time",n.value||"--:-- --"],["Hour (12h)",D.value],["Hour (24h)",q.value],["Minute",x.value],["Period",T.value],["Time (24h)",m.value??"--:--:--"],["Digits only",v.value],["Parsed Date",_.value?.toLocaleDateString("en-US",{hour:"2-digit",minute:"2-digit"})??null],["min",e.min?.toLocaleTimeString("en-US",{hour:"2-digit",minute:"2-digit"})??null],["max",e.max?.toLocaleTimeString("en-US",{hour:"2-digit",minute:"2-digit"})??null],["valid",a.value],["reason",f.value],["validationMessage",I.value]]),_=t.computed(()=>l(n.value)??null),a=t.computed(()=>{if(!B.value){if(!h.value)return!0;const u=_.value;return u?s(u):!1}if(!N.value)return!0;const o=_.value;return!h.value||!o?!1:s(o)}),f=t.computed(()=>{if(!B.value){if(!h.value)return;const u=_.value;return u?s(u)?"valid":"out-of-bounds":"invalid-time"}if(!N.value)return;if(v.value.length===0||!h.value)return"incomplete";const o=_.value;return o?s(o)?"valid":"out-of-bounds":"invalid-time"}),I=t.computed(()=>{const o=f.value;if(!o||o==="valid")return"";if(o==="incomplete")return"Required";if(o==="invalid-time")return`Must be in ${L.value} format.`;const u={hour:"2-digit",minute:"2-digit"},g=e.min?e.min.toLocaleTimeString("en-US",u):null,M=e.max?e.max.toLocaleTimeString("en-US",u):null;if(o==="out-of-bounds"){if(g&&M)return`Must be between ${g} and ${M}.`;if(g)return`Must be ${g} or later.`;if(M)return`Must be ${M} or earlier.`}return""}),Q=()=>{t.nextTick(()=>{const o=document.getElementById(e.id);if(!o){console.warn(`#${e.id} not found for styling.`);return}const u=o.closest(".k-timepicker");if(!u)console.warn(`.k-timepicker parent of #${e.id} not found for styling.`);else{const g=u.parentElement;g?g.classList.add("fk-timepicker"):console.warn(`Parent of .k-timepicker not found for #${e.id} styling.`)}})};return t.onMounted(()=>{Q()}),{raw:n,rules:w,debugEnabled:P,debugLines:Y,placeholder:L,isValid:a,reason:t.readonly(f),validationMessage:I,isComplete:h,inRangeTime:s,cursorPos:d,hour:t.readonly(D),hour24:t.readonly(q),minute:t.readonly(x),period:t.readonly(T),time24:t.readonly(m),parsedRawTime:t.readonly(_),handleChange:y,handleKeyDown:$,handleKeyUp:re,handleClick:A,handleWheel:H,handleBlur:z}}function Ie(e){return t.getCurrentScope()?(t.onScopeDispose(e),!0):!1}const ke=typeof window<"u"&&typeof document<"u";typeof WorkerGlobalScope<"u"&&globalThis instanceof WorkerGlobalScope;const Ce=Object.prototype.toString,Pe=e=>Ce.call(e)==="[object Object]",se=()=>{},Le=qe();function qe(){var e,n;return ke&&((e=window?.navigator)==null?void 0:e.userAgent)&&(/iP(?:ad|hone|od)/.test(window.navigator.userAgent)||((n=window?.navigator)==null?void 0:n.maxTouchPoints)>2&&/iPad|Macintosh/.test(window?.navigator.userAgent))}function he(e){return Array.isArray(e)?e:[e]}function Re(e,n,d){return t.watch(e,n,{...d,immediate:!0})}const De=ke?window:void 0;function fe(e){var n;const d=t.toValue(e);return(n=d?.$el)!=null?n:d}function ve(...e){const n=[],d=()=>{n.forEach(k=>k()),n.length=0},P=(k,b,v,w)=>(k.addEventListener(b,v,w),()=>k.removeEventListener(b,v,w)),L=t.computed(()=>{const k=he(t.toValue(e[0])).filter(b=>b!=null);return k.every(b=>typeof b!="string")?k:void 0}),B=Re(()=>{var k,b;return[(b=(k=L.value)==null?void 0:k.map(v=>fe(v)))!=null?b:[De].filter(v=>v!=null),he(t.toValue(L.value?e[1]:e[0])),he(t.unref(L.value?e[2]:e[1])),t.toValue(L.value?e[3]:e[2])]},([k,b,v,w])=>{if(d(),!k?.length||!b?.length||!v?.length)return;const C=Pe(w)?{...w}:w;n.push(...k.flatMap(D=>b.flatMap(x=>v.map(T=>P(D,x,T,C)))))},{flush:"post"}),N=()=>{B(),d()};return Ie(d),N}let Ae=!1;function Fe(e,n,d={}){const{window:P=De,ignore:L=[],capture:B=!0,detectIframe:N=!1,controls:k=!1}=d;if(!P)return k?{stop:se,cancel:se,trigger:se}:se;if(Le&&!Ae){Ae=!0;const m={passive:!0};Array.from(P.document.body.children).forEach(h=>h.addEventListener("click",se,m)),P.document.documentElement.addEventListener("click",se,m)}let b=!0;const v=m=>t.toValue(L).some(h=>{if(typeof h=="string")return Array.from(P.document.querySelectorAll(h)).some(F=>F===m.target||m.composedPath().includes(F));{const F=fe(h);return F&&(m.target===F||m.composedPath().includes(F))}});function w(m){const h=t.toValue(m);return h&&h.$.subTree.shapeFlag===16}function C(m,h){const F=t.toValue(m),l=F.$.subTree&&F.$.subTree.children;return l==null||!Array.isArray(l)?!1:l.some(p=>p.el===h.target||h.composedPath().includes(p.el))}const D=m=>{const h=fe(e);if(m.target!=null&&!(!(h instanceof Element)&&w(e)&&C(e,m))&&!(!h||h===m.target||m.composedPath().includes(h))){if("detail"in m&&m.detail===0&&(b=!v(m)),!b){b=!0;return}n(m)}};let x=!1;const T=[ve(P,"click",m=>{x||(x=!0,setTimeout(()=>{x=!1},0),D(m))},{passive:!0,capture:B}),ve(P,"pointerdown",m=>{const h=fe(e);b=!v(m)&&!!(h&&!m.composedPath().includes(h))},{passive:!0}),N&&ve(P,"blur",m=>{setTimeout(()=>{var h;const F=fe(e);((h=P.document.activeElement)==null?void 0:h.tagName)==="IFRAME"&&!F?.contains(P.document.activeElement)&&n(m)},0)},{passive:!0})].filter(Boolean),q=()=>T.forEach(m=>m());return k?{stop:q,cancel:()=>{b=!1},trigger:m=>{b=!0,D(m),b=!1}}:q}function Oe(e){const n=t.shallowRef(null),d=[".k-animation-container .k-popup",".k-popup",".k-timepicker-popup",".k-menu-popup"],P=Array.isArray(e.popupSelector)?e.popupSelector:[e.popupSelector??d].flat(),L=w=>w?typeof e.initialFocus=="string"?w.querySelector(e.initialFocus)??w:typeof e.initialFocus=="function"?e.initialFocus(w)??w:w.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])')??w:null,{activate:B,deactivate:N}=Ee.useFocusTrap(n,{escapeDeactivates:!1,clickOutsideDeactivates:!1,fallbackFocus:()=>n.value,initialFocus:()=>L(n.value),...e.focusTrapOptions??{}});let k=null,b=t.ref(null);const v=()=>{if(e.resolvePopupEl)return e.resolvePopupEl();const w=(D,x)=>{const T=Array.from(D.querySelectorAll(x));if(!T.length)return null;const q=T.filter(m=>m.offsetParent!==null||m.getClientRects().length>0);return q[q.length-1]??T[T.length-1]??null},C=e.triggerEl?.value?.closest?.(".k-animation-container")??document.body;for(const D of P){const x=w(C,D);if(x)return x}for(const D of P){const x=w(document,D);if(x)return x}return null};return Fe(n,w=>{b.value="outside",e.isOpen.value&&e.onRequestClose?.("outside",w)}),t.watch(()=>e.isOpen.value,w=>{w?(b.value=null,t.nextTick(()=>{const C=v();C&&(n.value=C,setTimeout(()=>B(),0),k||(k=D=>{D.key==="Escape"&&(b.value="escape",e.isOpen.value&&e.onRequestClose?.("escape",D))},document.addEventListener("keydown",k,!0)))})):(N(),k&&(document.removeEventListener("keydown",k,!0),k=null),n.value=null,b.value==="outside"&&t.nextTick(()=>{const C=()=>{const D=e.triggerEl?.value,x=D?.querySelector("input"),T=document.activeElement;T&&(T===x||D&&D.contains(T))&&(x??D)?.blur?.()};requestAnimationFrame(()=>setTimeout(C,0))}),e.returnFocusToTrigger!==!1&&b.value==="escape"&&e.triggerEl?.value&&(console.log("Returning focus to trigger element:",e.triggerEl.value),t.nextTick(()=>{const C=()=>{const D=e.triggerEl?.value;if(!D)return;(D.querySelector("input")??D)?.focus?.()};requestAnimationFrame(()=>setTimeout(C,0))})))}),{popupRef:n,activate:B,deactivate:N,lastCloseReason:t.readonly(b),setPopupEl:w=>n.value=w}}te.useGridA11y=xe,te.useMaskedDateInput=Me,te.useMaskedDateRangeInput=Te,te.useMaskedTimeInput=$e,te.usePopupTrap=Oe,Object.defineProperty(te,Symbol.toStringTag,{value:"Module"})}));
1
+ (function(J,t){typeof exports=="object"&&typeof module<"u"?t(exports,require("vue"),require("@vueuse/integrations/useFocusTrap")):typeof define=="function"&&define.amd?define(["exports","vue","@vueuse/integrations/useFocusTrap"],t):(J=typeof globalThis<"u"?globalThis:J||self,t(J.FeatherKComposables={},J.Vue,J.useFocusTrap))})(this,(function(J,t,xe){"use strict";const Me=(e,n)=>{const u=t.ref(null);let q=!1,$=null,F=null;const K=[],A=".k-table-row[data-grid-row-index] [tabindex]",w=()=>e?.value?.columns,S=l=>{const y=l.key||l.code;[" ","Spacebar","Space","Enter"].includes(y)&&(l.preventDefault(),l.stopPropagation(),u.value=l.target,l.target.click())},v=l=>{if(!u.value)return;if(l.code==="Escape"){l.stopPropagation(),u.value&&u.value.focus();return}const y=Array.from(document.querySelectorAll(".k-animation-container .k-popup .k-column-menu .k-columnmenu-item-wrapper .k-columnmenu-item")),i=document.querySelector(".k-animation-container .k-popup .k-column-menu .k-filter-menu-container");if(i){if(l.code==="Tab"){const c=[".k-filter-menu-container .k-dropdownlist[tabindex='0']",".k-filter-menu-container input.k-input-inner:not([tabindex='-1']):not([disabled])",".k-filter-menu-container button:not([tabindex='-1']):not([disabled])",".k-checkbox"],g=n?.focusableMenuSelectors??c,b=Array.from(i.querySelectorAll(g.join(",")));if(b.length===0)return;const D=b.findIndex(N=>N===document.activeElement);let C;D===-1?C=0:l.shiftKey?C=(D-1+b.length)%b.length:C=(D+1)%b.length,l.preventDefault(),l.stopPropagation(),b[C]?.focus()}}else if(l.code==="ArrowUp"||l.code==="ArrowDown"){l.preventDefault(),l.stopPropagation();const c=y.findIndex(b=>b===document.activeElement);let g=c;l.code==="ArrowUp"?g=c>0?c-1:y.length-1:l.code==="ArrowDown"&&(g=c<y.length-1?c+1:0),y[g]?.focus();return}if(l.code==="Tab"){l.preventDefault(),l.stopPropagation();const c=u.value?.parentElement;(l.shiftKey?c?.previousElementSibling:c?.nextElementSibling)?.querySelector("button, [role='button'], .k-link")?.focus()}},L=()=>{$=new MutationObserver(l=>{l.forEach(y=>{y.addedNodes.forEach(i=>{if(i.nodeType===Node.ELEMENT_NODE){const c=i;if(c.classList.contains("k-animation-container")){const b=u.value;b&&(b.dataset.featherKSortable==="true"||t.nextTick(()=>{c.querySelectorAll(".k-columnmenu-item-wrapper").forEach(N=>{N.textContent?.toLowerCase().includes("sort")&&N.remove()})})),c.addEventListener("keydown",v),t.nextTick(()=>{const D=()=>{const C=Array.from(c.querySelectorAll(".k-animation-container .k-popup .k-column-menu .k-columnmenu-item-wrapper .k-columnmenu-item"));if(C.length===1)C[0].focus(),C[0].click(),D.attempts=0;else if(C.length>1){D.attempts=0;return}else D.attempts===void 0&&(D.attempts=0),D.attempts++<3&&setTimeout(D,200)};D()})}c.querySelectorAll(".k-animation-container").forEach(b=>{b.addEventListener("keydown",v)})}}),y.removedNodes.forEach(i=>{if(i.nodeType===Node.ELEMENT_NODE){const c=i;c.classList.contains("k-animation-container")&&c.removeEventListener("keydown",v),c.querySelectorAll(".k-animation-container").forEach(b=>{b.removeEventListener("keydown",v)})}})})}),$.observe(document.body,{childList:!0,subtree:!0})},E=l=>{if(!l.type||!l)return;const y=l.target;if(y){if(l.code==="Escape"){const i=document.activeElement?.closest(".k-table-row[data-grid-row-index]");if(i){l.preventDefault(),l.stopPropagation();try{Array.from(e?.value.$el.querySelectorAll(".k-table-row[data-grid-row-index]")).forEach(g=>g.setAttribute("tabindex","-1"))}catch{}i.setAttribute("tabindex","0"),i.focus();return}}if(["ArrowDown","ArrowLeft","ArrowRight","ArrowUp","Enter","Space"].includes(l.code)){if(l.preventDefault(),y.classList.contains("k-grid-header-menu")&&y.classList.contains("k-grid-column-menu")){u.value=y;return}const i=y.closest(".k-table-row[data-grid-row-index]");if(i){if(["ArrowDown","ArrowUp"].includes(l.code)){const c=(b,D)=>{let C=D==="next"?b.nextElementSibling:b.previousElementSibling;for(;C;){const N=C;try{if(N.hasAttribute&&N.classList.contains("k-table-row"))return N}catch{}C=D==="next"?C.nextElementSibling:C.previousElementSibling}return null},g=l.code==="ArrowDown"?c(i,"next"):c(i,"previous");g&&(i.setAttribute("tabindex","-1"),g.setAttribute("tabindex","0"),g.focus());return}if(["ArrowLeft","ArrowRight"].includes(l.code)){l.preventDefault();const c=i.querySelectorAll(A);if(c.length===0)return;let g=Array.from(c).findIndex(b=>b===document.activeElement);if(g===-1&&document.activeElement===i){c[0].focus();return}l.code==="ArrowRight"?g=g===c.length-1?0:g+1:l.code==="ArrowLeft"&&(g=g===c.length-1?g-1:c.length-1),c[g].focus();return}}}}},T=()=>{t.nextTick(()=>{const l=e.value.$el.closest(".k-grid");l&&l.classList.add("fk-grid")})},I=()=>{if(!F)try{const l=()=>{try{const c=Array.from(e.value.$el.querySelectorAll(".k-table-row[data-grid-row-index]"));if(!c||c.length===0||c.filter(D=>D.getAttribute("tabindex")==="0").length===1)return;const b=c.find(D=>D===document.activeElement||D.contains(document.activeElement));if(c.forEach(D=>D.setAttribute("tabindex","-1")),b){b.setAttribute("tabindex","0");return}c[0].setAttribute("tabindex","0")}catch(c){console.error("ensureSingleTabindex error:",c)}},y=Array.from(e.value.$el.querySelectorAll(".k-table-row[data-grid-row-index]"));y.length>0&&y.forEach((c,g)=>{c.setAttribute("tabindex",g===0?"0":"-1")});const i=e.value.$el.querySelector(".k-table-tbody");i&&(F=new MutationObserver(()=>{l()}),F.observe(i,{childList:!0,subtree:!0}))}catch(l){console.error("Error setting up row navigation:",l)}},O=()=>{t.nextTick(()=>{const y=document.querySelectorAll(".k-grid-header .k-grid-header-menu.k-grid-column-menu");y&&y.forEach(i=>{i.setAttribute("role","button"),i.addEventListener("keydown",S)}),L(),h()})},p=()=>{const y=document.querySelectorAll(".k-grid-header .k-grid-header-menu.k-grid-column-menu");y&&y.forEach(i=>{i.removeEventListener("keydown",S)}),$&&($.disconnect(),$=null),F&&(F.disconnect(),F=null),K.forEach(i=>i()),K.length=0},h=()=>{document.querySelectorAll(".k-grid-header .k-table-thead th").forEach((i,c)=>{const g=i.querySelector(".k-grid-header-menu.k-grid-column-menu");if(!g)return;const b=w();if(b&&b[c]){const P=b[c].field??"";i.setAttribute("data-feather-k-field",P),i.setAttribute("data-feather-k-filterable",b[c].filterable===!1?"false":"true"),i.setAttribute("data-feather-k-sortable",b[c].sortable===!1?"false":"true")}const D=i.dataset.featherKFilterable!=="false",C=i.dataset.featherKSortable!=="false";g.setAttribute("tabindex","-1"),D||C?i.style.cursor="pointer":i.style.cursor="default",D?(i.setAttribute("tabindex","0"),i.setAttribute("role","button"),i.setAttribute("aria-haspopup","menu")):(i.setAttribute("tabindex","0"),i.setAttribute("role","columnheader"),i.removeAttribute("aria-haspopup"));const N=P=>{P.target?.closest(".k-column-resizer")||(u.value=i,g.click())},_=P=>{if(D)u.value=i,P.preventDefault(),P.stopPropagation(),N(P);else if(C){u.value=i;const ee=new KeyboardEvent("keydown",{key:"Enter",code:"Enter",keyCode:13,which:13,bubbles:!0,cancelable:!0});i.dispatchEvent(ee)}};i.addEventListener("click",_),K.push(()=>{i.removeEventListener("click",_)});const re=P=>{if((P.code==="Enter"||P.code==="Space")&&(D||C)){if(u.value=i,u.value.focus(),D)P.preventDefault(),P.stopPropagation(),N(P);else if(C){const ee=i.querySelector(".k-link");ee&&ee.click()}}};i.addEventListener("keydown",re,!0),K.push(()=>{i.removeEventListener("keydown",re,!0)})});const y=document.querySelector(".k-grid-header .k-table-thead");if(y){const i=c=>{const g=c.target.closest("th");g&&(c.code==="Enter"||c.code==="Space")&&g.dataset.featherKFilterable==="false"&&g.dataset.featherKSortable==="false"&&(c.preventDefault(),c.stopImmediatePropagation())};y.addEventListener("keydown",i,!0),K.push(()=>{y.removeEventListener("keydown",i,!0)})}},U=function(l,y){const i=l?.event.event.target,c=w();if(!i||!c)return;const g=i.classList.contains("k-link"),b=i.classList.contains("k-columnmenu-item"),D=c.find(C=>C.field===l.event.field)?.sortable&&!0;if(!g){if(b&&!D){(l.event.sort&&void 0)?.filter(N=>N.field!==l.event.field);return}typeof y=="function"&&t.nextTick(()=>{u.value&&u.value.focus(),y(l)})}},j=()=>{if(!q)try{T(),I(),O(),q=!0}catch(l){console.error("initA11y failed:",l),p()}};return t.onBeforeUnmount(()=>{p()}),{activeFilterButton:u,handleGridKeyDown:E,handleSortChange:U,initA11y:j}};function Te(e){const n=t.ref(""),u=t.ref(void 0),q=t.ref(!!e.debug),$=t.ref(e.dateFormat??"mm/dd/yyyy"),F=t.computed(()=>!!e.required),K=t.ref(!1),A=["ArrowUp","ArrowDown"],w=["ArrowLeft","ArrowRight"],S=t.computed(()=>(n.value??"").replace(/\D/g,"")),v=a=>a<=2?"mm":a<=5?"dd":S.value.length<=10?"yyyy":"mm",L=t.computed(()=>{const a=n.value&&n.value.substring(0,2).replace(/\D/g,"0")||"0";return parseInt(a).toString().padStart(2,"0")}),E=t.computed(()=>{const a=n.value&&n.value.substring(3,5).replace(/\D/g,"0")||"0";return parseInt(a).toString().padStart(2,"0")}),T=t.computed(()=>{const a=n.value&&n.value.substring(6,10).replace(/\D/g,"0")||"0";return parseInt(a).toString().padStart(4,"0")}),I=a=>{if(S.value.length===0){e.onChange({value:null,event:a});return}if(S.value.length<8){e.onChange({value:null,event:a});return}if((n.value??"").length===10&&S.value.length===8){const[f,M,o]=n.value.split("/"),s=parseInt(f),m=parseInt(M),k=parseInt(o);if(j(k,s,m)){const V=new Date(k,s-1,m);O(V)?e.onChange({value:V,event:a}):e.onChange({value:null,event:a})}else e.onChange({value:null,event:a})}},O=a=>{const f=e.min??void 0,M=e.max??void 0;return!(f&&a<f||M&&a>M)},p=t.computed(()=>{if((n.value??"").length===10&&S.value.length===8){const[a,f,M]=(n.value??"").split("/"),o=parseInt(a),s=parseInt(f),m=parseInt(M);if(j(m,o,s))return new Date(m,o-1,s)}return null}),h=t.computed(()=>(n.value??"").length===10&&S.value.length===8),U=(a,f)=>new Date(a,f,0).getDate(),j=(a,f,M)=>f>=1&&f<=12&&a>=1900&&M>=1&&M<=U(a,f),l=a=>{n.value=a.value;const f=a.event?.target;u.value=f?.selectionStart??0,I(a)},y=a=>{u.value=a.target.selectionStart??0},i=(a,f,M)=>{const o=f?.selectionStart??u.value??0;u.value=o;let s=parseInt(L.value),m=parseInt(E.value),k=parseInt(T.value);if(!(S.value.length>=8)||!j(k,s,m)){const B=e.defaultValue??new Date;s=B.getMonth()+1,m=B.getDate(),k=B.getFullYear(),n.value=`${String(s).padStart(2,"0")}/${String(m).padStart(2,"0")}/${String(k)}`;const W=new Date(k,s-1,m);e.onChange({value:O(W)?W:null,event:M}),C({useRAF:!0});return}const z=v(o);if(z==="mm")s=a==="ArrowUp"?s<12?s+1:1:s>1?s-1:12;else if(z==="dd"){const B=new Date(k,s,0).getDate();m=a==="ArrowUp"?m<B?m+1:1:m>1?m-1:B}else z==="yyyy"&&(k=a==="ArrowUp"?k+1:Math.max(1,k-1));n.value=`${String(s).padStart(2,"0")}/${String(m).padStart(2,"0")}/${String(k)}`;const[G,H,ae]=n.value.split("/"),oe=new Date(parseInt(ae),parseInt(G)-1,parseInt(H));oe.toString()!=="Invalid Date"&&parseInt(ae)>=1e3?e.onChange({value:O(oe)?oe:null,event:M}):e.onChange({value:null,event:M}),C({useRAF:!0})},c=a=>{if(a.code==="Space"||a.key===" "){e.onShowCalendar(a);return}if(A.includes(a.key)){if(a.altKey)return;a.preventDefault();const f=a.target;i(a.key,f,a)}},g=a=>{a.preventDefault();const f=a.deltaY<0?"ArrowUp":"ArrowDown";i(f,a.target,a)},b=a=>{const f=a.target;if(w.includes(a.key)){u.value=f?.selectionStart??0;return}if(A.includes(a.key)){if(a.altKey)return;a.preventDefault(),u.value=f?.selectionStart??0}},D=a=>{K.value=!0,F.value&&!e.defaultValue&&e.externalValue&&e.externalValue.value===void 0&&S.value.length===0&&(e.externalValue.value="");const f=a.target;f&&(u.value=f.selectionStart??0)},C=a=>{const f=()=>{const M=document.getElementById(e.id);if(!M)return;const o=a?.pos??u.value??M.value.length;try{M.focus(),M.setSelectionRange(o,o)}catch{}};t.nextTick(()=>{if(a?.delay&&a.delay>0){setTimeout(f,a.delay);return}if(a?.useRAF){requestAnimationFrame(f);return}f()})};e.externalValue&&t.watch(e.externalValue,a=>{if(a){const f=new Date(a);if(f.toString()!=="Invalid Date"){const M=(f.getMonth()+1).toString().padStart(2,"0"),o=f.getDate().toString().padStart(2,"0"),s=f.getFullYear().toString();n.value=`${M}/${o}/${s}`,C({delay:50});return}}},{immediate:!0});const N=t.computed(()=>[["Date",`${L.value} / ${E.value} / ${T.value}`],["Digits only",S.value],["min",e.min?.toLocaleDateString("en-US",{year:"numeric",month:"2-digit",day:"2-digit"})??null],["max",e.max?.toLocaleDateString("en-US",{year:"numeric",month:"2-digit",day:"2-digit"})??null]]),_=t.computed(()=>{if(!F.value){if(!h.value)return!0;const f=p.value;return f?O(f):!1}if(!K.value)return!0;const a=p.value;return!h.value||!a?!1:O(a)}),re=t.computed(()=>{if(!F.value){if(!h.value)return;const f=p.value;return f?O(f)?"valid":"out-of-bounds":"invalid-date"}if(!K.value)return;if(S.value.length===0||!h.value)return"incomplete";const a=p.value;return a?O(a)?"valid":"out-of-bounds":"invalid-date"}),P=t.computed(()=>{const a=re.value;if(!a||a==="valid")return"";if(a==="incomplete")return"Required";if(a==="invalid-date")return`Must be in ${$.value} format.`;const f=e.min?e.min.toLocaleDateString("en-US",{year:"numeric",month:"2-digit",day:"2-digit"}):null,M=e.max?e.max.toLocaleDateString("en-US",{year:"numeric",month:"2-digit",day:"2-digit"}):null;if(a==="out-of-bounds"){if(f&&M)return`Must be between ${f} and ${M}.`;if(f)return`Must be on or after ${f}.`;if(M)return`Must be on or before ${M}.`}return""}),ee=()=>{t.nextTick(()=>{const a=document.getElementById(e.id);if(!a){console.warn(`ID (#${e.id}) not found for styling.`);return}const f=a.closest(".k-datepicker");if(!f){console.warn(`.k-datepicker parent not found for #${e.id} styling.`);return}const M=f.parentElement;if(M){if(M.classList.contains("fk-datepicker"))return;M.classList.add("fk-datepicker")}else console.warn(`Parent of .k-datepicker not found for #${e.id} styling.`)})};return t.onMounted(()=>{ee()}),{raw:n,cursorPos:u,debugEnabled:q,debugLines:N,placeholder:$,isValid:_,reason:t.readonly(re),validationMessage:P,digitsOnly:S,month:t.readonly(L),day:t.readonly(E),year:t.readonly(T),datePart:v,handleChange:l,handleKeyDown:c,handleWheel:g,handleKeyUp:b,handleClick:y,handleBlur:D,initStyling:ee}}function Ce(e){const n=t.ref(""),u=t.ref(void 0),q=t.ref(!!e.debug),$=t.ref(!1),K=365*(1440*60*1e3),A=new Date,w=new Date(A.getTime()-K),S=new Date(A.getTime()+K);e.min=e.min??w,e.max=e.max??S;const v=t.computed(()=>(n.value??"").replace(/\D/g,"")),L=(r,d)=>new Date(r,d,0).getDate(),E=(r,d,x)=>d>=1&&d<=12&&r>=1e3&&x>=1&&x<=L(r,d),T=r=>Date.UTC(r.getFullYear(),r.getMonth(),r.getDate()),I=r=>{if(!r)return null;const d=e.min,x=e.max,R=T(r);return R<T(d)||R>T(x)?null:r},O=(r,d)=>e.allowReverse??!1?!0:r<=d,p=t.computed(()=>(n.value?.length??0)>=23&&v.value.length>=16),h=r=>{if((r??"").length<23||v.value.length<16)return{start:null,end:null};const d=r.substring(0,10),x=r.substring(13,23),[R,Q,ne]=d.split("/").map(ie=>parseInt(ie||"0",10)),[me,ue,ce]=x.split("/").map(ie=>parseInt(ie||"0",10)),de=new Date(ne,R-1,Q),ye=new Date(ce,me-1,ue),be=E(ne,R,Q)&&de.toString()!=="Invalid Date",Se=E(ce,me,ue)&&ye.toString()!=="Invalid Date";return{start:be?de:null,end:Se?ye:null}},U=e.externalValid??t.ref(!0),j=t.computed(()=>h(n.value)),l=t.computed(()=>{const r=I(j.value.start),d=I(j.value.end);return{start:r,end:d}}),y=t.computed(()=>{if(!p.value)return;const r=l.value.start,d=l.value.end;if(!r||!d)return;const x=Math.abs(T(d)-T(r));return Math.round(x/864e5+1)}),i=t.computed(()=>{if(!p.value)return!1;const{start:r,end:d}=j.value;if(!r||!d||!l.value.start||!l.value.end)return!1;const x=l.value.start,R=l.value.end;return!(!O(x,R)||typeof e.maxSpanDays=="number"&&y.value!==void 0&&y.value>e.maxSpanDays)}),c=t.computed(()=>{const{start:r,end:d}=j.value;if(!p.value)return"incomplete";if(!r||!d)return"invalid-date";if(!l.value.start||!l.value.end)return"out-of-bounds";const x=l.value.start,R=l.value.end;return O(x,R)?typeof e.maxSpanDays=="number"&&y.value!==void 0&&y.value>e.maxSpanDays?"span-exceeds-limit":"valid":"reversed-range"}),g=t.ref(void 0),b=t.computed(()=>{if(U.value!==!1)return"";const{min:r,max:d}=e,x=g.value;if(!x)return"";switch(x){case"incomplete":return"Required";case"invalid-date":return"One or both dates invalid.";case"reversed-range":return"End Date must be on or after Start Date.";case"out-of-bounds":return r&&d?`Dates must be between ${_(r)} and ${_(d)}.`:"Dates must be within the allowed range.";case"span-exceeds-limit":return typeof e.maxSpanDays=="number"?`Date range exceeds ${e.maxSpanDays} days.`:"Date range exceeds maximum allowed span.";case"valid":default:return""}}),D=["ArrowUp","ArrowDown"],C=["ArrowLeft","ArrowRight"],N=(r,d)=>String(r).padStart(d,"0"),_=r=>`${N(r.getMonth()+1,2)}/${N(r.getDate(),2)}/${N(r.getFullYear(),4)}`,re=r=>r<=2?{side:"start",part:"mm"}:r<=5?{side:"start",part:(r<=3,"dd")}:r<=11?{side:"start",part:"yyyy"}:r<=15?{side:"end",part:"mm"}:r<=18?{side:"end",part:"dd"}:{side:"end",part:"yyyy"},P=(r,d,x)=>{const R=d?.selectionStart??u.value??0;u.value=R;const{start:Q,end:ne}=h(n.value);if(!Q&&!ne){const Y=new Date,le=_(Y);n.value=`${le} - ${le}`,e.onChange({value:{start:Y,end:Y},event:x}),t.nextTick(()=>{requestAnimationFrame(()=>{const X=document.getElementById(e.id),Z=u.value??0;X&&(X.focus(),X.setSelectionRange(Z,Z))})});return}const me=new Date,ue=re(R);let ce=Q?new Date(Q):new Date(me),de=ne?new Date(ne):new Date(me);const ye=(Y,le)=>{if(le==="mm"){const X=Y.getMonth()+1,Z=r==="ArrowUp"?X<12?X+1:1:X>1?X-1:12;Y.setMonth(Z-1);const ge=L(Y.getFullYear(),Z);Y.getDate()>ge&&Y.setDate(ge)}else if(le==="dd"){const X=L(Y.getFullYear(),Y.getMonth()+1),Z=Y.getDate(),ge=r==="ArrowUp"?Z<X?Z+1:1:Z>1?Z-1:X;Y.setDate(ge)}else if(le==="yyyy"){const X=Y.getFullYear();Y.setFullYear(r==="ArrowUp"?X+1:Math.max(1,X-1));const Z=L(Y.getFullYear(),Y.getMonth()+1);Y.getDate()>Z&&Y.setDate(Z)}};ue.side==="start"?ye(ce,ue.part):ye(de,ue.part);const be=_(ce),Se=_(de);n.value=`${be} - ${Se}`;const ie=I(ce),ke=I(de);ie&&ke&&O(ie,ke)?e.onChange({value:{start:ie,end:ke},event:x}):e.onChange({value:null,event:x}),t.nextTick(()=>{requestAnimationFrame(()=>{const Y=document.getElementById(e.id),le=u.value??0;Y&&(Y.focus(),Y.setSelectionRange(le,le))})})},ee=r=>{const{start:d,end:x}=h(n.value);if(!d||!x){e.onChange({value:null,event:r});return}const R=I(d),Q=I(x);if(!R||!Q){e.onChange({value:null,event:r});return}if(!O(R,Q)){e.onChange({value:null,event:r});return}e.onChange({value:{start:R,end:Q},event:r})},a=r=>{const d=r.value??"",x=r.event;if(!d&&x&&x.type==="click"){V(x);return}n.value=d;const R=x?.target;u.value=R?.selectionStart??0,ee(r)},f=r=>{u.value=r.target.selectionStart??0},M=r=>{if(r.code==="Space"||r.key===" "){r.preventDefault(),e.onShowCalendar(r);return}if(r.key==="ArrowDown"&&r.altKey){r.preventDefault(),e.onShowCalendar(r);return}if(D.includes(r.key)){r.preventDefault();const d=r.target;P(r.key,d,r)}},o=r=>{r.preventDefault();const d=r.deltaY<0?"ArrowUp":"ArrowDown";P(d,r.target,r)},s=r=>{if(C.includes(r.key)||D.includes(r.key)){r.preventDefault();const d=r.target;u.value=d?.selectionStart??0}},m=()=>{g.value=c.value,(e.manageValid??!0)&&(U.value=i.value)},k=r=>{m()},V=r=>{console.log("Clear event:",r),n.value="",u.value=0,e.onChange({value:null,event:r}),m(),t.nextTick(()=>{const d=document.getElementById(e.id);d&&(d.focus(),d.setSelectionRange(0,0))})};e.externalValue&&t.watch(e.externalValue,r=>{const d=r?.start??null,x=r?.end??null;if(d&&x){if(n.value=`${_(d)} - ${_(x)}`,e.isOpen?.value&&$.value&&e.onRequestClose){const R=typeof e.closeDelay=="number"?e.closeDelay:e.closeDelay?.value??0;setTimeout(()=>{e.onRequestClose?.(),$.value=!1,m()},R)}return}},{immediate:!0});const z=t.computed(()=>n.value&&n.value.substring(0,2).replace(/\D/g,"0")||"0"),G=t.computed(()=>n.value&&n.value.substring(3,5).replace(/\D/g,"0")||"0"),H=t.computed(()=>n.value&&n.value.substring(6,10).replace(/\D/g,"0")||"0"),ae=t.computed(()=>n.value&&n.value.substring(13,15).replace(/\D/g,"0")||"0"),oe=t.computed(()=>n.value&&n.value.substring(16,18).replace(/\D/g,"0")||"0"),B=t.computed(()=>n.value&&n.value.substring(19,23).replace(/\D/g,"0")||"0"),W=t.computed(()=>{const{start:r,end:d}=h(n.value);return[{label:"Raw",value:n.value},{label:"Min Date",value:`${e.min?e.min.toDateString():"-"}`},{label:"Max Date",value:`${e.max?e.max.toDateString():"-"}`},{label:"Start",value:`${String(z.value).padStart(2,"0")} / ${String(G.value).padStart(2,"0")} / ${String(H.value).padStart(4,"0")}`},{label:"End",value:`${String(ae.value).padStart(2,"0")} / ${String(oe.value).padStart(2,"0")} / ${String(B.value).padStart(4,"0")}`},{label:"Digits only",value:v.value},{label:"Mask complete",value:`${p.value}`},{label:"Parsed",value:`${r?r.toDateString():"-"} | ${d?d.toDateString():"-"}`},{label:"Valid (managed)",value:`${U.value??"-"}`},{label:"Span (days)",value:`${y.value??"-"}`},{label:"Reason",value:`${c.value??"-"}`},{label:"Cursor in",value:`${u.value??"-"} (${(()=>{const x=u.value??0,R=re(x);return`${R.side}.${R.part}`})()})`}]}),te=()=>{t.nextTick(()=>{const r=document.getElementById(e.id);if(!r){console.warn(`#${e.id} not found for styling.`);return}const d=r.closest("div");if(!d){console.warn(`Parent div of #${e.id} not found for styling.`);return}d.classList.contains("fk-daterangepicker")||d.classList.add("fk-daterangepicker")})};t.onMounted(()=>{te()});const pe=()=>{t.nextTick(()=>{try{const r=Array.from(document.querySelectorAll(".k-animation-container"));if(!r.length)return;const x=[...r].reverse().find(ne=>ne.querySelector(".k-calendar"))?.querySelector(".k-calendar");if(!x)return;const R=x.querySelectorAll(".k-calendar-table");let Q=!1;R.forEach(ne=>{ne.tabIndex===0&&(Q?ne.tabIndex=-1:Q=!0)})}catch(r){console.warn(r)}})};return e.isOpen&&t.watch(e.isOpen,r=>{r&&setTimeout(()=>pe(),0)},{immediate:!1}),{raw:n,cursorPos:u,debugEnabled:q,debugLines:W,digitsOnly:v,valid:U,validComputed:t.readonly(i),reason:t.readonly(c),validationMessage:t.readonly(b),spanDays:t.readonly(y),month1:t.readonly(z),day1:t.readonly(G),year1:t.readonly(H),month2:t.readonly(ae),day2:t.readonly(oe),year2:t.readonly(B),handleChange:a,handleKeyDown:M,handleWheel:o,handleKeyUp:s,handleClick:f,handleBlur:k,handleClear:V,onCalendarChange:()=>{$.value=!0},initStyling:te}}function $e(e){const n=t.ref(""),u=t.ref(void 0),q=t.ref(!!e.debug),$=t.ref(e.timeFormat??"hh:mm AM"),F=t.computed(()=>!!e.required),K=t.ref(!1),A=["ArrowUp","ArrowDown"],w=["ArrowLeft","ArrowRight"],S=t.computed(()=>(n.value??"").replace(/\D/g,"")),v={H:/[0-9]/,h:/[0-9]/,M:/[0-9]/,m:/[0-9]/,A:/[AaPp]/,a:/[Mm]/},L=o=>o<=2?"hh":o<=5?"mm":"ampm",E=t.computed(()=>{const o=n.value&&n.value.substring(0,2).replace(/\D/g,"0")||"0",s=parseInt(o);return Math.min(Math.max(s,0),23)}),T=t.computed(()=>{const o=n.value&&n.value.substring(3,5).replace(/\D/g,"0")||"0",s=parseInt(o);return Math.min(Math.max(s,0),59)}),I=t.computed(()=>(n.value?.substring(6,8)||"AM").toUpperCase().startsWith("P")?"PM":"AM"),O=t.computed(()=>{const o=parseInt(n.value?.substring(0,2).replace(/\D/g,"0")||"0"),s=I.value;return o===12?s==="AM"?0:12:s==="PM"?o+12:o}),p=t.computed(()=>h.value?`${String(O.value).padStart(2,"0")}:${String(T.value).padStart(2,"0")}:00`:null),h=t.computed(()=>/^(\d{2}):(\d{2})\s([AP]M)$/i.test(n.value??"")),U=(o,s,m)=>{let k=o%12;return k===0&&(k=12),`${String(k).padStart(2,"0")}:${String(s).padStart(2,"0")} ${m}`},j=o=>{const s=o.match(/^(\d{2}):(\d{2})\s([AP]M)$/i);if(!s)return null;const m=parseInt(s[1]),k=parseInt(s[2]),V=s[3].toUpperCase();if(m<1||m>12||k<0||k>59)return null;let z=m%12;V==="PM"&&(z+=12);const G=new Date;return G.setSeconds(0,0),G.setHours(z),G.setMinutes(k),G},l=o=>{if(S.value.length===0){e.onChange({value:null,event:o});return}if(!h.value){e.onChange({value:null,event:o});return}const s=j(n.value);s&&i(s)?e.onChange({value:s,event:o}):e.onChange({value:null,event:o})},y=o=>o.getHours()*60+o.getMinutes(),i=o=>{const s=e.min??void 0,m=e.max??void 0,k=y(o);if(s){const V=y(s);if(k<V)return!1}if(m){const V=y(m);if(k>V)return!1}return!0},c=o=>{n.value=o.value;const s=o.event?.target;u.value=s?.selectionStart??0;try{const m=u.value??0;if(L(m)==="ampm"&&(n.value??"").length>=8){const k=n.value.charAt(6);/[Aa]/.test(k)?(n.value=`${n.value.slice(0,6)}AM${n.value.slice(8)}`,t.nextTick(()=>{requestAnimationFrame(()=>{const V=document.getElementById(e.id);V&&(V.focus(),V.setSelectionRange(8,8))})})):/[Pp]/.test(k)&&(n.value=`${n.value.slice(0,6)}PM${n.value.slice(8)}`,t.nextTick(()=>{requestAnimationFrame(()=>{const V=document.getElementById(e.id);V&&(V.focus(),V.setSelectionRange(8,8))})}))}}catch{}l(o)},g=o=>{u.value=o.target.selectionStart??0},b=(o,s,m)=>{const k=s?.selectionStart??u.value??0;u.value=k;const V=L(k),z=(n.value??"").match(/^(\d{2}):(\d{2})\s([AP]M)$/i);if(!z){if((n.value??"").length===0||S.value.length===0){const B=new Date,W=B.getHours(),te=W>=12?"PM":"AM";n.value=U(W,B.getMinutes(),te);const pe=j(n.value);pe&&i(pe)?e.onChange({value:pe,event:m}):e.onChange({value:null,event:m}),t.nextTick(()=>{requestAnimationFrame(()=>{const r=document.getElementById(e.id),d=u.value??0;r&&(r.focus(),r.setSelectionRange(d,d))})})}return}let G=parseInt(z[1]),H=parseInt(z[2]),ae=z[3].toUpperCase();if(V==="hh")o==="ArrowUp"?G=G<12?G+1:1:G=G>1?G-1:12;else if(V==="mm"){const B=e.minuteStepRef?.value??e.minuteStep??1;if(B===1)o==="ArrowUp"?H=H<59?H+1:0:H=H>0?H-1:59;else if(o==="ArrowUp"){const W=H%B;let te=W===0?H+B:H+(B-W);te>=60&&(te=0),H=te}else{const W=H%B;let te=W===0?H-B:H-W;te<0&&(te=60-B),H=te}}else V==="ampm"&&(ae=ae==="AM"?"PM":"AM");n.value=`${String(G).padStart(2,"0")}:${String(H).padStart(2,"0")} ${ae}`;const oe=j(n.value);oe&&i(oe)?e.onChange({value:oe,event:m}):e.onChange({value:null,event:m}),t.nextTick(()=>{requestAnimationFrame(()=>{const B=document.getElementById(e.id),W=u.value??0;B&&(B.focus(),B.setSelectionRange(W,W))})})},D=o=>{if(o.code==="Space"||o.key===" "){e.onShowPicker(o);return}if(A.includes(o.key)){o.preventDefault();const s=o.target;b(o.key,s,o)}},C=o=>{o.preventDefault();const s=o.deltaY<0?"ArrowUp":"ArrowDown";b(s,o.target,o)},N=o=>{const s=o.target;if(w.includes(o.key)){u.value=s?.selectionStart??0;return}A.includes(o.key)&&(o.preventDefault(),u.value=s?.selectionStart??0)},_=o=>{K.value=!0,F.value&&e.externalValue&&e.externalValue.value===void 0&&S.value.length===0&&(e.externalValue.value="");const s=o.target;s&&(u.value=s.selectionStart??0)};e.externalValue&&t.watch(e.externalValue,o=>{if(o){const s=new Date(o);if(s.toString()!=="Invalid Date"){const m=s.getHours(),k=m>=12?"PM":"AM";n.value=U(m,s.getMinutes(),k);return}}},{immediate:!0});const re=t.computed(()=>[["Time",n.value||"--:-- --"],["Hour (12h)",E.value],["Hour (24h)",O.value],["Minute",T.value],["Period",I.value],["Time (24h)",p.value??"--:--:--"],["Digits only",S.value],["Parsed Date",P.value?.toLocaleDateString("en-US",{hour:"2-digit",minute:"2-digit"})??null],["min",e.min?.toLocaleTimeString("en-US",{hour:"2-digit",minute:"2-digit"})??null],["max",e.max?.toLocaleTimeString("en-US",{hour:"2-digit",minute:"2-digit"})??null],["valid",ee.value],["reason",a.value],["validationMessage",f.value]]),P=t.computed(()=>j(n.value)??null),ee=t.computed(()=>{if(!F.value){if(!h.value)return!0;const s=P.value;return s?i(s):!1}if(!K.value)return!0;const o=P.value;return!h.value||!o?!1:i(o)}),a=t.computed(()=>{if(!F.value){if(!h.value)return;const s=P.value;return s?i(s)?"valid":"out-of-bounds":"invalid-time"}if(!K.value)return;if(S.value.length===0||!h.value)return"incomplete";const o=P.value;return o?i(o)?"valid":"out-of-bounds":"invalid-time"}),f=t.computed(()=>{const o=a.value;if(!o||o==="valid")return"";if(o==="incomplete")return"Required";if(o==="invalid-time")return`Must be in ${$.value} format.`;const s={hour:"2-digit",minute:"2-digit"},m=e.min?e.min.toLocaleTimeString("en-US",s):null,k=e.max?e.max.toLocaleTimeString("en-US",s):null;if(o==="out-of-bounds"){if(m&&k)return`Must be between ${m} and ${k}.`;if(m)return`Must be ${m} or later.`;if(k)return`Must be ${k} or earlier.`}return""}),M=()=>{t.nextTick(()=>{const o=document.getElementById(e.id);if(!o){console.warn(`#${e.id} not found for styling.`);return}const s=o.closest(".k-timepicker");if(!s){console.warn(`.k-timepicker parent of #${e.id} not found for styling.`);return}const m=s.parentElement;if(!m){console.warn(`Parent of .k-timepicker not found for #${e.id} styling.`);return}m.classList.contains("fk-timepicker")||m.classList.add("fk-timepicker")})};return t.onMounted(()=>{M()}),{raw:n,rules:v,debugEnabled:q,debugLines:re,placeholder:$,isValid:ee,reason:t.readonly(a),validationMessage:f,isComplete:h,inRangeTime:i,cursorPos:u,hour:t.readonly(E),hour24:t.readonly(O),minute:t.readonly(T),period:t.readonly(I),time24:t.readonly(p),parsedRawTime:t.readonly(P),handleChange:c,handleKeyDown:D,handleKeyUp:N,handleClick:g,handleWheel:C,handleBlur:_,initStyling:M}}function Ie(e){return t.getCurrentScope()?(t.onScopeDispose(e),!0):!1}const we=typeof window<"u"&&typeof document<"u";typeof WorkerGlobalScope<"u"&&globalThis instanceof WorkerGlobalScope;const Fe=Object.prototype.toString,Le=e=>Fe.call(e)==="[object Object]",se=()=>{},Pe=Re();function Re(){var e,n;return we&&((e=window?.navigator)==null?void 0:e.userAgent)&&(/iP(?:ad|hone|od)/.test(window.navigator.userAgent)||((n=window?.navigator)==null?void 0:n.maxTouchPoints)>2&&/iPad|Macintosh/.test(window?.navigator.userAgent))}function he(e){return Array.isArray(e)?e:[e]}function qe(e,n,u){return t.watch(e,n,{...u,immediate:!0})}const De=we?window:void 0;function fe(e){var n;const u=t.toValue(e);return(n=u?.$el)!=null?n:u}function ve(...e){const n=[],u=()=>{n.forEach(A=>A()),n.length=0},q=(A,w,S,v)=>(A.addEventListener(w,S,v),()=>A.removeEventListener(w,S,v)),$=t.computed(()=>{const A=he(t.toValue(e[0])).filter(w=>w!=null);return A.every(w=>typeof w!="string")?A:void 0}),F=qe(()=>{var A,w;return[(w=(A=$.value)==null?void 0:A.map(S=>fe(S)))!=null?w:[De].filter(S=>S!=null),he(t.toValue($.value?e[1]:e[0])),he(t.unref($.value?e[2]:e[1])),t.toValue($.value?e[3]:e[2])]},([A,w,S,v])=>{if(u(),!A?.length||!w?.length||!S?.length)return;const L=Le(v)?{...v}:v;n.push(...A.flatMap(E=>w.flatMap(T=>S.map(I=>q(E,T,I,L)))))},{flush:"post"}),K=()=>{F(),u()};return Ie(u),K}let Ae=!1;function Oe(e,n,u={}){const{window:q=De,ignore:$=[],capture:F=!0,detectIframe:K=!1,controls:A=!1}=u;if(!q)return A?{stop:se,cancel:se,trigger:se}:se;if(Pe&&!Ae){Ae=!0;const p={passive:!0};Array.from(q.document.body.children).forEach(h=>h.addEventListener("click",se,p)),q.document.documentElement.addEventListener("click",se,p)}let w=!0;const S=p=>t.toValue($).some(h=>{if(typeof h=="string")return Array.from(q.document.querySelectorAll(h)).some(U=>U===p.target||p.composedPath().includes(U));{const U=fe(h);return U&&(p.target===U||p.composedPath().includes(U))}});function v(p){const h=t.toValue(p);return h&&h.$.subTree.shapeFlag===16}function L(p,h){const U=t.toValue(p),j=U.$.subTree&&U.$.subTree.children;return j==null||!Array.isArray(j)?!1:j.some(l=>l.el===h.target||h.composedPath().includes(l.el))}const E=p=>{const h=fe(e);if(p.target!=null&&!(!(h instanceof Element)&&v(e)&&L(e,p))&&!(!h||h===p.target||p.composedPath().includes(h))){if("detail"in p&&p.detail===0&&(w=!S(p)),!w){w=!0;return}n(p)}};let T=!1;const I=[ve(q,"click",p=>{T||(T=!0,setTimeout(()=>{T=!1},0),E(p))},{passive:!0,capture:F}),ve(q,"pointerdown",p=>{const h=fe(e);w=!S(p)&&!!(h&&!p.composedPath().includes(h))},{passive:!0}),K&&ve(q,"blur",p=>{setTimeout(()=>{var h;const U=fe(e);((h=q.document.activeElement)==null?void 0:h.tagName)==="IFRAME"&&!U?.contains(q.document.activeElement)&&n(p)},0)},{passive:!0})].filter(Boolean),O=()=>I.forEach(p=>p());return A?{stop:O,cancel:()=>{w=!1},trigger:p=>{w=!0,E(p),w=!1}}:O}function Ue(e){const n=t.shallowRef(null),u=[".k-animation-container .k-popup",".k-popup",".k-timepicker-popup",".k-menu-popup"],q=Array.isArray(e.popupSelector)?e.popupSelector:[e.popupSelector??u].flat(),$=v=>v?typeof e.initialFocus=="string"?v.querySelector(e.initialFocus)??v:typeof e.initialFocus=="function"?e.initialFocus(v)??v:v.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])')??v:null,{activate:F,deactivate:K}=xe.useFocusTrap(n,{escapeDeactivates:!1,clickOutsideDeactivates:!1,fallbackFocus:()=>n.value,initialFocus:()=>$(n.value),...e.focusTrapOptions??{}});let A=null,w=t.ref(null);const S=()=>{if(e.resolvePopupEl)return e.resolvePopupEl();const v=(E,T)=>{const I=Array.from(E.querySelectorAll(T));if(!I.length)return null;const O=I.filter(p=>p.offsetParent!==null||p.getClientRects().length>0);return O[O.length-1]??I[I.length-1]??null},L=e.triggerEl?.value?.closest?.(".k-animation-container")??document.body;for(const E of q){const T=v(L,E);if(T)return T}for(const E of q){const T=v(document,E);if(T)return T}return null};return Oe(n,v=>{w.value="outside",e.isOpen.value&&e.onRequestClose?.("outside",v)}),t.watch(()=>e.isOpen.value,v=>{v?(w.value=null,t.nextTick(()=>{const L=S();L&&(n.value=L,setTimeout(()=>F(),0),A||(A=E=>{E.key==="Escape"&&(w.value="escape",e.isOpen.value&&e.onRequestClose?.("escape",E))},document.addEventListener("keydown",A,!0)))})):(K(),A&&(document.removeEventListener("keydown",A,!0),A=null),n.value=null,w.value==="outside"&&t.nextTick(()=>{const L=()=>{const E=e.triggerEl?.value,T=E?.querySelector("input"),I=document.activeElement;I&&(I===T||E&&E.contains(I))&&(T??E)?.blur?.()};requestAnimationFrame(()=>setTimeout(L,0))}),e.returnFocusToTrigger!==!1&&w.value==="escape"&&e.triggerEl?.value&&(console.log("Returning focus to trigger element:",e.triggerEl.value),t.nextTick(()=>{const L=()=>{const E=e.triggerEl?.value;if(!E)return;(E.querySelector("input")??E)?.focus?.()};requestAnimationFrame(()=>setTimeout(L,0))})))}),{popupRef:n,activate:F,deactivate:K,lastCloseReason:t.readonly(w),setPopupEl:v=>n.value=v}}const Ve=e=>!!e&&typeof e=="object"&&"filters"in e&&Array.isArray(e.filters),Be=e=>!!e&&typeof e=="object"&&"field"in e,Ee=(e,n)=>!e||typeof e!="object"?!1:Ve(e)?e.filters.some(u=>Ee(u,n)):Be(e)?e.field===n:!1,Ke=e=>{const n=t.ref({}),u=$=>!e.value||!e.value.filters?!1:e.value.filters.some(F=>Ee(F,$));return{activeClasses:n,hasFieldFilter:u,updateActiveClass:$=>{const F=u($);console.log("updateActiveClass for",$,"hasFilter:",F),n.value[$]=F?"active":"",console.log("activeClasses after update",n.value)}}};J.useGridA11y=Me,J.useGridFilter=Ke,J.useMaskedDateInput=Te,J.useMaskedDateRangeInput=Ce,J.useMaskedTimeInput=$e,J.usePopupTrap=Ue,Object.defineProperty(J,Symbol.toStringTag,{value:"Module"})}));
package/dist/index.d.ts CHANGED
@@ -6,3 +6,4 @@ export type { RangeChangePayload } from "./range";
6
6
  export { useMaskedTimeInput } from "./time";
7
7
  export type { ChangePayload as TimeChangePayload } from "./time";
8
8
  export { usePopupTrap } from "./trap";
9
+ export { useGridFilter } from "./useGridFilter";
@@ -47,4 +47,5 @@ export declare function useMaskedDateRangeInput(args: {
47
47
  handleBlur: (_event: FocusEvent) => void;
48
48
  handleClear: (event?: Event) => void;
49
49
  onCalendarChange: () => void;
50
+ initStyling: () => void;
50
51
  };
@@ -47,4 +47,5 @@ export declare function useMaskedTimeInput(args: {
47
47
  handleClick: (event: MouseEvent) => void;
48
48
  handleWheel: (event: WheelEvent) => void;
49
49
  handleBlur: (event: FocusEvent) => void;
50
+ initStyling: () => void;
50
51
  };
@@ -6,7 +6,9 @@
6
6
  */
7
7
  import { type Ref } from "vue";
8
8
  import type { GridSortChangeEvent } from "./types/kendo";
9
- export declare const useGridA11y: (gridRef: Ref<any>) => {
9
+ export declare const useGridA11y: (gridRef: Ref<any>, options?: {
10
+ focusableMenuSelectors?: string[];
11
+ }) => {
10
12
  activeFilterButton: Ref<HTMLElement, HTMLElement>;
11
13
  handleGridKeyDown: (e: KeyboardEvent) => void;
12
14
  handleSortChange: (event?: GridSortChangeEvent, customHandler?: any) => void;
@@ -0,0 +1,7 @@
1
+ import { type Ref } from "vue";
2
+ import type { CompositeFilterDescriptor } from "@progress/kendo-data-query";
3
+ export declare const useGridFilter: (filterRef: Ref<CompositeFilterDescriptor | undefined>) => {
4
+ activeClasses: Ref<Record<string, string>, Record<string, string>>;
5
+ hasFieldFilter: (field: string) => boolean;
6
+ updateActiveClass: (field: string) => void;
7
+ };
@@ -22,10 +22,11 @@ import { ref } from "vue";
22
22
  import { DatePicker } from "@progress/kendo-vue-dateinputs";
23
23
  import { MaskedTextBox } from "@progress/kendo-vue-inputs";
24
24
  import { Error } from "@progress/kendo-vue-labels";
25
- import { useMaskedDateInput } from "@featherk/composables/date";
25
+ import { useMaskedDateInput, usePopupTrap } from "@featherk/composables";
26
26
 
27
27
  const selectedDate = ref<Date | null | undefined>();
28
28
  const showPicker = ref(false);
29
+ const pickerRoot = ref<HTMLElement | null>(null);
29
30
 
30
31
  const MIN_DATE = new Date(2024, 0, 1);
31
32
  const MAX_DATE = new Date(2026, 11, 31);
@@ -43,46 +44,55 @@ const masked = useMaskedDateInput({
43
44
 
44
45
  // Destructure only values used as component props
45
46
  // (avoids .value in templates while keeping handlers namespaced)
46
- const { isValid, validationMessage, debugEnabled, debugLines } = masked;
47
+ const { debugEnabled, debugLines, isValid, placeholder, raw, validationMessage } = masked;
48
+
49
+ // Integrate focus trap for the DatePicker popup
50
+ usePopupTrap({
51
+ isOpen: showPicker,
52
+ onRequestClose: () => (showPicker.value = false),
53
+ triggerEl: pickerRoot,
54
+ });
47
55
  </script>
48
56
 
49
57
  <template>
50
- <DatePicker
51
- v-model="selectedDate"
52
- dateInput="masked"
53
- :min="MIN_DATE"
54
- :max="MAX_DATE"
55
- :valid="isValid"
56
- :show="showPicker"
57
- :validationMessage="validationMessage"
58
- @open="showPicker = true"
59
- @close="showPicker = false"
60
- >
61
- <template #masked="{ props }">
62
- <div data-ref-id="custom-date-input" class="custom-date-input">
63
- <MaskedTextBox
64
- id="startDate"
65
- class="masked-date-input"
66
- :mask="'00/00/0000'"
67
- :value="masked.raw"
68
- :placeholder="masked.placeholder"
69
- :showClearButton="false"
70
- @change="masked.handleChange"
71
- @keydown="masked.handleKeyDown"
72
- @keyup="masked.handleKeyUp"
73
- @click="masked.handleClick"
74
- @wheel="masked.handleWheel"
75
- @blur="(e) => { masked.handleBlur(e); props.onBlur(); }"
76
- />
77
-
78
- <div v-if="debugEnabled" class="composable-debugging debug-info">
79
- <div v-for="(row, idx) in debugLines" :key="idx">
80
- <strong>{{ row[0] }}:</strong> {{ row[1] }}
58
+ <div ref="pickerRoot">
59
+ <DatePicker
60
+ v-model="selectedDate"
61
+ dateInput="masked"
62
+ :min="MIN_DATE"
63
+ :max="MAX_DATE"
64
+ :valid="isValid"
65
+ :show="showPicker"
66
+ :validationMessage="validationMessage"
67
+ @open="showPicker = true"
68
+ @close="showPicker = false"
69
+ >
70
+ <template #masked="{ props }">
71
+ <div data-ref-id="custom-date-input" class="custom-date-input">
72
+ <MaskedTextBox
73
+ id="startDate"
74
+ class="masked-date-input"
75
+ :mask="'00/00/0000'"
76
+ :value="raw"
77
+ :placeholder="placeholder"
78
+ :showClearButton="false"
79
+ @change="masked.handleChange"
80
+ @keydown="masked.handleKeyDown"
81
+ @keyup="masked.handleKeyUp"
82
+ @click="masked.handleClick"
83
+ @wheel="masked.handleWheel"
84
+ @blur="masked.handleBlur"
85
+ />
86
+
87
+ <div v-if="debugEnabled" class="composable-debugging debug-info">
88
+ <div v-for="(row, idx) in debugLines" :key="idx">
89
+ <strong>{{ row[0] }}:</strong> {{ row[1] }}
90
+ </div>
81
91
  </div>
82
92
  </div>
83
- </div>
84
- </template>
85
- </DatePicker>
93
+ </template>
94
+ </DatePicker>
95
+ </div>
86
96
 
87
97
  <Error for="startDate">{{ validationMessage }}</Error>
88
98
 
@@ -134,6 +144,8 @@ Creates a controller for a masked single-date input.
134
144
  - `Must be in mm/dd/yyyy format.` (or your custom `dateFormat`) when `reason === "invalid-date"`.
135
145
  - Range messages (between/on or after/on or before) when `reason === "out-of-bounds"`.
136
146
  - `datePart(pos: number): 'mm' | 'dd' | 'yyyy'`: Helper to determine focused part from caret position.
147
+ - `datePart(pos: number): 'mm' | 'dd' | 'yyyy'`: Helper to determine focused part from caret position.
148
+ - `initStyling(): void`: Re-applies the `fk-datepicker` class to the parent of the closest `.k-datepicker` element. This is exposed so consumers can re-run theming after Kendo manipulates the DOM; the function is idempotent. Use this to apply the fk-datepicker style hook when the date picker isn't available on initial load.
137
149
  - Event handlers to wire to the input:
138
150
  - `handleChange(event)`
139
151
  - `handleKeyDown(event)` — Space opens calendar via `onShowCalendar`; ArrowUp/ArrowDown act as steppers.
@@ -154,7 +166,7 @@ Creates a controller for a masked single-date input.
154
166
  - **Caret persistence**: After programmatic updates (including steppers), the caret is restored to the prior position to preserve typing flow.
155
167
  - **Space key**: The input consumes Space and calls `onShowCalendar` to open the DatePicker popup without inserting a space into `raw`.
156
168
  - **External sync**: When `externalValue` is set to a valid date, `raw` mirrors it (e.g., from a calendar selection). If external becomes null/invalid, `raw` is preserved to avoid clobbering in-progress text.
157
- - **Styling hook**: On mount, adds `fk-datepicker` class to the parent of the closest `.k-datepicker` element for theming.
169
+ - **Styling hook**: On mount, adds `fk-datepicker` class to the parent of the closest `.k-datepicker` element for theming. The composable also exposes `initStyling()` so consumers can re-run styling when needed (for example, after Kendo performs DOM updates). `initStyling()` is safe to call repeatedly — it is idempotent.
158
170
 
159
171
  ## Integration Patterns
160
172
 
@@ -200,7 +200,7 @@ function onFilterChange(event: any) {
200
200
 
201
201
  ## API
202
202
 
203
- ### `useGridA11y(gridRef: Ref<any>)`
203
+ ### `useGridA11y(gridRef: Ref<any>, options?: { focusableMenuSelectors?: string[] })`
204
204
 
205
205
  Returns helpers to initialize accessibility, manage focus, and handle keyboard and sorting interactions.
206
206
 
@@ -213,6 +213,17 @@ Returns helpers to initialize accessibility, manage focus, and handle keyboard a
213
213
  - Safeguards menu triggers to defer to column menu logic.
214
214
  - **`handleSortChange(event: any, cb?: (event: any) => void): void`**: Composable-aware sort handling; optionally call a custom callback before applying sort.
215
215
 
216
+ ### Options
217
+
218
+ - `options.focusableMenuSelectors?: string[]` — Optional array of CSS selectors used to determine which elements inside a column filter form should be considered focusable for Tab-trapping. If omitted, the composable uses the following built-in defaults targeting common Kendo filter form controls:
219
+
220
+ - `.k-filter-menu-container .k-dropdownlist[tabindex='0']`
221
+ - `.k-filter-menu-container input.k-input-inner:not([tabindex='-1']):not([disabled])`
222
+ - `.k-filter-menu-container button:not([tabindex='-1']):not([disabled])`
223
+ - `.k-checkbox`
224
+
225
+ Provide this option when your app uses custom widgets or different markup inside filter forms.
226
+
216
227
  Internal behaviors include:
217
228
 
218
229
  - Column menu keyboard support (Space/Enter activation on triggers; ArrowUp/ArrowDown navigation; Tab trapping in filter forms; Escape returns focus).
@@ -22,10 +22,11 @@ import { MaskedTextBox } from "@progress/kendo-vue-inputs";
22
22
  import { SvgIcon } from "@progress/kendo-vue-common";
23
23
  import { Calendar, type SelectionRange } from "@progress/kendo-vue-dateinputs";
24
24
  import { Popup } from "@progress/kendo-vue-popup";
25
- import { useMaskedDateRangeInput } from "@featherk/composables/range";
25
+ import { useMaskedDateRangeInput, usePopupTrap } from "@featherk/composables/range";
26
26
 
27
27
  const showCal = ref(false);
28
28
  const dateRange = ref<SelectionRange | null | undefined>();
29
+ const maskedTextBoxRef = ref<InstanceType<typeof MaskedTextBox> | null>(null);
29
30
 
30
31
  // Example bounds (customize for your app)
31
32
  const ONE_YEAR = 365 * 24 * 60 * 60 * 1000;
@@ -56,10 +57,19 @@ const dateRangeIcon = { name: "calendar" } as any; // use @featherk/icons getCus
56
57
 
57
58
  const rawInput = range.raw;
58
59
  const clickAdornment = () => { showCal.value ? closeCalendar() : openCalendar(); };
60
+
61
+ // Focus trap for the calendar popup
62
+ usePopupTrap({
63
+ isOpen: showCal,
64
+ onRequestClose: closeCalendar,
65
+ triggerEl: maskedTextBoxRef,
66
+ popupSelector: [".k-calendar", ".k-popup"],
67
+ });
59
68
  </script>
60
69
 
61
70
  <template>
62
71
  <MaskedTextBox
72
+ ref="maskedTextBoxRef"
63
73
  id="date-range-input"
64
74
  v-model="rawInput"
65
75
  :mask="'00/00/0000 - 00/00/0000'"
@@ -139,6 +149,7 @@ Creates a controller for a masked date range input.
139
149
  - **`reason: Readonly<ComputedRef<string | undefined>>`**: Explanation for invalid states; returns `'valid'` when the range passes validation.
140
150
  - **`spanDays: Readonly<ComputedRef<number | undefined>>`**: Span in days between clamped start/end; `undefined` when incomplete or invalid.
141
151
  - Readonly computed parts: **`month1`**, **`day1`**, **`year1`**, **`month2`**, **`day2`**, **`year2`** (strings). Useful for diagnostics.
152
+ - **`initStyling(): void`**: Re-applies the `fk-daterangepicker` class to the input's parent container. Exposed so consumers can re-run theming after Kendo manipulates the DOM; the function is idempotent. Use this to apply the fk-daterangepicker style hook when the date range picker isn't available on initial load
142
153
  - Event handlers to wire to the input:
143
154
  - **`handleChange(event)`**: Assigns `raw` from the input event and emits parsed range when complete and valid.
144
155
  - **`handleKeyDown(event)`**:
@@ -167,6 +178,7 @@ Creates a controller for a masked date range input.
167
178
  - **External sync**: When `externalValue` is set (typically by the calendar), `raw` is updated to reflect the selected range. If a popup is open and the change is marked calendar-originated, the composable calls `onRequestClose` after `closeDelay`.
168
179
  - **Raw preservation**: When external range becomes invalid/empty, the composable does not overwrite `raw`, preserving in-progress text.
169
180
  - **Styling hook**: On mount, adds `fk-daterangepicker` class to the input's parent container for theming.
181
+ - **Styling hook**: On mount, adds `fk-daterangepicker` class to the input's parent container for theming. The composable also exposes `initStyling()` so consumers can re-run styling when needed (for example, after Kendo performs DOM updates). `initStyling()` is safe to call repeatedly — it is idempotent.
170
182
 
171
183
  ## Integration Pattern (Kendo + Popup)
172
184
 
@@ -20,11 +20,12 @@ import { ref } from "vue";
20
20
  import { TimePicker } from "@progress/kendo-vue-dateinputs";
21
21
  import { MaskedTextBox } from "@progress/kendo-vue-inputs";
22
22
  import { Error } from "@progress/kendo-vue-labels";
23
- import { useMaskedTimeInput } from "@featherk/composables/time";
23
+ import { useMaskedTimeInput, usePopupTrap } from "@featherk/composables";
24
24
 
25
25
  // Shared model for TimePicker and composable
26
26
  const selectedTime = ref<Date | null | undefined>();
27
27
  const showPicker = ref(false);
28
+ const timePickerRef = ref<HTMLElement | null>(null);
28
29
 
29
30
  // Example bounds (customize for your app)
30
31
  const minTime = new Date(new Date().setHours(8, 0, 0, 0)); // 8:00 AM
@@ -54,35 +55,45 @@ const {
54
55
  debugEnabled,
55
56
  debugLines,
56
57
  } = masked;
58
+
59
+ // Integrate focus trap for the TimePicker popup
60
+ usePopupTrap({
61
+ isOpen: showPicker,
62
+ onRequestClose: () => (showPicker.value = false),
63
+ triggerEl: timePickerRef,
64
+ popupSelector: [".k-timeselector", ".k-popup"],
65
+ });
57
66
  </script>
58
67
 
59
68
  <template>
60
- <TimePicker
61
- v-model="selectedTime"
62
- dateInput="masked"
63
- :format="'hh:mm a'"
64
- :show="showPicker"
65
- @open="showPicker = true"
66
- @close="showPicker = false"
67
- :style="{ width: 'fit-content' }"
68
- >
69
- <template #masked="{ props }">
70
- <MaskedTextBox
71
- id="startTime"
72
- :mask="'Hh:Mm Aa'"
73
- :rules="rules"
74
- :value="raw"
75
- :placeholder="placeholder"
76
- :showClearButton="false"
77
- @change="masked.handleChange"
78
- @keydown="masked.handleKeyDown"
79
- @keyup="masked.handleKeyUp"
80
- @click="masked.handleClick"
81
- @wheel="masked.handleWheel"
82
- @blur="masked.handleBlur"
83
- />
84
- </template>
85
- </TimePicker>
69
+ <div ref="timePickerRef">
70
+ <TimePicker
71
+ v-model="selectedTime"
72
+ dateInput="masked"
73
+ :format="'hh:mm a'"
74
+ :show="showPicker"
75
+ @open="showPicker = true"
76
+ @close="showPicker = false"
77
+ :style="{ width: 'fit-content' }"
78
+ >
79
+ <template #masked="{ props }">
80
+ <MaskedTextBox
81
+ id="startTime"
82
+ :mask="'Hh:Mm Aa'"
83
+ :rules="rules"
84
+ :value="raw"
85
+ :placeholder="placeholder"
86
+ :showClearButton="false"
87
+ @change="masked.handleChange"
88
+ @keydown="masked.handleKeyDown"
89
+ @keyup="masked.handleKeyUp"
90
+ @click="masked.handleClick"
91
+ @wheel="masked.handleWheel"
92
+ @blur="masked.handleBlur"
93
+ />
94
+ </template>
95
+ </TimePicker>
96
+ </div>
86
97
  <Error for="startTime">{{ validationMessage }}</Error>
87
98
 
88
99
  <!-- Optional: show internal debug lines during integration -->
@@ -132,6 +143,8 @@ Creates a controller for a masked single-time input.
132
143
  - `period: Readonly<Computed<"AM" | "PM">>`: AM or PM period.
133
144
  - `time24: Readonly<Computed<string | null>>`: Time in 24-hour `HH:MM:SS` format (e.g., `"14:30:00"`) for database storage. Returns `null` if input is incomplete or invalid.
134
145
  - `parsedRawTime: Readonly<Computed<Date | null>>`: The parsed time as a `Date` object (today's date with the entered time). Returns `null` if input is incomplete or invalid.
146
+ - `parsedRawTime: Readonly<Computed<Date | null>>`: The parsed time as a `Date` object (today's date with the entered time). Returns `null` if input is incomplete or invalid.
147
+ - `initStyling(): void`: Re-applies the `fk-timepicker` theming class to the parent of the closest `.k-timepicker` element. Exposed so consumers can re-run theming when Kendo updates the DOM; the function is idempotent. Use this to apply the fk-timepicker style hook when the time picker isn't available on initial load
135
148
  - `isComplete: Computed<boolean>`: `true` when the raw string matches `^(\d{2}):(\d{2})\s([AP]M)$`.
136
149
  - `isValid: Computed<boolean>`: Validity considering completeness, parsability, min/max bounds, and (when enabled) required state.
137
150
  - `reason: Computed<string | undefined>`: Machine-readable reason for the current validation state:
@@ -172,6 +185,7 @@ Creates a controller for a masked single-time input.
172
185
  - **Space key**: The input consumes Space and calls `onShowPicker` to open a time menu without inserting a space into `raw`.
173
186
  - **External sync**: When `externalValue` is set to a valid `Date`, `raw` mirrors it (e.g., from a `TimePicker` selection). If external becomes null/invalid, `raw` is preserved to avoid clobbering in-progress text.
174
187
  - **Styling hook**: On mount, adds a theming class (e.g., `fk-timepicker`) to the parent of the closest Kendo time picker element for styling.
188
+ - **Styling hook**: On mount, adds a theming class (e.g., `fk-timepicker`) to the parent of the closest Kendo time picker element for styling. The composable also exposes `initStyling()` so consumers can re-run styling when needed (for example, after Kendo performs DOM updates). `initStyling()` is safe to call repeatedly — it is idempotent.
175
189
 
176
190
  ## Integration Patterns
177
191
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@featherk/composables",
3
- "version": "0.6.5",
3
+ "version": "0.6.7",
4
4
  "main": "dist/featherk-composables.umd.js",
5
5
  "module": "dist/featherk-composables.es.js",
6
6
  "types": "dist/index.d.ts",