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.
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. |
value-type |
'GREGORIAN' | 'JALALI' | 'TIME_STAMP' |
GREGORIAN |
Controls the canonical .value returned by the component. |
input-type |
'GREGORIAN' | 'JALALI' |
locale based | Controls what date system users type and see in the calendar. |
format |
string |
YYYY-MM-DDTHH:mm:ss.SSS[Z] |
Format used for .value, min, and max when value-type is GREGORIAN or JALALI. |
min |
string |
none | Minimum accepted date. Must use the configured value-type and format. |
max |
string |
none | Maximum accepted date. Must use the configured value-type and format. |
name |
string |
"" |
Form field name. |
label |
string |
"" |
Label forwarded to the internal jb-input. |
message |
string |
"" |
Helper message forwarded to the internal jb-input. |
placeholder |
string |
null |
Placeholder shown while the date value is empty. |
required |
boolean |
false |
Enables required validation. Empty attribute and "true" mean true. |
disabled |
boolean |
false |
Disables the internal input and sets the disabled custom state. |
error |
string |
"" |
External validation error message. |
direction |
'ltr' | 'rtl' |
inherited | Direction forwarded to the internal calendar. |
show-persian-number |
boolean |
locale based | Displays Persian digits while .value remains English digits. |
size |
'xs' | 'sm' | 'md' | 'lg' | 'xl' |
md style defaults |
Visual size forwarded to the internal jb-input. |
autocomplete |
string |
browser default | Forwarded to the internal jb-input. |
readonly |
boolean |
device based | Forwarded to the internal jb-input; mobile devices become readonly to favor the picker. |
| name | type | readonly | description |
|---|---|---|---|
value |
string |
no | Canonical value submitted with forms. Set with string, Date, or null. |
valueInDate |
Date | null |
yes | Current complete value as a JavaScript Date, or null when empty/incomplete. |
inputValue |
string |
yes | Visible typed text in YYYY/MM/DD display format. |
inputType |
'GREGORIAN' | 'JALALI' |
no | Date system used by the input UI and calendar. |
valueType |
'GREGORIAN' | 'JALALI' | 'TIME_STAMP' |
no | Date system or timestamp mode used for .value. |
valueFormat |
string |
yes | Current value format. Change it with setFormat(). |
dateRestrictions |
{ min: Date | null; max: Date | null } |
no | Runtime min/max restrictions used by validation and calendar. |
validation |
ValidationHelper<ValidationValue> |
yes | Validation helper from jb-validation; set validation.list for custom rules. |
isAutoValidationDisabled |
boolean |
no | Disables automatic validation when true. |
required |
boolean |
no | Enables required validation. |
disabled |
boolean |
no | Enables or disables the internal input. |
showPersianNumber |
boolean |
no | Displays Persian digits while .value remains English digits. |
showCalendar |
boolean |
no | Opens or closes the internal calendar popover. |
placeholder |
string | null |
no | Placeholder shown while empty. |
form |
HTMLFormElement | null |
yes | Associated form from ElementInternals. |
isDirty |
boolean |
yes | true when current .value differs from initialValue. |
validationMessage |
string |
yes | Current validation message from ElementInternals. |
yearValue / monthValue / dayValue |
number | null |
yes | Date parts in the configured valueType. |
yearDisplayValue / monthDisplayValue / dayDisplayValue |
number | null |
yes | Date parts in the configured inputType. |
elements |
ElementsObject |
no | Internal input, calendar, popover, and calendarTriggerButton for advanced integrations. |
| name | returns | description |
|---|---|---|
setFormat(newFormat) |
void |
Sets the value format used for .value, min, and max. |
setMinDate(minDate) |
void |
Sets or clears the minimum accepted date. Accepts string, Date, or null. |
setMaxDate(maxDate) |
void |
Sets or clears the maximum accepted date. Accepts string, Date, or null. |
setMonthList(inputType, monthName) |
void |
Overrides month labels for GREGORIAN or JALALI. |
setCalendarDefaultDateView(year, month, dateType?) |
void |
Sets the year/month shown when the value is empty. |
getDateValue(type?) |
string |
Returns current value in GREGORIAN, JALALI, or TIME_STAMP mode. |
focus() |
void |
Focuses the internal input and opens the calendar. |
setSelectionRange(start, end, direction?) |
void |
Forwards selection range to the internal input. |
checkValidity() |
boolean |
Runs validation without showing the error message. Dispatches invalid when invalid. |
reportValidity() |
boolean |
Runs validation and shows the first error message. Dispatches invalid when invalid. |
clearValidationError() |
void |
Clears the visible validation error. |
triggerInputValidation(showError?) |
ValidationResult | undefined |
Deprecated; use checkValidity(), reportValidity(), or validation.checkValidity(). |
| event | description |
|---|---|
load |
Dispatched from connectedCallback before property initialization. |
init |
Dispatched after internal components are defined and the initial value is applied. |
beforeinput |
Cancelable event dispatched before typed input is applied. |
input |
Dispatched after user typing changes the visible input text. |
change |
Dispatched when the committed date value changes after blur or calendar selection. Canceling it reverts the date. |
select |
Dispatched when the user selects a date from the calendar. |
focus |
Re-dispatched when the internal input receives focus. |
blur |
Re-dispatched when the internal input loses focus. |
keydown |
Re-dispatched from the internal input. ArrowUp/ArrowDown change the selected date part. |
keyup |
Re-dispatched from the internal input after the value object is updated. |
keypress |
Re-dispatched from the internal input. |
invalid |
Dispatched when checkValidity() or reportValidity() fails. |
input-type controls what users see and edit. value-type controls what developers receive from .value.
<!-- 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.
const dateInput = document.querySelector('jb-date-input');
dateInput.value = '2024-01-15T00:00:00.000Z';
console.log(dateInput.value);
console.log(dateInput.valueInDate);
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. valueInDate returns null while the date is empty or incomplete.
The default format is compatible with Date.prototype.toISOString():
<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:
<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. Use validation.list for custom rules.
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.
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.
For app-wide locale, calendar, and numbering-system setup, configure jb-core/i18n.
| slot | description |
|---|---|
inline-start-section |
Content rendered at the start of the internal input box. |
inline-end-section |
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-section">Birthday</span>
<span slot="inline-end-section">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.
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.
const dateInput = document.querySelector('jb-date-input');
dateInput.elements.popover.overflowHandler = 'SLIDE';
dateInput.elements.popover.overflowDom = document.querySelector('.modal-body');| 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. |
| CSS variable name | description |
|---|---|
--jb-date-input-margin |
Host component margin. |
--jb-date-input-calendar-trigger-display |
Calendar trigger display value. |
--jb-date-input-calendar-trigger-width |
Calendar trigger width. |
--jb-date-input-calendar-trigger-height |
Calendar trigger height. |
--jb-date-input-calendar-icon-color |
Calendar icon color. |
--jb-date-input-calendar-icon-color-active |
Calendar icon color while calendar is open. |
Internal jb-input, jb-calendar, and jb-popover CSS variables also apply.
jb-date-input {
--jb-date-input-margin: 16px 0;
--jb-date-input-calendar-icon-color: #2563eb;
}
jb-date-input::part(input) {
--jb-input-border-radius: 8px;
}
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 Storybook docs for a complete example.
- 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.valueInDatewhen a JavaScriptDateis needed. - Use
show-persian-numberonly for display;.valueremains English digits. - Use
inline-start-section,inline-end-section, andcalendar-trigger-iconslots. Do not usestart-sectionorend-sectiondirectly 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.