UNPKG

headless-datetimepicker

Version:
5 lines (4 loc) 13.3 kB
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const c=require("react"),j=require("react/jsx-runtime"),x=require("@floating-ui/react-dom"),D=require("date-fns");function L(e,r){if(e in r){const t=r[e];return typeof t=="function"?t(e):t}throw new Error("Invalid match value")}function T(e,r){return(e%r+r)%r}const J=(e,{type:r,payload:t})=>{switch(r){case"action":return R(e,t);case"registerPicker":return{...e,pickers:{...e.pickers,[t.id]:{nestedLevel:t.nestedLevel,defaultType:t.defaultType,type:t.defaultType,attach:void 0,isOpen:t.defaultOpen,alwaysOpen:t.alwaysOpen}}};case"unregisterPicker":{const{[t]:n,...o}=e.pickers;return{...e,pickers:o}}case"select":{const n=t.action?R(e,{action:t.action,pickerId:t.pickerId}):{...e};let o=null;switch(t.item.type){case"day":{o=new Date(t.item.value),o.setHours(e.hour,e.minute);break}case"month":{n.month=t.item.value;break}case"year":{n.year=t.item.value;break}case"hour":{o=e.valueRef.current?new Date(e.valueRef.current):new Date,o.setHours(t.item.value),n.hour=t.item.value;break}case"minute":{o=e.valueRef.current?new Date(e.valueRef.current):new Date,o.setMinutes(t.item.value),n.minute=t.item.value;break}default:return e}return o&&n.onChange(o),n}case"defaultChanged":return{...e,...t};case"externalValueChanged":{const n=e.config.toDateParts(t);return{...e,year:n.year,month:n.month,hour:t.getHours(),minute:t.getMinutes()}}default:throw new Error("Invalid action "+r)}};function R(e,r){let t=r.action,n="";const o=r.action.match(/^(open|close|next|prev|showYear|showMonth|showDay|toggleYear|toggleMonth|toggleDay|toggle)(.*)$/);if(o&&(t=o[1],n=o[2],n===""&&(n=r.pickerId||Object.keys(e.pickers).reverse()[0],n===void 0)))throw new Error("There is no Picker in the current Provider");switch(t){case"open":return{...e,pickers:{...e.pickers,[n]:{...e.pickers[n],attach:r.ref,isOpen:!0}}};case"close":return{...e,pickers:{...e.pickers,[n]:{...e.pickers[n],isOpen:!1,type:e.pickers[n].defaultType}}};case"toggle":return{...e,pickers:{...e.pickers,[n]:{...e.pickers[n],attach:r.ref,isOpen:!e.pickers[n].isOpen,type:e.pickers[n].defaultType}}};case"next":{if(!e.pickers[n].type)return e;const{month:i,year:s}=e;return L(e.pickers[n].type,{hour:()=>e,minute:()=>e,day:()=>({...e,year:i===12?s+1:s,month:i%12+1}),month:()=>({...e,year:s+1,month:i}),year:()=>({...e,year:s+1,month:i})})}case"prev":{if(!e.pickers[n].type)return e;const{month:i,year:s}=e;return L(e.pickers[n].type,{hour:()=>e,minute:()=>e,day:()=>({...e,year:i===1?s-1:s,month:T(i-2,12)+1}),month:()=>({...e,year:s-1,month:i}),year:()=>({...e,year:s-1,month:i})})}case"showYear":return{...e,pickers:{...e.pickers,[n]:{...e.pickers[n],type:"year"}}};case"toggleYear":return{...e,pickers:{...e.pickers,[n]:{...e.pickers[n],type:e.pickers[n].type==="year"?e.pickers[n].defaultType:"year"}}};case"showMonth":return{...e,pickers:{...e.pickers,[n]:{...e.pickers[n],type:"month"}}};case"toggleMonth":return{...e,pickers:{...e.pickers,[n]:{...e.pickers[n],type:e.pickers[n].type==="month"?e.pickers[n].defaultType:"month"}}};case"showDay":return{...e,pickers:{...e.pickers,[n]:{...e.pickers[n],type:"day"}}};case"toggleDay":return{...e,pickers:{...e.pickers,[n]:{...e.pickers[n],type:e.pickers[n].type==="day"?e.pickers[n].defaultType:"day"}}};case"today":{const i=new Date;i.setHours(e.hour,e.minute),e.onChange(i);const s=e.config.toDateParts(i);return{...e,year:s.year,month:s.month}}case"todayHour":{const i=new Date;e.onChange(i);const s=e.config.toDateParts(i);return{...e,year:s.year,month:s.month}}default:throw new Error("Invalid action "+r.action)}}const H=c.createContext(null);function W(){const e=c.useContext(H);if(!e)throw new Error("You need to use component inside Datepicker");return e}function P(){const e=W();return{...e,slot:q(e.state)}}function q(e){return{pickers:e.pickers,disabled:e.disabled,value:e.valueRef.current,month:e.month,monthName:e.config.monthNames[e.month-1],year:e.year,hour:e.hour,minute:e.minute}}const M=(e,r)=>{c.useEffect(()=>{r&&(typeof r=="function"?r(e.current):r.current=e.current)})};function N(...e){return e.filter(Boolean).join(" ")}function E(e,r,t={},n,o,i={}){if((i==null?void 0:i.visible)===!1&&i.hideOnClose!==!0)return null;const{as:s,children:u,...a}=S(r,e),h=s||n,l=typeof u=="function"?u(t):u;if(typeof a.className=="function"&&(a.className=a.className(t)),h===c.Fragment&&Object.keys(a).length>0){if(!c.isValidElement(l)||Array.isArray(l)&&l.length>1)throw new Error(['Passing props on "Fragment"!',"",'The current component is rendering a "Fragment".',"However we need to passthrough the following props:",Object.keys(a).map(m=>` - ${m}`).join(` `),"","You can apply a few solutions:",['Add an `as="..."` prop, to ensure that we render an actual element instead of a "Fragment".',"Render a single element as the child so that we can forward the props onto that element."].map(m=>` - ${m}`).join(` `)].join(` `));const{childClassName:d,...k}=l.props,f=typeof d=="function"?(...m)=>N(d(...m),a.className):N(d,a.className),v=f?{className:f,ref:o}:{ref:o};return c.cloneElement(l,Object.assign({},S(k,a),v))}return c.createElement(h,{...a,ref:o},l)}function S(...e){if(e.length===0)return{};if(e.length===1)return e[0];const r={},t={};for(const n of e)for(const o in n)o.startsWith("on")&&typeof n[o]=="function"?(t[o]??(t[o]=[]),t[o].push(n[o])):r[o]=n[o];if(r.disabled||r["aria-disabled"])return Object.assign(r,Object.fromEntries(Object.keys(t).map(n=>[n,void 0])));for(const n in t)Object.assign(r,{[n](o,...i){const s=t[n];for(const u of s){if((o instanceof Event||(o==null?void 0:o.nativeEvent)instanceof Event)&&o.defaultPrevented)return;u(o,...i)}}});return r}function O(e){return c.forwardRef(e)}const $=typeof window<"u"?c.useLayoutEffect:c.useEffect;function K(e,r,t,n){const o=c.useRef(r);$(()=>{o.current=r},[r]),c.useEffect(()=>{const i=(t==null?void 0:t.current)??window;if(!(i&&i.addEventListener))return;const s=u=>o.current(u);return i.addEventListener(e,s,n),()=>{i.removeEventListener(e,s,n)}},[e,t,n])}function z(e,r){K("mousedown",t=>{(Array.isArray(e)?e:[e]).some(n=>{if(n===void 0)return!1;const o=n==null?void 0:n.current;if(!o||o.contains(t.target))return!0})||r(t)})}const Q="div",X=[x.offset(10),x.flip({fallbackAxisSideDirection:"end",crossAxis:!1}),x.shift()],A=c.createContext({nestedLevel:0}),Z=O(({alwaysOpen:e,hideOnClose:r,middleware:t=X,attachTo:n,style:o,defaultType:i,defaultOpen:s=!1,disableClickOutside:u=!1,id:a,...h},l)=>{const{nestedLevel:d}=c.useContext(A),k=c.useId(),f=a||k,{state:v,slot:m,dispatch:w}=P(),y=c.useRef(i),b=c.useRef(s);c.useEffect(()=>(w({type:"registerPicker",payload:{id:f,nestedLevel:d+1,defaultType:y.current,defaultOpen:b.current,alwaysOpen:e}}),()=>w({type:"unregisterPicker",payload:f})),[w,f,d,e]);const p=v.pickers[f],g=n===!1?void 0:n!==void 0?n:e||p==null?void 0:p.attach,F=e||(p==null?void 0:p.isOpen)||!1,{refs:I,floatingStyles:U}=x.useFloating({open:F,elements:{reference:g?g.current:null},middleware:t,whileElementsMounted:x.autoUpdate});M(I.floating,l);const G=()=>{u!==!0&&(p!=null&&p.isOpen)&&w({type:"action",payload:{action:`close${f}`}})};z([I.floating,g],G);const B={style:{...o,...g!=null&&g.current?U:{}}};return j.jsx(A.Provider,{value:c.useMemo(()=>({nestedLevel:d+1,id:f,defaultType:y.current}),[d,f]),children:E(B,h,m,Q,I.setFloating,{visible:F,hideOnClose:r})})}),ee="button",ne=O(({action:e,...r},t)=>{const{id:n}=c.useContext(A),o=c.useRef(null);M(o,t);const{slot:i,dispatch:s}=P();return E({onClick:()=>s({type:"action",payload:{action:e,ref:o,pickerId:n}})},r,i,ee,o)});function V(){const[e]=c.useState(te);return c.useEffect(()=>()=>e.dispose(),[e]),e}function te(){const e=[],r={addEventListener(t,n,o,i){return t.addEventListener(n,o,i),r.add(()=>t.removeEventListener(n,o,i))},requestAnimationFrame(...t){const n=requestAnimationFrame(...t);return r.add(()=>cancelAnimationFrame(n))},nextFrame(...t){return r.requestAnimationFrame(()=>r.requestAnimationFrame(...t))},add(t){return e.push(t),()=>{const n=e.indexOf(t);if(n>=0)for(const o of e.splice(n,1))o()}},dispose(){for(const t of e.splice(0))t()}};return r}const C=function(r){const t=c.useRef(r);return $(()=>{t.current=r},[r]),c.useCallback((...n)=>t.current(...n),[t])},re="input",oe=O(({format:e="yyyy/MM/dd",parse:r,type:t,...n},o)=>{const i=c.useRef(null);M(i,o);const{state:s,slot:u,dispatch:a}=P(),h=c.useCallback(p=>typeof e=="function"?e(p):s.config.format(p,e),[e,s.config]),[l,d]=c.useState(void 0),k=c.useMemo(()=>h(u.value),[u.value,h]),f=V(),v=C(()=>f.nextFrame(()=>a({type:"action",payload:{action:"open",ref:i}}))),m=C(p=>d(p.target.value)),w=C(p=>{let g=null;if(p.target.value)try{g=typeof e=="function"?r(p.target.value,u.value):s.config.parse(p.target.value,e,u.value)}catch{}g!==null&&D.isValid(g)&&s.onChange(g),f.nextFrame(()=>d(void 0))}),y=typeof e=="function"&&typeof r!="function",b={type:t||"text",readOnly:y,disabled:s.disabled,value:l!==void 0?l:k,onFocus:v,onChange:y?void 0:m,onBlur:y?void 0:w};return E(b,n,u,re,i)}),se="button",_="data-calendar-item-id",ie=O(({item:e,action:r,...t},n)=>{const{id:o}=c.useContext(A),{state:i,slot:s,dispatch:u}=P(),a={[_]:e.type+"-"+e.text,onClick:"isHeader"in e&&e.isHeader||i.disabled?void 0:()=>{u({type:"select",payload:{item:e,pickerId:o,action:r}})}};return E(a,t,s,se,n)});function ce(e,r,t){c.useLayoutEffect(()=>{if(e&&t&&r){const n=document.querySelector(`[${_}="${r}-${t}"]`);n&&n.scrollIntoView({block:"nearest"})}},[r,t,e])}const ue="div",ae=O(({type:e,disableAutoScroll:r,...t},n)=>{const{id:o,defaultType:i}=c.useContext(A),{state:s}=P(),u=o?s.pickers[o]:void 0,a=e||(u==null?void 0:u.type)||i;if(a===void 0)throw new Error("No type provided, You need either need set the type to Items or set the defaultType to Picker component");const h=s.valueRef.current,l=s.filterDate,d=c.useMemo(()=>a==="hour"||a==="minute"?s.config[a+"s"]({type:a,hour:s.hour,minute:s.minute}):s.config[a+"s"]({type:a,year:s.year,month:s.month,value:h,startOfWeek:s.startOfWeek}).map(f=>f.type==="day"&&!f.isHeader&&!l(f.value)?{...f,isDisabled:!0}:f),[a,h,s.config,s.month,s.year,s.hour,s.minute,s.startOfWeek,l]);return ce(r!==!0&&u!==void 0&&(u.alwaysOpen===!0||u.isOpen)&&["year","hour","minute"].includes(a),a,a!=="day"?s[a]:void 0),E({},t,{items:d,type:a,...s},ue,n)}),Y={dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],format:function(e,r){return e?D.format(e,r):""},parse:function(e,r,t){return D.parse(e,r,t||new Date)},toDateParts:function(e){return new Intl.DateTimeFormat("en-US",{year:"numeric",month:"numeric",day:"numeric"}).formatToParts(e).reduce((r,t)=>(t.type!=="literal"&&(r[t.type]=+t.value),r),{})},years:function({type:e,year:r}){const t=new Date().getFullYear();return[...Array(200).keys()].map(n=>({type:e,key:e+n,isToday:t===n+1900,isSelected:r===n+1900,isHeader:!1,isDisabled:!1,value:n+1900,text:n+1900+""}))},months:function({type:e,month:r}){const t=new Date().getMonth();return[...this.monthNames.keys()].map(n=>({type:e,key:e+n,isToday:t===n,isSelected:r===n+1,isHeader:!1,isDisabled:!1,value:n+1,text:this.monthNames[n]}))},days:function({type:e,month:r,startOfWeek:t,year:n,value:o}){const i=new Date(n,r-1,1),s=D.startOfMonth(i),u=D.endOfMonth(i),a=T(t-1,7),h=D.startOfToday().getTime(),l=o?D.startOfDay(o).getTime():0;return this.dayNames.map((d,k)=>{const f=T(t+k,7);return{type:e,key:"weekday"+f,isToday:!1,isSelected:!1,isHeader:!0,isDisabled:!1,value:k,text:this.dayNames[f]}}).concat(D.eachDayOfInterval({start:D.addDays(s,-T(s.getDay()-t,7)),end:D.addDays(u,T(a-u.getDay(),7))}).map(d=>({type:e,key:d.toString(),isToday:h===d.getTime(),isSelected:l===d.getTime(),isHeader:!1,isInCurrentMonth:d>=s&&d<=u,isDisabled:d<s||d>u,value:d,text:d.getDate()+""})))},hours:function({type:e,hour:r}){return[...Array(24).keys()].map(t=>({type:e,key:t,value:t,text:t+"",isToday:!1,isSelected:r===t,isHeader:!1,isDisabled:!1}))},minutes:function({type:e,minute:r}){return[...Array(60).keys()].map(t=>({type:e,key:t,value:t,text:t+"",isToday:!1,isSelected:r===t,isHeader:!1,isDisabled:!1}))}},de=c.Fragment,fe=c.forwardRef(({defaultValue:e,value:r,onChange:t,disabledKeyboardNavigation:n,disabled:o=!1,config:i=Y,startOfWeek:s=0,filterDate:u=()=>!0,...a},h)=>{const l=c.useRef(r||e||null),d=V(),k=C(y=>{le(l.current,y)||y&&!u(y)||d.nextFrame(()=>{l.current=y,t==null||t(l.current),m({type:"externalValueChanged",payload:y||new Date})})}),f=C(u),[v,m]=c.useReducer(J,null,()=>{const y=l.current||new Date,b=i.toDateParts(y);return{config:i,disabled:o,year:b.year,month:b.month,hour:y.getHours(),minute:y.getMinutes(),calendarOpen:!1,hourOpen:!1,valueRef:l,startOfWeek:s,onChange:k,filterDate:f,pickers:{}}});c.useEffect(()=>{k(r||null)},[r,k]),c.useEffect(()=>{m({type:"defaultChanged",payload:{startOfWeek:s}})},[s]),c.useEffect(()=>{m({type:"defaultChanged",payload:{disabled:o}})},[o]);const w={};return j.jsx(H.Provider,{value:{state:v,dispatch:m},children:E(w,a,q(v),de,h)})});function le(e,r){return e===r||e!==null&&r!==null&&D.isEqual(e,r)}const pe=Object.assign(fe,{Picker:Z,Input:oe,Button:ne,Items:ae,Item:ie});exports.Datepicker=pe;exports.config=Y;