@wkly/datetime-picker 11.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.
Files changed (53) hide show
  1. package/API.md +112 -0
  2. package/LICENSE +21 -0
  3. package/README.md +402 -0
  4. package/bundles/wkly-datetime-picker-cdk-overlay.umd.js +653 -0
  5. package/bundles/wkly-datetime-picker-cdk-overlay.umd.js.map +1 -0
  6. package/bundles/wkly-datetime-picker-cdk-overlay.umd.min.js +2 -0
  7. package/bundles/wkly-datetime-picker-cdk-overlay.umd.min.js.map +1 -0
  8. package/bundles/wkly-datetime-picker.umd.js +2354 -0
  9. package/bundles/wkly-datetime-picker.umd.js.map +1 -0
  10. package/bundles/wkly-datetime-picker.umd.min.js +2 -0
  11. package/bundles/wkly-datetime-picker.umd.min.js.map +1 -0
  12. package/cdk-overlay/package.json +11 -0
  13. package/cdk-overlay/public-api.d.ts +19 -0
  14. package/cdk-overlay/public-api.ngfactory.d.ts +3 -0
  15. package/cdk-overlay/wkly-datetime-picker-cdk-overlay.d.ts +4 -0
  16. package/cdk-overlay/wkly-datetime-picker-cdk-overlay.metadata.json +1 -0
  17. package/config.d.ts +46 -0
  18. package/esm2015/cdk-overlay/public-api.js +127 -0
  19. package/esm2015/cdk-overlay/public-api.ngfactory.js +19 -0
  20. package/esm2015/cdk-overlay/public-api.ngsummary.json +1 -0
  21. package/esm2015/cdk-overlay/wkly-datetime-picker-cdk-overlay.js +5 -0
  22. package/esm2015/cdk-overlay/wkly-datetime-picker-cdk-overlay.ngsummary.json +1 -0
  23. package/esm2015/config.js +241 -0
  24. package/esm2015/config.ngsummary.json +1 -0
  25. package/esm2015/field.component.css.shim.ngstyle.js +9 -0
  26. package/esm2015/field.component.js +240 -0
  27. package/esm2015/field.component.ngfactory.js +52 -0
  28. package/esm2015/field.component.ngsummary.json +1 -0
  29. package/esm2015/picker.component.js +929 -0
  30. package/esm2015/picker.component.ngfactory.js +137 -0
  31. package/esm2015/picker.component.ngsummary.json +1 -0
  32. package/esm2015/presentation.js +295 -0
  33. package/esm2015/presentation.ngsummary.json +1 -0
  34. package/esm2015/public-api.js +24 -0
  35. package/esm2015/public-api.ngfactory.js +13 -0
  36. package/esm2015/public-api.ngsummary.json +1 -0
  37. package/esm2015/wkly-datetime-picker.js +5 -0
  38. package/esm2015/wkly-datetime-picker.ngsummary.json +1 -0
  39. package/fesm2015/wkly-datetime-picker-cdk-overlay.js +131 -0
  40. package/fesm2015/wkly-datetime-picker-cdk-overlay.js.map +1 -0
  41. package/fesm2015/wkly-datetime-picker.js +1713 -0
  42. package/fesm2015/wkly-datetime-picker.js.map +1 -0
  43. package/field.component.css.shim.ngstyle.d.ts +1 -0
  44. package/field.component.d.ts +41 -0
  45. package/field.component.ngfactory.d.ts +1 -0
  46. package/package.json +45 -0
  47. package/picker.component.d.ts +130 -0
  48. package/picker.component.ngfactory.d.ts +1 -0
  49. package/presentation.d.ts +57 -0
  50. package/public-api.d.ts +7 -0
  51. package/public-api.ngfactory.d.ts +3 -0
  52. package/wkly-datetime-picker.d.ts +5 -0
  53. package/wkly-datetime-picker.metadata.json +1 -0
