# jb-calendar

[![Published on webcomponents.org](https://img.shields.io/badge/webcomponents.org-published-blue.svg)](https://www.webcomponents.org/element/jb-calendar)
[![GitHub license](https://img.shields.io/badge/license-MIT-brightgreen.svg)](https://raw.githubusercontent.com/javadbat/jb-calendar/main/LICENSE)
[![NPM Version](https://img.shields.io/npm/v/jb-calendar)](https://www.npmjs.com/package/jb-calendar)
![GitHub Created At](https://img.shields.io/github/created-at/javadbat/jb-calendar)

Jalali and Gregorian calendar interface web component.

- Supports Jalali and Gregorian date selection.
- Supports day, month, and year selection views.
- Supports min/max date restrictions.
- Supports Persian digit rendering.
- Supports RTL and LTR layout.
- Customizable with CSS variables.

## When to use

Use `jb-calendar` when you need an inline calendar picker UI.

Use [`jb-date-input`](https://github.com/javadbat/jb-date-input) when you need a full date input field with label, validation, text entry, and form input behavior.

## Demo

- [Demo](https://javadbat.github.io/design-system/?path=/docs/components-jbcalendar)
- [CodePen](https://codepen.io/javadbat/pen/poRKYEY)

## Using With JS Frameworks

<a href="https://github.com/javadbat/jb-calendar/tree/main/react" target="_blank" rel="noopener noreferrer"><img src="https://img.shields.io/badge/React.js-jb--calendar%2Freact-000.svg?logo=react&logoColor=%2361DAFB" height="30" /></a>

Other integrations: <a href="https://javadbat.github.io/design-system/?path=/docs/getting-started-framework-integration--docs#angular" target="_blank" rel="noopener noreferrer">Angular</a> · <a href="https://javadbat.github.io/design-system/?path=/docs/getting-started-framework-integration--docs#vue" target="_blank" rel="noopener noreferrer">Vue</a> · <a href="https://javadbat.github.io/design-system/?path=/docs/getting-started-framework-integration--docs#nuxt" target="_blank" rel="noopener noreferrer">Nuxt</a> · <a href="https://javadbat.github.io/design-system/?path=/docs/getting-started-framework-integration--docs#svelte" target="_blank" rel="noopener noreferrer">Svelte</a> · <a href="https://javadbat.github.io/design-system/?path=/docs/getting-started-framework-integration--docs#sveltekit" target="_blank" rel="noopener noreferrer">SvelteKit</a> · <a href="https://javadbat.github.io/design-system/?path=/docs/getting-started-framework-integration--docs#solidjs" target="_blank" rel="noopener noreferrer">SolidJS</a> · <a href="https://javadbat.github.io/design-system/?path=/docs/getting-started-framework-integration--docs#lit" target="_blank" rel="noopener noreferrer">Lit</a> · <a href="https://javadbat.github.io/design-system/?path=/docs/getting-started-framework-integration--docs#nextjs" target="_blank" rel="noopener noreferrer">Next.js</a> · <a href="https://javadbat.github.io/design-system/?path=/docs/getting-started-framework-integration--docs#astro" target="_blank" rel="noopener noreferrer">Astro</a> · <a href="https://javadbat.github.io/design-system/?path=/docs/getting-started-framework-integration--docs#blazor" target="_blank" rel="noopener noreferrer">Blazor</a> · <a href="https://javadbat.github.io/design-system/?path=/docs/getting-started-framework-integration--docs#server-rendered-templates" target="_blank" rel="noopener noreferrer">Server-rendered templates</a> · <a href="https://javadbat.github.io/design-system/?path=/docs/getting-started-framework-integration--docs#wordpress" target="_blank" rel="noopener noreferrer">WordPress</a> · <a href="https://javadbat.github.io/design-system/?path=/docs/getting-started-framework-integration--docs#alpinejs-and-htmx" target="_blank" rel="noopener noreferrer">Alpine.js and HTMX</a>

## Installation

```sh
npm install jb-calendar
```

```js
import 'jb-calendar';
```

```html
<jb-calendar></jb-calendar>
```

## API reference

### Attributes

`jb-calendar` does not currently define public HTML attributes. Configure it with properties and methods.

### Properties

| name | type | readonly | description |
| --- | --- | --- | --- |
| `value` | `JBCalendarValue` | no | Selected date in the active `inputType`. Set `year`, `month`, and `day` together. [Demo](https://javadbat.github.io/design-system/?path=/story/components-jbcalendar--value-test) |
| `inputType` | `'JALALI' \| 'GREGORIAN'` | no | Calendar date system used for input and displayed values. [Jalali Demo](https://javadbat.github.io/design-system/?path=/story/components-jbcalendar--jalali) · [Gregorian Demo](https://javadbat.github.io/design-system/?path=/story/components-jbcalendar--gregorian) |
| `activeSection` | `'DAY' \| 'MONTH' \| 'YEAR'` | no | Visible selection section. |
| `showPersianNumber` | `boolean` | no | Renders numbers with Persian digits when `true`. [Demo](https://javadbat.github.io/design-system/?path=/story/components-jbcalendar--persian-numbers) |
| `direction` | `'rtl' \| 'ltr'` | no | Calendar layout direction. Leave unset to use computed CSS direction. [RTL Demo](https://javadbat.github.io/design-system/?path=/story/components-jbcalendar--right-to-left) |
| `cssDirection` | `'rtl' \| 'ltr'` | yes | Computed CSS direction of the host. |
| `defaultCalendarData` | `{ jalali, gregorian }` | no | Default visible year/month used when no date is selected. [Demo](https://javadbat.github.io/design-system/?path=/story/components-jbcalendar--default-visible-month) |
| `dateRestrictions` | `{ min: Date \| null; max: Date \| null }` | no | Mutable min/max date restriction object. Set `dateRestrictions.min` and `dateRestrictions.max`. [Demo](https://javadbat.github.io/design-system/?path=/story/components-jbcalendar--min-max) |
| `data` | `JBCalendarData` | no | Internal visible calendar state: `selectedYear`, `selectedMonth`, and `yearSelectionRange`. |

```ts
type JBCalendarValue = {
  year: number | null;
  month: number | null;
  day: number | null;
};
```

### Methods

| name | returns | description |
| --- | --- | --- |
| `select(year, month, day)` | `void` | Selects a date in the current `inputType` and updates `value`. [Demo](https://javadbat.github.io/design-system/?path=/story/components-jbcalendar--imperative-selection) |
| `selectToday()` | `void` | Selects today in the current `inputType`. [Demo](https://javadbat.github.io/design-system/?path=/story/components-jbcalendar--imperative-selection) |
| `setMonthList(inputType, monthList)` | `void` | Replaces the 12 month labels for `JALALI` or `GREGORIAN`. [Demo](https://javadbat.github.io/design-system/?path=/story/components-jbcalendar--custom-month-name) |
| `setupStyleBaseOnCssDirection(dir?)` | `void` | Refreshes direction-sensitive layout classes from `dir` or computed host direction. [Demo](https://javadbat.github.io/design-system/?path=/story/components-jbcalendar--right-to-left) |
| `checkIsDayDisable(dayDate)` | `{ min; max; isAllValid }` | Checks whether a `Date` is valid against min/max restrictions. [Demo](https://javadbat.github.io/design-system/?path=/story/components-jbcalendar--min-max) |

### Events

| event | detail | description |
| --- | --- | --- |
| `init` | none | Dispatched during construction after default properties are initialized. |
| `load` | none | Dispatched from `connectedCallback` before layout initialization. |
| `select` | none | Dispatched when the user selects an enabled day. Read `event.target.value`. [Demo](https://javadbat.github.io/design-system/?path=/story/components-jbcalendar--value-test) |

```js
const calendar = document.querySelector('jb-calendar');

calendar.addEventListener('select', (event) => {
  console.log(event.target.value);
});
```

## Select a date

Use `select()` or set `value` to choose a date programmatically; see the [imperative selection Demo](https://javadbat.github.io/design-system/?path=/story/components-jbcalendar--imperative-selection). User selection events expose the date through `event.target.value`; see the [selection event Demo](https://javadbat.github.io/design-system/?path=/story/components-jbcalendar--value-test).

```js
const calendar = document.querySelector('jb-calendar');

calendar.select(1402, 8, 24);
console.log(calendar.value); // { year: 1402, month: 8, day: 24 }
```

You can also set `value` directly:

```js
calendar.value = {
  year: 2026,
  month: 6,
  day: 16,
};
```

## Jalali and Gregorian input

Set `inputType` to `JALALI` or `GREGORIAN`; see the [Jalali Demo](https://javadbat.github.io/design-system/?path=/story/components-jbcalendar--jalali) or [Gregorian Demo](https://javadbat.github.io/design-system/?path=/story/components-jbcalendar--gregorian).

```js
const calendar = document.querySelector('jb-calendar');

calendar.inputType = 'GREGORIAN';
calendar.select(2026, 6, 16);
```

## Default visible month

`defaultCalendarData` controls the year and month shown before the user selects a date. Configure it before connecting the element so the initial layout uses the supplied month.

`defaultCalendarData` configuration is shown in the [configured initial-month Demo](https://javadbat.github.io/design-system/?path=/story/components-jbcalendar--default-visible-month).

```js
const calendar = document.createElement('jb-calendar');

calendar.defaultCalendarData = {
  gregorian: {
    year: 2026,
    month: 6,
  },
  jalali: {
    year: 1405,
    month: 3,
  },
};

document.body.append(calendar);
```

## Persian numbers

Set `showPersianNumber` to render Persian digits; see the [Persian-digit Demo](https://javadbat.github.io/design-system/?path=/story/components-jbcalendar--persian-numbers).

```js
document.querySelector('jb-calendar').showPersianNumber = true;
```

## Min and max restrictions

Set restrictions with JavaScript `Date` objects. The dates are compared against the currently rendered date system internally; see the [restricted date-range Demo](https://javadbat.github.io/design-system/?path=/story/components-jbcalendar--min-max).

```js
const calendar = document.querySelector('jb-calendar');

calendar.dateRestrictions.min = new Date(2026, 0, 1);
calendar.dateRestrictions.max = new Date(2026, 11, 31);
```

## Change month labels

Use `setMonthList` with exactly 12 labels; see the [custom Jalali month-label Demo](https://javadbat.github.io/design-system/?path=/story/components-jbcalendar--custom-month-name).

```js
const calendar = document.querySelector('jb-calendar');

calendar.setMonthList('JALALI', [
  'حمل',
  'ثور',
  'جوزا',
  'سرطان',
  'اسد',
  'سنبله',
  'میزان',
  'عقرب',
  'قوس',
  'جدی',
  'دلو',
  'حوت',
]);

calendar.setMonthList('GREGORIAN', [
  '1',
  '2',
  '3',
  '4',
  '5',
  '6',
  '7',
  '8',
  '9',
  '10',
  '11',
  '12',
]);
```

## Direction

The component reads CSS direction when it mounts. If your app changes direction after mount, call `setupStyleBaseOnCssDirection()` or set `direction`; see the [RTL Jalali Demo](https://javadbat.github.io/design-system/?path=/story/components-jbcalendar--right-to-left) or [RTL Gregorian Demo](https://javadbat.github.io/design-system/?path=/story/components-jbcalendar--rtl-gregorian).

```js
const calendar = document.querySelector('jb-calendar');

calendar.setupStyleBaseOnCssDirection();
calendar.setupStyleBaseOnCssDirection('ltr');
calendar.direction = 'rtl';
```

## Slots and CSS parts

`jb-calendar` does not currently expose public slots. It exposes CSS parts for navigator, day, month, year, and swipe-up hint internals; see [Styling](https://javadbat.github.io/design-system/?path=/docs/components-jbcalendar-styling) and the [CSS-part styling Demo](https://javadbat.github.io/design-system/?path=/story/components-jbcalendar-style--gallery).

## Custom style

Set CSS variables in the parent scope of the component.

For complete styling guidance, live examples, and copyable style recipes, see [Styling](https://javadbat.github.io/design-system/?path=/docs/components-jbcalendar-styling) and the [style gallery Demo](https://javadbat.github.io/design-system/?path=/story/components-jbcalendar-style--gallery).

```css
jb-calendar {
  --jb-calendar-day-bg-color-selected: var(--jb-primary);
  --jb-calendar-day-color-selected: var(--jb-white);
}
```

## Accessibility notes

- Navigator buttons have localized `title` attributes; inspect the interactive calendar [Demo](https://javadbat.github.io/design-system/?path=/story/components-jbcalendar--normal).
- Day, month, and year choices are rendered as clickable elements inside shadow DOM.
- The component is an inline calendar UI, not a form-associated input. Use `jb-date-input` when native form input behavior is required.

## Dependencies

`jb-calendar` uses [`date-fns`](https://github.com/date-fns/date-fns) and [`date-fns-jalali`](https://github.com/date-fns-jalali/date-fns-jalali) for Gregorian and Jalali date calculations.

## Related Docs

- See [`jb-calendar/react`](https://github.com/javadbat/jb-calendar/tree/main/react) if you want to use this component in React.
- See [All JB Design System Component List](https://javadbat.github.io/design-system/) for more components.
- Use [Contribution Guide](https://github.com/javadbat/design-system/blob/main/docs/contribution-guide.md) if you want to contribute to this component.

## AI agent notes

- Import `jb-calendar` once before using `<jb-calendar>`.
- Configure the component with properties and methods; it does not expose public HTML attributes.
- Use `inputType = 'JALALI'` or `inputType = 'GREGORIAN'` before setting/selecting values when the date system matters.
- Listen to `select` and read `event.target.value`; the event does not include selected date data in `event.detail`.
- Use `dateRestrictions.min` and `dateRestrictions.max` with JavaScript `Date` objects.
- Use `jb-date-input` instead of `jb-calendar` when a form-associated date input field is needed.
- This package includes [`custom-elements.json`](./custom-elements.json) and points to it with the package.json `customElements` field. The field is documented by the Custom Elements Manifest project in [Referencing manifests from npm packages](https://github.com/webcomponents/custom-elements-manifest#referencing-manifests-from-npm-packages).
- In `custom-elements.json`, `exports.kind: "js"` describes the JavaScript/TypeScript class export and `exports.kind: "custom-element-definition"` maps the `jb-calendar` tag name to that class.
