@waggylabs/yumekit 0.4.3-beta.44 → 0.4.3-beta.46
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 +4 -0
- package/dist/components/y-appbar.js +15 -10
- package/dist/components/y-dialog/y-dialog.d.ts +1 -40
- package/dist/components/y-dialog.d.ts +1 -40
- package/dist/components/y-dialog.js +24 -8
- package/dist/components/y-drawer.js +11 -7
- package/dist/components/y-menu.js +16 -9
- package/dist/components/y-stack/y-stack.d.ts +4 -1
- package/dist/components/y-stack.d.ts +4 -1
- package/dist/components/y-stack.js +10 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.js +113 -28
- package/dist/modules/helpers.d.ts +18 -0
- package/dist/modules/helpers.js +58 -0
- package/dist/yumekit.min.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -46,6 +46,10 @@ Delete any empty sections before publishing.
|
|
|
46
46
|
- `y-tabs`: `leftIcon` and `rightIcon` properties on option objects — set a `<y-icon>` name directly in the options JSON to render icons without requiring extra child elements or named slots.
|
|
47
47
|
- `y-tabs`: `tab-content-{id}` slot — place any content (icons, badges, custom markup) inside the tab button itself by targeting this slot. Takes full precedence over `leftIcon`/`rightIcon` and the default label rendering.
|
|
48
48
|
|
|
49
|
+
### Fixed
|
|
50
|
+
|
|
51
|
+
- `y-dialog`, `y-drawer`, `y-menu`: anchor lookup now tolerates DOM insertion races. Previously, setting the `anchor` attribute before the anchor element was in the DOM (common with React portals and async / lazy mounts) left the component without a click listener. Resolution now tries `getElementById` synchronously, retries once on the next animation frame, and falls back to a `MutationObserver` that fires when the anchor appears. `y-dialog` also now cleans up its anchor listener on disconnect.
|
|
52
|
+
|
|
49
53
|
### Deprecated
|
|
50
54
|
|
|
51
55
|
- `y-tabs`: `left-icon-{id}` and `right-icon-{id}` slots — these slots still function but emit a `console.warn` directing users to the `leftIcon`/`rightIcon` option properties or the `tab-content-{id}` slot. They will be removed before the release of version 1.0.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { contrastTextColor } from '../../modules/helpers.js';
|
|
1
|
+
import { contrastTextColor, resolveAnchor } from '../../modules/helpers.js';
|
|
2
2
|
import { getIcon } from '../../icons/registry.js';
|
|
3
3
|
|
|
4
4
|
class YumeButton extends HTMLElement {
|
|
@@ -1100,19 +1100,24 @@ class YumeMenu extends HTMLElement {
|
|
|
1100
1100
|
|
|
1101
1101
|
_setupAnchor() {
|
|
1102
1102
|
const id = this.anchor;
|
|
1103
|
-
if (id)
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1103
|
+
if (!id) return;
|
|
1104
|
+
const root = this.getRootNode();
|
|
1105
|
+
this._anchorResolveDispose = resolveAnchor(
|
|
1106
|
+
this,
|
|
1107
|
+
id,
|
|
1108
|
+
(el) => {
|
|
1109
1109
|
this._anchorEl = el;
|
|
1110
|
-
|
|
1111
|
-
}
|
|
1112
|
-
|
|
1110
|
+
el.addEventListener("click", this._onAnchorClick);
|
|
1111
|
+
},
|
|
1112
|
+
root && root.getElementById ? root : document,
|
|
1113
|
+
);
|
|
1113
1114
|
}
|
|
1114
1115
|
|
|
1115
1116
|
_teardownAnchor() {
|
|
1117
|
+
if (this._anchorResolveDispose) {
|
|
1118
|
+
this._anchorResolveDispose();
|
|
1119
|
+
this._anchorResolveDispose = null;
|
|
1120
|
+
}
|
|
1116
1121
|
if (this._anchorEl) {
|
|
1117
1122
|
this._anchorEl.removeEventListener("click", this._onAnchorClick);
|
|
1118
1123
|
this._anchorEl = null;
|
|
@@ -1,40 +1 @@
|
|
|
1
|
-
|
|
2
|
-
static get observedAttributes(): string[];
|
|
3
|
-
_onKeyDown(e: any): void;
|
|
4
|
-
_onAnchorClick(): void;
|
|
5
|
-
connectedCallback(): void;
|
|
6
|
-
attributeChangedCallback(name: any, oldValue: any, newValue: any): void;
|
|
7
|
-
set animate(val: boolean);
|
|
8
|
-
/** Whether the dialog uses an entrance animation. */
|
|
9
|
-
get animate(): boolean;
|
|
10
|
-
set anchor(id: string);
|
|
11
|
-
/** The id of the element that toggles this dialog on click. */
|
|
12
|
-
get anchor(): string;
|
|
13
|
-
set closable(val: boolean);
|
|
14
|
-
/** Whether the dialog renders a close button in the header. */
|
|
15
|
-
get closable(): boolean;
|
|
16
|
-
set position(val: string);
|
|
17
|
-
/** Screen position of the dialog. One of: center (default), top-left, top-center, top-right, left, right, bottom-left, bottom-center, bottom-right. */
|
|
18
|
-
get position(): string;
|
|
19
|
-
set showBackdrop(val: boolean);
|
|
20
|
-
/** Whether to apply a blurred backdrop behind the dialog. */
|
|
21
|
-
get showBackdrop(): boolean;
|
|
22
|
-
set visible(val: boolean);
|
|
23
|
-
/** Whether the dialog is currently displayed. */
|
|
24
|
-
get visible(): boolean;
|
|
25
|
-
/** Closes the dialog. */
|
|
26
|
-
hide(): void;
|
|
27
|
-
/** Rebuilds the shadow DOM. */
|
|
28
|
-
render(): void;
|
|
29
|
-
/** Opens the dialog and focuses it. */
|
|
30
|
-
show(): void;
|
|
31
|
-
_buildCloseButton(): HTMLElement;
|
|
32
|
-
_buildDialog(): HTMLDivElement;
|
|
33
|
-
_buildHeader(): HTMLDivElement;
|
|
34
|
-
_buildSection(slotName: any, partName: any): HTMLDivElement;
|
|
35
|
-
_buildStyles(): HTMLStyleElement;
|
|
36
|
-
_focusDialog(): void;
|
|
37
|
-
_hideIfEmpty(wrapper: any): void;
|
|
38
|
-
_setupAnchor(): void;
|
|
39
|
-
_anchorEl: HTMLElement;
|
|
40
|
-
}
|
|
1
|
+
export {};
|
|
@@ -1,40 +1 @@
|
|
|
1
|
-
|
|
2
|
-
static get observedAttributes(): string[];
|
|
3
|
-
_onKeyDown(e: any): void;
|
|
4
|
-
_onAnchorClick(): void;
|
|
5
|
-
connectedCallback(): void;
|
|
6
|
-
attributeChangedCallback(name: any, oldValue: any, newValue: any): void;
|
|
7
|
-
set animate(val: boolean);
|
|
8
|
-
/** Whether the dialog uses an entrance animation. */
|
|
9
|
-
get animate(): boolean;
|
|
10
|
-
set anchor(id: string);
|
|
11
|
-
/** The id of the element that toggles this dialog on click. */
|
|
12
|
-
get anchor(): string;
|
|
13
|
-
set closable(val: boolean);
|
|
14
|
-
/** Whether the dialog renders a close button in the header. */
|
|
15
|
-
get closable(): boolean;
|
|
16
|
-
set position(val: string);
|
|
17
|
-
/** Screen position of the dialog. One of: center (default), top-left, top-center, top-right, left, right, bottom-left, bottom-center, bottom-right. */
|
|
18
|
-
get position(): string;
|
|
19
|
-
set showBackdrop(val: boolean);
|
|
20
|
-
/** Whether to apply a blurred backdrop behind the dialog. */
|
|
21
|
-
get showBackdrop(): boolean;
|
|
22
|
-
set visible(val: boolean);
|
|
23
|
-
/** Whether the dialog is currently displayed. */
|
|
24
|
-
get visible(): boolean;
|
|
25
|
-
/** Closes the dialog. */
|
|
26
|
-
hide(): void;
|
|
27
|
-
/** Rebuilds the shadow DOM. */
|
|
28
|
-
render(): void;
|
|
29
|
-
/** Opens the dialog and focuses it. */
|
|
30
|
-
show(): void;
|
|
31
|
-
_buildCloseButton(): HTMLElement;
|
|
32
|
-
_buildDialog(): HTMLDivElement;
|
|
33
|
-
_buildHeader(): HTMLDivElement;
|
|
34
|
-
_buildSection(slotName: any, partName: any): HTMLDivElement;
|
|
35
|
-
_buildStyles(): HTMLStyleElement;
|
|
36
|
-
_focusDialog(): void;
|
|
37
|
-
_hideIfEmpty(wrapper: any): void;
|
|
38
|
-
_setupAnchor(): void;
|
|
39
|
-
_anchorEl: HTMLElement;
|
|
40
|
-
}
|
|
1
|
+
export {};
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { resolveAnchor } from '../../modules/helpers.js';
|
|
2
|
+
|
|
1
3
|
class YumeDialog extends HTMLElement {
|
|
2
4
|
static get observedAttributes() {
|
|
3
5
|
return ["visible", "anchor", "closable", "show-backdrop", "animate", "position"];
|
|
@@ -20,10 +22,17 @@ class YumeDialog extends HTMLElement {
|
|
|
20
22
|
if (this.visible) this.show();
|
|
21
23
|
}
|
|
22
24
|
|
|
25
|
+
disconnectedCallback() {
|
|
26
|
+
this._teardownAnchor();
|
|
27
|
+
}
|
|
28
|
+
|
|
23
29
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
24
30
|
if (oldValue === newValue) return;
|
|
25
31
|
if (name === "visible") this.visible ? this.show() : this.hide();
|
|
26
|
-
if (name === "anchor")
|
|
32
|
+
if (name === "anchor") {
|
|
33
|
+
this._teardownAnchor();
|
|
34
|
+
this._setupAnchor();
|
|
35
|
+
}
|
|
27
36
|
if (name === "closable") this.render();
|
|
28
37
|
}
|
|
29
38
|
|
|
@@ -259,15 +268,22 @@ class YumeDialog extends HTMLElement {
|
|
|
259
268
|
}
|
|
260
269
|
|
|
261
270
|
_setupAnchor() {
|
|
271
|
+
const id = this.anchor;
|
|
272
|
+
if (!id) return;
|
|
273
|
+
this._anchorResolveDispose = resolveAnchor(this, id, (el) => {
|
|
274
|
+
this._anchorEl = el;
|
|
275
|
+
el.addEventListener("click", this._onAnchorClick);
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
_teardownAnchor() {
|
|
280
|
+
if (this._anchorResolveDispose) {
|
|
281
|
+
this._anchorResolveDispose();
|
|
282
|
+
this._anchorResolveDispose = null;
|
|
283
|
+
}
|
|
262
284
|
if (this._anchorEl) {
|
|
263
285
|
this._anchorEl.removeEventListener("click", this._onAnchorClick);
|
|
264
|
-
|
|
265
|
-
if (this.anchor) {
|
|
266
|
-
const el = document.getElementById(this.anchor);
|
|
267
|
-
if (el) {
|
|
268
|
-
this._anchorEl = el;
|
|
269
|
-
el.addEventListener("click", this._onAnchorClick);
|
|
270
|
-
}
|
|
286
|
+
this._anchorEl = null;
|
|
271
287
|
}
|
|
272
288
|
}
|
|
273
289
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { resolveAnchor } from '../../modules/helpers.js';
|
|
2
|
+
|
|
1
3
|
var ellipsisV = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <circle cx=\"12\" cy=\"5\" r=\"1.5\"/>\n <circle cx=\"12\" cy=\"12\" r=\"1.5\"/>\n <circle cx=\"12\" cy=\"19\" r=\"1.5\"/>\n</svg>\n";
|
|
2
4
|
|
|
3
5
|
var ellipsisH = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <circle cx=\"5\" cy=\"12\" r=\"1.5\"/>\n <circle cx=\"12\" cy=\"12\" r=\"1.5\"/>\n <circle cx=\"19\" cy=\"12\" r=\"1.5\"/>\n</svg>\n";
|
|
@@ -427,13 +429,11 @@ class YumeDrawer extends HTMLElement {
|
|
|
427
429
|
|
|
428
430
|
_setupAnchor() {
|
|
429
431
|
const id = this.anchor;
|
|
430
|
-
if (id)
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
}
|
|
436
|
-
}
|
|
432
|
+
if (!id) return;
|
|
433
|
+
this._anchorResolveDispose = resolveAnchor(this, id, (el) => {
|
|
434
|
+
this._anchorEl = el;
|
|
435
|
+
el.addEventListener("click", this._onAnchorClick);
|
|
436
|
+
});
|
|
437
437
|
}
|
|
438
438
|
|
|
439
439
|
_show() {
|
|
@@ -453,6 +453,10 @@ class YumeDrawer extends HTMLElement {
|
|
|
453
453
|
}
|
|
454
454
|
|
|
455
455
|
_teardownAnchor() {
|
|
456
|
+
if (this._anchorResolveDispose) {
|
|
457
|
+
this._anchorResolveDispose();
|
|
458
|
+
this._anchorResolveDispose = null;
|
|
459
|
+
}
|
|
456
460
|
if (this._anchorEl) {
|
|
457
461
|
this._anchorEl.removeEventListener("click", this._onAnchorClick);
|
|
458
462
|
this._anchorEl = null;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { resolveAnchor } from '../../modules/helpers.js';
|
|
2
|
+
|
|
1
3
|
var chevronRight = "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\">\n <polyline points=\"9 18 15 12 9 6\"/>\n</svg>\n";
|
|
2
4
|
|
|
3
5
|
class YumeMenu extends HTMLElement {
|
|
@@ -308,19 +310,24 @@ class YumeMenu extends HTMLElement {
|
|
|
308
310
|
|
|
309
311
|
_setupAnchor() {
|
|
310
312
|
const id = this.anchor;
|
|
311
|
-
if (id)
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
313
|
+
if (!id) return;
|
|
314
|
+
const root = this.getRootNode();
|
|
315
|
+
this._anchorResolveDispose = resolveAnchor(
|
|
316
|
+
this,
|
|
317
|
+
id,
|
|
318
|
+
(el) => {
|
|
317
319
|
this._anchorEl = el;
|
|
318
|
-
|
|
319
|
-
}
|
|
320
|
-
|
|
320
|
+
el.addEventListener("click", this._onAnchorClick);
|
|
321
|
+
},
|
|
322
|
+
root && root.getElementById ? root : document,
|
|
323
|
+
);
|
|
321
324
|
}
|
|
322
325
|
|
|
323
326
|
_teardownAnchor() {
|
|
327
|
+
if (this._anchorResolveDispose) {
|
|
328
|
+
this._anchorResolveDispose();
|
|
329
|
+
this._anchorResolveDispose = null;
|
|
330
|
+
}
|
|
324
331
|
if (this._anchorEl) {
|
|
325
332
|
this._anchorEl.removeEventListener("click", this._onAnchorClick);
|
|
326
333
|
this._anchorEl = null;
|
|
@@ -27,7 +27,10 @@ export class YumeStack extends HTMLElement {
|
|
|
27
27
|
/** Main-axis distribution (flex mode only). */
|
|
28
28
|
get justify(): string;
|
|
29
29
|
set responsive(val: boolean);
|
|
30
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* Auto-reduce columns at narrow container widths. Defaults to `true`;
|
|
32
|
+
* set `responsive="false"` to disable.
|
|
33
|
+
*/
|
|
31
34
|
get responsive(): boolean;
|
|
32
35
|
render(): void;
|
|
33
36
|
_container: Element;
|
|
@@ -27,7 +27,10 @@ export class YumeStack extends HTMLElement {
|
|
|
27
27
|
/** Main-axis distribution (flex mode only). */
|
|
28
28
|
get justify(): string;
|
|
29
29
|
set responsive(val: boolean);
|
|
30
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* Auto-reduce columns at narrow container widths. Defaults to `true`;
|
|
32
|
+
* set `responsive="false"` to disable.
|
|
33
|
+
*/
|
|
31
34
|
get responsive(): boolean;
|
|
32
35
|
render(): void;
|
|
33
36
|
_container: Element;
|
|
@@ -110,13 +110,19 @@ class YumeStack extends HTMLElement {
|
|
|
110
110
|
this.setAttribute("justify", val);
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
-
/**
|
|
113
|
+
/**
|
|
114
|
+
* Auto-reduce columns at narrow container widths. Defaults to `true`;
|
|
115
|
+
* set `responsive="false"` to disable.
|
|
116
|
+
*/
|
|
114
117
|
get responsive() {
|
|
115
|
-
return this.
|
|
118
|
+
return this.getAttribute("responsive") !== "false";
|
|
116
119
|
}
|
|
117
120
|
set responsive(val) {
|
|
118
|
-
if (val
|
|
119
|
-
|
|
121
|
+
if (val === false || val === "false") {
|
|
122
|
+
this.setAttribute("responsive", "false");
|
|
123
|
+
} else {
|
|
124
|
+
this.removeAttribute("responsive");
|
|
125
|
+
}
|
|
120
126
|
}
|
|
121
127
|
|
|
122
128
|
// -------------------------------------------------------------------------
|
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ export * from "./components/y-color/y-color.js";
|
|
|
11
11
|
export * from "./components/y-colorpicker/y-colorpicker.js";
|
|
12
12
|
export * from "./components/y-date/y-date.js";
|
|
13
13
|
export * from "./components/y-datepicker/y-datepicker.js";
|
|
14
|
+
export * from "./components/y-dialog/y-dialog.js";
|
|
14
15
|
export * from "./components/y-drawer/y-drawer.js";
|
|
15
16
|
export * from "./components/y-dock/y-dock.js";
|
|
16
17
|
export * from "./components/y-gallery/y-gallery.js";
|
package/dist/index.js
CHANGED
|
@@ -810,6 +810,64 @@ function manageLabelVisibility(labelWrapper) {
|
|
|
810
810
|
});
|
|
811
811
|
}
|
|
812
812
|
|
|
813
|
+
/**
|
|
814
|
+
* Resolve an anchor element by id for a web component, tolerating DOM insertion
|
|
815
|
+
* races. A synchronous lookup runs first; if it misses, one
|
|
816
|
+
* `requestAnimationFrame` retry covers the common React portal commit-ordering
|
|
817
|
+
* case, and a final `MutationObserver` fallback covers async / lazy mounts.
|
|
818
|
+
*
|
|
819
|
+
* The callback fires at most once. If the host disconnects before the anchor
|
|
820
|
+
* appears, resolution is aborted. Callers must invoke the returned dispose
|
|
821
|
+
* function on teardown (disconnectedCallback, attribute change, etc.) to
|
|
822
|
+
* cancel any pending rAF or observer.
|
|
823
|
+
*
|
|
824
|
+
* @param {HTMLElement} host — component instance; resolution aborts if it disconnects.
|
|
825
|
+
* @param {string} id — the anchor element's id.
|
|
826
|
+
* @param {(el: HTMLElement) => void} onFound — invoked once when the anchor resolves.
|
|
827
|
+
* @param {Document|ShadowRoot} [root=document] — root to search within.
|
|
828
|
+
* @returns {() => void} — dispose function.
|
|
829
|
+
*/
|
|
830
|
+
function resolveAnchor(host, id, onFound, root = document) {
|
|
831
|
+
let disposed = false;
|
|
832
|
+
let rafId = null;
|
|
833
|
+
let observer = null;
|
|
834
|
+
|
|
835
|
+
const dispose = () => {
|
|
836
|
+
disposed = true;
|
|
837
|
+
if (rafId != null) cancelAnimationFrame(rafId);
|
|
838
|
+
if (observer) observer.disconnect();
|
|
839
|
+
rafId = null;
|
|
840
|
+
observer = null;
|
|
841
|
+
};
|
|
842
|
+
|
|
843
|
+
const find = () => {
|
|
844
|
+
if (disposed) return true;
|
|
845
|
+
const el = root.getElementById
|
|
846
|
+
? root.getElementById(id)
|
|
847
|
+
: document.getElementById(id);
|
|
848
|
+
if (el) {
|
|
849
|
+
dispose();
|
|
850
|
+
onFound(el);
|
|
851
|
+
return true;
|
|
852
|
+
}
|
|
853
|
+
return false;
|
|
854
|
+
};
|
|
855
|
+
|
|
856
|
+
if (find()) return dispose;
|
|
857
|
+
if (!host.isConnected) return dispose;
|
|
858
|
+
|
|
859
|
+
rafId = requestAnimationFrame(() => {
|
|
860
|
+
rafId = null;
|
|
861
|
+
if (find()) return;
|
|
862
|
+
const target = root === document ? document.body : root;
|
|
863
|
+
if (!target) return;
|
|
864
|
+
observer = new MutationObserver(find);
|
|
865
|
+
observer.observe(target, { childList: true, subtree: true });
|
|
866
|
+
});
|
|
867
|
+
|
|
868
|
+
return dispose;
|
|
869
|
+
}
|
|
870
|
+
|
|
813
871
|
// =============================================================================
|
|
814
872
|
// Slot utilities
|
|
815
873
|
// =============================================================================
|
|
@@ -1931,19 +1989,24 @@ class YumeMenu extends HTMLElement {
|
|
|
1931
1989
|
|
|
1932
1990
|
_setupAnchor() {
|
|
1933
1991
|
const id = this.anchor;
|
|
1934
|
-
if (id)
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1992
|
+
if (!id) return;
|
|
1993
|
+
const root = this.getRootNode();
|
|
1994
|
+
this._anchorResolveDispose = resolveAnchor(
|
|
1995
|
+
this,
|
|
1996
|
+
id,
|
|
1997
|
+
(el) => {
|
|
1940
1998
|
this._anchorEl = el;
|
|
1941
|
-
|
|
1942
|
-
}
|
|
1943
|
-
|
|
1999
|
+
el.addEventListener("click", this._onAnchorClick);
|
|
2000
|
+
},
|
|
2001
|
+
root && root.getElementById ? root : document,
|
|
2002
|
+
);
|
|
1944
2003
|
}
|
|
1945
2004
|
|
|
1946
2005
|
_teardownAnchor() {
|
|
2006
|
+
if (this._anchorResolveDispose) {
|
|
2007
|
+
this._anchorResolveDispose();
|
|
2008
|
+
this._anchorResolveDispose = null;
|
|
2009
|
+
}
|
|
1947
2010
|
if (this._anchorEl) {
|
|
1948
2011
|
this._anchorEl.removeEventListener("click", this._onAnchorClick);
|
|
1949
2012
|
this._anchorEl = null;
|
|
@@ -9725,10 +9788,17 @@ class YumeDialog extends HTMLElement {
|
|
|
9725
9788
|
if (this.visible) this.show();
|
|
9726
9789
|
}
|
|
9727
9790
|
|
|
9791
|
+
disconnectedCallback() {
|
|
9792
|
+
this._teardownAnchor();
|
|
9793
|
+
}
|
|
9794
|
+
|
|
9728
9795
|
attributeChangedCallback(name, oldValue, newValue) {
|
|
9729
9796
|
if (oldValue === newValue) return;
|
|
9730
9797
|
if (name === "visible") this.visible ? this.show() : this.hide();
|
|
9731
|
-
if (name === "anchor")
|
|
9798
|
+
if (name === "anchor") {
|
|
9799
|
+
this._teardownAnchor();
|
|
9800
|
+
this._setupAnchor();
|
|
9801
|
+
}
|
|
9732
9802
|
if (name === "closable") this.render();
|
|
9733
9803
|
}
|
|
9734
9804
|
|
|
@@ -9964,15 +10034,22 @@ class YumeDialog extends HTMLElement {
|
|
|
9964
10034
|
}
|
|
9965
10035
|
|
|
9966
10036
|
_setupAnchor() {
|
|
10037
|
+
const id = this.anchor;
|
|
10038
|
+
if (!id) return;
|
|
10039
|
+
this._anchorResolveDispose = resolveAnchor(this, id, (el) => {
|
|
10040
|
+
this._anchorEl = el;
|
|
10041
|
+
el.addEventListener("click", this._onAnchorClick);
|
|
10042
|
+
});
|
|
10043
|
+
}
|
|
10044
|
+
|
|
10045
|
+
_teardownAnchor() {
|
|
10046
|
+
if (this._anchorResolveDispose) {
|
|
10047
|
+
this._anchorResolveDispose();
|
|
10048
|
+
this._anchorResolveDispose = null;
|
|
10049
|
+
}
|
|
9967
10050
|
if (this._anchorEl) {
|
|
9968
10051
|
this._anchorEl.removeEventListener("click", this._onAnchorClick);
|
|
9969
|
-
|
|
9970
|
-
if (this.anchor) {
|
|
9971
|
-
const el = document.getElementById(this.anchor);
|
|
9972
|
-
if (el) {
|
|
9973
|
-
this._anchorEl = el;
|
|
9974
|
-
el.addEventListener("click", this._onAnchorClick);
|
|
9975
|
-
}
|
|
10052
|
+
this._anchorEl = null;
|
|
9976
10053
|
}
|
|
9977
10054
|
}
|
|
9978
10055
|
}
|
|
@@ -10406,13 +10483,11 @@ class YumeDrawer extends HTMLElement {
|
|
|
10406
10483
|
|
|
10407
10484
|
_setupAnchor() {
|
|
10408
10485
|
const id = this.anchor;
|
|
10409
|
-
if (id)
|
|
10410
|
-
|
|
10411
|
-
|
|
10412
|
-
|
|
10413
|
-
|
|
10414
|
-
}
|
|
10415
|
-
}
|
|
10486
|
+
if (!id) return;
|
|
10487
|
+
this._anchorResolveDispose = resolveAnchor(this, id, (el) => {
|
|
10488
|
+
this._anchorEl = el;
|
|
10489
|
+
el.addEventListener("click", this._onAnchorClick);
|
|
10490
|
+
});
|
|
10416
10491
|
}
|
|
10417
10492
|
|
|
10418
10493
|
_show() {
|
|
@@ -10432,6 +10507,10 @@ class YumeDrawer extends HTMLElement {
|
|
|
10432
10507
|
}
|
|
10433
10508
|
|
|
10434
10509
|
_teardownAnchor() {
|
|
10510
|
+
if (this._anchorResolveDispose) {
|
|
10511
|
+
this._anchorResolveDispose();
|
|
10512
|
+
this._anchorResolveDispose = null;
|
|
10513
|
+
}
|
|
10435
10514
|
if (this._anchorEl) {
|
|
10436
10515
|
this._anchorEl.removeEventListener("click", this._onAnchorClick);
|
|
10437
10516
|
this._anchorEl = null;
|
|
@@ -13432,13 +13511,19 @@ class YumeStack extends HTMLElement {
|
|
|
13432
13511
|
this.setAttribute("justify", val);
|
|
13433
13512
|
}
|
|
13434
13513
|
|
|
13435
|
-
/**
|
|
13514
|
+
/**
|
|
13515
|
+
* Auto-reduce columns at narrow container widths. Defaults to `true`;
|
|
13516
|
+
* set `responsive="false"` to disable.
|
|
13517
|
+
*/
|
|
13436
13518
|
get responsive() {
|
|
13437
|
-
return this.
|
|
13519
|
+
return this.getAttribute("responsive") !== "false";
|
|
13438
13520
|
}
|
|
13439
13521
|
set responsive(val) {
|
|
13440
|
-
if (val
|
|
13441
|
-
|
|
13522
|
+
if (val === false || val === "false") {
|
|
13523
|
+
this.setAttribute("responsive", "false");
|
|
13524
|
+
} else {
|
|
13525
|
+
this.removeAttribute("responsive");
|
|
13526
|
+
}
|
|
13442
13527
|
}
|
|
13443
13528
|
|
|
13444
13529
|
// -------------------------------------------------------------------------
|
|
@@ -91,6 +91,24 @@ export function createElement(tag: string, attrs?: any, children?: Array<string
|
|
|
91
91
|
* @param {HTMLElement} labelWrapper — the wrapper element containing the slot
|
|
92
92
|
*/
|
|
93
93
|
export function manageLabelVisibility(labelWrapper: HTMLElement): void;
|
|
94
|
+
/**
|
|
95
|
+
* Resolve an anchor element by id for a web component, tolerating DOM insertion
|
|
96
|
+
* races. A synchronous lookup runs first; if it misses, one
|
|
97
|
+
* `requestAnimationFrame` retry covers the common React portal commit-ordering
|
|
98
|
+
* case, and a final `MutationObserver` fallback covers async / lazy mounts.
|
|
99
|
+
*
|
|
100
|
+
* The callback fires at most once. If the host disconnects before the anchor
|
|
101
|
+
* appears, resolution is aborted. Callers must invoke the returned dispose
|
|
102
|
+
* function on teardown (disconnectedCallback, attribute change, etc.) to
|
|
103
|
+
* cancel any pending rAF or observer.
|
|
104
|
+
*
|
|
105
|
+
* @param {HTMLElement} host — component instance; resolution aborts if it disconnects.
|
|
106
|
+
* @param {string} id — the anchor element's id.
|
|
107
|
+
* @param {(el: HTMLElement) => void} onFound — invoked once when the anchor resolves.
|
|
108
|
+
* @param {Document|ShadowRoot} [root=document] — root to search within.
|
|
109
|
+
* @returns {() => void} — dispose function.
|
|
110
|
+
*/
|
|
111
|
+
export function resolveAnchor(host: HTMLElement, id: string, onFound: (el: HTMLElement) => void, root?: Document | ShadowRoot): () => void;
|
|
94
112
|
/**
|
|
95
113
|
* Resolve a CSS custom-property value to a concrete color string.
|
|
96
114
|
* Reads from the given element's computed style.
|
package/dist/modules/helpers.js
CHANGED
|
@@ -340,6 +340,64 @@ export function manageLabelVisibility(labelWrapper) {
|
|
|
340
340
|
});
|
|
341
341
|
}
|
|
342
342
|
|
|
343
|
+
/**
|
|
344
|
+
* Resolve an anchor element by id for a web component, tolerating DOM insertion
|
|
345
|
+
* races. A synchronous lookup runs first; if it misses, one
|
|
346
|
+
* `requestAnimationFrame` retry covers the common React portal commit-ordering
|
|
347
|
+
* case, and a final `MutationObserver` fallback covers async / lazy mounts.
|
|
348
|
+
*
|
|
349
|
+
* The callback fires at most once. If the host disconnects before the anchor
|
|
350
|
+
* appears, resolution is aborted. Callers must invoke the returned dispose
|
|
351
|
+
* function on teardown (disconnectedCallback, attribute change, etc.) to
|
|
352
|
+
* cancel any pending rAF or observer.
|
|
353
|
+
*
|
|
354
|
+
* @param {HTMLElement} host — component instance; resolution aborts if it disconnects.
|
|
355
|
+
* @param {string} id — the anchor element's id.
|
|
356
|
+
* @param {(el: HTMLElement) => void} onFound — invoked once when the anchor resolves.
|
|
357
|
+
* @param {Document|ShadowRoot} [root=document] — root to search within.
|
|
358
|
+
* @returns {() => void} — dispose function.
|
|
359
|
+
*/
|
|
360
|
+
export function resolveAnchor(host, id, onFound, root = document) {
|
|
361
|
+
let disposed = false;
|
|
362
|
+
let rafId = null;
|
|
363
|
+
let observer = null;
|
|
364
|
+
|
|
365
|
+
const dispose = () => {
|
|
366
|
+
disposed = true;
|
|
367
|
+
if (rafId != null) cancelAnimationFrame(rafId);
|
|
368
|
+
if (observer) observer.disconnect();
|
|
369
|
+
rafId = null;
|
|
370
|
+
observer = null;
|
|
371
|
+
};
|
|
372
|
+
|
|
373
|
+
const find = () => {
|
|
374
|
+
if (disposed) return true;
|
|
375
|
+
const el = root.getElementById
|
|
376
|
+
? root.getElementById(id)
|
|
377
|
+
: document.getElementById(id);
|
|
378
|
+
if (el) {
|
|
379
|
+
dispose();
|
|
380
|
+
onFound(el);
|
|
381
|
+
return true;
|
|
382
|
+
}
|
|
383
|
+
return false;
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
if (find()) return dispose;
|
|
387
|
+
if (!host.isConnected) return dispose;
|
|
388
|
+
|
|
389
|
+
rafId = requestAnimationFrame(() => {
|
|
390
|
+
rafId = null;
|
|
391
|
+
if (find()) return;
|
|
392
|
+
const target = root === document ? document.body : root;
|
|
393
|
+
if (!target) return;
|
|
394
|
+
observer = new MutationObserver(find);
|
|
395
|
+
observer.observe(target, { childList: true, subtree: true });
|
|
396
|
+
});
|
|
397
|
+
|
|
398
|
+
return dispose;
|
|
399
|
+
}
|
|
400
|
+
|
|
343
401
|
/**
|
|
344
402
|
* Resolve a CSS custom-property value to a concrete color string.
|
|
345
403
|
* Reads from the given element's computed style.
|