package/API.md ADDED
@@ -0,0 +1,112 @@
1
+ # Public API
2
+
3
+ The published picker uses `@wkly/datetime-picker@N.x.x` for Angular N, with separate version lines for Angular 11–22. The Angular components, module, forms integration, and optional CDK entry point come from the selected version. The `wkly-datetime-picker` source project provides Angular-independent presentation configuration, translations, input names, and CSS; date adapters live in `wkly-datetime-picker.adapters`.
4
+
5
+ All APIs are exported from public package entry points. Emitted TypeScript declarations contain complete signatures and readonly contracts.
6
+
7
+ ## Core
8
+
9
+ `EpochDay` and `AbsoluteWeek` are safe integer coordinate aliases. `WklyWeekOffset` is `0..6`. `integer(value)` validates safe integers. `floorDiv(a,b)` and `floorMod(a,b)` provide floor arithmetic for positive integer divisors. Invalid inputs and unsafe results throw `RangeError`.
10
+
11
+ `absoluteWeekOf(day,offset)` and `firstEpochDayOf(week,offset)` map coordinates in constant time. `generateWeek(week,offset)` returns a frozen `WklyWeek` with `absoluteWeek`, `weekOffset`, and a frozen seven-element `epochDays` tuple.
12
+
13
+ `createWeekGenerator(options?: WklyWeekGeneratorOptions)` returns `WklyWeekGenerator`: readonly offset/cache size, `getWeek(week)`, and `clearCache()`. Defaults are offset 0 and cache size 256; zero disables caching. Cache eviction is LRU.
14
+
15
+ `WklyViewportState` describes anchor/first/last weeks, focused day, active range endpoint, and calendar/manual view. `orderedRange(start,end,compare)` returns a frozen ascending pair without modifying endpoints.
16
+
17
+ ## Adapters
18
+
19
+ `WklyGregorianCalendarAdapter(locale='en-US')` implements proleptic Gregorian years 0–9999 using integer arithmetic. Low-level `gregorianDay(year,month,day)` and `gregorianDate(epochDay)` expose raw conversion; use adapter methods for date and supported-range validation. `pad(number,width=2)` is the codec's decimal padding helper.
20
+
21
+ `WklyCalendarAbstractAdapter` implements the `WklyCalendarAdapter` contract with abstract calendar operations and protected `getDateTimeFormatter(options?, locale?)` and `getNumberFormatter(options?, locale?)` helpers. Each adapter instance reuses formatters for matching locale and options. Custom adapters can extend this class or implement `WklyCalendarAdapter` directly.
22
+
23
+ Source-only examples are [`ShowcaseHebrewCalendarAdapter(locale='he-IL')`](../projects/wkly-datetime-picker.showcase/src/hebrew-adapter.ts), requiring `@hebcal/core`, and [`ShowcaseHijriCalendarAdapter(locale='ar-EG')`](../projects/wkly-datetime-picker.showcase/src/hijri-adapter.ts), requiring only WKLY and `Intl`. Neither is exported by an npm package. Both support Gregorian UTC 1900-01-01..2100-12-31 inclusive; Hijri uses the tabular civil `islamic-civil` variant and month codes `M01..M12`. See [calendar rules](CORE-AND-ADAPTERS.md). Viewport presets handle partial boundary months without requiring conversion of unsupported dates.
24
+
25
+ `calendarMonthBounds(adapter, epochDay)` in the shared presentation package returns a frozen inclusive pair of full-month epoch-day coordinates from a supported anchor. The coordinates may extend beyond the adapter's supported interval; viewport rendering applies the adapter bounds separately. It never asks the adapter to convert an unsupported month edge.
26
+
27
+ `WklyCalendarDate` has calendarId, year, one-based ordinal month, stable monthCode, day, and optional era. `WklyCalendarMonth` has month, monthCode, and label. `WklyCalendarDateError` has code, optional field, and messageKey.
28
+
29
+ | `WklyCalendarAdapter` member | Contract |
30
+ | --- | --- |
31
+ | calendarId | Stable calendar identity |
32
+ | supportedEpochDayRange, supportedYearRange | Inclusive supported bounds |
33
+ | validateDate(date) | Errors without correcting fields |
34
+ | dateToEpochDay(date), epochDayToDate(day) | Strict reversible conversions |
35
+ | getMonths(year,era?) | Ordered months with stable identities |
36
+ | getDaysInMonth(year,monthCode,era?) | Valid day count |
37
+ | addMonths(date,amount), addYears(date,amount) | Preserve impossible day drafts and month identity |
38
+ | formatDay, formatMonth, formatYear, formatDate, formatAccessibleDate | Localized date fields and accessible text |
39
+ | formatWeekday(day,width) | Short/long weekday |
40
+ | formatWeekLabel(week,mode) | Locale/ISO/absolute/hidden row label |
41
+ | normalizeDigits(input) | Recognized decimal digits to ASCII; other characters ignored |
42
+
43
+ `decodeIso(string)` returns `WklyDateTime {epochDay,hour,minute,second}` and rejects noncanonical input. `encodeIso(value,mode='datetime',showSeconds=false)` applies hidden-field normalization. `normalizeDigits(input)` is also a standalone helper. `resolveWeekOffset(locale,explicit?,application?,firstDay?)` applies precedence; optional locale firstDay uses Sunday=0 through Saturday=6.
44
+
45
+ `validateSelection(value,config,adapter)` returns readonly `WklyValidationError[]` without repairing the selection. `WklySelectionConfig` accepts mode, showSeconds, minuteStep, secondStep, min, max, required, disabled predicates, allowRangeAcrossDisabled, rangeValidator, and additional validators. `WklyValidationException.errors` exposes conversion failures. `error(code,rejectedValue?,field?,endpoint?)` constructs the stable error object.
46
+
47
+ | Public type | Meaning |
48
+ | --- | --- |
49
+ | WklySelectionMode | datetime, date, time, and their -range variants |
50
+ | WklyIsoString | Canonical UTC ISO string |
51
+ | WklyRangeValue | Readonly pair of strings |
52
+ | WklyPickerValue | String, range, or null |
53
+ | WklyEndpoint | single, start, end |
54
+ | WklyDatePredicateContext | mode, endpoint, calendarDate |
55
+ | WklyTimePredicateContext | mode, endpoint |
56
+ | WklyDisabledDatePredicate | (epochDay,context) => boolean |
57
+ | WklyDisabledTimePredicate | (secondsSinceMidnight,context) => boolean |
58
+ | WklyRangeValidator | (range,rangeMode) => error or null |
59
+ | WklyWeekLabelMode | locale, iso, absolute-week, hidden |
60
+ | WklyWeekLabelFormatter | (week,adapter) => string |
61
+ | WklyHourCycle | locale, h12, h24, switchable |
62
+ | WklyViewportPreset | full-month; full-month-and-around with extraWeeksBefore/After; weeks with visibleWeekCount |
63
+
64
+ Validation errors contain code, messageKey, and optional endpoint, field, rejectedValue, details. Stable codes: malformed-iso, wrong-value-shape, incomplete, invalid-calendar-date, unsupported-adapter-date, below-minimum, above-maximum, disabled-endpoint, range-crosses-disabled, invalid-time, step-mismatch, custom-validator, configuration-error.
65
+
66
+ ## Angular
67
+
68
+ `WklyDateTimePickerModule` exports component `wkly-datetime-picker` and directive `[wklyDateTimePickerDialog]` (exportAs wklyDialog), including forms accessors/validators. Adapters are imported separately.
69
+
70
+ | Shared input | Default |
71
+ | --- | --- |
72
+ | mode / value | datetime / null |
73
+ | calendarAdapter / locale | Gregorian / LOCALE_ID or application configuration |
74
+ | weekOffset | null: resolve configuration/locale |
75
+ | viewportPreset | full-month |
76
+ | hourCycle / showSeconds | locale / false |
77
+ | minuteStep / secondStep | 1 / 1; positive integer divisors of 60 |
78
+ | min / max | null / null, inclusive canonical bounds |
79
+ | isDateDisabled / isTimeDisabled / rangeValidator | null |
80
+ | allowRangeAcrossDisabled / required / disabled | false |
81
+ | weekLabelMode / weekLabelFormatter | locale / null |
82
+ | weekCacheSize / overscanWeeks | 256 / 3 |
83
+ | ariaLabel / ariaDescribedBy | null |
84
+ | initialEpochDay | null; selected value precedes initial anchor, then UTC today; also seeds empty manual date ranges |
85
+ | closeOnBackdrop | true |
86
+ | validators | Empty readonly array of value => error/null callbacks |
87
+
88
+ Boolean attributes are coerced. Supported visibleWeekCount is 1–52, extra rows 0–52, overscan 0–50. Invalid numeric configuration reports configuration-error.
89
+
90
+ The visible calendar stops at weeks containing dates inside both the adapter's `supportedYearRange` and `supportedEpochDayRange`. The default `DEFAULT_OVERSCAN_WEEKS` is 3; these rendered buffer weeks remain outside the visible viewport and can be blank at a range edge.
91
+
92
+ Outputs: valueChange (changed successful commits only), validationChange (readonly errors), opened, closed, viewportChange, viewModeChange. `WklyCloseReason` is submit, auto-submit, now, close-button, escape, backdrop, or programmatic. `WklyViewportChange` contains firstVisibleAbsoluteWeek, lastVisibleAbsoluteWeek, anchorAbsoluteWeek.
93
+
94
+ The component and triggers expose scrollToEpochDay, scrollToAbsoluteWeek, scrollToCalendarDate, and scrollToValue. `scrollToAbsoluteWeek` targets the first supported day when the adapter's first week starts outside its supported interval. `WklyJumpOptions` contains optional focus=false, select=false, align=center (start/end also supported). Navigation alone does not commit a value. Trigger jump methods open the transient picker when needed; triggers also expose open and close. Component field-action methods include toggleView, select, now, finish, submit, cancel, and focusDay; normal consumers use the UI and outputs.
95
+
96
+ Forms methods follow ControlValueAccessor/Validator: writeValue, registerOnChange, registerOnTouched, setDisabledState, validate, registerOnValidatorChange. Programmatic writes never invoke the registered change callback. Invalid drafts leave the last committed value intact.
97
+
98
+ Manual `date-range` and `datetime-range` End sections provide calendar-date and relative-day views. Relative input accepts signed integers in `-9999..9999` and updates the end date by epoch-day addition, keeping endpoint times. The toggle always shows the actual calendar-day difference, including ranges larger than the input limits. Completing an edit swaps reversed endpoints through the calendar's ordering path; negative typing previews remain until the existing one-second typing debounce, Enter or blur. Wheel completion uses 140 ms and touch completion occurs on release. Switching End views preserves the selection and does not emit `viewModeChange`, which continues to describe calendar/manual mode only.
99
+
100
+ Entering manual mode initializes missing endpoints in date ranges. With no selection, the date resolves from the input `initialEpochDay`, configured `initialEpochDay`, then the clock's UTC day; time initialization is shared with Now, including current UTC hours/minutes and visible seconds rounded to configured steps. A selected endpoint seeds its missing partner. Present drafts, including invalid edits, remain unchanged. Normal validation applies to the defaults, with successful inline initialization committing once and transient initialization remaining a draft until Confirm.
101
+
102
+ `WKLY_CLOCK` provides `WklyClock {now(): Date}`. `WKLY_CONFIG` provides readonly `WklyConfiguration {locale?,weekOffset?,initialEpochDay?}`. Explicit picker inputs precede application configuration; locale falls back to Angular's `LOCALE_ID`, and week start falls back to the effective locale. An existing selection precedes the initial-day input or configured anchor.
103
+
104
+ `WKLY_LOCALIZATION` provides per-instance `WklyStrings` overrides. `WKLY_TRANSLATIONS` accepts an optional locale-to-strings catalog; the showcase supplies its Arabic and Hebrew translations. Each label resolves overrides first, then the full locale followed by progressively broader tags (for example `he-IL` then `he`, or `zh-Hant-TW` then `zh-Hant` then `zh`), then built-in English, then the key itself. Catalog locale keys ignore case. The `translations` input replaces the injected catalog; `null` uses injection, while an empty catalog falls back to English. A different region's entry is never used. Shared `resolveWklyTranslation(key,locale,catalog,overrides?)` implements this resolution. `coerceBoolean` is the shared attribute coercion helper.
105
+
106
+ `WklyDateTimePickerDialogService.open(trigger,onCancel,backdrop=true,injector?)` returns `WklyPresentationRef {component,destroy()}` for custom hosts. The optional Angular injector supplies scoped providers; directives pass their trigger injector automatically. The shared `WklyPickerInputs` interface defines input property names and types. Angular 11–17 expose decorator inputs; Angular 18–22 expose signal inputs and emit `valueChange` through a separate `output()` on successful commits. Call the Angular 18–22 inputs as signals when accessing them from component code. `WklyTriggerBase` and `INPUT_NAMES` support presentation extensions. `WklyFieldComponent` is the numeric/wheel primitive with value, label, min/max/step, locale, disabled, invalid, optional labels, hideLabel, previousLabel and nextLabel inputs and valueChange/complete outputs. A negative min enables signed, localized-digit input bounded by min/max; hideLabel removes the top label row without removing the input's accessible label. Use the full picker for application forms.
107
+
108
+ Relative-day localization keys are `inDays` (`"In {{days}} days"`, interpolated with localized digits), `days`, `endDate`, `daysPrevious`, `daysNext`, and `daysUnavailable` (used for an uncomputable difference). They follow the same overrides and catalog fallback as other labels.
109
+
110
+ ## Optional CDK entry point
111
+
112
+ `@wkly/datetime-picker/cdk-overlay` exports `WklyDateTimePickerOverlayModule`, `WklyDateTimePickerOverlayDirective` (`[wklyDateTimePickerOverlay]`, exportAs wklyOverlay), and `WklyDateTimePickerOverlayService` for registered majors N (11–22). The directive inherits the shared API. Service open(trigger,onCancel,backdrop=true,injector?) returns WklyPresentationRef using CDK Overlay and its focus trap. Install the matching Angular CDK major and include overlay-prebuilt.css. Base/native-dialog imports do not load CDK.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 cokkto
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,402 @@
1
+ # WKLY date/time picker
2
+
3
+ WKLY is an Angular date and time picker with a continuous, scrollable calendar. Use it to select a date, a time, a date and time, or a range. It supports inline placement, dialogs, reactive forms, localized labels, and custom calendars.
4
+
5
+ - [Install and choose a version](#install-and-choose-a-version)
6
+ - [Add your first picker](#add-your-first-picker)
7
+ - [Configure selection and validation](#configure-selection-and-validation)
8
+ - [Use Angular forms](#use-angular-forms)
9
+ - [Open a dialog or anchored overlay](#open-a-dialog-or-anchored-overlay)
10
+ - [Customize the appearance](#customize-the-appearance)
11
+ - [Choose a locale and time format](#choose-a-locale-and-time-format)
12
+ - [Use a different calendar](#use-a-different-calendar)
13
+ - [Set application defaults](#set-application-defaults)
14
+ - [Use public types and methods](#use-public-types-and-methods)
15
+
16
+ ## Install and choose a version
17
+
18
+ Install `@wkly/datetime-picker` with the same major version as your Angular application. Angular 11–22 have corresponding package version lines.
19
+
20
+ For Angular 19:
21
+
22
+ ```sh
23
+ npm install @wkly/datetime-picker@19.x.x
24
+ ```
25
+
26
+ For another supported Angular major, replace `19` with that number. Keep the major in your dependency range when updating.
27
+
28
+ Versions follow `N.S.A`: `N` is the Angular major, `S` is the shared revision, and `A` is the revision for that Angular integration. For example, an Angular 19 fix advances `19.2.21` to `19.2.22`; a shared update advances the supported lines to `N.3.0`. Your application must satisfy the package's Angular and RxJS peer dependencies. CDK is optional and is needed only for the anchored overlay.
29
+
30
+ ## Add your first picker
31
+
32
+ Import `WklyDateTimePickerModule` into the component that uses the picker. This complete standalone example works with Angular 19:
33
+
34
+ ```ts
35
+ import { Component } from '@angular/core';
36
+ import {
37
+ WklyDateTimePickerModule,
38
+ WklyPickerValue,
39
+ } from '@wkly/datetime-picker';
40
+
41
+ @Component({
42
+ selector: 'app-booking',
43
+ standalone: true,
44
+ imports: [WklyDateTimePickerModule],
45
+ template: `<wkly-datetime-picker
46
+ mode="date"
47
+ [(value)]="value"
48
+ ariaLabel="Booking date">
49
+ </wkly-datetime-picker>`,
50
+ })
51
+ export class BookingComponent {
52
+ value: WklyPickerValue = null;
53
+ }
54
+ ```
55
+
56
+ Selecting a valid date updates `value`. Set it to `null` to clear the selection. In an application using NgModules, add `WklyDateTimePickerModule` to the `imports` of the module that declares your host component.
57
+
58
+ ### Choose what the user can select
59
+
60
+ Set `mode` to one of these six values:
61
+
62
+ | Mode | Selection | Example value |
63
+ | --- | --- | --- |
64
+ | `date` | One date | `'2099-12-16T00:00:00.000Z'` |
65
+ | `time` | One time | `'0000-01-01T13:00:00.000Z'` |
66
+ | `datetime` | One date and time; the default | `'2099-12-16T13:00:00.000Z'` |
67
+ | `date-range` | Two dates | `['2099-12-16T00:00:00.000Z', '2099-12-17T00:00:00.000Z']` |
68
+ | `time-range` | Two times | `['0000-01-01T09:00:00.000Z', '0000-01-01T17:00:00.000Z']` |
69
+ | `datetime-range` | Two dates and times | `['2099-12-16T13:00:00.000Z', '2099-12-17T15:00:00.000Z']` |
70
+
71
+ An empty selection is `null`. A completed range is an ordered readonly pair.
72
+
73
+ In manual entry for `date-range` and `datetime-range`, the End section lets you switch between calendar-date fields and **In X days**. The number always reflects the current end date relative to the start date, including calendar selections and programmatic writes. Enter or step through integers from `-9999` to `9999`; `0` selects the same calendar date as Start. Endpoint times are preserved. A negative count previews an earlier end date, then swaps the endpoints when the field edit settles (typing: one second, wheel: 140 ms, touch: release, or Enter/blur). Both views use the same validation and keep the same height.
74
+
75
+ Entering manual mode initializes missing range endpoints so you can edit only End. An empty range uses `initialEpochDay` from the picker or application configuration, falling back to the current UTC day. Its time uses the same initialization as **Now**, including current UTC hours, minutes and visible seconds rounded to their configured steps. A partial range copies its selected endpoint to the missing endpoint; supplied selections and edited drafts are preserved. Valid defaults commit inline, while dialogs and overlays wait for Confirm.
76
+
77
+ **Values are Gregorian UTC ISO strings.** WKLY does not convert timezones. Date selections use midnight, and time selections use the fixed date `0000-01-01`. Milliseconds must be `.000`; seconds must be `00` unless shown. Convert your application's timezone outside the picker. These rules also apply when the display uses a different calendar.
78
+
79
+ ## Configure selection and validation
80
+
81
+ Use inputs to limit available values and outputs to respond to user actions. For example, extend the first picker to require a date within a booking window:
82
+
83
+ ```html
84
+ <wkly-datetime-picker
85
+ mode="date"
86
+ [(value)]="value"
87
+ min="2099-12-01T00:00:00.000Z"
88
+ max="2099-12-31T00:00:00.000Z"
89
+ [required]="true"
90
+ (validationChange)="errors = $event">
91
+ </wkly-datetime-picker>
92
+ ```
93
+
94
+ Add this field to the host component, importing `WklyValidationError` from `@wkly/datetime-picker`:
95
+
96
+ ```ts
97
+ errors: readonly WklyValidationError[] = [];
98
+ ```
99
+
100
+ Invalid edits leave the last committed value intact. Inspect `errors` to present feedback in your own UI. Each error has a `code` and `messageKey`, with optional `endpoint`, `field`, `rejectedValue`, and `details`.
101
+
102
+ ### Selection and validation inputs
103
+
104
+ | Input | Default | Use it to |
105
+ | --- | --- | --- |
106
+ | `mode` | `'datetime'` | Choose one of the six selection modes above |
107
+ | `value` | `null` | Set the selection; use `[(value)]` for two-way binding |
108
+ | `required` | `false` | Report an empty selection as incomplete |
109
+ | `disabled` | `false` | Prevent interaction |
110
+ | `min`, `max` | `null` | Set inclusive bounds using canonical values for the selected mode |
111
+ | `isDateDisabled` | `null` | Reject dates with a predicate receiving an epoch day and its calendar context |
112
+ | `isTimeDisabled` | `null` | Reject times with a predicate receiving seconds since midnight and selection context |
113
+ | `allowRangeAcrossDisabled` | `false` | Allow a range to cross disabled values; its endpoints must still be valid |
114
+ | `rangeValidator` | `null` | Validate a complete ordered range and its range mode |
115
+ | `validators` | `[]` | Supply additional value callbacks returning a `WklyValidationError` or `null` |
116
+
117
+ An epoch day is an integer day index, with `1970-01-01 = 0`. Disabled-date callbacks also receive a `calendarDate`, so you can use calendar fields without calculating them yourself. Callback context identifies the selection mode and endpoint (`single`, `start`, or `end`).
118
+
119
+ ### Display and behavior inputs
120
+
121
+ | Input | Default | Use it to |
122
+ | --- | --- | --- |
123
+ | `locale` | Application configuration, then Angular `LOCALE_ID` | Set localized date labels, digits, and default time display |
124
+ | `calendarAdapter` | Gregorian adapter for the effective locale | Use a custom calendar |
125
+ | `translations` | Injected translation catalog | Supply localized action and validation labels |
126
+ | `weekOffset` | `null`: use application/locale settings | Choose the first day of the week: `0` Thursday, `1` Friday, `2` Saturday, `3` Sunday, `4` Monday, `5` Tuesday, `6` Wednesday |
127
+ | `viewportPreset` | `{ kind: 'full-month' }` | Show a month, a month with surrounding weeks, or a fixed number of weeks. Choose `'full-month'`, `'full-month-and-around'`, or `'weeks'` |
128
+ | `hourCycle` | `'locale'` | Choose `'locale'`, `'h12'`, `'h24'`, or `'switchable'` |
129
+ | `showSeconds` | `false` | Show and edit seconds |
130
+ | `minuteStep`, `secondStep` | `1` | Set allowed increments; each must be a positive divisor of 60 |
131
+ | `weekLabelMode` | `'locale'` | Choose `'locale'`, `'iso'`, `'absolute-week'`, or `'hidden'` |
132
+ | `weekLabelFormatter` | `null` | Override week labels with a callback receiving the week and adapter |
133
+ | `ariaLabel` | `null` | Replace the default accessible name, “Date and time picker” |
134
+ | `ariaDescribedBy` | `null` | Associate help or error text by element ID |
135
+ | `initialEpochDay` | `null` | Set the initial calendar position and empty manual range date; otherwise use the application default or UTC today |
136
+ | `weekCacheSize` | `256` | Limit cached weeks; `0` disables caching |
137
+ | `overscanWeeks` | `3` | Render extra weeks on either side of the viewport; supported range is `0..50` |
138
+ | `closeOnBackdrop` | `true` | Allow a dialog or overlay to close when its backdrop is clicked |
139
+
140
+ For a compact four-week view, bind `[viewportPreset]="{ kind: 'weeks', visibleWeekCount: 4 }"`. For a month with surrounding weeks, use `{ kind: 'full-month-and-around', extraWeeksBefore: 1, extraWeeksAfter: 1 }`. Fixed week counts support `1..52`; surrounding counts support `0..52`.
141
+
142
+ ### Outputs
143
+
144
+ | Output | Event value | When to use it |
145
+ | --- | --- | --- |
146
+ | `valueChange` | `WklyPickerValue` | Respond to a changed, successfully committed selection; also powers `[(value)]` |
147
+ | `validationChange` | `readonly WklyValidationError[]` | Update validation feedback |
148
+ | `viewportChange` | `WklyViewportChange` | Track the first and last visible weeks and the anchor week |
149
+ | `viewModeChange` | `'calendar'` or `'manual'` | Track switching between the calendar and manual entry |
150
+ | `opened` | No payload | Respond when a dialog or overlay opens |
151
+ | `closed` | `WklyCloseReason` | Distinguish submission from dismissal of a dialog or overlay |
152
+
153
+ Inline completed selections commit immediately. A dialog or overlay edits a draft: Confirm submits, while X, Escape, and backdrop dismissal discard the draft. Selecting a single date in calendar view can submit automatically; manual entry requires Confirm. Now validates and commits immediately.
154
+
155
+ ## Use Angular forms
156
+
157
+ Import `ReactiveFormsModule` alongside `WklyDateTimePickerModule` in the host component or NgModule. Create a control in the component:
158
+
159
+ ```ts
160
+ import { FormControl } from '@angular/forms';
161
+
162
+ // Field in the host component:
163
+ appointment = new FormControl('2099-12-16T13:00:00.000Z');
164
+ ```
165
+
166
+ ```html
167
+ <wkly-datetime-picker
168
+ [formControl]="appointment"
169
+ mode="datetime"
170
+ [required]="true">
171
+ </wkly-datetime-picker>
172
+ ```
173
+
174
+ Use the form control as the value source for this picker. Call `appointment.setValue(null)` to clear it, or `appointment.disable()` to disable it. The picker implements Angular's value accessor and validation contracts; programmatic writes do not emit a user change through the registered form callback.
175
+
176
+ ## Open a dialog or anchored overlay
177
+
178
+ The native dialog directive is included in `WklyDateTimePickerModule`:
179
+
180
+ ```html
181
+ <button wklyDateTimePickerDialog mode="date" [(value)]="value">
182
+ Choose booking date
183
+ </button>
184
+ ```
185
+
186
+ To anchor a picker to an input, install the Angular CDK major matching your application:
187
+
188
+ ```sh
189
+ npm install @angular/cdk@19
190
+ ```
191
+
192
+ Import `WklyDateTimePickerOverlayModule` from `@wkly/datetime-picker/cdk-overlay` into the host component or NgModule, and include `@angular/cdk/overlay-prebuilt.css` in your application's global styles.
193
+
194
+ ```html
195
+ <input
196
+ aria-label="Booking date"
197
+ wklyDateTimePickerOverlay
198
+ mode="date"
199
+ [(value)]="value">
200
+ ```
201
+
202
+ Trigger inputs are readonly displays; users edit through the picker. Both triggers accept the selection and display inputs above and expose the same outputs.
203
+
204
+ ## Customize the appearance
205
+
206
+ Set CSS variables directly on the `wkly-datetime-picker` element. For example, add this rule to your global stylesheet to theme inline, dialog, and overlay pickers:
207
+
208
+ ```css
209
+ wkly-datetime-picker {
210
+ --wkly-background-color: #ffffff;
211
+ --wkly-text-color: #20243a;
212
+ --wkly-accent-color: #5146a5;
213
+ --wkly-accent-color-alternate: #dcd8f2;
214
+ --wkly-accent-text-color: #ffffff;
215
+ --wkly-range-color: #eeecf8;
216
+ --wkly-size-multiplier: 1.15;
217
+ }
218
+ ```
219
+
220
+ For one inline picker, add a class to its element and scope the rule to that class. Dialog and overlay pickers are created outside the trigger's DOM subtree, so use a global picker rule to theme those presentations.
221
+
222
+ These are all available picker CSS variables:
223
+
224
+ | Variable | Default | Controls |
225
+ | --- | --- | --- |
226
+ | `--wkly-background-color` | `#fff` | Picker surface |
227
+ | `--wkly-background-color-alternate` | `#fafafa` | Alternating week backgrounds |
228
+ | `--wkly-text-color` | `#192c28` | Main text |
229
+ | `--wkly-muted-color` | `#52635e` | Secondary labels and text |
230
+ | `--wkly-border-color` | `#dce5e1` | Borders and separators |
231
+ | `--wkly-accent-color` | `#176c55` | Selection and primary actions |
232
+ | `--wkly-accent-color-alternate` | `#6ea494` | Hover and secondary accent states |
233
+ | `--wkly-accent-text-color` | `#fff` | Text on an accent background |
234
+ | `--wkly-range-color` | `#e5f1ee` | Selected range background |
235
+ | `--wkly-error-color` | `#b42318` | Invalid fields and errors |
236
+ | `--wkly-focus-color` | `#245bd6` | Keyboard focus indicators |
237
+ | `--wkly-size-multiplier` | `1` | Overall text scale, clamped to `1..1.5` |
238
+ | `--wkly-size-unit` | `3.5em` | Base dimensions for controls and calendar cells |
239
+
240
+ Changing size variables affects the space required by the calendar. Check your containing layout at the widths and scales your application uses.
241
+
242
+ ## Choose a locale and time format
243
+
244
+ Register the Angular locale data you need, then set the picker locale:
245
+
246
+ ```ts
247
+ import { registerLocaleData } from '@angular/common';
248
+ import enGb from '@angular/common/locales/en-GB';
249
+
250
+ registerLocaleData(enGb);
251
+ ```
252
+
253
+ ```html
254
+ <wkly-datetime-picker
255
+ mode="datetime"
256
+ [(value)]="value"
257
+ locale="en-GB"
258
+ hourCycle="h24"
259
+ [minuteStep]="5"
260
+ [showSeconds]="true">
261
+ </wkly-datetime-picker>
262
+ ```
263
+
264
+ `locale` controls localized calendar labels and digits. `hourCycle="locale"` follows the locale, `h12` uses AM/PM, `h24` uses 24-hour time, and `switchable` lets the user change the display. Use `secondStep` to limit seconds when they are shown. Display choices do not change the UTC value format.
265
+
266
+ ### Translate buttons and messages
267
+
268
+ English action and validation labels are included. Supply a `WklyTranslations` catalog with regional keys such as `en-GB` or `he-IL`, language keys such as `en` or `he`, or both. For each label, lookup tries the full locale and then progressively broader tags: `en-GB` checks `en-GB`, then `en`; `zh-Hant-TW` checks `zh-Hant-TW`, `zh-Hant`, then `zh`. Catalog keys are case-insensitive. A regional entry can override some labels while inheriting others from its language entry.
269
+
270
+ Add a catalog to the host component, importing `WklyTranslations` from `@wkly/datetime-picker`:
271
+
272
+ ```ts
273
+ translations: WklyTranslations = {
274
+ 'en-GB': {
275
+ confirm: 'Book this time',
276
+ },
277
+ en: {
278
+ now: 'Use current time',
279
+ 'below-minimum': 'Choose a later booking date.',
280
+ },
281
+ 'he-IL': {
282
+ now: 'עכשיו',
283
+ },
284
+ };
285
+ ```
286
+
287
+ ```html
288
+ <wkly-datetime-picker
289
+ mode="datetime"
290
+ [(value)]="value"
291
+ locale="en-GB"
292
+ [translations]="translations">
293
+ </wkly-datetime-picker>
294
+ ```
295
+
296
+ Label precedence is `WKLY_LOCALIZATION` overrides, matching regional/script catalog entries, the language catalog entry, then built-in English. Unknown keys fall back to the key itself. An input catalog replaces the injected `WKLY_TRANSLATIONS` catalog for that picker, including when the input is empty; `null` uses the injected catalog. Lookup does not use a different region's entry. Available keys cover actions, date/time fields, navigation, range endpoints, and validation codes; see the [English label catalog](https://github.com/cokkto/wkly-datetime-picker/blob/main/projects/wkly-datetime-picker/src/public-api.ts). The injection tokens are described below.
297
+
298
+ The relative-day view uses `inDays` (default `"In {{days}} days"`), `days`, `endDate`, `daysPrevious`, `daysNext`, and `daysUnavailable`. The picker replaces `{{days}}` with the localized number; `daysUnavailable` is shown when an incomplete or impossible date prevents calculating the difference.
299
+
300
+ ## Use a different calendar
301
+
302
+ The included calendar adapter is `WklyGregorianCalendarAdapter`, available from `wkly-datetime-picker.adapters`. It is selected automatically and supports Gregorian years `0000..9999` with localized labels. `WklyCalendarAbstractAdapter` is an optional base class for custom adapters, providing reusable locale formatters.
303
+
304
+ For another calendar, supply a `WklyCalendarAdapter` through `[calendarAdapter]`. The [Hebrew adapter](https://github.com/cokkto/wkly-datetime-picker/blob/main/projects/wkly-datetime-picker.showcase/src/hebrew-adapter.ts) and [Hijri adapter](https://github.com/cokkto/wkly-datetime-picker/blob/main/projects/wkly-datetime-picker.showcase/src/hijri-adapter.ts) are available as source from Git; neither is shipped in npm packages. Copy their source into your application. Hebrew requires `@hebcal/core`; Hijri has no additional dependency beyond WKLY and the platform's `Intl` calendar formatting.
305
+
306
+ After adding that example as `calendar/hebrew-adapter.ts` and installing its `@hebcal/core` dependency, configure it in your component:
307
+
308
+ ```ts
309
+ import { ShowcaseHebrewCalendarAdapter } from './calendar/hebrew-adapter';
310
+
311
+ // Field in the host component:
312
+ calendarAdapter = new ShowcaseHebrewCalendarAdapter('he-IL');
313
+ ```
314
+
315
+ ```html
316
+ <wkly-datetime-picker
317
+ mode="date"
318
+ [(value)]="value"
319
+ locale="he-IL"
320
+ [calendarAdapter]="calendarAdapter">
321
+ </wkly-datetime-picker>
322
+ ```
323
+
324
+ Register the matching Angular locale data and supply Hebrew action labels as needed. The adapter changes calendar conversion and date formatting; selected values remain Gregorian UTC strings.
325
+
326
+ For Hijri, copy `hijri-adapter.ts` and use the same picker binding with Arabic locale data and action labels:
327
+
328
+ ```ts
329
+ import { ShowcaseHijriCalendarAdapter } from './calendar/hijri-adapter';
330
+
331
+ calendarAdapter = new ShowcaseHijriCalendarAdapter('ar-EG');
332
+ ```
333
+
334
+ ```html
335
+ <wkly-datetime-picker mode="date" [(value)]="value" locale="ar-EG"
336
+ [calendarAdapter]="calendarAdapter">
337
+ </wkly-datetime-picker>
338
+ ```
339
+
340
+ Both examples support Gregorian UTC dates `1900-01-01..2100-12-31`, inclusive. Hijri implements `islamic-civil`, the tabular civil variant: a Friday epoch (Gregorian `0622-07-19`), alternating 30/29-day months, and leap years 2, 5, 7, 10, 13, 16, 18, 21, 24, 26, and 29 in each 30-year cycle. The last month has 30 days in leap years. This follows [Unicode's civil calendar definition](https://github.com/unicode-org/cldr/blob/main/common/bcp47/calendar.xml); it does not implement moon-sighting or Umm al-Qura rules. Conversion uses integer arithmetic; `Intl` supplies localized month labels only. The showcase's calendar page connects Gregorian, Hebrew, and Hijri selections to the same UTC day.
341
+
342
+ A custom adapter provides supported date bounds, reversible date conversion, month lists, validation, and display/accessibility labels. It must preserve invalid manual drafts for validation and stable month identities across years. See the [calendar adapter contract](https://github.com/cokkto/wkly-datetime-picker/blob/main/docs/API.md#adapters) for the complete interface.
343
+
344
+ ## Set application defaults
345
+
346
+ Provide these tokens at application level to share configuration across pickers. Import them from `@wkly/datetime-picker`.
347
+
348
+ | Token | Value type and default | Purpose |
349
+ | --- | --- | --- |
350
+ | `WKLY_CONFIG` | `WklyConfiguration`; `{}` | Default `locale`, `weekOffset`, and `initialEpochDay` |
351
+ | `WKLY_TRANSLATIONS` | `WklyTranslations`; `{}` | A language-to-label catalog shared across pickers |
352
+ | `WKLY_LOCALIZATION` | `WklyStrings`; `{}` | Override individual action or validation labels, regardless of locale |
353
+ | `WKLY_CLOCK` | `WklyClock`; `{ now: () => new Date() }` | Supply the clock used for today and Now; useful for deterministic tests |
354
+
355
+ For example, define a provider array and include it in your application configuration's `providers`, or your root NgModule's `providers`:
356
+
357
+ ```ts
358
+ import { Provider } from '@angular/core';
359
+ import {
360
+ WKLY_CONFIG,
361
+ WKLY_LOCALIZATION,
362
+ } from '@wkly/datetime-picker';
363
+
364
+ export const bookingPickerProviders: Provider[] = [
365
+ {
366
+ provide: WKLY_CONFIG,
367
+ useValue: { locale: 'en-GB', weekOffset: 4 },
368
+ },
369
+ {
370
+ provide: WKLY_LOCALIZATION,
371
+ useValue: { confirm: 'Book this time' },
372
+ },
373
+ ];
374
+ ```
375
+
376
+ Explicit picker settings take precedence over `WKLY_CONFIG`. When no locale is supplied, the picker uses Angular's `LOCALE_ID`. When no week offset is supplied, it resolves the start of the week from the effective locale. Offset `0` is an explicit Thursday start.
377
+
378
+ ## Use public types and methods
379
+
380
+ Use the public types when integrating with forms, application state, validation, or custom presentation.
381
+
382
+ | Type or interface | Import from | Purpose |
383
+ | --- | --- | --- |
384
+ | `WklyPickerValue`, `WklyIsoString`, `WklyRangeValue` | `@wkly/datetime-picker` | Type the nullable selection, UTC strings, and readonly range pairs |
385
+ | `WklySelectionMode`, `WklyHourCycle`, `WklyViewportPreset` | `@wkly/datetime-picker` | Type selection and display options |
386
+ | `WklyValidationError`, `WklyValidationErrorCode`, `WklyEndpoint` | `@wkly/datetime-picker` | Handle validation and identify the affected endpoint |
387
+ | `WklyDisabledDatePredicate`, `WklyDisabledTimePredicate`, `WklyRangeValidator` | `@wkly/datetime-picker` | Define availability rules and range validation |
388
+ | `WklyWeekLabelMode`, `WklyWeekLabelFormatter` | `@wkly/datetime-picker` | Choose or customize week labels |
389
+ | `WklyConfiguration`, `WklyStrings`, `WklyTranslations`, `WklyClock` | `@wkly/datetime-picker` | Type values supplied through injection tokens |
390
+ | `WklyViewportChange`, `WklyCloseReason`, `WklyJumpOptions` | `@wkly/datetime-picker` | Handle navigation, dismissal, and programmatic jumps |
391
+ | `WklyPresentationRef` | `@wkly/datetime-picker` | Access and destroy a presentation created through a presentation service |
392
+ | `WklyCalendarAdapter`, `WklyCalendarDate`, `WklyCalendarMonth`, `WklyCalendarDateError` | `wkly-datetime-picker.adapters` | Implement another calendar and its validation |
393
+ | `WklyDatePredicateContext`, `WklyTimePredicateContext`, `WklySelectionConfig` | `wkly-datetime-picker.adapters` | Work directly with predicate context and selection validation |
394
+ | `WklyPickerInputs`, `WklyPickerOutputs` | `wkly-datetime-picker` | Describe the shared binding contracts when building presentation extensions |
395
+
396
+ When importing an adapter or shared contract directly, declare its package as a direct dependency of your application.
397
+
398
+ The component and dialog/overlay triggers provide `scrollToEpochDay`, `scrollToAbsoluteWeek`, `scrollToCalendarDate`, and `scrollToValue`. Pass `WklyJumpOptions` to choose alignment (`start`, `center`, or `end`), focus, and whether to select the target. Defaults are center alignment with no focus or selection change. A trigger opens its presentation before navigating; triggers also expose `open()` and `close()`.
399
+
400
+ For custom hosts, `WklyDateTimePickerDialogService` and `WklyDateTimePickerOverlayService` create presentations. The overlay service is imported from `@wkly/datetime-picker/cdk-overlay`. See the [API reference](https://github.com/cokkto/wkly-datetime-picker/blob/main/docs/API.md) for method signatures and extension contracts.
401
+
402
+ WKLY is [MIT licensed](LICENSE). Contributors can start with the [project documentation](https://github.com/cokkto/wkly-datetime-picker/blob/main/docs/README.md).