jb-date-input is a form-associated Jalali and Gregorian date input web component with a typed input surface and a calendar popover.
- Supports Jalali and Gregorian input.
- Supports fast keyboard typing and ArrowUp/ArrowDown date-part changes.
- Opens a responsive, mobile-friendly calendar picker.
- Accepts Persian digits and can display Persian digits while keeping
.valuein English digits. - Supports
minandmaxdate limits. - Supports native HTML form submission through
ElementInternals. - Supports custom validation through
jb-validation. - Supports value output as Gregorian, Jalali, or timestamp.
- Supports custom value formats such as ISO strings,
YYYY/MM/DD, orYYYY_MM_DD. - Supports custom month names for Jalali and Gregorian calendars.
- Includes headless utilities for using the date typing logic with your own input.
- Supports TypeScript.
- Provides a smooth desktop typing experience.
- Supports ESM imports for modern JavaScript apps.
- Supports app-level i18n through
jb-core/i18n. - Supports custom styling with CSS variables and CSS parts. See CSS parts and variables.
- Uses
jb-input,jb-calendar, andjb-popoverinternally. - Framework friendly: use it in pure JavaScript or in frameworks such as React, Vue, and Angular.
Use jb-date-input when users should type or pick a date and the field needs Jalali/Gregorian conversion, form association, validation, min/max limits, custom value formats, or Persian digit display.
Use jb-calendar when you need only a calendar UI without an input field. Use jb-input when the value is plain text and not a date.
See the React documentation.
Other integrations: Angular · Vue · Nuxt · Svelte · SvelteKit · SolidJS · Lit · Next.js · Astro · Blazor · Server-rendered templates · WordPress · Alpine.js and HTMX
npm i jb-date-inputimport 'jb-date-input';<jb-date-input label="Date"></jb-date-input><script src="https://unpkg.com/jb-date-input/dist/jb-date-input.umd.js"></script>jb-date-input composes jb-input, jb-calendar, and jb-popover. For shared input styling and behavior, see the jb-input API.
| name | type | default | description |
|---|---|---|---|
value |
string |
empty date value | Date value in the configured value-type and format. Demo |
value-type |
'GREGORIAN' | 'JALALI' | 'TIME_STAMP' |
GREGORIAN |
Controls the canonical .value returned by the component. Demo |
input-type |
'GREGORIAN' | 'JALALI' |
locale based | Controls what date system users type and see in the calendar. Demo |
format |
string |
YYYY-MM-DDTHH:mm:ss.SSS[Z] |
Format used for .value, min, and max when value-type is GREGORIAN or JALALI. Demo |
min |
string |
none | Minimum accepted date. Must use the configured value-type and format. Demo |
max |
string |
none | Maximum accepted date. Must use the configured value-type and format. Demo |
name |
string |
"" |
Form field name. Demo |
label |
string |
"" |
Label forwarded to the internal jb-input. Demo |
message |
string |
"" |
Helper message forwarded to the internal jb-input. Demo |
placeholder |
string |
null |
Placeholder shown while the date value is empty. Demo |
required |
boolean |
false |
Enables required validation. Empty attribute and "true" mean true. Demo |
disabled |
boolean |
false |
Disables the internal input and sets the disabled custom state. Demo |
error |
string |
"" |
External validation error message. Demo |
dir |
'ltr' | 'rtl' |
inherited | Native layout direction inherited by the input and calendar. Demo |
show-persian-number |
boolean |
locale based | Displays Persian digits while .value remains English digits. Demo |
size |
'xs' | 'sm' | 'md' | 'lg' | 'xl' |
md style defaults |
Visual size forwarded to the internal jb-input. Demo |
autocomplete |
string |
browser default | Forwarded to the internal jb-input. Demo |
readonly |
boolean |
device based | Forwarded to the internal jb-input; mobile devices become readonly to favor the picker. Demo |
| name | type | readonly | description |
|---|---|---|---|
value |
string |
no | Canonical value submitted with forms. Set with string, Date, or null. Demo |
initialValue |
string | null |
no | Default and reset value. It initializes value until the live value is explicitly set. Demo |
valueAsDate |
Date | null |
yes | Current complete value as a JavaScript Date, or null when empty/incomplete. Demo |
displayValue |
string |
yes | Visible typed text in YYYY/MM/DD display format. Demo |
inputType |
'GREGORIAN' | 'JALALI' |
no | Date system used by the input UI and calendar. Demo |
valueType |
'GREGORIAN' | 'JALALI' | 'TIME_STAMP' |
no | Date system or timestamp mode used for .value. Demo |
valueFormat |
string |
yes | Current value format. Change it with setFormat(). Demo |
dateRestrictions |
{ min: Date | null; max: Date | null } |
no | Runtime min/max restrictions used by validation and calendar. Demo |
validation |
ValidationHelper<ValidationValue> |
yes | Validation helper from jb-validation; set validation.list for custom rules. Demo |
isAutoValidationDisabled |
boolean |
no | Disables automatic validation when true. Demo |
required |
boolean |
no | Enables required validation. Demo |
disabled |
boolean |
no | Enables or disables the internal input. Demo |
showPersianNumber |
boolean |
no | Displays Persian digits while .value remains English digits. Demo |
isOpen |
boolean |
no | Opens or closes the internal calendar popover. Demo |
placeholder |
string | null |
no | Placeholder shown while empty. |
form |
HTMLFormElement | null |
yes | Associated form from ElementInternals. Demo |
isDirty |
boolean |
yes | true when current .value differs from initialValue. Demo |
validationMessage |
string |
yes | Current validation message from ElementInternals. Demo |
yearValue / monthValue / dayValue |
number | null |
yes | Date parts in the configured valueType. Demo |
yearDisplayValue / monthDisplayValue / dayDisplayValue |
number | null |
yes | Date parts in the configured inputType. Demo |
elements |
ElementsObject |
no | Internal input, calendar, popover, and calendarTriggerButton for advanced integrations. Demo |
| name | returns | description |
|---|---|---|
setFormat(newFormat) |
void |
Sets the value format used for .value, min, and max. Demo |
setMinDate(minDate) |
void |
Sets or clears the minimum accepted date. Accepts string, Date, or null. Demo |
setMaxDate(maxDate) |
void |
Sets or clears the maximum accepted date. Accepts string, Date, or null. Demo |
setMonthList(inputType, monthName) |
void |
Overrides month labels for GREGORIAN or JALALI. Demo |
setCalendarDefaultDateView(year, month, dateType?) |
void |
Sets the year/month shown when the value is empty. Demo |
getDateValue(type?) |
string |
Returns current value in GREGORIAN, JALALI, or TIME_STAMP mode. Demo |
open() |
void |
Opens the internal calendar popover. |
close() |
void |
Closes the internal calendar popover. |
reset() |
void |
Restores initialValue and clears displayed validation. |
focus() |
void |
Focuses the internal input and opens the calendar. Demo |
setSelectionRange(start, end, direction?) |
void |
Forwards selection range to the internal input. Demo |
checkValidity() |
boolean |
Runs validation without showing the error message. Dispatches invalid when invalid. Demo |
reportValidity() |
boolean |
Runs validation and shows the first error message. Dispatches invalid when invalid. Demo |
clearValidationError() |
void |
Clears the visible validation error. Demo |
| event | description |
|---|---|
load |
Dispatched from connectedCallback before property initialization. Demo |
init |
Dispatched after internal components are defined and the initial value is applied. Demo |
beforeinput |
Cancelable event dispatched before typed input is applied. Demo |
input |
Dispatched after user typing changes the visible input text. Demo |
change |
Dispatched when the committed date value changes after blur or calendar selection. Canceling it reverts the date. Demo |
select |
Dispatched when the user selects a date from the calendar. Demo |
focus |
Re-dispatched when the internal input receives focus. Demo |
blur |
Re-dispatched when the internal input loses focus. Demo |
keydown |
Re-dispatched from the internal input. ArrowUp/ArrowDown change the selected date part. Demo |
keyup |
Re-dispatched from the internal input after the value object is updated. Demo |
keypress |
Re-dispatched from the internal input. Demo |
invalid |
Dispatched when checkValidity() or reportValidity() fails. Demo |
input-type controls what users see and edit. value-type controls what developers receive from .value; compare the Jalali and Gregorian demo and value-type demo.
<!-- User sees Jalali, developer receives Gregorian ISO-like value. -->
<jb-date-input input-type="JALALI" value-type="GREGORIAN"></jb-date-input>
<!-- User sees Gregorian, developer receives Jalali formatted value. -->
<jb-date-input input-type="GREGORIAN" value-type="JALALI"></jb-date-input>
<!-- Developer receives a timestamp string. -->
<jb-date-input value-type="TIME_STAMP"></jb-date-input>const dateInput = document.querySelector('jb-date-input');
dateInput.inputType = 'JALALI';
dateInput.valueType = 'GREGORIAN';Get and set value like a native input in the value demo.
const dateInput = document.querySelector('jb-date-input');
dateInput.value = '2024-01-15T00:00:00.000Z';
console.log(dateInput.value);
console.log(dateInput.valueAsDate);
dateInput.value = new Date();
dateInput.value = null;Empty values are represented with an empty date in the configured format, for example 0000-00-00T00:00:00.000Z in the default Gregorian format. valueAsDate returns null while the date is empty or incomplete.
The default format is compatible with Date.prototype.toISOString(); see the custom format demo:
<jb-date-input value="2024-01-15T00:00:00.000Z"></jb-date-input>Use format when your backend needs a different string.
<jb-date-input
format="YYYY/MM/DD"
value="2024/01/15"
min="2024/01/01"
max="2024/12/29"
></jb-date-input>format also controls how string min and max are parsed. Set format before setting value, min, or max in JavaScript.
Set date limits with attributes in the Gregorian min/max demo:
<jb-date-input
value="2020-08-10T08:51:23.176Z"
min="2020-08-05T08:51:23.176Z"
max="2020-08-15T08:51:23.176Z"
></jb-date-input>Or set them with JavaScript:
const dateInput = document.querySelector('jb-date-input');
dateInput.setMinDate(new Date());
dateInput.setMaxDate('2025-12-31T00:00:00.000Z');
dateInput.setMinDate(null);
dateInput.setMaxDate(null);min and max validation uses the configured valueType and format for string values.
jb-date-input uses jb-validation. Built-in validation handles required, error, min, and max; see the required and external error demos. Use validation.list for custom rules in the custom validation demo.
const dateInput = document.querySelector('jb-date-input');
dateInput.required = true;
dateInput.validation.list = [
{
validator: /^13.*$/g,
message: 'Date must be in the 13th century',
},
{
validator: ({ text, inputObject, valueObject, valueText }) => {
if (inputObject.year && inputObject.year < '1300') {
return 'Typed year must be 1300 or later';
}
return valueObject.jalali.day === 15;
},
message: 'Only the 15th day of the month is accepted',
},
];Custom validators receive:
| field | description |
|---|---|
text |
Visible input text in YYYY/MM/DD display format. |
inputObject |
Raw typed date parts before complete date conversion. |
valueObject |
Complete Gregorian, Jalali, timestamp, and time object. |
valueText |
Canonical .value. |
When the input is empty, the calendar opens on the current month. Use setCalendarDefaultDateView() to change that view in the default calendar date demo.
const dateInput = document.querySelector('jb-date-input');
dateInput.setCalendarDefaultDateView(1360, 5);
dateInput.setCalendarDefaultDateView(1985, 8, 'GREGORIAN');
dateInput.setCalendarDefaultDateView(1360, 5, 'JALALI');<jb-date-input show-persian-number></jb-date-input>
<jb-date-input show-persian-number="true"></jb-date-input>
<jb-date-input show-persian-number="false"></jb-date-input>document.querySelector('jb-date-input').showPersianNumber = true;This affects display only. .value remains English digits; see the Persian number demo.
For app-wide locale, calendar, and numbering-system setup, configure jb-core/i18n.
Use the inline-start and inline-end slots in the inline sections demo, and customize calendar-trigger-icon in the custom icon demo.
| slot | description |
|---|---|
inline-start |
Content rendered at the start of the internal input box. |
inline-end |
Content rendered after the calendar trigger in the internal input end section. |
calendar-trigger-icon |
Custom calendar trigger icon. |
<jb-date-input label="Birthday">
<span slot="inline-start">Birthday</span>
<span slot="inline-end">optional</span>
</jb-date-input><jb-date-input>
<span slot="calendar-trigger-icon">open</span>
</jb-date-input>Override calendar month labels when your product needs custom locale names in the custom month name demo.
const dateInput = document.querySelector('jb-date-input');
dateInput.setMonthList('JALALI', [
'ØÙŽÙ…ÙŽÙ„',
'ثَور',
'جَوزا',
'سَرَطان',
'اَسَد',
'س�نب�له',
'میزان',
'عَقرَب',
'قَوس',
'جَدْی',
'دَلو',
'ØÙˆØª',
]);
dateInput.setMonthList('GREGORIAN', [
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9',
'10',
'11',
'12',
]);When the calendar opens near the edge of a scroll area, configure the internal popover; compare the overflow handler and constrained parent demos.
const dateInput = document.querySelector('jb-date-input');
dateInput.elements.popover.overflowHandler = 'SLIDE';
dateInput.elements.popover.overflowDom = document.querySelector('.modal-body');For complete styling guidance, live examples, and copyable style recipes, see the Styling docs and style gallery.
| part | description |
|---|---|
input |
Internal jb-input. |
popover |
Internal jb-popover. |
calendar |
Internal jb-calendar. |
| custom state | description |
|---|---|
disabled |
Applied when disabled is true. |
invalid |
Applied while a validation error is visible. |
jb-date-input {
--jb-date-input-margin: 1rem 0;
--jb-date-input-calendar-icon-color: #2563eb;
}
jb-date-input::part(input) {
--jb-input-border-radius: 0.5rem;
}
jb-date-input::part(popover) {
--jb-popover-bg-color: #ffffff;
--jb-popover-border-radius: 1rem;
--jb-popover-padding: 1rem;
--jb-popover-z-index: 1000;
}
jb-date-input::part(calendar) {
--jb-calendar-day-bg-color-selected: #2563eb;
--jb-calendar-day-color-selected: #ffffff;
}
jb-date-input:state(invalid)::part(input) {
--jb-input-border-color: #dc2626;
}Use the headless utilities when you want jb-date-input typing, caret, and date-string behavior in your own input component.
import {
emptyInputValueString,
getFixedCaretPos,
handleBeforeInput,
} from 'jb-date-input/module';For React, use the headless hook:
import { useJBDateInput } from 'jb-date-input/react';See the Headless demo and headless documentation for complete examples.
The standard input demo shows the labeled field used by assistive technologies.
- The component is form-associated and submits
.value. - The shadow root delegates focus to the internal
jb-input. label,message,required,disabled, and validation states are forwarded to the internal input or synchronized withElementInternals.- The calendar trigger is focusable and opens/closes the popover.
- On mobile, the internal input is set to readonly so users interact through the picker.
- See
jb-date-input/reactif you want to use this component in React. - See
jb-input,jb-calendar, andjb-popoverfor composed component APIs. - See All JB Design System Component List for more components.
- Use Contribution Guide if you want to contribute to this component.
- Import
jb-date-inputonce before using<jb-date-input>. - Use
input-type/inputTypefor the date system the user sees. - Use
value-type/valueTypefor the canonical value returned by.value. - Set
formatbefore setting stringvalue,min, ormax. - Read
.valuefor form/submitted value and.valueAsDatewhen a JavaScriptDateis needed. - Use
show-persian-numberonly for display;.valueremains English digits. - Use
inline-start,inline-end, andcalendar-trigger-iconslots. Do not useinline-startorinline-enddirectly onjb-date-input. - Use
validation.listfor custom validation; validators receive{ text, inputObject, valueObject, valueText }. - This package includes
custom-elements.jsonand points to it with the package.jsoncustomElementsfield. The field is documented by the Custom Elements Manifest project in Referencing manifests from npm packages. - In
custom-elements.json,exports.kind: "js"describes JavaScript/TypeScript exports andexports.kind: "custom-element-definition"maps thejb-date-inputtag name toJBDateInputWebComponent.