@lekoala/date-picker 0.5.3 → 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 +122 -257
- package/dist/date-picker.min.css +1 -1
- package/dist/date-picker.min.js +12 -12
- package/dist/date-picker.standalone.min.js +12 -12
- package/dist/types/date-range.d.ts +10 -33
- package/dist/types/date-range.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 +11 -24
- package/docs/ARCHITECTURE.md +72 -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 +1 -1
- package/src/date-calendar.js +42 -25
- package/src/date-field.js +14 -7
- package/src/date-picker.css +2 -13
- package/src/date-picker.js +84 -236
- package/src/date-range.js +12 -54
- package/src/session.js +23 -0
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;
|
|
@@ -473,28 +473,12 @@
|
|
|
473
473
|
...canContinue ? {} : { close: true }
|
|
474
474
|
};
|
|
475
475
|
}
|
|
476
|
-
|
|
477
|
-
if (!isDate(date))
|
|
478
|
-
throw new TypeError(`Invalid range activation: ${date}`);
|
|
479
|
-
if (!this.complete || !editable(endpoint))
|
|
480
|
-
return this._refuse(endpoint);
|
|
481
|
-
const { start, end } = this;
|
|
482
|
-
const previous = endpoint === "start" ? start : end;
|
|
483
|
-
const target = endpoint === "start" ? earlier(date, end) : later(date, start);
|
|
484
|
-
return {
|
|
485
|
-
status: "complete",
|
|
486
|
-
endpoint,
|
|
487
|
-
changedEndpoints: target === previous ? [] : [endpoint],
|
|
488
|
-
range: endpoint === "start" ? { start: target, end } : { start, end: target },
|
|
489
|
-
activeEndpoint: endpoint
|
|
490
|
-
};
|
|
491
|
-
}
|
|
492
|
-
previewRange(date, endpoint = "", editable = () => true) {
|
|
476
|
+
previewRange(date, editable = () => true) {
|
|
493
477
|
if (!isDate(date))
|
|
494
478
|
return null;
|
|
495
|
-
if (
|
|
479
|
+
if (Boolean(this.start) === Boolean(this.end))
|
|
496
480
|
return null;
|
|
497
|
-
const transition =
|
|
481
|
+
const transition = this.project(date, editable);
|
|
498
482
|
if (transition.status === "refused")
|
|
499
483
|
return null;
|
|
500
484
|
const { start, end } = transition.range;
|
|
@@ -513,23 +497,6 @@
|
|
|
513
497
|
activate(date, editable = () => true) {
|
|
514
498
|
return this._apply(this.project(date, editable));
|
|
515
499
|
}
|
|
516
|
-
moveEndpoint(date, endpoint, editable = () => true) {
|
|
517
|
-
return this._apply(this.projectEndpoint(date, endpoint, editable));
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
function later(a, b) {
|
|
521
|
-
if (!a)
|
|
522
|
-
return b;
|
|
523
|
-
if (!b)
|
|
524
|
-
return a;
|
|
525
|
-
return compareDates(a, b) >= 0 ? a : b;
|
|
526
|
-
}
|
|
527
|
-
function earlier(a, b) {
|
|
528
|
-
if (!a)
|
|
529
|
-
return b;
|
|
530
|
-
if (!b)
|
|
531
|
-
return a;
|
|
532
|
-
return compareDates(a, b) <= 0 ? a : b;
|
|
533
500
|
}
|
|
534
501
|
|
|
535
502
|
// src/intl.js
|
|
@@ -744,6 +711,17 @@
|
|
|
744
711
|
};
|
|
745
712
|
}
|
|
746
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
|
+
|
|
747
725
|
// src/source.js
|
|
748
726
|
function normalizeDateStates(payload) {
|
|
749
727
|
const raw = payload && typeof payload === "object" && !Array.isArray(payload) && "dates" in payload ? payload.dates : payload;
|
|
@@ -851,7 +829,7 @@
|
|
|
851
829
|
this._id = `date-calendar-${++uid}`;
|
|
852
830
|
this._model = new CalendarModel;
|
|
853
831
|
this._connected = false;
|
|
854
|
-
this.
|
|
832
|
+
this._session = null;
|
|
855
833
|
this._rendering = false;
|
|
856
834
|
this._heading = null;
|
|
857
835
|
this._renderRoot = null;
|
|
@@ -881,7 +859,7 @@
|
|
|
881
859
|
connectedCallback() {
|
|
882
860
|
if (this._connected)
|
|
883
861
|
return;
|
|
884
|
-
this.
|
|
862
|
+
this._session = createSession();
|
|
885
863
|
upgradeProperties(this, [
|
|
886
864
|
"locale",
|
|
887
865
|
"min",
|
|
@@ -901,7 +879,10 @@
|
|
|
901
879
|
"value",
|
|
902
880
|
"display"
|
|
903
881
|
]);
|
|
882
|
+
this._normalizeAttributes();
|
|
904
883
|
this._syncModel();
|
|
884
|
+
if (this.hasAttribute("display"))
|
|
885
|
+
this._reflect("display", this._model.display);
|
|
905
886
|
upgradeProperties(this, ["focusedDate"]);
|
|
906
887
|
this._stopDefaultControlClasses = subscribeDefaultControlClasses(() => {
|
|
907
888
|
if (usesDefaultControlClasses(this._controlClasses))
|
|
@@ -912,10 +893,11 @@
|
|
|
912
893
|
this.render();
|
|
913
894
|
});
|
|
914
895
|
this._connected = true;
|
|
915
|
-
|
|
916
|
-
this.addEventListener("
|
|
917
|
-
this.addEventListener("
|
|
918
|
-
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 });
|
|
919
901
|
this.render();
|
|
920
902
|
}
|
|
921
903
|
disconnectedCallback() {
|
|
@@ -924,19 +906,29 @@
|
|
|
924
906
|
this._stopDefaultMessages?.();
|
|
925
907
|
this._stopDefaultMessages = null;
|
|
926
908
|
this._connected = false;
|
|
927
|
-
this._lifecycleId++;
|
|
928
909
|
this._loadController?.abort();
|
|
929
910
|
this._loadController = null;
|
|
930
911
|
this._loadingKey = "";
|
|
931
912
|
this._loadingPromise = null;
|
|
932
|
-
this.
|
|
933
|
-
this.
|
|
934
|
-
this.
|
|
935
|
-
|
|
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
|
+
}
|
|
936
926
|
}
|
|
937
927
|
attributeChangedCallback(name, _oldValue, newValue) {
|
|
938
928
|
if (this._rendering)
|
|
939
929
|
return;
|
|
930
|
+
if (!this._connected)
|
|
931
|
+
return;
|
|
940
932
|
if (name === "value" && newValue && !isDate(newValue)) {
|
|
941
933
|
this._reflect("value", this._model.value);
|
|
942
934
|
return;
|
|
@@ -958,18 +950,14 @@
|
|
|
958
950
|
return;
|
|
959
951
|
}
|
|
960
952
|
}
|
|
961
|
-
if (!this._connected)
|
|
962
|
-
return;
|
|
963
953
|
this._syncModel();
|
|
964
954
|
this.render();
|
|
965
955
|
}
|
|
966
956
|
_queueFocus(callback) {
|
|
967
|
-
const
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
callback();
|
|
972
|
-
});
|
|
957
|
+
const session = this._session;
|
|
958
|
+
if (!session)
|
|
959
|
+
return;
|
|
960
|
+
queueMicrotask(guard(session.signal, callback));
|
|
973
961
|
}
|
|
974
962
|
get locale() {
|
|
975
963
|
return resolveLocale(this.getAttribute("locale") || "");
|
|
@@ -1258,11 +1246,9 @@
|
|
|
1258
1246
|
} finally {
|
|
1259
1247
|
if (this._loadController === controller) {
|
|
1260
1248
|
this._loadController = null;
|
|
1261
|
-
this.removeAttribute("data-loading");
|
|
1262
|
-
}
|
|
1263
|
-
if (this._loadingKey === key) {
|
|
1264
1249
|
this._loadingKey = "";
|
|
1265
1250
|
this._loadingPromise = null;
|
|
1251
|
+
this.removeAttribute("data-loading");
|
|
1266
1252
|
}
|
|
1267
1253
|
}
|
|
1268
1254
|
})();
|
|
@@ -1397,7 +1383,7 @@
|
|
|
1397
1383
|
async activateDate(date) {
|
|
1398
1384
|
if (!this._connected)
|
|
1399
1385
|
return false;
|
|
1400
|
-
const
|
|
1386
|
+
const session = this._session;
|
|
1401
1387
|
const hostIntent = this._hostIntent?.date === date ? this._hostIntent.intent : undefined;
|
|
1402
1388
|
this._hostIntent = null;
|
|
1403
1389
|
const tagged = (event) => {
|
|
@@ -1406,7 +1392,7 @@
|
|
|
1406
1392
|
return event;
|
|
1407
1393
|
};
|
|
1408
1394
|
const confirmed = await this.ensureDate(date);
|
|
1409
|
-
if (!
|
|
1395
|
+
if (!session || session.signal.aborted)
|
|
1410
1396
|
return false;
|
|
1411
1397
|
const state = this.getDateState(date);
|
|
1412
1398
|
if (!confirmed || state.disabled) {
|
|
@@ -1418,7 +1404,7 @@
|
|
|
1418
1404
|
bubbles: true,
|
|
1419
1405
|
cancelable: true
|
|
1420
1406
|
})));
|
|
1421
|
-
if (!accepted)
|
|
1407
|
+
if (!accepted || session.signal.aborted)
|
|
1422
1408
|
return false;
|
|
1423
1409
|
if (this.selection === "single") {
|
|
1424
1410
|
const previousValue = this._model.value;
|
|
@@ -2037,7 +2023,7 @@
|
|
|
2037
2023
|
this.canonical = "";
|
|
2038
2024
|
this._dirty = false;
|
|
2039
2025
|
this._commitId = 0;
|
|
2040
|
-
this.
|
|
2026
|
+
this._session = createSession();
|
|
2041
2027
|
this._originalName = input.getAttribute("name") || "";
|
|
2042
2028
|
this._attributeObserver = null;
|
|
2043
2029
|
this.onAttributesChanged = null;
|
|
@@ -2140,7 +2126,8 @@
|
|
|
2140
2126
|
async commit(options = {}) {
|
|
2141
2127
|
const input = this.input;
|
|
2142
2128
|
const commitId = ++this._commitId;
|
|
2143
|
-
|
|
2129
|
+
const session = this._session;
|
|
2130
|
+
if (session.signal.aborted)
|
|
2144
2131
|
return { status: "stale", commitId };
|
|
2145
2132
|
const text = input.value.trim();
|
|
2146
2133
|
if (!text) {
|
|
@@ -2160,8 +2147,9 @@
|
|
|
2160
2147
|
}
|
|
2161
2148
|
if (this.confirm) {
|
|
2162
2149
|
const result = await this.confirm(parsed, options);
|
|
2163
|
-
if (
|
|
2150
|
+
if (session.signal.aborted || commitId !== this._commitId) {
|
|
2164
2151
|
return { status: "stale", commitId };
|
|
2152
|
+
}
|
|
2165
2153
|
if (!result?.ok) {
|
|
2166
2154
|
if (this.hidden)
|
|
2167
2155
|
this.hidden.value = "";
|
|
@@ -2194,7 +2182,7 @@
|
|
|
2194
2182
|
}
|
|
2195
2183
|
teardown() {
|
|
2196
2184
|
this.dirty();
|
|
2197
|
-
this.
|
|
2185
|
+
this._session.abort();
|
|
2198
2186
|
this._attributeObserver?.disconnect();
|
|
2199
2187
|
this._attributeObserver = null;
|
|
2200
2188
|
const hiddenName = this.hidden?.getAttribute("name") || this._originalName;
|
|
@@ -2236,7 +2224,6 @@
|
|
|
2236
2224
|
|
|
2237
2225
|
// src/date-picker.js
|
|
2238
2226
|
var uid2 = 0;
|
|
2239
|
-
var DRAG_THRESHOLD = 4;
|
|
2240
2227
|
|
|
2241
2228
|
class DatePickerElement extends HTMLElement {
|
|
2242
2229
|
static observedAttributes = ["value", "locale", "min", "max", "open-on-focus", "month-format"];
|
|
@@ -2268,8 +2255,6 @@
|
|
|
2268
2255
|
this._lastFocusEndpoint = "";
|
|
2269
2256
|
this._activationId = 0;
|
|
2270
2257
|
this._previewDate = "";
|
|
2271
|
-
this._drag = null;
|
|
2272
|
-
this._suppressGridClick = false;
|
|
2273
2258
|
this._buttons = [];
|
|
2274
2259
|
this._returnFocus = null;
|
|
2275
2260
|
this._panel = null;
|
|
@@ -2278,7 +2263,7 @@
|
|
|
2278
2263
|
this._rangeOriginalDescribedBy = ["", ""];
|
|
2279
2264
|
this._formatHint = null;
|
|
2280
2265
|
this._generatedPlaceholders = new WeakSet;
|
|
2281
|
-
this.
|
|
2266
|
+
this._session = null;
|
|
2282
2267
|
this._stopTracking = null;
|
|
2283
2268
|
this._open = false;
|
|
2284
2269
|
this._suppressFocusOpen = false;
|
|
@@ -2294,12 +2279,10 @@
|
|
|
2294
2279
|
_rangeMode() {
|
|
2295
2280
|
return this.hasAttribute("range") && Boolean(this._range);
|
|
2296
2281
|
}
|
|
2297
|
-
_ownsField(field) {
|
|
2298
|
-
return this._connected && (field === this._field || Boolean(this._fields?.includes(field)));
|
|
2299
|
-
}
|
|
2300
2282
|
connectedCallback() {
|
|
2301
2283
|
if (this._connected)
|
|
2302
2284
|
return;
|
|
2285
|
+
this._session = createSession();
|
|
2303
2286
|
upgradeProperties(this, [
|
|
2304
2287
|
"locale",
|
|
2305
2288
|
"min",
|
|
@@ -2314,17 +2297,31 @@
|
|
|
2314
2297
|
"renderDay",
|
|
2315
2298
|
"isDateDisabled"
|
|
2316
2299
|
]);
|
|
2300
|
+
this._normalizeAttributes();
|
|
2317
2301
|
if (this.hasAttribute("range"))
|
|
2318
2302
|
this._connectRange();
|
|
2319
2303
|
else
|
|
2320
2304
|
this._connectSingle();
|
|
2321
|
-
if (this._connected) {
|
|
2322
|
-
|
|
2323
|
-
this.
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
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);
|
|
2328
2325
|
}
|
|
2329
2326
|
}
|
|
2330
2327
|
_connectSingle() {
|
|
@@ -2436,8 +2433,8 @@
|
|
|
2436
2433
|
this._connected = false;
|
|
2437
2434
|
this._suppressFocusOpen = false;
|
|
2438
2435
|
this.hide(false);
|
|
2439
|
-
this.
|
|
2440
|
-
this.
|
|
2436
|
+
this._session?.abort();
|
|
2437
|
+
this._session = null;
|
|
2441
2438
|
this._clearTimeOrderValidity();
|
|
2442
2439
|
this._timeFields = [null, null];
|
|
2443
2440
|
if (this._rangeMode()) {
|
|
@@ -2477,6 +2474,8 @@
|
|
|
2477
2474
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
2478
2475
|
if (this._reflecting || oldValue === newValue)
|
|
2479
2476
|
return;
|
|
2477
|
+
if (!this._connected)
|
|
2478
|
+
return;
|
|
2480
2479
|
if (name === "value" && newValue && !isDate(newValue)) {
|
|
2481
2480
|
this._reflectValue(this._value);
|
|
2482
2481
|
return;
|
|
@@ -2489,8 +2488,6 @@
|
|
|
2489
2488
|
}
|
|
2490
2489
|
return;
|
|
2491
2490
|
}
|
|
2492
|
-
if (!this._connected)
|
|
2493
|
-
return;
|
|
2494
2491
|
if (name === "value") {
|
|
2495
2492
|
if (this._rangeMode())
|
|
2496
2493
|
return;
|
|
@@ -2686,7 +2683,6 @@
|
|
|
2686
2683
|
const field = this._fields[index];
|
|
2687
2684
|
button.disabled = Boolean(field?.input.disabled || field?.input.readOnly);
|
|
2688
2685
|
}
|
|
2689
|
-
this._syncDragAffordance();
|
|
2690
2686
|
const active = this._range?.activeEndpoint === "end" ? 1 : 0;
|
|
2691
2687
|
const activeInput = this._fields[active]?.input;
|
|
2692
2688
|
if (this._open && activeInput && !isEditable(activeInput))
|
|
@@ -2775,10 +2771,10 @@
|
|
|
2775
2771
|
if (!(event.target instanceof HTMLFormElement) || !input || event.target !== input.form)
|
|
2776
2772
|
return;
|
|
2777
2773
|
this.hide(false);
|
|
2778
|
-
queueMicrotask(() => {
|
|
2779
|
-
if (!
|
|
2774
|
+
queueMicrotask(guard(signal, () => {
|
|
2775
|
+
if (!event.defaultPrevented)
|
|
2780
2776
|
restore();
|
|
2781
|
-
});
|
|
2777
|
+
}));
|
|
2782
2778
|
}, { capture: true, signal });
|
|
2783
2779
|
this.addEventListener("keydown", (event) => this._onEscape(event), { signal });
|
|
2784
2780
|
}
|
|
@@ -2788,9 +2784,10 @@
|
|
|
2788
2784
|
const calendar = this._calendar;
|
|
2789
2785
|
if (!input || !button || !calendar)
|
|
2790
2786
|
return;
|
|
2791
|
-
const
|
|
2792
|
-
|
|
2793
|
-
|
|
2787
|
+
const session = this._session;
|
|
2788
|
+
if (!session)
|
|
2789
|
+
return;
|
|
2790
|
+
const { signal } = session;
|
|
2794
2791
|
input.addEventListener("input", () => {
|
|
2795
2792
|
this._field?.handleInput();
|
|
2796
2793
|
}, { signal });
|
|
@@ -2839,7 +2836,7 @@
|
|
|
2839
2836
|
return;
|
|
2840
2837
|
const intent = activationIntents.get(custom);
|
|
2841
2838
|
queueMicrotask(() => {
|
|
2842
|
-
if (signal.aborted || custom.defaultPrevented
|
|
2839
|
+
if (signal.aborted || custom.defaultPrevented)
|
|
2843
2840
|
return;
|
|
2844
2841
|
if (intent && intent.id !== this._activationId)
|
|
2845
2842
|
return;
|
|
@@ -2858,9 +2855,10 @@
|
|
|
2858
2855
|
const calendar = this._calendar;
|
|
2859
2856
|
if (!this._fields || !this._buttons.length || !calendar)
|
|
2860
2857
|
return;
|
|
2861
|
-
const
|
|
2862
|
-
|
|
2863
|
-
|
|
2858
|
+
const session = this._session;
|
|
2859
|
+
if (!session)
|
|
2860
|
+
return;
|
|
2861
|
+
const { signal } = session;
|
|
2864
2862
|
for (const [index, field] of this._fields.entries()) {
|
|
2865
2863
|
const endpoint = index === 1 ? "end" : "start";
|
|
2866
2864
|
field.input.addEventListener("input", () => {
|
|
@@ -2886,12 +2884,6 @@
|
|
|
2886
2884
|
});
|
|
2887
2885
|
}
|
|
2888
2886
|
calendar.addEventListener("click", (event) => {
|
|
2889
|
-
if (this._suppressGridClick) {
|
|
2890
|
-
this._suppressGridClick = false;
|
|
2891
|
-
event.preventDefault();
|
|
2892
|
-
event.stopImmediatePropagation();
|
|
2893
|
-
return;
|
|
2894
|
-
}
|
|
2895
2887
|
this._captureGridIntent(event);
|
|
2896
2888
|
}, { capture: true, signal });
|
|
2897
2889
|
calendar.addEventListener("keydown", (event) => this._captureGridIntent(event), {
|
|
@@ -2904,13 +2896,13 @@
|
|
|
2904
2896
|
if (!isDate(date))
|
|
2905
2897
|
return;
|
|
2906
2898
|
queueMicrotask(() => {
|
|
2907
|
-
if (signal.aborted || custom.defaultPrevented || !this.
|
|
2899
|
+
if (signal.aborted || custom.defaultPrevented || !this._range)
|
|
2908
2900
|
return;
|
|
2909
2901
|
const intent = activationIntents.get(custom);
|
|
2910
2902
|
if (intent === undefined || intent.id !== this._activationId)
|
|
2911
2903
|
return;
|
|
2912
2904
|
const editable = (bound) => this._boundEditable(bound);
|
|
2913
|
-
const result =
|
|
2905
|
+
const result = this._range.activate(date, editable);
|
|
2914
2906
|
if (result.status === "refused") {
|
|
2915
2907
|
this._calendar?.dispatchEvent(new CustomEvent("dateinvalid", {
|
|
2916
2908
|
detail: { date, state: this._calendar.getDateState(date) },
|
|
@@ -2919,8 +2911,6 @@
|
|
|
2919
2911
|
return;
|
|
2920
2912
|
}
|
|
2921
2913
|
this._applyRangeTransition(result);
|
|
2922
|
-
if (intent.endpoint)
|
|
2923
|
-
return;
|
|
2924
2914
|
if (result.close || result.status === "complete") {
|
|
2925
2915
|
this.hide(false);
|
|
2926
2916
|
this._focusField(result.endpoint);
|
|
@@ -2930,11 +2920,6 @@
|
|
|
2930
2920
|
calendar.addEventListener("datefocus", (event) => this._onGridDateFocus(event), { signal });
|
|
2931
2921
|
calendar.addEventListener("pointerover", (event) => this._onGridPointerOver(event), { signal });
|
|
2932
2922
|
calendar.addEventListener("pointerleave", () => this._onGridPointerLeave(), { signal });
|
|
2933
|
-
calendar.addEventListener("pointerdown", (event) => this._onGridPointerDown(event), { signal });
|
|
2934
|
-
calendar.addEventListener("pointermove", (event) => this._onGridPointerMove(event), { signal });
|
|
2935
|
-
calendar.addEventListener("pointerup", (event) => this._onGridPointerUp(event), { signal });
|
|
2936
|
-
calendar.addEventListener("pointercancel", (event) => this._onGridPointerCancel(event), { signal });
|
|
2937
|
-
calendar.addEventListener("lostpointercapture", (event) => this._onGridPointerCancel(event), { signal });
|
|
2938
2923
|
calendar.addEventListener("dateloadend", () => void this.validate(), { signal });
|
|
2939
2924
|
this._bindPopup(signal, this._fields?.[0]?.input, () => this._restoreRangeDefault());
|
|
2940
2925
|
}
|
|
@@ -3023,20 +3008,18 @@
|
|
|
3023
3008
|
if (key !== "Enter" && key !== " ")
|
|
3024
3009
|
return;
|
|
3025
3010
|
}
|
|
3026
|
-
if (event.type === "click" && this._suppressGridClick)
|
|
3027
|
-
return;
|
|
3028
3011
|
if (!(event.target instanceof Element))
|
|
3029
3012
|
return;
|
|
3030
3013
|
const cell = event.target.closest(".dp-day[data-date]");
|
|
3031
3014
|
const date = cell?.getAttribute("data-date") || "";
|
|
3032
3015
|
if (!isDate(date))
|
|
3033
3016
|
return;
|
|
3034
|
-
this._attachIntent(date
|
|
3017
|
+
this._attachIntent(date);
|
|
3035
3018
|
}
|
|
3036
|
-
_attachIntent(date
|
|
3019
|
+
_attachIntent(date) {
|
|
3037
3020
|
if (!this._calendar)
|
|
3038
3021
|
return;
|
|
3039
|
-
this._calendar._hostIntent = { date, intent: { id: ++this._activationId
|
|
3022
|
+
this._calendar._hostIntent = { date, intent: { id: ++this._activationId } };
|
|
3040
3023
|
}
|
|
3041
3024
|
_supersedeActivations() {
|
|
3042
3025
|
this._activationId++;
|
|
@@ -3069,12 +3052,12 @@
|
|
|
3069
3052
|
field.input.dispatchEvent(new Event("change", { bubbles: true }));
|
|
3070
3053
|
}
|
|
3071
3054
|
}
|
|
3072
|
-
_setPreview(date
|
|
3055
|
+
_setPreview(date) {
|
|
3073
3056
|
const calendar = this._calendar;
|
|
3074
3057
|
if (!calendar || !this._range || !this._open)
|
|
3075
3058
|
return;
|
|
3076
3059
|
const candidate = isDate(date) && !calendar.getDateState(date).disabled ? date : "";
|
|
3077
|
-
const preview = candidate ? this._range.previewRange(candidate,
|
|
3060
|
+
const preview = candidate ? this._range.previewRange(candidate, (bound) => this._boundEditable(bound)) : null;
|
|
3078
3061
|
if (!preview) {
|
|
3079
3062
|
this._clearPreview();
|
|
3080
3063
|
return;
|
|
@@ -3089,23 +3072,17 @@
|
|
|
3089
3072
|
this._syncHighlight();
|
|
3090
3073
|
}
|
|
3091
3074
|
_onGridDateFocus(event) {
|
|
3092
|
-
if (this._drag)
|
|
3093
|
-
return;
|
|
3094
3075
|
const date = event.detail?.date;
|
|
3095
3076
|
if (isDate(date))
|
|
3096
3077
|
this._setPreview(date);
|
|
3097
3078
|
}
|
|
3098
3079
|
_onGridPointerOver(event) {
|
|
3099
3080
|
const pointer = event;
|
|
3100
|
-
if (
|
|
3081
|
+
if (pointer.pointerType === "touch")
|
|
3101
3082
|
return;
|
|
3102
3083
|
this._setPreview(this._cellDate(pointer.target));
|
|
3103
3084
|
}
|
|
3104
3085
|
_onGridPointerLeave() {
|
|
3105
|
-
if (this._drag?.active === false)
|
|
3106
|
-
this._drag = null;
|
|
3107
|
-
if (this._drag)
|
|
3108
|
-
return;
|
|
3109
3086
|
this._clearPreview();
|
|
3110
3087
|
}
|
|
3111
3088
|
_cellDate(target) {
|
|
@@ -3113,116 +3090,6 @@
|
|
|
3113
3090
|
const date = cell?.getAttribute("data-date") || "";
|
|
3114
3091
|
return isDate(date) ? date : "";
|
|
3115
3092
|
}
|
|
3116
|
-
_dateAtPoint(x, y) {
|
|
3117
|
-
const element = this.ownerDocument.elementFromPoint(x, y);
|
|
3118
|
-
if (!(element instanceof Element) || !this._calendar?.contains(element))
|
|
3119
|
-
return "";
|
|
3120
|
-
return this._cellDate(element);
|
|
3121
|
-
}
|
|
3122
|
-
_onGridPointerDown(event) {
|
|
3123
|
-
const pointer = event;
|
|
3124
|
-
this._suppressGridClick = false;
|
|
3125
|
-
if (this._drag?.active === false)
|
|
3126
|
-
this._drag = null;
|
|
3127
|
-
if (!this._open || !this._range || this._drag)
|
|
3128
|
-
return;
|
|
3129
|
-
if (!pointer.isPrimary || pointer.button !== 0)
|
|
3130
|
-
return;
|
|
3131
|
-
if (pointer.pointerType !== "mouse" && pointer.pointerType !== "pen")
|
|
3132
|
-
return;
|
|
3133
|
-
if (!this._range.complete)
|
|
3134
|
-
return;
|
|
3135
|
-
const cell = pointer.target instanceof Element ? pointer.target.closest(".dp-day[data-date]") : null;
|
|
3136
|
-
if (!(cell instanceof HTMLElement))
|
|
3137
|
-
return;
|
|
3138
|
-
const isStart = cell.hasAttribute("data-range-start");
|
|
3139
|
-
const isEnd = cell.hasAttribute("data-range-end");
|
|
3140
|
-
if (isStart === isEnd)
|
|
3141
|
-
return;
|
|
3142
|
-
const endpoint = isStart ? "start" : "end";
|
|
3143
|
-
const date = this._cellDate(cell);
|
|
3144
|
-
if (!date || !this._boundEditable(endpoint))
|
|
3145
|
-
return;
|
|
3146
|
-
this._drag = {
|
|
3147
|
-
pointerId: pointer.pointerId,
|
|
3148
|
-
endpoint,
|
|
3149
|
-
x: pointer.clientX,
|
|
3150
|
-
y: pointer.clientY,
|
|
3151
|
-
date,
|
|
3152
|
-
active: false
|
|
3153
|
-
};
|
|
3154
|
-
}
|
|
3155
|
-
_onGridPointerMove(event) {
|
|
3156
|
-
const pointer = event;
|
|
3157
|
-
const drag = this._drag;
|
|
3158
|
-
if (!drag || pointer.pointerId !== drag.pointerId)
|
|
3159
|
-
return;
|
|
3160
|
-
if (!drag.active) {
|
|
3161
|
-
const travelled = Math.abs(pointer.clientX - drag.x) > DRAG_THRESHOLD || Math.abs(pointer.clientY - drag.y) > DRAG_THRESHOLD;
|
|
3162
|
-
if (!travelled)
|
|
3163
|
-
return;
|
|
3164
|
-
drag.active = true;
|
|
3165
|
-
try {
|
|
3166
|
-
this._calendar?.setPointerCapture(drag.pointerId);
|
|
3167
|
-
} catch {}
|
|
3168
|
-
this._syncDragAffordance();
|
|
3169
|
-
}
|
|
3170
|
-
const date = this._dateAtPoint(pointer.clientX, pointer.clientY);
|
|
3171
|
-
if (!date || this._calendar?.getDateState(date).disabled)
|
|
3172
|
-
return;
|
|
3173
|
-
drag.date = date;
|
|
3174
|
-
this._setPreview(date, drag.endpoint);
|
|
3175
|
-
}
|
|
3176
|
-
_onGridPointerUp(event) {
|
|
3177
|
-
const pointer = event;
|
|
3178
|
-
const drag = this._drag;
|
|
3179
|
-
if (!drag || pointer.pointerId !== drag.pointerId)
|
|
3180
|
-
return;
|
|
3181
|
-
this._drag = null;
|
|
3182
|
-
this._releaseDragCapture(drag.pointerId);
|
|
3183
|
-
if (!drag.active) {
|
|
3184
|
-
this._syncDragAffordance();
|
|
3185
|
-
return;
|
|
3186
|
-
}
|
|
3187
|
-
this._suppressGridClick = true;
|
|
3188
|
-
const transition = this._range?.projectEndpoint(drag.date, drag.endpoint, (bound) => this._boundEditable(bound));
|
|
3189
|
-
if (!transition || transition.status === "refused" || !transition.changedEndpoints.length) {
|
|
3190
|
-
this._syncHighlight();
|
|
3191
|
-
return;
|
|
3192
|
-
}
|
|
3193
|
-
const target = drag.endpoint === "start" ? transition.range.start : transition.range.end;
|
|
3194
|
-
this._attachIntent(target, drag.endpoint);
|
|
3195
|
-
this._calendar?.activateDate(target);
|
|
3196
|
-
}
|
|
3197
|
-
_onGridPointerCancel(event) {
|
|
3198
|
-
const pointer = event;
|
|
3199
|
-
const drag = this._drag;
|
|
3200
|
-
if (!drag || pointer.pointerId !== drag.pointerId)
|
|
3201
|
-
return;
|
|
3202
|
-
this._drag = null;
|
|
3203
|
-
this._releaseDragCapture(drag.pointerId);
|
|
3204
|
-
this._syncHighlight();
|
|
3205
|
-
}
|
|
3206
|
-
_releaseDragCapture(pointerId) {
|
|
3207
|
-
const calendar = this._calendar;
|
|
3208
|
-
if (calendar?.hasPointerCapture(pointerId))
|
|
3209
|
-
calendar.releasePointerCapture(pointerId);
|
|
3210
|
-
}
|
|
3211
|
-
_syncDragAffordance() {
|
|
3212
|
-
const calendar = this._calendar;
|
|
3213
|
-
if (!calendar || !this._range)
|
|
3214
|
-
return;
|
|
3215
|
-
if (this._drag?.active) {
|
|
3216
|
-
calendar.setAttribute("data-range-drag", "active");
|
|
3217
|
-
return;
|
|
3218
|
-
}
|
|
3219
|
-
const { start, end } = this._range;
|
|
3220
|
-
const draggable = this._range.complete && start !== end && (this._boundEditable("start") || this._boundEditable("end"));
|
|
3221
|
-
if (draggable)
|
|
3222
|
-
calendar.setAttribute("data-range-drag", "ready");
|
|
3223
|
-
else
|
|
3224
|
-
calendar.removeAttribute("data-range-drag");
|
|
3225
|
-
}
|
|
3226
3093
|
_onEscape(event) {
|
|
3227
3094
|
if (event.key === "Escape" && this._open) {
|
|
3228
3095
|
event.preventDefault();
|
|
@@ -3355,12 +3222,13 @@
|
|
|
3355
3222
|
}
|
|
3356
3223
|
async _commitText(emit, options = {}) {
|
|
3357
3224
|
const field = this._field;
|
|
3358
|
-
|
|
3225
|
+
const session = this._session;
|
|
3226
|
+
if (!field || !session)
|
|
3359
3227
|
return false;
|
|
3360
3228
|
if (!options.force && !field.isDirty)
|
|
3361
3229
|
return false;
|
|
3362
3230
|
const result = await field.commit(options);
|
|
3363
|
-
if (
|
|
3231
|
+
if (session.signal.aborted || !field.isCommitCurrent(result.commitId)) {
|
|
3364
3232
|
return false;
|
|
3365
3233
|
}
|
|
3366
3234
|
if (result.status === "stale" || result.status === "invalid")
|
|
@@ -3374,14 +3242,15 @@
|
|
|
3374
3242
|
}
|
|
3375
3243
|
async _commitFieldText(which) {
|
|
3376
3244
|
const fields = this._fields;
|
|
3377
|
-
|
|
3245
|
+
const session = this._session;
|
|
3246
|
+
if (!fields || !session)
|
|
3378
3247
|
return false;
|
|
3379
3248
|
const index = which === "end" ? 1 : 0;
|
|
3380
3249
|
const field = fields[index];
|
|
3381
3250
|
if (!field?.isDirty)
|
|
3382
3251
|
return false;
|
|
3383
3252
|
const result = await field.commit();
|
|
3384
|
-
if (
|
|
3253
|
+
if (session.signal.aborted || !field.isCommitCurrent(result.commitId))
|
|
3385
3254
|
return false;
|
|
3386
3255
|
if (result.status === "stale")
|
|
3387
3256
|
return false;
|
|
@@ -3460,7 +3329,6 @@
|
|
|
3460
3329
|
this._previewDate = "";
|
|
3461
3330
|
this._calendar.removeAttribute("data-range-preview");
|
|
3462
3331
|
this._calendar.highlightedRange = this._displayRange();
|
|
3463
|
-
this._syncDragAffordance();
|
|
3464
3332
|
}
|
|
3465
3333
|
_revalidateRange(which) {
|
|
3466
3334
|
if (!this._fields || !this._range)
|
|
@@ -3510,12 +3378,10 @@
|
|
|
3510
3378
|
this._timeOrderOwned.clear();
|
|
3511
3379
|
}
|
|
3512
3380
|
_defer(callback) {
|
|
3513
|
-
const
|
|
3514
|
-
|
|
3515
|
-
|
|
3516
|
-
|
|
3517
|
-
callback();
|
|
3518
|
-
}, 0);
|
|
3381
|
+
const session = this._session;
|
|
3382
|
+
if (!session)
|
|
3383
|
+
return;
|
|
3384
|
+
setTimeout(guard(session.signal, callback), 0);
|
|
3519
3385
|
}
|
|
3520
3386
|
_restoreDefault() {
|
|
3521
3387
|
const field = this._field;
|
|
@@ -3585,13 +3451,17 @@
|
|
|
3585
3451
|
return "";
|
|
3586
3452
|
}
|
|
3587
3453
|
async validate() {
|
|
3454
|
+
const session = this._session;
|
|
3588
3455
|
if (this._rangeMode()) {
|
|
3589
3456
|
const fields = this._fields;
|
|
3590
3457
|
if (!fields)
|
|
3591
3458
|
return true;
|
|
3592
3459
|
for (const [index, field] of fields.entries()) {
|
|
3593
3460
|
const result = await field.commit({ moveDisplay: false });
|
|
3594
|
-
if (!
|
|
3461
|
+
if (!session || session.signal.aborted) {
|
|
3462
|
+
return fields.every((field) => field.input.checkValidity());
|
|
3463
|
+
}
|
|
3464
|
+
if (!field.isCommitCurrent(result.commitId))
|
|
3595
3465
|
continue;
|
|
3596
3466
|
if (result.status === "invalid")
|
|
3597
3467
|
this._orderTags.delete(index);
|
|
@@ -3611,6 +3481,9 @@
|
|
|
3611
3481
|
return [...dateInputs, ...timeInputs].every((candidate) => candidate instanceof HTMLInputElement && candidate.checkValidity());
|
|
3612
3482
|
}
|
|
3613
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
|
+
}
|
|
3614
3487
|
this._revalidateTimeOrder("start");
|
|
3615
3488
|
this._revalidateTimeOrder("end");
|
|
3616
3489
|
const timesValid = this._timeFields.every((timeInput) => timeInput?.checkValidity() ?? true);
|
|
@@ -3649,12 +3522,9 @@
|
|
|
3649
3522
|
position();
|
|
3650
3523
|
this._stopTracking = autoUpdate(this, panel, position);
|
|
3651
3524
|
if (options.moveFocus !== false) {
|
|
3652
|
-
const
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
return;
|
|
3656
|
-
calendar.focusGrid();
|
|
3657
|
-
});
|
|
3525
|
+
const session = this._session;
|
|
3526
|
+
if (session)
|
|
3527
|
+
queueMicrotask(guard(session.signal, () => calendar.focusGrid()));
|
|
3658
3528
|
}
|
|
3659
3529
|
this.dispatchEvent(new Event("open", { bubbles: true }));
|
|
3660
3530
|
}
|
|
@@ -3677,11 +3547,6 @@
|
|
|
3677
3547
|
this._open = false;
|
|
3678
3548
|
this._setExpanded(false);
|
|
3679
3549
|
this._supersedeActivations();
|
|
3680
|
-
this._suppressGridClick = false;
|
|
3681
|
-
if (this._drag) {
|
|
3682
|
-
this._releaseDragCapture(this._drag.pointerId);
|
|
3683
|
-
this._drag = null;
|
|
3684
|
-
}
|
|
3685
3550
|
this._syncHighlight();
|
|
3686
3551
|
if (restoreFocus) {
|
|
3687
3552
|
if (this._rangeMode()) {
|