@michaelyagi/shoji 0.1.0-alpha.13 → 0.1.0-alpha.14
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/dist/esm/bodyScrollLock-BGbjxBMq.js +77 -0
- package/dist/esm/bodyScrollLock-BGbjxBMq.js.map +1 -0
- package/dist/esm/core/bodyScrollLock.d.ts +2 -0
- package/dist/esm/core/index.js +1 -64
- package/dist/esm/core/index.js.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/plugins/activeThumbnail/index.js +28 -17
- package/dist/esm/plugins/activeThumbnail/index.js.map +1 -1
- package/dist/shoji.js +36 -19
- package/dist/shoji.js.map +1 -1
- package/dist/shoji.min.js +1 -1
- package/dist/shoji.min.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
let lockCount = 0;
|
|
2
|
+
let savedHtmlOverflow = "";
|
|
3
|
+
let savedHtmlPaddingRight = "";
|
|
4
|
+
let savedHtmlPaddingLeft = "";
|
|
5
|
+
let savedScrollX = 0;
|
|
6
|
+
let savedScrollY = 0;
|
|
7
|
+
let styleObserver = null;
|
|
8
|
+
let intentionalScrollOccurred = false;
|
|
9
|
+
const LIGHTBOX_SELECTOR = ".shoji-outer";
|
|
10
|
+
function markIntentionalScroll() {
|
|
11
|
+
intentionalScrollOccurred = true;
|
|
12
|
+
}
|
|
13
|
+
function isRtl() {
|
|
14
|
+
return getComputedStyle(document.documentElement).direction === "rtl";
|
|
15
|
+
}
|
|
16
|
+
function onTouchMove(event) {
|
|
17
|
+
const target = event.target;
|
|
18
|
+
const insideLightbox = target instanceof Element && target.closest(LIGHTBOX_SELECTOR) !== null;
|
|
19
|
+
if (!insideLightbox) event.preventDefault();
|
|
20
|
+
}
|
|
21
|
+
function onStyleMutation() {
|
|
22
|
+
if (lockCount === 0) return;
|
|
23
|
+
const html = document.documentElement;
|
|
24
|
+
if (getComputedStyle(html).overflow !== "hidden") {
|
|
25
|
+
html.style.overflow = "hidden";
|
|
26
|
+
styleObserver == null ? void 0 : styleObserver.takeRecords();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function lockBodyScroll() {
|
|
30
|
+
if (lockCount === 0) {
|
|
31
|
+
savedScrollX = window.scrollX;
|
|
32
|
+
savedScrollY = window.scrollY;
|
|
33
|
+
intentionalScrollOccurred = false;
|
|
34
|
+
const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
|
|
35
|
+
const rtl = isRtl();
|
|
36
|
+
savedHtmlPaddingRight = document.documentElement.style.paddingRight;
|
|
37
|
+
savedHtmlPaddingLeft = document.documentElement.style.paddingLeft;
|
|
38
|
+
if (scrollbarWidth > 0) {
|
|
39
|
+
if (rtl) {
|
|
40
|
+
const currentPaddingLeft = parseFloat(getComputedStyle(document.documentElement).paddingLeft) || 0;
|
|
41
|
+
document.documentElement.style.paddingLeft = `${currentPaddingLeft + scrollbarWidth}px`;
|
|
42
|
+
} else {
|
|
43
|
+
const currentPaddingRight = parseFloat(getComputedStyle(document.documentElement).paddingRight) || 0;
|
|
44
|
+
document.documentElement.style.paddingRight = `${currentPaddingRight + scrollbarWidth}px`;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
savedHtmlOverflow = document.documentElement.style.overflow;
|
|
48
|
+
document.documentElement.style.overflow = "hidden";
|
|
49
|
+
document.addEventListener("touchmove", onTouchMove, { passive: false });
|
|
50
|
+
styleObserver = new MutationObserver(onStyleMutation);
|
|
51
|
+
styleObserver.observe(document.documentElement, {
|
|
52
|
+
attributes: true,
|
|
53
|
+
attributeFilter: ["style"]
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
lockCount++;
|
|
57
|
+
}
|
|
58
|
+
function unlockBodyScroll() {
|
|
59
|
+
lockCount = Math.max(0, lockCount - 1);
|
|
60
|
+
if (lockCount === 0) {
|
|
61
|
+
styleObserver == null ? void 0 : styleObserver.disconnect();
|
|
62
|
+
styleObserver = null;
|
|
63
|
+
document.removeEventListener("touchmove", onTouchMove);
|
|
64
|
+
document.documentElement.style.overflow = savedHtmlOverflow;
|
|
65
|
+
document.documentElement.style.paddingRight = savedHtmlPaddingRight;
|
|
66
|
+
document.documentElement.style.paddingLeft = savedHtmlPaddingLeft;
|
|
67
|
+
if (!intentionalScrollOccurred) {
|
|
68
|
+
window.scrollTo({ left: savedScrollX, top: savedScrollY, behavior: "instant" });
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
export {
|
|
73
|
+
lockBodyScroll as l,
|
|
74
|
+
markIntentionalScroll as m,
|
|
75
|
+
unlockBodyScroll as u
|
|
76
|
+
};
|
|
77
|
+
//# sourceMappingURL=bodyScrollLock-BGbjxBMq.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bodyScrollLock-BGbjxBMq.js","sources":["../../src/core/bodyScrollLock.ts"],"sourcesContent":["/** DESIGN.md §2.6a — reference-counted page scroll lock. */\nlet lockCount = 0;\nlet savedHtmlOverflow = '';\nlet savedHtmlPaddingRight = '';\nlet savedHtmlPaddingLeft = '';\nlet savedScrollX = 0;\nlet savedScrollY = 0;\nlet styleObserver: MutationObserver | null = null;\n// Set by markIntentionalScroll() (ActiveThumbnail's own scrollIntoView while\n// locked, DESIGN.md §2.6a/§4.2) — a real bug/regression: unlockBodyScroll()\n// unconditionally restoring savedScrollX/Y (below) was meant to undo\n// *unrelated* code hijacking scroll during the lock (a router, a stray\n// \"scroll to top\" button), but it just as unconditionally undid Shoji's own\n// legitimate background-page scrolling too, making ActiveThumbnail's\n// scrollIntoView a complete no-op the instant the lightbox that triggers it\n// is also what's holding the lock — every navigation while open, always.\n// Once anything marks an intentional scroll during this lock session, skip\n// the restore entirely rather than try to track a smooth-scroll animation's\n// eventual resting position (no reliable completion signal across browsers)\n// — same \"leave it where legitimate code put it\" reasoning, just without\n// pinpointing the exact pixel.\nlet intentionalScrollOccurred = false;\n\nconst LIGHTBOX_SELECTOR = '.shoji-outer';\n\n/** Call after intentionally scrolling something on the host page while the lock is active (e.g. ActiveThumbnail's own `scrollIntoView`) — tells `unlockBodyScroll()` not to undo it. */\nexport function markIntentionalScroll(): void {\n intentionalScrollOccurred = true;\n}\n\nfunction isRtl(): boolean {\n return getComputedStyle(document.documentElement).direction === 'rtl';\n}\n\n/**\n * A real gap: `overflow: hidden` on `<html>` doesn't reliably block iOS\n * Safari's own touch-driven rubber-band/bounce scroll in every case — a\n * well-known limitation of this technique across the ecosystem. The common\n * workaround (flipping `body` to `position: fixed` while locked) has its\n * own real tradeoffs: a full reflow, plus manual scroll-position capture/\n * restore that's a frequent source of bugs in other libraries (the exact\n * class of bug this whole lock has already had twice — see the other real\n * bugs in this file's history). Lighter alternative: block the browser's\n * default only for a touchmove that didn't start inside a lightbox,\n * leaving Shoji's own in-dialog gesture handling (which already manages\n * its own `preventDefault`, see `GestureEngine.ts`) completely untouched.\n * Not a passive listener — `preventDefault` is genuinely required here to\n * suppress the browser's native scroll, not just observe it.\n */\nfunction onTouchMove(event: TouchEvent): void {\n const target = event.target;\n const insideLightbox = target instanceof Element && target.closest(LIGHTBOX_SELECTOR) !== null;\n if (!insideLightbox) event.preventDefault();\n}\n\n/**\n * A real gap: this lock is reference-counted against other `Gallery`\n * instances, but has no way to know about unrelated code on the host page\n * — another modal/dropdown library that also sets\n * `document.documentElement.style.overflow`, then clears it back to `''`\n * on its own close, would silently undo this lock mid-lightbox with\n * neither library aware of the other. Watching the one attribute this\n * lock itself owns is the only way to detect and correct that reactively.\n * `takeRecords()` discards the mutation record our own corrective write\n * below just queued — otherwise the observer would fire again for a\n * change it caused itself, forever.\n */\nfunction onStyleMutation(): void {\n if (lockCount === 0) return;\n const html = document.documentElement;\n if (getComputedStyle(html).overflow !== 'hidden') {\n html.style.overflow = 'hidden';\n styleObserver?.takeRecords();\n }\n}\n\nexport function lockBodyScroll(): void {\n if (lockCount === 0) {\n // A real gap: `overflow: hidden` blocks wheel/touch/keyboard-driven\n // scrolling, but not a programmatic `window.scrollTo()`/`scrollTop`\n // write — confirmed directly. If the host's own code scrolls the\n // window while the lightbox is open (a router restoring scroll\n // position, an unrelated \"scroll to top\" button), the page ends up\n // somewhere different than where the viewer left it once the lock\n // releases. Restored unconditionally on unlock below — a scroll\n // *lock* implies the background stays frozen in place for the whole\n // time the lightbox is open, not just protected from direct input.\n savedScrollX = window.scrollX;\n savedScrollY = window.scrollY;\n intentionalScrollOccurred = false;\n\n // A real bug: hiding overflow below reclaims the scrollbar's own\n // gutter, widening <html>'s content box by however many px the\n // scrollbar was — on a host page whose content spans the full viewport\n // width, that reflow is visible as a shift right when the lightbox\n // opens/closes (and reverses on close). Measured *before* overflow is\n // hidden (clientWidth only grows once the gutter is actually reclaimed,\n // so measuring after would always read 0) and only compensated for when\n // a real scrollbar was actually there — a page that never had one gets\n // no padding at all, nothing to compensate for.\n //\n // Two rejected approaches, both real bugs of their own: padding-right\n // on `document.body` compensates the wrong element — a page whose body\n // is narrower than the viewport (a centered, `max-width`-capped layout,\n // this docs site included) never touches the scrollbar's gutter in the\n // first place, so padding body just shrinks its own content box by an\n // *extra* scrollbar-width's worth, a new, self-inflicted reflow.\n // `scrollbar-gutter: stable` compensates the right element (`<html>`,\n // the same one the width is measured on) but paints its own visible,\n // if non-interactive, scrollbar-track styling for as long as the lock\n // is active — trading a brief shift for a permanent scrollbar-shaped\n // strip sitting over the page the whole time the lightbox is open,\n // which reads as more wrong, not less. Padding is genuinely invisible\n // — the same blank space a wider margin would be — and, applied to\n // `<html>` (not `body`), compensates the actual element the scrollbar's\n // gutter belongs to either way.\n const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;\n const rtl = isRtl();\n savedHtmlPaddingRight = document.documentElement.style.paddingRight;\n savedHtmlPaddingLeft = document.documentElement.style.paddingLeft;\n if (scrollbarWidth > 0) {\n // A real gap: a classic scrollbar renders on the *left* on a\n // `direction: rtl` page, not the right — compensating the wrong\n // side would reintroduce the exact reflow this exists to prevent,\n // just mirrored. Checked at lock time, not baked in as a fixed\n // assumption.\n if (rtl) {\n const currentPaddingLeft =\n parseFloat(getComputedStyle(document.documentElement).paddingLeft) || 0;\n document.documentElement.style.paddingLeft = `${currentPaddingLeft + scrollbarWidth}px`;\n } else {\n const currentPaddingRight =\n parseFloat(getComputedStyle(document.documentElement).paddingRight) || 0;\n document.documentElement.style.paddingRight = `${currentPaddingRight + scrollbarWidth}px`;\n }\n }\n\n // A real bug: `document.body.style.overflow = 'hidden'` (this function's\n // original, and until now only, scroll-blocking mechanism) was still\n // set here alongside <html>'s own below — redundant, and not harmless:\n // any value of `overflow` other than `visible` makes an element\n // establish a new block-formatting context, which blocks top-margin\n // collapsing between it and its first child. Confirmed directly via\n // real-browser instrumentation: with body's overflow locked, an h1\n // immediately inside it rendered `bodyMarginTop + h1's own default\n // margin-top` below the viewport top (its margin no longer collapsing\n // into body's own); the instant `unlockBodyScroll()` restored body's\n // overflow, collapsing resumed and the h1 snapped back up by its own\n // margin's worth — reading as the page shifting upward right as the\n // lightbox closes, on *any* page where the first child's margin would\n // otherwise collapse with body's (essentially any page without padding/\n // border on body itself — not a corner case). <html>'s own overflow:\n // hidden below is sufficient on its own to block user-driven scrolling\n // (wheel/touch/keyboard) — confirmed directly — since it's the real\n // scrolling element in standards mode; body's lock was never adding\n // independent protection, only this side effect.\n //\n // <html>'s own overflow, not just body's — mobile viewport-widening\n // bug, see DESIGN.md §2.6a. Both axes, not just overflow-x: setting\n // only one non-'visible' axis forces the browser to silently promote\n // the other from 'visible' to 'auto' (mixing hidden+visible isn't\n // allowed per spec), which revealed a real scrollbar that wasn't\n // there before.\n savedHtmlOverflow = document.documentElement.style.overflow;\n document.documentElement.style.overflow = 'hidden';\n\n document.addEventListener('touchmove', onTouchMove, { passive: false });\n\n // Starts observing only after the writes above have already landed, so\n // it never reacts to its own initial setup — only to a later, external\n // change.\n styleObserver = new MutationObserver(onStyleMutation);\n styleObserver.observe(document.documentElement, {\n attributes: true,\n attributeFilter: ['style'],\n });\n }\n lockCount++;\n}\n\nexport function unlockBodyScroll(): void {\n lockCount = Math.max(0, lockCount - 1);\n if (lockCount === 0) {\n styleObserver?.disconnect();\n styleObserver = null;\n document.removeEventListener('touchmove', onTouchMove);\n\n document.documentElement.style.overflow = savedHtmlOverflow;\n document.documentElement.style.paddingRight = savedHtmlPaddingRight;\n document.documentElement.style.paddingLeft = savedHtmlPaddingLeft;\n\n if (!intentionalScrollOccurred) {\n window.scrollTo({ left: savedScrollX, top: savedScrollY, behavior: 'instant' });\n }\n }\n}\n"],"names":[],"mappings":"AACA,IAAI,YAAY;AAChB,IAAI,oBAAoB;AACxB,IAAI,wBAAwB;AAC5B,IAAI,uBAAuB;AAC3B,IAAI,eAAe;AACnB,IAAI,eAAe;AACnB,IAAI,gBAAyC;AAc7C,IAAI,4BAA4B;AAEhC,MAAM,oBAAoB;AAGnB,SAAS,wBAA8B;AAC5C,8BAA4B;AAC9B;AAEA,SAAS,QAAiB;AACxB,SAAO,iBAAiB,SAAS,eAAe,EAAE,cAAc;AAClE;AAiBA,SAAS,YAAY,OAAyB;AAC5C,QAAM,SAAS,MAAM;AACrB,QAAM,iBAAiB,kBAAkB,WAAW,OAAO,QAAQ,iBAAiB,MAAM;AAC1F,MAAI,CAAC,eAAgB,OAAM,eAAA;AAC7B;AAcA,SAAS,kBAAwB;AAC/B,MAAI,cAAc,EAAG;AACrB,QAAM,OAAO,SAAS;AACtB,MAAI,iBAAiB,IAAI,EAAE,aAAa,UAAU;AAChD,SAAK,MAAM,WAAW;AACtB,mDAAe;AAAA,EACjB;AACF;AAEO,SAAS,iBAAuB;AACrC,MAAI,cAAc,GAAG;AAUnB,mBAAe,OAAO;AACtB,mBAAe,OAAO;AACtB,gCAA4B;AA2B5B,UAAM,iBAAiB,OAAO,aAAa,SAAS,gBAAgB;AACpE,UAAM,MAAM,MAAA;AACZ,4BAAwB,SAAS,gBAAgB,MAAM;AACvD,2BAAuB,SAAS,gBAAgB,MAAM;AACtD,QAAI,iBAAiB,GAAG;AAMtB,UAAI,KAAK;AACP,cAAM,qBACJ,WAAW,iBAAiB,SAAS,eAAe,EAAE,WAAW,KAAK;AACxE,iBAAS,gBAAgB,MAAM,cAAc,GAAG,qBAAqB,cAAc;AAAA,MACrF,OAAO;AACL,cAAM,sBACJ,WAAW,iBAAiB,SAAS,eAAe,EAAE,YAAY,KAAK;AACzE,iBAAS,gBAAgB,MAAM,eAAe,GAAG,sBAAsB,cAAc;AAAA,MACvF;AAAA,IACF;AA4BA,wBAAoB,SAAS,gBAAgB,MAAM;AACnD,aAAS,gBAAgB,MAAM,WAAW;AAE1C,aAAS,iBAAiB,aAAa,aAAa,EAAE,SAAS,OAAO;AAKtE,oBAAgB,IAAI,iBAAiB,eAAe;AACpD,kBAAc,QAAQ,SAAS,iBAAiB;AAAA,MAC9C,YAAY;AAAA,MACZ,iBAAiB,CAAC,OAAO;AAAA,IAAA,CAC1B;AAAA,EACH;AACA;AACF;AAEO,SAAS,mBAAyB;AACvC,cAAY,KAAK,IAAI,GAAG,YAAY,CAAC;AACrC,MAAI,cAAc,GAAG;AACnB,mDAAe;AACf,oBAAgB;AAChB,aAAS,oBAAoB,aAAa,WAAW;AAErD,aAAS,gBAAgB,MAAM,WAAW;AAC1C,aAAS,gBAAgB,MAAM,eAAe;AAC9C,aAAS,gBAAgB,MAAM,cAAc;AAE7C,QAAI,CAAC,2BAA2B;AAC9B,aAAO,SAAS,EAAE,MAAM,cAAc,KAAK,cAAc,UAAU,WAAW;AAAA,IAChF;AAAA,EACF;AACF;"}
|
|
@@ -1,2 +1,4 @@
|
|
|
1
|
+
/** Call after intentionally scrolling something on the host page while the lock is active (e.g. ActiveThumbnail's own `scrollIntoView`) — tells `unlockBodyScroll()` not to undo it. */
|
|
2
|
+
export declare function markIntentionalScroll(): void;
|
|
1
3
|
export declare function lockBodyScroll(): void;
|
|
2
4
|
export declare function unlockBodyScroll(): void;
|
package/dist/esm/core/index.js
CHANGED
|
@@ -1,71 +1,8 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
2
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
3
3
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
4
|
+
import { l as lockBodyScroll, u as unlockBodyScroll } from "../bodyScrollLock-BGbjxBMq.js";
|
|
4
5
|
import { w as waitForTransitionEnd, c as containedBox, z as zoomIn, a as zoomOut } from "../zoomTransition-BeIimqDT.js";
|
|
5
|
-
let lockCount = 0;
|
|
6
|
-
let savedHtmlOverflow = "";
|
|
7
|
-
let savedHtmlPaddingRight = "";
|
|
8
|
-
let savedHtmlPaddingLeft = "";
|
|
9
|
-
let savedScrollX = 0;
|
|
10
|
-
let savedScrollY = 0;
|
|
11
|
-
let styleObserver = null;
|
|
12
|
-
const LIGHTBOX_SELECTOR = ".shoji-outer";
|
|
13
|
-
function isRtl() {
|
|
14
|
-
return getComputedStyle(document.documentElement).direction === "rtl";
|
|
15
|
-
}
|
|
16
|
-
function onTouchMove(event) {
|
|
17
|
-
const target = event.target;
|
|
18
|
-
const insideLightbox = target instanceof Element && target.closest(LIGHTBOX_SELECTOR) !== null;
|
|
19
|
-
if (!insideLightbox) event.preventDefault();
|
|
20
|
-
}
|
|
21
|
-
function onStyleMutation() {
|
|
22
|
-
if (lockCount === 0) return;
|
|
23
|
-
const html = document.documentElement;
|
|
24
|
-
if (getComputedStyle(html).overflow !== "hidden") {
|
|
25
|
-
html.style.overflow = "hidden";
|
|
26
|
-
styleObserver == null ? void 0 : styleObserver.takeRecords();
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
function lockBodyScroll() {
|
|
30
|
-
if (lockCount === 0) {
|
|
31
|
-
savedScrollX = window.scrollX;
|
|
32
|
-
savedScrollY = window.scrollY;
|
|
33
|
-
const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
|
|
34
|
-
const rtl = isRtl();
|
|
35
|
-
savedHtmlPaddingRight = document.documentElement.style.paddingRight;
|
|
36
|
-
savedHtmlPaddingLeft = document.documentElement.style.paddingLeft;
|
|
37
|
-
if (scrollbarWidth > 0) {
|
|
38
|
-
if (rtl) {
|
|
39
|
-
const currentPaddingLeft = parseFloat(getComputedStyle(document.documentElement).paddingLeft) || 0;
|
|
40
|
-
document.documentElement.style.paddingLeft = `${currentPaddingLeft + scrollbarWidth}px`;
|
|
41
|
-
} else {
|
|
42
|
-
const currentPaddingRight = parseFloat(getComputedStyle(document.documentElement).paddingRight) || 0;
|
|
43
|
-
document.documentElement.style.paddingRight = `${currentPaddingRight + scrollbarWidth}px`;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
savedHtmlOverflow = document.documentElement.style.overflow;
|
|
47
|
-
document.documentElement.style.overflow = "hidden";
|
|
48
|
-
document.addEventListener("touchmove", onTouchMove, { passive: false });
|
|
49
|
-
styleObserver = new MutationObserver(onStyleMutation);
|
|
50
|
-
styleObserver.observe(document.documentElement, {
|
|
51
|
-
attributes: true,
|
|
52
|
-
attributeFilter: ["style"]
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
lockCount++;
|
|
56
|
-
}
|
|
57
|
-
function unlockBodyScroll() {
|
|
58
|
-
lockCount = Math.max(0, lockCount - 1);
|
|
59
|
-
if (lockCount === 0) {
|
|
60
|
-
styleObserver == null ? void 0 : styleObserver.disconnect();
|
|
61
|
-
styleObserver = null;
|
|
62
|
-
document.removeEventListener("touchmove", onTouchMove);
|
|
63
|
-
document.documentElement.style.overflow = savedHtmlOverflow;
|
|
64
|
-
document.documentElement.style.paddingRight = savedHtmlPaddingRight;
|
|
65
|
-
document.documentElement.style.paddingLeft = savedHtmlPaddingLeft;
|
|
66
|
-
window.scrollTo({ left: savedScrollX, top: savedScrollY, behavior: "instant" });
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
6
|
class EventBus {
|
|
70
7
|
constructor() {
|
|
71
8
|
__publicField(this, "listeners", /* @__PURE__ */ new Map());
|