ten-protons-datepicker 1.0.0 → 1.1.0

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/README.md CHANGED
@@ -22,9 +22,11 @@ npm i ten-protons-datepicker
22
22
  import 'ten-protons-datepicker/locales/uk'; // optional UI strings for locale="uk"
23
23
  </script>
24
24
 
25
- <x-datepicker name="period" mode="range" locale="uk" min="2025-01-01" label="Period"></x-datepicker>
25
+ <ten-protons-datepicker name="period" mode="range" locale="uk" min="2025-01-01" label="Period"></ten-protons-datepicker>
26
26
  ```
27
27
 
28
+ `<x-datepicker>` is registered as an alias for the same element, so either tag works. Prefer `ten-protons-datepicker`: `x-datepicker` is a generic name another library could also claim, and the first one registered wins.
29
+
28
30
  `mode="range"` / `mode="multiple"` and `enable-time` load their module on demand, so single-date pages don't pay for them.
29
31
 
30
32
  | Attribute | Notes |
@@ -35,14 +37,37 @@ npm i ten-protons-datepicker
35
37
  | `number-of-months`, `show-other-months`, `allow-input`, `close-on-select`, `disabled-days`, `output-timestamp`, `enable-time`, `value-in-utc`, `inline` | booleans: present = true, `="false"` = false |
36
38
 
37
39
  ```js
38
- const el = document.querySelector('x-datepicker');
40
+ const el = document.querySelector('ten-protons-datepicker');
39
41
  el.value; // ISO string of the current selection
40
42
  el.options = { disabledDates: (d) => d.getDay() === 0, onChange: console.log };
41
43
  el.addEventListener('change', (e) => console.log(e.detail)); // also: open, close, monthChange, yearChange
42
44
  await el.ready; // resolves with the underlying Datepicker
43
45
  ```
44
46
 
45
- Style with `::part(input)`, `::part(toggle)` and the `--tp-*` variables.
47
+ The input is styled out of the box to match the calendar (border, radius and colours, light and dark, red border on invalid input). Restyle it with `::part(input)` and `::part(toggle)`, e.g. `ten-protons-datepicker::part(input) { border-radius: 0 }`. The calendar button is the web component's own icon, so `showIcon` doesn't apply to it.
48
+
49
+ ### Vue
50
+
51
+ Tell Vue that the tag is a custom element (Vite: `vue({ template: { compilerOptions: { isCustomElement: (tag) => tag === 'ten-protons-datepicker' } } })`), then bind `value` and listen to `change`:
52
+
53
+ ```vue
54
+ <script setup lang="ts">
55
+ import 'ten-protons-datepicker/wc'; // its CSS is built in; enable-time loads the time module itself
56
+
57
+ defineProps<{ modelValue: number | null }>();
58
+ const emit = defineEmits<{ 'update:modelValue': [timestamp: number | null] }>();
59
+ const onChange = (e: Event) => {
60
+ const value = (e as CustomEvent).detail;
61
+ emit('update:modelValue', typeof value === 'number' ? value : null);
62
+ };
63
+ </script>
64
+
65
+ <template>
66
+ <ten-protons-datepicker :value="modelValue ?? ''" label="Due" value-in-utc output-timestamp enable-time @change="onChange" />
67
+ </template>
68
+ ```
69
+
70
+ Attributes such as `theme` and `max` can be bound the same way. The element is created and destroyed with the component, so there is nothing to clean up. Other frameworks work the same: set attributes, listen to `change`.
46
71
 
47
72
  ## Imperative API
48
73
 
@@ -81,6 +106,7 @@ With `inline: true` the calendar renders inside the given element (any element,
81
106
  | `position` | `'auto'` | `auto top bottom left right`; auto flips above when there is no room below |
82
107
  | `theme` | auto | `'light' \| 'dark'` |
83
108
  | `allowInput` | `true` | `false` makes the input read-only |
109
+ | `showIcon` | `true` | calendar icon inside the input, so it reads as a date field even without a label. `false` removes it. Needs `core.css`; the web component has its own toggle button and ignores this option |
84
110
  | `closeOnSelect` | `true` (single, range), `false` (multiple, and with `enableTime`) | |
85
111
  | `closeOnOutsideClick` | `true` | outside pointer-down or focus |
86
112
  | `classes` | | replace any default class name (`ClassNames`) |
@@ -148,7 +174,7 @@ const dp = withTime(new Datepicker(input, { dateFormat: 'dd.MM.yyyy', onChange:
148
174
  ```
149
175
 
150
176
  ```html
151
- <x-datepicker enable-time output-timestamp name="meeting"></x-datepicker> <!-- loads the time module itself -->
177
+ <ten-protons-datepicker enable-time output-timestamp name="meeting"></ten-protons-datepicker> <!-- loads the time module itself -->
152
178
  ```
153
179
 
154
180
  How it behaves:
