@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.
@@ -1,4 +1,4 @@
1
- /*** @lekoala/date-picker v0.5.3 - https://github.com/lekoala/date-picker ***/
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
- projectEndpoint(date, endpoint, editable = () => true) {
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 (!endpoint && Boolean(this.start) === Boolean(this.end))
479
+ if (Boolean(this.start) === Boolean(this.end))
496
480
  return null;
497
- const transition = endpoint ? this.projectEndpoint(date, endpoint, editable) : this.project(date, editable);
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._lifecycleId = 0;
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._lifecycleId++;
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
- this.addEventListener("click", this._onClick);
916
- this.addEventListener("change", this._onChange);
917
- this.addEventListener("keydown", this._onKeyDown);
918
- this.addEventListener("focusin", this._onFocusIn);
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.removeEventListener("click", this._onClick);
933
- this.removeEventListener("change", this._onChange);
934
- this.removeEventListener("keydown", this._onKeyDown);
935
- this.removeEventListener("focusin", this._onFocusIn);
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 lifecycleId = this._lifecycleId;
968
- queueMicrotask(() => {
969
- if (!this._connected || lifecycleId !== this._lifecycleId)
970
- return;
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 lifecycleId = this._lifecycleId;
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 (!this._connected || lifecycleId !== this._lifecycleId)
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._disposed = false;
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
- if (this._disposed)
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 (this._disposed || commitId !== this._commitId)
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._disposed = true;
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._controller = null;
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
- upgradeProperties(this, ["value", "range"]);
2323
- this._stopDefaultMessages = subscribeDefaultMessages(() => {
2324
- if (this._messages === null)
2325
- this._refreshMessages();
2326
- });
2327
- this.validate();
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._controller?.abort();
2440
- this._controller = null;
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 (!signal.aborted && !event.defaultPrevented)
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 controller = new AbortController;
2792
- this._controller = controller;
2793
- const { signal } = controller;
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 || !this._connected)
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 controller = new AbortController;
2862
- this._controller = controller;
2863
- const { signal } = controller;
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._connected || !this._range)
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 = intent.endpoint ? this._range.moveEndpoint(date, intent.endpoint, editable) : this._range.activate(date, editable);
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, endpoint) {
3019
+ _attachIntent(date) {
3037
3020
  if (!this._calendar)
3038
3021
  return;
3039
- this._calendar._hostIntent = { date, intent: { id: ++this._activationId, endpoint } };
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, endpoint = "") {
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, endpoint, (bound) => this._boundEditable(bound)) : null;
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 (this._drag || pointer.pointerType === "touch")
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
- if (!field)
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 (!this._ownsField(field) || !field.isCommitCurrent(result.commitId)) {
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
- if (!fields)
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 (!this._ownsField(field) || !field.isCommitCurrent(result.commitId))
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 controller = this._controller;
3514
- setTimeout(() => {
3515
- if (!this._connected || !controller || controller.signal.aborted || this._controller !== controller)
3516
- return;
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 (!this._ownsField(field) || !field.isCommitCurrent(result.commitId))
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 controller = this._controller;
3653
- queueMicrotask(() => {
3654
- if (!this._connected || !controller || controller.signal.aborted || this._controller !== controller)
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()) {