@lekoala/date-picker 0.4.0 → 0.5.1

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.
Files changed (39) hide show
  1. package/README.md +294 -265
  2. package/custom-elements.json +50 -0
  3. package/dist/date-picker.css +20 -15
  4. package/dist/date-picker.js +366 -149
  5. package/dist/date-picker.min.css +1 -1
  6. package/dist/date-picker.min.js +13 -13
  7. package/dist/date-picker.standalone.min.js +34 -29
  8. package/dist/types/control-classes.d.ts +40 -0
  9. package/dist/types/control-classes.d.ts.map +1 -0
  10. package/dist/types/date-calendar.d.ts +35 -43
  11. package/dist/types/date-calendar.d.ts.map +1 -1
  12. package/dist/types/date-picker.d.ts +44 -53
  13. package/dist/types/date-picker.d.ts.map +1 -1
  14. package/dist/types/date.d.ts +4 -2
  15. package/dist/types/date.d.ts.map +1 -1
  16. package/dist/types/index.d.ts +1 -0
  17. package/dist/types/index.d.ts.map +1 -1
  18. package/dist/types/intl.d.ts.map +1 -1
  19. package/dist/types/messages.d.ts +2 -0
  20. package/dist/types/messages.d.ts.map +1 -1
  21. package/dist/types/source.d.ts +1 -0
  22. package/dist/types/source.d.ts.map +1 -1
  23. package/dist/types/upgrade-properties.d.ts +8 -0
  24. package/dist/types/upgrade-properties.d.ts.map +1 -0
  25. package/docs/API.md +442 -408
  26. package/docs/DECISIONS.md +74 -62
  27. package/docs/USE_CASES.md +156 -144
  28. package/package.json +3 -3
  29. package/src/control-classes.js +80 -0
  30. package/src/date-calendar.js +124 -27
  31. package/src/date-field.js +1 -1
  32. package/src/date-picker.css +20 -15
  33. package/src/date-picker.js +133 -74
  34. package/src/date.js +8 -3
  35. package/src/index.js +1 -0
  36. package/src/intl.js +39 -10
  37. package/src/messages.js +12 -0
  38. package/src/source.js +14 -4
  39. package/src/upgrade-properties.js +14 -0
@@ -1,4 +1,4 @@
1
- /*** @lekoala/date-picker v0.4.0 - https://github.com/lekoala/date-picker ***/
1
+ /*** @lekoala/date-picker v0.5.1 - https://github.com/lekoala/date-picker ***/
2
2
  (() => {
3
3
  var __defProp = Object.defineProperty;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -181,8 +181,10 @@
181
181
  for (let i = 0;i < 7; i++)
182
182
  week.push(addDays(cursor, i));
183
183
  weeks.push(week);
184
- if (compareDates(week[6], end) >= 0)
185
- break;
184
+ if (compareDates(week[6], end) >= 0) {
185
+ if (!options.fixedWeeks || weeks.length >= 6 || compareDates(week[6], addDays("9999-12-31", -7)) > 0)
186
+ break;
187
+ }
186
188
  cursor = addDays(cursor, 7);
187
189
  }
188
190
  return weeks;
@@ -296,6 +298,53 @@
296
298
  }
297
299
  }
298
300
 
301
+ // src/control-classes.js
302
+ function normalizeControlClass(value) {
303
+ if (typeof value !== "string")
304
+ return "";
305
+ return [
306
+ ...new Set(value.split(/\s+/).filter((token) => token && !token.startsWith("dp-") && ![...token].some((char) => char.charCodeAt(0) < 32 || char.charCodeAt(0) === 127)))
307
+ ].join(" ");
308
+ }
309
+ function sameControlClasses(a, b) {
310
+ return a.month === b.month && a.year === b.year && a.nav === b.nav;
311
+ }
312
+ var defaults = { month: "", year: "", nav: "" };
313
+ function getDefaultControlClasses() {
314
+ return { ...defaults };
315
+ }
316
+ function normalizeControlClasses(classes) {
317
+ if (classes == null)
318
+ return null;
319
+ const result = {};
320
+ for (const role of ["month", "year", "nav"]) {
321
+ if (Object.hasOwn(classes, role))
322
+ result[role] = normalizeControlClass(classes[role]);
323
+ }
324
+ return result;
325
+ }
326
+ function usesDefaultControlClasses(classes) {
327
+ return classes == null || ["month", "year", "nav"].some((role) => !Object.hasOwn(classes, role));
328
+ }
329
+ function resolveControlClasses(classes) {
330
+ return { ...getDefaultControlClasses(), ...normalizeControlClasses(classes) };
331
+ }
332
+ function setDefaultControlClasses(classes) {
333
+ const next = resolveControlClasses(classes);
334
+ if (sameControlClasses(defaults, next))
335
+ return;
336
+ defaults = next;
337
+ for (const listener of listeners)
338
+ listener();
339
+ }
340
+ var listeners = new Set;
341
+ function subscribeDefaultControlClasses(listener) {
342
+ listeners.add(listener);
343
+ return () => {
344
+ listeners.delete(listener);
345
+ };
346
+ }
347
+
299
348
  // src/date-range.js
