# certara-datepicker

Derived from [datepicker-plus](https://github.com/solomancode/datepicker-plus) (MIT License, Copyright (c) 2018). See [NOTICE.md](../../../NOTICE.md) in the package root for the full attribution and license text.

Accessible date/time control that works as a form polyfill: segmented/native inputs plus a popover calendar. Use `mode` to choose `date`, `month`, `datetime`, `time`, or `range`. Integrates with `<certara-form-group>` for labels and validation.

## Selection (`value`)

Bind the current selection with **`value`** prop. Formats by mode:

- `date`: `YYYY-MM-DD`
- `month`: `YYYY-MM`
- `datetime`: `YYYY-MM-DDTHH:mm`
- `time`: `HH:mm`
- `range`: `YYYY-MM-DD,YYYY-MM-DD` (start,end)

Set it as an attribute or from script:

```html
<certara-datepicker mode="date" value="2026-07-13"></certara-datepicker>
```

```js
customElements.whenDefined('certara-datepicker').then(() => {
  const el = document.getElementById('event-date');
  el.value = '2026-07-13';
  // range example: el.value = '2026-07-01,2026-07-04';
});
```

If `value` is empty, you can seed an initial calendar selection with **`config.selected`** (`DateString[]`; range needs at least two dates). Prefer `value` for forms and controlled updates; when both are set, **`value` wins**.

```js
el.config = {
  selected: ['2026-07-01', '2026-07-04'],
};
```

### Angular forms

With `certara-ui-angular`, `certara-datepicker` works with `[(ngModel)]` and reactive forms (`formControlName`) out of the box. The bound control value is the same per-mode ISO string documented above &mdash; for `range` that is a single `"start,end"` string, not an array. `valueFormat="display"` only changes the trigger's visible text; the Angular form value stays ISO.

```html
<certara-datepicker mode="range" [(ngModel)]="dateRange"></certara-datepicker>
<!-- dateRange is the string "2026-07-01,2026-07-04" -->
```

## Control shape and calendar config

- **`mode`** &mdash; chooses the control shape (`date | month | datetime | time | range`). Prefer this over `config.selectMode` (select mode is derived from `mode`).
- **`config`** &mdash; calendar behavior only: navigable window, presets, disabled days, i18n, etc. (see below). Keep `yearsBack` / `yearsForward` modest; very large ranges are unfolded into day cells and can warn or hurt performance.

Calendar config dates use **DateString** (`YYYY-MM-DD`).

## `DatepickerConfig`

Object assigned to the `config` prop.

| Field                        | Purpose                                                                                     |
| ---------------------------- | ------------------------------------------------------------------------------------------- |
| `viewRange`                  | `[start, end]` DateStrings for navigable months (default: current month)                    |
| `yearsBack` / `yearsForward` | Compute `viewRange` from today when set (overrides an explicit `viewRange`)                 |
| `disabled`                   | DateStrings that cannot be selected                                                         |
| `selected`                   | Optional init when `value` is empty (prefer `value` for form binding)                       |
| `monthsToShow`               | Side-by-side months in the popover (default `2`)                                            |
| `showNavigation`             | Prev/next month controls (default `true`)                                                   |
| `weekHeader`                 | `'per-month'` (each month renders its own weekday header)                                   |
| `presets`                    | Range sidebar options `{ id, label }[]` (defaults include Today, Last 7 Days, Custom, etc.) |
| `selectScopeSize`            | When greater than 0, limits how far a second date can be from the first                     |
| `i18n`                       | `weekDays`, `months`, `dateSeparator`, `timeSeparator`                                      |
| `stylesheetUrl`              | Optional stylesheet injected into the calendar                                              |

## Usage

### Date with a value

```html
<certara-datepicker mode="date" name="eventDate" value="2026-07-13" aria-label="Event date"></certara-datepicker>
```

### Range with config

```html
<certara-datepicker id="range" mode="range" name="dateRange" aria-label="Date range"></certara-datepicker>

<script>
  customElements.whenDefined('certara-datepicker').then(() => {
    document.getElementById('range').config = {
      yearsBack: 2,
      yearsForward: 1,
      monthsToShow: 2,
      showNavigation: true,
      weekHeader: 'per-month',
    };
  });
</script>
```

### Disabled dates and i18n

```html
<certara-datepicker id="holiday-picker" mode="date" aria-label="Holiday"></certara-datepicker>

<script>
  customElements.whenDefined('certara-datepicker').then(() => {
    document.getElementById('holiday-picker').config = {
      disabled: ['2026-12-25', '2026-01-01'],
      i18n: {
        dateSeparator: '/',
        months: [
          { name: 'January', abbr: 'Jan' },
          /* remaining months */
        ],
      },
    };
  });
</script>
```

### Restricting the allowed range (`min` / `max` / `step`)

`min` and `max` (ISO date or datetime attributes) bound the selectable value. Out-of-range days are disabled in the calendar and the composed value is validated (for `range`, both ends are checked). `step` (seconds) is applied to the time input in `time` / `datetime` modes.

```html
<certara-datepicker
  mode="date"
  name="eventDate"
  min="2026-07-01"
  max="2026-07-31"
  aria-label="Event date in July"
></certara-datepicker>

<!-- 15-minute increments on the time control -->
<certara-datepicker mode="time" name="slot" step="900" aria-label="Time slot"></certara-datepicker>
```

<!-- Auto Generated Below -->


## Properties

| Property      | Attribute      | Description                                                                                                                                                          | Type                                                   | Default          |
| ------------- | -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ | ---------------- |
| `ariaLabel`   | `aria-label`   | Accessible label when not inside a form-group                                                                                                                        | `string`                                               | `undefined`      |
| `config`      | --             | Datepicker configuration object (calendar layout, presets, i18n, etc.).                                                                                              | `DatepickerConfig`                                     | `DEFAULT_CONFIG` |
| `disabled`    | `disabled`     | Disable the control                                                                                                                                                  | `boolean`                                              | `false`          |
| `endName`     | `end-name`     | Hidden field name for range end (defaults to name.end)                                                                                                               | `string`                                               | `undefined`      |
| `max`         | `max`          | Maximum allowed value (ISO date or datetime string)                                                                                                                  | `string`                                               | `undefined`      |
| `min`         | `min`          | Minimum allowed value (ISO date or datetime string)                                                                                                                  | `string`                                               | `undefined`      |
| `mode`        | `mode`         | Control shape: date, month, datetime, or range                                                                                                                       | `"date" \| "datetime" \| "month" \| "range" \| "time"` | `'range'`        |
| `name`        | `name`         | Form field name (hidden ISO field; range uses name.start / name.end)                                                                                                 | `string`                                               | `undefined`      |
| `placement`   | `placement`    | Preferred vertical placement for the popover panel                                                                                                                   | `"bottom-start" \| "top-start"`                        | `'bottom-start'` |
| `position`    | `position`     | CSS positioning strategy for the popover panel                                                                                                                       | `"absolute" \| "fixed"`                                | `'absolute'`     |
| `readonly`    | `readonly`     | Read-only segments (indicator still opens popover)                                                                                                                   | `boolean`                                              | `false`          |
| `required`    | `required`     | Whether the field is required                                                                                                                                        | `boolean`                                              | `false`          |
| `startName`   | `start-name`   | Hidden field name for range start (defaults to name.start)                                                                                                           | `string`                                               | `undefined`      |
| `step`        | `step`         | Time step in seconds (datetime mode)                                                                                                                                 | `number`                                               | `undefined`      |
| `value`       | `value`        | Current value (ISO). Reflected as the value attribute.  date: YYYY-MM-DD \| month: YYYY-MM \| datetime: YYYY-MM-DDTHH:mm time: HH:mm \| range: YYYY-MM-DD,YYYY-MM-DD | `string`                                               | `''`             |
| `valueFormat` | `value-format` | Format for the trigger / form value                                                                                                                                  | `"display" \| "iso"`                                   | `'display'`      |
| `variant`     | `variant`      | Visual variant of the control                                                                                                                                        | `"default" \| "link"`                                  | `'default'`      |


## Events

| Event                             | Description                                                                                    | Type                              |
| --------------------------------- | ---------------------------------------------------------------------------------------------- | --------------------------------- |
| `certaraChange`                   | emits when the composed ISO value changes (certara-ui convention)                              | `CustomEvent<string>`             |
| `certaraDatepickerDateSelect`     | Emits when a date is selected. Use it to react to date selected                                | `CustomEvent<string[]>`           |
| `certaraDatepickerDeselect`       | Emits when a date is deselected. Use it to react to date deselected                            | `CustomEvent<string[]>`           |
| `certaraDatepickerHighlight`      | emits when a date or more is highlighted as potential select candidate                         | `CustomEvent<string[]>`           |
| `certaraDatepickerHighlightClear` | emits when date highlight is cleared after dates deselect                                      | `CustomEvent<void>`               |
| `certaraDatepickerPopoverToggle`  | emits when the popover panel opens or closes                                                   | `CustomEvent<{ open: boolean; }>` |
| `certaraDatepickerRangeSelect`    | emits when a complete date range is selected use it to react to a complete date range selected | `CustomEvent<string[]>`           |
| `certaraFormControlError`         | emits consolidated validation error for certara-form-group                                     | `CustomEvent<string>`             |


## Dependencies

### Depends on

- [certara-button](../button)
- [certara-icon](../icon)

### Graph
```mermaid
graph TD;
  certara-datepicker --> certara-button
  certara-datepicker --> certara-icon
  certara-button --> certara-icon
  style certara-datepicker fill:#f9f,stroke:#333,stroke-width:4px
```

----------------------------------------------


