@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.
- package/CHANGELOG.md +37 -0
- package/README.md +5 -0
- package/dist/types/components/calendar/calendar.d.ts +19 -2
- package/dist/types/components/dialog/dialog.d.ts +6 -1
- package/dist/types/components/dropdown/dropdown.d.ts +5 -0
- package/dist/types/components/launcher/launcher.d.ts +5 -0
- package/dist/types/components/message/message.d.ts +9 -1
- package/dist/types/components/modal/modal.d.ts +44 -7
- package/dist/types/components/sheet/sheet.d.ts +22 -12
- package/dist/types/core/overlay-host.d.ts +12 -0
- package/dist/zx-zeyos.esm.js +138 -32
- package/dist/zx-zeyos.esm.min.js +1 -1
- package/dist/zx.css +259 -132
- package/dist/zx.esm.js +277 -82
- package/dist/zx.esm.min.js +3 -3
- package/dist/zx.global.js +277 -82
- package/dist/zx.global.min.js +3 -3
- package/dist/zx.min.css +1 -1
- package/docs/api.json +36 -0
- package/docs/llms.md +37 -18
- package/docs/llms.txt +1 -1
- package/package.json +1 -1
- package/src/components/account-menu/account-menu.css +1 -1
- package/src/components/app-rail/app-rail.css +1 -1
- package/src/components/calendar/calendar.css +66 -24
- package/src/components/calendar/calendar.js +114 -19
- package/src/components/context-menu/context-menu.css +2 -2
- package/src/components/context-menu/context-menu.js +5 -1
- package/src/components/date-picker/date-picker.css +18 -11
- package/src/components/datebox/date-range-box.css +4 -2
- package/src/components/datebox/datebox.css +4 -2
- package/src/components/dialog/dialog.css +4 -3
- package/src/components/dialog/dialog.js +2 -1
- package/src/components/dropdown/dropdown.css +4 -2
- package/src/components/dropdown/dropdown.js +7 -2
- package/src/components/launcher/launcher.css +10 -8
- package/src/components/launcher/launcher.js +9 -2
- package/src/components/menu-button/menu-button.css +2 -2
- package/src/components/message/message.css +7 -16
- package/src/components/message/message.js +17 -11
- package/src/components/modal/modal.css +6 -4
- package/src/components/modal/modal.js +99 -25
- package/src/components/select/select.css +9 -7
- package/src/components/sheet/sheet.css +25 -7
- package/src/components/sheet/sheet.js +43 -23
- package/src/components/table/table.css +5 -3
- package/src/components/tag-picker/tag-picker.css +5 -3
- package/src/components/tooltip/tooltip.css +4 -2
- package/src/components/tooltip/tooltip.js +4 -1
- package/src/core/overlay-host.js +23 -0
- package/styles/tokens/dark.css +4 -0
- package/styles/tokens/semantic.css +83 -8
package/dist/zx.esm.js
CHANGED
|
@@ -10286,6 +10286,15 @@ function restore2(element, state) {
|
|
|
10286
10286
|
element.replaceChildren(...state.children);
|
|
10287
10287
|
}
|
|
10288
10288
|
|
|
10289
|
+
// src/core/overlay-host.js
|
|
10290
|
+
var SCOPE_SELECTOR = ".zx-scope, [data-zx-theme], [data-zx-density], [data-zx-preset]";
|
|
10291
|
+
function overlayHost(source = null) {
|
|
10292
|
+
const context = source == null ? document.activeElement instanceof Element ? document.activeElement : null : resolveElement(source);
|
|
10293
|
+
const scope2 = context?.closest?.(SCOPE_SELECTOR) ?? null;
|
|
10294
|
+
if (!scope2 || scope2 === document.documentElement || scope2 === document.body) return document.body;
|
|
10295
|
+
return scope2;
|
|
10296
|
+
}
|
|
10297
|
+
|
|
10289
10298
|
// src/components/modal/modal.js
|
|
10290
10299
|
var Modal = class extends Component {
|
|
10291
10300
|
static cssName = "modal";
|
|
@@ -10295,13 +10304,17 @@ var Modal = class extends Component {
|
|
|
10295
10304
|
width: "auto",
|
|
10296
10305
|
closable: true,
|
|
10297
10306
|
lightDismiss: false,
|
|
10298
|
-
destroyOnClose: false
|
|
10307
|
+
destroyOnClose: false,
|
|
10308
|
+
scope: null
|
|
10299
10309
|
};
|
|
10300
|
-
|
|
10301
|
-
#
|
|
10310
|
+
/** @type {Map<number, {result: unknown}>} */
|
|
10311
|
+
#pendingResults = /* @__PURE__ */ new Map();
|
|
10302
10312
|
#destroying = false;
|
|
10313
|
+
#presentation = 0;
|
|
10314
|
+
/** @type {number[]} */
|
|
10315
|
+
#nativeClosingPresentations = [];
|
|
10303
10316
|
/**
|
|
10304
|
-
* Creates a modal
|
|
10317
|
+
* Creates a modal in the configured theme scope, or at document level when none is present.
|
|
10305
10318
|
* @param {Element|string|null} [_target=null] Ignored; Modal always owns its root dialog.
|
|
10306
10319
|
* @param {ModalOptions} [options={}] Modal options.
|
|
10307
10320
|
*/
|
|
@@ -10314,14 +10327,7 @@ var Modal = class extends Component {
|
|
|
10314
10327
|
if (!this.options.closable || cancelEvent.defaultPrevented) event.preventDefault();
|
|
10315
10328
|
});
|
|
10316
10329
|
this.listen(this.el, "close", () => {
|
|
10317
|
-
|
|
10318
|
-
this.el.dataset.state = "closed";
|
|
10319
|
-
delete this.el.dataset.zxOverlayOrder;
|
|
10320
|
-
const result = this.#hasPendingResult ? this.#pendingResult : this.el.returnValue || void 0;
|
|
10321
|
-
this.#pendingResult = void 0;
|
|
10322
|
-
this.#hasPendingResult = false;
|
|
10323
|
-
this.emit("close", { result });
|
|
10324
|
-
if (this.options.destroyOnClose && !this.#destroying) this.destroy();
|
|
10330
|
+
this._settleClose(this.#nativeClosingPresentations.shift());
|
|
10325
10331
|
});
|
|
10326
10332
|
this.listen(this.el, "click", (event) => {
|
|
10327
10333
|
if (!this.options.lightDismiss || event.target !== this.el || !isBackdropClick(this.el, event)) return;
|
|
@@ -10337,7 +10343,7 @@ var Modal = class extends Component {
|
|
|
10337
10343
|
* @returns {Element}
|
|
10338
10344
|
*/
|
|
10339
10345
|
mountTarget() {
|
|
10340
|
-
return
|
|
10346
|
+
return overlayHost(this.options.scope);
|
|
10341
10347
|
}
|
|
10342
10348
|
/**
|
|
10343
10349
|
* Puts the dialog on screen. Overridden by subclasses that open non-modally.
|
|
@@ -10346,17 +10352,78 @@ var Modal = class extends Component {
|
|
|
10346
10352
|
_show() {
|
|
10347
10353
|
this.el.showModal();
|
|
10348
10354
|
}
|
|
10355
|
+
/**
|
|
10356
|
+
* Removes the dialog from its current presentation layer.
|
|
10357
|
+
* Subclasses may replace native dialog presentation while preserving Modal lifecycle events.
|
|
10358
|
+
* @param {string} [result=''] Native string return value.
|
|
10359
|
+
* @param {number} [presentation=this.#presentation] Presentation generation being hidden.
|
|
10360
|
+
* @returns {void}
|
|
10361
|
+
*/
|
|
10362
|
+
_hide(result = "", presentation = this.#presentation) {
|
|
10363
|
+
this.#nativeClosingPresentations.push(presentation);
|
|
10364
|
+
try {
|
|
10365
|
+
this.el.close(result);
|
|
10366
|
+
} catch (error2) {
|
|
10367
|
+
this.#nativeClosingPresentations.pop();
|
|
10368
|
+
throw error2;
|
|
10369
|
+
}
|
|
10370
|
+
}
|
|
10371
|
+
/**
|
|
10372
|
+
* Shows a new presentation and gives it a generation of its own. Close events are queued by the
|
|
10373
|
+
* platform, so the generation lets an event from an earlier presentation expire harmlessly if
|
|
10374
|
+
* the same overlay has already reopened.
|
|
10375
|
+
* @returns {void}
|
|
10376
|
+
*/
|
|
10377
|
+
_present() {
|
|
10378
|
+
this._show();
|
|
10379
|
+
this.#presentation += 1;
|
|
10380
|
+
}
|
|
10381
|
+
/**
|
|
10382
|
+
* Hides the current presentation and records which generation its queued close event belongs to.
|
|
10383
|
+
* @param {string} [result=''] Native string return value.
|
|
10384
|
+
* @returns {void}
|
|
10385
|
+
*/
|
|
10386
|
+
_dismiss(result = "") {
|
|
10387
|
+
this._hide(result, this.#presentation);
|
|
10388
|
+
}
|
|
10389
|
+
/**
|
|
10390
|
+
* Reports whether the current presentation layer is visible.
|
|
10391
|
+
* @returns {boolean}
|
|
10392
|
+
*/
|
|
10393
|
+
_isShown() {
|
|
10394
|
+
return this.el.open;
|
|
10395
|
+
}
|
|
10349
10396
|
/**
|
|
10350
10397
|
* Whether an incoming `close` event is a real dismissal.
|
|
10351
10398
|
*
|
|
10352
|
-
*
|
|
10353
|
-
*
|
|
10354
|
-
*
|
|
10355
|
-
*
|
|
10356
|
-
* `destroyOnClose`. Returning false from an override drops it at the source instead.
|
|
10399
|
+
* `close` is dispatched in a queued task, not synchronously. By the time it arrives the overlay
|
|
10400
|
+
* may have reopened or crossed presentation layers, so only the event for the current hidden
|
|
10401
|
+
* generation may settle state, emit lifecycle events, or trigger `destroyOnClose`.
|
|
10402
|
+
* @param {number|undefined} closingPresentation Presentation that produced the event, if known.
|
|
10357
10403
|
* @returns {boolean}
|
|
10358
10404
|
*/
|
|
10359
|
-
_isRealClose() {
|
|
10405
|
+
_isRealClose(closingPresentation) {
|
|
10406
|
+
if (closingPresentation !== void 0 && closingPresentation !== this.#presentation) return false;
|
|
10407
|
+
return !this._isShown();
|
|
10408
|
+
}
|
|
10409
|
+
/**
|
|
10410
|
+
* Settles one presentation's close without allowing a queued event to invalidate a newer one.
|
|
10411
|
+
* Popover-based subclasses call this directly; native dialog events arrive through the listener.
|
|
10412
|
+
* @param {number|undefined} closingPresentation Presentation that was hidden, if known.
|
|
10413
|
+
* @returns {boolean} Whether this event closed the current presentation.
|
|
10414
|
+
*/
|
|
10415
|
+
_settleClose(closingPresentation) {
|
|
10416
|
+
if (!this._isRealClose(closingPresentation)) {
|
|
10417
|
+
if (closingPresentation !== void 0) this.#pendingResults.delete(closingPresentation);
|
|
10418
|
+
return false;
|
|
10419
|
+
}
|
|
10420
|
+
this.el.dataset.state = "closed";
|
|
10421
|
+
delete this.el.dataset.zxOverlayOrder;
|
|
10422
|
+
const pending = closingPresentation === void 0 ? void 0 : this.#pendingResults.get(closingPresentation);
|
|
10423
|
+
if (closingPresentation !== void 0) this.#pendingResults.delete(closingPresentation);
|
|
10424
|
+
const result = pending ? pending.result : this.el.returnValue || void 0;
|
|
10425
|
+
this.emit("close", { result });
|
|
10426
|
+
if (this.options.destroyOnClose && !this.#destroying) this.destroy();
|
|
10360
10427
|
return true;
|
|
10361
10428
|
}
|
|
10362
10429
|
/**
|
|
@@ -10381,10 +10448,12 @@ var Modal = class extends Component {
|
|
|
10381
10448
|
*/
|
|
10382
10449
|
open() {
|
|
10383
10450
|
if (this.isOpen()) return this;
|
|
10451
|
+
const host = this.mountTarget();
|
|
10452
|
+
if (this.el.parentElement !== host) host.append(this.el);
|
|
10384
10453
|
this.el.dataset.zxOverlayOrder = String(nextOverlayOrder());
|
|
10385
10454
|
this.el.returnValue = "";
|
|
10386
10455
|
try {
|
|
10387
|
-
this.
|
|
10456
|
+
this._present();
|
|
10388
10457
|
} catch (error2) {
|
|
10389
10458
|
delete this.el.dataset.zxOverlayOrder;
|
|
10390
10459
|
throw error2;
|
|
@@ -10400,9 +10469,14 @@ var Modal = class extends Component {
|
|
|
10400
10469
|
*/
|
|
10401
10470
|
close(result) {
|
|
10402
10471
|
if (!this.isOpen()) return this;
|
|
10403
|
-
|
|
10404
|
-
this.#
|
|
10405
|
-
|
|
10472
|
+
const presentation = this.#presentation;
|
|
10473
|
+
this.#pendingResults.set(presentation, { result });
|
|
10474
|
+
try {
|
|
10475
|
+
this._dismiss(typeof result === "string" ? result : "");
|
|
10476
|
+
} catch (error2) {
|
|
10477
|
+
this.#pendingResults.delete(presentation);
|
|
10478
|
+
throw error2;
|
|
10479
|
+
}
|
|
10406
10480
|
return this;
|
|
10407
10481
|
}
|
|
10408
10482
|
/**
|
|
@@ -10419,7 +10493,7 @@ var Modal = class extends Component {
|
|
|
10419
10493
|
* @returns {boolean}
|
|
10420
10494
|
*/
|
|
10421
10495
|
isOpen() {
|
|
10422
|
-
return this.
|
|
10496
|
+
return this._isShown();
|
|
10423
10497
|
}
|
|
10424
10498
|
/**
|
|
10425
10499
|
* Closes and removes the owned dialog. Safe to call repeatedly.
|
|
@@ -10428,7 +10502,7 @@ var Modal = class extends Component {
|
|
|
10428
10502
|
destroy() {
|
|
10429
10503
|
if (this.#destroying) return;
|
|
10430
10504
|
this.#destroying = true;
|
|
10431
|
-
if (this.isOpen()) this.
|
|
10505
|
+
if (this.isOpen()) this._dismiss();
|
|
10432
10506
|
super.destroy();
|
|
10433
10507
|
}
|
|
10434
10508
|
/** @param {string|number} width @returns {void} */
|
|
@@ -10493,7 +10567,7 @@ var Dialog = class _Dialog extends Modal {
|
|
|
10493
10567
|
/** @type {Element|null} */
|
|
10494
10568
|
#opener = null;
|
|
10495
10569
|
/**
|
|
10496
|
-
* Creates a structured dialog
|
|
10570
|
+
* Creates a structured dialog in the configured theme scope, or at document level when unscoped.
|
|
10497
10571
|
* @param {Element|string|null} [_target=null] Ignored; Dialog always owns its root.
|
|
10498
10572
|
* @param {DialogOptions} [options={}] Dialog options.
|
|
10499
10573
|
*/
|
|
@@ -15390,7 +15464,8 @@ var Dropdown = class extends Component {
|
|
|
15390
15464
|
offset: 4,
|
|
15391
15465
|
matchWidth: false,
|
|
15392
15466
|
openOn: "click",
|
|
15393
|
-
closeOnSelect: false
|
|
15467
|
+
closeOnSelect: false,
|
|
15468
|
+
scope: null
|
|
15394
15469
|
};
|
|
15395
15470
|
/** @type {Element} */
|
|
15396
15471
|
#anchor;
|
|
@@ -15409,6 +15484,7 @@ var Dropdown = class extends Component {
|
|
|
15409
15484
|
if (!resolved) throw new TypeError("Dropdown anchor could not be resolved");
|
|
15410
15485
|
super(null, options);
|
|
15411
15486
|
this.#anchor = resolved;
|
|
15487
|
+
overlayHost(this.options.scope ?? resolved).append(this.el);
|
|
15412
15488
|
this.#rememberAnchorAttribute("aria-expanded");
|
|
15413
15489
|
this.#rememberAnchorAttribute("aria-controls");
|
|
15414
15490
|
this.#anchor.setAttribute("aria-expanded", "false");
|
|
@@ -15431,7 +15507,6 @@ var Dropdown = class extends Component {
|
|
|
15431
15507
|
popover: "manual"
|
|
15432
15508
|
});
|
|
15433
15509
|
panel.dataset.state = "closed";
|
|
15434
|
-
document.body.append(panel);
|
|
15435
15510
|
return panel;
|
|
15436
15511
|
}
|
|
15437
15512
|
/**
|
|
@@ -15441,6 +15516,8 @@ var Dropdown = class extends Component {
|
|
|
15441
15516
|
*/
|
|
15442
15517
|
open() {
|
|
15443
15518
|
if (this.isOpen() || this.#destroyed) return this;
|
|
15519
|
+
const host = overlayHost(this.options.scope ?? this.#anchor);
|
|
15520
|
+
if (this.el.parentElement !== host) host.append(this.el);
|
|
15444
15521
|
this.#position = position(this.#anchor, this.el, {
|
|
15445
15522
|
placement: this.options.placement,
|
|
15446
15523
|
offset: Number(this.options.offset),
|
|
@@ -20100,7 +20177,8 @@ var Launcher = class extends Component {
|
|
|
20100
20177
|
emptyText: "No results",
|
|
20101
20178
|
loadingText: "Searching\u2026",
|
|
20102
20179
|
shortcut: "mod+k",
|
|
20103
|
-
hints: { move: "Move", open: "Open", close: "Close" }
|
|
20180
|
+
hints: { move: "Move", open: "Open", close: "Close" },
|
|
20181
|
+
scope: null
|
|
20104
20182
|
};
|
|
20105
20183
|
/**
|
|
20106
20184
|
* Creates an owned launcher dialog or enhances an existing `<dialog>` target.
|
|
@@ -20191,7 +20269,7 @@ var Launcher = class extends Component {
|
|
|
20191
20269
|
)
|
|
20192
20270
|
);
|
|
20193
20271
|
dialog.dataset.state = "closed";
|
|
20194
|
-
if (this._createdRoot)
|
|
20272
|
+
if (this._createdRoot) overlayHost(this.options.scope).append(dialog);
|
|
20195
20273
|
this.listen(input, "input", () => {
|
|
20196
20274
|
this._query = /** @type {HTMLInputElement} */
|
|
20197
20275
|
input.value;
|
|
@@ -20242,6 +20320,10 @@ var Launcher = class extends Component {
|
|
|
20242
20320
|
/** Opens the launcher and focuses/selects its query. @returns {this} @fires Launcher#open */
|
|
20243
20321
|
open() {
|
|
20244
20322
|
if (this.isOpen() || this._destroyed) return this;
|
|
20323
|
+
if (this._createdRoot) {
|
|
20324
|
+
const host = overlayHost(this.options.scope);
|
|
20325
|
+
if (this.el.parentElement !== host) host.append(this.el);
|
|
20326
|
+
}
|
|
20245
20327
|
this.el.showModal();
|
|
20246
20328
|
this.el.dataset.state = "open";
|
|
20247
20329
|
this.refs.input.setAttribute("aria-expanded", "true");
|
|
@@ -21120,6 +21202,7 @@ var Tooltip = class extends Component {
|
|
|
21120
21202
|
if (!resolved) throw new TypeError("Tooltip anchor could not be resolved");
|
|
21121
21203
|
super(null, options);
|
|
21122
21204
|
this.#anchor = resolved;
|
|
21205
|
+
overlayHost(resolved).append(this.el);
|
|
21123
21206
|
this.#content = this.options.content;
|
|
21124
21207
|
this.#disabled = Boolean(this.options.disabled);
|
|
21125
21208
|
this.#describedBy = resolved.getAttribute("aria-describedby");
|
|
@@ -21180,7 +21263,6 @@ var Tooltip = class extends Component {
|
|
|
21180
21263
|
popover: "manual"
|
|
21181
21264
|
});
|
|
21182
21265
|
panel.dataset.state = "closed";
|
|
21183
|
-
document.body.append(panel);
|
|
21184
21266
|
return panel;
|
|
21185
21267
|
}
|
|
21186
21268
|
/**
|
|
@@ -21192,6 +21274,8 @@ var Tooltip = class extends Component {
|
|
|
21192
21274
|
show() {
|
|
21193
21275
|
if (this.#destroyed || this.#disabled || this.isOpen()) return this;
|
|
21194
21276
|
this.#cancelTimers();
|
|
21277
|
+
const host = overlayHost(this.#anchor);
|
|
21278
|
+
if (this.el.parentElement !== host) host.append(this.el);
|
|
21195
21279
|
const node = resolveContent(this.#content);
|
|
21196
21280
|
if (node === null) return this;
|
|
21197
21281
|
this.el.replaceChildren(node);
|
|
@@ -22638,8 +22722,8 @@ var Message = class _Message extends Component {
|
|
|
22638
22722
|
closable: true,
|
|
22639
22723
|
maxVisible: 5
|
|
22640
22724
|
};
|
|
22641
|
-
/** @type {Message
|
|
22642
|
-
static #floating =
|
|
22725
|
+
/** @type {WeakMap<Element, Message>} */
|
|
22726
|
+
static #floating = /* @__PURE__ */ new WeakMap();
|
|
22643
22727
|
/** @returns {HTMLElement} */
|
|
22644
22728
|
render() {
|
|
22645
22729
|
const created = !this.el;
|
|
@@ -22718,15 +22802,16 @@ var Message = class _Message extends Component {
|
|
|
22718
22802
|
* @returns {MessageHandle}
|
|
22719
22803
|
*/
|
|
22720
22804
|
static show(msg, options = {}) {
|
|
22721
|
-
return this.#floatingRegion().show(msg, options);
|
|
22805
|
+
return this.#floatingRegion(options.scope).show(msg, options);
|
|
22722
22806
|
}
|
|
22723
22807
|
/**
|
|
22724
22808
|
* Shows a floating progress status.
|
|
22725
22809
|
* @param {string} text Initial status text.
|
|
22810
|
+
* @param {{scope?: Element|string|null}} [options={}] Floating-region scope.
|
|
22726
22811
|
* @returns {ProgressHandle}
|
|
22727
22812
|
*/
|
|
22728
|
-
static progress(text4) {
|
|
22729
|
-
return this.#floatingRegion()._progress(text4);
|
|
22813
|
+
static progress(text4, options = {}) {
|
|
22814
|
+
return this.#floatingRegion(options.scope)._progress(text4);
|
|
22730
22815
|
}
|
|
22731
22816
|
/** @returns {void} */
|
|
22732
22817
|
destroy() {
|
|
@@ -22904,19 +22989,22 @@ var Message = class _Message extends Component {
|
|
|
22904
22989
|
this._entries.delete(entry);
|
|
22905
22990
|
this._queue.remove(entry);
|
|
22906
22991
|
}
|
|
22907
|
-
/** @returns {Message} */
|
|
22908
|
-
static #floatingRegion() {
|
|
22909
|
-
|
|
22992
|
+
/** @param {Element|string|null|undefined} scope @returns {Message} */
|
|
22993
|
+
static #floatingRegion(scope2) {
|
|
22994
|
+
const host = overlayHost(scope2 ?? null);
|
|
22995
|
+
const existing = this.#floating.get(host);
|
|
22996
|
+
if (existing) return existing;
|
|
22910
22997
|
const region = h("div", {
|
|
22911
22998
|
class: "zx-message-region",
|
|
22912
22999
|
popover: "manual",
|
|
22913
23000
|
role: "status",
|
|
22914
23001
|
ariaLive: "polite"
|
|
22915
23002
|
});
|
|
22916
|
-
|
|
22917
|
-
|
|
23003
|
+
host.append(region);
|
|
23004
|
+
const floating = new _Message(region);
|
|
23005
|
+
this.#floating.set(host, floating);
|
|
22918
23006
|
if (typeof region.showPopover === "function") region.showPopover();
|
|
22919
|
-
return
|
|
23007
|
+
return floating;
|
|
22920
23008
|
}
|
|
22921
23009
|
};
|
|
22922
23010
|
function normalizeKind3(value) {
|
|
@@ -23004,7 +23092,6 @@ var Sheet = class extends Dialog {
|
|
|
23004
23092
|
constructor(_target = null, options = {}) {
|
|
23005
23093
|
super(null, options);
|
|
23006
23094
|
this._dock = null;
|
|
23007
|
-
this._handoff = false;
|
|
23008
23095
|
this.setSide(this.options.side);
|
|
23009
23096
|
this.el.dataset.backdrop = BACKDROPS.has(this.options.backdrop) ? this.options.backdrop : "dim";
|
|
23010
23097
|
this.el.dataset.modality = modality(this.options.modal);
|
|
@@ -23179,7 +23266,7 @@ var Sheet = class extends Dialog {
|
|
|
23179
23266
|
* @returns {Element}
|
|
23180
23267
|
*/
|
|
23181
23268
|
mountTarget() {
|
|
23182
|
-
return this._dock?.el ??
|
|
23269
|
+
return this._dock?.el ?? super.mountTarget();
|
|
23183
23270
|
}
|
|
23184
23271
|
/**
|
|
23185
23272
|
* Reports whether a dock currently owns this sheet's positioning.
|
|
@@ -23205,35 +23292,23 @@ var Sheet = class extends Dialog {
|
|
|
23205
23292
|
/**
|
|
23206
23293
|
* Moves the dialog to its current mount and, when it was open, reopens it there.
|
|
23207
23294
|
*
|
|
23208
|
-
* The close is unavoidable — a dialog cannot cross between
|
|
23209
|
-
*
|
|
23210
|
-
* `open()` so no lifecycle event is emitted for what is only a change of address.
|
|
23295
|
+
* The close is unavoidable — a dialog cannot cross between presentation layers while open —
|
|
23296
|
+
* but it is invisible: Modal's presentation generation drops the stale event, and reopening
|
|
23297
|
+
* bypasses `open()` so no lifecycle event is emitted for what is only a change of address.
|
|
23211
23298
|
* @returns {void}
|
|
23212
23299
|
*/
|
|
23213
23300
|
_rehost() {
|
|
23214
23301
|
const wasOpen = this.isOpen();
|
|
23215
|
-
if (wasOpen)
|
|
23216
|
-
this._handoff = true;
|
|
23217
|
-
this.el.close();
|
|
23218
|
-
}
|
|
23302
|
+
if (wasOpen) this._dismiss();
|
|
23219
23303
|
this.mountTarget().append(this.el);
|
|
23220
23304
|
if (!wasOpen) return;
|
|
23221
23305
|
this.el.returnValue = "";
|
|
23222
|
-
this.
|
|
23306
|
+
this._present();
|
|
23223
23307
|
this.el.dataset.state = "open";
|
|
23224
23308
|
if (this._dock) delete /** @type {HTMLElement} */
|
|
23225
23309
|
this.el.dataset.zxOverlayOrder;
|
|
23226
23310
|
else this.el.dataset.zxOverlayOrder = String(nextOverlayOrder3());
|
|
23227
23311
|
}
|
|
23228
|
-
/**
|
|
23229
|
-
* Drops the stale `close` a re-hosting handoff leaves behind.
|
|
23230
|
-
* @returns {boolean}
|
|
23231
|
-
*/
|
|
23232
|
-
_isRealClose() {
|
|
23233
|
-
if (!this._handoff) return true;
|
|
23234
|
-
this._handoff = false;
|
|
23235
|
-
return false;
|
|
23236
|
-
}
|
|
23237
23312
|
/**
|
|
23238
23313
|
* Opens the sheet, trapping focus first where the modality asks for it.
|
|
23239
23314
|
* @returns {this}
|
|
@@ -23314,10 +23389,38 @@ var Sheet = class extends Dialog {
|
|
|
23314
23389
|
*/
|
|
23315
23390
|
_show() {
|
|
23316
23391
|
if (this.options.modal === true && !this._dock) {
|
|
23392
|
+
this.el.removeAttribute("popover");
|
|
23393
|
+
this.el.removeAttribute("aria-modal");
|
|
23317
23394
|
super._show();
|
|
23318
23395
|
return;
|
|
23319
23396
|
}
|
|
23320
|
-
this.el.
|
|
23397
|
+
this.el.setAttribute("aria-modal", "false");
|
|
23398
|
+
if (this._dock) {
|
|
23399
|
+
this.el.removeAttribute("popover");
|
|
23400
|
+
this.el.show();
|
|
23401
|
+
return;
|
|
23402
|
+
}
|
|
23403
|
+
this.el.setAttribute("popover", "manual");
|
|
23404
|
+
this.el.showPopover();
|
|
23405
|
+
}
|
|
23406
|
+
/**
|
|
23407
|
+
* Hides a native dialog or a non-modal Sheet promoted through the popover top layer.
|
|
23408
|
+
* @param {string} [result=''] Native string return value.
|
|
23409
|
+
* @param {number} [presentation] Presentation generation being hidden.
|
|
23410
|
+
* @returns {void}
|
|
23411
|
+
*/
|
|
23412
|
+
_hide(result = "", presentation) {
|
|
23413
|
+
if (!this.el.matches(":popover-open")) {
|
|
23414
|
+
super._hide(result, presentation);
|
|
23415
|
+
return;
|
|
23416
|
+
}
|
|
23417
|
+
this.el.returnValue = result;
|
|
23418
|
+
this.el.hidePopover();
|
|
23419
|
+
queueMicrotask(() => this._settleClose(presentation));
|
|
23420
|
+
}
|
|
23421
|
+
/** @returns {boolean} */
|
|
23422
|
+
_isShown() {
|
|
23423
|
+
return this.el.matches(":popover-open") || super._isShown();
|
|
23321
23424
|
}
|
|
23322
23425
|
/**
|
|
23323
23426
|
* Releases the focus trap and the owned dialog.
|
|
@@ -23642,7 +23745,11 @@ var ContextMenu = class extends Component {
|
|
|
23642
23745
|
super(null, options);
|
|
23643
23746
|
this.#target = resolved;
|
|
23644
23747
|
document.body.append(this.el);
|
|
23645
|
-
this.#dropdown = new Dropdown(this.el, {
|
|
23748
|
+
this.#dropdown = new Dropdown(this.el, {
|
|
23749
|
+
openOn: "manual",
|
|
23750
|
+
placement: "bottom-start",
|
|
23751
|
+
scope: resolved
|
|
23752
|
+
});
|
|
23646
23753
|
this.#panel = this.#dropdown.getPanel();
|
|
23647
23754
|
this.#panel.classList.add("zx-context-menu");
|
|
23648
23755
|
this.#panel.setAttribute("role", "menu");
|
|
@@ -24496,7 +24603,11 @@ var Calendar = class extends Component {
|
|
|
24496
24603
|
}).sort(compareEvents);
|
|
24497
24604
|
const row2 = h(
|
|
24498
24605
|
"section",
|
|
24499
|
-
{
|
|
24606
|
+
{
|
|
24607
|
+
class: "zx-calendar__agenda-day",
|
|
24608
|
+
role: "row",
|
|
24609
|
+
dataset: { date: calendarDayKey(day) }
|
|
24610
|
+
},
|
|
24500
24611
|
h("button", {
|
|
24501
24612
|
type: "button",
|
|
24502
24613
|
class: "zx-calendar__agenda-heading",
|
|
@@ -24506,11 +24617,13 @@ var Calendar = class extends Component {
|
|
|
24506
24617
|
disabled: this.options.disabled
|
|
24507
24618
|
}, this._format(day, { weekday: "long", day: "numeric", month: "long" }))
|
|
24508
24619
|
);
|
|
24620
|
+
const entries = h("div", { class: "zx-calendar__agenda-events", role: "gridcell" });
|
|
24509
24621
|
if (!events.length) {
|
|
24510
|
-
|
|
24622
|
+
entries.append(h("p", { class: "zx-calendar__agenda-empty" }, this.msg("noEvents")));
|
|
24511
24623
|
} else {
|
|
24512
|
-
for (const event of events)
|
|
24624
|
+
for (const event of events) entries.append(this._eventElement(event, { variant: "agenda", day }));
|
|
24513
24625
|
}
|
|
24626
|
+
row2.append(entries);
|
|
24514
24627
|
grid2.append(row2);
|
|
24515
24628
|
}
|
|
24516
24629
|
return grid2;
|
|
@@ -24780,6 +24893,7 @@ var Calendar = class extends Component {
|
|
|
24780
24893
|
dataset: {
|
|
24781
24894
|
eventId: key,
|
|
24782
24895
|
variant: context.variant,
|
|
24896
|
+
allDay: event.allDay ? "true" : null,
|
|
24783
24897
|
draggable: this._canMove(event) ? "true" : null
|
|
24784
24898
|
},
|
|
24785
24899
|
style: event.color ? { "--zx-calendar-event-color": event.color } : null
|
|
@@ -25046,7 +25160,9 @@ var Calendar = class extends Component {
|
|
|
25046
25160
|
const item = this._eventById(control.dataset.eventId);
|
|
25047
25161
|
const action = control.dataset.eventAction === "resize" ? "resize" : "move";
|
|
25048
25162
|
if (!item || (action === "move" ? !this._canMove(item) : !this._canResize(item))) return;
|
|
25049
|
-
|
|
25163
|
+
event.preventDefault();
|
|
25164
|
+
this._capturePointer(event.pointerId);
|
|
25165
|
+
const offset = action === "move" ? this._dragOffsetForEvent(item, event.clientX, event.clientY) : null;
|
|
25050
25166
|
this._pointer = {
|
|
25051
25167
|
type: "event",
|
|
25052
25168
|
pointerId: event.pointerId,
|
|
@@ -25056,6 +25172,8 @@ var Calendar = class extends Component {
|
|
|
25056
25172
|
event: cloneCalendarEvent(item),
|
|
25057
25173
|
action,
|
|
25058
25174
|
control,
|
|
25175
|
+
timeOffsetMinutes: offset?.minutes ?? 0,
|
|
25176
|
+
dayOffset: offset?.days ?? 0,
|
|
25059
25177
|
moved: false
|
|
25060
25178
|
};
|
|
25061
25179
|
return;
|
|
@@ -25064,7 +25182,8 @@ var Calendar = class extends Component {
|
|
|
25064
25182
|
if (!slot || !this.options.selectable) return;
|
|
25065
25183
|
const date = this._dateFromTarget(slot);
|
|
25066
25184
|
if (!date) return;
|
|
25067
|
-
|
|
25185
|
+
event.preventDefault();
|
|
25186
|
+
this._capturePointer(event.pointerId);
|
|
25068
25187
|
this._pointer = {
|
|
25069
25188
|
type: "selection",
|
|
25070
25189
|
pointerId: event.pointerId,
|
|
@@ -25097,7 +25216,13 @@ var Calendar = class extends Component {
|
|
|
25097
25216
|
const wrapper = pointer.control.closest(".zx-calendar__event");
|
|
25098
25217
|
if (wrapper) {
|
|
25099
25218
|
wrapper.dataset.state = "dragging";
|
|
25100
|
-
|
|
25219
|
+
if (pointer.action === "resize") {
|
|
25220
|
+
wrapper.style.transform = "";
|
|
25221
|
+
const height = this._timedPreviewHeight(proposed);
|
|
25222
|
+
if (height) wrapper.style.blockSize = height;
|
|
25223
|
+
} else {
|
|
25224
|
+
wrapper.style.transform = `translate(${event.clientX - pointer.startX}px, ${event.clientY - pointer.startY}px)`;
|
|
25225
|
+
}
|
|
25101
25226
|
wrapper.dataset.preview = this._eventTime(proposed, proposed.start);
|
|
25102
25227
|
}
|
|
25103
25228
|
this._announce(this.msg(
|
|
@@ -25112,6 +25237,7 @@ var Calendar = class extends Component {
|
|
|
25112
25237
|
const pointer = this._pointer;
|
|
25113
25238
|
if (!pointer || pointer.pointerId !== event.pointerId) return;
|
|
25114
25239
|
this._pointer = null;
|
|
25240
|
+
this._releasePointerCapture(pointer.pointerId);
|
|
25115
25241
|
this._clearSelectionPreview();
|
|
25116
25242
|
if (!pointer.moved) return;
|
|
25117
25243
|
event.preventDefault();
|
|
@@ -25129,6 +25255,7 @@ var Calendar = class extends Component {
|
|
|
25129
25255
|
_cancelPointer(event) {
|
|
25130
25256
|
if (!this._pointer || this._pointer.pointerId !== event.pointerId) return;
|
|
25131
25257
|
const control = this._pointer.control;
|
|
25258
|
+
this._releasePointerCapture(this._pointer.pointerId);
|
|
25132
25259
|
this._pointer = null;
|
|
25133
25260
|
this._clearSelectionPreview();
|
|
25134
25261
|
control.closest?.(".zx-calendar__event")?.removeAttribute("data-state");
|
|
@@ -25136,13 +25263,14 @@ var Calendar = class extends Component {
|
|
|
25136
25263
|
}
|
|
25137
25264
|
/** @param {CalendarEvent} event @param {'move'|'resize'} action @param {number} x @param {number} y @returns {CalendarEvent|null} */
|
|
25138
25265
|
_proposalAtPoint(event, action, x, y) {
|
|
25139
|
-
const
|
|
25266
|
+
const resizeTimed = action === "resize" && !calendarEventSpansDays(event);
|
|
25267
|
+
const timed = this._timeAtPoint(x, y, resizeTimed ? event.start : null);
|
|
25140
25268
|
if (timed && !calendarEventSpansDays(event)) {
|
|
25141
25269
|
if (action === "move") {
|
|
25142
25270
|
const duration = event.end.getTime() - event.start.getTime();
|
|
25143
25271
|
const next3 = cloneCalendarEvent(event);
|
|
25144
|
-
next3.start = timed;
|
|
25145
|
-
next3.end = new Date(
|
|
25272
|
+
next3.start = addMinutes(timed, -Number(this._pointer?.timeOffsetMinutes ?? 0));
|
|
25273
|
+
next3.end = new Date(next3.start.getTime() + duration);
|
|
25146
25274
|
return next3;
|
|
25147
25275
|
}
|
|
25148
25276
|
const next2 = cloneCalendarEvent(event);
|
|
@@ -25151,33 +25279,36 @@ var Calendar = class extends Component {
|
|
|
25151
25279
|
}
|
|
25152
25280
|
const day = this._dayAtPoint(x, y);
|
|
25153
25281
|
if (!day) return null;
|
|
25154
|
-
const
|
|
25282
|
+
const targetDay = addCalendarDays(day, -Number(this._pointer?.dayOffset ?? 0));
|
|
25283
|
+
const difference = calendarDayDifference(startOfCalendarDay(event.start), targetDay);
|
|
25155
25284
|
if (action === "move") return shiftCalendarEvent(event, { days: difference, minutes: 0 });
|
|
25156
25285
|
const next = cloneCalendarEvent(event);
|
|
25157
25286
|
const endDay = addCalendarDays(day, 1);
|
|
25158
25287
|
next.end = new Date(endDay.getTime());
|
|
25159
25288
|
return next.end > next.start ? next : null;
|
|
25160
25289
|
}
|
|
25161
|
-
/** @param {number} x @param {number} y @returns {Date|null} */
|
|
25162
|
-
_timeAtPoint(x, y) {
|
|
25290
|
+
/** @param {number} x @param {number} y @param {Date|null} [fixedDay=null] @returns {Date|null} */
|
|
25291
|
+
_timeAtPoint(x, y, fixedDay = null) {
|
|
25163
25292
|
const slots = this.refs.body.querySelector(".zx-calendar__slots");
|
|
25164
25293
|
if (!slots) return null;
|
|
25165
25294
|
const rect = slots.getBoundingClientRect();
|
|
25166
|
-
|
|
25295
|
+
const scroller = slots.closest(".zx-calendar__time-scroller");
|
|
25296
|
+
const viewport = scroller?.getBoundingClientRect();
|
|
25297
|
+
const left = viewport ? Math.max(rect.left, viewport.left) : rect.left;
|
|
25298
|
+
const right = viewport ? Math.min(rect.right, viewport.right) : rect.right;
|
|
25299
|
+
const top = viewport ? Math.max(rect.top, viewport.top) : rect.top;
|
|
25300
|
+
const bottom = viewport ? Math.min(rect.bottom, viewport.bottom) : rect.bottom;
|
|
25301
|
+
if (x < left || x > right || y < top || y > bottom || rect.width <= 0 || rect.height <= 0) return null;
|
|
25167
25302
|
const columns = Number(slots.closest('[role="grid"]')?.getAttribute("aria-colcount")) || 1;
|
|
25168
25303
|
const rows = Number(slots.closest('[role="grid"]')?.getAttribute("aria-rowcount")) || 1;
|
|
25169
|
-
const
|
|
25304
|
+
const fixedColumn = fixedDay ? this._timeGridDayIndex(fixedDay) : -1;
|
|
25305
|
+
const column = fixedColumn >= 0 ? fixedColumn : Math.max(0, Math.min(columns - 1, Math.floor((x - rect.left) / rect.width * columns)));
|
|
25170
25306
|
const row2 = Math.max(0, Math.min(rows - 1, Math.floor((y - rect.top) / rect.height * rows)));
|
|
25171
25307
|
const target = slots.querySelector(`[data-row-index="${row2}"][data-day-index="${column}"]`);
|
|
25172
25308
|
return target ? this._dateFromTarget(target) : null;
|
|
25173
25309
|
}
|
|
25174
25310
|
/** @param {number} x @param {number} y @returns {Date|null} */
|
|
25175
25311
|
_dayAtPoint(x, y) {
|
|
25176
|
-
const elements = typeof document.elementsFromPoint === "function" ? document.elementsFromPoint(x, y) : [];
|
|
25177
|
-
for (const element of elements) {
|
|
25178
|
-
const date = element instanceof HTMLElement ? element.dataset.date : null;
|
|
25179
|
-
if (date) return parseDayKey(date);
|
|
25180
|
-
}
|
|
25181
25312
|
const allDay = this.refs.body.querySelector(".zx-calendar__all-day-grid");
|
|
25182
25313
|
if (allDay) {
|
|
25183
25314
|
const rect = allDay.getBoundingClientRect();
|
|
@@ -25187,8 +25318,72 @@ var Calendar = class extends Component {
|
|
|
25187
25318
|
return parseDayKey(cells[index]?.dataset.date);
|
|
25188
25319
|
}
|
|
25189
25320
|
}
|
|
25321
|
+
for (const monthEvents of this.refs.body.querySelectorAll(".zx-calendar__month-events")) {
|
|
25322
|
+
const rect = monthEvents.getBoundingClientRect();
|
|
25323
|
+
if (x < rect.left || x > rect.right || y < rect.top || y > rect.bottom || rect.width <= 0) continue;
|
|
25324
|
+
const start = parseDayKey(monthEvents.closest(".zx-calendar__month-week")?.dataset.weekStart);
|
|
25325
|
+
if (!start) continue;
|
|
25326
|
+
const index = Math.max(0, Math.min(6, Math.floor((x - rect.left) / rect.width * 7)));
|
|
25327
|
+
return addCalendarDays(start, index);
|
|
25328
|
+
}
|
|
25329
|
+
for (const agendaDay of this.refs.body.querySelectorAll(".zx-calendar__agenda-day")) {
|
|
25330
|
+
const rect = agendaDay.getBoundingClientRect();
|
|
25331
|
+
if (x < rect.left || x > rect.right || y < rect.top || y > rect.bottom) continue;
|
|
25332
|
+
return parseDayKey(agendaDay.dataset.date);
|
|
25333
|
+
}
|
|
25334
|
+
const elements = typeof document.elementsFromPoint === "function" ? document.elementsFromPoint(x, y) : [];
|
|
25335
|
+
for (const element of elements) {
|
|
25336
|
+
const dateTarget = element instanceof HTMLElement ? element.closest("[data-date]") : null;
|
|
25337
|
+
const date = dateTarget instanceof HTMLElement ? dateTarget.dataset.date : null;
|
|
25338
|
+
if (date) return parseDayKey(date);
|
|
25339
|
+
}
|
|
25190
25340
|
return null;
|
|
25191
25341
|
}
|
|
25342
|
+
/** @param {CalendarEvent} event @param {number} x @param {number} y @returns {{minutes: number, days: number}} */
|
|
25343
|
+
_dragOffsetForEvent(event, x, y) {
|
|
25344
|
+
if (!calendarEventSpansDays(event)) {
|
|
25345
|
+
const timed = this._timeAtPoint(x, y);
|
|
25346
|
+
if (timed) {
|
|
25347
|
+
const slot = normalizeSlot(this.options.slotDuration);
|
|
25348
|
+
const duration = Math.max(0, Math.round((event.end.getTime() - event.start.getTime()) / 6e4));
|
|
25349
|
+
const maxOffset = Math.max(0, duration - slot);
|
|
25350
|
+
const minutes = Math.round((timed.getTime() - event.start.getTime()) / 6e4);
|
|
25351
|
+
return { minutes: Math.max(0, Math.min(maxOffset, minutes)), days: 0 };
|
|
25352
|
+
}
|
|
25353
|
+
}
|
|
25354
|
+
const day = this._dayAtPoint(x, y);
|
|
25355
|
+
const days = day ? calendarDayDifference(startOfCalendarDay(event.start), day) : 0;
|
|
25356
|
+
return { minutes: 0, days: Math.max(0, days) };
|
|
25357
|
+
}
|
|
25358
|
+
/** @param {Date} day @returns {number} */
|
|
25359
|
+
_timeGridDayIndex(day) {
|
|
25360
|
+
const key = calendarDayKey(day);
|
|
25361
|
+
const headings = [...this.refs.body.querySelectorAll(".zx-calendar__day-heading")];
|
|
25362
|
+
return headings.findIndex((heading) => heading.dataset.date === key);
|
|
25363
|
+
}
|
|
25364
|
+
/** @param {CalendarEvent} event @returns {string|null} */
|
|
25365
|
+
_timedPreviewHeight(event) {
|
|
25366
|
+
const grid2 = this.refs.body.querySelector(".zx-calendar__time-grid");
|
|
25367
|
+
if (!grid2 || calendarEventSpansDays(event)) return null;
|
|
25368
|
+
const min = normalizeMinute(this.options.slotMinTime, 0);
|
|
25369
|
+
const max = normalizeMinute(this.options.slotMaxTime, 1440, true);
|
|
25370
|
+
const slot = normalizeSlot(this.options.slotDuration);
|
|
25371
|
+
const start = event.start.getHours() * 60 + event.start.getMinutes();
|
|
25372
|
+
const end = event.end.getHours() * 60 + event.end.getMinutes();
|
|
25373
|
+
const minutes = Math.max(slot, Math.min(max, end) - Math.max(min, start));
|
|
25374
|
+
return `${minutes / (max - min) * 100}%`;
|
|
25375
|
+
}
|
|
25376
|
+
/** @param {number} pointerId @returns {void} */
|
|
25377
|
+
_capturePointer(pointerId) {
|
|
25378
|
+
try {
|
|
25379
|
+
this.el.setPointerCapture?.(pointerId);
|
|
25380
|
+
} catch {
|
|
25381
|
+
}
|
|
25382
|
+
}
|
|
25383
|
+
/** @param {number} pointerId @returns {void} */
|
|
25384
|
+
_releasePointerCapture(pointerId) {
|
|
25385
|
+
if (this.el.hasPointerCapture?.(pointerId)) this.el.releasePointerCapture?.(pointerId);
|
|
25386
|
+
}
|
|
25192
25387
|
/** @param {Date} start @param {Date} end @returns {void} */
|
|
25193
25388
|
_previewSelection(start, end) {
|
|
25194
25389
|
const low = Math.min(start.getTime(), end.getTime());
|