300
349
  function normalizeRange(range) {
301
350
  if (range == null)
@@ -480,6 +529,23 @@
480
529
 
481
530
  // src/intl.js
482
531
  var BIDI = /[\u200e\u200f\u061c\u202a-\u202e\u2066-\u2069]/g;
532
+ var dateFormatters = new Map;
533
+ var digitMaps = new Map;
534
+ function cached(cache, key, create) {
535
+ const existing = cache.get(key);
536
+ if (existing !== undefined)
537
+ return existing;
538
+ const value = create();
539
+ const oldest = cache.keys().next().value;
540
+ if (cache.size >= 64 && oldest !== undefined)
541
+ cache.delete(oldest);
542
+ cache.set(key, value);
543
+ return value;
544
+ }
545
+ function dateFormatter(locale, options) {
546
+ const key = JSON.stringify([locale, options]);
547
+ return cached(dateFormatters, key, () => new Intl.DateTimeFormat(locale, options));
548
+ }
483
549
  function resolveLocale(locale = "") {
484
550
  if (locale)
485
551
  return locale;
@@ -490,11 +556,13 @@
490
556
  return "en-US";
491
557
  }
492
558
  function digitMap(locale) {
493
- const formatter = new Intl.NumberFormat(locale, { useGrouping: false });
494
- const map = new Map;
495
- for (let i = 0;i <= 9; i++)
496
- map.set(formatter.format(i), String(i));
497
- return map;
559
+ return cached(digitMaps, locale, () => {
560
+ const formatter = new Intl.NumberFormat(locale, { useGrouping: false });
561
+ const map = new Map;
562
+ for (let i = 0;i <= 9; i++)
563
+ map.set(formatter.format(i), String(i));
564
+ return map;
565
+ });
498
566
  }
499
567
  function normalizeDigits(text, locale, options = {}) {
500
568
  let result = String(text || "").replace(BIDI, "");
@@ -506,7 +574,7 @@
506
574
  }
507
575
  function formatLongDate(value, locale = "") {
508
576
  const resolved = resolveLocale(locale);
509
- return new Intl.DateTimeFormat(resolved, {
577
+ return dateFormatter(resolved, {
510
578
  calendar: "gregory",
511
579
  weekday: "long",
512
580
  year: "numeric",
@@ -517,7 +585,7 @@
517
585
  }
518
586
  function formatMonthYear(value, locale = "") {
519
587
  const resolved = resolveLocale(locale);
520
- return new Intl.DateTimeFormat(resolved, {
588
+ return dateFormatter(resolved, {
521
589
  calendar: "gregory",
522
590
  year: "numeric",
523
591
  month: "long",
@@ -527,7 +595,7 @@
527
595
  function monthYearOrder(locale = "") {
528
596
  const resolved = resolveLocale(locale);
529
597
  try {
530
- const parts = new Intl.DateTimeFormat(resolved, {
598
+ const parts = dateFormatter(resolved, {
531
599
  calendar: "gregory",
532
600
  year: "numeric",
533
601
  month: "long",
@@ -552,12 +620,12 @@
552
620
  }
553
621
  function monthNames(locale = "", style = "long") {
554
622
  const resolved = resolveLocale(locale);
555
- const formatter = new Intl.DateTimeFormat(resolved, { calendar: "gregory", month: style, timeZone: "UTC" });
623
+ const formatter = dateFormatter(resolved, { calendar: "gregory", month: style, timeZone: "UTC" });
556
624
  return Array.from({ length: 12 }, (_, index) => formatter.format(toIntlDate(`2026-${String(index + 1).padStart(2, "0")}-15`)));
557
625
  }
558
626
  function weekdayNames(locale = "", firstDay = 1, style = "short") {
559
627
  const resolved = resolveLocale(locale);
560
- const formatter = new Intl.DateTimeFormat(resolved, {
628
+ const formatter = dateFormatter(resolved, {
561
629
  calendar: "gregory",
562
630
  weekday: style,
563
631
  timeZone: "UTC"
@@ -575,7 +643,7 @@
575
643
  }
576
644
  function createDateAdapter(locale = "") {
577
645
  const resolved = resolveLocale(locale);
578
- const formatter = new Intl.DateTimeFormat(resolved, {
646
+ const formatter = dateFormatter(resolved, {
579
647
  calendar: "gregory",
580
648
  year: "numeric",
581
649
  month: "2-digit",
@@ -654,9 +722,21 @@
654
722
  rangeOrderStart: "Start must be on or before end",
655
723
  rangeOrderEnd: "End must be on or after start"
656
724
  };
657
- var defaults = { ...DEFAULT_MESSAGES };
725
+ var defaults2 = { ...DEFAULT_MESSAGES };
658
726
  function getDefaultMessages() {
659
- return { ...defaults };
727
+ return { ...defaults2 };
728
+ }
729
+ function setDefaultMessages(messages) {
730
+ defaults2 = { ...defaults2, ...messages };
731
+ for (const listener of listeners2)
732
+ listener();
733
+ }
734
+ var listeners2 = new Set;
735
+ function subscribeDefaultMessages(listener) {
736
+ listeners2.add(listener);
737
+ return () => {
738
+ listeners2.delete(listener);
739
+ };
660
740
  }
661
741
 
662
742
  // src/source.js
@@ -680,6 +760,17 @@
680
760
  return map;
681
761
  }
682
762
 
763
+ // src/upgrade-properties.js
764
+ function upgradeProperties(element, properties) {
765
+ for (const property of properties) {
766
+ if (!Object.hasOwn(element, property))
767
+ continue;
768
+ const value = Reflect.get(element, property);
769
+ Reflect.deleteProperty(element, property);
770
+ Reflect.set(element, property, value);
771
+ }
772
+ }
773
+
683
774
  // src/date-calendar.js
684
775
  var uid = 0;
685
776
  function escapeHtml(value) {
@@ -738,6 +829,18 @@
738
829
  "selection",
739
830
  "month-format"
740
831
  ];
832
+ static setDefaultControlClasses(classes) {
833
+ setDefaultControlClasses(classes);
834
+ }
835
+ static getDefaultControlClasses() {
836
+ return getDefaultControlClasses();
837
+ }
838
+ static setDefaultMessages(messages) {
839
+ setDefaultMessages(messages);
840
+ }
841
+ static getDefaultMessages() {
842
+ return getDefaultMessages();
843
+ }
741
844
  constructor() {
742
845
  super();
743
846
  this._id = `date-calendar-${++uid}`;
@@ -756,7 +859,11 @@
756
859
  this._highlightedRange = { start: "", end: "" };
757
860
  this._paintedRange = { start: "", end: "" };
758
861
  this._paintedPreview = false;
759
- this._messages = getDefaultMessages();
862
+ this._renderedStates = new Map;
863
+ this._messages = null;
864
+ this._controlClasses = null;
865
+ this._stopDefaultMessages = null;
866
+ this._stopDefaultControlClasses = null;
760
867
  this._onClick = this._onClick.bind(this);
761
868
  this._onChange = this._onChange.bind(this);
762
869
  this._onKeyDown = this._onKeyDown.bind(this);
@@ -765,15 +872,47 @@
765
872
  connectedCallback() {
766
873
  if (this._connected)
767
874
  return;
875
+ upgradeProperties(this, [
876
+ "locale",
877
+ "min",
878
+ "max",
879
+ "firstDay",
880
+ "selection",
881
+ "monthFormat",
882
+ "fixedWeeks",
883
+ "showWeekNumbers",
884
+ "controlClasses",
885
+ "messages",
886
+ "source",
887
+ "dateState",
888
+ "renderDay",
889
+ "isDateDisabled",
890
+ "highlightedRange",
891
+ "value",
892
+ "display"
893
+ ]);
894
+ this._syncModel();
895
+ upgradeProperties(this, ["focusedDate"]);
896
+ this._stopDefaultControlClasses = subscribeDefaultControlClasses(() => {
897
+ if (usesDefaultControlClasses(this._controlClasses))
898
+ this.render();
899
+ });
900
+ this._stopDefaultMessages = subscribeDefaultMessages(() => {
901
+ if (this._messages === null)
902
+ this.render();
903
+ });
768
904
  this._connected = true;
769
905
  this.addEventListener("click", this._onClick);
770
906
  this.addEventListener("change", this._onChange);
771
907
  this.addEventListener("keydown", this._onKeyDown);
772
908
  this.addEventListener("focusin", this._onFocusIn);
773
- this._syncModel();
774
909
  this.render();
775
910
  }
776
911
  disconnectedCallback() {
912
+ this._stopDefaultControlClasses?.();
913
+ this._stopDefaultControlClasses = null;
914
+ this._stopDefaultMessages?.();
915
+ this._stopDefaultMessages = null;
777
916
  this._connected = false;
778
917
  this._loadController?.abort();
779
918
  this._loadController = null;
@@ -893,11 +1032,22 @@
893
1032
  set showWeekNumbers(value) {
894
1033
  this.toggleAttribute("show-week-numbers", Boolean(value));
895
1034
  }
1035
+ get controlClasses() {
1036
+ return resolveControlClasses(this._controlClasses);
1037
+ }
1038
+ set controlClasses(value) {
1039
+ const previous = this.controlClasses;
1040
+ this._controlClasses = normalizeControlClasses(value);
1041
+ if (sameControlClasses(previous, this.controlClasses))
1042
+ return;
1043
+ if (this._connected)
1044
+ this.render();
1045
+ }
896
1046
  get messages() {
897
- return this._messages;
1047
+ return this._messages ?? getDefaultMessages();
898
1048
  }
899
1049
  set messages(value) {
900
- this._messages = { ...getDefaultMessages(), ...value || {} };
1050
+ this._messages = value == null ? null : { ...getDefaultMessages(), ...value };
901
1051
  if (this._connected)
902
1052
  this.render();
903
1053
  }
@@ -973,18 +1123,10 @@
973
1123
  return compareDates(candidate, last) > 0 ? last : candidate;
974
1124
  }
975
1125
  _weeks(display = this.display) {
976
- const weeks = getMonthWeeks(clampDisplayMonth(display, this.firstDay), { firstDay: this.firstDay });
977
- if (!this.fixedWeeks || weeks.length >= 6)
978
- return weeks;
979
- let cursor = weeks[weeks.length - 1]?.[6] || "";
980
- while (weeks.length < 6 && cursor) {
981
- const week = [];
982
- for (let i = 1;i <= 7; i++)
983
- week.push(addDays(cursor, i));
984
- weeks.push(week);
985
- cursor = week[6];
986
- }
987
- return weeks;
1126
+ return getMonthWeeks(clampDisplayMonth(display, this.firstDay), {
1127
+ firstDay: this.firstDay,
1128
+ fixedWeeks: this.fixedWeeks
1129
+ });
988
1130
  }
989
1131
  _focusTargetKey(element) {
990
1132
  if (element.matches(".dp-month-select, .dp-year-input") && element.id) {
@@ -1166,11 +1308,13 @@
1166
1308
  return [
1167
1309
  formatLongDate(date, this.locale),
1168
1310
  description,
1169
- rangeLabel ? this._messages[rangeLabel] : "",
1170
- state.disabled ? this._messages.unavailable : ""
1311
+ rangeLabel ? this.messages[rangeLabel] : "",
1312
+ state.disabled ? this.messages.unavailable : ""
1171
1313
  ].filter(Boolean).join(". ");
1172
1314
  }
1173
1315
  _updateRangeDom() {
1316
+ const previousRange = this._paintedRange;
1317
+ const previousPreview = this._paintedPreview;
1174
1318
  this._paintedRange = { ...this._highlightedRange };
1175
1319
  this._paintedPreview = this.hasAttribute("data-range-preview");
1176
1320
  for (const cell of this.querySelectorAll(".dp-day[data-date]")) {
@@ -1178,13 +1322,20 @@
1178
1322
  continue;
1179
1323
  const date = cell.dataset.date || "";
1180
1324
  const position = rangePosition(date, this._highlightedRange);
1325
+ if (position === rangePosition(date, previousRange) && previousPreview === this._paintedPreview)
1326
+ continue;
1181
1327
  for (const [name, on] of Object.entries(rangeAttributeMap(position))) {
1182
1328
  if (on)
1183
1329
  cell.setAttribute(name, "true");
1184
1330
  else
1185
1331
  cell.removeAttribute(name);
1186
1332
  }
1187
- cell.setAttribute("aria-label", this._dayLabel(date, this.getDateState(date), position));
1333
+ if (!previousPreview || !this._paintedPreview) {
1334
+ const state = this._renderedStates.get(date) || {};
1335
+ const label = this._dayLabel(date, state, position);
1336
+ if (cell.getAttribute("aria-label") !== label)
1337
+ cell.setAttribute("aria-label", label);
1338
+ }
1188
1339
  }
1189
1340
  }
1190
1341
  focusGrid() {
@@ -1339,7 +1490,7 @@
1339
1490
  const minYearAttr = this.min ? ` min="${Number(this.min.slice(0, 4))}"` : "";
1340
1491
  const maxYearAttr = this.max ? ` max="${Number(this.max.slice(0, 4))}"` : "";
1341
1492
  const showWeeks = this.showWeekNumbers && this.firstDay === 1;
1342
- const weekHeader = showWeeks ? `<th scope="col" class="dp-week-heading" abbr="${escapeHtml(this._messages.week)}">#</th>` : "";
1493
+ const weekHeader = showWeeks ? `<th scope="col" class="dp-week-heading" abbr="${escapeHtml(this.messages.week)}">#</th>` : "";
1343
1494
  const monthOptions = names.map((name, index) => {
1344
1495
  const month = index + 1;
1345
1496
  const key = `${String(displayYear).padStart(4, "0")}-${String(month).padStart(2, "0")}`;
@@ -1347,10 +1498,12 @@
1347
1498
  return `<option value="${String(month).padStart(2, "0")}"${month === displayMonth ? " selected" : ""}${disabled ? " disabled" : ""}>${escapeHtml(name)}</option>`;
1348
1499
  }).join("");
1349
1500
  const dayHeaders = weekdayShort.map((name, index) => `<th scope="col" abbr="${escapeHtml(weekdayLong[index])}">${escapeHtml(name.replace(".", ""))}</th>`).join("");
1501
+ this._renderedStates.clear();
1350
1502
  const rows = weeks.map((week) => {
1351
1503
  const weekNumber = showWeeks ? `<th scope="row" class="dp-week-number">${isoWeekNumber(week[0])}</th>` : "";
1352
1504
  const cells = week.map((date) => {
1353
1505
  const state = this.getDateState(date);
1506
+ this._renderedStates.set(date, state);
1354
1507
  const outside = monthKey(date) !== display;
1355
1508
  const selected = this.value === date;
1356
1509
  const focused = this.focusedDate === date;
@@ -1365,18 +1518,22 @@
1365
1518
  const focusKey = focusedElement instanceof HTMLElement && this.contains(focusedElement) ? this._focusTargetKey(focusedElement) : "";
1366
1519
  const yearFirst = monthYearOrder(locale)[0] === "year";
1367
1520
  this.toggleAttribute("data-year-first", yearFirst);
1368
- const monthControl = `<label class="dp-visually-hidden" for="${this._id}-month">${escapeHtml(this._messages.month)}</label>
1369
- <select id="${this._id}-month" class="dp-month-select" aria-label="${escapeHtml(this._messages.month)}">${monthOptions}</select>`;
1370
- const yearControl = `<label class="dp-visually-hidden" for="${this._id}-year">${escapeHtml(this._messages.year)}</label>
1371
- <input id="${this._id}-year" class="dp-year-input" type="number" inputmode="numeric" value="${displayYear}"${minYearAttr}${maxYearAttr} aria-label="${escapeHtml(this._messages.year)}">`;
1521
+ const classes = this.controlClasses;
1522
+ const monthClass = escapeHtml(classes.month || "dp-skin");
1523
+ const yearClass = escapeHtml(classes.year || "dp-skin");
1524
+ const navClass = escapeHtml(classes.nav || "dp-skin");
1525
+ const monthControl = `<label class="dp-visually-hidden" for="${this._id}-month">${escapeHtml(this.messages.month)}</label>
1526
+ <select id="${this._id}-month" class="dp-month-select ${monthClass}" aria-label="${escapeHtml(this.messages.month)}">${monthOptions}</select>`;
1527
+ const yearControl = `<label class="dp-visually-hidden" for="${this._id}-year">${escapeHtml(this.messages.year)}</label>
1528
+ <input id="${this._id}-year" class="dp-year-input ${yearClass}" type="number" inputmode="numeric" value="${displayYear}"${minYearAttr}${maxYearAttr} aria-label="${escapeHtml(this.messages.year)}">`;
1372
1529
  this._rendering = true;
1373
1530
  this.innerHTML = `
1374
1531
  <div class="dp-calendar-shell">
1375
1532
  <div class="dp-calendar-header">
1376
1533
  ${yearFirst ? yearControl : monthControl}
1377
1534
  ${yearFirst ? monthControl : yearControl}
1378
- <button type="button" class="dp-nav dp-prev" 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>
1379
- <button type="button" class="dp-nav dp-next" 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>
1535
+ <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>
1536
+ <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>
1380
1537
  </div>
1381
1538
  <h2 id="${headingId}" class="dp-calendar-heading dp-visually-hidden" aria-live="polite">${escapeHtml(formatMonthYear(`${display}-15`, locale))}</h2>
1382
1539
  <table id="${gridId}" class="dp-grid" role="grid" aria-labelledby="${headingId}">
@@ -1406,7 +1563,7 @@
1406
1563
  const extra = cell.querySelector(".dp-day-extra");
1407
1564
  if (!(extra instanceof HTMLElement))
1408
1565
  continue;
1409
- const content = this._renderDay(date, this.getDateState(date));
1566
+ const content = this._renderDay(date, this._renderedStates.get(date) || {});
1410
1567
  if (content instanceof Node)
1411
1568
  extra.append(content);
1412
1569
  else if (content !== undefined && content !== null)
@@ -1422,13 +1579,15 @@
1422
1579
  function crossAxisFor(side) {
1423
1580
  return side === "top" || side === "bottom" ? "x" : "y";
1424
1581
  }
1582
+ var OPPOSITE = { top: "bottom", bottom: "top", left: "right", right: "left" };
1583
+ var PLACEMENTS = new Set(Object.keys(OPPOSITE).flatMap((side) => [side, `${side}-start`, `${side}-end`]));
1584
+ var COORDINATE_SPACES = new Set(["viewport", "document"]);
1425
1585
  function parsePlacement(placement) {
1586
+ if (!PLACEMENTS.has(placement))
1587
+ throw new TypeError(`Unknown placement: ${placement}`);
1426
1588
  const [side, align = null] = placement.split("-");
1427
1589
  return { side, align, crossAxis: crossAxisFor(side) };
1428
1590
  }
1429
- function flipSide(side) {
1430
- return { top: "bottom", bottom: "top", left: "right", right: "left" }[side] || side;
1431
- }
1432
1591
  function computeCoords(reference, floating, side, align, rtl, distance) {
1433
1592
  const crossAxis = crossAxisFor(side);
1434
1593
  const commonX = reference.x + reference.width / 2 - floating.width / 2;
@@ -1460,17 +1619,12 @@
1460
1619
  function overflowOn(position, size, start, end) {
1461
1620
  return Math.max(start - position, 0) + Math.max(position + size - end, 0);
1462
1621
  }
1463
- function isRTL(element) {
1464
- const direction = "dir" in element ? element.dir : "";
1465
- if (direction === "rtl")
1466
- return true;
1467
- if (direction === "ltr")
1468
- return false;
1469
- const win = element.ownerDocument?.defaultView;
1470
- if (win?.CSS?.supports?.("selector(:dir(rtl))") && typeof element.matches === "function") {
1471
- return element.matches(":dir(rtl)");
1622
+ function isRTL(reference) {
1623
+ const win = reference.ownerDocument?.defaultView;
1624
+ if (win && reference instanceof win.Element) {
1625
+ return win.getComputedStyle(reference).direction === "rtl";
1472
1626
  }
1473
- return Boolean(win?.Element && element instanceof win.Element && win.getComputedStyle(element).direction === "rtl");
1627
+ return "dir" in reference && reference.dir === "rtl";
1474
1628
  }
1475
1629
  var STABLE_SCROLLBAR_MAX_WIDTH = 25;
1476
1630
  function getViewportBoundary(doc) {
@@ -1508,8 +1662,14 @@
1508
1662
  const percent = (referenceCenter - boxStart) / size * 100;
1509
1663
  return Math.round(Math.min(100, Math.max(0, percent)) * 1000) / 1000;
1510
1664
  }
1511
- function isOutsideBoundary(rect, boundary) {
1512
- return rect.right < boundary.x || rect.left > boundary.right || rect.bottom < boundary.y || rect.top > boundary.bottom;
1665
+ function isOutsideBoundary(rects, boundary) {
1666
+ for (let i = 0;i < rects.length; i++) {
1667
+ const rect = rects[i];
1668
+ if (rect.right >= boundary.x && rect.left <= boundary.right && rect.bottom >= boundary.y && rect.top <= boundary.bottom) {
1669
+ return false;
1670
+ }
1671
+ }
1672
+ return true;
1513
1673
  }
1514
1674
  function getAvailableHeight(referenceRect, side, boundary, distance, padding) {
1515
1675
  if (side === "top") {
@@ -1564,10 +1724,22 @@
1564
1724
  for (const [subscription, type] of notifications) {
1565
1725
  if (!subscriptions.has(subscription) || !subscription.floating.isConnected)
1566
1726
  continue;
1567
- subscription.callback({ type });
1727
+ try {
1728
+ subscription.callback({ type });
1729
+ } catch (error) {
1730
+ reportError(error);
1731
+ }
1568
1732
  }
1569
1733
  });
1570
1734
  }
1735
+ function reportError(error) {
1736
+ if (typeof win.reportError === "function")
1737
+ win.reportError(error);
1738
+ else
1739
+ win.setTimeout(() => {
1740
+ throw error;
1741
+ });
1742
+ }
1571
1743
  function notifyAll(type) {
1572
1744
  for (const subscription of subscriptions)
1573
1745
  queue(subscription, type);
@@ -1658,28 +1830,32 @@
1658
1830
  return trackerFor(floating).add(reference, floating, callback);
1659
1831
  }
1660
1832
  function positionOnce(reference, floating, options) {
1833
+ const placement = options.placement === undefined ? "bottom-start" : options.placement;
1834
+ let { side, align, crossAxis } = parsePlacement(placement);
1835
+ const coordinateSpace = options.coordinateSpace === undefined ? "viewport" : options.coordinateSpace;
1836
+ if (!COORDINATE_SPACES.has(coordinateSpace)) {
1837
+ throw new TypeError(`Unknown coordinateSpace: ${coordinateSpace}`);
1838
+ }
1661
1839
  if (!isVisible(floating))
1662
1840
  return null;
1663
- const placement = options.placement || "bottom-start";
1664
1841
  const distance = options.distance || 0;
1665
1842
  const flip = options.flip !== false;
1666
1843
  const shift = options.shift !== false;
1667
1844
  const shiftPadding = options.shiftPadding ?? 4;
1668
- let { side, align, crossAxis } = parsePlacement(placement);
1669
1845
  const rtl = align ? isRTL(reference) : false;
1670
1846
  const rects = reference.getClientRects();
1671
- const referenceRect = side === "bottom" ? rects[rects.length - 1] : rects[0];
1672
- if (!referenceRect)
1847
+ if (!rects.length)
1673
1848
  return null;
1849
+ const rectFor = (s) => s === "bottom" ? rects[rects.length - 1] : rects[0];
1674
1850
  const boundary = getBoundary(reference, options);
1675
- if (!boundary || isOutsideBoundary(referenceRect, boundary))
1851
+ if (!boundary || isOutsideBoundary(rects, boundary))
1676
1852
  return null;
1677
1853
  const floatingRect = getFloatingSize(floating);
1678
1854
  const limits = {
1679
1855
  x: { size: floatingRect.width, start: boundary.x, end: boundary.right },
1680
1856
  y: { size: floatingRect.height, start: boundary.y, end: boundary.bottom }
1681
1857
  };
1682
- const place = (nextSide, nextAlign) => computeCoords(referenceRect, floatingRect, nextSide, nextAlign, rtl, distance);
1858
+ const place = (nextSide, nextAlign) => computeCoords(rectFor(nextSide), floatingRect, nextSide, nextAlign, rtl, distance);
1683
1859
  const overflowAt = (position, axis) => {
1684
1860
  const { size, start, end } = limits[axis];
1685
1861
  return overflowOn(position, size, start + shiftPadding, end - shiftPadding);
@@ -1689,31 +1865,30 @@
1689
1865
  return overflowAt(shift ? clampToBoundary(position, size, start, end, shiftPadding) : position, axis);
1690
1866
  };
1691
1867
  let coords = place(side, align);
1868
+ const overflowFor = (nextSide, at) => {
1869
+ const cross = crossAxisFor(nextSide);
1870
+ const main = cross === "x" ? "y" : "x";
1871
+ const mainOverflow = overflowAt(at[main], main);
1872
+ return { main: mainOverflow, total: mainOverflow + shiftedOverflowAt(at[cross], cross) };
1873
+ };
1692
1874
  if (flip) {
1693
- const mainAxis = crossAxis === "x" ? "y" : "x";
1694
- let overflow = overflowAt(coords[mainAxis], mainAxis);
1695
- if (overflow > 0) {
1696
- const opposite = flipSide(side);
1697
- const flipped = place(opposite, align);
1698
- const flippedOverflow = overflowAt(flipped[mainAxis], mainAxis);
1699
- if (flippedOverflow < overflow) {
1700
- side = opposite;
1701
- coords = flipped;
1702
- overflow = flippedOverflow;
1703
- }
1704
- }
1705
- if (mainAxis === "x" && overflow > 0) {
1706
- const above = place("top", align);
1707
- const below = place("bottom", align);
1708
- const useBottom = overflowAt(below.y, "y") < overflowAt(above.y, "y");
1709
- const candidate = useBottom ? below : above;
1710
- const swapped = overflowAt(candidate.y, "y") + shiftedOverflowAt(candidate.x, "x");
1711
- if (swapped < overflow + shiftedOverflowAt(coords.y, "y")) {
1712
- side = useBottom ? "bottom" : "top";
1713
- crossAxis = "x";
1714
- coords = candidate;
1875
+ let best = overflowFor(side, coords);
1876
+ const consider = (nextSide) => {
1877
+ const next = place(nextSide, align);
1878
+ const overflow = overflowFor(nextSide, next);
1879
+ if (overflow.total < best.total) {
1880
+ side = nextSide;
1881
+ coords = next;
1882
+ best = overflow;
1715
1883
  }
1884
+ };
1885
+ if (best.main > 0)
1886
+ consider(OPPOSITE[side]);
1887
+ if (crossAxis === "y" && best.main > 0) {
1888
+ consider("top");
1889
+ consider("bottom");
1716
1890
  }
1891
+ crossAxis = crossAxisFor(side);
1717
1892
  }
1718
1893
  if (crossAxis === "x" && shift && align) {
1719
1894
  const overflow = overflowAt(coords.x, "x");
@@ -1730,12 +1905,13 @@
1730
1905
  const { size, start, end } = limits[crossAxis];
1731
1906
  coords[crossAxis] = clampToBoundary(coords[crossAxis], size, start, end, shiftPadding);
1732
1907
  }
1733
- const arrowX = arrowPercent(referenceRect.x + referenceRect.width / 2, coords.x, floatingRect.width);
1734
- const arrowY = arrowPercent(referenceRect.y + referenceRect.height / 2, coords.y, floatingRect.height);
1735
- const availableHeight = `${getAvailableHeight(referenceRect, side, boundary, distance, shiftPadding)}px`;
1908
+ const resolvedRect = rectFor(side);
1909
+ const arrowX = arrowPercent(resolvedRect.x + resolvedRect.width / 2, coords.x, floatingRect.width);
1910
+ const arrowY = arrowPercent(resolvedRect.y + resolvedRect.height / 2, coords.y, floatingRect.height);
1911
+ const availableHeight = `${getAvailableHeight(resolvedRect, side, boundary, distance, shiftPadding)}px`;
1736
1912
  const { style } = floating;
1737
1913
  const roomChanged = style.getPropertyValue("--available-height") !== availableHeight;
1738
- const win = options.coordinateSpace === "document" ? reference.ownerDocument.defaultView : null;
1914
+ const win = coordinateSpace === "document" ? reference.ownerDocument.defaultView : null;
1739
1915
  const originX = win ? win.scrollX : 0;
1740
1916
  const originY = win ? win.scrollY : 0;
1741
1917
  style.left = `${coords.x + originX}px`;
@@ -1863,7 +2039,7 @@
1863
2039
  input.setCustomValidity("");
1864
2040
  return;
1865
2041
  }
1866
- input.setCustomValidity(text === canonical ? "" : this.messages.invalidDate);
2042
+ input.setCustomValidity(this.messages.invalidDate);
1867
2043
  }
1868
2044
  async commit(options = {}) {
1869
2045
  const input = this.input;
@@ -1961,6 +2137,18 @@
1961
2137
 
1962
2138
  class DatePickerElement extends HTMLElement {
1963
2139
  static observedAttributes = ["value", "locale", "min", "max", "open-on-focus", "month-format"];
2140
+ static setDefaultControlClasses(classes) {
2141
+ setDefaultControlClasses(classes);
2142
+ }
2143
+ static getDefaultControlClasses() {
2144
+ return getDefaultControlClasses();
2145
+ }
2146
+ static setDefaultMessages(messages) {
2147
+ setDefaultMessages(messages);
2148
+ }
2149
+ static getDefaultMessages() {
2150
+ return getDefaultMessages();
2151
+ }
1964
2152
  constructor() {
1965
2153
  super();
1966
2154
  this._id = `date-picker-${++uid2}`;
@@ -1992,7 +2180,9 @@
1992
2180
  this._stopTracking = null;
1993
2181
  this._open = false;
1994
2182
  this._suppressFocusOpen = false;
1995
- this._messages = getDefaultMessages();
2183
+ this._messages = null;
2184
+ this._controlClasses = null;
2185
+ this._stopDefaultMessages = null;
1996
2186
  this._source = null;
1997
2187
  this._dateState = null;
1998
2188
  this._renderDay = null;
@@ -2005,11 +2195,31 @@
2005
2195
  connectedCallback() {
2006
2196
  if (this._connected)
2007
2197
  return;
2008
- if (this.hasAttribute("range")) {
2198
+ upgradeProperties(this, [
2199
+ "locale",
2200
+ "min",
2201
+ "max",
2202
+ "monthFormat",
2203
+ "openOnFocus",
2204
+ "coordinateSpace",
2205
+ "controlClasses",
2206
+ "messages",
2207
+ "source",
2208
+ "dateState",
2209
+ "renderDay",
2210
+ "isDateDisabled"
2211
+ ]);
2212
+ if (this.hasAttribute("range"))
2009
2213
  this._connectRange();
2010
- return;
2214
+ else
2215
+ this._connectSingle();
2216
+ if (this._connected) {
2217
+ upgradeProperties(this, ["value", "range"]);
2218
+ this._stopDefaultMessages = subscribeDefaultMessages(() => {
2219
+ if (this._messages === null)
2220
+ this._refreshMessages();
2221
+ });
2011
2222
  }
2012
- this._connectSingle();
2013
2223
  }
2014
2224
  _connectSingle() {
2015
2225
  const input = this.querySelector(":scope > input:not([type=hidden]):not([type=time]):not([data-time-start]):not([data-time-end])");
@@ -2020,7 +2230,7 @@
2020
2230
  this._connected = true;
2021
2231
  this._input = input;
2022
2232
  this._discoverTimeFields();
2023
- this._field = new DateFieldController(input, { messages: this._messages, locale: this.locale });
2233
+ this._field = new DateFieldController(input, { messages: this.messages, locale: this.locale });
2024
2234
  this._field.onAttributesChanged = () => this._syncInputState();
2025
2235
  this._field.confirm = (date, options) => this._confirmDate(date, options);
2026
2236
  this._setupFormValue();
@@ -2035,7 +2245,7 @@
2035
2245
  else if (!input.value)
2036
2246
  this._setValue("", { emit: false, format: false });
2037
2247
  else
2038
- input.setCustomValidity(this._messages.invalidDate);
2248
+ input.setCustomValidity(this.messages.invalidDate);
2039
2249
  if (this._field.hidden)
2040
2250
  this._field.hidden.defaultValue = this._value;
2041
2251
  if (input.getAttribute("value") == null && input.defaultValue === "") {
@@ -2076,8 +2286,8 @@
2076
2286
  this._connected = true;
2077
2287
  this._input = null;
2078
2288
  this._fields = [
2079
- new DateFieldController(startInput, { messages: this._messages, locale: this.locale }),
2080
- new DateFieldController(endInput, { messages: this._messages, locale: this.locale })
2289
+ new DateFieldController(startInput, { messages: this.messages, locale: this.locale }),
2290
+ new DateFieldController(endInput, { messages: this.messages, locale: this.locale })
2081
2291
  ];
2082
2292
  this._range = new DateRangeController;
2083
2293
  this._rangeOriginalDescribedBy = [
@@ -2099,9 +2309,9 @@
2099
2309
  const initialEnd = isDate(endInput.value) ? endInput.value : adapter.parse(endInput.value);
2100
2310
  this._setRange(initialStart || "", initialEnd || "", { emit: false });
2101
2311
  if (startInput.value.trim() && !isDate(initialStart))
2102
- startInput.setCustomValidity(this._messages.invalidDate);
2312
+ startInput.setCustomValidity(this.messages.invalidDate);
2103
2313
  if (endInput.value.trim() && !isDate(initialEnd))
2104
- endInput.setCustomValidity(this._messages.invalidDate);
2314
+ endInput.setCustomValidity(this.messages.invalidDate);
2105
2315
  if (this._fields[0].hidden)
2106
2316
  this._fields[0].hidden.defaultValue = this._range.start;
2107
2317
  if (this._fields[1].hidden)
@@ -2114,6 +2324,8 @@
2114
2324
  }
2115
2325
  }
2116
2326
  disconnectedCallback() {
2327
+ this._stopDefaultMessages?.();
2328
+ this._stopDefaultMessages = null;
2117
2329
  this._connected = false;
2118
2330
  this.hide(false);
2119
2331
  this._controller?.abort();
@@ -2247,18 +2459,35 @@
2247
2459
  get open() {
2248
2460
  return this._open;
2249
2461
  }
2462
+ get controlClasses() {
2463
+ return resolveControlClasses(this._controlClasses);
2464
+ }
2465
+ set controlClasses(value) {
2466
+ this._controlClasses = normalizeControlClasses(value);
2467
+ if (this._calendar)
2468
+ this._calendar.controlClasses = this._controlClasses;
2469
+ }
2250
2470
  get messages() {
2251
- return this._messages;
2471
+ return this._messages ?? getDefaultMessages();
2252
2472
  }
2253
2473
  set messages(value) {
2254
- this._messages = { ...getDefaultMessages(), ...value || {} };
2474
+ this._messages = value == null ? null : { ...getDefaultMessages(), ...value };
2255
2475
  if (this._calendar)
2256
2476
  this._calendar.messages = this._messages;
2477
+ this._refreshMessages();
2478
+ }
2479
+ _refreshMessages() {
2480
+ const messages = this.messages;
2257
2481
  for (const field of this._fields || [])
2258
- field.setMessages(this._messages);
2259
- this._field?.setMessages(this._messages);
2482
+ field.setMessages(messages);
2483
+ this._field?.setMessages(messages);
2484
+ this._panel?.setAttribute("aria-label", messages.calendar);
2485
+ const field = this._field ?? this._fields?.[0];
2486
+ if (this._formatHint && field)
2487
+ this._formatHint.textContent = `${messages.formatHint}: ${field.placeholder}`;
2260
2488
  this._refreshButtonLabel();
2261
- this.validate();
2489
+ if (this._connected)
2490
+ this.validate();
2262
2491
  }
2263
2492
  get source() {
2264
2493
  return this._source;
@@ -2386,7 +2615,7 @@
2386
2615
  panel.className = "dp-picker-panel";
2387
2616
  panel.setAttribute("popover", "manual");
2388
2617
  panel.setAttribute("role", "dialog");
2389
- panel.setAttribute("aria-label", this._messages.calendar);
2618
+ panel.setAttribute("aria-label", this.messages.calendar);
2390
2619
  const calendar = new DateCalendarElement;
2391
2620
  calendar.selection = "none";
2392
2621
  calendar.fixedWeeks = true;
@@ -2410,6 +2639,23 @@
2410
2639
  this._refreshLocale();
2411
2640
  this._refreshButtonLabel();
2412
2641
  }
2642
+ _bindPopup(signal, input, restore) {
2643
+ this.ownerDocument.addEventListener("pointerdown", (event) => {
2644
+ if (!this._open || event.composedPath().includes(this))
2645
+ return;
2646
+ this.hide(false);
2647
+ }, { capture: true, signal });
2648
+ this.ownerDocument.addEventListener("reset", (event) => {
2649
+ if (!(event.target instanceof HTMLFormElement) || !input || event.target !== input.form)
2650
+ return;
2651
+ this.hide(false);
2652
+ queueMicrotask(() => {
2653
+ if (!event.defaultPrevented)
2654
+ restore();
2655
+ });
2656
+ }, { capture: true, signal });
2657
+ this.addEventListener("keydown", (event) => this._onEscape(event), { signal });
2658
+ }
2413
2659
  _bind() {
2414
2660
  const input = this._input;
2415
2661
  const button = this._buttons[0]?.button;
@@ -2472,22 +2718,7 @@
2472
2718
  });
2473
2719
  }, { signal });
2474
2720
  calendar.addEventListener("dateloadend", () => void this.validate(), { signal });
2475
- this.ownerDocument.addEventListener("pointerdown", (event) => {
2476
- if (!this._open || event.composedPath().includes(this))
2477
- return;
2478
- this.hide(false);
2479
- }, { capture: true, signal });
2480
- this.ownerDocument.addEventListener("reset", (event) => {
2481
- const form = event.target;
2482
- if (form instanceof HTMLFormElement && this._input && form === this._input.form) {
2483
- this.hide(false);
2484
- queueMicrotask(() => {
2485
- if (!event.defaultPrevented)
2486
- this._restoreDefault();
2487
- });
2488
- }
2489
- }, { capture: true, signal });
2490
- this.addEventListener("keydown", (event) => this._onEscape(event), { signal });
2721
+ this._bindPopup(signal, this._input, () => this._restoreDefault());
2491
2722
  }
2492
2723
  _bindRange() {
2493
2724
  const calendar = this._calendar;
@@ -2567,22 +2798,7 @@
2567
2798
  calendar.addEventListener("pointercancel", (event) => this._onGridPointerCancel(event), { signal });
2568
2799
  calendar.addEventListener("lostpointercapture", (event) => this._onGridPointerCancel(event), { signal });
2569
2800
  calendar.addEventListener("dateloadend", () => void this.validate(), { signal });
2570
- this.ownerDocument.addEventListener("pointerdown", (event) => {
2571
- if (!this._open || event.composedPath().includes(this))
2572
- return;
2573
- this.hide(false);
2574
- }, { capture: true, signal });
2575
- this.ownerDocument.addEventListener("reset", (event) => {
2576
- const form = event.target;
2577
- if (form instanceof HTMLFormElement && this._fields && form === this._fields[0].input.form) {
2578
- this.hide(false);
2579
- queueMicrotask(() => {
2580
- if (!event.defaultPrevented)
2581
- this._restoreRangeDefault();
2582
- });
2583
- }
2584
- }, { capture: true, signal });
2585
- this.addEventListener("keydown", (event) => this._onEscape(event), { signal });
2801
+ this._bindPopup(signal, this._fields?.[0]?.input, () => this._restoreRangeDefault());
2586
2802
  }
2587
2803
  _activateRangeEndpoint(endpoint) {
2588
2804
  const calendar = this._calendar;
@@ -2879,6 +3095,7 @@
2879
3095
  calendar.min = this.min;
2880
3096
  calendar.max = this.max;
2881
3097
  calendar.monthFormat = this.monthFormat;
3098
+ calendar.controlClasses = this._controlClasses;
2882
3099
  calendar.messages = this._messages;
2883
3100
  calendar.source = this._source;
2884
3101
  calendar.dateState = this._dateState;
@@ -2887,7 +3104,7 @@
2887
3104
  if (!this._rangeMode() && this._value)
2888
3105
  calendar.value = this._value;
2889
3106
  if (panel)
2890
- panel.setAttribute("aria-label", this._messages.calendar);
3107
+ panel.setAttribute("aria-label", this.messages.calendar);
2891
3108
  }
2892
3109
  _refreshLocale() {
2893
3110
  const hint = this._formatHint;
@@ -2896,7 +3113,7 @@
2896
3113
  if (this._rangeMode() && this._fields) {
2897
3114
  this._fields[0].setLocale(this.locale);
2898
3115
  this._fields[1].setLocale(this.locale);
2899
- hint.textContent = `${this._messages.formatHint}: ${this._fields[0].placeholder}`;
3116
+ hint.textContent = `${this.messages.formatHint}: ${this._fields[0].placeholder}`;
2900
3117
  for (const [index, field] of this._fields.entries()) {
2901
3118
  if (!field.input.hasAttribute("placeholder") || this._generatedPlaceholder) {
2902
3119
  field.input.placeholder = field.placeholder;
@@ -2913,7 +3130,7 @@
2913
3130
  if (!field)
2914
3131
  return;
2915
3132
  field.setLocale(this.locale);
2916
- hint.textContent = `${this._messages.formatHint}: ${field.placeholder}`;
3133
+ hint.textContent = `${this.messages.formatHint}: ${field.placeholder}`;
2917
3134
  if (!field.input.hasAttribute("placeholder") || this._generatedPlaceholder) {
2918
3135
  field.input.placeholder = field.placeholder;
2919
3136
  this._generatedPlaceholder = true;
@@ -2930,7 +3147,7 @@
2930
3147
  this._refreshRangeButtonLabel();
2931
3148
  return;
2932
3149
  }
2933
- const prefix = this._value ? this._messages.changeDate : this._messages.chooseDate;
3150
+ const prefix = this._value ? this.messages.changeDate : this.messages.chooseDate;
2934
3151
  const suffix = this._value ? `, ${formatLongDate(this._value, this.locale)}` : "";
2935
3152
  single.setAttribute("aria-label", `${prefix}${suffix}`);
2936
3153
  }
@@ -2940,9 +3157,9 @@
2940
3157
  const { start, end } = this._range;
2941
3158
  for (const { button, endpoint } of this._buttons) {
2942
3159
  const bound = endpoint === "end" ? end : start;
2943
- const prefix = bound ? this._messages.changeDate : this._messages.chooseDate;
3160
+ const prefix = bound ? this.messages.changeDate : this.messages.chooseDate;
2944
3161
  const suffix = bound ? `, ${formatLongDate(bound, this.locale)}` : "";
2945
- const boundLabel = endpoint === "end" ? this._messages.rangeEnd : this._messages.rangeStart;
3162
+ const boundLabel = endpoint === "end" ? this.messages.rangeEnd : this.messages.rangeStart;
2946
3163
  button.setAttribute("aria-label", `${prefix}${suffix}, ${boundLabel}`);
2947
3164
  }
2948
3165
  }
@@ -2989,7 +3206,7 @@
2989
3206
  const confirmed = await calendar.ensureDate(date);
2990
3207
  const state = calendar.getDateState(date);
2991
3208
  if (!confirmed || state.disabled)
2992
- return { ok: false, message: this._messages.unavailableDate };
3209
+ return { ok: false, message: this.messages.unavailableDate };
2993
3210
  return { ok: true };
2994
3211
  }
2995
3212
  async _commitText(emit, options = {}) {
@@ -3105,7 +3322,7 @@
3105
3322
  for (const bound of bounds) {
3106
3323
  const index = bound === "end" ? 1 : 0;
3107
3324
  const input = this._fields[index].input;
3108
- const message = bound === "end" ? this._messages.rangeOrderEnd : this._messages.rangeOrderStart;
3325
+ const message = bound === "end" ? this.messages.rangeOrderEnd : this.messages.rangeOrderStart;
3109
3326
  const shouldHaveOrder = inverted && bound === which;
3110
3327
  if (shouldHaveOrder) {
3111
3328
  input.setCustomValidity(message);
@@ -3127,7 +3344,7 @@
3127
3344
  const input = inputs[index];
3128
3345
  if (!input)
3129
3346
  continue;
3130
- const message = bound === "end" ? this._messages.rangeOrderEnd : this._messages.rangeOrderStart;
3347
+ const message = bound === "end" ? this.messages.rangeOrderEnd : this.messages.rangeOrderStart;
3131
3348
  const shouldHaveOrder = inverted && bound === which;
3132
3349
  if (shouldHaveOrder) {
3133
3350
  input.setCustomValidity(message);