@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.global.js
CHANGED
|
@@ -10527,6 +10527,15 @@ var zx = (() => {
|
|
|
10527
10527
|
element.replaceChildren(...state.children);
|
|
10528
10528
|
}
|
|
10529
10529
|
|
|
10530
|
+
// src/core/overlay-host.js
|
|
10531
|
+
var SCOPE_SELECTOR = ".zx-scope, [data-zx-theme], [data-zx-density], [data-zx-preset]";
|
|
10532
|
+
function overlayHost(source = null) {
|
|
10533
|
+
const context = source == null ? document.activeElement instanceof Element ? document.activeElement : null : resolveElement(source);
|
|
10534
|
+
const scope2 = context?.closest?.(SCOPE_SELECTOR) ?? null;
|
|
10535
|
+
if (!scope2 || scope2 === document.documentElement || scope2 === document.body) return document.body;
|
|
10536
|
+
return scope2;
|
|
10537
|
+
}
|
|
10538
|
+
|
|
10530
10539
|
// src/components/modal/modal.js
|
|
10531
10540
|
var Modal = class extends Component {
|
|
10532
10541
|
static cssName = "modal";
|
|
@@ -10536,13 +10545,17 @@ var zx = (() => {
|
|
|
10536
10545
|
width: "auto",
|
|
10537
10546
|
closable: true,
|
|
10538
10547
|
lightDismiss: false,
|
|
10539
|
-
destroyOnClose: false
|
|
10548
|
+
destroyOnClose: false,
|
|
10549
|
+
scope: null
|
|
10540
10550
|
};
|
|
10541
|
-
|
|
10542
|
-
#
|
|
10551
|
+
/** @type {Map<number, {result: unknown}>} */
|
|
10552
|
+
#pendingResults = /* @__PURE__ */ new Map();
|
|
10543
10553
|
#destroying = false;
|
|
10554
|
+
#presentation = 0;
|
|
10555
|
+
/** @type {number[]} */
|
|
10556
|
+
#nativeClosingPresentations = [];
|
|
10544
10557
|
/**
|
|
10545
|
-
* Creates a modal
|
|
10558
|
+
* Creates a modal in the configured theme scope, or at document level when none is present.
|
|
10546
10559
|
* @param {Element|string|null} [_target=null] Ignored; Modal always owns its root dialog.
|
|
10547
10560
|
* @param {ModalOptions} [options={}] Modal options.
|
|
10548
10561
|
*/
|
|
@@ -10555,14 +10568,7 @@ var zx = (() => {
|
|
|
10555
10568
|
if (!this.options.closable || cancelEvent.defaultPrevented) event.preventDefault();
|
|
10556
10569
|
});
|
|
10557
10570
|
this.listen(this.el, "close", () => {
|
|
10558
|
-
|
|
10559
|
-
this.el.dataset.state = "closed";
|
|
10560
|
-
delete this.el.dataset.zxOverlayOrder;
|
|
10561
|
-
const result = this.#hasPendingResult ? this.#pendingResult : this.el.returnValue || void 0;
|
|
10562
|
-
this.#pendingResult = void 0;
|
|
10563
|
-
this.#hasPendingResult = false;
|
|
10564
|
-
this.emit("close", { result });
|
|
10565
|
-
if (this.options.destroyOnClose && !this.#destroying) this.destroy();
|
|
10571
|
+
this._settleClose(this.#nativeClosingPresentations.shift());
|
|
10566
10572
|
});
|
|
10567
10573
|
this.listen(this.el, "click", (event) => {
|
|
10568
10574
|
if (!this.options.lightDismiss || event.target !== this.el || !isBackdropClick(this.el, event)) return;
|
|
@@ -10578,7 +10584,7 @@ var zx = (() => {
|
|
|
10578
10584
|
* @returns {Element}
|
|
10579
10585
|
*/
|
|
10580
10586
|
mountTarget() {
|
|
10581
|
-
return
|
|
10587
|
+
return overlayHost(this.options.scope);
|
|
10582
10588
|
}
|
|
10583
10589
|
/**
|
|
10584
10590
|
* Puts the dialog on screen. Overridden by subclasses that open non-modally.
|
|
@@ -10587,17 +10593,78 @@ var zx = (() => {
|
|
|
10587
10593
|
_show() {
|
|
10588
10594
|
this.el.showModal();
|
|
10589
10595
|
}
|
|
10596
|
+
/**
|
|
10597
|
+
* Removes the dialog from its current presentation layer.
|
|
10598
|
+
* Subclasses may replace native dialog presentation while preserving Modal lifecycle events.
|
|
10599
|
+
* @param {string} [result=''] Native string return value.
|
|
10600
|
+
* @param {number} [presentation=this.#presentation] Presentation generation being hidden.
|
|
10601
|
+
* @returns {void}
|
|
10602
|
+
*/
|
|
10603
|
+
_hide(result = "", presentation = this.#presentation) {
|
|
10604
|
+
this.#nativeClosingPresentations.push(presentation);
|
|
10605
|
+
try {
|
|
10606
|
+
this.el.close(result);
|
|
10607
|
+
} catch (error2) {
|
|
10608
|
+
this.#nativeClosingPresentations.pop();
|
|
10609
|
+
throw error2;
|
|
10610
|
+
}
|
|
10611
|
+
}
|
|
10612
|
+
/**
|
|
10613
|
+
* Shows a new presentation and gives it a generation of its own. Close events are queued by the
|
|
10614
|
+
* platform, so the generation lets an event from an earlier presentation expire harmlessly if
|
|
10615
|
+
* the same overlay has already reopened.
|
|
10616
|
+
* @returns {void}
|
|
10617
|
+
*/
|
|
10618
|
+
_present() {
|
|
10619
|
+
this._show();
|
|
10620
|
+
this.#presentation += 1;
|
|
10621
|
+
}
|
|
10622
|
+
/**
|
|
10623
|
+
* Hides the current presentation and records which generation its queued close event belongs to.
|
|
10624
|
+
* @param {string} [result=''] Native string return value.
|
|
10625
|
+
* @returns {void}
|
|
10626
|
+
*/
|
|
10627
|
+
_dismiss(result = "") {
|
|
10628
|
+
this._hide(result, this.#presentation);
|
|
10629
|
+
}
|
|
10630
|
+
/**
|
|
10631
|
+
* Reports whether the current presentation layer is visible.
|
|
10632
|
+
* @returns {boolean}
|
|
10633
|
+
*/
|
|
10634
|
+
_isShown() {
|
|
10635
|
+
return this.el.open;
|
|
10636
|
+
}
|
|
10590
10637
|
/**
|
|
10591
10638
|
* Whether an incoming `close` event is a real dismissal.
|
|
10592
10639
|
*
|
|
10593
|
-
*
|
|
10594
|
-
*
|
|
10595
|
-
*
|
|
10596
|
-
*
|
|
10597
|
-
* `destroyOnClose`. Returning false from an override drops it at the source instead.
|
|
10640
|
+
* `close` is dispatched in a queued task, not synchronously. By the time it arrives the overlay
|
|
10641
|
+
* may have reopened or crossed presentation layers, so only the event for the current hidden
|
|
10642
|
+
* generation may settle state, emit lifecycle events, or trigger `destroyOnClose`.
|
|
10643
|
+
* @param {number|undefined} closingPresentation Presentation that produced the event, if known.
|
|
10598
10644
|
* @returns {boolean}
|
|
10599
10645
|
*/
|
|
10600
|
-
_isRealClose() {
|
|
10646
|
+
_isRealClose(closingPresentation) {
|
|
10647
|
+
if (closingPresentation !== void 0 && closingPresentation !== this.#presentation) return false;
|
|
10648
|
+
return !this._isShown();
|
|
10649
|
+
}
|
|
10650
|
+
/**
|
|
10651
|
+
* Settles one presentation's close without allowing a queued event to invalidate a newer one.
|
|
10652
|
+
* Popover-based subclasses call this directly; native dialog events arrive through the listener.
|
|
10653
|
+
* @param {number|undefined} closingPresentation Presentation that was hidden, if known.
|
|
10654
|
+
* @returns {boolean} Whether this event closed the current presentation.
|
|
10655
|
+
*/
|
|
10656
|
+
_settleClose(closingPresentation) {
|
|
10657
|
+
if (!this._isRealClose(closingPresentation)) {
|
|
10658
|
+
if (closingPresentation !== void 0) this.#pendingResults.delete(closingPresentation);
|
|
10659
|
+
return false;
|
|
10660
|
+
}
|
|
10661
|
+
this.el.dataset.state = "closed";
|
|
10662
|
+
delete this.el.dataset.zxOverlayOrder;
|
|
10663
|
+
const pending = closingPresentation === void 0 ? void 0 : this.#pendingResults.get(closingPresentation);
|
|
10664
|
+
if (closingPresentation !== void 0) this.#pendingResults.delete(closingPresentation);
|
|
10665
|
+
const result = pending ? pending.result : this.el.returnValue || void 0;
|
|
10666
|
+
this.emit("close", { result });
|
|
10667
|
+
if (this.options.destroyOnClose && !this.#destroying) this.destroy();
|
|
10601
10668
|
return true;
|
|
10602
10669
|
}
|
|
10603
10670
|
/**
|
|
@@ -10622,10 +10689,12 @@ var zx = (() => {
|
|
|
10622
10689
|
*/
|
|
10623
10690
|
open() {
|
|
10624
10691
|
if (this.isOpen()) return this;
|
|
10692
|
+
const host = this.mountTarget();
|
|
10693
|
+
if (this.el.parentElement !== host) host.append(this.el);
|
|
10625
10694
|
this.el.dataset.zxOverlayOrder = String(nextOverlayOrder());
|
|
10626
10695
|
this.el.returnValue = "";
|
|
10627
10696
|
try {
|
|
10628
|
-
this.
|
|
10697
|
+
this._present();
|
|
10629
10698
|
} catch (error2) {
|
|
10630
10699
|
delete this.el.dataset.zxOverlayOrder;
|
|
10631
10700
|
throw error2;
|
|
@@ -10641,9 +10710,14 @@ var zx = (() => {
|
|
|
10641
10710
|
*/
|
|
10642
10711
|
close(result) {
|
|
10643
10712
|
if (!this.isOpen()) return this;
|
|
10644
|
-
|
|
10645
|
-
this.#
|
|
10646
|
-
|
|
10713
|
+
const presentation = this.#presentation;
|
|
10714
|
+
this.#pendingResults.set(presentation, { result });
|
|
10715
|
+
try {
|
|
10716
|
+
this._dismiss(typeof result === "string" ? result : "");
|
|
10717
|
+
} catch (error2) {
|
|
10718
|
+
this.#pendingResults.delete(presentation);
|
|
10719
|
+
throw error2;
|
|
10720
|
+
}
|
|
10647
10721
|
return this;
|
|
10648
10722
|
}
|
|
10649
10723
|
/**
|
|
@@ -10660,7 +10734,7 @@ var zx = (() => {
|
|
|
10660
10734
|
* @returns {boolean}
|
|
10661
10735
|
*/
|
|
10662
10736
|
isOpen() {
|
|
10663
|
-
return this.
|
|
10737
|
+
return this._isShown();
|
|
10664
10738
|
}
|
|
10665
10739
|
/**
|
|
10666
10740
|
* Closes and removes the owned dialog. Safe to call repeatedly.
|
|
@@ -10669,7 +10743,7 @@ var zx = (() => {
|
|
|
10669
10743
|
destroy() {
|
|
10670
10744
|
if (this.#destroying) return;
|
|
10671
10745
|
this.#destroying = true;
|
|
10672
|
-
if (this.isOpen()) this.
|
|
10746
|
+
if (this.isOpen()) this._dismiss();
|
|
10673
10747
|
super.destroy();
|
|
10674
10748
|
}
|
|
10675
10749
|
/** @param {string|number} width @returns {void} */
|
|
@@ -10734,7 +10808,7 @@ var zx = (() => {
|
|
|
10734
10808
|
/** @type {Element|null} */
|
|
10735
10809
|
#opener = null;
|
|
10736
10810
|
/**
|
|
10737
|
-
* Creates a structured dialog
|
|
10811
|
+
* Creates a structured dialog in the configured theme scope, or at document level when unscoped.
|
|
10738
10812
|
* @param {Element|string|null} [_target=null] Ignored; Dialog always owns its root.
|
|
10739
10813
|
* @param {DialogOptions} [options={}] Dialog options.
|
|
10740
10814
|
*/
|
|
@@ -15631,7 +15705,8 @@ var zx = (() => {
|
|
|
15631
15705
|
offset: 4,
|
|
15632
15706
|
matchWidth: false,
|
|
15633
15707
|
openOn: "click",
|
|
15634
|
-
closeOnSelect: false
|
|
15708
|
+
closeOnSelect: false,
|
|
15709
|
+
scope: null
|
|
15635
15710
|
};
|
|
15636
15711
|
/** @type {Element} */
|
|
15637
15712
|
#anchor;
|
|
@@ -15650,6 +15725,7 @@ var zx = (() => {
|
|
|
15650
15725
|
if (!resolved) throw new TypeError("Dropdown anchor could not be resolved");
|
|
15651
15726
|
super(null, options);
|
|
15652
15727
|
this.#anchor = resolved;
|
|
15728
|
+
overlayHost(this.options.scope ?? resolved).append(this.el);
|
|
15653
15729
|
this.#rememberAnchorAttribute("aria-expanded");
|
|
15654
15730
|
this.#rememberAnchorAttribute("aria-controls");
|
|
15655
15731
|
this.#anchor.setAttribute("aria-expanded", "false");
|
|
@@ -15672,7 +15748,6 @@ var zx = (() => {
|
|
|
15672
15748
|
popover: "manual"
|
|
15673
15749
|
});
|
|
15674
15750
|
panel.dataset.state = "closed";
|
|
15675
|
-
document.body.append(panel);
|
|
15676
15751
|
return panel;
|
|
15677
15752
|
}
|
|
15678
15753
|
/**
|
|
@@ -15682,6 +15757,8 @@ var zx = (() => {
|
|
|
15682
15757
|
*/
|
|
15683
15758
|
open() {
|
|
15684
15759
|
if (this.isOpen() || this.#destroyed) return this;
|
|
15760
|
+
const host = overlayHost(this.options.scope ?? this.#anchor);
|
|
15761
|
+
if (this.el.parentElement !== host) host.append(this.el);
|
|
15685
15762
|
this.#position = position(this.#anchor, this.el, {
|
|
15686
15763
|
placement: this.options.placement,
|
|
15687
15764
|
offset: Number(this.options.offset),
|
|
@@ -20341,7 +20418,8 @@ var zx = (() => {
|
|
|
20341
20418
|
emptyText: "No results",
|
|
20342
20419
|
loadingText: "Searching\u2026",
|
|
20343
20420
|
shortcut: "mod+k",
|
|
20344
|
-
hints: { move: "Move", open: "Open", close: "Close" }
|
|
20421
|
+
hints: { move: "Move", open: "Open", close: "Close" },
|
|
20422
|
+
scope: null
|
|
20345
20423
|
};
|
|
20346
20424
|
/**
|
|
20347
20425
|
* Creates an owned launcher dialog or enhances an existing `<dialog>` target.
|
|
@@ -20432,7 +20510,7 @@ var zx = (() => {
|
|
|
20432
20510
|
)
|
|
20433
20511
|
);
|
|
20434
20512
|
dialog.dataset.state = "closed";
|
|
20435
|
-
if (this._createdRoot)
|
|
20513
|
+
if (this._createdRoot) overlayHost(this.options.scope).append(dialog);
|
|
20436
20514
|
this.listen(input, "input", () => {
|
|
20437
20515
|
this._query = /** @type {HTMLInputElement} */
|
|
20438
20516
|
input.value;
|
|
@@ -20483,6 +20561,10 @@ var zx = (() => {
|
|
|
20483
20561
|
/** Opens the launcher and focuses/selects its query. @returns {this} @fires Launcher#open */
|
|
20484
20562
|
open() {
|
|
20485
20563
|
if (this.isOpen() || this._destroyed) return this;
|
|
20564
|
+
if (this._createdRoot) {
|
|
20565
|
+
const host = overlayHost(this.options.scope);
|
|
20566
|
+
if (this.el.parentElement !== host) host.append(this.el);
|
|
20567
|
+
}
|
|
20486
20568
|
this.el.showModal();
|
|
20487
20569
|
this.el.dataset.state = "open";
|
|
20488
20570
|
this.refs.input.setAttribute("aria-expanded", "true");
|
|
@@ -21361,6 +21443,7 @@ var zx = (() => {
|
|
|
21361
21443
|
if (!resolved) throw new TypeError("Tooltip anchor could not be resolved");
|
|
21362
21444
|
super(null, options);
|
|
21363
21445
|
this.#anchor = resolved;
|
|
21446
|
+
overlayHost(resolved).append(this.el);
|
|
21364
21447
|
this.#content = this.options.content;
|
|
21365
21448
|
this.#disabled = Boolean(this.options.disabled);
|
|
21366
21449
|
this.#describedBy = resolved.getAttribute("aria-describedby");
|
|
@@ -21421,7 +21504,6 @@ var zx = (() => {
|
|
|
21421
21504
|
popover: "manual"
|
|
21422
21505
|
});
|
|
21423
21506
|
panel.dataset.state = "closed";
|
|
21424
|
-
document.body.append(panel);
|
|
21425
21507
|
return panel;
|
|
21426
21508
|
}
|
|
21427
21509
|
/**
|
|
@@ -21433,6 +21515,8 @@ var zx = (() => {
|
|
|
21433
21515
|
show() {
|
|
21434
21516
|
if (this.#destroyed || this.#disabled || this.isOpen()) return this;
|
|
21435
21517
|
this.#cancelTimers();
|
|
21518
|
+
const host = overlayHost(this.#anchor);
|
|
21519
|
+
if (this.el.parentElement !== host) host.append(this.el);
|
|
21436
21520
|
const node = resolveContent(this.#content);
|
|
21437
21521
|
if (node === null) return this;
|
|
21438
21522
|
this.el.replaceChildren(node);
|
|
@@ -22879,8 +22963,8 @@ var zx = (() => {
|
|
|
22879
22963
|
closable: true,
|
|
22880
22964
|
maxVisible: 5
|
|
22881
22965
|
};
|
|
22882
|
-
/** @type {Message
|
|
22883
|
-
static #floating =
|
|
22966
|
+
/** @type {WeakMap<Element, Message>} */
|
|
22967
|
+
static #floating = /* @__PURE__ */ new WeakMap();
|
|
22884
22968
|
/** @returns {HTMLElement} */
|
|
22885
22969
|
render() {
|
|
22886
22970
|
const created = !this.el;
|
|
@@ -22959,15 +23043,16 @@ var zx = (() => {
|
|
|
22959
23043
|
* @returns {MessageHandle}
|
|
22960
23044
|
*/
|
|
22961
23045
|
static show(msg, options = {}) {
|
|
22962
|
-
return this.#floatingRegion().show(msg, options);
|
|
23046
|
+
return this.#floatingRegion(options.scope).show(msg, options);
|
|
22963
23047
|
}
|
|
22964
23048
|
/**
|
|
22965
23049
|
* Shows a floating progress status.
|
|
22966
23050
|
* @param {string} text Initial status text.
|
|
23051
|
+
* @param {{scope?: Element|string|null}} [options={}] Floating-region scope.
|
|
22967
23052
|
* @returns {ProgressHandle}
|
|
22968
23053
|
*/
|
|
22969
|
-
static progress(text4) {
|
|
22970
|
-
return this.#floatingRegion()._progress(text4);
|
|
23054
|
+
static progress(text4, options = {}) {
|
|
23055
|
+
return this.#floatingRegion(options.scope)._progress(text4);
|
|
22971
23056
|
}
|
|
22972
23057
|
/** @returns {void} */
|
|
22973
23058
|
destroy() {
|
|
@@ -23145,19 +23230,22 @@ var zx = (() => {
|
|
|
23145
23230
|
this._entries.delete(entry);
|
|
23146
23231
|
this._queue.remove(entry);
|
|
23147
23232
|
}
|
|
23148
|
-
/** @returns {Message} */
|
|
23149
|
-
static #floatingRegion() {
|
|
23150
|
-
|
|
23233
|
+
/** @param {Element|string|null|undefined} scope @returns {Message} */
|
|
23234
|
+
static #floatingRegion(scope2) {
|
|
23235
|
+
const host = overlayHost(scope2 ?? null);
|
|
23236
|
+
const existing = this.#floating.get(host);
|
|
23237
|
+
if (existing) return existing;
|
|
23151
23238
|
const region = h("div", {
|
|
23152
23239
|
class: "zx-message-region",
|
|
23153
23240
|
popover: "manual",
|
|
23154
23241
|
role: "status",
|
|
23155
23242
|
ariaLive: "polite"
|
|
23156
23243
|
});
|
|
23157
|
-
|
|
23158
|
-
|
|
23244
|
+
host.append(region);
|
|
23245
|
+
const floating = new _Message(region);
|
|
23246
|
+
this.#floating.set(host, floating);
|
|
23159
23247
|
if (typeof region.showPopover === "function") region.showPopover();
|
|
23160
|
-
return
|
|
23248
|
+
return floating;
|
|
23161
23249
|
}
|
|
23162
23250
|
};
|
|
23163
23251
|
function normalizeKind3(value) {
|
|
@@ -23245,7 +23333,6 @@ var zx = (() => {
|
|
|
23245
23333
|
constructor(_target = null, options = {}) {
|
|
23246
23334
|
super(null, options);
|
|
23247
23335
|
this._dock = null;
|
|
23248
|
-
this._handoff = false;
|
|
23249
23336
|
this.setSide(this.options.side);
|
|
23250
23337
|
this.el.dataset.backdrop = BACKDROPS.has(this.options.backdrop) ? this.options.backdrop : "dim";
|
|
23251
23338
|
this.el.dataset.modality = modality(this.options.modal);
|
|
@@ -23420,7 +23507,7 @@ var zx = (() => {
|
|
|
23420
23507
|
* @returns {Element}
|
|
23421
23508
|
*/
|
|
23422
23509
|
mountTarget() {
|
|
23423
|
-
return this._dock?.el ??
|
|
23510
|
+
return this._dock?.el ?? super.mountTarget();
|
|
23424
23511
|
}
|
|
23425
23512
|
/**
|
|
23426
23513
|
* Reports whether a dock currently owns this sheet's positioning.
|
|
@@ -23446,35 +23533,23 @@ var zx = (() => {
|
|
|
23446
23533
|
/**
|
|
23447
23534
|
* Moves the dialog to its current mount and, when it was open, reopens it there.
|
|
23448
23535
|
*
|
|
23449
|
-
* The close is unavoidable — a dialog cannot cross between
|
|
23450
|
-
*
|
|
23451
|
-
* `open()` so no lifecycle event is emitted for what is only a change of address.
|
|
23536
|
+
* The close is unavoidable — a dialog cannot cross between presentation layers while open —
|
|
23537
|
+
* but it is invisible: Modal's presentation generation drops the stale event, and reopening
|
|
23538
|
+
* bypasses `open()` so no lifecycle event is emitted for what is only a change of address.
|
|
23452
23539
|
* @returns {void}
|
|
23453
23540
|
*/
|
|
23454
23541
|
_rehost() {
|
|
23455
23542
|
const wasOpen = this.isOpen();
|
|
23456
|
-
if (wasOpen)
|
|
23457
|
-
this._handoff = true;
|
|
23458
|
-
this.el.close();
|
|
23459
|
-
}
|
|
23543
|
+
if (wasOpen) this._dismiss();
|
|
23460
23544
|
this.mountTarget().append(this.el);
|
|
23461
23545
|
if (!wasOpen) return;
|
|
23462
23546
|
this.el.returnValue = "";
|
|
23463
|
-
this.
|
|
23547
|
+
this._present();
|
|
23464
23548
|
this.el.dataset.state = "open";
|
|
23465
23549
|
if (this._dock) delete /** @type {HTMLElement} */
|
|
23466
23550
|
this.el.dataset.zxOverlayOrder;
|
|
23467
23551
|
else this.el.dataset.zxOverlayOrder = String(nextOverlayOrder3());
|
|
23468
23552
|
}
|
|
23469
|
-
/**
|
|
23470
|
-
* Drops the stale `close` a re-hosting handoff leaves behind.
|
|
23471
|
-
* @returns {boolean}
|
|
23472
|
-
*/
|
|
23473
|
-
_isRealClose() {
|
|
23474
|
-
if (!this._handoff) return true;
|
|
23475
|
-
this._handoff = false;
|
|
23476
|
-
return false;
|
|
23477
|
-
}
|
|
23478
23553
|
/**
|
|
23479
23554
|
* Opens the sheet, trapping focus first where the modality asks for it.
|
|
23480
23555
|
* @returns {this}
|
|
@@ -23555,10 +23630,38 @@ var zx = (() => {
|
|
|
23555
23630
|
*/
|
|
23556
23631
|
_show() {
|
|
23557
23632
|
if (this.options.modal === true && !this._dock) {
|
|
23633
|
+
this.el.removeAttribute("popover");
|
|
23634
|
+
this.el.removeAttribute("aria-modal");
|
|
23558
23635
|
super._show();
|
|
23559
23636
|
return;
|
|
23560
23637
|
}
|
|
23561
|
-
this.el.
|
|
23638
|
+
this.el.setAttribute("aria-modal", "false");
|
|
23639
|
+
if (this._dock) {
|
|
23640
|
+
this.el.removeAttribute("popover");
|
|
23641
|
+
this.el.show();
|
|
23642
|
+
return;
|
|
23643
|
+
}
|
|
23644
|
+
this.el.setAttribute("popover", "manual");
|
|
23645
|
+
this.el.showPopover();
|
|
23646
|
+
}
|
|
23647
|
+
/**
|
|
23648
|
+
* Hides a native dialog or a non-modal Sheet promoted through the popover top layer.
|
|
23649
|
+
* @param {string} [result=''] Native string return value.
|
|
23650
|
+
* @param {number} [presentation] Presentation generation being hidden.
|
|
23651
|
+
* @returns {void}
|
|
23652
|
+
*/
|
|
23653
|
+
_hide(result = "", presentation) {
|
|
23654
|
+
if (!this.el.matches(":popover-open")) {
|
|
23655
|
+
super._hide(result, presentation);
|
|
23656
|
+
return;
|
|
23657
|
+
}
|
|
23658
|
+
this.el.returnValue = result;
|
|
23659
|
+
this.el.hidePopover();
|
|
23660
|
+
queueMicrotask(() => this._settleClose(presentation));
|
|
23661
|
+
}
|
|
23662
|
+
/** @returns {boolean} */
|
|
23663
|
+
_isShown() {
|
|
23664
|
+
return this.el.matches(":popover-open") || super._isShown();
|
|
23562
23665
|
}
|
|
23563
23666
|
/**
|
|
23564
23667
|
* Releases the focus trap and the owned dialog.
|
|
@@ -23883,7 +23986,11 @@ var zx = (() => {
|
|
|
23883
23986
|
super(null, options);
|
|
23884
23987
|
this.#target = resolved;
|
|
23885
23988
|
document.body.append(this.el);
|
|
23886
|
-
this.#dropdown = new Dropdown(this.el, {
|
|
23989
|
+
this.#dropdown = new Dropdown(this.el, {
|
|
23990
|
+
openOn: "manual",
|
|
23991
|
+
placement: "bottom-start",
|
|
23992
|
+
scope: resolved
|
|
23993
|
+
});
|
|
23887
23994
|
this.#panel = this.#dropdown.getPanel();
|
|
23888
23995
|
this.#panel.classList.add("zx-context-menu");
|
|
23889
23996
|
this.#panel.setAttribute("role", "menu");
|
|
@@ -24737,7 +24844,11 @@ var zx = (() => {
|
|
|
24737
24844
|
}).sort(compareEvents);
|
|
24738
24845
|
const row2 = h(
|
|
24739
24846
|
"section",
|
|
24740
|
-
{
|
|
24847
|
+
{
|
|
24848
|
+
class: "zx-calendar__agenda-day",
|
|
24849
|
+
role: "row",
|
|
24850
|
+
dataset: { date: calendarDayKey(day) }
|
|
24851
|
+
},
|
|
24741
24852
|
h("button", {
|
|
24742
24853
|
type: "button",
|
|
24743
24854
|
class: "zx-calendar__agenda-heading",
|
|
@@ -24747,11 +24858,13 @@ var zx = (() => {
|
|
|
24747
24858
|
disabled: this.options.disabled
|
|
24748
24859
|
}, this._format(day, { weekday: "long", day: "numeric", month: "long" }))
|
|
24749
24860
|
);
|
|
24861
|
+
const entries = h("div", { class: "zx-calendar__agenda-events", role: "gridcell" });
|
|
24750
24862
|
if (!events.length) {
|
|
24751
|
-
|
|
24863
|
+
entries.append(h("p", { class: "zx-calendar__agenda-empty" }, this.msg("noEvents")));
|
|
24752
24864
|
} else {
|
|
24753
|
-
for (const event of events)
|
|
24865
|
+
for (const event of events) entries.append(this._eventElement(event, { variant: "agenda", day }));
|
|
24754
24866
|
}
|
|
24867
|
+
row2.append(entries);
|
|
24755
24868
|
grid2.append(row2);
|
|
24756
24869
|
}
|
|
24757
24870
|
return grid2;
|
|
@@ -25021,6 +25134,7 @@ var zx = (() => {
|
|
|
25021
25134
|
dataset: {
|
|
25022
25135
|
eventId: key,
|
|
25023
25136
|
variant: context.variant,
|
|
25137
|
+
allDay: event.allDay ? "true" : null,
|
|
25024
25138
|
draggable: this._canMove(event) ? "true" : null
|
|
25025
25139
|
},
|
|
25026
25140
|
style: event.color ? { "--zx-calendar-event-color": event.color } : null
|
|
@@ -25287,7 +25401,9 @@ var zx = (() => {
|
|
|
25287
25401
|
const item = this._eventById(control.dataset.eventId);
|
|
25288
25402
|
const action = control.dataset.eventAction === "resize" ? "resize" : "move";
|
|
25289
25403
|
if (!item || (action === "move" ? !this._canMove(item) : !this._canResize(item))) return;
|
|
25290
|
-
|
|
25404
|
+
event.preventDefault();
|
|
25405
|
+
this._capturePointer(event.pointerId);
|
|
25406
|
+
const offset = action === "move" ? this._dragOffsetForEvent(item, event.clientX, event.clientY) : null;
|
|
25291
25407
|
this._pointer = {
|
|
25292
25408
|
type: "event",
|
|
25293
25409
|
pointerId: event.pointerId,
|
|
@@ -25297,6 +25413,8 @@ var zx = (() => {
|
|
|
25297
25413
|
event: cloneCalendarEvent(item),
|
|
25298
25414
|
action,
|
|
25299
25415
|
control,
|
|
25416
|
+
timeOffsetMinutes: offset?.minutes ?? 0,
|
|
25417
|
+
dayOffset: offset?.days ?? 0,
|
|
25300
25418
|
moved: false
|
|
25301
25419
|
};
|
|
25302
25420
|
return;
|
|
@@ -25305,7 +25423,8 @@ var zx = (() => {
|
|
|
25305
25423
|
if (!slot || !this.options.selectable) return;
|
|
25306
25424
|
const date = this._dateFromTarget(slot);
|
|
25307
25425
|
if (!date) return;
|
|
25308
|
-
|
|
25426
|
+
event.preventDefault();
|
|
25427
|
+
this._capturePointer(event.pointerId);
|
|
25309
25428
|
this._pointer = {
|
|
25310
25429
|
type: "selection",
|
|
25311
25430
|
pointerId: event.pointerId,
|
|
@@ -25338,7 +25457,13 @@ var zx = (() => {
|
|
|
25338
25457
|
const wrapper = pointer.control.closest(".zx-calendar__event");
|
|
25339
25458
|
if (wrapper) {
|
|
25340
25459
|
wrapper.dataset.state = "dragging";
|
|
25341
|
-
|
|
25460
|
+
if (pointer.action === "resize") {
|
|
25461
|
+
wrapper.style.transform = "";
|
|
25462
|
+
const height = this._timedPreviewHeight(proposed);
|
|
25463
|
+
if (height) wrapper.style.blockSize = height;
|
|
25464
|
+
} else {
|
|
25465
|
+
wrapper.style.transform = `translate(${event.clientX - pointer.startX}px, ${event.clientY - pointer.startY}px)`;
|
|
25466
|
+
}
|
|
25342
25467
|
wrapper.dataset.preview = this._eventTime(proposed, proposed.start);
|
|
25343
25468
|
}
|
|
25344
25469
|
this._announce(this.msg(
|
|
@@ -25353,6 +25478,7 @@ var zx = (() => {
|
|
|
25353
25478
|
const pointer = this._pointer;
|
|
25354
25479
|
if (!pointer || pointer.pointerId !== event.pointerId) return;
|
|
25355
25480
|
this._pointer = null;
|
|
25481
|
+
this._releasePointerCapture(pointer.pointerId);
|
|
25356
25482
|
this._clearSelectionPreview();
|
|
25357
25483
|
if (!pointer.moved) return;
|
|
25358
25484
|
event.preventDefault();
|
|
@@ -25370,6 +25496,7 @@ var zx = (() => {
|
|
|
25370
25496
|
_cancelPointer(event) {
|
|
25371
25497
|
if (!this._pointer || this._pointer.pointerId !== event.pointerId) return;
|
|
25372
25498
|
const control = this._pointer.control;
|
|
25499
|
+
this._releasePointerCapture(this._pointer.pointerId);
|
|
25373
25500
|
this._pointer = null;
|
|
25374
25501
|
this._clearSelectionPreview();
|
|
25375
25502
|
control.closest?.(".zx-calendar__event")?.removeAttribute("data-state");
|
|
@@ -25377,13 +25504,14 @@ var zx = (() => {
|
|
|
25377
25504
|
}
|
|
25378
25505
|
/** @param {CalendarEvent} event @param {'move'|'resize'} action @param {number} x @param {number} y @returns {CalendarEvent|null} */
|
|
25379
25506
|
_proposalAtPoint(event, action, x, y) {
|
|
25380
|
-
const
|
|
25507
|
+
const resizeTimed = action === "resize" && !calendarEventSpansDays(event);
|
|
25508
|
+
const timed = this._timeAtPoint(x, y, resizeTimed ? event.start : null);
|
|
25381
25509
|
if (timed && !calendarEventSpansDays(event)) {
|
|
25382
25510
|
if (action === "move") {
|
|
25383
25511
|
const duration = event.end.getTime() - event.start.getTime();
|
|
25384
25512
|
const next3 = cloneCalendarEvent(event);
|
|
25385
|
-
next3.start = timed;
|
|
25386
|
-
next3.end = new Date(
|
|
25513
|
+
next3.start = addMinutes(timed, -Number(this._pointer?.timeOffsetMinutes ?? 0));
|
|
25514
|
+
next3.end = new Date(next3.start.getTime() + duration);
|
|
25387
25515
|
return next3;
|
|
25388
25516
|
}
|
|
25389
25517
|
const next2 = cloneCalendarEvent(event);
|
|
@@ -25392,33 +25520,36 @@ var zx = (() => {
|
|
|
25392
25520
|
}
|
|
25393
25521
|
const day = this._dayAtPoint(x, y);
|
|
25394
25522
|
if (!day) return null;
|
|
25395
|
-
const
|
|
25523
|
+
const targetDay = addCalendarDays(day, -Number(this._pointer?.dayOffset ?? 0));
|
|
25524
|
+
const difference = calendarDayDifference(startOfCalendarDay(event.start), targetDay);
|
|
25396
25525
|
if (action === "move") return shiftCalendarEvent(event, { days: difference, minutes: 0 });
|
|
25397
25526
|
const next = cloneCalendarEvent(event);
|
|
25398
25527
|
const endDay = addCalendarDays(day, 1);
|
|
25399
25528
|
next.end = new Date(endDay.getTime());
|
|
25400
25529
|
return next.end > next.start ? next : null;
|
|
25401
25530
|
}
|
|
25402
|
-
/** @param {number} x @param {number} y @returns {Date|null} */
|
|
25403
|
-
_timeAtPoint(x, y) {
|
|
25531
|
+
/** @param {number} x @param {number} y @param {Date|null} [fixedDay=null] @returns {Date|null} */
|
|
25532
|
+
_timeAtPoint(x, y, fixedDay = null) {
|
|
25404
25533
|
const slots = this.refs.body.querySelector(".zx-calendar__slots");
|
|
25405
25534
|
if (!slots) return null;
|
|
25406
25535
|
const rect = slots.getBoundingClientRect();
|
|
25407
|
-
|
|
25536
|
+
const scroller = slots.closest(".zx-calendar__time-scroller");
|
|
25537
|
+
const viewport = scroller?.getBoundingClientRect();
|
|
25538
|
+
const left = viewport ? Math.max(rect.left, viewport.left) : rect.left;
|
|
25539
|
+
const right = viewport ? Math.min(rect.right, viewport.right) : rect.right;
|
|
25540
|
+
const top = viewport ? Math.max(rect.top, viewport.top) : rect.top;
|
|
25541
|
+
const bottom = viewport ? Math.min(rect.bottom, viewport.bottom) : rect.bottom;
|
|
25542
|
+
if (x < left || x > right || y < top || y > bottom || rect.width <= 0 || rect.height <= 0) return null;
|
|
25408
25543
|
const columns = Number(slots.closest('[role="grid"]')?.getAttribute("aria-colcount")) || 1;
|
|
25409
25544
|
const rows = Number(slots.closest('[role="grid"]')?.getAttribute("aria-rowcount")) || 1;
|
|
25410
|
-
const
|
|
25545
|
+
const fixedColumn = fixedDay ? this._timeGridDayIndex(fixedDay) : -1;
|
|
25546
|
+
const column = fixedColumn >= 0 ? fixedColumn : Math.max(0, Math.min(columns - 1, Math.floor((x - rect.left) / rect.width * columns)));
|
|
25411
25547
|
const row2 = Math.max(0, Math.min(rows - 1, Math.floor((y - rect.top) / rect.height * rows)));
|
|
25412
25548
|
const target = slots.querySelector(`[data-row-index="${row2}"][data-day-index="${column}"]`);
|
|
25413
25549
|
return target ? this._dateFromTarget(target) : null;
|
|
25414
25550
|
}
|
|
25415
25551
|
/** @param {number} x @param {number} y @returns {Date|null} */
|
|
25416
25552
|
_dayAtPoint(x, y) {
|
|
25417
|
-
const elements = typeof document.elementsFromPoint === "function" ? document.elementsFromPoint(x, y) : [];
|
|
25418
|
-
for (const element of elements) {
|
|
25419
|
-
const date = element instanceof HTMLElement ? element.dataset.date : null;
|
|
25420
|
-
if (date) return parseDayKey(date);
|
|
25421
|
-
}
|
|
25422
25553
|
const allDay = this.refs.body.querySelector(".zx-calendar__all-day-grid");
|
|
25423
25554
|
if (allDay) {
|
|
25424
25555
|
const rect = allDay.getBoundingClientRect();
|
|
@@ -25428,8 +25559,72 @@ var zx = (() => {
|
|
|
25428
25559
|
return parseDayKey(cells[index]?.dataset.date);
|
|
25429
25560
|
}
|
|
25430
25561
|
}
|
|
25562
|
+
for (const monthEvents of this.refs.body.querySelectorAll(".zx-calendar__month-events")) {
|
|
25563
|
+
const rect = monthEvents.getBoundingClientRect();
|
|
25564
|
+
if (x < rect.left || x > rect.right || y < rect.top || y > rect.bottom || rect.width <= 0) continue;
|
|
25565
|
+
const start = parseDayKey(monthEvents.closest(".zx-calendar__month-week")?.dataset.weekStart);
|
|
25566
|
+
if (!start) continue;
|
|
25567
|
+
const index = Math.max(0, Math.min(6, Math.floor((x - rect.left) / rect.width * 7)));
|
|
25568
|
+
return addCalendarDays(start, index);
|
|
25569
|
+
}
|
|
25570
|
+
for (const agendaDay of this.refs.body.querySelectorAll(".zx-calendar__agenda-day")) {
|
|
25571
|
+
const rect = agendaDay.getBoundingClientRect();
|
|
25572
|
+
if (x < rect.left || x > rect.right || y < rect.top || y > rect.bottom) continue;
|
|
25573
|
+
return parseDayKey(agendaDay.dataset.date);
|
|
25574
|
+
}
|
|
25575
|
+
const elements = typeof document.elementsFromPoint === "function" ? document.elementsFromPoint(x, y) : [];
|
|
25576
|
+
for (const element of elements) {
|
|
25577
|
+
const dateTarget = element instanceof HTMLElement ? element.closest("[data-date]") : null;
|
|
25578
|
+
const date = dateTarget instanceof HTMLElement ? dateTarget.dataset.date : null;
|
|
25579
|
+
if (date) return parseDayKey(date);
|
|
25580
|
+
}
|
|
25431
25581
|
return null;
|
|
25432
25582
|
}
|
|
25583
|
+
/** @param {CalendarEvent} event @param {number} x @param {number} y @returns {{minutes: number, days: number}} */
|
|
25584
|
+
_dragOffsetForEvent(event, x, y) {
|
|
25585
|
+
if (!calendarEventSpansDays(event)) {
|
|
25586
|
+
const timed = this._timeAtPoint(x, y);
|
|
25587
|
+
if (timed) {
|
|
25588
|
+
const slot = normalizeSlot(this.options.slotDuration);
|
|
25589
|
+
const duration = Math.max(0, Math.round((event.end.getTime() - event.start.getTime()) / 6e4));
|
|
25590
|
+
const maxOffset = Math.max(0, duration - slot);
|
|
25591
|
+
const minutes = Math.round((timed.getTime() - event.start.getTime()) / 6e4);
|
|
25592
|
+
return { minutes: Math.max(0, Math.min(maxOffset, minutes)), days: 0 };
|
|
25593
|
+
}
|
|
25594
|
+
}
|
|
25595
|
+
const day = this._dayAtPoint(x, y);
|
|
25596
|
+
const days = day ? calendarDayDifference(startOfCalendarDay(event.start), day) : 0;
|
|
25597
|
+
return { minutes: 0, days: Math.max(0, days) };
|
|
25598
|
+
}
|
|
25599
|
+
/** @param {Date} day @returns {number} */
|
|
25600
|
+
_timeGridDayIndex(day) {
|
|
25601
|
+
const key = calendarDayKey(day);
|
|
25602
|
+
const headings = [...this.refs.body.querySelectorAll(".zx-calendar__day-heading")];
|
|
25603
|
+
return headings.findIndex((heading) => heading.dataset.date === key);
|
|
25604
|
+
}
|
|
25605
|
+
/** @param {CalendarEvent} event @returns {string|null} */
|
|
25606
|
+
_timedPreviewHeight(event) {
|
|
25607
|
+
const grid2 = this.refs.body.querySelector(".zx-calendar__time-grid");
|
|
25608
|
+
if (!grid2 || calendarEventSpansDays(event)) return null;
|
|
25609
|
+
const min = normalizeMinute(this.options.slotMinTime, 0);
|
|
25610
|
+
const max = normalizeMinute(this.options.slotMaxTime, 1440, true);
|
|
25611
|
+
const slot = normalizeSlot(this.options.slotDuration);
|
|
25612
|
+
const start = event.start.getHours() * 60 + event.start.getMinutes();
|
|
25613
|
+
const end = event.end.getHours() * 60 + event.end.getMinutes();
|
|
25614
|
+
const minutes = Math.max(slot, Math.min(max, end) - Math.max(min, start));
|
|
25615
|
+
return `${minutes / (max - min) * 100}%`;
|
|
25616
|
+
}
|
|
25617
|
+
/** @param {number} pointerId @returns {void} */
|
|
25618
|
+
_capturePointer(pointerId) {
|
|
25619
|
+
try {
|
|
25620
|
+
this.el.setPointerCapture?.(pointerId);
|
|
25621
|
+
} catch {
|
|
25622
|
+
}
|
|
25623
|
+
}
|
|
25624
|
+
/** @param {number} pointerId @returns {void} */
|
|
25625
|
+
_releasePointerCapture(pointerId) {
|
|
25626
|
+
if (this.el.hasPointerCapture?.(pointerId)) this.el.releasePointerCapture?.(pointerId);
|
|
25627
|
+
}
|
|
25433
25628
|
/** @param {Date} start @param {Date} end @returns {void} */
|
|
25434
25629
|
_previewSelection(start, end) {
|
|
25435
25630
|
const low = Math.min(start.getTime(), end.getTime());
|