@featherk/composables 0.6.4 → 0.6.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/date/useMaskedDateInput.d.ts +1 -0
- package/dist/featherk-composables.es.js +809 -780
- package/dist/featherk-composables.umd.js +1 -1
- package/dist/range/useMaskedDateRangeInput.d.ts +3 -0
- package/dist/time/useMaskedTimeInput.d.ts +1 -0
- package/docs/date/useMaskedDateInput.md +49 -37
- package/docs/range/useMaskedDateRangeInput.md +17 -1
- package/docs/time/useMaskedTimeInput.md +41 -27
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
(function(Z,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):(Z=typeof globalThis<"u"?globalThis:Z||self,t(Z.FeatherKComposables={},Z.Vue,Z.useFocusTrap))})(this,(function(Z,t,we){"use strict";const ke=e=>{const r=t.ref(null);let f=!1,L=null,q=null;const K=[],N=".k-table-row[data-grid-row-index] [tabindex]",A=()=>e?.value?.columns,k=a=>{const p=a.key||a.code;[" ","Spacebar","Space","Enter"].includes(p)&&(a.preventDefault(),a.stopPropagation(),r.value=a.target,a.target.click())},b=a=>{if(!r.value)return;if(a.code==="Escape"){a.preventDefault(),a.stopPropagation(),r.value&&r.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(a.code==="Tab"){const u=[".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(u.join(",")));if(y.length===0)return;const x=y.findIndex(P=>P===document.activeElement);let w;x===-1?w=0:a.shiftKey?w=(x-1+y.length)%y.length:w=(x+1)%y.length,a.preventDefault(),a.stopPropagation(),y[w]?.focus();return}}else if(a.code==="ArrowUp"||a.code==="ArrowDown"){a.preventDefault(),a.stopPropagation();const u=p.findIndex(x=>x===document.activeElement);let y=u;a.code==="ArrowUp"?y=u>0?u-1:p.length-1:a.code==="ArrowDown"&&(y=u<p.length-1?u+1:0),p[y]?.focus();return}a.code==="Tab"&&(a.preventDefault(),a.stopPropagation(),a.shiftKey?(r.value?.previousElementSibling).focus():(r.value?.nextElementSibling).focus())},D=()=>{L=new MutationObserver(a=>{a.forEach(p=>{p.addedNodes.forEach(i=>{if(i.nodeType===Node.ELEMENT_NODE){const u=i;if(u.classList.contains("k-animation-container")){const x=r.value;x&&(x.dataset.featherKSortable==="true"||t.nextTick(()=>{u.querySelectorAll(".k-columnmenu-item-wrapper").forEach(H=>{H.textContent?.toLowerCase().includes("sort")&&H.remove()})})),u.addEventListener("keydown",b),t.nextTick(()=>{const w=()=>{const P=Array.from(u.querySelectorAll(".k-animation-container .k-popup .k-column-menu .k-columnmenu-item-wrapper .k-columnmenu-item"));if(P.length===1)P[0].focus(),P[0].click(),w.attempts=0;else if(P.length>1){w.attempts=0;return}else w.attempts===void 0&&(w.attempts=0),w.attempts++<3&&setTimeout(w,200)};w()})}u.querySelectorAll(".k-animation-container").forEach(x=>{x.addEventListener("keydown",b)})}}),p.removedNodes.forEach(i=>{if(i.nodeType===Node.ELEMENT_NODE){const u=i;u.classList.contains("k-animation-container")&&u.removeEventListener("keydown",b),u.querySelectorAll(".k-animation-container").forEach(x=>{x.removeEventListener("keydown",b)})}})})}),L.observe(document.body,{childList:!0,subtree:!0})},C=a=>{if(!a.type||!a)return;const p=a.target;if(p){if(a.code==="Escape"){const i=document.activeElement?.closest(".k-table-row[data-grid-row-index]");if(i){a.preventDefault(),a.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(a.code)){if(a.preventDefault(),p.classList.contains("k-grid-header-menu")&&p.classList.contains("k-grid-column-menu")){r.value=p;return}const i=p.closest(".k-table-row[data-grid-row-index]");if(i){if(["ArrowDown","ArrowUp"].includes(a.code)){const u=(x,w)=>{let P=w==="next"?x.nextElementSibling:x.previousElementSibling;for(;P;){const H=P;try{if(H.hasAttribute&&H.classList.contains("k-table-row"))return H}catch{}P=w==="next"?P.nextElementSibling:P.previousElementSibling}return null},y=a.code==="ArrowDown"?u(i,"next"):u(i,"previous");y&&(i.setAttribute("tabindex","-1"),y.setAttribute("tabindex","0"),y.focus());return}if(["ArrowLeft","ArrowRight"].includes(a.code)){a.preventDefault();const u=i.querySelectorAll(N);if(u.length===0)return;let y=Array.from(u).findIndex(x=>x===document.activeElement);if(y===-1&&document.activeElement===i){u[0].focus();return}a.code==="ArrowRight"?y=y===u.length-1?0:y+1:a.code==="ArrowLeft"&&(y=y===u.length-1?y-1:u.length-1),u[y].focus();return}}}}},E=()=>{t.nextTick(()=>{const a=e.value.$el.closest(".k-grid");a&&a.classList.add("fk-grid")})},S=()=>{if(!q)try{const a=()=>{try{const u=Array.from(e.value.$el.querySelectorAll(".k-table-row[data-grid-row-index]"));if(!u||u.length===0||u.filter(w=>w.getAttribute("tabindex")==="0").length===1)return;const x=u.find(w=>w===document.activeElement||w.contains(document.activeElement));if(u.forEach(w=>w.setAttribute("tabindex","-1")),x){x.setAttribute("tabindex","0");return}u[0].setAttribute("tabindex","0")}catch(u){console.error("ensureSingleTabindex error:",u)}},p=Array.from(e.value.$el.querySelectorAll(".k-table-row[data-grid-row-index]"));p.length>0&&p.forEach((u,y)=>{u.setAttribute("tabindex",y===0?"0":"-1")});const i=e.value.$el.querySelector(".k-table-tbody");i&&(q=new MutationObserver(()=>{a()}),q.observe(i,{childList:!0,subtree:!0}))}catch(a){console.error("Error setting up row navigation:",a)}},$=()=>{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",k)}),D(),m()})},F=()=>{const p=document.querySelectorAll(".k-grid-header .k-grid-header-menu.k-grid-column-menu");p&&p.forEach(i=>{i.removeEventListener("keydown",k)}),L&&(L.disconnect(),L=null),q&&(q.disconnect(),q=null),K.forEach(i=>i()),K.length=0},m=()=>{document.querySelectorAll(".k-grid-header .k-table-thead th").forEach((i,u)=>{const y=i.querySelector(".k-grid-header-menu.k-grid-column-menu");if(!y)return;const x=A();if(x&&x[u]){const B=x[u].field??"";i.setAttribute("data-feather-k-field",B),i.setAttribute("data-feather-k-filterable",x[u].filterable===!1?"false":"true"),i.setAttribute("data-feather-k-sortable",x[u].sortable===!1?"false":"true")}const w=i.dataset.featherKFilterable!=="false",P=i.dataset.featherKSortable!=="false";y.setAttribute("tabindex","-1"),w||P?i.style.cursor="pointer":i.style.cursor="default",w?(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=B=>{B.target?.closest(".k-column-resizer")||(r.value=i,y.click())},G=B=>{if(w)r.value=i,B.preventDefault(),B.stopPropagation(),H(B);else if(P){r.value=i;const _=new KeyboardEvent("keydown",{key:"Enter",code:"Enter",keyCode:13,which:13,bubbles:!0,cancelable:!0});i.dispatchEvent(_)}};i.addEventListener("click",G),K.push(()=>{i.removeEventListener("click",G)});const te=B=>{if((B.code==="Enter"||B.code==="Space")&&(w||P)){if(r.value=i,r.value.focus(),w)B.preventDefault(),B.stopPropagation(),H(B);else if(P){const _=i.querySelector(".k-link");_&&_.click()}}};i.addEventListener("keydown",te,!0),K.push(()=>{i.removeEventListener("keydown",te,!0)})});const p=document.querySelector(".k-grid-header .k-table-thead");if(p){const i=u=>{const y=u.target.closest("th");y&&(u.code==="Enter"||u.code==="Space")&&y.dataset.featherKFilterable==="false"&&y.dataset.featherKSortable==="false"&&(u.preventDefault(),u.stopImmediatePropagation())};p.addEventListener("keydown",i,!0),K.push(()=>{p.removeEventListener("keydown",i,!0)})}},h=function(a,p){const i=a?.event.event.target,u=A();if(!i||!u)return;const y=i.classList.contains("k-link"),x=i.classList.contains("k-columnmenu-item"),w=u.find(P=>P.field===a.event.field)?.sortable&&!0;if(!y){if(x&&!w){(a.event.sort&&void 0)?.filter(H=>H.field!==a.event.field);return}typeof p=="function"&&t.nextTick(()=>{r.value&&r.value.focus(),p(a)})}},U=()=>{if(!f)try{E(),S(),$(),f=!0}catch(a){console.error("initA11y failed:",a),F()}};return t.onBeforeUnmount(()=>{F()}),{activeFilterButton:r,handleGridKeyDown:C,handleSortChange:h,initA11y:U}};function De(e){const r=t.ref(""),f=t.ref(void 0),L=t.ref(!!e.debug),q=t.ref(e.dateFormat??"mm/dd/yyyy"),K=t.computed(()=>!!e.required),N=t.ref(!1),A=["ArrowUp","ArrowDown"],k=["ArrowLeft","ArrowRight"],b=t.computed(()=>(r.value??"").replace(/\D/g,"")),D=l=>l<=2?"mm":l<=5?"dd":b.value.length<=10?"yyyy":"mm",C=t.computed(()=>{const l=r.value&&r.value.substring(0,2).replace(/\D/g,"0")||"0";return parseInt(l).toString().padStart(2,"0")}),E=t.computed(()=>{const l=r.value&&r.value.substring(3,5).replace(/\D/g,"0")||"0";return parseInt(l).toString().padStart(2,"0")}),S=t.computed(()=>{const l=r.value&&r.value.substring(6,10).replace(/\D/g,"0")||"0";return parseInt(l).toString().padStart(4,"0")}),$=l=>{if(b.value.length===0){e.onChange({value:null,event:l});return}if(b.value.length<8){e.onChange({value:null,event:l});return}if((r.value??"").length===10&&b.value.length===8){const[d,I,J]=r.value.split("/"),o=parseInt(d),s=parseInt(I),v=parseInt(J);if(a(v,o,s)){const T=new Date(v,o-1,s);F(T)?e.onChange({value:T,event:l}):e.onChange({value:null,event:l})}else e.onChange({value:null,event:l})}},F=l=>{const d=e.min??void 0,I=e.max??void 0;return!(d&&l<d||I&&l>I)},m=t.computed(()=>{if((r.value??"").length===10&&b.value.length===8){const[l,d,I]=(r.value??"").split("/"),J=parseInt(l),o=parseInt(d),s=parseInt(I);if(a(s,J,o))return new Date(s,J-1,o)}return null}),h=t.computed(()=>(r.value??"").length===10&&b.value.length===8),U=(l,d)=>new Date(l,d,0).getDate(),a=(l,d,I)=>d>=1&&d<=12&&l>=1900&&I>=1&&I<=U(l,d),p=l=>{r.value=l.value;const d=l.event?.target;f.value=d?.selectionStart??0,$(l)},i=l=>{f.value=l.target.selectionStart??0},u=(l,d,I)=>{const J=d?.selectionStart??f.value??0;f.value=J;let o=parseInt(C.value),s=parseInt(E.value),v=parseInt(S.value);if(!(b.value.length>=8)||!a(v,o,s)){const j=e.defaultValue??new Date;o=j.getMonth()+1,s=j.getDate(),v=j.getFullYear(),r.value=`${String(o).padStart(2,"0")}/${String(s).padStart(2,"0")}/${String(v)}`;const n=new Date(v,o-1,s);e.onChange({value:F(n)?n:null,event:I}),t.nextTick(()=>{requestAnimationFrame(()=>{const c=document.getElementById(e.id),g=f.value??0;c&&(c.focus(),c.setSelectionRange(g,g))})});return}const R=D(J);if(R==="mm")o=l==="ArrowUp"?o<12?o+1:1:o>1?o-1:12;else if(R==="dd"){const j=new Date(v,o,0).getDate();s=l==="ArrowUp"?s<j?s+1:1:s>1?s-1:j}else R==="yyyy"&&(v=l==="ArrowUp"?v+1:Math.max(1,v-1));r.value=`${String(o).padStart(2,"0")}/${String(s).padStart(2,"0")}/${String(v)}`;const[ee,W,Y]=r.value.split("/"),ne=new Date(parseInt(Y),parseInt(ee)-1,parseInt(W));ne.toString()!=="Invalid Date"&&parseInt(Y)>=1e3?e.onChange({value:F(ne)?ne:null,event:I}):e.onChange({value:null,event:I}),t.nextTick(()=>{requestAnimationFrame(()=>{const j=document.getElementById(e.id),n=f.value??0;j&&(j.focus(),j.setSelectionRange(n,n))})})},y=l=>{if(l.code==="Space"||l.key===" "){e.onShowCalendar(l);return}if(A.includes(l.key)){l.preventDefault();const d=l.target;u(l.key,d,l)}},x=l=>{l.preventDefault();const d=l.deltaY<0?"ArrowUp":"ArrowDown";u(d,l.target,l)},w=l=>{const d=l.target;if(k.includes(l.key)){f.value=d?.selectionStart??0;return}A.includes(l.key)&&(l.preventDefault(),f.value=d?.selectionStart??0)},P=l=>{N.value=!0,K.value&&!e.defaultValue&&e.externalValue&&e.externalValue.value===void 0&&b.value.length===0&&(e.externalValue.value="");const d=l.target;d&&(f.value=d.selectionStart??0)};e.externalValue&&t.watch(e.externalValue,l=>{if(l){const d=new Date(l);if(d.toString()!=="Invalid Date"){const I=(d.getMonth()+1).toString().padStart(2,"0"),J=d.getDate().toString().padStart(2,"0"),o=d.getFullYear().toString();r.value=`${I}/${J}/${o}`;return}}},{immediate:!0});const H=t.computed(()=>[["Date",`${C.value} / ${E.value} / ${S.value}`],["Digits only",b.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]]),G=t.computed(()=>{if(!K.value){if(!h.value)return!0;const d=m.value;return d?F(d):!1}if(!N.value)return!0;const l=m.value;return!h.value||!l?!1:F(l)}),te=t.computed(()=>{if(!K.value){if(!h.value)return;const d=m.value;return d?F(d)?"valid":"out-of-bounds":"invalid-date"}if(!N.value)return;if(b.value.length===0||!h.value)return"incomplete";const l=m.value;return l?F(l)?"valid":"out-of-bounds":"invalid-date"}),B=t.computed(()=>{const l=te.value;if(!l||l==="valid")return"";if(l==="incomplete")return"Required";if(l==="invalid-date")return`Must be in ${q.value} format.`;const d=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(l==="out-of-bounds"){if(d&&I)return`Must be between ${d} and ${I}.`;if(d)return`Must be on or after ${d}.`;if(I)return`Must be on or before ${I}.`}return""}),_=()=>{t.nextTick(()=>{const l=document.getElementById(e.id);if(!l){console.warn(`ID (#${e.id}) not found for styling.`);return}const d=l.closest(".k-datepicker");if(d){const I=d.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:r,cursorPos:f,debugEnabled:L,debugLines:H,placeholder:q,isValid:G,reason:t.readonly(te),validationMessage:B,digitsOnly:b,month:t.readonly(C),day:t.readonly(E),year:t.readonly(S),datePart:D,handleChange:p,handleKeyDown:y,handleWheel:x,handleKeyUp:w,handleClick:i,handleBlur:P}}function Ae(e){const r=t.ref(""),f=t.ref(void 0),L=t.ref(!!e.debug),q=t.ref(!1),N=365*(1440*60*1e3),A=new Date,k=new Date(A.getTime()-N),b=new Date(A.getTime()+N);e.min=e.min??k,e.max=e.max??b;const D=t.computed(()=>(r.value??"").replace(/\D/g,"")),C=(n,c)=>new Date(n,c,0).getDate(),E=(n,c,g)=>c>=1&&c<=12&&n>=1e3&&g>=1&&g<=C(n,c),S=n=>Date.UTC(n.getFullYear(),n.getMonth(),n.getDate()),$=n=>{if(!n)return null;const c=e.min,g=e.max,M=S(n);return M<S(c)||M>S(g)?null:n},F=(n,c)=>e.allowReverse??!1?!0:n<=c,m=t.computed(()=>(r.value?.length??0)>=23&&D.value.length>=16),h=n=>{if((n??"").length<23||D.value.length<16)return{start:null,end:null};const c=n.substring(0,10),g=n.substring(13,23),[M,V,z]=c.split("/").map(oe=>parseInt(oe||"0",10)),[ce,le,ie]=g.split("/").map(oe=>parseInt(oe||"0",10)),se=new Date(z,M-1,V),de=new Date(ie,ce-1,le),ye=E(z,M,V)&&se.toString()!=="Invalid Date",ge=E(ie,ce,le)&&de.toString()!=="Invalid Date";return{start:ye?se:null,end:ge?de:null}},U=e.externalValid??t.ref(void 0),a=t.computed(()=>h(r.value)),p=t.computed(()=>{const n=$(a.value.start),c=$(a.value.end);return{start:n,end:c}}),i=t.computed(()=>{if(!m.value)return;const n=p.value.start,c=p.value.end;if(!n||!c)return;const g=V=>Date.UTC(V.getFullYear(),V.getMonth(),V.getDate()),M=Math.abs(g(c)-g(n));return Math.round(M/864e5)}),u=t.computed(()=>{const{start:n,end:c}=a.value;if(!m.value)return;if(!n||!c||!p.value.start||!p.value.end)return!1;const g=p.value.start,M=p.value.end;return!(!F(g,M)||typeof e.maxSpanDays=="number"&&i.value!==void 0&&i.value>e.maxSpanDays)}),y=t.computed(()=>{const{start:n,end:c}=a.value;if(!m.value)return"incomplete";if(!n||!c)return"invalid-date";if(!p.value.start||!p.value.end)return"out-of-bounds";const g=p.value.start,M=p.value.end;return F(g,M)?typeof e.maxSpanDays=="number"&&i.value!==void 0&&i.value>e.maxSpanDays?"span-exceeds-limit":"valid":"reversed-range"}),x=t.computed(()=>{const{start:n,end:c}=a.value,{min:g,max:M}=e;switch(console.table({start:n,end:c,min:g,max:M}),y.value){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 n&&c&&(S(n)<S(g)||S(c)<S(g)||S(n)>S(M)||S(c)>S(M))?`Dates must be between ${G(g)} and ${G(M)}.`:"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""}});t.watch(u,n=>{(e.manageValid??!0)&&(U.value=n)},{immediate:!0});const w=["ArrowUp","ArrowDown"],P=["ArrowLeft","ArrowRight"],H=(n,c)=>String(n).padStart(c,"0"),G=n=>`${H(n.getMonth()+1,2)}/${H(n.getDate(),2)}/${H(n.getFullYear(),4)}`,te=n=>n<=2?{side:"start",part:"mm"}:n<=5?{side:"start",part:(n<=3,"dd")}:n<=11?{side:"start",part:"yyyy"}:n<=15?{side:"end",part:"mm"}:n<=18?{side:"end",part:"dd"}:{side:"end",part:"yyyy"},B=(n,c,g)=>{const M=c?.selectionStart??f.value??0;f.value=M;const{start:V,end:z}=h(r.value);if(!V&&!z){const O=new Date,re=G(O);r.value=`${re} - ${re}`,e.onChange({value:{start:O,end:O},event:g}),t.nextTick(()=>{requestAnimationFrame(()=>{const X=document.getElementById(e.id),Q=f.value??0;X&&(X.focus(),X.setSelectionRange(Q,Q))})});return}const ce=new Date,le=te(M);let ie=V?new Date(V):new Date(ce),se=z?new Date(z):new Date(ce);const de=(O,re)=>{if(re==="mm"){const X=O.getMonth()+1,Q=n==="ArrowUp"?X<12?X+1:1:X>1?X-1:12;O.setMonth(Q-1);const fe=C(O.getFullYear(),Q);O.getDate()>fe&&O.setDate(fe)}else if(re==="dd"){const X=C(O.getFullYear(),O.getMonth()+1),Q=O.getDate(),fe=n==="ArrowUp"?Q<X?Q+1:1:Q>1?Q-1:X;O.setDate(fe)}else if(re==="yyyy"){const X=O.getFullYear();O.setFullYear(n==="ArrowUp"?X+1:Math.max(1,X-1));const Q=C(O.getFullYear(),O.getMonth()+1);O.getDate()>Q&&O.setDate(Q)}};le.side==="start"?de(ie,le.part):de(se,le.part);const ye=G(ie),ge=G(se);r.value=`${ye} - ${ge}`;const oe=$(ie),he=$(se);oe&&he&&F(oe,he)?e.onChange({value:{start:oe,end:he},event:g}):e.onChange({value:null,event:g}),t.nextTick(()=>{requestAnimationFrame(()=>{const O=document.getElementById(e.id),re=f.value??0;O&&(O.focus(),O.setSelectionRange(re,re))})})},_=n=>{const{start:c,end:g}=h(r.value);if(!c||!g){e.onChange({value:null,event:n});return}const M=$(c),V=$(g);if(!M||!V){e.onChange({value:null,event:n});return}if(!F(M,V)){e.onChange({value:null,event:n});return}e.onChange({value:{start:M,end:V},event:n})},l=n=>{r.value=n.value;const c=n.event?.target;f.value=c?.selectionStart??0,_(n)},d=n=>{f.value=n.target.selectionStart??0},I=n=>{if(n.code==="Space"||n.key===" "){n.preventDefault(),e.onShowCalendar(n);return}if(n.key==="ArrowDown"&&n.altKey){n.preventDefault(),e.onShowCalendar(n);return}if(w.includes(n.key)){n.preventDefault();const c=n.target;B(n.key,c,n)}},J=n=>{n.preventDefault();const c=n.deltaY<0?"ArrowUp":"ArrowDown";B(c,n.target,n)},o=n=>{if(P.includes(n.key)||w.includes(n.key)){n.preventDefault();const c=n.target;f.value=c?.selectionStart??0}};e.externalValue&&t.watch(e.externalValue,n=>{const c=n?.start??null,g=n?.end??null;if(c&&g){if(r.value=`${G(c)} - ${G(g)}`,e.isOpen?.value&&q.value&&e.onRequestClose){const M=typeof e.closeDelay=="number"?e.closeDelay:e.closeDelay?.value??0;setTimeout(()=>{e.onRequestClose?.(),q.value=!1},M)}return}},{immediate:!0});const s=t.computed(()=>r.value&&r.value.substring(0,2).replace(/\D/g,"0")||"0"),v=t.computed(()=>r.value&&r.value.substring(3,5).replace(/\D/g,"0")||"0"),T=t.computed(()=>r.value&&r.value.substring(6,10).replace(/\D/g,"0")||"0"),R=t.computed(()=>r.value&&r.value.substring(13,15).replace(/\D/g,"0")||"0"),ee=t.computed(()=>r.value&&r.value.substring(16,18).replace(/\D/g,"0")||"0"),W=t.computed(()=>r.value&&r.value.substring(19,23).replace(/\D/g,"0")||"0"),Y=t.computed(()=>{const{start:n,end:c}=h(r.value);return[{label:"Raw",value:r.value},{label:"Min Date",value:`${e.min?e.min.toDateString():"-"}`},{label:"Max Date",value:`${e.max?e.max.toDateString():"-"}`},{label:"Start",value:`${String(s.value).padStart(2,"0")} / ${String(v.value).padStart(2,"0")} / ${String(T.value).padStart(4,"0")}`},{label:"End",value:`${String(R.value).padStart(2,"0")} / ${String(ee.value).padStart(2,"0")} / ${String(W.value).padStart(4,"0")}`},{label:"Digits only",value:D.value},{label:"Mask complete",value:`${m.value}`},{label:"Parsed",value:`${n?n.toDateString():"-"} | ${c?c.toDateString():"-"}`},{label:"Valid (managed)",value:`${U.value??"-"}`},{label:"Span (days)",value:`${i.value??"-"}`},{label:"Reason",value:`${y.value??"-"}`},{label:"Cursor in",value:`${f.value??"-"} (${(()=>{const g=f.value??0,M=te(g);return`${M.side}.${M.part}`})()})`}]}),ne=()=>{t.nextTick(()=>{const n=document.getElementById(e.id);if(!n){console.warn(`#${e.id} not found for styling.`);return}const c=n.closest("div");c?c.classList.add("fk-daterangepicker"):console.warn(`Parent div of #${e.id} not found for styling.`)})};t.onMounted(()=>{ne()});const j=()=>{t.nextTick(()=>{try{const n=Array.from(document.querySelectorAll(".k-animation-container"));if(!n.length)return;const g=[...n].reverse().find(z=>z.querySelector(".k-calendar"))?.querySelector(".k-calendar");if(!g)return;const M=g.querySelectorAll(".k-calendar-table");let V=!1;M.forEach(z=>{z.tabIndex===0&&(V?z.tabIndex=-1:V=!0)})}catch(n){console.warn(n)}})};return e.isOpen&&t.watch(e.isOpen,n=>{n&&setTimeout(()=>j(),0)},{immediate:!1}),{raw:r,cursorPos:f,debugEnabled:L,debugLines:Y,digitsOnly:D,valid:U,validComputed:t.readonly(u),reason:t.readonly(y),validationMessage:t.readonly(x),spanDays:t.readonly(i),month1:t.readonly(s),day1:t.readonly(v),year1:t.readonly(T),month2:t.readonly(R),day2:t.readonly(ee),year2:t.readonly(W),handleChange:l,handleKeyDown:I,handleWheel:J,handleKeyUp:o,handleClick:d,onCalendarChange:()=>{q.value=!0}}}function Ee(e){const r=t.ref(""),f=t.ref(void 0),L=t.ref(!!e.debug),q=t.ref(e.timeFormat??"hh:mm AM"),K=t.computed(()=>!!e.required),N=t.ref(!1),A=["ArrowUp","ArrowDown"],k=["ArrowLeft","ArrowRight"],b=t.computed(()=>(r.value??"").replace(/\D/g,"")),D={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",E=t.computed(()=>{const o=r.value&&r.value.substring(0,2).replace(/\D/g,"0")||"0",s=parseInt(o);return Math.min(Math.max(s,0),23)}),S=t.computed(()=>{const o=r.value&&r.value.substring(3,5).replace(/\D/g,"0")||"0",s=parseInt(o);return Math.min(Math.max(s,0),59)}),$=t.computed(()=>(r.value?.substring(6,8)||"AM").toUpperCase().startsWith("P")?"PM":"AM"),F=t.computed(()=>{const o=parseInt(r.value?.substring(0,2).replace(/\D/g,"0")||"0"),s=$.value;return o===12?s==="AM"?0:12:s==="PM"?o+12:o}),m=t.computed(()=>h.value?`${String(F.value).padStart(2,"0")}:${String(S.value).padStart(2,"0")}:00`:null),h=t.computed(()=>/^(\d{2}):(\d{2})\s([AP]M)$/i.test(r.value??"")),U=(o,s,v)=>{let T=o%12;return T===0&&(T=12),`${String(T).padStart(2,"0")}:${String(s).padStart(2,"0")} ${v}`},a=o=>{const s=o.match(/^(\d{2}):(\d{2})\s([AP]M)$/i);if(!s)return null;const v=parseInt(s[1]),T=parseInt(s[2]),R=s[3].toUpperCase();if(v<1||v>12||T<0||T>59)return null;let ee=v%12;R==="PM"&&(ee+=12);const W=new Date;return W.setSeconds(0,0),W.setHours(ee),W.setMinutes(T),W},p=o=>{if(b.value.length===0){e.onChange({value:null,event:o});return}if(!h.value){e.onChange({value:null,event:o});return}const s=a(r.value);s&&u(s)?e.onChange({value:s,event:o}):e.onChange({value:null,event:o})},i=o=>o.getHours()*60+o.getMinutes(),u=o=>{const s=e.min??void 0,v=e.max??void 0,T=i(o);if(s){const R=i(s);if(T<R)return!1}if(v){const R=i(v);if(T>R)return!1}return!0},y=o=>{r.value=o.value;const s=o.event?.target;f.value=s?.selectionStart??0;try{const v=f.value??0;if(C(v)==="ampm"&&(r.value??"").length>=8){const T=r.value.charAt(6);/[Aa]/.test(T)?(r.value=`${r.value.slice(0,6)}AM${r.value.slice(8)}`,t.nextTick(()=>{requestAnimationFrame(()=>{const R=document.getElementById(e.id);R&&(R.focus(),R.setSelectionRange(8,8))})})):/[Pp]/.test(T)&&(r.value=`${r.value.slice(0,6)}PM${r.value.slice(8)}`,t.nextTick(()=>{requestAnimationFrame(()=>{const R=document.getElementById(e.id);R&&(R.focus(),R.setSelectionRange(8,8))})}))}}catch{}p(o)},x=o=>{f.value=o.target.selectionStart??0},w=(o,s,v)=>{const T=s?.selectionStart??f.value??0;f.value=T;const R=C(T),ee=(r.value??"").match(/^(\d{2}):(\d{2})\s([AP]M)$/i);if(!ee){if((r.value??"").length===0||b.value.length===0){const n=new Date,c=n.getHours(),g=c>=12?"PM":"AM";r.value=U(c,n.getMinutes(),g);const M=a(r.value);M&&u(M)?e.onChange({value:M,event:v}):e.onChange({value:null,event:v}),t.nextTick(()=>{requestAnimationFrame(()=>{const V=document.getElementById(e.id),z=f.value??0;V&&(V.focus(),V.setSelectionRange(z,z))})})}return}let W=parseInt(ee[1]),Y=parseInt(ee[2]),ne=ee[3].toUpperCase();if(R==="hh")o==="ArrowUp"?W=W<12?W+1:1:W=W>1?W-1:12;else if(R==="mm"){const n=e.minuteStepRef?.value??e.minuteStep??1;if(n===1)o==="ArrowUp"?Y=Y<59?Y+1:0:Y=Y>0?Y-1:59;else if(o==="ArrowUp"){const c=Y%n;let g=c===0?Y+n:Y+(n-c);g>=60&&(g=0),Y=g}else{const c=Y%n;let g=c===0?Y-n:Y-c;g<0&&(g=60-n),Y=g}}else R==="ampm"&&(ne=ne==="AM"?"PM":"AM");r.value=`${String(W).padStart(2,"0")}:${String(Y).padStart(2,"0")} ${ne}`;const j=a(r.value);j&&u(j)?e.onChange({value:j,event:v}):e.onChange({value:null,event:v}),t.nextTick(()=>{requestAnimationFrame(()=>{const n=document.getElementById(e.id),c=f.value??0;n&&(n.focus(),n.setSelectionRange(c,c))})})},P=o=>{if(o.code==="Space"||o.key===" "){e.onShowPicker(o);return}if(A.includes(o.key)){o.preventDefault();const s=o.target;w(o.key,s,o)}},H=o=>{o.preventDefault();const s=o.deltaY<0?"ArrowUp":"ArrowDown";w(s,o.target,o)},G=o=>{const s=o.target;if(k.includes(o.key)){f.value=s?.selectionStart??0;return}A.includes(o.key)&&(o.preventDefault(),f.value=s?.selectionStart??0)},te=o=>{N.value=!0,K.value&&e.externalValue&&e.externalValue.value===void 0&&b.value.length===0&&(e.externalValue.value="");const s=o.target;s&&(f.value=s.selectionStart??0)};e.externalValue&&t.watch(e.externalValue,o=>{if(o){const s=new Date(o);if(s.toString()!=="Invalid Date"){const v=s.getHours(),T=v>=12?"PM":"AM";r.value=U(v,s.getMinutes(),T);return}}},{immediate:!0});const B=t.computed(()=>[["Time",r.value||"--:-- --"],["Hour (12h)",E.value],["Hour (24h)",F.value],["Minute",S.value],["Period",$.value],["Time (24h)",m.value??"--:--:--"],["Digits only",b.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",l.value],["reason",d.value],["validationMessage",I.value]]),_=t.computed(()=>a(r.value)??null),l=t.computed(()=>{if(!K.value){if(!h.value)return!0;const s=_.value;return s?u(s):!1}if(!N.value)return!0;const o=_.value;return!h.value||!o?!1:u(o)}),d=t.computed(()=>{if(!K.value){if(!h.value)return;const s=_.value;return s?u(s)?"valid":"out-of-bounds":"invalid-time"}if(!N.value)return;if(b.value.length===0||!h.value)return"incomplete";const o=_.value;return o?u(o)?"valid":"out-of-bounds":"invalid-time"}),I=t.computed(()=>{const o=d.value;if(!o||o==="valid")return"";if(o==="incomplete")return"Required";if(o==="invalid-time")return`Must be in ${q.value} format.`;const s={hour:"2-digit",minute:"2-digit"},v=e.min?e.min.toLocaleTimeString("en-US",s):null,T=e.max?e.max.toLocaleTimeString("en-US",s):null;if(o==="out-of-bounds"){if(v&&T)return`Must be between ${v} and ${T}.`;if(v)return`Must be ${v} or later.`;if(T)return`Must be ${T} or earlier.`}return""}),J=()=>{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.`);else{const v=s.parentElement;v?v.classList.add("fk-timepicker"):console.warn(`Parent of .k-timepicker not found for #${e.id} styling.`)}})};return t.onMounted(()=>{J()}),{raw:r,rules:D,debugEnabled:L,debugLines:B,placeholder:q,isValid:l,reason:t.readonly(d),validationMessage:I,isComplete:h,inRangeTime:u,cursorPos:f,hour:t.readonly(E),hour24:t.readonly(F),minute:t.readonly(S),period:t.readonly($),time24:t.readonly(m),parsedRawTime:t.readonly(_),handleChange:y,handleKeyDown:P,handleKeyUp:G,handleClick:x,handleWheel:H,handleBlur:te}}function xe(e){return t.getCurrentScope()?(t.onScopeDispose(e),!0):!1}const ve=typeof window<"u"&&typeof document<"u";typeof WorkerGlobalScope<"u"&&globalThis instanceof WorkerGlobalScope;const Me=Object.prototype.toString,Te=e=>Me.call(e)==="[object Object]",ae=()=>{},$e=Ie();function Ie(){var e,r;return ve&&((e=window?.navigator)==null?void 0:e.userAgent)&&(/iP(?:ad|hone|od)/.test(window.navigator.userAgent)||((r=window?.navigator)==null?void 0:r.maxTouchPoints)>2&&/iPad|Macintosh/.test(window?.navigator.userAgent))}function me(e){return Array.isArray(e)?e:[e]}function Ce(e,r,f){return t.watch(e,r,{...f,immediate:!0})}const be=ve?window:void 0;function ue(e){var r;const f=t.toValue(e);return(r=f?.$el)!=null?r:f}function pe(...e){const r=[],f=()=>{r.forEach(A=>A()),r.length=0},L=(A,k,b,D)=>(A.addEventListener(k,b,D),()=>A.removeEventListener(k,b,D)),q=t.computed(()=>{const A=me(t.toValue(e[0])).filter(k=>k!=null);return A.every(k=>typeof k!="string")?A:void 0}),K=Ce(()=>{var A,k;return[(k=(A=q.value)==null?void 0:A.map(b=>ue(b)))!=null?k:[be].filter(b=>b!=null),me(t.toValue(q.value?e[1]:e[0])),me(t.unref(q.value?e[2]:e[1])),t.toValue(q.value?e[3]:e[2])]},([A,k,b,D])=>{if(f(),!A?.length||!k?.length||!b?.length)return;const C=Te(D)?{...D}:D;r.push(...A.flatMap(E=>k.flatMap(S=>b.map($=>L(E,S,$,C)))))},{flush:"post"}),N=()=>{K(),f()};return xe(f),N}let Se=!1;function Pe(e,r,f={}){const{window:L=be,ignore:q=[],capture:K=!0,detectIframe:N=!1,controls:A=!1}=f;if(!L)return A?{stop:ae,cancel:ae,trigger:ae}:ae;if($e&&!Se){Se=!0;const m={passive:!0};Array.from(L.document.body.children).forEach(h=>h.addEventListener("click",ae,m)),L.document.documentElement.addEventListener("click",ae,m)}let k=!0;const b=m=>t.toValue(q).some(h=>{if(typeof h=="string")return Array.from(L.document.querySelectorAll(h)).some(U=>U===m.target||m.composedPath().includes(U));{const U=ue(h);return U&&(m.target===U||m.composedPath().includes(U))}});function D(m){const h=t.toValue(m);return h&&h.$.subTree.shapeFlag===16}function C(m,h){const U=t.toValue(m),a=U.$.subTree&&U.$.subTree.children;return a==null||!Array.isArray(a)?!1:a.some(p=>p.el===h.target||h.composedPath().includes(p.el))}const E=m=>{const h=ue(e);if(m.target!=null&&!(!(h instanceof Element)&&D(e)&&C(e,m))&&!(!h||h===m.target||m.composedPath().includes(h))){if("detail"in m&&m.detail===0&&(k=!b(m)),!k){k=!0;return}r(m)}};let S=!1;const $=[pe(L,"click",m=>{S||(S=!0,setTimeout(()=>{S=!1},0),E(m))},{passive:!0,capture:K}),pe(L,"pointerdown",m=>{const h=ue(e);k=!b(m)&&!!(h&&!m.composedPath().includes(h))},{passive:!0}),N&&pe(L,"blur",m=>{setTimeout(()=>{var h;const U=ue(e);((h=L.document.activeElement)==null?void 0:h.tagName)==="IFRAME"&&!U?.contains(L.document.activeElement)&&r(m)},0)},{passive:!0})].filter(Boolean),F=()=>$.forEach(m=>m());return A?{stop:F,cancel:()=>{k=!1},trigger:m=>{k=!0,E(m),k=!1}}:F}function Le(e){const r=t.shallowRef(null),f=[".k-animation-container .k-popup",".k-popup",".k-timepicker-popup",".k-menu-popup"],L=Array.isArray(e.popupSelector)?e.popupSelector:[e.popupSelector??f].flat(),q=D=>D?typeof e.initialFocus=="string"?D.querySelector(e.initialFocus)??D:typeof e.initialFocus=="function"?e.initialFocus(D)??D:D.querySelector('button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])')??D:null,{activate:K,deactivate:N}=we.useFocusTrap(r,{escapeDeactivates:!1,clickOutsideDeactivates:!1,fallbackFocus:()=>r.value,initialFocus:()=>q(r.value),...e.focusTrapOptions??{}});let A=null,k=t.ref(null);const b=()=>{if(e.resolvePopupEl)return e.resolvePopupEl();const D=(E,S)=>{const $=Array.from(E.querySelectorAll(S));if(!$.length)return null;const F=$.filter(m=>m.offsetParent!==null||m.getClientRects().length>0);return F[F.length-1]??$[$.length-1]??null},C=e.triggerEl?.value?.closest?.(".k-animation-container")??document.body;for(const E of L){const S=D(C,E);if(S)return S}for(const E of L){const S=D(document,E);if(S)return S}return null};return Pe(r,D=>{k.value="outside",e.isOpen.value&&e.onRequestClose?.("outside",D)}),t.watch(()=>e.isOpen.value,D=>{D?(k.value=null,t.nextTick(()=>{const C=b();C&&(r.value=C,setTimeout(()=>K(),0),A||(A=E=>{E.key==="Escape"&&(k.value="escape",e.isOpen.value&&e.onRequestClose?.("escape",E))},document.addEventListener("keydown",A,!0)))})):(N(),A&&(document.removeEventListener("keydown",A,!0),A=null),r.value=null,k.value==="outside"&&t.nextTick(()=>{const C=()=>{const E=e.triggerEl?.value,S=E?.querySelector("input"),$=document.activeElement;$&&($===S||E&&E.contains($))&&(S??E)?.blur?.()};requestAnimationFrame(()=>setTimeout(C,0))}),e.returnFocusToTrigger!==!1&&k.value==="escape"&&e.triggerEl?.value&&(console.log("Returning focus to trigger element:",e.triggerEl.value),t.nextTick(()=>{const C=()=>{const E=e.triggerEl?.value;if(!E)return;(E.querySelector("input")??E)?.focus?.()};requestAnimationFrame(()=>setTimeout(C,0))})))}),{popupRef:r,activate:K,deactivate:N,lastCloseReason:t.readonly(k),setPopupEl:D=>r.value=D}}Z.useGridA11y=ke,Z.useMaskedDateInput=De,Z.useMaskedDateRangeInput=Ae,Z.useMaskedTimeInput=Ee,Z.usePopupTrap=Le,Object.defineProperty(Z,Symbol.toStringTag,{value:"Module"})}));
|
|
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,L=null,P=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(I=>I===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=()=>{L=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 I=Array.from(s.querySelectorAll(".k-animation-container .k-popup .k-column-menu .k-columnmenu-item-wrapper .k-columnmenu-item"));if(I.length===1)I[0].focus(),I[0].click(),S.attempts=0;else if(I.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)})}})})}),L.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 I=S==="next"?A.nextElementSibling:A.previousElementSibling;for(;I;){const H=I;try{if(H.hasAttribute&&H.classList.contains("k-table-row"))return H}catch{}I=S==="next"?I.nextElementSibling:I.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(!P)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&&(P=new MutationObserver(()=>{l()}),P.observe(i,{childList:!0,subtree:!0}))}catch(l){console.error("Error setting up row navigation:",l)}},$=()=>{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)}),L&&(L.disconnect(),L=null),P&&(P.disconnect(),P=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=i.dataset.featherKSortable!=="false";y.setAttribute("tabindex","-1"),S||I?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(I){n.value=i;const W=new KeyboardEvent("keydown",{key:"Enter",code:"Enter",keyCode:13,which:13,bubbles:!0,cancelable:!0});i.dispatchEvent(W)}};i.addEventListener("click",re),B.push(()=>{i.removeEventListener("click",re)});const z=Y=>{if((Y.code==="Enter"||Y.code==="Space")&&(S||I)){if(n.value=i,n.value.focus(),S)Y.preventDefault(),Y.stopPropagation(),H(Y);else if(I){const W=i.querySelector(".k-link");W&&W.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(I=>I.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(),$(),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),L=t.ref(!!e.debug),P=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")}),$=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,M,J]=n.value.split("/"),o=parseInt(f),u=parseInt(M),g=parseInt(J);if(l(g,o,u)){const T=new Date(g,o-1,u);q(T)?e.onChange({value:T,event:a}):e.onChange({value:null,event:a})}else e.onChange({value:null,event:a})}},q=a=>{const f=e.min??void 0,M=e.max??void 0;return!(f&&a<f||M&&a>M)},m=t.computed(()=>{if((n.value??"").length===10&&v.value.length===8){const[a,f,M]=(n.value??"").split("/"),J=parseInt(a),o=parseInt(f),u=parseInt(M);if(l(u,J,o))return new Date(u,J-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,M)=>f>=1&&f<=12&&a>=1900&&M>=1&&M<=F(a,f),p=a=>{n.value=a.value;const f=a.event?.target;d.value=f?.selectionStart??0,$(a)},i=a=>{d.value=a.target.selectionStart??0},s=(a,f,M)=>{const J=f?.selectionStart??d.value??0;d.value=J;let o=parseInt(C.value),u=parseInt(D.value),g=parseInt(x.value);if(!(v.value.length>=8)||!l(g,o,u)){const G=e.defaultValue??new Date;o=G.getMonth()+1,u=G.getDate(),g=G.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:M}),t.nextTick(()=>{requestAnimationFrame(()=>{const _=document.getElementById(e.id),X=d.value??0;_&&(_.focus(),_.setSelectionRange(X,X))})});return}const O=w(J);if(O==="mm")o=a==="ArrowUp"?o<12?o+1:1:o>1?o-1:12;else if(O==="dd"){const G=new Date(g,o,0).getDate();u=a==="ArrowUp"?u<G?u+1:1:u>1?u-1:G}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,j,K]=n.value.split("/"),ae=new Date(parseInt(K),parseInt(ne)-1,parseInt(j));ae.toString()!=="Invalid Date"&&parseInt(K)>=1e3?e.onChange({value:q(ae)?ae:null,event:M}):e.onChange({value:null,event:M}),t.nextTick(()=>{requestAnimationFrame(()=>{const G=document.getElementById(e.id),U=d.value??0;G&&(G.focus(),G.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)},I=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 M=(f.getMonth()+1).toString().padStart(2,"0"),J=f.getDate().toString().padStart(2,"0"),o=f.getFullYear().toString();n.value=`${M}/${J}/${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 ${P.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""}),W=()=>{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(()=>{W()}),{raw:n,cursorPos:d,debugEnabled:L,debugLines:H,placeholder:P,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:I,initStyling:W}}function Te(e){const n=t.ref(""),d=t.ref(void 0),L=t.ref(!!e.debug),P=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()),$=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=$(l.value.start),c=$(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""}}),I=["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"},W=(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 Q=document.getElementById(e.id),ee=d.value??0;Q&&(Q.focus(),Q.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 Q=V.getMonth()+1,ee=r==="ArrowUp"?Q<12?Q+1:1:Q>1?Q-1:12;V.setMonth(ee-1);const ge=C(V.getFullYear(),ee);V.getDate()>ge&&V.setDate(ge)}else if(le==="dd"){const Q=C(V.getFullYear(),V.getMonth()+1),ee=V.getDate(),ge=r==="ArrowUp"?ee<Q?ee+1:1:ee>1?ee-1:Q;V.setDate(ge)}else if(le==="yyyy"){const Q=V.getFullYear();V.setFullYear(r==="ArrowUp"?Q+1:Math.max(1,Q-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=$(ce),we=$(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=$(c),Z=$(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)},M=r=>{d.value=r.target.selectionStart??0},J=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(I.includes(r.key)){r.preventDefault();const c=r.target;W(r.key,c,r)}},o=r=>{r.preventDefault();const c=r.deltaY<0?"ArrowUp":"ArrowDown";W(c,r.target,r)},u=r=>{if(H.includes(r.key)||I.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)},T=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&&P.value&&e.onRequestClose){const R=typeof e.closeDelay=="number"?e.closeDelay:e.closeDelay?.value??0;setTimeout(()=>{e.onRequestClose?.(),P.value=!1,g()},R)}return}},{immediate:!0});const ne=t.computed(()=>n.value&&n.value.substring(0,2).replace(/\D/g,"0")||"0"),j=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"),G=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"),_=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(j.value).padStart(2,"0")} / ${String(K.value).padStart(4,"0")}`},{label:"End",value:`${String(ae.value).padStart(2,"0")} / ${String(G.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");if(!c){console.warn(`Parent div of #${e.id} not found for styling.`);return}c.classList.contains("fk-daterangepicker")||c.classList.add("fk-daterangepicker")})};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:L,debugLines:_,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(j),year1:t.readonly(K),month2:t.readonly(ae),day2:t.readonly(G),year2:t.readonly(U),handleChange:f,handleKeyDown:J,handleWheel:o,handleKeyUp:u,handleClick:M,handleBlur:T,handleClear:O,onCalendarChange:()=>{P.value=!0},initStyling:X}}function $e(e){const n=t.ref(""),d=t.ref(void 0),L=t.ref(!!e.debug),P=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.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=$.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 T=o%12;return T===0&&(T=12),`${String(T).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]),T=parseInt(u[2]),O=u[3].toUpperCase();if(g<1||g>12||T<0||T>59)return null;let ne=g%12;O==="PM"&&(ne+=12);const j=new Date;return j.setSeconds(0,0),j.setHours(ne),j.setMinutes(T),j},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,T=i(o);if(u){const O=i(u);if(T<O)return!1}if(g){const O=i(g);if(T>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 T=n.value.charAt(6);/[Aa]/.test(T)?(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(T)&&(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 T=u?.selectionStart??d.value??0;d.value=T;const O=C(T),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,_=U.getHours(),X=_>=12?"PM":"AM";n.value=F(_,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 j=parseInt(ne[1]),K=parseInt(ne[2]),ae=ne[3].toUpperCase();if(O==="hh")o==="ArrowUp"?j=j<12?j+1:1:j=j>1?j-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 _=K%U;let X=_===0?K+U:K+(U-_);X>=60&&(X=0),K=X}else{const _=K%U;let X=_===0?K-U:K-_;X<0&&(X=60-U),K=X}}else O==="ampm"&&(ae=ae==="AM"?"PM":"AM");n.value=`${String(j).padStart(2,"0")}:${String(K).padStart(2,"0")} ${ae}`;const G=l(n.value);G&&s(G)?e.onChange({value:G,event:g}):e.onChange({value:null,event:g}),t.nextTick(()=>{requestAnimationFrame(()=>{const U=document.getElementById(e.id),_=d.value??0;U&&(U.focus(),U.setSelectionRange(_,_))})})},I=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(),T=g>=12?"PM":"AM";n.value=F(g,u.getMinutes(),T);return}}},{immediate:!0});const Y=t.computed(()=>[["Time",n.value||"--:-- --"],["Hour (12h)",D.value],["Hour (24h)",q.value],["Minute",x.value],["Period",$.value],["Time (24h)",m.value??"--:--:--"],["Digits only",v.value],["Parsed Date",W.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",M.value]]),W=t.computed(()=>l(n.value)??null),a=t.computed(()=>{if(!B.value){if(!h.value)return!0;const u=W.value;return u?s(u):!1}if(!N.value)return!0;const o=W.value;return!h.value||!o?!1:s(o)}),f=t.computed(()=>{if(!B.value){if(!h.value)return;const u=W.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=W.value;return o?s(o)?"valid":"out-of-bounds":"invalid-time"}),M=t.computed(()=>{const o=f.value;if(!o||o==="valid")return"";if(o==="incomplete")return"Required";if(o==="invalid-time")return`Must be in ${P.value} format.`;const u={hour:"2-digit",minute:"2-digit"},g=e.min?e.min.toLocaleTimeString("en-US",u):null,T=e.max?e.max.toLocaleTimeString("en-US",u):null;if(o==="out-of-bounds"){if(g&&T)return`Must be between ${g} and ${T}.`;if(g)return`Must be ${g} or later.`;if(T)return`Must be ${T} or earlier.`}return""}),J=()=>{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.`);return}const g=u.parentElement;if(!g){console.warn(`Parent of .k-timepicker not found for #${e.id} styling.`);return}g.classList.contains("fk-timepicker")||g.classList.add("fk-timepicker")})};return t.onMounted(()=>{J()}),{raw:n,rules:w,debugEnabled:L,debugLines:Y,placeholder:P,isValid:a,reason:t.readonly(f),validationMessage:M,isComplete:h,inRangeTime:s,cursorPos:d,hour:t.readonly(D),hour24:t.readonly(q),minute:t.readonly(x),period:t.readonly($),time24:t.readonly(m),parsedRawTime:t.readonly(W),handleChange:y,handleKeyDown:I,handleKeyUp:re,handleClick:A,handleWheel:H,handleBlur:z,initStyling:J}}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,Le=e=>Ce.call(e)==="[object Object]",se=()=>{},Pe=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},L=(k,b,v,w)=>(k.addEventListener(b,v,w),()=>k.removeEventListener(b,v,w)),P=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=P.value)==null?void 0:k.map(v=>fe(v)))!=null?b:[De].filter(v=>v!=null),he(t.toValue(P.value?e[1]:e[0])),he(t.unref(P.value?e[2]:e[1])),t.toValue(P.value?e[3]:e[2])]},([k,b,v,w])=>{if(d(),!k?.length||!b?.length||!v?.length)return;const C=Le(w)?{...w}:w;n.push(...k.flatMap(D=>b.flatMap(x=>v.map($=>L(D,x,$,C)))))},{flush:"post"}),N=()=>{B(),d()};return Ie(d),N}let Ae=!1;function Fe(e,n,d={}){const{window:L=De,ignore:P=[],capture:B=!0,detectIframe:N=!1,controls:k=!1}=d;if(!L)return k?{stop:se,cancel:se,trigger:se}:se;if(Pe&&!Ae){Ae=!0;const m={passive:!0};Array.from(L.document.body.children).forEach(h=>h.addEventListener("click",se,m)),L.document.documentElement.addEventListener("click",se,m)}let b=!0;const v=m=>t.toValue(P).some(h=>{if(typeof h=="string")return Array.from(L.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 $=[ve(L,"click",m=>{x||(x=!0,setTimeout(()=>{x=!1},0),D(m))},{passive:!0,capture:B}),ve(L,"pointerdown",m=>{const h=fe(e);b=!v(m)&&!!(h&&!m.composedPath().includes(h))},{passive:!0}),N&&ve(L,"blur",m=>{setTimeout(()=>{var h;const F=fe(e);((h=L.document.activeElement)==null?void 0:h.tagName)==="IFRAME"&&!F?.contains(L.document.activeElement)&&n(m)},0)},{passive:!0})].filter(Boolean),q=()=>$.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"],L=Array.isArray(e.popupSelector)?e.popupSelector:[e.popupSelector??d].flat(),P=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:()=>P(n.value),...e.focusTrapOptions??{}});let k=null,b=t.ref(null);const v=()=>{if(e.resolvePopupEl)return e.resolvePopupEl();const w=(D,x)=>{const $=Array.from(D.querySelectorAll(x));if(!$.length)return null;const q=$.filter(m=>m.offsetParent!==null||m.getClientRects().length>0);return q[q.length-1]??$[$.length-1]??null},C=e.triggerEl?.value?.closest?.(".k-animation-container")??document.body;for(const D of L){const x=w(C,D);if(x)return x}for(const D of L){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"),$=document.activeElement;$&&($===x||D&&D.contains($))&&(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"})}));
|
|
@@ -44,5 +44,8 @@ export declare function useMaskedDateRangeInput(args: {
|
|
|
44
44
|
handleWheel: (event: WheelEvent) => void;
|
|
45
45
|
handleKeyUp: (event: KeyboardEvent) => void;
|
|
46
46
|
handleClick: (event: MouseEvent) => void;
|
|
47
|
+
handleBlur: (_event: FocusEvent) => void;
|
|
48
|
+
handleClear: (event?: Event) => void;
|
|
47
49
|
onCalendarChange: () => void;
|
|
50
|
+
initStyling: () => void;
|
|
48
51
|
};
|
|
@@ -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
|
|
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,
|
|
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
|
-
<
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
<
|
|
63
|
-
<
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
<div v-
|
|
80
|
-
<
|
|
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
|
-
</
|
|
84
|
-
</
|
|
85
|
-
</
|
|
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
|
|
|
@@ -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'"
|
|
@@ -70,6 +80,7 @@ const clickAdornment = () => { showCal.value ? closeCalendar() : openCalendar();
|
|
|
70
80
|
@keyup="range.handleKeyUp"
|
|
71
81
|
@wheel.prevent="range.handleWheel"
|
|
72
82
|
@click="range.handleClick"
|
|
83
|
+
@blur="range.handleBlur"
|
|
73
84
|
>
|
|
74
85
|
<template #calendar-adornment>
|
|
75
86
|
<SvgIcon
|
|
@@ -138,6 +149,7 @@ Creates a controller for a masked date range input.
|
|
|
138
149
|
- **`reason: Readonly<ComputedRef<string | undefined>>`**: Explanation for invalid states; returns `'valid'` when the range passes validation.
|
|
139
150
|
- **`spanDays: Readonly<ComputedRef<number | undefined>>`**: Span in days between clamped start/end; `undefined` when incomplete or invalid.
|
|
140
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
|
|
141
153
|
- Event handlers to wire to the input:
|
|
142
154
|
- **`handleChange(event)`**: Assigns `raw` from the input event and emits parsed range when complete and valid.
|
|
143
155
|
- **`handleKeyDown(event)`**:
|
|
@@ -146,12 +158,14 @@ Creates a controller for a masked date range input.
|
|
|
146
158
|
- **`handleWheel(event)`**: Prevents page scroll; interprets wheel as steppers (up/down) for the focused part.
|
|
147
159
|
- **`handleKeyUp(event)`**: Maintains caret position after cursor keys/steppers.
|
|
148
160
|
- **`handleClick(event)`**: Captures caret position on click for restoring.
|
|
161
|
+
- **`handleBlur(event)`**: Validates the input and updates the validity state when the input loses focus.
|
|
149
162
|
- **`onCalendarChange()`**: Marks subsequent `externalValue` updates as calendar-originated; used to optionally auto-close the popup.
|
|
150
163
|
|
|
151
164
|
## Behavior Details
|
|
152
165
|
|
|
153
166
|
- **Mask and parsing**: Expects `00/00/0000 - 00/00/0000`. Parsing requires both dates to be complete (10 chars each) and valid per calendar rules.
|
|
154
167
|
- **Validation**:
|
|
168
|
+
- Validation is performed only when the input loses focus (on blur).
|
|
155
169
|
- Each side must be a valid date (including month/day bounds like Feb 29).
|
|
156
170
|
- Clamped to `min`/`max` if provided; outside results in `value=null`.
|
|
157
171
|
- Ordered range required unless `allowReverse=true`.
|
|
@@ -164,6 +178,7 @@ Creates a controller for a masked date range input.
|
|
|
164
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`.
|
|
165
179
|
- **Raw preservation**: When external range becomes invalid/empty, the composable does not overwrite `raw`, preserving in-progress text.
|
|
166
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.
|
|
167
182
|
|
|
168
183
|
## Integration Pattern (Kendo + Popup)
|
|
169
184
|
|
|
@@ -176,6 +191,7 @@ Key event bindings:
|
|
|
176
191
|
- `@keyup="range.handleKeyUp"`
|
|
177
192
|
- `@wheel.prevent="range.handleWheel"`
|
|
178
193
|
- `@click="range.handleClick"`
|
|
194
|
+
- `@blur="range.handleBlur"`
|
|
179
195
|
|
|
180
196
|
Calendar coordination:
|
|
181
197
|
|
|
@@ -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
|
|
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
|
-
<
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
<
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|
|