@forcecalendar/interface 1.2.0 → 1.3.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.
@@ -1012,6 +1012,87 @@ var n = class extends HTMLElement {
1012
1012
  let t = e.dataset.eventId, n = this.stateManager.getEvents().find((e) => e.id === t);
1013
1013
  n && this.stateManager.selectEvent(n);
1014
1014
  }
1015
+ _enhanceTimeGridAccessibility(e, t) {
1016
+ let n = this.container.querySelector(".fc-time-grid");
1017
+ if (!n) return;
1018
+ n.setAttribute("role", "grid"), n.setAttribute("aria-label", t);
1019
+ let r = this.container.querySelector(".fc-time-gutter");
1020
+ r && r.setAttribute("aria-hidden", "true");
1021
+ let i = this.stateManager.getState().config.locale || "en-US", a = new Intl.DateTimeFormat(i, {
1022
+ weekday: "long",
1023
+ month: "long",
1024
+ day: "numeric"
1025
+ }), o = Array.from(this.container.querySelectorAll(e));
1026
+ for (let e of o) {
1027
+ e.setAttribute("role", "row");
1028
+ let t = new Date(e.dataset.date), n = a.format(t);
1029
+ e.setAttribute("aria-label", n);
1030
+ for (let t of e.querySelectorAll(".fc-hour-slot")) t.setAttribute("role", "gridcell"), t.setAttribute("tabindex", "-1"), t.setAttribute("aria-label", `${n}, ${this.formatHour(Number(t.dataset.hour))}`);
1031
+ }
1032
+ if (this._applySlotRovingTabindex(o), this._pendingSlotFocus) {
1033
+ let { colIndex: e, hour: t } = this._pendingSlotFocus;
1034
+ this._pendingSlotFocus = null;
1035
+ let n = this._slotAt(o, e, t);
1036
+ n && (this._applySlotRovingTabindex(o, n), n.focus());
1037
+ }
1038
+ this.addListener(this.container, "keydown", (t) => {
1039
+ let n = t.target.closest(".fc-hour-slot");
1040
+ if (!n || !this.container.contains(n)) return;
1041
+ let r = n.closest(e), i = o.indexOf(r), a = Number(n.dataset.hour), s = null;
1042
+ switch (t.key) {
1043
+ case "ArrowDown":
1044
+ s = this._slotAt(o, i, a + 1);
1045
+ break;
1046
+ case "ArrowUp":
1047
+ s = this._slotAt(o, i, a - 1);
1048
+ break;
1049
+ case "ArrowRight":
1050
+ s = this._slotAt(o, i + 1, a);
1051
+ break;
1052
+ case "ArrowLeft":
1053
+ s = this._slotAt(o, i - 1, a);
1054
+ break;
1055
+ case "Home":
1056
+ s = this._slotAt(o, i, 0);
1057
+ break;
1058
+ case "End":
1059
+ s = this._slotAt(o, i, 23);
1060
+ break;
1061
+ case "PageUp":
1062
+ case "PageDown":
1063
+ t.preventDefault(), this._pendingSlotFocus = {
1064
+ colIndex: i,
1065
+ hour: a
1066
+ }, t.key === "PageDown" ? this.stateManager.next() : this.stateManager.previous();
1067
+ return;
1068
+ case "Enter":
1069
+ case " ": {
1070
+ t.preventDefault();
1071
+ let e = new Date(r.dataset.date);
1072
+ e.setHours(a, 0, 0, 0), this._pendingSlotFocus = {
1073
+ colIndex: i,
1074
+ hour: a
1075
+ }, this.stateManager.selectDate(e);
1076
+ return;
1077
+ }
1078
+ default: return;
1079
+ }
1080
+ t.preventDefault(), s && (this._applySlotRovingTabindex(o, s), s.scrollIntoView?.({ block: "nearest" }), s.focus());
1081
+ });
1082
+ }
1083
+ _slotAt(e, t, n) {
1084
+ return t < 0 || t >= e.length || n < 0 || n > 23 ? null : e[t].querySelector(`.fc-hour-slot[data-hour="${n}"]`);
1085
+ }
1086
+ _applySlotRovingTabindex(e, t = null) {
1087
+ let n = this.container.querySelectorAll(".fc-hour-slot");
1088
+ if (n.length !== 0) {
1089
+ if (!t) {
1090
+ let r = e.find((e) => this.isToday(new Date(e.dataset.date))) || e[0];
1091
+ t = r && r.querySelector(".fc-hour-slot[data-hour=\"9\"]"), t ||= n[0];
1092
+ }
1093
+ for (let e of n) e.setAttribute("tabindex", e === t ? "0" : "-1");
1094
+ }
1095
+ }
1015
1096
  _enhanceEventAccessibility() {
1016
1097
  for (let e of this.container.querySelectorAll(".fc-event")) if (e.setAttribute("role", "button"), e.setAttribute("tabindex", "0"), !e.hasAttribute("aria-label")) {
1017
1098
  let t = (e.getAttribute("title") || e.textContent || "").trim();
@@ -1258,7 +1339,7 @@ var n = class extends HTMLElement {
1258
1339
  return `
1259
1340
  <div class="fc-week-day-column" data-date="${e.date.toISOString()}" style="border-right: 1px solid var(--fc-border-color); position: relative; cursor: pointer;">
1260
1341
  <!-- Hour grid lines -->
1261
- ${t.map(() => `<div style="height: ${this.hourHeight}px; border-bottom: 1px solid var(--fc-background-hover);"></div>`).join("")}
1342
+ ${t.map((e) => `<div class="fc-hour-slot" data-hour="${e}" style="height: ${this.hourHeight}px; border-bottom: 1px solid var(--fc-background-hover);"></div>`).join("")}
1262
1343
 
1263
1344
  <!-- Now indicator for today -->
1264
1345
  ${e.isToday ? this.renderNowIndicator() : ""}
@@ -1281,6 +1362,12 @@ var n = class extends HTMLElement {
1281
1362
  let n = new Date(t.dataset.date), r = this.container.querySelector("#week-scroll-container"), i = t.offsetTop, a = e.clientY - t.getBoundingClientRect().top + (r ? r.scrollTop : 0) - i, o = Math.max(0, Math.min(a + i, this.totalHeight));
1282
1363
  n.setHours(Math.floor(o / this.hourHeight), Math.floor(o % this.hourHeight / (this.hourHeight / 60)), 0, 0), this.stateManager.selectDate(n);
1283
1364
  }), this.attachCommonEventHandlers();
1365
+ let e = this.stateManager.getViewData()?.days || [], t = this.stateManager.getState().config.locale || "en-US", n = e[0] ? new Date(e[0].date) : /* @__PURE__ */ new Date(), r = `Week of ${new Intl.DateTimeFormat(t, {
1366
+ month: "long",
1367
+ day: "numeric",
1368
+ year: "numeric"
1369
+ }).format(n)}`;
1370
+ this._enhanceTimeGridAccessibility(".fc-week-day-column", r);
1284
1371
  }
1285
1372
  _scrollToCurrentTime() {
1286
1373
  if (this._scrolled) return;
@@ -1395,7 +1482,7 @@ var n = class extends HTMLElement {
1395
1482
  return `
1396
1483
  <div class="fc-day-column" data-date="${n.toISOString()}" style="position: relative; cursor: pointer;">
1397
1484
  <!-- Hour grid lines -->
1398
- ${r.map(() => `<div style="height: ${this.hourHeight}px; border-bottom: 1px solid var(--fc-background-hover);"></div>`).join("")}
1485
+ ${r.map((e) => `<div class="fc-hour-slot" data-hour="${e}" style="height: ${this.hourHeight}px; border-bottom: 1px solid var(--fc-background-hover);"></div>`).join("")}
1399
1486
 
1400
1487
  <!-- Now indicator for today -->
1401
1488
  ${t ? this.renderNowIndicator() : ""}
@@ -1418,6 +1505,13 @@ var n = class extends HTMLElement {
1418
1505
  let n = new Date(t.dataset.date), r = this.container.querySelector("#day-scroll-container"), i = t.offsetTop, a = e.clientY - t.getBoundingClientRect().top + (r ? r.scrollTop : 0) - i, o = Math.max(0, Math.min(a + i, this.totalHeight));
1419
1506
  n.setHours(Math.floor(o / this.hourHeight), Math.floor(o % this.hourHeight / (this.hourHeight / 60)), 0, 0), this.stateManager.selectDate(n);
1420
1507
  }), this.attachCommonEventHandlers();
1508
+ let e = this.stateManager.getState().config.locale || "en-US", t = this.stateManager.getState().currentDate || /* @__PURE__ */ new Date(), n = new Intl.DateTimeFormat(e, {
1509
+ weekday: "long",
1510
+ month: "long",
1511
+ day: "numeric",
1512
+ year: "numeric"
1513
+ }).format(t);
1514
+ this._enhanceTimeGridAccessibility(".fc-day-column", n);
1421
1515
  }
1422
1516
  _scrollToCurrentTime() {
1423
1517
  if (this._scrolled) return;
@@ -1989,6 +2083,7 @@ var m = class e extends n {
1989
2083
  }
1990
2084
 
1991
2085
  .fc-month-day:focus-visible,
2086
+ .fc-hour-slot:focus-visible,
1992
2087
  .fc-event:focus-visible {
1993
2088
  outline: 2px solid var(--fc-primary-color);
1994
2089
  outline-offset: -2px;