@zeyos/zx 4.2.0 → 4.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.
Files changed (52) hide show
  1. package/CHANGELOG.md +37 -0
  2. package/README.md +5 -0
  3. package/dist/types/components/calendar/calendar.d.ts +19 -2
  4. package/dist/types/components/dialog/dialog.d.ts +6 -1
  5. package/dist/types/components/dropdown/dropdown.d.ts +5 -0
  6. package/dist/types/components/launcher/launcher.d.ts +5 -0
  7. package/dist/types/components/message/message.d.ts +9 -1
  8. package/dist/types/components/modal/modal.d.ts +44 -7
  9. package/dist/types/components/sheet/sheet.d.ts +22 -12
  10. package/dist/types/core/overlay-host.d.ts +12 -0
  11. package/dist/zx-zeyos.esm.js +138 -32
  12. package/dist/zx-zeyos.esm.min.js +1 -1
  13. package/dist/zx.css +259 -132
  14. package/dist/zx.esm.js +277 -82
  15. package/dist/zx.esm.min.js +3 -3
  16. package/dist/zx.global.js +277 -82
  17. package/dist/zx.global.min.js +3 -3
  18. package/dist/zx.min.css +1 -1
  19. package/docs/api.json +36 -0
  20. package/docs/llms.md +37 -18
  21. package/docs/llms.txt +1 -1
  22. package/package.json +1 -1
  23. package/src/components/account-menu/account-menu.css +1 -1
  24. package/src/components/app-rail/app-rail.css +1 -1
  25. package/src/components/calendar/calendar.css +66 -24
  26. package/src/components/calendar/calendar.js +114 -19
  27. package/src/components/context-menu/context-menu.css +2 -2
  28. package/src/components/context-menu/context-menu.js +5 -1
  29. package/src/components/date-picker/date-picker.css +18 -11
  30. package/src/components/datebox/date-range-box.css +4 -2
  31. package/src/components/datebox/datebox.css +4 -2
  32. package/src/components/dialog/dialog.css +4 -3
  33. package/src/components/dialog/dialog.js +2 -1
  34. package/src/components/dropdown/dropdown.css +4 -2
  35. package/src/components/dropdown/dropdown.js +7 -2
  36. package/src/components/launcher/launcher.css +10 -8
  37. package/src/components/launcher/launcher.js +9 -2
  38. package/src/components/menu-button/menu-button.css +2 -2
  39. package/src/components/message/message.css +7 -16
  40. package/src/components/message/message.js +17 -11
  41. package/src/components/modal/modal.css +6 -4
  42. package/src/components/modal/modal.js +99 -25
  43. package/src/components/select/select.css +9 -7
  44. package/src/components/sheet/sheet.css +25 -7
  45. package/src/components/sheet/sheet.js +43 -23
  46. package/src/components/table/table.css +5 -3
  47. package/src/components/tag-picker/tag-picker.css +5 -3
  48. package/src/components/tooltip/tooltip.css +4 -2
  49. package/src/components/tooltip/tooltip.js +4 -1
  50. package/src/core/overlay-host.js +23 -0
  51. package/styles/tokens/dark.css +4 -0
  52. package/styles/tokens/semantic.css +83 -8
@@ -9563,6 +9563,15 @@ function currencyCode(value) {
9563
9563
  return /^[A-Z]{3}$/.test(code) ? code : null;
9564
9564
  }
9565
9565
 
9566
+ // src/core/overlay-host.js
9567
+ var SCOPE_SELECTOR = ".zx-scope, [data-zx-theme], [data-zx-density], [data-zx-preset]";
9568
+ function overlayHost(source = null) {
9569
+ const context = source == null ? document.activeElement instanceof Element ? document.activeElement : null : resolveElement(source);
9570
+ const scope2 = context?.closest?.(SCOPE_SELECTOR) ?? null;
9571
+ if (!scope2 || scope2 === document.documentElement || scope2 === document.body) return document.body;
9572
+ return scope2;
9573
+ }
9574
+
9566
9575
  // src/components/table/sort.js
