flexible-multi-calendar-datepicker 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 SHIVATALEBI
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,578 @@
1
+ # Flexible Persian DatePicker — React Multi-Calendar DatePicker
2
+
3
+ [![npm version](https://img.shields.io/npm/v/flexible-multi-calendar-datepicker.svg)](https://www.npmjs.com/package/flexible-multi-calendar-datepicker)
4
+ [![npm downloads](https://img.shields.io/npm/dm/flexible-multi-calendar-datepicker.svg)](https://www.npmjs.com/package/flexible-multi-calendar-datepicker)
5
+ [![license](https://img.shields.io/npm/l/flexible-multi-calendar-datepicker.svg)](./LICENSE)
6
+
7
+ **Flexible Persian DatePicker** is a responsive, self-contained datepicker for React 18+. One component supports **Jalali (Shamsi / Solar Hijri)**, **Islamic Hijri** and **Gregorian** calendars and includes complete TypeScript declarations.
8
+
9
+ Use it as a **Shamsi Calendar** on an editable `input`, `button`, `span`, or any custom HTML element. The package includes its own Persian font and isolated styles, supports multiple Solar Hijri date formats, and does not depend on the host application's UI framework.
10
+
11
+ ## Package links
12
+
13
+ - [Install Flexible Multi-Calendar DatePicker from npm](https://www.npmjs.com/package/flexible-multi-calendar-datepicker)
14
+ - [Source code and documentation on GitHub](https://github.com/shivatalebi/react-jalali-datepicker)
15
+ - [Report an issue or request a feature](https://github.com/shivatalebi/react-jalali-datepicker/issues)
16
+
17
+ ## Preview
18
+
19
+ | Jalali / Shamsi | Islamic Hijri | Gregorian |
20
+ | --- | --- | --- |
21
+ | ![Jalali Shamsi calendar](./docs/assets/calendar-jalali.png) | ![Islamic Hijri calendar](./docs/assets/calendar-islamic.png) | ![Gregorian calendar](./docs/assets/calendar-gregorian.png) |
22
+
23
+ All screenshots above come directly from the test project. The UI, direction,
24
+ digits, month names, weekday names and default action labels are selected
25
+ automatically for the active calendar.
26
+
27
+ ## Features and benefits
28
+
29
+ - Jalali / Persian / Solar Hijri calendar
30
+ - Islamic Hijri calendar with Persian and English month names
31
+ - Gregorian calendar
32
+ - Conversion and parsing between Jalali, Islamic and Gregorian dates
33
+ - Configurable Islamic date adjustment for official or locally observed dates
34
+ - React JavaScript and React TypeScript support
35
+ - Controlled and uncontrolled standard JavaScript `Date` values
36
+ - Immediate selection or optional Confirm/Cancel workflow
37
+ - Editable input with live calendar synchronization
38
+ - Reliable first-click selection after clearing an input
39
+ - Seven display and parse formats
40
+ - Persian, Arabic and Latin digit parsing
41
+ - Different optional labels and UI texts for every calendar instance
42
+ - Contextual **Today** shortcut after navigating to another day, month or year
43
+ - Multiple inclusive disabled date ranges
44
+ - Width-driven responsive sizing on mobile, tablet and desktop
45
+ - Consistent `rem`-based typography, spacing and corner radius
46
+ - Responsive placement without covering the trigger element
47
+ - Automatic repositioning on resize and orientation changes
48
+ - Safe closing on page or container scroll without breaking internal combobox scrolling
49
+ - Portal rendering to avoid clipping by parent containers
50
+ - Outside-click and Escape-key closing
51
+ - Seven-column day alignment with or without the optional action footer
52
+ - Left-to-right year values inside the year combobox
53
+ - Bundled `IRANSansFaNum` font and automatically injected styles
54
+ - Per-instance custom font through a CSS variable
55
+ - RTL Persian UI and optional English direction/labels
56
+ - ESM, CommonJS and TypeScript declarations
57
+ - No manual CSS import required
58
+
59
+ ## Installation
60
+
61
+ ```bash
62
+ npm install flexible-multi-calendar-datepicker
63
+ ```
64
+
65
+ React and React DOM 18 or newer are peer dependencies.
66
+
67
+ ## Quick start
68
+
69
+ The value exchanged with your application is always a standard JavaScript
70
+ `Date | null`. Set `calendar` to choose how that value is displayed and edited:
71
+
72
+ | Calendar | `calendar` value | Default UI |
73
+ | --- | --- | --- |
74
+ | Jalali / Shamsi | `"jalali"` | Persian, RTL and Persian digits |
75
+ | Islamic Hijri | `"islamic"` | Arabic, RTL and Arabic-Indic digits |
76
+ | Gregorian | `"gregorian"` | English, LTR and Latin digits |
77
+
78
+ This reusable input works with every supported calendar:
79
+
80
+ ```tsx
81
+ import { useRef, useState } from "react";
82
+ import {
83
+ JalaliDatepicker,
84
+ formatCalendarDate,
85
+ parseCalendarDate,
86
+ type CalendarDisplayFormat,
87
+ type CalendarSystem,
88
+ } from "flexible-multi-calendar-datepicker";
89
+
90
+ type CalendarInputProps = {
91
+ calendar: CalendarSystem;
92
+ format?: CalendarDisplayFormat;
93
+ label?: string;
94
+ showActionButtons?: boolean;
95
+ };
96
+
97
+ export function CalendarInput({
98
+ calendar,
99
+ format = "YYYY/MM/DD",
100
+ label,
101
+ showActionButtons = true,
102
+ }: CalendarInputProps) {
103
+ const anchorRef = useRef<HTMLInputElement | null>(null);
104
+ const [open, setOpen] = useState(false);
105
+ const [date, setDate] = useState<Date | null>(null);
106
+ const [text, setText] = useState("");
107
+
108
+ const commit = (next: Date | null) => {
109
+ setDate(next);
110
+ setText(formatCalendarDate(next, format, { calendar }));
111
+ };
112
+
113
+ return (
114
+ <>
115
+ <input
116
+ ref={anchorRef}
117
+ value={text}
118
+ placeholder={format}
119
+ onFocus={() => setOpen(true)}
120
+ onChange={(event) => {
121
+ const nextText = event.target.value;
122
+ setText(nextText);
123
+ setDate(parseCalendarDate(nextText, format, { calendar }));
124
+ }}
125
+ />
126
+
127
+ <JalaliDatepicker
128
+ calendar={calendar}
129
+ open={open}
130
+ anchorRef={anchorRef}
131
+ value={date}
132
+ label={label}
133
+ showActionButtons={showActionButtons}
134
+ onConfirm={commit}
135
+ onClose={() => setOpen(false)}
136
+ />
137
+ </>
138
+ );
139
+ }
140
+ ```
141
+
142
+ Use it for each calendar as follows:
143
+
144
+ ```tsx
145
+ // Jalali / Shamsi — Persian UI and 1405/05/24 output
146
+ <CalendarInput
147
+ calendar="jalali"
148
+ format="YYYY/MM/DD"
149
+ label="تاریخ شروع"
150
+ />
151
+
152
+ // Islamic Hijri — Arabic UI and textual month name
153
+ <CalendarInput
154
+ calendar="islamic"
155
+ format="DD MMM YYYY"
156
+ label="تاريخ العقد"
157
+ />
158
+
159
+ // Gregorian — English UI, Latin digits and Confirm/Cancel footer
160
+ <CalendarInput
161
+ calendar="gregorian"
162
+ format="dddd, DD MMMM YYYY"
163
+ label="Start date"
164
+ showActionButtons
165
+ />
166
+ ```
167
+
168
+ `onConfirm` receives a normal JavaScript `Date | null`, regardless of the
169
+ selected calendar. This makes it safe to store one value in state, send it to
170
+ an API, and display it in any supported calendar system.
171
+
172
+ ## Jalali, Islamic and Gregorian calendars
173
+
174
+ `calendar` defaults to `"jalali"`, so existing integrations remain unchanged. Use the same component and JavaScript `Date` value for all supported calendar systems:
175
+
176
+ ```tsx
177
+ import {
178
+ PersianDatepicker,
179
+ formatCalendarDate,
180
+ parseCalendarDate,
181
+ type CalendarSystem,
182
+ } from "flexible-multi-calendar-datepicker";
183
+
184
+ const calendar: CalendarSystem = "islamic"; // jalali | islamic | gregorian
185
+
186
+ const text = formatCalendarDate(date, "YYYY/MM/DD", {
187
+ calendar,
188
+ locale: "fa",
189
+ });
190
+
191
+ const dateObject = parseCalendarDate(text, "YYYY/MM/DD", {
192
+ calendar,
193
+ locale: "fa",
194
+ });
195
+
196
+ // Islamic: both numeric and textual output are supported.
197
+ const islamicNumeric = formatCalendarDate(date, "YYYY/MM/DD", {
198
+ calendar: "islamic",
199
+ locale: "fa",
200
+ }); // 1446/02/10
201
+
202
+ const islamicText = formatCalendarDate(date, "DD MMM YYYY", {
203
+ calendar: "islamic",
204
+ locale: "fa",
205
+ }); // 10 صفر 1446
206
+
207
+ // Gregorian mode is automatically English, LTR and uses Latin digits.
208
+ const gregorianText = formatCalendarDate(date, "dddd, DD MMMM YYYY", {
209
+ calendar: "gregorian",
210
+ }); // Thursday, 15 August 2024
211
+
212
+ <PersianDatepicker
213
+ calendar={calendar}
214
+ open={open}
215
+ anchorRef={anchorRef}
216
+ value={dateObject}
217
+ onConfirm={setDate}
218
+ onClose={() => setOpen(false)}
219
+ />;
220
+ ```
221
+
222
+ Gregorian mode consistently renders English weekday/month names, Latin digits,
223
+ LTR dropdowns and English default action labels. The `labels` prop can still
224
+ override action texts for a specific instance.
225
+
226
+ It also ignores the bundled Persian digit font and uses an isolated system
227
+ Latin font stack. A consumer can customize that stack without affecting other
228
+ calendar modes:
229
+
230
+ ```tsx
231
+ <PersianDatepicker
232
+ calendar="gregorian"
233
+ style={{
234
+ "--rjd-gregorian-font-family": 'Inter, "Segoe UI", sans-serif',
235
+ } as React.CSSProperties}
236
+ {...props}
237
+ />
238
+ ```
239
+
240
+ Islamic mode uses a deterministic Civil Hijri calculation and applies a default `+1` day adjustment to match commonly announced dates. Lunar calendars can differ by country, timezone and moon sighting. Override the adjustment per instance when required:
241
+
242
+ With the default `locale="fa"`, Islamic mode presents an Arabic RTL interface:
243
+ Arabic month and weekday names, meaningful single-letter weekday headings
244
+ (`س، ح، ن، ث، ر، خ، ج`), Arabic-Indic calendar digits and Arabic default action
245
+ texts. Pass `locale="en"` for the English Islamic interface. Per-instance
246
+ `labels` still override all default action texts.
247
+
248
+ ```tsx
249
+ <PersianDatepicker
250
+ calendar="islamic"
251
+ islamicDateAdjustment={0} // -2 | -1 | 0 | 1 | 2
252
+ {...props}
253
+ />
254
+ ```
255
+
256
+ The same adjustment must be passed to `formatCalendarDate` and `parseCalendarDate` when a non-default value is used. This keeps display, parsing and selection fully reversible without an accidental one-day drift.
257
+
258
+ ## Selection modes
259
+
260
+ The default mode commits and closes immediately after selecting a valid day:
261
+
262
+ ```tsx
263
+ <JalaliDatepicker
264
+ open={open}
265
+ anchorRef={anchorRef}
266
+ value={date}
267
+ showActionButtons={false}
268
+ onConfirm={setDate}
269
+ onClose={() => setOpen(false)}
270
+ />
271
+ ```
272
+
273
+ With `showActionButtons`, a selection remains internal until Confirm is clicked. Cancel, Escape and outside close preserve the previous consumer value.
274
+
275
+ ```tsx
276
+ <JalaliDatepicker
277
+ open={open}
278
+ anchorRef={anchorRef}
279
+ value={date}
280
+ showActionButtons
281
+ labels={{ confirm: "ثبت", cancel: "بازگشت" }}
282
+ onConfirm={setDate}
283
+ onClose={() => setOpen(false)}
284
+ />
285
+ ```
286
+
287
+ When neither `value` nor `defaultValue` is supplied, today is selected visually on open. It is emitted only after the user selects a date or confirms it.
288
+
289
+ ## Editable input with live synchronization
290
+
291
+ The input belongs to the consumer and remains fully editable. Parse its text and pass the result back as `value`; changing the day, month or year updates an open calendar immediately.
292
+
293
+ ```tsx
294
+ import { useRef, useState } from "react";
295
+ import {
296
+ JalaliDatepicker,
297
+ formatJalaliDate,
298
+ parseJalaliDate,
299
+ type JalaliDisplayFormat,
300
+ } from "flexible-multi-calendar-datepicker";
301
+
302
+ const format: JalaliDisplayFormat = "YYYY/MM/DD";
303
+
304
+ export function EditableDateInput() {
305
+ const anchorRef = useRef<HTMLInputElement | null>(null);
306
+ const [open, setOpen] = useState(false);
307
+ const [text, setText] = useState("");
308
+ const [date, setDate] = useState<Date | null>(null);
309
+
310
+ const commit = (next: Date | null) => {
311
+ setDate(next);
312
+ setText(formatJalaliDate(next, format, "fa"));
313
+ };
314
+
315
+ return (
316
+ <>
317
+ <input
318
+ ref={anchorRef}
319
+ value={text}
320
+ placeholder={format}
321
+ onFocus={() => setOpen(true)}
322
+ onChange={(event) => {
323
+ const nextText = event.target.value;
324
+ setText(nextText);
325
+ setDate(parseJalaliDate(nextText, format, "fa"));
326
+ }}
327
+ />
328
+ <button type="button" onClick={() => commit(null)}>پاک‌کردن</button>
329
+
330
+ <JalaliDatepicker
331
+ open={open}
332
+ anchorRef={anchorRef}
333
+ value={date}
334
+ showActionButtons
335
+ onConfirm={commit}
336
+ onClose={() => setOpen(false)}
337
+ />
338
+ </>
339
+ );
340
+ }
341
+ ```
342
+
343
+ `parseJalaliDate` accepts Latin (`1405`), Persian (`۱۴۰۵`) and Arabic (`١٤٠٥`) digits. Empty, incomplete or invalid input returns `null`, removing the visible selection until a valid date is entered.
344
+
345
+ ## Button, span or custom trigger
346
+
347
+ Any HTMLElement can anchor the popup:
348
+
349
+ ```tsx
350
+ const anchorRef = useRef<HTMLSpanElement | null>(null);
351
+
352
+ <span
353
+ ref={anchorRef}
354
+ role="button"
355
+ tabIndex={0}
356
+ onClick={() => setOpen(true)}
357
+ >
358
+ {date ? formatJalaliDate(date, "dddd, DD MMMM YYYY", "fa") : "انتخاب تاریخ"}
359
+ </span>
360
+
361
+ <JalaliDatepicker
362
+ open={open}
363
+ anchorRef={anchorRef}
364
+ value={date}
365
+ onConfirm={setDate}
366
+ onClose={() => setOpen(false)}
367
+ />
368
+ ```
369
+
370
+ ## Supported formats
371
+
372
+ Both formatting and parsing support:
373
+
374
+ | Format | Example |
375
+ | --- | --- |
376
+ | `YYYY-MM-DD` | `1405-05-24` |
377
+ | `YYYY/MM/DD` | `1405/05/24` |
378
+ | `DD/MM/YYYY` | `24/05/1405` |
379
+ | `DD MMM YYYY` | `24 مرداد 1405` |
380
+ | `MMMM DD, YYYY` | `مرداد 24، 1405` |
381
+ | `dddd DD MMMM YYYY` | `شنبه 24 مرداد 1405` |
382
+ | `dddd, DD MMMM YYYY` | `شنبه، 24 مرداد 1405` |
383
+
384
+ ```tsx
385
+ const apiText = formatJalaliDate(date, "YYYY-MM-DD", "en");
386
+ const faText = formatJalaliDate(date, "dddd, DD MMMM YYYY", "fa");
387
+ const dateObject = parseJalaliDate("1405/05/24", "YYYY/MM/DD", "fa");
388
+ ```
389
+
390
+ ## Custom label per instance
391
+
392
+ `label` accepts any React node. Omit it, pass `null`, or pass an empty string to hide it.
393
+
394
+ ```tsx
395
+ <JalaliDatepicker label="تاریخ شروع قرارداد" {...startProps} />
396
+ <JalaliDatepicker label={<strong>تاریخ تحویل</strong>} {...deliveryProps} />
397
+ <JalaliDatepicker label={null} {...compactProps} />
398
+ ```
399
+
400
+ ## Today shortcut
401
+
402
+ When the selected date or visible month/year differs from today, a blue `امروز` action appears beside the date heading. It returns from any month or year to today and selects it.
403
+
404
+ ```tsx
405
+ <JalaliDatepicker labels={{ today: "برو به امروز" }} {...props} />
406
+ ```
407
+
408
+ It waits for Confirm in confirmation mode and commits immediately in immediate mode. If today is disabled, the action is disabled.
409
+
410
+ ## Disabled date ranges
411
+
412
+ Pass any number of inclusive ranges. Disabled dates remain visible in light purple/gray, cannot be selected, and do not close the popup. Reversed boundaries are normalized automatically.
413
+
414
+ ```tsx
415
+ import {
416
+ parseJalaliDate,
417
+ type JalaliDisabledDateRange,
418
+ } from "flexible-multi-calendar-datepicker";
419
+
420
+ const disabledDateRanges: JalaliDisabledDateRange[] = [
421
+ {
422
+ from: parseJalaliDate("1405/05/26", "YYYY/MM/DD", "fa")!,
423
+ to: parseJalaliDate("1405/06/03", "YYYY/MM/DD", "fa")!,
424
+ },
425
+ {
426
+ from: parseJalaliDate("1405/07/10", "YYYY/MM/DD", "fa")!,
427
+ to: parseJalaliDate("1405/07/12", "YYYY/MM/DD", "fa")!,
428
+ },
429
+ ];
430
+
431
+ <JalaliDatepicker disabledDateRanges={disabledDateRanges} {...props} />
432
+ ```
433
+
434
+ ## Controlled and default values
435
+
436
+ ```tsx
437
+ // Controlled
438
+ <JalaliDatepicker value={date} onChange={setDate} {...props} />
439
+
440
+ // Initial uncontrolled value
441
+ <JalaliDatepicker defaultValue={new Date(2026, 7, 15)} {...props} />
442
+ ```
443
+
444
+ `onChange` is optional. It runs when a value is committed: immediately in immediate mode, or with Confirm in confirmation mode.
445
+
446
+ ## Built-in and custom fonts
447
+
448
+ `IRANSansFaNum` and the required CSS are bundled and injected automatically. The calendar keeps its own font even when the host application uses another font; no CSS import or asset copy is required.
449
+
450
+ Override one instance with `--rjd-font-family`:
451
+
452
+ ```tsx
453
+ <JalaliDatepicker className="product-datepicker" {...props} />
454
+ ```
455
+
456
+ ```css
457
+ @font-face {
458
+ font-family: "MyProductFont";
459
+ src: url("/fonts/my-product-font.woff2") format("woff2");
460
+ }
461
+
462
+ .product-datepicker {
463
+ --rjd-font-family: "MyProductFont", sans-serif;
464
+ }
465
+ ```
466
+
467
+ Or inline:
468
+
469
+ ```tsx
470
+ <JalaliDatepicker
471
+ style={{
472
+ "--rjd-font-family": '"MyProductFont", sans-serif',
473
+ } as React.CSSProperties}
474
+ {...props}
475
+ />
476
+ ```
477
+
478
+ ## Custom texts and locale
479
+
480
+ ```tsx
481
+ <JalaliDatepicker
482
+ locale="fa"
483
+ labels={{
484
+ confirm: "تایید",
485
+ cancel: "انصراف",
486
+ chooseDate: "انتخاب تاریخ",
487
+ today: "امروز",
488
+ titleFrom: "از تاریخ",
489
+ titleTo: "تا تاریخ",
490
+ }}
491
+ {...props}
492
+ />
493
+ ```
494
+
495
+ `locale="fa"` uses RTL and `locale="en"` uses LTR. `titleFrom` and `titleTo` are retained for compatibility when `label` is exactly `از تاریخ` or `تا تاریخ`; new code should pass the final text directly through `label`.
496
+
497
+ ## Portal and responsive behavior
498
+
499
+ The popup renders in `document.body` by default, avoiding clipping by cards, modals and `overflow` containers. It measures the anchor and viewport, chooses a suitable side, and recalculates on scrolling, resizing and orientation changes.
500
+
501
+ ```tsx
502
+ const portalHost = document.getElementById("calendar-layer");
503
+ <JalaliDatepicker portalContainer={portalHost} {...props} />
504
+ ```
505
+
506
+ All dimensions use `rem`; changing the root font size scales the calendar consistently:
507
+
508
+ ```css
509
+ html { font-size: 16px; }
510
+ @media (max-width: 480px) {
511
+ html { font-size: 14px; }
512
+ }
513
+ ```
514
+
515
+ ## Complete API
516
+
517
+ ### `JalaliDatepickerProps`
518
+
519
+ | Prop | Type | Default | Description |
520
+ | --- | --- | --- | --- |
521
+ | `open` | `boolean` | required | Controls popup visibility. |
522
+ | `anchorRef` | `RefObject<HTMLElement>` | required | Element used for popup positioning. |
523
+ | `value` | `Date \| null` | — | Controlled selected value. |
524
+ | `defaultValue` | `Date \| null` | `null` | Initial uncontrolled value. |
525
+ | `onConfirm` | `(date: Date \| null) => void` | required | Receives a committed date. |
526
+ | `onClose` | `() => void` | required | Requests that the consumer close the popup. |
527
+ | `onChange` | `(date: Date \| null) => void` | — | Optional committed-value notification. |
528
+ | `showActionButtons` | `boolean` | `false` | Shows Confirm/Cancel instead of immediate commit. |
529
+ | `label` | `ReactNode` | — | Per-instance heading; empty values render nothing. |
530
+ | `locale` | `"fa" \| "en"` | `"fa"` | Direction and localized output. Gregorian mode always resolves to English/LTR. |
531
+ | `calendar` | `"jalali" \| "islamic" \| "gregorian"` | `"jalali"` | Selects the calendar system. |
532
+ | `islamicDateAdjustment` | `-2 \| -1 \| 0 \| 1 \| 2` | `1` | Aligns Islamic dates with an official or locally observed calendar. |
533
+ | `labels` | `object` | Persian texts | Overrides Today, Confirm, Cancel and helper texts. |
534
+ | `disabledDateRanges` | `readonly { from: Date; to: Date }[]` | `[]` | Inclusive non-selectable ranges. |
535
+ | `className` | `string` | — | Extra class on the popup root. |
536
+ | `style` | `React.CSSProperties` | — | Extra inline styles and CSS variables. |
537
+ | `portalContainer` | `HTMLElement \| null` | `document.body` | Optional portal host. |
538
+
539
+ ### Utility API
540
+
541
+ ```ts
542
+ formatCalendarDate(
543
+ date: Date | null | undefined,
544
+ format?: CalendarDisplayFormat,
545
+ options?: CalendarFormatOptions
546
+ ): string;
547
+
548
+ parseCalendarDate(
549
+ input: string,
550
+ format: CalendarDisplayFormat,
551
+ options?: CalendarFormatOptions
552
+ ): Date | null;
553
+
554
+ formatJalaliDate(
555
+ date: Date | null | undefined,
556
+ format?: JalaliDisplayFormat,
557
+ locale?: "fa" | "en"
558
+ ): string;
559
+
560
+ parseJalaliDate(
561
+ input: string,
562
+ format: JalaliDisplayFormat,
563
+ locale?: "fa" | "en"
564
+ ): Date | null;
565
+ ```
566
+
567
+ Exported types include `CalendarSystem`, `CalendarLocale`, `IslamicDateAdjustment`, `CalendarDisplayFormat`, `CalendarFormatOptions`, `JalaliDatepickerProps`, `JalaliDisabledDateRange`, `JalaliDisplayFormat`, and `JalaliFormatLocale`.
568
+
569
+ ## Accessibility and closing
570
+
571
+ - Escape and outside pointer interactions close the popup.
572
+ - For a custom trigger such as `span`, add `role`, `tabIndex`, keyboard handlers and an accessible name.
573
+ - Disabled dates expose disabled state and cannot commit a value.
574
+ - Month and year controls support keyboard interaction.
575
+
576
+ ## License
577
+
578
+ [MIT](./LICENSE) © SHIVATALEBI