@lekoala/date-picker 0.5.0 → 0.5.2
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/README.md +296 -281
- package/custom-elements.json +45 -2
- package/dist/date-picker.js +300 -107
- package/dist/date-picker.min.css +1 -1
- package/dist/date-picker.min.js +11 -11
- package/dist/date-picker.standalone.min.js +13 -506
- package/dist/types/activation-intents.d.ts +10 -0
- package/dist/types/activation-intents.d.ts.map +1 -0
- package/dist/types/control-classes.d.ts +11 -1
- package/dist/types/control-classes.d.ts.map +1 -1
- package/dist/types/date-calendar.d.ts +39 -51
- package/dist/types/date-calendar.d.ts.map +1 -1
- package/dist/types/date-field.d.ts +14 -0
- package/dist/types/date-field.d.ts.map +1 -1
- package/dist/types/date-picker.d.ts +71 -81
- package/dist/types/date-picker.d.ts.map +1 -1
- package/dist/types/messages.d.ts +2 -0
- package/dist/types/messages.d.ts.map +1 -1
- package/dist/types/upgrade-properties.d.ts +8 -0
- package/dist/types/upgrade-properties.d.ts.map +1 -0
- package/docs/API.md +442 -430
- package/docs/DECISIONS.md +74 -68
- package/docs/USE_CASES.md +156 -156
- package/package.json +2 -2
- package/src/activation-intents.js +9 -0
- package/src/control-classes.js +36 -6
- package/src/date-calendar.js +127 -35
- package/src/date-field.js +32 -1
- package/src/date-picker.js +202 -101
- package/src/messages.js +12 -0
- package/src/upgrade-properties.js +14 -0
package/dist/date-picker.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*** @lekoala/date-picker v0.5.
|
|
1
|
+
/*** @lekoala/date-picker v0.5.2 - https://github.com/lekoala/date-picker ***/
|
|
2
2
|
(() => {
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
@@ -44,6 +44,9 @@
|
|
|
44
44
|
defineDatePicker: () => defineDatePicker
|
|
45
45
|
});
|
|
46
46
|
|
|
47
|
+
// src/activation-intents.js
|
|
48
|
+
var activationIntents = new WeakMap;
|
|
49
|
+
|
|
47
50
|
// src/date.js
|
|
48
51
|
var DATE_RE = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
49
52
|
var MONTH_RE = /^(\d{4})-(\d{2})$/;
|
|
@@ -313,14 +316,37 @@
|
|
|
313
316
|
function getDefaultControlClasses() {
|
|
314
317
|
return { ...defaults };
|
|
315
318
|
}
|
|
316
|
-
function
|
|
317
|
-
|
|
319
|
+
function normalizeControlClasses(classes) {
|
|
320
|
+
if (classes == null)
|
|
321
|
+
return null;
|
|
322
|
+
const result = {};
|
|
318
323
|
for (const role of ["month", "year", "nav"]) {
|
|
319
|
-
if (
|
|
324
|
+
if (Object.hasOwn(classes, role))
|
|
320
325
|
result[role] = normalizeControlClass(classes[role]);
|
|
321
326
|
}
|
|
322
327
|
return result;
|
|
323
328
|
}
|
|
329
|
+
function usesDefaultControlClasses(classes) {
|
|
330
|
+
return classes == null || ["month", "year", "nav"].some((role) => !Object.hasOwn(classes, role));
|
|
331
|
+
}
|
|
332
|
+
function resolveControlClasses(classes) {
|
|
333
|
+
return { ...getDefaultControlClasses(), ...normalizeControlClasses(classes) };
|
|
334
|
+
}
|
|
335
|
+
function setDefaultControlClasses(classes) {
|
|
336
|
+
const next = resolveControlClasses(classes);
|
|
337
|
+
if (sameControlClasses(defaults, next))
|
|
338
|
+
return;
|
|
339
|
+
defaults = next;
|
|
340
|
+
for (const listener of listeners)
|
|
341
|
+
listener();
|
|
342
|
+
}
|
|
343
|
+
var listeners = new Set;
|
|
344
|
+
function subscribeDefaultControlClasses(listener) {
|
|
345
|
+
listeners.add(listener);
|
|
346
|
+
return () => {
|
|
347
|
+
listeners.delete(listener);
|
|
348
|
+
};
|
|
349
|
+
}
|
|
324
350
|
|
|
325
351
|
// src/date-range.js
|
|
326
352
|
function normalizeRange(range) {
|
|
@@ -703,6 +729,18 @@
|
|
|
703
729
|
function getDefaultMessages() {
|
|
704
730
|
return { ...defaults2 };
|
|
705
731
|
}
|
|
732
|
+
function setDefaultMessages(messages) {
|
|
733
|
+
defaults2 = { ...defaults2, ...messages };
|
|
734
|
+
for (const listener of listeners2)
|
|
735
|
+
listener();
|
|
736
|
+
}
|
|
737
|
+
var listeners2 = new Set;
|
|
738
|
+
function subscribeDefaultMessages(listener) {
|
|
739
|
+
listeners2.add(listener);
|
|
740
|
+
return () => {
|
|
741
|
+
listeners2.delete(listener);
|
|
742
|
+
};
|
|
743
|
+
}
|
|
706
744
|
|
|
707
745
|
// src/source.js
|
|
708
746
|
function normalizeDateStates(payload) {
|
|
@@ -725,6 +763,17 @@
|
|
|
725
763
|
return map;
|
|
726
764
|
}
|
|
727
765
|
|
|
766
|
+
// src/upgrade-properties.js
|
|
767
|
+
function upgradeProperties(element, properties) {
|
|
768
|
+
for (const property of properties) {
|
|
769
|
+
if (!Object.hasOwn(element, property))
|
|
770
|
+
continue;
|
|
771
|
+
const value = Reflect.get(element, property);
|
|
772
|
+
Reflect.deleteProperty(element, property);
|
|
773
|
+
Reflect.set(element, property, value);
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
|
|
728
777
|
// src/date-calendar.js
|
|
729
778
|
var uid = 0;
|
|
730
779
|
function escapeHtml(value) {
|
|
@@ -783,6 +832,18 @@
|
|
|
783
832
|
"selection",
|
|
784
833
|
"month-format"
|
|
785
834
|
];
|
|
835
|
+
static setDefaultControlClasses(classes) {
|
|
836
|
+
setDefaultControlClasses(classes);
|
|
837
|
+
}
|
|
838
|
+
static getDefaultControlClasses() {
|
|
839
|
+
return getDefaultControlClasses();
|
|
840
|
+
}
|
|
841
|
+
static setDefaultMessages(messages) {
|
|
842
|
+
setDefaultMessages(messages);
|
|
843
|
+
}
|
|
844
|
+
static getDefaultMessages() {
|
|
845
|
+
return getDefaultMessages();
|
|
846
|
+
}
|
|
786
847
|
constructor() {
|
|
787
848
|
super();
|
|
788
849
|
this._id = `date-calendar-${++uid}`;
|
|
@@ -790,6 +851,7 @@
|
|
|
790
851
|
this._connected = false;
|
|
791
852
|
this._rendering = false;
|
|
792
853
|
this._source = null;
|
|
854
|
+
this._hostIntent = null;
|
|
793
855
|
this._sourceStates = new Map;
|
|
794
856
|
this._loadedRanges = new Set;
|
|
795
857
|
this._loadController = null;
|
|
@@ -802,8 +864,10 @@
|
|
|
802
864
|
this._paintedRange = { start: "", end: "" };
|
|
803
865
|
this._paintedPreview = false;
|
|
804
866
|
this._renderedStates = new Map;
|
|
805
|
-
this._messages =
|
|
806
|
-
this._controlClasses =
|
|
867
|
+
this._messages = null;
|
|
868
|
+
this._controlClasses = null;
|
|
869
|
+
this._stopDefaultMessages = null;
|
|
870
|
+
this._stopDefaultControlClasses = null;
|
|
807
871
|
this._onClick = this._onClick.bind(this);
|
|
808
872
|
this._onChange = this._onChange.bind(this);
|
|
809
873
|
this._onKeyDown = this._onKeyDown.bind(this);
|
|
@@ -812,15 +876,47 @@
|
|
|
812
876
|
connectedCallback() {
|
|
813
877
|
if (this._connected)
|
|
814
878
|
return;
|
|
879
|
+
upgradeProperties(this, [
|
|
880
|
+
"locale",
|
|
881
|
+
"min",
|
|
882
|
+
"max",
|
|
883
|
+
"firstDay",
|
|
884
|
+
"selection",
|
|
885
|
+
"monthFormat",
|
|
886
|
+
"fixedWeeks",
|
|
887
|
+
"showWeekNumbers",
|
|
888
|
+
"controlClasses",
|
|
889
|
+
"messages",
|
|
890
|
+
"source",
|
|
891
|
+
"dateState",
|
|
892
|
+
"renderDay",
|
|
893
|
+
"isDateDisabled",
|
|
894
|
+
"highlightedRange",
|
|
895
|
+
"value",
|
|
896
|
+
"display"
|
|
897
|
+
]);
|
|
898
|
+
this._syncModel();
|
|
899
|
+
upgradeProperties(this, ["focusedDate"]);
|
|
900
|
+
this._stopDefaultControlClasses = subscribeDefaultControlClasses(() => {
|
|
901
|
+
if (usesDefaultControlClasses(this._controlClasses))
|
|
902
|
+
this.render();
|
|
903
|
+
});
|
|
904
|
+
this._stopDefaultMessages = subscribeDefaultMessages(() => {
|
|
905
|
+
if (this._messages === null)
|
|
906
|
+
this.render();
|
|
907
|
+
});
|
|
815
908
|
this._connected = true;
|
|
816
909
|
this.addEventListener("click", this._onClick);
|
|
817
910
|
this.addEventListener("change", this._onChange);
|
|
818
911
|
this.addEventListener("keydown", this._onKeyDown);
|
|
819
912
|
this.addEventListener("focusin", this._onFocusIn);
|
|
820
|
-
this._syncModel();
|
|
821
913
|
this.render();
|
|
822
914
|
}
|
|
823
915
|
disconnectedCallback() {
|
|
916
|
+
this._stopDefaultControlClasses?.();
|
|
917
|
+
this._stopDefaultControlClasses = null;
|
|
918
|
+
this._stopDefaultMessages?.();
|
|
919
|
+
this._stopDefaultMessages = null;
|
|
824
920
|
this._connected = false;
|
|
825
921
|
this._loadController?.abort();
|
|
826
922
|
this._loadController = null;
|
|
@@ -941,21 +1037,21 @@
|
|
|
941
1037
|
this.toggleAttribute("show-week-numbers", Boolean(value));
|
|
942
1038
|
}
|
|
943
1039
|
get controlClasses() {
|
|
944
|
-
return
|
|
1040
|
+
return resolveControlClasses(this._controlClasses);
|
|
945
1041
|
}
|
|
946
1042
|
set controlClasses(value) {
|
|
947
|
-
const
|
|
948
|
-
|
|
1043
|
+
const previous = this.controlClasses;
|
|
1044
|
+
this._controlClasses = normalizeControlClasses(value);
|
|
1045
|
+
if (sameControlClasses(previous, this.controlClasses))
|
|
949
1046
|
return;
|
|
950
|
-
this._controlClasses = classes;
|
|
951
1047
|
if (this._connected)
|
|
952
1048
|
this.render();
|
|
953
1049
|
}
|
|
954
1050
|
get messages() {
|
|
955
|
-
return this._messages;
|
|
1051
|
+
return this._messages ?? getDefaultMessages();
|
|
956
1052
|
}
|
|
957
1053
|
set messages(value) {
|
|
958
|
-
this._messages = { ...getDefaultMessages(), ...value
|
|
1054
|
+
this._messages = value == null ? null : { ...getDefaultMessages(), ...value };
|
|
959
1055
|
if (this._connected)
|
|
960
1056
|
this.render();
|
|
961
1057
|
}
|
|
@@ -1192,6 +1288,15 @@
|
|
|
1192
1288
|
this.focusGrid();
|
|
1193
1289
|
}
|
|
1194
1290
|
}
|
|
1291
|
+
_syncRovingDom(date) {
|
|
1292
|
+
for (const cell of this.querySelectorAll('.dp-day[tabindex="0"]')) {
|
|
1293
|
+
if (cell instanceof HTMLElement && cell.dataset.date !== date)
|
|
1294
|
+
cell.tabIndex = -1;
|
|
1295
|
+
}
|
|
1296
|
+
const cell = this.querySelector(`.dp-day[data-date="${CSS.escape(date)}"]`);
|
|
1297
|
+
if (cell instanceof HTMLElement)
|
|
1298
|
+
cell.tabIndex = 0;
|
|
1299
|
+
}
|
|
1195
1300
|
_moveSelectionDom(previousValue, nextValue) {
|
|
1196
1301
|
if (previousValue) {
|
|
1197
1302
|
const prev = this.querySelector(`.dp-day[data-date="${CSS.escape(previousValue)}"]`);
|
|
@@ -1216,8 +1321,8 @@
|
|
|
1216
1321
|
return [
|
|
1217
1322
|
formatLongDate(date, this.locale),
|
|
1218
1323
|
description,
|
|
1219
|
-
rangeLabel ? this.
|
|
1220
|
-
state.disabled ? this.
|
|
1324
|
+
rangeLabel ? this.messages[rangeLabel] : "",
|
|
1325
|
+
state.disabled ? this.messages.unavailable : ""
|
|
1221
1326
|
].filter(Boolean).join(". ");
|
|
1222
1327
|
}
|
|
1223
1328
|
_updateRangeDom() {
|
|
@@ -1252,17 +1357,24 @@
|
|
|
1252
1357
|
target.focus();
|
|
1253
1358
|
}
|
|
1254
1359
|
async activateDate(date) {
|
|
1360
|
+
const hostIntent = this._hostIntent?.date === date ? this._hostIntent.intent : undefined;
|
|
1361
|
+
this._hostIntent = null;
|
|
1362
|
+
const tagged = (event) => {
|
|
1363
|
+
if (hostIntent !== undefined)
|
|
1364
|
+
activationIntents.set(event, hostIntent);
|
|
1365
|
+
return event;
|
|
1366
|
+
};
|
|
1255
1367
|
const confirmed = await this.ensureDate(date);
|
|
1256
1368
|
const state = this.getDateState(date);
|
|
1257
1369
|
if (!confirmed || state.disabled) {
|
|
1258
|
-
this.dispatchEvent(new CustomEvent("dateinvalid", { detail: { date, state }, bubbles: true }));
|
|
1370
|
+
this.dispatchEvent(tagged(new CustomEvent("dateinvalid", { detail: { date, state }, bubbles: true })));
|
|
1259
1371
|
return false;
|
|
1260
1372
|
}
|
|
1261
|
-
const accepted = this.dispatchEvent(new CustomEvent("dateactivate", {
|
|
1373
|
+
const accepted = this.dispatchEvent(tagged(new CustomEvent("dateactivate", {
|
|
1262
1374
|
detail: { date, state },
|
|
1263
1375
|
bubbles: true,
|
|
1264
1376
|
cancelable: true
|
|
1265
|
-
}));
|
|
1377
|
+
})));
|
|
1266
1378
|
if (!accepted)
|
|
1267
1379
|
return false;
|
|
1268
1380
|
if (this.selection === "single") {
|
|
@@ -1307,6 +1419,8 @@
|
|
|
1307
1419
|
this._reflect("display", this._model.display);
|
|
1308
1420
|
if (previousDisplay !== this.display)
|
|
1309
1421
|
this._emitDisplayChange();
|
|
1422
|
+
else
|
|
1423
|
+
this._syncRovingDom(this._model.focused);
|
|
1310
1424
|
this.activateDate(date);
|
|
1311
1425
|
}
|
|
1312
1426
|
_onChange(event) {
|
|
@@ -1317,7 +1431,7 @@
|
|
|
1317
1431
|
}
|
|
1318
1432
|
if (target instanceof HTMLInputElement && target.matches(".dp-year-input")) {
|
|
1319
1433
|
const year = Number(target.value);
|
|
1320
|
-
if (!Number.isInteger(year) || year < 1 || year >
|
|
1434
|
+
if (!Number.isInteger(year) || year < 1 || year > 9999) {
|
|
1321
1435
|
if (this._connected)
|
|
1322
1436
|
this.render(false);
|
|
1323
1437
|
return;
|
|
@@ -1333,6 +1447,7 @@
|
|
|
1333
1447
|
if (!isDate(date))
|
|
1334
1448
|
return;
|
|
1335
1449
|
this._model.focused = date;
|
|
1450
|
+
this._syncRovingDom(date);
|
|
1336
1451
|
this.dispatchEvent(new CustomEvent("datefocus", { detail: { date, state: this.getDateState(date) }, bubbles: true }));
|
|
1337
1452
|
}
|
|
1338
1453
|
_onKeyDown(event) {
|
|
@@ -1395,10 +1510,10 @@
|
|
|
1395
1510
|
const nextKey = stepMonthKey(display, 1);
|
|
1396
1511
|
const prevDisabled = Boolean(minMonth && prevKey !== null && prevKey < minMonth);
|
|
1397
1512
|
const nextDisabled = Boolean(maxMonth && nextKey !== null && nextKey > maxMonth);
|
|
1398
|
-
const minYearAttr =
|
|
1399
|
-
const maxYearAttr =
|
|
1513
|
+
const minYearAttr = ` min="${this.min ? Number(this.min.slice(0, 4)) : 1}"`;
|
|
1514
|
+
const maxYearAttr = ` max="${this.max ? Number(this.max.slice(0, 4)) : 9999}"`;
|
|
1400
1515
|
const showWeeks = this.showWeekNumbers && this.firstDay === 1;
|
|
1401
|
-
const weekHeader = showWeeks ? `<th scope="col" class="dp-week-heading" abbr="${escapeHtml(this.
|
|
1516
|
+
const weekHeader = showWeeks ? `<th scope="col" class="dp-week-heading" abbr="${escapeHtml(this.messages.week)}">#</th>` : "";
|
|
1402
1517
|
const monthOptions = names.map((name, index) => {
|
|
1403
1518
|
const month = index + 1;
|
|
1404
1519
|
const key = `${String(displayYear).padStart(4, "0")}-${String(month).padStart(2, "0")}`;
|
|
@@ -1426,22 +1541,22 @@
|
|
|
1426
1541
|
const focusKey = focusedElement instanceof HTMLElement && this.contains(focusedElement) ? this._focusTargetKey(focusedElement) : "";
|
|
1427
1542
|
const yearFirst = monthYearOrder(locale)[0] === "year";
|
|
1428
1543
|
this.toggleAttribute("data-year-first", yearFirst);
|
|
1429
|
-
const classes = this.
|
|
1544
|
+
const classes = this.controlClasses;
|
|
1430
1545
|
const monthClass = escapeHtml(classes.month || "dp-skin");
|
|
1431
1546
|
const yearClass = escapeHtml(classes.year || "dp-skin");
|
|
1432
1547
|
const navClass = escapeHtml(classes.nav || "dp-skin");
|
|
1433
|
-
const monthControl = `<label class="dp-visually-hidden" for="${this._id}-month">${escapeHtml(this.
|
|
1434
|
-
<select id="${this._id}-month" class="dp-month-select ${monthClass}" aria-label="${escapeHtml(this.
|
|
1435
|
-
const yearControl = `<label class="dp-visually-hidden" for="${this._id}-year">${escapeHtml(this.
|
|
1436
|
-
<input id="${this._id}-year" class="dp-year-input ${yearClass}" type="number" inputmode="numeric" value="${displayYear}"${minYearAttr}${maxYearAttr} aria-label="${escapeHtml(this.
|
|
1548
|
+
const monthControl = `<label class="dp-visually-hidden" for="${this._id}-month">${escapeHtml(this.messages.month)}</label>
|
|
1549
|
+
<select id="${this._id}-month" class="dp-month-select ${monthClass}" aria-label="${escapeHtml(this.messages.month)}">${monthOptions}</select>`;
|
|
1550
|
+
const yearControl = `<label class="dp-visually-hidden" for="${this._id}-year">${escapeHtml(this.messages.year)}</label>
|
|
1551
|
+
<input id="${this._id}-year" class="dp-year-input ${yearClass}" type="number" inputmode="numeric" value="${displayYear}"${minYearAttr}${maxYearAttr} aria-label="${escapeHtml(this.messages.year)}">`;
|
|
1437
1552
|
this._rendering = true;
|
|
1438
1553
|
this.innerHTML = `
|
|
1439
1554
|
<div class="dp-calendar-shell">
|
|
1440
1555
|
<div class="dp-calendar-header">
|
|
1441
1556
|
${yearFirst ? yearControl : monthControl}
|
|
1442
1557
|
${yearFirst ? monthControl : yearControl}
|
|
1443
|
-
<button type="button" class="dp-nav dp-prev ${navClass}" data-calendar-action="previous" aria-label="${escapeHtml(this.
|
|
1444
|
-
<button type="button" class="dp-nav dp-next ${navClass}" data-calendar-action="next" aria-label="${escapeHtml(this.
|
|
1558
|
+
<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
|
+
<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>
|
|
1445
1560
|
</div>
|
|
1446
1561
|
<h2 id="${headingId}" class="dp-calendar-heading dp-visually-hidden" aria-live="polite">${escapeHtml(formatMonthYear(`${display}-15`, locale))}</h2>
|
|
1447
1562
|
<table id="${gridId}" class="dp-grid" role="grid" aria-labelledby="${headingId}">
|
|
@@ -1854,6 +1969,10 @@
|
|
|
1854
1969
|
}
|
|
1855
1970
|
|
|
1856
1971
|
// src/date-field.js
|
|
1972
|
+
function isEditable(input) {
|
|
1973
|
+
return !input.matches(":disabled") && !input.readOnly;
|
|
1974
|
+
}
|
|
1975
|
+
|
|
1857
1976
|
class DateFieldController {
|
|
1858
1977
|
constructor(input, options = {}) {
|
|
1859
1978
|
this.input = input;
|
|
@@ -1867,9 +1986,22 @@
|
|
|
1867
1986
|
this._attributeObserver = null;
|
|
1868
1987
|
this.onAttributesChanged = null;
|
|
1869
1988
|
this.confirm = null;
|
|
1989
|
+
this._generatedDefault = null;
|
|
1870
1990
|
}
|
|
1871
1991
|
setLocale(locale) {
|
|
1992
|
+
const generated = this._generatedDefault;
|
|
1993
|
+
const previous = generated ? this.adapter.format(generated) : null;
|
|
1872
1994
|
this.adapter = createDateAdapter(locale || "");
|
|
1995
|
+
if (generated && this.input.defaultValue === previous) {
|
|
1996
|
+
this.input.defaultValue = this.adapter.format(generated);
|
|
1997
|
+
}
|
|
1998
|
+
}
|
|
1999
|
+
adoptDefault() {
|
|
2000
|
+
const input = this.input;
|
|
2001
|
+
if (input.getAttribute("value") != null || input.defaultValue !== "")
|
|
2002
|
+
return;
|
|
2003
|
+
input.defaultValue = input.value;
|
|
2004
|
+
this._generatedDefault = this.canonical && input.value ? this.canonical : null;
|
|
1873
2005
|
}
|
|
1874
2006
|
setMessages(messages) {
|
|
1875
2007
|
this.messages = messages || {};
|
|
@@ -1884,7 +2016,7 @@
|
|
|
1884
2016
|
return this.adapter.placeholder;
|
|
1885
2017
|
}
|
|
1886
2018
|
get isDisabled() {
|
|
1887
|
-
return this.input.disabled;
|
|
2019
|
+
return this.input.matches(":disabled");
|
|
1888
2020
|
}
|
|
1889
2021
|
get isReadOnly() {
|
|
1890
2022
|
return this.input.readOnly;
|
|
@@ -2045,6 +2177,18 @@
|
|
|
2045
2177
|
|
|
2046
2178
|
class DatePickerElement extends HTMLElement {
|
|
2047
2179
|
static observedAttributes = ["value", "locale", "min", "max", "open-on-focus", "month-format"];
|
|
2180
|
+
static setDefaultControlClasses(classes) {
|
|
2181
|
+
setDefaultControlClasses(classes);
|
|
2182
|
+
}
|
|
2183
|
+
static getDefaultControlClasses() {
|
|
2184
|
+
return getDefaultControlClasses();
|
|
2185
|
+
}
|
|
2186
|
+
static setDefaultMessages(messages) {
|
|
2187
|
+
setDefaultMessages(messages);
|
|
2188
|
+
}
|
|
2189
|
+
static getDefaultMessages() {
|
|
2190
|
+
return getDefaultMessages();
|
|
2191
|
+
}
|
|
2048
2192
|
constructor() {
|
|
2049
2193
|
super();
|
|
2050
2194
|
this._id = `date-picker-${++uid2}`;
|
|
@@ -2059,8 +2203,7 @@
|
|
|
2059
2203
|
this._timeFields = [null, null];
|
|
2060
2204
|
this._timeOrderOwned = new Set;
|
|
2061
2205
|
this._lastFocusEndpoint = "";
|
|
2062
|
-
this.
|
|
2063
|
-
this._pendingIntents = new Map;
|
|
2206
|
+
this._activationId = 0;
|
|
2064
2207
|
this._previewDate = "";
|
|
2065
2208
|
this._drag = null;
|
|
2066
2209
|
this._suppressGridClick = false;
|
|
@@ -2076,8 +2219,9 @@
|
|
|
2076
2219
|
this._stopTracking = null;
|
|
2077
2220
|
this._open = false;
|
|
2078
2221
|
this._suppressFocusOpen = false;
|
|
2079
|
-
this._messages =
|
|
2080
|
-
this._controlClasses =
|
|
2222
|
+
this._messages = null;
|
|
2223
|
+
this._controlClasses = null;
|
|
2224
|
+
this._stopDefaultMessages = null;
|
|
2081
2225
|
this._source = null;
|
|
2082
2226
|
this._dateState = null;
|
|
2083
2227
|
this._renderDay = null;
|
|
@@ -2090,11 +2234,32 @@
|
|
|
2090
2234
|
connectedCallback() {
|
|
2091
2235
|
if (this._connected)
|
|
2092
2236
|
return;
|
|
2093
|
-
|
|
2237
|
+
upgradeProperties(this, [
|
|
2238
|
+
"locale",
|
|
2239
|
+
"min",
|
|
2240
|
+
"max",
|
|
2241
|
+
"monthFormat",
|
|
2242
|
+
"openOnFocus",
|
|
2243
|
+
"coordinateSpace",
|
|
2244
|
+
"controlClasses",
|
|
2245
|
+
"messages",
|
|
2246
|
+
"source",
|
|
2247
|
+
"dateState",
|
|
2248
|
+
"renderDay",
|
|
2249
|
+
"isDateDisabled"
|
|
2250
|
+
]);
|
|
2251
|
+
if (this.hasAttribute("range"))
|
|
2094
2252
|
this._connectRange();
|
|
2095
|
-
|
|
2253
|
+
else
|
|
2254
|
+
this._connectSingle();
|
|
2255
|
+
if (this._connected) {
|
|
2256
|
+
upgradeProperties(this, ["value", "range"]);
|
|
2257
|
+
this._stopDefaultMessages = subscribeDefaultMessages(() => {
|
|
2258
|
+
if (this._messages === null)
|
|
2259
|
+
this._refreshMessages();
|
|
2260
|
+
});
|
|
2261
|
+
this.validate();
|
|
2096
2262
|
}
|
|
2097
|
-
this._connectSingle();
|
|
2098
2263
|
}
|
|
2099
2264
|
_connectSingle() {
|
|
2100
2265
|
const input = this.querySelector(":scope > input:not([type=hidden]):not([type=time]):not([data-time-start]):not([data-time-end])");
|
|
@@ -2105,7 +2270,7 @@
|
|
|
2105
2270
|
this._connected = true;
|
|
2106
2271
|
this._input = input;
|
|
2107
2272
|
this._discoverTimeFields();
|
|
2108
|
-
this._field = new DateFieldController(input, { messages: this.
|
|
2273
|
+
this._field = new DateFieldController(input, { messages: this.messages, locale: this.locale });
|
|
2109
2274
|
this._field.onAttributesChanged = () => this._syncInputState();
|
|
2110
2275
|
this._field.confirm = (date, options) => this._confirmDate(date, options);
|
|
2111
2276
|
this._setupFormValue();
|
|
@@ -2120,12 +2285,10 @@
|
|
|
2120
2285
|
else if (!input.value)
|
|
2121
2286
|
this._setValue("", { emit: false, format: false });
|
|
2122
2287
|
else
|
|
2123
|
-
input.setCustomValidity(this.
|
|
2288
|
+
input.setCustomValidity(this.messages.invalidDate);
|
|
2124
2289
|
if (this._field.hidden)
|
|
2125
2290
|
this._field.hidden.defaultValue = this._value;
|
|
2126
|
-
|
|
2127
|
-
input.defaultValue = input.value;
|
|
2128
|
-
}
|
|
2291
|
+
this._field.adoptDefault();
|
|
2129
2292
|
}
|
|
2130
2293
|
_discoverTimeFields() {
|
|
2131
2294
|
this._timeFields = [null, null];
|
|
@@ -2161,8 +2324,8 @@
|
|
|
2161
2324
|
this._connected = true;
|
|
2162
2325
|
this._input = null;
|
|
2163
2326
|
this._fields = [
|
|
2164
|
-
new DateFieldController(startInput, { messages: this.
|
|
2165
|
-
new DateFieldController(endInput, { messages: this.
|
|
2327
|
+
new DateFieldController(startInput, { messages: this.messages, locale: this.locale }),
|
|
2328
|
+
new DateFieldController(endInput, { messages: this.messages, locale: this.locale })
|
|
2166
2329
|
];
|
|
2167
2330
|
this._range = new DateRangeController;
|
|
2168
2331
|
this._rangeOriginalDescribedBy = [
|
|
@@ -2182,23 +2345,28 @@
|
|
|
2182
2345
|
const adapter = this._adapter();
|
|
2183
2346
|
const initialStart = isDate(startInput.value) ? startInput.value : adapter.parse(startInput.value);
|
|
2184
2347
|
const initialEnd = isDate(endInput.value) ? endInput.value : adapter.parse(endInput.value);
|
|
2348
|
+
const startText = startInput.value;
|
|
2349
|
+
const endText = endInput.value;
|
|
2185
2350
|
this._setRange(initialStart || "", initialEnd || "", { emit: false });
|
|
2186
|
-
|
|
2187
|
-
startInput
|
|
2188
|
-
|
|
2189
|
-
|
|
2351
|
+
for (const [input, text, initial] of [
|
|
2352
|
+
[startInput, startText, initialStart],
|
|
2353
|
+
[endInput, endText, initialEnd]
|
|
2354
|
+
]) {
|
|
2355
|
+
if (!text.trim() || isDate(initial))
|
|
2356
|
+
continue;
|
|
2357
|
+
input.value = text;
|
|
2358
|
+
input.setCustomValidity(this.messages.invalidDate);
|
|
2359
|
+
}
|
|
2190
2360
|
if (this._fields[0].hidden)
|
|
2191
2361
|
this._fields[0].hidden.defaultValue = this._range.start;
|
|
2192
2362
|
if (this._fields[1].hidden)
|
|
2193
2363
|
this._fields[1].hidden.defaultValue = this._range.end;
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
}
|
|
2197
|
-
if (endInput.getAttribute("value") == null && endInput.defaultValue === "") {
|
|
2198
|
-
endInput.defaultValue = endInput.value;
|
|
2199
|
-
}
|
|
2364
|
+
for (const field of this._fields)
|
|
2365
|
+
field.adoptDefault();
|
|
2200
2366
|
}
|
|
2201
2367
|
disconnectedCallback() {
|
|
2368
|
+
this._stopDefaultMessages?.();
|
|
2369
|
+
this._stopDefaultMessages = null;
|
|
2202
2370
|
this._connected = false;
|
|
2203
2371
|
this.hide(false);
|
|
2204
2372
|
this._controller?.abort();
|
|
@@ -2245,8 +2413,10 @@
|
|
|
2245
2413
|
if (name === "value") {
|
|
2246
2414
|
if (this._rangeMode())
|
|
2247
2415
|
return;
|
|
2248
|
-
if (!newValue || isDate(newValue))
|
|
2416
|
+
if (!newValue || isDate(newValue)) {
|
|
2417
|
+
this._supersedeActivations();
|
|
2249
2418
|
this._setValue(newValue || "", { emit: false, format: true, reflect: false });
|
|
2419
|
+
}
|
|
2250
2420
|
return;
|
|
2251
2421
|
}
|
|
2252
2422
|
if (name === "locale")
|
|
@@ -2271,6 +2441,7 @@
|
|
|
2271
2441
|
}
|
|
2272
2442
|
if (value && !isDate(value))
|
|
2273
2443
|
throw new TypeError(`Invalid date-picker value: ${value}`);
|
|
2444
|
+
this._supersedeActivations();
|
|
2274
2445
|
this._setValue(value || "", { emit: false, format: true });
|
|
2275
2446
|
}
|
|
2276
2447
|
get range() {
|
|
@@ -2280,6 +2451,7 @@
|
|
|
2280
2451
|
if (!this._rangeMode())
|
|
2281
2452
|
throw new TypeError("range is only available on <date-picker range>");
|
|
2282
2453
|
const { start, end } = normalizeRange(value);
|
|
2454
|
+
this._supersedeActivations();
|
|
2283
2455
|
this._setRange(start, end);
|
|
2284
2456
|
}
|
|
2285
2457
|
get locale() {
|
|
@@ -2333,28 +2505,34 @@
|
|
|
2333
2505
|
return this._open;
|
|
2334
2506
|
}
|
|
2335
2507
|
get controlClasses() {
|
|
2336
|
-
return
|
|
2508
|
+
return resolveControlClasses(this._controlClasses);
|
|
2337
2509
|
}
|
|
2338
2510
|
set controlClasses(value) {
|
|
2339
|
-
|
|
2340
|
-
if (sameControlClasses(classes, this._controlClasses))
|
|
2341
|
-
return;
|
|
2342
|
-
this._controlClasses = classes;
|
|
2511
|
+
this._controlClasses = normalizeControlClasses(value);
|
|
2343
2512
|
if (this._calendar)
|
|
2344
2513
|
this._calendar.controlClasses = this._controlClasses;
|
|
2345
2514
|
}
|
|
2346
2515
|
get messages() {
|
|
2347
|
-
return this._messages;
|
|
2516
|
+
return this._messages ?? getDefaultMessages();
|
|
2348
2517
|
}
|
|
2349
2518
|
set messages(value) {
|
|
2350
|
-
this._messages = { ...getDefaultMessages(), ...value
|
|
2519
|
+
this._messages = value == null ? null : { ...getDefaultMessages(), ...value };
|
|
2351
2520
|
if (this._calendar)
|
|
2352
2521
|
this._calendar.messages = this._messages;
|
|
2522
|
+
this._refreshMessages();
|
|
2523
|
+
}
|
|
2524
|
+
_refreshMessages() {
|
|
2525
|
+
const messages = this.messages;
|
|
2353
2526
|
for (const field of this._fields || [])
|
|
2354
|
-
field.setMessages(
|
|
2355
|
-
this._field?.setMessages(
|
|
2527
|
+
field.setMessages(messages);
|
|
2528
|
+
this._field?.setMessages(messages);
|
|
2529
|
+
this._panel?.setAttribute("aria-label", messages.calendar);
|
|
2530
|
+
const field = this._field ?? this._fields?.[0];
|
|
2531
|
+
if (this._formatHint && field)
|
|
2532
|
+
this._formatHint.textContent = `${messages.formatHint}: ${field.placeholder}`;
|
|
2356
2533
|
this._refreshButtonLabel();
|
|
2357
|
-
this.
|
|
2534
|
+
if (this._connected)
|
|
2535
|
+
this.validate();
|
|
2358
2536
|
}
|
|
2359
2537
|
get source() {
|
|
2360
2538
|
return this._source;
|
|
@@ -2414,7 +2592,7 @@
|
|
|
2414
2592
|
const button = this._buttons[0]?.button;
|
|
2415
2593
|
if (button)
|
|
2416
2594
|
button.disabled = input.disabled || input.readOnly;
|
|
2417
|
-
if (this._open && (input
|
|
2595
|
+
if (this._open && !isEditable(input))
|
|
2418
2596
|
this.hide(false);
|
|
2419
2597
|
}
|
|
2420
2598
|
_syncRangeFields() {
|
|
@@ -2429,9 +2607,9 @@
|
|
|
2429
2607
|
}
|
|
2430
2608
|
this._syncDragAffordance();
|
|
2431
2609
|
const active = this._range?.activeEndpoint === "end" ? 1 : 0;
|
|
2432
|
-
|
|
2610
|
+
const activeInput = this._fields[active]?.input;
|
|
2611
|
+
if (this._open && activeInput && !isEditable(activeInput))
|
|
2433
2612
|
this.hide(false);
|
|
2434
|
-
}
|
|
2435
2613
|
}
|
|
2436
2614
|
_setRangeAria() {
|
|
2437
2615
|
if (!this._fields || !this._panel || !this._formatHint)
|
|
@@ -2482,7 +2660,7 @@
|
|
|
2482
2660
|
panel.className = "dp-picker-panel";
|
|
2483
2661
|
panel.setAttribute("popover", "manual");
|
|
2484
2662
|
panel.setAttribute("role", "dialog");
|
|
2485
|
-
panel.setAttribute("aria-label", this.
|
|
2663
|
+
panel.setAttribute("aria-label", this.messages.calendar);
|
|
2486
2664
|
const calendar = new DateCalendarElement;
|
|
2487
2665
|
calendar.selection = "none";
|
|
2488
2666
|
calendar.fixedWeeks = true;
|
|
@@ -2568,15 +2746,23 @@
|
|
|
2568
2746
|
this.show({ returnFocus: button });
|
|
2569
2747
|
}, { signal });
|
|
2570
2748
|
button.addEventListener("keydown", (event) => this._onTriggerKeyDown("", event), { signal });
|
|
2749
|
+
calendar.addEventListener("click", (event) => this._captureGridIntent(event), { capture: true, signal });
|
|
2750
|
+
calendar.addEventListener("keydown", (event) => this._captureGridIntent(event), {
|
|
2751
|
+
capture: true,
|
|
2752
|
+
signal
|
|
2753
|
+
});
|
|
2571
2754
|
calendar.addEventListener("dateactivate", (event) => {
|
|
2572
2755
|
const custom = event;
|
|
2573
2756
|
const date = custom.detail?.date;
|
|
2574
2757
|
if (!isDate(date))
|
|
2575
2758
|
return;
|
|
2759
|
+
const intent = activationIntents.get(custom);
|
|
2576
2760
|
queueMicrotask(() => {
|
|
2577
2761
|
if (custom.defaultPrevented || !this._connected)
|
|
2578
2762
|
return;
|
|
2579
|
-
if (
|
|
2763
|
+
if (intent && intent.id !== this._activationId)
|
|
2764
|
+
return;
|
|
2765
|
+
if (!this._input || !isEditable(this._input))
|
|
2580
2766
|
return;
|
|
2581
2767
|
this._field?.dirty();
|
|
2582
2768
|
this._setValue(date, { emit: true, format: true });
|
|
@@ -2596,7 +2782,12 @@
|
|
|
2596
2782
|
const { signal } = controller;
|
|
2597
2783
|
for (const [index, field] of this._fields.entries()) {
|
|
2598
2784
|
const endpoint = index === 1 ? "end" : "start";
|
|
2599
|
-
field.input.addEventListener("input", () =>
|
|
2785
|
+
field.input.addEventListener("input", () => {
|
|
2786
|
+
field.handleInput();
|
|
2787
|
+
this._orderTags.delete(index);
|
|
2788
|
+
if (!field.isDirty)
|
|
2789
|
+
this._revalidateRange(endpoint);
|
|
2790
|
+
}, { signal });
|
|
2600
2791
|
field.input.addEventListener("change", () => void this._commitFieldText(endpoint), { signal });
|
|
2601
2792
|
field.input.addEventListener("blur", () => void this._commitFieldText(endpoint), { signal });
|
|
2602
2793
|
field.input.addEventListener("focus", (event) => this._onFieldFocus(endpoint, event), { signal });
|
|
@@ -2634,10 +2825,9 @@
|
|
|
2634
2825
|
queueMicrotask(() => {
|
|
2635
2826
|
if (custom.defaultPrevented || !this._connected || !this._range)
|
|
2636
2827
|
return;
|
|
2637
|
-
const intent =
|
|
2638
|
-
if (intent === undefined || intent.id !== this.
|
|
2828
|
+
const intent = activationIntents.get(custom);
|
|
2829
|
+
if (intent === undefined || intent.id !== this._activationId)
|
|
2639
2830
|
return;
|
|
2640
|
-
this._pendingIntents.delete(date);
|
|
2641
2831
|
const editable = (bound) => this._boundEditable(bound);
|
|
2642
2832
|
const result = intent.endpoint ? this._range.moveEndpoint(date, intent.endpoint, editable) : this._range.activate(date, editable);
|
|
2643
2833
|
if (result.status === "refused") {
|
|
@@ -2672,8 +2862,7 @@
|
|
|
2672
2862
|
if (!this._range || !calendar)
|
|
2673
2863
|
return;
|
|
2674
2864
|
this._range.focus(endpoint);
|
|
2675
|
-
this.
|
|
2676
|
-
this._pendingIntents.clear();
|
|
2865
|
+
this._activationId++;
|
|
2677
2866
|
this._lastFocusEndpoint = endpoint;
|
|
2678
2867
|
const target = this._boundCanonical(endpoint) || todayISO();
|
|
2679
2868
|
calendar.display = monthKey(target);
|
|
@@ -2735,8 +2924,7 @@
|
|
|
2735
2924
|
this._lastFocusEndpoint = endpoint;
|
|
2736
2925
|
this._range?.focus(endpoint);
|
|
2737
2926
|
if (switched) {
|
|
2738
|
-
this.
|
|
2739
|
-
this._pendingIntents.clear();
|
|
2927
|
+
this._activationId++;
|
|
2740
2928
|
}
|
|
2741
2929
|
if (!this.openOnFocus || this._suppressFocusOpen)
|
|
2742
2930
|
return;
|
|
@@ -2747,25 +2935,34 @@
|
|
|
2747
2935
|
this.show({ moveFocus: false });
|
|
2748
2936
|
}
|
|
2749
2937
|
_captureGridIntent(event) {
|
|
2750
|
-
if (
|
|
2938
|
+
if (this._rangeMode() ? !this._range : !this._field)
|
|
2751
2939
|
return;
|
|
2752
2940
|
if (event.type === "keydown") {
|
|
2753
2941
|
const key = event.key;
|
|
2754
2942
|
if (key !== "Enter" && key !== " ")
|
|
2755
2943
|
return;
|
|
2756
2944
|
}
|
|
2945
|
+
if (event.type === "click" && this._suppressGridClick)
|
|
2946
|
+
return;
|
|
2757
2947
|
if (!(event.target instanceof Element))
|
|
2758
2948
|
return;
|
|
2759
2949
|
const cell = event.target.closest(".dp-day[data-date]");
|
|
2760
2950
|
const date = cell?.getAttribute("data-date") || "";
|
|
2761
2951
|
if (!isDate(date))
|
|
2762
2952
|
return;
|
|
2763
|
-
this.
|
|
2764
|
-
|
|
2953
|
+
this._attachIntent(date, "");
|
|
2954
|
+
}
|
|
2955
|
+
_attachIntent(date, endpoint) {
|
|
2956
|
+
if (!this._calendar)
|
|
2957
|
+
return;
|
|
2958
|
+
this._calendar._hostIntent = { date, intent: { id: ++this._activationId, endpoint } };
|
|
2959
|
+
}
|
|
2960
|
+
_supersedeActivations() {
|
|
2961
|
+
this._activationId++;
|
|
2765
2962
|
}
|
|
2766
2963
|
_boundEditable(bound) {
|
|
2767
2964
|
const field = this._fields?.[bound === "end" ? 1 : 0];
|
|
2768
|
-
return field != null &&
|
|
2965
|
+
return field != null && isEditable(field.input);
|
|
2769
2966
|
}
|
|
2770
2967
|
_applyRangeTransition(transition) {
|
|
2771
2968
|
const fields = this._fields;
|
|
@@ -2913,8 +3110,7 @@
|
|
|
2913
3110
|
return;
|
|
2914
3111
|
}
|
|
2915
3112
|
const target = drag.endpoint === "start" ? transition.range.start : transition.range.end;
|
|
2916
|
-
this.
|
|
2917
|
-
this._pendingIntents.set(target, { id: ++this._rangeCommitId, endpoint: drag.endpoint });
|
|
3113
|
+
this._attachIntent(target, drag.endpoint);
|
|
2918
3114
|
this._calendar?.activateDate(target);
|
|
2919
3115
|
}
|
|
2920
3116
|
_onGridPointerCancel(event) {
|
|
@@ -2971,7 +3167,7 @@
|
|
|
2971
3167
|
if (!this._rangeMode() && this._value)
|
|
2972
3168
|
calendar.value = this._value;
|
|
2973
3169
|
if (panel)
|
|
2974
|
-
panel.setAttribute("aria-label", this.
|
|
3170
|
+
panel.setAttribute("aria-label", this.messages.calendar);
|
|
2975
3171
|
}
|
|
2976
3172
|
_refreshLocale() {
|
|
2977
3173
|
const hint = this._formatHint;
|
|
@@ -2980,7 +3176,7 @@
|
|
|
2980
3176
|
if (this._rangeMode() && this._fields) {
|
|
2981
3177
|
this._fields[0].setLocale(this.locale);
|
|
2982
3178
|
this._fields[1].setLocale(this.locale);
|
|
2983
|
-
hint.textContent = `${this.
|
|
3179
|
+
hint.textContent = `${this.messages.formatHint}: ${this._fields[0].placeholder}`;
|
|
2984
3180
|
for (const [index, field] of this._fields.entries()) {
|
|
2985
3181
|
if (!field.input.hasAttribute("placeholder") || this._generatedPlaceholder) {
|
|
2986
3182
|
field.input.placeholder = field.placeholder;
|
|
@@ -2997,7 +3193,7 @@
|
|
|
2997
3193
|
if (!field)
|
|
2998
3194
|
return;
|
|
2999
3195
|
field.setLocale(this.locale);
|
|
3000
|
-
hint.textContent = `${this.
|
|
3196
|
+
hint.textContent = `${this.messages.formatHint}: ${field.placeholder}`;
|
|
3001
3197
|
if (!field.input.hasAttribute("placeholder") || this._generatedPlaceholder) {
|
|
3002
3198
|
field.input.placeholder = field.placeholder;
|
|
3003
3199
|
this._generatedPlaceholder = true;
|
|
@@ -3014,7 +3210,7 @@
|
|
|
3014
3210
|
this._refreshRangeButtonLabel();
|
|
3015
3211
|
return;
|
|
3016
3212
|
}
|
|
3017
|
-
const prefix = this._value ? this.
|
|
3213
|
+
const prefix = this._value ? this.messages.changeDate : this.messages.chooseDate;
|
|
3018
3214
|
const suffix = this._value ? `, ${formatLongDate(this._value, this.locale)}` : "";
|
|
3019
3215
|
single.setAttribute("aria-label", `${prefix}${suffix}`);
|
|
3020
3216
|
}
|
|
@@ -3024,9 +3220,9 @@
|
|
|
3024
3220
|
const { start, end } = this._range;
|
|
3025
3221
|
for (const { button, endpoint } of this._buttons) {
|
|
3026
3222
|
const bound = endpoint === "end" ? end : start;
|
|
3027
|
-
const prefix = bound ? this.
|
|
3223
|
+
const prefix = bound ? this.messages.changeDate : this.messages.chooseDate;
|
|
3028
3224
|
const suffix = bound ? `, ${formatLongDate(bound, this.locale)}` : "";
|
|
3029
|
-
const boundLabel = endpoint === "end" ? this.
|
|
3225
|
+
const boundLabel = endpoint === "end" ? this.messages.rangeEnd : this.messages.rangeStart;
|
|
3030
3226
|
button.setAttribute("aria-label", `${prefix}${suffix}, ${boundLabel}`);
|
|
3031
3227
|
}
|
|
3032
3228
|
}
|
|
@@ -3073,7 +3269,7 @@
|
|
|
3073
3269
|
const confirmed = await calendar.ensureDate(date);
|
|
3074
3270
|
const state = calendar.getDateState(date);
|
|
3075
3271
|
if (!confirmed || state.disabled)
|
|
3076
|
-
return { ok: false, message: this.
|
|
3272
|
+
return { ok: false, message: this.messages.unavailableDate };
|
|
3077
3273
|
return { ok: true };
|
|
3078
3274
|
}
|
|
3079
3275
|
async _commitText(emit, options = {}) {
|
|
@@ -3120,7 +3316,7 @@
|
|
|
3120
3316
|
const field = fields[index];
|
|
3121
3317
|
if (!field)
|
|
3122
3318
|
return false;
|
|
3123
|
-
if (options.user === true && (field.input
|
|
3319
|
+
if (options.user === true && !isEditable(field.input))
|
|
3124
3320
|
return false;
|
|
3125
3321
|
const next = value || "";
|
|
3126
3322
|
const previous = field.canonical;
|
|
@@ -3189,7 +3385,7 @@
|
|
|
3189
3385
|
for (const bound of bounds) {
|
|
3190
3386
|
const index = bound === "end" ? 1 : 0;
|
|
3191
3387
|
const input = this._fields[index].input;
|
|
3192
|
-
const message = bound === "end" ? this.
|
|
3388
|
+
const message = bound === "end" ? this.messages.rangeOrderEnd : this.messages.rangeOrderStart;
|
|
3193
3389
|
const shouldHaveOrder = inverted && bound === which;
|
|
3194
3390
|
if (shouldHaveOrder) {
|
|
3195
3391
|
input.setCustomValidity(message);
|
|
@@ -3204,14 +3400,14 @@
|
|
|
3204
3400
|
const [startInput, endInput] = this._timeFields;
|
|
3205
3401
|
const bounds = ["start", "end"];
|
|
3206
3402
|
const inputs = [startInput, endInput];
|
|
3207
|
-
const startValue = startInput && !startInput.disabled ? startInput.value.trim() : "";
|
|
3208
|
-
const endValue = endInput && !endInput.disabled ? endInput.value.trim() : "";
|
|
3403
|
+
const startValue = startInput && !startInput.matches(":disabled") ? startInput.value.trim() : "";
|
|
3404
|
+
const endValue = endInput && !endInput.matches(":disabled") ? endInput.value.trim() : "";
|
|
3209
3405
|
const inverted = Boolean(startInput && endInput && startValue && endValue) && isTime(startValue) && isTime(endValue) && compareTimes(endValue, startValue) < 0;
|
|
3210
3406
|
for (const [index, bound] of bounds.entries()) {
|
|
3211
3407
|
const input = inputs[index];
|
|
3212
3408
|
if (!input)
|
|
3213
3409
|
continue;
|
|
3214
|
-
const message = bound === "end" ? this.
|
|
3410
|
+
const message = bound === "end" ? this.messages.rangeOrderEnd : this.messages.rangeOrderStart;
|
|
3215
3411
|
const shouldHaveOrder = inverted && bound === which;
|
|
3216
3412
|
if (shouldHaveOrder) {
|
|
3217
3413
|
input.setCustomValidity(message);
|
|
@@ -3284,12 +3480,12 @@
|
|
|
3284
3480
|
return "";
|
|
3285
3481
|
const preferred = this._lastFocusEndpoint || "start";
|
|
3286
3482
|
const preferredIndex = preferred === "end" ? 1 : 0;
|
|
3287
|
-
if (
|
|
3483
|
+
if (isEditable(this._fields[preferredIndex].input)) {
|
|
3288
3484
|
return preferred;
|
|
3289
3485
|
}
|
|
3290
3486
|
const alternative = preferred === "end" ? "start" : "end";
|
|
3291
3487
|
const alternativeIndex = alternative === "end" ? 1 : 0;
|
|
3292
|
-
if (
|
|
3488
|
+
if (isEditable(this._fields[alternativeIndex].input)) {
|
|
3293
3489
|
return alternative;
|
|
3294
3490
|
}
|
|
3295
3491
|
return "";
|
|
@@ -3301,6 +3497,8 @@
|
|
|
3301
3497
|
return true;
|
|
3302
3498
|
for (const [index, field] of fields.entries()) {
|
|
3303
3499
|
const result = await field.commit({ moveDisplay: false });
|
|
3500
|
+
if (result.status === "invalid")
|
|
3501
|
+
this._orderTags.delete(index);
|
|
3304
3502
|
if (result.status === "ok" || result.status === "clear") {
|
|
3305
3503
|
const which = index === 1 ? "end" : "start";
|
|
3306
3504
|
this._setBound(which, result.value || "", { format: result.status === "ok" });
|
|
@@ -3313,11 +3511,7 @@
|
|
|
3313
3511
|
const input = this._field?.input;
|
|
3314
3512
|
if (!input)
|
|
3315
3513
|
return true;
|
|
3316
|
-
|
|
3317
|
-
input.setCustomValidity("");
|
|
3318
|
-
} else {
|
|
3319
|
-
await this._commitText(false, { force: true, moveDisplay: false });
|
|
3320
|
-
}
|
|
3514
|
+
await this._commitText(false, { force: true, moveDisplay: false });
|
|
3321
3515
|
this._revalidateTimeOrder("start");
|
|
3322
3516
|
this._revalidateTimeOrder("end");
|
|
3323
3517
|
const timesValid = this._timeFields.every((timeInput) => timeInput?.checkValidity() ?? true);
|
|
@@ -3335,7 +3529,7 @@
|
|
|
3335
3529
|
this._activateRangeEndpoint(endpoint);
|
|
3336
3530
|
} else {
|
|
3337
3531
|
const input = this._input;
|
|
3338
|
-
if (!input || input
|
|
3532
|
+
if (!input || !isEditable(input))
|
|
3339
3533
|
return;
|
|
3340
3534
|
const target = this._value || this._adapter().parse(input.value) || todayISO();
|
|
3341
3535
|
calendar.display = monthKey(target);
|
|
@@ -3377,8 +3571,7 @@
|
|
|
3377
3571
|
} catch {}
|
|
3378
3572
|
this._open = false;
|
|
3379
3573
|
this._setExpanded(false);
|
|
3380
|
-
this.
|
|
3381
|
-
this._pendingIntents.clear();
|
|
3574
|
+
this._supersedeActivations();
|
|
3382
3575
|
this._suppressGridClick = false;
|
|
3383
3576
|
if (this._drag) {
|
|
3384
3577
|
this._releaseDragCapture(this._drag.pointerId);
|
|
@@ -3401,7 +3594,7 @@
|
|
|
3401
3594
|
if (active) {
|
|
3402
3595
|
const index = active === "end" ? 1 : 0;
|
|
3403
3596
|
const field = this._fields?.[index];
|
|
3404
|
-
if (field &&
|
|
3597
|
+
if (field && isEditable(field.input))
|
|
3405
3598
|
return active;
|
|
3406
3599
|
}
|
|
3407
3600
|
return this._resolveRangeEndpoint();
|