@lekoala/date-picker 0.5.2 → 0.6.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.
- package/dist/date-picker.css +2 -13
- package/dist/date-picker.js +222 -252
- package/dist/date-picker.min.css +1 -1
- package/dist/date-picker.min.js +12 -13
- package/dist/date-picker.standalone.min.js +11 -12
- package/dist/types/date-calendar.d.ts +2 -98
- package/dist/types/date-picker.d.ts +0 -316
- package/dist/types/date-range.d.ts +10 -33
- package/dist/types/date-range.d.ts.map +1 -1
- package/dist/types/date.d.ts.map +1 -1
- package/dist/types/session.d.ts +17 -0
- package/dist/types/session.d.ts.map +1 -0
- package/docs/ACCESSIBILITY.md +1 -1
- package/docs/API.md +14 -25
- package/docs/ARCHITECTURE.md +74 -0
- package/docs/CALENDAR-INTEGRATION.md +97 -0
- package/docs/DECISIONS.md +30 -3
- package/docs/TESTING.md +8 -0
- package/docs/USE_CASES.md +1 -2
- package/package.json +2 -2
- package/src/date-calendar.js +90 -18
- package/src/date-field.js +32 -9
- package/src/date-picker.css +2 -13
- package/src/date-picker.js +134 -228
- package/src/date-range.js +12 -54
- package/src/date.js +4 -1
- package/src/session.js +23 -0
- package/dist/types/activation-intents.d.ts +0 -10
- package/dist/types/activation-intents.d.ts.map +0 -1
- package/dist/types/date-calendar.d.ts.map +0 -1
- package/dist/types/date-field.d.ts +0 -118
- package/dist/types/date-field.d.ts.map +0 -1
- package/dist/types/date-picker.d.ts.map +0 -1
- package/dist/types/time.d.ts +0 -8
- package/dist/types/time.d.ts.map +0 -1
- package/dist/types/upgrade-properties.d.ts +0 -8
- package/dist/types/upgrade-properties.d.ts.map +0 -1
package/dist/date-picker.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*** @lekoala/date-picker v0.
|
|
1
|
+
/*** @lekoala/date-picker v0.6.0 - https://github.com/lekoala/date-picker ***/
|
|
2
2
|
(() => {
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -78,9 +78,11 @@
|
|
|
78
78
|
const text = String(value || "");
|
|
79
79
|
const monthMatch = MONTH_RE.exec(text);
|
|
80
80
|
if (monthMatch) {
|
|
81
|
+
const year = Number(monthMatch[1]);
|
|
81
82
|
const month = Number(monthMatch[2]);
|
|
82
|
-
if (month >= 1 && month <= 12)
|
|
83
|
+
if (year >= 1 && year <= 9999 && month >= 1 && month <= 12) {
|
|
83
84
|
return `${monthMatch[1]}-${String(month).padStart(2, "0")}`;
|
|
85
|
+
}
|
|
84
86
|
}
|
|
85
87
|
const parsed = parseDate(text);
|
|
86
88
|
if (!parsed)
|
|
@@ -471,28 +473,12 @@
|
|
|
471
473
|
...canContinue ? {} : { close: true }
|
|
472
474
|
};
|
|
473
475
|
}
|
|
474
|
-
|
|
475
|
-
if (!isDate(date))
|
|
476
|
-
throw new TypeError(`Invalid range activation: ${date}`);
|
|
477
|
-
if (!this.complete || !editable(endpoint))
|
|
478
|
-
return this._refuse(endpoint);
|
|
479
|
-
const { start, end } = this;
|
|
480
|
-
const previous = endpoint === "start" ? start : end;
|
|
481
|
-
const target = endpoint === "start" ? earlier(date, end) : later(date, start);
|
|
482
|
-
return {
|
|
483
|
-
status: "complete",
|
|
484
|
-
endpoint,
|
|
485
|
-
changedEndpoints: target === previous ? [] : [endpoint],
|
|
486
|
-
range: endpoint === "start" ? { start: target, end } : { start, end: target },
|
|
487
|
-
activeEndpoint: endpoint
|
|
488
|
-
};
|
|
489
|
-
}
|
|
490
|
-
previewRange(date, endpoint = "", editable = () => true) {
|
|
476
|
+
previewRange(date, editable = () => true) {
|
|
491
477
|
if (!isDate(date))
|
|
492
478
|
return null;
|
|
493
|
-
if (
|
|
479
|
+
if (Boolean(this.start) === Boolean(this.end))
|
|
494
480
|
return null;
|
|
495
|
-
const transition =
|
|
481
|
+
const transition = this.project(date, editable);
|
|
496
482
|
if (transition.status === "refused")
|
|
497
483
|
return null;
|
|
498
484
|
const { start, end } = transition.range;
|
|
@@ -511,23 +497,6 @@
|
|
|
511
497
|
activate(date, editable = () => true) {
|
|
512
498
|
return this._apply(this.project(date, editable));
|
|
513
499
|
}
|
|
514
|
-
moveEndpoint(date, endpoint, editable = () => true) {
|
|
515
|
-
return this._apply(this.projectEndpoint(date, endpoint, editable));
|
|
516
|
-
}
|
|
517
|
-
}
|
|
518
|
-
function later(a, b) {
|
|
519
|
-
if (!a)
|
|
520
|
-
return b;
|
|
521
|
-
if (!b)
|
|
522
|
-
return a;
|
|
523
|
-
return compareDates(a, b) >= 0 ? a : b;
|
|
524
|
-
}
|
|
525
|
-
function earlier(a, b) {
|
|
526
|
-
if (!a)
|
|
527
|
-
return b;
|
|
528
|
-
if (!b)
|
|
529
|
-
return a;
|
|
530
|
-
return compareDates(a, b) <= 0 ? a : b;
|
|
531
500
|
}
|
|
532
501
|
|
|
533
502
|
// src/intl.js
|
|
@@ -742,6 +711,17 @@
|
|
|
742
711
|
};
|
|
743
712
|
}
|
|
744
713
|
|
|
714
|
+
// src/session.js
|
|
715
|
+
function createSession() {
|
|
716
|
+
return new AbortController;
|
|
717
|
+
}
|
|
718
|
+
function guard(signal, callback) {
|
|
719
|
+
return () => {
|
|
720
|
+
if (!signal.aborted)
|
|
721
|
+
callback();
|
|
722
|
+
};
|
|
723
|
+
}
|
|
724
|
+
|
|
745
725
|
// src/source.js
|
|
746
726
|
function normalizeDateStates(payload) {
|
|
747
727
|
const raw = payload && typeof payload === "object" && !Array.isArray(payload) && "dates" in payload ? payload.dates : payload;
|
|
@@ -849,7 +829,10 @@
|
|
|
849
829
|
this._id = `date-calendar-${++uid}`;
|
|
850
830
|
this._model = new CalendarModel;
|
|
851
831
|
this._connected = false;
|
|
832
|
+
this._session = null;
|
|
852
833
|
this._rendering = false;
|
|
834
|
+
this._heading = null;
|
|
835
|
+
this._renderRoot = null;
|
|
853
836
|
this._source = null;
|
|
854
837
|
this._hostIntent = null;
|
|
855
838
|
this._sourceStates = new Map;
|
|
@@ -876,6 +859,7 @@
|
|
|
876
859
|
connectedCallback() {
|
|
877
860
|
if (this._connected)
|
|
878
861
|
return;
|
|
862
|
+
this._session = createSession();
|
|
879
863
|
upgradeProperties(this, [
|
|
880
864
|
"locale",
|
|
881
865
|
"min",
|
|
@@ -895,7 +879,10 @@
|
|
|
895
879
|
"value",
|
|
896
880
|
"display"
|
|
897
881
|
]);
|
|
882
|
+
this._normalizeAttributes();
|
|
898
883
|
this._syncModel();
|
|
884
|
+
if (this.hasAttribute("display"))
|
|
885
|
+
this._reflect("display", this._model.display);
|
|
899
886
|
upgradeProperties(this, ["focusedDate"]);
|
|
900
887
|
this._stopDefaultControlClasses = subscribeDefaultControlClasses(() => {
|
|
901
888
|
if (usesDefaultControlClasses(this._controlClasses))
|
|
@@ -906,10 +893,11 @@
|
|
|
906
893
|
this.render();
|
|
907
894
|
});
|
|
908
895
|
this._connected = true;
|
|
909
|
-
|
|
910
|
-
this.addEventListener("
|
|
911
|
-
this.addEventListener("
|
|
912
|
-
this.addEventListener("
|
|
896
|
+
const { signal } = this._session;
|
|
897
|
+
this.addEventListener("click", this._onClick, { signal });
|
|
898
|
+
this.addEventListener("change", this._onChange, { signal });
|
|
899
|
+
this.addEventListener("keydown", this._onKeyDown, { signal });
|
|
900
|
+
this.addEventListener("focusin", this._onFocusIn, { signal });
|
|
913
901
|
this.render();
|
|
914
902
|
}
|
|
915
903
|
disconnectedCallback() {
|
|
@@ -922,17 +910,55 @@
|
|
|
922
910
|
this._loadController = null;
|
|
923
911
|
this._loadingKey = "";
|
|
924
912
|
this._loadingPromise = null;
|
|
925
|
-
this.
|
|
926
|
-
this.
|
|
927
|
-
this.
|
|
928
|
-
|
|
913
|
+
this.removeAttribute("data-loading");
|
|
914
|
+
this._session?.abort();
|
|
915
|
+
this._session = null;
|
|
916
|
+
}
|
|
917
|
+
_normalizeAttributes() {
|
|
918
|
+
const value = this.getAttribute("value");
|
|
919
|
+
if (value && !isDate(value))
|
|
920
|
+
this.removeAttribute("value");
|
|
921
|
+
for (const name of ["min", "max"]) {
|
|
922
|
+
const raw = this.getAttribute(name);
|
|
923
|
+
if (raw && !isDate(raw))
|
|
924
|
+
this.removeAttribute(name);
|
|
925
|
+
}
|
|
929
926
|
}
|
|
930
|
-
attributeChangedCallback() {
|
|
931
|
-
if (
|
|
927
|
+
attributeChangedCallback(name, _oldValue, newValue) {
|
|
928
|
+
if (this._rendering)
|
|
929
|
+
return;
|
|
930
|
+
if (!this._connected)
|
|
931
|
+
return;
|
|
932
|
+
if (name === "value" && newValue && !isDate(newValue)) {
|
|
933
|
+
this._reflect("value", this._model.value);
|
|
934
|
+
return;
|
|
935
|
+
}
|
|
936
|
+
if ((name === "min" || name === "max") && newValue && !isDate(newValue)) {
|
|
937
|
+
this._reflect(name, "");
|
|
938
|
+
if (this._connected) {
|
|
939
|
+
this._syncModel();
|
|
940
|
+
this.render();
|
|
941
|
+
}
|
|
932
942
|
return;
|
|
943
|
+
}
|
|
944
|
+
if (name === "display" && newValue) {
|
|
945
|
+
try {
|
|
946
|
+
if (monthKey(newValue) !== newValue)
|
|
947
|
+
throw new TypeError("Non-canonical month");
|
|
948
|
+
} catch {
|
|
949
|
+
this._reflect("display", this._model.display);
|
|
950
|
+
return;
|
|
951
|
+
}
|
|
952
|
+
}
|
|
933
953
|
this._syncModel();
|
|
934
954
|
this.render();
|
|
935
955
|
}
|
|
956
|
+
_queueFocus(callback) {
|
|
957
|
+
const session = this._session;
|
|
958
|
+
if (!session)
|
|
959
|
+
return;
|
|
960
|
+
queueMicrotask(guard(session.signal, callback));
|
|
961
|
+
}
|
|
936
962
|
get locale() {
|
|
937
963
|
return resolveLocale(this.getAttribute("locale") || "");
|
|
938
964
|
}
|
|
@@ -1220,11 +1246,9 @@
|
|
|
1220
1246
|
} finally {
|
|
1221
1247
|
if (this._loadController === controller) {
|
|
1222
1248
|
this._loadController = null;
|
|
1223
|
-
this.removeAttribute("data-loading");
|
|
1224
|
-
}
|
|
1225
|
-
if (this._loadingKey === key) {
|
|
1226
1249
|
this._loadingKey = "";
|
|
1227
1250
|
this._loadingPromise = null;
|
|
1251
|
+
this.removeAttribute("data-loading");
|
|
1228
1252
|
}
|
|
1229
1253
|
}
|
|
1230
1254
|
})();
|
|
@@ -1273,7 +1297,7 @@
|
|
|
1273
1297
|
this._moveFocusDom(previousFocused, this._model.focused, moveFocus);
|
|
1274
1298
|
}
|
|
1275
1299
|
if (moveFocus)
|
|
1276
|
-
|
|
1300
|
+
this._queueFocus(() => this.focusGrid());
|
|
1277
1301
|
}
|
|
1278
1302
|
_moveFocusDom(previous, next, moveFocus = true) {
|
|
1279
1303
|
const prevCell = previous ? this.querySelector(`.dp-day[data-date="${CSS.escape(previous)}"]`) : null;
|
|
@@ -1357,6 +1381,9 @@
|
|
|
1357
1381
|
target.focus();
|
|
1358
1382
|
}
|
|
1359
1383
|
async activateDate(date) {
|
|
1384
|
+
if (!this._connected)
|
|
1385
|
+
return false;
|
|
1386
|
+
const session = this._session;
|
|
1360
1387
|
const hostIntent = this._hostIntent?.date === date ? this._hostIntent.intent : undefined;
|
|
1361
1388
|
this._hostIntent = null;
|
|
1362
1389
|
const tagged = (event) => {
|
|
@@ -1365,6 +1392,8 @@
|
|
|
1365
1392
|
return event;
|
|
1366
1393
|
};
|
|
1367
1394
|
const confirmed = await this.ensureDate(date);
|
|
1395
|
+
if (!session || session.signal.aborted)
|
|
1396
|
+
return false;
|
|
1368
1397
|
const state = this.getDateState(date);
|
|
1369
1398
|
if (!confirmed || state.disabled) {
|
|
1370
1399
|
this.dispatchEvent(tagged(new CustomEvent("dateinvalid", { detail: { date, state }, bubbles: true })));
|
|
@@ -1375,7 +1404,7 @@
|
|
|
1375
1404
|
bubbles: true,
|
|
1376
1405
|
cancelable: true
|
|
1377
1406
|
})));
|
|
1378
|
-
if (!accepted)
|
|
1407
|
+
if (!accepted || session.signal.aborted)
|
|
1379
1408
|
return false;
|
|
1380
1409
|
if (this.selection === "single") {
|
|
1381
1410
|
const previousValue = this._model.value;
|
|
@@ -1549,8 +1578,20 @@
|
|
|
1549
1578
|
<select id="${this._id}-month" class="dp-month-select ${monthClass}" aria-label="${escapeHtml(this.messages.month)}">${monthOptions}</select>`;
|
|
1550
1579
|
const yearControl = `<label class="dp-visually-hidden" for="${this._id}-year">${escapeHtml(this.messages.year)}</label>
|
|
1551
1580
|
<input id="${this._id}-year" class="dp-year-input ${yearClass}" type="number" inputmode="numeric" value="${displayYear}"${minYearAttr}${maxYearAttr} aria-label="${escapeHtml(this.messages.year)}">`;
|
|
1581
|
+
if (!this._heading?.isConnected || !this._renderRoot?.isConnected) {
|
|
1582
|
+
this.replaceChildren();
|
|
1583
|
+
const heading = document.createElement("h2");
|
|
1584
|
+
heading.id = headingId;
|
|
1585
|
+
heading.className = "dp-calendar-heading dp-visually-hidden";
|
|
1586
|
+
heading.setAttribute("aria-live", "polite");
|
|
1587
|
+
const renderRoot = document.createElement("div");
|
|
1588
|
+
renderRoot.className = "dp-calendar-render";
|
|
1589
|
+
this.append(heading, renderRoot);
|
|
1590
|
+
this._heading = heading;
|
|
1591
|
+
this._renderRoot = renderRoot;
|
|
1592
|
+
}
|
|
1552
1593
|
this._rendering = true;
|
|
1553
|
-
this.innerHTML = `
|
|
1594
|
+
this._renderRoot.innerHTML = `
|
|
1554
1595
|
<div class="dp-calendar-shell">
|
|
1555
1596
|
<div class="dp-calendar-header">
|
|
1556
1597
|
${yearFirst ? yearControl : monthControl}
|
|
@@ -1558,17 +1599,17 @@
|
|
|
1558
1599
|
<button type="button" class="dp-nav dp-prev ${navClass}" data-calendar-action="previous" aria-label="${escapeHtml(this.messages.previousMonth)}"${prevDisabled ? " disabled" : ""}><svg aria-hidden="true" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="m4 10 4-4 4 4"/></svg></button>
|
|
1559
1600
|
<button type="button" class="dp-nav dp-next ${navClass}" data-calendar-action="next" aria-label="${escapeHtml(this.messages.nextMonth)}"${nextDisabled ? " disabled" : ""}><svg aria-hidden="true" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"><path d="m4 6 4 4 4-4"/></svg></button>
|
|
1560
1601
|
</div>
|
|
1561
|
-
<h2 id="${headingId}" class="dp-calendar-heading dp-visually-hidden" aria-live="polite">${escapeHtml(formatMonthYear(`${display}-15`, locale))}</h2>
|
|
1562
1602
|
<table id="${gridId}" class="dp-grid" role="grid" aria-labelledby="${headingId}">
|
|
1563
1603
|
<thead><tr>${weekHeader}${dayHeaders}</tr></thead>
|
|
1564
1604
|
<tbody>${rows}</tbody>
|
|
1565
1605
|
</table>
|
|
1566
1606
|
</div>`;
|
|
1607
|
+
this._heading.textContent = formatMonthYear(`${display}-15`, locale);
|
|
1567
1608
|
this._rendering = false;
|
|
1568
1609
|
this._paintedRange = { ...this._highlightedRange };
|
|
1569
1610
|
this._paintedPreview = this.hasAttribute("data-range-preview");
|
|
1570
1611
|
if (focusKey) {
|
|
1571
|
-
|
|
1612
|
+
this._queueFocus(() => {
|
|
1572
1613
|
let selector = focusKey;
|
|
1573
1614
|
if (selector.startsWith(".dp-day[data-date=")) {
|
|
1574
1615
|
selector = `.dp-day[data-date="${CSS.escape(this._model.focused)}"]`;
|
|
@@ -1982,6 +2023,7 @@
|
|
|
1982
2023
|
this.canonical = "";
|
|
1983
2024
|
this._dirty = false;
|
|
1984
2025
|
this._commitId = 0;
|
|
2026
|
+
this._session = createSession();
|
|
1985
2027
|
this._originalName = input.getAttribute("name") || "";
|
|
1986
2028
|
this._attributeObserver = null;
|
|
1987
2029
|
this.onAttributesChanged = null;
|
|
@@ -2084,34 +2126,41 @@
|
|
|
2084
2126
|
async commit(options = {}) {
|
|
2085
2127
|
const input = this.input;
|
|
2086
2128
|
const commitId = ++this._commitId;
|
|
2129
|
+
const session = this._session;
|
|
2130
|
+
if (session.signal.aborted)
|
|
2131
|
+
return { status: "stale", commitId };
|
|
2087
2132
|
const text = input.value.trim();
|
|
2088
2133
|
if (!text) {
|
|
2089
2134
|
if (commitId !== this._commitId)
|
|
2090
|
-
return { status: "stale" };
|
|
2135
|
+
return { status: "stale", commitId };
|
|
2091
2136
|
input.setCustomValidity("");
|
|
2092
|
-
return { status: "clear", value: "" };
|
|
2137
|
+
return { status: "clear", value: "", commitId };
|
|
2093
2138
|
}
|
|
2094
2139
|
const parsed = this.adapter.parse(text);
|
|
2095
2140
|
if (!parsed) {
|
|
2096
2141
|
if (commitId !== this._commitId)
|
|
2097
|
-
return { status: "stale" };
|
|
2142
|
+
return { status: "stale", commitId };
|
|
2098
2143
|
if (this.hidden)
|
|
2099
2144
|
this.hidden.value = "";
|
|
2100
2145
|
input.setCustomValidity(this.messages.invalidDate);
|
|
2101
|
-
return { status: "invalid" };
|
|
2146
|
+
return { status: "invalid", commitId };
|
|
2102
2147
|
}
|
|
2103
2148
|
if (this.confirm) {
|
|
2104
2149
|
const result = await this.confirm(parsed, options);
|
|
2105
|
-
if (commitId !== this._commitId)
|
|
2106
|
-
return { status: "stale" };
|
|
2150
|
+
if (session.signal.aborted || commitId !== this._commitId) {
|
|
2151
|
+
return { status: "stale", commitId };
|
|
2152
|
+
}
|
|
2107
2153
|
if (!result?.ok) {
|
|
2108
2154
|
if (this.hidden)
|
|
2109
2155
|
this.hidden.value = "";
|
|
2110
2156
|
input.setCustomValidity(result?.message || this.messages.unavailableDate);
|
|
2111
|
-
return { status: "invalid" };
|
|
2157
|
+
return { status: "invalid", commitId };
|
|
2112
2158
|
}
|
|
2113
2159
|
}
|
|
2114
|
-
return { status: "ok", value: parsed };
|
|
2160
|
+
return { status: "ok", value: parsed, commitId };
|
|
2161
|
+
}
|
|
2162
|
+
isCommitCurrent(commitId) {
|
|
2163
|
+
return commitId === this._commitId;
|
|
2115
2164
|
}
|
|
2116
2165
|
setCanonical(value, options = {}) {
|
|
2117
2166
|
const next = value || "";
|
|
@@ -2132,6 +2181,8 @@
|
|
|
2132
2181
|
return parsed && isDate(parsed) ? parsed : "";
|
|
2133
2182
|
}
|
|
2134
2183
|
teardown() {
|
|
2184
|
+
this.dirty();
|
|
2185
|
+
this._session.abort();
|
|
2135
2186
|
this._attributeObserver?.disconnect();
|
|
2136
2187
|
this._attributeObserver = null;
|
|
2137
2188
|
const hiddenName = this.hidden?.getAttribute("name") || this._originalName;
|
|
@@ -2173,7 +2224,6 @@
|
|
|
2173
2224
|
|
|
2174
2225
|
// src/date-picker.js
|
|
2175
2226
|
var uid2 = 0;
|
|
2176
|
-
var DRAG_THRESHOLD = 4;
|
|
2177
2227
|
|
|
2178
2228
|
class DatePickerElement extends HTMLElement {
|
|
2179
2229
|
static observedAttributes = ["value", "locale", "min", "max", "open-on-focus", "month-format"];
|
|
@@ -2205,8 +2255,6 @@
|
|
|
2205
2255
|
this._lastFocusEndpoint = "";
|
|
2206
2256
|
this._activationId = 0;
|
|
2207
2257
|
this._previewDate = "";
|
|
2208
|
-
this._drag = null;
|
|
2209
|
-
this._suppressGridClick = false;
|
|
2210
2258
|
this._buttons = [];
|
|
2211
2259
|
this._returnFocus = null;
|
|
2212
2260
|
this._panel = null;
|
|
@@ -2214,8 +2262,8 @@
|
|
|
2214
2262
|
this._originalDescribedBy = "";
|
|
2215
2263
|
this._rangeOriginalDescribedBy = ["", ""];
|
|
2216
2264
|
this._formatHint = null;
|
|
2217
|
-
this.
|
|
2218
|
-
this.
|
|
2265
|
+
this._generatedPlaceholders = new WeakSet;
|
|
2266
|
+
this._session = null;
|
|
2219
2267
|
this._stopTracking = null;
|
|
2220
2268
|
this._open = false;
|
|
2221
2269
|
this._suppressFocusOpen = false;
|
|
@@ -2234,6 +2282,7 @@
|
|
|
2234
2282
|
connectedCallback() {
|
|
2235
2283
|
if (this._connected)
|
|
2236
2284
|
return;
|
|
2285
|
+
this._session = createSession();
|
|
2237
2286
|
upgradeProperties(this, [
|
|
2238
2287
|
"locale",
|
|
2239
2288
|
"min",
|
|
@@ -2248,17 +2297,31 @@
|
|
|
2248
2297
|
"renderDay",
|
|
2249
2298
|
"isDateDisabled"
|
|
2250
2299
|
]);
|
|
2300
|
+
this._normalizeAttributes();
|
|
2251
2301
|
if (this.hasAttribute("range"))
|
|
2252
2302
|
this._connectRange();
|
|
2253
2303
|
else
|
|
2254
2304
|
this._connectSingle();
|
|
2255
|
-
if (this._connected) {
|
|
2256
|
-
|
|
2257
|
-
this.
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2305
|
+
if (!this._connected) {
|
|
2306
|
+
this._session.abort();
|
|
2307
|
+
this._session = null;
|
|
2308
|
+
return;
|
|
2309
|
+
}
|
|
2310
|
+
upgradeProperties(this, ["value", "range"]);
|
|
2311
|
+
this._stopDefaultMessages = subscribeDefaultMessages(() => {
|
|
2312
|
+
if (this._messages === null)
|
|
2313
|
+
this._refreshMessages();
|
|
2314
|
+
});
|
|
2315
|
+
this.validate();
|
|
2316
|
+
}
|
|
2317
|
+
_normalizeAttributes() {
|
|
2318
|
+
const value = this.getAttribute("value");
|
|
2319
|
+
if (value && !isDate(value))
|
|
2320
|
+
this.removeAttribute("value");
|
|
2321
|
+
for (const name of ["min", "max"]) {
|
|
2322
|
+
const raw = this.getAttribute(name);
|
|
2323
|
+
if (raw && !isDate(raw))
|
|
2324
|
+
this.removeAttribute(name);
|
|
2262
2325
|
}
|
|
2263
2326
|
}
|
|
2264
2327
|
_connectSingle() {
|
|
@@ -2368,9 +2431,10 @@
|
|
|
2368
2431
|
this._stopDefaultMessages?.();
|
|
2369
2432
|
this._stopDefaultMessages = null;
|
|
2370
2433
|
this._connected = false;
|
|
2434
|
+
this._suppressFocusOpen = false;
|
|
2371
2435
|
this.hide(false);
|
|
2372
|
-
this.
|
|
2373
|
-
this.
|
|
2436
|
+
this._session?.abort();
|
|
2437
|
+
this._session = null;
|
|
2374
2438
|
this._clearTimeOrderValidity();
|
|
2375
2439
|
this._timeFields = [null, null];
|
|
2376
2440
|
if (this._rangeMode()) {
|
|
@@ -2408,8 +2472,22 @@
|
|
|
2408
2472
|
input.removeAttribute("aria-controls");
|
|
2409
2473
|
}
|
|
2410
2474
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
2411
|
-
if (
|
|
2475
|
+
if (this._reflecting || oldValue === newValue)
|
|
2476
|
+
return;
|
|
2477
|
+
if (!this._connected)
|
|
2412
2478
|
return;
|
|
2479
|
+
if (name === "value" && newValue && !isDate(newValue)) {
|
|
2480
|
+
this._reflectValue(this._value);
|
|
2481
|
+
return;
|
|
2482
|
+
}
|
|
2483
|
+
if ((name === "min" || name === "max") && newValue && !isDate(newValue)) {
|
|
2484
|
+
this.removeAttribute(name);
|
|
2485
|
+
if (this._connected) {
|
|
2486
|
+
this._syncCalendarOptions();
|
|
2487
|
+
this.validate();
|
|
2488
|
+
}
|
|
2489
|
+
return;
|
|
2490
|
+
}
|
|
2413
2491
|
if (name === "value") {
|
|
2414
2492
|
if (this._rangeMode())
|
|
2415
2493
|
return;
|
|
@@ -2605,7 +2683,6 @@
|
|
|
2605
2683
|
const field = this._fields[index];
|
|
2606
2684
|
button.disabled = Boolean(field?.input.disabled || field?.input.readOnly);
|
|
2607
2685
|
}
|
|
2608
|
-
this._syncDragAffordance();
|
|
2609
2686
|
const active = this._range?.activeEndpoint === "end" ? 1 : 0;
|
|
2610
2687
|
const activeInput = this._fields[active]?.input;
|
|
2611
2688
|
if (this._open && activeInput && !isEditable(activeInput))
|
|
@@ -2694,10 +2771,10 @@
|
|
|
2694
2771
|
if (!(event.target instanceof HTMLFormElement) || !input || event.target !== input.form)
|
|
2695
2772
|
return;
|
|
2696
2773
|
this.hide(false);
|
|
2697
|
-
queueMicrotask(() => {
|
|
2774
|
+
queueMicrotask(guard(signal, () => {
|
|
2698
2775
|
if (!event.defaultPrevented)
|
|
2699
2776
|
restore();
|
|
2700
|
-
});
|
|
2777
|
+
}));
|
|
2701
2778
|
}, { capture: true, signal });
|
|
2702
2779
|
this.addEventListener("keydown", (event) => this._onEscape(event), { signal });
|
|
2703
2780
|
}
|
|
@@ -2707,9 +2784,10 @@
|
|
|
2707
2784
|
const calendar = this._calendar;
|
|
2708
2785
|
if (!input || !button || !calendar)
|
|
2709
2786
|
return;
|
|
2710
|
-
const
|
|
2711
|
-
|
|
2712
|
-
|
|
2787
|
+
const session = this._session;
|
|
2788
|
+
if (!session)
|
|
2789
|
+
return;
|
|
2790
|
+
const { signal } = session;
|
|
2713
2791
|
input.addEventListener("input", () => {
|
|
2714
2792
|
this._field?.handleInput();
|
|
2715
2793
|
}, { signal });
|
|
@@ -2737,7 +2815,7 @@
|
|
|
2737
2815
|
button.addEventListener("click", (event) => {
|
|
2738
2816
|
if (this._open) {
|
|
2739
2817
|
if (event.detail === 0) {
|
|
2740
|
-
|
|
2818
|
+
this._defer(() => this._calendar?.focusGrid());
|
|
2741
2819
|
return;
|
|
2742
2820
|
}
|
|
2743
2821
|
this.hide(false);
|
|
@@ -2758,7 +2836,7 @@
|
|
|
2758
2836
|
return;
|
|
2759
2837
|
const intent = activationIntents.get(custom);
|
|
2760
2838
|
queueMicrotask(() => {
|
|
2761
|
-
if (
|
|
2839
|
+
if (signal.aborted || custom.defaultPrevented)
|
|
2762
2840
|
return;
|
|
2763
2841
|
if (intent && intent.id !== this._activationId)
|
|
2764
2842
|
return;
|
|
@@ -2777,9 +2855,10 @@
|
|
|
2777
2855
|
const calendar = this._calendar;
|
|
2778
2856
|
if (!this._fields || !this._buttons.length || !calendar)
|
|
2779
2857
|
return;
|
|
2780
|
-
const
|
|
2781
|
-
|
|
2782
|
-
|
|
2858
|
+
const session = this._session;
|
|
2859
|
+
if (!session)
|
|
2860
|
+
return;
|
|
2861
|
+
const { signal } = session;
|
|
2783
2862
|
for (const [index, field] of this._fields.entries()) {
|
|
2784
2863
|
const endpoint = index === 1 ? "end" : "start";
|
|
2785
2864
|
field.input.addEventListener("input", () => {
|
|
@@ -2805,12 +2884,6 @@
|
|
|
2805
2884
|
});
|
|
2806
2885
|
}
|
|
2807
2886
|
calendar.addEventListener("click", (event) => {
|
|
2808
|
-
if (this._suppressGridClick) {
|
|
2809
|
-
this._suppressGridClick = false;
|
|
2810
|
-
event.preventDefault();
|
|
2811
|
-
event.stopImmediatePropagation();
|
|
2812
|
-
return;
|
|
2813
|
-
}
|
|
2814
2887
|
this._captureGridIntent(event);
|
|
2815
2888
|
}, { capture: true, signal });
|
|
2816
2889
|
calendar.addEventListener("keydown", (event) => this._captureGridIntent(event), {
|
|
@@ -2823,13 +2896,13 @@
|
|
|
2823
2896
|
if (!isDate(date))
|
|
2824
2897
|
return;
|
|
2825
2898
|
queueMicrotask(() => {
|
|
2826
|
-
if (
|
|
2899
|
+
if (signal.aborted || custom.defaultPrevented || !this._range)
|
|
2827
2900
|
return;
|
|
2828
2901
|
const intent = activationIntents.get(custom);
|
|
2829
2902
|
if (intent === undefined || intent.id !== this._activationId)
|
|
2830
2903
|
return;
|
|
2831
2904
|
const editable = (bound) => this._boundEditable(bound);
|
|
2832
|
-
const result =
|
|
2905
|
+
const result = this._range.activate(date, editable);
|
|
2833
2906
|
if (result.status === "refused") {
|
|
2834
2907
|
this._calendar?.dispatchEvent(new CustomEvent("dateinvalid", {
|
|
2835
2908
|
detail: { date, state: this._calendar.getDateState(date) },
|
|
@@ -2838,8 +2911,6 @@
|
|
|
2838
2911
|
return;
|
|
2839
2912
|
}
|
|
2840
2913
|
this._applyRangeTransition(result);
|
|
2841
|
-
if (intent.endpoint)
|
|
2842
|
-
return;
|
|
2843
2914
|
if (result.close || result.status === "complete") {
|
|
2844
2915
|
this.hide(false);
|
|
2845
2916
|
this._focusField(result.endpoint);
|
|
@@ -2849,11 +2920,6 @@
|
|
|
2849
2920
|
calendar.addEventListener("datefocus", (event) => this._onGridDateFocus(event), { signal });
|
|
2850
2921
|
calendar.addEventListener("pointerover", (event) => this._onGridPointerOver(event), { signal });
|
|
2851
2922
|
calendar.addEventListener("pointerleave", () => this._onGridPointerLeave(), { signal });
|
|
2852
|
-
calendar.addEventListener("pointerdown", (event) => this._onGridPointerDown(event), { signal });
|
|
2853
|
-
calendar.addEventListener("pointermove", (event) => this._onGridPointerMove(event), { signal });
|
|
2854
|
-
calendar.addEventListener("pointerup", (event) => this._onGridPointerUp(event), { signal });
|
|
2855
|
-
calendar.addEventListener("pointercancel", (event) => this._onGridPointerCancel(event), { signal });
|
|
2856
|
-
calendar.addEventListener("lostpointercapture", (event) => this._onGridPointerCancel(event), { signal });
|
|
2857
2923
|
calendar.addEventListener("dateloadend", () => void this.validate(), { signal });
|
|
2858
2924
|
this._bindPopup(signal, this._fields?.[0]?.input, () => this._restoreRangeDefault());
|
|
2859
2925
|
}
|
|
@@ -2876,7 +2942,7 @@
|
|
|
2876
2942
|
}
|
|
2877
2943
|
if (event.detail === 0) {
|
|
2878
2944
|
this._activateRangeEndpoint(endpoint);
|
|
2879
|
-
|
|
2945
|
+
this._defer(() => this._calendar?.focusGrid());
|
|
2880
2946
|
return;
|
|
2881
2947
|
}
|
|
2882
2948
|
if (endpoint !== this._range?.activeEndpoint) {
|
|
@@ -2892,7 +2958,7 @@
|
|
|
2892
2958
|
if (this._open) {
|
|
2893
2959
|
if (this._rangeMode() && endpoint)
|
|
2894
2960
|
this._activateRangeEndpoint(endpoint);
|
|
2895
|
-
|
|
2961
|
+
this._defer(() => this._calendar?.focusGrid());
|
|
2896
2962
|
return;
|
|
2897
2963
|
}
|
|
2898
2964
|
if (this._rangeMode())
|
|
@@ -2908,7 +2974,7 @@
|
|
|
2908
2974
|
this._range?.focus(endpoint);
|
|
2909
2975
|
}
|
|
2910
2976
|
if (this._open) {
|
|
2911
|
-
|
|
2977
|
+
this._defer(() => this._calendar?.focusGrid());
|
|
2912
2978
|
} else {
|
|
2913
2979
|
this.show();
|
|
2914
2980
|
}
|
|
@@ -2942,20 +3008,18 @@
|
|
|
2942
3008
|
if (key !== "Enter" && key !== " ")
|
|
2943
3009
|
return;
|
|
2944
3010
|
}
|
|
2945
|
-
if (event.type === "click" && this._suppressGridClick)
|
|
2946
|
-
return;
|
|
2947
3011
|
if (!(event.target instanceof Element))
|
|
2948
3012
|
return;
|
|
2949
3013
|
const cell = event.target.closest(".dp-day[data-date]");
|
|
2950
3014
|
const date = cell?.getAttribute("data-date") || "";
|
|
2951
3015
|
if (!isDate(date))
|
|
2952
3016
|
return;
|
|
2953
|
-
this._attachIntent(date
|
|
3017
|
+
this._attachIntent(date);
|
|
2954
3018
|
}
|
|
2955
|
-
_attachIntent(date
|
|
3019
|
+
_attachIntent(date) {
|
|
2956
3020
|
if (!this._calendar)
|
|
2957
3021
|
return;
|
|
2958
|
-
this._calendar._hostIntent = { date, intent: { id: ++this._activationId
|
|
3022
|
+
this._calendar._hostIntent = { date, intent: { id: ++this._activationId } };
|
|
2959
3023
|
}
|
|
2960
3024
|
_supersedeActivations() {
|
|
2961
3025
|
this._activationId++;
|
|
@@ -2988,12 +3052,12 @@
|
|
|
2988
3052
|
field.input.dispatchEvent(new Event("change", { bubbles: true }));
|
|
2989
3053
|
}
|
|
2990
3054
|
}
|
|
2991
|
-
_setPreview(date
|
|
3055
|
+
_setPreview(date) {
|
|
2992
3056
|
const calendar = this._calendar;
|
|
2993
3057
|
if (!calendar || !this._range || !this._open)
|
|
2994
3058
|
return;
|
|
2995
3059
|
const candidate = isDate(date) && !calendar.getDateState(date).disabled ? date : "";
|
|
2996
|
-
const preview = candidate ? this._range.previewRange(candidate,
|
|
3060
|
+
const preview = candidate ? this._range.previewRange(candidate, (bound) => this._boundEditable(bound)) : null;
|
|
2997
3061
|
if (!preview) {
|
|
2998
3062
|
this._clearPreview();
|
|
2999
3063
|
return;
|
|
@@ -3008,23 +3072,17 @@
|
|
|
3008
3072
|
this._syncHighlight();
|
|
3009
3073
|
}
|
|
3010
3074
|
_onGridDateFocus(event) {
|
|
3011
|
-
if (this._drag)
|
|
3012
|
-
return;
|
|
3013
3075
|
const date = event.detail?.date;
|
|
3014
3076
|
if (isDate(date))
|
|
3015
3077
|
this._setPreview(date);
|
|
3016
3078
|
}
|
|
3017
3079
|
_onGridPointerOver(event) {
|
|
3018
3080
|
const pointer = event;
|
|
3019
|
-
if (
|
|
3081
|
+
if (pointer.pointerType === "touch")
|
|
3020
3082
|
return;
|
|
3021
3083
|
this._setPreview(this._cellDate(pointer.target));
|
|
3022
3084
|
}
|
|
3023
3085
|
_onGridPointerLeave() {
|
|
3024
|
-
if (this._drag?.active === false)
|
|
3025
|
-
this._drag = null;
|
|
3026
|
-
if (this._drag)
|
|
3027
|
-
return;
|
|
3028
3086
|
this._clearPreview();
|
|
3029
3087
|
}
|
|
3030
3088
|
_cellDate(target) {
|
|
@@ -3032,116 +3090,6 @@
|
|
|
3032
3090
|
const date = cell?.getAttribute("data-date") || "";
|
|
3033
3091
|
return isDate(date) ? date : "";
|
|
3034
3092
|
}
|
|
3035
|
-
_dateAtPoint(x, y) {
|
|
3036
|
-
const element = this.ownerDocument.elementFromPoint(x, y);
|
|
3037
|
-
if (!(element instanceof Element) || !this._calendar?.contains(element))
|
|
3038
|
-
return "";
|
|
3039
|
-
return this._cellDate(element);
|
|
3040
|
-
}
|
|
3041
|
-
_onGridPointerDown(event) {
|
|
3042
|
-
const pointer = event;
|
|
3043
|
-
this._suppressGridClick = false;
|
|
3044
|
-
if (this._drag?.active === false)
|
|
3045
|
-
this._drag = null;
|
|
3046
|
-
if (!this._open || !this._range || this._drag)
|
|
3047
|
-
return;
|
|
3048
|
-
if (!pointer.isPrimary || pointer.button !== 0)
|
|
3049
|
-
return;
|
|
3050
|
-
if (pointer.pointerType !== "mouse" && pointer.pointerType !== "pen")
|
|
3051
|
-
return;
|
|
3052
|
-
if (!this._range.complete)
|
|
3053
|
-
return;
|
|
3054
|
-
const cell = pointer.target instanceof Element ? pointer.target.closest(".dp-day[data-date]") : null;
|
|
3055
|
-
if (!(cell instanceof HTMLElement))
|
|
3056
|
-
return;
|
|
3057
|
-
const isStart = cell.hasAttribute("data-range-start");
|
|
3058
|
-
const isEnd = cell.hasAttribute("data-range-end");
|
|
3059
|
-
if (isStart === isEnd)
|
|
3060
|
-
return;
|
|
3061
|
-
const endpoint = isStart ? "start" : "end";
|
|
3062
|
-
const date = this._cellDate(cell);
|
|
3063
|
-
if (!date || !this._boundEditable(endpoint))
|
|
3064
|
-
return;
|
|
3065
|
-
this._drag = {
|
|
3066
|
-
pointerId: pointer.pointerId,
|
|
3067
|
-
endpoint,
|
|
3068
|
-
x: pointer.clientX,
|
|
3069
|
-
y: pointer.clientY,
|
|
3070
|
-
date,
|
|
3071
|
-
active: false
|
|
3072
|
-
};
|
|
3073
|
-
}
|
|
3074
|
-
_onGridPointerMove(event) {
|
|
3075
|
-
const pointer = event;
|
|
3076
|
-
const drag = this._drag;
|
|
3077
|
-
if (!drag || pointer.pointerId !== drag.pointerId)
|
|
3078
|
-
return;
|
|
3079
|
-
if (!drag.active) {
|
|
3080
|
-
const travelled = Math.abs(pointer.clientX - drag.x) > DRAG_THRESHOLD || Math.abs(pointer.clientY - drag.y) > DRAG_THRESHOLD;
|
|
3081
|
-
if (!travelled)
|
|
3082
|
-
return;
|
|
3083
|
-
drag.active = true;
|
|
3084
|
-
try {
|
|
3085
|
-
this._calendar?.setPointerCapture(drag.pointerId);
|
|
3086
|
-
} catch {}
|
|
3087
|
-
this._syncDragAffordance();
|
|
3088
|
-
}
|
|
3089
|
-
const date = this._dateAtPoint(pointer.clientX, pointer.clientY);
|
|
3090
|
-
if (!date || this._calendar?.getDateState(date).disabled)
|
|
3091
|
-
return;
|
|
3092
|
-
drag.date = date;
|
|
3093
|
-
this._setPreview(date, drag.endpoint);
|
|
3094
|
-
}
|
|
3095
|
-
_onGridPointerUp(event) {
|
|
3096
|
-
const pointer = event;
|
|
3097
|
-
const drag = this._drag;
|
|
3098
|
-
if (!drag || pointer.pointerId !== drag.pointerId)
|
|
3099
|
-
return;
|
|
3100
|
-
this._drag = null;
|
|
3101
|
-
this._releaseDragCapture(drag.pointerId);
|
|
3102
|
-
if (!drag.active) {
|
|
3103
|
-
this._syncDragAffordance();
|
|
3104
|
-
return;
|
|
3105
|
-
}
|
|
3106
|
-
this._suppressGridClick = true;
|
|
3107
|
-
const transition = this._range?.projectEndpoint(drag.date, drag.endpoint, (bound) => this._boundEditable(bound));
|
|
3108
|
-
if (!transition || transition.status === "refused" || !transition.changedEndpoints.length) {
|
|
3109
|
-
this._syncHighlight();
|
|
3110
|
-
return;
|
|
3111
|
-
}
|
|
3112
|
-
const target = drag.endpoint === "start" ? transition.range.start : transition.range.end;
|
|
3113
|
-
this._attachIntent(target, drag.endpoint);
|
|
3114
|
-
this._calendar?.activateDate(target);
|
|
3115
|
-
}
|
|
3116
|
-
_onGridPointerCancel(event) {
|
|
3117
|
-
const pointer = event;
|
|
3118
|
-
const drag = this._drag;
|
|
3119
|
-
if (!drag || pointer.pointerId !== drag.pointerId)
|
|
3120
|
-
return;
|
|
3121
|
-
this._drag = null;
|
|
3122
|
-
this._releaseDragCapture(drag.pointerId);
|
|
3123
|
-
this._syncHighlight();
|
|
3124
|
-
}
|
|
3125
|
-
_releaseDragCapture(pointerId) {
|
|
3126
|
-
const calendar = this._calendar;
|
|
3127
|
-
if (calendar?.hasPointerCapture(pointerId))
|
|
3128
|
-
calendar.releasePointerCapture(pointerId);
|
|
3129
|
-
}
|
|
3130
|
-
_syncDragAffordance() {
|
|
3131
|
-
const calendar = this._calendar;
|
|
3132
|
-
if (!calendar || !this._range)
|
|
3133
|
-
return;
|
|
3134
|
-
if (this._drag?.active) {
|
|
3135
|
-
calendar.setAttribute("data-range-drag", "active");
|
|
3136
|
-
return;
|
|
3137
|
-
}
|
|
3138
|
-
const { start, end } = this._range;
|
|
3139
|
-
const draggable = this._range.complete && start !== end && (this._boundEditable("start") || this._boundEditable("end"));
|
|
3140
|
-
if (draggable)
|
|
3141
|
-
calendar.setAttribute("data-range-drag", "ready");
|
|
3142
|
-
else
|
|
3143
|
-
calendar.removeAttribute("data-range-drag");
|
|
3144
|
-
}
|
|
3145
3093
|
_onEscape(event) {
|
|
3146
3094
|
if (event.key === "Escape" && this._open) {
|
|
3147
3095
|
event.preventDefault();
|
|
@@ -3178,9 +3126,9 @@
|
|
|
3178
3126
|
this._fields[1].setLocale(this.locale);
|
|
3179
3127
|
hint.textContent = `${this.messages.formatHint}: ${this._fields[0].placeholder}`;
|
|
3180
3128
|
for (const [index, field] of this._fields.entries()) {
|
|
3181
|
-
if (!field.input.hasAttribute("placeholder") || this.
|
|
3129
|
+
if (!field.input.hasAttribute("placeholder") || this._generatedPlaceholders.has(field.input)) {
|
|
3182
3130
|
field.input.placeholder = field.placeholder;
|
|
3183
|
-
this.
|
|
3131
|
+
this._generatedPlaceholders.add(field.input);
|
|
3184
3132
|
}
|
|
3185
3133
|
const canonical = index === 1 ? this._range?.end || "" : this._range?.start || "";
|
|
3186
3134
|
if (canonical)
|
|
@@ -3194,9 +3142,9 @@
|
|
|
3194
3142
|
return;
|
|
3195
3143
|
field.setLocale(this.locale);
|
|
3196
3144
|
hint.textContent = `${this.messages.formatHint}: ${field.placeholder}`;
|
|
3197
|
-
if (!field.input.hasAttribute("placeholder") || this.
|
|
3145
|
+
if (!field.input.hasAttribute("placeholder") || this._generatedPlaceholders.has(field.input)) {
|
|
3198
3146
|
field.input.placeholder = field.placeholder;
|
|
3199
|
-
this.
|
|
3147
|
+
this._generatedPlaceholders.add(field.input);
|
|
3200
3148
|
}
|
|
3201
3149
|
if (this._value)
|
|
3202
3150
|
field.input.value = field.format(this._value);
|
|
@@ -3274,11 +3222,15 @@
|
|
|
3274
3222
|
}
|
|
3275
3223
|
async _commitText(emit, options = {}) {
|
|
3276
3224
|
const field = this._field;
|
|
3277
|
-
|
|
3225
|
+
const session = this._session;
|
|
3226
|
+
if (!field || !session)
|
|
3278
3227
|
return false;
|
|
3279
3228
|
if (!options.force && !field.isDirty)
|
|
3280
3229
|
return false;
|
|
3281
3230
|
const result = await field.commit(options);
|
|
3231
|
+
if (session.signal.aborted || !field.isCommitCurrent(result.commitId)) {
|
|
3232
|
+
return false;
|
|
3233
|
+
}
|
|
3282
3234
|
if (result.status === "stale" || result.status === "invalid")
|
|
3283
3235
|
return false;
|
|
3284
3236
|
this._setValue(result.value || "", {
|
|
@@ -3290,13 +3242,16 @@
|
|
|
3290
3242
|
}
|
|
3291
3243
|
async _commitFieldText(which) {
|
|
3292
3244
|
const fields = this._fields;
|
|
3293
|
-
|
|
3245
|
+
const session = this._session;
|
|
3246
|
+
if (!fields || !session)
|
|
3294
3247
|
return false;
|
|
3295
3248
|
const index = which === "end" ? 1 : 0;
|
|
3296
3249
|
const field = fields[index];
|
|
3297
3250
|
if (!field?.isDirty)
|
|
3298
3251
|
return false;
|
|
3299
3252
|
const result = await field.commit();
|
|
3253
|
+
if (session.signal.aborted || !field.isCommitCurrent(result.commitId))
|
|
3254
|
+
return false;
|
|
3300
3255
|
if (result.status === "stale")
|
|
3301
3256
|
return false;
|
|
3302
3257
|
if (result.status === "invalid") {
|
|
@@ -3374,7 +3329,6 @@
|
|
|
3374
3329
|
this._previewDate = "";
|
|
3375
3330
|
this._calendar.removeAttribute("data-range-preview");
|
|
3376
3331
|
this._calendar.highlightedRange = this._displayRange();
|
|
3377
|
-
this._syncDragAffordance();
|
|
3378
3332
|
}
|
|
3379
3333
|
_revalidateRange(which) {
|
|
3380
3334
|
if (!this._fields || !this._range)
|
|
@@ -3423,6 +3377,12 @@
|
|
|
3423
3377
|
input.setCustomValidity("");
|
|
3424
3378
|
this._timeOrderOwned.clear();
|
|
3425
3379
|
}
|
|
3380
|
+
_defer(callback) {
|
|
3381
|
+
const session = this._session;
|
|
3382
|
+
if (!session)
|
|
3383
|
+
return;
|
|
3384
|
+
setTimeout(guard(session.signal, callback), 0);
|
|
3385
|
+
}
|
|
3426
3386
|
_restoreDefault() {
|
|
3427
3387
|
const field = this._field;
|
|
3428
3388
|
if (!field)
|
|
@@ -3459,10 +3419,10 @@
|
|
|
3459
3419
|
if (!input)
|
|
3460
3420
|
return;
|
|
3461
3421
|
this._suppressFocusOpen = true;
|
|
3462
|
-
|
|
3422
|
+
this._defer(() => {
|
|
3463
3423
|
input.focus();
|
|
3464
3424
|
this._suppressFocusOpen = false;
|
|
3465
|
-
}
|
|
3425
|
+
});
|
|
3466
3426
|
}
|
|
3467
3427
|
_restoreFocus() {
|
|
3468
3428
|
const target = this._returnFocus;
|
|
@@ -3470,10 +3430,10 @@
|
|
|
3470
3430
|
if (!(target instanceof HTMLElement) || !target.isConnected || target.matches(":disabled"))
|
|
3471
3431
|
return;
|
|
3472
3432
|
this._suppressFocusOpen = true;
|
|
3473
|
-
|
|
3433
|
+
this._defer(() => {
|
|
3474
3434
|
target.focus();
|
|
3475
3435
|
this._suppressFocusOpen = false;
|
|
3476
|
-
}
|
|
3436
|
+
});
|
|
3477
3437
|
}
|
|
3478
3438
|
_resolveRangeEndpoint() {
|
|
3479
3439
|
if (!this._fields)
|
|
@@ -3491,12 +3451,18 @@
|
|
|
3491
3451
|
return "";
|
|
3492
3452
|
}
|
|
3493
3453
|
async validate() {
|
|
3454
|
+
const session = this._session;
|
|
3494
3455
|
if (this._rangeMode()) {
|
|
3495
3456
|
const fields = this._fields;
|
|
3496
3457
|
if (!fields)
|
|
3497
3458
|
return true;
|
|
3498
3459
|
for (const [index, field] of fields.entries()) {
|
|
3499
3460
|
const result = await field.commit({ moveDisplay: false });
|
|
3461
|
+
if (!session || session.signal.aborted) {
|
|
3462
|
+
return fields.every((field) => field.input.checkValidity());
|
|
3463
|
+
}
|
|
3464
|
+
if (!field.isCommitCurrent(result.commitId))
|
|
3465
|
+
continue;
|
|
3500
3466
|
if (result.status === "invalid")
|
|
3501
3467
|
this._orderTags.delete(index);
|
|
3502
3468
|
if (result.status === "ok" || result.status === "clear") {
|
|
@@ -3509,9 +3475,15 @@
|
|
|
3509
3475
|
return fields.every((field) => field.input.checkValidity());
|
|
3510
3476
|
}
|
|
3511
3477
|
const input = this._field?.input;
|
|
3512
|
-
if (!input)
|
|
3513
|
-
|
|
3478
|
+
if (!input) {
|
|
3479
|
+
const dateInputs = this.hasAttribute("range") ? this.querySelectorAll(":scope > input[data-range-start], :scope > input[data-range-end]") : this._input ? [this._input] : [];
|
|
3480
|
+
const timeInputs = this.querySelectorAll(":scope > input[type=time][data-time-start], :scope > input[type=time][data-time-end]");
|
|
3481
|
+
return [...dateInputs, ...timeInputs].every((candidate) => candidate instanceof HTMLInputElement && candidate.checkValidity());
|
|
3482
|
+
}
|
|
3514
3483
|
await this._commitText(false, { force: true, moveDisplay: false });
|
|
3484
|
+
if (!session || session.signal.aborted) {
|
|
3485
|
+
return input.checkValidity() && this._timeFields.every((timeInput) => timeInput?.checkValidity() ?? true);
|
|
3486
|
+
}
|
|
3515
3487
|
this._revalidateTimeOrder("start");
|
|
3516
3488
|
this._revalidateTimeOrder("end");
|
|
3517
3489
|
const timesValid = this._timeFields.every((timeInput) => timeInput?.checkValidity() ?? true);
|
|
@@ -3549,8 +3521,11 @@
|
|
|
3549
3521
|
});
|
|
3550
3522
|
position();
|
|
3551
3523
|
this._stopTracking = autoUpdate(this, panel, position);
|
|
3552
|
-
if (options.moveFocus !== false)
|
|
3553
|
-
|
|
3524
|
+
if (options.moveFocus !== false) {
|
|
3525
|
+
const session = this._session;
|
|
3526
|
+
if (session)
|
|
3527
|
+
queueMicrotask(guard(session.signal, () => calendar.focusGrid()));
|
|
3528
|
+
}
|
|
3554
3529
|
this.dispatchEvent(new Event("open", { bubbles: true }));
|
|
3555
3530
|
}
|
|
3556
3531
|
_setExpanded(expanded) {
|
|
@@ -3572,11 +3547,6 @@
|
|
|
3572
3547
|
this._open = false;
|
|
3573
3548
|
this._setExpanded(false);
|
|
3574
3549
|
this._supersedeActivations();
|
|
3575
|
-
this._suppressGridClick = false;
|
|
3576
|
-
if (this._drag) {
|
|
3577
|
-
this._releaseDragCapture(this._drag.pointerId);
|
|
3578
|
-
this._drag = null;
|
|
3579
|
-
}
|
|
3580
3550
|
this._syncHighlight();
|
|
3581
3551
|
if (restoreFocus) {
|
|
3582
3552
|
if (this._rangeMode()) {
|