@vaadin/date-picker 25.3.0-alpha8 → 25.3.0-beta1
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.
- package/custom-elements.json +550 -15
- package/package.json +13 -13
- package/src/styles/vaadin-date-picker-overlay-content-base-styles.js +9 -0
- package/src/vaadin-date-metadata-controller.d.ts +94 -0
- package/src/vaadin-date-metadata-controller.js +268 -0
- package/src/vaadin-date-picker-helper.d.ts +144 -13
- package/src/vaadin-date-picker-helper.js +119 -15
- package/src/vaadin-date-picker-mixin.d.ts +100 -0
- package/src/vaadin-date-picker-mixin.js +150 -8
- package/src/vaadin-date-picker-overlay-content-mixin.js +152 -50
- package/src/vaadin-date-picker-overlay-content.js +4 -1
- package/src/vaadin-date-picker-year.js +3 -1
- package/src/vaadin-date-picker.d.ts +73 -7
- package/src/vaadin-date-picker.js +66 -6
- package/src/vaadin-infinite-scroller.js +19 -6
- package/src/vaadin-month-calendar-mixin.js +55 -29
- package/web-types.json +37 -8
- package/web-types.lit.json +20 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/date-picker",
|
|
3
|
-
"version": "25.3.0-
|
|
3
|
+
"version": "25.3.0-beta1",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -35,21 +35,21 @@
|
|
|
35
35
|
],
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"@open-wc/dedupe-mixin": "^1.3.0",
|
|
38
|
-
"@vaadin/a11y-base": "25.3.0-
|
|
39
|
-
"@vaadin/button": "25.3.0-
|
|
40
|
-
"@vaadin/component-base": "25.3.0-
|
|
41
|
-
"@vaadin/field-base": "25.3.0-
|
|
42
|
-
"@vaadin/input-container": "25.3.0-
|
|
43
|
-
"@vaadin/overlay": "25.3.0-
|
|
44
|
-
"@vaadin/vaadin-themable-mixin": "25.3.0-
|
|
38
|
+
"@vaadin/a11y-base": "25.3.0-beta1",
|
|
39
|
+
"@vaadin/button": "25.3.0-beta1",
|
|
40
|
+
"@vaadin/component-base": "25.3.0-beta1",
|
|
41
|
+
"@vaadin/field-base": "25.3.0-beta1",
|
|
42
|
+
"@vaadin/input-container": "25.3.0-beta1",
|
|
43
|
+
"@vaadin/overlay": "25.3.0-beta1",
|
|
44
|
+
"@vaadin/vaadin-themable-mixin": "25.3.0-beta1",
|
|
45
45
|
"lit": "^3.0.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
|
-
"@vaadin/aura": "25.3.0-
|
|
49
|
-
"@vaadin/chai-plugins": "25.3.0-
|
|
50
|
-
"@vaadin/test-runner-commands": "25.3.0-
|
|
48
|
+
"@vaadin/aura": "25.3.0-beta1",
|
|
49
|
+
"@vaadin/chai-plugins": "25.3.0-beta1",
|
|
50
|
+
"@vaadin/test-runner-commands": "25.3.0-beta1",
|
|
51
51
|
"@vaadin/testing-helpers": "^2.0.0",
|
|
52
|
-
"@vaadin/vaadin-lumo-styles": "25.3.0-
|
|
52
|
+
"@vaadin/vaadin-lumo-styles": "25.3.0-beta1",
|
|
53
53
|
"sinon": "^22.0.0"
|
|
54
54
|
},
|
|
55
55
|
"customElements": "custom-elements.json",
|
|
@@ -57,5 +57,5 @@
|
|
|
57
57
|
"web-types.json",
|
|
58
58
|
"web-types.lit.json"
|
|
59
59
|
],
|
|
60
|
-
"gitHead": "
|
|
60
|
+
"gitHead": "295432e44a6967e1aff36462b2e3e1d0e64eb8cc"
|
|
61
61
|
}
|
|
@@ -17,6 +17,7 @@ export const overlayContentStyles = css`
|
|
|
17
17
|
height: 100%;
|
|
18
18
|
outline: none;
|
|
19
19
|
overflow: hidden;
|
|
20
|
+
position: relative;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
:host([desktop]) {
|
|
@@ -49,6 +50,14 @@ export const overlayContentStyles = css`
|
|
|
49
50
|
display: none !important;
|
|
50
51
|
}
|
|
51
52
|
|
|
53
|
+
[part='loader'] {
|
|
54
|
+
position: absolute;
|
|
55
|
+
z-index: 1;
|
|
56
|
+
inset-block-start: var(--vaadin-date-picker-month-header-font-size, 0.9375rem);
|
|
57
|
+
inset-inline: 0;
|
|
58
|
+
margin-inline: auto;
|
|
59
|
+
}
|
|
60
|
+
|
|
52
61
|
::slotted([slot='months']) {
|
|
53
62
|
--vaadin-infinite-scroller-item-height: round(
|
|
54
63
|
var(--vaadin-date-picker-month-header-font-size, 0.9375rem) + 0.75rem +
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2016 - 2026 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import type { ReactiveController, ReactiveControllerHost, ReactiveElement } from 'lit';
|
|
7
|
+
import type { DatePickerDateMetadata, DatePickerDateMetadataProvider } from './vaadin-date-picker-mixin.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* A reactive controller that resolves the metadata (currently the disabled state)
|
|
11
|
+
* for the dates shown by the date-picker's `dateMetadataProvider`.
|
|
12
|
+
*
|
|
13
|
+
* The provider is called for a range of months and may return an array
|
|
14
|
+
* synchronously or a `Promise`, so results from a server (Flow) or a remote
|
|
15
|
+
* availability service can be awaited. The range and each returned entry identify
|
|
16
|
+
* a date by an ISO 8601 string, e.g. `{ date: '2026-01-01', disabled: true }`.
|
|
17
|
+
*
|
|
18
|
+
* `ARCHITECTURE.md` in this package records the reasoning behind the request,
|
|
19
|
+
* caching, notification and failure behavior.
|
|
20
|
+
*/
|
|
21
|
+
export class DateMetadataController implements ReactiveController {
|
|
22
|
+
/**
|
|
23
|
+
* The controller host element.
|
|
24
|
+
*/
|
|
25
|
+
host: HTMLElement & ReactiveControllerHost;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The provider function, or `null` when none is set.
|
|
29
|
+
*/
|
|
30
|
+
provider: DatePickerDateMetadataProvider | null;
|
|
31
|
+
|
|
32
|
+
constructor(host: HTMLElement & ReactiveControllerHost, onChange?: () => void);
|
|
33
|
+
|
|
34
|
+
hostConnected(): void;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Registers an element to be re-rendered whenever the resolved metadata or the
|
|
38
|
+
* loading state changes. The element must render from its bindings, and must not be
|
|
39
|
+
* the one whose own observer triggers a load. It stays registered for the
|
|
40
|
+
* controller's lifetime.
|
|
41
|
+
*/
|
|
42
|
+
subscribe(element: ReactiveElement): void;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Whether any month range is currently being fetched.
|
|
46
|
+
*/
|
|
47
|
+
isLoading(): boolean;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Sets the provider function and clears the cache. Passing the same provider again
|
|
51
|
+
* is a no-op, so callers should keep a stable reference.
|
|
52
|
+
*/
|
|
53
|
+
setProvider(provider: DatePickerDateMetadataProvider | null | undefined): void;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Clears the cache and invalidates any in-flight requests.
|
|
57
|
+
*/
|
|
58
|
+
clearCache(): void;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Whether the provider has answered for the month containing the given date.
|
|
62
|
+
* A month whose request failed is not loaded and will be requested again.
|
|
63
|
+
*/
|
|
64
|
+
isMonthLoaded(date: Date | null | undefined): boolean;
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Whether the month containing the given date is currently being fetched. A month
|
|
68
|
+
* that has not been asked about is not pending, so this reports the same state as
|
|
69
|
+
* `isLoading()` does for the whole cache.
|
|
70
|
+
*/
|
|
71
|
+
isMonthPending(date: Date | null | undefined): boolean;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* The metadata resolved for the given date, or `undefined` when the date has
|
|
75
|
+
* no metadata or its month has not been resolved yet. Returns the entry the
|
|
76
|
+
* provider supplied, which the caller must not modify.
|
|
77
|
+
*/
|
|
78
|
+
getMetadata(date: Date | null | undefined): DatePickerDateMetadata | undefined;
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Whether the given date is disabled by its metadata.
|
|
82
|
+
*/
|
|
83
|
+
isDateDisabled(date: Date | null | undefined): boolean;
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Ensures the provider has been consulted for the inclusive range between the
|
|
87
|
+
* given dates, rounded out to whole blocks of months. Months already loaded or in
|
|
88
|
+
* flight are skipped, and the ones left over are requested with a single call.
|
|
89
|
+
*
|
|
90
|
+
* Each call that finds a missing month issues its own request, so a caller that
|
|
91
|
+
* loads on scroll should debounce.
|
|
92
|
+
*/
|
|
93
|
+
ensureRangeLoaded(startDate: Date | null | undefined, endDate: Date | null | undefined): void;
|
|
94
|
+
}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2016 - 2026 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { microTask } from '@vaadin/component-base/src/async.js';
|
|
7
|
+
import { Debouncer } from '@vaadin/component-base/src/debounce.js';
|
|
8
|
+
import { issueWarning } from '@vaadin/component-base/src/warnings.js';
|
|
9
|
+
import { formatISODate, lastOfMonth, monthDate, monthIndex, parseDate } from './vaadin-date-picker-helper.js';
|
|
10
|
+
|
|
11
|
+
// Counted from January of year 0, so a block is one calendar year.
|
|
12
|
+
const BLOCK_MONTHS = 12;
|
|
13
|
+
|
|
14
|
+
function blockStart(month) {
|
|
15
|
+
return Math.floor(month / BLOCK_MONTHS) * BLOCK_MONTHS;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const PENDING_MONTH = Object.freeze({ pending: true });
|
|
19
|
+
|
|
20
|
+
// The date of an entry, or `undefined` when its `date` is not one. Checked for being a string first,
|
|
21
|
+
// since coercing another type to one can throw, and an entry comes from outside.
|
|
22
|
+
function entryDate(entry) {
|
|
23
|
+
return typeof entry?.date === 'string' ? parseDate(entry.date) : undefined;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function groupEntriesByMonth(months, entries) {
|
|
27
|
+
const result = new Map(months.map((month) => [month, new Map()]));
|
|
28
|
+
|
|
29
|
+
if (Array.isArray(entries)) {
|
|
30
|
+
entries.forEach((entry) => {
|
|
31
|
+
const date = entryDate(entry);
|
|
32
|
+
if (date) {
|
|
33
|
+
result.get(monthIndex(date))?.set(date.getDate(), entry);
|
|
34
|
+
} else {
|
|
35
|
+
issueWarning('Ignored `dateMetadataProvider` entries whose `date` is not an ISO 8601 date.');
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
} else if (entries != null) {
|
|
39
|
+
issueWarning('Expected `dateMetadataProvider` to return an array of date metadata objects.');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return result;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* A reactive controller that resolves the metadata (currently the disabled state)
|
|
47
|
+
* for the dates shown by the date-picker's `dateMetadataProvider`.
|
|
48
|
+
*
|
|
49
|
+
* The provider is called for a range of months and may return an array
|
|
50
|
+
* synchronously or a `Promise`, so results from a server (Flow) or a remote
|
|
51
|
+
* availability service can be awaited. The range and each returned entry identify
|
|
52
|
+
* a date by an ISO 8601 string, e.g. `{ date: '2026-01-01', disabled: true }`.
|
|
53
|
+
*
|
|
54
|
+
* `ARCHITECTURE.md` in this package records the reasoning behind the request,
|
|
55
|
+
* caching, notification and failure behavior.
|
|
56
|
+
*/
|
|
57
|
+
export class DateMetadataController {
|
|
58
|
+
/**
|
|
59
|
+
* The controller host element.
|
|
60
|
+
* @type {import('lit').ReactiveControllerHost & HTMLElement}
|
|
61
|
+
*/
|
|
62
|
+
host;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* The provider function, or `null` when none is set.
|
|
66
|
+
* @type {Function | null}
|
|
67
|
+
*/
|
|
68
|
+
provider = null;
|
|
69
|
+
|
|
70
|
+
/** @type {(() => void) | undefined} */
|
|
71
|
+
#onChange;
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* What is known about each month, keyed by month index: a shared marker while its request is in
|
|
75
|
+
* flight, or a record holding the resolved entries by day. A month is absent until it is loaded,
|
|
76
|
+
* and absent again if its request failed.
|
|
77
|
+
* @type {Map<number, { pending: boolean, entries?: Map<number, object> }>}
|
|
78
|
+
*/
|
|
79
|
+
#months = new Map();
|
|
80
|
+
|
|
81
|
+
/** @type {Set<import('lit').ReactiveElement>} */
|
|
82
|
+
#subscribers = new Set();
|
|
83
|
+
|
|
84
|
+
#requestId = 0;
|
|
85
|
+
|
|
86
|
+
/** @type {import('@vaadin/component-base/src/debounce.js').Debouncer} */
|
|
87
|
+
#notifyDebouncer;
|
|
88
|
+
|
|
89
|
+
constructor(host, onChange) {
|
|
90
|
+
this.host = host;
|
|
91
|
+
this.#onChange = onChange;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
hostConnected() {
|
|
95
|
+
this.#notify();
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Registers an element to be re-rendered whenever the resolved metadata or the
|
|
100
|
+
* loading state changes. The element must render from its bindings, and must not be
|
|
101
|
+
* the one whose own observer triggers a load. It stays registered for the
|
|
102
|
+
* controller's lifetime.
|
|
103
|
+
*
|
|
104
|
+
* @param {import('lit').ReactiveElement} element
|
|
105
|
+
*/
|
|
106
|
+
subscribe(element) {
|
|
107
|
+
this.#subscribers.add(element);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Whether any month range is currently being fetched.
|
|
112
|
+
* @return {boolean}
|
|
113
|
+
*/
|
|
114
|
+
isLoading() {
|
|
115
|
+
for (const { pending } of this.#months.values()) {
|
|
116
|
+
if (pending) {
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Sets the provider function and clears the cache. Passing the same provider again
|
|
125
|
+
* is a no-op, so callers should keep a stable reference.
|
|
126
|
+
*
|
|
127
|
+
* @param {Function | null | undefined} provider
|
|
128
|
+
*/
|
|
129
|
+
setProvider(provider) {
|
|
130
|
+
const next = provider ?? null;
|
|
131
|
+
if (this.provider === next) {
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
this.provider = next;
|
|
135
|
+
this.clearCache();
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Clears the cache and invalidates any in-flight requests.
|
|
140
|
+
*/
|
|
141
|
+
clearCache() {
|
|
142
|
+
this.#months.clear();
|
|
143
|
+
this.#requestId += 1;
|
|
144
|
+
this.#notify();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Whether the provider has answered for the month containing the given date.
|
|
149
|
+
* A month whose request failed is not loaded and will be requested again.
|
|
150
|
+
* @param {Date | null | undefined} date
|
|
151
|
+
* @return {boolean}
|
|
152
|
+
*/
|
|
153
|
+
isMonthLoaded(date) {
|
|
154
|
+
return !!this.#resolvedMonth(date);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Whether the month containing the given date is currently being fetched. A month
|
|
159
|
+
* that has not been asked about is not pending, so this reports the same state as
|
|
160
|
+
* `isLoading()` does for the whole cache.
|
|
161
|
+
* @param {Date | null | undefined} date
|
|
162
|
+
* @return {boolean}
|
|
163
|
+
*/
|
|
164
|
+
isMonthPending(date) {
|
|
165
|
+
return !!date && !!this.#months.get(monthIndex(date))?.pending;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* The metadata resolved for the given date, or `undefined` when the date has
|
|
170
|
+
* no metadata or its month has not been resolved yet. Returns the entry the
|
|
171
|
+
* provider supplied, which the caller must not modify.
|
|
172
|
+
* @param {Date | null | undefined} date
|
|
173
|
+
* @return {object | undefined}
|
|
174
|
+
*/
|
|
175
|
+
getMetadata(date) {
|
|
176
|
+
return this.#resolvedMonth(date)?.entries.get(date.getDate());
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Whether the given date is disabled by its metadata.
|
|
181
|
+
* @param {Date | null | undefined} date
|
|
182
|
+
* @return {boolean}
|
|
183
|
+
*/
|
|
184
|
+
isDateDisabled(date) {
|
|
185
|
+
return !!this.getMetadata(date)?.disabled;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Ensures the provider has been consulted for the inclusive range between the
|
|
190
|
+
* given dates, rounded out to whole blocks of months. Months already loaded or in
|
|
191
|
+
* flight are skipped, and the ones left over are requested with a single call.
|
|
192
|
+
*
|
|
193
|
+
* Each call that finds a missing month issues its own request, so a caller that
|
|
194
|
+
* loads on scroll should debounce.
|
|
195
|
+
*
|
|
196
|
+
* @param {Date | null | undefined} startDate
|
|
197
|
+
* @param {Date | null | undefined} endDate
|
|
198
|
+
*/
|
|
199
|
+
ensureRangeLoaded(startDate, endDate) {
|
|
200
|
+
if (!this.provider || !startDate || !endDate) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const first = blockStart(monthIndex(startDate));
|
|
205
|
+
const last = blockStart(monthIndex(endDate)) + BLOCK_MONTHS - 1;
|
|
206
|
+
|
|
207
|
+
const months = [];
|
|
208
|
+
for (let month = first; month <= last; month++) {
|
|
209
|
+
if (!this.#months.has(month)) {
|
|
210
|
+
months.push(month);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
if (months.length > 0) {
|
|
215
|
+
this.#loadMonths(months);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
#resolvedMonth(date) {
|
|
220
|
+
const month = date && this.#months.get(monthIndex(date));
|
|
221
|
+
return month && !month.pending ? month : undefined;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
async #loadMonths(months) {
|
|
225
|
+
const requestId = this.#requestId;
|
|
226
|
+
months.forEach((month) => this.#months.set(month, PENDING_MONTH));
|
|
227
|
+
this.#notify();
|
|
228
|
+
|
|
229
|
+
const range = {
|
|
230
|
+
start: formatISODate(monthDate(months[0])),
|
|
231
|
+
end: formatISODate(lastOfMonth(monthDate(months.at(-1)))),
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
let entries;
|
|
235
|
+
try {
|
|
236
|
+
const data = await this.provider(range);
|
|
237
|
+
entries = groupEntriesByMonth(months, data);
|
|
238
|
+
} catch (error) {
|
|
239
|
+
console.error(error);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (requestId !== this.#requestId) {
|
|
243
|
+
return;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
months.forEach((month) => {
|
|
247
|
+
if (entries) {
|
|
248
|
+
this.#months.set(month, { pending: false, entries: entries.get(month) });
|
|
249
|
+
} else {
|
|
250
|
+
this.#months.delete(month);
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
this.#notify();
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
#notify() {
|
|
258
|
+
this.#subscribers.forEach((element) => element.requestUpdate());
|
|
259
|
+
|
|
260
|
+
if (this.#onChange) {
|
|
261
|
+
this.#notifyDebouncer = Debouncer.debounce(this.#notifyDebouncer, microTask, () => {
|
|
262
|
+
if (this.host.isConnected) {
|
|
263
|
+
this.#onChange();
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
}
|
|
@@ -3,21 +3,88 @@
|
|
|
3
3
|
* Copyright (c) 2016 - 2026 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
|
+
import type { DateMetadataController } from './vaadin-date-metadata-controller.js';
|
|
6
7
|
import type { DatePickerDate } from './vaadin-date-picker-mixin.js';
|
|
7
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Create a date at midnight in local time. Unlike `new Date(year, month, day)`,
|
|
11
|
+
* this supports years below 100, which the constructor maps into the 20th
|
|
12
|
+
* century. The month is assigned before the day so that the initial day of month
|
|
13
|
+
* (1) always exists in the target month.
|
|
14
|
+
*
|
|
15
|
+
* @param month Zero-based month, may be out of range to shift the year
|
|
16
|
+
* @param day May be `0` to select the last day of the previous month
|
|
17
|
+
*/
|
|
18
|
+
declare function createDate(year: number, month: number, day: number): Date;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Get the first day of the month the given date is in.
|
|
22
|
+
*/
|
|
23
|
+
declare function firstOfMonth(date: Date): Date;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Get the last day of the month the given date is in.
|
|
27
|
+
*/
|
|
28
|
+
declare function lastOfMonth(date: Date): Date;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Get the index of a month, counted from January of year 0. Reduces a month to a single
|
|
32
|
+
* integer, so a lookup builds no key and two months are adjacent when their indexes are.
|
|
33
|
+
*
|
|
34
|
+
* @param month Zero-based month
|
|
35
|
+
*/
|
|
36
|
+
declare function monthIndexOf(year: number, month: number): number;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Get the index of the month the given date is in.
|
|
40
|
+
*/
|
|
41
|
+
declare function monthIndex(date: Date): number;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Get the first day of the month with the given index, inverting `monthIndexOf`. Counting from
|
|
45
|
+
* January of year 0 also inverts negative indexes, since `createDate` normalizes a month outside
|
|
46
|
+
* 0-11 into the year.
|
|
47
|
+
*/
|
|
48
|
+
declare function monthDate(index: number): Date;
|
|
49
|
+
|
|
8
50
|
/**
|
|
9
51
|
* Get ISO 8601 week number for the given date.
|
|
10
52
|
*
|
|
11
53
|
* @returns Week number
|
|
12
54
|
*/
|
|
13
|
-
declare function getISOWeekNumber(
|
|
55
|
+
declare function getISOWeekNumber(date: Date): number;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Creates a new object with the same date, but sets the hours, minutes, seconds and milliseconds to 0.
|
|
59
|
+
*
|
|
60
|
+
* @param date in system timezone
|
|
61
|
+
* @returns The same date with time elements set to 0, in system timezone.
|
|
62
|
+
*/
|
|
63
|
+
declare function normalizeDate(date: Date): Date;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Creates a new object with the same date, but sets the hours, minutes, seconds and milliseconds to 0.
|
|
67
|
+
*
|
|
68
|
+
* Uses UTC date components to allow handling date instances independently of
|
|
69
|
+
* the system time-zone.
|
|
70
|
+
*
|
|
71
|
+
* @param date in UTC timezone
|
|
72
|
+
* @returns The same date with time elements set to 0, in UTC timezone.
|
|
73
|
+
*/
|
|
74
|
+
declare function normalizeUTCDate(date: Date): Date;
|
|
14
75
|
|
|
15
76
|
/**
|
|
16
77
|
* Check if two dates are equal.
|
|
17
78
|
*
|
|
18
79
|
* @returns True if the given date objects refer to the same date
|
|
19
80
|
*/
|
|
20
|
-
declare function dateEquals(date1: Date | null, date2: Date | null): boolean;
|
|
81
|
+
declare function dateEquals(date1: Date | null, date2: Date | null, normalizer?: (date: Date) => Date): boolean;
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Extracts the basic component parts of a date (day, month and year)
|
|
85
|
+
* to the expected format.
|
|
86
|
+
*/
|
|
87
|
+
declare function extractDateParts(date: Date): { day: number; month: number; year: number };
|
|
21
88
|
|
|
22
89
|
/**
|
|
23
90
|
* Check if the given date is in the range of allowed dates.
|
|
@@ -31,6 +98,21 @@ declare function dateAllowed(
|
|
|
31
98
|
isDateDisabled: (date: DatePickerDate) => boolean | null,
|
|
32
99
|
): boolean;
|
|
33
100
|
|
|
101
|
+
/**
|
|
102
|
+
* Check if the given date can be selected: allowed by `dateAllowed` and not reported as disabled
|
|
103
|
+
* by the date metadata controller. This is narrower than `dateAllowed`, which decides what can be
|
|
104
|
+
* focused: a disabled date is still focusable, it just cannot be selected.
|
|
105
|
+
*
|
|
106
|
+
* @returns True if the date can be selected
|
|
107
|
+
*/
|
|
108
|
+
declare function dateSelectable(
|
|
109
|
+
date: Date,
|
|
110
|
+
min: Date | null,
|
|
111
|
+
max: Date | null,
|
|
112
|
+
isDateDisabled: (date: DatePickerDate) => boolean | null,
|
|
113
|
+
controller?: DateMetadataController | null,
|
|
114
|
+
): boolean;
|
|
115
|
+
|
|
34
116
|
/**
|
|
35
117
|
* Get closest date from array of dates.
|
|
36
118
|
*
|
|
@@ -39,36 +121,85 @@ declare function dateAllowed(
|
|
|
39
121
|
declare function getClosestDate(date: Date, dates: Date[]): Date;
|
|
40
122
|
|
|
41
123
|
/**
|
|
42
|
-
*
|
|
43
|
-
* to the expected format.
|
|
124
|
+
* Get difference in months between today and given months value.
|
|
44
125
|
*/
|
|
45
|
-
declare function
|
|
126
|
+
declare function dateAfterXMonths(months: number): Date;
|
|
46
127
|
|
|
47
128
|
/**
|
|
48
|
-
*
|
|
129
|
+
* Calculate the year of the date based on the provided reference date.
|
|
130
|
+
* Gets a two-digit year and returns a full year.
|
|
131
|
+
*
|
|
132
|
+
* @param year Should be in the range of [0, 99]
|
|
133
|
+
* @returns Adjusted year value
|
|
49
134
|
*/
|
|
50
|
-
declare function
|
|
135
|
+
declare function getAdjustedYear(referenceDate: Date, year: number, month?: number, day?: number): number;
|
|
51
136
|
|
|
52
137
|
/**
|
|
53
|
-
*
|
|
54
|
-
*
|
|
138
|
+
* Parse date string of one of the following date formats:
|
|
139
|
+
* - ISO 8601 `"YYYY-MM-DD"`
|
|
140
|
+
* - Extended ISO 8601 with a signed year, e.g. `"+012026-MM-DD"` or `"-0001-MM-DD"`
|
|
141
|
+
*
|
|
142
|
+
* A date that does not exist, such as `"2026-02-30"`, is not parsed. Building it would carry the
|
|
143
|
+
* surplus into the next month or year and answer with a date that was never asked for.
|
|
144
|
+
*
|
|
145
|
+
* @param str Date string to parse
|
|
146
|
+
* @returns Parsed date in system timezone, or `undefined` when the string is not a date
|
|
55
147
|
*/
|
|
56
|
-
declare function
|
|
148
|
+
declare function parseDate(str: string): Date | undefined;
|
|
57
149
|
|
|
58
150
|
/**
|
|
59
151
|
* Parse date string of one of the following date formats:
|
|
60
152
|
* - ISO 8601 `"YYYY-MM-DD"`
|
|
61
|
-
* -
|
|
153
|
+
* - Extended ISO 8601 with a signed year, e.g. `"+012026-MM-DD"` or `"-0001-MM-DD"`
|
|
154
|
+
*
|
|
155
|
+
* Uses UTC date components to allow handling date instances independently of
|
|
156
|
+
* the system time-zone.
|
|
157
|
+
*
|
|
158
|
+
* A date that does not exist, such as `"2026-02-30"`, is not parsed, as in `parseDate`.
|
|
159
|
+
*
|
|
160
|
+
* @param str Date string to parse
|
|
161
|
+
* @returns Parsed date in UTC timezone, or `undefined` when the string is not a date
|
|
62
162
|
*/
|
|
63
|
-
declare function
|
|
163
|
+
declare function parseUTCDate(str: string): Date | undefined;
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Format a date instance in ISO 8601 (`"YYYY-MM-DD"`) or 6-digit extended ISO
|
|
167
|
+
* 8601 (`"+YYYYYY-MM-DD"`, `"-YYYYYY-MM-DD"`) format.
|
|
168
|
+
*
|
|
169
|
+
* @param date in system timezone
|
|
170
|
+
*/
|
|
171
|
+
declare function formatISODate(date: Date): string;
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Format a date instance in ISO 8601 (`"YYYY-MM-DD"`) or 6-digit extended ISO
|
|
175
|
+
* 8601 (`"+YYYYYY-MM-DD"`, `"-YYYYYY-MM-DD"`) format.
|
|
176
|
+
*
|
|
177
|
+
* Uses UTC date components to allow handling date instances independently of
|
|
178
|
+
* the system time-zone.
|
|
179
|
+
*
|
|
180
|
+
* @param date in UTC timezone
|
|
181
|
+
*/
|
|
182
|
+
declare function formatUTCISODate(date: Date): string;
|
|
64
183
|
|
|
65
184
|
export {
|
|
185
|
+
createDate,
|
|
186
|
+
firstOfMonth,
|
|
187
|
+
lastOfMonth,
|
|
188
|
+
monthIndexOf,
|
|
189
|
+
monthIndex,
|
|
190
|
+
monthDate,
|
|
66
191
|
getISOWeekNumber,
|
|
192
|
+
normalizeDate,
|
|
193
|
+
normalizeUTCDate,
|
|
67
194
|
dateEquals,
|
|
195
|
+
extractDateParts,
|
|
68
196
|
dateAllowed,
|
|
197
|
+
dateSelectable,
|
|
69
198
|
getClosestDate,
|
|
70
|
-
extractDateParts,
|
|
71
199
|
dateAfterXMonths,
|
|
72
200
|
getAdjustedYear,
|
|
73
201
|
parseDate,
|
|
202
|
+
parseUTCDate,
|
|
203
|
+
formatISODate,
|
|
204
|
+
formatUTCISODate,
|
|
74
205
|
};
|