9567
9576
  function compareStrings(left, right) {
9568
9577
  return String(left).localeCompare(String(right));
@@ -12056,7 +12065,8 @@ var Launcher = class extends Component {
12056
12065
  emptyText: "No results",
12057
12066
  loadingText: "Searching\u2026",
12058
12067
  shortcut: "mod+k",
12059
- hints: { move: "Move", open: "Open", close: "Close" }
12068
+ hints: { move: "Move", open: "Open", close: "Close" },
12069
+ scope: null
12060
12070
  };
12061
12071
  /**
12062
12072
  * Creates an owned launcher dialog or enhances an existing `<dialog>` target.
@@ -12147,7 +12157,7 @@ var Launcher = class extends Component {
12147
12157
  )
12148
12158
  );
12149
12159
  dialog.dataset.state = "closed";
12150
- if (this._createdRoot) document.body.append(dialog);
12160
+ if (this._createdRoot) overlayHost(this.options.scope).append(dialog);
12151
12161
  this.listen(input, "input", () => {
12152
12162
  this._query = /** @type {HTMLInputElement} */
12153
12163
  input.value;
@@ -12198,6 +12208,10 @@ var Launcher = class extends Component {
12198
12208
  /** Opens the launcher and focuses/selects its query. @returns {this} @fires Launcher#open */
12199
12209
  open() {
12200
12210
  if (this.isOpen() || this._destroyed) return this;
12211
+ if (this._createdRoot) {
12212
+ const host = overlayHost(this.options.scope);
12213
+ if (this.el.parentElement !== host) host.append(this.el);
12214
+ }
12201
12215
  this.el.showModal();
12202
12216
  this.el.dataset.state = "open";
12203
12217
  this.refs.input.setAttribute("aria-expanded", "true");
@@ -12753,8 +12767,8 @@ var Message = class _Message extends Component {
12753
12767
  closable: true,
12754
12768
  maxVisible: 5
12755
12769
  };
12756
- /** @type {Message|null} */
12757
- static #floating = null;
12770
+ /** @type {WeakMap<Element, Message>} */
12771
+ static #floating = /* @__PURE__ */ new WeakMap();
12758
12772
  /** @returns {HTMLElement} */
12759
12773
  render() {
12760
12774
  const created = !this.el;
@@ -12833,15 +12847,16 @@ var Message = class _Message extends Component {
12833
12847
  * @returns {MessageHandle}
12834
12848
  */
12835
12849
  static show(msg, options = {}) {
12836
- return this.#floatingRegion().show(msg, options);
12850
+ return this.#floatingRegion(options.scope).show(msg, options);
12837
12851
  }
12838
12852
  /**
12839
12853
  * Shows a floating progress status.
12840
12854
  * @param {string} text Initial status text.
12855
+ * @param {{scope?: Element|string|null}} [options={}] Floating-region scope.
12841
12856
  * @returns {ProgressHandle}
12842
12857
  */
12843
- static progress(text3) {
12844
- return this.#floatingRegion()._progress(text3);
12858
+ static progress(text3, options = {}) {
12859
+ return this.#floatingRegion(options.scope)._progress(text3);
12845
12860
  }
12846
12861
  /** @returns {void} */
12847
12862
  destroy() {
@@ -13019,19 +13034,22 @@ var Message = class _Message extends Component {
13019
13034
  this._entries.delete(entry);
13020
13035
  this._queue.remove(entry);
13021
13036
  }
13022
- /** @returns {Message} */
13023
- static #floatingRegion() {
13024
- if (this.#floating) return this.#floating;
13037
+ /** @param {Element|string|null|undefined} scope @returns {Message} */
13038
+ static #floatingRegion(scope2) {
13039
+ const host = overlayHost(scope2 ?? null);
13040
+ const existing = this.#floating.get(host);
13041
+ if (existing) return existing;
13025
13042
  const region = h("div", {
13026
13043
  class: "zx-message-region",
13027
13044
  popover: "manual",
13028
13045
  role: "status",
13029
13046
  ariaLive: "polite"
13030
13047
  });
13031
- document.body.append(region);
13032
- this.#floating = new _Message(region);
13048
+ host.append(region);
13049
+ const floating = new _Message(region);
13050
+ this.#floating.set(host, floating);
13033
13051
  if (typeof region.showPopover === "function") region.showPopover();
13034
- return this.#floating;
13052
+ return floating;
13035
13053
  }
13036
13054
  };
13037
13055
  function normalizeKind(value) {
@@ -13708,7 +13726,11 @@ var Calendar = class extends Component {
13708
13726
  }).sort(compareEvents);
13709
13727
  const row = h(
13710
13728
  "section",
13711
- { class: "zx-calendar__agenda-day", role: "row" },
13729
+ {
13730
+ class: "zx-calendar__agenda-day",
13731
+ role: "row",
13732
+ dataset: { date: calendarDayKey(day) }
13733
+ },
13712
13734
  h("button", {
13713
13735
  type: "button",
13714
13736
  class: "zx-calendar__agenda-heading",
@@ -13718,11 +13740,13 @@ var Calendar = class extends Component {
13718
13740
  disabled: this.options.disabled
13719
13741
  }, this._format(day, { weekday: "long", day: "numeric", month: "long" }))
13720
13742
  );
13743
+ const entries = h("div", { class: "zx-calendar__agenda-events", role: "gridcell" });
13721
13744
  if (!events.length) {
13722
- row.append(h("p", { class: "zx-calendar__agenda-empty", role: "gridcell" }, this.msg("noEvents")));
13745
+ entries.append(h("p", { class: "zx-calendar__agenda-empty" }, this.msg("noEvents")));
13723
13746
  } else {
13724
- for (const event of events) row.append(this._eventElement(event, { variant: "agenda", day }));
13747
+ for (const event of events) entries.append(this._eventElement(event, { variant: "agenda", day }));
13725
13748
  }
13749
+ row.append(entries);
13726
13750
  grid.append(row);
13727
13751
  }
13728
13752
  return grid;
@@ -13992,6 +14016,7 @@ var Calendar = class extends Component {
13992
14016
  dataset: {
13993
14017
  eventId: key,
13994
14018
  variant: context.variant,
14019
+ allDay: event.allDay ? "true" : null,
13995
14020
  draggable: this._canMove(event) ? "true" : null
13996
14021
  },
13997
14022
  style: event.color ? { "--zx-calendar-event-color": event.color } : null
@@ -14258,7 +14283,9 @@ var Calendar = class extends Component {
14258
14283
  const item = this._eventById(control.dataset.eventId);
14259
14284
  const action = control.dataset.eventAction === "resize" ? "resize" : "move";
14260
14285
  if (!item || (action === "move" ? !this._canMove(item) : !this._canResize(item))) return;
14261
- control.setPointerCapture?.(event.pointerId);
14286
+ event.preventDefault();
14287
+ this._capturePointer(event.pointerId);
14288
+ const offset = action === "move" ? this._dragOffsetForEvent(item, event.clientX, event.clientY) : null;
14262
14289
  this._pointer = {
14263
14290
  type: "event",
14264
14291
  pointerId: event.pointerId,
@@ -14268,6 +14295,8 @@ var Calendar = class extends Component {
14268
14295
  event: cloneCalendarEvent(item),
14269
14296
  action,
14270
14297
  control,
14298
+ timeOffsetMinutes: offset?.minutes ?? 0,
14299
+ dayOffset: offset?.days ?? 0,
14271
14300
  moved: false
14272
14301
  };
14273
14302
  return;
@@ -14276,7 +14305,8 @@ var Calendar = class extends Component {
14276
14305
  if (!slot || !this.options.selectable) return;
14277
14306
  const date = this._dateFromTarget(slot);
14278
14307
  if (!date) return;
14279
- slot.setPointerCapture?.(event.pointerId);
14308
+ event.preventDefault();
14309
+ this._capturePointer(event.pointerId);
14280
14310
  this._pointer = {
14281
14311
  type: "selection",
14282
14312
  pointerId: event.pointerId,
@@ -14309,7 +14339,13 @@ var Calendar = class extends Component {
14309
14339
  const wrapper = pointer.control.closest(".zx-calendar__event");
14310
14340
  if (wrapper) {
14311
14341
  wrapper.dataset.state = "dragging";
14312
- wrapper.style.transform = `translate(${event.clientX - pointer.startX}px, ${event.clientY - pointer.startY}px)`;
14342
+ if (pointer.action === "resize") {
14343
+ wrapper.style.transform = "";
14344
+ const height = this._timedPreviewHeight(proposed);
14345
+ if (height) wrapper.style.blockSize = height;
14346
+ } else {
14347
+ wrapper.style.transform = `translate(${event.clientX - pointer.startX}px, ${event.clientY - pointer.startY}px)`;
14348
+ }
14313
14349
  wrapper.dataset.preview = this._eventTime(proposed, proposed.start);
14314
14350
  }
14315
14351
  this._announce(this.msg(
@@ -14324,6 +14360,7 @@ var Calendar = class extends Component {
14324
14360
  const pointer = this._pointer;
14325
14361
  if (!pointer || pointer.pointerId !== event.pointerId) return;
14326
14362
  this._pointer = null;
14363
+ this._releasePointerCapture(pointer.pointerId);
14327
14364
  this._clearSelectionPreview();
14328
14365
  if (!pointer.moved) return;
14329
14366
  event.preventDefault();
@@ -14341,6 +14378,7 @@ var Calendar = class extends Component {
14341
14378
  _cancelPointer(event) {
14342
14379
  if (!this._pointer || this._pointer.pointerId !== event.pointerId) return;
14343
14380
  const control = this._pointer.control;
14381
+ this._releasePointerCapture(this._pointer.pointerId);
14344
14382
  this._pointer = null;
14345
14383
  this._clearSelectionPreview();
14346
14384
  control.closest?.(".zx-calendar__event")?.removeAttribute("data-state");
@@ -14348,13 +14386,14 @@ var Calendar = class extends Component {
14348
14386
  }
14349
14387
  /** @param {CalendarEvent} event @param {'move'|'resize'} action @param {number} x @param {number} y @returns {CalendarEvent|null} */
14350
14388
  _proposalAtPoint(event, action, x, y) {
14351
- const timed = this._timeAtPoint(x, y);
14389
+ const resizeTimed = action === "resize" && !calendarEventSpansDays(event);
14390
+ const timed = this._timeAtPoint(x, y, resizeTimed ? event.start : null);
14352
14391
  if (timed && !calendarEventSpansDays(event)) {
14353
14392
  if (action === "move") {
14354
14393
  const duration = event.end.getTime() - event.start.getTime();
14355
14394
  const next3 = cloneCalendarEvent(event);
14356
- next3.start = timed;
14357
- next3.end = new Date(timed.getTime() + duration);
14395
+ next3.start = addMinutes(timed, -Number(this._pointer?.timeOffsetMinutes ?? 0));
14396
+ next3.end = new Date(next3.start.getTime() + duration);
14358
14397
  return next3;
14359
14398
  }
14360
14399
  const next2 = cloneCalendarEvent(event);
@@ -14363,33 +14402,36 @@ var Calendar = class extends Component {
14363
14402
  }
14364
14403
  const day = this._dayAtPoint(x, y);
14365
14404
  if (!day) return null;
14366
- const difference = calendarDayDifference(startOfCalendarDay(event.start), day);
14405
+ const targetDay = addCalendarDays(day, -Number(this._pointer?.dayOffset ?? 0));
14406
+ const difference = calendarDayDifference(startOfCalendarDay(event.start), targetDay);
14367
14407
  if (action === "move") return shiftCalendarEvent(event, { days: difference, minutes: 0 });
14368
14408
  const next = cloneCalendarEvent(event);
14369
14409
  const endDay = addCalendarDays(day, 1);
14370
14410
  next.end = new Date(endDay.getTime());
14371
14411
  return next.end > next.start ? next : null;
14372
14412
  }
14373
- /** @param {number} x @param {number} y @returns {Date|null} */
14374
- _timeAtPoint(x, y) {
14413
+ /** @param {number} x @param {number} y @param {Date|null} [fixedDay=null] @returns {Date|null} */
14414
+ _timeAtPoint(x, y, fixedDay = null) {
14375
14415
  const slots = this.refs.body.querySelector(".zx-calendar__slots");
14376
14416
  if (!slots) return null;
14377
14417
  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;
14418
+ const scroller = slots.closest(".zx-calendar__time-scroller");
14419
+ const viewport = scroller?.getBoundingClientRect();
14420
+ const left = viewport ? Math.max(rect.left, viewport.left) : rect.left;
14421
+ const right = viewport ? Math.min(rect.right, viewport.right) : rect.right;
14422
+ const top = viewport ? Math.max(rect.top, viewport.top) : rect.top;
14423
+ const bottom = viewport ? Math.min(rect.bottom, viewport.bottom) : rect.bottom;
14424
+ if (x < left || x > right || y < top || y > bottom || rect.width <= 0 || rect.height <= 0) return null;
14379
14425
  const columns = Number(slots.closest('[role="grid"]')?.getAttribute("aria-colcount")) || 1;
14380
14426
  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)));
14427
+ const fixedColumn = fixedDay ? this._timeGridDayIndex(fixedDay) : -1;
14428
+ const column = fixedColumn >= 0 ? fixedColumn : Math.max(0, Math.min(columns - 1, Math.floor((x - rect.left) / rect.width * columns)));
14382
14429
  const row = Math.max(0, Math.min(rows - 1, Math.floor((y - rect.top) / rect.height * rows)));
14383
14430
  const target = slots.querySelector(`[data-row-index="${row}"][data-day-index="${column}"]`);
14384
14431
  return target ? this._dateFromTarget(target) : null;
14385
14432
  }
14386
14433
  /** @param {number} x @param {number} y @returns {Date|null} */
14387
14434
  _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
14435
  const allDay = this.refs.body.querySelector(".zx-calendar__all-day-grid");
14394
14436
  if (allDay) {
14395
14437
  const rect = allDay.getBoundingClientRect();
@@ -14399,8 +14441,72 @@ var Calendar = class extends Component {
14399
14441
  return parseDayKey(cells[index]?.dataset.date);
14400
14442
  }
14401
14443
  }
14444
+ for (const monthEvents of this.refs.body.querySelectorAll(".zx-calendar__month-events")) {
14445
+ const rect = monthEvents.getBoundingClientRect();
14446
+ if (x < rect.left || x > rect.right || y < rect.top || y > rect.bottom || rect.width <= 0) continue;
14447
+ const start = parseDayKey(monthEvents.closest(".zx-calendar__month-week")?.dataset.weekStart);
14448
+ if (!start) continue;
14449
+ const index = Math.max(0, Math.min(6, Math.floor((x - rect.left) / rect.width * 7)));
14450
+ return addCalendarDays(start, index);
14451
+ }
14452
+ for (const agendaDay of this.refs.body.querySelectorAll(".zx-calendar__agenda-day")) {
14453
+ const rect = agendaDay.getBoundingClientRect();
14454
+ if (x < rect.left || x > rect.right || y < rect.top || y > rect.bottom) continue;
14455
+ return parseDayKey(agendaDay.dataset.date);
14456
+ }
14457
+ const elements = typeof document.elementsFromPoint === "function" ? document.elementsFromPoint(x, y) : [];
14458
+ for (const element of elements) {
14459
+ const dateTarget = element instanceof HTMLElement ? element.closest("[data-date]") : null;
14460
+ const date = dateTarget instanceof HTMLElement ? dateTarget.dataset.date : null;
14461
+ if (date) return parseDayKey(date);
14462
+ }
14402
14463
  return null;
14403
14464
  }
14465
+ /** @param {CalendarEvent} event @param {number} x @param {number} y @returns {{minutes: number, days: number}} */
14466
+ _dragOffsetForEvent(event, x, y) {
14467
+ if (!calendarEventSpansDays(event)) {
14468
+ const timed = this._timeAtPoint(x, y);
14469
+ if (timed) {
14470
+ const slot = normalizeSlot(this.options.slotDuration);
14471
+ const duration = Math.max(0, Math.round((event.end.getTime() - event.start.getTime()) / 6e4));
14472
+ const maxOffset = Math.max(0, duration - slot);
14473
+ const minutes = Math.round((timed.getTime() - event.start.getTime()) / 6e4);
14474
+ return { minutes: Math.max(0, Math.min(maxOffset, minutes)), days: 0 };
14475
+ }
14476
+ }
14477
+ const day = this._dayAtPoint(x, y);
14478
+ const days = day ? calendarDayDifference(startOfCalendarDay(event.start), day) : 0;
14479
+ return { minutes: 0, days: Math.max(0, days) };
14480
+ }
14481
+ /** @param {Date} day @returns {number} */
14482
+ _timeGridDayIndex(day) {
14483
+ const key = calendarDayKey(day);
14484
+ const headings = [...this.refs.body.querySelectorAll(".zx-calendar__day-heading")];
14485
+ return headings.findIndex((heading) => heading.dataset.date === key);
14486
+ }
14487
+ /** @param {CalendarEvent} event @returns {string|null} */
14488
+ _timedPreviewHeight(event) {
14489
+ const grid = this.refs.body.querySelector(".zx-calendar__time-grid");
14490
+ if (!grid || calendarEventSpansDays(event)) return null;
14491
+ const min = normalizeMinute(this.options.slotMinTime, 0);
14492
+ const max = normalizeMinute(this.options.slotMaxTime, 1440, true);
14493
+ const slot = normalizeSlot(this.options.slotDuration);
14494
+ const start = event.start.getHours() * 60 + event.start.getMinutes();
14495
+ const end = event.end.getHours() * 60 + event.end.getMinutes();
14496
+ const minutes = Math.max(slot, Math.min(max, end) - Math.max(min, start));
14497
+ return `${minutes / (max - min) * 100}%`;
14498
+ }
14499
+ /** @param {number} pointerId @returns {void} */
14500
+ _capturePointer(pointerId) {
14501
+ try {
14502
+ this.el.setPointerCapture?.(pointerId);
14503
+ } catch {
14504
+ }
14505
+ }
14506
+ /** @param {number} pointerId @returns {void} */
14507
+ _releasePointerCapture(pointerId) {
14508
+ if (this.el.hasPointerCapture?.(pointerId)) this.el.releasePointerCapture?.(pointerId);
14509
+ }
14404
14510
  /** @param {Date} start @param {Date} end @returns {void} */
14405
14511
  _previewSelection(start, end) {
14406
14512
  const low = Math.min(start.getTime(), end.getTime());