@zeyos/zx 4.2.0 → 4.3.4

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 (69) hide show
  1. package/CHANGELOG.md +148 -1
  2. package/README.md +5 -3
  3. package/dist/types/components/calendar/calendar-model.d.ts +22 -0
  4. package/dist/types/components/calendar/calendar.d.ts +19 -2
  5. package/dist/types/components/card-view/card-view.d.ts +1 -1
  6. package/dist/types/components/card-view/record-card.d.ts +47 -5
  7. package/dist/types/components/dialog/dialog.d.ts +6 -1
  8. package/dist/types/components/dropdown/dropdown.d.ts +5 -0
  9. package/dist/types/components/kanban-view/kanban-policy.d.ts +268 -0
  10. package/dist/types/components/kanban-view/kanban-view.d.ts +669 -24
  11. package/dist/types/components/launcher/launcher.d.ts +5 -0
  12. package/dist/types/components/message/message.d.ts +9 -1
  13. package/dist/types/components/modal/modal.d.ts +44 -7
  14. package/dist/types/components/sheet/sheet.d.ts +22 -12
  15. package/dist/types/core/component.d.ts +6 -1
  16. package/dist/types/core/overlay-host.d.ts +12 -0
  17. package/dist/types/index.d.ts +2 -1
  18. package/dist/zx-zeyos.esm.js +173 -43
  19. package/dist/zx-zeyos.esm.min.js +1 -1
  20. package/dist/zx.css +876 -230
  21. package/dist/zx.esm.js +2053 -338
  22. package/dist/zx.esm.min.js +3 -3
  23. package/dist/zx.global.js +2053 -338
  24. package/dist/zx.global.min.js +3 -3
  25. package/dist/zx.min.css +1 -1
  26. package/docs/api.json +250 -2
  27. package/docs/llms.md +67 -48
  28. package/docs/llms.txt +1 -3
  29. package/package.json +1 -2
  30. package/src/components/account-menu/account-menu.css +1 -1
  31. package/src/components/app-rail/app-rail.css +1 -1
  32. package/src/components/calendar/calendar-model.js +45 -0
  33. package/src/components/calendar/calendar.css +96 -34
  34. package/src/components/calendar/calendar.js +122 -29
  35. package/src/components/card-view/card-view.css +211 -9
  36. package/src/components/card-view/card-view.js +7 -7
  37. package/src/components/card-view/record-card.js +92 -19
  38. package/src/components/context-menu/context-menu.css +2 -2
  39. package/src/components/context-menu/context-menu.js +5 -1
  40. package/src/components/date-picker/date-picker.css +18 -11
  41. package/src/components/datebox/date-range-box.css +4 -2
  42. package/src/components/datebox/datebox.css +4 -2
  43. package/src/components/dialog/dialog.css +4 -3
  44. package/src/components/dialog/dialog.js +2 -1
  45. package/src/components/dropdown/dropdown.css +4 -2
  46. package/src/components/dropdown/dropdown.js +7 -2
  47. package/src/components/kanban-view/kanban-policy.js +412 -0
  48. package/src/components/kanban-view/kanban-view.css +480 -36
  49. package/src/components/kanban-view/kanban-view.js +1514 -235
  50. package/src/components/launcher/launcher.css +10 -8
  51. package/src/components/launcher/launcher.js +9 -2
  52. package/src/components/menu-button/menu-button.css +2 -2
  53. package/src/components/message/message.css +15 -25
  54. package/src/components/message/message.js +17 -11
  55. package/src/components/modal/modal.css +6 -4
  56. package/src/components/modal/modal.js +99 -25
  57. package/src/components/select/select.css +9 -7
  58. package/src/components/sheet/sheet.css +25 -7
  59. package/src/components/sheet/sheet.js +43 -23
  60. package/src/components/table/table.css +5 -3
  61. package/src/components/tag-picker/tag-picker.css +5 -3
  62. package/src/components/tooltip/tooltip.css +4 -2
  63. package/src/components/tooltip/tooltip.js +4 -1
  64. package/src/core/component.js +8 -3
  65. package/src/core/overlay-host.js +23 -0
  66. package/src/index.js +8 -3
  67. package/styles/tokens/dark.css +4 -0
  68. package/styles/tokens/semantic.css +83 -8
  69. package/DESIGN-SYSTEM.md +0 -182
