11import flatpickr from "flatpickr" ;
22
3+ /**
4+ * Minimal flatpickr instance shape used by updateClasses and updateMonthNode.
5+ * Matches flatpickr's Instance where some elements may be optional.
6+ * @typedef {{
7+ * calendarContainer: HTMLElement;
8+ * days: HTMLElement;
9+ * daysContainer?: HTMLElement;
10+ * weekdayContainer: HTMLElement;
11+ * selectedDates: unknown[];
12+ * l10n: { months: { longhand: string[] }; weekdays?: { shorthand?: string[] } };
13+ * currentMonth: number;
14+ * monthNav: HTMLElement;
15+ * monthsDropdownContainer: HTMLElement;
16+ * }} FlatpickrInstance
17+ */
18+
19+ /**
20+ * Locale override with optional en.weekdays.shorthand for custom formatting.
21+ * @typedef {{ en?: { weekdays: { shorthand: string[] } } } } L10nOverrides
22+ */
23+
24+ /** @type {L10nOverrides | undefined } */
325let l10n ;
426
27+ /**
28+ * @param {FlatpickrInstance } instance
29+ */
530function updateClasses ( instance ) {
631 const {
732 calendarContainer,
@@ -14,14 +39,16 @@ function updateClasses(instance) {
1439 calendarContainer . classList . add ( "bx--date-picker__calendar" ) ;
1540 calendarContainer
1641 . querySelector ( ".flatpickr-month" )
17- . classList . add ( "bx--date-picker__month" ) ;
42+ ? .classList . add ( "bx--date-picker__month" ) ;
1843
1944 weekdayContainer . classList . add ( "bx--date-picker__weekdays" ) ;
2045 for ( const node of weekdayContainer . querySelectorAll ( ".flatpickr-weekday" ) ) {
2146 node . classList . add ( "bx--date-picker__weekday" ) ;
2247 }
2348
24- daysContainer . classList . add ( "bx--date-picker__days" ) ;
49+ if ( daysContainer ) {
50+ daysContainer . classList . add ( "bx--date-picker__days" ) ;
51+ }
2552 for ( const node of days . querySelectorAll ( ".flatpickr-day" ) ) {
2653 node . classList . add ( "bx--date-picker__day" ) ;
2754 if ( node . classList . contains ( "today" ) && selectedDates . length > 0 ) {
@@ -32,6 +59,9 @@ function updateClasses(instance) {
3259 }
3360}
3461
62+ /**
63+ * @param {FlatpickrInstance } instance
64+ */
3565function updateMonthNode ( instance ) {
3666 const monthText = instance . l10n . months . longhand [ instance . currentMonth ] ;
3767 const staticMonthNode = instance . monthNav . querySelector ( ".cur-month" ) ;
@@ -43,39 +73,59 @@ function updateMonthNode(instance) {
4373 const span = document . createElement ( "span" ) ;
4474 span . setAttribute ( "class" , "cur-month" ) ;
4575 span . textContent = monthText ;
46- monthSelectNode . parentNode . replaceChild ( span , monthSelectNode ) ;
76+ monthSelectNode . parentNode ? .replaceChild ( span , monthSelectNode ) ;
4777 }
4878}
4979
80+ /**
81+ * @typedef {{
82+ * options: { locale?: string; mode?: string };
83+ * base: HTMLElement;
84+ * input: HTMLInputElement;
85+ * dispatch: (event: string) => void;
86+ * }} CreateCalendarArgs
87+ */
88+
89+ /**
90+ * @param {CreateCalendarArgs } args
91+ * @returns {Promise<FlatpickrInstance> }
92+ */
5093async function createCalendar ( { options, base, input, dispatch } ) {
94+ /** @type {string | L10nOverrides["en"] } */
5195 let locale = options . locale ;
5296
5397 if ( options . locale === "en" && l10n && l10n . en ) {
54- for ( let index = 0 ; index < l10n . en . weekdays . shorthand . length ; index ++ ) {
55- const _ = l10n . en . weekdays . shorthand [ index ] ;
56- const shorthand = _ . slice ( 0 , 2 ) ;
57- l10n . en . weekdays . shorthand [ index ] =
58- shorthand === "Th" ? "Th" : shorthand . charAt ( 0 ) ;
98+ const shorthand = l10n . en . weekdays . shorthand ;
99+ if ( shorthand ) {
100+ for ( let index = 0 ; index < shorthand . length ; index ++ ) {
101+ const _ = shorthand [ index ] ;
102+ const s = _ . slice ( 0 , 2 ) ;
103+ shorthand [ index ] = s === "Th" ? "Th" : s . charAt ( 0 ) ;
104+ }
59105 }
60-
61106 locale = l10n . en ;
62107 }
63108
64- let rangePlugin ;
109+ /** @type {((new (config: { position: string; input: HTMLInputElement }) => unknown) | undefined) } */
110+ let RangePlugin ;
65111
66112 if ( options . mode === "range" ) {
67113 const importee = await import ( "flatpickr/dist/esm/plugins/rangePlugin" ) ;
68- rangePlugin = importee . default ;
114+ RangePlugin = importee . default ;
69115 }
70116
71- return new flatpickr ( base , {
117+ const plugins = [
118+ options . mode === "range" && RangePlugin
119+ ? new RangePlugin ( { position : "left" , input } )
120+ : false ,
121+ ] . filter ( Boolean ) ;
122+
123+ const config = {
72124 allowInput : true ,
73125 disableMobile : true ,
74126 clickOpens : true ,
75127 locale,
76- plugins : [
77- options . mode === "range" && new rangePlugin ( { position : "left" , input } ) ,
78- ] . filter ( Boolean ) ,
128+ plugins,
79129 nextArrow :
80130 '<svg width="16px" height="16px" viewBox="0 0 16 16"><polygon points="11,8 6,13 5.3,12.3 9.6,8 5.3,3.7 6,3 "/><rect width="16" height="16" style="fill: none" /></svg>' ,
81131 prevArrow :
@@ -86,16 +136,25 @@ async function createCalendar({ options, base, input, dispatch }) {
86136 onClose : ( ) => {
87137 dispatch ( "close" ) ;
88138 } ,
89- onMonthChange : ( _s , _d , instance ) => {
139+ onMonthChange : (
140+ /** @type {any } */ _s ,
141+ /** @type {any } */ _d ,
142+ /** @type {FlatpickrInstance } */ instance ,
143+ ) => {
90144 updateMonthNode ( instance ) ;
91145 } ,
92- onOpen : ( _s , _d , instance ) => {
146+ onOpen : (
147+ /** @type {any } */ _s ,
148+ /** @type {any } */ _d ,
149+ /** @type {FlatpickrInstance } */ instance ,
150+ ) => {
93151 dispatch ( "open" ) ;
94152 updateClasses ( instance ) ;
95153 updateMonthNode ( instance ) ;
96154 } ,
97155 ...options ,
98- } ) ;
156+ } ;
157+ return new /** @type {any } */ ( flatpickr ) ( base , config ) ;
99158}
100159
101160export { createCalendar } ;
0 commit comments