@@ -197,7 +223,7 @@ withTime(new Datepicker(input, { dateFormat: 'dd.MM.yyyy', outputTimestamp: true
197
223
  // typed "1742044029" shows 15.03.2025 13:07:09 getDate() = 1742044029 exact round trip
198
224
  ```
199
225
 
200
- Ranges work the same way: `withTime(withRange(new Datepicker(input, { outputTimestamp: true })))` returns `[1741597200, 1741804200]` for 10 March 09:00:00 to 12 March 18:30:00 (UTC). In the web component, `<x-datepicker enable-time mode="range">` has the value `2025-03-10T09:00:00/2025-03-12T18:30:00`, or `1741597200/1741804200` with `output-timestamp`.
226
+ Ranges work the same way: `withTime(withRange(new Datepicker(input, { outputTimestamp: true })))` returns `[1741597200, 1741804200]` for 10 March 09:00:00 to 12 March 18:30:00 (UTC). In the web component, `<ten-protons-datepicker enable-time mode="range">` has the value `2025-03-10T09:00:00/2025-03-12T18:30:00`, or `1741597200/1741804200` with `output-timestamp`.
201
227
 
202
228
  Things to know:
203
229
 
@@ -216,7 +242,7 @@ dp.getDate().toISOString(); // '2025-03-15T00:00:00.000Z', s
216
242
  ```
217
243
 
218
244
  ```html
219
- <x-datepicker name="due" value-in-utc value="2025-03-15T00:00:00.000Z"></x-datepicker>
245
+ <ten-protons-datepicker name="due" value-in-utc value="2025-03-15T00:00:00.000Z"></ten-protons-datepicker>
220
246
  ```
221
247
 
222
248
  Without it, a user in Kyiv (UTC+2) who picks 15 March gets a `Date` for **local** midnight, and `toISOString()` sends `2025-03-14T22:00:00.000Z`: the backend stores the 14th. That is the bug this option removes.
@@ -282,6 +308,8 @@ The calendar is always Gregorian, and manual input accepts Arabic-Indic and Pers
282
308
  Import `core.css` (and `themes.css` for dark mode). Customise with CSS variables on `.tp-dp`:
283
309
  `--tp-bg --tp-fg --tp-muted --tp-border --tp-hover --tp-accent --tp-accent-fg --tp-range --tp-focus --tp-radius --tp-cell --tp-pad --tp-z --tp-shadow --tp-font`.
284
310
 
311
+ The input's calendar icon (`showIcon`) is a CSS background on the `.tp-icon` class, with extra left padding (right in RTL). To change it, override `background-image` on `input.tp-icon`; to remove it, pass `showIcon: false`.
312
+
285
313
  Dark mode follows `prefers-color-scheme` unless `theme: 'light'` / `data-theme="light"`; `theme: 'dark'` forces it. To style with Tailwind or CSS Modules, pass `classes` and skip `core.css`.
286
314
 
287
315
  ## Browsers
@@ -111,6 +111,8 @@ interface DatepickerOptions {
111
111
  valueInUtc?: boolean;
112
112
  /** Allow typing a date. Default `true`. When `false` the input is read-only. */
113
113
  allowInput?: boolean;
114
+ /** Show a calendar icon inside the input so it reads as a date field even without a label. Default `true`. Needs `core.css`. */
115
+ showIcon?: boolean;
114
116
  /** Close once a selection is complete. Defaults to `true` for single/range, `false` for multiple and with `enableTime`. */
115
117
  closeOnSelect?: boolean;
116
118
  closeOnOutsideClick?: boolean;
@@ -0,0 +1 @@
1
+ import {c as c$2}from'./chunk-CUGUCENC.js';import {c,b as b$1}from'./chunk-Q2P4Y4T6.js';import {b as b$2}from'./chunk-BHROFXOE.js';import {b,f,c as c$1,i,h,m,l,e,j as j$1,k as k$1,g as g$1,d,a}from'./chunk-ANB32WKT.js';var j=(h,n,t,e$1)=>{if(h.ctrlKey||h.metaKey||h.altKey)return null;let i=(n.getDay()-t+7)%7,s=e$1?-1:1;switch(h.key){case "ArrowLeft":return d(n,-s);case "ArrowRight":return d(n,s);case "ArrowUp":return d(n,-7);case "ArrowDown":return d(n,7);case "Home":return d(n,-i);case "End":return d(n,6-i);case "PageUp":return e(n,h.shiftKey?-12:-1);case "PageDown":return e(n,h.shiftKey?12:1);default:return null}};var W={root:"tp-dp",pop:"tp-pop",months:"tp-months",head:"tp-head",title:"tp-title",nav:"tp-nav",grid:"tp-grid",dow:"tp-dow",day:"tp-day",out:"tp-out",today:"tp-today",selected:"tp-selected",disabled:"tp-disabled",inRange:"tp-in-range",rangeStart:"tp-range-start",rangeEnd:"tp-range-end",foot:"tp-foot",btn:"tp-btn",time:"tp-time",timeField:"tp-time-field",sr:"tp-sr"},g=(h,n="",t={})=>{let e=document.createElement(h);n&&(e.className=n);for(let i in t)e.setAttribute(i,t[i]);return e},z=(...h)=>h.filter(Boolean).join(" "),k=(h,n,t)=>{h.getAttribute(n)!==t&&(t===null?h.removeAttribute(n):h.setAttribute(n,t));},x=class{constructor(n){this.o=n;this.panels=[];this.layoutKey=-1;this.focusTd=null;let{loc:t,cls:e,on:i}=n,s=this.el=g("div",z(e.root,!n.inline&&e.pop),{id:n.id,dir:t.rtl?"rtl":"ltr","aria-label":t.strings.label,...n.inline?{role:"group"}:{role:"dialog","aria-modal":"true"},...n.theme?{"data-theme":n.theme}:{}}),o=g("div",e.months);for(let a=0;a<n.months;a++)o.append(this.panel(a));let r=g("div",e.foot);for(let a of ["today","clear"]){let d=g("button",e.btn,{type:"button","data-a":a});d.textContent=t.strings[a],r.append(d);}this.live=g("div",e.sr,{"aria-live":"polite","aria-atomic":"true"}),this.timeUI=n.time?.({loc:t,cls:e,id:n.id,change:i.time}),s.append(o,...this.timeUI?[this.timeUI.el]:[],r,this.live),this.prev=s.querySelector("[data-a=prev]"),this.next=s.querySelector("[data-a=next]");let l=a=>a.target.closest("td[data-k]");s.addEventListener("click",a=>{let d=l(a);if(d)return i.pick(g$1(+d.dataset.k));let m=a.target.closest("[data-a]")?.dataset.a;m==="prev"?i.nav(-1):m==="next"?i.nav(1):m==="today"?i.today():m==="clear"&&i.clear();}),s.addEventListener("pointerover",a=>{let d=l(a);d&&i.hover(+d.dataset.k);}),s.addEventListener("pointerleave",()=>i.hover(null)),s.addEventListener("keydown",a=>this.onKey(a));}update(n,t=false){let e=f(n.view);e!==this.layoutKey&&(this.layoutKey=e,this.layout(n.view)),this.paint(n),t&&this.focusCell();}focusCell(){this.focusTd?.focus({preventScroll:true});}announce(n){this.live.textContent=n;}panel(n){let{loc:t,cls:e,id:i,months:s}=this.o,o=`${i}-t${n}`,r=y=>g("button",e.nav,{type:"button","data-a":y,"aria-label":t.strings[y==="prev"?"prevMonth":"nextMonth"]}),l=g("h2",e.title,{id:o,"aria-live":"polite"}),a=g("div",e.head);a.append(n===0?r("prev"):g("span",e.nav),l,n===s-1?r("next"):g("span",e.nav));let d=g("tr");for(let y=0;y<7;y++){let D=(t.firstDay+y)%7,v=g("th",e.dow,{scope:"col",abbr:t.dow(D,true)});v.textContent=t.dow(D),d.append(v);}let m=g("thead");m.append(d);let f=g("tbody"),p=g("table",e.grid,{role:"grid","aria-labelledby":o});p.append(m,f),this.panels.push({title:l,body:f,cells:[]});let u=g("div");return u.append(a,p),u}layout(n){let{loc:t,cls:e$1,otherMonths:i}=this.o;this.panels.forEach((s,o)=>{let r=e(n,o),l=d(r,-((r.getDay()-t.firstDay+7)%7)),a=document.createDocumentFragment();s.title.textContent=t.title(r),s.cells=[];for(let d$1=0;d$1<6;d$1++){let m=g("tr"),f$1=false;for(let p=0;p<7;p++){let u=d(l,d$1*7+p),y=u.getMonth()!==r.getMonth(),D=y&&!i,v=g("td",e$1.day,{role:"gridcell"});D?v.setAttribute("aria-hidden","true"):(f$1=true,v.tabIndex=-1,v.dataset.k=String(f(u)),v.textContent=t.num(u.getDate()),v.setAttribute("aria-label",t.label(u))),s.cells.push({td:v,d:u,k:f(u),out:y,hidden:D}),m.append(v);}f$1||m.setAttribute("aria-hidden","true"),a.append(m);}s.body.replaceChildren(a);});}paint(n){let{cls:t}=this.o,e=f(n.focus),i=n.span;this.focusTd=null;for(let s of this.panels)for(let{td:o,d:r,k:l,out:a,hidden:d}of s.cells){if(d)continue;let m=n.keys.includes(l)||!!i&&!n.preview&&l>=i[0]&&l<=i[1],f=n.disabled(r),p=z(t.day,a&&t.out,l===n.today&&t.today,m&&t.selected,f&&t.disabled,i&&l>i[0]&&l<i[1]&&t.inRange,i&&l===i[0]&&t.rangeStart,i&&l===i[1]&&t.rangeEnd);o.className!==p&&(o.className=p),k(o,"aria-selected",m?"true":null),k(o,"aria-disabled",f?"true":null),k(o,"aria-current",l===n.today?"date":null);let u=l===e&&!a;k(o,"tabindex",u?"0":"-1"),u&&(this.focusTd=o);}this.timeUI?.set(n.time),k(this.prev,"aria-disabled",n.canPrev?null:"true"),k(this.next,"aria-disabled",n.canNext?null:"true");}onKey(n){let{loc:t,on:e,inline:i}=this.o;if(n.key==="Escape")return i?void 0:(n.stopPropagation(),e.close());if(n.key==="Tab"&&!i)return this.trapTab(n);let s=n.target.closest("td[data-k]");if(!s)return;let o=g$1(+s.dataset.k);if(n.key==="Enter"||n.key===" ")return n.preventDefault(),e.pick(o);let r=j(n,o,t.firstDay,t.rtl);r&&(n.preventDefault(),e.move(r));}trapTab(n){let t=[...this.el.querySelectorAll('button, input, td[tabindex="0"]')],[e,i]=[t[0],t[t.length-1]],s=n.shiftKey?e:i;(n.target===s||!t.includes(n.target))&&(n.preventDefault(),(n.shiftKey?i:e)?.focus());}};var Y=/'([^']*)'|(yyyy|yy|MMMM|MMM|MM|M|dd|d|EEEE|EEE)|([^'yMdE]+|.)/g,G=/[\p{L}\p{N}]/u,Z=/(\d{1,2}):(\d{2})(?::(\d{2}))?/g,M=(h,n=2)=>String(h).padStart(n,"0"),C=h=>`${M(h.getHours())}:${M(h.getMinutes())}:${M(h.getSeconds())}`,q=(h,n,t)=>n.replace(Y,(e,i,s,o)=>{if(!s)return i??o??"";let[r,l,a]=[h.getFullYear(),h.getMonth(),h.getDate()];switch(s){case "yyyy":return M(r,4);case "yy":return M(r%100);case "MMMM":return t.month(l);case "MMM":return t.month(l,true);case "MM":return M(l+1);case "M":return String(l+1);case "dd":return M(a);case "d":return String(a);default:return t.dow(h.getDay(),s==="EEEE")}}),_=(h,n,t,e)=>{let i=[],s="";for(let[,f,p,u]of n.matchAll(Y))if(p)p[0]==="E"?s+="(?:\\p{L}+\\.?[^\\p{L}\\p{N}]+)?":(i.push(p),s+=p==="yyyy"?"(\\d{4})":p==="yy"?"(\\d{2})":p.length>2?"(\\p{L}+\\.?)":"(\\d{1,2})");else {let y=f??u??"";s+=G.test(y)?`\\s*(?:${y.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")})?\\s*`:"[^\\p{L}\\p{N}]*";}let o=h.replace(/[٠-٩۰-۹]/g,f=>String(f.charCodeAt(0)&15)),r=[];e&&(o=o.replace(Z,(f,p,u,y)=>(r.push([+p,+u,+(y??0)])," ")));let l=new Date,a$1=[],d="",m=0;for(let f of o.matchAll(new RegExp(s,"gu"))){let[p,u,y]=[l.getFullYear(),l.getMonth(),1];i.forEach((v,X)=>{let w=f[X+1];v==="yyyy"?p=+w:v==="yy"?p=2e3+ +w>l.getFullYear()+50?1900+ +w:2e3+ +w:v[0]==="d"?y=+w:u=v.length>2?t.monthIndex(w):+w-1;});let D=a(p,u,y);if(u<0||D.getMonth()!==u||D.getDate()!==y)return null;if(e){let v=r.length?r[a$1.length]:e;if(!v||v[0]>23||v[1]>59||v[2]>59)return null;D.setHours(...v);}a$1.push(D),d+=o.slice(m,f.index),m=f.index+f[0].length;}return d+=o.slice(m),a$1.length&&!G.test(d)&&(!r.length||r.length===a$1.length)?a$1:null};var B=(h,n,t,e)=>{let i=h.getBoundingClientRect(),[s,o]=[n.offsetWidth,n.offsetHeight],[r,l]=[document.documentElement.clientWidth,document.documentElement.clientHeight],a=(f,p,u)=>Math.max(8,Math.min(f,u-p-8)),d=e?i.right-s:i.left,m;t==="left"||t==="right"?(d=t==="left"?i.left-s-4:i.right+4,m=i.top):m=t==="top"||t==="auto"&&l-i.bottom<o+4&&i.top>l-i.bottom?i.top-o-4:i.bottom+4,n.style.left=`${a(d,s,r)}px`,n.style.top=`${a(m,o,l)}px`;};var J={mode:"single",position:"auto",numberOfMonths:1,allowInput:true,showIcon:true,closeOnOutsideClick:true},K="tp-icon",tt=0,et=h=>Object.fromEntries(Object.entries(h).filter(([,n])=>n!==void 0)),Q=class extends EventTarget{constructor(t,e={}){super();this.id=`tp-${++tt}`;this.user={};this.o=J;this.fmt="";this.lo=null;this.hi=null;this.skip=null;this.sel=[];this.pending=null;this.tod=[0,0,0];this.view=new Date;this.focus=new Date;this.hover=null;this.cal=null;this.isOpen=false;this.destroyed=false;this.opener=null;this.wasReadOnly=false;this.added=[];this.offs=[];this.openOffs=[];this.handlers={pick:t=>this.pick(t),move:t=>this.move(t),nav:t=>this.nav(t),hover:t=>{t!==this.hover&&(this.hover=t,this.pending&&this.refresh());},today:()=>this.pick(b(new Date)),clear:()=>this.setSel([],true),close:()=>this.hide(true),time:t=>this.setTime(t)};this.isDisabled=t=>{let e=f(t),i=this.o.disabledDates;return this.lo!==null&&e<f(this.lo)||this.hi!==null&&e>f(this.hi)||!!this.o.disabledDaysOfWeek?.includes(t.getDay())||!!this.skip?.has(e)||typeof i=="function"&&i(t)};this.reposition=()=>{this.cal&&this.isOpen&&!this.o.inline&&B(this.anchor,this.cal.el,this.o.position??"auto",this.loc.rtl);};this.el=t,this.input=t instanceof HTMLInputElement?t:null,this.anchor=e.anchor??t,this.resolve(e);let i=e.selected===void 0&&this.input?.value.trim()?this.read(this.input.value):null;this.sel=i?this.mode.clean(i):this.normalize(e.selected),this.sel[0]&&(this.tod=c(this.sel[0])),this.focus=this.clamp(this.sel[0]??this.home()),this.view=c$1(this.focus),this.input&&this.bindInput(this.input),this.sel.length&&this.writeInput(),this.o.inline&&(this.mount(),this.isOpen=true,this.refresh());}get strings(){return this.loc.strings}open(){this.present(true);}close(){this.hide(true);}toggle(){this.isOpen?this.close():this.open();}getDate(){let{outputTimestamp:t,enableTime:e,valueInUtc:i$1}=this.o,s=this.sel.map(o=>t?i(o,e,i$1):h(o,e,i$1));return this.mode.max===1?s[0]??null:s.length?s:null}setDate(t,e=false){if(this.destroyed)return;let i=this.normalize(t);i[0]&&this.reveal(i[0]),this.setSel(i,e);}jumpToDate(t){let e=m(t,!!this.o.enableTime,!!this.o.valueInUtc);this.destroyed||!e||(this.reveal(e),this.refresh());}setRange(t,e){this.setDate([t,e]);}setOptions(t){if(this.destroyed)return;let e=this.text();this.resolve({...this.user,...t}),this.sel="selected"in t?this.normalize(t.selected):this.mode.clean(this.sel.map(s=>l(s,!!this.o.enableTime))),this.sel[0]&&(this.tod=c(this.sel[0])),this.pending=null,this.focus=this.clamp(this.sel[0]??this.focus),this.input&&(this.input.readOnly=this.wasReadOnly||this.o.allowInput===false,this.input.classList.toggle(K,!!this.o.showIcon)),e!==this.text()?this.writeInput():this.o.isoInput&&this.writeISO();let i=this.cal?.el.matches(":focus-within");this.cal?.el.remove(),this.cal=null,this.reveal(this.focus),this.isOpen&&(this.mount(),this.cal.el.hidden=false,this.refresh(),this.reposition(),i&&this.cal.focusCell());}destroy(){this.destroyed||(this.destroyed=true,this.openOffs.splice(0).forEach(t=>t()),this.offs.splice(0).forEach(t=>t()),this.cal?.el.remove(),this.cal=null,this.isOpen=false,this.input&&([...this.added,"aria-controls","aria-invalid"].forEach(t=>this.input.removeAttribute(t)),this.input.readOnly=this.wasReadOnly,this.input.classList.remove(K)));}resolve(t){let e={...J,...et(t)},i=c$2(e.mode);if(!i)throw new Error(`[datepicker] mode "${e.mode}" is not registered. Import "ten-protons-datepicker/${e.mode}" first.`);if(e.enableTime&&!b$1())throw new Error('[datepicker] enableTime needs the time module. Import "ten-protons-datepicker/time" first.');this.user=t,this.o=e,this.mode=i,this.loc=b$2(e.locale,e.firstDayOfWeek),this.fmt=e.dateFormat??this.loc.format;let[s,o]=[!!e.enableTime,!!e.valueInUtc];this.lo=m(e.minDate,s,o),this.hi=m(e.maxDate,s,o);let r=e.disabledDates;this.skip=Array.isArray(r)?new Set(r.map(l=>f(m(l,s,o)??l))):null;}monthsShown(){return this.o.numberOfMonths===2?2:1}home(){return m(this.o.defaultDate,!!this.o.enableTime,!!this.o.valueInUtc)??b(new Date)}clamp(t){let e=f(t);return this.lo&&e<f(this.lo)?new Date(this.lo):this.hi&&e>f(this.hi)?new Date(this.hi):t}normalize(t){let e=t==null?[]:Array.isArray(t)?t:[t],[i,s]=[!!this.o.enableTime,!!this.o.valueInUtc];return this.mode.clean(e.map(o=>m(o,i,s)).filter(o=>o!==null))}stamp(t){if(!this.o.enableTime)return t;let e=new Date(t);return e.setHours(...this.tod),e}setSel(t,e){let i=this.o.enableTime?o=>+o:f,s=t.length===this.sel.length&&t.every((o,r)=>i(o)===i(this.sel[r]));this.sel=t,t[0]&&(this.tod=c(t[0])),this.pending=null,this.writeInput(),this.refresh(),e&&!s&&this.emit("change",this.getDate());}pick(t){if(this.isDisabled(t))return this.move(t);let e=this.stamp(t),i=this.mode.pick(this.pending??this.sel,e);if(this.hover=f(t),this.reveal(e),this.announce(i.sel),!i.complete)return this.pending=i.sel,this.refresh(true);this.setSel(i.sel,true),this.o.closeOnSelect??(this.mode.autoClose&&!this.o.enableTime)?this.hide(true):this.cal?.focusCell();}setTime(t){this.tod=t,this.pending?(this.pending=this.pending.map(e=>this.stamp(e)),this.refresh()):this.sel.length&&this.setSel(this.sel.map(e=>this.stamp(e)),true);}announce(t){let{strings:e,label:i}=this.loc,s=o=>this.o.enableTime?`${i(o)} ${C(o)}`:i(o);this.cal?.announce(t.length?`${e.selected}: ${t.map(s).join(", ")}`:"");}reveal(t){this.focus=this.clamp(t);let e$1=this.monthsShown(),i=c$1(this.focus),s=f(i),o=s<f(this.view)?i:s>f(e(this.view,e$1-1))?e(i,1-e$1):this.view;this.lo&&f(o)<f(c$1(this.lo))&&(o=c$1(this.lo)),this.setView(o);}setView(t){let e=this.view;f(t)!==f(e)&&(this.view=t,this.emit("monthChange",new Date(t)),t.getFullYear()!==e.getFullYear()&&this.emit("yearChange",new Date(t)));}move(t){this.reveal(t),this.hover=f(this.focus),this.refresh(true);}nav(t){let e$1=this.state();(t<0?!e$1.canPrev:!e$1.canNext)||(this.focus=this.clamp(e(this.focus,t)),this.setView(e(this.view,t)),this.refresh());}state(){let t=(this.pending??this.sel).map(f);return {view:this.view,focus:this.focus,keys:t,span:this.mode.span?.(t,this.hover)??null,preview:!!this.pending,today:f(new Date),time:this.tod,disabled:this.isDisabled,canPrev:!this.lo||f(this.view)>f(c$1(this.lo)),canNext:!this.hi||f(e(this.view,this.monthsShown()))<=f(this.hi)}}refresh(t=false){this.cal?.update(this.state(),t);}mount(){if(this.cal)return;let t=this.o,e=this.cal=new x({id:this.id,loc:this.loc,cls:{...W,...t.classes},months:this.monthsShown(),otherMonths:!!t.showOtherMonths,inline:!!t.inline,theme:t.theme,time:t.enableTime?b$1():void 0,on:this.handlers});if(t.inline){this.input?this.el.after(e.el):this.el.append(e.el);return}e.el.hidden=true,(t.appendTo??this.el.ownerDocument.body).append(e.el),this.input?.setAttribute("aria-controls",this.id);}present(t){if(this.destroyed||this.o.inline)return;if(this.isOpen)return t?this.cal?.focusCell():void 0;this.mount();let e=this.cal,i=this.el.getRootNode().activeElement;this.opener=i===this.el.ownerDocument.body?null:i,this.reveal(this.sel[0]??this.focus),e.el.hidden=false,this.isOpen=true,this.refresh(),this.reposition(),this.input?.setAttribute("aria-expanded","true"),this.listenWhileOpen(),t&&e.focusCell(),this.emit("open");}hide(t){if(!this.isOpen||this.o.inline)return;let e=this.cal,i=t&&e.el.matches(":focus-within");this.pending=null,this.hover=null,this.isOpen=false,e.el.hidden=true,this.openOffs.splice(0).forEach(s=>s()),this.input?.setAttribute("aria-expanded","false"),i&&(this.opener?.isConnected?this.opener:this.el).focus({preventScroll:true}),this.emit("close");}listenWhileOpen(){let t=this.el.ownerDocument,e=(i,s,o,r=false)=>{i.addEventListener(s,o,r),this.openOffs.push(()=>i.removeEventListener(s,o,r));};if(this.o.closeOnOutsideClick!==false){let i=s=>{let o=s.composedPath();!o.includes(this.cal.el)&&!o.includes(this.anchor)&&this.hide(false);};e(t,"pointerdown",i,true),e(t,"focusin",i,true);}e(t.defaultView??window,"resize",this.reposition),e(t,"scroll",this.reposition,true);}on(t,e,i){t.addEventListener(e,i),this.offs.push(()=>t.removeEventListener(e,i));}bindInput(t){let e=(i,s)=>{t.hasAttribute(i)||(t.setAttribute(i,s),this.added.push(i));};e("aria-haspopup","dialog"),e("aria-expanded","false"),e("autocomplete","off"),this.wasReadOnly=t.readOnly,t.readOnly=this.wasReadOnly||this.o.allowInput===false,t.classList.toggle(K,!!this.o.showIcon),this.on(t,"click",()=>this.present(this.o.allowInput===false)),this.on(t,"input",()=>t.removeAttribute("aria-invalid")),this.on(t,"blur",()=>this.commitInput(true)),this.on(t,"keydown",i=>{if(i.key==="ArrowDown")i.preventDefault(),this.isOpen?this.cal?.focusCell():this.present(true);else if(i.key==="Enter"){let s=this.commitInput(false);(!s||this.isOpen)&&i.preventDefault(),s&&this.hide(false);}else i.key==="Escape"&&this.isOpen&&(i.stopPropagation(),this.hide(false));});}text(){return this.sel.map(t=>q(t,this.fmt,this.loc)+(this.o.enableTime?` ${C(t)}`:"")).join(this.mode.join)}writeISO(){let{isoInput:t,outputTimestamp:e,enableTime:i$1,valueInUtc:s}=this.o;t&&(t.value=this.sel.map(o=>e?i(o,i$1,s):j$1(o,i$1,s)).join(this.mode.iso));}writeInput(){this.input&&(this.input.value=this.text(),this.input.removeAttribute("aria-invalid")),this.writeISO();}read(t){let e=!!this.o.enableTime,i=k$1(t,e,!!this.o.valueInUtc);return i?.length?i:_(t,this.fmt,this.loc,e?this.tod:void 0)}commitInput(t){let e=this.input;if(!e||this.destroyed)return true;let i=e.value.trim();if(i===this.text())return true;let s=[];return i&&(s=this.read(i),s&&(s.length>this.mode.max||s.some(this.isDisabled))&&(s=null)),s?(s=this.mode.clean(s),s[0]&&this.reveal(s[0]),this.setSel(s,true),true):(t?this.writeInput():e.setAttribute("aria-invalid","true"),false)}emit(t,e){this.dispatchEvent(new CustomEvent(t,{detail:e}));let i=this.o;t==="change"?(i.onChange?.(e,this),this.input?.dispatchEvent(new Event("input",{bubbles:true})),this.input?.dispatchEvent(new Event("change",{bubbles:true}))):t==="open"?i.onOpen?.(this):t==="close"?i.onClose?.(this):t==="monthChange"&&i.onMonthChange?.(e,this);}};export{Q as a};
package/dist/core.css CHANGED
@@ -1,8 +1,10 @@
1
- .tp-dp{
1
+ .tp-dp,:host{
2
2
  --tp-bg:#fff;--tp-fg:#1f2328;--tp-muted:#656d76;--tp-border:#d0d7de;--tp-hover:#eef1f4;
3
3
  --tp-accent:#2563eb;--tp-accent-fg:#fff;--tp-range:#dbe7fd;--tp-focus:#2563eb;
4
4
  --tp-radius:.5rem;--tp-cell:2.25rem;--tp-pad:.75rem;--tp-z:1000;
5
- --tp-shadow:0 8px 24px rgba(0,0,0,.15);
5
+ --tp-shadow:0 8px 24px rgba(0,0,0,.15)
6
+ }
7
+ .tp-dp{
6
8
  position:relative;box-sizing:border-box;width:max-content;max-width:calc(100vw - 1rem);padding:var(--tp-pad);
7
9
  background:var(--tp-bg);color:var(--tp-fg);border:1px solid var(--tp-border);border-radius:var(--tp-radius);
8
10
  font:.875rem/1.4 var(--tp-font,inherit)
@@ -47,6 +49,10 @@
47
49
  .tp-dp .tp-time-field:focus-visible{outline:2px solid var(--tp-focus);outline-offset:1px}
48
50
  .tp-time>span{text-align:center;color:var(--tp-muted)}
49
51
 
52
+ /* Calendar icon in the bound input (`showIcon`). Longhands only, so the input keeps its own background colour; the doubled class beats a page's `input[type=text]{background;padding}`. */
53
+ .tp-icon.tp-icon{padding-inline-start:2.25rem;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%237d8590' stroke-width='2' stroke-linecap='round'%3E%3Crect x='3' y='5' width='18' height='16' rx='2'/%3E%3Cpath d='M8 3v4M16 3v4M3 10h18'/%3E%3C/svg%3E");background-repeat:no-repeat;background-size:1rem;background-position:.75rem 50%}
54
+ .tp-icon.tp-icon:dir(rtl){background-position:calc(100% - .75rem) 50%}
55
+
50
56
  .tp-foot{display:flex;justify-content:space-between;margin-top:.5rem}
51
57
  .tp-btn{padding:.25rem .5rem;border:0;border-radius:var(--tp-radius);background:none;color:var(--tp-accent);font:inherit;cursor:pointer}
52
58
  .tp-btn:hover{background:var(--tp-hover)}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { L as LocaleObject } from './Datepicker-BFcQ6Txe.js';
2
- export { C as ClassNames, D as DateInput, a as Datepicker, b as DatepickerEventMap, c as DatepickerMode, d as DatepickerOptions, e as DatepickerValue, f as LocaleStrings, P as Position, W as Weekday } from './Datepicker-BFcQ6Txe.js';
1
+ import { L as LocaleObject } from './Datepicker-Dt5Dt_UX.js';
2
+ export { C as ClassNames, D as DateInput, a as Datepicker, b as DatepickerEventMap, c as DatepickerMode, d as DatepickerOptions, e as DatepickerValue, f as LocaleStrings, P as Position, W as Weekday } from './Datepicker-Dt5Dt_UX.js';
3
3
 
4
4
  /** Makes a locale available by tag, e.g. for `<x-datepicker locale="uk">`. */
5
5
  declare const registerLocale: (locale: LocaleObject) => void;
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- export{a as Datepicker}from'./chunk-LUHEXL2S.js';export{a as byDay,b as registerMode}from'./chunk-CUGUCENC.js';import'./chunk-Q2P4Y4T6.js';export{a as registerLocale}from'./chunk-BHROFXOE.js';import'./chunk-ANB32WKT.js';
1
+ export{a as Datepicker}from'./chunk-MTBE7EMZ.js';export{a as byDay,b as registerMode}from'./chunk-CUGUCENC.js';import'./chunk-Q2P4Y4T6.js';export{a as registerLocale}from'./chunk-BHROFXOE.js';import'./chunk-ANB32WKT.js';
@@ -1,4 +1,4 @@
1
- import { L as LocaleObject } from '../Datepicker-BFcQ6Txe.js';
1
+ import { L as LocaleObject } from '../Datepicker-Dt5Dt_UX.js';
2
2
 
3
3
  /** Ukrainian UI strings. Month and weekday names come from `Intl`. Importing registers `uk` for `<x-datepicker locale="uk">`. */
4
4
  declare const uk: LocaleObject;
@@ -1,4 +1,4 @@
1
- import { a as Datepicker } from './Datepicker-BFcQ6Txe.js';
1
+ import { a as Datepicker } from './Datepicker-Dt5Dt_UX.js';
2
2
 
3
3
  /** Switches `dp` to multiple mode: `const dp = withMultiple(new Datepicker(input))`. */
4
4
  declare const withMultiple: <T extends Datepicker>(dp: T) => T;
package/dist/range.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as Datepicker } from './Datepicker-BFcQ6Txe.js';
1
+ import { a as Datepicker } from './Datepicker-Dt5Dt_UX.js';
2
2
 
3
3
  /** Switches `dp` to range mode: `const dp = withRange(new Datepicker(input))`. */
4
4
  declare const withRange: <T extends Datepicker>(dp: T) => T;
package/dist/themes.css CHANGED
@@ -1,10 +1,10 @@
1
1
  /* Dark follows prefers-color-scheme unless data-theme="light"; data-theme="dark" forces it. */
2
- .tp-dp[data-theme=dark]{
2
+ .tp-dp[data-theme=dark],:host([theme=dark]){
3
3
  --tp-bg:#161b22;--tp-fg:#e6edf3;--tp-muted:#8d96a0;--tp-border:#30363d;--tp-hover:#21262d;
4
4
  --tp-accent:#4c8dff;--tp-accent-fg:#0b1220;--tp-range:#1b2f52;--tp-focus:#79a8ff;--tp-shadow:0 8px 24px rgba(0,0,0,.5)
5
5
  }
6
6
  @media (prefers-color-scheme:dark){
7
- .tp-dp:not([data-theme=light]){
7
+ .tp-dp:not([data-theme=light]),:host(:not([theme=light])){
8
8
  --tp-bg:#161b22;--tp-fg:#e6edf3;--tp-muted:#8d96a0;--tp-border:#30363d;--tp-hover:#21262d;
9
9
  --tp-accent:#4c8dff;--tp-accent-fg:#0b1220;--tp-range:#1b2f52;--tp-focus:#79a8ff;--tp-shadow:0 8px 24px rgba(0,0,0,.5)
10
10
  }
package/dist/time.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as Datepicker } from './Datepicker-BFcQ6Txe.js';
1
+ import { a as Datepicker } from './Datepicker-Dt5Dt_UX.js';
2
2
 
3
3
  /** Switches `dp` to date & time: `const dp = withTime(new Datepicker(input))`. */
4
4
  declare const withTime: <T extends Datepicker>(dp: T) => T;
package/dist/wc.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { a as Datepicker, d as DatepickerOptions } from './Datepicker-BFcQ6Txe.js';
1
+ import { a as Datepicker, d as DatepickerOptions } from './Datepicker-Dt5Dt_UX.js';
2
2
 
3
3
  declare const Base: typeof HTMLElement;
4
4
  /**
5
- * `<x-datepicker>`: an input + calendar toggle with the popup inside its shadow root.
5
+ * `<ten-protons-datepicker>` (alias `<x-datepicker>`): an input + calendar toggle with the popup inside its shadow root.
6
6
  *
7
7
  * Attributes: `value` (ISO or Unix seconds, ranges `a/b`, multiple `a,b`), `name`, `placeholder`, `label`, `disabled`,
8
8
  * `mode`, `locale`, `min`, `max`, `date-format`, `first-day`, `position`, `theme`, `number-of-months`,
@@ -51,6 +51,7 @@ declare class XDatepicker extends Base {
51
51
  declare global {
52
52
  interface HTMLElementTagNameMap {
53
53
  'x-datepicker': XDatepicker;
54
+ 'ten-protons-datepicker': XDatepicker;
54
55
  }
55
56
  }
56
57
 
package/dist/wc.js CHANGED
@@ -1,8 +1,10 @@
1
- import {a as a$1}from'./chunk-LUHEXL2S.js';import'./chunk-CUGUCENC.js';import'./chunk-Q2P4Y4T6.js';import'./chunk-BHROFXOE.js';import'./chunk-ANB32WKT.js';var d=`.tp-dp{
1
+ import {a as a$1}from'./chunk-MTBE7EMZ.js';import'./chunk-CUGUCENC.js';import'./chunk-Q2P4Y4T6.js';import'./chunk-BHROFXOE.js';import'./chunk-ANB32WKT.js';var l=`.tp-dp,:host{
2
2
  --tp-bg:#fff;--tp-fg:#1f2328;--tp-muted:#656d76;--tp-border:#d0d7de;--tp-hover:#eef1f4;
3
3
  --tp-accent:#2563eb;--tp-accent-fg:#fff;--tp-range:#dbe7fd;--tp-focus:#2563eb;
4
4
  --tp-radius:.5rem;--tp-cell:2.25rem;--tp-pad:.75rem;--tp-z:1000;
5
- --tp-shadow:0 8px 24px rgba(0,0,0,.15);
5
+ --tp-shadow:0 8px 24px rgba(0,0,0,.15)
6
+ }
7
+ .tp-dp{
6
8
  position:relative;box-sizing:border-box;width:max-content;max-width:calc(100vw - 1rem);padding:var(--tp-pad);
7
9
  background:var(--tp-bg);color:var(--tp-fg);border:1px solid var(--tp-border);border-radius:var(--tp-radius);
8
10
  font:.875rem/1.4 var(--tp-font,inherit)
@@ -47,6 +49,10 @@ import {a as a$1}from'./chunk-LUHEXL2S.js';import'./chunk-CUGUCENC.js';import'./
47
49
  .tp-dp .tp-time-field:focus-visible{outline:2px solid var(--tp-focus);outline-offset:1px}
48
50
  .tp-time>span{text-align:center;color:var(--tp-muted)}
49
51
 
52
+ /* Calendar icon in the bound input (\`showIcon\`). Longhands only, so the input keeps its own background colour; the doubled class beats a page's \`input[type=text]{background;padding}\`. */
53
+ .tp-icon.tp-icon{padding-inline-start:2.25rem;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%237d8590' stroke-width='2' stroke-linecap='round'%3E%3Crect x='3' y='5' width='18' height='16' rx='2'/%3E%3Cpath d='M8 3v4M16 3v4M3 10h18'/%3E%3C/svg%3E");background-repeat:no-repeat;background-size:1rem;background-position:.75rem 50%}
54
+ .tp-icon.tp-icon:dir(rtl){background-position:calc(100% - .75rem) 50%}
55
+
50
56
  .tp-foot{display:flex;justify-content:space-between;margin-top:.5rem}
51
57
  .tp-btn{padding:.25rem .5rem;border:0;border-radius:var(--tp-radius);background:none;color:var(--tp-accent);font:inherit;cursor:pointer}
52
58
  .tp-btn:hover{background:var(--tp-hover)}
@@ -56,15 +62,15 @@ import {a as a$1}from'./chunk-LUHEXL2S.js';import'./chunk-CUGUCENC.js';import'./
56
62
  @media (forced-colors:active){
57
63
  .tp-selected{forced-color-adjust:none;background:Highlight;color:HighlightText}
58
64
  }
59
- `;var l=`/* Dark follows prefers-color-scheme unless data-theme="light"; data-theme="dark" forces it. */
60
- .tp-dp[data-theme=dark]{
65
+ `;var c=`/* Dark follows prefers-color-scheme unless data-theme="light"; data-theme="dark" forces it. */
66
+ .tp-dp[data-theme=dark],:host([theme=dark]){
61
67
  --tp-bg:#161b22;--tp-fg:#e6edf3;--tp-muted:#8d96a0;--tp-border:#30363d;--tp-hover:#21262d;
62
68
  --tp-accent:#4c8dff;--tp-accent-fg:#0b1220;--tp-range:#1b2f52;--tp-focus:#79a8ff;--tp-shadow:0 8px 24px rgba(0,0,0,.5)
63
69
  }
64
70
  @media (prefers-color-scheme:dark){
65
- .tp-dp:not([data-theme=light]){
71
+ .tp-dp:not([data-theme=light]),:host(:not([theme=light])){
66
72
  --tp-bg:#161b22;--tp-fg:#e6edf3;--tp-muted:#8d96a0;--tp-border:#30363d;--tp-hover:#21262d;
67
73
  --tp-accent:#4c8dff;--tp-accent-fg:#0b1220;--tp-range:#1b2f52;--tp-focus:#79a8ff;--tp-shadow:0 8px 24px rgba(0,0,0,.5)
68
74
  }
69
75
  }
70
- `;var f={range:()=>import('./range.js'),multiple:()=>import('./multiple.js')},v=()=>import('./time.js'),o=e=>e??void 0,c=e=>e===null?void 0:Number(e),a=e=>e===null?void 0:e!=="false",y=e=>e===null?void 0:e.split(",").map(Number),u=e=>e.split(/\s*[/,;]\s*/).filter(Boolean),h={mode:["mode",o],locale:["locale",o],min:["minDate",o],max:["maxDate",o],"date-format":["dateFormat",o],"first-day":["firstDayOfWeek",c],position:["position",o],theme:["theme",o],"number-of-months":["numberOfMonths",c],"show-other-months":["showOtherMonths",a],"allow-input":["allowInput",a],"close-on-select":["closeOnSelect",a],"disabled-days":["disabledDaysOfWeek",y],"output-timestamp":["outputTimestamp",a],"enable-time":["enableTime",a],"value-in-utc":["valueInUtc",a],inline:["inline",a]},k=["change","open","close","monthChange","yearChange"],w='<svg viewBox="0 0 24 24" width="18" height="18" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><rect x="3" y="5" width="18" height="16" rx="2"/><path d="M8 3v4M16 3v4M3 10h18"/></svg>',x=":host{display:inline-block}:host([hidden]){display:none}.wrap{position:relative;display:flex;align-items:center}input{box-sizing:border-box;width:100%;padding-inline-end:2.25rem;font:inherit}.toggle{position:absolute;inset-inline-end:.25rem;display:grid;place-items:center;width:1.75rem;height:1.75rem;padding:0;border:0;border-radius:.25rem;background:none;color:inherit;cursor:pointer}.toggle:disabled{opacity:.4;cursor:default}:host([inline]) .toggle{display:none}",E=typeof HTMLElement>"u"?class{}:HTMLElement,n=class extends E{constructor(){super();this.ready=Promise.resolve(null);this.picker=null;this.extra={};this.gen=0;this.internals=this.attachInternals?.();let t=this.root=this.attachShadow({mode:"open",delegatesFocus:true});t.innerHTML=`<style>${d}${l}${x}</style><div class="wrap" part="wrap"><input part="input"><button type="button" class="toggle" part="toggle" aria-haspopup="dialog">${w}</button></div>`,this.wrap=t.querySelector(".wrap"),this.input=t.querySelector("input"),this.toggleBtn=t.querySelector("button"),this.iso=document.createElement("input"),this.toggleBtn.addEventListener("click",()=>this.picker?.toggle());}get value(){return this.iso.value}set value(t){this.setAttribute("value",t);}set options(t){this.extra={...this.extra,...t},this.apply();}open(){this.picker?.open();}close(){this.picker?.close();}toggle(){this.picker?.toggle();}connectedCallback(){this.ready=this.init();}disconnectedCallback(){this.teardown();}attributeChangedCallback(t,i,r){if(t==="placeholder")this.input.placeholder=r??"";else if(t==="label")r===null?this.input.removeAttribute("aria-label"):this.input.setAttribute("aria-label",r);else if(t==="disabled")this.setDisabled(r!==null);else if(this.picker)t==="value"?this.setValue(r):t==="inline"?(this.teardown(),this.ready=this.init()):this.apply();else return}formResetCallback(){this.setValue(this.getAttribute("value"));}formDisabledCallback(t){this.setDisabled(t);}opts(){let t={};for(let[i,[r,s]]of Object.entries(h))t[r]=s(this.getAttribute(i));return {...t,...this.extra}}async load({mode:t,enableTime:i}){await Promise.all([t&&f[t]?.(),i&&v()]);}async init(){if(this.picker)return this.picker;let t=++this.gen;if(await this.load(this.opts()),t!==this.gen||!this.isConnected)return null;let i=this.getAttribute("value"),r=this.picker=new a$1(this.input,{...this.opts(),selected:i?u(i):null,isoInput:this.iso,anchor:this.wrap,appendTo:this.root});for(let s of k)r.addEventListener(s,g=>{s==="change"&&this.syncForm(),this.dispatchEvent(new CustomEvent(s,{detail:g.detail,bubbles:true,composed:true}));});return this.toggleBtn.setAttribute("aria-label",r.strings.label),this.setDisabled(this.hasAttribute("disabled")),this.syncForm(),r}teardown(){this.gen++,this.picker?.destroy(),this.picker=null;}async apply(){let t=this.opts();await this.load(t),this.picker&&(this.picker.setOptions(t),this.syncForm(),this.toggleBtn.setAttribute("aria-label",this.picker.strings.label));}setValue(t){this.picker?.setDate(t?u(t):[]),this.syncForm();}setDisabled(t){this.input.disabled=this.toggleBtn.disabled=t,t&&this.picker?.close();}syncForm(){this.internals?.setFormValue?.(this.iso.value||null);}};n.formAssociated=true,n.observedAttributes=[...Object.keys(h),"value","placeholder","label","disabled"];typeof customElements<"u"&&!customElements.get("x-datepicker")&&customElements.define("x-datepicker",n);export{n as XDatepicker};
76
+ `;var v={range:()=>import('./range.js'),multiple:()=>import('./multiple.js')},k=()=>import('./time.js'),o=e=>e??void 0,u=e=>e===null?void 0:Number(e),a=e=>e===null?void 0:e!=="false",w=e=>e===null?void 0:e.split(",").map(Number),h=e=>e.split(/\s*[/,;]\s*/).filter(Boolean),g={mode:["mode",o],locale:["locale",o],min:["minDate",o],max:["maxDate",o],"date-format":["dateFormat",o],"first-day":["firstDayOfWeek",u],position:["position",o],theme:["theme",o],"number-of-months":["numberOfMonths",u],"show-other-months":["showOtherMonths",a],"allow-input":["allowInput",a],"close-on-select":["closeOnSelect",a],"disabled-days":["disabledDaysOfWeek",w],"output-timestamp":["outputTimestamp",a],"enable-time":["enableTime",a],"value-in-utc":["valueInUtc",a],inline:["inline",a]},y=["change","open","close","monthChange","yearChange"],x='<svg viewBox="0 0 24 24" width="18" height="18" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><rect x="3" y="5" width="18" height="16" rx="2"/><path d="M8 3v4M16 3v4M3 10h18"/></svg>',E=":host{display:inline-block}:host([hidden]){display:none}.wrap{position:relative;display:flex;align-items:center}input{box-sizing:border-box;width:100%;padding:.5rem .75rem;padding-inline-end:2.25rem;font:inherit;color:var(--tp-fg);background:var(--tp-bg);border:1px solid var(--tp-border);border-radius:var(--tp-radius)}input:disabled{opacity:.6}input[aria-invalid=true]{border-color:#d1242f}.toggle{position:absolute;inset-inline-end:.25rem;display:grid;place-items:center;width:1.75rem;height:1.75rem;padding:0;border:0;border-radius:.25rem;background:none;color:var(--tp-fg);cursor:pointer}.toggle:disabled{opacity:.4;cursor:default}:host([inline]) .toggle{display:none}",D=typeof HTMLElement>"u"?class{}:HTMLElement,n=class extends D{constructor(){super();this.ready=Promise.resolve(null);this.picker=null;this.extra={};this.gen=0;this.internals=this.attachInternals?.();let t=this.root=this.attachShadow({mode:"open",delegatesFocus:true});t.innerHTML=`<style>${l}${c}${E}</style><div class="wrap" part="wrap"><input part="input"><button type="button" class="toggle" part="toggle" aria-haspopup="dialog">${x}</button></div>`,this.wrap=t.querySelector(".wrap"),this.input=t.querySelector("input"),this.toggleBtn=t.querySelector("button"),this.iso=document.createElement("input"),this.toggleBtn.addEventListener("click",()=>this.picker?.toggle());}get value(){return this.iso.value}set value(t){this.setAttribute("value",t);}set options(t){this.extra={...this.extra,...t},this.apply();}open(){this.picker?.open();}close(){this.picker?.close();}toggle(){this.picker?.toggle();}connectedCallback(){this.ready=this.init();}disconnectedCallback(){this.teardown();}attributeChangedCallback(t,i,r){if(t==="placeholder")this.input.placeholder=r??"";else if(t==="label")r===null?this.input.removeAttribute("aria-label"):this.input.setAttribute("aria-label",r);else if(t==="disabled")this.setDisabled(r!==null);else if(this.picker)t==="value"?this.setValue(r):t==="inline"?(this.teardown(),this.ready=this.init()):this.apply();else return}formResetCallback(){this.setValue(this.getAttribute("value"));}formDisabledCallback(t){this.setDisabled(t);}opts(){let t={};for(let[i,[r,s]]of Object.entries(g))t[r]=s(this.getAttribute(i));return {...t,...this.extra}}async load({mode:t,enableTime:i}){await Promise.all([t&&v[t]?.(),i&&k()]);}async init(){if(this.picker)return this.picker;let t=++this.gen;if(await this.load(this.opts()),t!==this.gen||!this.isConnected)return null;let i=this.getAttribute("value"),r=this.picker=new a$1(this.input,{...this.opts(),showIcon:false,selected:i?h(i):null,isoInput:this.iso,anchor:this.wrap,appendTo:this.root});for(let s of y)r.addEventListener(s,b=>{s==="change"&&this.syncForm(),this.dispatchEvent(new CustomEvent(s,{detail:b.detail,bubbles:true,composed:true}));});return this.toggleBtn.setAttribute("aria-label",r.strings.label),this.setDisabled(this.hasAttribute("disabled")),this.syncForm(),r}teardown(){this.gen++,this.picker?.destroy(),this.picker=null;}async apply(){let t=this.opts();await this.load(t),this.picker&&(this.picker.setOptions(t),this.syncForm(),this.toggleBtn.setAttribute("aria-label",this.picker.strings.label));}setValue(t){this.picker?.setDate(t?h(t):[]),this.syncForm();}setDisabled(t){this.input.disabled=this.toggleBtn.disabled=t,t&&this.picker?.close();}syncForm(){this.internals?.setFormValue?.(this.iso.value||null);}};n.formAssociated=true,n.observedAttributes=[...Object.keys(g),"value","placeholder","label","disabled"];var M={"ten-protons-datepicker":class extends n{},"x-datepicker":n};if(typeof customElements<"u")for(let[e,p]of Object.entries(M))customElements.get(e)||customElements.define(e,p);export{n as XDatepicker};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ten-protons-datepicker",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Zero-dependency, accessible, tiny datepicker. Vanilla TypeScript + Web Component.",
5
5
  "keywords": [
6
6
  "datepicker",
@@ -1 +0,0 @@
1
- import {c as c$2}from'./chunk-CUGUCENC.js';import {c,b as b$1}from'./chunk-Q2P4Y4T6.js';import {b as b$2}from'./chunk-BHROFXOE.js';import {b,f,c as c$1,i,h,m,l,e,j as j$1,k as k$1,g as g$1,d,a}from'./chunk-ANB32WKT.js';var R=(h,n,t,e$1)=>{if(h.ctrlKey||h.metaKey||h.altKey)return null;let i=(n.getDay()-t+7)%7,s=e$1?-1:1;switch(h.key){case "ArrowLeft":return d(n,-s);case "ArrowRight":return d(n,s);case "ArrowUp":return d(n,-7);case "ArrowDown":return d(n,7);case "Home":return d(n,-i);case "End":return d(n,6-i);case "PageUp":return e(n,h.shiftKey?-12:-1);case "PageDown":return e(n,h.shiftKey?12:1);default:return null}};var z={root:"tp-dp",pop:"tp-pop",months:"tp-months",head:"tp-head",title:"tp-title",nav:"tp-nav",grid:"tp-grid",dow:"tp-dow",day:"tp-day",out:"tp-out",today:"tp-today",selected:"tp-selected",disabled:"tp-disabled",inRange:"tp-in-range",rangeStart:"tp-range-start",rangeEnd:"tp-range-end",foot:"tp-foot",btn:"tp-btn",time:"tp-time",timeField:"tp-time-field",sr:"tp-sr"},g=(h,n="",t={})=>{let e=document.createElement(h);n&&(e.className=n);for(let i in t)e.setAttribute(i,t[i]);return e},j=(...h)=>h.filter(Boolean).join(" "),k=(h,n,t)=>{h.getAttribute(n)!==t&&(t===null?h.removeAttribute(n):h.setAttribute(n,t));},x=class{constructor(n){this.o=n;this.panels=[];this.layoutKey=-1;this.focusTd=null;let{loc:t,cls:e,on:i}=n,s=this.el=g("div",j(e.root,!n.inline&&e.pop),{id:n.id,dir:t.rtl?"rtl":"ltr","aria-label":t.strings.label,...n.inline?{role:"group"}:{role:"dialog","aria-modal":"true"},...n.theme?{"data-theme":n.theme}:{}}),o=g("div",e.months);for(let a=0;a<n.months;a++)o.append(this.panel(a));let r=g("div",e.foot);for(let a of ["today","clear"]){let c=g("button",e.btn,{type:"button","data-a":a});c.textContent=t.strings[a],r.append(c);}this.live=g("div",e.sr,{"aria-live":"polite","aria-atomic":"true"}),this.timeUI=n.time?.({loc:t,cls:e,id:n.id,change:i.time}),s.append(o,...this.timeUI?[this.timeUI.el]:[],r,this.live),this.prev=s.querySelector("[data-a=prev]"),this.next=s.querySelector("[data-a=next]");let l=a=>a.target.closest("td[data-k]");s.addEventListener("click",a=>{let c=l(a);if(c)return i.pick(g$1(+c.dataset.k));let m=a.target.closest("[data-a]")?.dataset.a;m==="prev"?i.nav(-1):m==="next"?i.nav(1):m==="today"?i.today():m==="clear"&&i.clear();}),s.addEventListener("pointerover",a=>{let c=l(a);c&&i.hover(+c.dataset.k);}),s.addEventListener("pointerleave",()=>i.hover(null)),s.addEventListener("keydown",a=>this.onKey(a));}update(n,t=false){let e=f(n.view);e!==this.layoutKey&&(this.layoutKey=e,this.layout(n.view)),this.paint(n),t&&this.focusCell();}focusCell(){this.focusTd?.focus({preventScroll:true});}announce(n){this.live.textContent=n;}panel(n){let{loc:t,cls:e,id:i,months:s}=this.o,o=`${i}-t${n}`,r=y=>g("button",e.nav,{type:"button","data-a":y,"aria-label":t.strings[y==="prev"?"prevMonth":"nextMonth"]}),l=g("h2",e.title,{id:o,"aria-live":"polite"}),a=g("div",e.head);a.append(n===0?r("prev"):g("span",e.nav),l,n===s-1?r("next"):g("span",e.nav));let c=g("tr");for(let y=0;y<7;y++){let D=(t.firstDay+y)%7,v=g("th",e.dow,{scope:"col",abbr:t.dow(D,true)});v.textContent=t.dow(D),c.append(v);}let m=g("thead");m.append(c);let f=g("tbody"),p=g("table",e.grid,{role:"grid","aria-labelledby":o});p.append(m,f),this.panels.push({title:l,body:f,cells:[]});let u=g("div");return u.append(a,p),u}layout(n){let{loc:t,cls:e$1,otherMonths:i}=this.o;this.panels.forEach((s,o)=>{let r=e(n,o),l=d(r,-((r.getDay()-t.firstDay+7)%7)),a=document.createDocumentFragment();s.title.textContent=t.title(r),s.cells=[];for(let c=0;c<6;c++){let m=g("tr"),f$1=false;for(let p=0;p<7;p++){let u=d(l,c*7+p),y=u.getMonth()!==r.getMonth(),D=y&&!i,v=g("td",e$1.day,{role:"gridcell"});D?v.setAttribute("aria-hidden","true"):(f$1=true,v.tabIndex=-1,v.dataset.k=String(f(u)),v.textContent=t.num(u.getDate()),v.setAttribute("aria-label",t.label(u))),s.cells.push({td:v,d:u,k:f(u),out:y,hidden:D}),m.append(v);}f$1||m.setAttribute("aria-hidden","true"),a.append(m);}s.body.replaceChildren(a);});}paint(n){let{cls:t}=this.o,e=f(n.focus),i=n.span;this.focusTd=null;for(let s of this.panels)for(let{td:o,d:r,k:l,out:a,hidden:c}of s.cells){if(c)continue;let m=n.keys.includes(l)||!!i&&!n.preview&&l>=i[0]&&l<=i[1],f=n.disabled(r),p=j(t.day,a&&t.out,l===n.today&&t.today,m&&t.selected,f&&t.disabled,i&&l>i[0]&&l<i[1]&&t.inRange,i&&l===i[0]&&t.rangeStart,i&&l===i[1]&&t.rangeEnd);o.className!==p&&(o.className=p),k(o,"aria-selected",m?"true":null),k(o,"aria-disabled",f?"true":null),k(o,"aria-current",l===n.today?"date":null);let u=l===e&&!a;k(o,"tabindex",u?"0":"-1"),u&&(this.focusTd=o);}this.timeUI?.set(n.time),k(this.prev,"aria-disabled",n.canPrev?null:"true"),k(this.next,"aria-disabled",n.canNext?null:"true");}onKey(n){let{loc:t,on:e,inline:i}=this.o;if(n.key==="Escape")return i?void 0:(n.stopPropagation(),e.close());if(n.key==="Tab"&&!i)return this.trapTab(n);let s=n.target.closest("td[data-k]");if(!s)return;let o=g$1(+s.dataset.k);if(n.key==="Enter"||n.key===" ")return n.preventDefault(),e.pick(o);let r=R(n,o,t.firstDay,t.rtl);r&&(n.preventDefault(),e.move(r));}trapTab(n){let t=[...this.el.querySelectorAll('button, input, td[tabindex="0"]')],[e,i]=[t[0],t[t.length-1]],s=n.shiftKey?e:i;(n.target===s||!t.includes(n.target))&&(n.preventDefault(),(n.shiftKey?i:e)?.focus());}};var G=/'([^']*)'|(yyyy|yy|MMMM|MMM|MM|M|dd|d|EEEE|EEE)|([^'yMdE]+|.)/g,W=/[\p{L}\p{N}]/u,X=/(\d{1,2}):(\d{2})(?::(\d{2}))?/g,M=(h,n=2)=>String(h).padStart(n,"0"),C=h=>`${M(h.getHours())}:${M(h.getMinutes())}:${M(h.getSeconds())}`,Y=(h,n,t)=>n.replace(G,(e,i,s,o)=>{if(!s)return i??o??"";let[r,l,a]=[h.getFullYear(),h.getMonth(),h.getDate()];switch(s){case "yyyy":return M(r,4);case "yy":return M(r%100);case "MMMM":return t.month(l);case "MMM":return t.month(l,true);case "MM":return M(l+1);case "M":return String(l+1);case "dd":return M(a);case "d":return String(a);default:return t.dow(h.getDay(),s==="EEEE")}}),q=(h,n,t,e)=>{let i=[],s="";for(let[,f,p,u]of n.matchAll(G))if(p)p[0]==="E"?s+="(?:\\p{L}+\\.?[^\\p{L}\\p{N}]+)?":(i.push(p),s+=p==="yyyy"?"(\\d{4})":p==="yy"?"(\\d{2})":p.length>2?"(\\p{L}+\\.?)":"(\\d{1,2})");else {let y=f??u??"";s+=W.test(y)?`\\s*(?:${y.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")})?\\s*`:"[^\\p{L}\\p{N}]*";}let o=h.replace(/[٠-٩۰-۹]/g,f=>String(f.charCodeAt(0)&15)),r=[];e&&(o=o.replace(X,(f,p,u,y)=>(r.push([+p,+u,+(y??0)])," ")));let l=new Date,a$1=[],c="",m=0;for(let f of o.matchAll(new RegExp(s,"gu"))){let[p,u,y]=[l.getFullYear(),l.getMonth(),1];i.forEach((v,Q)=>{let w=f[Q+1];v==="yyyy"?p=+w:v==="yy"?p=2e3+ +w>l.getFullYear()+50?1900+ +w:2e3+ +w:v[0]==="d"?y=+w:u=v.length>2?t.monthIndex(w):+w-1;});let D=a(p,u,y);if(u<0||D.getMonth()!==u||D.getDate()!==y)return null;if(e){let v=r.length?r[a$1.length]:e;if(!v||v[0]>23||v[1]>59||v[2]>59)return null;D.setHours(...v);}a$1.push(D),c+=o.slice(m,f.index),m=f.index+f[0].length;}return c+=o.slice(m),a$1.length&&!W.test(c)&&(!r.length||r.length===a$1.length)?a$1:null};var B=(h,n,t,e)=>{let i=h.getBoundingClientRect(),[s,o]=[n.offsetWidth,n.offsetHeight],[r,l]=[document.documentElement.clientWidth,document.documentElement.clientHeight],a=(f,p,u)=>Math.max(8,Math.min(f,u-p-8)),c=e?i.right-s:i.left,m;t==="left"||t==="right"?(c=t==="left"?i.left-s-4:i.right+4,m=i.top):m=t==="top"||t==="auto"&&l-i.bottom<o+4&&i.top>l-i.bottom?i.top-o-4:i.bottom+4,n.style.left=`${a(c,s,r)}px`,n.style.top=`${a(m,o,l)}px`;};var _={mode:"single",position:"auto",numberOfMonths:1,allowInput:true,closeOnOutsideClick:true},Z=0,tt=h=>Object.fromEntries(Object.entries(h).filter(([,n])=>n!==void 0)),J=class extends EventTarget{constructor(t,e={}){super();this.id=`tp-${++Z}`;this.user={};this.o=_;this.fmt="";this.lo=null;this.hi=null;this.skip=null;this.sel=[];this.pending=null;this.tod=[0,0,0];this.view=new Date;this.focus=new Date;this.hover=null;this.cal=null;this.isOpen=false;this.destroyed=false;this.opener=null;this.wasReadOnly=false;this.added=[];this.offs=[];this.openOffs=[];this.handlers={pick:t=>this.pick(t),move:t=>this.move(t),nav:t=>this.nav(t),hover:t=>{t!==this.hover&&(this.hover=t,this.pending&&this.refresh());},today:()=>this.pick(b(new Date)),clear:()=>this.setSel([],true),close:()=>this.hide(true),time:t=>this.setTime(t)};this.isDisabled=t=>{let e=f(t),i=this.o.disabledDates;return this.lo!==null&&e<f(this.lo)||this.hi!==null&&e>f(this.hi)||!!this.o.disabledDaysOfWeek?.includes(t.getDay())||!!this.skip?.has(e)||typeof i=="function"&&i(t)};this.reposition=()=>{this.cal&&this.isOpen&&B(this.anchor,this.cal.el,this.o.position??"auto",this.loc.rtl);};this.el=t,this.input=t instanceof HTMLInputElement?t:null,this.anchor=e.anchor??t,this.resolve(e);let i=e.selected===void 0&&this.input?.value.trim()?this.read(this.input.value):null;this.sel=i?this.mode.clean(i):this.normalize(e.selected),this.sel[0]&&(this.tod=c(this.sel[0])),this.focus=this.clamp(this.sel[0]??this.home()),this.view=c$1(this.focus),this.input&&this.bindInput(this.input),this.sel.length&&this.writeInput(),this.o.inline&&(this.mount(),this.isOpen=true,this.refresh());}get strings(){return this.loc.strings}open(){this.present(true);}close(){this.hide(true);}toggle(){this.isOpen?this.close():this.open();}getDate(){let{outputTimestamp:t,enableTime:e,valueInUtc:i$1}=this.o,s=this.sel.map(o=>t?i(o,e,i$1):h(o,e,i$1));return this.mode.max===1?s[0]??null:s.length?s:null}setDate(t,e=false){if(this.destroyed)return;let i=this.normalize(t);i[0]&&this.reveal(i[0]),this.setSel(i,e);}jumpToDate(t){let e=m(t,!!this.o.enableTime,!!this.o.valueInUtc);this.destroyed||!e||(this.reveal(e),this.refresh());}setRange(t,e){this.setDate([t,e]);}setOptions(t){if(this.destroyed)return;let e=this.text();this.resolve({...this.user,...t}),this.sel="selected"in t?this.normalize(t.selected):this.mode.clean(this.sel.map(s=>l(s,!!this.o.enableTime))),this.sel[0]&&(this.tod=c(this.sel[0])),this.pending=null,this.focus=this.clamp(this.sel[0]??this.focus),this.input&&(this.input.readOnly=this.wasReadOnly||this.o.allowInput===false),e!==this.text()?this.writeInput():this.o.isoInput&&this.writeISO();let i=this.cal?.el.matches(":focus-within");this.cal?.el.remove(),this.cal=null,this.reveal(this.focus),this.isOpen&&(this.mount(),this.cal.el.hidden=false,this.refresh(),this.reposition(),i&&this.cal.focusCell());}destroy(){this.destroyed||(this.destroyed=true,this.openOffs.splice(0).forEach(t=>t()),this.offs.splice(0).forEach(t=>t()),this.cal?.el.remove(),this.cal=null,this.isOpen=false,this.input&&([...this.added,"aria-controls","aria-invalid"].forEach(t=>this.input.removeAttribute(t)),this.input.readOnly=this.wasReadOnly));}resolve(t){let e={..._,...tt(t)},i=c$2(e.mode);if(!i)throw new Error(`[datepicker] mode "${e.mode}" is not registered. Import "ten-protons-datepicker/${e.mode}" first.`);if(e.enableTime&&!b$1())throw new Error('[datepicker] enableTime needs the time module. Import "ten-protons-datepicker/time" first.');this.user=t,this.o=e,this.mode=i,this.loc=b$2(e.locale,e.firstDayOfWeek),this.fmt=e.dateFormat??this.loc.format;let[s,o]=[!!e.enableTime,!!e.valueInUtc];this.lo=m(e.minDate,s,o),this.hi=m(e.maxDate,s,o);let r=e.disabledDates;this.skip=Array.isArray(r)?new Set(r.map(l=>f(m(l,s,o)??l))):null;}monthsShown(){return this.o.numberOfMonths===2?2:1}home(){return m(this.o.defaultDate,!!this.o.enableTime,!!this.o.valueInUtc)??b(new Date)}clamp(t){let e=f(t);return this.lo&&e<f(this.lo)?new Date(this.lo):this.hi&&e>f(this.hi)?new Date(this.hi):t}normalize(t){let e=t==null?[]:Array.isArray(t)?t:[t],[i,s]=[!!this.o.enableTime,!!this.o.valueInUtc];return this.mode.clean(e.map(o=>m(o,i,s)).filter(o=>o!==null))}stamp(t){if(!this.o.enableTime)return t;let e=new Date(t);return e.setHours(...this.tod),e}setSel(t,e){let i=this.o.enableTime?o=>+o:f,s=t.length===this.sel.length&&t.every((o,r)=>i(o)===i(this.sel[r]));this.sel=t,t[0]&&(this.tod=c(t[0])),this.pending=null,this.writeInput(),this.refresh(),e&&!s&&this.emit("change",this.getDate());}pick(t){if(this.isDisabled(t))return this.move(t);let e=this.stamp(t),i=this.mode.pick(this.pending??this.sel,e);if(this.hover=f(t),this.reveal(e),this.announce(i.sel),!i.complete)return this.pending=i.sel,this.refresh(true);this.setSel(i.sel,true),this.o.closeOnSelect??(this.mode.autoClose&&!this.o.enableTime)?this.hide(true):this.cal?.focusCell();}setTime(t){this.tod=t,this.pending?(this.pending=this.pending.map(e=>this.stamp(e)),this.refresh()):this.sel.length&&this.setSel(this.sel.map(e=>this.stamp(e)),true);}announce(t){let{strings:e,label:i}=this.loc,s=o=>this.o.enableTime?`${i(o)} ${C(o)}`:i(o);this.cal?.announce(t.length?`${e.selected}: ${t.map(s).join(", ")}`:"");}reveal(t){this.focus=this.clamp(t);let e$1=this.monthsShown(),i=c$1(this.focus),s=f(i),o=s<f(this.view)?i:s>f(e(this.view,e$1-1))?e(i,1-e$1):this.view;this.lo&&f(o)<f(c$1(this.lo))&&(o=c$1(this.lo)),this.setView(o);}setView(t){let e=this.view;f(t)!==f(e)&&(this.view=t,this.emit("monthChange",new Date(t)),t.getFullYear()!==e.getFullYear()&&this.emit("yearChange",new Date(t)));}move(t){this.reveal(t),this.hover=f(this.focus),this.refresh(true);}nav(t){let e$1=this.state();(t<0?!e$1.canPrev:!e$1.canNext)||(this.focus=this.clamp(e(this.focus,t)),this.setView(e(this.view,t)),this.refresh());}state(){let t=(this.pending??this.sel).map(f);return {view:this.view,focus:this.focus,keys:t,span:this.mode.span?.(t,this.hover)??null,preview:!!this.pending,today:f(new Date),time:this.tod,disabled:this.isDisabled,canPrev:!this.lo||f(this.view)>f(c$1(this.lo)),canNext:!this.hi||f(e(this.view,this.monthsShown()))<=f(this.hi)}}refresh(t=false){this.cal?.update(this.state(),t);}mount(){if(this.cal)return;let t=this.o,e=this.cal=new x({id:this.id,loc:this.loc,cls:{...z,...t.classes},months:this.monthsShown(),otherMonths:!!t.showOtherMonths,inline:!!t.inline,theme:t.theme,time:t.enableTime?b$1():void 0,on:this.handlers});if(t.inline){this.input?this.el.after(e.el):this.el.append(e.el);return}e.el.hidden=true,(t.appendTo??this.el.ownerDocument.body).append(e.el),this.input?.setAttribute("aria-controls",this.id);}present(t){if(this.destroyed||this.o.inline)return;if(this.isOpen)return t?this.cal?.focusCell():void 0;this.mount();let e=this.cal,i=this.el.getRootNode().activeElement;this.opener=i===this.el.ownerDocument.body?null:i,this.reveal(this.sel[0]??this.focus),e.el.hidden=false,this.isOpen=true,this.refresh(),this.reposition(),this.input?.setAttribute("aria-expanded","true"),this.listenWhileOpen(),t&&e.focusCell(),this.emit("open");}hide(t){if(!this.isOpen||this.o.inline)return;let e=this.cal,i=t&&e.el.matches(":focus-within");this.pending=null,this.hover=null,this.isOpen=false,e.el.hidden=true,this.openOffs.splice(0).forEach(s=>s()),this.input?.setAttribute("aria-expanded","false"),i&&(this.opener?.isConnected?this.opener:this.el).focus({preventScroll:true}),this.emit("close");}listenWhileOpen(){let t=this.el.ownerDocument,e=(i,s,o,r=false)=>{i.addEventListener(s,o,r),this.openOffs.push(()=>i.removeEventListener(s,o,r));};if(this.o.closeOnOutsideClick!==false){let i=s=>{let o=s.composedPath();!o.includes(this.cal.el)&&!o.includes(this.anchor)&&this.hide(false);};e(t,"pointerdown",i,true),e(t,"focusin",i,true);}e(t.defaultView??window,"resize",this.reposition),e(t,"scroll",this.reposition,true);}on(t,e,i){t.addEventListener(e,i),this.offs.push(()=>t.removeEventListener(e,i));}bindInput(t){let e=(i,s)=>{t.hasAttribute(i)||(t.setAttribute(i,s),this.added.push(i));};e("aria-haspopup","dialog"),e("aria-expanded","false"),e("autocomplete","off"),this.wasReadOnly=t.readOnly,t.readOnly=this.wasReadOnly||this.o.allowInput===false,this.on(t,"click",()=>this.present(this.o.allowInput===false)),this.on(t,"input",()=>t.removeAttribute("aria-invalid")),this.on(t,"blur",()=>this.commitInput(true)),this.on(t,"keydown",i=>{if(i.key==="ArrowDown")i.preventDefault(),this.isOpen?this.cal?.focusCell():this.present(true);else if(i.key==="Enter"){let s=this.commitInput(false);(!s||this.isOpen)&&i.preventDefault(),s&&this.hide(false);}else i.key==="Escape"&&this.isOpen&&(i.stopPropagation(),this.hide(false));});}text(){return this.sel.map(t=>Y(t,this.fmt,this.loc)+(this.o.enableTime?` ${C(t)}`:"")).join(this.mode.join)}writeISO(){let{isoInput:t,outputTimestamp:e,enableTime:i$1,valueInUtc:s}=this.o;t&&(t.value=this.sel.map(o=>e?i(o,i$1,s):j$1(o,i$1,s)).join(this.mode.iso));}writeInput(){this.input&&(this.input.value=this.text(),this.input.removeAttribute("aria-invalid")),this.writeISO();}read(t){let e=!!this.o.enableTime,i=k$1(t,e,!!this.o.valueInUtc);return i?.length?i:q(t,this.fmt,this.loc,e?this.tod:void 0)}commitInput(t){let e=this.input;if(!e||this.destroyed)return true;let i=e.value.trim();if(i===this.text())return true;let s=[];return i&&(s=this.read(i),s&&(s.length>this.mode.max||s.some(this.isDisabled))&&(s=null)),s?(s=this.mode.clean(s),s[0]&&this.reveal(s[0]),this.setSel(s,true),true):(t?this.writeInput():e.setAttribute("aria-invalid","true"),false)}emit(t,e){this.dispatchEvent(new CustomEvent(t,{detail:e}));let i=this.o;t==="change"?(i.onChange?.(e,this),this.input?.dispatchEvent(new Event("input",{bubbles:true})),this.input?.dispatchEvent(new Event("change",{bubbles:true}))):t==="open"?i.onOpen?.(this):t==="close"?i.onClose?.(this):t==="monthChange"&&i.onMonthChange?.(e,this);}};export{J as a};