@@ -870,21 +870,26 @@ var Component = class extends EventTarget {
870
870
  * Dispatches a component event and a bubbling, composed `zx-*` DOM event.
871
871
  * @param {string} type Lowercase event name.
872
872
  * @param {Record<string, unknown>} [detail={}] Single event detail object.
873
+ * @param {{honorDomCancellation?:boolean}} [options={}] Mirrored DOM-event behavior. Components
874
+ * with a cancelable mutation boundary may opt into treating `preventDefault()` on the bubbling
875
+ * `zx-*` event exactly like cancellation of the component event.
873
876
  * @returns {Event & {detail: Record<string, unknown>}}
874
877
  * @fires Component#event
875
878
  */
876
- emit(type, detail = {}) {
879
+ emit(type, detail = {}, options = {}) {
877
880
  if (detail === null || typeof detail !== "object" || Array.isArray(detail)) {
878
881
  throw new TypeError("Event detail must be an object");
879
882
  }
880
883
  const componentEvent = createCustomEvent(type, detail, { cancelable: true });
881
884
  this.dispatchEvent(componentEvent);
882
885
  if (this.el) {
883
- this.el.dispatchEvent(createCustomEvent(`zx-${type}`, detail, {
886
+ const domEvent = createCustomEvent(`zx-${type}`, detail, {
884
887
  bubbles: true,
885
888
  composed: true,
886
889
  cancelable: true
887
- }));
890
+ });
891
+ this.el.dispatchEvent(domEvent);
892
+ if (options.honorDomCancellation && domEvent.defaultPrevented) componentEvent.preventDefault();
888
893
  }
889
894
  return componentEvent;
890
895
  }
@@ -9563,6 +9568,15 @@ function currencyCode(value) {
9563
9568
  return /^[A-Z]{3}$/.test(code) ? code : null;
9564
9569
  }
9565
9570
 
9571
+ // src/core/overlay-host.js
9572
+ var SCOPE_SELECTOR = ".zx-scope, [data-zx-theme], [data-zx-density], [data-zx-preset]";
9573
+ function overlayHost(source = null) {
9574
+ const context = source == null ? document.activeElement instanceof Element ? document.activeElement : null : resolveElement(source);
9575
+ const scope2 = context?.closest?.(SCOPE_SELECTOR) ?? null;
9576
+ if (!scope2 || scope2 === document.documentElement || scope2 === document.body) return document.body;
9577
+ return scope2;
9578
+ }
9579
+
9566
9580
  // src/components/table/sort.js
9567
9581
  function compareStrings(left, right) {
9568
9582
  return String(left).localeCompare(String(right));
@@ -12056,7 +12070,8 @@ var Launcher = class extends Component {
12056
12070
  emptyText: "No results",
12057
12071
  loadingText: "Searching\u2026",
12058
12072
  shortcut: "mod+k",
12059
- hints: { move: "Move", open: "Open", close: "Close" }
12073
+ hints: { move: "Move", open: "Open", close: "Close" },
12074
+ scope: null
12060
12075
  };
12061
12076
  /**
12062
12077
  * Creates an owned launcher dialog or enhances an existing `<dialog>` target.
@@ -12147,7 +12162,7 @@ var Launcher = class extends Component {
12147
12162
  )
12148
12163
  );
12149
12164
  dialog.dataset.state = "closed";
12150
- if (this._createdRoot) document.body.append(dialog);
12165
+ if (this._createdRoot) overlayHost(this.options.scope).append(dialog);
12151
12166
  this.listen(input, "input", () => {
12152
12167
  this._query = /** @type {HTMLInputElement} */
12153
12168
  input.value;
@@ -12198,6 +12213,10 @@ var Launcher = class extends Component {
12198
12213
  /** Opens the launcher and focuses/selects its query. @returns {this} @fires Launcher#open */
12199
12214
  open() {
12200
12215
  if (this.isOpen() || this._destroyed) return this;
12216
+ if (this._createdRoot) {
12217
+ const host = overlayHost(this.options.scope);
12218
+ if (this.el.parentElement !== host) host.append(this.el);
12219
+ }
12201
12220
  this.el.showModal();
12202
12221
  this.el.dataset.state = "open";
12203
12222
  this.refs.input.setAttribute("aria-expanded", "true");
@@ -12753,8 +12772,8 @@ var Message = class _Message extends Component {
12753
12772
  closable: true,
12754
12773
  maxVisible: 5
12755
12774
  };
12756
- /** @type {Message|null} */
12757
- static #floating = null;
12775
+ /** @type {WeakMap<Element, Message>} */
12776
+ static #floating = /* @__PURE__ */ new WeakMap();
12758
12777
  /** @returns {HTMLElement} */
12759
12778
  render() {
12760
12779
  const created = !this.el;
@@ -12833,15 +12852,16 @@ var Message = class _Message extends Component {
12833
12852
  * @returns {MessageHandle}
12834
12853
  */
12835
12854
  static show(msg, options = {}) {
12836
- return this.#floatingRegion().show(msg, options);
12855
+ return this.#floatingRegion(options.scope).show(msg, options);
12837
12856
  }
12838
12857
  /**
12839
12858
  * Shows a floating progress status.
12840
12859
  * @param {string} text Initial status text.
12860
+ * @param {{scope?: Element|string|null}} [options={}] Floating-region scope.
12841
12861
  * @returns {ProgressHandle}
12842
12862
  */
12843
- static progress(text3) {
12844
- return this.#floatingRegion()._progress(text3);
12863
+ static progress(text3, options = {}) {
12864
+ return this.#floatingRegion(options.scope)._progress(text3);
12845
12865
  }
12846
12866
  /** @returns {void} */
12847
12867
  destroy() {
@@ -13019,19 +13039,22 @@ var Message = class _Message extends Component {
13019
13039
  this._entries.delete(entry);
13020
13040
  this._queue.remove(entry);
13021
13041
  }
13022
- /** @returns {Message} */
13023
- static #floatingRegion() {
13024
- if (this.#floating) return this.#floating;
13042
+ /** @param {Element|string|null|undefined} scope @returns {Message} */
13043
+ static #floatingRegion(scope2) {
13044
+ const host = overlayHost(scope2 ?? null);
13045
+ const existing = this.#floating.get(host);
13046
+ if (existing) return existing;
13025
13047
  const region = h("div", {
13026
13048
  class: "zx-message-region",
13027
13049
  popover: "manual",
13028
13050
  role: "status",
13029
13051
  ariaLive: "polite"
13030
13052
  });
13031
- document.body.append(region);
13032
- this.#floating = new _Message(region);
13053
+ host.append(region);
13054
+ const floating = new _Message(region);
13055
+ this.#floating.set(host, floating);
13033
13056
  if (typeof region.showPopover === "function") region.showPopover();
13034
- return this.#floating;
13057
+ return floating;
13035
13058
  }
13036
13059
  };
13037
13060
  function normalizeKind(value) {
@@ -13114,6 +13137,29 @@ function calendarRange(view, anchor, options = {}) {
13114
13137
  }
13115
13138
  return { start, end };
13116
13139
  }
13140
+ function calendarPageDate(view, anchor, direction, options = {}) {
13141
+ const date = validDate5(anchor, "Calendar date");
13142
+ const step = integer(direction, "direction");
13143
+ if (view === "day") date.setDate(date.getDate() + step);
13144
+ else if (view === "agenda") {
13145
+ date.setDate(date.getDate() + step * positiveInteger(options.agendaDays ?? 14, "agendaDays"));
13146
+ } else if (view === "week") date.setDate(date.getDate() + step * 7);
13147
+ else if (view === "month") return addCalendarMonths(date, step);
13148
+ else if (view === "year") return addCalendarMonths(date, step * 12);
13149
+ else throw new RangeError(`Unknown calendar view: ${view}`);
13150
+ return date;
13151
+ }
13152
+ function addCalendarMonths(value, months) {
13153
+ const date = validDate5(value, "Calendar date");
13154
+ const day = date.getDate();
13155
+ date.setDate(1);
13156
+ date.setMonth(date.getMonth() + integer(months, "month amount"));
13157
+ date.setDate(Math.min(day, daysInCalendarMonth(date.getFullYear(), date.getMonth())));
13158
+ return date;
13159
+ }
13160
+ function daysInCalendarMonth(year, month) {
13161
+ return new Date(year, month + 1, 0).getDate();
13162
+ }
13117
13163
  function normalizeCalendarEvents(records, options = {}) {
13118
13164
  if (!Array.isArray(records)) throw new TypeError("Calendar events must be an array");
13119
13165
  const readers = {
@@ -13557,7 +13603,7 @@ var Calendar = class extends Component {
13557
13603
  durationEditable: Object.prototype.hasOwnProperty.call(changes, "durationEditable") ? changes.durationEditable : current.durationEditable,
13558
13604
  data: changes.data ?? current.data
13559
13605
  };
13560
- const [next] = normalizeCalendarEvents([source]);
13606
+ const [next] = normalizeCalendarEvents([source], { dateUnit: this.options.dateUnit });
13561
13607
  next.data = source.data;
13562
13608
  this._events = this._events.map((event, eventIndex) => eventIndex === index ? next : event);
13563
13609
  this._mutationVersions.delete(String(id));
@@ -13708,7 +13754,11 @@ var Calendar = class extends Component {
13708
13754
  }).sort(compareEvents);
13709
13755
  const row = h(
13710
13756
  "section",
13711
- { class: "zx-calendar__agenda-day", role: "row" },
13757
+ {
13758
+ class: "zx-calendar__agenda-day",
13759
+ role: "row",
13760
+ dataset: { date: calendarDayKey(day) }
13761
+ },
13712
13762
  h("button", {
13713
13763
  type: "button",
13714
13764
  class: "zx-calendar__agenda-heading",
@@ -13718,11 +13768,13 @@ var Calendar = class extends Component {
13718
13768
  disabled: this.options.disabled
13719
13769
  }, this._format(day, { weekday: "long", day: "numeric", month: "long" }))
13720
13770
  );
13771
+ const entries = h("div", { class: "zx-calendar__agenda-events", role: "gridcell" });
13721
13772
  if (!events.length) {
13722
- row.append(h("p", { class: "zx-calendar__agenda-empty", role: "gridcell" }, this.msg("noEvents")));
13773
+ entries.append(h("p", { class: "zx-calendar__agenda-empty" }, this.msg("noEvents")));
13723
13774
  } else {
13724
- for (const event of events) row.append(this._eventElement(event, { variant: "agenda", day }));
13775
+ for (const event of events) entries.append(this._eventElement(event, { variant: "agenda", day }));
13725
13776
  }
13777
+ row.append(entries);
13726
13778
  grid.append(row);
13727
13779
  }
13728
13780
  return grid;
@@ -13992,6 +14044,7 @@ var Calendar = class extends Component {
13992
14044
  dataset: {
13993
14045
  eventId: key,
13994
14046
  variant: context.variant,
14047
+ allDay: event.allDay ? "true" : null,
13995
14048
  draggable: this._canMove(event) ? "true" : null
13996
14049
  },
13997
14050
  style: event.color ? { "--zx-calendar-event-color": event.color } : null
@@ -14258,7 +14311,9 @@ var Calendar = class extends Component {
14258
14311
  const item = this._eventById(control.dataset.eventId);
14259
14312
  const action = control.dataset.eventAction === "resize" ? "resize" : "move";
14260
14313
  if (!item || (action === "move" ? !this._canMove(item) : !this._canResize(item))) return;
14261
- control.setPointerCapture?.(event.pointerId);
14314
+ event.preventDefault();
14315
+ this._capturePointer(event.pointerId);
14316
+ const offset = action === "move" ? this._dragOffsetForEvent(item, event.clientX, event.clientY) : null;
14262
14317
  this._pointer = {
14263
14318
  type: "event",
14264
14319
  pointerId: event.pointerId,
@@ -14268,6 +14323,8 @@ var Calendar = class extends Component {
14268
14323
  event: cloneCalendarEvent(item),
14269
14324
  action,
14270
14325
  control,
14326
+ timeOffsetMinutes: offset?.minutes ?? 0,
14327
+ dayOffset: offset?.days ?? 0,
14271
14328
  moved: false
14272
14329
  };
14273
14330
  return;
@@ -14276,7 +14333,8 @@ var Calendar = class extends Component {
14276
14333
  if (!slot || !this.options.selectable) return;
14277
14334
  const date = this._dateFromTarget(slot);
14278
14335
  if (!date) return;
14279
- slot.setPointerCapture?.(event.pointerId);
14336
+ event.preventDefault();
14337
+ this._capturePointer(event.pointerId);
14280
14338
  this._pointer = {
14281
14339
  type: "selection",
14282
14340
  pointerId: event.pointerId,
@@ -14309,7 +14367,13 @@ var Calendar = class extends Component {
14309
14367
  const wrapper = pointer.control.closest(".zx-calendar__event");
14310
14368
  if (wrapper) {
14311
14369
  wrapper.dataset.state = "dragging";
14312
- wrapper.style.transform = `translate(${event.clientX - pointer.startX}px, ${event.clientY - pointer.startY}px)`;
14370
+ if (pointer.action === "resize") {
14371
+ wrapper.style.transform = "";
14372
+ const height = this._timedPreviewHeight(proposed);
14373
+ if (height) wrapper.style.blockSize = height;
14374
+ } else {
14375
+ wrapper.style.transform = `translate(${event.clientX - pointer.startX}px, ${event.clientY - pointer.startY}px)`;
14376
+ }
14313
14377
  wrapper.dataset.preview = this._eventTime(proposed, proposed.start);
14314
14378
  }
14315
14379
  this._announce(this.msg(
@@ -14324,6 +14388,7 @@ var Calendar = class extends Component {
14324
14388
  const pointer = this._pointer;
14325
14389
  if (!pointer || pointer.pointerId !== event.pointerId) return;
14326
14390
  this._pointer = null;
14391
+ this._releasePointerCapture(pointer.pointerId);
14327
14392
  this._clearSelectionPreview();
14328
14393
  if (!pointer.moved) return;
14329
14394
  event.preventDefault();
@@ -14341,6 +14406,7 @@ var Calendar = class extends Component {
14341
14406
  _cancelPointer(event) {
14342
14407
  if (!this._pointer || this._pointer.pointerId !== event.pointerId) return;
14343
14408
  const control = this._pointer.control;
14409
+ this._releasePointerCapture(this._pointer.pointerId);
14344
14410
  this._pointer = null;
14345
14411
  this._clearSelectionPreview();
14346
14412
  control.closest?.(".zx-calendar__event")?.removeAttribute("data-state");
@@ -14348,13 +14414,14 @@ var Calendar = class extends Component {
14348
14414
  }
14349
14415
  /** @param {CalendarEvent} event @param {'move'|'resize'} action @param {number} x @param {number} y @returns {CalendarEvent|null} */
14350
14416
  _proposalAtPoint(event, action, x, y) {
14351
- const timed = this._timeAtPoint(x, y);
14417
+ const resizeTimed = action === "resize" && !calendarEventSpansDays(event);
14418
+ const timed = this._timeAtPoint(x, y, resizeTimed ? event.start : null);
14352
14419
  if (timed && !calendarEventSpansDays(event)) {
14353
14420
  if (action === "move") {
14354
14421
  const duration = event.end.getTime() - event.start.getTime();
14355
14422
  const next3 = cloneCalendarEvent(event);
14356
- next3.start = timed;
14357
- next3.end = new Date(timed.getTime() + duration);
14423
+ next3.start = addMinutes(timed, -Number(this._pointer?.timeOffsetMinutes ?? 0));
14424
+ next3.end = new Date(next3.start.getTime() + duration);
14358
14425
  return next3;
14359
14426
  }
14360
14427
  const next2 = cloneCalendarEvent(event);
@@ -14363,33 +14430,36 @@ var Calendar = class extends Component {
14363
14430
  }
14364
14431
  const day = this._dayAtPoint(x, y);
14365
14432
  if (!day) return null;
14366
- const difference = calendarDayDifference(startOfCalendarDay(event.start), day);
14433
+ const targetDay = addCalendarDays(day, -Number(this._pointer?.dayOffset ?? 0));
14434
+ const difference = calendarDayDifference(startOfCalendarDay(event.start), targetDay);
14367
14435
  if (action === "move") return shiftCalendarEvent(event, { days: difference, minutes: 0 });
14368
14436
  const next = cloneCalendarEvent(event);
14369
14437
  const endDay = addCalendarDays(day, 1);
14370
14438
  next.end = new Date(endDay.getTime());
14371
14439
  return next.end > next.start ? next : null;
14372
14440
  }
14373
- /** @param {number} x @param {number} y @returns {Date|null} */
14374
- _timeAtPoint(x, y) {
14441
+ /** @param {number} x @param {number} y @param {Date|null} [fixedDay=null] @returns {Date|null} */
14442
+ _timeAtPoint(x, y, fixedDay = null) {
14375
14443
  const slots = this.refs.body.querySelector(".zx-calendar__slots");
14376
14444
  if (!slots) return null;
14377
14445
  const rect = slots.getBoundingClientRect();
14378
- if (x < rect.left || x > rect.right || y < rect.top || y > rect.bottom || rect.width <= 0 || rect.height <= 0) return null;
14446
+ const scroller = slots.closest(".zx-calendar__time-scroller");
14447
+ const viewport = scroller?.getBoundingClientRect();
14448
+ const left = viewport ? Math.max(rect.left, viewport.left) : rect.left;
14449
+ const right = viewport ? Math.min(rect.right, viewport.right) : rect.right;
14450
+ const top = viewport ? Math.max(rect.top, viewport.top) : rect.top;
14451
+ const bottom = viewport ? Math.min(rect.bottom, viewport.bottom) : rect.bottom;
14452
+ if (x < left || x > right || y < top || y > bottom || rect.width <= 0 || rect.height <= 0) return null;
14379
14453
  const columns = Number(slots.closest('[role="grid"]')?.getAttribute("aria-colcount")) || 1;
14380
14454
  const rows = Number(slots.closest('[role="grid"]')?.getAttribute("aria-rowcount")) || 1;
14381
- const column = Math.max(0, Math.min(columns - 1, Math.floor((x - rect.left) / rect.width * columns)));
14455
+ const fixedColumn = fixedDay ? this._timeGridDayIndex(fixedDay) : -1;
14456
+ const column = fixedColumn >= 0 ? fixedColumn : Math.max(0, Math.min(columns - 1, Math.floor((x - rect.left) / rect.width * columns)));
14382
14457
  const row = Math.max(0, Math.min(rows - 1, Math.floor((y - rect.top) / rect.height * rows)));
14383
14458
  const target = slots.querySelector(`[data-row-index="${row}"][data-day-index="${column}"]`);
14384
14459
  return target ? this._dateFromTarget(target) : null;
14385
14460
  }
14386
14461
  /** @param {number} x @param {number} y @returns {Date|null} */
14387
14462
  _dayAtPoint(x, y) {
14388
- const elements = typeof document.elementsFromPoint === "function" ? document.elementsFromPoint(x, y) : [];
14389
- for (const element of elements) {
14390
- const date = element instanceof HTMLElement ? element.dataset.date : null;
14391
- if (date) return parseDayKey(date);
14392
- }
14393
14463
  const allDay = this.refs.body.querySelector(".zx-calendar__all-day-grid");
14394
14464
  if (allDay) {
14395
14465
  const rect = allDay.getBoundingClientRect();
@@ -14399,8 +14469,72 @@ var Calendar = class extends Component {
14399
14469
  return parseDayKey(cells[index]?.dataset.date);
14400
14470
  }
14401
14471
  }
14472
+ for (const monthEvents of this.refs.body.querySelectorAll(".zx-calendar__month-events")) {
14473
+ const rect = monthEvents.getBoundingClientRect();
14474
+ if (x < rect.left || x > rect.right || y < rect.top || y > rect.bottom || rect.width <= 0) continue;
14475
+ const start = parseDayKey(monthEvents.closest(".zx-calendar__month-week")?.dataset.weekStart);
14476
+ if (!start) continue;
14477
+ const index = Math.max(0, Math.min(6, Math.floor((x - rect.left) / rect.width * 7)));
14478
+ return addCalendarDays(start, index);
14479
+ }
14480
+ for (const agendaDay of this.refs.body.querySelectorAll(".zx-calendar__agenda-day")) {
14481
+ const rect = agendaDay.getBoundingClientRect();
14482
+ if (x < rect.left || x > rect.right || y < rect.top || y > rect.bottom) continue;
14483
+ return parseDayKey(agendaDay.dataset.date);
14484
+ }
14485
+ const elements = typeof document.elementsFromPoint === "function" ? document.elementsFromPoint(x, y) : [];
14486
+ for (const element of elements) {
14487
+ const dateTarget = element instanceof HTMLElement ? element.closest("[data-date]") : null;
14488
+ const date = dateTarget instanceof HTMLElement ? dateTarget.dataset.date : null;
14489
+ if (date) return parseDayKey(date);
14490
+ }
14402
14491
  return null;
14403
14492
  }
14493
+ /** @param {CalendarEvent} event @param {number} x @param {number} y @returns {{minutes: number, days: number}} */
14494
+ _dragOffsetForEvent(event, x, y) {
14495
+ if (!calendarEventSpansDays(event)) {
14496
+ const timed = this._timeAtPoint(x, y);
14497
+ if (timed) {
14498
+ const slot = normalizeSlot(this.options.slotDuration);
14499
+ const duration = Math.max(0, Math.round((event.end.getTime() - event.start.getTime()) / 6e4));
14500
+ const maxOffset = Math.max(0, duration - slot);
14501
+ const minutes = Math.round((timed.getTime() - event.start.getTime()) / 6e4);
14502
+ return { minutes: Math.max(0, Math.min(maxOffset, minutes)), days: 0 };
14503
+ }
14504
+ }
14505
+ const day = this._dayAtPoint(x, y);
14506
+ const days = day ? calendarDayDifference(startOfCalendarDay(event.start), day) : 0;
14507
+ return { minutes: 0, days: Math.max(0, days) };
14508
+ }
14509
+ /** @param {Date} day @returns {number} */
14510
+ _timeGridDayIndex(day) {
14511
+ const key = calendarDayKey(day);
14512
+ const headings = [...this.refs.body.querySelectorAll(".zx-calendar__day-heading")];
14513
+ return headings.findIndex((heading) => heading.dataset.date === key);
14514
+ }
14515
+ /** @param {CalendarEvent} event @returns {string|null} */
14516
+ _timedPreviewHeight(event) {
14517
+ const grid = this.refs.body.querySelector(".zx-calendar__time-grid");
14518
+ if (!grid || calendarEventSpansDays(event)) return null;
14519
+ const min = normalizeMinute(this.options.slotMinTime, 0);
14520
+ const max = normalizeMinute(this.options.slotMaxTime, 1440, true);
14521
+ const slot = normalizeSlot(this.options.slotDuration);
14522
+ const start = event.start.getHours() * 60 + event.start.getMinutes();
14523
+ const end = event.end.getHours() * 60 + event.end.getMinutes();
14524
+ const minutes = Math.max(slot, Math.min(max, end) - Math.max(min, start));
14525
+ return `${minutes / (max - min) * 100}%`;
14526
+ }
14527
+ /** @param {number} pointerId @returns {void} */
14528
+ _capturePointer(pointerId) {
14529
+ try {
14530
+ this.el.setPointerCapture?.(pointerId);
14531
+ } catch {
14532
+ }
14533
+ }
14534
+ /** @param {number} pointerId @returns {void} */
14535
+ _releasePointerCapture(pointerId) {
14536
+ if (this.el.hasPointerCapture?.(pointerId)) this.el.releasePointerCapture?.(pointerId);
14537
+ }
14404
14538
  /** @param {Date} start @param {Date} end @returns {void} */
14405
14539
  _previewSelection(start, end) {
14406
14540
  const low = Math.min(start.getTime(), end.getTime());
@@ -14495,13 +14629,9 @@ var Calendar = class extends Component {
14495
14629
  }
14496
14630
  /** @param {number} direction @returns {this} */
14497
14631
  _page(direction) {
14498
- const date = new Date(this._date.getTime());
14499
- if (this._view === "day") date.setDate(date.getDate() + direction);
14500
- else if (this._view === "agenda") date.setDate(date.getDate() + direction * this.options.agendaDays);
14501
- else if (this._view === "week") date.setDate(date.getDate() + direction * 7);
14502
- else if (this._view === "month") date.setMonth(date.getMonth() + direction);
14503
- else date.setFullYear(date.getFullYear() + direction);
14504
- return this.setDate(date);
14632
+ return this.setDate(calendarPageDate(this._view, this._date, direction, {
14633
+ agendaDays: this.options.agendaDays
14634
+ }));
14505
14635
  }
14506
14636
  /** @param {{start: Date, end: Date}} range @returns {string} */
14507
14637
  _rangeTitle(range) {