🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@ginxjs/dom

Package Overview
Dependencies
Maintainers
1
Versions
14
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ginxjs/dom - npm Package Compare versions

Comparing version
0.0.1
to
0.0.4
+18
dist/anatomy-C9pDRrRN.d.mts
//#region src/shared/anatomy/create-anatomy.d.ts
interface AnatomyPart {
selector: string;
attrs: Record<"data-scope" | "data-part", string>;
}
type AnatomyInstance<T extends string> = Omit<Anatomy<T>, "parts">;
type AnatomyPartName<T> = T extends AnatomyInstance<infer U> ? U : never;
interface Anatomy<T extends string> {
parts: <U extends string>(...parts: U[]) => AnatomyInstance<U>;
extendWith: <V extends string>(...parts: V[]) => AnatomyInstance<T | V>;
build: () => Record<T, AnatomyPart>;
rename: (newName: string) => Anatomy<T>;
keys: () => T[];
omit: <U extends T>(...values: U[]) => AnatomyInstance<Exclude<T, U>>;
}
declare const createAnatomy: <T extends string>(name: string, parts?: T[]) => Anatomy<T>;
//#endregion
export { createAnatomy as a, AnatomyPartName as i, AnatomyInstance as n, AnatomyPart as r, Anatomy as t };
//#region src/shared/anatomy/create-anatomy.d.ts
interface AnatomyPart {
selector: string;
attrs: Record<"data-scope" | "data-part", string>;
}
type AnatomyInstance<T extends string> = Omit<Anatomy<T>, "parts">;
type AnatomyPartName<T> = T extends AnatomyInstance<infer U> ? U : never;
interface Anatomy<T extends string> {
parts: <U extends string>(...parts: U[]) => AnatomyInstance<U>;
extendWith: <V extends string>(...parts: V[]) => AnatomyInstance<T | V>;
build: () => Record<T, AnatomyPart>;
rename: (newName: string) => Anatomy<T>;
keys: () => T[];
omit: <U extends T>(...values: U[]) => AnatomyInstance<Exclude<T, U>>;
}
declare const createAnatomy: <T extends string>(name: string, parts?: T[]) => Anatomy<T>;
//#endregion
export { createAnatomy as a, AnatomyPartName as i, AnatomyInstance as n, AnatomyPart as r, Anatomy as t };
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_create_anatomy = require("./create-anatomy-CpViYTjA.cjs");
exports.createAnatomy = require_create_anatomy.createAnatomy;
import { a as createAnatomy, i as AnatomyPartName, n as AnatomyInstance, r as AnatomyPart, t as Anatomy } from "./anatomy-DFl8j10C.cjs";
export { Anatomy, AnatomyInstance, AnatomyPart, AnatomyPartName, createAnatomy };
import { a as createAnatomy, i as AnatomyPartName, n as AnatomyInstance, r as AnatomyPart, t as Anatomy } from "./anatomy-C9pDRrRN.mjs";
export { Anatomy, AnatomyInstance, AnatomyPart, AnatomyPartName, createAnatomy };
import { t as createAnatomy } from "./create-anatomy-tqxVmw3d.mjs";
export { createAnatomy };
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_dom_query = require("./dom-query-BT6fffRP.cjs");
//#region src/shared/aria-hidden/walk-tree-outside.ts
let counterMap = /* @__PURE__ */ new WeakMap();
let uncontrolledNodes = /* @__PURE__ */ new WeakMap();
let markerMap = {};
let lockCount = 0;
const unwrapHost = (node) => node && (node.host || unwrapHost(node.parentNode));
const correctTargets = (parent, targets) => targets.map((target) => {
if (parent.contains(target)) return target;
const correctedTarget = unwrapHost(target);
if (correctedTarget && parent.contains(correctedTarget)) return correctedTarget;
console.error("[ginxjs > ariaHidden] target", target, "in not contained inside", parent, ". Doing nothing");
return null;
}).filter((x) => Boolean(x));
const ignoreableNodes = new Set([
"script",
"output",
"status",
"next-route-announcer"
]);
const isIgnoredNode = (node) => {
if (ignoreableNodes.has(node.localName)) return true;
if (node.role === "status") return true;
if (node.hasAttribute("aria-live")) return true;
return node.matches("[data-live-announcer]");
};
const walkTreeOutside = (originalTarget, props) => {
const { parentNode, markerName, controlAttribute, explicitBooleanValue, followControlledElements = true } = props;
const targets = correctTargets(parentNode, Array.isArray(originalTarget) ? originalTarget : [originalTarget]);
markerMap[markerName] ||= /* @__PURE__ */ new WeakMap();
const markerCounter = markerMap[markerName];
const hiddenNodes = [];
const elementsToKeep = /* @__PURE__ */ new Set();
const elementsToStop = new Set(targets);
const keep = (el) => {
if (!el || elementsToKeep.has(el)) return;
elementsToKeep.add(el);
keep(el.parentNode);
};
targets.forEach((target) => {
keep(target);
if (followControlledElements && require_dom_query.isHTMLElement(target)) require_dom_query.findControlledElements(target, (controlledElement) => {
keep(controlledElement);
});
});
const deep = (parent) => {
if (!parent || elementsToStop.has(parent)) return;
Array.prototype.forEach.call(parent.children, (node) => {
if (elementsToKeep.has(node)) deep(node);
else try {
if (isIgnoredNode(node)) return;
const attr = node.getAttribute(controlAttribute);
const alreadyHidden = explicitBooleanValue ? attr === "true" : attr !== null && attr !== "false";
const counterValue = (counterMap.get(node) || 0) + 1;
const markerValue = (markerCounter.get(node) || 0) + 1;
counterMap.set(node, counterValue);
markerCounter.set(node, markerValue);
hiddenNodes.push(node);
if (counterValue === 1 && alreadyHidden) uncontrolledNodes.set(node, true);
if (markerValue === 1) node.setAttribute(markerName, "");
if (!alreadyHidden) node.setAttribute(controlAttribute, explicitBooleanValue ? "true" : "");
} catch (e) {
console.error("[ginxjs > ariaHidden] cannot operate on ", node, e);
}
});
};
deep(parentNode);
elementsToKeep.clear();
lockCount++;
return () => {
hiddenNodes.forEach((node) => {
const counterValue = counterMap.get(node) - 1;
const markerValue = markerCounter.get(node) - 1;
counterMap.set(node, counterValue);
markerCounter.set(node, markerValue);
if (!counterValue) {
if (!uncontrolledNodes.has(node)) node.removeAttribute(controlAttribute);
uncontrolledNodes.delete(node);
}
if (!markerValue) node.removeAttribute(markerName);
});
lockCount--;
if (!lockCount) {
counterMap = /* @__PURE__ */ new WeakMap();
counterMap = /* @__PURE__ */ new WeakMap();
uncontrolledNodes = /* @__PURE__ */ new WeakMap();
markerMap = {};
}
};
};
//#endregion
//#region src/shared/aria-hidden/aria-hidden.ts
const getParentNode = (originalTarget) => {
return (Array.isArray(originalTarget) ? originalTarget[0] : originalTarget).ownerDocument.body;
};
const hideOthers = (originalTarget, parentNode = getParentNode(originalTarget), markerName = "data-aria-hidden", followControlledElements = true) => {
if (!parentNode) return;
return walkTreeOutside(originalTarget, {
parentNode,
markerName,
controlAttribute: "aria-hidden",
explicitBooleanValue: true,
followControlledElements
});
};
//#endregion
//#region src/shared/aria-hidden/index.ts
const raf = (fn) => {
const frameId = requestAnimationFrame(() => fn());
return () => cancelAnimationFrame(frameId);
};
function ariaHidden(targetsOrFn, options = {}) {
const { defer = true } = options;
const func = defer ? raf : (v) => v();
const cleanups = [];
cleanups.push(func(() => {
const elements = (typeof targetsOrFn === "function" ? targetsOrFn() : targetsOrFn).filter(Boolean);
if (elements.length === 0) return;
cleanups.push(hideOthers(elements));
}));
return () => {
cleanups.forEach((fn) => fn?.());
};
}
//#endregion
exports.ariaHidden = ariaHidden;
//#region src/shared/aria-hidden/index.d.ts
type MaybeElement = HTMLElement | null;
type Targets = Array<MaybeElement>;
type TargetsOrFn = Targets | (() => Targets);
type Options = {
defer?: boolean | undefined;
};
declare function ariaHidden(targetsOrFn: TargetsOrFn, options?: Options): () => void;
//#endregion
export { ariaHidden };
//#region src/shared/aria-hidden/index.d.ts
type MaybeElement = HTMLElement | null;
type Targets = Array<MaybeElement>;
type TargetsOrFn = Targets | (() => Targets);
type Options = {
defer?: boolean | undefined;
};
declare function ariaHidden(targetsOrFn: TargetsOrFn, options?: Options): () => void;
//#endregion
export { ariaHidden };
import { Kt as findControlledElements, gn as isHTMLElement } from "./dom-query-BgxIO7_X.mjs";
//#region src/shared/aria-hidden/walk-tree-outside.ts
let counterMap = /* @__PURE__ */ new WeakMap();
let uncontrolledNodes = /* @__PURE__ */ new WeakMap();
let markerMap = {};
let lockCount = 0;
const unwrapHost = (node) => node && (node.host || unwrapHost(node.parentNode));
const correctTargets = (parent, targets) => targets.map((target) => {
if (parent.contains(target)) return target;
const correctedTarget = unwrapHost(target);
if (correctedTarget && parent.contains(correctedTarget)) return correctedTarget;
console.error("[ginxjs > ariaHidden] target", target, "in not contained inside", parent, ". Doing nothing");
return null;
}).filter((x) => Boolean(x));
const ignoreableNodes = new Set([
"script",
"output",
"status",
"next-route-announcer"
]);
const isIgnoredNode = (node) => {
if (ignoreableNodes.has(node.localName)) return true;
if (node.role === "status") return true;
if (node.hasAttribute("aria-live")) return true;
return node.matches("[data-live-announcer]");
};
const walkTreeOutside = (originalTarget, props) => {
const { parentNode, markerName, controlAttribute, explicitBooleanValue, followControlledElements = true } = props;
const targets = correctTargets(parentNode, Array.isArray(originalTarget) ? originalTarget : [originalTarget]);
markerMap[markerName] ||= /* @__PURE__ */ new WeakMap();
const markerCounter = markerMap[markerName];
const hiddenNodes = [];
const elementsToKeep = /* @__PURE__ */ new Set();
const elementsToStop = new Set(targets);
const keep = (el) => {
if (!el || elementsToKeep.has(el)) return;
elementsToKeep.add(el);
keep(el.parentNode);
};
targets.forEach((target) => {
keep(target);
if (followControlledElements && isHTMLElement(target)) findControlledElements(target, (controlledElement) => {
keep(controlledElement);
});
});
const deep = (parent) => {
if (!parent || elementsToStop.has(parent)) return;
Array.prototype.forEach.call(parent.children, (node) => {
if (elementsToKeep.has(node)) deep(node);
else try {
if (isIgnoredNode(node)) return;
const attr = node.getAttribute(controlAttribute);
const alreadyHidden = explicitBooleanValue ? attr === "true" : attr !== null && attr !== "false";
const counterValue = (counterMap.get(node) || 0) + 1;
const markerValue = (markerCounter.get(node) || 0) + 1;
counterMap.set(node, counterValue);
markerCounter.set(node, markerValue);
hiddenNodes.push(node);
if (counterValue === 1 && alreadyHidden) uncontrolledNodes.set(node, true);
if (markerValue === 1) node.setAttribute(markerName, "");
if (!alreadyHidden) node.setAttribute(controlAttribute, explicitBooleanValue ? "true" : "");
} catch (e) {
console.error("[ginxjs > ariaHidden] cannot operate on ", node, e);
}
});
};
deep(parentNode);
elementsToKeep.clear();
lockCount++;
return () => {
hiddenNodes.forEach((node) => {
const counterValue = counterMap.get(node) - 1;
const markerValue = markerCounter.get(node) - 1;
counterMap.set(node, counterValue);
markerCounter.set(node, markerValue);
if (!counterValue) {
if (!uncontrolledNodes.has(node)) node.removeAttribute(controlAttribute);
uncontrolledNodes.delete(node);
}
if (!markerValue) node.removeAttribute(markerName);
});
lockCount--;
if (!lockCount) {
counterMap = /* @__PURE__ */ new WeakMap();
counterMap = /* @__PURE__ */ new WeakMap();
uncontrolledNodes = /* @__PURE__ */ new WeakMap();
markerMap = {};
}
};
};
//#endregion
//#region src/shared/aria-hidden/aria-hidden.ts
const getParentNode = (originalTarget) => {
return (Array.isArray(originalTarget) ? originalTarget[0] : originalTarget).ownerDocument.body;
};
const hideOthers = (originalTarget, parentNode = getParentNode(originalTarget), markerName = "data-aria-hidden", followControlledElements = true) => {
if (!parentNode) return;
return walkTreeOutside(originalTarget, {
parentNode,
markerName,
controlAttribute: "aria-hidden",
explicitBooleanValue: true,
followControlledElements
});
};
//#endregion
//#region src/shared/aria-hidden/index.ts
const raf = (fn) => {
const frameId = requestAnimationFrame(() => fn());
return () => cancelAnimationFrame(frameId);
};
function ariaHidden(targetsOrFn, options = {}) {
const { defer = true } = options;
const func = defer ? raf : (v) => v();
const cleanups = [];
cleanups.push(func(() => {
const elements = (typeof targetsOrFn === "function" ? targetsOrFn() : targetsOrFn).filter(Boolean);
if (elements.length === 0) return;
cleanups.push(hideOthers(elements));
}));
return () => {
cleanups.forEach((fn) => fn?.());
};
}
//#endregion
export { ariaHidden };
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_dom_query = require("./dom-query-BT6fffRP.cjs");
//#region src/shared/auto-resize/visual-style.ts
function getVisualStyles(node) {
if (!node) return;
const style = require_dom_query.getComputedStyle(node);
return "box-sizing:" + style.boxSizing + ";border-left:" + style.borderLeftWidth + " solid red;border-right:" + style.borderRightWidth + " solid red;font-family:" + style.fontFamily + ";font-feature-settings:" + style.fontFeatureSettings + ";font-kerning:" + style.fontKerning + ";font-size:" + style.fontSize + ";font-stretch:" + style.fontStretch + ";font-style:" + style.fontStyle + ";font-variant:" + style.fontVariant + ";font-variant-caps:" + style.fontVariantCaps + ";font-variant-ligatures:" + style.fontVariantLigatures + ";font-variant-numeric:" + style.fontVariantNumeric + ";font-weight:" + style.fontWeight + ";letter-spacing:" + style.letterSpacing + ";margin-left:" + style.marginLeft + ";margin-right:" + style.marginRight + ";padding-left:" + style.paddingLeft + ";padding-right:" + style.paddingRight + ";text-indent:" + style.textIndent + ";text-transform:" + style.textTransform;
}
//#endregion
//#region src/shared/auto-resize/autoresize-input.ts
function createGhostElement(doc) {
const el = doc.createElement("div");
el.id = "ghost";
el.style.cssText = "display:inline-block;height:0;overflow:hidden;position:absolute;top:0;visibility:hidden;white-space:nowrap;";
doc.body.appendChild(el);
return el;
}
function autoResizeInput(input) {
if (!input) return;
const doc = require_dom_query.getDocument(input);
const win = require_dom_query.getWindow(input);
const ghost = createGhostElement(doc);
const cssText = getVisualStyles(input);
if (cssText) ghost.style.cssText += cssText;
function resize() {
win.requestAnimationFrame(() => {
ghost.innerHTML = input.value;
const rect = win.getComputedStyle(ghost);
input?.style.setProperty("width", rect.width);
});
}
resize();
input?.addEventListener("input", resize);
input?.addEventListener("change", resize);
return () => {
doc.body.removeChild(ghost);
input?.removeEventListener("input", resize);
input?.removeEventListener("change", resize);
};
}
//#endregion
//#region src/shared/auto-resize/autoresize-textarea.ts
const autoresizeTextarea = (el) => {
if (!el) return;
const style = require_dom_query.getComputedStyle(el);
const win = require_dom_query.getWindow(el);
const doc = require_dom_query.getDocument(el);
const resize = () => {
requestAnimationFrame(() => {
el.style.height = "auto";
let newHeight;
if (style.boxSizing === "content-box") newHeight = el.scrollHeight - (parseFloat(style.paddingTop) + parseFloat(style.paddingBottom));
else newHeight = el.scrollHeight + parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);
if (style.maxHeight !== "none" && newHeight > parseFloat(style.maxHeight)) {
if (style.overflowY === "hidden") el.style.overflowY = "scroll";
newHeight = parseFloat(style.maxHeight);
} else if (style.overflowY !== "hidden") el.style.overflowY = "hidden";
el.style.height = `${newHeight}px`;
});
};
el.addEventListener("input", resize);
el.form?.addEventListener("reset", resize);
const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(el), "value");
if (descriptor) Object.defineProperty(el, "value", {
...descriptor,
set(newValue) {
const prevValue = descriptor.get?.call(this);
descriptor.set?.call(this, newValue);
resize();
if (prevValue !== newValue) queueMicrotask(() => {
el.dispatchEvent(new win.InputEvent("input", { bubbles: true }));
});
}
});
const resizeObserver = new win.ResizeObserver(() => {
requestAnimationFrame(() => resize());
});
resizeObserver.observe(el);
const attrObserver = new win.MutationObserver(() => resize());
attrObserver.observe(el, {
attributes: true,
attributeFilter: ["rows", "placeholder"]
});
doc.fonts?.addEventListener("loadingdone", resize);
return () => {
el.removeEventListener("input", resize);
el.form?.removeEventListener("reset", resize);
doc.fonts?.removeEventListener("loadingdone", resize);
resizeObserver.disconnect();
attrObserver.disconnect();
};
};
//#endregion
exports.autoResizeInput = autoResizeInput;
exports.autoresizeTextarea = autoresizeTextarea;
//#region src/shared/auto-resize/autoresize-input.d.ts
declare function autoResizeInput(input: HTMLInputElement | null): (() => void) | undefined;
//#endregion
//#region src/shared/auto-resize/autoresize-textarea.d.ts
declare const autoresizeTextarea: (el: HTMLTextAreaElement | null) => (() => void) | undefined;
//#endregion
export { autoResizeInput, autoresizeTextarea };
//#region src/shared/auto-resize/autoresize-input.d.ts
declare function autoResizeInput(input: HTMLInputElement | null): (() => void) | undefined;
//#endregion
//#region src/shared/auto-resize/autoresize-textarea.d.ts
declare const autoresizeTextarea: (el: HTMLTextAreaElement | null) => (() => void) | undefined;
//#endregion
export { autoResizeInput, autoresizeTextarea };
import { $t as getComputedStyle, ln as getWindow, rn as getDocument } from "./dom-query-BgxIO7_X.mjs";
//#region src/shared/auto-resize/visual-style.ts
function getVisualStyles(node) {
if (!node) return;
const style = getComputedStyle(node);
return "box-sizing:" + style.boxSizing + ";border-left:" + style.borderLeftWidth + " solid red;border-right:" + style.borderRightWidth + " solid red;font-family:" + style.fontFamily + ";font-feature-settings:" + style.fontFeatureSettings + ";font-kerning:" + style.fontKerning + ";font-size:" + style.fontSize + ";font-stretch:" + style.fontStretch + ";font-style:" + style.fontStyle + ";font-variant:" + style.fontVariant + ";font-variant-caps:" + style.fontVariantCaps + ";font-variant-ligatures:" + style.fontVariantLigatures + ";font-variant-numeric:" + style.fontVariantNumeric + ";font-weight:" + style.fontWeight + ";letter-spacing:" + style.letterSpacing + ";margin-left:" + style.marginLeft + ";margin-right:" + style.marginRight + ";padding-left:" + style.paddingLeft + ";padding-right:" + style.paddingRight + ";text-indent:" + style.textIndent + ";text-transform:" + style.textTransform;
}
//#endregion
//#region src/shared/auto-resize/autoresize-input.ts
function createGhostElement(doc) {
const el = doc.createElement("div");
el.id = "ghost";
el.style.cssText = "display:inline-block;height:0;overflow:hidden;position:absolute;top:0;visibility:hidden;white-space:nowrap;";
doc.body.appendChild(el);
return el;
}
function autoResizeInput(input) {
if (!input) return;
const doc = getDocument(input);
const win = getWindow(input);
const ghost = createGhostElement(doc);
const cssText = getVisualStyles(input);
if (cssText) ghost.style.cssText += cssText;
function resize() {
win.requestAnimationFrame(() => {
ghost.innerHTML = input.value;
const rect = win.getComputedStyle(ghost);
input?.style.setProperty("width", rect.width);
});
}
resize();
input?.addEventListener("input", resize);
input?.addEventListener("change", resize);
return () => {
doc.body.removeChild(ghost);
input?.removeEventListener("input", resize);
input?.removeEventListener("change", resize);
};
}
//#endregion
//#region src/shared/auto-resize/autoresize-textarea.ts
const autoresizeTextarea = (el) => {
if (!el) return;
const style = getComputedStyle(el);
const win = getWindow(el);
const doc = getDocument(el);
const resize = () => {
requestAnimationFrame(() => {
el.style.height = "auto";
let newHeight;
if (style.boxSizing === "content-box") newHeight = el.scrollHeight - (parseFloat(style.paddingTop) + parseFloat(style.paddingBottom));
else newHeight = el.scrollHeight + parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);
if (style.maxHeight !== "none" && newHeight > parseFloat(style.maxHeight)) {
if (style.overflowY === "hidden") el.style.overflowY = "scroll";
newHeight = parseFloat(style.maxHeight);
} else if (style.overflowY !== "hidden") el.style.overflowY = "hidden";
el.style.height = `${newHeight}px`;
});
};
el.addEventListener("input", resize);
el.form?.addEventListener("reset", resize);
const descriptor = Object.getOwnPropertyDescriptor(Object.getPrototypeOf(el), "value");
if (descriptor) Object.defineProperty(el, "value", {
...descriptor,
set(newValue) {
const prevValue = descriptor.get?.call(this);
descriptor.set?.call(this, newValue);
resize();
if (prevValue !== newValue) queueMicrotask(() => {
el.dispatchEvent(new win.InputEvent("input", { bubbles: true }));
});
}
});
const resizeObserver = new win.ResizeObserver(() => {
requestAnimationFrame(() => resize());
});
resizeObserver.observe(el);
const attrObserver = new win.MutationObserver(() => resize());
attrObserver.observe(el, {
attributes: true,
attributeFilter: ["rows", "placeholder"]
});
doc.fonts?.addEventListener("loadingdone", resize);
return () => {
el.removeEventListener("input", resize);
el.form?.removeEventListener("reset", resize);
doc.fonts?.removeEventListener("loadingdone", resize);
resizeObserver.disconnect();
attrObserver.disconnect();
};
};
//#endregion
export { autoResizeInput, autoresizeTextarea };
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
let _ginxjs_core_utils = require("@ginxjs/core/utils");
//#region src/shared/color-utils/color-format-gradient.ts
const generateRGB_R = (orientation, dir, zValue) => {
const maskImage = `linear-gradient(to ${orientation[Number(!dir)]}, transparent, #000)`;
return {
areaStyles: { backgroundImage: `linear-gradient(to ${orientation[Number(dir)]},rgb(${zValue},0,0),rgb(${zValue},255,0))` },
areaGradientStyles: {
backgroundImage: `linear-gradient(to ${orientation[Number(dir)]},rgb(${zValue},0,255),rgb(${zValue},255,255))`,
WebkitMaskImage: maskImage,
maskImage
}
};
};
const generateRGB_G = (orientation, dir, zValue) => {
const maskImage = `linear-gradient(to ${orientation[Number(!dir)]}, transparent, #000)`;
return {
areaStyles: { backgroundImage: `linear-gradient(to ${orientation[Number(dir)]},rgb(0,${zValue},0),rgb(255,${zValue},0))` },
areaGradientStyles: {
backgroundImage: `linear-gradient(to ${orientation[Number(dir)]},rgb(0,${zValue},255),rgb(255,${zValue},255))`,
WebkitMaskImage: maskImage,
maskImage
}
};
};
const generateRGB_B = (orientation, dir, zValue) => {
const maskImage = `linear-gradient(to ${orientation[Number(!dir)]}, transparent, #000)`;
return {
areaStyles: { backgroundImage: `linear-gradient(to ${orientation[Number(dir)]},rgb(0,0,${zValue}),rgb(255,0,${zValue}))` },
areaGradientStyles: {
backgroundImage: `linear-gradient(to ${orientation[Number(dir)]},rgb(0,255,${zValue}),rgb(255,255,${zValue}))`,
WebkitMaskImage: maskImage,
maskImage
}
};
};
const generateHSL_H = (orientation, dir, zValue) => {
return {
areaStyles: {},
areaGradientStyles: { background: [
`linear-gradient(to ${orientation[Number(dir)]}, hsla(0,0%,0%,1) 0%, hsla(0,0%,0%,0) 50%, hsla(0,0%,100%,0) 50%, hsla(0,0%,100%,1) 100%)`,
`linear-gradient(to ${orientation[Number(!dir)]},hsl(0,0%,50%),hsla(0,0%,50%,0))`,
`hsl(${zValue}, 100%, 50%)`
].join(",") }
};
};
const generateHSL_S = (orientation, dir, alphaValue) => {
return {
areaStyles: {},
areaGradientStyles: { background: [
`linear-gradient(to ${orientation[Number(!dir)]}, hsla(0,0%,0%,${alphaValue}) 0%, hsla(0,0%,0%,0) 50%, hsla(0,0%,100%,0) 50%, hsla(0,0%,100%,${alphaValue}) 100%)`,
`linear-gradient(to ${orientation[Number(dir)]},hsla(0,100%,50%,${alphaValue}),hsla(60,100%,50%,${alphaValue}),hsla(120,100%,50%,${alphaValue}),hsla(180,100%,50%,${alphaValue}),hsla(240,100%,50%,${alphaValue}),hsla(300,100%,50%,${alphaValue}),hsla(359,100%,50%,${alphaValue}))`,
"hsl(0, 0%, 50%)"
].join(",") }
};
};
const generateHSL_L = (orientation, dir, zValue) => {
return {
areaStyles: {},
areaGradientStyles: { backgroundImage: [`linear-gradient(to ${orientation[Number(!dir)]},hsl(0,0%,${zValue}%),hsla(0,0%,${zValue}%,0))`, `linear-gradient(to ${orientation[Number(dir)]},hsl(0,100%,${zValue}%),hsl(60,100%,${zValue}%),hsl(120,100%,${zValue}%),hsl(180,100%,${zValue}%),hsl(240,100%,${zValue}%),hsl(300,100%,${zValue}%),hsl(360,100%,${zValue}%))`].join(",") }
};
};
const generateHSB_H = (orientation, dir, zValue) => {
return {
areaStyles: {},
areaGradientStyles: { background: [
`linear-gradient(to ${orientation[Number(dir)]},hsl(0,0%,0%),hsla(0,0%,0%,0))`,
`linear-gradient(to ${orientation[Number(!dir)]},hsl(0,0%,100%),hsla(0,0%,100%,0))`,
`hsl(${zValue}, 100%, 50%)`
].join(",") }
};
};
const generateHSB_S = (orientation, dir, alphaValue) => {
return {
areaStyles: {},
areaGradientStyles: { background: [
`linear-gradient(to ${orientation[Number(!dir)]},hsla(0,0%,0%,${alphaValue}),hsla(0,0%,0%,0))`,
`linear-gradient(to ${orientation[Number(dir)]},hsla(0,100%,50%,${alphaValue}),hsla(60,100%,50%,${alphaValue}),hsla(120,100%,50%,${alphaValue}),hsla(180,100%,50%,${alphaValue}),hsla(240,100%,50%,${alphaValue}),hsla(300,100%,50%,${alphaValue}),hsla(359,100%,50%,${alphaValue}))`,
`linear-gradient(to ${orientation[Number(!dir)]},hsl(0,0%,0%),hsl(0,0%,100%))`
].join(",") }
};
};
const generateHSB_B = (orientation, dir, alphaValue) => {
return {
areaStyles: {},
areaGradientStyles: { background: [
`linear-gradient(to ${orientation[Number(!dir)]},hsla(0,0%,100%,${alphaValue}),hsla(0,0%,100%,0))`,
`linear-gradient(to ${orientation[Number(dir)]},hsla(0,100%,50%,${alphaValue}),hsla(60,100%,50%,${alphaValue}),hsla(120,100%,50%,${alphaValue}),hsla(180,100%,50%,${alphaValue}),hsla(240,100%,50%,${alphaValue}),hsla(300,100%,50%,${alphaValue}),hsla(359,100%,50%,${alphaValue}))`,
"#000"
].join(",") }
};
};
//#endregion
//#region src/shared/color-utils/area-gradient.ts
function getColorAreaGradient(color, options) {
const { xChannel, yChannel, dir: dirProp = "ltr" } = options;
const { zChannel } = color.getColorAxes({
xChannel,
yChannel
});
const zValue = color.getChannelValue(zChannel);
const { minValue: zMin, maxValue: zMax } = color.getChannelRange(zChannel);
const orientation = ["top", dirProp === "rtl" ? "left" : "right"];
let dir = false;
let background = {
areaStyles: {},
areaGradientStyles: {}
};
let alphaValue = (zValue - zMin) / (zMax - zMin);
let isHSL = color.getFormat() === "hsla";
switch (zChannel) {
case "red":
dir = xChannel === "green";
background = generateRGB_R(orientation, dir, zValue);
break;
case "green":
dir = xChannel === "red";
background = generateRGB_G(orientation, dir, zValue);
break;
case "blue":
dir = xChannel === "red";
background = generateRGB_B(orientation, dir, zValue);
break;
case "hue":
dir = xChannel !== "saturation";
if (isHSL) background = generateHSL_H(orientation, dir, zValue);
else background = generateHSB_H(orientation, dir, zValue);
break;
case "saturation":
dir = xChannel === "hue";
if (isHSL) background = generateHSL_S(orientation, dir, alphaValue);
else background = generateHSB_S(orientation, dir, alphaValue);
break;
case "brightness":
dir = xChannel === "hue";
background = generateHSB_B(orientation, dir, alphaValue);
break;
case "lightness":
dir = xChannel === "hue";
background = generateHSL_L(orientation, dir, zValue);
break;
}
return background;
}
//#endregion
//#region src/shared/color-utils/color.ts
const isEqualObject = (a, b) => {
if (Object.keys(a).length !== Object.keys(b).length) return false;
for (let key in a) if (a[key] !== b[key]) return false;
return true;
};
var Color = class {
toHexInt() {
return this.toFormat("rgba").toHexInt();
}
getChannelValue(channel) {
if (channel in this) return this[channel];
throw new Error("Unsupported color channel: " + channel);
}
getChannelValuePercent(channel, valueToCheck) {
const value = valueToCheck ?? this.getChannelValue(channel);
const { minValue, maxValue } = this.getChannelRange(channel);
return (0, _ginxjs_core_utils.getValuePercent)(value, minValue, maxValue);
}
getChannelPercentValue(channel, percentToCheck) {
const { minValue, maxValue, step } = this.getChannelRange(channel);
return (0, _ginxjs_core_utils.snapValueToStep)((0, _ginxjs_core_utils.getPercentValue)(percentToCheck, minValue, maxValue, step), minValue, maxValue, step);
}
withChannelValue(channel, value) {
const { minValue, maxValue } = this.getChannelRange(channel);
if (channel in this) {
let clone = this.clone();
clone[channel] = (0, _ginxjs_core_utils.clampValue)(value, minValue, maxValue);
return clone;
}
throw new Error("Unsupported color channel: " + channel);
}
getColorAxes(xyChannels) {
let { xChannel, yChannel } = xyChannels;
let xCh = xChannel || this.getChannels().find((c) => c !== yChannel);
let yCh = yChannel || this.getChannels().find((c) => c !== xCh);
return {
xChannel: xCh,
yChannel: yCh,
zChannel: this.getChannels().find((c) => c !== xCh && c !== yCh)
};
}
incrementChannel(channel, stepSize) {
const { minValue, maxValue, step } = this.getChannelRange(channel);
const value = (0, _ginxjs_core_utils.snapValueToStep)((0, _ginxjs_core_utils.clampValue)(this.getChannelValue(channel) + stepSize, minValue, maxValue), minValue, maxValue, step);
return this.withChannelValue(channel, value);
}
decrementChannel(channel, stepSize) {
return this.incrementChannel(channel, -stepSize);
}
isEqual(color) {
return isEqualObject(this.toJSON(), color.toJSON()) && this.getChannelValue("alpha") === color.getChannelValue("alpha");
}
};
//#endregion
//#region src/shared/color-utils/rgb-color.ts
const HEX_COLOR_REGEX = /^#[\da-f]+$/i;
const RGB_COLOR_REGEX = /^rgba?\((.*)\)$/;
const HEX_STARTING_REGEX = /[^#]/gi;
var RGBColor = class RGBColor extends Color {
red;
green;
blue;
alpha;
constructor(red, green, blue, alpha) {
super();
this.red = red;
this.green = green;
this.blue = blue;
this.alpha = alpha;
}
static parse(value) {
let colors = [];
if (HEX_COLOR_REGEX.test(value) && [
4,
5,
7,
9
].includes(value.length)) {
const values = (value.length < 6 ? value.replace(HEX_STARTING_REGEX, "$&$&") : value).slice(1).split("");
while (values.length > 0) colors.push(parseInt(values.splice(0, 2).join(""), 16));
colors[3] = colors[3] !== void 0 ? colors[3] / 255 : void 0;
}
const match = value.match(RGB_COLOR_REGEX);
if (match?.[1]) colors = match[1].split(",").map((value) => Number(value.trim())).map((num, i) => (0, _ginxjs_core_utils.clampValue)(num, 0, i < 3 ? 255 : 1));
return colors.length < 3 ? void 0 : new RGBColor(colors[0], colors[1], colors[2], colors[3] ?? 1);
}
toString(format = "css") {
switch (format) {
case "hex": return "#" + (this.red.toString(16).padStart(2, "0") + this.green.toString(16).padStart(2, "0") + this.blue.toString(16).padStart(2, "0")).toUpperCase();
case "hexa": return "#" + (this.red.toString(16).padStart(2, "0") + this.green.toString(16).padStart(2, "0") + this.blue.toString(16).padStart(2, "0") + Math.round(this.alpha * 255).toString(16).padStart(2, "0")).toUpperCase();
case "rgb": return `rgb(${this.red}, ${this.green}, ${this.blue})`;
case "css":
case "rgba": return `rgba(${this.red}, ${this.green}, ${this.blue}, ${this.alpha})`;
case "hsl": return this.toHSL().toString("hsl");
case "hsb": return this.toHSB().toString("hsb");
default: return this.toFormat(format).toString(format);
}
}
toFormat(format) {
switch (format) {
case "rgba": return this;
case "hsba": return this.toHSB();
case "hsla": return this.toHSL();
default: throw new Error("Unsupported color conversion: rgb -> " + format);
}
}
toHexInt() {
return this.red << 16 | this.green << 8 | this.blue;
}
toHSB() {
const red = this.red / 255;
const green = this.green / 255;
const blue = this.blue / 255;
const min = Math.min(red, green, blue);
const brightness = Math.max(red, green, blue);
const chroma = brightness - min;
const saturation = brightness === 0 ? 0 : chroma / brightness;
let hue = 0;
if (chroma !== 0) {
switch (brightness) {
case red:
hue = (green - blue) / chroma + (green < blue ? 6 : 0);
break;
case green:
hue = (blue - red) / chroma + 2;
break;
case blue:
hue = (red - green) / chroma + 4;
break;
}
hue /= 6;
}
return new HSBColor((0, _ginxjs_core_utils.toFixedNumber)(hue * 360, 2), (0, _ginxjs_core_utils.toFixedNumber)(saturation * 100, 2), (0, _ginxjs_core_utils.toFixedNumber)(brightness * 100, 2), (0, _ginxjs_core_utils.toFixedNumber)(this.alpha, 2));
}
toHSL() {
const red = this.red / 255;
const green = this.green / 255;
const blue = this.blue / 255;
const min = Math.min(red, green, blue);
const max = Math.max(red, green, blue);
const lightness = (max + min) / 2;
const chroma = max - min;
let hue = -1;
let saturation = -1;
if (chroma === 0) hue = saturation = 0;
else {
saturation = chroma / (lightness < .5 ? max + min : 2 - max - min);
switch (max) {
case red:
hue = (green - blue) / chroma + (green < blue ? 6 : 0);
break;
case green:
hue = (blue - red) / chroma + 2;
break;
case blue:
hue = (red - green) / chroma + 4;
break;
}
hue /= 6;
}
return new HSLColor((0, _ginxjs_core_utils.toFixedNumber)(hue * 360, 2), (0, _ginxjs_core_utils.toFixedNumber)(saturation * 100, 2), (0, _ginxjs_core_utils.toFixedNumber)(lightness * 100, 2), (0, _ginxjs_core_utils.toFixedNumber)(this.alpha, 2));
}
clone() {
return new RGBColor(this.red, this.green, this.blue, this.alpha);
}
getChannelFormatOptions(channel) {
switch (channel) {
case "red":
case "green":
case "blue": return { style: "decimal" };
case "alpha": return { style: "percent" };
default: throw new Error("Unknown color channel: " + channel);
}
}
formatChannelValue(channel, locale) {
let options = this.getChannelFormatOptions(channel);
let value = this.getChannelValue(channel);
return new Intl.NumberFormat(locale, options).format(value);
}
getChannelRange(channel) {
switch (channel) {
case "red":
case "green":
case "blue": return {
minValue: 0,
maxValue: 255,
step: 1,
pageSize: 17
};
case "alpha": return {
minValue: 0,
maxValue: 1,
step: .01,
pageSize: .1
};
default: throw new Error("Unknown color channel: " + channel);
}
}
toJSON() {
return {
r: this.red,
g: this.green,
b: this.blue,
a: this.alpha
};
}
getFormat() {
return "rgba";
}
static colorChannels = [
"red",
"green",
"blue"
];
getChannels() {
return RGBColor.colorChannels;
}
};
//#endregion
//#region src/shared/color-utils/hsl-color.ts
const HSL_REGEX = /hsl\(([-+]?\d+(?:.\d+)?\s*,\s*[-+]?\d+(?:.\d+)?%\s*,\s*[-+]?\d+(?:.\d+)?%)\)|hsla\(([-+]?\d+(?:.\d+)?\s*,\s*[-+]?\d+(?:.\d+)?%\s*,\s*[-+]?\d+(?:.\d+)?%\s*,\s*[-+]?\d(.\d+)?)\)/;
var HSLColor = class HSLColor extends Color {
hue;
saturation;
lightness;
alpha;
constructor(hue, saturation, lightness, alpha) {
super();
this.hue = hue;
this.saturation = saturation;
this.lightness = lightness;
this.alpha = alpha;
}
static parse(value) {
let m;
if (m = value.match(HSL_REGEX)) {
const [h, s, l, a] = (m[1] ?? m[2]).split(",").map((n) => Number(n.trim().replace("%", "")));
return new HSLColor((0, _ginxjs_core_utils.mod)(h, 360), (0, _ginxjs_core_utils.clampValue)(s, 0, 100), (0, _ginxjs_core_utils.clampValue)(l, 0, 100), (0, _ginxjs_core_utils.clampValue)(a ?? 1, 0, 1));
}
}
toString(format = "css") {
switch (format) {
case "hex": return this.toRGB().toString("hex");
case "hexa": return this.toRGB().toString("hexa");
case "hsl": return `hsl(${this.hue}, ${(0, _ginxjs_core_utils.toFixedNumber)(this.saturation, 2)}%, ${(0, _ginxjs_core_utils.toFixedNumber)(this.lightness, 2)}%)`;
case "css":
case "hsla": return `hsla(${this.hue}, ${(0, _ginxjs_core_utils.toFixedNumber)(this.saturation, 2)}%, ${(0, _ginxjs_core_utils.toFixedNumber)(this.lightness, 2)}%, ${this.alpha})`;
case "hsb": return this.toHSB().toString("hsb");
case "rgb": return this.toRGB().toString("rgb");
default: return this.toFormat(format).toString(format);
}
}
toFormat(format) {
switch (format) {
case "hsla": return this;
case "hsba": return this.toHSB();
case "rgba": return this.toRGB();
default: throw new Error("Unsupported color conversion: hsl -> " + format);
}
}
toHSB() {
let saturation = this.saturation / 100;
let lightness = this.lightness / 100;
let brightness = lightness + saturation * Math.min(lightness, 1 - lightness);
saturation = brightness === 0 ? 0 : 2 * (1 - lightness / brightness);
return new HSBColor((0, _ginxjs_core_utils.toFixedNumber)(this.hue, 2), (0, _ginxjs_core_utils.toFixedNumber)(saturation * 100, 2), (0, _ginxjs_core_utils.toFixedNumber)(brightness * 100, 2), (0, _ginxjs_core_utils.toFixedNumber)(this.alpha, 2));
}
toRGB() {
let hue = this.hue;
let saturation = this.saturation / 100;
let lightness = this.lightness / 100;
let a = saturation * Math.min(lightness, 1 - lightness);
let fn = (n, k = (n + hue / 30) % 12) => lightness - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
return new RGBColor(Math.round(fn(0) * 255), Math.round(fn(8) * 255), Math.round(fn(4) * 255), (0, _ginxjs_core_utils.toFixedNumber)(this.alpha, 2));
}
clone() {
return new HSLColor(this.hue, this.saturation, this.lightness, this.alpha);
}
getChannelFormatOptions(channel) {
switch (channel) {
case "hue": return {
style: "unit",
unit: "degree",
unitDisplay: "narrow"
};
case "saturation":
case "lightness":
case "alpha": return { style: "percent" };
default: throw new Error("Unknown color channel: " + channel);
}
}
formatChannelValue(channel, locale) {
let options = this.getChannelFormatOptions(channel);
let value = this.getChannelValue(channel);
if (channel === "saturation" || channel === "lightness") value /= 100;
return new Intl.NumberFormat(locale, options).format(value);
}
getChannelRange(channel) {
switch (channel) {
case "hue": return {
minValue: 0,
maxValue: 360,
step: 1,
pageSize: 15
};
case "saturation":
case "lightness": return {
minValue: 0,
maxValue: 100,
step: 1,
pageSize: 10
};
case "alpha": return {
minValue: 0,
maxValue: 1,
step: .01,
pageSize: .1
};
default: throw new Error("Unknown color channel: " + channel);
}
}
toJSON() {
return {
h: this.hue,
s: this.saturation,
l: this.lightness,
a: this.alpha
};
}
getFormat() {
return "hsla";
}
static colorChannels = [
"hue",
"saturation",
"lightness"
];
getChannels() {
return HSLColor.colorChannels;
}
};
//#endregion
//#region src/shared/color-utils/hsb-color.ts
const HSB_REGEX = /hsb\(([-+]?\d+(?:.\d+)?\s*,\s*[-+]?\d+(?:.\d+)?%\s*,\s*[-+]?\d+(?:.\d+)?%)\)|hsba\(([-+]?\d+(?:.\d+)?\s*,\s*[-+]?\d+(?:.\d+)?%\s*,\s*[-+]?\d+(?:.\d+)?%\s*,\s*[-+]?\d(.\d+)?)\)/;
var HSBColor = class HSBColor extends Color {
hue;
saturation;
brightness;
alpha;
constructor(hue, saturation, brightness, alpha) {
super();
this.hue = hue;
this.saturation = saturation;
this.brightness = brightness;
this.alpha = alpha;
}
static parse(value) {
let m;
if (m = value.match(HSB_REGEX)) {
const [h, s, b, a] = (m[1] ?? m[2]).split(",").map((n) => Number(n.trim().replace("%", "")));
return new HSBColor((0, _ginxjs_core_utils.mod)(h, 360), (0, _ginxjs_core_utils.clampValue)(s, 0, 100), (0, _ginxjs_core_utils.clampValue)(b, 0, 100), (0, _ginxjs_core_utils.clampValue)(a ?? 1, 0, 1));
}
}
toString(format = "css") {
switch (format) {
case "css": return this.toHSL().toString("css");
case "hex": return this.toRGB().toString("hex");
case "hexa": return this.toRGB().toString("hexa");
case "hsb": return `hsb(${this.hue}, ${(0, _ginxjs_core_utils.toFixedNumber)(this.saturation, 2)}%, ${(0, _ginxjs_core_utils.toFixedNumber)(this.brightness, 2)}%)`;
case "hsba": return `hsba(${this.hue}, ${(0, _ginxjs_core_utils.toFixedNumber)(this.saturation, 2)}%, ${(0, _ginxjs_core_utils.toFixedNumber)(this.brightness, 2)}%, ${this.alpha})`;
case "hsl": return this.toHSL().toString("hsl");
case "rgb": return this.toRGB().toString("rgb");
default: return this.toFormat(format).toString(format);
}
}
toFormat(format) {
switch (format) {
case "hsba": return this;
case "hsla": return this.toHSL();
case "rgba": return this.toRGB();
default: throw new Error("Unsupported color conversion: hsb -> " + format);
}
}
toHSL() {
let saturation = this.saturation / 100;
let brightness = this.brightness / 100;
let lightness = brightness * (1 - saturation / 2);
saturation = lightness === 0 || lightness === 1 ? 0 : (brightness - lightness) / Math.min(lightness, 1 - lightness);
return new HSLColor((0, _ginxjs_core_utils.toFixedNumber)(this.hue, 2), (0, _ginxjs_core_utils.toFixedNumber)(saturation * 100, 2), (0, _ginxjs_core_utils.toFixedNumber)(lightness * 100, 2), (0, _ginxjs_core_utils.toFixedNumber)(this.alpha, 2));
}
toRGB() {
let hue = this.hue;
let saturation = this.saturation / 100;
let brightness = this.brightness / 100;
let fn = (n, k = (n + hue / 60) % 6) => brightness - saturation * brightness * Math.max(Math.min(k, 4 - k, 1), 0);
return new RGBColor(Math.round(fn(5) * 255), Math.round(fn(3) * 255), Math.round(fn(1) * 255), (0, _ginxjs_core_utils.toFixedNumber)(this.alpha, 2));
}
clone() {
return new HSBColor(this.hue, this.saturation, this.brightness, this.alpha);
}
getChannelFormatOptions(channel) {
switch (channel) {
case "hue": return {
style: "unit",
unit: "degree",
unitDisplay: "narrow"
};
case "saturation":
case "brightness":
case "alpha": return { style: "percent" };
default: throw new Error("Unknown color channel: " + channel);
}
}
formatChannelValue(channel, locale) {
let options = this.getChannelFormatOptions(channel);
let value = this.getChannelValue(channel);
if (channel === "saturation" || channel === "brightness") value /= 100;
return new Intl.NumberFormat(locale, options).format(value);
}
getChannelRange(channel) {
switch (channel) {
case "hue": return {
minValue: 0,
maxValue: 360,
step: 1,
pageSize: 15
};
case "saturation":
case "brightness": return {
minValue: 0,
maxValue: 100,
step: 1,
pageSize: 10
};
case "alpha": return {
minValue: 0,
maxValue: 1,
step: .01,
pageSize: .1
};
default: throw new Error("Unknown color channel: " + channel);
}
}
toJSON() {
return {
h: this.hue,
s: this.saturation,
b: this.brightness,
a: this.alpha
};
}
getFormat() {
return "hsba";
}
static colorChannels = [
"hue",
"saturation",
"brightness"
];
getChannels() {
return HSBColor.colorChannels;
}
};
//#endregion
//#region src/shared/color-utils/native-color.ts
const nativeColors = "aliceblue:f0f8ff,antiquewhite:faebd7,aqua:00ffff,aquamarine:7fffd4,azure:f0ffff,beige:f5f5dc,bisque:ffe4c4,black:000000,blanchedalmond:ffebcd,blue:0000ff,blueviolet:8a2be2,brown:a52a2a,burlywood:deb887,cadetblue:5f9ea0,chartreuse:7fff00,chocolate:d2691e,coral:ff7f50,cornflowerblue:6495ed,cornsilk:fff8dc,crimson:dc143c,cyan:00ffff,darkblue:00008b,darkcyan:008b8b,darkgoldenrod:b8860b,darkgray:a9a9a9,darkgreen:006400,darkkhaki:bdb76b,darkmagenta:8b008b,darkolivegreen:556b2f,darkorange:ff8c00,darkorchid:9932cc,darkred:8b0000,darksalmon:e9967a,darkseagreen:8fbc8f,darkslateblue:483d8b,darkslategray:2f4f4f,darkturquoise:00ced1,darkviolet:9400d3,deeppink:ff1493,deepskyblue:00bfff,dimgray:696969,dodgerblue:1e90ff,firebrick:b22222,floralwhite:fffaf0,forestgreen:228b22,fuchsia:ff00ff,gainsboro:dcdcdc,ghostwhite:f8f8ff,gold:ffd700,goldenrod:daa520,gray:808080,green:008000,greenyellow:adff2f,honeydew:f0fff0,hotpink:ff69b4,indianred:cd5c5c,indigo:4b0082,ivory:fffff0,khaki:f0e68c,lavender:e6e6fa,lavenderblush:fff0f5,lawngreen:7cfc00,lemonchiffon:fffacd,lightblue:add8e6,lightcoral:f08080,lightcyan:e0ffff,lightgoldenrodyellow:fafad2,lightgrey:d3d3d3,lightgreen:90ee90,lightpink:ffb6c1,lightsalmon:ffa07a,lightseagreen:20b2aa,lightskyblue:87cefa,lightslategray:778899,lightsteelblue:b0c4de,lightyellow:ffffe0,lime:00ff00,limegreen:32cd32,linen:faf0e6,magenta:ff00ff,maroon:800000,mediumaquamarine:66cdaa,mediumblue:0000cd,mediumorchid:ba55d3,mediumpurple:9370d8,mediumseagreen:3cb371,mediumslateblue:7b68ee,mediumspringgreen:00fa9a,mediumturquoise:48d1cc,mediumvioletred:c71585,midnightblue:191970,mintcream:f5fffa,mistyrose:ffe4e1,moccasin:ffe4b5,navajowhite:ffdead,navy:000080,oldlace:fdf5e6,olive:808000,olivedrab:6b8e23,orange:ffa500,orangered:ff4500,orchid:da70d6,palegoldenrod:eee8aa,palegreen:98fb98,paleturquoise:afeeee,palevioletred:d87093,papayawhip:ffefd5,peachpuff:ffdab9,peru:cd853f,pink:ffc0cb,plum:dda0dd,powderblue:b0e0e6,purple:800080,rebeccapurple:663399,red:ff0000,rosybrown:bc8f8f,royalblue:4169e1,saddlebrown:8b4513,salmon:fa8072,sandybrown:f4a460,seagreen:2e8b57,seashell:fff5ee,sienna:a0522d,silver:c0c0c0,skyblue:87ceeb,slateblue:6a5acd,slategray:708090,snow:fffafa,springgreen:00ff7f,steelblue:4682b4,tan:d2b48c,teal:008080,thistle:d8bfd8,tomato:ff6347,turquoise:40e0d0,violet:ee82ee,wheat:f5deb3,white:ffffff,whitesmoke:f5f5f5,yellow:ffff00,yellowgreen:9acd32";
const makeMap = (str) => {
const map = /* @__PURE__ */ new Map();
const list = str.split(",");
for (let i = 0; i < list.length; i++) {
const [key, val] = list[i].split(":");
map.set(key, `#${val}`);
if (key.includes("gray")) map.set(key.replace("gray", "grey"), `#${val}`);
}
return map;
};
const nativeColorMap = makeMap(nativeColors);
//#endregion
//#region src/shared/color-utils/parse-color.ts
const parseColor = (value) => {
if (nativeColorMap.has(value)) return parseColor(nativeColorMap.get(value));
const result = RGBColor.parse(value) || HSBColor.parse(value) || HSLColor.parse(value);
if (!result) {
const error = /* @__PURE__ */ new Error("Invalid color value: " + value);
Error.captureStackTrace?.(error, parseColor);
throw error;
}
return result;
};
const normalizeColor = (v) => {
return typeof v === "string" ? parseColor(v) : v;
};
//#endregion
exports.Color = Color;
exports.getColorAreaGradient = getColorAreaGradient;
exports.normalizeColor = normalizeColor;
exports.parseColor = parseColor;
//#region src/shared/color-utils/types.d.ts
type ColorHexFormat = "hex" | "hexa";
type ColorFormat = "rgba" | "hsla" | "hsba";
type ColorStringFormat = ColorHexFormat | ColorFormat | "rgb" | "hsl" | "hsb" | "css";
type ColorChannel = "hue" | "saturation" | "brightness" | "lightness" | "red" | "green" | "blue" | "alpha";
interface Color2DAxes {
xChannel: ColorChannel;
yChannel: ColorChannel;
}
interface ColorAxes extends Color2DAxes {
zChannel: ColorChannel;
}
interface ColorChannelRange {
minValue: number;
maxValue: number;
step: number;
pageSize: number;
}
interface ColorType {
toFormat(format: ColorFormat): ColorType;
toJSON(): Record<string, number>;
toString(format?: ColorStringFormat): string;
toHexInt(): number;
getChannelValue(channel: ColorChannel): number;
withChannelValue(channel: ColorChannel, value: number): ColorType;
formatChannelValue(channel: ColorChannel, locale: string): string;
getChannelRange(channel: ColorChannel): ColorChannelRange;
getFormat(): ColorFormat;
getColorAxes(xyChannels: Color2DAxes): ColorAxes;
getChannels(): [ColorChannel, ColorChannel, ColorChannel];
clone(): ColorType;
isEqual(color: ColorType): boolean;
incrementChannel(channel: ColorChannel, stepSize: number): ColorType;
decrementChannel(channel: ColorChannel, stepSize: number): ColorType;
getChannelValuePercent(channel: ColorChannel, value?: number): number;
getChannelPercentValue(channel: ColorChannel, percent: number): number;
}
//#endregion
//#region src/shared/color-utils/color.d.ts
declare abstract class Color implements ColorType {
abstract toFormat(format: ColorFormat): ColorType;
abstract toJSON(): Record<string, number>;
abstract toString(format?: ColorStringFormat): string;
abstract clone(): ColorType;
abstract getChannelRange(channel: ColorChannel): ColorChannelRange;
abstract getFormat(): ColorFormat;
abstract getChannels(): [ColorChannel, ColorChannel, ColorChannel];
abstract formatChannelValue(channel: ColorChannel, locale: string): string;
toHexInt(): number;
getChannelValue(channel: ColorChannel): number;
getChannelValuePercent(channel: ColorChannel, valueToCheck?: number): number;
getChannelPercentValue(channel: ColorChannel, percentToCheck: number): number;
withChannelValue(channel: ColorChannel, value: number): ColorType;
getColorAxes(xyChannels: Color2DAxes): ColorAxes;
incrementChannel(channel: ColorChannel, stepSize: number): ColorType;
decrementChannel(channel: ColorChannel, stepSize: number): ColorType;
isEqual(color: ColorType): boolean;
}
//#endregion
//#region src/shared/color-utils/area-gradient.d.ts
interface GradientOptions {
xChannel: ColorChannel;
yChannel: ColorChannel;
dir?: "rtl" | "ltr" | undefined;
}
interface GradientStyles {
areaStyles: Record<string, string>;
areaGradientStyles: Record<string, string>;
}
declare function getColorAreaGradient(color: Color, options: GradientOptions): GradientStyles;
//#endregion
//#region src/shared/color-utils/parse-color.d.ts
declare const parseColor: (value: string) => ColorType;
declare const normalizeColor: (v: string | ColorType) => ColorType;
//#endregion
export { Color, ColorAxes, ColorChannel, ColorChannelRange, ColorFormat, ColorStringFormat, ColorType, getColorAreaGradient, normalizeColor, parseColor };
//#region src/shared/color-utils/types.d.ts
type ColorHexFormat = "hex" | "hexa";
type ColorFormat = "rgba" | "hsla" | "hsba";
type ColorStringFormat = ColorHexFormat | ColorFormat | "rgb" | "hsl" | "hsb" | "css";
type ColorChannel = "hue" | "saturation" | "brightness" | "lightness" | "red" | "green" | "blue" | "alpha";
interface Color2DAxes {
xChannel: ColorChannel;
yChannel: ColorChannel;
}
interface ColorAxes extends Color2DAxes {
zChannel: ColorChannel;
}
interface ColorChannelRange {
minValue: number;
maxValue: number;
step: number;
pageSize: number;
}
interface ColorType {
toFormat(format: ColorFormat): ColorType;
toJSON(): Record<string, number>;
toString(format?: ColorStringFormat): string;
toHexInt(): number;
getChannelValue(channel: ColorChannel): number;
withChannelValue(channel: ColorChannel, value: number): ColorType;
formatChannelValue(channel: ColorChannel, locale: string): string;
getChannelRange(channel: ColorChannel): ColorChannelRange;
getFormat(): ColorFormat;
getColorAxes(xyChannels: Color2DAxes): ColorAxes;
getChannels(): [ColorChannel, ColorChannel, ColorChannel];
clone(): ColorType;
isEqual(color: ColorType): boolean;
incrementChannel(channel: ColorChannel, stepSize: number): ColorType;
decrementChannel(channel: ColorChannel, stepSize: number): ColorType;
getChannelValuePercent(channel: ColorChannel, value?: number): number;
getChannelPercentValue(channel: ColorChannel, percent: number): number;
}
//#endregion
//#region src/shared/color-utils/color.d.ts
declare abstract class Color implements ColorType {
abstract toFormat(format: ColorFormat): ColorType;
abstract toJSON(): Record<string, number>;
abstract toString(format?: ColorStringFormat): string;
abstract clone(): ColorType;
abstract getChannelRange(channel: ColorChannel): ColorChannelRange;
abstract getFormat(): ColorFormat;
abstract getChannels(): [ColorChannel, ColorChannel, ColorChannel];
abstract formatChannelValue(channel: ColorChannel, locale: string): string;
toHexInt(): number;
getChannelValue(channel: ColorChannel): number;
getChannelValuePercent(channel: ColorChannel, valueToCheck?: number): number;
getChannelPercentValue(channel: ColorChannel, percentToCheck: number): number;
withChannelValue(channel: ColorChannel, value: number): ColorType;
getColorAxes(xyChannels: Color2DAxes): ColorAxes;
incrementChannel(channel: ColorChannel, stepSize: number): ColorType;
decrementChannel(channel: ColorChannel, stepSize: number): ColorType;
isEqual(color: ColorType): boolean;
}
//#endregion
//#region src/shared/color-utils/area-gradient.d.ts
interface GradientOptions {
xChannel: ColorChannel;
yChannel: ColorChannel;
dir?: "rtl" | "ltr" | undefined;
}
interface GradientStyles {
areaStyles: Record<string, string>;
areaGradientStyles: Record<string, string>;
}
declare function getColorAreaGradient(color: Color, options: GradientOptions): GradientStyles;
//#endregion
//#region src/shared/color-utils/parse-color.d.ts
declare const parseColor: (value: string) => ColorType;
declare const normalizeColor: (v: string | ColorType) => ColorType;
//#endregion
export { Color, ColorAxes, ColorChannel, ColorChannelRange, ColorFormat, ColorStringFormat, ColorType, getColorAreaGradient, normalizeColor, parseColor };
import { clampValue, getPercentValue, getValuePercent, mod, snapValueToStep, toFixedNumber } from "@ginxjs/core/utils";
//#region src/shared/color-utils/color-format-gradient.ts
const generateRGB_R = (orientation, dir, zValue) => {
const maskImage = `linear-gradient(to ${orientation[Number(!dir)]}, transparent, #000)`;
return {
areaStyles: { backgroundImage: `linear-gradient(to ${orientation[Number(dir)]},rgb(${zValue},0,0),rgb(${zValue},255,0))` },
areaGradientStyles: {
backgroundImage: `linear-gradient(to ${orientation[Number(dir)]},rgb(${zValue},0,255),rgb(${zValue},255,255))`,
WebkitMaskImage: maskImage,
maskImage
}
};
};
const generateRGB_G = (orientation, dir, zValue) => {
const maskImage = `linear-gradient(to ${orientation[Number(!dir)]}, transparent, #000)`;
return {
areaStyles: { backgroundImage: `linear-gradient(to ${orientation[Number(dir)]},rgb(0,${zValue},0),rgb(255,${zValue},0))` },
areaGradientStyles: {
backgroundImage: `linear-gradient(to ${orientation[Number(dir)]},rgb(0,${zValue},255),rgb(255,${zValue},255))`,
WebkitMaskImage: maskImage,
maskImage
}
};
};
const generateRGB_B = (orientation, dir, zValue) => {
const maskImage = `linear-gradient(to ${orientation[Number(!dir)]}, transparent, #000)`;
return {
areaStyles: { backgroundImage: `linear-gradient(to ${orientation[Number(dir)]},rgb(0,0,${zValue}),rgb(255,0,${zValue}))` },
areaGradientStyles: {
backgroundImage: `linear-gradient(to ${orientation[Number(dir)]},rgb(0,255,${zValue}),rgb(255,255,${zValue}))`,
WebkitMaskImage: maskImage,
maskImage
}
};
};
const generateHSL_H = (orientation, dir, zValue) => {
return {
areaStyles: {},
areaGradientStyles: { background: [
`linear-gradient(to ${orientation[Number(dir)]}, hsla(0,0%,0%,1) 0%, hsla(0,0%,0%,0) 50%, hsla(0,0%,100%,0) 50%, hsla(0,0%,100%,1) 100%)`,
`linear-gradient(to ${orientation[Number(!dir)]},hsl(0,0%,50%),hsla(0,0%,50%,0))`,
`hsl(${zValue}, 100%, 50%)`
].join(",") }
};
};
const generateHSL_S = (orientation, dir, alphaValue) => {
return {
areaStyles: {},
areaGradientStyles: { background: [
`linear-gradient(to ${orientation[Number(!dir)]}, hsla(0,0%,0%,${alphaValue}) 0%, hsla(0,0%,0%,0) 50%, hsla(0,0%,100%,0) 50%, hsla(0,0%,100%,${alphaValue}) 100%)`,
`linear-gradient(to ${orientation[Number(dir)]},hsla(0,100%,50%,${alphaValue}),hsla(60,100%,50%,${alphaValue}),hsla(120,100%,50%,${alphaValue}),hsla(180,100%,50%,${alphaValue}),hsla(240,100%,50%,${alphaValue}),hsla(300,100%,50%,${alphaValue}),hsla(359,100%,50%,${alphaValue}))`,
"hsl(0, 0%, 50%)"
].join(",") }
};
};
const generateHSL_L = (orientation, dir, zValue) => {
return {
areaStyles: {},
areaGradientStyles: { backgroundImage: [`linear-gradient(to ${orientation[Number(!dir)]},hsl(0,0%,${zValue}%),hsla(0,0%,${zValue}%,0))`, `linear-gradient(to ${orientation[Number(dir)]},hsl(0,100%,${zValue}%),hsl(60,100%,${zValue}%),hsl(120,100%,${zValue}%),hsl(180,100%,${zValue}%),hsl(240,100%,${zValue}%),hsl(300,100%,${zValue}%),hsl(360,100%,${zValue}%))`].join(",") }
};
};
const generateHSB_H = (orientation, dir, zValue) => {
return {
areaStyles: {},
areaGradientStyles: { background: [
`linear-gradient(to ${orientation[Number(dir)]},hsl(0,0%,0%),hsla(0,0%,0%,0))`,
`linear-gradient(to ${orientation[Number(!dir)]},hsl(0,0%,100%),hsla(0,0%,100%,0))`,
`hsl(${zValue}, 100%, 50%)`
].join(",") }
};
};
const generateHSB_S = (orientation, dir, alphaValue) => {
return {
areaStyles: {},
areaGradientStyles: { background: [
`linear-gradient(to ${orientation[Number(!dir)]},hsla(0,0%,0%,${alphaValue}),hsla(0,0%,0%,0))`,
`linear-gradient(to ${orientation[Number(dir)]},hsla(0,100%,50%,${alphaValue}),hsla(60,100%,50%,${alphaValue}),hsla(120,100%,50%,${alphaValue}),hsla(180,100%,50%,${alphaValue}),hsla(240,100%,50%,${alphaValue}),hsla(300,100%,50%,${alphaValue}),hsla(359,100%,50%,${alphaValue}))`,
`linear-gradient(to ${orientation[Number(!dir)]},hsl(0,0%,0%),hsl(0,0%,100%))`
].join(",") }
};
};
const generateHSB_B = (orientation, dir, alphaValue) => {
return {
areaStyles: {},
areaGradientStyles: { background: [
`linear-gradient(to ${orientation[Number(!dir)]},hsla(0,0%,100%,${alphaValue}),hsla(0,0%,100%,0))`,
`linear-gradient(to ${orientation[Number(dir)]},hsla(0,100%,50%,${alphaValue}),hsla(60,100%,50%,${alphaValue}),hsla(120,100%,50%,${alphaValue}),hsla(180,100%,50%,${alphaValue}),hsla(240,100%,50%,${alphaValue}),hsla(300,100%,50%,${alphaValue}),hsla(359,100%,50%,${alphaValue}))`,
"#000"
].join(",") }
};
};
//#endregion
//#region src/shared/color-utils/area-gradient.ts
function getColorAreaGradient(color, options) {
const { xChannel, yChannel, dir: dirProp = "ltr" } = options;
const { zChannel } = color.getColorAxes({
xChannel,
yChannel
});
const zValue = color.getChannelValue(zChannel);
const { minValue: zMin, maxValue: zMax } = color.getChannelRange(zChannel);
const orientation = ["top", dirProp === "rtl" ? "left" : "right"];
let dir = false;
let background = {
areaStyles: {},
areaGradientStyles: {}
};
let alphaValue = (zValue - zMin) / (zMax - zMin);
let isHSL = color.getFormat() === "hsla";
switch (zChannel) {
case "red":
dir = xChannel === "green";
background = generateRGB_R(orientation, dir, zValue);
break;
case "green":
dir = xChannel === "red";
background = generateRGB_G(orientation, dir, zValue);
break;
case "blue":
dir = xChannel === "red";
background = generateRGB_B(orientation, dir, zValue);
break;
case "hue":
dir = xChannel !== "saturation";
if (isHSL) background = generateHSL_H(orientation, dir, zValue);
else background = generateHSB_H(orientation, dir, zValue);
break;
case "saturation":
dir = xChannel === "hue";
if (isHSL) background = generateHSL_S(orientation, dir, alphaValue);
else background = generateHSB_S(orientation, dir, alphaValue);
break;
case "brightness":
dir = xChannel === "hue";
background = generateHSB_B(orientation, dir, alphaValue);
break;
case "lightness":
dir = xChannel === "hue";
background = generateHSL_L(orientation, dir, zValue);
break;
}
return background;
}
//#endregion
//#region src/shared/color-utils/color.ts
const isEqualObject = (a, b) => {
if (Object.keys(a).length !== Object.keys(b).length) return false;
for (let key in a) if (a[key] !== b[key]) return false;
return true;
};
var Color = class {
toHexInt() {
return this.toFormat("rgba").toHexInt();
}
getChannelValue(channel) {
if (channel in this) return this[channel];
throw new Error("Unsupported color channel: " + channel);
}
getChannelValuePercent(channel, valueToCheck) {
const value = valueToCheck ?? this.getChannelValue(channel);
const { minValue, maxValue } = this.getChannelRange(channel);
return getValuePercent(value, minValue, maxValue);
}
getChannelPercentValue(channel, percentToCheck) {
const { minValue, maxValue, step } = this.getChannelRange(channel);
return snapValueToStep(getPercentValue(percentToCheck, minValue, maxValue, step), minValue, maxValue, step);
}
withChannelValue(channel, value) {
const { minValue, maxValue } = this.getChannelRange(channel);
if (channel in this) {
let clone = this.clone();
clone[channel] = clampValue(value, minValue, maxValue);
return clone;
}
throw new Error("Unsupported color channel: " + channel);
}
getColorAxes(xyChannels) {
let { xChannel, yChannel } = xyChannels;
let xCh = xChannel || this.getChannels().find((c) => c !== yChannel);
let yCh = yChannel || this.getChannels().find((c) => c !== xCh);
return {
xChannel: xCh,
yChannel: yCh,
zChannel: this.getChannels().find((c) => c !== xCh && c !== yCh)
};
}
incrementChannel(channel, stepSize) {
const { minValue, maxValue, step } = this.getChannelRange(channel);
const value = snapValueToStep(clampValue(this.getChannelValue(channel) + stepSize, minValue, maxValue), minValue, maxValue, step);
return this.withChannelValue(channel, value);
}
decrementChannel(channel, stepSize) {
return this.incrementChannel(channel, -stepSize);
}
isEqual(color) {
return isEqualObject(this.toJSON(), color.toJSON()) && this.getChannelValue("alpha") === color.getChannelValue("alpha");
}
};
//#endregion
//#region src/shared/color-utils/rgb-color.ts
const HEX_COLOR_REGEX = /^#[\da-f]+$/i;
const RGB_COLOR_REGEX = /^rgba?\((.*)\)$/;
const HEX_STARTING_REGEX = /[^#]/gi;
var RGBColor = class RGBColor extends Color {
red;
green;
blue;
alpha;
constructor(red, green, blue, alpha) {
super();
this.red = red;
this.green = green;
this.blue = blue;
this.alpha = alpha;
}
static parse(value) {
let colors = [];
if (HEX_COLOR_REGEX.test(value) && [
4,
5,
7,
9
].includes(value.length)) {
const values = (value.length < 6 ? value.replace(HEX_STARTING_REGEX, "$&$&") : value).slice(1).split("");
while (values.length > 0) colors.push(parseInt(values.splice(0, 2).join(""), 16));
colors[3] = colors[3] !== void 0 ? colors[3] / 255 : void 0;
}
const match = value.match(RGB_COLOR_REGEX);
if (match?.[1]) colors = match[1].split(",").map((value) => Number(value.trim())).map((num, i) => clampValue(num, 0, i < 3 ? 255 : 1));
return colors.length < 3 ? void 0 : new RGBColor(colors[0], colors[1], colors[2], colors[3] ?? 1);
}
toString(format = "css") {
switch (format) {
case "hex": return "#" + (this.red.toString(16).padStart(2, "0") + this.green.toString(16).padStart(2, "0") + this.blue.toString(16).padStart(2, "0")).toUpperCase();
case "hexa": return "#" + (this.red.toString(16).padStart(2, "0") + this.green.toString(16).padStart(2, "0") + this.blue.toString(16).padStart(2, "0") + Math.round(this.alpha * 255).toString(16).padStart(2, "0")).toUpperCase();
case "rgb": return `rgb(${this.red}, ${this.green}, ${this.blue})`;
case "css":
case "rgba": return `rgba(${this.red}, ${this.green}, ${this.blue}, ${this.alpha})`;
case "hsl": return this.toHSL().toString("hsl");
case "hsb": return this.toHSB().toString("hsb");
default: return this.toFormat(format).toString(format);
}
}
toFormat(format) {
switch (format) {
case "rgba": return this;
case "hsba": return this.toHSB();
case "hsla": return this.toHSL();
default: throw new Error("Unsupported color conversion: rgb -> " + format);
}
}
toHexInt() {
return this.red << 16 | this.green << 8 | this.blue;
}
toHSB() {
const red = this.red / 255;
const green = this.green / 255;
const blue = this.blue / 255;
const min = Math.min(red, green, blue);
const brightness = Math.max(red, green, blue);
const chroma = brightness - min;
const saturation = brightness === 0 ? 0 : chroma / brightness;
let hue = 0;
if (chroma !== 0) {
switch (brightness) {
case red:
hue = (green - blue) / chroma + (green < blue ? 6 : 0);
break;
case green:
hue = (blue - red) / chroma + 2;
break;
case blue:
hue = (red - green) / chroma + 4;
break;
}
hue /= 6;
}
return new HSBColor(toFixedNumber(hue * 360, 2), toFixedNumber(saturation * 100, 2), toFixedNumber(brightness * 100, 2), toFixedNumber(this.alpha, 2));
}
toHSL() {
const red = this.red / 255;
const green = this.green / 255;
const blue = this.blue / 255;
const min = Math.min(red, green, blue);
const max = Math.max(red, green, blue);
const lightness = (max + min) / 2;
const chroma = max - min;
let hue = -1;
let saturation = -1;
if (chroma === 0) hue = saturation = 0;
else {
saturation = chroma / (lightness < .5 ? max + min : 2 - max - min);
switch (max) {
case red:
hue = (green - blue) / chroma + (green < blue ? 6 : 0);
break;
case green:
hue = (blue - red) / chroma + 2;
break;
case blue:
hue = (red - green) / chroma + 4;
break;
}
hue /= 6;
}
return new HSLColor(toFixedNumber(hue * 360, 2), toFixedNumber(saturation * 100, 2), toFixedNumber(lightness * 100, 2), toFixedNumber(this.alpha, 2));
}
clone() {
return new RGBColor(this.red, this.green, this.blue, this.alpha);
}
getChannelFormatOptions(channel) {
switch (channel) {
case "red":
case "green":
case "blue": return { style: "decimal" };
case "alpha": return { style: "percent" };
default: throw new Error("Unknown color channel: " + channel);
}
}
formatChannelValue(channel, locale) {
let options = this.getChannelFormatOptions(channel);
let value = this.getChannelValue(channel);
return new Intl.NumberFormat(locale, options).format(value);
}
getChannelRange(channel) {
switch (channel) {
case "red":
case "green":
case "blue": return {
minValue: 0,
maxValue: 255,
step: 1,
pageSize: 17
};
case "alpha": return {
minValue: 0,
maxValue: 1,
step: .01,
pageSize: .1
};
default: throw new Error("Unknown color channel: " + channel);
}
}
toJSON() {
return {
r: this.red,
g: this.green,
b: this.blue,
a: this.alpha
};
}
getFormat() {
return "rgba";
}
static colorChannels = [
"red",
"green",
"blue"
];
getChannels() {
return RGBColor.colorChannels;
}
};
//#endregion
//#region src/shared/color-utils/hsl-color.ts
const HSL_REGEX = /hsl\(([-+]?\d+(?:.\d+)?\s*,\s*[-+]?\d+(?:.\d+)?%\s*,\s*[-+]?\d+(?:.\d+)?%)\)|hsla\(([-+]?\d+(?:.\d+)?\s*,\s*[-+]?\d+(?:.\d+)?%\s*,\s*[-+]?\d+(?:.\d+)?%\s*,\s*[-+]?\d(.\d+)?)\)/;
var HSLColor = class HSLColor extends Color {
hue;
saturation;
lightness;
alpha;
constructor(hue, saturation, lightness, alpha) {
super();
this.hue = hue;
this.saturation = saturation;
this.lightness = lightness;
this.alpha = alpha;
}
static parse(value) {
let m;
if (m = value.match(HSL_REGEX)) {
const [h, s, l, a] = (m[1] ?? m[2]).split(",").map((n) => Number(n.trim().replace("%", "")));
return new HSLColor(mod(h, 360), clampValue(s, 0, 100), clampValue(l, 0, 100), clampValue(a ?? 1, 0, 1));
}
}
toString(format = "css") {
switch (format) {
case "hex": return this.toRGB().toString("hex");
case "hexa": return this.toRGB().toString("hexa");
case "hsl": return `hsl(${this.hue}, ${toFixedNumber(this.saturation, 2)}%, ${toFixedNumber(this.lightness, 2)}%)`;
case "css":
case "hsla": return `hsla(${this.hue}, ${toFixedNumber(this.saturation, 2)}%, ${toFixedNumber(this.lightness, 2)}%, ${this.alpha})`;
case "hsb": return this.toHSB().toString("hsb");
case "rgb": return this.toRGB().toString("rgb");
default: return this.toFormat(format).toString(format);
}
}
toFormat(format) {
switch (format) {
case "hsla": return this;
case "hsba": return this.toHSB();
case "rgba": return this.toRGB();
default: throw new Error("Unsupported color conversion: hsl -> " + format);
}
}
toHSB() {
let saturation = this.saturation / 100;
let lightness = this.lightness / 100;
let brightness = lightness + saturation * Math.min(lightness, 1 - lightness);
saturation = brightness === 0 ? 0 : 2 * (1 - lightness / brightness);
return new HSBColor(toFixedNumber(this.hue, 2), toFixedNumber(saturation * 100, 2), toFixedNumber(brightness * 100, 2), toFixedNumber(this.alpha, 2));
}
toRGB() {
let hue = this.hue;
let saturation = this.saturation / 100;
let lightness = this.lightness / 100;
let a = saturation * Math.min(lightness, 1 - lightness);
let fn = (n, k = (n + hue / 30) % 12) => lightness - a * Math.max(Math.min(k - 3, 9 - k, 1), -1);
return new RGBColor(Math.round(fn(0) * 255), Math.round(fn(8) * 255), Math.round(fn(4) * 255), toFixedNumber(this.alpha, 2));
}
clone() {
return new HSLColor(this.hue, this.saturation, this.lightness, this.alpha);
}
getChannelFormatOptions(channel) {
switch (channel) {
case "hue": return {
style: "unit",
unit: "degree",
unitDisplay: "narrow"
};
case "saturation":
case "lightness":
case "alpha": return { style: "percent" };
default: throw new Error("Unknown color channel: " + channel);
}
}
formatChannelValue(channel, locale) {
let options = this.getChannelFormatOptions(channel);
let value = this.getChannelValue(channel);
if (channel === "saturation" || channel === "lightness") value /= 100;
return new Intl.NumberFormat(locale, options).format(value);
}
getChannelRange(channel) {
switch (channel) {
case "hue": return {
minValue: 0,
maxValue: 360,
step: 1,
pageSize: 15
};
case "saturation":
case "lightness": return {
minValue: 0,
maxValue: 100,
step: 1,
pageSize: 10
};
case "alpha": return {
minValue: 0,
maxValue: 1,
step: .01,
pageSize: .1
};
default: throw new Error("Unknown color channel: " + channel);
}
}
toJSON() {
return {
h: this.hue,
s: this.saturation,
l: this.lightness,
a: this.alpha
};
}
getFormat() {
return "hsla";
}
static colorChannels = [
"hue",
"saturation",
"lightness"
];
getChannels() {
return HSLColor.colorChannels;
}
};
//#endregion
//#region src/shared/color-utils/hsb-color.ts
const HSB_REGEX = /hsb\(([-+]?\d+(?:.\d+)?\s*,\s*[-+]?\d+(?:.\d+)?%\s*,\s*[-+]?\d+(?:.\d+)?%)\)|hsba\(([-+]?\d+(?:.\d+)?\s*,\s*[-+]?\d+(?:.\d+)?%\s*,\s*[-+]?\d+(?:.\d+)?%\s*,\s*[-+]?\d(.\d+)?)\)/;
var HSBColor = class HSBColor extends Color {
hue;
saturation;
brightness;
alpha;
constructor(hue, saturation, brightness, alpha) {
super();
this.hue = hue;
this.saturation = saturation;
this.brightness = brightness;
this.alpha = alpha;
}
static parse(value) {
let m;
if (m = value.match(HSB_REGEX)) {
const [h, s, b, a] = (m[1] ?? m[2]).split(",").map((n) => Number(n.trim().replace("%", "")));
return new HSBColor(mod(h, 360), clampValue(s, 0, 100), clampValue(b, 0, 100), clampValue(a ?? 1, 0, 1));
}
}
toString(format = "css") {
switch (format) {
case "css": return this.toHSL().toString("css");
case "hex": return this.toRGB().toString("hex");
case "hexa": return this.toRGB().toString("hexa");
case "hsb": return `hsb(${this.hue}, ${toFixedNumber(this.saturation, 2)}%, ${toFixedNumber(this.brightness, 2)}%)`;
case "hsba": return `hsba(${this.hue}, ${toFixedNumber(this.saturation, 2)}%, ${toFixedNumber(this.brightness, 2)}%, ${this.alpha})`;
case "hsl": return this.toHSL().toString("hsl");
case "rgb": return this.toRGB().toString("rgb");
default: return this.toFormat(format).toString(format);
}
}
toFormat(format) {
switch (format) {
case "hsba": return this;
case "hsla": return this.toHSL();
case "rgba": return this.toRGB();
default: throw new Error("Unsupported color conversion: hsb -> " + format);
}
}
toHSL() {
let saturation = this.saturation / 100;
let brightness = this.brightness / 100;
let lightness = brightness * (1 - saturation / 2);
saturation = lightness === 0 || lightness === 1 ? 0 : (brightness - lightness) / Math.min(lightness, 1 - lightness);
return new HSLColor(toFixedNumber(this.hue, 2), toFixedNumber(saturation * 100, 2), toFixedNumber(lightness * 100, 2), toFixedNumber(this.alpha, 2));
}
toRGB() {
let hue = this.hue;
let saturation = this.saturation / 100;
let brightness = this.brightness / 100;
let fn = (n, k = (n + hue / 60) % 6) => brightness - saturation * brightness * Math.max(Math.min(k, 4 - k, 1), 0);
return new RGBColor(Math.round(fn(5) * 255), Math.round(fn(3) * 255), Math.round(fn(1) * 255), toFixedNumber(this.alpha, 2));
}
clone() {
return new HSBColor(this.hue, this.saturation, this.brightness, this.alpha);
}
getChannelFormatOptions(channel) {
switch (channel) {
case "hue": return {
style: "unit",
unit: "degree",
unitDisplay: "narrow"
};
case "saturation":
case "brightness":
case "alpha": return { style: "percent" };
default: throw new Error("Unknown color channel: " + channel);
}
}
formatChannelValue(channel, locale) {
let options = this.getChannelFormatOptions(channel);
let value = this.getChannelValue(channel);
if (channel === "saturation" || channel === "brightness") value /= 100;
return new Intl.NumberFormat(locale, options).format(value);
}
getChannelRange(channel) {
switch (channel) {
case "hue": return {
minValue: 0,
maxValue: 360,
step: 1,
pageSize: 15
};
case "saturation":
case "brightness": return {
minValue: 0,
maxValue: 100,
step: 1,
pageSize: 10
};
case "alpha": return {
minValue: 0,
maxValue: 1,
step: .01,
pageSize: .1
};
default: throw new Error("Unknown color channel: " + channel);
}
}
toJSON() {
return {
h: this.hue,
s: this.saturation,
b: this.brightness,
a: this.alpha
};
}
getFormat() {
return "hsba";
}
static colorChannels = [
"hue",
"saturation",
"brightness"
];
getChannels() {
return HSBColor.colorChannels;
}
};
//#endregion
//#region src/shared/color-utils/native-color.ts
const nativeColors = "aliceblue:f0f8ff,antiquewhite:faebd7,aqua:00ffff,aquamarine:7fffd4,azure:f0ffff,beige:f5f5dc,bisque:ffe4c4,black:000000,blanchedalmond:ffebcd,blue:0000ff,blueviolet:8a2be2,brown:a52a2a,burlywood:deb887,cadetblue:5f9ea0,chartreuse:7fff00,chocolate:d2691e,coral:ff7f50,cornflowerblue:6495ed,cornsilk:fff8dc,crimson:dc143c,cyan:00ffff,darkblue:00008b,darkcyan:008b8b,darkgoldenrod:b8860b,darkgray:a9a9a9,darkgreen:006400,darkkhaki:bdb76b,darkmagenta:8b008b,darkolivegreen:556b2f,darkorange:ff8c00,darkorchid:9932cc,darkred:8b0000,darksalmon:e9967a,darkseagreen:8fbc8f,darkslateblue:483d8b,darkslategray:2f4f4f,darkturquoise:00ced1,darkviolet:9400d3,deeppink:ff1493,deepskyblue:00bfff,dimgray:696969,dodgerblue:1e90ff,firebrick:b22222,floralwhite:fffaf0,forestgreen:228b22,fuchsia:ff00ff,gainsboro:dcdcdc,ghostwhite:f8f8ff,gold:ffd700,goldenrod:daa520,gray:808080,green:008000,greenyellow:adff2f,honeydew:f0fff0,hotpink:ff69b4,indianred:cd5c5c,indigo:4b0082,ivory:fffff0,khaki:f0e68c,lavender:e6e6fa,lavenderblush:fff0f5,lawngreen:7cfc00,lemonchiffon:fffacd,lightblue:add8e6,lightcoral:f08080,lightcyan:e0ffff,lightgoldenrodyellow:fafad2,lightgrey:d3d3d3,lightgreen:90ee90,lightpink:ffb6c1,lightsalmon:ffa07a,lightseagreen:20b2aa,lightskyblue:87cefa,lightslategray:778899,lightsteelblue:b0c4de,lightyellow:ffffe0,lime:00ff00,limegreen:32cd32,linen:faf0e6,magenta:ff00ff,maroon:800000,mediumaquamarine:66cdaa,mediumblue:0000cd,mediumorchid:ba55d3,mediumpurple:9370d8,mediumseagreen:3cb371,mediumslateblue:7b68ee,mediumspringgreen:00fa9a,mediumturquoise:48d1cc,mediumvioletred:c71585,midnightblue:191970,mintcream:f5fffa,mistyrose:ffe4e1,moccasin:ffe4b5,navajowhite:ffdead,navy:000080,oldlace:fdf5e6,olive:808000,olivedrab:6b8e23,orange:ffa500,orangered:ff4500,orchid:da70d6,palegoldenrod:eee8aa,palegreen:98fb98,paleturquoise:afeeee,palevioletred:d87093,papayawhip:ffefd5,peachpuff:ffdab9,peru:cd853f,pink:ffc0cb,plum:dda0dd,powderblue:b0e0e6,purple:800080,rebeccapurple:663399,red:ff0000,rosybrown:bc8f8f,royalblue:4169e1,saddlebrown:8b4513,salmon:fa8072,sandybrown:f4a460,seagreen:2e8b57,seashell:fff5ee,sienna:a0522d,silver:c0c0c0,skyblue:87ceeb,slateblue:6a5acd,slategray:708090,snow:fffafa,springgreen:00ff7f,steelblue:4682b4,tan:d2b48c,teal:008080,thistle:d8bfd8,tomato:ff6347,turquoise:40e0d0,violet:ee82ee,wheat:f5deb3,white:ffffff,whitesmoke:f5f5f5,yellow:ffff00,yellowgreen:9acd32";
const makeMap = (str) => {
const map = /* @__PURE__ */ new Map();
const list = str.split(",");
for (let i = 0; i < list.length; i++) {
const [key, val] = list[i].split(":");
map.set(key, `#${val}`);
if (key.includes("gray")) map.set(key.replace("gray", "grey"), `#${val}`);
}
return map;
};
const nativeColorMap = makeMap(nativeColors);
//#endregion
//#region src/shared/color-utils/parse-color.ts
const parseColor = (value) => {
if (nativeColorMap.has(value)) return parseColor(nativeColorMap.get(value));
const result = RGBColor.parse(value) || HSBColor.parse(value) || HSLColor.parse(value);
if (!result) {
const error = /* @__PURE__ */ new Error("Invalid color value: " + value);
Error.captureStackTrace?.(error, parseColor);
throw error;
}
return result;
};
const normalizeColor = (v) => {
return typeof v === "string" ? parseColor(v) : v;
};
//#endregion
export { Color, getColorAreaGradient, normalizeColor, parseColor };
import { rn as getDocument, tn as getActiveElement, un as isActiveElement } from "./dom-query-BgxIO7_X.mjs";
import { callAll, ensure, invariant, isEqual, isString } from "@ginxjs/core/utils";
//#region src/shared/core/merge-props.ts
const clsx = (...args) => args.map((str) => str?.trim?.()).filter(Boolean).join(" ");
const CSS_REGEX = /((?:--)?(?:\w+-?)+)\s*:\s*([^;]*)/g;
const serialize = (style) => {
const res = {};
let match;
while (match = CSS_REGEX.exec(style)) res[match[1]] = match[2];
return res;
};
const css = (a, b) => {
if (isString(a)) {
if (isString(b)) return `${a};${b}`;
a = serialize(a);
} else if (isString(b)) b = serialize(b);
return Object.assign({}, a ?? {}, b ?? {});
};
function mergeProps(...args) {
let result = {};
for (let props of args) {
if (!props) continue;
for (let key in result) {
if (key.startsWith("on") && typeof result[key] === "function" && typeof props[key] === "function") {
result[key] = callAll(props[key], result[key]);
continue;
}
if (key === "className" || key === "class") {
result[key] = clsx(result[key], props[key]);
continue;
}
if (key === "style") {
result[key] = css(result[key], props[key]);
continue;
}
result[key] = props[key] !== void 0 ? props[key] : result[key];
}
for (let key in props) if (result[key] === void 0) result[key] = props[key];
const symbols = Object.getOwnPropertySymbols(props);
for (let symbol of symbols) result[symbol] = props[symbol];
}
return result;
}
//#endregion
//#region src/shared/core/memo.ts
function memo(getDeps, fn, opts) {
let deps = [];
let result;
return (depArgs) => {
const newDeps = getDeps(depArgs);
if (!(newDeps.length !== deps.length || newDeps.some((dep, index) => !isEqual(deps[index], dep)))) return result;
deps = newDeps;
result = fn(newDeps, depArgs);
opts?.onChange?.(result);
return result;
};
}
//#endregion
//#region src/shared/core/state.ts
const STATE_DELIMITER = ".";
const ABSOLUTE_PREFIX = "#";
const stateIndexCache = /* @__PURE__ */ new WeakMap();
const stateIdIndexCache = /* @__PURE__ */ new WeakMap();
function joinStatePath(parts) {
return parts.join(STATE_DELIMITER);
}
function isAbsoluteStatePath(value) {
return value.includes(STATE_DELIMITER);
}
function isExplicitAbsoluteStatePath(value) {
return value.startsWith(ABSOLUTE_PREFIX);
}
function isChildTarget(value) {
return value.startsWith(STATE_DELIMITER);
}
function stripAbsolutePrefix(value) {
return isExplicitAbsoluteStatePath(value) ? value.slice(1) : value;
}
function appendStatePath(base, segment) {
return base ? `${base}${STATE_DELIMITER}${segment}` : segment;
}
function buildStateIndex(machine) {
const index = /* @__PURE__ */ new Map();
const idIndex = /* @__PURE__ */ new Map();
const visit = (basePath, state) => {
index.set(basePath, state);
const stateId = state.id;
if (stateId) {
if (idIndex.has(stateId)) invariant(`[ginxjs] Duplicate state id: "${stateId}"`);
idIndex.set(stateId, basePath);
}
const childStates = state.states;
if (!childStates) return;
ensure(state.initial, () => `[ginxjs] Compound state "${basePath}" has child states but no "initial" property`);
if (!(state.initial in childStates)) invariant(`[ginxjs] Compound state "${basePath}" has initial "${String(state.initial)}" which is not a child state`);
for (const [childKey, childState] of Object.entries(childStates)) {
if (!childState) continue;
visit(appendStatePath(basePath, childKey), childState);
}
};
for (const [topKey, topState] of Object.entries(machine.states)) {
if (!topState) continue;
visit(topKey, topState);
}
return {
index,
idIndex
};
}
function ensureStateIndex(machine) {
const cached = stateIndexCache.get(machine);
if (cached) return cached;
const { index, idIndex } = buildStateIndex(machine);
stateIndexCache.set(machine, index);
stateIdIndexCache.set(machine, idIndex);
return index;
}
function getStatePathById(machine, stateId) {
ensureStateIndex(machine);
return stateIdIndexCache.get(machine)?.get(stateId);
}
function toSegments(value) {
if (!value) return [];
return String(value).split(STATE_DELIMITER).filter(Boolean);
}
function getStateChain(machine, state) {
if (!state) return [];
const stateIndex = ensureStateIndex(machine);
const segments = toSegments(state);
const chain = [];
const statePath = [];
for (const segment of segments) {
statePath.push(segment);
const path = joinStatePath(statePath);
const current = stateIndex.get(path);
if (!current) break;
chain.push({
path,
state: current
});
}
return chain;
}
function resolveAbsoluteStateValue(machine, value) {
const stateIndex = ensureStateIndex(machine);
const segments = toSegments(value);
if (!segments.length) return value;
const resolved = [];
for (const segment of segments) {
resolved.push(segment);
const path = joinStatePath(resolved);
if (!stateIndex.has(path)) return value;
}
let resolvedPath = joinStatePath(resolved);
let current = stateIndex.get(resolvedPath);
while (current?.initial) {
const nextPath = `${resolvedPath}${STATE_DELIMITER}${current.initial}`;
const nextState = stateIndex.get(nextPath);
if (!nextState) break;
resolvedPath = nextPath;
current = nextState;
}
return resolvedPath;
}
function hasStatePath(machine, value) {
return ensureStateIndex(machine).has(value);
}
function resolveStateValue(machine, value, source) {
const stateValue = String(value);
if (isExplicitAbsoluteStatePath(stateValue)) {
const stateId = stripAbsolutePrefix(stateValue);
const statePath = getStatePathById(machine, stateId);
ensure(statePath, () => `[ginxjs] Unknown state id: "${stateId}"`);
return resolveAbsoluteStateValue(machine, statePath);
}
if (isChildTarget(stateValue) && source) return resolveAbsoluteStateValue(machine, appendStatePath(source, stateValue.slice(1)));
if (!isAbsoluteStatePath(stateValue) && source) {
const sourceSegments = toSegments(source);
for (let index = sourceSegments.length - 1; index >= 1; index--) {
const candidate = appendStatePath(sourceSegments.slice(0, index).join(STATE_DELIMITER), stateValue);
if (hasStatePath(machine, candidate)) return resolveAbsoluteStateValue(machine, candidate);
}
if (hasStatePath(machine, stateValue)) return resolveAbsoluteStateValue(machine, stateValue);
}
return resolveAbsoluteStateValue(machine, stateValue);
}
function getStateDefinition(machine, state) {
const chain = getStateChain(machine, state);
return chain[chain.length - 1]?.state;
}
function findTransition(machine, state, eventType) {
const chain = getStateChain(machine, state);
for (let index = chain.length - 1; index >= 0; index--) {
const transition = (chain[index]?.state.on)?.[eventType];
if (transition) return {
transitions: transition,
source: chain[index]?.path
};
}
return {
transitions: machine.on?.[eventType],
source: void 0
};
}
function getExitEnterStates(machine, prevState, nextState, reenter) {
const prevChain = prevState ? getStateChain(machine, prevState) : [];
const nextChain = getStateChain(machine, nextState);
let commonIndex = 0;
while (commonIndex < prevChain.length && commonIndex < nextChain.length && prevChain[commonIndex]?.path === nextChain[commonIndex]?.path) commonIndex += 1;
let exiting = prevChain.slice(commonIndex).reverse();
let entering = nextChain.slice(commonIndex);
const sameLeaf = prevChain.at(-1)?.path === nextChain.at(-1)?.path;
if (reenter && sameLeaf) {
exiting = prevChain.slice().reverse();
entering = nextChain;
}
return {
exiting,
entering
};
}
function matchesState(current, value) {
if (!current) return false;
return current === value || current.startsWith(`${value}${STATE_DELIMITER}`);
}
function hasTag(machine, state, tag) {
return getStateChain(machine, state).some((item) => item.state.tags?.includes(tag));
}
//#endregion
//#region src/shared/core/create-machine.ts
function createGuards() {
return {
and: (...guards) => {
return function andGuard(params) {
return guards.every((str) => params.guard(str));
};
},
or: (...guards) => {
return function orGuard(params) {
return guards.some((str) => params.guard(str));
};
},
not: (guard) => {
return function notGuard(params) {
return !params.guard(guard);
};
}
};
}
function createMachine(config) {
ensureStateIndex(config);
return config;
}
function setup() {
return {
guards: createGuards(),
createMachine: (config) => {
return createMachine(config);
},
choose: (transitions) => {
return function chooseFn({ choose }) {
return choose(transitions)?.actions;
};
}
};
}
//#endregion
//#region src/shared/core/types.ts
let MachineStatus = /* @__PURE__ */ function(MachineStatus) {
MachineStatus["NotStarted"] = "Not Started";
MachineStatus["Started"] = "Started";
MachineStatus["Stopped"] = "Stopped";
return MachineStatus;
}({});
const INIT_STATE = "__init__";
//#endregion
//#region src/shared/core/scope.ts
function createScope(props) {
const getRootNode = () => props.getRootNode?.() ?? document;
const getDoc = () => getDocument(getRootNode());
const getWin = () => getDoc().defaultView ?? window;
const getActiveElementFn = () => getActiveElement(getRootNode());
const getById = (id) => getRootNode().getElementById(id);
return {
...props,
getRootNode,
getDoc,
getWin,
getActiveElement: getActiveElementFn,
isActiveElement,
getById
};
}
//#endregion
export { createMachine as a, findTransition as c, getStateDefinition as d, hasTag as f, mergeProps as g, memo as h, createGuards as i, getExitEnterStates as l, resolveStateValue as m, INIT_STATE as n, setup as o, matchesState as p, MachineStatus as r, ensureStateIndex as s, createScope as t, getStateChain as u };
const require_dom_query = require("./dom-query-BT6fffRP.cjs");
let _ginxjs_core_utils = require("@ginxjs/core/utils");
//#region src/shared/core/merge-props.ts
const clsx = (...args) => args.map((str) => str?.trim?.()).filter(Boolean).join(" ");
const CSS_REGEX = /((?:--)?(?:\w+-?)+)\s*:\s*([^;]*)/g;
const serialize = (style) => {
const res = {};
let match;
while (match = CSS_REGEX.exec(style)) res[match[1]] = match[2];
return res;
};
const css = (a, b) => {
if ((0, _ginxjs_core_utils.isString)(a)) {
if ((0, _ginxjs_core_utils.isString)(b)) return `${a};${b}`;
a = serialize(a);
} else if ((0, _ginxjs_core_utils.isString)(b)) b = serialize(b);
return Object.assign({}, a ?? {}, b ?? {});
};
function mergeProps(...args) {
let result = {};
for (let props of args) {
if (!props) continue;
for (let key in result) {
if (key.startsWith("on") && typeof result[key] === "function" && typeof props[key] === "function") {
result[key] = (0, _ginxjs_core_utils.callAll)(props[key], result[key]);
continue;
}
if (key === "className" || key === "class") {
result[key] = clsx(result[key], props[key]);
continue;
}
if (key === "style") {
result[key] = css(result[key], props[key]);
continue;
}
result[key] = props[key] !== void 0 ? props[key] : result[key];
}
for (let key in props) if (result[key] === void 0) result[key] = props[key];
const symbols = Object.getOwnPropertySymbols(props);
for (let symbol of symbols) result[symbol] = props[symbol];
}
return result;
}
//#endregion
//#region src/shared/core/memo.ts
function memo(getDeps, fn, opts) {
let deps = [];
let result;
return (depArgs) => {
const newDeps = getDeps(depArgs);
if (!(newDeps.length !== deps.length || newDeps.some((dep, index) => !(0, _ginxjs_core_utils.isEqual)(deps[index], dep)))) return result;
deps = newDeps;
result = fn(newDeps, depArgs);
opts?.onChange?.(result);
return result;
};
}
//#endregion
//#region src/shared/core/state.ts
const STATE_DELIMITER = ".";
const ABSOLUTE_PREFIX = "#";
const stateIndexCache = /* @__PURE__ */ new WeakMap();
const stateIdIndexCache = /* @__PURE__ */ new WeakMap();
function joinStatePath(parts) {
return parts.join(STATE_DELIMITER);
}
function isAbsoluteStatePath(value) {
return value.includes(STATE_DELIMITER);
}
function isExplicitAbsoluteStatePath(value) {
return value.startsWith(ABSOLUTE_PREFIX);
}
function isChildTarget(value) {
return value.startsWith(STATE_DELIMITER);
}
function stripAbsolutePrefix(value) {
return isExplicitAbsoluteStatePath(value) ? value.slice(1) : value;
}
function appendStatePath(base, segment) {
return base ? `${base}${STATE_DELIMITER}${segment}` : segment;
}
function buildStateIndex(machine) {
const index = /* @__PURE__ */ new Map();
const idIndex = /* @__PURE__ */ new Map();
const visit = (basePath, state) => {
index.set(basePath, state);
const stateId = state.id;
if (stateId) {
if (idIndex.has(stateId)) (0, _ginxjs_core_utils.invariant)(`[ginxjs] Duplicate state id: "${stateId}"`);
idIndex.set(stateId, basePath);
}
const childStates = state.states;
if (!childStates) return;
(0, _ginxjs_core_utils.ensure)(state.initial, () => `[ginxjs] Compound state "${basePath}" has child states but no "initial" property`);
if (!(state.initial in childStates)) (0, _ginxjs_core_utils.invariant)(`[ginxjs] Compound state "${basePath}" has initial "${String(state.initial)}" which is not a child state`);
for (const [childKey, childState] of Object.entries(childStates)) {
if (!childState) continue;
visit(appendStatePath(basePath, childKey), childState);
}
};
for (const [topKey, topState] of Object.entries(machine.states)) {
if (!topState) continue;
visit(topKey, topState);
}
return {
index,
idIndex
};
}
function ensureStateIndex(machine) {
const cached = stateIndexCache.get(machine);
if (cached) return cached;
const { index, idIndex } = buildStateIndex(machine);
stateIndexCache.set(machine, index);
stateIdIndexCache.set(machine, idIndex);
return index;
}
function getStatePathById(machine, stateId) {
ensureStateIndex(machine);
return stateIdIndexCache.get(machine)?.get(stateId);
}
function toSegments(value) {
if (!value) return [];
return String(value).split(STATE_DELIMITER).filter(Boolean);
}
function getStateChain(machine, state) {
if (!state) return [];
const stateIndex = ensureStateIndex(machine);
const segments = toSegments(state);
const chain = [];
const statePath = [];
for (const segment of segments) {
statePath.push(segment);
const path = joinStatePath(statePath);
const current = stateIndex.get(path);
if (!current) break;
chain.push({
path,
state: current
});
}
return chain;
}
function resolveAbsoluteStateValue(machine, value) {
const stateIndex = ensureStateIndex(machine);
const segments = toSegments(value);
if (!segments.length) return value;
const resolved = [];
for (const segment of segments) {
resolved.push(segment);
const path = joinStatePath(resolved);
if (!stateIndex.has(path)) return value;
}
let resolvedPath = joinStatePath(resolved);
let current = stateIndex.get(resolvedPath);
while (current?.initial) {
const nextPath = `${resolvedPath}${STATE_DELIMITER}${current.initial}`;
const nextState = stateIndex.get(nextPath);
if (!nextState) break;
resolvedPath = nextPath;
current = nextState;
}
return resolvedPath;
}
function hasStatePath(machine, value) {
return ensureStateIndex(machine).has(value);
}
function resolveStateValue(machine, value, source) {
const stateValue = String(value);
if (isExplicitAbsoluteStatePath(stateValue)) {
const stateId = stripAbsolutePrefix(stateValue);
const statePath = getStatePathById(machine, stateId);
(0, _ginxjs_core_utils.ensure)(statePath, () => `[ginxjs] Unknown state id: "${stateId}"`);
return resolveAbsoluteStateValue(machine, statePath);
}
if (isChildTarget(stateValue) && source) return resolveAbsoluteStateValue(machine, appendStatePath(source, stateValue.slice(1)));
if (!isAbsoluteStatePath(stateValue) && source) {
const sourceSegments = toSegments(source);
for (let index = sourceSegments.length - 1; index >= 1; index--) {
const candidate = appendStatePath(sourceSegments.slice(0, index).join(STATE_DELIMITER), stateValue);
if (hasStatePath(machine, candidate)) return resolveAbsoluteStateValue(machine, candidate);
}
if (hasStatePath(machine, stateValue)) return resolveAbsoluteStateValue(machine, stateValue);
}
return resolveAbsoluteStateValue(machine, stateValue);
}
function getStateDefinition(machine, state) {
const chain = getStateChain(machine, state);
return chain[chain.length - 1]?.state;
}
function findTransition(machine, state, eventType) {
const chain = getStateChain(machine, state);
for (let index = chain.length - 1; index >= 0; index--) {
const transition = (chain[index]?.state.on)?.[eventType];
if (transition) return {
transitions: transition,
source: chain[index]?.path
};
}
return {
transitions: machine.on?.[eventType],
source: void 0
};
}
function getExitEnterStates(machine, prevState, nextState, reenter) {
const prevChain = prevState ? getStateChain(machine, prevState) : [];
const nextChain = getStateChain(machine, nextState);
let commonIndex = 0;
while (commonIndex < prevChain.length && commonIndex < nextChain.length && prevChain[commonIndex]?.path === nextChain[commonIndex]?.path) commonIndex += 1;
let exiting = prevChain.slice(commonIndex).reverse();
let entering = nextChain.slice(commonIndex);
const sameLeaf = prevChain.at(-1)?.path === nextChain.at(-1)?.path;
if (reenter && sameLeaf) {
exiting = prevChain.slice().reverse();
entering = nextChain;
}
return {
exiting,
entering
};
}
function matchesState(current, value) {
if (!current) return false;
return current === value || current.startsWith(`${value}${STATE_DELIMITER}`);
}
function hasTag(machine, state, tag) {
return getStateChain(machine, state).some((item) => item.state.tags?.includes(tag));
}
//#endregion
//#region src/shared/core/create-machine.ts
function createGuards() {
return {
and: (...guards) => {
return function andGuard(params) {
return guards.every((str) => params.guard(str));
};
},
or: (...guards) => {
return function orGuard(params) {
return guards.some((str) => params.guard(str));
};
},
not: (guard) => {
return function notGuard(params) {
return !params.guard(guard);
};
}
};
}
function createMachine(config) {
ensureStateIndex(config);
return config;
}
function setup() {
return {
guards: createGuards(),
createMachine: (config) => {
return createMachine(config);
},
choose: (transitions) => {
return function chooseFn({ choose }) {
return choose(transitions)?.actions;
};
}
};
}
//#endregion
//#region src/shared/core/types.ts
let MachineStatus = /* @__PURE__ */ function(MachineStatus) {
MachineStatus["NotStarted"] = "Not Started";
MachineStatus["Started"] = "Started";
MachineStatus["Stopped"] = "Stopped";
return MachineStatus;
}({});
const INIT_STATE = "__init__";
//#endregion
//#region src/shared/core/scope.ts
function createScope(props) {
const getRootNode = () => props.getRootNode?.() ?? document;
const getDoc = () => require_dom_query.getDocument(getRootNode());
const getWin = () => getDoc().defaultView ?? window;
const getActiveElementFn = () => require_dom_query.getActiveElement(getRootNode());
const getById = (id) => getRootNode().getElementById(id);
return {
...props,
getRootNode,
getDoc,
getWin,
getActiveElement: getActiveElementFn,
isActiveElement: require_dom_query.isActiveElement,
getById
};
}
//#endregion
Object.defineProperty(exports, "INIT_STATE", {
enumerable: true,
get: function() {
return INIT_STATE;
}
});
Object.defineProperty(exports, "MachineStatus", {
enumerable: true,
get: function() {
return MachineStatus;
}
});
Object.defineProperty(exports, "createGuards", {
enumerable: true,
get: function() {
return createGuards;
}
});
Object.defineProperty(exports, "createMachine", {
enumerable: true,
get: function() {
return createMachine;
}
});
Object.defineProperty(exports, "createScope", {
enumerable: true,
get: function() {
return createScope;
}
});
Object.defineProperty(exports, "ensureStateIndex", {
enumerable: true,
get: function() {
return ensureStateIndex;
}
});
Object.defineProperty(exports, "findTransition", {
enumerable: true,
get: function() {
return findTransition;
}
});
Object.defineProperty(exports, "getExitEnterStates", {
enumerable: true,
get: function() {
return getExitEnterStates;
}
});
Object.defineProperty(exports, "getStateChain", {
enumerable: true,
get: function() {
return getStateChain;
}
});
Object.defineProperty(exports, "getStateDefinition", {
enumerable: true,
get: function() {
return getStateDefinition;
}
});
Object.defineProperty(exports, "hasTag", {
enumerable: true,
get: function() {
return hasTag;
}
});
Object.defineProperty(exports, "matchesState", {
enumerable: true,
get: function() {
return matchesState;
}
});
Object.defineProperty(exports, "memo", {
enumerable: true,
get: function() {
return memo;
}
});
Object.defineProperty(exports, "mergeProps", {
enumerable: true,
get: function() {
return mergeProps;
}
});
Object.defineProperty(exports, "resolveStateValue", {
enumerable: true,
get: function() {
return resolveStateValue;
}
});
Object.defineProperty(exports, "setup", {
enumerable: true,
get: function() {
return setup;
}
});
//#region src/shared/anatomy/create-anatomy.ts
const createAnatomy = (name, parts = []) => ({
parts: (...values) => {
if (isEmpty(parts)) return createAnatomy(name, values);
throw new Error("createAnatomy().parts(...) should only be called once. Did you mean to use .extendWith(...) ?");
},
extendWith: (...values) => createAnatomy(name, [...parts, ...values]),
omit: (...values) => createAnatomy(name, parts.filter((part) => !values.includes(part))),
rename: (newName) => createAnatomy(newName, parts),
keys: () => parts,
build: () => [...new Set(parts)].reduce((prev, part) => Object.assign(prev, { [part]: {
selector: [`&[data-scope="${toKebabCase(name)}"][data-part="${toKebabCase(part)}"]`, `& [data-scope="${toKebabCase(name)}"][data-part="${toKebabCase(part)}"]`].join(", "),
attrs: {
"data-scope": toKebabCase(name),
"data-part": toKebabCase(part)
}
} }), {})
});
const toKebabCase = (value) => value.replace(/([A-Z])([A-Z])/g, "$1-$2").replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase();
const isEmpty = (v) => v.length === 0;
//#endregion
Object.defineProperty(exports, "createAnatomy", {
enumerable: true,
get: function() {
return createAnatomy;
}
});
//#region src/shared/anatomy/create-anatomy.ts
const createAnatomy = (name, parts = []) => ({
parts: (...values) => {
if (isEmpty(parts)) return createAnatomy(name, values);
throw new Error("createAnatomy().parts(...) should only be called once. Did you mean to use .extendWith(...) ?");
},
extendWith: (...values) => createAnatomy(name, [...parts, ...values]),
omit: (...values) => createAnatomy(name, parts.filter((part) => !values.includes(part))),
rename: (newName) => createAnatomy(newName, parts),
keys: () => parts,
build: () => [...new Set(parts)].reduce((prev, part) => Object.assign(prev, { [part]: {
selector: [`&[data-scope="${toKebabCase(name)}"][data-part="${toKebabCase(part)}"]`, `& [data-scope="${toKebabCase(name)}"][data-part="${toKebabCase(part)}"]`].join(", "),
attrs: {
"data-scope": toKebabCase(name),
"data-part": toKebabCase(part)
}
} }), {})
});
const toKebabCase = (value) => value.replace(/([A-Z])([A-Z])/g, "$1-$2").replace(/([a-z])([A-Z])/g, "$1-$2").replace(/[\s_]+/g, "-").toLowerCase();
const isEmpty = (v) => v.length === 0;
//#endregion
export { createAnatomy as t };
//#region src/shared/types/create-props.ts
const createProps = () => (props) => Array.from(new Set(props));
//#endregion
export { createProps as t };
//#region src/shared/types/create-props.ts
const createProps = () => (props) => Array.from(new Set(props));
//#endregion
Object.defineProperty(exports, "createProps", {
enumerable: true,
get: function() {
return createProps;
}
});
import { $t as getComputedStyle, G as raf, U as nextTick, dt as addDomEvent, en as contains, gn as isHTMLElement, gt as getEventTarget, rn as getDocument, t as waitForElement, u as setStyle } from "./dom-query-BgxIO7_X.mjs";
import { t as trackInteractOutside } from "./interact-outside-DEkrkU2U.mjs";
import { isFunction, warn } from "@ginxjs/core/utils";
//#region src/shared/dismissable/escape-keydown.ts
function trackEscapeKeydown(node, fn) {
const handleKeyDown = (event) => {
if (event.key !== "Escape") return;
if (event.isComposing) return;
fn?.(event);
};
return addDomEvent(getDocument(node), "keydown", handleKeyDown, { capture: true });
}
//#endregion
//#region src/shared/dismissable/layer-stack.ts
const LAYER_REQUEST_DISMISS_EVENT = "layer:request-dismiss";
const layerStack = {
layers: [],
branches: [],
recentlyRemoved: /* @__PURE__ */ new Set(),
count() {
return this.layers.length;
},
pointerBlockingLayers() {
return this.layers.filter((layer) => layer.pointerBlocking);
},
topMostPointerBlockingLayer() {
return [...this.pointerBlockingLayers()].slice(-1)[0];
},
hasPointerBlockingLayer() {
return this.pointerBlockingLayers().length > 0;
},
isBelowPointerBlockingLayer(node) {
return this.indexOf(node) < (this.topMostPointerBlockingLayer() ? this.indexOf(this.topMostPointerBlockingLayer()?.node) : -1);
},
isTopMost(node) {
return this.layers[this.count() - 1]?.node === node;
},
getNestedLayers(node) {
return Array.from(this.layers).slice(this.indexOf(node) + 1);
},
getLayersByType(type) {
return this.layers.filter((layer) => layer.type === type);
},
getNestedLayersByType(node, type) {
const index = this.indexOf(node);
if (index === -1) return [];
return this.layers.slice(index + 1).filter((layer) => layer.type === type);
},
getParentLayerOfType(node, type) {
const index = this.indexOf(node);
if (index <= 0) return void 0;
return this.layers.slice(0, index).reverse().find((layer) => layer.type === type);
},
countNestedLayersOfType(node, type) {
return this.getNestedLayersByType(node, type).length;
},
isInNestedLayer(node, target) {
if (this.getNestedLayers(node).some((layer) => contains(layer.node, target))) return true;
if (this.recentlyRemoved.size > 0) return true;
return false;
},
isInBranch(target) {
return Array.from(this.branches).some((branch) => contains(branch, target));
},
add(layer) {
const existingIndex = this.indexOf(layer.node);
if (existingIndex !== -1) this.layers.splice(existingIndex, 1);
this.layers.push(layer);
this.syncLayers();
},
addBranch(node) {
this.branches.push(node);
},
remove(node) {
const index = this.indexOf(node);
if (index < 0) return;
this.layers[index].styleTargets?.forEach((getTarget) => {
const target = getTarget();
if (target) clearLayerStyleMirror(target);
});
this.recentlyRemoved.add(node);
nextTick(() => this.recentlyRemoved.delete(node));
if (index < this.count() - 1) this.getNestedLayers(node).forEach((layer) => layerStack.dismiss(layer.node, node));
this.layers.splice(index, 1);
this.syncLayers();
},
removeBranch(node) {
const index = this.branches.indexOf(node);
if (index >= 0) this.branches.splice(index, 1);
},
syncLayers() {
this.layers.forEach((layer, index) => {
applyLayerStackMetadata(layer, index, layer.node);
layer.styleTargets?.forEach((getTarget) => {
const target = getTarget();
if (!target || target === layer.node) return;
applyLayerStackMetadata(layer, index, target);
const { zIndex } = getComputedStyle(layer.node);
target.style.setProperty("--z-index", zIndex);
});
});
},
indexOf(node) {
return this.layers.findIndex((layer) => layer.node === node);
},
dismiss(node, parent) {
const index = this.indexOf(node);
if (index === -1) return;
const layer = this.layers[index];
addListenerOnce(node, LAYER_REQUEST_DISMISS_EVENT, (event) => {
layer.requestDismiss?.(event);
if (!event.defaultPrevented) layer?.dismiss();
});
fireCustomEvent(node, LAYER_REQUEST_DISMISS_EVENT, {
originalLayer: node,
targetLayer: parent,
originalIndex: index,
targetIndex: parent ? this.indexOf(parent) : -1
});
this.syncLayers();
},
clear() {
this.remove(this.layers[0].node);
}
};
function applyLayerStackMetadata(layer, index, el) {
el.style.setProperty("--layer-index", `${index}`);
el.removeAttribute("data-nested");
el.removeAttribute("data-has-nested");
if (layerStack.getParentLayerOfType(layer.node, layer.type)) el.setAttribute("data-nested", layer.type);
const nestedCount = layerStack.countNestedLayersOfType(layer.node, layer.type);
if (nestedCount > 0) el.setAttribute("data-has-nested", layer.type);
el.style.setProperty("--nested-layer-count", `${nestedCount}`);
}
function clearLayerStyleMirror(el) {
el.style.removeProperty("--layer-index");
el.style.removeProperty("--nested-layer-count");
el.style.removeProperty("--z-index");
el.removeAttribute("data-nested");
el.removeAttribute("data-has-nested");
}
function fireCustomEvent(el, type, detail) {
const event = new (el.ownerDocument.defaultView || window).CustomEvent(type, {
cancelable: true,
bubbles: true,
detail
});
return el.dispatchEvent(event);
}
function addListenerOnce(el, type, callback) {
el.addEventListener(type, callback, { once: true });
}
//#endregion
//#region src/shared/dismissable/pointer-event-outside.ts
let originalBodyPointerEvents;
function assignPointerEventToLayers() {
layerStack.layers.forEach(({ node }) => {
node.style.pointerEvents = layerStack.isBelowPointerBlockingLayer(node) ? "none" : "auto";
});
}
function clearPointerEvent(node) {
node.style.pointerEvents = "";
}
function disablePointerEventsOutside(node, persistentElements) {
const doc = getDocument(node);
const cleanups = [];
if (layerStack.hasPointerBlockingLayer() && !doc.body.hasAttribute("data-inert")) {
originalBodyPointerEvents = document.body.style.pointerEvents;
queueMicrotask(() => {
doc.body.style.pointerEvents = "none";
doc.body.setAttribute("data-inert", "");
});
}
persistentElements?.forEach((el) => {
const [promise, abort] = waitForElement(() => {
const node = el();
return isHTMLElement(node) ? node : null;
}, { timeout: 1e3 });
promise.then((el) => cleanups.push(setStyle(el, { pointerEvents: "auto" })));
cleanups.push(abort);
});
return () => {
if (layerStack.hasPointerBlockingLayer()) return;
queueMicrotask(() => {
doc.body.style.pointerEvents = originalBodyPointerEvents;
doc.body.removeAttribute("data-inert");
if (doc.body.style.length === 0) doc.body.removeAttribute("style");
});
cleanups.forEach((fn) => fn());
};
}
//#endregion
//#region src/shared/dismissable/dismissable-layer.ts
function trackDismissableElementImpl(node, options) {
const { warnOnMissingNode = true } = options;
if (warnOnMissingNode && !node) {
warn("[@ginxjs/dismissable] node is `null` or `undefined`");
return;
}
if (!node) return;
const { onDismiss, onRequestDismiss, pointerBlocking, exclude: excludeContainers, debug, type = "dialog", layerStyleTargets } = options;
const layer = {
dismiss: onDismiss,
node,
type,
pointerBlocking,
requestDismiss: onRequestDismiss,
styleTargets: layerStyleTargets
};
layerStack.add(layer);
assignPointerEventToLayers();
function onPointerDownOutside(event) {
const target = getEventTarget(event.detail.originalEvent);
if (layerStack.isBelowPointerBlockingLayer(node) || layerStack.isInBranch(target)) return;
options.onPointerDownOutside?.(event);
options.onInteractOutside?.(event);
if (event.defaultPrevented) return;
if (debug) console.log("onPointerDownOutside:", event.detail.originalEvent);
onDismiss?.();
}
function onFocusOutside(event) {
const target = getEventTarget(event.detail.originalEvent);
if (layerStack.isInBranch(target)) return;
options.onFocusOutside?.(event);
options.onInteractOutside?.(event);
if (event.defaultPrevented) return;
if (debug) console.log("onFocusOutside:", event.detail.originalEvent);
onDismiss?.();
}
function onEscapeKeyDown(event) {
if (!layerStack.isTopMost(node)) return;
options.onEscapeKeyDown?.(event);
if (!event.defaultPrevented && onDismiss) {
event.preventDefault();
onDismiss();
}
}
function exclude(target) {
if (!node) return false;
const containers = typeof excludeContainers === "function" ? excludeContainers() : excludeContainers;
const _containers = Array.isArray(containers) ? containers : [containers];
const persistentElements = options.persistentElements?.map((fn) => fn()).filter(isHTMLElement);
if (persistentElements) _containers.push(...persistentElements);
return _containers.some((node) => contains(node, target)) || layerStack.isInNestedLayer(node, target);
}
const cleanups = [
pointerBlocking ? disablePointerEventsOutside(node, options.persistentElements) : void 0,
trackEscapeKeydown(node, onEscapeKeyDown),
trackInteractOutside(node, {
exclude,
onFocusOutside,
onPointerDownOutside,
defer: options.defer
})
];
return () => {
layerStack.remove(node);
assignPointerEventToLayers();
clearPointerEvent(node);
cleanups.forEach((fn) => fn?.());
};
}
function trackDismissableElement(nodeOrFn, options) {
const { defer } = options;
const func = defer ? raf : (v) => v();
const cleanups = [];
cleanups.push(func(() => {
const node = isFunction(nodeOrFn) ? nodeOrFn() : nodeOrFn;
cleanups.push(trackDismissableElementImpl(node, options));
}));
return () => {
cleanups.forEach((fn) => fn?.());
};
}
function trackDismissableBranch(nodeOrFn, options = {}) {
const { defer } = options;
const func = defer ? raf : (v) => v();
const cleanups = [];
cleanups.push(func(() => {
const node = isFunction(nodeOrFn) ? nodeOrFn() : nodeOrFn;
if (!node) {
warn("[@ginxjs/dismissable] branch node is `null` or `undefined`");
return;
}
layerStack.addBranch(node);
cleanups.push(() => {
layerStack.removeBranch(node);
});
}));
return () => {
cleanups.forEach((fn) => fn?.());
};
}
//#endregion
export { trackDismissableElement as n, trackDismissableBranch as t };
const require_dom_query = require("./dom-query-BT6fffRP.cjs");
const require_interact_outside = require("./interact-outside-DyL5V-m4.cjs");
let _ginxjs_core_utils = require("@ginxjs/core/utils");
//#region src/shared/dismissable/escape-keydown.ts
function trackEscapeKeydown(node, fn) {
const handleKeyDown = (event) => {
if (event.key !== "Escape") return;
if (event.isComposing) return;
fn?.(event);
};
return require_dom_query.addDomEvent(require_dom_query.getDocument(node), "keydown", handleKeyDown, { capture: true });
}
//#endregion
//#region src/shared/dismissable/layer-stack.ts
const LAYER_REQUEST_DISMISS_EVENT = "layer:request-dismiss";
const layerStack = {
layers: [],
branches: [],
recentlyRemoved: /* @__PURE__ */ new Set(),
count() {
return this.layers.length;
},
pointerBlockingLayers() {
return this.layers.filter((layer) => layer.pointerBlocking);
},
topMostPointerBlockingLayer() {
return [...this.pointerBlockingLayers()].slice(-1)[0];
},
hasPointerBlockingLayer() {
return this.pointerBlockingLayers().length > 0;
},
isBelowPointerBlockingLayer(node) {
return this.indexOf(node) < (this.topMostPointerBlockingLayer() ? this.indexOf(this.topMostPointerBlockingLayer()?.node) : -1);
},
isTopMost(node) {
return this.layers[this.count() - 1]?.node === node;
},
getNestedLayers(node) {
return Array.from(this.layers).slice(this.indexOf(node) + 1);
},
getLayersByType(type) {
return this.layers.filter((layer) => layer.type === type);
},
getNestedLayersByType(node, type) {
const index = this.indexOf(node);
if (index === -1) return [];
return this.layers.slice(index + 1).filter((layer) => layer.type === type);
},
getParentLayerOfType(node, type) {
const index = this.indexOf(node);
if (index <= 0) return void 0;
return this.layers.slice(0, index).reverse().find((layer) => layer.type === type);
},
countNestedLayersOfType(node, type) {
return this.getNestedLayersByType(node, type).length;
},
isInNestedLayer(node, target) {
if (this.getNestedLayers(node).some((layer) => require_dom_query.contains(layer.node, target))) return true;
if (this.recentlyRemoved.size > 0) return true;
return false;
},
isInBranch(target) {
return Array.from(this.branches).some((branch) => require_dom_query.contains(branch, target));
},
add(layer) {
const existingIndex = this.indexOf(layer.node);
if (existingIndex !== -1) this.layers.splice(existingIndex, 1);
this.layers.push(layer);
this.syncLayers();
},
addBranch(node) {
this.branches.push(node);
},
remove(node) {
const index = this.indexOf(node);
if (index < 0) return;
this.layers[index].styleTargets?.forEach((getTarget) => {
const target = getTarget();
if (target) clearLayerStyleMirror(target);
});
this.recentlyRemoved.add(node);
require_dom_query.nextTick(() => this.recentlyRemoved.delete(node));
if (index < this.count() - 1) this.getNestedLayers(node).forEach((layer) => layerStack.dismiss(layer.node, node));
this.layers.splice(index, 1);
this.syncLayers();
},
removeBranch(node) {
const index = this.branches.indexOf(node);
if (index >= 0) this.branches.splice(index, 1);
},
syncLayers() {
this.layers.forEach((layer, index) => {
applyLayerStackMetadata(layer, index, layer.node);
layer.styleTargets?.forEach((getTarget) => {
const target = getTarget();
if (!target || target === layer.node) return;
applyLayerStackMetadata(layer, index, target);
const { zIndex } = require_dom_query.getComputedStyle(layer.node);
target.style.setProperty("--z-index", zIndex);
});
});
},
indexOf(node) {
return this.layers.findIndex((layer) => layer.node === node);
},
dismiss(node, parent) {
const index = this.indexOf(node);
if (index === -1) return;
const layer = this.layers[index];
addListenerOnce(node, LAYER_REQUEST_DISMISS_EVENT, (event) => {
layer.requestDismiss?.(event);
if (!event.defaultPrevented) layer?.dismiss();
});
fireCustomEvent(node, LAYER_REQUEST_DISMISS_EVENT, {
originalLayer: node,
targetLayer: parent,
originalIndex: index,
targetIndex: parent ? this.indexOf(parent) : -1
});
this.syncLayers();
},
clear() {
this.remove(this.layers[0].node);
}
};
function applyLayerStackMetadata(layer, index, el) {
el.style.setProperty("--layer-index", `${index}`);
el.removeAttribute("data-nested");
el.removeAttribute("data-has-nested");
if (layerStack.getParentLayerOfType(layer.node, layer.type)) el.setAttribute("data-nested", layer.type);
const nestedCount = layerStack.countNestedLayersOfType(layer.node, layer.type);
if (nestedCount > 0) el.setAttribute("data-has-nested", layer.type);
el.style.setProperty("--nested-layer-count", `${nestedCount}`);
}
function clearLayerStyleMirror(el) {
el.style.removeProperty("--layer-index");
el.style.removeProperty("--nested-layer-count");
el.style.removeProperty("--z-index");
el.removeAttribute("data-nested");
el.removeAttribute("data-has-nested");
}
function fireCustomEvent(el, type, detail) {
const event = new (el.ownerDocument.defaultView || window).CustomEvent(type, {
cancelable: true,
bubbles: true,
detail
});
return el.dispatchEvent(event);
}
function addListenerOnce(el, type, callback) {
el.addEventListener(type, callback, { once: true });
}
//#endregion
//#region src/shared/dismissable/pointer-event-outside.ts
let originalBodyPointerEvents;
function assignPointerEventToLayers() {
layerStack.layers.forEach(({ node }) => {
node.style.pointerEvents = layerStack.isBelowPointerBlockingLayer(node) ? "none" : "auto";
});
}
function clearPointerEvent(node) {
node.style.pointerEvents = "";
}
function disablePointerEventsOutside(node, persistentElements) {
const doc = require_dom_query.getDocument(node);
const cleanups = [];
if (layerStack.hasPointerBlockingLayer() && !doc.body.hasAttribute("data-inert")) {
originalBodyPointerEvents = document.body.style.pointerEvents;
queueMicrotask(() => {
doc.body.style.pointerEvents = "none";
doc.body.setAttribute("data-inert", "");
});
}
persistentElements?.forEach((el) => {
const [promise, abort] = require_dom_query.waitForElement(() => {
const node = el();
return require_dom_query.isHTMLElement(node) ? node : null;
}, { timeout: 1e3 });
promise.then((el) => cleanups.push(require_dom_query.setStyle(el, { pointerEvents: "auto" })));
cleanups.push(abort);
});
return () => {
if (layerStack.hasPointerBlockingLayer()) return;
queueMicrotask(() => {
doc.body.style.pointerEvents = originalBodyPointerEvents;
doc.body.removeAttribute("data-inert");
if (doc.body.style.length === 0) doc.body.removeAttribute("style");
});
cleanups.forEach((fn) => fn());
};
}
//#endregion
//#region src/shared/dismissable/dismissable-layer.ts
function trackDismissableElementImpl(node, options) {
const { warnOnMissingNode = true } = options;
if (warnOnMissingNode && !node) {
(0, _ginxjs_core_utils.warn)("[@ginxjs/dismissable] node is `null` or `undefined`");
return;
}
if (!node) return;
const { onDismiss, onRequestDismiss, pointerBlocking, exclude: excludeContainers, debug, type = "dialog", layerStyleTargets } = options;
const layer = {
dismiss: onDismiss,
node,
type,
pointerBlocking,
requestDismiss: onRequestDismiss,
styleTargets: layerStyleTargets
};
layerStack.add(layer);
assignPointerEventToLayers();
function onPointerDownOutside(event) {
const target = require_dom_query.getEventTarget(event.detail.originalEvent);
if (layerStack.isBelowPointerBlockingLayer(node) || layerStack.isInBranch(target)) return;
options.onPointerDownOutside?.(event);
options.onInteractOutside?.(event);
if (event.defaultPrevented) return;
if (debug) console.log("onPointerDownOutside:", event.detail.originalEvent);
onDismiss?.();
}
function onFocusOutside(event) {
const target = require_dom_query.getEventTarget(event.detail.originalEvent);
if (layerStack.isInBranch(target)) return;
options.onFocusOutside?.(event);
options.onInteractOutside?.(event);
if (event.defaultPrevented) return;
if (debug) console.log("onFocusOutside:", event.detail.originalEvent);
onDismiss?.();
}
function onEscapeKeyDown(event) {
if (!layerStack.isTopMost(node)) return;
options.onEscapeKeyDown?.(event);
if (!event.defaultPrevented && onDismiss) {
event.preventDefault();
onDismiss();
}
}
function exclude(target) {
if (!node) return false;
const containers = typeof excludeContainers === "function" ? excludeContainers() : excludeContainers;
const _containers = Array.isArray(containers) ? containers : [containers];
const persistentElements = options.persistentElements?.map((fn) => fn()).filter(require_dom_query.isHTMLElement);
if (persistentElements) _containers.push(...persistentElements);
return _containers.some((node) => require_dom_query.contains(node, target)) || layerStack.isInNestedLayer(node, target);
}
const cleanups = [
pointerBlocking ? disablePointerEventsOutside(node, options.persistentElements) : void 0,
trackEscapeKeydown(node, onEscapeKeyDown),
require_interact_outside.trackInteractOutside(node, {
exclude,
onFocusOutside,
onPointerDownOutside,
defer: options.defer
})
];
return () => {
layerStack.remove(node);
assignPointerEventToLayers();
clearPointerEvent(node);
cleanups.forEach((fn) => fn?.());
};
}
function trackDismissableElement(nodeOrFn, options) {
const { defer } = options;
const func = defer ? require_dom_query.raf : (v) => v();
const cleanups = [];
cleanups.push(func(() => {
const node = (0, _ginxjs_core_utils.isFunction)(nodeOrFn) ? nodeOrFn() : nodeOrFn;
cleanups.push(trackDismissableElementImpl(node, options));
}));
return () => {
cleanups.forEach((fn) => fn?.());
};
}
function trackDismissableBranch(nodeOrFn, options = {}) {
const { defer } = options;
const func = defer ? require_dom_query.raf : (v) => v();
const cleanups = [];
cleanups.push(func(() => {
const node = (0, _ginxjs_core_utils.isFunction)(nodeOrFn) ? nodeOrFn() : nodeOrFn;
if (!node) {
(0, _ginxjs_core_utils.warn)("[@ginxjs/dismissable] branch node is `null` or `undefined`");
return;
}
layerStack.addBranch(node);
cleanups.push(() => {
layerStack.removeBranch(node);
});
}));
return () => {
cleanups.forEach((fn) => fn?.());
};
}
//#endregion
Object.defineProperty(exports, "trackDismissableBranch", {
enumerable: true,
get: function() {
return trackDismissableBranch;
}
});
Object.defineProperty(exports, "trackDismissableElement", {
enumerable: true,
get: function() {
return trackDismissableElement;
}
});
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_dismissable = require("./dismissable-BxNRrW5W.cjs");
exports.trackDismissableBranch = require_dismissable.trackDismissableBranch;
exports.trackDismissableElement = require_dismissable.trackDismissableElement;
import { c as PointerDownOutsideEvent, i as InteractOutsideHandlers, n as FocusOutsideEvent, r as InteractOutsideEvent } from "./index-jO45BUcW.cjs";
import { a as trackDismissableElement, i as trackDismissableBranch, n as DismissableElementOptions, o as LayerStyleTarget, r as PersistentElementOptions, s as LayerType, t as DismissableElementHandlers } from "./index-Clj-5omp.cjs";
export { DismissableElementHandlers, DismissableElementOptions, FocusOutsideEvent, InteractOutsideEvent, InteractOutsideHandlers, LayerStyleTarget, LayerType, PersistentElementOptions, PointerDownOutsideEvent, trackDismissableBranch, trackDismissableElement };
import { c as PointerDownOutsideEvent, i as InteractOutsideHandlers, n as FocusOutsideEvent, r as InteractOutsideEvent } from "./index-C3Jj4aYp.mjs";
import { a as trackDismissableElement, i as trackDismissableBranch, n as DismissableElementOptions, o as LayerStyleTarget, r as PersistentElementOptions, s as LayerType, t as DismissableElementHandlers } from "./index-mjZsVHsA.mjs";
export { DismissableElementHandlers, DismissableElementOptions, FocusOutsideEvent, InteractOutsideEvent, InteractOutsideHandlers, LayerStyleTarget, LayerType, PersistentElementOptions, PointerDownOutsideEvent, trackDismissableBranch, trackDismissableElement };
import { n as trackDismissableElement, t as trackDismissableBranch } from "./dismissable-BR1e7NIW.mjs";
export { trackDismissableBranch, trackDismissableElement };
//#region src/shared/dom-query/caret.ts
function isCaretAtStart(input) {
if (!input) return false;
try {
return input.selectionStart === 0 && input.selectionEnd === 0;
} catch {
return input.value === "";
}
}
function setCaretToEnd(input) {
if (!input) return;
try {
if (input.ownerDocument.activeElement !== input) return;
const len = input.value.length;
input.setSelectionRange(len, len);
} catch {}
}
//#endregion
//#region src/shared/dom-query/shared.ts
const clamp = (value) => Math.max(0, Math.min(1, value));
const wrap = (v, idx) => {
return v.map((_, index) => v[(Math.max(idx, 0) + index) % v.length]);
};
const pipe = (...fns) => (arg) => fns.reduce((acc, fn) => fn(acc), arg);
const noop = () => void 0;
const isObject = (v) => typeof v === "object" && v !== null;
const MAX_Z_INDEX = 2147483647;
const dataAttr = (guard) => guard ? "" : void 0;
const ariaAttr = (guard) => guard ? "true" : void 0;
//#endregion
//#region src/shared/dom-query/node.ts
const ELEMENT_NODE = 1;
const DOCUMENT_NODE = 9;
const DOCUMENT_FRAGMENT_NODE = 11;
const isElement = (el) => isObject(el) && el.nodeType === ELEMENT_NODE && typeof el.nodeName === "string";
const isHTMLElement = (el) => isObject(el) && el.nodeType === ELEMENT_NODE && typeof el.nodeName === "string";
const isDocument = (el) => isObject(el) && el.nodeType === DOCUMENT_NODE;
const isWindow = (el) => isObject(el) && el === el.window;
const isVisualViewport = (el) => isObject(el) && el.constructor.name === "VisualViewport";
const getNodeName = (node) => {
if (isHTMLElement(node)) return node.localName || "";
return "#document";
};
function isRootElement(node) {
return [
"html",
"body",
"#document"
].includes(getNodeName(node));
}
const isNode = (el) => isObject(el) && el.nodeType !== void 0;
const isShadowRoot = (el) => isNode(el) && el.nodeType === DOCUMENT_FRAGMENT_NODE && "host" in el;
const isInputElement = (el) => isHTMLElement(el) && el.localName === "input";
const isAnchorElement = (el) => !!el?.matches("a[href]");
const isElementVisible = (el) => {
if (!isHTMLElement(el)) return false;
return el.offsetWidth > 0 || el.offsetHeight > 0 || el.getClientRects().length > 0;
};
function isActiveElement(element) {
if (!element) return false;
return getActiveElement(element.getRootNode()) === element;
}
const TEXTAREA_SELECT_REGEX = /(textarea|select)/;
function isEditableElement(el) {
if (el == null || !isHTMLElement(el)) return false;
try {
return isInputElement(el) && el.selectionStart != null || TEXTAREA_SELECT_REGEX.test(el.localName) || el.isContentEditable || el.getAttribute("contenteditable") === "true" || el.getAttribute("contenteditable") === "";
} catch {
return false;
}
}
/** Whether `parent` contains `child` in the light tree, or `child` is inside a shadow tree hosted under `parent`. */
function getParentElement(node) {
const parentNode = node.parentNode;
if (isShadowRoot(parentNode)) return parentNode.host;
return parentNode;
}
function getAncestorElements(node) {
const ancestors = [];
while (node) {
ancestors.push(node);
node = getParentElement(node);
}
return ancestors;
}
function contains(parent, child) {
if (!parent || !child) return false;
if (!isHTMLElement(parent) || !isNode(child)) return false;
if (isHTMLElement(child) && parent === child) return true;
if (parent.contains(child)) return true;
const rootNode = child.getRootNode?.();
if (rootNode && isShadowRoot(rootNode)) {
let next = child;
while (next) {
if (parent === next) return true;
next = next.parentNode || next.host;
}
}
return false;
}
function getDocument(el) {
if (isDocument(el)) return el;
if (isWindow(el)) return el.document;
return el?.ownerDocument ?? document;
}
function getDocumentElement(el) {
return getDocument(el).documentElement;
}
function getWindow(el) {
if (isShadowRoot(el)) return getWindow(el.host);
if (isDocument(el)) return el.defaultView ?? window;
if (isHTMLElement(el)) return el.ownerDocument?.defaultView ?? window;
return window;
}
function getActiveElement(rootNode) {
let activeElement = rootNode.activeElement;
while (activeElement?.shadowRoot) {
const el = activeElement.shadowRoot.activeElement;
if (!el || el === activeElement) break;
else activeElement = el;
}
return activeElement;
}
function getParentNode(node) {
if (getNodeName(node) === "html") return node;
const result = node.assignedSlot || node.parentNode || isShadowRoot(node) && node.host || getDocumentElement(node);
return isShadowRoot(result) ? result.host : result;
}
function getRootNode(node) {
let result;
try {
result = node.getRootNode({ composed: true });
if (isDocument(result) || isShadowRoot(result)) return result;
} catch {}
return node.ownerDocument ?? document;
}
//#endregion
//#region src/shared/dom-query/computed-style.ts
const styleCache = /* @__PURE__ */ new WeakMap();
function getComputedStyle(el) {
if (!styleCache.has(el)) styleCache.set(el, getWindow(el).getComputedStyle(el));
return styleCache.get(el);
}
//#endregion
//#region src/shared/dom-query/controller.ts
const INTERACTIVE_CONTAINER_ROLE = new Set([
"menu",
"listbox",
"dialog",
"grid",
"tree",
"region",
"application"
]);
const isInteractiveContainerRole = (role) => INTERACTIVE_CONTAINER_ROLE.has(role);
const getAriaControls = (element) => element.getAttribute("aria-controls")?.split(" ") || [];
function isControlledElement(container, element) {
const visitedIds = /* @__PURE__ */ new Set();
const rootNode = getRootNode(container);
const checkElement = (searchRoot) => {
const controllingElements = searchRoot.querySelectorAll("[aria-controls]");
for (const controller of controllingElements) {
if (controller.getAttribute("aria-expanded") !== "true") continue;
const controlledIds = getAriaControls(controller);
for (const id of controlledIds) {
if (!id || visitedIds.has(id)) continue;
visitedIds.add(id);
const controlledElement = rootNode.getElementById(id);
if (controlledElement) {
const role = controlledElement.getAttribute("role");
const modal = controlledElement.getAttribute("aria-modal") === "true";
if (role && isInteractiveContainerRole(role) && !modal) {
if (controlledElement === element || controlledElement.contains(element)) return true;
if (checkElement(controlledElement)) return true;
}
}
}
}
return false;
};
return checkElement(container);
}
function findControlledElements(searchRoot, callback) {
const rootNode = getRootNode(searchRoot);
const visitedIds = /* @__PURE__ */ new Set();
const findRecursive = (root) => {
const controllingElements = root.querySelectorAll("[aria-controls]");
for (const controller of controllingElements) {
if (controller.getAttribute("aria-expanded") !== "true") continue;
const controlledIds = getAriaControls(controller);
for (const id of controlledIds) {
if (!id || visitedIds.has(id)) continue;
visitedIds.add(id);
const controlledElement = rootNode.getElementById(id);
if (controlledElement) {
const role = controlledElement.getAttribute("role");
const modal = controlledElement.getAttribute("aria-modal") === "true";
if (role && INTERACTIVE_CONTAINER_ROLE.has(role) && !modal) {
callback(controlledElement);
findRecursive(controlledElement);
}
}
}
}
};
findRecursive(searchRoot);
}
function getControlledElements(container) {
const controlledElements = /* @__PURE__ */ new Set();
findControlledElements(container, (controlledElement) => {
if (!container.contains(controlledElement)) controlledElements.add(controlledElement);
});
return Array.from(controlledElements);
}
function isInteractiveContainerElement(element) {
const role = element.getAttribute("role");
return Boolean(role && INTERACTIVE_CONTAINER_ROLE.has(role));
}
function isControllerElement(element) {
return element.hasAttribute("aria-controls") && element.getAttribute("aria-expanded") === "true";
}
function hasControllerElements(element) {
if (isControllerElement(element)) return true;
return Boolean(element.querySelector?.("[aria-controls][aria-expanded=\"true\"]"));
}
function isControlledByExpandedController(element) {
if (!element.id) return false;
const rootNode = getRootNode(element);
const escapedId = CSS.escape(element.id);
const selector = `[aria-controls~="${escapedId}"][aria-expanded="true"], [aria-controls="${escapedId}"][aria-expanded="true"]`;
const controller = rootNode.querySelector(selector);
return Boolean(controller && isInteractiveContainerElement(element));
}
//#endregion
//#region src/shared/dom-query/data-url.ts
function getDataUrl(svg, opts) {
const { type, quality = .92, background } = opts;
if (!svg) throw new Error("[ginxjs > getDataUrl]: Could not find the svg element");
const win = getWindow(svg);
const doc = win.document;
const svgBounds = svg.getBoundingClientRect();
const svgClone = svg.cloneNode(true);
if (!svgClone.hasAttribute("viewBox")) svgClone.setAttribute("viewBox", `0 0 ${svgBounds.width} ${svgBounds.height}`);
const source = "<?xml version=\"1.0\" standalone=\"no\"?>\r\n" + new win.XMLSerializer().serializeToString(svgClone);
const svgString = "data:image/svg+xml;charset=utf-8," + encodeURIComponent(source);
if (type === "image/svg+xml") return Promise.resolve(svgString).then((str) => {
svgClone.remove();
return str;
});
const dpr = win.devicePixelRatio || 1;
const canvas = doc.createElement("canvas");
const image = new win.Image();
image.src = svgString;
canvas.width = svgBounds.width * dpr;
canvas.height = svgBounds.height * dpr;
const context = canvas.getContext("2d");
if (type === "image/jpeg" || background) {
context.fillStyle = background || "white";
context.fillRect(0, 0, canvas.width, canvas.height);
}
return new Promise((resolve) => {
image.onload = () => {
context?.drawImage(image, 0, 0, canvas.width, canvas.height);
resolve(canvas.toDataURL(type, quality));
svgClone.remove();
};
});
}
//#endregion
//#region src/shared/dom-query/platform.ts
const isDom = () => typeof document !== "undefined";
function getPlatform() {
return navigator.userAgentData?.platform ?? navigator.platform;
}
function getUserAgent() {
const ua = navigator.userAgentData;
if (ua && Array.isArray(ua.brands)) return ua.brands.map(({ brand, version }) => `${brand}/${version}`).join(" ");
return navigator.userAgent;
}
const pt = (v) => isDom() && v.test(getPlatform());
const ua = (v) => isDom() && v.test(getUserAgent());
const vn = (v) => isDom() && v.test(navigator.vendor);
const isTouchDevice = () => isDom() && !!navigator.maxTouchPoints;
const isIPhone = () => pt(/^iPhone/i);
const isIPad = () => pt(/^iPad/i) || isMac() && navigator.maxTouchPoints > 1;
const isIos = () => isIPhone() || isIPad();
const isApple = () => isMac() || isIos();
const isMac = () => pt(/^Mac/i);
const isSafari = () => isApple() && vn(/apple/i);
const isFirefox = () => ua(/Firefox/i);
const isChrome = () => ua(/Chrome/i);
const isWebKit = () => ua(/AppleWebKit/i) && !isChrome();
const isAndroid = () => ua(/Android/i);
//#endregion
//#region src/shared/dom-query/event.ts
function getBeforeInputValue(event) {
const { selectionStart, selectionEnd, value } = event.currentTarget;
const data = event.data;
return value.slice(0, selectionStart) + (data ?? "") + value.slice(selectionEnd);
}
function getComposedPath(event) {
return event.composedPath?.() ?? event.nativeEvent?.composedPath?.();
}
function getEventTarget(event) {
return getComposedPath(event)?.[0] ?? event.target;
}
function isOpeningInNewTab(event) {
const element = event.currentTarget;
if (!element) return false;
if (!element.matches("a[href], button[type='submit'], input[type='submit']")) return false;
const isMiddleClick = event.button === 1;
const isModKeyClick = isCtrlOrMetaKey(event);
return isMiddleClick || isModKeyClick;
}
function isDownloadingEvent(event) {
const element = event.currentTarget;
if (!element) return false;
const localName = element.localName;
if (!event.altKey) return false;
if (localName === "a") return true;
if (localName === "button" && element.type === "submit") return true;
if (localName === "input" && element.type === "submit") return true;
return false;
}
function isComposingEvent(event) {
return getNativeEvent(event).isComposing || event.keyCode === 229;
}
function isKeyboardClick(e) {
return e.detail === 0 || e.clientX === 0 && e.clientY === 0;
}
function isCtrlOrMetaKey(e) {
if (isMac()) return e.metaKey;
return e.ctrlKey;
}
function isPrintableKey(e) {
return e.key.length === 1 && !e.ctrlKey && !e.metaKey;
}
function isVirtualPointerEvent(e) {
return e.width === 0 && e.height === 0 || e.width === 1 && e.height === 1 && e.pressure === 0 && e.detail === 0 && e.pointerType === "mouse";
}
function isVirtualClick(e) {
if (e.pointerType === "" && e.isTrusted) return true;
if (isAndroid() && e.pointerType) return e.type === "click" && e.buttons === 1;
return e.detail === 0 && !e.pointerType;
}
const isLeftClick = (e) => e.button === 0;
const isContextMenuEvent = (e) => {
return e.button === 2 || isMac() && e.ctrlKey && e.button === 0;
};
const isModifierKey = (e) => e.ctrlKey || e.altKey || e.metaKey;
const isTouchEvent = (event) => "touches" in event && event.touches.length > 0;
const keyMap = {
Up: "ArrowUp",
Down: "ArrowDown",
Esc: "Escape",
" ": "Space",
",": "Comma",
Left: "ArrowLeft",
Right: "ArrowRight"
};
const rtlKeyMap = {
ArrowLeft: "ArrowRight",
ArrowRight: "ArrowLeft"
};
function getEventKey(event, options = {}) {
const { dir = "ltr", orientation = "horizontal" } = options;
let key = event.key;
key = keyMap[key] ?? key;
if (dir === "rtl" && orientation === "horizontal" && key in rtlKeyMap) key = rtlKeyMap[key];
return key;
}
function getNativeEvent(event) {
return event.nativeEvent ?? event;
}
const pageKeys = new Set(["PageUp", "PageDown"]);
const arrowKeys = new Set([
"ArrowUp",
"ArrowDown",
"ArrowLeft",
"ArrowRight"
]);
function getEventStep(event) {
if (event.ctrlKey || event.metaKey) return .1;
else return pageKeys.has(event.key) || event.shiftKey && arrowKeys.has(event.key) ? 10 : 1;
}
function getEventPoint(event, type = "client") {
const point = isTouchEvent(event) ? event.touches[0] || event.changedTouches[0] : event;
return {
x: point[`${type}X`],
y: point[`${type}Y`]
};
}
const addDomEvent = (target, eventName, handler, options) => {
const node = typeof target === "function" ? target() : target;
node?.addEventListener(eventName, handler, options);
return () => {
node?.removeEventListener(eventName, handler, options);
};
};
const isSelfTarget = (event) => {
const target = getComposedPath(event)?.[0] ?? event.target;
return event.currentTarget === target;
};
//#endregion
//#region src/shared/dom-query/form.ts
function getDescriptor(el, options) {
const { type = "HTMLInputElement", property = "value" } = options;
const proto = getWindow(el)[type].prototype;
return Object.getOwnPropertyDescriptor(proto, property) ?? {};
}
function getElementType(el) {
if (el.localName === "input") return "HTMLInputElement";
if (el.localName === "textarea") return "HTMLTextAreaElement";
if (el.localName === "select") return "HTMLSelectElement";
}
function setElementValue(el, value, property = "value") {
if (!el) return;
const type = getElementType(el);
if (type) getDescriptor(el, {
type,
property
}).set?.call(el, value);
el.setAttribute(property, value);
}
function setElementChecked(el, checked) {
if (!el) return;
getDescriptor(el, {
type: "HTMLInputElement",
property: "checked"
}).set?.call(el, checked);
if (checked) el.setAttribute("checked", "");
else el.removeAttribute("checked");
}
function dispatchInputValueEvent(el, options) {
const { value, bubbles = true } = options;
if (!el) return;
const win = getWindow(el);
if (!(el instanceof win.HTMLInputElement)) return;
setElementValue(el, `${value}`);
const event = new win.Event("input", { bubbles });
el.dispatchEvent(markAsInternalChangeEvent(event));
}
function dispatchInputCheckedEvent(el, options) {
const { checked, bubbles = true } = options;
if (!el) return;
const win = getWindow(el);
if (!(el instanceof win.HTMLInputElement)) return;
setElementChecked(el, checked);
const event = new win.Event("click", { bubbles });
el.dispatchEvent(markAsInternalChangeEvent(event));
}
function isFormElement(el) {
return el.matches("textarea, input, select, button");
}
function trackFormReset(el, callback) {
if (!el) return;
const form = isFormElement(el) ? el.form : el.closest("form");
const onReset = (e) => {
if (e.defaultPrevented) return;
callback();
};
form?.addEventListener("reset", onReset, { passive: true });
return () => form?.removeEventListener("reset", onReset);
}
function trackFieldsetDisabled(el, callback) {
const fieldset = el?.closest("fieldset");
if (!fieldset) return;
callback(fieldset.disabled);
const obs = new (getWindow(fieldset)).MutationObserver(() => callback(fieldset.disabled));
obs.observe(fieldset, {
attributes: true,
attributeFilter: ["disabled"]
});
return () => obs.disconnect();
}
function trackFormControl(el, options) {
if (!el) return;
const { onFieldsetDisabledChange, onFormReset } = options;
const cleanups = [trackFormReset(el, onFormReset), trackFieldsetDisabled(el, onFieldsetDisabledChange)];
return () => cleanups.forEach((cleanup) => cleanup?.());
}
const INTERNAL_CHANGE_EVENT = Symbol.for("ginx.changeEvent");
function isInternalChangeEvent(e) {
return Object.prototype.hasOwnProperty.call(e, INTERNAL_CHANGE_EVENT);
}
function markAsInternalChangeEvent(event) {
if (isInternalChangeEvent(event)) return event;
Object.defineProperty(event, INTERNAL_CHANGE_EVENT, { value: true });
return event;
}
//#endregion
//#region src/shared/dom-query/tabbable.ts
const isFrame = (el) => isHTMLElement(el) && el.tagName === "IFRAME";
const NATURALLY_TABBABLE_REGEX = /^(audio|video|details)$/;
function parseTabIndex(el) {
const attr = el.getAttribute("tabindex");
if (!attr) return NaN;
return parseInt(attr, 10);
}
const hasTabIndex = (el) => !Number.isNaN(parseTabIndex(el));
const hasNegativeTabIndex = (el) => parseTabIndex(el) < 0;
function isRadioInput(element) {
return isInputElement(element) && element.type === "radio";
}
function isTabbableRadio(element) {
if (!isRadioInput(element) || !element.name) return true;
if (element.checked) return true;
const selector = `input[type="radio"][name="${CSS.escape(element.name)}"]`;
const scope = element.form ?? element.ownerDocument;
const group = Array.from(scope.querySelectorAll(selector)).filter((radio) => radio.form === element.form && isFocusable(radio));
const checked = group.find((radio) => radio.checked);
if (checked) return checked === element;
return group[0] === element;
}
function getShadowRootForNode(element, getShadowRoot) {
if (!getShadowRoot) return null;
if (getShadowRoot === true) return element.shadowRoot || null;
const result = getShadowRoot(element);
return (result === true ? element.shadowRoot : result) || null;
}
function collectElementsWithShadowDOM(elements, getShadowRoot, filterFn) {
const allElements = [...elements];
const toProcess = [...elements];
const processed = /* @__PURE__ */ new Set();
const positionMap = /* @__PURE__ */ new Map();
elements.forEach((el, i) => positionMap.set(el, i));
let processIndex = 0;
while (processIndex < toProcess.length) {
const element = toProcess[processIndex++];
if (!element || processed.has(element)) continue;
processed.add(element);
const shadowRoot = getShadowRootForNode(element, getShadowRoot);
if (shadowRoot) {
const shadowElements = Array.from(shadowRoot.querySelectorAll(focusableSelector)).filter(filterFn);
const hostIndex = positionMap.get(element);
if (hostIndex !== void 0) {
const insertPosition = hostIndex + 1;
allElements.splice(insertPosition, 0, ...shadowElements);
shadowElements.forEach((el, i) => {
positionMap.set(el, insertPosition + i);
});
for (let i = insertPosition + shadowElements.length; i < allElements.length; i++) positionMap.set(allElements[i], i);
} else {
const insertPosition = allElements.length;
allElements.push(...shadowElements);
shadowElements.forEach((el, i) => {
positionMap.set(el, insertPosition + i);
});
}
toProcess.push(...shadowElements);
}
}
return allElements;
}
const focusableSelector = "input:not([type='hidden']):not([disabled]), select:not([disabled]), textarea:not([disabled]), a[href], button:not([disabled]), [tabindex], iframe, object, embed, area[href], audio[controls], video[controls], [contenteditable]:not([contenteditable='false']), details > summary:first-of-type";
const getFocusables = (container, options = {}) => {
if (!container) return [];
const { includeContainer = false, getShadowRoot } = options;
const elements = Array.from(container.querySelectorAll(focusableSelector));
if ((includeContainer == true || includeContainer == "if-empty" && elements.length === 0) && isHTMLElement(container) && isFocusable(container)) elements.unshift(container);
const focusableElements = [];
for (const element of elements) {
if (!isFocusable(element)) continue;
if (isFrame(element) && element.contentDocument) {
const frameBody = element.contentDocument.body;
focusableElements.push(...getFocusables(frameBody, { getShadowRoot }));
continue;
}
focusableElements.push(element);
}
if (getShadowRoot) return collectElementsWithShadowDOM(focusableElements, getShadowRoot, isFocusable);
return focusableElements;
};
function isFocusable(element) {
if (!isHTMLElement(element) || element.closest("[inert]")) return false;
return element.matches(focusableSelector) && isElementVisible(element);
}
function getFirstFocusable(container, options = {}) {
const [first] = getFocusables(container, options);
return first || null;
}
function getTabbables(container, options = {}) {
if (!container) return [];
const { includeContainer, getShadowRoot } = options;
const elements = Array.from(container.querySelectorAll(focusableSelector));
if (includeContainer && isTabbable(container)) elements.unshift(container);
const tabbableElements = [];
for (const element of elements) {
if (!isTabbable(element)) continue;
if (isFrame(element) && element.contentDocument) {
const frameBody = element.contentDocument.body;
tabbableElements.push(...getTabbables(frameBody, { getShadowRoot }));
continue;
}
tabbableElements.push(element);
}
if (getShadowRoot) {
const allElements = collectElementsWithShadowDOM(tabbableElements, getShadowRoot, isTabbable);
if (!allElements.length && includeContainer) return elements;
return allElements;
}
if (!tabbableElements.length && includeContainer) return elements;
return tabbableElements;
}
function isTabbable(el) {
if (isHTMLElement(el) && el.tabIndex > 0) return true;
if (!isFocusable(el) || hasNegativeTabIndex(el)) return false;
return isTabbableRadio(el);
}
function getFirstTabbable(container, options = {}) {
const [first] = getTabbables(container, options);
return first || null;
}
function getLastTabbable(container, options = {}) {
const elements = getTabbables(container, options);
return elements[elements.length - 1] || null;
}
function getTabbableEdges(container, options = {}) {
const elements = getTabbables(container, options);
return [elements[0] || null, elements[elements.length - 1] || null];
}
function getNextTabbable(container, options = {}) {
const { current, getShadowRoot } = options;
const tabbables = getTabbables(container, { getShadowRoot });
const doc = container?.ownerDocument || document;
const currentElement = current ?? getActiveElement(doc);
if (!currentElement) return null;
return tabbables[tabbables.indexOf(currentElement) + 1] || null;
}
function getTabIndex(node) {
if (node.tabIndex < 0) {
if ((NATURALLY_TABBABLE_REGEX.test(node.localName) || isEditableElement(node)) && !hasTabIndex(node)) return 0;
}
return node.tabIndex;
}
//#endregion
//#region src/shared/dom-query/initial-focus.ts
function getInitialFocus(options) {
const { root, getInitialEl, filter, enabled = true } = options;
if (!enabled) return;
let node = null;
node ||= typeof getInitialEl === "function" ? getInitialEl() : getInitialEl;
node ||= root?.querySelector("[data-autofocus],[autofocus]");
if (!node) {
const tabbables = getTabbables(root);
node = filter ? tabbables.filter(filter)[0] : tabbables[0];
}
return node || root || void 0;
}
function isValidTabEvent(event) {
const container = event.currentTarget;
if (!container) return false;
const [firstTabbable, lastTabbable] = getTabbableEdges(container);
if (isActiveElement(firstTabbable) && event.shiftKey) return false;
if (isActiveElement(lastTabbable) && !event.shiftKey) return false;
if (!firstTabbable && !lastTabbable) return false;
return true;
}
//#endregion
//#region src/shared/dom-query/raf.ts
var AnimationFrame = class AnimationFrame {
static create() {
return new AnimationFrame();
}
id = null;
fn_cleanup;
request(fn) {
this.cancel();
this.id = globalThis.requestAnimationFrame(() => {
this.id = null;
this.fn_cleanup = fn?.();
});
}
cancel() {
if (this.id !== null) {
globalThis.cancelAnimationFrame(this.id);
this.id = null;
}
this.fn_cleanup?.();
this.fn_cleanup = void 0;
}
isActive() {
return this.id !== null;
}
cleanup = () => {
this.cancel();
};
};
function raf(fn) {
const frame = AnimationFrame.create();
frame.request(fn);
return frame.cleanup;
}
function nextTick(fn) {
const set = /* @__PURE__ */ new Set();
function raf(fn) {
const id = globalThis.requestAnimationFrame(fn);
set.add(() => globalThis.cancelAnimationFrame(id));
}
raf(() => raf(fn));
return function cleanup() {
set.forEach((fn) => fn());
};
}
function queueBeforeEvent(el, type, cb) {
const cancelTimer = raf(() => {
el.removeEventListener(type, exec, true);
cb();
});
const exec = () => {
cancelTimer();
cb();
};
el.addEventListener(type, exec, {
once: true,
capture: true
});
return cancelTimer;
}
//#endregion
//#region src/shared/dom-query/mutation-observer.ts
function observeAttributesImpl(node, options) {
if (!node) return;
const { attributes, callback: fn } = options;
const obs = new (node.ownerDocument.defaultView || window).MutationObserver((changes) => {
for (const change of changes) if (change.type === "attributes" && change.attributeName && attributes.includes(change.attributeName)) fn(change);
});
obs.observe(node, {
attributes: true,
attributeFilter: attributes
});
return () => obs.disconnect();
}
function observeAttributes(nodeOrFn, options) {
const { defer } = options;
const func = defer ? raf : (v) => v();
const cleanups = [];
cleanups.push(func(() => {
const node = typeof nodeOrFn === "function" ? nodeOrFn() : nodeOrFn;
cleanups.push(observeAttributesImpl(node, options));
}));
return () => {
cleanups.forEach((fn) => fn?.());
};
}
function observeChildrenImpl(node, options) {
const { callback: fn } = options;
if (!node) return;
const obs = new (node.ownerDocument.defaultView || window).MutationObserver(fn);
obs.observe(node, {
childList: true,
subtree: true
});
return () => obs.disconnect();
}
function observeChildren(nodeOrFn, options) {
const { defer } = options;
const func = defer ? raf : (v) => v();
const cleanups = [];
cleanups.push(func(() => {
const node = typeof nodeOrFn === "function" ? nodeOrFn() : nodeOrFn;
cleanups.push(observeChildrenImpl(node, options));
}));
return () => {
cleanups.forEach((fn) => fn?.());
};
}
//#endregion
//#region src/shared/dom-query/navigate.ts
function navigate(items, current, options = {}) {
if (!current) return null;
const { orientation = "both", loop = true, dir = "ltr", key } = options;
if (!items.length || !key) return null;
const isVertical = key === "ArrowUp" || key === "ArrowDown";
const isHorizontal = key === "ArrowLeft" || key === "ArrowRight";
if (!isVertical && !isHorizontal && key !== "Home" && key !== "End") return null;
if (orientation === "vertical" && isHorizontal || orientation === "horizontal" && isVertical) return null;
if (key === "Home") return items[0] || null;
if (key === "End") return items[items.length - 1] || null;
const idx = items.indexOf(current);
if (idx === -1) return null;
let isForward;
if (orientation === "both") isForward = key === "ArrowDown" || (dir === "ltr" ? key === "ArrowRight" : key === "ArrowLeft");
else isForward = isVertical ? key === "ArrowDown" : dir === "ltr" ? key === "ArrowRight" : key === "ArrowLeft";
return items[isForward ? loop ? (idx + 1) % items.length : Math.min(idx + 1, items.length - 1) : loop ? (idx - 1 + items.length) % items.length : Math.max(0, idx - 1)] || null;
}
function clickIfLink(el) {
const click = () => {
const win = getWindow(el);
el.dispatchEvent(new win.MouseEvent("click"));
};
if (isFirefox()) queueBeforeEvent(el, "keyup", click);
else queueMicrotask(click);
}
//#endregion
//#region src/shared/dom-query/overflow.ts
function getNearestOverflowAncestor(el) {
const parentNode = getParentNode(el);
if (isRootElement(parentNode)) return getDocument(parentNode).body;
if (isHTMLElement(parentNode) && isOverflowElement(parentNode)) return parentNode;
return getNearestOverflowAncestor(parentNode);
}
function getOverflowAncestors(el, list = []) {
const scrollableAncestor = getNearestOverflowAncestor(el);
const isBody = scrollableAncestor === el.ownerDocument.body;
const win = getWindow(scrollableAncestor);
if (isBody) return list.concat(win, win.visualViewport || [], isOverflowElement(scrollableAncestor) ? scrollableAncestor : []);
return list.concat(scrollableAncestor, getOverflowAncestors(scrollableAncestor, []));
}
const getElementRect = (el) => {
if (isHTMLElement(el)) return el.getBoundingClientRect();
if (isVisualViewport(el)) return {
top: 0,
left: 0,
bottom: el.height,
right: el.width
};
return {
top: 0,
left: 0,
bottom: el.innerHeight,
right: el.innerWidth
};
};
function isInView(el, ancestor) {
if (!isHTMLElement(el)) return true;
const ancestorRect = getElementRect(ancestor);
const elRect = el.getBoundingClientRect();
return elRect.top >= ancestorRect.top && elRect.left >= ancestorRect.left && elRect.bottom <= ancestorRect.bottom && elRect.right <= ancestorRect.right;
}
const OVERFLOW_RE = /auto|scroll|overlay|hidden|clip/;
const nonOverflowValues = new Set(["inline", "contents"]);
function isOverflowElement(el) {
const { overflow, overflowX, overflowY, display } = getWindow(el).getComputedStyle(el);
return OVERFLOW_RE.test(overflow + overflowY + overflowX) && !nonOverflowValues.has(display);
}
function isScrollable(el) {
return el.scrollHeight > el.clientHeight || el.scrollWidth > el.clientWidth;
}
function scrollIntoView(el, options) {
const { rootEl, ...scrollOptions } = options || {};
if (!el || !rootEl) return;
if (!isOverflowElement(rootEl) || !isScrollable(rootEl)) return;
el.scrollIntoView(scrollOptions);
}
function getScrollPosition(element) {
if (isHTMLElement(element)) return {
scrollLeft: element.scrollLeft,
scrollTop: element.scrollTop
};
return {
scrollLeft: element.scrollX,
scrollTop: element.scrollY
};
}
//#endregion
//#region src/shared/dom-query/point.ts
function getRelativePoint(point, element) {
const { left, top, width, height } = element.getBoundingClientRect();
const offset = {
x: point.x - left,
y: point.y - top
};
const percent = {
x: clamp(offset.x / width),
y: clamp(offset.y / height)
};
function getPercentValue(options = {}) {
const { dir = "ltr", orientation = "horizontal", inverted } = options;
const invertX = typeof inverted === "object" ? inverted.x : inverted;
const invertY = typeof inverted === "object" ? inverted.y : inverted;
if (orientation === "horizontal") return dir === "rtl" || invertX ? 1 - percent.x : percent.x;
return invertY ? 1 - percent.y : percent.y;
}
return {
offset,
percent,
getPercentValue
};
}
//#endregion
//#region src/shared/dom-query/pointer-lock.ts
function requestPointerLock(doc, fn) {
const body = doc.body;
const supported = "pointerLockElement" in doc || "mozPointerLockElement" in doc;
const isLocked = () => !!doc.pointerLockElement;
function onPointerChange() {
fn?.(isLocked());
}
function onPointerError(event) {
if (isLocked()) fn?.(false);
console.error("PointerLock error occurred:", event);
doc.exitPointerLock();
}
if (!supported) return;
try {
body.requestPointerLock();
} catch {}
const cleanup = [addDomEvent(doc, "pointerlockchange", onPointerChange, false), addDomEvent(doc, "pointerlockerror", onPointerError, false)];
return () => {
cleanup.forEach((cleanup) => cleanup());
doc.exitPointerLock();
};
}
//#endregion
//#region src/shared/dom-query/text-selection.ts
let state = "default";
let userSelect = "";
const elementMap = /* @__PURE__ */ new WeakMap();
function disableTextSelectionImpl(options = {}) {
const { target, doc } = options;
const docNode = doc ?? document;
const rootEl = docNode.documentElement;
if (isIos()) {
if (state === "default") {
userSelect = rootEl.style.webkitUserSelect;
rootEl.style.webkitUserSelect = "none";
}
state = "disabled";
} else if (target) {
elementMap.set(target, target.style.userSelect);
target.style.userSelect = "none";
}
return () => restoreTextSelection({
target,
doc: docNode
});
}
function restoreTextSelection(options = {}) {
const { target, doc } = options;
const rootEl = (doc ?? document).documentElement;
if (isIos()) {
if (state !== "disabled") return;
state = "restoring";
setTimeout(() => {
nextTick(() => {
if (state === "restoring") {
if (rootEl.style.webkitUserSelect === "none") rootEl.style.webkitUserSelect = userSelect || "";
userSelect = "";
state = "default";
}
});
}, 300);
} else if (target && elementMap.has(target)) {
const prevUserSelect = elementMap.get(target);
if (target.style.userSelect === "none") target.style.userSelect = prevUserSelect ?? "";
if (target.getAttribute("style") === "") target.removeAttribute("style");
elementMap.delete(target);
}
}
function disableTextSelection(options = {}) {
const { defer, target, ...restOptions } = options;
const func = defer ? raf : (v) => v();
const cleanups = [];
cleanups.push(func(() => {
const node = typeof target === "function" ? target() : target;
cleanups.push(disableTextSelectionImpl({
...restOptions,
target: node
}));
}));
return () => {
cleanups.forEach((fn) => fn?.());
};
}
//#endregion
//#region src/shared/dom-query/pointer-move.ts
function trackPointerMove(doc, handlers) {
const { onPointerMove, onPointerUp } = handlers;
const handleMove = (event) => {
const point = getEventPoint(event);
if (Math.sqrt(point.x ** 2 + point.y ** 2) < (event.pointerType === "touch" ? 10 : 5)) return;
if (event.pointerType === "mouse" && event.buttons === 0) {
handleUp(event);
return;
}
onPointerMove({
point,
event
});
};
const handleUp = (event) => {
onPointerUp({
point: getEventPoint(event),
event
});
};
const cleanups = [
addDomEvent(doc, "pointermove", handleMove, false),
addDomEvent(doc, "pointerup", handleUp, false),
addDomEvent(doc, "pointercancel", handleUp, false),
addDomEvent(doc, "contextmenu", handleUp, false),
disableTextSelection({ doc })
];
return () => {
cleanups.forEach((cleanup) => cleanup());
};
}
//#endregion
//#region src/shared/dom-query/press.ts
function trackPress(options) {
const { pointerNode, keyboardNode = pointerNode, onPress, onPressStart, onPressEnd, isValidKey = (e) => e.key === "Enter" } = options;
if (!pointerNode) return noop;
const win = getWindow(pointerNode);
let removeStartListeners = noop;
let removeEndListeners = noop;
let removeAccessibleListeners = noop;
const getInfo = (event) => ({
point: getEventPoint(event),
event
});
function startPress(event) {
onPressStart?.(getInfo(event));
}
function cancelPress(event) {
onPressEnd?.(getInfo(event));
}
const startPointerPress = (startEvent) => {
removeEndListeners();
const endPointerPress = (endEvent) => {
if (contains(pointerNode, getEventTarget(endEvent))) onPress?.(getInfo(endEvent));
else onPressEnd?.(getInfo(endEvent));
};
removeEndListeners = pipe(addDomEvent(win, "pointerup", endPointerPress, {
passive: !onPress,
once: true
}), addDomEvent(win, "pointercancel", cancelPress, {
passive: !onPressEnd,
once: true
}));
if (isActiveElement(keyboardNode) && startEvent.pointerType === "mouse") startEvent.preventDefault();
startPress(startEvent);
};
removeStartListeners = pipe(addDomEvent(pointerNode, "pointerdown", startPointerPress, { passive: !onPressStart }), addDomEvent(keyboardNode, "focus", startAccessiblePress));
function startAccessiblePress() {
const handleKeydown = (keydownEvent) => {
if (!isValidKey(keydownEvent)) return;
const handleKeyup = (keyupEvent) => {
if (!isValidKey(keyupEvent)) return;
const info = getInfo(new win.PointerEvent("pointerup"));
onPress?.(info);
onPressEnd?.(info);
};
removeEndListeners();
removeEndListeners = addDomEvent(keyboardNode, "keyup", handleKeyup);
startPress(new win.PointerEvent("pointerdown"));
};
const handleBlur = () => {
cancelPress(new win.PointerEvent("pointercancel"));
};
removeAccessibleListeners = pipe(addDomEvent(keyboardNode, "keydown", handleKeydown), addDomEvent(keyboardNode, "blur", handleBlur));
}
return () => {
removeStartListeners();
removeEndListeners();
removeAccessibleListeners();
};
}
//#endregion
//#region src/shared/dom-query/proxy-tab-focus.ts
function proxyTabFocusImpl(container, options = {}) {
const { triggerElement, onFocus, onFocusEnter, getShadowRoot } = options;
const doc = container?.ownerDocument || document;
const body = doc.body;
function onKeyDown(event) {
if (event.key !== "Tab") return;
let elementToFocus = null;
const [firstTabbable, lastTabbable] = getTabbableEdges(container, {
includeContainer: true,
getShadowRoot
});
const nextTabbableAfterTrigger = getNextTabbable(body, {
current: triggerElement,
getShadowRoot
});
const noTabbableElements = !firstTabbable && !lastTabbable;
if (event.shiftKey && isActiveElement(nextTabbableAfterTrigger)) {
onFocusEnter?.();
elementToFocus = lastTabbable;
} else if (event.shiftKey && (isActiveElement(firstTabbable) || noTabbableElements)) elementToFocus = triggerElement;
else if (!event.shiftKey && isActiveElement(triggerElement)) {
onFocusEnter?.();
elementToFocus = firstTabbable;
} else if (!event.shiftKey && (isActiveElement(lastTabbable) || noTabbableElements)) elementToFocus = nextTabbableAfterTrigger;
if (!elementToFocus) return;
event.preventDefault();
if (typeof onFocus === "function") onFocus(elementToFocus);
else elementToFocus.focus();
}
return addDomEvent(doc, "keydown", onKeyDown, true);
}
function proxyTabFocus(container, options) {
const { defer, triggerElement, ...restOptions } = options;
const func = defer ? raf : (v) => v();
const cleanups = [];
cleanups.push(func(() => {
const node = typeof container === "function" ? container() : container;
const trigger = typeof triggerElement === "function" ? triggerElement() : triggerElement;
cleanups.push(proxyTabFocusImpl(node, {
triggerElement: trigger,
...restOptions
}));
}));
return () => {
cleanups.forEach((fn) => fn?.());
};
}
//#endregion
//#region src/shared/dom-query/query.ts
function queryAll(root, selector) {
return Array.from(root?.querySelectorAll(selector) ?? []);
}
function query(root, selector) {
return root?.querySelector(selector) ?? null;
}
const defaultItemToId = (v) => v.id;
function itemById(v, id, itemToId = defaultItemToId) {
return v.find((item) => itemToId(item) === id);
}
function indexOfId(v, id, itemToId = defaultItemToId) {
const item = itemById(v, id, itemToId);
return item ? v.indexOf(item) : -1;
}
function nextById(v, id, loop = true) {
let idx = indexOfId(v, id);
idx = loop ? (idx + 1) % v.length : Math.min(idx + 1, v.length - 1);
return v[idx];
}
function prevById(v, id, loop = true) {
let idx = indexOfId(v, id);
if (idx === -1) return loop ? v[v.length - 1] : null;
idx = loop ? (idx - 1 + v.length) % v.length : Math.max(0, idx - 1);
return v[idx];
}
//#endregion
//#region src/shared/dom-query/resize-observer.ts
function createSharedResizeObserver(options) {
const listeners = /* @__PURE__ */ new WeakMap();
let observer;
const entries = /* @__PURE__ */ new WeakMap();
const getObserver = (win) => {
if (observer) return observer;
observer = new win.ResizeObserver((observedEntries) => {
for (const entry of observedEntries) {
entries.set(entry.target, entry);
const elementListeners = listeners.get(entry.target);
if (elementListeners) for (const listener of elementListeners) listener(entry);
}
});
return observer;
};
const observe = (element, listener) => {
let elementListeners = listeners.get(element) || /* @__PURE__ */ new Set();
elementListeners.add(listener);
listeners.set(element, elementListeners);
const win = getWindow(element);
getObserver(win).observe(element, options);
return () => {
const elementListeners = listeners.get(element);
if (!elementListeners) return;
elementListeners.delete(listener);
if (elementListeners.size === 0) {
listeners.delete(element);
getObserver(win).unobserve(element);
}
};
};
const unobserve = (element) => {
listeners.delete(element);
observer?.unobserve(element);
};
return {
observe,
unobserve
};
}
const resizeObserverContentBox = /* @__PURE__ */ createSharedResizeObserver({ box: "content-box" });
const resizeObserverBorderBox = /* @__PURE__ */ createSharedResizeObserver({ box: "border-box" });
const resizeObserverDevicePixelContentBox = /* @__PURE__ */ createSharedResizeObserver({ box: "device-pixel-content-box" });
//#endregion
//#region src/shared/dom-query/scale.ts
function getScale(element) {
const rect = element.getBoundingClientRect();
const offsetWidth = element.offsetWidth;
const offsetHeight = element.offsetHeight;
const hasTransform = Math.round(rect.width) !== offsetWidth || Math.round(rect.height) !== offsetHeight;
let x = hasTransform ? Math.round(rect.width) / offsetWidth : 1;
let y = hasTransform ? Math.round(rect.height) / offsetHeight : 1;
if (!x || !Number.isFinite(x)) x = 1;
if (!y || !Number.isFinite(y)) y = 1;
return {
x,
y
};
}
//#endregion
//#region src/shared/dom-query/scope.ts
function createScope(methods) {
const dom = {
getRootNode: (ctx) => ctx.getRootNode?.() ?? document,
getDoc: (ctx) => getDocument(dom.getRootNode(ctx)),
getWin: (ctx) => dom.getDoc(ctx).defaultView ?? window,
getActiveElement: (ctx) => getActiveElement(dom.getRootNode(ctx)),
isActiveElement,
getById: (ctx, id) => dom.getRootNode(ctx).getElementById(id),
setValue: (elem, value) => {
if (elem == null || value == null) return;
setElementValue(elem, value.toString());
}
};
return {
...dom,
...methods
};
}
//#endregion
//#region src/shared/dom-query/searchable.ts
const sanitize = (str) => str.split("").map((char) => {
const code = char.charCodeAt(0);
if (code > 0 && code < 128) return char;
if (code >= 128 && code <= 255) return `/x${code.toString(16)}`.replace("/", "\\");
return "";
}).join("").trim();
const getValueText = (el) => {
return sanitize(el.dataset?.valuetext ?? el.textContent ?? "");
};
const match = (valueText, query) => {
return valueText.trim().toLowerCase().startsWith(query.toLowerCase());
};
function getByText(v, text, currentId, itemToId = defaultItemToId) {
const index = currentId ? indexOfId(v, currentId, itemToId) : -1;
let items = currentId ? wrap(v, index) : v;
if (text.length === 1) items = items.filter((item) => itemToId(item) !== currentId);
return items.find((item) => match(getValueText(item), text));
}
//#endregion
//#region src/shared/dom-query/set.ts
function setAttribute(el, attr, v) {
const prev = el.getAttribute(attr);
const exists = prev != null;
if (prev === v) return noop;
el.setAttribute(attr, v);
return () => {
if (!exists) el.removeAttribute(attr);
else el.setAttribute(attr, prev);
};
}
function setProperty(el, prop, v) {
const exists = prop in el;
const prev = el[prop];
if (prev === v) return noop;
el[prop] = v;
return () => {
if (!exists) delete el[prop];
else el[prop] = prev;
};
}
function setStyle(el, style) {
if (!el) return noop;
const prev = Object.keys(style).reduce((acc, key) => {
acc[key] = el.style.getPropertyValue(key);
return acc;
}, {});
if (isEqual(prev, style)) return noop;
Object.assign(el.style, style);
return () => {
Object.assign(el.style, prev);
if (el.style.length === 0) el.removeAttribute("style");
};
}
function setStyleProperty(el, prop, value) {
if (!el) return noop;
const prev = el.style.getPropertyValue(prop);
if (prev === value) return noop;
el.style.setProperty(prop, value);
return () => {
el.style.setProperty(prop, prev);
if (el.style.length === 0) el.removeAttribute("style");
};
}
function isEqual(a, b) {
return Object.keys(a).every((key) => a[key] === b[key]);
}
//#endregion
//#region src/shared/dom-query/typeahead.ts
function getByTypeaheadImpl(baseItems, options) {
const { state, activeId, key, timeout = 350, itemToId } = options;
const search = state.keysSoFar + key;
const query = search.length > 1 && Array.from(search).every((char) => char === search[0]) ? search[0] : search;
const next = getByText(baseItems.slice(), query, activeId, itemToId);
function cleanup() {
clearTimeout(state.timer);
state.timer = -1;
}
function update(value) {
state.keysSoFar = value;
cleanup();
if (value !== "") state.timer = +setTimeout(() => {
update("");
cleanup();
}, timeout);
}
update(search);
return next;
}
const getByTypeahead = Object.assign(getByTypeaheadImpl, {
defaultOptions: {
keysSoFar: "",
timer: -1
},
isValidEvent: isValidTypeaheadEvent
});
function isValidTypeaheadEvent(event) {
return event.key.length === 1 && !event.ctrlKey && !event.metaKey;
}
//#endregion
//#region src/shared/dom-query/visual-viewport.ts
function trackVisualViewport(doc, fn) {
const win = doc?.defaultView || window;
const onResize = () => {
fn?.(getViewportSize(win));
};
onResize();
return addDomEvent(win.visualViewport ?? win, "resize", onResize);
}
function getViewportSize(win) {
return {
width: win.visualViewport?.width || win.innerWidth,
height: win.visualViewport?.height || win.innerHeight
};
}
//#endregion
//#region src/shared/dom-query/visually-hidden.ts
const visuallyHiddenStyle = {
border: "0",
clip: "rect(0 0 0 0)",
height: "1px",
margin: "-1px",
overflow: "hidden",
padding: "0",
position: "absolute",
width: "1px",
whiteSpace: "nowrap",
wordWrap: "normal"
};
function setVisuallyHidden(el) {
Object.assign(el.style, visuallyHiddenStyle);
}
//#endregion
//#region src/shared/dom-query/wait-for.ts
function waitForPromise(promise, controller, timeout) {
const { signal } = controller;
const wrappedPromise = new Promise((resolve, reject) => {
const timeoutId = setTimeout(() => {
reject(/* @__PURE__ */ new Error(`Timeout of ${timeout}ms exceeded`));
}, timeout);
signal.addEventListener("abort", () => {
clearTimeout(timeoutId);
reject(new DOMException("Promise aborted", "AbortError"));
});
promise.then((result) => {
if (!signal.aborted) {
clearTimeout(timeoutId);
resolve(result);
}
}).catch((error) => {
if (!signal.aborted) {
clearTimeout(timeoutId);
reject(error);
}
});
});
const abort = () => controller.abort();
return [wrappedPromise, abort];
}
function waitForElement(target, options) {
const { timeout, rootNode } = options;
const win = getWindow(rootNode);
const doc = getDocument(rootNode);
const controller = new win.AbortController();
return waitForPromise(new Promise((resolve) => {
const el = target();
if (el) {
resolve(el);
return;
}
const observer = new win.MutationObserver(() => {
const el = target();
if (el && el.isConnected) {
observer.disconnect();
resolve(el);
}
});
observer.observe(doc.body, {
childList: true,
subtree: true
});
}), controller, timeout);
}
function waitForEvent(target, event, options) {
let cleanup;
const { predicate, ...listenerOptions } = options ?? {};
return [new Promise((resolve) => {
const element = target?.();
if (!element) return;
const handler = (e) => {
if (!predicate || predicate(element)) {
resolve(e);
cleanup?.();
}
};
element.addEventListener(event, handler, listenerOptions);
cleanup = () => element.removeEventListener(event, handler, listenerOptions);
}), () => cleanup?.()];
}
//#endregion
export { getTabIndex as $, getComputedStyle as $t, requestPointerLock as A, isVirtualPointerEvent as At, observeAttributes as B, isIos as Bt, query as C, MAX_Z_INDEX as Cn, isLeftClick as Ct, trackPointerMove as D, setCaretToEnd as Dn, isSelfTarget as Dt, trackPress as E, isCaretAtStart as En, isPrintableKey as Et, isInView as F, isChrome as Ft, raf as G, getDataUrl as Gt, AnimationFrame as H, isSafari as Ht, isOverflowElement as I, isDom as It, getFirstFocusable as J, hasControllerElements as Jt, getInitialFocus as K, findControlledElements as Kt, scrollIntoView as L, isFirefox as Lt, getNearestOverflowAncestor as M, getUserAgent as Mt, getOverflowAncestors as N, isAndroid as Nt, disableTextSelection as O, isTouchEvent as Ot, getScrollPosition as P, isApple as Pt, getNextTabbable as Q, isInteractiveContainerElement as Qt, clickIfLink as R, isIPad as Rt, prevById as S, isWindow as Sn, isKeyboardClick as St, proxyTabFocus as T, dataAttr as Tn, isOpeningInNewTab as Tt, nextTick as U, isTouchDevice as Ut, observeChildren as V, isMac as Vt, queueBeforeEvent as W, isWebKit as Wt, getFocusables as X, isControlledElement as Xt, getFirstTabbable as Y, isControlledByExpandedController as Yt, getLastTabbable as Z, isControllerElement as Zt, resizeObserverDevicePixelContentBox as _, isInputElement as _n, getNativeEvent as _t, visuallyHiddenStyle as a, getNodeName as an, dispatchInputValueEvent as at, itemById as b, isShadowRoot as bn, isCtrlOrMetaKey as bt, setAttribute as c, getRootNode as cn, setElementChecked as ct, setStyleProperty as d, isAnchorElement as dn, addDomEvent as dt, contains as en, getTabbableEdges as et, getByText as f, isDocument as fn, getBeforeInputValue as ft, resizeObserverContentBox as g, isHTMLElement as gn, getEventTarget as gt, resizeObserverBorderBox as h, isElementVisible as hn, getEventStep as ht, setVisuallyHidden as i, getDocumentElement as in, dispatchInputCheckedEvent as it, getRelativePoint as j, getPlatform as jt, restoreTextSelection as k, isVirtualClick as kt, setProperty as l, getWindow as ln, setElementValue as lt, getScale as m, isElement as mn, getEventPoint as mt, waitForEvent as n, getAncestorElements as nn, isFocusable as nt, trackVisualViewport as o, getParentElement as on, isInternalChangeEvent as ot, createScope as p, isEditableElement as pn, getEventKey as pt, isValidTabEvent as q, getControlledElements as qt, waitForPromise as r, getDocument as rn, isTabbable as rt, getByTypeahead as s, getParentNode as sn, markAsInternalChangeEvent as st, waitForElement as t, getActiveElement as tn, getTabbables as tt, setStyle as u, isActiveElement as un, trackFormControl as ut, defaultItemToId as v, isNode as vn, isComposingEvent as vt, queryAll as w, ariaAttr as wn, isModifierKey as wt, nextById as x, isVisualViewport as xn, isDownloadingEvent as xt, indexOfId as y, isRootElement as yn, isContextMenuEvent as yt, navigate as z, isIPhone as zt };

Sorry, the diff of this file is too big to display

Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_dom_query = require("./dom-query-BT6fffRP.cjs");
exports.AnimationFrame = require_dom_query.AnimationFrame;
exports.MAX_Z_INDEX = require_dom_query.MAX_Z_INDEX;
exports.addDomEvent = require_dom_query.addDomEvent;
exports.ariaAttr = require_dom_query.ariaAttr;
exports.clickIfLink = require_dom_query.clickIfLink;
exports.contains = require_dom_query.contains;
exports.createScope = require_dom_query.createScope;
exports.dataAttr = require_dom_query.dataAttr;
exports.defaultItemToId = require_dom_query.defaultItemToId;
exports.disableTextSelection = require_dom_query.disableTextSelection;
exports.dispatchInputCheckedEvent = require_dom_query.dispatchInputCheckedEvent;
exports.dispatchInputValueEvent = require_dom_query.dispatchInputValueEvent;
exports.findControlledElements = require_dom_query.findControlledElements;
exports.getActiveElement = require_dom_query.getActiveElement;
exports.getAncestorElements = require_dom_query.getAncestorElements;
exports.getBeforeInputValue = require_dom_query.getBeforeInputValue;
exports.getByText = require_dom_query.getByText;
exports.getByTypeahead = require_dom_query.getByTypeahead;
exports.getComputedStyle = require_dom_query.getComputedStyle;
exports.getControlledElements = require_dom_query.getControlledElements;
exports.getDataUrl = require_dom_query.getDataUrl;
exports.getDocument = require_dom_query.getDocument;
exports.getDocumentElement = require_dom_query.getDocumentElement;
exports.getEventKey = require_dom_query.getEventKey;
exports.getEventPoint = require_dom_query.getEventPoint;
exports.getEventStep = require_dom_query.getEventStep;
exports.getEventTarget = require_dom_query.getEventTarget;
exports.getFirstFocusable = require_dom_query.getFirstFocusable;
exports.getFirstTabbable = require_dom_query.getFirstTabbable;
exports.getFocusables = require_dom_query.getFocusables;
exports.getInitialFocus = require_dom_query.getInitialFocus;
exports.getLastTabbable = require_dom_query.getLastTabbable;
exports.getNativeEvent = require_dom_query.getNativeEvent;
exports.getNearestOverflowAncestor = require_dom_query.getNearestOverflowAncestor;
exports.getNextTabbable = require_dom_query.getNextTabbable;
exports.getNodeName = require_dom_query.getNodeName;
exports.getOverflowAncestors = require_dom_query.getOverflowAncestors;
exports.getParentElement = require_dom_query.getParentElement;
exports.getParentNode = require_dom_query.getParentNode;
exports.getPlatform = require_dom_query.getPlatform;
exports.getRelativePoint = require_dom_query.getRelativePoint;
exports.getRootNode = require_dom_query.getRootNode;
exports.getScale = require_dom_query.getScale;
exports.getScrollPosition = require_dom_query.getScrollPosition;
exports.getTabIndex = require_dom_query.getTabIndex;
exports.getTabbableEdges = require_dom_query.getTabbableEdges;
exports.getTabbables = require_dom_query.getTabbables;
exports.getUserAgent = require_dom_query.getUserAgent;
exports.getWindow = require_dom_query.getWindow;
exports.hasControllerElements = require_dom_query.hasControllerElements;
exports.indexOfId = require_dom_query.indexOfId;
exports.isActiveElement = require_dom_query.isActiveElement;
exports.isAnchorElement = require_dom_query.isAnchorElement;
exports.isAndroid = require_dom_query.isAndroid;
exports.isApple = require_dom_query.isApple;
exports.isCaretAtStart = require_dom_query.isCaretAtStart;
exports.isChrome = require_dom_query.isChrome;
exports.isComposingEvent = require_dom_query.isComposingEvent;
exports.isContextMenuEvent = require_dom_query.isContextMenuEvent;
exports.isControlledByExpandedController = require_dom_query.isControlledByExpandedController;
exports.isControlledElement = require_dom_query.isControlledElement;
exports.isControllerElement = require_dom_query.isControllerElement;
exports.isCtrlOrMetaKey = require_dom_query.isCtrlOrMetaKey;
exports.isDocument = require_dom_query.isDocument;
exports.isDom = require_dom_query.isDom;
exports.isDownloadingEvent = require_dom_query.isDownloadingEvent;
exports.isEditableElement = require_dom_query.isEditableElement;
exports.isElement = require_dom_query.isElement;
exports.isElementVisible = require_dom_query.isElementVisible;
exports.isFirefox = require_dom_query.isFirefox;
exports.isFocusable = require_dom_query.isFocusable;
exports.isHTMLElement = require_dom_query.isHTMLElement;
exports.isIPad = require_dom_query.isIPad;
exports.isIPhone = require_dom_query.isIPhone;
exports.isInView = require_dom_query.isInView;
exports.isInputElement = require_dom_query.isInputElement;
exports.isInteractiveContainerElement = require_dom_query.isInteractiveContainerElement;
exports.isInternalChangeEvent = require_dom_query.isInternalChangeEvent;
exports.isIos = require_dom_query.isIos;
exports.isKeyboardClick = require_dom_query.isKeyboardClick;
exports.isLeftClick = require_dom_query.isLeftClick;
exports.isMac = require_dom_query.isMac;
exports.isModifierKey = require_dom_query.isModifierKey;
exports.isNode = require_dom_query.isNode;
exports.isOpeningInNewTab = require_dom_query.isOpeningInNewTab;
exports.isOverflowElement = require_dom_query.isOverflowElement;
exports.isPrintableKey = require_dom_query.isPrintableKey;
exports.isRootElement = require_dom_query.isRootElement;
exports.isSafari = require_dom_query.isSafari;
exports.isSelfTarget = require_dom_query.isSelfTarget;
exports.isShadowRoot = require_dom_query.isShadowRoot;
exports.isTabbable = require_dom_query.isTabbable;
exports.isTouchDevice = require_dom_query.isTouchDevice;
exports.isTouchEvent = require_dom_query.isTouchEvent;
exports.isValidTabEvent = require_dom_query.isValidTabEvent;
exports.isVirtualClick = require_dom_query.isVirtualClick;
exports.isVirtualPointerEvent = require_dom_query.isVirtualPointerEvent;
exports.isVisualViewport = require_dom_query.isVisualViewport;
exports.isWebKit = require_dom_query.isWebKit;
exports.isWindow = require_dom_query.isWindow;
exports.itemById = require_dom_query.itemById;
exports.markAsInternalChangeEvent = require_dom_query.markAsInternalChangeEvent;
exports.navigate = require_dom_query.navigate;
exports.nextById = require_dom_query.nextById;
exports.nextTick = require_dom_query.nextTick;
exports.observeAttributes = require_dom_query.observeAttributes;
exports.observeChildren = require_dom_query.observeChildren;
exports.prevById = require_dom_query.prevById;
exports.proxyTabFocus = require_dom_query.proxyTabFocus;
exports.query = require_dom_query.query;
exports.queryAll = require_dom_query.queryAll;
exports.queueBeforeEvent = require_dom_query.queueBeforeEvent;
exports.raf = require_dom_query.raf;
exports.requestPointerLock = require_dom_query.requestPointerLock;
exports.resizeObserverBorderBox = require_dom_query.resizeObserverBorderBox;
exports.resizeObserverContentBox = require_dom_query.resizeObserverContentBox;
exports.resizeObserverDevicePixelContentBox = require_dom_query.resizeObserverDevicePixelContentBox;
exports.restoreTextSelection = require_dom_query.restoreTextSelection;
exports.scrollIntoView = require_dom_query.scrollIntoView;
exports.setAttribute = require_dom_query.setAttribute;
exports.setCaretToEnd = require_dom_query.setCaretToEnd;
exports.setElementChecked = require_dom_query.setElementChecked;
exports.setElementValue = require_dom_query.setElementValue;
exports.setProperty = require_dom_query.setProperty;
exports.setStyle = require_dom_query.setStyle;
exports.setStyleProperty = require_dom_query.setStyleProperty;
exports.setVisuallyHidden = require_dom_query.setVisuallyHidden;
exports.trackFormControl = require_dom_query.trackFormControl;
exports.trackPointerMove = require_dom_query.trackPointerMove;
exports.trackPress = require_dom_query.trackPress;
exports.trackVisualViewport = require_dom_query.trackVisualViewport;
exports.visuallyHiddenStyle = require_dom_query.visuallyHiddenStyle;
exports.waitForElement = require_dom_query.waitForElement;
exports.waitForEvent = require_dom_query.waitForEvent;
exports.waitForPromise = require_dom_query.waitForPromise;
import { $ as getNextTabbable, $n as hasControllerElements, $t as isElementVisible, A as resizeObserverContentBox, An as getEventPoint, At as ScrollOptions, B as nextById, Bn as isModifierKey, Bt as getAncestorElements, C as setStyleProperty, Cn as markAsInternalChangeEvent, Ct as isIPhone, D as createScope, Dn as addDomEvent, Dt as isTouchDevice, E as ScopeContext, En as trackFormControl, Et as isSafari, F as raf, Fn as isContextMenuEvent, Ft as isInView, G as proxyTabFocus, Gn as isVirtualClick, Gt as getParentNode, H as query, Hn as isPrintableKey, Ht as getDocumentElement, I as ItemToId, In as isCtrlOrMetaKey, It as isOverflowElement, J as TabbableOptions, Jn as DataUrlType, Jt as isActiveElement, K as GetShadowRootOption, Kn as isVirtualPointerEvent, Kt as getRootNode, L as defaultItemToId, Ln as isDownloadingEvent, Lt as scrollIntoView, M as AnimationFrame, Mn as getEventTarget, Mt as getNearestOverflowAncestor, N as nextTick, Nn as getNativeEvent, Nt as getOverflowAncestors, O as getScale, On as getBeforeInputValue, Ot as isWebKit, P as queueBeforeEvent, Pn as isComposingEvent, Pt as getScrollPosition, Q as getLastTabbable, Qn as getControlledElements, Qt as isElement, R as indexOfId, Rn as isKeyboardClick, Rt as contains, S as setStyle, Sn as isInternalChangeEvent, St as isIPad, T as getByText, Tn as setElementValue, Tt as isMac, U as queryAll, Un as isSelfTarget, Ut as getNodeName, V as prevById, Vn as isOpeningInNewTab, Vt as getDocument, W as ProxyTabFocusOptions, Wn as isTouchEvent, Wt as getParentElement, X as getFirstTabbable, Xn as ControlledElementOptions, Xt as isDocument, Y as getFirstFocusable, Yn as getDataUrl, Yt as isAnchorElement, Z as getFocusables, Zn as findControlledElements, Zt as isEditableElement, _ as MAX_Z_INDEX, _n as CheckedEventOptions, _t as isAndroid, a as waitForEvent, an as isVisualViewport, ar as isCaretAtStart, at as PressDetails, b as setAttribute, bn as dispatchInputCheckedEvent, bt as isDom, c as visuallyHiddenStyle, cn as clickIfLink, ct as PointerMoveDetails, d as TypeaheadOptions, dn as ObserveChildrenOptions, dt as trackPointerMove, en as isHTMLElement, er as isControlledByExpandedController, et as getTabIndex, f as TypeaheadState, fn as observeAttributes, ft as requestPointerLock, g as restoreTextSelection, gn as isValidTabEvent, gt as getUserAgent, h as disableTextSelection, hn as getInitialFocus, ht as getPlatform, i as waitForElement, in as isShadowRoot, ir as getComputedStyle, it as isTabbable, j as resizeObserverDevicePixelContentBox, jn as getEventStep, jt as ScrollPosition, k as resizeObserverBorderBox, kn as getEventKey, kt as OverflowAncestor, l as ViewportSize, ln as navigate, lt as PointerMoveHandlers, m as DisableTextSelectionOptions, mn as InitialFocusOptions, mt as getRelativePoint, n as WaitForOptions, nn as isNode, nr as isControllerElement, nt as getTabbables, o as waitForPromise, on as isWindow, or as setCaretToEnd, ot as TrackPressOptions, p as getByTypeahead, pn as observeChildren, pt as PercentValueOptions, q as NextTabbableOptions, qn as DataUrlOptions, qt as getWindow, r as WaitForPromiseReturn, rn as isRootElement, rr as isInteractiveContainerElement, rt as isFocusable, s as setVisuallyHidden, sn as NavigateOptions, st as trackPress, t as WaitForEventOptions, tn as isInputElement, tr as isControlledElement, tt as getTabbableEdges, u as trackVisualViewport, un as ObserveAttributeOptions, ut as PointerUpDetails, v as ariaAttr, vn as InputValueEventOptions, vt as isApple, w as SearchableItem, wn as setElementChecked, wt as isIos, x as setProperty, xn as dispatchInputValueEvent, xt as isFirefox, y as dataAttr, yn as TrackFormControlOptions, yt as isChrome, z as itemById, zn as isLeftClick, zt as getActiveElement } from "./index-CeVk_nT2.cjs";
export { AnimationFrame, CheckedEventOptions, ControlledElementOptions, DataUrlOptions, DataUrlType, DisableTextSelectionOptions, GetShadowRootOption, InitialFocusOptions, InputValueEventOptions, ItemToId, MAX_Z_INDEX, NavigateOptions, NextTabbableOptions, ObserveAttributeOptions, ObserveChildrenOptions, OverflowAncestor, PercentValueOptions, PointerMoveDetails, PointerMoveHandlers, PointerUpDetails, PressDetails, ProxyTabFocusOptions, ScopeContext, ScrollOptions, ScrollPosition, SearchableItem, TabbableOptions, TrackFormControlOptions, TrackPressOptions, TypeaheadOptions, TypeaheadState, ViewportSize, WaitForEventOptions, WaitForOptions, WaitForPromiseReturn, addDomEvent, ariaAttr, clickIfLink, contains, createScope, dataAttr, defaultItemToId, disableTextSelection, dispatchInputCheckedEvent, dispatchInputValueEvent, findControlledElements, getActiveElement, getAncestorElements, getBeforeInputValue, getByText, getByTypeahead, getComputedStyle, getControlledElements, getDataUrl, getDocument, getDocumentElement, getEventKey, getEventPoint, getEventStep, getEventTarget, getFirstFocusable, getFirstTabbable, getFocusables, getInitialFocus, getLastTabbable, getNativeEvent, getNearestOverflowAncestor, getNextTabbable, getNodeName, getOverflowAncestors, getParentElement, getParentNode, getPlatform, getRelativePoint, getRootNode, getScale, getScrollPosition, getTabIndex, getTabbableEdges, getTabbables, getUserAgent, getWindow, hasControllerElements, indexOfId, isActiveElement, isAnchorElement, isAndroid, isApple, isCaretAtStart, isChrome, isComposingEvent, isContextMenuEvent, isControlledByExpandedController, isControlledElement, isControllerElement, isCtrlOrMetaKey, isDocument, isDom, isDownloadingEvent, isEditableElement, isElement, isElementVisible, isFirefox, isFocusable, isHTMLElement, isIPad, isIPhone, isInView, isInputElement, isInteractiveContainerElement, isInternalChangeEvent, isIos, isKeyboardClick, isLeftClick, isMac, isModifierKey, isNode, isOpeningInNewTab, isOverflowElement, isPrintableKey, isRootElement, isSafari, isSelfTarget, isShadowRoot, isTabbable, isTouchDevice, isTouchEvent, isValidTabEvent, isVirtualClick, isVirtualPointerEvent, isVisualViewport, isWebKit, isWindow, itemById, markAsInternalChangeEvent, navigate, nextById, nextTick, observeAttributes, observeChildren, prevById, proxyTabFocus, query, queryAll, queueBeforeEvent, raf, requestPointerLock, resizeObserverBorderBox, resizeObserverContentBox, resizeObserverDevicePixelContentBox, restoreTextSelection, scrollIntoView, setAttribute, setCaretToEnd, setElementChecked, setElementValue, setProperty, setStyle, setStyleProperty, setVisuallyHidden, trackFormControl, trackPointerMove, trackPress, trackVisualViewport, visuallyHiddenStyle, waitForElement, waitForEvent, waitForPromise };
import { $ as getNextTabbable, $n as hasControllerElements, $t as isElementVisible, A as resizeObserverContentBox, An as getEventPoint, At as ScrollOptions, B as nextById, Bn as isModifierKey, Bt as getAncestorElements, C as setStyleProperty, Cn as markAsInternalChangeEvent, Ct as isIPhone, D as createScope, Dn as addDomEvent, Dt as isTouchDevice, E as ScopeContext, En as trackFormControl, Et as isSafari, F as raf, Fn as isContextMenuEvent, Ft as isInView, G as proxyTabFocus, Gn as isVirtualClick, Gt as getParentNode, H as query, Hn as isPrintableKey, Ht as getDocumentElement, I as ItemToId, In as isCtrlOrMetaKey, It as isOverflowElement, J as TabbableOptions, Jn as DataUrlType, Jt as isActiveElement, K as GetShadowRootOption, Kn as isVirtualPointerEvent, Kt as getRootNode, L as defaultItemToId, Ln as isDownloadingEvent, Lt as scrollIntoView, M as AnimationFrame, Mn as getEventTarget, Mt as getNearestOverflowAncestor, N as nextTick, Nn as getNativeEvent, Nt as getOverflowAncestors, O as getScale, On as getBeforeInputValue, Ot as isWebKit, P as queueBeforeEvent, Pn as isComposingEvent, Pt as getScrollPosition, Q as getLastTabbable, Qn as getControlledElements, Qt as isElement, R as indexOfId, Rn as isKeyboardClick, Rt as contains, S as setStyle, Sn as isInternalChangeEvent, St as isIPad, T as getByText, Tn as setElementValue, Tt as isMac, U as queryAll, Un as isSelfTarget, Ut as getNodeName, V as prevById, Vn as isOpeningInNewTab, Vt as getDocument, W as ProxyTabFocusOptions, Wn as isTouchEvent, Wt as getParentElement, X as getFirstTabbable, Xn as ControlledElementOptions, Xt as isDocument, Y as getFirstFocusable, Yn as getDataUrl, Yt as isAnchorElement, Z as getFocusables, Zn as findControlledElements, Zt as isEditableElement, _ as MAX_Z_INDEX, _n as CheckedEventOptions, _t as isAndroid, a as waitForEvent, an as isVisualViewport, ar as isCaretAtStart, at as PressDetails, b as setAttribute, bn as dispatchInputCheckedEvent, bt as isDom, c as visuallyHiddenStyle, cn as clickIfLink, ct as PointerMoveDetails, d as TypeaheadOptions, dn as ObserveChildrenOptions, dt as trackPointerMove, en as isHTMLElement, er as isControlledByExpandedController, et as getTabIndex, f as TypeaheadState, fn as observeAttributes, ft as requestPointerLock, g as restoreTextSelection, gn as isValidTabEvent, gt as getUserAgent, h as disableTextSelection, hn as getInitialFocus, ht as getPlatform, i as waitForElement, in as isShadowRoot, ir as getComputedStyle, it as isTabbable, j as resizeObserverDevicePixelContentBox, jn as getEventStep, jt as ScrollPosition, k as resizeObserverBorderBox, kn as getEventKey, kt as OverflowAncestor, l as ViewportSize, ln as navigate, lt as PointerMoveHandlers, m as DisableTextSelectionOptions, mn as InitialFocusOptions, mt as getRelativePoint, n as WaitForOptions, nn as isNode, nr as isControllerElement, nt as getTabbables, o as waitForPromise, on as isWindow, or as setCaretToEnd, ot as TrackPressOptions, p as getByTypeahead, pn as observeChildren, pt as PercentValueOptions, q as NextTabbableOptions, qn as DataUrlOptions, qt as getWindow, r as WaitForPromiseReturn, rn as isRootElement, rr as isInteractiveContainerElement, rt as isFocusable, s as setVisuallyHidden, sn as NavigateOptions, st as trackPress, t as WaitForEventOptions, tn as isInputElement, tr as isControlledElement, tt as getTabbableEdges, u as trackVisualViewport, un as ObserveAttributeOptions, ut as PointerUpDetails, v as ariaAttr, vn as InputValueEventOptions, vt as isApple, w as SearchableItem, wn as setElementChecked, wt as isIos, x as setProperty, xn as dispatchInputValueEvent, xt as isFirefox, y as dataAttr, yn as TrackFormControlOptions, yt as isChrome, z as itemById, zn as isLeftClick, zt as getActiveElement } from "./index-BhthKUrF.mjs";
export { AnimationFrame, CheckedEventOptions, ControlledElementOptions, DataUrlOptions, DataUrlType, DisableTextSelectionOptions, GetShadowRootOption, InitialFocusOptions, InputValueEventOptions, ItemToId, MAX_Z_INDEX, NavigateOptions, NextTabbableOptions, ObserveAttributeOptions, ObserveChildrenOptions, OverflowAncestor, PercentValueOptions, PointerMoveDetails, PointerMoveHandlers, PointerUpDetails, PressDetails, ProxyTabFocusOptions, ScopeContext, ScrollOptions, ScrollPosition, SearchableItem, TabbableOptions, TrackFormControlOptions, TrackPressOptions, TypeaheadOptions, TypeaheadState, ViewportSize, WaitForEventOptions, WaitForOptions, WaitForPromiseReturn, addDomEvent, ariaAttr, clickIfLink, contains, createScope, dataAttr, defaultItemToId, disableTextSelection, dispatchInputCheckedEvent, dispatchInputValueEvent, findControlledElements, getActiveElement, getAncestorElements, getBeforeInputValue, getByText, getByTypeahead, getComputedStyle, getControlledElements, getDataUrl, getDocument, getDocumentElement, getEventKey, getEventPoint, getEventStep, getEventTarget, getFirstFocusable, getFirstTabbable, getFocusables, getInitialFocus, getLastTabbable, getNativeEvent, getNearestOverflowAncestor, getNextTabbable, getNodeName, getOverflowAncestors, getParentElement, getParentNode, getPlatform, getRelativePoint, getRootNode, getScale, getScrollPosition, getTabIndex, getTabbableEdges, getTabbables, getUserAgent, getWindow, hasControllerElements, indexOfId, isActiveElement, isAnchorElement, isAndroid, isApple, isCaretAtStart, isChrome, isComposingEvent, isContextMenuEvent, isControlledByExpandedController, isControlledElement, isControllerElement, isCtrlOrMetaKey, isDocument, isDom, isDownloadingEvent, isEditableElement, isElement, isElementVisible, isFirefox, isFocusable, isHTMLElement, isIPad, isIPhone, isInView, isInputElement, isInteractiveContainerElement, isInternalChangeEvent, isIos, isKeyboardClick, isLeftClick, isMac, isModifierKey, isNode, isOpeningInNewTab, isOverflowElement, isPrintableKey, isRootElement, isSafari, isSelfTarget, isShadowRoot, isTabbable, isTouchDevice, isTouchEvent, isValidTabEvent, isVirtualClick, isVirtualPointerEvent, isVisualViewport, isWebKit, isWindow, itemById, markAsInternalChangeEvent, navigate, nextById, nextTick, observeAttributes, observeChildren, prevById, proxyTabFocus, query, queryAll, queueBeforeEvent, raf, requestPointerLock, resizeObserverBorderBox, resizeObserverContentBox, resizeObserverDevicePixelContentBox, restoreTextSelection, scrollIntoView, setAttribute, setCaretToEnd, setElementChecked, setElementValue, setProperty, setStyle, setStyleProperty, setVisuallyHidden, trackFormControl, trackPointerMove, trackPress, trackVisualViewport, visuallyHiddenStyle, waitForElement, waitForEvent, waitForPromise };
import { $ as getTabIndex, $t as getComputedStyle, A as requestPointerLock, At as isVirtualPointerEvent, B as observeAttributes, Bt as isIos, C as query, Cn as MAX_Z_INDEX, Ct as isLeftClick, D as trackPointerMove, Dn as setCaretToEnd, Dt as isSelfTarget, E as trackPress, En as isCaretAtStart, Et as isPrintableKey, F as isInView, Ft as isChrome, G as raf, Gt as getDataUrl, H as AnimationFrame, Ht as isSafari, I as isOverflowElement, It as isDom, J as getFirstFocusable, Jt as hasControllerElements, K as getInitialFocus, Kt as findControlledElements, L as scrollIntoView, Lt as isFirefox, M as getNearestOverflowAncestor, Mt as getUserAgent, N as getOverflowAncestors, Nt as isAndroid, O as disableTextSelection, Ot as isTouchEvent, P as getScrollPosition, Pt as isApple, Q as getNextTabbable, Qt as isInteractiveContainerElement, R as clickIfLink, Rt as isIPad, S as prevById, Sn as isWindow, St as isKeyboardClick, T as proxyTabFocus, Tn as dataAttr, Tt as isOpeningInNewTab, U as nextTick, Ut as isTouchDevice, V as observeChildren, Vt as isMac, W as queueBeforeEvent, Wt as isWebKit, X as getFocusables, Xt as isControlledElement, Y as getFirstTabbable, Yt as isControlledByExpandedController, Z as getLastTabbable, Zt as isControllerElement, _ as resizeObserverDevicePixelContentBox, _n as isInputElement, _t as getNativeEvent, a as visuallyHiddenStyle, an as getNodeName, at as dispatchInputValueEvent, b as itemById, bn as isShadowRoot, bt as isCtrlOrMetaKey, c as setAttribute, cn as getRootNode, ct as setElementChecked, d as setStyleProperty, dn as isAnchorElement, dt as addDomEvent, en as contains, et as getTabbableEdges, f as getByText, fn as isDocument, ft as getBeforeInputValue, g as resizeObserverContentBox, gn as isHTMLElement, gt as getEventTarget, h as resizeObserverBorderBox, hn as isElementVisible, ht as getEventStep, i as setVisuallyHidden, in as getDocumentElement, it as dispatchInputCheckedEvent, j as getRelativePoint, jt as getPlatform, k as restoreTextSelection, kt as isVirtualClick, l as setProperty, ln as getWindow, lt as setElementValue, m as getScale, mn as isElement, mt as getEventPoint, n as waitForEvent, nn as getAncestorElements, nt as isFocusable, o as trackVisualViewport, on as getParentElement, ot as isInternalChangeEvent, p as createScope, pn as isEditableElement, pt as getEventKey, q as isValidTabEvent, qt as getControlledElements, r as waitForPromise, rn as getDocument, rt as isTabbable, s as getByTypeahead, sn as getParentNode, st as markAsInternalChangeEvent, t as waitForElement, tn as getActiveElement, tt as getTabbables, u as setStyle, un as isActiveElement, ut as trackFormControl, v as defaultItemToId, vn as isNode, vt as isComposingEvent, w as queryAll, wn as ariaAttr, wt as isModifierKey, x as nextById, xn as isVisualViewport, xt as isDownloadingEvent, y as indexOfId, yn as isRootElement, yt as isContextMenuEvent, z as navigate, zt as isIPhone } from "./dom-query-BgxIO7_X.mjs";
export { AnimationFrame, MAX_Z_INDEX, addDomEvent, ariaAttr, clickIfLink, contains, createScope, dataAttr, defaultItemToId, disableTextSelection, dispatchInputCheckedEvent, dispatchInputValueEvent, findControlledElements, getActiveElement, getAncestorElements, getBeforeInputValue, getByText, getByTypeahead, getComputedStyle, getControlledElements, getDataUrl, getDocument, getDocumentElement, getEventKey, getEventPoint, getEventStep, getEventTarget, getFirstFocusable, getFirstTabbable, getFocusables, getInitialFocus, getLastTabbable, getNativeEvent, getNearestOverflowAncestor, getNextTabbable, getNodeName, getOverflowAncestors, getParentElement, getParentNode, getPlatform, getRelativePoint, getRootNode, getScale, getScrollPosition, getTabIndex, getTabbableEdges, getTabbables, getUserAgent, getWindow, hasControllerElements, indexOfId, isActiveElement, isAnchorElement, isAndroid, isApple, isCaretAtStart, isChrome, isComposingEvent, isContextMenuEvent, isControlledByExpandedController, isControlledElement, isControllerElement, isCtrlOrMetaKey, isDocument, isDom, isDownloadingEvent, isEditableElement, isElement, isElementVisible, isFirefox, isFocusable, isHTMLElement, isIPad, isIPhone, isInView, isInputElement, isInteractiveContainerElement, isInternalChangeEvent, isIos, isKeyboardClick, isLeftClick, isMac, isModifierKey, isNode, isOpeningInNewTab, isOverflowElement, isPrintableKey, isRootElement, isSafari, isSelfTarget, isShadowRoot, isTabbable, isTouchDevice, isTouchEvent, isValidTabEvent, isVirtualClick, isVirtualPointerEvent, isVisualViewport, isWebKit, isWindow, itemById, markAsInternalChangeEvent, navigate, nextById, nextTick, observeAttributes, observeChildren, prevById, proxyTabFocus, query, queryAll, queueBeforeEvent, raf, requestPointerLock, resizeObserverBorderBox, resizeObserverContentBox, resizeObserverDevicePixelContentBox, restoreTextSelection, scrollIntoView, setAttribute, setCaretToEnd, setElementChecked, setElementValue, setProperty, setStyle, setStyleProperty, setVisuallyHidden, trackFormControl, trackPointerMove, trackPress, trackVisualViewport, visuallyHiddenStyle, waitForElement, waitForEvent, waitForPromise };
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region src/shared/file-utils/data-transfer.ts
const getItemEntry = (item) => typeof item.getAsEntry === "function" ? item.getAsEntry() : typeof item.webkitGetAsEntry === "function" ? item.webkitGetAsEntry() : null;
const isDirectoryEntry = (entry) => entry.isDirectory;
const isFileEntry = (entry) => entry.isFile;
const addRelativePath = (file, path) => {
Object.defineProperty(file, "relativePath", { value: path ? `${path}/${file.name}` : file.name });
return file;
};
const getFileEntries = (items, traverseDirectories) => Promise.all(Array.from(items).filter((item) => item.kind === "file").map((item) => {
const entry = getItemEntry(item);
if (!entry) return null;
if (isDirectoryEntry(entry) && traverseDirectories) return getDirectoryFiles(entry.createReader(), `${entry.name}`);
if (isFileEntry(entry) && typeof item.getAsFile === "function") {
const file = item.getAsFile();
return Promise.resolve(file ? addRelativePath(file, "") : null);
}
if (isFileEntry(entry)) return new Promise((resolve) => {
entry.file((file) => {
resolve(addRelativePath(file, ""));
});
});
}).filter((b) => b));
const getDirectoryFiles = (reader, path = "") => new Promise((resolve) => {
const entryPromises = [];
const readDirectoryEntries = () => {
reader.readEntries((entries) => {
if (entries.length === 0) {
resolve(Promise.all(entryPromises).then((entries) => entries.flat()));
return;
}
const promises = entries.map((entry) => {
if (!entry) return null;
if (isDirectoryEntry(entry)) return getDirectoryFiles(entry.createReader(), `${path}${entry.name}`);
if (isFileEntry(entry)) return new Promise((resolve) => {
entry.file((file) => {
resolve(addRelativePath(file, path));
});
});
}).filter((b) => b);
entryPromises.push(Promise.all(promises));
readDirectoryEntries();
});
};
readDirectoryEntries();
});
//#endregion
//#region src/shared/file-utils/data-url-to-blob.ts
function dataURItoBlob(uri) {
const binary = atob(uri.split(",")[1]);
const mimeString = uri.split(",")[0].split(":")[1].split(";")[0];
const buffer = new ArrayBuffer(binary.length);
const intArray = new Uint8Array(buffer);
for (let i = 0; i < binary.length; i++) intArray[i] = binary.charCodeAt(i);
return new Blob([buffer], { type: mimeString });
}
//#endregion
//#region src/shared/file-utils/download-file.ts
const BOM_REGEX = /^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i;
const MAC_REGEX = /Macintosh/;
const APPLE_WEBKIT_REGEX = /AppleWebKit/;
const SAFARI_REGEX = /Safari/;
function getBlob(blobOrString, type, appendBOM) {
let blob = typeof blobOrString === "string" ? new Blob([blobOrString], { type }) : blobOrString;
if (appendBOM && BOM_REGEX.test(blob.type)) return new Blob([String.fromCharCode(65279), blob], { type: blob.type });
return blob;
}
function isMSEdge(win) {
return Boolean(win.navigator && win.navigator.msSaveOrOpenBlob);
}
function isWebView(win) {
return win.navigator && MAC_REGEX.test(win.navigator.userAgent) && APPLE_WEBKIT_REGEX.test(win.navigator.userAgent) && !SAFARI_REGEX.test(win.navigator.userAgent);
}
function downloadFile(options) {
const { file, win = window, type, name, appendBOM, revokeTimeout = 0 } = options;
const doc = win.document;
const blob = getBlob(file, type, appendBOM);
const fileName = (file instanceof File ? name || file.name : name) || "file-download";
if (isMSEdge(win)) {
win.navigator.msSaveOrOpenBlob(blob, fileName);
return;
}
const isMacOSWebView = isWebView(win);
const anchor = doc.createElement("a");
if ("download" in anchor && !isMacOSWebView) {
const url = win.URL.createObjectURL(blob);
anchor.href = url;
anchor.rel = "noopener";
anchor.download = fileName;
anchor.style.display = "none";
doc.body.appendChild(anchor);
anchor.dispatchEvent(new win.MouseEvent("click"));
setTimeout(() => {
win.URL.revokeObjectURL(url);
anchor.remove();
}, revokeTimeout);
return;
}
const url = win.URL.createObjectURL(blob);
if (!win.open(url, "_blank")) win.location.href = url;
setTimeout(() => {
win.URL.revokeObjectURL(url);
}, revokeTimeout);
}
//#endregion
//#region src/shared/file-utils/get-accept-attr.ts
function isMIMEType(v) {
return v === "audio/*" || v === "video/*" || v === "image/*" || v === "text/*" || /\w+\/[-+.\w]+/g.test(v);
}
function isExt(v) {
return /^.*\.[\w]+$/.test(v);
}
const isValidMIME = (v) => isMIMEType(v) || isExt(v);
function getAcceptAttrString(accept) {
if (accept == null) return;
if (typeof accept === "string") return accept;
if (Array.isArray(accept)) return accept.filter(isValidMIME).join(",");
return Object.entries(accept).reduce((a, [mimeType, ext]) => [
...a,
mimeType,
...ext
], []).filter(isValidMIME).join(",");
}
//#endregion
//#region src/shared/file-utils/get-file-data-url.ts
const getFileDataUrl = async (file) => {
const reader = new FileReader();
return new Promise((resolve, reject) => {
reader.onerror = () => {
reader.abort();
reject(/* @__PURE__ */ new Error("There was an error reading a file"));
};
reader.onloadend = () => {
const { result } = reader;
if (result instanceof ArrayBuffer) reject(/* @__PURE__ */ new Error("Expected DataURL as string from Blob/File, got ArrayBuffer"));
else resolve(result || void 0);
};
reader.readAsDataURL(file);
});
};
//#endregion
//#region src/shared/file-utils/get-total-file-size.ts
const getTotalFileSize = (files) => {
return files.reduce((acc, file) => acc + file.size, 0);
};
//#endregion
//#region src/shared/file-utils/is-file-equal.ts
const isFileEqual = (file1, file2) => {
return file1.name === file2.name && file1.size === file2.size && file1.type === file2.type;
};
//#endregion
//#region src/shared/file-utils/is-valid-file-size.ts
const isDefined = (v) => v !== void 0 && v !== null;
function isValidFileSize(file, minSize, maxSize) {
if (isDefined(file.size)) {
if (isDefined(minSize) && isDefined(maxSize)) {
if (file.size > maxSize) return [false, "FILE_TOO_LARGE"];
if (file.size < minSize) return [false, "FILE_TOO_SMALL"];
} else if (isDefined(minSize) && file.size < minSize) return [false, "FILE_TOO_SMALL"];
else if (isDefined(maxSize) && file.size > maxSize) return [false, "FILE_TOO_LARGE"];
}
return [true, null];
}
const mimeTypesMap = new Map("3g2_video/3gpp2[3gp,3gpp_video/3gpp[3mf_model/3mf[7z_application/x-7z-compressed[aac_audio/aac[ac_application/pkix-attr-cert[adp_audio/adpcm[adts_audio/aac[ai_application/postscript[aml_application/automationml-aml+xml[amlx_application/automationml-amlx+zip[amr_audio/amr[apk_application/vnd.android.package-archive[apng_image/apng[appcache,manifest_text/cache-manifest[appinstaller_application/appinstaller[appx_application/appx[appxbundle_application/appxbundle[asc_application/pgp-keys[atom_application/atom+xml[atomcat_application/atomcat+xml[atomdeleted_application/atomdeleted+xml[atomsvc_application/atomsvc+xml[au,snd_audio/basic[avi_video/x-msvideo[avci_image/avci[avcs_image/avcs[avif_image/avif[aw_application/applixware[bdoc_application/bdoc[bin,bpk,buffer,deb,deploy,dist,distz,dll,dmg,dms,dump,elc,exe,img,iso,lrf,mar,msi,msm,msp,pkg,so_application/octet-stream[bmp,dib_image/bmp[btf,btif_image/prs.btif[bz2_application/x-bzip2[c_text/x-c[ccxml_application/ccxml+xml[cdfx_application/cdfx+xml[cdmia_application/cdmi-capability[cdmic_application/cdmi-container[cdmid_application/cdmi-domain[cdmio_application/cdmi-object[cdmiq_application/cdmi-queue[cer_application/pkix-cert[cgm_image/cgm[cjs_application/node[class_application/java-vm[coffee,litcoffee_text/coffeescript[conf,def,in,ini,list,log,text,txt_text/plain[cpp,cxx,cc_text/x-c++src[cpl_application/cpl+xml[cpt_application/mac-compactpro[crl_application/pkix-crl[css_text/css[csv_text/csv[cu_application/cu-seeme[cwl_application/cwl[cww_application/prs.cww[davmount_application/davmount+xml[dbk_application/docbook+xml[doc_application/msword[docx_application/vnd.openxmlformats-officedocument.wordprocessingml.document[dsc_text/prs.lines.tag[dssc_application/dssc+der[dtd_application/xml-dtd[dwd_application/atsc-dwd+xml[ear,jar,war_application/java-archive[ecma_application/ecmascript[emf_image/emf[eml,mime_message/rfc822[emma_application/emma+xml[emotionml_application/emotionml+xml[eot_application/vnd.ms-fontobject[eps,ps_application/postscript[epub_application/epub+zip[exi_application/exi[exp_application/express[exr_image/aces[ez_application/andrew-inset[fdf_application/fdf[fdt_application/fdt+xml[fits_image/fits[flac_audio/flac[flv_video/x-flv[g3_image/g3fax[geojson_application/geo+json[gif_image/gif[glb_model/gltf-binary[gltf_model/gltf+json[gml_application/gml+xml[go_text/x-go[gpx_application/gpx+xml[gz_application/gzip[h_text/x-h[h261_video/h261[h263_video/h263[h264_video/h264[heic_image/heic[heics_image/heic-sequence[heif_image/heif[heifs_image/heif-sequence[htm,html,shtml_text/html[ico_image/x-icon[icns_image/x-icns[ics,ifb_text/calendar[iges,igs_model/iges[ink,inkml_application/inkml+xml[ipa_application/octet-stream[java_text/x-java-source[jp2,jpg2_image/jp2[jpeg,jpe,jpg_image/jpeg[jpf,jpx_image/jpx[jpm,jpgm_image/jpm[jpgv_video/jpeg[jph_image/jph[js,mjs_text/javascript[json_application/json[json5_application/json5[jsonld_application/ld+json[jsx_text/jsx[jxl_image/jxl[jxr_image/jxr[ktx_image/ktx[ktx2_image/ktx2[less_text/less[m1v,m2v,mpe,mpeg,mpg_video/mpeg[m4a_audio/mp4[m4v_video/x-m4v[md,markdown_text/markdown[mid,midi,kar,rmi_audio/midi[mkv_video/x-matroska[mp2,mp2a,mp3,mpga,m3a,m2a_audio/mpeg[mp4,mp4v,mpg4_video/mp4[mp4a_audio/mp4[mp4s,m4p_application/mp4[odp_application/vnd.oasis.opendocument.presentation[oda_application/oda[ods_application/vnd.oasis.opendocument.spreadsheet[odt_application/vnd.oasis.opendocument.text[oga,ogg,opus,spx_audio/ogg[ogv_video/ogg[ogx_application/ogg[otf_font/otf[p12,pfx_application/x-pkcs12[pdf_application/pdf[pem_application/x-pem-file[php_text/x-php[png_image/png[ppt_application/vnd.ms-powerpoint[pptx_application/vnd.openxmlformats-officedocument.presentationml.presentation[pskcxml_application/pskc+xml[psd_image/vnd.adobe.photoshop[py_text/x-python[qt,mov_video/quicktime[rar_application/vnd.rar[rdf_application/rdf+xml[rtf_text/rtf[sass_text/x-sass[scss_text/x-scss[sgm,sgml_text/sgml[sh_application/x-sh[svg,svgz_image/svg+xml[swf_application/x-shockwave-flash[tar_application/x-tar[tif,tiff_image/tiff[toml_application/toml[ts_video/mp2t[tsx_text/tsx[tsv_text/tab-separated-values[ttc_font/collection[ttf_font/ttf[vtt_text/vtt[wasm_application/wasm[wav_audio/wav[weba_audio/webm[webm_video/webm[webmanifest_application/manifest+json[webp_image/webp[wma_audio/x-ms-wma[wmv_video/x-ms-wmv[woff_font/woff[woff2_font/woff2[xls_application/vnd.ms-excel[xlsx_application/vnd.openxmlformats-officedocument.spreadsheetml.sheet[xml_application/xml[xz_application/x-xz[yaml,yml_text/yaml[zip_application/zip".split("[").flatMap((mime) => {
const [extensions, mimeType] = mime.split("_");
return extensions.split(",").map((ext) => [ext, mimeType]);
}));
//#endregion
//#region src/shared/file-utils/get-file-mime-type.ts
function getFileMimeType(name) {
const extension = name.split(".").pop();
return extension ? mimeTypesMap.get(extension) || null : null;
}
//#endregion
//#region src/shared/file-utils/is-valid-file-type.ts
function isFileAccepted(file, accept) {
if (file && accept) {
const types = Array.isArray(accept) ? accept : typeof accept === "string" ? accept.split(",") : [];
if (types.length === 0) return true;
const fileName = file.name || "";
const mimeType = (file.type || getFileMimeType(fileName) || "").toLowerCase();
const baseMimeType = mimeType.replace(/\/.*$/, "");
return types.some((type) => {
const validType = type.trim().toLowerCase();
if (validType.charAt(0) === ".") return fileName.toLowerCase().endsWith(validType);
if (validType.endsWith("/*")) return baseMimeType === validType.replace(/\/.*$/, "");
return mimeType === validType;
});
}
return true;
}
function isValidFileType(file, accept) {
const isAcceptable = file.type === "application/x-moz-file" || isFileAccepted(file, accept);
return [isAcceptable, isAcceptable ? null : "FILE_INVALID_TYPE"];
}
//#endregion
exports.dataURItoBlob = dataURItoBlob;
exports.downloadFile = downloadFile;
exports.getAcceptAttrString = getAcceptAttrString;
exports.getFileDataUrl = getFileDataUrl;
exports.getFileEntries = getFileEntries;
exports.getFileMimeType = getFileMimeType;
exports.getTotalFileSize = getTotalFileSize;
exports.isFileEqual = isFileEqual;
exports.isValidFileSize = isValidFileSize;
exports.isValidFileType = isValidFileType;
//#region src/shared/file-utils/data-transfer.d.ts
declare const getFileEntries: (items: DataTransferItemList, traverseDirectories: boolean | undefined) => Promise<(File | (File | null)[] | null | undefined)[]>;
//#endregion
//#region src/shared/file-utils/data-url-to-blob.d.ts
declare function dataURItoBlob(uri: string): Blob;
//#endregion
//#region src/shared/file-utils/download-file.d.ts
interface DownloadFileOptions {
name?: string | undefined;
type: string;
file: File | Blob | string;
win?: typeof window | undefined;
appendBOM?: boolean | undefined;
revokeTimeout?: number | undefined;
}
declare function downloadFile(options: DownloadFileOptions): void;
//#endregion
//#region src/shared/file-utils/get-accept-attr.d.ts
declare function getAcceptAttrString(accept: Record<string, string[]> | string | string[] | undefined): string | undefined;
//#endregion
//#region src/shared/file-utils/get-file-data-url.d.ts
declare const getFileDataUrl: (file: File | Blob) => Promise<string | undefined>;
//#endregion
//#region src/shared/file-utils/get-total-file-size.d.ts
declare const getTotalFileSize: (files: File[]) => number;
//#endregion
//#region src/shared/file-utils/is-file-equal.d.ts
declare const isFileEqual: (file1: File, file2: File) => boolean;
//#endregion
//#region src/shared/file-utils/types.d.ts
type AnyString = string & {};
type FileError = "TOO_MANY_FILES" | "FILE_INVALID_TYPE" | "FILE_TOO_LARGE" | "FILE_TOO_SMALL" | "FILE_INVALID" | "FILE_EXISTS" | AnyString;
type ImageFileMimeType = "image/png" | "image/gif" | "image/jpeg" | "image/svg+xml" | "image/webp" | "image/avif" | "image/heic" | "image/bmp";
type ApplicationFileMimeType = "application/pdf" | "application/zip" | "application/json" | "application/xml" | "application/msword" | "application/vnd.openxmlformats-officedocument.wordprocessingml.document" | "application/vnd.ms-excel" | "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" | "application/vnd.ms-powerpoint" | "application/vnd.openxmlformats-officedocument.presentationml.presentation" | "application/rtf" | "application/x-rar" | "application/x-7z-compressed" | "application/x-tar" | "application/vnd.microsoft.portable-executable";
type TextFileMimeType = "text/css" | "text/csv" | "text/html" | "text/markdown" | "text/plain";
type FontFileMimeType = "font/ttf" | "font/otf" | "font/woff" | "font/woff2" | "font/eot" | "font/svg";
type VideoFileMimeType = "video/mp4" | "video/webm" | "video/ogg" | "video/quicktime" | "video/x-msvideo";
type AudioFileMimeType = "audio/mpeg" | "audio/ogg" | "audio/wav" | "audio/webm" | "audio/aac" | "audio/flac" | "audio/x-m4a";
type FileMimeTypeGroup = "image/*" | "audio/*" | "video/*" | "text/*" | "application/*" | "font/*";
type FileMimeType = ImageFileMimeType | ApplicationFileMimeType | TextFileMimeType | FontFileMimeType | VideoFileMimeType | AudioFileMimeType | FileMimeTypeGroup | AnyString;
//#endregion
//#region src/shared/file-utils/is-valid-file-size.d.ts
declare function isValidFileSize(file: File, minSize?: number, maxSize?: number): [boolean, FileError | null];
//#endregion
//#region src/shared/file-utils/is-valid-file-type.d.ts
declare function isValidFileType(file: File, accept: string | undefined): [boolean, FileError | null];
//#endregion
//#region src/shared/file-utils/get-file-mime-type.d.ts
declare function getFileMimeType(name: string): FileMimeType | null;
//#endregion
export { ApplicationFileMimeType, AudioFileMimeType, DownloadFileOptions, FileError, FileMimeType, FileMimeTypeGroup, FontFileMimeType, ImageFileMimeType, TextFileMimeType, VideoFileMimeType, dataURItoBlob, downloadFile, getAcceptAttrString, getFileDataUrl, getFileEntries, getFileMimeType, getTotalFileSize, isFileEqual, isValidFileSize, isValidFileType };
//#region src/shared/file-utils/data-transfer.d.ts
declare const getFileEntries: (items: DataTransferItemList, traverseDirectories: boolean | undefined) => Promise<(File | (File | null)[] | null | undefined)[]>;
//#endregion
//#region src/shared/file-utils/data-url-to-blob.d.ts
declare function dataURItoBlob(uri: string): Blob;
//#endregion
//#region src/shared/file-utils/download-file.d.ts
interface DownloadFileOptions {
name?: string | undefined;
type: string;
file: File | Blob | string;
win?: typeof window | undefined;
appendBOM?: boolean | undefined;
revokeTimeout?: number | undefined;
}
declare function downloadFile(options: DownloadFileOptions): void;
//#endregion
//#region src/shared/file-utils/get-accept-attr.d.ts
declare function getAcceptAttrString(accept: Record<string, string[]> | string | string[] | undefined): string | undefined;
//#endregion
//#region src/shared/file-utils/get-file-data-url.d.ts
declare const getFileDataUrl: (file: File | Blob) => Promise<string | undefined>;
//#endregion
//#region src/shared/file-utils/get-total-file-size.d.ts
declare const getTotalFileSize: (files: File[]) => number;
//#endregion
//#region src/shared/file-utils/is-file-equal.d.ts
declare const isFileEqual: (file1: File, file2: File) => boolean;
//#endregion
//#region src/shared/file-utils/types.d.ts
type AnyString = string & {};
type FileError = "TOO_MANY_FILES" | "FILE_INVALID_TYPE" | "FILE_TOO_LARGE" | "FILE_TOO_SMALL" | "FILE_INVALID" | "FILE_EXISTS" | AnyString;
type ImageFileMimeType = "image/png" | "image/gif" | "image/jpeg" | "image/svg+xml" | "image/webp" | "image/avif" | "image/heic" | "image/bmp";
type ApplicationFileMimeType = "application/pdf" | "application/zip" | "application/json" | "application/xml" | "application/msword" | "application/vnd.openxmlformats-officedocument.wordprocessingml.document" | "application/vnd.ms-excel" | "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" | "application/vnd.ms-powerpoint" | "application/vnd.openxmlformats-officedocument.presentationml.presentation" | "application/rtf" | "application/x-rar" | "application/x-7z-compressed" | "application/x-tar" | "application/vnd.microsoft.portable-executable";
type TextFileMimeType = "text/css" | "text/csv" | "text/html" | "text/markdown" | "text/plain";
type FontFileMimeType = "font/ttf" | "font/otf" | "font/woff" | "font/woff2" | "font/eot" | "font/svg";
type VideoFileMimeType = "video/mp4" | "video/webm" | "video/ogg" | "video/quicktime" | "video/x-msvideo";
type AudioFileMimeType = "audio/mpeg" | "audio/ogg" | "audio/wav" | "audio/webm" | "audio/aac" | "audio/flac" | "audio/x-m4a";
type FileMimeTypeGroup = "image/*" | "audio/*" | "video/*" | "text/*" | "application/*" | "font/*";
type FileMimeType = ImageFileMimeType | ApplicationFileMimeType | TextFileMimeType | FontFileMimeType | VideoFileMimeType | AudioFileMimeType | FileMimeTypeGroup | AnyString;
//#endregion
//#region src/shared/file-utils/is-valid-file-size.d.ts
declare function isValidFileSize(file: File, minSize?: number, maxSize?: number): [boolean, FileError | null];
//#endregion
//#region src/shared/file-utils/is-valid-file-type.d.ts
declare function isValidFileType(file: File, accept: string | undefined): [boolean, FileError | null];
//#endregion
//#region src/shared/file-utils/get-file-mime-type.d.ts
declare function getFileMimeType(name: string): FileMimeType | null;
//#endregion
export { ApplicationFileMimeType, AudioFileMimeType, DownloadFileOptions, FileError, FileMimeType, FileMimeTypeGroup, FontFileMimeType, ImageFileMimeType, TextFileMimeType, VideoFileMimeType, dataURItoBlob, downloadFile, getAcceptAttrString, getFileDataUrl, getFileEntries, getFileMimeType, getTotalFileSize, isFileEqual, isValidFileSize, isValidFileType };
//#region src/shared/file-utils/data-transfer.ts
const getItemEntry = (item) => typeof item.getAsEntry === "function" ? item.getAsEntry() : typeof item.webkitGetAsEntry === "function" ? item.webkitGetAsEntry() : null;
const isDirectoryEntry = (entry) => entry.isDirectory;
const isFileEntry = (entry) => entry.isFile;
const addRelativePath = (file, path) => {
Object.defineProperty(file, "relativePath", { value: path ? `${path}/${file.name}` : file.name });
return file;
};
const getFileEntries = (items, traverseDirectories) => Promise.all(Array.from(items).filter((item) => item.kind === "file").map((item) => {
const entry = getItemEntry(item);
if (!entry) return null;
if (isDirectoryEntry(entry) && traverseDirectories) return getDirectoryFiles(entry.createReader(), `${entry.name}`);
if (isFileEntry(entry) && typeof item.getAsFile === "function") {
const file = item.getAsFile();
return Promise.resolve(file ? addRelativePath(file, "") : null);
}
if (isFileEntry(entry)) return new Promise((resolve) => {
entry.file((file) => {
resolve(addRelativePath(file, ""));
});
});
}).filter((b) => b));
const getDirectoryFiles = (reader, path = "") => new Promise((resolve) => {
const entryPromises = [];
const readDirectoryEntries = () => {
reader.readEntries((entries) => {
if (entries.length === 0) {
resolve(Promise.all(entryPromises).then((entries) => entries.flat()));
return;
}
const promises = entries.map((entry) => {
if (!entry) return null;
if (isDirectoryEntry(entry)) return getDirectoryFiles(entry.createReader(), `${path}${entry.name}`);
if (isFileEntry(entry)) return new Promise((resolve) => {
entry.file((file) => {
resolve(addRelativePath(file, path));
});
});
}).filter((b) => b);
entryPromises.push(Promise.all(promises));
readDirectoryEntries();
});
};
readDirectoryEntries();
});
//#endregion
//#region src/shared/file-utils/data-url-to-blob.ts
function dataURItoBlob(uri) {
const binary = atob(uri.split(",")[1]);
const mimeString = uri.split(",")[0].split(":")[1].split(";")[0];
const buffer = new ArrayBuffer(binary.length);
const intArray = new Uint8Array(buffer);
for (let i = 0; i < binary.length; i++) intArray[i] = binary.charCodeAt(i);
return new Blob([buffer], { type: mimeString });
}
//#endregion
//#region src/shared/file-utils/download-file.ts
const BOM_REGEX = /^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i;
const MAC_REGEX = /Macintosh/;
const APPLE_WEBKIT_REGEX = /AppleWebKit/;
const SAFARI_REGEX = /Safari/;
function getBlob(blobOrString, type, appendBOM) {
let blob = typeof blobOrString === "string" ? new Blob([blobOrString], { type }) : blobOrString;
if (appendBOM && BOM_REGEX.test(blob.type)) return new Blob([String.fromCharCode(65279), blob], { type: blob.type });
return blob;
}
function isMSEdge(win) {
return Boolean(win.navigator && win.navigator.msSaveOrOpenBlob);
}
function isWebView(win) {
return win.navigator && MAC_REGEX.test(win.navigator.userAgent) && APPLE_WEBKIT_REGEX.test(win.navigator.userAgent) && !SAFARI_REGEX.test(win.navigator.userAgent);
}
function downloadFile(options) {
const { file, win = window, type, name, appendBOM, revokeTimeout = 0 } = options;
const doc = win.document;
const blob = getBlob(file, type, appendBOM);
const fileName = (file instanceof File ? name || file.name : name) || "file-download";
if (isMSEdge(win)) {
win.navigator.msSaveOrOpenBlob(blob, fileName);
return;
}
const isMacOSWebView = isWebView(win);
const anchor = doc.createElement("a");
if ("download" in anchor && !isMacOSWebView) {
const url = win.URL.createObjectURL(blob);
anchor.href = url;
anchor.rel = "noopener";
anchor.download = fileName;
anchor.style.display = "none";
doc.body.appendChild(anchor);
anchor.dispatchEvent(new win.MouseEvent("click"));
setTimeout(() => {
win.URL.revokeObjectURL(url);
anchor.remove();
}, revokeTimeout);
return;
}
const url = win.URL.createObjectURL(blob);
if (!win.open(url, "_blank")) win.location.href = url;
setTimeout(() => {
win.URL.revokeObjectURL(url);
}, revokeTimeout);
}
//#endregion
//#region src/shared/file-utils/get-accept-attr.ts
function isMIMEType(v) {
return v === "audio/*" || v === "video/*" || v === "image/*" || v === "text/*" || /\w+\/[-+.\w]+/g.test(v);
}
function isExt(v) {
return /^.*\.[\w]+$/.test(v);
}
const isValidMIME = (v) => isMIMEType(v) || isExt(v);
function getAcceptAttrString(accept) {
if (accept == null) return;
if (typeof accept === "string") return accept;
if (Array.isArray(accept)) return accept.filter(isValidMIME).join(",");
return Object.entries(accept).reduce((a, [mimeType, ext]) => [
...a,
mimeType,
...ext
], []).filter(isValidMIME).join(",");
}
//#endregion
//#region src/shared/file-utils/get-file-data-url.ts
const getFileDataUrl = async (file) => {
const reader = new FileReader();
return new Promise((resolve, reject) => {
reader.onerror = () => {
reader.abort();
reject(/* @__PURE__ */ new Error("There was an error reading a file"));
};
reader.onloadend = () => {
const { result } = reader;
if (result instanceof ArrayBuffer) reject(/* @__PURE__ */ new Error("Expected DataURL as string from Blob/File, got ArrayBuffer"));
else resolve(result || void 0);
};
reader.readAsDataURL(file);
});
};
//#endregion
//#region src/shared/file-utils/get-total-file-size.ts
const getTotalFileSize = (files) => {
return files.reduce((acc, file) => acc + file.size, 0);
};
//#endregion
//#region src/shared/file-utils/is-file-equal.ts
const isFileEqual = (file1, file2) => {
return file1.name === file2.name && file1.size === file2.size && file1.type === file2.type;
};
//#endregion
//#region src/shared/file-utils/is-valid-file-size.ts
const isDefined = (v) => v !== void 0 && v !== null;
function isValidFileSize(file, minSize, maxSize) {
if (isDefined(file.size)) {
if (isDefined(minSize) && isDefined(maxSize)) {
if (file.size > maxSize) return [false, "FILE_TOO_LARGE"];
if (file.size < minSize) return [false, "FILE_TOO_SMALL"];
} else if (isDefined(minSize) && file.size < minSize) return [false, "FILE_TOO_SMALL"];
else if (isDefined(maxSize) && file.size > maxSize) return [false, "FILE_TOO_LARGE"];
}
return [true, null];
}
const mimeTypesMap = new Map("3g2_video/3gpp2[3gp,3gpp_video/3gpp[3mf_model/3mf[7z_application/x-7z-compressed[aac_audio/aac[ac_application/pkix-attr-cert[adp_audio/adpcm[adts_audio/aac[ai_application/postscript[aml_application/automationml-aml+xml[amlx_application/automationml-amlx+zip[amr_audio/amr[apk_application/vnd.android.package-archive[apng_image/apng[appcache,manifest_text/cache-manifest[appinstaller_application/appinstaller[appx_application/appx[appxbundle_application/appxbundle[asc_application/pgp-keys[atom_application/atom+xml[atomcat_application/atomcat+xml[atomdeleted_application/atomdeleted+xml[atomsvc_application/atomsvc+xml[au,snd_audio/basic[avi_video/x-msvideo[avci_image/avci[avcs_image/avcs[avif_image/avif[aw_application/applixware[bdoc_application/bdoc[bin,bpk,buffer,deb,deploy,dist,distz,dll,dmg,dms,dump,elc,exe,img,iso,lrf,mar,msi,msm,msp,pkg,so_application/octet-stream[bmp,dib_image/bmp[btf,btif_image/prs.btif[bz2_application/x-bzip2[c_text/x-c[ccxml_application/ccxml+xml[cdfx_application/cdfx+xml[cdmia_application/cdmi-capability[cdmic_application/cdmi-container[cdmid_application/cdmi-domain[cdmio_application/cdmi-object[cdmiq_application/cdmi-queue[cer_application/pkix-cert[cgm_image/cgm[cjs_application/node[class_application/java-vm[coffee,litcoffee_text/coffeescript[conf,def,in,ini,list,log,text,txt_text/plain[cpp,cxx,cc_text/x-c++src[cpl_application/cpl+xml[cpt_application/mac-compactpro[crl_application/pkix-crl[css_text/css[csv_text/csv[cu_application/cu-seeme[cwl_application/cwl[cww_application/prs.cww[davmount_application/davmount+xml[dbk_application/docbook+xml[doc_application/msword[docx_application/vnd.openxmlformats-officedocument.wordprocessingml.document[dsc_text/prs.lines.tag[dssc_application/dssc+der[dtd_application/xml-dtd[dwd_application/atsc-dwd+xml[ear,jar,war_application/java-archive[ecma_application/ecmascript[emf_image/emf[eml,mime_message/rfc822[emma_application/emma+xml[emotionml_application/emotionml+xml[eot_application/vnd.ms-fontobject[eps,ps_application/postscript[epub_application/epub+zip[exi_application/exi[exp_application/express[exr_image/aces[ez_application/andrew-inset[fdf_application/fdf[fdt_application/fdt+xml[fits_image/fits[flac_audio/flac[flv_video/x-flv[g3_image/g3fax[geojson_application/geo+json[gif_image/gif[glb_model/gltf-binary[gltf_model/gltf+json[gml_application/gml+xml[go_text/x-go[gpx_application/gpx+xml[gz_application/gzip[h_text/x-h[h261_video/h261[h263_video/h263[h264_video/h264[heic_image/heic[heics_image/heic-sequence[heif_image/heif[heifs_image/heif-sequence[htm,html,shtml_text/html[ico_image/x-icon[icns_image/x-icns[ics,ifb_text/calendar[iges,igs_model/iges[ink,inkml_application/inkml+xml[ipa_application/octet-stream[java_text/x-java-source[jp2,jpg2_image/jp2[jpeg,jpe,jpg_image/jpeg[jpf,jpx_image/jpx[jpm,jpgm_image/jpm[jpgv_video/jpeg[jph_image/jph[js,mjs_text/javascript[json_application/json[json5_application/json5[jsonld_application/ld+json[jsx_text/jsx[jxl_image/jxl[jxr_image/jxr[ktx_image/ktx[ktx2_image/ktx2[less_text/less[m1v,m2v,mpe,mpeg,mpg_video/mpeg[m4a_audio/mp4[m4v_video/x-m4v[md,markdown_text/markdown[mid,midi,kar,rmi_audio/midi[mkv_video/x-matroska[mp2,mp2a,mp3,mpga,m3a,m2a_audio/mpeg[mp4,mp4v,mpg4_video/mp4[mp4a_audio/mp4[mp4s,m4p_application/mp4[odp_application/vnd.oasis.opendocument.presentation[oda_application/oda[ods_application/vnd.oasis.opendocument.spreadsheet[odt_application/vnd.oasis.opendocument.text[oga,ogg,opus,spx_audio/ogg[ogv_video/ogg[ogx_application/ogg[otf_font/otf[p12,pfx_application/x-pkcs12[pdf_application/pdf[pem_application/x-pem-file[php_text/x-php[png_image/png[ppt_application/vnd.ms-powerpoint[pptx_application/vnd.openxmlformats-officedocument.presentationml.presentation[pskcxml_application/pskc+xml[psd_image/vnd.adobe.photoshop[py_text/x-python[qt,mov_video/quicktime[rar_application/vnd.rar[rdf_application/rdf+xml[rtf_text/rtf[sass_text/x-sass[scss_text/x-scss[sgm,sgml_text/sgml[sh_application/x-sh[svg,svgz_image/svg+xml[swf_application/x-shockwave-flash[tar_application/x-tar[tif,tiff_image/tiff[toml_application/toml[ts_video/mp2t[tsx_text/tsx[tsv_text/tab-separated-values[ttc_font/collection[ttf_font/ttf[vtt_text/vtt[wasm_application/wasm[wav_audio/wav[weba_audio/webm[webm_video/webm[webmanifest_application/manifest+json[webp_image/webp[wma_audio/x-ms-wma[wmv_video/x-ms-wmv[woff_font/woff[woff2_font/woff2[xls_application/vnd.ms-excel[xlsx_application/vnd.openxmlformats-officedocument.spreadsheetml.sheet[xml_application/xml[xz_application/x-xz[yaml,yml_text/yaml[zip_application/zip".split("[").flatMap((mime) => {
const [extensions, mimeType] = mime.split("_");
return extensions.split(",").map((ext) => [ext, mimeType]);
}));
//#endregion
//#region src/shared/file-utils/get-file-mime-type.ts
function getFileMimeType(name) {
const extension = name.split(".").pop();
return extension ? mimeTypesMap.get(extension) || null : null;
}
//#endregion
//#region src/shared/file-utils/is-valid-file-type.ts
function isFileAccepted(file, accept) {
if (file && accept) {
const types = Array.isArray(accept) ? accept : typeof accept === "string" ? accept.split(",") : [];
if (types.length === 0) return true;
const fileName = file.name || "";
const mimeType = (file.type || getFileMimeType(fileName) || "").toLowerCase();
const baseMimeType = mimeType.replace(/\/.*$/, "");
return types.some((type) => {
const validType = type.trim().toLowerCase();
if (validType.charAt(0) === ".") return fileName.toLowerCase().endsWith(validType);
if (validType.endsWith("/*")) return baseMimeType === validType.replace(/\/.*$/, "");
return mimeType === validType;
});
}
return true;
}
function isValidFileType(file, accept) {
const isAcceptable = file.type === "application/x-moz-file" || isFileAccepted(file, accept);
return [isAcceptable, isAcceptable ? null : "FILE_INVALID_TYPE"];
}
//#endregion
export { dataURItoBlob, downloadFile, getAcceptAttrString, getFileDataUrl, getFileEntries, getFileMimeType, getTotalFileSize, isFileEqual, isValidFileSize, isValidFileType };
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_dom_query = require("./dom-query-BT6fffRP.cjs");
//#region src/shared/focus-trap/focus-trap.ts
const activeFocusTraps = {
activateTrap(trapStack, trap) {
if (trapStack.length > 0) {
const activeTrap = trapStack[trapStack.length - 1];
if (activeTrap !== trap) activeTrap.pause();
}
const trapIndex = trapStack.indexOf(trap);
if (trapIndex === -1) trapStack.push(trap);
else {
trapStack.splice(trapIndex, 1);
trapStack.push(trap);
}
},
deactivateTrap(trapStack, trap) {
const trapIndex = trapStack.indexOf(trap);
if (trapIndex !== -1) trapStack.splice(trapIndex, 1);
if (trapStack.length > 0) trapStack[trapStack.length - 1].unpause();
}
};
const sharedTrapStack = [];
var FocusTrap = class {
trapStack;
config;
doc;
state = {
containers: [],
containerGroups: [],
tabbableGroups: [],
nodeFocusedBeforeActivation: null,
mostRecentlyFocusedNode: null,
active: false,
paused: false,
delayInitialFocusTimer: void 0,
recentNavEvent: void 0
};
portalContainers = /* @__PURE__ */ new Set();
addPortalContainer(controlledElement) {
const portalContainer = controlledElement.parentElement;
if (portalContainer && !this.portalContainers.has(portalContainer)) {
this.portalContainers.add(portalContainer);
if (this.state.active && !this.state.paused) this.observePortalContainer(portalContainer);
}
}
observePortalContainer(portalContainer) {
this._mutationObserver?.observe(portalContainer, {
subtree: true,
childList: true,
attributes: true,
attributeFilter: ["aria-controls", "aria-expanded"]
});
}
updatePortalContainers() {
if (!this.config.followControlledElements) return;
this.state.containers.forEach((container) => {
require_dom_query.getControlledElements(container).forEach((controlledElement) => {
this.addPortalContainer(controlledElement);
});
});
}
get active() {
return this.state.active;
}
get paused() {
return this.state.paused;
}
constructor(elements, options) {
this.trapStack = options.trapStack || sharedTrapStack;
const config = {
returnFocusOnDeactivate: true,
escapeDeactivates: true,
delayInitialFocus: true,
followControlledElements: true,
isKeyForward,
isKeyBackward,
...options
};
this.doc = config.document || require_dom_query.getDocument(Array.isArray(elements) ? elements[0] : elements);
this.config = config;
this.updateContainerElements(elements);
this.setupMutationObserver();
}
findContainerIndex(element, event) {
const composedPath = typeof event?.composedPath === "function" ? event.composedPath() : void 0;
return this.state.containerGroups.findIndex(({ container, tabbableNodes }) => container.contains(element) || composedPath?.includes(container) || tabbableNodes.find((node) => node === element) || this.isControlledElement(container, element));
}
isControlledElement(container, element) {
if (!this.config.followControlledElements) return false;
return require_dom_query.isControlledElement(container, element);
}
updateTabbableNodes() {
this.state.containerGroups = this.state.containers.map((container) => {
const tabbableNodes = require_dom_query.getTabbables(container, { getShadowRoot: this.config.getShadowRoot });
const focusableNodes = require_dom_query.getFocusables(container, { getShadowRoot: this.config.getShadowRoot });
const firstTabbableNode = tabbableNodes[0];
const lastTabbableNode = tabbableNodes[tabbableNodes.length - 1];
const firstDomTabbableNode = firstTabbableNode;
const lastDomTabbableNode = lastTabbableNode;
let posTabIndexesFound = false;
for (let i = 0; i < tabbableNodes.length; i++) if (require_dom_query.getTabIndex(tabbableNodes[i]) > 0) {
posTabIndexesFound = true;
break;
}
function nextTabbableNode(node, forward = true) {
const nodeIdx = tabbableNodes.indexOf(node);
if (nodeIdx >= 0) return tabbableNodes[nodeIdx + (forward ? 1 : -1)];
const focusableIdx = focusableNodes.indexOf(node);
if (focusableIdx < 0) return void 0;
if (forward) {
for (let i = focusableIdx + 1; i < focusableNodes.length; i++) if (require_dom_query.isTabbable(focusableNodes[i])) return focusableNodes[i];
} else for (let i = focusableIdx - 1; i >= 0; i--) if (require_dom_query.isTabbable(focusableNodes[i])) return focusableNodes[i];
}
return {
container,
tabbableNodes,
focusableNodes,
posTabIndexesFound,
firstTabbableNode,
lastTabbableNode,
firstDomTabbableNode,
lastDomTabbableNode,
nextTabbableNode
};
});
this.state.tabbableGroups = this.state.containerGroups.filter((group) => group.tabbableNodes.length > 0);
if (this.state.tabbableGroups.length <= 0 && !this.getNodeForOption("fallbackFocus")) throw new Error("Your focus-trap must have at least one container with at least one tabbable node in it at all times");
if (this.state.containerGroups.find((g) => g.posTabIndexesFound) && this.state.containerGroups.length > 1) throw new Error("At least one node with a positive tabindex was found in one of your focus-trap's multiple containers. Positive tabindexes are only supported in single-container focus-traps.");
}
listenerCleanups = [];
addListeners() {
if (!this.state.active) return;
activeFocusTraps.activateTrap(this.trapStack, this);
this.state.delayInitialFocusTimer = this.config.delayInitialFocus ? delay(() => {
this.tryFocus(this.getInitialFocusNode());
}) : this.tryFocus(this.getInitialFocusNode());
this.listenerCleanups.push(require_dom_query.addDomEvent(this.doc, "focusin", this.handleFocus, true), require_dom_query.addDomEvent(this.doc, "mousedown", this.handlePointerDown, {
capture: true,
passive: false
}), require_dom_query.addDomEvent(this.doc, "touchstart", this.handlePointerDown, {
capture: true,
passive: false
}), require_dom_query.addDomEvent(this.doc, "click", this.handleClick, {
capture: true,
passive: false
}), require_dom_query.addDomEvent(this.doc, "keydown", this.handleTabKey, {
capture: true,
passive: false
}), require_dom_query.addDomEvent(this.doc, "keydown", this.handleEscapeKey));
return this;
}
removeListeners() {
if (!this.state.active) return;
this.listenerCleanups.forEach((cleanup) => cleanup());
this.listenerCleanups = [];
return this;
}
handleFocus = (event) => {
const target = require_dom_query.getEventTarget(event);
const targetContained = this.findContainerIndex(target, event) >= 0;
if (targetContained || require_dom_query.isDocument(target)) {
if (targetContained) this.state.mostRecentlyFocusedNode = target;
} else {
event.stopImmediatePropagation();
let nextNode;
let navAcrossContainers = true;
if (this.state.mostRecentlyFocusedNode) {
if (require_dom_query.getTabIndex(this.state.mostRecentlyFocusedNode) > 0) {
const mruContainerIdx = this.findContainerIndex(this.state.mostRecentlyFocusedNode);
const { tabbableNodes } = this.state.containerGroups[mruContainerIdx];
if (tabbableNodes.length > 0) {
const mruTabIdx = tabbableNodes.findIndex((node) => node === this.state.mostRecentlyFocusedNode);
if (mruTabIdx >= 0) {
if (this.config.isKeyForward(this.state.recentNavEvent)) {
if (mruTabIdx + 1 < tabbableNodes.length) {
nextNode = tabbableNodes[mruTabIdx + 1];
navAcrossContainers = false;
}
} else if (mruTabIdx - 1 >= 0) {
nextNode = tabbableNodes[mruTabIdx - 1];
navAcrossContainers = false;
}
}
}
} else if (!this.state.containerGroups.some((g) => g.tabbableNodes.some((n) => require_dom_query.getTabIndex(n) > 0))) navAcrossContainers = false;
} else navAcrossContainers = false;
if (navAcrossContainers) nextNode = this.findNextNavNode({
target: this.state.mostRecentlyFocusedNode,
isBackward: this.config.isKeyBackward(this.state.recentNavEvent)
});
if (nextNode) this.tryFocus(nextNode);
else this.tryFocus(this.state.mostRecentlyFocusedNode || this.getInitialFocusNode());
}
this.state.recentNavEvent = void 0;
};
handlePointerDown = (event) => {
const target = require_dom_query.getEventTarget(event);
if (this.findContainerIndex(target, event) >= 0) return;
if (valueOrHandler(this.config.clickOutsideDeactivates, event)) {
this.deactivate({ returnFocus: this.config.returnFocusOnDeactivate });
return;
}
if (valueOrHandler(this.config.allowOutsideClick, event)) return;
event.preventDefault();
};
handleClick = (event) => {
const target = require_dom_query.getEventTarget(event);
if (this.findContainerIndex(target, event) >= 0) return;
if (valueOrHandler(this.config.clickOutsideDeactivates, event)) return;
if (valueOrHandler(this.config.allowOutsideClick, event)) return;
event.preventDefault();
event.stopImmediatePropagation();
};
handleTabKey = (event) => {
if (this.config.isKeyForward(event) || this.config.isKeyBackward(event)) {
this.state.recentNavEvent = event;
const isBackward = this.config.isKeyBackward(event);
const destinationNode = this.findNextNavNode({
event,
isBackward
});
if (!destinationNode) return;
if (isTabEvent(event)) event.preventDefault();
this.tryFocus(destinationNode);
}
};
handleEscapeKey = (event) => {
if (isEscapeEvent(event) && valueOrHandler(this.config.escapeDeactivates, event) !== false) {
event.preventDefault();
this.deactivate();
}
};
_mutationObserver;
setupMutationObserver = () => {
const win = this.doc.defaultView || window;
this._mutationObserver = new win.MutationObserver((mutations) => {
if (mutations.some((mutation) => {
return Array.from(mutation.removedNodes).some((node) => node === this.state.mostRecentlyFocusedNode);
})) this.tryFocus(this.getInitialFocusNode());
if (mutations.some((mutation) => {
if (mutation.type === "attributes" && (mutation.attributeName === "aria-controls" || mutation.attributeName === "aria-expanded")) return true;
if (mutation.type === "childList" && mutation.addedNodes.length > 0) return Array.from(mutation.addedNodes).some((node) => {
if (node.nodeType !== Node.ELEMENT_NODE) return false;
const element = node;
if (require_dom_query.hasControllerElements(element)) return true;
if (element.id && !this.state.containers.some((c) => c.contains(element))) return require_dom_query.isControlledByExpandedController(element);
return false;
});
return false;
}) && this.state.active && !this.state.paused) {
this.updateTabbableNodes();
this.updatePortalContainers();
}
});
};
updateObservedNodes = () => {
this._mutationObserver?.disconnect();
if (this.state.active && !this.state.paused) {
this.state.containers.map((container) => {
this._mutationObserver?.observe(container, {
subtree: true,
childList: true,
attributes: true,
attributeFilter: ["aria-controls", "aria-expanded"]
});
});
this.portalContainers.forEach((portalContainer) => {
this.observePortalContainer(portalContainer);
});
}
};
getInitialFocusNode = () => {
let node = this.getNodeForOption("initialFocus", { hasFallback: true });
if (node === false) return false;
if (node === void 0 || node && !require_dom_query.isFocusable(node)) {
const activeElement = require_dom_query.getActiveElement(this.doc);
if (activeElement && this.findContainerIndex(activeElement) >= 0) node = activeElement;
else {
const firstTabbableGroup = this.state.tabbableGroups[0];
node = firstTabbableGroup && firstTabbableGroup.firstTabbableNode || this.getNodeForOption("fallbackFocus");
}
} else if (node === null) node = this.getNodeForOption("fallbackFocus");
if (!node) throw new Error("Your focus-trap needs to have at least one focusable element");
if (!node.isConnected) node = this.getNodeForOption("fallbackFocus");
if (!node || !node.isConnected) throw new Error("Your focus-trap needs to have at least one focusable element");
return node;
};
tryFocus = (node) => {
if (node === false) return;
if (node === require_dom_query.getActiveElement(this.doc)) return;
if (!node || !node.focus) {
this.tryFocus(this.getInitialFocusNode());
return;
}
node.focus({ preventScroll: !!this.config.preventScroll });
this.state.mostRecentlyFocusedNode = node;
if (isSelectableInput(node)) node.select();
};
activate(activateOptions) {
if (this.state.active) return this;
const onActivate = this.getOption(activateOptions, "onActivate");
const onPostActivate = this.getOption(activateOptions, "onPostActivate");
const checkCanFocusTrap = this.getOption(activateOptions, "checkCanFocusTrap");
if (!checkCanFocusTrap) this.updateTabbableNodes();
this.state.active = true;
this.state.paused = false;
this.state.nodeFocusedBeforeActivation = require_dom_query.getActiveElement(this.doc);
onActivate?.();
const finishActivation = () => {
if (checkCanFocusTrap) this.updateTabbableNodes();
this.addListeners();
this.updateObservedNodes();
onPostActivate?.();
};
if (checkCanFocusTrap) {
checkCanFocusTrap(this.state.containers.concat()).then(finishActivation, finishActivation);
return this;
}
finishActivation();
return this;
}
deactivate = (deactivateOptions) => {
if (!this.state.active) return this;
const options = {
onDeactivate: this.config.onDeactivate,
onPostDeactivate: this.config.onPostDeactivate,
checkCanReturnFocus: this.config.checkCanReturnFocus,
...deactivateOptions
};
clearTimeout(this.state.delayInitialFocusTimer);
this.state.delayInitialFocusTimer = void 0;
this.removeListeners();
this.state.active = false;
this.state.paused = false;
this.updateObservedNodes();
activeFocusTraps.deactivateTrap(this.trapStack, this);
this.portalContainers.clear();
const onDeactivate = this.getOption(options, "onDeactivate");
const onPostDeactivate = this.getOption(options, "onPostDeactivate");
const checkCanReturnFocus = this.getOption(options, "checkCanReturnFocus");
const returnFocus = this.getOption(options, "returnFocus", "returnFocusOnDeactivate");
onDeactivate?.();
const finishDeactivation = () => {
delay(() => {
if (returnFocus) {
const returnFocusNode = this.getReturnFocusNode(this.state.nodeFocusedBeforeActivation);
this.tryFocus(returnFocusNode);
}
onPostDeactivate?.();
});
};
if (returnFocus && checkCanReturnFocus) {
checkCanReturnFocus(this.getReturnFocusNode(this.state.nodeFocusedBeforeActivation)).then(finishDeactivation, finishDeactivation);
return this;
}
finishDeactivation();
return this;
};
pause = (pauseOptions) => {
if (this.state.paused || !this.state.active) return this;
const onPause = this.getOption(pauseOptions, "onPause");
const onPostPause = this.getOption(pauseOptions, "onPostPause");
this.state.paused = true;
onPause?.();
this.removeListeners();
this.updateObservedNodes();
onPostPause?.();
return this;
};
unpause = (unpauseOptions) => {
if (!this.state.paused || !this.state.active) return this;
const onUnpause = this.getOption(unpauseOptions, "onUnpause");
const onPostUnpause = this.getOption(unpauseOptions, "onPostUnpause");
this.state.paused = false;
onUnpause?.();
this.updateTabbableNodes();
this.addListeners();
this.updateObservedNodes();
onPostUnpause?.();
return this;
};
updateContainerElements = (containerElements) => {
this.state.containers = Array.isArray(containerElements) ? containerElements.filter(Boolean) : [containerElements].filter(Boolean);
if (this.state.active) this.updateTabbableNodes();
this.updateObservedNodes();
return this;
};
getReturnFocusNode = (previousActiveElement) => {
const node = this.getNodeForOption("setReturnFocus", { params: [previousActiveElement] });
return node ? node : node === false ? false : previousActiveElement;
};
getOption = (configOverrideOptions, optionName, configOptionName) => {
return configOverrideOptions && configOverrideOptions[optionName] !== void 0 ? configOverrideOptions[optionName] : this.config[configOptionName || optionName];
};
getNodeForOption = (optionName, { hasFallback = false, params = [] } = {}) => {
let optionValue = this.config[optionName];
if (typeof optionValue === "function") optionValue = optionValue(...params);
if (optionValue === true) optionValue = void 0;
if (!optionValue) {
if (optionValue === void 0 || optionValue === false) return optionValue;
throw new Error(`\`${optionName}\` was specified but was not a node, or did not return a node`);
}
let node = optionValue;
if (typeof optionValue === "string") {
try {
node = this.doc.querySelector(optionValue);
} catch (err) {
throw new Error(`\`${optionName}\` appears to be an invalid selector; error="${err.message}"`);
}
if (!node) {
if (!hasFallback) throw new Error(`\`${optionName}\` as selector refers to no known node`);
}
}
return node;
};
findNextNavNode = (opts) => {
const { event, isBackward = false } = opts;
const target = opts.target || require_dom_query.getEventTarget(event);
this.updateTabbableNodes();
let destinationNode = null;
if (this.state.tabbableGroups.length > 0) {
const containerIndex = this.findContainerIndex(target, event);
const containerGroup = containerIndex >= 0 ? this.state.containerGroups[containerIndex] : void 0;
if (containerIndex < 0) if (isBackward) destinationNode = this.state.tabbableGroups[this.state.tabbableGroups.length - 1].lastTabbableNode;
else destinationNode = this.state.tabbableGroups[0].firstTabbableNode;
else if (isBackward) {
let startOfGroupIndex = this.state.tabbableGroups.findIndex(({ firstTabbableNode }) => target === firstTabbableNode);
if (startOfGroupIndex < 0 && (containerGroup?.container === target || require_dom_query.isFocusable(target) && !require_dom_query.isTabbable(target) && !containerGroup?.nextTabbableNode(target, false))) startOfGroupIndex = containerIndex;
if (startOfGroupIndex >= 0) {
const destinationGroupIndex = startOfGroupIndex === 0 ? this.state.tabbableGroups.length - 1 : startOfGroupIndex - 1;
const destinationGroup = this.state.tabbableGroups[destinationGroupIndex];
destinationNode = require_dom_query.getTabIndex(target) >= 0 ? destinationGroup.lastTabbableNode : destinationGroup.lastDomTabbableNode;
} else if (!isTabEvent(event)) destinationNode = containerGroup?.nextTabbableNode(target, false);
} else {
let lastOfGroupIndex = this.state.tabbableGroups.findIndex(({ lastTabbableNode }) => target === lastTabbableNode);
if (lastOfGroupIndex < 0 && (containerGroup?.container === target || require_dom_query.isFocusable(target) && !require_dom_query.isTabbable(target) && !containerGroup?.nextTabbableNode(target))) lastOfGroupIndex = containerIndex;
if (lastOfGroupIndex >= 0) {
const destinationGroupIndex = lastOfGroupIndex === this.state.tabbableGroups.length - 1 ? 0 : lastOfGroupIndex + 1;
const destinationGroup = this.state.tabbableGroups[destinationGroupIndex];
destinationNode = require_dom_query.getTabIndex(target) >= 0 ? destinationGroup.firstTabbableNode : destinationGroup.firstDomTabbableNode;
} else if (!isTabEvent(event)) destinationNode = containerGroup?.nextTabbableNode(target);
}
} else destinationNode = this.getNodeForOption("fallbackFocus");
return destinationNode;
};
};
const isKeyboardEvent = (event) => event?.type === "keydown";
const isTabEvent = (event) => isKeyboardEvent(event) && event?.key === "Tab";
const isKeyForward = (e) => isKeyboardEvent(e) && e.key === "Tab" && !e?.shiftKey;
const isKeyBackward = (e) => isKeyboardEvent(e) && e.key === "Tab" && e?.shiftKey;
const valueOrHandler = (value, ...params) => typeof value === "function" ? value(...params) : value;
const isEscapeEvent = (event) => !event.isComposing && event.key === "Escape";
const delay = (fn) => setTimeout(fn, 0);
const isSelectableInput = (node) => node.localName === "input" && "select" in node && typeof node.select === "function";
//#endregion
//#region src/shared/focus-trap/index.ts
function trapFocus(el, options = {}) {
let trap;
const cleanup = require_dom_query.raf(() => {
const resolvedElements = (Array.isArray(el) ? el : [el]).map((e) => typeof e === "function" ? e() : e).filter((e) => e != null);
if (resolvedElements.length === 0) return;
const primaryEl = resolvedElements[0];
trap = new FocusTrap(resolvedElements, {
escapeDeactivates: false,
allowOutsideClick: true,
preventScroll: true,
returnFocusOnDeactivate: true,
delayInitialFocus: false,
fallbackFocus: primaryEl,
...options,
document: require_dom_query.getDocument(primaryEl)
});
try {
trap.activate();
} catch {}
});
return function destroy() {
trap?.deactivate();
cleanup();
};
}
//#endregion
exports.FocusTrap = FocusTrap;
exports.trapFocus = trapFocus;
//#region src/shared/focus-trap/types.d.ts
type FocusableElement = HTMLElement | SVGElement;
type FocusTargetValue = FocusableElement | string;
type FocusTargetValueOrFalse = FocusTargetValue | false;
/**
* A DOM node, a selector string (which will be passed to
* `document.querySelector()` to find the DOM node), or a function that
* returns a DOM node.
*/
type FocusTarget = FocusTargetValue | (() => FocusTargetValue);
/**
* A DOM node, a selector string (which will be passed to
* `document.querySelector()` to find the DOM node), `false` to explicitly indicate
* an opt-out, or a function that returns a DOM node or `false`.
*/
type FocusTargetOrFalse = FocusTargetValueOrFalse | (() => FocusTargetValueOrFalse);
type MouseEventToBoolean = (event: MouseEvent | TouchEvent) => boolean;
type KeyboardEventToBoolean = (event: KeyboardEvent) => boolean;
interface FocusTrapOptions {
/**
* A function that will be called **before** sending focus to the
* target element upon activation.
*/
onActivate?: VoidFunction | undefined;
/**
* A function that will be called **after** focus has been sent to the
* target element upon activation.
*/
onPostActivate?: VoidFunction | undefined;
/**
* A function that will be called immediately after the trap's state is updated to be paused.
*/
onPause?: VoidFunction | undefined;
/**
* A function that will be called after the trap has been completely paused and is no longer
* managing/trapping focus.
*/
onPostPause?: VoidFunction | undefined;
/**
* A function that will be called immediately after the trap's state is updated to be active
* again, but prior to updating its knowledge of what nodes are tabbable within its containers,
* and prior to actively managing/trapping focus.
*/
onUnpause?: VoidFunction | undefined;
/**
* A function that will be called after the trap has been completely unpaused and is once
* again managing/trapping focus.
*/
onPostUnpause?: VoidFunction | undefined;
/**
* A function for determining if it is safe to send focus to the focus trap
* or not.
*
* It should return a promise that only resolves once all the listed `containers`
* are able to receive focus.
*
* The purpose of this is to prevent early focus-trap activation on animated
* dialogs that fade in and out. When a dialog fades in, there is a brief delay
* between the activation of the trap and the trap element being focusable.
*/
checkCanFocusTrap?: ((containers: Array<HTMLElement | SVGElement>) => Promise<void>) | undefined;
/**
* A function that will be called **before** sending focus to the
* trigger element upon deactivation.
*/
onDeactivate?: VoidFunction | undefined;
/**
* A function that will be called after the trap is deactivated, after `onDeactivate`.
* If `returnFocus` was set, it will be called **after** focus has been sent to the trigger
* element upon deactivation; otherwise, it will be called after deactivation completes.
*/
onPostDeactivate?: VoidFunction | undefined;
/**
* A function for determining if it is safe to send focus back to the `trigger` element.
*
* It should return a promise that only resolves once `trigger` is focusable.
*
* The purpose of this is to prevent the focus being sent to an animated trigger element too early.
* If a trigger element fades in upon trap deactivation, there is a brief delay between the deactivation
* of the trap and when the trigger element is focusable.
*
* `trigger` will be either the node that had focus prior to the trap being activated,
* or the result of the `setReturnFocus` option, if configured.
*
* This handler is **not** called if the `returnFocusOnDeactivate` configuration option
* (or the `returnFocus` deactivation option) is falsy.
*/
checkCanReturnFocus?: ((trigger: HTMLElement | SVGElement) => Promise<void>) | undefined;
/**
* By default, when a focus trap is activated the first element in the
* focus trap's tab order will receive focus. With this option you can
* specify a different element to receive that initial focus, or use `false`
* for no initially focused element at all.
*
* NOTE: Setting this option to `false` (or a function that returns `false`)
* will prevent the `fallbackFocus` option from being used.
*
* Setting this option to `undefined` (or a function that returns `undefined`)
* will result in the default behavior.
*/
initialFocus?: FocusTargetOrFalse | undefined | VoidFunction;
/**
* By default, an error will be thrown if the focus trap contains no
* elements in its tab order. With this option you can specify a
* fallback element to programmatically receive focus if no other
* tabbable elements are found. For example, you may want a popover's
* `<div>` to receive focus if the popover's content includes no
* tabbable elements. *Make sure the fallback element has a negative
* `tabindex` so it can be programmatically focused.
*
* NOTE: If `initialFocus` is `false` (or a function that returns `false`),
* this function will not be called when the trap is activated, and no element
* will be initially focused. This function may still be called while the trap
* is active if things change such that there are no longer any tabbable nodes
* in the trap.
*/
fallbackFocus?: FocusTarget | undefined;
/**
* Default: `true`. If `false`, when the trap is deactivated,
* focus will *not* return to the element that had focus before activation.
*/
returnFocusOnDeactivate?: boolean | undefined;
/**
* By default, focus trap on deactivation will return to the element
* that was focused before activation.
*/
setReturnFocus?: FocusTargetValueOrFalse | ((nodeFocusedBeforeActivation: HTMLElement | SVGElement) => FocusTargetValueOrFalse) | undefined;
/**
* Default: `true`. If `false` or returns `false`, the `Escape` key will not trigger
* deactivation of the focus trap. This can be useful if you want
* to force the user to make a decision instead of allowing an easy
* way out. Note that if a function is given, it's only called if the ESC key
* was pressed.
*/
escapeDeactivates?: boolean | KeyboardEventToBoolean | undefined;
/**
* If `true` or returns `true`, a click outside the focus trap will
* deactivate the focus trap and allow the click event to do its thing (i.e.
* to pass-through to the element that was clicked). This option **takes
* precedence** over `allowOutsideClick` when it's set to `true`, causing
* that option to be ignored. Default: `false`.
*/
clickOutsideDeactivates?: boolean | MouseEventToBoolean | undefined;
/**
* If set and is or returns `true`, a click outside the focus trap will not
* be prevented, even when `clickOutsideDeactivates` is `false`. When
* `clickOutsideDeactivates` is `true`, this option is **ignored** (i.e.
* if it's a function, it will not be called). Use this option to control
* if (and even which) clicks are allowed outside the trap in conjunction
* with `clickOutsideDeactivates: false`. Default: `false`.
*/
allowOutsideClick?: boolean | MouseEventToBoolean | undefined;
/**
* By default, focus() will scroll to the element if not in viewport.
* It can produce unintended effects like scrolling back to the top of a modal.
* If set to `true`, no scroll will happen.
*/
preventScroll?: boolean | undefined;
/**
* Default: `true`. Delays the autofocus when the focus trap is activated.
* This prevents elements within the focusable element from capturing
* the event that triggered the focus trap activation.
*/
delayInitialFocus?: boolean | undefined;
/**
* Default: `window.document`. Document where the focus trap will be active.
* This allows to use FocusTrap in an iFrame context.
*/
document?: Document | undefined;
/**
* Determines if the given keyboard event is a "tab forward" event that will move
* the focus to the next trapped element in tab order. Defaults to the `TAB` key.
* Use this to override the trap's behavior if you want to use arrow keys to control
* keyboard navigation within the trap, for example. Also see `isKeyBackward()` option.
*/
isKeyForward?: KeyboardEventToBoolean | undefined;
/**
* Determines if the given keyboard event is a "tab backward" event that will move
* the focus to the previous trapped element in tab order. Defaults to the `SHIFT+TAB` key.
* Use this to override the trap's behavior if you want to use arrow keys to control
* keyboard navigation within the trap, for example. Also see `isKeyForward()` option.
*/
isKeyBackward?: KeyboardEventToBoolean | undefined;
/**
* Default: `[]`. An array of FocusTrap instances that will be managed by this FocusTrap.
*/
trapStack?: any[] | undefined;
/**
* Default: `true`. If `true`, the focus trap will recursively include elements
* that are controlled by elements within the trap via `aria-controls`. Only elements
* with `aria-expanded="true"` and interactive container roles (menu, listbox, dialog, etc.)
* will be included. This allows nested menus, select dropdowns, and other portalled
* content to remain within the focus trap.
*/
followControlledElements?: boolean | undefined;
/**
* Optional function to support shadow DOM traversal. When provided, it enables
* the focus trap to find tabbable elements inside shadow roots (web components).
*
* - `true`: Enable shadow DOM support for open shadow roots
* - `false` or `undefined`: Disable shadow DOM support (default)
* - Function: Called with each element; return `true` if it has a shadow root to traverse,
* the `ShadowRoot` instance, or a falsy value if no shadow root exists
*
* This is required for proper focus management when using web components or custom elements
* with shadow DOM.
*
* @example
* ```ts
* // Enable for all open shadow roots
* getShadowRoot: true
*
* // Custom function for closed shadow roots
* getShadowRoot: (node) => {
* if (node === myCustomElement) return myCustomElement.shadowRoot
* return node.shadowRoot
* }
* ```
*/
getShadowRoot?: boolean | ((node: FocusableElement) => ShadowRoot | boolean | undefined) | undefined;
}
interface DeactivateOptions extends Pick<FocusTrapOptions, "onDeactivate" | "onPostDeactivate" | "checkCanReturnFocus"> {
returnFocus?: boolean | undefined;
}
type ActivateOptions = Pick<FocusTrapOptions, "onActivate" | "onPostActivate" | "checkCanFocusTrap">;
type PauseOptions = Pick<FocusTrapOptions, "onPause" | "onPostPause">;
type UnpauseOptions = Pick<FocusTrapOptions, "onUnpause" | "onPostUnpause">;
//#endregion
//#region src/shared/focus-trap/focus-trap.d.ts
declare class FocusTrap {
private trapStack;
private config;
private doc;
private state;
private portalContainers;
private addPortalContainer;
private observePortalContainer;
private updatePortalContainers;
get active(): boolean;
get paused(): boolean;
constructor(elements: HTMLElement | HTMLElement[], options: FocusTrapOptions);
private findContainerIndex;
private isControlledElement;
private updateTabbableNodes;
private listenerCleanups;
private addListeners;
private removeListeners;
private handleFocus;
private handlePointerDown;
private handleClick;
private handleTabKey;
private handleEscapeKey;
private _mutationObserver?;
private setupMutationObserver;
private updateObservedNodes;
private getInitialFocusNode;
private tryFocus;
activate(activateOptions?: ActivateOptions): this;
deactivate: (deactivateOptions?: DeactivateOptions) => this;
pause: (pauseOptions?: PauseOptions) => this;
unpause: (unpauseOptions?: UnpauseOptions) => this;
updateContainerElements: (containerElements: HTMLElement | HTMLElement[]) => this;
private getReturnFocusNode;
private getOption;
private getNodeForOption;
private findNextNavNode;
}
//#endregion
//#region src/shared/focus-trap/index.d.ts
type ElementOrGetter = HTMLElement | null | (() => HTMLElement | null);
type ElementsOrGetter = ElementOrGetter | ElementOrGetter[];
interface TrapFocusOptions extends Omit<FocusTrapOptions, "document"> {}
declare function trapFocus(el: ElementsOrGetter, options?: TrapFocusOptions): () => void;
//#endregion
export { FocusTrap, type FocusTrapOptions, TrapFocusOptions, trapFocus };
//#region src/shared/focus-trap/types.d.ts
type FocusableElement = HTMLElement | SVGElement;
type FocusTargetValue = FocusableElement | string;
type FocusTargetValueOrFalse = FocusTargetValue | false;
/**
* A DOM node, a selector string (which will be passed to
* `document.querySelector()` to find the DOM node), or a function that
* returns a DOM node.
*/
type FocusTarget = FocusTargetValue | (() => FocusTargetValue);
/**
* A DOM node, a selector string (which will be passed to
* `document.querySelector()` to find the DOM node), `false` to explicitly indicate
* an opt-out, or a function that returns a DOM node or `false`.
*/
type FocusTargetOrFalse = FocusTargetValueOrFalse | (() => FocusTargetValueOrFalse);
type MouseEventToBoolean = (event: MouseEvent | TouchEvent) => boolean;
type KeyboardEventToBoolean = (event: KeyboardEvent) => boolean;
interface FocusTrapOptions {
/**
* A function that will be called **before** sending focus to the
* target element upon activation.
*/
onActivate?: VoidFunction | undefined;
/**
* A function that will be called **after** focus has been sent to the
* target element upon activation.
*/
onPostActivate?: VoidFunction | undefined;
/**
* A function that will be called immediately after the trap's state is updated to be paused.
*/
onPause?: VoidFunction | undefined;
/**
* A function that will be called after the trap has been completely paused and is no longer
* managing/trapping focus.
*/
onPostPause?: VoidFunction | undefined;
/**
* A function that will be called immediately after the trap's state is updated to be active
* again, but prior to updating its knowledge of what nodes are tabbable within its containers,
* and prior to actively managing/trapping focus.
*/
onUnpause?: VoidFunction | undefined;
/**
* A function that will be called after the trap has been completely unpaused and is once
* again managing/trapping focus.
*/
onPostUnpause?: VoidFunction | undefined;
/**
* A function for determining if it is safe to send focus to the focus trap
* or not.
*
* It should return a promise that only resolves once all the listed `containers`
* are able to receive focus.
*
* The purpose of this is to prevent early focus-trap activation on animated
* dialogs that fade in and out. When a dialog fades in, there is a brief delay
* between the activation of the trap and the trap element being focusable.
*/
checkCanFocusTrap?: ((containers: Array<HTMLElement | SVGElement>) => Promise<void>) | undefined;
/**
* A function that will be called **before** sending focus to the
* trigger element upon deactivation.
*/
onDeactivate?: VoidFunction | undefined;
/**
* A function that will be called after the trap is deactivated, after `onDeactivate`.
* If `returnFocus` was set, it will be called **after** focus has been sent to the trigger
* element upon deactivation; otherwise, it will be called after deactivation completes.
*/
onPostDeactivate?: VoidFunction | undefined;
/**
* A function for determining if it is safe to send focus back to the `trigger` element.
*
* It should return a promise that only resolves once `trigger` is focusable.
*
* The purpose of this is to prevent the focus being sent to an animated trigger element too early.
* If a trigger element fades in upon trap deactivation, there is a brief delay between the deactivation
* of the trap and when the trigger element is focusable.
*
* `trigger` will be either the node that had focus prior to the trap being activated,
* or the result of the `setReturnFocus` option, if configured.
*
* This handler is **not** called if the `returnFocusOnDeactivate` configuration option
* (or the `returnFocus` deactivation option) is falsy.
*/
checkCanReturnFocus?: ((trigger: HTMLElement | SVGElement) => Promise<void>) | undefined;
/**
* By default, when a focus trap is activated the first element in the
* focus trap's tab order will receive focus. With this option you can
* specify a different element to receive that initial focus, or use `false`
* for no initially focused element at all.
*
* NOTE: Setting this option to `false` (or a function that returns `false`)
* will prevent the `fallbackFocus` option from being used.
*
* Setting this option to `undefined` (or a function that returns `undefined`)
* will result in the default behavior.
*/
initialFocus?: FocusTargetOrFalse | undefined | VoidFunction;
/**
* By default, an error will be thrown if the focus trap contains no
* elements in its tab order. With this option you can specify a
* fallback element to programmatically receive focus if no other
* tabbable elements are found. For example, you may want a popover's
* `<div>` to receive focus if the popover's content includes no
* tabbable elements. *Make sure the fallback element has a negative
* `tabindex` so it can be programmatically focused.
*
* NOTE: If `initialFocus` is `false` (or a function that returns `false`),
* this function will not be called when the trap is activated, and no element
* will be initially focused. This function may still be called while the trap
* is active if things change such that there are no longer any tabbable nodes
* in the trap.
*/
fallbackFocus?: FocusTarget | undefined;
/**
* Default: `true`. If `false`, when the trap is deactivated,
* focus will *not* return to the element that had focus before activation.
*/
returnFocusOnDeactivate?: boolean | undefined;
/**
* By default, focus trap on deactivation will return to the element
* that was focused before activation.
*/
setReturnFocus?: FocusTargetValueOrFalse | ((nodeFocusedBeforeActivation: HTMLElement | SVGElement) => FocusTargetValueOrFalse) | undefined;
/**
* Default: `true`. If `false` or returns `false`, the `Escape` key will not trigger
* deactivation of the focus trap. This can be useful if you want
* to force the user to make a decision instead of allowing an easy
* way out. Note that if a function is given, it's only called if the ESC key
* was pressed.
*/
escapeDeactivates?: boolean | KeyboardEventToBoolean | undefined;
/**
* If `true` or returns `true`, a click outside the focus trap will
* deactivate the focus trap and allow the click event to do its thing (i.e.
* to pass-through to the element that was clicked). This option **takes
* precedence** over `allowOutsideClick` when it's set to `true`, causing
* that option to be ignored. Default: `false`.
*/
clickOutsideDeactivates?: boolean | MouseEventToBoolean | undefined;
/**
* If set and is or returns `true`, a click outside the focus trap will not
* be prevented, even when `clickOutsideDeactivates` is `false`. When
* `clickOutsideDeactivates` is `true`, this option is **ignored** (i.e.
* if it's a function, it will not be called). Use this option to control
* if (and even which) clicks are allowed outside the trap in conjunction
* with `clickOutsideDeactivates: false`. Default: `false`.
*/
allowOutsideClick?: boolean | MouseEventToBoolean | undefined;
/**
* By default, focus() will scroll to the element if not in viewport.
* It can produce unintended effects like scrolling back to the top of a modal.
* If set to `true`, no scroll will happen.
*/
preventScroll?: boolean | undefined;
/**
* Default: `true`. Delays the autofocus when the focus trap is activated.
* This prevents elements within the focusable element from capturing
* the event that triggered the focus trap activation.
*/
delayInitialFocus?: boolean | undefined;
/**
* Default: `window.document`. Document where the focus trap will be active.
* This allows to use FocusTrap in an iFrame context.
*/
document?: Document | undefined;
/**
* Determines if the given keyboard event is a "tab forward" event that will move
* the focus to the next trapped element in tab order. Defaults to the `TAB` key.
* Use this to override the trap's behavior if you want to use arrow keys to control
* keyboard navigation within the trap, for example. Also see `isKeyBackward()` option.
*/
isKeyForward?: KeyboardEventToBoolean | undefined;
/**
* Determines if the given keyboard event is a "tab backward" event that will move
* the focus to the previous trapped element in tab order. Defaults to the `SHIFT+TAB` key.
* Use this to override the trap's behavior if you want to use arrow keys to control
* keyboard navigation within the trap, for example. Also see `isKeyForward()` option.
*/
isKeyBackward?: KeyboardEventToBoolean | undefined;
/**
* Default: `[]`. An array of FocusTrap instances that will be managed by this FocusTrap.
*/
trapStack?: any[] | undefined;
/**
* Default: `true`. If `true`, the focus trap will recursively include elements
* that are controlled by elements within the trap via `aria-controls`. Only elements
* with `aria-expanded="true"` and interactive container roles (menu, listbox, dialog, etc.)
* will be included. This allows nested menus, select dropdowns, and other portalled
* content to remain within the focus trap.
*/
followControlledElements?: boolean | undefined;
/**
* Optional function to support shadow DOM traversal. When provided, it enables
* the focus trap to find tabbable elements inside shadow roots (web components).
*
* - `true`: Enable shadow DOM support for open shadow roots
* - `false` or `undefined`: Disable shadow DOM support (default)
* - Function: Called with each element; return `true` if it has a shadow root to traverse,
* the `ShadowRoot` instance, or a falsy value if no shadow root exists
*
* This is required for proper focus management when using web components or custom elements
* with shadow DOM.
*
* @example
* ```ts
* // Enable for all open shadow roots
* getShadowRoot: true
*
* // Custom function for closed shadow roots
* getShadowRoot: (node) => {
* if (node === myCustomElement) return myCustomElement.shadowRoot
* return node.shadowRoot
* }
* ```
*/
getShadowRoot?: boolean | ((node: FocusableElement) => ShadowRoot | boolean | undefined) | undefined;
}
interface DeactivateOptions extends Pick<FocusTrapOptions, "onDeactivate" | "onPostDeactivate" | "checkCanReturnFocus"> {
returnFocus?: boolean | undefined;
}
type ActivateOptions = Pick<FocusTrapOptions, "onActivate" | "onPostActivate" | "checkCanFocusTrap">;
type PauseOptions = Pick<FocusTrapOptions, "onPause" | "onPostPause">;
type UnpauseOptions = Pick<FocusTrapOptions, "onUnpause" | "onPostUnpause">;
//#endregion
//#region src/shared/focus-trap/focus-trap.d.ts
declare class FocusTrap {
private trapStack;
private config;
private doc;
private state;
private portalContainers;
private addPortalContainer;
private observePortalContainer;
private updatePortalContainers;
get active(): boolean;
get paused(): boolean;
constructor(elements: HTMLElement | HTMLElement[], options: FocusTrapOptions);
private findContainerIndex;
private isControlledElement;
private updateTabbableNodes;
private listenerCleanups;
private addListeners;
private removeListeners;
private handleFocus;
private handlePointerDown;
private handleClick;
private handleTabKey;
private handleEscapeKey;
private _mutationObserver?;
private setupMutationObserver;
private updateObservedNodes;
private getInitialFocusNode;
private tryFocus;
activate(activateOptions?: ActivateOptions): this;
deactivate: (deactivateOptions?: DeactivateOptions) => this;
pause: (pauseOptions?: PauseOptions) => this;
unpause: (unpauseOptions?: UnpauseOptions) => this;
updateContainerElements: (containerElements: HTMLElement | HTMLElement[]) => this;
private getReturnFocusNode;
private getOption;
private getNodeForOption;
private findNextNavNode;
}
//#endregion
//#region src/shared/focus-trap/index.d.ts
type ElementOrGetter = HTMLElement | null | (() => HTMLElement | null);
type ElementsOrGetter = ElementOrGetter | ElementOrGetter[];
interface TrapFocusOptions extends Omit<FocusTrapOptions, "document"> {}
declare function trapFocus(el: ElementsOrGetter, options?: TrapFocusOptions): () => void;
//#endregion
export { FocusTrap, type FocusTrapOptions, TrapFocusOptions, trapFocus };
import { $ as getTabIndex, G as raf, Jt as hasControllerElements, X as getFocusables, Xt as isControlledElement, Yt as isControlledByExpandedController, dt as addDomEvent, fn as isDocument, gt as getEventTarget, nt as isFocusable, qt as getControlledElements, rn as getDocument, rt as isTabbable, tn as getActiveElement, tt as getTabbables } from "./dom-query-BgxIO7_X.mjs";
//#region src/shared/focus-trap/focus-trap.ts
const activeFocusTraps = {
activateTrap(trapStack, trap) {
if (trapStack.length > 0) {
const activeTrap = trapStack[trapStack.length - 1];
if (activeTrap !== trap) activeTrap.pause();
}
const trapIndex = trapStack.indexOf(trap);
if (trapIndex === -1) trapStack.push(trap);
else {
trapStack.splice(trapIndex, 1);
trapStack.push(trap);
}
},
deactivateTrap(trapStack, trap) {
const trapIndex = trapStack.indexOf(trap);
if (trapIndex !== -1) trapStack.splice(trapIndex, 1);
if (trapStack.length > 0) trapStack[trapStack.length - 1].unpause();
}
};
const sharedTrapStack = [];
var FocusTrap = class {
trapStack;
config;
doc;
state = {
containers: [],
containerGroups: [],
tabbableGroups: [],
nodeFocusedBeforeActivation: null,
mostRecentlyFocusedNode: null,
active: false,
paused: false,
delayInitialFocusTimer: void 0,
recentNavEvent: void 0
};
portalContainers = /* @__PURE__ */ new Set();
addPortalContainer(controlledElement) {
const portalContainer = controlledElement.parentElement;
if (portalContainer && !this.portalContainers.has(portalContainer)) {
this.portalContainers.add(portalContainer);
if (this.state.active && !this.state.paused) this.observePortalContainer(portalContainer);
}
}
observePortalContainer(portalContainer) {
this._mutationObserver?.observe(portalContainer, {
subtree: true,
childList: true,
attributes: true,
attributeFilter: ["aria-controls", "aria-expanded"]
});
}
updatePortalContainers() {
if (!this.config.followControlledElements) return;
this.state.containers.forEach((container) => {
getControlledElements(container).forEach((controlledElement) => {
this.addPortalContainer(controlledElement);
});
});
}
get active() {
return this.state.active;
}
get paused() {
return this.state.paused;
}
constructor(elements, options) {
this.trapStack = options.trapStack || sharedTrapStack;
const config = {
returnFocusOnDeactivate: true,
escapeDeactivates: true,
delayInitialFocus: true,
followControlledElements: true,
isKeyForward,
isKeyBackward,
...options
};
this.doc = config.document || getDocument(Array.isArray(elements) ? elements[0] : elements);
this.config = config;
this.updateContainerElements(elements);
this.setupMutationObserver();
}
findContainerIndex(element, event) {
const composedPath = typeof event?.composedPath === "function" ? event.composedPath() : void 0;
return this.state.containerGroups.findIndex(({ container, tabbableNodes }) => container.contains(element) || composedPath?.includes(container) || tabbableNodes.find((node) => node === element) || this.isControlledElement(container, element));
}
isControlledElement(container, element) {
if (!this.config.followControlledElements) return false;
return isControlledElement(container, element);
}
updateTabbableNodes() {
this.state.containerGroups = this.state.containers.map((container) => {
const tabbableNodes = getTabbables(container, { getShadowRoot: this.config.getShadowRoot });
const focusableNodes = getFocusables(container, { getShadowRoot: this.config.getShadowRoot });
const firstTabbableNode = tabbableNodes[0];
const lastTabbableNode = tabbableNodes[tabbableNodes.length - 1];
const firstDomTabbableNode = firstTabbableNode;
const lastDomTabbableNode = lastTabbableNode;
let posTabIndexesFound = false;
for (let i = 0; i < tabbableNodes.length; i++) if (getTabIndex(tabbableNodes[i]) > 0) {
posTabIndexesFound = true;
break;
}
function nextTabbableNode(node, forward = true) {
const nodeIdx = tabbableNodes.indexOf(node);
if (nodeIdx >= 0) return tabbableNodes[nodeIdx + (forward ? 1 : -1)];
const focusableIdx = focusableNodes.indexOf(node);
if (focusableIdx < 0) return void 0;
if (forward) {
for (let i = focusableIdx + 1; i < focusableNodes.length; i++) if (isTabbable(focusableNodes[i])) return focusableNodes[i];
} else for (let i = focusableIdx - 1; i >= 0; i--) if (isTabbable(focusableNodes[i])) return focusableNodes[i];
}
return {
container,
tabbableNodes,
focusableNodes,
posTabIndexesFound,
firstTabbableNode,
lastTabbableNode,
firstDomTabbableNode,
lastDomTabbableNode,
nextTabbableNode
};
});
this.state.tabbableGroups = this.state.containerGroups.filter((group) => group.tabbableNodes.length > 0);
if (this.state.tabbableGroups.length <= 0 && !this.getNodeForOption("fallbackFocus")) throw new Error("Your focus-trap must have at least one container with at least one tabbable node in it at all times");
if (this.state.containerGroups.find((g) => g.posTabIndexesFound) && this.state.containerGroups.length > 1) throw new Error("At least one node with a positive tabindex was found in one of your focus-trap's multiple containers. Positive tabindexes are only supported in single-container focus-traps.");
}
listenerCleanups = [];
addListeners() {
if (!this.state.active) return;
activeFocusTraps.activateTrap(this.trapStack, this);
this.state.delayInitialFocusTimer = this.config.delayInitialFocus ? delay(() => {
this.tryFocus(this.getInitialFocusNode());
}) : this.tryFocus(this.getInitialFocusNode());
this.listenerCleanups.push(addDomEvent(this.doc, "focusin", this.handleFocus, true), addDomEvent(this.doc, "mousedown", this.handlePointerDown, {
capture: true,
passive: false
}), addDomEvent(this.doc, "touchstart", this.handlePointerDown, {
capture: true,
passive: false
}), addDomEvent(this.doc, "click", this.handleClick, {
capture: true,
passive: false
}), addDomEvent(this.doc, "keydown", this.handleTabKey, {
capture: true,
passive: false
}), addDomEvent(this.doc, "keydown", this.handleEscapeKey));
return this;
}
removeListeners() {
if (!this.state.active) return;
this.listenerCleanups.forEach((cleanup) => cleanup());
this.listenerCleanups = [];
return this;
}
handleFocus = (event) => {
const target = getEventTarget(event);
const targetContained = this.findContainerIndex(target, event) >= 0;
if (targetContained || isDocument(target)) {
if (targetContained) this.state.mostRecentlyFocusedNode = target;
} else {
event.stopImmediatePropagation();
let nextNode;
let navAcrossContainers = true;
if (this.state.mostRecentlyFocusedNode) {
if (getTabIndex(this.state.mostRecentlyFocusedNode) > 0) {
const mruContainerIdx = this.findContainerIndex(this.state.mostRecentlyFocusedNode);
const { tabbableNodes } = this.state.containerGroups[mruContainerIdx];
if (tabbableNodes.length > 0) {
const mruTabIdx = tabbableNodes.findIndex((node) => node === this.state.mostRecentlyFocusedNode);
if (mruTabIdx >= 0) {
if (this.config.isKeyForward(this.state.recentNavEvent)) {
if (mruTabIdx + 1 < tabbableNodes.length) {
nextNode = tabbableNodes[mruTabIdx + 1];
navAcrossContainers = false;
}
} else if (mruTabIdx - 1 >= 0) {
nextNode = tabbableNodes[mruTabIdx - 1];
navAcrossContainers = false;
}
}
}
} else if (!this.state.containerGroups.some((g) => g.tabbableNodes.some((n) => getTabIndex(n) > 0))) navAcrossContainers = false;
} else navAcrossContainers = false;
if (navAcrossContainers) nextNode = this.findNextNavNode({
target: this.state.mostRecentlyFocusedNode,
isBackward: this.config.isKeyBackward(this.state.recentNavEvent)
});
if (nextNode) this.tryFocus(nextNode);
else this.tryFocus(this.state.mostRecentlyFocusedNode || this.getInitialFocusNode());
}
this.state.recentNavEvent = void 0;
};
handlePointerDown = (event) => {
const target = getEventTarget(event);
if (this.findContainerIndex(target, event) >= 0) return;
if (valueOrHandler(this.config.clickOutsideDeactivates, event)) {
this.deactivate({ returnFocus: this.config.returnFocusOnDeactivate });
return;
}
if (valueOrHandler(this.config.allowOutsideClick, event)) return;
event.preventDefault();
};
handleClick = (event) => {
const target = getEventTarget(event);
if (this.findContainerIndex(target, event) >= 0) return;
if (valueOrHandler(this.config.clickOutsideDeactivates, event)) return;
if (valueOrHandler(this.config.allowOutsideClick, event)) return;
event.preventDefault();
event.stopImmediatePropagation();
};
handleTabKey = (event) => {
if (this.config.isKeyForward(event) || this.config.isKeyBackward(event)) {
this.state.recentNavEvent = event;
const isBackward = this.config.isKeyBackward(event);
const destinationNode = this.findNextNavNode({
event,
isBackward
});
if (!destinationNode) return;
if (isTabEvent(event)) event.preventDefault();
this.tryFocus(destinationNode);
}
};
handleEscapeKey = (event) => {
if (isEscapeEvent(event) && valueOrHandler(this.config.escapeDeactivates, event) !== false) {
event.preventDefault();
this.deactivate();
}
};
_mutationObserver;
setupMutationObserver = () => {
const win = this.doc.defaultView || window;
this._mutationObserver = new win.MutationObserver((mutations) => {
if (mutations.some((mutation) => {
return Array.from(mutation.removedNodes).some((node) => node === this.state.mostRecentlyFocusedNode);
})) this.tryFocus(this.getInitialFocusNode());
if (mutations.some((mutation) => {
if (mutation.type === "attributes" && (mutation.attributeName === "aria-controls" || mutation.attributeName === "aria-expanded")) return true;
if (mutation.type === "childList" && mutation.addedNodes.length > 0) return Array.from(mutation.addedNodes).some((node) => {
if (node.nodeType !== Node.ELEMENT_NODE) return false;
const element = node;
if (hasControllerElements(element)) return true;
if (element.id && !this.state.containers.some((c) => c.contains(element))) return isControlledByExpandedController(element);
return false;
});
return false;
}) && this.state.active && !this.state.paused) {
this.updateTabbableNodes();
this.updatePortalContainers();
}
});
};
updateObservedNodes = () => {
this._mutationObserver?.disconnect();
if (this.state.active && !this.state.paused) {
this.state.containers.map((container) => {
this._mutationObserver?.observe(container, {
subtree: true,
childList: true,
attributes: true,
attributeFilter: ["aria-controls", "aria-expanded"]
});
});
this.portalContainers.forEach((portalContainer) => {
this.observePortalContainer(portalContainer);
});
}
};
getInitialFocusNode = () => {
let node = this.getNodeForOption("initialFocus", { hasFallback: true });
if (node === false) return false;
if (node === void 0 || node && !isFocusable(node)) {
const activeElement = getActiveElement(this.doc);
if (activeElement && this.findContainerIndex(activeElement) >= 0) node = activeElement;
else {
const firstTabbableGroup = this.state.tabbableGroups[0];
node = firstTabbableGroup && firstTabbableGroup.firstTabbableNode || this.getNodeForOption("fallbackFocus");
}
} else if (node === null) node = this.getNodeForOption("fallbackFocus");
if (!node) throw new Error("Your focus-trap needs to have at least one focusable element");
if (!node.isConnected) node = this.getNodeForOption("fallbackFocus");
if (!node || !node.isConnected) throw new Error("Your focus-trap needs to have at least one focusable element");
return node;
};
tryFocus = (node) => {
if (node === false) return;
if (node === getActiveElement(this.doc)) return;
if (!node || !node.focus) {
this.tryFocus(this.getInitialFocusNode());
return;
}
node.focus({ preventScroll: !!this.config.preventScroll });
this.state.mostRecentlyFocusedNode = node;
if (isSelectableInput(node)) node.select();
};
activate(activateOptions) {
if (this.state.active) return this;
const onActivate = this.getOption(activateOptions, "onActivate");
const onPostActivate = this.getOption(activateOptions, "onPostActivate");
const checkCanFocusTrap = this.getOption(activateOptions, "checkCanFocusTrap");
if (!checkCanFocusTrap) this.updateTabbableNodes();
this.state.active = true;
this.state.paused = false;
this.state.nodeFocusedBeforeActivation = getActiveElement(this.doc);
onActivate?.();
const finishActivation = () => {
if (checkCanFocusTrap) this.updateTabbableNodes();
this.addListeners();
this.updateObservedNodes();
onPostActivate?.();
};
if (checkCanFocusTrap) {
checkCanFocusTrap(this.state.containers.concat()).then(finishActivation, finishActivation);
return this;
}
finishActivation();
return this;
}
deactivate = (deactivateOptions) => {
if (!this.state.active) return this;
const options = {
onDeactivate: this.config.onDeactivate,
onPostDeactivate: this.config.onPostDeactivate,
checkCanReturnFocus: this.config.checkCanReturnFocus,
...deactivateOptions
};
clearTimeout(this.state.delayInitialFocusTimer);
this.state.delayInitialFocusTimer = void 0;
this.removeListeners();
this.state.active = false;
this.state.paused = false;
this.updateObservedNodes();
activeFocusTraps.deactivateTrap(this.trapStack, this);
this.portalContainers.clear();
const onDeactivate = this.getOption(options, "onDeactivate");
const onPostDeactivate = this.getOption(options, "onPostDeactivate");
const checkCanReturnFocus = this.getOption(options, "checkCanReturnFocus");
const returnFocus = this.getOption(options, "returnFocus", "returnFocusOnDeactivate");
onDeactivate?.();
const finishDeactivation = () => {
delay(() => {
if (returnFocus) {
const returnFocusNode = this.getReturnFocusNode(this.state.nodeFocusedBeforeActivation);
this.tryFocus(returnFocusNode);
}
onPostDeactivate?.();
});
};
if (returnFocus && checkCanReturnFocus) {
checkCanReturnFocus(this.getReturnFocusNode(this.state.nodeFocusedBeforeActivation)).then(finishDeactivation, finishDeactivation);
return this;
}
finishDeactivation();
return this;
};
pause = (pauseOptions) => {
if (this.state.paused || !this.state.active) return this;
const onPause = this.getOption(pauseOptions, "onPause");
const onPostPause = this.getOption(pauseOptions, "onPostPause");
this.state.paused = true;
onPause?.();
this.removeListeners();
this.updateObservedNodes();
onPostPause?.();
return this;
};
unpause = (unpauseOptions) => {
if (!this.state.paused || !this.state.active) return this;
const onUnpause = this.getOption(unpauseOptions, "onUnpause");
const onPostUnpause = this.getOption(unpauseOptions, "onPostUnpause");
this.state.paused = false;
onUnpause?.();
this.updateTabbableNodes();
this.addListeners();
this.updateObservedNodes();
onPostUnpause?.();
return this;
};
updateContainerElements = (containerElements) => {
this.state.containers = Array.isArray(containerElements) ? containerElements.filter(Boolean) : [containerElements].filter(Boolean);
if (this.state.active) this.updateTabbableNodes();
this.updateObservedNodes();
return this;
};
getReturnFocusNode = (previousActiveElement) => {
const node = this.getNodeForOption("setReturnFocus", { params: [previousActiveElement] });
return node ? node : node === false ? false : previousActiveElement;
};
getOption = (configOverrideOptions, optionName, configOptionName) => {
return configOverrideOptions && configOverrideOptions[optionName] !== void 0 ? configOverrideOptions[optionName] : this.config[configOptionName || optionName];
};
getNodeForOption = (optionName, { hasFallback = false, params = [] } = {}) => {
let optionValue = this.config[optionName];
if (typeof optionValue === "function") optionValue = optionValue(...params);
if (optionValue === true) optionValue = void 0;
if (!optionValue) {
if (optionValue === void 0 || optionValue === false) return optionValue;
throw new Error(`\`${optionName}\` was specified but was not a node, or did not return a node`);
}
let node = optionValue;
if (typeof optionValue === "string") {
try {
node = this.doc.querySelector(optionValue);
} catch (err) {
throw new Error(`\`${optionName}\` appears to be an invalid selector; error="${err.message}"`);
}
if (!node) {
if (!hasFallback) throw new Error(`\`${optionName}\` as selector refers to no known node`);
}
}
return node;
};
findNextNavNode = (opts) => {
const { event, isBackward = false } = opts;
const target = opts.target || getEventTarget(event);
this.updateTabbableNodes();
let destinationNode = null;
if (this.state.tabbableGroups.length > 0) {
const containerIndex = this.findContainerIndex(target, event);
const containerGroup = containerIndex >= 0 ? this.state.containerGroups[containerIndex] : void 0;
if (containerIndex < 0) if (isBackward) destinationNode = this.state.tabbableGroups[this.state.tabbableGroups.length - 1].lastTabbableNode;
else destinationNode = this.state.tabbableGroups[0].firstTabbableNode;
else if (isBackward) {
let startOfGroupIndex = this.state.tabbableGroups.findIndex(({ firstTabbableNode }) => target === firstTabbableNode);
if (startOfGroupIndex < 0 && (containerGroup?.container === target || isFocusable(target) && !isTabbable(target) && !containerGroup?.nextTabbableNode(target, false))) startOfGroupIndex = containerIndex;
if (startOfGroupIndex >= 0) {
const destinationGroupIndex = startOfGroupIndex === 0 ? this.state.tabbableGroups.length - 1 : startOfGroupIndex - 1;
const destinationGroup = this.state.tabbableGroups[destinationGroupIndex];
destinationNode = getTabIndex(target) >= 0 ? destinationGroup.lastTabbableNode : destinationGroup.lastDomTabbableNode;
} else if (!isTabEvent(event)) destinationNode = containerGroup?.nextTabbableNode(target, false);
} else {
let lastOfGroupIndex = this.state.tabbableGroups.findIndex(({ lastTabbableNode }) => target === lastTabbableNode);
if (lastOfGroupIndex < 0 && (containerGroup?.container === target || isFocusable(target) && !isTabbable(target) && !containerGroup?.nextTabbableNode(target))) lastOfGroupIndex = containerIndex;
if (lastOfGroupIndex >= 0) {
const destinationGroupIndex = lastOfGroupIndex === this.state.tabbableGroups.length - 1 ? 0 : lastOfGroupIndex + 1;
const destinationGroup = this.state.tabbableGroups[destinationGroupIndex];
destinationNode = getTabIndex(target) >= 0 ? destinationGroup.firstTabbableNode : destinationGroup.firstDomTabbableNode;
} else if (!isTabEvent(event)) destinationNode = containerGroup?.nextTabbableNode(target);
}
} else destinationNode = this.getNodeForOption("fallbackFocus");
return destinationNode;
};
};
const isKeyboardEvent = (event) => event?.type === "keydown";
const isTabEvent = (event) => isKeyboardEvent(event) && event?.key === "Tab";
const isKeyForward = (e) => isKeyboardEvent(e) && e.key === "Tab" && !e?.shiftKey;
const isKeyBackward = (e) => isKeyboardEvent(e) && e.key === "Tab" && e?.shiftKey;
const valueOrHandler = (value, ...params) => typeof value === "function" ? value(...params) : value;
const isEscapeEvent = (event) => !event.isComposing && event.key === "Escape";
const delay = (fn) => setTimeout(fn, 0);
const isSelectableInput = (node) => node.localName === "input" && "select" in node && typeof node.select === "function";
//#endregion
//#region src/shared/focus-trap/index.ts
function trapFocus(el, options = {}) {
let trap;
const cleanup = raf(() => {
const resolvedElements = (Array.isArray(el) ? el : [el]).map((e) => typeof e === "function" ? e() : e).filter((e) => e != null);
if (resolvedElements.length === 0) return;
const primaryEl = resolvedElements[0];
trap = new FocusTrap(resolvedElements, {
escapeDeactivates: false,
allowOutsideClick: true,
preventScroll: true,
returnFocusOnDeactivate: true,
delayInitialFocus: false,
fallbackFocus: primaryEl,
...options,
document: getDocument(primaryEl)
});
try {
trap.activate();
} catch {}
});
return function destroy() {
trap?.deactivate();
cleanup();
};
}
//#endregion
export { FocusTrap, trapFocus };
const require_dom_query = require("./dom-query-BT6fffRP.cjs");
//#region src/shared/focus-visible/index.ts
function isValidKey(e) {
return !(e.metaKey || !require_dom_query.isMac() && e.altKey || e.ctrlKey || e.key === "Control" || e.key === "Shift" || e.key === "Meta");
}
const nonTextInputTypes = new Set([
"checkbox",
"radio",
"range",
"color",
"file",
"image",
"button",
"submit",
"reset"
]);
function isKeyboardFocusEvent(isTextInput, modality, e) {
const eventTarget = e ? require_dom_query.getEventTarget(e) : null;
const doc = require_dom_query.getDocument(eventTarget);
const win = require_dom_query.getWindow(eventTarget);
const activeElement = require_dom_query.getActiveElement(doc);
isTextInput = isTextInput || activeElement instanceof win.HTMLInputElement && !nonTextInputTypes.has(activeElement?.type) || activeElement instanceof win.HTMLTextAreaElement || activeElement instanceof win.HTMLElement && activeElement.isContentEditable;
return !(isTextInput && modality === "keyboard" && e instanceof win.KeyboardEvent && !Reflect.has(FOCUS_VISIBLE_INPUT_KEYS, e.key));
}
let currentModality = null;
let changeHandlers = /* @__PURE__ */ new Set();
let listenerMap = /* @__PURE__ */ new Map();
let hasEventBeforeFocus = false;
let hasBlurredWindowRecently = false;
let ignoreFocusEvent = false;
const FOCUS_VISIBLE_INPUT_KEYS = {
Tab: true,
Escape: true
};
function triggerChangeHandlers(modality, e) {
for (let handler of changeHandlers) handler(modality, e);
}
function handleKeyboardEvent(e) {
hasEventBeforeFocus = true;
if (isValidKey(e)) {
currentModality = "keyboard";
triggerChangeHandlers("keyboard", e);
}
}
function handlePointerEvent(e) {
currentModality = "pointer";
if (e.type === "mousedown" || e.type === "pointerdown") {
hasEventBeforeFocus = true;
triggerChangeHandlers("pointer", e);
}
}
function handleClickEvent(e) {
if (require_dom_query.isVirtualClick(e)) {
hasEventBeforeFocus = true;
currentModality = "virtual";
}
}
function handleFocusEvent(e) {
const target = require_dom_query.getEventTarget(e);
if (target === require_dom_query.getWindow(target) || target === require_dom_query.getDocument(target) || !e.isTrusted) return;
if (!hasEventBeforeFocus && !hasBlurredWindowRecently) {
currentModality = "virtual";
triggerChangeHandlers("virtual", e);
}
hasEventBeforeFocus = false;
hasBlurredWindowRecently = false;
}
function handleWindowBlur() {
hasEventBeforeFocus = false;
hasBlurredWindowRecently = true;
}
function setupGlobalFocusEvents(root) {
if (typeof window === "undefined" || listenerMap.get(require_dom_query.getWindow(root))) return;
const win = require_dom_query.getWindow(root);
const doc = require_dom_query.getDocument(root);
let focus = win.HTMLElement.prototype.focus;
function patchedFocus() {
hasEventBeforeFocus = true;
focus.apply(this, arguments);
}
try {
Object.defineProperty(win.HTMLElement.prototype, "focus", {
configurable: true,
value: patchedFocus
});
} catch {}
doc.addEventListener("keydown", handleKeyboardEvent, true);
doc.addEventListener("keyup", handleKeyboardEvent, true);
doc.addEventListener("click", handleClickEvent, true);
win.addEventListener("focus", handleFocusEvent, true);
win.addEventListener("blur", handleWindowBlur, false);
if (typeof win.PointerEvent !== "undefined") {
doc.addEventListener("pointerdown", handlePointerEvent, true);
doc.addEventListener("pointermove", handlePointerEvent, true);
doc.addEventListener("pointerup", handlePointerEvent, true);
} else {
doc.addEventListener("mousedown", handlePointerEvent, true);
doc.addEventListener("mousemove", handlePointerEvent, true);
doc.addEventListener("mouseup", handlePointerEvent, true);
}
win.addEventListener("beforeunload", () => {
tearDownWindowFocusTracking(root);
}, { once: true });
listenerMap.set(win, { focus });
}
const tearDownWindowFocusTracking = (root, loadListener) => {
const win = require_dom_query.getWindow(root);
const doc = require_dom_query.getDocument(root);
if (loadListener) doc.removeEventListener("DOMContentLoaded", loadListener);
const listenerData = listenerMap.get(win);
if (!listenerData) return;
try {
Object.defineProperty(win.HTMLElement.prototype, "focus", {
configurable: true,
value: listenerData.focus
});
} catch {}
doc.removeEventListener("keydown", handleKeyboardEvent, true);
doc.removeEventListener("keyup", handleKeyboardEvent, true);
doc.removeEventListener("click", handleClickEvent, true);
win.removeEventListener("focus", handleFocusEvent, true);
win.removeEventListener("blur", handleWindowBlur, false);
if (typeof win.PointerEvent !== "undefined") {
doc.removeEventListener("pointerdown", handlePointerEvent, true);
doc.removeEventListener("pointermove", handlePointerEvent, true);
doc.removeEventListener("pointerup", handlePointerEvent, true);
} else {
doc.removeEventListener("mousedown", handlePointerEvent, true);
doc.removeEventListener("mousemove", handlePointerEvent, true);
doc.removeEventListener("mouseup", handlePointerEvent, true);
}
listenerMap.delete(win);
};
function getInteractionModality() {
return currentModality;
}
function setInteractionModality(modality) {
currentModality = modality;
triggerChangeHandlers(modality, null);
}
function trackInteractionModality(props) {
const { onChange, root } = props;
setupGlobalFocusEvents(root);
onChange({ modality: currentModality });
const handler = () => onChange({ modality: currentModality });
changeHandlers.add(handler);
return () => {
changeHandlers.delete(handler);
};
}
function isFocusVisible() {
return currentModality === "keyboard" || currentModality === "virtual";
}
function trackFocusVisible(props = {}) {
const { isTextInput, autoFocus, onChange, root } = props;
setupGlobalFocusEvents(root);
onChange?.({
isFocusVisible: autoFocus || isFocusVisible(),
modality: currentModality
});
const handler = (modality, e) => {
if (!isKeyboardFocusEvent(!!isTextInput, modality, e)) return;
onChange?.({
isFocusVisible: isFocusVisible(),
modality
});
};
changeHandlers.add(handler);
return () => {
changeHandlers.delete(handler);
};
}
//#endregion
Object.defineProperty(exports, "getInteractionModality", {
enumerable: true,
get: function() {
return getInteractionModality;
}
});
Object.defineProperty(exports, "ignoreFocusEvent", {
enumerable: true,
get: function() {
return ignoreFocusEvent;
}
});
Object.defineProperty(exports, "isFocusVisible", {
enumerable: true,
get: function() {
return isFocusVisible;
}
});
Object.defineProperty(exports, "listenerMap", {
enumerable: true,
get: function() {
return listenerMap;
}
});
Object.defineProperty(exports, "setInteractionModality", {
enumerable: true,
get: function() {
return setInteractionModality;
}
});
Object.defineProperty(exports, "trackFocusVisible", {
enumerable: true,
get: function() {
return trackFocusVisible;
}
});
Object.defineProperty(exports, "trackInteractionModality", {
enumerable: true,
get: function() {
return trackInteractionModality;
}
});
import { Vt as isMac, gt as getEventTarget, kt as isVirtualClick, ln as getWindow, rn as getDocument, tn as getActiveElement } from "./dom-query-BgxIO7_X.mjs";
//#region src/shared/focus-visible/index.ts
function isValidKey(e) {
return !(e.metaKey || !isMac() && e.altKey || e.ctrlKey || e.key === "Control" || e.key === "Shift" || e.key === "Meta");
}
const nonTextInputTypes = new Set([
"checkbox",
"radio",
"range",
"color",
"file",
"image",
"button",
"submit",
"reset"
]);
function isKeyboardFocusEvent(isTextInput, modality, e) {
const eventTarget = e ? getEventTarget(e) : null;
const doc = getDocument(eventTarget);
const win = getWindow(eventTarget);
const activeElement = getActiveElement(doc);
isTextInput = isTextInput || activeElement instanceof win.HTMLInputElement && !nonTextInputTypes.has(activeElement?.type) || activeElement instanceof win.HTMLTextAreaElement || activeElement instanceof win.HTMLElement && activeElement.isContentEditable;
return !(isTextInput && modality === "keyboard" && e instanceof win.KeyboardEvent && !Reflect.has(FOCUS_VISIBLE_INPUT_KEYS, e.key));
}
let currentModality = null;
let changeHandlers = /* @__PURE__ */ new Set();
let listenerMap = /* @__PURE__ */ new Map();
let hasEventBeforeFocus = false;
let hasBlurredWindowRecently = false;
let ignoreFocusEvent = false;
const FOCUS_VISIBLE_INPUT_KEYS = {
Tab: true,
Escape: true
};
function triggerChangeHandlers(modality, e) {
for (let handler of changeHandlers) handler(modality, e);
}
function handleKeyboardEvent(e) {
hasEventBeforeFocus = true;
if (isValidKey(e)) {
currentModality = "keyboard";
triggerChangeHandlers("keyboard", e);
}
}
function handlePointerEvent(e) {
currentModality = "pointer";
if (e.type === "mousedown" || e.type === "pointerdown") {
hasEventBeforeFocus = true;
triggerChangeHandlers("pointer", e);
}
}
function handleClickEvent(e) {
if (isVirtualClick(e)) {
hasEventBeforeFocus = true;
currentModality = "virtual";
}
}
function handleFocusEvent(e) {
const target = getEventTarget(e);
if (target === getWindow(target) || target === getDocument(target) || !e.isTrusted) return;
if (!hasEventBeforeFocus && !hasBlurredWindowRecently) {
currentModality = "virtual";
triggerChangeHandlers("virtual", e);
}
hasEventBeforeFocus = false;
hasBlurredWindowRecently = false;
}
function handleWindowBlur() {
hasEventBeforeFocus = false;
hasBlurredWindowRecently = true;
}
function setupGlobalFocusEvents(root) {
if (typeof window === "undefined" || listenerMap.get(getWindow(root))) return;
const win = getWindow(root);
const doc = getDocument(root);
let focus = win.HTMLElement.prototype.focus;
function patchedFocus() {
hasEventBeforeFocus = true;
focus.apply(this, arguments);
}
try {
Object.defineProperty(win.HTMLElement.prototype, "focus", {
configurable: true,
value: patchedFocus
});
} catch {}
doc.addEventListener("keydown", handleKeyboardEvent, true);
doc.addEventListener("keyup", handleKeyboardEvent, true);
doc.addEventListener("click", handleClickEvent, true);
win.addEventListener("focus", handleFocusEvent, true);
win.addEventListener("blur", handleWindowBlur, false);
if (typeof win.PointerEvent !== "undefined") {
doc.addEventListener("pointerdown", handlePointerEvent, true);
doc.addEventListener("pointermove", handlePointerEvent, true);
doc.addEventListener("pointerup", handlePointerEvent, true);
} else {
doc.addEventListener("mousedown", handlePointerEvent, true);
doc.addEventListener("mousemove", handlePointerEvent, true);
doc.addEventListener("mouseup", handlePointerEvent, true);
}
win.addEventListener("beforeunload", () => {
tearDownWindowFocusTracking(root);
}, { once: true });
listenerMap.set(win, { focus });
}
const tearDownWindowFocusTracking = (root, loadListener) => {
const win = getWindow(root);
const doc = getDocument(root);
if (loadListener) doc.removeEventListener("DOMContentLoaded", loadListener);
const listenerData = listenerMap.get(win);
if (!listenerData) return;
try {
Object.defineProperty(win.HTMLElement.prototype, "focus", {
configurable: true,
value: listenerData.focus
});
} catch {}
doc.removeEventListener("keydown", handleKeyboardEvent, true);
doc.removeEventListener("keyup", handleKeyboardEvent, true);
doc.removeEventListener("click", handleClickEvent, true);
win.removeEventListener("focus", handleFocusEvent, true);
win.removeEventListener("blur", handleWindowBlur, false);
if (typeof win.PointerEvent !== "undefined") {
doc.removeEventListener("pointerdown", handlePointerEvent, true);
doc.removeEventListener("pointermove", handlePointerEvent, true);
doc.removeEventListener("pointerup", handlePointerEvent, true);
} else {
doc.removeEventListener("mousedown", handlePointerEvent, true);
doc.removeEventListener("mousemove", handlePointerEvent, true);
doc.removeEventListener("mouseup", handlePointerEvent, true);
}
listenerMap.delete(win);
};
function getInteractionModality() {
return currentModality;
}
function setInteractionModality(modality) {
currentModality = modality;
triggerChangeHandlers(modality, null);
}
function trackInteractionModality(props) {
const { onChange, root } = props;
setupGlobalFocusEvents(root);
onChange({ modality: currentModality });
const handler = () => onChange({ modality: currentModality });
changeHandlers.add(handler);
return () => {
changeHandlers.delete(handler);
};
}
function isFocusVisible() {
return currentModality === "keyboard" || currentModality === "virtual";
}
function trackFocusVisible(props = {}) {
const { isTextInput, autoFocus, onChange, root } = props;
setupGlobalFocusEvents(root);
onChange?.({
isFocusVisible: autoFocus || isFocusVisible(),
modality: currentModality
});
const handler = (modality, e) => {
if (!isKeyboardFocusEvent(!!isTextInput, modality, e)) return;
onChange?.({
isFocusVisible: isFocusVisible(),
modality
});
};
changeHandlers.add(handler);
return () => {
changeHandlers.delete(handler);
};
}
//#endregion
export { setInteractionModality as a, listenerMap as i, ignoreFocusEvent as n, trackFocusVisible as o, isFocusVisible as r, trackInteractionModality as s, getInteractionModality as t };
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_focus_visible = require("./focus-visible-B0GjxLkR.cjs");
exports.getInteractionModality = require_focus_visible.getInteractionModality;
exports.ignoreFocusEvent = require_focus_visible.ignoreFocusEvent;
exports.isFocusVisible = require_focus_visible.isFocusVisible;
exports.listenerMap = require_focus_visible.listenerMap;
exports.setInteractionModality = require_focus_visible.setInteractionModality;
exports.trackFocusVisible = require_focus_visible.trackFocusVisible;
exports.trackInteractionModality = require_focus_visible.trackInteractionModality;
//#region src/shared/focus-visible/index.d.ts
type Modality = "keyboard" | "pointer" | "virtual";
type RootNode = Document | ShadowRoot | Node;
interface GlobalListenerData {
focus: VoidFunction;
}
declare let listenerMap: Map<Window, GlobalListenerData>;
declare let ignoreFocusEvent: boolean;
declare function getInteractionModality(): Modality | null;
declare function setInteractionModality(modality: Modality): void;
interface InteractionModalityChangeDetails {
modality: Modality | null;
}
interface InteractionModalityProps {
root?: RootNode | undefined;
onChange: (details: InteractionModalityChangeDetails) => void;
}
declare function trackInteractionModality(props: InteractionModalityProps): VoidFunction;
declare function isFocusVisible(): boolean;
interface FocusVisibleChangeDetails {
isFocusVisible: boolean;
modality: Modality | null;
}
interface FocusVisibleProps {
root?: RootNode | undefined;
isTextInput?: boolean | undefined;
autoFocus?: boolean | undefined;
onChange?: ((details: FocusVisibleChangeDetails) => void) | undefined;
}
declare function trackFocusVisible(props?: FocusVisibleProps): VoidFunction;
//#endregion
export { FocusVisibleChangeDetails, FocusVisibleProps, InteractionModalityChangeDetails, InteractionModalityProps, Modality, getInteractionModality, ignoreFocusEvent, isFocusVisible, listenerMap, setInteractionModality, trackFocusVisible, trackInteractionModality };
//#region src/shared/focus-visible/index.d.ts
type Modality = "keyboard" | "pointer" | "virtual";
type RootNode = Document | ShadowRoot | Node;
interface GlobalListenerData {
focus: VoidFunction;
}
declare let listenerMap: Map<Window, GlobalListenerData>;
declare let ignoreFocusEvent: boolean;
declare function getInteractionModality(): Modality | null;
declare function setInteractionModality(modality: Modality): void;
interface InteractionModalityChangeDetails {
modality: Modality | null;
}
interface InteractionModalityProps {
root?: RootNode | undefined;
onChange: (details: InteractionModalityChangeDetails) => void;
}
declare function trackInteractionModality(props: InteractionModalityProps): VoidFunction;
declare function isFocusVisible(): boolean;
interface FocusVisibleChangeDetails {
isFocusVisible: boolean;
modality: Modality | null;
}
interface FocusVisibleProps {
root?: RootNode | undefined;
isTextInput?: boolean | undefined;
autoFocus?: boolean | undefined;
onChange?: ((details: FocusVisibleChangeDetails) => void) | undefined;
}
declare function trackFocusVisible(props?: FocusVisibleProps): VoidFunction;
//#endregion
export { FocusVisibleChangeDetails, FocusVisibleProps, InteractionModalityChangeDetails, InteractionModalityProps, Modality, getInteractionModality, ignoreFocusEvent, isFocusVisible, listenerMap, setInteractionModality, trackFocusVisible, trackInteractionModality };
import { a as setInteractionModality, i as listenerMap, n as ignoreFocusEvent, o as trackFocusVisible, r as isFocusVisible, s as trackInteractionModality, t as getInteractionModality } from "./focus-visible-CEAbLeAJ.mjs";
export { getInteractionModality, ignoreFocusEvent, isFocusVisible, listenerMap, setInteractionModality, trackFocusVisible, trackInteractionModality };
export { };
export { };
export {};
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_dom_query = require("./dom-query-BT6fffRP.cjs");
//#region src/shared/i18n-utils/cache.ts
function i18nCache(Ins) {
const formatterCache = /* @__PURE__ */ new Map();
return function create(locale, options) {
const cacheKey = locale + (options ? Object.entries(options).sort((a, b) => a[0] < b[0] ? -1 : 1).join() : "");
if (formatterCache.has(cacheKey)) return formatterCache.get(cacheKey);
let formatter = new Ins(locale, options);
formatterCache.set(cacheKey, formatter);
return formatter;
};
}
//#endregion
//#region src/shared/i18n-utils/collator.ts
const getCollator = i18nCache(Intl.Collator);
function createCollator(locale = "en-US", options = {}) {
return getCollator(locale, options);
}
//#endregion
//#region src/shared/i18n-utils/filter.ts
const collatorCache = i18nCache(Intl.Collator);
function createFilter(options) {
const { locale, ...rest } = options || {};
const collator = collatorCache(locale || "en-US", {
usage: "search",
...rest
});
function normalize(string) {
string = string.normalize("NFC");
if (collator.resolvedOptions().ignorePunctuation) string = string.replace(/\p{P}/gu, "");
return string;
}
function startsWith(string, substring) {
if (substring.length === 0) return true;
string = normalize(string);
substring = normalize(substring);
return collator.compare(string.slice(0, substring.length), substring) === 0;
}
function endsWith(string, substring) {
if (substring.length === 0) return true;
string = normalize(string);
substring = normalize(substring);
return collator.compare(string.slice(-substring.length), substring) === 0;
}
function contains(string, substring) {
if (substring.length === 0) return true;
string = normalize(string);
substring = normalize(substring);
let scan = 0;
let sliceLen = substring.length;
for (; scan + sliceLen <= string.length; scan++) {
let slice = string.slice(scan, scan + sliceLen);
if (collator.compare(substring, slice) === 0) return true;
}
return false;
}
return {
startsWith,
endsWith,
contains
};
}
//#endregion
//#region src/shared/i18n-utils/format-number.ts
const getNumberFormatter = i18nCache(Intl.NumberFormat);
function formatNumber(v, locale, options = {}) {
return getNumberFormatter(locale, options).format(v);
}
//#endregion
//#region src/shared/i18n-utils/format-bytes.ts
const bitPrefixes = [
"",
"kilo",
"mega",
"giga",
"tera"
];
const bytePrefixes = [
"",
"kilo",
"mega",
"giga",
"tera",
"peta"
];
const formatBytes = (bytes, locale = "en-US", options = {}) => {
if (Number.isNaN(bytes)) return "";
if (bytes === 0) return "0 B";
const { unitSystem = "decimal", precision = 3, unit = "byte", unitDisplay = "short" } = options;
const factor = unitSystem === "binary" ? 1024 : 1e3;
const prefix = unit === "bit" ? bitPrefixes : bytePrefixes;
const isNegative = bytes < 0;
let value = Math.abs(bytes);
let index = 0;
while (value >= factor && index < prefix.length - 1) {
value /= factor;
index++;
}
const v = parseFloat(value.toPrecision(precision));
return formatNumber(isNegative ? -v : v, locale, {
style: "unit",
unit: prefix[index] + unit,
unitDisplay
});
};
//#endregion
//#region src/shared/i18n-utils/format-date.ts
const symbols = "\\s|\\.|-|/|\\\\|,|\\$|\\!|\\?|:|;";
function createRegEx(sign) {
return new RegExp("(^|>|" + symbols + ")(" + sign + ")($|<|\\s|\\.|-|/|\\\\|,|\\$|\\!|\\?|:|;)", "g");
}
const FORMATS = [
"G",
"GG",
"GGG",
"GGGG",
"GGGGG",
"y",
"yo",
"yy",
"yyy",
"yyyy",
"Y",
"Yo",
"YY",
"YYY",
"YYYY",
"Q",
"Qo",
"QQ",
"QQQ",
"QQQQ",
"QQQQQ",
"M",
"Mo",
"MM",
"MMM",
"MMMM",
"MMMMM",
"E",
"EE",
"EEE",
"EEEE",
"EEEEE",
"EEEEEE",
"a",
"aa",
"aaa",
"aaaa",
"aaaaa",
"d",
"do",
"dd",
"D",
"Do",
"DD",
"DDD",
"w",
"wo",
"ww",
"s",
"so",
"ss",
"m",
"mo",
"mm",
"h",
"ho",
"hh",
"H",
"Ho",
"HH",
"z",
"zz",
"zzz",
"zzzz",
"T"
];
function ordinal(num) {
const n = typeof num === "string" ? parseFloat(num) : num;
let suffix = "th";
if (n % 10 === 1 && n % 100 !== 11) suffix = "st";
else if (n % 10 === 2 && n % 100 !== 12) suffix = "nd";
else if (n % 10 === 3 && n % 100 !== 13) suffix = "rd";
return `${n}${suffix}`;
}
function pad(num, length) {
return String(num).padStart(length, "0");
}
function zone(str) {
return str.split(/AM|PM/)[1].trim();
}
function getFormat(date, options) {
const { locale, format, timeZone } = options;
switch (format) {
case "G":
case "GG":
case "GGG": return date.toLocaleString(locale, { era: "short" });
case "GGGG": return date.toLocaleString(locale, { era: "long" });
case "GGGGG": return date.toLocaleString(locale, { era: "narrow" });
case "y":
case "Y": return date.getFullYear();
case "yo":
case "Yo": return ordinal(date.toLocaleString(locale, { year: "numeric" }));
case "yy":
case "YY": return date.toLocaleString(locale, { year: "2-digit" });
case "yyy":
case "YYY": return date.toLocaleString(locale, { year: "numeric" }).padStart(3, "0");
case "yyyy":
case "YYYY": return date.toLocaleString(locale, { year: "numeric" }).padStart(4, "0");
case "Q":
case "QQQQQ": return Math.ceil((date.getMonth() + 1) / 3);
case "Qo": return ordinal(Math.ceil((date.getMonth() + 1) / 3));
case "QQ": return pad(Math.ceil((date.getMonth() + 1) / 3), 2);
case "QQQ": return `Q${Math.ceil((date.getMonth() + 1) / 3)}`;
case "QQQQ": return `${ordinal(String(Math.ceil((date.getMonth() + 1) / 3)))} quarter`;
case "M": return date.getMonth() + 1;
case "Mo": return ordinal(date.getMonth() + 1);
case "MM": return date.toLocaleString(locale, { month: "2-digit" });
case "MMM": return date.toLocaleString(locale, { month: "short" });
case "MMMM": return date.toLocaleString(locale, { month: "long" });
case "MMMMM": return date.toLocaleString(locale, { month: "narrow" });
case "w": return Math.ceil(date.getDate() / 7);
case "wo": return ordinal(Math.ceil(date.getDate() / 7));
case "ww": return pad(Math.ceil(date.getDate() / 7), 2);
case "d":
case "D": return date.getDate();
case "do":
case "Do": return ordinal(date.getDate());
case "dd":
case "DD": return date.toLocaleString(locale, { day: "2-digit" });
case "DDD": return pad(date.getDate(), 3);
case "E":
case "EE":
case "EEE": return date.toLocaleString(locale, { weekday: "short" });
case "EEEE": return date.toLocaleString(locale, { weekday: "long" });
case "EEEEE": return date.toLocaleString(locale, { weekday: "narrow" });
case "EEEEEE": return date.toLocaleString(locale, { weekday: "short" }).slice(0, 2);
case "h": return date.toLocaleString(locale, {
hour: "numeric",
hour12: true
});
case "ho": return ordinal(date.toLocaleString(locale, {
hour: "2-digit",
hour12: true
}));
case "hh": return date.toLocaleString(locale, {
hour: "2-digit",
hour12: true
});
case "H": return date.toLocaleString(locale, {
hour: "numeric",
hour12: false
});
case "Ho": return ordinal(+date.toLocaleString(locale, {
hour: "numeric",
hour12: false
}));
case "HH": return date.toLocaleString(locale, {
hour: "2-digit",
hour12: false
});
case "m": return date.toLocaleString(locale, { minute: "numeric" });
case "mo": return ordinal(date.toLocaleString(locale, { minute: "numeric" }));
case "mm": return date.toLocaleString(locale, { minute: "2-digit" });
case "s": return date.toLocaleString(locale, { second: "numeric" });
case "so": return ordinal(date.toLocaleString(locale, { second: "numeric" }));
case "ss": return date.toLocaleString(locale, { second: "2-digit" });
case "T": return date.getTime();
case "a":
case "aa":
case "aaa": return date.toLocaleString(locale, {
hour: "numeric",
hour12: true
}).toLocaleUpperCase();
case "aaaa": return date.toLocaleString(locale, {
hour: "numeric",
hour12: true
}).toLocaleLowerCase();
case "aaaaa": return date.toLocaleString(locale, {
hour: "numeric",
hour12: true
}).charAt(0);
case "z":
case "zz":
case "zzz": return zone(date.toLocaleString(locale, {
timeZone,
timeZoneName: "shortOffset"
}));
case "zzzz": return zone(date.toLocaleString(locale, {
timeZone,
timeZoneName: "longOffset"
}));
default: throw new Error(`Unknown format: ${format}`);
}
}
function formatDate(date, format, locale, timeZone) {
let result = format;
for (const key of FORMATS) {
const res = getFormat(date, {
locale,
format: key,
timeZone
});
result = result.replace(createRegEx(key), "$1" + res + "$3");
}
return result;
}
//#endregion
//#region src/shared/i18n-utils/format-list.ts
const getListFormatter = i18nCache(Intl.ListFormat);
function formatList(list, locale, options = {}) {
return getListFormatter(locale, options).format(list);
}
//#endregion
//#region src/shared/i18n-utils/format-relative-time.ts
const getRelativeTimeFormatter = i18nCache(Intl.RelativeTimeFormat);
function formatRelativeTime(value, locale, options = {}) {
const rtf = getRelativeTimeFormatter(locale, options);
const diff = getDistance(/* @__PURE__ */ new Date(), value);
if (diff.years > 0) return rtf.format(diff.years * diff.sign, "year");
if (diff.months > 0) return rtf.format(diff.months * diff.sign, "month");
if (diff.weeks > 0) return rtf.format(diff.weeks * diff.sign, "week");
if (diff.days > 0) return rtf.format(diff.days * diff.sign, "day");
if (diff.hours > 0) return rtf.format(diff.hours * diff.sign, "hour");
if (diff.minutes > 0) return rtf.format(diff.minutes * diff.sign, "minute");
return rtf.format(diff.seconds * diff.sign, "second");
}
const SECOND_TO_MS = 1e3;
const MINUTE_TO_MS = 1e3 * 60;
const HOUR_TO_MS = 1e3 * 60 * 60;
const DAY_TO_MS = 1e3 * 60 * 60 * 24;
const WEEK_TO_MS = 1e3 * 60 * 60 * 24 * 7;
const MONTH_TO_MS = 1e3 * 60 * 60 * 24 * 30;
const YEAR_TO_MS = 1e3 * 60 * 60 * 24 * 365;
function getDistance(startDate, endDate) {
const endTime = endDate.getTime();
const startTime = startDate.getTime();
const distance = Math.abs(endTime - startTime);
return {
sign: Math.sign(endTime - startTime),
days: Math.floor(distance / DAY_TO_MS),
hours: Math.floor(distance % DAY_TO_MS / HOUR_TO_MS),
minutes: Math.floor(distance % HOUR_TO_MS / MINUTE_TO_MS),
seconds: Math.floor(distance % MINUTE_TO_MS / SECOND_TO_MS),
weeks: Math.floor(distance / WEEK_TO_MS),
months: Math.floor(distance / MONTH_TO_MS),
years: Math.floor(distance / YEAR_TO_MS)
};
}
//#endregion
//#region src/shared/i18n-utils/format-time.ts
const getTimeFormatter = i18nCache(Intl.DateTimeFormat);
function splitTimeString(timeString) {
const [hours = null, minutes = null, seconds = null] = timeString.split(":");
const parsedHours = hours === null ? null : Number(hours);
const parsedMinutes = minutes === null ? null : Number(minutes);
const parsedSeconds = seconds === null ? null : Number(seconds);
return {
hours: Number.isNaN(parsedHours) ? null : parsedHours,
minutes: Number.isNaN(parsedMinutes) ? null : parsedMinutes,
seconds: Number.isNaN(parsedSeconds) ? null : parsedSeconds
};
}
function getTimeParts(value) {
if (value instanceof Date) {
if (Number.isNaN(value.getTime())) return null;
return {
date: value,
hours: value.getHours(),
minutes: value.getMinutes(),
seconds: value.getSeconds()
};
}
const { hours, minutes, seconds } = splitTimeString(value);
if (hours === null || minutes === null) return null;
if (hours < 0 || hours > 23 || minutes < 0 || minutes > 59) return null;
if (seconds !== null && (seconds < 0 || seconds > 59)) return null;
const date = /* @__PURE__ */ new Date(0);
date.setHours(hours, minutes, seconds ?? 0, 0);
return {
date,
hours,
minutes,
seconds: seconds ?? 0
};
}
function formatTime(value, locale, options = {}) {
const { format = "24h", amLabel, pmLabel, withSeconds = false } = options;
const parts = getTimeParts(value);
if (!parts) return null;
const formatter = getTimeFormatter(locale, {
hour: format === "24h" ? "2-digit" : "numeric",
minute: "2-digit",
second: withSeconds ? "2-digit" : void 0,
hour12: format === "12h"
});
if (format !== "12h") return formatter.format(parts.date);
const isPm = parts.hours >= 12;
return formatter.formatToParts(parts.date).map((token) => {
if (token.type !== "dayPeriod") return token.value;
if (isPm) return pmLabel ?? token.value;
return amLabel ?? token.value;
}).join("");
}
//#endregion
//#region src/shared/i18n-utils/is-rtl.ts
const RTL_SCRIPTS = new Set([
"Avst",
"Arab",
"Armi",
"Syrc",
"Samr",
"Mand",
"Thaa",
"Mend",
"Nkoo",
"Adlm",
"Rohg",
"Hebr"
]);
const RTL_LANGS = new Set([
"ae",
"ar",
"arc",
"bcc",
"bqi",
"ckb",
"dv",
"fa",
"glk",
"he",
"ku",
"mzn",
"nqo",
"pnb",
"ps",
"sd",
"ug",
"ur",
"yi"
]);
function isRTL(locale) {
if (Intl.Locale) {
const script = new Intl.Locale(locale).maximize().script ?? "";
return RTL_SCRIPTS.has(script);
}
const lang = locale.split("-")[0];
return RTL_LANGS.has(lang);
}
function getLocaleDir(locale) {
return isRTL(locale) ? "rtl" : "ltr";
}
//#endregion
//#region src/shared/i18n-utils/locale.ts
function getDefaultLocale() {
let locale = typeof navigator !== "undefined" && (navigator.language || navigator.userLanguage) || "en-US";
try {
Intl.DateTimeFormat.supportedLocalesOf([locale]);
} catch {
locale = "en-US";
}
return {
locale,
dir: isRTL(locale) ? "rtl" : "ltr"
};
}
//#endregion
//#region src/shared/i18n-utils/track-locale.ts
function trackLocale(options = {}) {
const { getRootNode, onLocaleChange } = options;
onLocaleChange?.(getDefaultLocale());
const handleLocaleChange = () => {
onLocaleChange?.(getDefaultLocale());
};
const win = getRootNode ? require_dom_query.getWindow(getRootNode()) : window;
win.addEventListener("languagechange", handleLocaleChange);
return () => {
win.removeEventListener("languagechange", handleLocaleChange);
};
}
//#endregion
exports.createCollator = createCollator;
exports.createFilter = createFilter;
exports.formatBytes = formatBytes;
exports.formatDate = formatDate;
exports.formatList = formatList;
exports.formatNumber = formatNumber;
exports.formatRelativeTime = formatRelativeTime;
exports.formatTime = formatTime;
exports.getDefaultLocale = getDefaultLocale;
exports.getLocaleDir = getLocaleDir;
exports.isRTL = isRTL;
exports.trackLocale = trackLocale;
//#region src/shared/i18n-utils/collator.d.ts
declare function createCollator(locale?: string, options?: Intl.CollatorOptions): Intl.Collator;
//#endregion
//#region src/shared/i18n-utils/filter.d.ts
interface FilterReturn {
startsWith(string: string, substring: string): boolean;
endsWith(string: string, substring: string): boolean;
contains(string: string, substring: string): boolean;
}
interface FilterOptions extends Intl.CollatorOptions {
locale?: string | undefined;
}
declare function createFilter(options?: FilterOptions): FilterReturn;
//#endregion
//#region src/shared/i18n-utils/format-bytes.d.ts
interface FormatBytesOptions {
precision?: number | undefined;
unitSystem?: "binary" | "decimal" | undefined;
unit?: "bit" | "byte" | undefined;
unitDisplay?: "long" | "short" | "narrow" | undefined;
}
declare const formatBytes: (bytes: number, locale?: string, options?: FormatBytesOptions) => string;
//#endregion
//#region src/shared/i18n-utils/format-date.d.ts
declare function formatDate(date: Date, format: string, locale: string, timeZone?: string): string;
//#endregion
//#region src/shared/i18n-utils/format-list.d.ts
declare function formatList(list: string[], locale: string, options?: Intl.ListFormatOptions): string;
//#endregion
//#region src/shared/i18n-utils/format-number.d.ts
declare function formatNumber(v: number, locale: string, options?: Intl.NumberFormatOptions): string;
//#endregion
//#region src/shared/i18n-utils/format-relative-time.d.ts
declare function formatRelativeTime(value: Date, locale: string, options?: Intl.RelativeTimeFormatOptions): string;
//#endregion
//#region src/shared/i18n-utils/format-time.d.ts
type TimeFormat = "12h" | "24h";
interface FormatTimeOptions {
format?: TimeFormat;
amLabel?: string;
pmLabel?: string;
withSeconds?: boolean;
}
declare function formatTime(value: string | Date, locale: string, options?: FormatTimeOptions): string | null;
//#endregion
//#region src/shared/i18n-utils/is-rtl.d.ts
declare function isRTL(locale: string): boolean;
declare function getLocaleDir(locale: string): "ltr" | "rtl";
//#endregion
//#region src/shared/i18n-utils/locale.d.ts
type Direction = "rtl" | "ltr";
interface Locale {
locale: string;
dir: Direction;
}
declare global {
interface Navigator {
userLanguage?: string | undefined;
}
}
declare function getDefaultLocale(): Locale;
//#endregion
//#region src/shared/i18n-utils/track-locale.d.ts
interface LocaleOptions {
locale?: string | undefined;
getRootNode?: (() => ShadowRoot | Document | Node) | undefined;
onLocaleChange?: ((locale: Locale) => void) | undefined;
}
declare function trackLocale(options?: LocaleOptions): () => void;
//#endregion
export { FilterOptions, FilterReturn, FormatBytesOptions, FormatTimeOptions, type Locale, type LocaleOptions, TimeFormat, createCollator, createFilter, formatBytes, formatDate, formatList, formatNumber, formatRelativeTime, formatTime, getDefaultLocale, getLocaleDir, isRTL, trackLocale };
//#region src/shared/i18n-utils/collator.d.ts
declare function createCollator(locale?: string, options?: Intl.CollatorOptions): Intl.Collator;
//#endregion
//#region src/shared/i18n-utils/filter.d.ts
interface FilterReturn {
startsWith(string: string, substring: string): boolean;
endsWith(string: string, substring: string): boolean;
contains(string: string, substring: string): boolean;
}
interface FilterOptions extends Intl.CollatorOptions {
locale?: string | undefined;
}
declare function createFilter(options?: FilterOptions): FilterReturn;
//#endregion
//#region src/shared/i18n-utils/format-bytes.d.ts
interface FormatBytesOptions {
precision?: number | undefined;
unitSystem?: "binary" | "decimal" | undefined;
unit?: "bit" | "byte" | undefined;
unitDisplay?: "long" | "short" | "narrow" | undefined;
}
declare const formatBytes: (bytes: number, locale?: string, options?: FormatBytesOptions) => string;
//#endregion
//#region src/shared/i18n-utils/format-date.d.ts
declare function formatDate(date: Date, format: string, locale: string, timeZone?: string): string;
//#endregion
//#region src/shared/i18n-utils/format-list.d.ts
declare function formatList(list: string[], locale: string, options?: Intl.ListFormatOptions): string;
//#endregion
//#region src/shared/i18n-utils/format-number.d.ts
declare function formatNumber(v: number, locale: string, options?: Intl.NumberFormatOptions): string;
//#endregion
//#region src/shared/i18n-utils/format-relative-time.d.ts
declare function formatRelativeTime(value: Date, locale: string, options?: Intl.RelativeTimeFormatOptions): string;
//#endregion
//#region src/shared/i18n-utils/format-time.d.ts
type TimeFormat = "12h" | "24h";
interface FormatTimeOptions {
format?: TimeFormat;
amLabel?: string;
pmLabel?: string;
withSeconds?: boolean;
}
declare function formatTime(value: string | Date, locale: string, options?: FormatTimeOptions): string | null;
//#endregion
//#region src/shared/i18n-utils/is-rtl.d.ts
declare function isRTL(locale: string): boolean;
declare function getLocaleDir(locale: string): "ltr" | "rtl";
//#endregion
//#region src/shared/i18n-utils/locale.d.ts
type Direction = "rtl" | "ltr";
interface Locale {
locale: string;
dir: Direction;
}
declare global {
interface Navigator {
userLanguage?: string | undefined;
}
}
declare function getDefaultLocale(): Locale;
//#endregion
//#region src/shared/i18n-utils/track-locale.d.ts
interface LocaleOptions {
locale?: string | undefined;
getRootNode?: (() => ShadowRoot | Document | Node) | undefined;
onLocaleChange?: ((locale: Locale) => void) | undefined;
}
declare function trackLocale(options?: LocaleOptions): () => void;
//#endregion
export { FilterOptions, FilterReturn, FormatBytesOptions, FormatTimeOptions, type Locale, type LocaleOptions, TimeFormat, createCollator, createFilter, formatBytes, formatDate, formatList, formatNumber, formatRelativeTime, formatTime, getDefaultLocale, getLocaleDir, isRTL, trackLocale };
import { ln as getWindow } from "./dom-query-BgxIO7_X.mjs";
//#region src/shared/i18n-utils/cache.ts
function i18nCache(Ins) {
const formatterCache = /* @__PURE__ */ new Map();
return function create(locale, options) {
const cacheKey = locale + (options ? Object.entries(options).sort((a, b) => a[0] < b[0] ? -1 : 1).join() : "");
if (formatterCache.has(cacheKey)) return formatterCache.get(cacheKey);
let formatter = new Ins(locale, options);
formatterCache.set(cacheKey, formatter);
return formatter;
};
}
//#endregion
//#region src/shared/i18n-utils/collator.ts
const getCollator = i18nCache(Intl.Collator);
function createCollator(locale = "en-US", options = {}) {
return getCollator(locale, options);
}
//#endregion
//#region src/shared/i18n-utils/filter.ts
const collatorCache = i18nCache(Intl.Collator);
function createFilter(options) {
const { locale, ...rest } = options || {};
const collator = collatorCache(locale || "en-US", {
usage: "search",
...rest
});
function normalize(string) {
string = string.normalize("NFC");
if (collator.resolvedOptions().ignorePunctuation) string = string.replace(/\p{P}/gu, "");
return string;
}
function startsWith(string, substring) {
if (substring.length === 0) return true;
string = normalize(string);
substring = normalize(substring);
return collator.compare(string.slice(0, substring.length), substring) === 0;
}
function endsWith(string, substring) {
if (substring.length === 0) return true;
string = normalize(string);
substring = normalize(substring);
return collator.compare(string.slice(-substring.length), substring) === 0;
}
function contains(string, substring) {
if (substring.length === 0) return true;
string = normalize(string);
substring = normalize(substring);
let scan = 0;
let sliceLen = substring.length;
for (; scan + sliceLen <= string.length; scan++) {
let slice = string.slice(scan, scan + sliceLen);
if (collator.compare(substring, slice) === 0) return true;
}
return false;
}
return {
startsWith,
endsWith,
contains
};
}
//#endregion
//#region src/shared/i18n-utils/format-number.ts
const getNumberFormatter = i18nCache(Intl.NumberFormat);
function formatNumber(v, locale, options = {}) {
return getNumberFormatter(locale, options).format(v);
}
//#endregion
//#region src/shared/i18n-utils/format-bytes.ts
const bitPrefixes = [
"",
"kilo",
"mega",
"giga",
"tera"
];
const bytePrefixes = [
"",
"kilo",
"mega",
"giga",
"tera",
"peta"
];
const formatBytes = (bytes, locale = "en-US", options = {}) => {
if (Number.isNaN(bytes)) return "";
if (bytes === 0) return "0 B";
const { unitSystem = "decimal", precision = 3, unit = "byte", unitDisplay = "short" } = options;
const factor = unitSystem === "binary" ? 1024 : 1e3;
const prefix = unit === "bit" ? bitPrefixes : bytePrefixes;
const isNegative = bytes < 0;
let value = Math.abs(bytes);
let index = 0;
while (value >= factor && index < prefix.length - 1) {
value /= factor;
index++;
}
const v = parseFloat(value.toPrecision(precision));
return formatNumber(isNegative ? -v : v, locale, {
style: "unit",
unit: prefix[index] + unit,
unitDisplay
});
};
//#endregion
//#region src/shared/i18n-utils/format-date.ts
const symbols = "\\s|\\.|-|/|\\\\|,|\\$|\\!|\\?|:|;";
function createRegEx(sign) {
return new RegExp("(^|>|" + symbols + ")(" + sign + ")($|<|\\s|\\.|-|/|\\\\|,|\\$|\\!|\\?|:|;)", "g");
}
const FORMATS = [
"G",
"GG",
"GGG",
"GGGG",
"GGGGG",
"y",
"yo",
"yy",
"yyy",
"yyyy",
"Y",
"Yo",
"YY",
"YYY",
"YYYY",
"Q",
"Qo",
"QQ",
"QQQ",
"QQQQ",
"QQQQQ",
"M",
"Mo",
"MM",
"MMM",
"MMMM",
"MMMMM",
"E",
"EE",
"EEE",
"EEEE",
"EEEEE",
"EEEEEE",
"a",
"aa",
"aaa",
"aaaa",
"aaaaa",
"d",
"do",
"dd",
"D",
"Do",
"DD",
"DDD",
"w",
"wo",
"ww",
"s",
"so",
"ss",
"m",
"mo",
"mm",
"h",
"ho",
"hh",
"H",
"Ho",
"HH",
"z",
"zz",
"zzz",
"zzzz",
"T"
];
function ordinal(num) {
const n = typeof num === "string" ? parseFloat(num) : num;
let suffix = "th";
if (n % 10 === 1 && n % 100 !== 11) suffix = "st";
else if (n % 10 === 2 && n % 100 !== 12) suffix = "nd";
else if (n % 10 === 3 && n % 100 !== 13) suffix = "rd";
return `${n}${suffix}`;
}
function pad(num, length) {
return String(num).padStart(length, "0");
}
function zone(str) {
return str.split(/AM|PM/)[1].trim();
}
function getFormat(date, options) {
const { locale, format, timeZone } = options;
switch (format) {
case "G":
case "GG":
case "GGG": return date.toLocaleString(locale, { era: "short" });
case "GGGG": return date.toLocaleString(locale, { era: "long" });
case "GGGGG": return date.toLocaleString(locale, { era: "narrow" });
case "y":
case "Y": return date.getFullYear();
case "yo":
case "Yo": return ordinal(date.toLocaleString(locale, { year: "numeric" }));
case "yy":
case "YY": return date.toLocaleString(locale, { year: "2-digit" });
case "yyy":
case "YYY": return date.toLocaleString(locale, { year: "numeric" }).padStart(3, "0");
case "yyyy":
case "YYYY": return date.toLocaleString(locale, { year: "numeric" }).padStart(4, "0");
case "Q":
case "QQQQQ": return Math.ceil((date.getMonth() + 1) / 3);
case "Qo": return ordinal(Math.ceil((date.getMonth() + 1) / 3));
case "QQ": return pad(Math.ceil((date.getMonth() + 1) / 3), 2);
case "QQQ": return `Q${Math.ceil((date.getMonth() + 1) / 3)}`;
case "QQQQ": return `${ordinal(String(Math.ceil((date.getMonth() + 1) / 3)))} quarter`;
case "M": return date.getMonth() + 1;
case "Mo": return ordinal(date.getMonth() + 1);
case "MM": return date.toLocaleString(locale, { month: "2-digit" });
case "MMM": return date.toLocaleString(locale, { month: "short" });
case "MMMM": return date.toLocaleString(locale, { month: "long" });
case "MMMMM": return date.toLocaleString(locale, { month: "narrow" });
case "w": return Math.ceil(date.getDate() / 7);
case "wo": return ordinal(Math.ceil(date.getDate() / 7));
case "ww": return pad(Math.ceil(date.getDate() / 7), 2);
case "d":
case "D": return date.getDate();
case "do":
case "Do": return ordinal(date.getDate());
case "dd":
case "DD": return date.toLocaleString(locale, { day: "2-digit" });
case "DDD": return pad(date.getDate(), 3);
case "E":
case "EE":
case "EEE": return date.toLocaleString(locale, { weekday: "short" });
case "EEEE": return date.toLocaleString(locale, { weekday: "long" });
case "EEEEE": return date.toLocaleString(locale, { weekday: "narrow" });
case "EEEEEE": return date.toLocaleString(locale, { weekday: "short" }).slice(0, 2);
case "h": return date.toLocaleString(locale, {
hour: "numeric",
hour12: true
});
case "ho": return ordinal(date.toLocaleString(locale, {
hour: "2-digit",
hour12: true
}));
case "hh": return date.toLocaleString(locale, {
hour: "2-digit",
hour12: true
});
case "H": return date.toLocaleString(locale, {
hour: "numeric",
hour12: false
});
case "Ho": return ordinal(+date.toLocaleString(locale, {
hour: "numeric",
hour12: false
}));
case "HH": return date.toLocaleString(locale, {
hour: "2-digit",
hour12: false
});
case "m": return date.toLocaleString(locale, { minute: "numeric" });
case "mo": return ordinal(date.toLocaleString(locale, { minute: "numeric" }));
case "mm": return date.toLocaleString(locale, { minute: "2-digit" });
case "s": return date.toLocaleString(locale, { second: "numeric" });
case "so": return ordinal(date.toLocaleString(locale, { second: "numeric" }));
case "ss": return date.toLocaleString(locale, { second: "2-digit" });
case "T": return date.getTime();
case "a":
case "aa":
case "aaa": return date.toLocaleString(locale, {
hour: "numeric",
hour12: true
}).toLocaleUpperCase();
case "aaaa": return date.toLocaleString(locale, {
hour: "numeric",
hour12: true
}).toLocaleLowerCase();
case "aaaaa": return date.toLocaleString(locale, {
hour: "numeric",
hour12: true
}).charAt(0);
case "z":
case "zz":
case "zzz": return zone(date.toLocaleString(locale, {
timeZone,
timeZoneName: "shortOffset"
}));
case "zzzz": return zone(date.toLocaleString(locale, {
timeZone,
timeZoneName: "longOffset"
}));
default: throw new Error(`Unknown format: ${format}`);
}
}
function formatDate(date, format, locale, timeZone) {
let result = format;
for (const key of FORMATS) {
const res = getFormat(date, {
locale,
format: key,
timeZone
});
result = result.replace(createRegEx(key), "$1" + res + "$3");
}
return result;
}
//#endregion
//#region src/shared/i18n-utils/format-list.ts
const getListFormatter = i18nCache(Intl.ListFormat);
function formatList(list, locale, options = {}) {
return getListFormatter(locale, options).format(list);
}
//#endregion
//#region src/shared/i18n-utils/format-relative-time.ts
const getRelativeTimeFormatter = i18nCache(Intl.RelativeTimeFormat);
function formatRelativeTime(value, locale, options = {}) {
const rtf = getRelativeTimeFormatter(locale, options);
const diff = getDistance(/* @__PURE__ */ new Date(), value);
if (diff.years > 0) return rtf.format(diff.years * diff.sign, "year");
if (diff.months > 0) return rtf.format(diff.months * diff.sign, "month");
if (diff.weeks > 0) return rtf.format(diff.weeks * diff.sign, "week");
if (diff.days > 0) return rtf.format(diff.days * diff.sign, "day");
if (diff.hours > 0) return rtf.format(diff.hours * diff.sign, "hour");
if (diff.minutes > 0) return rtf.format(diff.minutes * diff.sign, "minute");
return rtf.format(diff.seconds * diff.sign, "second");
}
const SECOND_TO_MS = 1e3;
const MINUTE_TO_MS = 1e3 * 60;
const HOUR_TO_MS = 1e3 * 60 * 60;
const DAY_TO_MS = 1e3 * 60 * 60 * 24;
const WEEK_TO_MS = 1e3 * 60 * 60 * 24 * 7;
const MONTH_TO_MS = 1e3 * 60 * 60 * 24 * 30;
const YEAR_TO_MS = 1e3 * 60 * 60 * 24 * 365;
function getDistance(startDate, endDate) {
const endTime = endDate.getTime();
const startTime = startDate.getTime();
const distance = Math.abs(endTime - startTime);
return {
sign: Math.sign(endTime - startTime),
days: Math.floor(distance / DAY_TO_MS),
hours: Math.floor(distance % DAY_TO_MS / HOUR_TO_MS),
minutes: Math.floor(distance % HOUR_TO_MS / MINUTE_TO_MS),
seconds: Math.floor(distance % MINUTE_TO_MS / SECOND_TO_MS),
weeks: Math.floor(distance / WEEK_TO_MS),
months: Math.floor(distance / MONTH_TO_MS),
years: Math.floor(distance / YEAR_TO_MS)
};
}
//#endregion
//#region src/shared/i18n-utils/format-time.ts
const getTimeFormatter = i18nCache(Intl.DateTimeFormat);
function splitTimeString(timeString) {
const [hours = null, minutes = null, seconds = null] = timeString.split(":");
const parsedHours = hours === null ? null : Number(hours);
const parsedMinutes = minutes === null ? null : Number(minutes);
const parsedSeconds = seconds === null ? null : Number(seconds);
return {
hours: Number.isNaN(parsedHours) ? null : parsedHours,
minutes: Number.isNaN(parsedMinutes) ? null : parsedMinutes,
seconds: Number.isNaN(parsedSeconds) ? null : parsedSeconds
};
}
function getTimeParts(value) {
if (value instanceof Date) {
if (Number.isNaN(value.getTime())) return null;
return {
date: value,
hours: value.getHours(),
minutes: value.getMinutes(),
seconds: value.getSeconds()
};
}
const { hours, minutes, seconds } = splitTimeString(value);
if (hours === null || minutes === null) return null;
if (hours < 0 || hours > 23 || minutes < 0 || minutes > 59) return null;
if (seconds !== null && (seconds < 0 || seconds > 59)) return null;
const date = /* @__PURE__ */ new Date(0);
date.setHours(hours, minutes, seconds ?? 0, 0);
return {
date,
hours,
minutes,
seconds: seconds ?? 0
};
}
function formatTime(value, locale, options = {}) {
const { format = "24h", amLabel, pmLabel, withSeconds = false } = options;
const parts = getTimeParts(value);
if (!parts) return null;
const formatter = getTimeFormatter(locale, {
hour: format === "24h" ? "2-digit" : "numeric",
minute: "2-digit",
second: withSeconds ? "2-digit" : void 0,
hour12: format === "12h"
});
if (format !== "12h") return formatter.format(parts.date);
const isPm = parts.hours >= 12;
return formatter.formatToParts(parts.date).map((token) => {
if (token.type !== "dayPeriod") return token.value;
if (isPm) return pmLabel ?? token.value;
return amLabel ?? token.value;
}).join("");
}
//#endregion
//#region src/shared/i18n-utils/is-rtl.ts
const RTL_SCRIPTS = new Set([
"Avst",
"Arab",
"Armi",
"Syrc",
"Samr",
"Mand",
"Thaa",
"Mend",
"Nkoo",
"Adlm",
"Rohg",
"Hebr"
]);
const RTL_LANGS = new Set([
"ae",
"ar",
"arc",
"bcc",
"bqi",
"ckb",
"dv",
"fa",
"glk",
"he",
"ku",
"mzn",
"nqo",
"pnb",
"ps",
"sd",
"ug",
"ur",
"yi"
]);
function isRTL(locale) {
if (Intl.Locale) {
const script = new Intl.Locale(locale).maximize().script ?? "";
return RTL_SCRIPTS.has(script);
}
const lang = locale.split("-")[0];
return RTL_LANGS.has(lang);
}
function getLocaleDir(locale) {
return isRTL(locale) ? "rtl" : "ltr";
}
//#endregion
//#region src/shared/i18n-utils/locale.ts
function getDefaultLocale() {
let locale = typeof navigator !== "undefined" && (navigator.language || navigator.userLanguage) || "en-US";
try {
Intl.DateTimeFormat.supportedLocalesOf([locale]);
} catch {
locale = "en-US";
}
return {
locale,
dir: isRTL(locale) ? "rtl" : "ltr"
};
}
//#endregion
//#region src/shared/i18n-utils/track-locale.ts
function trackLocale(options = {}) {
const { getRootNode, onLocaleChange } = options;
onLocaleChange?.(getDefaultLocale());
const handleLocaleChange = () => {
onLocaleChange?.(getDefaultLocale());
};
const win = getRootNode ? getWindow(getRootNode()) : window;
win.addEventListener("languagechange", handleLocaleChange);
return () => {
win.removeEventListener("languagechange", handleLocaleChange);
};
}
//#endregion
export { createCollator, createFilter, formatBytes, formatDate, formatList, formatNumber, formatRelativeTime, formatTime, getDefaultLocale, getLocaleDir, isRTL, trackLocale };
import { C as JSX, c as MaybeFn, u as Nullable } from "./index-Cq2OwLf_.mjs";
//#region src/shared/dom-query/caret.d.ts
declare function isCaretAtStart(input: HTMLInputElement | HTMLTextAreaElement | null): boolean;
declare function setCaretToEnd(input: HTMLInputElement | HTMLTextAreaElement | null): void;
//#endregion
//#region src/shared/dom-query/computed-style.d.ts
declare function getComputedStyle(el: Element): CSSStyleDeclaration;
//#endregion
//#region src/shared/dom-query/controller.d.ts
interface ControlledElementOptions {
followControlledElements?: boolean | undefined;
}
declare function isControlledElement(container: HTMLElement, element: HTMLElement): boolean;
declare function findControlledElements(searchRoot: HTMLElement, callback: (controlledElement: HTMLElement) => void): void;
declare function getControlledElements(container: HTMLElement): HTMLElement[];
declare function isInteractiveContainerElement(element: Element): boolean;
declare function isControllerElement(element: Element): boolean;
declare function hasControllerElements(element: Element): boolean;
declare function isControlledByExpandedController(element: Element): boolean;
//#endregion
//#region src/shared/dom-query/data-url.d.ts
type DataUrlType = "image/png" | "image/jpeg" | "image/svg+xml";
interface DataUrlOptions {
type: DataUrlType;
quality?: number | undefined;
background?: string | undefined;
}
declare function getDataUrl(svg: SVGSVGElement | undefined | null, opts: DataUrlOptions): Promise<string>;
//#endregion
//#region src/shared/dom-query/types.d.ts
type Booleanish = boolean | "true" | "false";
interface Point {
x: number;
y: number;
}
interface EventKeyOptions {
dir?: "ltr" | "rtl" | undefined;
orientation?: "horizontal" | "vertical" | undefined;
}
type NativeEvent<E> = JSX.ChangeEvent<any> extends E ? InputEvent : E extends JSX.SyntheticEvent<any, infer T> ? T : never;
type AnyPointerEvent = MouseEvent | TouchEvent | PointerEvent;
type MaybeElement$1 = Nullable<HTMLElement>;
type MaybeElementOrFn = MaybeFn<MaybeElement$1>;
type HTMLElementWithValue = HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement;
//#endregion
//#region src/shared/dom-query/event.d.ts
declare function getBeforeInputValue(event: Pick<InputEvent, "currentTarget">): string;
declare function getEventTarget<T extends EventTarget>(event: Partial<Pick<UIEvent, "target" | "composedPath">>): T | null;
declare function isOpeningInNewTab(event: Pick<MouseEvent, "currentTarget" | "metaKey" | "ctrlKey" | "button">): boolean;
declare function isDownloadingEvent(event: Pick<MouseEvent, "altKey" | "currentTarget">): boolean;
declare function isComposingEvent(event: any): boolean;
declare function isKeyboardClick(e: Pick<MouseEvent, "detail" | "clientX" | "clientY">): boolean;
declare function isCtrlOrMetaKey(e: Pick<KeyboardEvent, "ctrlKey" | "metaKey">): boolean;
declare function isPrintableKey(e: Pick<KeyboardEvent, "key" | "ctrlKey" | "metaKey">): boolean;
declare function isVirtualPointerEvent(e: PointerEvent): boolean;
declare function isVirtualClick(e: MouseEvent | PointerEvent): boolean;
declare const isLeftClick: (e: Pick<MouseEvent, "button">) => boolean;
declare const isContextMenuEvent: (e: Pick<MouseEvent, "button" | "ctrlKey" | "metaKey">) => boolean;
declare const isModifierKey: (e: Pick<KeyboardEvent, "ctrlKey" | "metaKey" | "altKey">) => boolean;
declare const isTouchEvent: (event: AnyPointerEvent) => event is TouchEvent;
declare function getEventKey(event: Pick<KeyboardEvent, "key">, options?: EventKeyOptions): string;
declare function getNativeEvent<E>(event: E): NativeEvent<E>;
declare function getEventStep(event: Pick<KeyboardEvent, "ctrlKey" | "metaKey" | "key" | "shiftKey">): 1 | 0.1 | 10;
declare function getEventPoint(event: any, type?: "page" | "client"): {
x: number;
y: number;
};
interface DOMEventMap extends DocumentEventMap, WindowEventMap, HTMLElementEventMap {}
declare const addDomEvent: <K extends keyof DOMEventMap>(target: MaybeFn<EventTarget | null>, eventName: K | (string & {}), handler: (event: DOMEventMap[K]) => void, options?: boolean | AddEventListenerOptions) => () => void;
declare const isSelfTarget: (event: Partial<Pick<UIEvent, "currentTarget" | "target" | "composedPath">>) => boolean;
//#endregion
//#region src/shared/dom-query/form.d.ts
declare function setElementValue(el: HTMLElementWithValue | null, value: string, property?: "value" | "checked"): void;
declare function setElementChecked(el: HTMLInputElement | null, checked: boolean): void;
interface InputValueEventOptions {
value: string | number;
bubbles?: boolean | undefined;
}
declare function dispatchInputValueEvent(el: HTMLElementWithValue | null, options: InputValueEventOptions): void;
interface CheckedEventOptions {
checked: boolean;
bubbles?: boolean | undefined;
}
declare function dispatchInputCheckedEvent(el: HTMLInputElement | null, options: CheckedEventOptions): void;
interface TrackFormControlOptions {
onFieldsetDisabledChange: (disabled: boolean) => void;
onFormReset: VoidFunction;
}
declare function trackFormControl(el: HTMLElement | null, options: TrackFormControlOptions): (() => void) | undefined;
declare const INTERNAL_CHANGE_EVENT: unique symbol;
type InternalChangeEventProps = {
[INTERNAL_CHANGE_EVENT]?: boolean;
};
declare function isInternalChangeEvent<T extends Event>(e: T): e is T & InternalChangeEventProps;
declare function markAsInternalChangeEvent<T extends Event>(event: T): T & InternalChangeEventProps;
//#endregion
//#region src/shared/dom-query/initial-focus.d.ts
interface InitialFocusOptions {
root: HTMLElement | null;
getInitialEl?: (() => HTMLElement | null) | undefined;
enabled?: boolean | undefined;
filter?: ((el: HTMLElement) => boolean) | undefined;
}
declare function getInitialFocus(options: InitialFocusOptions): HTMLElement | undefined;
declare function isValidTabEvent(event: Pick<KeyboardEvent, "shiftKey" | "currentTarget">): boolean;
//#endregion
//#region src/shared/dom-query/mutation-observer.d.ts
interface ObserveAttributeOptions {
attributes: string[];
callback(record: MutationRecord): void;
defer?: boolean | undefined;
}
declare function observeAttributes(nodeOrFn: MaybeElementOrFn, options: ObserveAttributeOptions): () => void;
interface ObserveChildrenOptions {
callback: MutationCallback;
defer?: boolean | undefined;
}
declare function observeChildren(nodeOrFn: MaybeElementOrFn, options: ObserveChildrenOptions): () => void;
//#endregion
//#region src/shared/dom-query/navigate.d.ts
interface NavigateOptions {
key?: string;
orientation?: "both" | "vertical" | "horizontal";
loop?: boolean;
dir?: "ltr" | "rtl";
}
declare function navigate<T extends HTMLElement>(items: T[], current: T | null, options?: NavigateOptions): T | null;
declare function clickIfLink(el: HTMLAnchorElement): void;
//#endregion
//#region src/shared/dom-query/node.d.ts
declare const isElement: (el: any) => el is Element;
declare const isHTMLElement: (el: any) => el is HTMLElement;
declare const isDocument: (el: any) => el is Document;
declare const isWindow: (el: any) => el is Window;
declare const isVisualViewport: (el: any) => el is VisualViewport;
declare const getNodeName: (node: Node | Window) => string;
declare function isRootElement(node: Node): boolean;
declare const isNode: (el: any) => el is Node;
declare const isShadowRoot: (el: any) => el is ShadowRoot;
declare const isInputElement: (el: any) => el is HTMLInputElement;
declare const isAnchorElement: (el: HTMLElement | null | undefined) => el is HTMLAnchorElement;
declare const isElementVisible: (el: Node) => boolean;
declare function isActiveElement(element: Element | null | undefined): boolean;
declare function isEditableElement(el: HTMLElement | EventTarget | null): boolean;
type Target = HTMLElement | EventTarget | null | undefined;
/** Whether `parent` contains `child` in the light tree, or `child` is inside a shadow tree hosted under `parent`. */
declare function getParentElement(node: Element): Element | null;
declare function getAncestorElements(node: Element | null): Element[];
declare function contains(parent: Target, child: Target): boolean;
declare function getDocument(el: Element | Window | Node | Document | null | undefined): Document;
declare function getDocumentElement(el: Element | Node | Window | Document | null | undefined): HTMLElement;
declare function getWindow(el: Node | ShadowRoot | Document | null | undefined): Window & typeof globalThis;
declare function getActiveElement(rootNode: Document | ShadowRoot): HTMLElement | null;
declare function getParentNode(node: Node): Node;
declare function getRootNode(node: Node): Document | ShadowRoot;
//#endregion
//#region src/shared/dom-query/overflow.d.ts
type OverflowAncestor = Array<VisualViewport | Window | HTMLElement | null>;
declare function getNearestOverflowAncestor(el: Node): HTMLElement;
declare function getOverflowAncestors(el: HTMLElement, list?: OverflowAncestor): OverflowAncestor;
declare function isInView(el: HTMLElement | Window | VisualViewport, ancestor: HTMLElement | Window | VisualViewport): boolean;
declare function isOverflowElement(el: HTMLElement): boolean;
interface ScrollOptions extends ScrollIntoViewOptions {
rootEl: HTMLElement | null;
}
declare function scrollIntoView(el: HTMLElement | null | undefined, options?: ScrollOptions): void;
interface ScrollPosition {
scrollLeft: number;
scrollTop: number;
}
declare function getScrollPosition(element: HTMLElement | Window): ScrollPosition;
//#endregion
//#region src/shared/dom-query/platform.d.ts
declare const isDom: () => boolean;
declare function getPlatform(): string;
declare function getUserAgent(): string;
declare const isTouchDevice: () => boolean;
declare const isIPhone: () => boolean;
declare const isIPad: () => boolean;
declare const isIos: () => boolean;
declare const isApple: () => boolean;
declare const isMac: () => boolean;
declare const isSafari: () => boolean;
declare const isFirefox: () => boolean;
declare const isChrome: () => boolean;
declare const isWebKit: () => boolean;
declare const isAndroid: () => boolean;
//#endregion
//#region src/shared/dom-query/point.d.ts
interface PercentValueOptions {
inverted?: boolean | {
x?: boolean | undefined;
y?: boolean | undefined;
} | undefined;
dir?: "ltr" | "rtl" | undefined;
orientation?: "vertical" | "horizontal" | undefined;
}
declare function getRelativePoint(point: Point, element: HTMLElement): {
offset: {
x: number;
y: number;
};
percent: {
x: number;
y: number;
};
getPercentValue: (options?: PercentValueOptions) => number;
};
//#endregion
//#region src/shared/dom-query/pointer-lock.d.ts
declare function requestPointerLock(doc: Document, fn?: (locked: boolean) => void): (() => void) | undefined;
//#endregion
//#region src/shared/dom-query/pointer-move.d.ts
interface PointerMoveDetails {
point: Point;
event: PointerEvent;
}
interface PointerUpDetails {
point: Point;
event: PointerEvent;
}
interface PointerMoveHandlers {
onPointerUp: (details: PointerUpDetails) => void;
onPointerMove: (details: PointerMoveDetails) => void;
}
declare function trackPointerMove(doc: Document, handlers: PointerMoveHandlers): () => void;
//#endregion
//#region src/shared/dom-query/press.d.ts
interface PressDetails {
point: Point;
event: PointerEvent;
}
interface TrackPressOptions {
pointerNode: Element | null;
keyboardNode?: Element | null | undefined;
isValidKey?(event: KeyboardEvent): boolean;
onPress?(details: PressDetails): void;
onPressStart?(details: PressDetails): void;
onPressEnd?(details: PressDetails): void;
}
declare function trackPress(options: TrackPressOptions): () => void;
//#endregion
//#region src/shared/dom-query/tabbable.d.ts
type IncludeContainerType = boolean | "if-empty";
type GetShadowRootOption = boolean | ((node: HTMLElement) => ShadowRoot | boolean | undefined) | undefined;
interface TabbableOptions {
includeContainer?: IncludeContainerType;
getShadowRoot?: GetShadowRootOption;
}
interface NextTabbableOptions {
current?: HTMLElement | undefined | null;
getShadowRoot?: GetShadowRootOption;
}
declare const getFocusables: (container: Pick<HTMLElement, "querySelectorAll"> | null, options?: TabbableOptions) => HTMLElement[];
declare function isFocusable(element: HTMLElement | EventTarget | null): element is HTMLElement;
declare function getFirstFocusable(container: HTMLElement | null, options?: TabbableOptions): HTMLElement | null;
declare function getTabbables(container: HTMLElement | null, options?: TabbableOptions): HTMLElement[];
declare function isTabbable(el: HTMLElement | EventTarget | null): el is HTMLElement;
declare function getFirstTabbable(container: HTMLElement | null, options?: TabbableOptions): HTMLElement | null;
declare function getLastTabbable(container: HTMLElement | null, options?: TabbableOptions): HTMLElement | null;
declare function getTabbableEdges(container: HTMLElement | null, options?: TabbableOptions): [HTMLElement, HTMLElement] | [null, null];
declare function getNextTabbable(container: HTMLElement | null, options?: NextTabbableOptions): HTMLElement | null;
declare function getTabIndex(node: HTMLElement | SVGElement): number;
//#endregion
//#region src/shared/dom-query/proxy-tab-focus.d.ts
interface ProxyTabFocusOptions<T = MaybeElement$1> {
triggerElement?: T | undefined;
onFocus?: ((elementToFocus: HTMLElement) => void) | undefined;
onFocusEnter?: VoidFunction | undefined;
defer?: boolean | undefined;
getShadowRoot?: GetShadowRootOption | undefined;
}
declare function proxyTabFocus(container: MaybeElementOrFn, options: ProxyTabFocusOptions<MaybeElementOrFn>): () => void;
//#endregion
//#region src/shared/dom-query/query.d.ts
type Root = Document | Element | null | undefined;
declare function queryAll<T extends Element = HTMLElement>(root: Root, selector: string): T[];
declare function query<T extends Element = HTMLElement>(root: Root, selector: string): T | null;
type ItemToId<T> = (v: T) => string;
interface Item {
id: string;
}
declare const defaultItemToId: <T extends Item>(v: T) => string;
declare function itemById<T extends Item>(v: T[], id: string, itemToId?: ItemToId<T>): T | undefined;
declare function indexOfId<T extends Item>(v: T[], id: string, itemToId?: ItemToId<T>): number;
declare function nextById<T extends Item>(v: T[], id: string, loop?: boolean): T;
declare function prevById<T extends Item>(v: T[], id: string, loop?: boolean): T | null;
//#endregion
//#region src/shared/dom-query/raf.d.ts
declare class AnimationFrame {
static create(): AnimationFrame;
private id;
private fn_cleanup;
request(fn?: VoidFunction | (() => VoidFunction)): void;
cancel(): void;
isActive(): boolean;
cleanup: () => void;
}
declare function raf(fn: VoidFunction | (() => VoidFunction)): () => void;
declare function nextTick(fn: VoidFunction): () => void;
declare function queueBeforeEvent(el: EventTarget, type: string, cb: () => void): () => void;
//#endregion
//#region src/shared/dom-query/resize-observer.d.ts
type Subscriber<T> = (entry: T) => void;
interface SharedResizeObserver {
observe: (element: Element, listener: Subscriber<ResizeObserverEntry>) => () => void;
unobserve: (element: Element) => void;
}
declare const resizeObserverContentBox: SharedResizeObserver;
declare const resizeObserverBorderBox: SharedResizeObserver;
declare const resizeObserverDevicePixelContentBox: SharedResizeObserver;
//#endregion
//#region src/shared/dom-query/scale.d.ts
declare function getScale(element: HTMLElement): {
x: number;
y: number;
};
//#endregion
//#region src/shared/dom-query/scope.d.ts
interface ScopeContext {
getRootNode?: (() => Document | ShadowRoot | Node) | undefined;
}
declare function createScope<T>(methods: T): {
getRootNode: (ctx: ScopeContext) => Document | ShadowRoot;
getDoc: (ctx: ScopeContext) => Document;
getWin: (ctx: ScopeContext) => Window & typeof globalThis;
getActiveElement: (ctx: ScopeContext) => HTMLElement | null;
isActiveElement: typeof isActiveElement;
getById: <T_1 extends Element = HTMLElement>(ctx: ScopeContext, id: string) => T_1 | null;
setValue: <T_1 extends HTMLElementWithValue>(elem: T_1 | null, value: string | number | null | undefined) => void;
} & T;
//#endregion
//#region src/shared/dom-query/searchable.d.ts
interface SearchableItem {
id: string;
textContent: string | null;
dataset?: any | undefined;
}
declare function getByText<T extends SearchableItem>(v: T[], text: string, currentId?: string | null, itemToId?: ItemToId<T>): T | undefined;
//#endregion
//#region src/shared/dom-query/set.d.ts
declare function setAttribute(el: Element, attr: string, v: string): () => void;
declare function setProperty<T extends Element, K extends keyof T & string>(el: T, prop: K, v: T[K]): () => void;
declare function setStyle(el: HTMLElement | null | undefined, style: Partial<CSSStyleDeclaration>): () => void;
declare function setStyleProperty(el: HTMLElement | null | undefined, prop: string, value: string): () => void;
//#endregion
//#region src/shared/dom-query/shared.d.ts
declare const MAX_Z_INDEX = 2147483647;
declare const dataAttr: (guard: boolean | undefined) => Booleanish;
declare const ariaAttr: (guard: boolean | undefined) => "true" | undefined;
//#endregion
//#region src/shared/dom-query/text-selection.d.ts
interface DisableTextSelectionOptions<T = MaybeElement> {
target?: T | undefined;
doc?: Document | undefined;
defer?: boolean | undefined;
}
declare function restoreTextSelection(options?: DisableTextSelectionOptions): void;
type MaybeElement = HTMLElement | null | undefined;
type NodeOrFn = MaybeElement | (() => MaybeElement);
declare function disableTextSelection(options?: DisableTextSelectionOptions<NodeOrFn>): () => void;
//#endregion
//#region src/shared/dom-query/typeahead.d.ts
interface TypeaheadState {
keysSoFar: string;
timer: number;
}
interface TypeaheadOptions<T> {
state: TypeaheadState;
activeId: string | null;
key: string;
timeout?: number | undefined;
itemToId?: ItemToId<T> | undefined;
}
declare function getByTypeaheadImpl<T extends SearchableItem>(baseItems: T[], options: TypeaheadOptions<T>): T | undefined;
declare const getByTypeahead: typeof getByTypeaheadImpl & {
defaultOptions: {
keysSoFar: string;
timer: number;
};
isValidEvent: typeof isValidTypeaheadEvent;
};
declare function isValidTypeaheadEvent(event: Pick<KeyboardEvent, "key" | "ctrlKey" | "metaKey">): boolean;
//#endregion
//#region src/shared/dom-query/visual-viewport.d.ts
interface ViewportSize {
width: number;
height: number;
}
declare function trackVisualViewport(doc: Document, fn: (data: ViewportSize) => void): () => void;
//#endregion
//#region src/shared/dom-query/visually-hidden.d.ts
declare const visuallyHiddenStyle: {
readonly border: "0";
readonly clip: "rect(0 0 0 0)";
readonly height: "1px";
readonly margin: "-1px";
readonly overflow: "hidden";
readonly padding: "0";
readonly position: "absolute";
readonly width: "1px";
readonly whiteSpace: "nowrap";
readonly wordWrap: "normal";
};
declare function setVisuallyHidden(el: HTMLElement): void;
//#endregion
//#region src/shared/dom-query/wait-for.d.ts
interface WaitForOptions {
timeout: number;
rootNode?: Document | ShadowRoot | undefined;
}
type WaitForPromiseReturn<T> = [Promise<T>, () => void];
declare function waitForPromise<T>(promise: Promise<T>, controller: AbortController, timeout: number): WaitForPromiseReturn<T>;
declare function waitForElement(target: () => HTMLElement | null, options: WaitForOptions): WaitForPromiseReturn<HTMLElement>;
type WaitForEventReturn<K extends keyof HTMLElementEventMap> = [Promise<HTMLElementEventMap[K]>, VoidFunction];
interface WaitForEventOptions<T extends HTMLElement = HTMLElement> extends AddEventListenerOptions {
predicate?: (element: T) => boolean;
}
declare function waitForEvent<T extends HTMLElement = HTMLElement, K extends keyof HTMLElementEventMap = keyof HTMLElementEventMap>(target: (() => HTMLElement | null) | undefined, event: K, options?: WaitForEventOptions<T>): WaitForEventReturn<K>;
//#endregion
export { getNextTabbable as $, hasControllerElements as $n, isElementVisible as $t, resizeObserverContentBox as A, getEventPoint as An, ScrollOptions as At, nextById as B, isModifierKey as Bn, getAncestorElements as Bt, setStyleProperty as C, markAsInternalChangeEvent as Cn, isIPhone as Ct, createScope as D, addDomEvent as Dn, isTouchDevice as Dt, ScopeContext as E, trackFormControl as En, isSafari as Et, raf as F, isContextMenuEvent as Fn, isInView as Ft, proxyTabFocus as G, isVirtualClick as Gn, getParentNode as Gt, query as H, isPrintableKey as Hn, getDocumentElement as Ht, ItemToId as I, isCtrlOrMetaKey as In, isOverflowElement as It, TabbableOptions as J, DataUrlType as Jn, isActiveElement as Jt, GetShadowRootOption as K, isVirtualPointerEvent as Kn, getRootNode as Kt, defaultItemToId as L, isDownloadingEvent as Ln, scrollIntoView as Lt, AnimationFrame as M, getEventTarget as Mn, getNearestOverflowAncestor as Mt, nextTick as N, getNativeEvent as Nn, getOverflowAncestors as Nt, getScale as O, getBeforeInputValue as On, isWebKit as Ot, queueBeforeEvent as P, isComposingEvent as Pn, getScrollPosition as Pt, getLastTabbable as Q, getControlledElements as Qn, isElement as Qt, indexOfId as R, isKeyboardClick as Rn, contains as Rt, setStyle as S, isInternalChangeEvent as Sn, isIPad as St, getByText as T, setElementValue as Tn, isMac as Tt, queryAll as U, isSelfTarget as Un, getNodeName as Ut, prevById as V, isOpeningInNewTab as Vn, getDocument as Vt, ProxyTabFocusOptions as W, isTouchEvent as Wn, getParentElement as Wt, getFirstTabbable as X, ControlledElementOptions as Xn, isDocument as Xt, getFirstFocusable as Y, getDataUrl as Yn, isAnchorElement as Yt, getFocusables as Z, findControlledElements as Zn, isEditableElement as Zt, MAX_Z_INDEX as _, CheckedEventOptions as _n, isAndroid as _t, waitForEvent as a, isVisualViewport as an, isCaretAtStart as ar, PressDetails as at, setAttribute as b, dispatchInputCheckedEvent as bn, isDom as bt, visuallyHiddenStyle as c, clickIfLink as cn, PointerMoveDetails as ct, TypeaheadOptions as d, ObserveChildrenOptions as dn, trackPointerMove as dt, isHTMLElement as en, isControlledByExpandedController as er, getTabIndex as et, TypeaheadState as f, observeAttributes as fn, requestPointerLock as ft, restoreTextSelection as g, isValidTabEvent as gn, getUserAgent as gt, disableTextSelection as h, getInitialFocus as hn, getPlatform as ht, waitForElement as i, isShadowRoot as in, getComputedStyle as ir, isTabbable as it, resizeObserverDevicePixelContentBox as j, getEventStep as jn, ScrollPosition as jt, resizeObserverBorderBox as k, getEventKey as kn, OverflowAncestor as kt, ViewportSize as l, navigate as ln, PointerMoveHandlers as lt, DisableTextSelectionOptions as m, InitialFocusOptions as mn, getRelativePoint as mt, WaitForOptions as n, isNode as nn, isControllerElement as nr, getTabbables as nt, waitForPromise as o, isWindow as on, setCaretToEnd as or, TrackPressOptions as ot, getByTypeahead as p, observeChildren as pn, PercentValueOptions as pt, NextTabbableOptions as q, DataUrlOptions as qn, getWindow as qt, WaitForPromiseReturn as r, isRootElement as rn, isInteractiveContainerElement as rr, isFocusable as rt, setVisuallyHidden as s, NavigateOptions as sn, trackPress as st, WaitForEventOptions as t, isInputElement as tn, isControlledElement as tr, getTabbableEdges as tt, trackVisualViewport as u, ObserveAttributeOptions as un, PointerUpDetails as ut, ariaAttr as v, InputValueEventOptions as vn, isApple as vt, SearchableItem as w, setElementChecked as wn, isIos as wt, setProperty as x, dispatchInputValueEvent as xn, isFirefox as xt, dataAttr as y, TrackFormControlOptions as yn, isChrome as yt, itemById as z, isLeftClick as zn, getActiveElement as zt };
import { Jt as isActiveElement } from "./index-CeVk_nT2.cjs";
//#region src/shared/core/merge-props.d.ts
interface Props {
[key: string | symbol]: any;
}
type TupleTypes<T extends any[]> = T[number];
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
declare function mergeProps<T extends Props>(...args: Array<T | undefined>): UnionToIntersection<TupleTypes<T[]>>;
//#endregion
//#region src/shared/core/memo.d.ts
type NoInfer<T> = [T][T extends any ? 0 : never];
declare function memo<TDeps extends any[], TDepArgs, TResult>(getDeps: (depArgs: TDepArgs) => [...TDeps], fn: (args: NoInfer<[...TDeps]>, deps: TDepArgs) => TResult, opts?: {
onChange?: ((result: TResult) => void) | undefined;
}): (depArgs: TDepArgs) => TResult;
//#endregion
//#region src/shared/core/types.d.ts
type Dict = Record<string, any>;
interface ComputedParams<T extends Dict> {
context: BindableContext<T>;
event: EventType<T["event"]>;
prop: PropFn<T>;
refs: BindableRefs<T>;
scope: Scope;
computed: ComputedFn<T>;
}
interface ContextParams<T extends Dict> {
prop: PropFn<T>;
bindable: BindableFn;
scope: Scope;
getContext: () => BindableContext<T>;
getComputed: () => ComputedFn<T>;
getRefs: () => BindableRefs<T>;
getEvent: () => EventType<T["event"]>;
flush: (fn: VoidFunction) => void;
}
interface PropFn<T extends Dict> {
<K extends keyof T["props"]>(key: K): T["props"][K];
}
interface ComputedFn<T extends Dict> {
<K extends keyof T["computed"]>(key: K): T["computed"][K];
}
type AnyFunction = () => string | number | boolean | null | undefined;
type TrackFn = (deps: AnyFunction[], fn: VoidFunction) => void;
interface BindableParams<T> {
defaultValue?: T | undefined;
value?: T | undefined;
hash?: ((a: T) => string) | undefined;
isEqual?: ((a: T, b: T | undefined) => boolean) | undefined;
onChange?: ((value: T, prev: T | undefined) => void) | undefined;
debug?: string | undefined;
sync?: boolean | undefined;
}
type ValueOrFn<T> = T | ((prev: T) => T);
interface Bindable<T> {
initial: T | undefined;
ref: any;
get: () => T;
set(value: ValueOrFn<T>): void;
invoke(nextValue: T, prevValue: T): void;
hash(value: T): string;
}
interface BindableRefs<T extends Dict> {
set<K extends keyof T["refs"]>(key: K, value: T["refs"][K]): void;
get<K extends keyof T["refs"]>(key: K): T["refs"][K];
}
interface BindableContext<T extends Dict> {
set<K extends keyof T["context"]>(key: K, value: ValueOrFn<T["context"][K]>): void;
get<K extends keyof T["context"]>(key: K): T["context"][K];
initial<K extends keyof T["context"]>(key: K): T["context"][K];
hash<K extends keyof T["context"]>(key: K): string;
}
interface BindableRef<T> {
get: () => T;
set: (next: T) => void;
}
interface BindableFn {
<K>(params: () => BindableParams<K>): Bindable<K>;
cleanup: (fn: VoidFunction) => void;
ref: <T>(defaultValue: T) => BindableRef<T>;
}
interface Scope {
id?: string | undefined;
ids?: Record<string, any> | undefined;
getRootNode: () => ShadowRoot | Document | Node;
getById: <T extends Element = HTMLElement>(id: string) => T | null;
getActiveElement: () => HTMLElement | null;
isActiveElement: (elem: HTMLElement | null) => boolean;
getDoc: () => typeof document;
getWin: () => typeof window;
}
type EventType<T = any> = T & {
previousEvent?: (T & {
[key: string]: any;
}) | undefined;
src?: string | undefined;
[key: string]: any;
};
type EventObject = EventType<{
type: string;
}>;
interface Params<T extends Dict> {
prop: PropFn<T>;
action: (action: T["action"][]) => void;
context: BindableContext<T>;
refs: BindableRefs<T>;
track: TrackFn;
flush: (fn: VoidFunction) => void;
event: EventType<T["event"]> & {
current: () => EventType<T["event"]>;
previous: () => EventType<T["event"]>;
};
send: (event: EventType<T["event"]>) => void;
computed: ComputedFn<T>;
scope: Scope;
state: Bindable<T["state"]> & {
matches: (...values: T["state"][]) => boolean;
hasTag: (tag: T["tag"]) => boolean;
};
choose: ChooseFn<T>;
guard: (key: T["guard"] | GuardFn<T>) => boolean | undefined;
}
type GuardFn<T extends Dict> = (params: Params<T>) => boolean;
type TopLevelState<S extends string> = S extends `${infer Top}.${string}` ? Top : S;
type ChildStateKey<S extends string, Parent extends string> = S extends `${Parent}.${infer Rest}` ? Rest extends `${infer Child}.${string}` ? Child : Rest : never;
type ParentPath<S extends string> = S extends `${infer Parent}.${string}` ? Parent : never;
type AncestorPaths<S extends string> = S | (ParentPath<S> extends never ? never : AncestorPaths<ParentPath<S>>);
type StateIdTarget = `#${string}`;
type SiblingStateTarget<S extends string, Source extends string> = TopLevelState<S> | ChildStateKey<S, Exclude<AncestorPaths<Source>, Source>>;
type ChildStateTarget<S extends string, Source extends string> = `.${ChildStateKey<S, Source>}`;
interface Transition<T extends Dict, Source extends string | undefined = string | undefined> {
target?: T["state"] | StateIdTarget | (Source extends string ? SiblingStateTarget<T["state"], Source> : never) | (Source extends string ? ChildStateTarget<T["state"], Source> : never) | undefined;
actions?: T["action"][] | undefined;
guard?: T["guard"] | GuardFn<T> | undefined;
reenter?: boolean | undefined;
}
type TransitionSet<T extends Dict> = Transition<T> | Transition<T>[] | undefined;
type TransitionMap<T extends Dict> = Record<string, TransitionSet<T>>;
type TransitionMatch<T extends Dict> = {
transitions: TransitionSet<T>;
source: string | undefined;
};
type MaybeArray<T> = T | T[];
type ChooseFn<T extends Dict> = (transitions: MaybeArray<Omit<Transition<T, string>, "target">> | null | undefined) => Transition<T> | undefined;
interface PropsParams<T extends Dict> {
props: Partial<T["props"]>;
scope: Scope;
}
interface RefsParams<T extends Dict> {
prop: PropFn<T>;
context: BindableContext<T>;
}
type ActionsOrFn<T extends Dict> = T["action"][] | ((params: Params<T>) => T["action"][] | undefined);
type EffectsOrFn<T extends Dict> = T["effect"][] | ((params: Params<T>) => T["effect"][] | undefined);
interface MachineState<T extends Dict, Parent extends string = string> {
id?: string | undefined;
tags?: T["tag"][] | undefined;
entry?: ActionsOrFn<T> | undefined;
exit?: ActionsOrFn<T> | undefined;
effects?: EffectsOrFn<T> | undefined;
initial?: ChildStateKey<T["state"], Parent> | undefined;
states?: { [K in ChildStateKey<T["state"], Parent>]?: MachineState<T, `${Parent}.${K}`> } | undefined;
on?: { [E in T["event"]["type"]]?: Transition<T, Parent> | Array<Transition<T, Parent>> } | undefined;
}
interface Machine<T extends Dict> {
debug?: boolean | undefined;
props?: ((params: PropsParams<T>) => T["props"]) | undefined;
context?: ((params: ContextParams<T>) => { [K in keyof T["context"]]: Bindable<T["context"][K]> }) | undefined;
computed?: { [K in keyof T["computed"]]: (params: ComputedParams<T>) => T["computed"][K] } | undefined;
initialState: (params: {
prop: PropFn<T>;
}) => T["state"];
entry?: ActionsOrFn<T> | undefined;
exit?: ActionsOrFn<T> | undefined;
effects?: EffectsOrFn<T> | undefined;
refs?: ((params: RefsParams<T>) => T["refs"]) | undefined;
watch?: ((params: Params<T>) => void) | undefined;
on?: { [E in T["event"]["type"]]?: Transition<T, undefined> | Array<Transition<T, undefined>> } | undefined;
states: { [K in TopLevelState<T["state"]>]: MachineState<T, K> };
implementations?: {
guards?: { [K in T["guard"]]: (params: Params<T>) => boolean } | undefined;
actions?: { [K in T["action"]]: (params: Params<T>) => void } | undefined;
effects?: { [K in T["effect"]]: (params: Params<T>) => void | VoidFunction } | undefined;
} | undefined;
}
interface MachineBaseProps {
id?: string | undefined;
ids?: Record<string, any> | undefined;
getRootNode?: (() => ShadowRoot | Document | Node) | undefined;
[key: string]: any;
}
interface MachineSchema {
props?: MachineBaseProps | undefined;
context?: Record<string, any> | undefined;
refs?: Record<string, any> | undefined;
computed?: Record<string, any> | undefined;
state?: string | undefined;
tag?: string | undefined;
guard?: string | undefined;
action?: string | undefined;
effect?: string | undefined;
event?: ({
type: string;
} & Dict) | undefined;
}
type State<T extends MachineSchema> = Bindable<T["state"]> & {
hasTag: (tag: T["tag"]) => boolean;
matches: (...values: T["state"][]) => boolean;
};
type Service<T extends MachineSchema> = {
getStatus: () => MachineStatus;
state: State<T> & {
matches: (...values: T["state"][]) => boolean;
hasTag: (tag: T["tag"]) => boolean;
};
context: BindableContext<T>;
send: (event: EventType<T["event"]>) => void;
prop: PropFn<T>;
scope: Scope;
computed: ComputedFn<T>;
refs: BindableRefs<T>;
event: EventType<T["event"]> & {
current: () => EventType<T["event"]>;
previous: () => EventType<T["event"]>;
};
};
declare enum MachineStatus {
NotStarted = "Not Started",
Started = "Started",
Stopped = "Stopped"
}
declare const INIT_STATE = "__init__";
//#endregion
//#region src/shared/core/create-machine.d.ts
declare function createGuards<T extends MachineSchema>(): {
and: (...guards: Array<GuardFn<T> | T["guard"]>) => (params: any) => boolean;
or: (...guards: Array<GuardFn<T> | T["guard"]>) => (params: any) => boolean;
not: (guard: GuardFn<T> | T["guard"]) => (params: any) => boolean;
};
declare function createMachine<T extends MachineSchema>(config: Machine<T>): Machine<T>;
declare function setup<T extends MachineSchema>(): {
guards: {
and: (...guards: (GuardFn<T> | T["guard"])[]) => (params: any) => boolean;
or: (...guards: (GuardFn<T> | T["guard"])[]) => (params: any) => boolean;
not: (guard: GuardFn<T> | T["guard"]) => (params: any) => boolean;
};
createMachine: (config: Machine<T>) => Machine<T>;
choose: (transitions: Transition<T> | Transition<T>[]) => ({
choose
}: Params<T>) => T["action"][] | undefined;
};
//#endregion
//#region src/shared/core/state.d.ts
declare function ensureStateIndex<T extends MachineSchema>(machine: Machine<T>): Map<string, MachineState<T, string>>;
type StateChain<T extends MachineSchema> = Array<{
path: string;
state: MachineState<T>;
}>;
declare function getStateChain<T extends MachineSchema>(machine: Machine<T>, state: T["state"] | undefined): StateChain<T>;
declare function resolveStateValue<T extends MachineSchema>(machine: Machine<T>, value: T["state"] | string, source?: string): T["state"];
declare function getStateDefinition<T extends MachineSchema>(machine: Machine<T>, state: T["state"]): MachineState<T, string>;
declare function findTransition<T extends MachineSchema>(machine: Machine<T>, state: T["state"], eventType: string): TransitionMatch<T>;
declare function getExitEnterStates<T extends MachineSchema>(machine: Machine<T>, prevState: T["state"] | undefined, nextState: T["state"], reenter?: boolean): {
exiting: {
path: string;
state: MachineState<T, string>;
}[];
entering: {
path: string;
state: MachineState<T, string>;
}[];
};
declare function matchesState(current: string | undefined, value: string): boolean;
declare function hasTag<T extends MachineSchema>(machine: Machine<T>, state: T["state"], tag: T["tag"]): boolean;
//#endregion
//#region src/shared/core/scope.d.ts
declare function createScope(props: Pick<Scope, "id" | "ids" | "getRootNode">): {
getRootNode: () => Document | ShadowRoot;
getDoc: () => Document;
getWin: () => Window & typeof globalThis;
getActiveElement: () => HTMLElement | null;
isActiveElement: typeof isActiveElement;
getById: <T extends Element = HTMLElement>(id: string) => T | null;
ids?: Record<string, any> | undefined;
id?: string | undefined | undefined;
};
//#endregion
export { PropFn as A, GuardFn as C, MachineState as D, MachineSchema as E, TransitionMatch as F, TransitionSet as I, ValueOrFn as L, Service as M, Transition as N, MachineStatus as O, TransitionMap as P, memo as R, EventObject as S, Machine as T, BindableParams as _, getStateChain as a, ComputedFn as b, matchesState as c, createMachine as d, setup as f, BindableFn as g, BindableContext as h, getExitEnterStates as i, Scope as j, Params as k, resolveStateValue as l, Bindable as m, ensureStateIndex as n, getStateDefinition as o, ActionsOrFn as p, findTransition as r, hasTag as s, createScope as t, createGuards as u, BindableRefs as v, INIT_STATE as w, EffectsOrFn as x, ChooseFn as y, mergeProps as z };
//#region src/shared/interact-outside/index.d.ts
interface InteractOutsideHandlers {
onPointerDownOutside?: ((event: PointerDownOutsideEvent) => void) | undefined;
onFocusOutside?: ((event: FocusOutsideEvent) => void) | undefined;
onInteractOutside?: ((event: InteractOutsideEvent) => void) | undefined;
}
interface InteractOutsideOptions extends InteractOutsideHandlers {
exclude?: ((target: HTMLElement) => boolean) | undefined;
defer?: boolean | undefined;
followControlledElements?: boolean | undefined;
}
interface EventDetails<T> {
originalEvent: T;
contextmenu: boolean;
focusable: boolean;
target: EventTarget;
}
type PointerDownOutsideEvent = CustomEvent<EventDetails<PointerEvent>>;
type FocusOutsideEvent = CustomEvent<EventDetails<FocusEvent>>;
type InteractOutsideEvent = PointerDownOutsideEvent | FocusOutsideEvent;
type MaybeElement = HTMLElement | null | undefined;
type NodeOrFn = MaybeElement | (() => MaybeElement);
declare function trackInteractOutside(nodeOrFn: NodeOrFn, options: InteractOutsideOptions): () => void;
//#endregion
export { InteractOutsideOptions as a, PointerDownOutsideEvent as c, InteractOutsideHandlers as i, trackInteractOutside as l, FocusOutsideEvent as n, MaybeElement as o, InteractOutsideEvent as r, NodeOrFn as s, EventDetails as t };
import { AutoUpdateOptions, Boundary, ComputePositionReturn, Placement, Placement as Placement$1, VirtualElement } from "@floating-ui/dom";
//#region src/shared/popper/types.d.ts
type MaybeRectElement = HTMLElement | VirtualElement | null;
type MaybeElement = HTMLElement | null;
type MaybeFn<T> = T | (() => T);
type PlacementSide = "top" | "right" | "bottom" | "left";
type PlacementAlign = "start" | "center" | "end";
interface AnchorRect {
x?: number | undefined;
y?: number | undefined;
width?: number | undefined;
height?: number | undefined;
}
interface PositioningOptions {
/**
* Whether styles applied by the positioning utility should be restored on cleanup.
*/
restoreStyles?: boolean | undefined;
/**
* Whether the popover should be hidden when the reference element is detached
*/
hideWhenDetached?: boolean | undefined;
/**
* The strategy to use for positioning
*/
strategy?: "absolute" | "fixed" | undefined;
/**
* The initial placement of the floating element
*/
placement?: Placement$1 | undefined;
/**
* The offset of the floating element
*/
offset?: {
mainAxis?: number | undefined;
crossAxis?: number | undefined;
} | undefined;
/**
* The main axis offset or gap between the reference and floating elements
*/
gutter?: number | undefined;
/**
* The secondary axis offset or gap between the reference and floating elements
*/
shift?: number | undefined;
/**
* The virtual padding around the viewport edges to check for overflow
*/
overflowPadding?: number | undefined;
/**
* The minimum padding between the arrow and the floating element's corner.
* @default 4
*/
arrowPadding?: number | undefined;
/**
* Whether to flip the placement
*/
flip?: boolean | Placement$1[] | undefined;
/**
* Whether the popover should slide when it overflows.
*/
slide?: boolean | undefined;
/**
* Whether the floating element can overlap the reference element
* @default false
*/
overlap?: boolean | undefined;
/**
* Whether to make the floating element same width as the reference element
*/
sameWidth?: boolean | undefined;
/**
* Whether the popover should fit the viewport.
*/
fitViewport?: boolean | undefined;
/**
* Whether to use the size middleware from Floating UI.
* It computes and sets CSS variables (`--reference-width`, `--reference-height`, `--available-width`, `--available-height`) used by `sameWidth` and `fitViewport`.
*
* Disabling it improves scroll performance with heavy content by avoiding layout thrashing on each update.
* Only applies when both `sameWidth` and `fitViewport` are false — the middleware is always used when either is enabled.
* @default true
*/
sizeMiddleware?: boolean | undefined;
/**
* The overflow boundary of the reference element
* Accepts a function returning a Boundary, a Boundary directly,
* or the shorthand string 'clipping-ancestors' which maps to Floating UI's 'clippingAncestors'.
*/
boundary?: (() => Boundary) | Boundary | "clipping-ancestors" | undefined;
/**
* Options to activate auto-update listeners
*/
listeners?: boolean | AutoUpdateOptions | undefined;
/**
* Function called when the placement is computed
*/
onComplete?: ((data: ComputePositionReturn) => void) | undefined;
/**
* Function called when the floating element is positioned or not
*/
onPositioned?: ((data: {
placed: boolean;
}) => void) | undefined;
/**
* Function that returns the anchor element.
* Useful when you want to use a different element as the anchor.
*/
getAnchorElement?: (() => HTMLElement | VirtualElement | null) | undefined;
/**
* Function that returns the anchor rect
* @deprecated Use `getAnchorElement` instead
*/
getAnchorRect?: ((element: HTMLElement | VirtualElement | null) => AnchorRect | null) | undefined;
/**
* A callback that will be called when the popover needs to calculate its
* position.
*/
updatePosition?: ((data: {
updatePosition: () => Promise<void>;
floatingElement: HTMLElement | null;
}) => void | Promise<void>) | undefined;
}
//#endregion
//#region src/shared/popper/get-placement.d.ts
declare function getPlacement(referenceOrFn: MaybeFn<MaybeRectElement>, floatingOrFn: MaybeFn<MaybeElement>, opts?: PositioningOptions & {
defer?: boolean | undefined;
}): () => void;
//#endregion
//#region src/shared/popper/middleware.d.ts
declare const cssVars: {
arrowSize: {
variable: string;
reference: string;
};
arrowSizeHalf: {
variable: string;
reference: string;
};
arrowBg: {
variable: string;
reference: string;
};
transformOrigin: {
variable: string;
reference: string;
};
arrowOffset: {
variable: string;
reference: string;
};
};
//#endregion
//#region src/shared/popper/get-styles.d.ts
interface GetPlacementStylesOptions {
placement?: Placement | undefined;
}
declare function getPlacementStyles(options?: Pick<PositioningOptions, "placement" | "sameWidth" | "fitViewport" | "strategy">): {
arrow: {
readonly [cssVars.arrowSizeHalf.variable]: `calc(${string} / 2)`;
readonly [cssVars.arrowOffset.variable]: `calc(${string} * -1)`;
readonly position: "absolute";
readonly width: string;
readonly height: string;
};
arrowTip: {
readonly transform: any;
readonly background: string;
readonly top: "0";
readonly left: "0";
readonly width: "100%";
readonly height: "100%";
readonly position: "absolute";
readonly zIndex: "inherit";
};
floating: {
readonly position: "absolute" | "fixed";
readonly isolation: "isolate";
readonly minWidth: "max-content" | undefined;
readonly width: "var(--reference-width)" | undefined;
readonly maxWidth: "var(--available-width)" | undefined;
readonly maxHeight: "var(--available-height)" | undefined;
readonly pointerEvents: "none" | undefined;
readonly top: "0px";
readonly left: "0px";
readonly transform: "translate3d(var(--x), var(--y), 0)" | "translate3d(0, -100vh, 0)";
readonly zIndex: "var(--z-index)";
};
};
//#endregion
//#region src/shared/popper/placement.d.ts
declare function isValidPlacement(v: string): v is Placement;
declare function getPlacementSide(placement: Placement): PlacementSide;
//#endregion
export { getPlacement as a, Boundary as c, PlacementAlign as d, PlacementSide as f, getPlacementStyles as i, ComputePositionReturn as l, isValidPlacement as n, AnchorRect as o, PositioningOptions as p, GetPlacementStylesOptions as r, AutoUpdateOptions as s, getPlacementSide as t, Placement$1 as u };
import { C as JSX, c as MaybeFn, u as Nullable } from "./index-DFJGBSAc.cjs";
//#region src/shared/dom-query/caret.d.ts
declare function isCaretAtStart(input: HTMLInputElement | HTMLTextAreaElement | null): boolean;
declare function setCaretToEnd(input: HTMLInputElement | HTMLTextAreaElement | null): void;
//#endregion
//#region src/shared/dom-query/computed-style.d.ts
declare function getComputedStyle(el: Element): CSSStyleDeclaration;
//#endregion
//#region src/shared/dom-query/controller.d.ts
interface ControlledElementOptions {
followControlledElements?: boolean | undefined;
}
declare function isControlledElement(container: HTMLElement, element: HTMLElement): boolean;
declare function findControlledElements(searchRoot: HTMLElement, callback: (controlledElement: HTMLElement) => void): void;
declare function getControlledElements(container: HTMLElement): HTMLElement[];
declare function isInteractiveContainerElement(element: Element): boolean;
declare function isControllerElement(element: Element): boolean;
declare function hasControllerElements(element: Element): boolean;
declare function isControlledByExpandedController(element: Element): boolean;
//#endregion
//#region src/shared/dom-query/data-url.d.ts
type DataUrlType = "image/png" | "image/jpeg" | "image/svg+xml";
interface DataUrlOptions {
type: DataUrlType;
quality?: number | undefined;
background?: string | undefined;
}
declare function getDataUrl(svg: SVGSVGElement | undefined | null, opts: DataUrlOptions): Promise<string>;
//#endregion
//#region src/shared/dom-query/types.d.ts
type Booleanish = boolean | "true" | "false";
interface Point {
x: number;
y: number;
}
interface EventKeyOptions {
dir?: "ltr" | "rtl" | undefined;
orientation?: "horizontal" | "vertical" | undefined;
}
type NativeEvent<E> = JSX.ChangeEvent<any> extends E ? InputEvent : E extends JSX.SyntheticEvent<any, infer T> ? T : never;
type AnyPointerEvent = MouseEvent | TouchEvent | PointerEvent;
type MaybeElement$1 = Nullable<HTMLElement>;
type MaybeElementOrFn = MaybeFn<MaybeElement$1>;
type HTMLElementWithValue = HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement;
//#endregion
//#region src/shared/dom-query/event.d.ts
declare function getBeforeInputValue(event: Pick<InputEvent, "currentTarget">): string;
declare function getEventTarget<T extends EventTarget>(event: Partial<Pick<UIEvent, "target" | "composedPath">>): T | null;
declare function isOpeningInNewTab(event: Pick<MouseEvent, "currentTarget" | "metaKey" | "ctrlKey" | "button">): boolean;
declare function isDownloadingEvent(event: Pick<MouseEvent, "altKey" | "currentTarget">): boolean;
declare function isComposingEvent(event: any): boolean;
declare function isKeyboardClick(e: Pick<MouseEvent, "detail" | "clientX" | "clientY">): boolean;
declare function isCtrlOrMetaKey(e: Pick<KeyboardEvent, "ctrlKey" | "metaKey">): boolean;
declare function isPrintableKey(e: Pick<KeyboardEvent, "key" | "ctrlKey" | "metaKey">): boolean;
declare function isVirtualPointerEvent(e: PointerEvent): boolean;
declare function isVirtualClick(e: MouseEvent | PointerEvent): boolean;
declare const isLeftClick: (e: Pick<MouseEvent, "button">) => boolean;
declare const isContextMenuEvent: (e: Pick<MouseEvent, "button" | "ctrlKey" | "metaKey">) => boolean;
declare const isModifierKey: (e: Pick<KeyboardEvent, "ctrlKey" | "metaKey" | "altKey">) => boolean;
declare const isTouchEvent: (event: AnyPointerEvent) => event is TouchEvent;
declare function getEventKey(event: Pick<KeyboardEvent, "key">, options?: EventKeyOptions): string;
declare function getNativeEvent<E>(event: E): NativeEvent<E>;
declare function getEventStep(event: Pick<KeyboardEvent, "ctrlKey" | "metaKey" | "key" | "shiftKey">): 1 | 0.1 | 10;
declare function getEventPoint(event: any, type?: "page" | "client"): {
x: number;
y: number;
};
interface DOMEventMap extends DocumentEventMap, WindowEventMap, HTMLElementEventMap {}
declare const addDomEvent: <K extends keyof DOMEventMap>(target: MaybeFn<EventTarget | null>, eventName: K | (string & {}), handler: (event: DOMEventMap[K]) => void, options?: boolean | AddEventListenerOptions) => () => void;
declare const isSelfTarget: (event: Partial<Pick<UIEvent, "currentTarget" | "target" | "composedPath">>) => boolean;
//#endregion
//#region src/shared/dom-query/form.d.ts
declare function setElementValue(el: HTMLElementWithValue | null, value: string, property?: "value" | "checked"): void;
declare function setElementChecked(el: HTMLInputElement | null, checked: boolean): void;
interface InputValueEventOptions {
value: string | number;
bubbles?: boolean | undefined;
}
declare function dispatchInputValueEvent(el: HTMLElementWithValue | null, options: InputValueEventOptions): void;
interface CheckedEventOptions {
checked: boolean;
bubbles?: boolean | undefined;
}
declare function dispatchInputCheckedEvent(el: HTMLInputElement | null, options: CheckedEventOptions): void;
interface TrackFormControlOptions {
onFieldsetDisabledChange: (disabled: boolean) => void;
onFormReset: VoidFunction;
}
declare function trackFormControl(el: HTMLElement | null, options: TrackFormControlOptions): (() => void) | undefined;
declare const INTERNAL_CHANGE_EVENT: unique symbol;
type InternalChangeEventProps = {
[INTERNAL_CHANGE_EVENT]?: boolean;
};
declare function isInternalChangeEvent<T extends Event>(e: T): e is T & InternalChangeEventProps;
declare function markAsInternalChangeEvent<T extends Event>(event: T): T & InternalChangeEventProps;
//#endregion
//#region src/shared/dom-query/initial-focus.d.ts
interface InitialFocusOptions {
root: HTMLElement | null;
getInitialEl?: (() => HTMLElement | null) | undefined;
enabled?: boolean | undefined;
filter?: ((el: HTMLElement) => boolean) | undefined;
}
declare function getInitialFocus(options: InitialFocusOptions): HTMLElement | undefined;
declare function isValidTabEvent(event: Pick<KeyboardEvent, "shiftKey" | "currentTarget">): boolean;
//#endregion
//#region src/shared/dom-query/mutation-observer.d.ts
interface ObserveAttributeOptions {
attributes: string[];
callback(record: MutationRecord): void;
defer?: boolean | undefined;
}
declare function observeAttributes(nodeOrFn: MaybeElementOrFn, options: ObserveAttributeOptions): () => void;
interface ObserveChildrenOptions {
callback: MutationCallback;
defer?: boolean | undefined;
}
declare function observeChildren(nodeOrFn: MaybeElementOrFn, options: ObserveChildrenOptions): () => void;
//#endregion
//#region src/shared/dom-query/navigate.d.ts
interface NavigateOptions {
key?: string;
orientation?: "both" | "vertical" | "horizontal";
loop?: boolean;
dir?: "ltr" | "rtl";
}
declare function navigate<T extends HTMLElement>(items: T[], current: T | null, options?: NavigateOptions): T | null;
declare function clickIfLink(el: HTMLAnchorElement): void;
//#endregion
//#region src/shared/dom-query/node.d.ts
declare const isElement: (el: any) => el is Element;
declare const isHTMLElement: (el: any) => el is HTMLElement;
declare const isDocument: (el: any) => el is Document;
declare const isWindow: (el: any) => el is Window;
declare const isVisualViewport: (el: any) => el is VisualViewport;
declare const getNodeName: (node: Node | Window) => string;
declare function isRootElement(node: Node): boolean;
declare const isNode: (el: any) => el is Node;
declare const isShadowRoot: (el: any) => el is ShadowRoot;
declare const isInputElement: (el: any) => el is HTMLInputElement;
declare const isAnchorElement: (el: HTMLElement | null | undefined) => el is HTMLAnchorElement;
declare const isElementVisible: (el: Node) => boolean;
declare function isActiveElement(element: Element | null | undefined): boolean;
declare function isEditableElement(el: HTMLElement | EventTarget | null): boolean;
type Target = HTMLElement | EventTarget | null | undefined;
/** Whether `parent` contains `child` in the light tree, or `child` is inside a shadow tree hosted under `parent`. */
declare function getParentElement(node: Element): Element | null;
declare function getAncestorElements(node: Element | null): Element[];
declare function contains(parent: Target, child: Target): boolean;
declare function getDocument(el: Element | Window | Node | Document | null | undefined): Document;
declare function getDocumentElement(el: Element | Node | Window | Document | null | undefined): HTMLElement;
declare function getWindow(el: Node | ShadowRoot | Document | null | undefined): Window & typeof globalThis;
declare function getActiveElement(rootNode: Document | ShadowRoot): HTMLElement | null;
declare function getParentNode(node: Node): Node;
declare function getRootNode(node: Node): Document | ShadowRoot;
//#endregion
//#region src/shared/dom-query/overflow.d.ts
type OverflowAncestor = Array<VisualViewport | Window | HTMLElement | null>;
declare function getNearestOverflowAncestor(el: Node): HTMLElement;
declare function getOverflowAncestors(el: HTMLElement, list?: OverflowAncestor): OverflowAncestor;
declare function isInView(el: HTMLElement | Window | VisualViewport, ancestor: HTMLElement | Window | VisualViewport): boolean;
declare function isOverflowElement(el: HTMLElement): boolean;
interface ScrollOptions extends ScrollIntoViewOptions {
rootEl: HTMLElement | null;
}
declare function scrollIntoView(el: HTMLElement | null | undefined, options?: ScrollOptions): void;
interface ScrollPosition {
scrollLeft: number;
scrollTop: number;
}
declare function getScrollPosition(element: HTMLElement | Window): ScrollPosition;
//#endregion
//#region src/shared/dom-query/platform.d.ts
declare const isDom: () => boolean;
declare function getPlatform(): string;
declare function getUserAgent(): string;
declare const isTouchDevice: () => boolean;
declare const isIPhone: () => boolean;
declare const isIPad: () => boolean;
declare const isIos: () => boolean;
declare const isApple: () => boolean;
declare const isMac: () => boolean;
declare const isSafari: () => boolean;
declare const isFirefox: () => boolean;
declare const isChrome: () => boolean;
declare const isWebKit: () => boolean;
declare const isAndroid: () => boolean;
//#endregion
//#region src/shared/dom-query/point.d.ts
interface PercentValueOptions {
inverted?: boolean | {
x?: boolean | undefined;
y?: boolean | undefined;
} | undefined;
dir?: "ltr" | "rtl" | undefined;
orientation?: "vertical" | "horizontal" | undefined;
}
declare function getRelativePoint(point: Point, element: HTMLElement): {
offset: {
x: number;
y: number;
};
percent: {
x: number;
y: number;
};
getPercentValue: (options?: PercentValueOptions) => number;
};
//#endregion
//#region src/shared/dom-query/pointer-lock.d.ts
declare function requestPointerLock(doc: Document, fn?: (locked: boolean) => void): (() => void) | undefined;
//#endregion
//#region src/shared/dom-query/pointer-move.d.ts
interface PointerMoveDetails {
point: Point;
event: PointerEvent;
}
interface PointerUpDetails {
point: Point;
event: PointerEvent;
}
interface PointerMoveHandlers {
onPointerUp: (details: PointerUpDetails) => void;
onPointerMove: (details: PointerMoveDetails) => void;
}
declare function trackPointerMove(doc: Document, handlers: PointerMoveHandlers): () => void;
//#endregion
//#region src/shared/dom-query/press.d.ts
interface PressDetails {
point: Point;
event: PointerEvent;
}
interface TrackPressOptions {
pointerNode: Element | null;
keyboardNode?: Element | null | undefined;
isValidKey?(event: KeyboardEvent): boolean;
onPress?(details: PressDetails): void;
onPressStart?(details: PressDetails): void;
onPressEnd?(details: PressDetails): void;
}
declare function trackPress(options: TrackPressOptions): () => void;
//#endregion
//#region src/shared/dom-query/tabbable.d.ts
type IncludeContainerType = boolean | "if-empty";
type GetShadowRootOption = boolean | ((node: HTMLElement) => ShadowRoot | boolean | undefined) | undefined;
interface TabbableOptions {
includeContainer?: IncludeContainerType;
getShadowRoot?: GetShadowRootOption;
}
interface NextTabbableOptions {
current?: HTMLElement | undefined | null;
getShadowRoot?: GetShadowRootOption;
}
declare const getFocusables: (container: Pick<HTMLElement, "querySelectorAll"> | null, options?: TabbableOptions) => HTMLElement[];
declare function isFocusable(element: HTMLElement | EventTarget | null): element is HTMLElement;
declare function getFirstFocusable(container: HTMLElement | null, options?: TabbableOptions): HTMLElement | null;
declare function getTabbables(container: HTMLElement | null, options?: TabbableOptions): HTMLElement[];
declare function isTabbable(el: HTMLElement | EventTarget | null): el is HTMLElement;
declare function getFirstTabbable(container: HTMLElement | null, options?: TabbableOptions): HTMLElement | null;
declare function getLastTabbable(container: HTMLElement | null, options?: TabbableOptions): HTMLElement | null;
declare function getTabbableEdges(container: HTMLElement | null, options?: TabbableOptions): [HTMLElement, HTMLElement] | [null, null];
declare function getNextTabbable(container: HTMLElement | null, options?: NextTabbableOptions): HTMLElement | null;
declare function getTabIndex(node: HTMLElement | SVGElement): number;
//#endregion
//#region src/shared/dom-query/proxy-tab-focus.d.ts
interface ProxyTabFocusOptions<T = MaybeElement$1> {
triggerElement?: T | undefined;
onFocus?: ((elementToFocus: HTMLElement) => void) | undefined;
onFocusEnter?: VoidFunction | undefined;
defer?: boolean | undefined;
getShadowRoot?: GetShadowRootOption | undefined;
}
declare function proxyTabFocus(container: MaybeElementOrFn, options: ProxyTabFocusOptions<MaybeElementOrFn>): () => void;
//#endregion
//#region src/shared/dom-query/query.d.ts
type Root = Document | Element | null | undefined;
declare function queryAll<T extends Element = HTMLElement>(root: Root, selector: string): T[];
declare function query<T extends Element = HTMLElement>(root: Root, selector: string): T | null;
type ItemToId<T> = (v: T) => string;
interface Item {
id: string;
}
declare const defaultItemToId: <T extends Item>(v: T) => string;
declare function itemById<T extends Item>(v: T[], id: string, itemToId?: ItemToId<T>): T | undefined;
declare function indexOfId<T extends Item>(v: T[], id: string, itemToId?: ItemToId<T>): number;
declare function nextById<T extends Item>(v: T[], id: string, loop?: boolean): T;
declare function prevById<T extends Item>(v: T[], id: string, loop?: boolean): T | null;
//#endregion
//#region src/shared/dom-query/raf.d.ts
declare class AnimationFrame {
static create(): AnimationFrame;
private id;
private fn_cleanup;
request(fn?: VoidFunction | (() => VoidFunction)): void;
cancel(): void;
isActive(): boolean;
cleanup: () => void;
}
declare function raf(fn: VoidFunction | (() => VoidFunction)): () => void;
declare function nextTick(fn: VoidFunction): () => void;
declare function queueBeforeEvent(el: EventTarget, type: string, cb: () => void): () => void;
//#endregion
//#region src/shared/dom-query/resize-observer.d.ts
type Subscriber<T> = (entry: T) => void;
interface SharedResizeObserver {
observe: (element: Element, listener: Subscriber<ResizeObserverEntry>) => () => void;
unobserve: (element: Element) => void;
}
declare const resizeObserverContentBox: SharedResizeObserver;
declare const resizeObserverBorderBox: SharedResizeObserver;
declare const resizeObserverDevicePixelContentBox: SharedResizeObserver;
//#endregion
//#region src/shared/dom-query/scale.d.ts
declare function getScale(element: HTMLElement): {
x: number;
y: number;
};
//#endregion
//#region src/shared/dom-query/scope.d.ts
interface ScopeContext {
getRootNode?: (() => Document | ShadowRoot | Node) | undefined;
}
declare function createScope<T>(methods: T): {
getRootNode: (ctx: ScopeContext) => Document | ShadowRoot;
getDoc: (ctx: ScopeContext) => Document;
getWin: (ctx: ScopeContext) => Window & typeof globalThis;
getActiveElement: (ctx: ScopeContext) => HTMLElement | null;
isActiveElement: typeof isActiveElement;
getById: <T_1 extends Element = HTMLElement>(ctx: ScopeContext, id: string) => T_1 | null;
setValue: <T_1 extends HTMLElementWithValue>(elem: T_1 | null, value: string | number | null | undefined) => void;
} & T;
//#endregion
//#region src/shared/dom-query/searchable.d.ts
interface SearchableItem {
id: string;
textContent: string | null;
dataset?: any | undefined;
}
declare function getByText<T extends SearchableItem>(v: T[], text: string, currentId?: string | null, itemToId?: ItemToId<T>): T | undefined;
//#endregion
//#region src/shared/dom-query/set.d.ts
declare function setAttribute(el: Element, attr: string, v: string): () => void;
declare function setProperty<T extends Element, K extends keyof T & string>(el: T, prop: K, v: T[K]): () => void;
declare function setStyle(el: HTMLElement | null | undefined, style: Partial<CSSStyleDeclaration>): () => void;
declare function setStyleProperty(el: HTMLElement | null | undefined, prop: string, value: string): () => void;
//#endregion
//#region src/shared/dom-query/shared.d.ts
declare const MAX_Z_INDEX = 2147483647;
declare const dataAttr: (guard: boolean | undefined) => Booleanish;
declare const ariaAttr: (guard: boolean | undefined) => "true" | undefined;
//#endregion
//#region src/shared/dom-query/text-selection.d.ts
interface DisableTextSelectionOptions<T = MaybeElement> {
target?: T | undefined;
doc?: Document | undefined;
defer?: boolean | undefined;
}
declare function restoreTextSelection(options?: DisableTextSelectionOptions): void;
type MaybeElement = HTMLElement | null | undefined;
type NodeOrFn = MaybeElement | (() => MaybeElement);
declare function disableTextSelection(options?: DisableTextSelectionOptions<NodeOrFn>): () => void;
//#endregion
//#region src/shared/dom-query/typeahead.d.ts
interface TypeaheadState {
keysSoFar: string;
timer: number;
}
interface TypeaheadOptions<T> {
state: TypeaheadState;
activeId: string | null;
key: string;
timeout?: number | undefined;
itemToId?: ItemToId<T> | undefined;
}
declare function getByTypeaheadImpl<T extends SearchableItem>(baseItems: T[], options: TypeaheadOptions<T>): T | undefined;
declare const getByTypeahead: typeof getByTypeaheadImpl & {
defaultOptions: {
keysSoFar: string;
timer: number;
};
isValidEvent: typeof isValidTypeaheadEvent;
};
declare function isValidTypeaheadEvent(event: Pick<KeyboardEvent, "key" | "ctrlKey" | "metaKey">): boolean;
//#endregion
//#region src/shared/dom-query/visual-viewport.d.ts
interface ViewportSize {
width: number;
height: number;
}
declare function trackVisualViewport(doc: Document, fn: (data: ViewportSize) => void): () => void;
//#endregion
//#region src/shared/dom-query/visually-hidden.d.ts
declare const visuallyHiddenStyle: {
readonly border: "0";
readonly clip: "rect(0 0 0 0)";
readonly height: "1px";
readonly margin: "-1px";
readonly overflow: "hidden";
readonly padding: "0";
readonly position: "absolute";
readonly width: "1px";
readonly whiteSpace: "nowrap";
readonly wordWrap: "normal";
};
declare function setVisuallyHidden(el: HTMLElement): void;
//#endregion
//#region src/shared/dom-query/wait-for.d.ts
interface WaitForOptions {
timeout: number;
rootNode?: Document | ShadowRoot | undefined;
}
type WaitForPromiseReturn<T> = [Promise<T>, () => void];
declare function waitForPromise<T>(promise: Promise<T>, controller: AbortController, timeout: number): WaitForPromiseReturn<T>;
declare function waitForElement(target: () => HTMLElement | null, options: WaitForOptions): WaitForPromiseReturn<HTMLElement>;
type WaitForEventReturn<K extends keyof HTMLElementEventMap> = [Promise<HTMLElementEventMap[K]>, VoidFunction];
interface WaitForEventOptions<T extends HTMLElement = HTMLElement> extends AddEventListenerOptions {
predicate?: (element: T) => boolean;
}
declare function waitForEvent<T extends HTMLElement = HTMLElement, K extends keyof HTMLElementEventMap = keyof HTMLElementEventMap>(target: (() => HTMLElement | null) | undefined, event: K, options?: WaitForEventOptions<T>): WaitForEventReturn<K>;
//#endregion
export { getNextTabbable as $, hasControllerElements as $n, isElementVisible as $t, resizeObserverContentBox as A, getEventPoint as An, ScrollOptions as At, nextById as B, isModifierKey as Bn, getAncestorElements as Bt, setStyleProperty as C, markAsInternalChangeEvent as Cn, isIPhone as Ct, createScope as D, addDomEvent as Dn, isTouchDevice as Dt, ScopeContext as E, trackFormControl as En, isSafari as Et, raf as F, isContextMenuEvent as Fn, isInView as Ft, proxyTabFocus as G, isVirtualClick as Gn, getParentNode as Gt, query as H, isPrintableKey as Hn, getDocumentElement as Ht, ItemToId as I, isCtrlOrMetaKey as In, isOverflowElement as It, TabbableOptions as J, DataUrlType as Jn, isActiveElement as Jt, GetShadowRootOption as K, isVirtualPointerEvent as Kn, getRootNode as Kt, defaultItemToId as L, isDownloadingEvent as Ln, scrollIntoView as Lt, AnimationFrame as M, getEventTarget as Mn, getNearestOverflowAncestor as Mt, nextTick as N, getNativeEvent as Nn, getOverflowAncestors as Nt, getScale as O, getBeforeInputValue as On, isWebKit as Ot, queueBeforeEvent as P, isComposingEvent as Pn, getScrollPosition as Pt, getLastTabbable as Q, getControlledElements as Qn, isElement as Qt, indexOfId as R, isKeyboardClick as Rn, contains as Rt, setStyle as S, isInternalChangeEvent as Sn, isIPad as St, getByText as T, setElementValue as Tn, isMac as Tt, queryAll as U, isSelfTarget as Un, getNodeName as Ut, prevById as V, isOpeningInNewTab as Vn, getDocument as Vt, ProxyTabFocusOptions as W, isTouchEvent as Wn, getParentElement as Wt, getFirstTabbable as X, ControlledElementOptions as Xn, isDocument as Xt, getFirstFocusable as Y, getDataUrl as Yn, isAnchorElement as Yt, getFocusables as Z, findControlledElements as Zn, isEditableElement as Zt, MAX_Z_INDEX as _, CheckedEventOptions as _n, isAndroid as _t, waitForEvent as a, isVisualViewport as an, isCaretAtStart as ar, PressDetails as at, setAttribute as b, dispatchInputCheckedEvent as bn, isDom as bt, visuallyHiddenStyle as c, clickIfLink as cn, PointerMoveDetails as ct, TypeaheadOptions as d, ObserveChildrenOptions as dn, trackPointerMove as dt, isHTMLElement as en, isControlledByExpandedController as er, getTabIndex as et, TypeaheadState as f, observeAttributes as fn, requestPointerLock as ft, restoreTextSelection as g, isValidTabEvent as gn, getUserAgent as gt, disableTextSelection as h, getInitialFocus as hn, getPlatform as ht, waitForElement as i, isShadowRoot as in, getComputedStyle as ir, isTabbable as it, resizeObserverDevicePixelContentBox as j, getEventStep as jn, ScrollPosition as jt, resizeObserverBorderBox as k, getEventKey as kn, OverflowAncestor as kt, ViewportSize as l, navigate as ln, PointerMoveHandlers as lt, DisableTextSelectionOptions as m, InitialFocusOptions as mn, getRelativePoint as mt, WaitForOptions as n, isNode as nn, isControllerElement as nr, getTabbables as nt, waitForPromise as o, isWindow as on, setCaretToEnd as or, TrackPressOptions as ot, getByTypeahead as p, observeChildren as pn, PercentValueOptions as pt, NextTabbableOptions as q, DataUrlOptions as qn, getWindow as qt, WaitForPromiseReturn as r, isRootElement as rn, isInteractiveContainerElement as rr, isFocusable as rt, setVisuallyHidden as s, NavigateOptions as sn, trackPress as st, WaitForEventOptions as t, isInputElement as tn, isControlledElement as tr, getTabbableEdges as tt, trackVisualViewport as u, ObserveAttributeOptions as un, PointerUpDetails as ut, ariaAttr as v, InputValueEventOptions as vn, isApple as vt, SearchableItem as w, setElementChecked as wn, isIos as wt, setProperty as x, dispatchInputValueEvent as xn, isFirefox as xt, dataAttr as y, TrackFormControlOptions as yn, isChrome as yt, itemById as z, isLeftClick as zn, getActiveElement as zt };
import { i as InteractOutsideHandlers } from "./index-jO45BUcW.cjs";
import { MaybeFunction } from "@ginxjs/core/utils";
//#region src/shared/dismissable/layer-stack.d.ts
type LayerType = "dialog" | "popover" | "menu" | "listbox" | (string & {});
type LayerDismissEventDetail = {
originalLayer: HTMLElement;
targetLayer: HTMLElement | undefined;
originalIndex: number;
targetIndex: number;
};
type LayerDismissEvent = CustomEvent<LayerDismissEventDetail>;
type LayerStyleTarget = () => HTMLElement | null;
//#endregion
//#region src/shared/dismissable/dismissable-layer.d.ts
type MaybeElement = HTMLElement | null;
type Container = MaybeElement | Array<MaybeElement>;
type NodeOrFn = MaybeFunction<MaybeElement>;
interface DismissableElementHandlers extends InteractOutsideHandlers {
onEscapeKeyDown?: ((event: KeyboardEvent) => void) | undefined;
onRequestDismiss?: ((event: LayerDismissEvent) => void) | undefined;
}
interface PersistentElementOptions {
persistentElements?: Array<() => Element | null> | undefined;
}
interface DismissableElementOptions extends DismissableElementHandlers, PersistentElementOptions {
layerStyleTargets?: LayerStyleTarget[] | undefined;
debug?: boolean | undefined;
pointerBlocking?: boolean | undefined;
onDismiss: VoidFunction;
exclude?: MaybeFunction<Container> | undefined;
defer?: boolean | undefined;
warnOnMissingNode?: boolean | undefined;
type?: LayerType | undefined;
}
declare function trackDismissableElement(nodeOrFn: NodeOrFn, options: DismissableElementOptions): () => void;
declare function trackDismissableBranch(nodeOrFn: NodeOrFn, options?: {
defer?: boolean | undefined;
}): () => void;
//#endregion
export { trackDismissableElement as a, trackDismissableBranch as i, DismissableElementOptions as n, LayerStyleTarget as o, PersistentElementOptions as r, LayerType as s, DismissableElementHandlers as t };

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

import { Jt as isActiveElement } from "./index-BhthKUrF.mjs";
//#region src/shared/core/merge-props.d.ts
interface Props {
[key: string | symbol]: any;
}
type TupleTypes<T extends any[]> = T[number];
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
declare function mergeProps<T extends Props>(...args: Array<T | undefined>): UnionToIntersection<TupleTypes<T[]>>;
//#endregion
//#region src/shared/core/memo.d.ts
type NoInfer<T> = [T][T extends any ? 0 : never];
declare function memo<TDeps extends any[], TDepArgs, TResult>(getDeps: (depArgs: TDepArgs) => [...TDeps], fn: (args: NoInfer<[...TDeps]>, deps: TDepArgs) => TResult, opts?: {
onChange?: ((result: TResult) => void) | undefined;
}): (depArgs: TDepArgs) => TResult;
//#endregion
//#region src/shared/core/types.d.ts
type Dict = Record<string, any>;
interface ComputedParams<T extends Dict> {
context: BindableContext<T>;
event: EventType<T["event"]>;
prop: PropFn<T>;
refs: BindableRefs<T>;
scope: Scope;
computed: ComputedFn<T>;
}
interface ContextParams<T extends Dict> {
prop: PropFn<T>;
bindable: BindableFn;
scope: Scope;
getContext: () => BindableContext<T>;
getComputed: () => ComputedFn<T>;
getRefs: () => BindableRefs<T>;
getEvent: () => EventType<T["event"]>;
flush: (fn: VoidFunction) => void;
}
interface PropFn<T extends Dict> {
<K extends keyof T["props"]>(key: K): T["props"][K];
}
interface ComputedFn<T extends Dict> {
<K extends keyof T["computed"]>(key: K): T["computed"][K];
}
type AnyFunction = () => string | number | boolean | null | undefined;
type TrackFn = (deps: AnyFunction[], fn: VoidFunction) => void;
interface BindableParams<T> {
defaultValue?: T | undefined;
value?: T | undefined;
hash?: ((a: T) => string) | undefined;
isEqual?: ((a: T, b: T | undefined) => boolean) | undefined;
onChange?: ((value: T, prev: T | undefined) => void) | undefined;
debug?: string | undefined;
sync?: boolean | undefined;
}
type ValueOrFn<T> = T | ((prev: T) => T);
interface Bindable<T> {
initial: T | undefined;
ref: any;
get: () => T;
set(value: ValueOrFn<T>): void;
invoke(nextValue: T, prevValue: T): void;
hash(value: T): string;
}
interface BindableRefs<T extends Dict> {
set<K extends keyof T["refs"]>(key: K, value: T["refs"][K]): void;
get<K extends keyof T["refs"]>(key: K): T["refs"][K];
}
interface BindableContext<T extends Dict> {
set<K extends keyof T["context"]>(key: K, value: ValueOrFn<T["context"][K]>): void;
get<K extends keyof T["context"]>(key: K): T["context"][K];
initial<K extends keyof T["context"]>(key: K): T["context"][K];
hash<K extends keyof T["context"]>(key: K): string;
}
interface BindableRef<T> {
get: () => T;
set: (next: T) => void;
}
interface BindableFn {
<K>(params: () => BindableParams<K>): Bindable<K>;
cleanup: (fn: VoidFunction) => void;
ref: <T>(defaultValue: T) => BindableRef<T>;
}
interface Scope {
id?: string | undefined;
ids?: Record<string, any> | undefined;
getRootNode: () => ShadowRoot | Document | Node;
getById: <T extends Element = HTMLElement>(id: string) => T | null;
getActiveElement: () => HTMLElement | null;
isActiveElement: (elem: HTMLElement | null) => boolean;
getDoc: () => typeof document;
getWin: () => typeof window;
}
type EventType<T = any> = T & {
previousEvent?: (T & {
[key: string]: any;
}) | undefined;
src?: string | undefined;
[key: string]: any;
};
type EventObject = EventType<{
type: string;
}>;
interface Params<T extends Dict> {
prop: PropFn<T>;
action: (action: T["action"][]) => void;
context: BindableContext<T>;
refs: BindableRefs<T>;
track: TrackFn;
flush: (fn: VoidFunction) => void;
event: EventType<T["event"]> & {
current: () => EventType<T["event"]>;
previous: () => EventType<T["event"]>;
};
send: (event: EventType<T["event"]>) => void;
computed: ComputedFn<T>;
scope: Scope;
state: Bindable<T["state"]> & {
matches: (...values: T["state"][]) => boolean;
hasTag: (tag: T["tag"]) => boolean;
};
choose: ChooseFn<T>;
guard: (key: T["guard"] | GuardFn<T>) => boolean | undefined;
}
type GuardFn<T extends Dict> = (params: Params<T>) => boolean;
type TopLevelState<S extends string> = S extends `${infer Top}.${string}` ? Top : S;
type ChildStateKey<S extends string, Parent extends string> = S extends `${Parent}.${infer Rest}` ? Rest extends `${infer Child}.${string}` ? Child : Rest : never;
type ParentPath<S extends string> = S extends `${infer Parent}.${string}` ? Parent : never;
type AncestorPaths<S extends string> = S | (ParentPath<S> extends never ? never : AncestorPaths<ParentPath<S>>);
type StateIdTarget = `#${string}`;
type SiblingStateTarget<S extends string, Source extends string> = TopLevelState<S> | ChildStateKey<S, Exclude<AncestorPaths<Source>, Source>>;
type ChildStateTarget<S extends string, Source extends string> = `.${ChildStateKey<S, Source>}`;
interface Transition<T extends Dict, Source extends string | undefined = string | undefined> {
target?: T["state"] | StateIdTarget | (Source extends string ? SiblingStateTarget<T["state"], Source> : never) | (Source extends string ? ChildStateTarget<T["state"], Source> : never) | undefined;
actions?: T["action"][] | undefined;
guard?: T["guard"] | GuardFn<T> | undefined;
reenter?: boolean | undefined;
}
type TransitionSet<T extends Dict> = Transition<T> | Transition<T>[] | undefined;
type TransitionMap<T extends Dict> = Record<string, TransitionSet<T>>;
type TransitionMatch<T extends Dict> = {
transitions: TransitionSet<T>;
source: string | undefined;
};
type MaybeArray<T> = T | T[];
type ChooseFn<T extends Dict> = (transitions: MaybeArray<Omit<Transition<T, string>, "target">> | null | undefined) => Transition<T> | undefined;
interface PropsParams<T extends Dict> {
props: Partial<T["props"]>;
scope: Scope;
}
interface RefsParams<T extends Dict> {
prop: PropFn<T>;
context: BindableContext<T>;
}
type ActionsOrFn<T extends Dict> = T["action"][] | ((params: Params<T>) => T["action"][] | undefined);
type EffectsOrFn<T extends Dict> = T["effect"][] | ((params: Params<T>) => T["effect"][] | undefined);
interface MachineState<T extends Dict, Parent extends string = string> {
id?: string | undefined;
tags?: T["tag"][] | undefined;
entry?: ActionsOrFn<T> | undefined;
exit?: ActionsOrFn<T> | undefined;
effects?: EffectsOrFn<T> | undefined;
initial?: ChildStateKey<T["state"], Parent> | undefined;
states?: { [K in ChildStateKey<T["state"], Parent>]?: MachineState<T, `${Parent}.${K}`> } | undefined;
on?: { [E in T["event"]["type"]]?: Transition<T, Parent> | Array<Transition<T, Parent>> } | undefined;
}
interface Machine<T extends Dict> {
debug?: boolean | undefined;
props?: ((params: PropsParams<T>) => T["props"]) | undefined;
context?: ((params: ContextParams<T>) => { [K in keyof T["context"]]: Bindable<T["context"][K]> }) | undefined;
computed?: { [K in keyof T["computed"]]: (params: ComputedParams<T>) => T["computed"][K] } | undefined;
initialState: (params: {
prop: PropFn<T>;
}) => T["state"];
entry?: ActionsOrFn<T> | undefined;
exit?: ActionsOrFn<T> | undefined;
effects?: EffectsOrFn<T> | undefined;
refs?: ((params: RefsParams<T>) => T["refs"]) | undefined;
watch?: ((params: Params<T>) => void) | undefined;
on?: { [E in T["event"]["type"]]?: Transition<T, undefined> | Array<Transition<T, undefined>> } | undefined;
states: { [K in TopLevelState<T["state"]>]: MachineState<T, K> };
implementations?: {
guards?: { [K in T["guard"]]: (params: Params<T>) => boolean } | undefined;
actions?: { [K in T["action"]]: (params: Params<T>) => void } | undefined;
effects?: { [K in T["effect"]]: (params: Params<T>) => void | VoidFunction } | undefined;
} | undefined;
}
interface MachineBaseProps {
id?: string | undefined;
ids?: Record<string, any> | undefined;
getRootNode?: (() => ShadowRoot | Document | Node) | undefined;
[key: string]: any;
}
interface MachineSchema {
props?: MachineBaseProps | undefined;
context?: Record<string, any> | undefined;
refs?: Record<string, any> | undefined;
computed?: Record<string, any> | undefined;
state?: string | undefined;
tag?: string | undefined;
guard?: string | undefined;
action?: string | undefined;
effect?: string | undefined;
event?: ({
type: string;
} & Dict) | undefined;
}
type State<T extends MachineSchema> = Bindable<T["state"]> & {
hasTag: (tag: T["tag"]) => boolean;
matches: (...values: T["state"][]) => boolean;
};
type Service<T extends MachineSchema> = {
getStatus: () => MachineStatus;
state: State<T> & {
matches: (...values: T["state"][]) => boolean;
hasTag: (tag: T["tag"]) => boolean;
};
context: BindableContext<T>;
send: (event: EventType<T["event"]>) => void;
prop: PropFn<T>;
scope: Scope;
computed: ComputedFn<T>;
refs: BindableRefs<T>;
event: EventType<T["event"]> & {
current: () => EventType<T["event"]>;
previous: () => EventType<T["event"]>;
};
};
declare enum MachineStatus {
NotStarted = "Not Started",
Started = "Started",
Stopped = "Stopped"
}
declare const INIT_STATE = "__init__";
//#endregion
//#region src/shared/core/create-machine.d.ts
declare function createGuards<T extends MachineSchema>(): {
and: (...guards: Array<GuardFn<T> | T["guard"]>) => (params: any) => boolean;
or: (...guards: Array<GuardFn<T> | T["guard"]>) => (params: any) => boolean;
not: (guard: GuardFn<T> | T["guard"]) => (params: any) => boolean;
};
declare function createMachine<T extends MachineSchema>(config: Machine<T>): Machine<T>;
declare function setup<T extends MachineSchema>(): {
guards: {
and: (...guards: (GuardFn<T> | T["guard"])[]) => (params: any) => boolean;
or: (...guards: (GuardFn<T> | T["guard"])[]) => (params: any) => boolean;
not: (guard: GuardFn<T> | T["guard"]) => (params: any) => boolean;
};
createMachine: (config: Machine<T>) => Machine<T>;
choose: (transitions: Transition<T> | Transition<T>[]) => ({
choose
}: Params<T>) => T["action"][] | undefined;
};
//#endregion
//#region src/shared/core/state.d.ts
declare function ensureStateIndex<T extends MachineSchema>(machine: Machine<T>): Map<string, MachineState<T, string>>;
type StateChain<T extends MachineSchema> = Array<{
path: string;
state: MachineState<T>;
}>;
declare function getStateChain<T extends MachineSchema>(machine: Machine<T>, state: T["state"] | undefined): StateChain<T>;
declare function resolveStateValue<T extends MachineSchema>(machine: Machine<T>, value: T["state"] | string, source?: string): T["state"];
declare function getStateDefinition<T extends MachineSchema>(machine: Machine<T>, state: T["state"]): MachineState<T, string>;
declare function findTransition<T extends MachineSchema>(machine: Machine<T>, state: T["state"], eventType: string): TransitionMatch<T>;
declare function getExitEnterStates<T extends MachineSchema>(machine: Machine<T>, prevState: T["state"] | undefined, nextState: T["state"], reenter?: boolean): {
exiting: {
path: string;
state: MachineState<T, string>;
}[];
entering: {
path: string;
state: MachineState<T, string>;
}[];
};
declare function matchesState(current: string | undefined, value: string): boolean;
declare function hasTag<T extends MachineSchema>(machine: Machine<T>, state: T["state"], tag: T["tag"]): boolean;
//#endregion
//#region src/shared/core/scope.d.ts
declare function createScope(props: Pick<Scope, "id" | "ids" | "getRootNode">): {
getRootNode: () => Document | ShadowRoot;
getDoc: () => Document;
getWin: () => Window & typeof globalThis;
getActiveElement: () => HTMLElement | null;
isActiveElement: typeof isActiveElement;
getById: <T extends Element = HTMLElement>(id: string) => T | null;
ids?: Record<string, any> | undefined;
id?: string | undefined | undefined;
};
//#endregion
export { PropFn as A, GuardFn as C, MachineState as D, MachineSchema as E, TransitionMatch as F, TransitionSet as I, ValueOrFn as L, Service as M, Transition as N, MachineStatus as O, TransitionMap as P, memo as R, EventObject as S, Machine as T, BindableParams as _, getStateChain as a, ComputedFn as b, matchesState as c, createMachine as d, setup as f, BindableFn as g, BindableContext as h, getExitEnterStates as i, Scope as j, Params as k, resolveStateValue as l, Bindable as m, ensureStateIndex as n, getStateDefinition as o, ActionsOrFn as p, findTransition as r, hasTag as s, createScope as t, createGuards as u, BindableRefs as v, INIT_STATE as w, EffectsOrFn as x, ChooseFn as y, mergeProps as z };
//#region src/shared/interact-outside/index.d.ts
interface InteractOutsideHandlers {
onPointerDownOutside?: ((event: PointerDownOutsideEvent) => void) | undefined;
onFocusOutside?: ((event: FocusOutsideEvent) => void) | undefined;
onInteractOutside?: ((event: InteractOutsideEvent) => void) | undefined;
}
interface InteractOutsideOptions extends InteractOutsideHandlers {
exclude?: ((target: HTMLElement) => boolean) | undefined;
defer?: boolean | undefined;
followControlledElements?: boolean | undefined;
}
interface EventDetails<T> {
originalEvent: T;
contextmenu: boolean;
focusable: boolean;
target: EventTarget;
}
type PointerDownOutsideEvent = CustomEvent<EventDetails<PointerEvent>>;
type FocusOutsideEvent = CustomEvent<EventDetails<FocusEvent>>;
type InteractOutsideEvent = PointerDownOutsideEvent | FocusOutsideEvent;
type MaybeElement = HTMLElement | null | undefined;
type NodeOrFn = MaybeElement | (() => MaybeElement);
declare function trackInteractOutside(nodeOrFn: NodeOrFn, options: InteractOutsideOptions): () => void;
//#endregion
export { InteractOutsideOptions as a, PointerDownOutsideEvent as c, InteractOutsideHandlers as i, trackInteractOutside as l, FocusOutsideEvent as n, MaybeElement as o, InteractOutsideEvent as r, NodeOrFn as s, EventDetails as t };
import { i as InteractOutsideHandlers } from "./index-C3Jj4aYp.mjs";
import { MaybeFunction } from "@ginxjs/core/utils";
//#region src/shared/dismissable/layer-stack.d.ts
type LayerType = "dialog" | "popover" | "menu" | "listbox" | (string & {});
type LayerDismissEventDetail = {
originalLayer: HTMLElement;
targetLayer: HTMLElement | undefined;
originalIndex: number;
targetIndex: number;
};
type LayerDismissEvent = CustomEvent<LayerDismissEventDetail>;
type LayerStyleTarget = () => HTMLElement | null;
//#endregion
//#region src/shared/dismissable/dismissable-layer.d.ts
type MaybeElement = HTMLElement | null;
type Container = MaybeElement | Array<MaybeElement>;
type NodeOrFn = MaybeFunction<MaybeElement>;
interface DismissableElementHandlers extends InteractOutsideHandlers {
onEscapeKeyDown?: ((event: KeyboardEvent) => void) | undefined;
onRequestDismiss?: ((event: LayerDismissEvent) => void) | undefined;
}
interface PersistentElementOptions {
persistentElements?: Array<() => Element | null> | undefined;
}
interface DismissableElementOptions extends DismissableElementHandlers, PersistentElementOptions {
layerStyleTargets?: LayerStyleTarget[] | undefined;
debug?: boolean | undefined;
pointerBlocking?: boolean | undefined;
onDismiss: VoidFunction;
exclude?: MaybeFunction<Container> | undefined;
defer?: boolean | undefined;
warnOnMissingNode?: boolean | undefined;
type?: LayerType | undefined;
}
declare function trackDismissableElement(nodeOrFn: NodeOrFn, options: DismissableElementOptions): () => void;
declare function trackDismissableBranch(nodeOrFn: NodeOrFn, options?: {
defer?: boolean | undefined;
}): () => void;
//#endregion
export { trackDismissableElement as a, trackDismissableBranch as i, DismissableElementOptions as n, LayerStyleTarget as o, PersistentElementOptions as r, LayerType as s, DismissableElementHandlers as t };
import { AutoUpdateOptions, Boundary, ComputePositionReturn, Placement, Placement as Placement$1, VirtualElement } from "@floating-ui/dom";
//#region src/shared/popper/types.d.ts
type MaybeRectElement = HTMLElement | VirtualElement | null;
type MaybeElement = HTMLElement | null;
type MaybeFn<T> = T | (() => T);
type PlacementSide = "top" | "right" | "bottom" | "left";
type PlacementAlign = "start" | "center" | "end";
interface AnchorRect {
x?: number | undefined;
y?: number | undefined;
width?: number | undefined;
height?: number | undefined;
}
interface PositioningOptions {
/**
* Whether styles applied by the positioning utility should be restored on cleanup.
*/
restoreStyles?: boolean | undefined;
/**
* Whether the popover should be hidden when the reference element is detached
*/
hideWhenDetached?: boolean | undefined;
/**
* The strategy to use for positioning
*/
strategy?: "absolute" | "fixed" | undefined;
/**
* The initial placement of the floating element
*/
placement?: Placement$1 | undefined;
/**
* The offset of the floating element
*/
offset?: {
mainAxis?: number | undefined;
crossAxis?: number | undefined;
} | undefined;
/**
* The main axis offset or gap between the reference and floating elements
*/
gutter?: number | undefined;
/**
* The secondary axis offset or gap between the reference and floating elements
*/
shift?: number | undefined;
/**
* The virtual padding around the viewport edges to check for overflow
*/
overflowPadding?: number | undefined;
/**
* The minimum padding between the arrow and the floating element's corner.
* @default 4
*/
arrowPadding?: number | undefined;
/**
* Whether to flip the placement
*/
flip?: boolean | Placement$1[] | undefined;
/**
* Whether the popover should slide when it overflows.
*/
slide?: boolean | undefined;
/**
* Whether the floating element can overlap the reference element
* @default false
*/
overlap?: boolean | undefined;
/**
* Whether to make the floating element same width as the reference element
*/
sameWidth?: boolean | undefined;
/**
* Whether the popover should fit the viewport.
*/
fitViewport?: boolean | undefined;
/**
* Whether to use the size middleware from Floating UI.
* It computes and sets CSS variables (`--reference-width`, `--reference-height`, `--available-width`, `--available-height`) used by `sameWidth` and `fitViewport`.
*
* Disabling it improves scroll performance with heavy content by avoiding layout thrashing on each update.
* Only applies when both `sameWidth` and `fitViewport` are false — the middleware is always used when either is enabled.
* @default true
*/
sizeMiddleware?: boolean | undefined;
/**
* The overflow boundary of the reference element
* Accepts a function returning a Boundary, a Boundary directly,
* or the shorthand string 'clipping-ancestors' which maps to Floating UI's 'clippingAncestors'.
*/
boundary?: (() => Boundary) | Boundary | "clipping-ancestors" | undefined;
/**
* Options to activate auto-update listeners
*/
listeners?: boolean | AutoUpdateOptions | undefined;
/**
* Function called when the placement is computed
*/
onComplete?: ((data: ComputePositionReturn) => void) | undefined;
/**
* Function called when the floating element is positioned or not
*/
onPositioned?: ((data: {
placed: boolean;
}) => void) | undefined;
/**
* Function that returns the anchor element.
* Useful when you want to use a different element as the anchor.
*/
getAnchorElement?: (() => HTMLElement | VirtualElement | null) | undefined;
/**
* Function that returns the anchor rect
* @deprecated Use `getAnchorElement` instead
*/
getAnchorRect?: ((element: HTMLElement | VirtualElement | null) => AnchorRect | null) | undefined;
/**
* A callback that will be called when the popover needs to calculate its
* position.
*/
updatePosition?: ((data: {
updatePosition: () => Promise<void>;
floatingElement: HTMLElement | null;
}) => void | Promise<void>) | undefined;
}
//#endregion
//#region src/shared/popper/get-placement.d.ts
declare function getPlacement(referenceOrFn: MaybeFn<MaybeRectElement>, floatingOrFn: MaybeFn<MaybeElement>, opts?: PositioningOptions & {
defer?: boolean | undefined;
}): () => void;
//#endregion
//#region src/shared/popper/middleware.d.ts
declare const cssVars: {
arrowSize: {
variable: string;
reference: string;
};
arrowSizeHalf: {
variable: string;
reference: string;
};
arrowBg: {
variable: string;
reference: string;
};
transformOrigin: {
variable: string;
reference: string;
};
arrowOffset: {
variable: string;
reference: string;
};
};
//#endregion
//#region src/shared/popper/get-styles.d.ts
interface GetPlacementStylesOptions {
placement?: Placement | undefined;
}
declare function getPlacementStyles(options?: Pick<PositioningOptions, "placement" | "sameWidth" | "fitViewport" | "strategy">): {
arrow: {
readonly [cssVars.arrowSizeHalf.variable]: `calc(${string} / 2)`;
readonly [cssVars.arrowOffset.variable]: `calc(${string} * -1)`;
readonly position: "absolute";
readonly width: string;
readonly height: string;
};
arrowTip: {
readonly transform: any;
readonly background: string;
readonly top: "0";
readonly left: "0";
readonly width: "100%";
readonly height: "100%";
readonly position: "absolute";
readonly zIndex: "inherit";
};
floating: {
readonly position: "absolute" | "fixed";
readonly isolation: "isolate";
readonly minWidth: "max-content" | undefined;
readonly width: "var(--reference-width)" | undefined;
readonly maxWidth: "var(--available-width)" | undefined;
readonly maxHeight: "var(--available-height)" | undefined;
readonly pointerEvents: "none" | undefined;
readonly top: "0px";
readonly left: "0px";
readonly transform: "translate3d(var(--x), var(--y), 0)" | "translate3d(0, -100vh, 0)";
readonly zIndex: "var(--z-index)";
};
};
//#endregion
//#region src/shared/popper/placement.d.ts
declare function isValidPlacement(v: string): v is Placement;
declare function getPlacementSide(placement: Placement): PlacementSide;
//#endregion
export { getPlacement as a, Boundary as c, PlacementAlign as d, PlacementSide as f, getPlacementStyles as i, ComputePositionReturn as l, isValidPlacement as n, AnchorRect as o, PositioningOptions as p, GetPlacementStylesOptions as r, AutoUpdateOptions as s, getPlacementSide as t, Placement$1 as u };
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_core = require("./core-DH_mBI7F.cjs");
exports.INIT_STATE = require_core.INIT_STATE;
exports.MachineStatus = require_core.MachineStatus;
exports.createGuards = require_core.createGuards;
exports.createMachine = require_core.createMachine;
exports.createScope = require_core.createScope;
exports.ensureStateIndex = require_core.ensureStateIndex;
exports.findTransition = require_core.findTransition;
exports.getExitEnterStates = require_core.getExitEnterStates;
exports.getStateChain = require_core.getStateChain;
exports.getStateDefinition = require_core.getStateDefinition;
exports.hasTag = require_core.hasTag;
exports.matchesState = require_core.matchesState;
exports.memo = require_core.memo;
exports.mergeProps = require_core.mergeProps;
exports.resolveStateValue = require_core.resolveStateValue;
exports.setup = require_core.setup;
import { A as PropFn, C as GuardFn, D as MachineState, E as MachineSchema, F as TransitionMatch, I as TransitionSet, L as ValueOrFn, M as Service, N as Transition, O as MachineStatus, P as TransitionMap, R as memo, S as EventObject, T as Machine, _ as BindableParams, a as getStateChain, b as ComputedFn, c as matchesState, d as createMachine, f as setup, g as BindableFn, h as BindableContext, i as getExitEnterStates, j as Scope, k as Params, l as resolveStateValue, m as Bindable, n as ensureStateIndex, o as getStateDefinition, p as ActionsOrFn, r as findTransition, s as hasTag, t as createScope, u as createGuards, v as BindableRefs, w as INIT_STATE, x as EffectsOrFn, y as ChooseFn, z as mergeProps } from "./index-BNaxg4iu.cjs";
export { ActionsOrFn, Bindable, BindableContext, BindableFn, BindableParams, BindableRefs, ChooseFn, ComputedFn, EffectsOrFn, EventObject, GuardFn, INIT_STATE, Machine, MachineSchema, MachineState, MachineStatus, Params, PropFn, Scope, Service, Transition, TransitionMap, TransitionMatch, TransitionSet, ValueOrFn, createGuards, createMachine, createScope, ensureStateIndex, findTransition, getExitEnterStates, getStateChain, getStateDefinition, hasTag, matchesState, memo, mergeProps, resolveStateValue, setup };
import { A as PropFn, C as GuardFn, D as MachineState, E as MachineSchema, F as TransitionMatch, I as TransitionSet, L as ValueOrFn, M as Service, N as Transition, O as MachineStatus, P as TransitionMap, R as memo, S as EventObject, T as Machine, _ as BindableParams, a as getStateChain, b as ComputedFn, c as matchesState, d as createMachine, f as setup, g as BindableFn, h as BindableContext, i as getExitEnterStates, j as Scope, k as Params, l as resolveStateValue, m as Bindable, n as ensureStateIndex, o as getStateDefinition, p as ActionsOrFn, r as findTransition, s as hasTag, t as createScope, u as createGuards, v as BindableRefs, w as INIT_STATE, x as EffectsOrFn, y as ChooseFn, z as mergeProps } from "./index-g2S6NCuN.mjs";
export { ActionsOrFn, Bindable, BindableContext, BindableFn, BindableParams, BindableRefs, ChooseFn, ComputedFn, EffectsOrFn, EventObject, GuardFn, INIT_STATE, Machine, MachineSchema, MachineState, MachineStatus, Params, PropFn, Scope, Service, Transition, TransitionMap, TransitionMatch, TransitionSet, ValueOrFn, createGuards, createMachine, createScope, ensureStateIndex, findTransition, getExitEnterStates, getStateChain, getStateDefinition, hasTag, matchesState, memo, mergeProps, resolveStateValue, setup };
import { a as createMachine, c as findTransition, d as getStateDefinition, f as hasTag, g as mergeProps, h as memo, i as createGuards, l as getExitEnterStates, m as resolveStateValue, n as INIT_STATE, o as setup, p as matchesState, r as MachineStatus, s as ensureStateIndex, t as createScope, u as getStateChain } from "./core-D3PQ0tSv.mjs";
export { INIT_STATE, MachineStatus, createGuards, createMachine, createScope, ensureStateIndex, findTransition, getExitEnterStates, getStateChain, getStateDefinition, hasTag, matchesState, memo, mergeProps, resolveStateValue, setup };
import { G as raf, M as getNearestOverflowAncestor, Ut as isTouchDevice, Xt as isControlledElement, bn as isShadowRoot, dt as addDomEvent, en as contains, gn as isHTMLElement, gt as getEventTarget, ln as getWindow, nt as isFocusable, rn as getDocument, yt as isContextMenuEvent } from "./dom-query-BgxIO7_X.mjs";
import { callAll } from "@ginxjs/core/utils";
//#region src/shared/interact-outside/frame-utils.ts
function getWindowFrames(win) {
const frames = {
each(cb) {
for (let i = 0; i < win.frames?.length; i += 1) {
const frame = win.frames[i];
if (frame) cb(frame);
}
},
addEventListener(event, listener, options) {
frames.each((frame) => {
try {
frame.document.addEventListener(event, listener, options);
} catch {}
});
return () => {
try {
frames.removeEventListener(event, listener, options);
} catch {}
};
},
removeEventListener(event, listener, options) {
frames.each((frame) => {
try {
frame.document.removeEventListener(event, listener, options);
} catch {}
});
}
};
return frames;
}
function getParentWindow(win) {
const parent = win.frameElement != null ? win.parent : null;
return {
addEventListener: (event, listener, options) => {
try {
parent?.addEventListener(event, listener, options);
} catch {}
return () => {
try {
parent?.removeEventListener(event, listener, options);
} catch {}
};
},
removeEventListener: (event, listener, options) => {
try {
parent?.removeEventListener(event, listener, options);
} catch {}
}
};
}
//#endregion
//#region src/shared/interact-outside/index.ts
const POINTER_OUTSIDE_EVENT = "pointerdown.outside";
const FOCUS_OUTSIDE_EVENT = "focus.outside";
function isComposedPathFocusable(composedPath) {
for (const node of composedPath) if (isHTMLElement(node) && isFocusable(node)) return true;
return false;
}
const isPointerEvent = (event) => "clientY" in event;
function isEventPointWithin(node, event) {
if (!isPointerEvent(event) || !node) return false;
const rect = node.getBoundingClientRect();
if (rect.width === 0 || rect.height === 0) return false;
return rect.top <= event.clientY && event.clientY <= rect.top + rect.height && rect.left <= event.clientX && event.clientX <= rect.left + rect.width;
}
function isPointInRect(rect, point) {
return rect.y <= point.y && point.y <= rect.y + rect.height && rect.x <= point.x && point.x <= rect.x + rect.width;
}
function isEventWithinScrollbar(event, ancestor) {
if (!ancestor || !isPointerEvent(event)) return false;
const isScrollableY = ancestor.scrollHeight > ancestor.clientHeight;
const onScrollbarY = isScrollableY && event.clientX > ancestor.offsetLeft + ancestor.clientWidth;
const isScrollableX = ancestor.scrollWidth > ancestor.clientWidth;
const onScrollbarX = isScrollableX && event.clientY > ancestor.offsetTop + ancestor.clientHeight;
if (!isPointInRect({
x: ancestor.offsetLeft,
y: ancestor.offsetTop,
width: ancestor.clientWidth + (isScrollableY ? 16 : 0),
height: ancestor.clientHeight + (isScrollableX ? 16 : 0)
}, {
x: event.clientX,
y: event.clientY
})) return false;
return onScrollbarY || onScrollbarX;
}
function trackInteractOutsideImpl(node, options) {
const { exclude, onFocusOutside, onPointerDownOutside, onInteractOutside, defer, followControlledElements = true } = options;
if (!node) return;
const doc = getDocument(node);
const win = getWindow(node);
const frames = getWindowFrames(win);
const parentWin = getParentWindow(win);
function isEventOutside(event, target) {
if (!isHTMLElement(target)) return false;
if (!target.isConnected) return false;
if (contains(node, target)) return false;
if (isEventPointWithin(node, event)) return false;
if (followControlledElements && isControlledElement(node, target)) return false;
const triggerEl = doc.querySelector(`[aria-controls="${node.id}"]`);
if (triggerEl) {
if (isEventWithinScrollbar(event, getNearestOverflowAncestor(triggerEl))) return false;
}
if (isEventWithinScrollbar(event, getNearestOverflowAncestor(node))) return false;
return !exclude?.(target);
}
const pointerdownCleanups = /* @__PURE__ */ new Set();
const isInShadowRoot = isShadowRoot(node?.getRootNode());
let isPointerDown = false;
function onPointerDown(event) {
isPointerDown = true;
const onPointerUp = () => {
isPointerDown = false;
};
doc.addEventListener("pointerup", onPointerUp, { once: true });
win.addEventListener("pointerup", onPointerUp, { once: true });
function handler(clickEvent) {
const func = defer && !isTouchDevice() ? raf : (v) => v();
const evt = clickEvent ?? event;
const composedPath = evt?.composedPath?.() ?? [evt?.target];
func(() => {
const target = isInShadowRoot ? composedPath[0] : getEventTarget(event);
if (!node || !isEventOutside(event, target)) return;
if (onPointerDownOutside || onInteractOutside) {
const handler = callAll(onPointerDownOutside, onInteractOutside);
node.addEventListener(POINTER_OUTSIDE_EVENT, handler, { once: true });
}
fireCustomEvent(node, POINTER_OUTSIDE_EVENT, {
bubbles: false,
cancelable: true,
detail: {
originalEvent: evt,
contextmenu: isContextMenuEvent(evt),
focusable: isComposedPathFocusable(composedPath),
target
}
});
});
}
if (event.pointerType === "touch") {
pointerdownCleanups.forEach((fn) => fn());
pointerdownCleanups.add(addDomEvent(doc, "click", handler, { once: true }));
pointerdownCleanups.add(parentWin.addEventListener("click", handler, { once: true }));
pointerdownCleanups.add(frames.addEventListener("click", handler, { once: true }));
} else handler();
}
const cleanups = /* @__PURE__ */ new Set();
const timer = setTimeout(() => {
cleanups.add(addDomEvent(doc, "pointerdown", onPointerDown, true));
cleanups.add(parentWin.addEventListener("pointerdown", onPointerDown, true));
cleanups.add(frames.addEventListener("pointerdown", onPointerDown, true));
}, 0);
function onFocusin(event) {
if (isPointerDown) return;
(defer ? raf : (v) => v())(() => {
const composedPath = event?.composedPath?.() ?? [event?.target];
const target = isInShadowRoot ? composedPath[0] : getEventTarget(event);
if (!node || !isEventOutside(event, target)) return;
if (onFocusOutside || onInteractOutside) {
const handler = callAll(onFocusOutside, onInteractOutside);
node.addEventListener(FOCUS_OUTSIDE_EVENT, handler, { once: true });
}
fireCustomEvent(node, FOCUS_OUTSIDE_EVENT, {
bubbles: false,
cancelable: true,
detail: {
originalEvent: event,
contextmenu: false,
focusable: isFocusable(target),
target
}
});
});
}
if (!isTouchDevice()) {
cleanups.add(addDomEvent(doc, "focusin", onFocusin, true));
cleanups.add(parentWin.addEventListener("focusin", onFocusin, true));
cleanups.add(frames.addEventListener("focusin", onFocusin, true));
}
return () => {
clearTimeout(timer);
pointerdownCleanups.forEach((fn) => fn());
cleanups.forEach((fn) => fn());
};
}
function trackInteractOutside(nodeOrFn, options) {
const { defer } = options;
const func = defer ? raf : (v) => v();
const cleanups = [];
cleanups.push(func(() => {
const node = typeof nodeOrFn === "function" ? nodeOrFn() : nodeOrFn;
cleanups.push(trackInteractOutsideImpl(node, options));
}));
return () => {
cleanups.forEach((fn) => fn?.());
};
}
function fireCustomEvent(el, type, init) {
const event = new (el.ownerDocument.defaultView || window).CustomEvent(type, init);
return el.dispatchEvent(event);
}
//#endregion
export { trackInteractOutside as t };
const require_dom_query = require("./dom-query-BT6fffRP.cjs");
let _ginxjs_core_utils = require("@ginxjs/core/utils");
//#region src/shared/interact-outside/frame-utils.ts
function getWindowFrames(win) {
const frames = {
each(cb) {
for (let i = 0; i < win.frames?.length; i += 1) {
const frame = win.frames[i];
if (frame) cb(frame);
}
},
addEventListener(event, listener, options) {
frames.each((frame) => {
try {
frame.document.addEventListener(event, listener, options);
} catch {}
});
return () => {
try {
frames.removeEventListener(event, listener, options);
} catch {}
};
},
removeEventListener(event, listener, options) {
frames.each((frame) => {
try {
frame.document.removeEventListener(event, listener, options);
} catch {}
});
}
};
return frames;
}
function getParentWindow(win) {
const parent = win.frameElement != null ? win.parent : null;
return {
addEventListener: (event, listener, options) => {
try {
parent?.addEventListener(event, listener, options);
} catch {}
return () => {
try {
parent?.removeEventListener(event, listener, options);
} catch {}
};
},
removeEventListener: (event, listener, options) => {
try {
parent?.removeEventListener(event, listener, options);
} catch {}
}
};
}
//#endregion
//#region src/shared/interact-outside/index.ts
const POINTER_OUTSIDE_EVENT = "pointerdown.outside";
const FOCUS_OUTSIDE_EVENT = "focus.outside";
function isComposedPathFocusable(composedPath) {
for (const node of composedPath) if (require_dom_query.isHTMLElement(node) && require_dom_query.isFocusable(node)) return true;
return false;
}
const isPointerEvent = (event) => "clientY" in event;
function isEventPointWithin(node, event) {
if (!isPointerEvent(event) || !node) return false;
const rect = node.getBoundingClientRect();
if (rect.width === 0 || rect.height === 0) return false;
return rect.top <= event.clientY && event.clientY <= rect.top + rect.height && rect.left <= event.clientX && event.clientX <= rect.left + rect.width;
}
function isPointInRect(rect, point) {
return rect.y <= point.y && point.y <= rect.y + rect.height && rect.x <= point.x && point.x <= rect.x + rect.width;
}
function isEventWithinScrollbar(event, ancestor) {
if (!ancestor || !isPointerEvent(event)) return false;
const isScrollableY = ancestor.scrollHeight > ancestor.clientHeight;
const onScrollbarY = isScrollableY && event.clientX > ancestor.offsetLeft + ancestor.clientWidth;
const isScrollableX = ancestor.scrollWidth > ancestor.clientWidth;
const onScrollbarX = isScrollableX && event.clientY > ancestor.offsetTop + ancestor.clientHeight;
if (!isPointInRect({
x: ancestor.offsetLeft,
y: ancestor.offsetTop,
width: ancestor.clientWidth + (isScrollableY ? 16 : 0),
height: ancestor.clientHeight + (isScrollableX ? 16 : 0)
}, {
x: event.clientX,
y: event.clientY
})) return false;
return onScrollbarY || onScrollbarX;
}
function trackInteractOutsideImpl(node, options) {
const { exclude, onFocusOutside, onPointerDownOutside, onInteractOutside, defer, followControlledElements = true } = options;
if (!node) return;
const doc = require_dom_query.getDocument(node);
const win = require_dom_query.getWindow(node);
const frames = getWindowFrames(win);
const parentWin = getParentWindow(win);
function isEventOutside(event, target) {
if (!require_dom_query.isHTMLElement(target)) return false;
if (!target.isConnected) return false;
if (require_dom_query.contains(node, target)) return false;
if (isEventPointWithin(node, event)) return false;
if (followControlledElements && require_dom_query.isControlledElement(node, target)) return false;
const triggerEl = doc.querySelector(`[aria-controls="${node.id}"]`);
if (triggerEl) {
if (isEventWithinScrollbar(event, require_dom_query.getNearestOverflowAncestor(triggerEl))) return false;
}
if (isEventWithinScrollbar(event, require_dom_query.getNearestOverflowAncestor(node))) return false;
return !exclude?.(target);
}
const pointerdownCleanups = /* @__PURE__ */ new Set();
const isInShadowRoot = require_dom_query.isShadowRoot(node?.getRootNode());
let isPointerDown = false;
function onPointerDown(event) {
isPointerDown = true;
const onPointerUp = () => {
isPointerDown = false;
};
doc.addEventListener("pointerup", onPointerUp, { once: true });
win.addEventListener("pointerup", onPointerUp, { once: true });
function handler(clickEvent) {
const func = defer && !require_dom_query.isTouchDevice() ? require_dom_query.raf : (v) => v();
const evt = clickEvent ?? event;
const composedPath = evt?.composedPath?.() ?? [evt?.target];
func(() => {
const target = isInShadowRoot ? composedPath[0] : require_dom_query.getEventTarget(event);
if (!node || !isEventOutside(event, target)) return;
if (onPointerDownOutside || onInteractOutside) {
const handler = (0, _ginxjs_core_utils.callAll)(onPointerDownOutside, onInteractOutside);
node.addEventListener(POINTER_OUTSIDE_EVENT, handler, { once: true });
}
fireCustomEvent(node, POINTER_OUTSIDE_EVENT, {
bubbles: false,
cancelable: true,
detail: {
originalEvent: evt,
contextmenu: require_dom_query.isContextMenuEvent(evt),
focusable: isComposedPathFocusable(composedPath),
target
}
});
});
}
if (event.pointerType === "touch") {
pointerdownCleanups.forEach((fn) => fn());
pointerdownCleanups.add(require_dom_query.addDomEvent(doc, "click", handler, { once: true }));
pointerdownCleanups.add(parentWin.addEventListener("click", handler, { once: true }));
pointerdownCleanups.add(frames.addEventListener("click", handler, { once: true }));
} else handler();
}
const cleanups = /* @__PURE__ */ new Set();
const timer = setTimeout(() => {
cleanups.add(require_dom_query.addDomEvent(doc, "pointerdown", onPointerDown, true));
cleanups.add(parentWin.addEventListener("pointerdown", onPointerDown, true));
cleanups.add(frames.addEventListener("pointerdown", onPointerDown, true));
}, 0);
function onFocusin(event) {
if (isPointerDown) return;
(defer ? require_dom_query.raf : (v) => v())(() => {
const composedPath = event?.composedPath?.() ?? [event?.target];
const target = isInShadowRoot ? composedPath[0] : require_dom_query.getEventTarget(event);
if (!node || !isEventOutside(event, target)) return;
if (onFocusOutside || onInteractOutside) {
const handler = (0, _ginxjs_core_utils.callAll)(onFocusOutside, onInteractOutside);
node.addEventListener(FOCUS_OUTSIDE_EVENT, handler, { once: true });
}
fireCustomEvent(node, FOCUS_OUTSIDE_EVENT, {
bubbles: false,
cancelable: true,
detail: {
originalEvent: event,
contextmenu: false,
focusable: require_dom_query.isFocusable(target),
target
}
});
});
}
if (!require_dom_query.isTouchDevice()) {
cleanups.add(require_dom_query.addDomEvent(doc, "focusin", onFocusin, true));
cleanups.add(parentWin.addEventListener("focusin", onFocusin, true));
cleanups.add(frames.addEventListener("focusin", onFocusin, true));
}
return () => {
clearTimeout(timer);
pointerdownCleanups.forEach((fn) => fn());
cleanups.forEach((fn) => fn());
};
}
function trackInteractOutside(nodeOrFn, options) {
const { defer } = options;
const func = defer ? require_dom_query.raf : (v) => v();
const cleanups = [];
cleanups.push(func(() => {
const node = typeof nodeOrFn === "function" ? nodeOrFn() : nodeOrFn;
cleanups.push(trackInteractOutsideImpl(node, options));
}));
return () => {
cleanups.forEach((fn) => fn?.());
};
}
function fireCustomEvent(el, type, init) {
const event = new (el.ownerDocument.defaultView || window).CustomEvent(type, init);
return el.dispatchEvent(event);
}
//#endregion
Object.defineProperty(exports, "trackInteractOutside", {
enumerable: true,
get: function() {
return trackInteractOutside;
}
});
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_interact_outside = require("./interact-outside-DyL5V-m4.cjs");
exports.trackInteractOutside = require_interact_outside.trackInteractOutside;
import { a as InteractOutsideOptions, c as PointerDownOutsideEvent, i as InteractOutsideHandlers, l as trackInteractOutside, n as FocusOutsideEvent, o as MaybeElement, r as InteractOutsideEvent, s as NodeOrFn, t as EventDetails } from "./index-jO45BUcW.cjs";
export { EventDetails, FocusOutsideEvent, InteractOutsideEvent, InteractOutsideHandlers, InteractOutsideOptions, MaybeElement, NodeOrFn, PointerDownOutsideEvent, trackInteractOutside };
import { a as InteractOutsideOptions, c as PointerDownOutsideEvent, i as InteractOutsideHandlers, l as trackInteractOutside, n as FocusOutsideEvent, o as MaybeElement, r as InteractOutsideEvent, s as NodeOrFn, t as EventDetails } from "./index-C3Jj4aYp.mjs";
export { EventDetails, FocusOutsideEvent, InteractOutsideEvent, InteractOutsideHandlers, InteractOutsideOptions, MaybeElement, NodeOrFn, PointerDownOutsideEvent, trackInteractOutside };
import { t as trackInteractOutside } from "./interact-outside-DEkrkU2U.mjs";
export { trackInteractOutside };
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region src/shared/json-tree-utils/json-to-tree.ts
const MAX_DEPTH = 20;
const jsonToTree = (data, props = {}) => {
const { visited = /* @__PURE__ */ new WeakSet(), keyPath = ["$"], depth = 0 } = props;
const options = getPreviewOptions(props.options);
if (depth > MAX_DEPTH) return {
value: "[Max Depth Reached]",
type: "string",
keyPath
};
if (data && typeof data === "object") {
if (visited.has(data)) return {
value: "[Circular Reference]",
type: "circular",
keyPath
};
visited.add(data);
}
return (dataTypes.find((dataType) => dataType.check(data)) || PrimitiveType).node({
value: data,
createNode: (nestedKeyPath, value) => jsonToTree(value, {
visited,
keyPath: [...keyPath, ...nestedKeyPath],
options,
depth: depth + 1
}),
keyPath,
options
});
};
//#endregion
//#region src/shared/json-tree-utils/shared.ts
const regexReturnCharacters = /\r/g;
function hash(str) {
const v = str.replace(regexReturnCharacters, "");
let hash = 5381;
let i = v.length;
while (i--) hash = (hash << 5) - hash ^ v.charCodeAt(i);
return (hash >>> 0).toString(36);
}
function getProp(value, key) {
return value[key];
}
function defu(a, b) {
const res = { ...a };
for (const key in b) if (b[key] !== void 0) res[key] = b[key];
return res;
}
const isObj = (v) => v != null && typeof v === "object" && !Array.isArray(v);
const typeOf = (value) => Object.prototype.toString.call(value);
//#endregion
//#region src/shared/json-tree-utils/node-conversion.ts
const ROOT_KEY = "$";
const PATH_SEP = ".";
function isRootKeyPath(keyPath) {
return keyPath.length === 1 && keyPath[0] === "$";
}
function keyPathToId(keyPath) {
return keyPath.join(".");
}
function keyPathToKey(keyPath, opts) {
if (keyPath.length === 0) return "";
if (opts?.excludeRoot && isRootKeyPath(keyPath)) return "";
return String(keyPath[keyPath.length - 1]);
}
function nodeToValue(node) {
return hash(keyPathToId(node.keyPath));
}
function jsonPathToValue(path) {
return hash(path);
}
function nodeToString(node) {
return keyPathToKey(node.keyPath) || "root";
}
function getRootNode(data, opts) {
return {
value: "",
type: "object",
keyPath: [],
children: [jsonToTree(data, {
visited: /* @__PURE__ */ new WeakSet(),
keyPath: ["$"],
options: getPreviewOptions(opts)
})]
};
}
const DEFAULT_PREVIEW_OPTIONS = {
maxPreviewItems: 3,
collapseStringsAfterLength: 30,
groupArraysAfterLength: 100,
showNonenumerable: true
};
const getPreviewOptions = (opts) => {
if (!opts) return DEFAULT_PREVIEW_OPTIONS;
return defu(DEFAULT_PREVIEW_OPTIONS, opts);
};
//#endregion
//#region src/shared/json-tree-utils/data-type.ts
const generatePreviewText = (items, hasMore) => {
return ` ${items.join(", ")}${hasMore ? ", … " : " "}`;
};
const ENTRIES_KEY = "[[Entries]]";
const txt = (value) => ({
type: "text",
value
});
const jsx = (tagName, properties = {}, children = []) => ({
type: "element",
tagName,
properties,
children
});
const formatValueMini = (child) => {
if (child.type === "string") return `"${child.value}"`;
if (child.type === "null") return "null";
if (child.type === "undefined" || child.type === "symbol") return "undefined";
if (child.type === "object") return "{…}";
if (child.type === "array") return "[…]";
if (child.type === "set") return "Set(…)";
if (child.type === "map") return "Map(…)";
if (child.type === "iterable") return "Iterable(…)";
if (child.type === "function") return "ƒ(…)";
return String(child.value);
};
const formatValue = (value) => {
if (value === null) return "null";
if (value === void 0) return "undefined";
if (typeof value === "string") return `"${value}"`;
if (typeof value === "number" || typeof value === "boolean") return String(value);
if (value instanceof Date) return value.toISOString();
if (value instanceof Set) return `Set(${value.size})`;
if (value instanceof Map) return `Map(${value.size})`;
if (Array.isArray(value)) return `Array(${value.length})`;
if (typeof value === "object") return "Object";
return String(value);
};
function dataType(opts) {
return opts;
}
const NullType = dataType({
type: "null",
description: "null",
check(value) {
return value === null;
},
previewElement() {
return jsx("span", {}, [txt("null")]);
},
node({ value, keyPath }) {
return {
value,
type: "null",
keyPath
};
}
});
const UndefinedType = dataType({
type: "undefined",
description: "undefined",
check(value) {
return value === void 0;
},
previewElement() {
return jsx("span", {}, [txt("undefined")]);
},
node({ value, keyPath }) {
return {
type: "undefined",
value,
keyPath
};
}
});
const SymbolType = dataType({
type: "symbol",
description(node) {
return String(node.value);
},
check(value) {
return typeof value === "symbol";
},
previewElement(node) {
return jsx("span", {}, [txt(node.value.toString())]);
},
node({ value, keyPath }) {
return {
type: "symbol",
value,
keyPath
};
}
});
const BigIntType = dataType({
type: "bigint",
description(node) {
return `${node.value}n`;
},
check(value) {
return typeof value === "bigint";
},
previewElement(node) {
return jsx("span", {}, [txt(`${node.value}n`)]);
},
node({ value, keyPath }) {
return {
type: "bigint",
value,
keyPath
};
}
});
const SetType = dataType({
type: "set",
description(node) {
return `Set(${node.value.size})`;
},
check(value) {
return value instanceof Set;
},
previewText(node, opts) {
const maxItems = opts.maxPreviewItems;
const entries = Array.from(node.value);
return generatePreviewText(entries.slice(0, maxItems).map(formatValue), entries.length > maxItems);
},
previewElement(node, opts) {
const preview = this.previewText?.(node, opts) ?? "";
const size = node.value.size;
const children = [jsx("span", { kind: "constructor" }, [txt(`Set(${size})`)]), jsx("span", { kind: "brace" }, [txt(" {")])];
if (preview) children.push(jsx("span", { kind: "preview-text" }, [txt(preview)]));
children.push(jsx("span", { kind: "brace" }, [txt("}")]));
return jsx("span", {}, children);
},
node({ value, keyPath, createNode }) {
const entriesChildren = Array.from(value).map((item, index) => createNode([ENTRIES_KEY, index.toString()], item));
return {
type: "set",
value,
keyPath,
children: [{
value: Array.from(value),
keyPath: [...keyPath, ENTRIES_KEY],
type: "array",
children: entriesChildren,
isNonEnumerable: true
}, createNode(["size"], value.size)]
};
}
});
const WeakSetType = dataType({
type: "weakset",
description: "WeakSet",
check(value) {
return value instanceof WeakSet;
},
previewElement() {
return jsx("span", {}, [
jsx("span", { kind: "constructor" }, [txt("WeakSet")]),
jsx("span", { kind: "brace" }, [txt(" {")]),
jsx("span", { kind: "preview" }, [txt(" [[Entries]]: not enumerable ")]),
jsx("span", { kind: "brace" }, [txt("}")])
]);
},
node({ value, keyPath }) {
return {
type: "weakset",
value,
keyPath
};
}
});
const WeakMapType = dataType({
type: "weakmap",
description: "WeakMap",
check(value) {
return value instanceof WeakMap;
},
previewElement() {
return jsx("span", {}, [
jsx("span", { kind: "constructor" }, [txt("WeakMap")]),
jsx("span", { kind: "brace" }, [txt(" {")]),
jsx("span", { kind: "preview" }, [txt(" [[Entries]]: not enumerable ")]),
jsx("span", { kind: "brace" }, [txt("}")])
]);
},
node({ value, keyPath }) {
return {
type: "weakmap",
value,
keyPath
};
}
});
const REGEX_KEYS = [
"lastIndex",
"dotAll",
"flags",
"global",
"hasIndices",
"ignoreCase",
"multiline",
"source",
"sticky",
"unicode"
];
const RegexType = dataType({
type: "regex",
description(node) {
return String(node.value);
},
check(value) {
return value instanceof RegExp;
},
previewElement(node) {
return jsx("span", {}, [txt(String(node.value))]);
},
node({ value, keyPath, createNode }) {
return {
value,
type: "regex",
keyPath,
children: REGEX_KEYS.map((key) => createNode([key], getProp(value, key)))
};
}
});
const DATA_VIEW_KEYS = [
"byteLength",
"byteOffset",
"buffer"
];
const DataViewType = dataType({
type: "dataview",
description(node) {
return `DataView(${node.value.byteLength})`;
},
check(value) {
return value instanceof DataView;
},
previewElement(node) {
const dataView = node.value;
return jsx("span", {}, [
jsx("span", { kind: "constructor" }, [txt(`DataView(${dataView.byteLength})`)]),
jsx("span", { kind: "brace" }, [txt(" { ")]),
jsx("span", { kind: "preview" }, [txt(` buffer: ArrayBuffer(${dataView.buffer.byteLength}), byteOffset: ${dataView.byteOffset} `)]),
jsx("span", { kind: "brace" }, [txt(" }")])
]);
},
node({ value, keyPath, createNode }) {
return {
value,
keyPath,
type: "dataview",
children: DATA_VIEW_KEYS.map((key) => createNode([key], getProp(value, key)))
};
}
});
const URL_KEYS = [
"href",
"origin",
"protocol",
"username",
"password",
"host",
"hostname",
"port",
"pathname",
"search",
"searchParams",
"hash"
];
const UrlType = dataType({
type: "url",
description: "URL",
check(value) {
return typeOf(value) === "[object URL]";
},
previewElement(node, opts) {
const url = node.value;
const maxItems = opts.maxPreviewItems;
const preview = URL_KEYS.slice(0, maxItems).map((key) => `${key}: '${url[key]}'`).join(", ");
const hasMore = URL_KEYS.length > maxItems;
return jsx("span", {}, [
jsx("span", { kind: "constructor" }, [txt("URL")]),
jsx("span", { kind: "brace" }, [txt(" { ")]),
jsx("span", { kind: "preview-text" }, [txt(` ${preview}${hasMore ? ", …" : ""} `)]),
jsx("span", { kind: "brace" }, [txt(" }")])
]);
},
node({ value, keyPath, createNode }) {
return {
value,
keyPath,
type: "url",
children: URL_KEYS.map((key) => createNode([key], Reflect.get(value, key)))
};
}
});
const URLSearchParamsType = dataType({
type: "urlsearchparams",
description: "URLSearchParams",
check(value) {
return typeOf(value) === "[object URLSearchParams]";
},
previewElement(node) {
const params = node.value;
const paramsArray = Array.from(params.entries());
return jsx("span", {}, [
jsx("span", { kind: "constructor" }, [txt("URLSearchParams")]),
jsx("span", { kind: "brace" }, [txt(" { ")]),
jsx("span", { kind: "preview" }, [txt(`size: ${paramsArray.length}`)]),
jsx("span", { kind: "brace" }, [txt(" }")])
]);
},
node({ value, keyPath, createNode }) {
const entriesChildren = Array.from(value.entries()).map(([key, value], index) => {
const keyStr = String(key);
const keyNode = createNode([
ENTRIES_KEY,
keyStr,
"key"
], key);
const valueNode = createNode([
ENTRIES_KEY,
keyStr,
"value"
], value);
return {
keyPath: [
...keyPath,
ENTRIES_KEY,
index
],
value: { [key]: value },
type: "object",
children: [keyNode, valueNode]
};
});
return {
value,
keyPath,
type: "urlsearchparams",
children: [{
keyPath: [...keyPath, "[[Entries]]"],
value: Array.from(value.entries()),
type: "array",
children: entriesChildren,
isNonEnumerable: true
}, createNode(["size"], Array.from(value.entries()).length)]
};
}
});
const BLOB_KEYS = ["size", "type"];
const BlobType = dataType({
type: "blob",
description(node) {
return `Blob(${node.value.size})`;
},
check(value) {
return typeOf(value) === "[object Blob]";
},
previewElement(node) {
const blob = node.value;
return jsx("span", {}, [
jsx("span", { kind: "constructor" }, [txt("Blob")]),
jsx("span", { kind: "brace" }, [txt(" { ")]),
jsx("span", { kind: "preview" }, [txt(`size: ${blob.size}, type: '${blob.type || "application/octet-stream"}'`)]),
jsx("span", { kind: "brace" }, [txt(" }")])
]);
},
node({ value, keyPath, createNode }) {
return {
value,
keyPath,
type: "blob",
children: BLOB_KEYS.map((key) => ({
key,
value: Reflect.get(value, key)
})).map(({ key, value }) => createNode([key], value))
};
}
});
const FILE_KEYS = [
"name",
"size",
"type",
"lastModified",
"webkitRelativePath"
];
const FileType = dataType({
type: "file",
description(node) {
return `File(${node.value.size})`;
},
check(value) {
return typeOf(value) === "[object File]";
},
previewElement(node) {
const file = node.value;
const hasMore = FILE_KEYS.length > 2;
return jsx("span", {}, [
jsx("span", { kind: "constructor" }, [txt("File")]),
jsx("span", { kind: "brace" }, [txt(" { ")]),
jsx("span", { kind: "preview" }, [txt(`name: '${file.name}', lastModified: ${file.lastModified}${hasMore ? ", …" : ""}`)]),
jsx("span", { kind: "brace" }, [txt(" }")])
]);
},
node({ value, keyPath, createNode }) {
return {
value,
keyPath,
type: "file",
children: FILE_KEYS.map((key) => ({
key,
value: getProp(value, key) || ""
})).map(({ key, value }) => createNode([key], value))
};
}
});
const getFunctionString = (func) => {
try {
return func.toString();
} catch {
switch (func.constructor.name) {
case "AsyncFunction": return "async function () {}";
case "AsyncGeneratorFunction": return "async function * () {}";
case "GeneratorFunction": return "function * () {}";
default: return "function () {}";
}
}
};
const FUNCTION_SIGNATURE_REGEX = /(?:async\s+)?(?:function\s*\*?\s*)?([^(]*\([^)]*\))/;
const getFunctionSignature = (func) => {
const signatureMatch = getFunctionString(func).match(FUNCTION_SIGNATURE_REGEX);
return signatureMatch ? signatureMatch[1] : `${func.name || "anonymous"}()`;
};
const FUNC_KEYS = [
"name",
"length",
"prototype",
"caller",
"arguments"
];
const FunctionType = dataType({
type: "function",
description(node) {
const func = node.value;
const name = func.name || "anonymous";
switch (func.constructor.name) {
case "AsyncFunction": return `async ƒ ${name}()`;
case "AsyncGeneratorFunction": return `async ƒ* ${name}()`;
case "GeneratorFunction": return `ƒ* ${name}()`;
default: return `ƒ ${name}()`;
}
},
check(value) {
return typeof value === "function";
},
previewElement(node) {
const func = node.value;
const signature = getFunctionSignature(func);
const constructorName = func.constructor.name;
const preview = signature.length > 50 ? `${signature.substring(0, 47)}...` : signature;
let functionTypePrefix = "";
if (constructorName === "AsyncFunction") functionTypePrefix += "async ";
if (constructorName === "AsyncGeneratorFunction") functionTypePrefix += "async ";
if (constructorName === "GeneratorFunction" || constructorName === "AsyncGeneratorFunction") functionTypePrefix += "ƒ* ";
if (!constructorName.includes("Generator")) functionTypePrefix += "ƒ ";
return jsx("span", {}, [jsx("span", { kind: "function-type" }, [txt(functionTypePrefix)]), jsx("span", { kind: "function-body" }, [txt(preview)])]);
},
node({ value, keyPath, createNode, options }) {
const funcName = value.name || "anonymous";
const constructorName = value.constructor.name;
const enumerableProperties = [];
const nonEnumerableProperties = [];
const funcString = getFunctionString(value);
nonEnumerableProperties.push({
key: "[[Function]]",
value: funcString
});
enumerableProperties.push({
key: "name",
value: funcName
});
enumerableProperties.push({
key: "length",
value: value.length
});
enumerableProperties.push({
key: "constructor",
value: constructorName
});
const additionalProps = Object.getOwnPropertyNames(value).filter((key) => !FUNC_KEYS.includes(key)).map((key) => ({
key,
value: Reflect.get(value, key)
}));
enumerableProperties.push(...additionalProps);
const enumerableChildren = enumerableProperties.map(({ key, value }) => createNode([key], value));
const nonEnumerableChildren = options?.showNonenumerable ? nonEnumerableProperties.map(({ key, value }) => {
const node = createNode([key], value);
node.isNonEnumerable = true;
return node;
}) : [];
return {
value,
type: "function",
keyPath,
children: [...enumerableChildren, ...nonEnumerableChildren]
};
}
});
const ArrayBufferType = dataType({
type: "arraybuffer",
description(node) {
return `ArrayBuffer(${node.value.byteLength})`;
},
check(value) {
return value instanceof ArrayBuffer;
},
previewElement(node) {
return jsx("span", { nodeType: "arraybuffer" }, [txt(node.value.toString())]);
},
node({ value, keyPath }) {
return {
value,
keyPath,
type: "arraybuffer"
};
}
});
const SharedArrayBufferType = dataType({
type: "sharedarraybuffer",
description(node) {
return `SharedArrayBuffer(${node.value.byteLength})`;
},
check(value) {
return typeof SharedArrayBuffer !== "undefined" && value instanceof SharedArrayBuffer;
},
previewElement() {
return jsx("span", { nodeType: "sharedarraybuffer" }, [txt("sharedarraybuffer")]);
},
node({ value, keyPath }) {
return {
value,
keyPath,
type: "sharedarraybuffer"
};
}
});
const BufferType = dataType({
type: "buffer",
description(node) {
return `Buffer(${node.value.length})`;
},
check(value) {
return typeof Buffer !== "undefined" && value instanceof Buffer;
},
previewElement(node) {
const buffer = node.value;
const preview = Array.from(new Uint8Array(buffer).slice(0, 8)).map((byte) => byte.toString(16).padStart(2, "0")).join(" ");
const hasMore = buffer.length > 8;
return jsx("span", {}, [
jsx("span", { kind: "constructor" }, [txt(`Buffer(${buffer.length})`)]),
jsx("span", { kind: "brace" }, [txt(" ['")]),
jsx("span", { kind: "preview-text" }, [txt(preview + (hasMore ? " …" : ""))]),
jsx("span", { kind: "brace" }, [txt("']")])
]);
},
node({ value, keyPath }) {
return {
value,
keyPath,
type: "buffer"
};
}
});
const DateType = dataType({
type: "date",
description(node) {
return String(node.value);
},
check(value) {
return value instanceof Date;
},
previewElement(node) {
return jsx("span", {}, [txt(node.value.toISOString())]);
},
node({ value, keyPath }) {
return {
value,
keyPath,
type: "date"
};
}
});
const MapType = dataType({
type: "map",
description(node) {
return `Map(${node.value.size})`;
},
check(value) {
return value instanceof Map;
},
previewText(node, opts) {
const maxItems = opts.maxPreviewItems;
const entries = Array.from(node.value.entries());
return generatePreviewText(entries.slice(0, maxItems).map(([key, value]) => {
const valueDesc = formatValue(value);
return `${typeof key === "string" ? `"${key}"` : String(key)} => ${valueDesc}`;
}), entries.length > maxItems);
},
previewElement(node, opts) {
const preview = this.previewText?.(node, opts) || "";
const size = node.value.size;
const children = [jsx("span", { kind: "constructor" }, [txt(`Map(${size})`)]), jsx("span", { kind: "brace" }, [txt(" {")])];
if (preview) children.push(jsx("span", { kind: "preview-text" }, [txt(preview)]));
children.push(jsx("span", { kind: "brace" }, [txt("}")]));
return jsx("span", {}, children);
},
node({ value, keyPath, createNode }) {
const entriesChildren = Array.from(value.entries()).map(([key, value], index) => {
const keyStr = String(key);
const keyNode = createNode([
ENTRIES_KEY,
keyStr,
"key"
], key);
const valueNode = createNode([
ENTRIES_KEY,
keyStr,
"value"
], value);
return {
keyPath: [
...keyPath,
ENTRIES_KEY,
index
],
value: { [keyStr]: value },
type: "object",
children: [keyNode, valueNode]
};
});
return {
value,
keyPath,
type: "map",
children: [{
keyPath: [...keyPath, ENTRIES_KEY],
value: Array.from(value.entries()),
type: "array",
children: entriesChildren,
isNonEnumerable: true
}, createNode(["size"], value.size)]
};
}
});
const ERROR_KEYS = [
"name",
"message",
"stack"
];
const ErrorType = dataType({
type: "error",
description(node) {
const err = node.value;
return `${err.name}: ${err.message}`;
},
check(value) {
return value instanceof Error;
},
previewElement(node) {
const err = node.value;
return jsx("span", {}, [
jsx("span", { kind: "constructor" }, [txt(err.name)]),
jsx("span", { kind: "colon" }, [txt(": ")]),
jsx("span", {}, [txt(err.message)])
]);
},
node({ value, keyPath, createNode }) {
const errorProperties = ERROR_KEYS.map((key) => ({
key,
value: Reflect.get(value, key)
}));
const additionalProps = Object.getOwnPropertyNames(value).filter((key) => !ERROR_KEYS.includes(key)).map((key) => ({
key,
value: getProp(value, key)
}));
return {
value,
keyPath,
type: "error",
children: [...errorProperties, ...additionalProps].map(({ key, value }) => createNode([key], value))
};
}
});
function errorStackToElement(stack) {
const stackLines = stack?.split("\n").filter((line) => line.trim()) || [];
return jsx("span", {}, stackLines.map((line, index) => {
const appendNewLine = index < stackLines.length - 1;
return jsx("span", {
nodeType: "string",
kind: "error-stack"
}, [jsx("span", {}, [txt(line + (appendNewLine ? "\\n" : ""))]), jsx("span", { kind: "operator" }, [txt(appendNewLine ? " +" : "")])]);
}));
}
const HeadersType = dataType({
type: "headers",
description: "Headers",
check(value) {
return typeOf(value) === "[object Headers]";
},
previewElement(node) {
const headers = node.value;
const entriesArray = Array.from(headers.entries());
const preview = entriesArray.slice(0, 2).map(([key, value]) => `${key}: ${value}`).join(", ");
const hasMore = entriesArray.length > 2;
return jsx("span", {}, [
jsx("span", { kind: "constructor" }, [txt(`Headers(${entriesArray.length})`)]),
jsx("span", { kind: "brace" }, [txt(" {")]),
jsx("span", { kind: "preview-text" }, [txt(` ${preview}${hasMore ? ", …" : ""} `)]),
jsx("span", { kind: "brace" }, [txt("}")])
]);
},
node({ value, keyPath, createNode }) {
const entriesChildren = Array.from(value.entries()).map(([key, value], index) => {
const keyStr = String(key);
const keyNode = createNode([
ENTRIES_KEY,
keyStr,
"key"
], key);
const valueNode = createNode([
ENTRIES_KEY,
keyStr,
"value"
], value);
return {
keyPath: [
...keyPath,
ENTRIES_KEY,
index
],
value: { [key]: value },
type: "object",
children: [keyNode, valueNode]
};
});
return {
value,
keyPath,
type: "headers",
children: [{
keyPath: [...keyPath, ENTRIES_KEY],
value: Array.from(value.entries()),
type: "array",
children: entriesChildren,
isNonEnumerable: true
}]
};
}
});
const FormDataType = dataType({
type: "formdata",
description: "FormData",
check(value) {
return typeOf(value) === "[object FormData]";
},
previewElement(node) {
const formData = node.value;
const entriesArray = Array.from(formData.entries());
const preview = entriesArray.slice(0, 2).map(([key, value]) => {
return `${key}: ${FileType.check(value) ? `File(${value.size})` : String(value)}`;
}).join(", ");
const hasMore = entriesArray.length > 2;
return jsx("span", {}, [
jsx("span", { kind: "constructor" }, [txt(`FormData(${entriesArray.length})`)]),
jsx("span", { kind: "brace" }, [txt(" {")]),
jsx("span", { kind: "preview-text" }, [txt(` ${preview}${hasMore ? ", …" : ""} `)]),
jsx("span", { kind: "brace" }, [txt("}")])
]);
},
node({ value, keyPath, createNode }) {
const entriesChildren = Array.from(value.entries()).map(([key, value], index) => {
const keyNode = createNode([
ENTRIES_KEY,
index,
"key"
], key);
const valueNode = createNode([
ENTRIES_KEY,
index,
"value"
], value);
return {
keyPath: [
...keyPath,
ENTRIES_KEY,
index
],
value: { [key]: value },
type: "object",
children: [keyNode, valueNode]
};
});
return {
value,
keyPath,
type: "formdata",
children: [{
keyPath: [...keyPath, ENTRIES_KEY],
value: Array.from(value.entries()),
type: "array",
children: entriesChildren,
isNonEnumerable: true
}]
};
}
});
const ArrayType = dataType({
type: "array",
description(node) {
return `Array(${node.value.length})`;
},
check(value) {
return Array.isArray(value);
},
previewText(node, opts) {
const maxItems = opts.maxPreviewItems;
const enumerableChildren = (node.children || []).filter((child) => !child.isNonEnumerable && keyPathToKey(child.keyPath) !== "length");
return generatePreviewText(enumerableChildren.slice(0, maxItems).map(formatValueMini), enumerableChildren.length > maxItems);
},
previewElement(node, opts) {
const preview = this.previewText?.(node, opts) || "";
const count = node.value.length;
const children = [];
if (count > 0) children.push(jsx("span", { kind: "constructor" }, [txt(`(${count}) `)]));
children.push(jsx("span", { kind: "brace" }, [txt("[")]));
if (preview) children.push(jsx("span", { kind: "preview-text" }, [txt(preview)]));
children.push(jsx("span", { kind: "brace" }, [txt("]")]));
return jsx("span", {}, children);
},
node({ value, keyPath, createNode, options }) {
const arrayChildren = [];
const definedIndices = Object.keys(value).filter((key) => !Number.isNaN(Number(key))).map(Number).sort((a, b) => a - b);
const chunkSize = options?.groupArraysAfterLength;
if (chunkSize && definedIndices.length > chunkSize) {
const chunks = [];
for (let i = 0; i < definedIndices.length; i += chunkSize) chunks.push(definedIndices.slice(i, i + chunkSize));
for (let chunkIndex = 0; chunkIndex < chunks.length; chunkIndex++) {
const chunk = chunks[chunkIndex];
const groupKey = `[${chunk[0]}…${chunk[chunk.length - 1]}]`;
const groupChildren = chunk.map((index) => createNode([index.toString()], value[index]));
const groupNode = {
keyPath: [...keyPath, groupKey],
value: chunk.map((index) => value[index]),
type: "array",
children: groupChildren,
isNonEnumerable: false
};
arrayChildren.push(groupNode);
}
} else for (const index of definedIndices) arrayChildren.push(createNode([index.toString()], value[index]));
const lengthChild = createNode(["length"], value.length);
const propertyNames = Object.getOwnPropertyNames(value);
const enumerableKeys = Object.keys(value).filter((key) => !Number.isNaN(Number(key)));
const nonEnumerableKeys = propertyNames.filter((key) => !enumerableKeys.includes(key) && key !== "length" && Number.isNaN(Number(key)));
const nonEnumerableChildren = options?.showNonenumerable ? nonEnumerableKeys.map((key) => {
const descriptor = Object.getOwnPropertyDescriptor(value, key);
const node = createNode([key], Reflect.get(value, key));
node.isNonEnumerable = true;
node.propertyDescriptor = descriptor;
return node;
}) : [];
return {
value,
type: "array",
children: [
...arrayChildren,
lengthChild,
...nonEnumerableChildren
],
keyPath
};
}
});
const typedArrayConstructors = {
Int8Array: "int8array",
Uint8Array: "uint8array",
Uint8ClampedArray: "uint8clampedarray",
Int16Array: "int16array",
Uint16Array: "uint16array",
Int32Array: "int32array",
Uint32Array: "uint32array",
Float32Array: "float32array",
Float64Array: "float64array",
BigInt64Array: "bigint64array",
BigUint64Array: "biguint64array"
};
const revertTypedArrayConstructors = Object.fromEntries(Object.entries(typedArrayConstructors).map(([key, value]) => [value, key]));
const TYPED_ARRAY_KEYS = [
"length",
"byteLength",
"byteOffset",
"buffer"
];
const TypedArrayType = dataType({
type: (value) => Reflect.get(typedArrayConstructors, value.constructor.name),
description(node) {
const typedArray = node.value;
return `${revertTypedArrayConstructors[typedArray.constructor.name]}(${typedArray.length})`;
},
check(value) {
return isObj(value) && value.constructor.name in typedArrayConstructors;
},
previewElement(node) {
const typedArray = node.value;
const constructorName = typedArray.constructor.name;
const preview = Array.from(typedArray).slice(0, 5).join(", ");
const hasMore = typedArray.length > 5;
return jsx("span", {}, [
jsx("span", { kind: "constructor" }, [txt(`${constructorName}(${typedArray.length})`)]),
jsx("span", { kind: "brace" }, [txt(" [ ")]),
jsx("span", { kind: "preview-text" }, [txt(preview + (hasMore ? ", …" : ""))]),
jsx("span", { kind: "brace" }, [txt(" ]")])
]);
},
node({ value, keyPath, createNode, options }) {
const typedArray = value;
const enumerableChildren = TYPED_ARRAY_KEYS.map((key) => ({
key,
value: Reflect.get(typedArray, key)
})).map(({ key, value }) => createNode([key], value));
const nonEnumerableChildren = options?.showNonenumerable ? (() => {
const node = createNode(["[[Values]]"], Array.from(typedArray).slice(0, 100));
node.isNonEnumerable = true;
return [node];
})() : [];
const children = [...enumerableChildren, ...nonEnumerableChildren];
return {
value,
keyPath,
type: Reflect.get(typedArrayConstructors, value.constructor.name),
children
};
}
});
const IterableType = dataType({
type: "iterable",
description: "Iterable",
check(value) {
return Boolean(value && typeof value === "object" && typeof value[Symbol.iterator] === "function" && !(value instanceof Set) && !(value instanceof Map) && !Array.isArray(value) && !(value instanceof Date) && !(value instanceof RegExp) && !(value instanceof ArrayBuffer));
},
previewElement(node, opts) {
const preview = SetType.previewText?.(node, opts) ?? "";
const entriesArray = Array.from(node.value);
const children = [jsx("span", { kind: "constructor" }, [txt(`Iterable(${node.value.size ?? node.value.length ?? entriesArray.length})`)]), jsx("span", { kind: "brace" }, [txt(" {")])];
if (preview) children.push(jsx("span", { kind: "preview-text" }, [txt(preview)]));
children.push(jsx("span", { kind: "brace" }, [txt("}")]));
return jsx("span", {}, children);
},
node({ value, keyPath, createNode }) {
const entriesArray = Array.from(value);
const entriesChildren = entriesArray.map((item, index) => createNode([ENTRIES_KEY, index], item));
return {
value,
type: "iterable",
children: [{
keyPath: [...keyPath, ENTRIES_KEY],
value: entriesArray,
type: "array",
children: entriesChildren,
isNonEnumerable: true
}, createNode(["size"], value.size ?? value.length ?? entriesArray.length)],
keyPath
};
}
});
const ClassType = dataType({
type: "object",
description(node) {
return node.constructorName || "Object";
},
check(value) {
return typeof value === "object" && value !== null && value.constructor !== Object;
},
previewText(node, opts) {
return ObjectType.previewText?.(node, opts) || "";
},
previewElement(node, opts) {
return ObjectType.previewElement(node, opts);
},
node({ value, keyPath, createNode, options }) {
const constructorName = value.constructor.name;
const allPropertyNames = Object.getOwnPropertyNames(value);
const enumerableKeys = Object.keys(value);
const nonEnumerableKeys = allPropertyNames.filter((key) => !enumerableKeys.includes(key));
const enumerableChildren = enumerableKeys.map((key) => createNode([key], Reflect.get(value, key)));
const nonEnumerableChildren = options?.showNonenumerable ? nonEnumerableKeys.map((key) => {
const descriptor = Object.getOwnPropertyDescriptor(value, key);
const node = createNode([`[[${key}]]`], getProp(value, key));
node.isNonEnumerable = true;
node.propertyDescriptor = descriptor;
return node;
}) : [];
return {
value,
keyPath,
type: "object",
constructorName,
children: [...enumerableChildren, ...nonEnumerableChildren]
};
}
});
const ObjectType = dataType({
type: "object",
description: "Object",
check(value) {
return typeof value === "object" && value !== null;
},
previewText(node, opts) {
const maxItems = opts.maxPreviewItems;
const children = node.children || [];
return generatePreviewText(children.slice(0, maxItems).map((child) => {
const valueDesc = getNodeTypeDescription(child);
return `${keyPathToKey(child.keyPath)}: ${valueDesc}`;
}), children.length > maxItems);
},
previewElement(node, opts) {
const preview = this.previewText?.(node, opts) ?? "";
const children = [];
if (node.constructorName) children.push(jsx("span", { kind: "constructor" }, [txt(`${node.constructorName} `)]));
children.push(jsx("span", { kind: "brace" }, [txt("{")]));
if (preview) children.push(jsx("span", { kind: "preview-text" }, [txt(preview)]));
children.push(jsx("span", { kind: "brace" }, [txt("}")]));
return jsx("span", {}, children);
},
node({ value, keyPath, createNode, options }) {
const allPropertyNames = Object.getOwnPropertyNames(value);
const enumerableKeys = Object.keys(value);
const nonEnumerableKeys = allPropertyNames.filter((key) => !enumerableKeys.includes(key));
const enumerableChildren = enumerableKeys.map((key) => createNode([key], getProp(value, key)));
const nonEnumerableChildren = options?.showNonenumerable ? nonEnumerableKeys.map((key) => {
const descriptor = Object.getOwnPropertyDescriptor(value, key);
const node = createNode([`[[${key}]]`], getProp(value, key));
node.isNonEnumerable = true;
node.propertyDescriptor = descriptor;
return node;
}) : [];
return {
value,
type: "object",
children: [...enumerableChildren, ...nonEnumerableChildren],
keyPath
};
}
});
const ELEMENT_KEYS = [
"attributes",
"childElementCount",
"className",
"dataset",
"hidden",
"id",
"inert",
"isConnected",
"isContentEditable",
"nodeType",
"style",
"tabIndex",
"tagName"
];
const isSvg = (el) => typeof el === "object" && el.tagName === "svg" && el.namespaceURI === "http://www.w3.org/2000/svg";
const isHTML = (el) => typeof el === "object" && el.namespaceURI === "http://www.w3.org/1999/xhtml";
const ElementType = dataType({
type: "element",
description(node) {
return typeOf(node.value);
},
check(value) {
return isSvg(value) || isHTML(value);
},
previewElement(node) {
const el = node.value;
const classList = Array.from(el.classList).slice(0, 3);
return jsx("span", {}, [
jsx("span", { kind: "constructor" }, [txt(el.constructor.name)]),
jsx("span", {}, [txt(" ")]),
jsx("span", { kind: "preview-text" }, [txt(`<${el.localName}${el.id ? `#${el.id}` : ""}${classList.length > 0 ? "." + classList.join(".") : ""}>`)])
]);
},
node({ value, keyPath, createNode }) {
return {
value,
keyPath,
type: "element",
children: ELEMENT_KEYS.reduce((acc, key) => {
let childValue = Reflect.get(value, key);
if (key === "attributes") {
const attrs = Array.from(value.attributes);
childValue = attrs.length ? Object.fromEntries(attrs.map((attr) => [attr.name, attr.value])) : void 0;
}
if (key === "style") {
const style = Array.from(value.style);
childValue = style.length ? Object.fromEntries(style.map((key) => [key, value.style.getPropertyValue(key)])) : void 0;
}
acc.push(createNode([key], childValue));
return acc;
}, [])
};
}
});
const DOCUMENT_KEYS = [
"title",
"URL",
"documentElement",
"head",
"body",
"contentType",
"readyState"
];
const DocumentType = dataType({
type: "document",
description: "Document",
check(value) {
return typeOf(value) === "[object HTMLDocument]";
},
previewElement(node) {
const url = node.value.URL || "unknown";
return jsx("span", {}, [jsx("span", { kind: "constructor" }, [txt("#document")]), jsx("span", { kind: "preview-text" }, [txt(` (${url})`)])]);
},
node({ value, keyPath, createNode }) {
return {
value,
keyPath,
type: "document",
children: DOCUMENT_KEYS.map((key) => createNode([key], Reflect.get(value, key)))
};
}
});
const WINDOW_KEYS = [
"location",
"navigator",
"document",
"innerWidth",
"innerHeight",
"devicePixelRatio",
"origin"
];
const WindowType = dataType({
type: "window",
description: "Window",
check(value) {
return typeOf(value) === "[object Window]";
},
previewElement() {
return jsx("span", {}, [jsx("span", { kind: "constructor" }, [txt("Window")]), jsx("span", { kind: "preview-text" }, [txt(" { … }")])]);
},
node({ value, keyPath, createNode }) {
return {
value,
keyPath,
type: "window",
children: WINDOW_KEYS.map((key) => {
const childValue = Reflect.get(value, key);
return createNode([key], childValue);
})
};
}
});
const REACT_ELEMENT_KEYS = [
"$$typeof",
"type",
"key",
"ref",
"props"
];
const getElementTypeName = (type) => {
if (typeof type === "string") return type;
if (typeof type === "function") return type.displayName || type.name || "Component";
return type?.toString() || "Component";
};
const ReactElementType = dataType({
type: "react-element",
description(node) {
const el = node.value;
return getElementTypeName(el.type);
},
check(value) {
return isObj(value) && "$$typeof" in value && "props" in value;
},
previewElement(node, opts) {
const el = node.value;
const elName = getElementTypeName(el.type);
const props = Object.entries(el.props);
const hasMore = props.length > opts.maxPreviewItems;
return jsx("span", {}, [
txt(`<${elName} `),
...props.slice(0, opts.maxPreviewItems).reduce((acc, [key, value]) => {
if (key === "children") return acc;
acc.push(jsx("span", {}, [txt(` ${key}=${typeof value === "string" ? `"${value}"` : `{${value}}`}`)]));
return acc;
}, []),
...hasMore ? [txt(" …")] : [],
txt(el.children ? `> {…} </${elName}>` : ` />`)
]);
},
node({ value, keyPath, createNode }) {
return {
value,
type: "react-element",
keyPath,
children: REACT_ELEMENT_KEYS.reduce((acc, key) => {
let childValue = Reflect.get(value, key);
if (key === "type") childValue = getElementTypeName(childValue);
acc.push(createNode([key], childValue));
return acc;
}, [])
};
}
});
const map = {
"\n": "\\n",
" ": "\\t",
"\r": "\\r"
};
const STRING_ESCAPE_REGEXP = /[\n\t\r]/g;
const StringType = dataType({
type: "string",
description(node, opts) {
return `"${this.previewText?.(node, opts) ?? node.value}"`;
},
check(value) {
return typeof value === "string";
},
previewText(node, opts) {
const serialised = node.value.replace(STRING_ESCAPE_REGEXP, (_) => map[_]);
return serialised.slice(0, opts.collapseStringsAfterLength) + (serialised.length > opts.collapseStringsAfterLength ? "…" : "");
},
previewElement(node) {
return jsx("span", {}, [txt(`"${node.value.replace(STRING_ESCAPE_REGEXP, (_) => map[_])}"`)]);
},
node({ value, keyPath }) {
return {
value,
type: "string",
keyPath
};
}
});
const PrimitiveType = dataType({
type(value) {
return typeof value;
},
description(node) {
return String(node.value);
},
check(value) {
return value !== null && value !== void 0;
},
previewElement(node) {
return jsx("span", {}, [txt(String(node.value))]);
},
node({ value, keyPath }) {
return {
value,
type: typeof value,
keyPath
};
}
});
const dataTypes = [
NullType,
UndefinedType,
SymbolType,
BigIntType,
FunctionType,
ArrayBufferType,
SharedArrayBufferType,
BufferType,
DataViewType,
ErrorType,
DateType,
RegexType,
SetType,
MapType,
WeakMapType,
WeakSetType,
FileType,
BlobType,
ReactElementType,
WindowType,
DocumentType,
ElementType,
UrlType,
URLSearchParamsType,
HeadersType,
FormDataType,
ArrayType,
TypedArrayType,
IterableType,
ClassType,
ObjectType,
StringType,
PrimitiveType
];
const jsonNodeToElement = (node, opts) => {
const options = getPreviewOptions(opts);
const key = keyPathToKey(node.keyPath, { excludeRoot: true });
if (key === "stack" && typeof node.value === "string") return errorStackToElement(node.value);
const dataType = dataTypes.find((dataType) => dataType.check(node.value));
if (!dataType) return jsx("span", {}, [txt(String(node.value))]);
const element = dataType.previewElement(node, options);
if (!key) element.properties.root = true;
element.properties.kind = "preview";
element.properties.nodeType = typeof dataType.type === "function" ? dataType.type(node.value) : dataType.type;
return element;
};
const getNodeTypeDescription = (node, opts) => {
const options = getPreviewOptions(opts);
const dataType = dataTypes.find((dataType) => dataType.check(node.value));
if (dataType) return typeof dataType.description === "function" ? dataType.description(node, options) : dataType.description;
return String(node.value);
};
//#endregion
//#region src/shared/json-tree-utils/accessibility.ts
const propertyWord = (count) => count === 1 ? "property" : "properties";
const isPrimitive = (node) => {
return node.type === "string" || node.type === "number" || node.type === "boolean";
};
const getAccessibleDescription = (node, opts) => {
const typeDescription = getNodeTypeDescription(node, opts);
const key = keyPathToKey(node.keyPath, { excludeRoot: true });
const nonEnumerablePrefix = node.isNonEnumerable ? "non-enumerable " : "";
const format = (text) => {
return [key, `${nonEnumerablePrefix}${text}`].filter(Boolean).join(": ");
};
if (node.children && node.children.length > 0) {
const childCount = node.children.length;
if (key === "[[Entries]]") return format(`${childCount} ${propertyWord(childCount)}`);
return format(`${typeDescription}, expandable with ${childCount} ${propertyWord(childCount)}`);
}
if (isPrimitive(node)) {
if (key === "stack") return format(node.value.split("\n")[1]?.trim() || "trace");
if (key === "[[Function]]") return format("function implementation");
return format(`${typeof node.value === "string" ? `"${node.value}"` : String(node.value)}${node.isNonEnumerable && node.propertyDescriptor ? `, ${getDescriptorInfo(node.propertyDescriptor)}` : ""}`);
}
if (node.type === "null") return format("null");
if (node.type === "undefined") return format("undefined");
if (node.type === "circular") return format("circular reference");
return format(`${nonEnumerablePrefix}${typeDescription}${node.isNonEnumerable && node.propertyDescriptor ? `, ${getDescriptorInfo(node.propertyDescriptor)}` : ""}`);
};
const getDescriptorInfo = (descriptor) => {
const parts = [];
if (!descriptor.writable) parts.push("read-only");
if (!descriptor.configurable) parts.push("non-configurable");
return parts.length > 0 ? parts.join(", ") : "non-enumerable";
};
//#endregion
exports.ArrayBufferType = ArrayBufferType;
exports.ArrayType = ArrayType;
exports.BigIntType = BigIntType;
exports.BlobType = BlobType;
exports.BufferType = BufferType;
exports.ClassType = ClassType;
exports.DEFAULT_PREVIEW_OPTIONS = DEFAULT_PREVIEW_OPTIONS;
exports.DataViewType = DataViewType;
exports.DateType = DateType;
exports.DocumentType = DocumentType;
exports.ElementType = ElementType;
exports.ErrorType = ErrorType;
exports.FileType = FileType;
exports.FormDataType = FormDataType;
exports.FunctionType = FunctionType;
exports.HeadersType = HeadersType;
exports.IterableType = IterableType;
exports.MapType = MapType;
exports.NullType = NullType;
exports.ObjectType = ObjectType;
exports.PATH_SEP = PATH_SEP;
exports.PrimitiveType = PrimitiveType;
exports.ROOT_KEY = ROOT_KEY;
exports.ReactElementType = ReactElementType;
exports.RegexType = RegexType;
exports.SetType = SetType;
exports.SharedArrayBufferType = SharedArrayBufferType;
exports.StringType = StringType;
exports.SymbolType = SymbolType;
exports.TypedArrayType = TypedArrayType;
exports.URLSearchParamsType = URLSearchParamsType;
exports.UndefinedType = UndefinedType;
exports.UrlType = UrlType;
exports.WeakMapType = WeakMapType;
exports.WeakSetType = WeakSetType;
exports.WindowType = WindowType;
exports.dataTypes = dataTypes;
exports.getAccessibleDescription = getAccessibleDescription;
exports.getNodeTypeDescription = getNodeTypeDescription;
exports.getPreviewOptions = getPreviewOptions;
exports.getRootNode = getRootNode;
exports.isRootKeyPath = isRootKeyPath;
exports.jsonNodeToElement = jsonNodeToElement;
exports.jsonPathToValue = jsonPathToValue;
exports.jsonToTree = jsonToTree;
exports.keyPathToId = keyPathToId;
exports.keyPathToKey = keyPathToKey;
exports.nodeToString = nodeToString;
exports.nodeToValue = nodeToValue;
//#region src/shared/json-tree-utils/types.d.ts
type JsonNodeType = "object" | "array" | "boolean" | "number" | "string" | "null" | "set" | "map" | "weakset" | "weakmap" | "regex" | "date" | "undefined" | "symbol" | "bigint" | "arraybuffer" | "sharedarraybuffer" | "buffer" | "dataview" | "blob" | "file" | "url" | "urlsearchparams" | "formdata" | "promise" | "headers" | "int8array" | "uint8array" | "uint8clampedarray" | "int16array" | "uint16array" | "int32array" | "uint32array" | "float32array" | "float64array" | "bigint64array" | "biguint64array" | "iterable" | "error" | "function" | "circular" | "element" | "document" | "window" | "react-element";
type JsonNodeKeyPath = (string | number)[];
type JsonNodeSyntaxKind = "constructor" | "brace" | "preview" | "preview-text" | "function-type" | "function-body" | "colon" | "circular" | "operator" | "error-stack";
interface JsonNodeElement {
type: "element";
tagName: "span" | "div" | "a";
properties: {
root?: boolean;
nodeType?: JsonNodeType;
kind?: JsonNodeSyntaxKind;
[key: string]: any;
};
children: Array<JsonNodeElement | JsonNodeText>;
}
interface JsonNodeText {
type: "text";
value: string | number | boolean | null | undefined;
}
type JsonNodeHastElement = JsonNodeElement | JsonNodeText;
interface JsonNode<T = any> {
value: T;
type: JsonNodeType;
keyPath: JsonNodeKeyPath;
constructorName?: string | undefined;
isNonEnumerable?: boolean;
propertyDescriptor?: PropertyDescriptor | undefined;
children?: JsonNode[];
}
interface JsonNodePreviewOptions {
maxPreviewItems: number;
collapseStringsAfterLength: number;
groupArraysAfterLength: number;
showNonenumerable: boolean;
}
interface JsonDataTypeOptions<T = any> {
type: JsonNodeType | ((value: T) => JsonNodeType);
check: (value: any) => boolean;
node: JsonNodeCreatorFn<T>;
description: string | ((node: JsonNode<T>, opts: JsonNodePreviewOptions) => string);
previewText?: (node: JsonNode<T>, opts: JsonNodePreviewOptions) => string;
previewElement: (node: JsonNode<T>, opts: JsonNodePreviewOptions) => JsonNodeElement;
}
interface JsonNodeCreatorParams<T = any> {
value: T;
keyPath: JsonNodeKeyPath;
options: JsonNodePreviewOptions | undefined;
createNode: (keyPath: JsonNodeKeyPath, value: unknown) => JsonNode;
}
type JsonNodeCreatorFn<T = any> = (opts: JsonNodeCreatorParams<T>) => JsonNode;
//#endregion
//#region src/shared/json-tree-utils/accessibility.d.ts
declare const getAccessibleDescription: (node: JsonNode, opts?: JsonNodePreviewOptions) => string;
//#endregion
//#region src/shared/json-tree-utils/data-type.d.ts
declare const NullType: JsonDataTypeOptions<null>;
declare const UndefinedType: JsonDataTypeOptions<undefined>;
declare const SymbolType: JsonDataTypeOptions<symbol>;
declare const BigIntType: JsonDataTypeOptions<bigint>;
declare const SetType: JsonDataTypeOptions<Set<unknown>>;
declare const WeakSetType: JsonDataTypeOptions<WeakSet<WeakKey>>;
declare const WeakMapType: JsonDataTypeOptions<WeakMap<WeakKey, WeakKey>>;
declare const RegexType: JsonDataTypeOptions<RegExp>;
declare const DataViewType: JsonDataTypeOptions<DataView<ArrayBufferLike>>;
declare const UrlType: JsonDataTypeOptions<URL>;
declare const URLSearchParamsType: JsonDataTypeOptions<URLSearchParams>;
declare const BlobType: JsonDataTypeOptions<Blob>;
declare const FileType: JsonDataTypeOptions<File>;
declare const FunctionType: JsonDataTypeOptions<Function>;
declare const ArrayBufferType: JsonDataTypeOptions<ArrayBuffer>;
declare const SharedArrayBufferType: JsonDataTypeOptions<SharedArrayBuffer>;
declare const BufferType: JsonDataTypeOptions<Buffer<ArrayBufferLike>>;
declare const DateType: JsonDataTypeOptions<Date>;
declare const MapType: JsonDataTypeOptions<Map<unknown, unknown>>;
declare const ErrorType: JsonDataTypeOptions<Error>;
declare const HeadersType: JsonDataTypeOptions<Headers>;
declare const FormDataType: JsonDataTypeOptions<FormData>;
declare const ArrayType: JsonDataTypeOptions<unknown[]>;
declare const TypedArrayType: JsonDataTypeOptions<any>;
declare const IterableType: JsonDataTypeOptions<any>;
declare const ClassType: JsonDataTypeOptions<any>;
declare const ObjectType: JsonDataTypeOptions<object>;
declare const ElementType: JsonDataTypeOptions<HTMLElement | SVGElement>;
declare const DocumentType: JsonDataTypeOptions<Document>;
declare const WindowType: JsonDataTypeOptions<Window>;
declare const ReactElementType: JsonDataTypeOptions<any>;
declare const StringType: JsonDataTypeOptions<string>;
declare const PrimitiveType: JsonDataTypeOptions<any>;
declare const dataTypes: JsonDataTypeOptions<any>[];
declare const jsonNodeToElement: (node: JsonNode, opts?: Partial<JsonNodePreviewOptions>) => JsonNodeHastElement;
declare const getNodeTypeDescription: (node: JsonNode, opts?: Partial<JsonNodePreviewOptions>) => string;
//#endregion
//#region src/shared/json-tree-utils/json-to-tree.d.ts
interface JsonToTreeOptions {
visited?: WeakSet<WeakKey> | undefined;
keyPath?: (string | number)[] | undefined;
options?: JsonNodePreviewOptions | undefined;
depth?: number | undefined;
}
declare const jsonToTree: (data: unknown, props?: JsonToTreeOptions) => JsonNode;
//#endregion
//#region src/shared/json-tree-utils/node-conversion.d.ts
declare const ROOT_KEY = "$";
declare const PATH_SEP = ".";
declare function isRootKeyPath(keyPath: Array<string | number>): boolean;
declare function keyPathToId(keyPath: Array<string | number>): string;
declare function keyPathToKey(keyPath: Array<string | number>, opts?: {
excludeRoot?: boolean;
}): string;
declare function nodeToValue(node: JsonNode): string;
declare function jsonPathToValue(path: string): string;
declare function nodeToString(node: JsonNode): string;
declare function getRootNode(data: unknown, opts?: Partial<JsonNodePreviewOptions>): JsonNode;
declare const DEFAULT_PREVIEW_OPTIONS: JsonNodePreviewOptions;
declare const getPreviewOptions: (opts?: Partial<JsonNodePreviewOptions> | undefined) => JsonNodePreviewOptions;
//#endregion
export { ArrayBufferType, ArrayType, BigIntType, BlobType, BufferType, ClassType, DEFAULT_PREVIEW_OPTIONS, DataViewType, DateType, DocumentType, ElementType, ErrorType, FileType, FormDataType, FunctionType, HeadersType, IterableType, JsonDataTypeOptions, JsonNode, JsonNodeCreatorFn, JsonNodeCreatorParams, JsonNodeElement, JsonNodeHastElement, JsonNodeKeyPath, JsonNodePreviewOptions, JsonNodeSyntaxKind, JsonNodeText, JsonNodeType, JsonToTreeOptions, MapType, NullType, ObjectType, PATH_SEP, PrimitiveType, ROOT_KEY, ReactElementType, RegexType, SetType, SharedArrayBufferType, StringType, SymbolType, TypedArrayType, URLSearchParamsType, UndefinedType, UrlType, WeakMapType, WeakSetType, WindowType, dataTypes, getAccessibleDescription, getNodeTypeDescription, getPreviewOptions, getRootNode, isRootKeyPath, jsonNodeToElement, jsonPathToValue, jsonToTree, keyPathToId, keyPathToKey, nodeToString, nodeToValue };
//#region src/shared/json-tree-utils/types.d.ts
type JsonNodeType = "object" | "array" | "boolean" | "number" | "string" | "null" | "set" | "map" | "weakset" | "weakmap" | "regex" | "date" | "undefined" | "symbol" | "bigint" | "arraybuffer" | "sharedarraybuffer" | "buffer" | "dataview" | "blob" | "file" | "url" | "urlsearchparams" | "formdata" | "promise" | "headers" | "int8array" | "uint8array" | "uint8clampedarray" | "int16array" | "uint16array" | "int32array" | "uint32array" | "float32array" | "float64array" | "bigint64array" | "biguint64array" | "iterable" | "error" | "function" | "circular" | "element" | "document" | "window" | "react-element";
type JsonNodeKeyPath = (string | number)[];
type JsonNodeSyntaxKind = "constructor" | "brace" | "preview" | "preview-text" | "function-type" | "function-body" | "colon" | "circular" | "operator" | "error-stack";
interface JsonNodeElement {
type: "element";
tagName: "span" | "div" | "a";
properties: {
root?: boolean;
nodeType?: JsonNodeType;
kind?: JsonNodeSyntaxKind;
[key: string]: any;
};
children: Array<JsonNodeElement | JsonNodeText>;
}
interface JsonNodeText {
type: "text";
value: string | number | boolean | null | undefined;
}
type JsonNodeHastElement = JsonNodeElement | JsonNodeText;
interface JsonNode<T = any> {
value: T;
type: JsonNodeType;
keyPath: JsonNodeKeyPath;
constructorName?: string | undefined;
isNonEnumerable?: boolean;
propertyDescriptor?: PropertyDescriptor | undefined;
children?: JsonNode[];
}
interface JsonNodePreviewOptions {
maxPreviewItems: number;
collapseStringsAfterLength: number;
groupArraysAfterLength: number;
showNonenumerable: boolean;
}
interface JsonDataTypeOptions<T = any> {
type: JsonNodeType | ((value: T) => JsonNodeType);
check: (value: any) => boolean;
node: JsonNodeCreatorFn<T>;
description: string | ((node: JsonNode<T>, opts: JsonNodePreviewOptions) => string);
previewText?: (node: JsonNode<T>, opts: JsonNodePreviewOptions) => string;
previewElement: (node: JsonNode<T>, opts: JsonNodePreviewOptions) => JsonNodeElement;
}
interface JsonNodeCreatorParams<T = any> {
value: T;
keyPath: JsonNodeKeyPath;
options: JsonNodePreviewOptions | undefined;
createNode: (keyPath: JsonNodeKeyPath, value: unknown) => JsonNode;
}
type JsonNodeCreatorFn<T = any> = (opts: JsonNodeCreatorParams<T>) => JsonNode;
//#endregion
//#region src/shared/json-tree-utils/accessibility.d.ts
declare const getAccessibleDescription: (node: JsonNode, opts?: JsonNodePreviewOptions) => string;
//#endregion
//#region src/shared/json-tree-utils/data-type.d.ts
declare const NullType: JsonDataTypeOptions<null>;
declare const UndefinedType: JsonDataTypeOptions<undefined>;
declare const SymbolType: JsonDataTypeOptions<symbol>;
declare const BigIntType: JsonDataTypeOptions<bigint>;
declare const SetType: JsonDataTypeOptions<Set<unknown>>;
declare const WeakSetType: JsonDataTypeOptions<WeakSet<WeakKey>>;
declare const WeakMapType: JsonDataTypeOptions<WeakMap<WeakKey, WeakKey>>;
declare const RegexType: JsonDataTypeOptions<RegExp>;
declare const DataViewType: JsonDataTypeOptions<DataView<ArrayBufferLike>>;
declare const UrlType: JsonDataTypeOptions<URL>;
declare const URLSearchParamsType: JsonDataTypeOptions<URLSearchParams>;
declare const BlobType: JsonDataTypeOptions<Blob>;
declare const FileType: JsonDataTypeOptions<File>;
declare const FunctionType: JsonDataTypeOptions<Function>;
declare const ArrayBufferType: JsonDataTypeOptions<ArrayBuffer>;
declare const SharedArrayBufferType: JsonDataTypeOptions<SharedArrayBuffer>;
declare const BufferType: JsonDataTypeOptions<Buffer<ArrayBufferLike>>;
declare const DateType: JsonDataTypeOptions<Date>;
declare const MapType: JsonDataTypeOptions<Map<unknown, unknown>>;
declare const ErrorType: JsonDataTypeOptions<Error>;
declare const HeadersType: JsonDataTypeOptions<Headers>;
declare const FormDataType: JsonDataTypeOptions<FormData>;
declare const ArrayType: JsonDataTypeOptions<unknown[]>;
declare const TypedArrayType: JsonDataTypeOptions<any>;
declare const IterableType: JsonDataTypeOptions<any>;
declare const ClassType: JsonDataTypeOptions<any>;
declare const ObjectType: JsonDataTypeOptions<object>;
declare const ElementType: JsonDataTypeOptions<HTMLElement | SVGElement>;
declare const DocumentType: JsonDataTypeOptions<Document>;
declare const WindowType: JsonDataTypeOptions<Window>;
declare const ReactElementType: JsonDataTypeOptions<any>;
declare const StringType: JsonDataTypeOptions<string>;
declare const PrimitiveType: JsonDataTypeOptions<any>;
declare const dataTypes: JsonDataTypeOptions<any>[];
declare const jsonNodeToElement: (node: JsonNode, opts?: Partial<JsonNodePreviewOptions>) => JsonNodeHastElement;
declare const getNodeTypeDescription: (node: JsonNode, opts?: Partial<JsonNodePreviewOptions>) => string;
//#endregion
//#region src/shared/json-tree-utils/json-to-tree.d.ts
interface JsonToTreeOptions {
visited?: WeakSet<WeakKey> | undefined;
keyPath?: (string | number)[] | undefined;
options?: JsonNodePreviewOptions | undefined;
depth?: number | undefined;
}
declare const jsonToTree: (data: unknown, props?: JsonToTreeOptions) => JsonNode;
//#endregion
//#region src/shared/json-tree-utils/node-conversion.d.ts
declare const ROOT_KEY = "$";
declare const PATH_SEP = ".";
declare function isRootKeyPath(keyPath: Array<string | number>): boolean;
declare function keyPathToId(keyPath: Array<string | number>): string;
declare function keyPathToKey(keyPath: Array<string | number>, opts?: {
excludeRoot?: boolean;
}): string;
declare function nodeToValue(node: JsonNode): string;
declare function jsonPathToValue(path: string): string;
declare function nodeToString(node: JsonNode): string;
declare function getRootNode(data: unknown, opts?: Partial<JsonNodePreviewOptions>): JsonNode;
declare const DEFAULT_PREVIEW_OPTIONS: JsonNodePreviewOptions;
declare const getPreviewOptions: (opts?: Partial<JsonNodePreviewOptions> | undefined) => JsonNodePreviewOptions;
//#endregion
export { ArrayBufferType, ArrayType, BigIntType, BlobType, BufferType, ClassType, DEFAULT_PREVIEW_OPTIONS, DataViewType, DateType, DocumentType, ElementType, ErrorType, FileType, FormDataType, FunctionType, HeadersType, IterableType, JsonDataTypeOptions, JsonNode, JsonNodeCreatorFn, JsonNodeCreatorParams, JsonNodeElement, JsonNodeHastElement, JsonNodeKeyPath, JsonNodePreviewOptions, JsonNodeSyntaxKind, JsonNodeText, JsonNodeType, JsonToTreeOptions, MapType, NullType, ObjectType, PATH_SEP, PrimitiveType, ROOT_KEY, ReactElementType, RegexType, SetType, SharedArrayBufferType, StringType, SymbolType, TypedArrayType, URLSearchParamsType, UndefinedType, UrlType, WeakMapType, WeakSetType, WindowType, dataTypes, getAccessibleDescription, getNodeTypeDescription, getPreviewOptions, getRootNode, isRootKeyPath, jsonNodeToElement, jsonPathToValue, jsonToTree, keyPathToId, keyPathToKey, nodeToString, nodeToValue };
//#region src/shared/json-tree-utils/json-to-tree.ts
const MAX_DEPTH = 20;
const jsonToTree = (data, props = {}) => {
const { visited = /* @__PURE__ */ new WeakSet(), keyPath = ["$"], depth = 0 } = props;
const options = getPreviewOptions(props.options);
if (depth > MAX_DEPTH) return {
value: "[Max Depth Reached]",
type: "string",
keyPath
};
if (data && typeof data === "object") {
if (visited.has(data)) return {
value: "[Circular Reference]",
type: "circular",
keyPath
};
visited.add(data);
}
return (dataTypes.find((dataType) => dataType.check(data)) || PrimitiveType).node({
value: data,
createNode: (nestedKeyPath, value) => jsonToTree(value, {
visited,
keyPath: [...keyPath, ...nestedKeyPath],
options,
depth: depth + 1
}),
keyPath,
options
});
};
//#endregion
//#region src/shared/json-tree-utils/shared.ts
const regexReturnCharacters = /\r/g;
function hash(str) {
const v = str.replace(regexReturnCharacters, "");
let hash = 5381;
let i = v.length;
while (i--) hash = (hash << 5) - hash ^ v.charCodeAt(i);
return (hash >>> 0).toString(36);
}
function getProp(value, key) {
return value[key];
}
function defu(a, b) {
const res = { ...a };
for (const key in b) if (b[key] !== void 0) res[key] = b[key];
return res;
}
const isObj = (v) => v != null && typeof v === "object" && !Array.isArray(v);
const typeOf = (value) => Object.prototype.toString.call(value);
//#endregion
//#region src/shared/json-tree-utils/node-conversion.ts
const ROOT_KEY = "$";
const PATH_SEP = ".";
function isRootKeyPath(keyPath) {
return keyPath.length === 1 && keyPath[0] === "$";
}
function keyPathToId(keyPath) {
return keyPath.join(".");
}
function keyPathToKey(keyPath, opts) {
if (keyPath.length === 0) return "";
if (opts?.excludeRoot && isRootKeyPath(keyPath)) return "";
return String(keyPath[keyPath.length - 1]);
}
function nodeToValue(node) {
return hash(keyPathToId(node.keyPath));
}
function jsonPathToValue(path) {
return hash(path);
}
function nodeToString(node) {
return keyPathToKey(node.keyPath) || "root";
}
function getRootNode(data, opts) {
return {
value: "",
type: "object",
keyPath: [],
children: [jsonToTree(data, {
visited: /* @__PURE__ */ new WeakSet(),
keyPath: ["$"],
options: getPreviewOptions(opts)
})]
};
}
const DEFAULT_PREVIEW_OPTIONS = {
maxPreviewItems: 3,
collapseStringsAfterLength: 30,
groupArraysAfterLength: 100,
showNonenumerable: true
};
const getPreviewOptions = (opts) => {
if (!opts) return DEFAULT_PREVIEW_OPTIONS;
return defu(DEFAULT_PREVIEW_OPTIONS, opts);
};
//#endregion
//#region src/shared/json-tree-utils/data-type.ts
const generatePreviewText = (items, hasMore) => {
return ` ${items.join(", ")}${hasMore ? ", … " : " "}`;
};
const ENTRIES_KEY = "[[Entries]]";
const txt = (value) => ({
type: "text",
value
});
const jsx = (tagName, properties = {}, children = []) => ({
type: "element",
tagName,
properties,
children
});
const formatValueMini = (child) => {
if (child.type === "string") return `"${child.value}"`;
if (child.type === "null") return "null";
if (child.type === "undefined" || child.type === "symbol") return "undefined";
if (child.type === "object") return "{…}";
if (child.type === "array") return "[…]";
if (child.type === "set") return "Set(…)";
if (child.type === "map") return "Map(…)";
if (child.type === "iterable") return "Iterable(…)";
if (child.type === "function") return "ƒ(…)";
return String(child.value);
};
const formatValue = (value) => {
if (value === null) return "null";
if (value === void 0) return "undefined";
if (typeof value === "string") return `"${value}"`;
if (typeof value === "number" || typeof value === "boolean") return String(value);
if (value instanceof Date) return value.toISOString();
if (value instanceof Set) return `Set(${value.size})`;
if (value instanceof Map) return `Map(${value.size})`;
if (Array.isArray(value)) return `Array(${value.length})`;
if (typeof value === "object") return "Object";
return String(value);
};
function dataType(opts) {
return opts;
}
const NullType = dataType({
type: "null",
description: "null",
check(value) {
return value === null;
},
previewElement() {
return jsx("span", {}, [txt("null")]);
},
node({ value, keyPath }) {
return {
value,
type: "null",
keyPath
};
}
});
const UndefinedType = dataType({
type: "undefined",
description: "undefined",
check(value) {
return value === void 0;
},
previewElement() {
return jsx("span", {}, [txt("undefined")]);
},
node({ value, keyPath }) {
return {
type: "undefined",
value,
keyPath
};
}
});
const SymbolType = dataType({
type: "symbol",
description(node) {
return String(node.value);
},
check(value) {
return typeof value === "symbol";
},
previewElement(node) {
return jsx("span", {}, [txt(node.value.toString())]);
},
node({ value, keyPath }) {
return {
type: "symbol",
value,
keyPath
};
}
});
const BigIntType = dataType({
type: "bigint",
description(node) {
return `${node.value}n`;
},
check(value) {
return typeof value === "bigint";
},
previewElement(node) {
return jsx("span", {}, [txt(`${node.value}n`)]);
},
node({ value, keyPath }) {
return {
type: "bigint",
value,
keyPath
};
}
});
const SetType = dataType({
type: "set",
description(node) {
return `Set(${node.value.size})`;
},
check(value) {
return value instanceof Set;
},
previewText(node, opts) {
const maxItems = opts.maxPreviewItems;
const entries = Array.from(node.value);
return generatePreviewText(entries.slice(0, maxItems).map(formatValue), entries.length > maxItems);
},
previewElement(node, opts) {
const preview = this.previewText?.(node, opts) ?? "";
const size = node.value.size;
const children = [jsx("span", { kind: "constructor" }, [txt(`Set(${size})`)]), jsx("span", { kind: "brace" }, [txt(" {")])];
if (preview) children.push(jsx("span", { kind: "preview-text" }, [txt(preview)]));
children.push(jsx("span", { kind: "brace" }, [txt("}")]));
return jsx("span", {}, children);
},
node({ value, keyPath, createNode }) {
const entriesChildren = Array.from(value).map((item, index) => createNode([ENTRIES_KEY, index.toString()], item));
return {
type: "set",
value,
keyPath,
children: [{
value: Array.from(value),
keyPath: [...keyPath, ENTRIES_KEY],
type: "array",
children: entriesChildren,
isNonEnumerable: true
}, createNode(["size"], value.size)]
};
}
});
const WeakSetType = dataType({
type: "weakset",
description: "WeakSet",
check(value) {
return value instanceof WeakSet;
},
previewElement() {
return jsx("span", {}, [
jsx("span", { kind: "constructor" }, [txt("WeakSet")]),
jsx("span", { kind: "brace" }, [txt(" {")]),
jsx("span", { kind: "preview" }, [txt(" [[Entries]]: not enumerable ")]),
jsx("span", { kind: "brace" }, [txt("}")])
]);
},
node({ value, keyPath }) {
return {
type: "weakset",
value,
keyPath
};
}
});
const WeakMapType = dataType({
type: "weakmap",
description: "WeakMap",
check(value) {
return value instanceof WeakMap;
},
previewElement() {
return jsx("span", {}, [
jsx("span", { kind: "constructor" }, [txt("WeakMap")]),
jsx("span", { kind: "brace" }, [txt(" {")]),
jsx("span", { kind: "preview" }, [txt(" [[Entries]]: not enumerable ")]),
jsx("span", { kind: "brace" }, [txt("}")])
]);
},
node({ value, keyPath }) {
return {
type: "weakmap",
value,
keyPath
};
}
});
const REGEX_KEYS = [
"lastIndex",
"dotAll",
"flags",
"global",
"hasIndices",
"ignoreCase",
"multiline",
"source",
"sticky",
"unicode"
];
const RegexType = dataType({
type: "regex",
description(node) {
return String(node.value);
},
check(value) {
return value instanceof RegExp;
},
previewElement(node) {
return jsx("span", {}, [txt(String(node.value))]);
},
node({ value, keyPath, createNode }) {
return {
value,
type: "regex",
keyPath,
children: REGEX_KEYS.map((key) => createNode([key], getProp(value, key)))
};
}
});
const DATA_VIEW_KEYS = [
"byteLength",
"byteOffset",
"buffer"
];
const DataViewType = dataType({
type: "dataview",
description(node) {
return `DataView(${node.value.byteLength})`;
},
check(value) {
return value instanceof DataView;
},
previewElement(node) {
const dataView = node.value;
return jsx("span", {}, [
jsx("span", { kind: "constructor" }, [txt(`DataView(${dataView.byteLength})`)]),
jsx("span", { kind: "brace" }, [txt(" { ")]),
jsx("span", { kind: "preview" }, [txt(` buffer: ArrayBuffer(${dataView.buffer.byteLength}), byteOffset: ${dataView.byteOffset} `)]),
jsx("span", { kind: "brace" }, [txt(" }")])
]);
},
node({ value, keyPath, createNode }) {
return {
value,
keyPath,
type: "dataview",
children: DATA_VIEW_KEYS.map((key) => createNode([key], getProp(value, key)))
};
}
});
const URL_KEYS = [
"href",
"origin",
"protocol",
"username",
"password",
"host",
"hostname",
"port",
"pathname",
"search",
"searchParams",
"hash"
];
const UrlType = dataType({
type: "url",
description: "URL",
check(value) {
return typeOf(value) === "[object URL]";
},
previewElement(node, opts) {
const url = node.value;
const maxItems = opts.maxPreviewItems;
const preview = URL_KEYS.slice(0, maxItems).map((key) => `${key}: '${url[key]}'`).join(", ");
const hasMore = URL_KEYS.length > maxItems;
return jsx("span", {}, [
jsx("span", { kind: "constructor" }, [txt("URL")]),
jsx("span", { kind: "brace" }, [txt(" { ")]),
jsx("span", { kind: "preview-text" }, [txt(` ${preview}${hasMore ? ", …" : ""} `)]),
jsx("span", { kind: "brace" }, [txt(" }")])
]);
},
node({ value, keyPath, createNode }) {
return {
value,
keyPath,
type: "url",
children: URL_KEYS.map((key) => createNode([key], Reflect.get(value, key)))
};
}
});
const URLSearchParamsType = dataType({
type: "urlsearchparams",
description: "URLSearchParams",
check(value) {
return typeOf(value) === "[object URLSearchParams]";
},
previewElement(node) {
const params = node.value;
const paramsArray = Array.from(params.entries());
return jsx("span", {}, [
jsx("span", { kind: "constructor" }, [txt("URLSearchParams")]),
jsx("span", { kind: "brace" }, [txt(" { ")]),
jsx("span", { kind: "preview" }, [txt(`size: ${paramsArray.length}`)]),
jsx("span", { kind: "brace" }, [txt(" }")])
]);
},
node({ value, keyPath, createNode }) {
const entriesChildren = Array.from(value.entries()).map(([key, value], index) => {
const keyStr = String(key);
const keyNode = createNode([
ENTRIES_KEY,
keyStr,
"key"
], key);
const valueNode = createNode([
ENTRIES_KEY,
keyStr,
"value"
], value);
return {
keyPath: [
...keyPath,
ENTRIES_KEY,
index
],
value: { [key]: value },
type: "object",
children: [keyNode, valueNode]
};
});
return {
value,
keyPath,
type: "urlsearchparams",
children: [{
keyPath: [...keyPath, "[[Entries]]"],
value: Array.from(value.entries()),
type: "array",
children: entriesChildren,
isNonEnumerable: true
}, createNode(["size"], Array.from(value.entries()).length)]
};
}
});
const BLOB_KEYS = ["size", "type"];
const BlobType = dataType({
type: "blob",
description(node) {
return `Blob(${node.value.size})`;
},
check(value) {
return typeOf(value) === "[object Blob]";
},
previewElement(node) {
const blob = node.value;
return jsx("span", {}, [
jsx("span", { kind: "constructor" }, [txt("Blob")]),
jsx("span", { kind: "brace" }, [txt(" { ")]),
jsx("span", { kind: "preview" }, [txt(`size: ${blob.size}, type: '${blob.type || "application/octet-stream"}'`)]),
jsx("span", { kind: "brace" }, [txt(" }")])
]);
},
node({ value, keyPath, createNode }) {
return {
value,
keyPath,
type: "blob",
children: BLOB_KEYS.map((key) => ({
key,
value: Reflect.get(value, key)
})).map(({ key, value }) => createNode([key], value))
};
}
});
const FILE_KEYS = [
"name",
"size",
"type",
"lastModified",
"webkitRelativePath"
];
const FileType = dataType({
type: "file",
description(node) {
return `File(${node.value.size})`;
},
check(value) {
return typeOf(value) === "[object File]";
},
previewElement(node) {
const file = node.value;
const hasMore = FILE_KEYS.length > 2;
return jsx("span", {}, [
jsx("span", { kind: "constructor" }, [txt("File")]),
jsx("span", { kind: "brace" }, [txt(" { ")]),
jsx("span", { kind: "preview" }, [txt(`name: '${file.name}', lastModified: ${file.lastModified}${hasMore ? ", …" : ""}`)]),
jsx("span", { kind: "brace" }, [txt(" }")])
]);
},
node({ value, keyPath, createNode }) {
return {
value,
keyPath,
type: "file",
children: FILE_KEYS.map((key) => ({
key,
value: getProp(value, key) || ""
})).map(({ key, value }) => createNode([key], value))
};
}
});
const getFunctionString = (func) => {
try {
return func.toString();
} catch {
switch (func.constructor.name) {
case "AsyncFunction": return "async function () {}";
case "AsyncGeneratorFunction": return "async function * () {}";
case "GeneratorFunction": return "function * () {}";
default: return "function () {}";
}
}
};
const FUNCTION_SIGNATURE_REGEX = /(?:async\s+)?(?:function\s*\*?\s*)?([^(]*\([^)]*\))/;
const getFunctionSignature = (func) => {
const signatureMatch = getFunctionString(func).match(FUNCTION_SIGNATURE_REGEX);
return signatureMatch ? signatureMatch[1] : `${func.name || "anonymous"}()`;
};
const FUNC_KEYS = [
"name",
"length",
"prototype",
"caller",
"arguments"
];
const FunctionType = dataType({
type: "function",
description(node) {
const func = node.value;
const name = func.name || "anonymous";
switch (func.constructor.name) {
case "AsyncFunction": return `async ƒ ${name}()`;
case "AsyncGeneratorFunction": return `async ƒ* ${name}()`;
case "GeneratorFunction": return `ƒ* ${name}()`;
default: return `ƒ ${name}()`;
}
},
check(value) {
return typeof value === "function";
},
previewElement(node) {
const func = node.value;
const signature = getFunctionSignature(func);
const constructorName = func.constructor.name;
const preview = signature.length > 50 ? `${signature.substring(0, 47)}...` : signature;
let functionTypePrefix = "";
if (constructorName === "AsyncFunction") functionTypePrefix += "async ";
if (constructorName === "AsyncGeneratorFunction") functionTypePrefix += "async ";
if (constructorName === "GeneratorFunction" || constructorName === "AsyncGeneratorFunction") functionTypePrefix += "ƒ* ";
if (!constructorName.includes("Generator")) functionTypePrefix += "ƒ ";
return jsx("span", {}, [jsx("span", { kind: "function-type" }, [txt(functionTypePrefix)]), jsx("span", { kind: "function-body" }, [txt(preview)])]);
},
node({ value, keyPath, createNode, options }) {
const funcName = value.name || "anonymous";
const constructorName = value.constructor.name;
const enumerableProperties = [];
const nonEnumerableProperties = [];
const funcString = getFunctionString(value);
nonEnumerableProperties.push({
key: "[[Function]]",
value: funcString
});
enumerableProperties.push({
key: "name",
value: funcName
});
enumerableProperties.push({
key: "length",
value: value.length
});
enumerableProperties.push({
key: "constructor",
value: constructorName
});
const additionalProps = Object.getOwnPropertyNames(value).filter((key) => !FUNC_KEYS.includes(key)).map((key) => ({
key,
value: Reflect.get(value, key)
}));
enumerableProperties.push(...additionalProps);
const enumerableChildren = enumerableProperties.map(({ key, value }) => createNode([key], value));
const nonEnumerableChildren = options?.showNonenumerable ? nonEnumerableProperties.map(({ key, value }) => {
const node = createNode([key], value);
node.isNonEnumerable = true;
return node;
}) : [];
return {
value,
type: "function",
keyPath,
children: [...enumerableChildren, ...nonEnumerableChildren]
};
}
});
const ArrayBufferType = dataType({
type: "arraybuffer",
description(node) {
return `ArrayBuffer(${node.value.byteLength})`;
},
check(value) {
return value instanceof ArrayBuffer;
},
previewElement(node) {
return jsx("span", { nodeType: "arraybuffer" }, [txt(node.value.toString())]);
},
node({ value, keyPath }) {
return {
value,
keyPath,
type: "arraybuffer"
};
}
});
const SharedArrayBufferType = dataType({
type: "sharedarraybuffer",
description(node) {
return `SharedArrayBuffer(${node.value.byteLength})`;
},
check(value) {
return typeof SharedArrayBuffer !== "undefined" && value instanceof SharedArrayBuffer;
},
previewElement() {
return jsx("span", { nodeType: "sharedarraybuffer" }, [txt("sharedarraybuffer")]);
},
node({ value, keyPath }) {
return {
value,
keyPath,
type: "sharedarraybuffer"
};
}
});
const BufferType = dataType({
type: "buffer",
description(node) {
return `Buffer(${node.value.length})`;
},
check(value) {
return typeof Buffer !== "undefined" && value instanceof Buffer;
},
previewElement(node) {
const buffer = node.value;
const preview = Array.from(new Uint8Array(buffer).slice(0, 8)).map((byte) => byte.toString(16).padStart(2, "0")).join(" ");
const hasMore = buffer.length > 8;
return jsx("span", {}, [
jsx("span", { kind: "constructor" }, [txt(`Buffer(${buffer.length})`)]),
jsx("span", { kind: "brace" }, [txt(" ['")]),
jsx("span", { kind: "preview-text" }, [txt(preview + (hasMore ? " …" : ""))]),
jsx("span", { kind: "brace" }, [txt("']")])
]);
},
node({ value, keyPath }) {
return {
value,
keyPath,
type: "buffer"
};
}
});
const DateType = dataType({
type: "date",
description(node) {
return String(node.value);
},
check(value) {
return value instanceof Date;
},
previewElement(node) {
return jsx("span", {}, [txt(node.value.toISOString())]);
},
node({ value, keyPath }) {
return {
value,
keyPath,
type: "date"
};
}
});
const MapType = dataType({
type: "map",
description(node) {
return `Map(${node.value.size})`;
},
check(value) {
return value instanceof Map;
},
previewText(node, opts) {
const maxItems = opts.maxPreviewItems;
const entries = Array.from(node.value.entries());
return generatePreviewText(entries.slice(0, maxItems).map(([key, value]) => {
const valueDesc = formatValue(value);
return `${typeof key === "string" ? `"${key}"` : String(key)} => ${valueDesc}`;
}), entries.length > maxItems);
},
previewElement(node, opts) {
const preview = this.previewText?.(node, opts) || "";
const size = node.value.size;
const children = [jsx("span", { kind: "constructor" }, [txt(`Map(${size})`)]), jsx("span", { kind: "brace" }, [txt(" {")])];
if (preview) children.push(jsx("span", { kind: "preview-text" }, [txt(preview)]));
children.push(jsx("span", { kind: "brace" }, [txt("}")]));
return jsx("span", {}, children);
},
node({ value, keyPath, createNode }) {
const entriesChildren = Array.from(value.entries()).map(([key, value], index) => {
const keyStr = String(key);
const keyNode = createNode([
ENTRIES_KEY,
keyStr,
"key"
], key);
const valueNode = createNode([
ENTRIES_KEY,
keyStr,
"value"
], value);
return {
keyPath: [
...keyPath,
ENTRIES_KEY,
index
],
value: { [keyStr]: value },
type: "object",
children: [keyNode, valueNode]
};
});
return {
value,
keyPath,
type: "map",
children: [{
keyPath: [...keyPath, ENTRIES_KEY],
value: Array.from(value.entries()),
type: "array",
children: entriesChildren,
isNonEnumerable: true
}, createNode(["size"], value.size)]
};
}
});
const ERROR_KEYS = [
"name",
"message",
"stack"
];
const ErrorType = dataType({
type: "error",
description(node) {
const err = node.value;
return `${err.name}: ${err.message}`;
},
check(value) {
return value instanceof Error;
},
previewElement(node) {
const err = node.value;
return jsx("span", {}, [
jsx("span", { kind: "constructor" }, [txt(err.name)]),
jsx("span", { kind: "colon" }, [txt(": ")]),
jsx("span", {}, [txt(err.message)])
]);
},
node({ value, keyPath, createNode }) {
const errorProperties = ERROR_KEYS.map((key) => ({
key,
value: Reflect.get(value, key)
}));
const additionalProps = Object.getOwnPropertyNames(value).filter((key) => !ERROR_KEYS.includes(key)).map((key) => ({
key,
value: getProp(value, key)
}));
return {
value,
keyPath,
type: "error",
children: [...errorProperties, ...additionalProps].map(({ key, value }) => createNode([key], value))
};
}
});
function errorStackToElement(stack) {
const stackLines = stack?.split("\n").filter((line) => line.trim()) || [];
return jsx("span", {}, stackLines.map((line, index) => {
const appendNewLine = index < stackLines.length - 1;
return jsx("span", {
nodeType: "string",
kind: "error-stack"
}, [jsx("span", {}, [txt(line + (appendNewLine ? "\\n" : ""))]), jsx("span", { kind: "operator" }, [txt(appendNewLine ? " +" : "")])]);
}));
}
const HeadersType = dataType({
type: "headers",
description: "Headers",
check(value) {
return typeOf(value) === "[object Headers]";
},
previewElement(node) {
const headers = node.value;
const entriesArray = Array.from(headers.entries());
const preview = entriesArray.slice(0, 2).map(([key, value]) => `${key}: ${value}`).join(", ");
const hasMore = entriesArray.length > 2;
return jsx("span", {}, [
jsx("span", { kind: "constructor" }, [txt(`Headers(${entriesArray.length})`)]),
jsx("span", { kind: "brace" }, [txt(" {")]),
jsx("span", { kind: "preview-text" }, [txt(` ${preview}${hasMore ? ", …" : ""} `)]),
jsx("span", { kind: "brace" }, [txt("}")])
]);
},
node({ value, keyPath, createNode }) {
const entriesChildren = Array.from(value.entries()).map(([key, value], index) => {
const keyStr = String(key);
const keyNode = createNode([
ENTRIES_KEY,
keyStr,
"key"
], key);
const valueNode = createNode([
ENTRIES_KEY,
keyStr,
"value"
], value);
return {
keyPath: [
...keyPath,
ENTRIES_KEY,
index
],
value: { [key]: value },
type: "object",
children: [keyNode, valueNode]
};
});
return {
value,
keyPath,
type: "headers",
children: [{
keyPath: [...keyPath, ENTRIES_KEY],
value: Array.from(value.entries()),
type: "array",
children: entriesChildren,
isNonEnumerable: true
}]
};
}
});
const FormDataType = dataType({
type: "formdata",
description: "FormData",
check(value) {
return typeOf(value) === "[object FormData]";
},
previewElement(node) {
const formData = node.value;
const entriesArray = Array.from(formData.entries());
const preview = entriesArray.slice(0, 2).map(([key, value]) => {
return `${key}: ${FileType.check(value) ? `File(${value.size})` : String(value)}`;
}).join(", ");
const hasMore = entriesArray.length > 2;
return jsx("span", {}, [
jsx("span", { kind: "constructor" }, [txt(`FormData(${entriesArray.length})`)]),
jsx("span", { kind: "brace" }, [txt(" {")]),
jsx("span", { kind: "preview-text" }, [txt(` ${preview}${hasMore ? ", …" : ""} `)]),
jsx("span", { kind: "brace" }, [txt("}")])
]);
},
node({ value, keyPath, createNode }) {
const entriesChildren = Array.from(value.entries()).map(([key, value], index) => {
const keyNode = createNode([
ENTRIES_KEY,
index,
"key"
], key);
const valueNode = createNode([
ENTRIES_KEY,
index,
"value"
], value);
return {
keyPath: [
...keyPath,
ENTRIES_KEY,
index
],
value: { [key]: value },
type: "object",
children: [keyNode, valueNode]
};
});
return {
value,
keyPath,
type: "formdata",
children: [{
keyPath: [...keyPath, ENTRIES_KEY],
value: Array.from(value.entries()),
type: "array",
children: entriesChildren,
isNonEnumerable: true
}]
};
}
});
const ArrayType = dataType({
type: "array",
description(node) {
return `Array(${node.value.length})`;
},
check(value) {
return Array.isArray(value);
},
previewText(node, opts) {
const maxItems = opts.maxPreviewItems;
const enumerableChildren = (node.children || []).filter((child) => !child.isNonEnumerable && keyPathToKey(child.keyPath) !== "length");
return generatePreviewText(enumerableChildren.slice(0, maxItems).map(formatValueMini), enumerableChildren.length > maxItems);
},
previewElement(node, opts) {
const preview = this.previewText?.(node, opts) || "";
const count = node.value.length;
const children = [];
if (count > 0) children.push(jsx("span", { kind: "constructor" }, [txt(`(${count}) `)]));
children.push(jsx("span", { kind: "brace" }, [txt("[")]));
if (preview) children.push(jsx("span", { kind: "preview-text" }, [txt(preview)]));
children.push(jsx("span", { kind: "brace" }, [txt("]")]));
return jsx("span", {}, children);
},
node({ value, keyPath, createNode, options }) {
const arrayChildren = [];
const definedIndices = Object.keys(value).filter((key) => !Number.isNaN(Number(key))).map(Number).sort((a, b) => a - b);
const chunkSize = options?.groupArraysAfterLength;
if (chunkSize && definedIndices.length > chunkSize) {
const chunks = [];
for (let i = 0; i < definedIndices.length; i += chunkSize) chunks.push(definedIndices.slice(i, i + chunkSize));
for (let chunkIndex = 0; chunkIndex < chunks.length; chunkIndex++) {
const chunk = chunks[chunkIndex];
const groupKey = `[${chunk[0]}…${chunk[chunk.length - 1]}]`;
const groupChildren = chunk.map((index) => createNode([index.toString()], value[index]));
const groupNode = {
keyPath: [...keyPath, groupKey],
value: chunk.map((index) => value[index]),
type: "array",
children: groupChildren,
isNonEnumerable: false
};
arrayChildren.push(groupNode);
}
} else for (const index of definedIndices) arrayChildren.push(createNode([index.toString()], value[index]));
const lengthChild = createNode(["length"], value.length);
const propertyNames = Object.getOwnPropertyNames(value);
const enumerableKeys = Object.keys(value).filter((key) => !Number.isNaN(Number(key)));
const nonEnumerableKeys = propertyNames.filter((key) => !enumerableKeys.includes(key) && key !== "length" && Number.isNaN(Number(key)));
const nonEnumerableChildren = options?.showNonenumerable ? nonEnumerableKeys.map((key) => {
const descriptor = Object.getOwnPropertyDescriptor(value, key);
const node = createNode([key], Reflect.get(value, key));
node.isNonEnumerable = true;
node.propertyDescriptor = descriptor;
return node;
}) : [];
return {
value,
type: "array",
children: [
...arrayChildren,
lengthChild,
...nonEnumerableChildren
],
keyPath
};
}
});
const typedArrayConstructors = {
Int8Array: "int8array",
Uint8Array: "uint8array",
Uint8ClampedArray: "uint8clampedarray",
Int16Array: "int16array",
Uint16Array: "uint16array",
Int32Array: "int32array",
Uint32Array: "uint32array",
Float32Array: "float32array",
Float64Array: "float64array",
BigInt64Array: "bigint64array",
BigUint64Array: "biguint64array"
};
const revertTypedArrayConstructors = Object.fromEntries(Object.entries(typedArrayConstructors).map(([key, value]) => [value, key]));
const TYPED_ARRAY_KEYS = [
"length",
"byteLength",
"byteOffset",
"buffer"
];
const TypedArrayType = dataType({
type: (value) => Reflect.get(typedArrayConstructors, value.constructor.name),
description(node) {
const typedArray = node.value;
return `${revertTypedArrayConstructors[typedArray.constructor.name]}(${typedArray.length})`;
},
check(value) {
return isObj(value) && value.constructor.name in typedArrayConstructors;
},
previewElement(node) {
const typedArray = node.value;
const constructorName = typedArray.constructor.name;
const preview = Array.from(typedArray).slice(0, 5).join(", ");
const hasMore = typedArray.length > 5;
return jsx("span", {}, [
jsx("span", { kind: "constructor" }, [txt(`${constructorName}(${typedArray.length})`)]),
jsx("span", { kind: "brace" }, [txt(" [ ")]),
jsx("span", { kind: "preview-text" }, [txt(preview + (hasMore ? ", …" : ""))]),
jsx("span", { kind: "brace" }, [txt(" ]")])
]);
},
node({ value, keyPath, createNode, options }) {
const typedArray = value;
const enumerableChildren = TYPED_ARRAY_KEYS.map((key) => ({
key,
value: Reflect.get(typedArray, key)
})).map(({ key, value }) => createNode([key], value));
const nonEnumerableChildren = options?.showNonenumerable ? (() => {
const node = createNode(["[[Values]]"], Array.from(typedArray).slice(0, 100));
node.isNonEnumerable = true;
return [node];
})() : [];
const children = [...enumerableChildren, ...nonEnumerableChildren];
return {
value,
keyPath,
type: Reflect.get(typedArrayConstructors, value.constructor.name),
children
};
}
});
const IterableType = dataType({
type: "iterable",
description: "Iterable",
check(value) {
return Boolean(value && typeof value === "object" && typeof value[Symbol.iterator] === "function" && !(value instanceof Set) && !(value instanceof Map) && !Array.isArray(value) && !(value instanceof Date) && !(value instanceof RegExp) && !(value instanceof ArrayBuffer));
},
previewElement(node, opts) {
const preview = SetType.previewText?.(node, opts) ?? "";
const entriesArray = Array.from(node.value);
const children = [jsx("span", { kind: "constructor" }, [txt(`Iterable(${node.value.size ?? node.value.length ?? entriesArray.length})`)]), jsx("span", { kind: "brace" }, [txt(" {")])];
if (preview) children.push(jsx("span", { kind: "preview-text" }, [txt(preview)]));
children.push(jsx("span", { kind: "brace" }, [txt("}")]));
return jsx("span", {}, children);
},
node({ value, keyPath, createNode }) {
const entriesArray = Array.from(value);
const entriesChildren = entriesArray.map((item, index) => createNode([ENTRIES_KEY, index], item));
return {
value,
type: "iterable",
children: [{
keyPath: [...keyPath, ENTRIES_KEY],
value: entriesArray,
type: "array",
children: entriesChildren,
isNonEnumerable: true
}, createNode(["size"], value.size ?? value.length ?? entriesArray.length)],
keyPath
};
}
});
const ClassType = dataType({
type: "object",
description(node) {
return node.constructorName || "Object";
},
check(value) {
return typeof value === "object" && value !== null && value.constructor !== Object;
},
previewText(node, opts) {
return ObjectType.previewText?.(node, opts) || "";
},
previewElement(node, opts) {
return ObjectType.previewElement(node, opts);
},
node({ value, keyPath, createNode, options }) {
const constructorName = value.constructor.name;
const allPropertyNames = Object.getOwnPropertyNames(value);
const enumerableKeys = Object.keys(value);
const nonEnumerableKeys = allPropertyNames.filter((key) => !enumerableKeys.includes(key));
const enumerableChildren = enumerableKeys.map((key) => createNode([key], Reflect.get(value, key)));
const nonEnumerableChildren = options?.showNonenumerable ? nonEnumerableKeys.map((key) => {
const descriptor = Object.getOwnPropertyDescriptor(value, key);
const node = createNode([`[[${key}]]`], getProp(value, key));
node.isNonEnumerable = true;
node.propertyDescriptor = descriptor;
return node;
}) : [];
return {
value,
keyPath,
type: "object",
constructorName,
children: [...enumerableChildren, ...nonEnumerableChildren]
};
}
});
const ObjectType = dataType({
type: "object",
description: "Object",
check(value) {
return typeof value === "object" && value !== null;
},
previewText(node, opts) {
const maxItems = opts.maxPreviewItems;
const children = node.children || [];
return generatePreviewText(children.slice(0, maxItems).map((child) => {
const valueDesc = getNodeTypeDescription(child);
return `${keyPathToKey(child.keyPath)}: ${valueDesc}`;
}), children.length > maxItems);
},
previewElement(node, opts) {
const preview = this.previewText?.(node, opts) ?? "";
const children = [];
if (node.constructorName) children.push(jsx("span", { kind: "constructor" }, [txt(`${node.constructorName} `)]));
children.push(jsx("span", { kind: "brace" }, [txt("{")]));
if (preview) children.push(jsx("span", { kind: "preview-text" }, [txt(preview)]));
children.push(jsx("span", { kind: "brace" }, [txt("}")]));
return jsx("span", {}, children);
},
node({ value, keyPath, createNode, options }) {
const allPropertyNames = Object.getOwnPropertyNames(value);
const enumerableKeys = Object.keys(value);
const nonEnumerableKeys = allPropertyNames.filter((key) => !enumerableKeys.includes(key));
const enumerableChildren = enumerableKeys.map((key) => createNode([key], getProp(value, key)));
const nonEnumerableChildren = options?.showNonenumerable ? nonEnumerableKeys.map((key) => {
const descriptor = Object.getOwnPropertyDescriptor(value, key);
const node = createNode([`[[${key}]]`], getProp(value, key));
node.isNonEnumerable = true;
node.propertyDescriptor = descriptor;
return node;
}) : [];
return {
value,
type: "object",
children: [...enumerableChildren, ...nonEnumerableChildren],
keyPath
};
}
});
const ELEMENT_KEYS = [
"attributes",
"childElementCount",
"className",
"dataset",
"hidden",
"id",
"inert",
"isConnected",
"isContentEditable",
"nodeType",
"style",
"tabIndex",
"tagName"
];
const isSvg = (el) => typeof el === "object" && el.tagName === "svg" && el.namespaceURI === "http://www.w3.org/2000/svg";
const isHTML = (el) => typeof el === "object" && el.namespaceURI === "http://www.w3.org/1999/xhtml";
const ElementType = dataType({
type: "element",
description(node) {
return typeOf(node.value);
},
check(value) {
return isSvg(value) || isHTML(value);
},
previewElement(node) {
const el = node.value;
const classList = Array.from(el.classList).slice(0, 3);
return jsx("span", {}, [
jsx("span", { kind: "constructor" }, [txt(el.constructor.name)]),
jsx("span", {}, [txt(" ")]),
jsx("span", { kind: "preview-text" }, [txt(`<${el.localName}${el.id ? `#${el.id}` : ""}${classList.length > 0 ? "." + classList.join(".") : ""}>`)])
]);
},
node({ value, keyPath, createNode }) {
return {
value,
keyPath,
type: "element",
children: ELEMENT_KEYS.reduce((acc, key) => {
let childValue = Reflect.get(value, key);
if (key === "attributes") {
const attrs = Array.from(value.attributes);
childValue = attrs.length ? Object.fromEntries(attrs.map((attr) => [attr.name, attr.value])) : void 0;
}
if (key === "style") {
const style = Array.from(value.style);
childValue = style.length ? Object.fromEntries(style.map((key) => [key, value.style.getPropertyValue(key)])) : void 0;
}
acc.push(createNode([key], childValue));
return acc;
}, [])
};
}
});
const DOCUMENT_KEYS = [
"title",
"URL",
"documentElement",
"head",
"body",
"contentType",
"readyState"
];
const DocumentType = dataType({
type: "document",
description: "Document",
check(value) {
return typeOf(value) === "[object HTMLDocument]";
},
previewElement(node) {
const url = node.value.URL || "unknown";
return jsx("span", {}, [jsx("span", { kind: "constructor" }, [txt("#document")]), jsx("span", { kind: "preview-text" }, [txt(` (${url})`)])]);
},
node({ value, keyPath, createNode }) {
return {
value,
keyPath,
type: "document",
children: DOCUMENT_KEYS.map((key) => createNode([key], Reflect.get(value, key)))
};
}
});
const WINDOW_KEYS = [
"location",
"navigator",
"document",
"innerWidth",
"innerHeight",
"devicePixelRatio",
"origin"
];
const WindowType = dataType({
type: "window",
description: "Window",
check(value) {
return typeOf(value) === "[object Window]";
},
previewElement() {
return jsx("span", {}, [jsx("span", { kind: "constructor" }, [txt("Window")]), jsx("span", { kind: "preview-text" }, [txt(" { … }")])]);
},
node({ value, keyPath, createNode }) {
return {
value,
keyPath,
type: "window",
children: WINDOW_KEYS.map((key) => {
const childValue = Reflect.get(value, key);
return createNode([key], childValue);
})
};
}
});
const REACT_ELEMENT_KEYS = [
"$$typeof",
"type",
"key",
"ref",
"props"
];
const getElementTypeName = (type) => {
if (typeof type === "string") return type;
if (typeof type === "function") return type.displayName || type.name || "Component";
return type?.toString() || "Component";
};
const ReactElementType = dataType({
type: "react-element",
description(node) {
const el = node.value;
return getElementTypeName(el.type);
},
check(value) {
return isObj(value) && "$$typeof" in value && "props" in value;
},
previewElement(node, opts) {
const el = node.value;
const elName = getElementTypeName(el.type);
const props = Object.entries(el.props);
const hasMore = props.length > opts.maxPreviewItems;
return jsx("span", {}, [
txt(`<${elName} `),
...props.slice(0, opts.maxPreviewItems).reduce((acc, [key, value]) => {
if (key === "children") return acc;
acc.push(jsx("span", {}, [txt(` ${key}=${typeof value === "string" ? `"${value}"` : `{${value}}`}`)]));
return acc;
}, []),
...hasMore ? [txt(" …")] : [],
txt(el.children ? `> {…} </${elName}>` : ` />`)
]);
},
node({ value, keyPath, createNode }) {
return {
value,
type: "react-element",
keyPath,
children: REACT_ELEMENT_KEYS.reduce((acc, key) => {
let childValue = Reflect.get(value, key);
if (key === "type") childValue = getElementTypeName(childValue);
acc.push(createNode([key], childValue));
return acc;
}, [])
};
}
});
const map = {
"\n": "\\n",
" ": "\\t",
"\r": "\\r"
};
const STRING_ESCAPE_REGEXP = /[\n\t\r]/g;
const StringType = dataType({
type: "string",
description(node, opts) {
return `"${this.previewText?.(node, opts) ?? node.value}"`;
},
check(value) {
return typeof value === "string";
},
previewText(node, opts) {
const serialised = node.value.replace(STRING_ESCAPE_REGEXP, (_) => map[_]);
return serialised.slice(0, opts.collapseStringsAfterLength) + (serialised.length > opts.collapseStringsAfterLength ? "…" : "");
},
previewElement(node) {
return jsx("span", {}, [txt(`"${node.value.replace(STRING_ESCAPE_REGEXP, (_) => map[_])}"`)]);
},
node({ value, keyPath }) {
return {
value,
type: "string",
keyPath
};
}
});
const PrimitiveType = dataType({
type(value) {
return typeof value;
},
description(node) {
return String(node.value);
},
check(value) {
return value !== null && value !== void 0;
},
previewElement(node) {
return jsx("span", {}, [txt(String(node.value))]);
},
node({ value, keyPath }) {
return {
value,
type: typeof value,
keyPath
};
}
});
const dataTypes = [
NullType,
UndefinedType,
SymbolType,
BigIntType,
FunctionType,
ArrayBufferType,
SharedArrayBufferType,
BufferType,
DataViewType,
ErrorType,
DateType,
RegexType,
SetType,
MapType,
WeakMapType,
WeakSetType,
FileType,
BlobType,
ReactElementType,
WindowType,
DocumentType,
ElementType,
UrlType,
URLSearchParamsType,
HeadersType,
FormDataType,
ArrayType,
TypedArrayType,
IterableType,
ClassType,
ObjectType,
StringType,
PrimitiveType
];
const jsonNodeToElement = (node, opts) => {
const options = getPreviewOptions(opts);
const key = keyPathToKey(node.keyPath, { excludeRoot: true });
if (key === "stack" && typeof node.value === "string") return errorStackToElement(node.value);
const dataType = dataTypes.find((dataType) => dataType.check(node.value));
if (!dataType) return jsx("span", {}, [txt(String(node.value))]);
const element = dataType.previewElement(node, options);
if (!key) element.properties.root = true;
element.properties.kind = "preview";
element.properties.nodeType = typeof dataType.type === "function" ? dataType.type(node.value) : dataType.type;
return element;
};
const getNodeTypeDescription = (node, opts) => {
const options = getPreviewOptions(opts);
const dataType = dataTypes.find((dataType) => dataType.check(node.value));
if (dataType) return typeof dataType.description === "function" ? dataType.description(node, options) : dataType.description;
return String(node.value);
};
//#endregion
//#region src/shared/json-tree-utils/accessibility.ts
const propertyWord = (count) => count === 1 ? "property" : "properties";
const isPrimitive = (node) => {
return node.type === "string" || node.type === "number" || node.type === "boolean";
};
const getAccessibleDescription = (node, opts) => {
const typeDescription = getNodeTypeDescription(node, opts);
const key = keyPathToKey(node.keyPath, { excludeRoot: true });
const nonEnumerablePrefix = node.isNonEnumerable ? "non-enumerable " : "";
const format = (text) => {
return [key, `${nonEnumerablePrefix}${text}`].filter(Boolean).join(": ");
};
if (node.children && node.children.length > 0) {
const childCount = node.children.length;
if (key === "[[Entries]]") return format(`${childCount} ${propertyWord(childCount)}`);
return format(`${typeDescription}, expandable with ${childCount} ${propertyWord(childCount)}`);
}
if (isPrimitive(node)) {
if (key === "stack") return format(node.value.split("\n")[1]?.trim() || "trace");
if (key === "[[Function]]") return format("function implementation");
return format(`${typeof node.value === "string" ? `"${node.value}"` : String(node.value)}${node.isNonEnumerable && node.propertyDescriptor ? `, ${getDescriptorInfo(node.propertyDescriptor)}` : ""}`);
}
if (node.type === "null") return format("null");
if (node.type === "undefined") return format("undefined");
if (node.type === "circular") return format("circular reference");
return format(`${nonEnumerablePrefix}${typeDescription}${node.isNonEnumerable && node.propertyDescriptor ? `, ${getDescriptorInfo(node.propertyDescriptor)}` : ""}`);
};
const getDescriptorInfo = (descriptor) => {
const parts = [];
if (!descriptor.writable) parts.push("read-only");
if (!descriptor.configurable) parts.push("non-configurable");
return parts.length > 0 ? parts.join(", ") : "non-enumerable";
};
//#endregion
export { ArrayBufferType, ArrayType, BigIntType, BlobType, BufferType, ClassType, DEFAULT_PREVIEW_OPTIONS, DataViewType, DateType, DocumentType, ElementType, ErrorType, FileType, FormDataType, FunctionType, HeadersType, IterableType, MapType, NullType, ObjectType, PATH_SEP, PrimitiveType, ROOT_KEY, ReactElementType, RegexType, SetType, SharedArrayBufferType, StringType, SymbolType, TypedArrayType, URLSearchParamsType, UndefinedType, UrlType, WeakMapType, WeakSetType, WindowType, dataTypes, getAccessibleDescription, getNodeTypeDescription, getPreviewOptions, getRootNode, isRootKeyPath, jsonNodeToElement, jsonPathToValue, jsonToTree, keyPathToId, keyPathToKey, nodeToString, nodeToValue };
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
//#region src/shared/live-region/index.ts
const ID = "__live-region__";
function createLiveRegion(opts = {}) {
const { level = "polite", document: doc = document, root, delay: _delay = 0 } = opts;
const win = doc.defaultView ?? window;
const parent = root ?? doc.body;
function announce(message, delay) {
doc.getElementById(ID)?.remove();
delay = delay ?? _delay;
const region = doc.createElement("span");
region.id = ID;
region.dataset.liveAnnouncer = "true";
const role = level !== "assertive" ? "status" : "alert";
region.setAttribute("aria-live", level);
region.setAttribute("role", role);
Object.assign(region.style, {
border: "0",
clip: "rect(0 0 0 0)",
height: "1px",
margin: "-1px",
overflow: "hidden",
padding: "0",
position: "absolute",
width: "1px",
whiteSpace: "nowrap",
wordWrap: "normal"
});
parent.appendChild(region);
win.setTimeout(() => {
region.textContent = message;
}, delay);
}
function destroy() {
doc.getElementById(ID)?.remove();
}
return {
announce,
destroy,
toJSON() {
return ID;
}
};
}
//#endregion
exports.createLiveRegion = createLiveRegion;
//#region src/shared/live-region/index.d.ts
interface LiveRegionOptions {
level: "polite" | "assertive";
document?: Document | undefined;
root?: HTMLElement | null | undefined;
delay?: number | undefined;
}
type LiveRegion = ReturnType<typeof createLiveRegion>;
declare function createLiveRegion(opts?: Partial<LiveRegionOptions>): {
announce: (message: string, delay?: number) => void;
destroy: () => void;
toJSON(): string;
};
//#endregion
export { LiveRegion, LiveRegionOptions, createLiveRegion };
//#region src/shared/live-region/index.d.ts
interface LiveRegionOptions {
level: "polite" | "assertive";
document?: Document | undefined;
root?: HTMLElement | null | undefined;
delay?: number | undefined;
}
type LiveRegion = ReturnType<typeof createLiveRegion>;
declare function createLiveRegion(opts?: Partial<LiveRegionOptions>): {
announce: (message: string, delay?: number) => void;
destroy: () => void;
toJSON(): string;
};
//#endregion
export { LiveRegion, LiveRegionOptions, createLiveRegion };
//#region src/shared/live-region/index.ts
const ID = "__live-region__";
function createLiveRegion(opts = {}) {
const { level = "polite", document: doc = document, root, delay: _delay = 0 } = opts;
const win = doc.defaultView ?? window;
const parent = root ?? doc.body;
function announce(message, delay) {
doc.getElementById(ID)?.remove();
delay = delay ?? _delay;
const region = doc.createElement("span");
region.id = ID;
region.dataset.liveAnnouncer = "true";
const role = level !== "assertive" ? "status" : "alert";
region.setAttribute("aria-live", level);
region.setAttribute("role", role);
Object.assign(region.style, {
border: "0",
clip: "rect(0 0 0 0)",
height: "1px",
margin: "-1px",
overflow: "hidden",
padding: "0",
position: "absolute",
width: "1px",
whiteSpace: "nowrap",
wordWrap: "normal"
});
parent.appendChild(region);
win.setTimeout(() => {
region.textContent = message;
}, delay);
}
function destroy() {
doc.getElementById(ID)?.remove();
}
return {
announce,
destroy,
toJSON() {
return ID;
}
};
}
//#endregion
export { createLiveRegion };
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_create_anatomy = require("../../create-anatomy-CpViYTjA.cjs");
const require_dom_query = require("../../dom-query-BT6fffRP.cjs");
const require_core = require("../../core-DH_mBI7F.cjs");
const require_create_props = require("../../create-props-MMZJXgtK.cjs");
let _ginxjs_core_utils = require("@ginxjs/core/utils");
//#region src/machines/accordion/accordion.anatomy.ts
const anatomy = require_create_anatomy.createAnatomy("accordion").parts("root", "item", "itemTrigger", "itemContent", "itemIndicator");
const parts = anatomy.build();
//#endregion
//#region src/machines/accordion/accordion.dom.ts
const getRootId = (ctx) => ctx.ids?.root ?? `accordion:${ctx.id}`;
const getItemId = (ctx, value) => ctx.ids?.item?.(value) ?? `accordion:${ctx.id}:item:${value}`;
const getItemContentId = (ctx, value) => ctx.ids?.itemContent?.(value) ?? `accordion:${ctx.id}:content:${value}`;
const getItemTriggerId = (ctx, value) => ctx.ids?.itemTrigger?.(value) ?? `accordion:${ctx.id}:trigger:${value}`;
const getRootEl = (ctx) => ctx.getById(getRootId(ctx));
const getTriggerEls = (ctx) => {
const selector = `[data-controls][data-ownedby='${CSS.escape(getRootId(ctx))}']:not([disabled])`;
return require_dom_query.queryAll(getRootEl(ctx), selector);
};
const getFirstTriggerEl = (ctx) => (0, _ginxjs_core_utils.first)(getTriggerEls(ctx));
const getLastTriggerEl = (ctx) => (0, _ginxjs_core_utils.last)(getTriggerEls(ctx));
const getNextTriggerEl = (ctx, id) => require_dom_query.nextById(getTriggerEls(ctx), getItemTriggerId(ctx, id));
const getPrevTriggerEl = (ctx, id) => require_dom_query.prevById(getTriggerEls(ctx), getItemTriggerId(ctx, id));
//#endregion
//#region src/machines/accordion/accordion.connect.ts
function connect(service, normalize) {
const { send, context, prop, scope, computed } = service;
const focusedValue = context.get("focusedValue");
const value = context.get("value");
const multiple = prop("multiple");
function setValue(value) {
let nextValue = value;
if (!multiple && nextValue.length > 1) nextValue = [nextValue[0]];
send({
type: "VALUE.SET",
value: nextValue
});
}
function getItemState(props) {
return {
expanded: value.includes(props.value),
focused: focusedValue === props.value,
disabled: Boolean(props.disabled ?? prop("disabled"))
};
}
return {
focusedValue,
value,
setValue,
getItemState,
getRootProps() {
return normalize.element({
...parts.root.attrs,
dir: prop("dir"),
id: getRootId(scope),
"data-orientation": prop("orientation")
});
},
getItemProps(props) {
const itemState = getItemState(props);
return normalize.element({
...parts.item.attrs,
dir: prop("dir"),
id: getItemId(scope, props.value),
"data-state": itemState.expanded ? "open" : "closed",
"data-focus": require_dom_query.dataAttr(itemState.focused),
"data-disabled": require_dom_query.dataAttr(itemState.disabled),
"data-orientation": prop("orientation")
});
},
getItemContentProps(props) {
const itemState = getItemState(props);
return normalize.element({
...parts.itemContent.attrs,
dir: prop("dir"),
role: "region",
id: getItemContentId(scope, props.value),
"aria-labelledby": getItemTriggerId(scope, props.value),
hidden: !itemState.expanded,
"data-state": itemState.expanded ? "open" : "closed",
"data-disabled": require_dom_query.dataAttr(itemState.disabled),
"data-focus": require_dom_query.dataAttr(itemState.focused),
"data-orientation": prop("orientation")
});
},
getItemIndicatorProps(props) {
const itemState = getItemState(props);
return normalize.element({
...parts.itemIndicator.attrs,
dir: prop("dir"),
"aria-hidden": true,
"data-state": itemState.expanded ? "open" : "closed",
"data-disabled": require_dom_query.dataAttr(itemState.disabled),
"data-focus": require_dom_query.dataAttr(itemState.focused),
"data-orientation": prop("orientation")
});
},
getItemTriggerProps(props) {
const { value } = props;
const itemState = getItemState(props);
return normalize.button({
...parts.itemTrigger.attrs,
type: "button",
dir: prop("dir"),
id: getItemTriggerId(scope, value),
"aria-controls": getItemContentId(scope, value),
"data-controls": getItemContentId(scope, value),
"aria-expanded": itemState.expanded,
disabled: itemState.disabled,
"data-orientation": prop("orientation"),
"aria-disabled": itemState.disabled,
"data-state": itemState.expanded ? "open" : "closed",
"data-focus": require_dom_query.dataAttr(itemState.focused),
"data-ownedby": getRootId(scope),
onFocus() {
if (itemState.disabled) return;
send({
type: "TRIGGER.FOCUS",
value
});
},
onBlur() {
if (itemState.disabled) return;
send({ type: "TRIGGER.BLUR" });
},
onClick(event) {
if (itemState.disabled) return;
if (require_dom_query.isSafari()) event.currentTarget.focus();
send({
type: "TRIGGER.CLICK",
value
});
},
onKeyDown(event) {
if (event.defaultPrevented) return;
if (itemState.disabled) return;
const exec = {
ArrowDown() {
if (computed("isHorizontal")) return;
send({
type: "GOTO.NEXT",
value
});
},
ArrowUp() {
if (computed("isHorizontal")) return;
send({
type: "GOTO.PREV",
value
});
},
ArrowRight() {
if (!computed("isHorizontal")) return;
send({
type: "GOTO.NEXT",
value
});
},
ArrowLeft() {
if (!computed("isHorizontal")) return;
send({
type: "GOTO.PREV",
value
});
},
Home() {
send({
type: "GOTO.FIRST",
value
});
},
End() {
send({
type: "GOTO.LAST",
value
});
}
}[require_dom_query.getEventKey(event, {
dir: prop("dir"),
orientation: prop("orientation")
})];
if (exec) {
exec(event);
event.preventDefault();
}
}
});
}
};
}
//#endregion
//#region src/machines/accordion/accordion.machine.ts
const { and, not } = require_core.createGuards();
const machine = require_core.createMachine({
props({ props }) {
return {
collapsible: false,
multiple: false,
orientation: "vertical",
defaultValue: [],
...props
};
},
initialState() {
return "idle";
},
context({ prop, bindable }) {
return {
focusedValue: bindable(() => ({
defaultValue: null,
sync: true,
onChange(value) {
prop("onFocusChange")?.({ value });
}
})),
value: bindable(() => ({
defaultValue: prop("defaultValue"),
value: prop("value"),
onChange(value) {
prop("onValueChange")?.({ value });
}
}))
};
},
computed: { isHorizontal: ({ prop }) => prop("orientation") === "horizontal" },
on: { "VALUE.SET": { actions: ["setValue"] } },
states: {
idle: { on: { "TRIGGER.FOCUS": {
target: "focused",
actions: ["setFocusedValue"]
} } },
focused: { on: {
"GOTO.NEXT": { actions: ["focusNextTrigger"] },
"GOTO.PREV": { actions: ["focusPrevTrigger"] },
"TRIGGER.CLICK": [{
guard: and("isExpanded", "canToggle"),
actions: ["collapse"]
}, {
guard: not("isExpanded"),
actions: ["expand"]
}],
"GOTO.FIRST": { actions: ["focusFirstTrigger"] },
"GOTO.LAST": { actions: ["focusLastTrigger"] },
"TRIGGER.BLUR": {
target: "idle",
actions: ["clearFocusedValue"]
}
} }
},
implementations: {
guards: {
canToggle: ({ prop }) => !!prop("collapsible") || !!prop("multiple"),
isExpanded: ({ context, event }) => context.get("value").includes(event.value)
},
actions: {
collapse({ context, prop, event }) {
const next = prop("multiple") ? (0, _ginxjs_core_utils.remove)(context.get("value"), event.value) : [];
context.set("value", next);
},
expand({ context, prop, event }) {
const next = prop("multiple") ? (0, _ginxjs_core_utils.add)(context.get("value"), event.value) : [event.value];
context.set("value", next);
},
focusFirstTrigger({ scope }) {
getFirstTriggerEl(scope)?.focus();
},
focusLastTrigger({ scope }) {
getLastTriggerEl(scope)?.focus();
},
focusNextTrigger({ context, scope }) {
const focusedValue = context.get("focusedValue");
if (!focusedValue) return;
getNextTriggerEl(scope, focusedValue)?.focus();
},
focusPrevTrigger({ context, scope }) {
const focusedValue = context.get("focusedValue");
if (!focusedValue) return;
getPrevTriggerEl(scope, focusedValue)?.focus();
},
setFocusedValue({ context, event }) {
context.set("focusedValue", event.value);
},
clearFocusedValue({ context }) {
context.set("focusedValue", null);
},
setValue({ context, event }) {
context.set("value", event.value);
},
coarseValue({ context, prop }) {
if (!prop("multiple") && context.get("value").length > 1) {
(0, _ginxjs_core_utils.warn)(`The value of accordion should be a single value when multiple is false.`);
context.set("value", [context.get("value")[0]]);
}
}
}
}
});
//#endregion
//#region src/machines/accordion/accordion.props.ts
const props = require_create_props.createProps()([
"collapsible",
"dir",
"disabled",
"getRootNode",
"id",
"ids",
"multiple",
"onFocusChange",
"onValueChange",
"orientation",
"value",
"defaultValue"
]);
const splitProps = (0, _ginxjs_core_utils.createSplitProps)(props);
const itemProps = require_create_props.createProps()(["value", "disabled"]);
const splitItemProps = (0, _ginxjs_core_utils.createSplitProps)(itemProps);
//#endregion
exports.anatomy = anatomy;
exports.connect = connect;
exports.itemProps = itemProps;
exports.machine = machine;
exports.props = props;
exports.splitItemProps = splitItemProps;
exports.splitProps = splitProps;
import { n as AnatomyInstance } from "../../anatomy-DFl8j10C.cjs";
import { b as NormalizeProps, g as RequiredBy, r as DirectionProperty, t as CommonProperties, x as PropTypes } from "../../index-DFJGBSAc.cjs";
import { M as Service, S as EventObject, T as Machine } from "../../index-BNaxg4iu.cjs";
//#region src/machines/accordion/accordion.anatomy.d.ts
declare const anatomy: AnatomyInstance<"root" | "item" | "itemTrigger" | "itemContent" | "itemIndicator">;
//#endregion
//#region src/machines/accordion/accordion.types.d.ts
interface ValueChangeDetails {
value: string[];
}
interface FocusChangeDetails {
value: string | null;
}
type ElementIds = Partial<{
root: string;
item: (value: string) => string;
itemContent: (value: string) => string;
itemTrigger: (value: string) => string;
}>;
interface AccordionProps extends DirectionProperty, CommonProperties {
ids?: ElementIds | undefined;
multiple?: boolean | undefined;
collapsible?: boolean | undefined;
value?: string[] | undefined;
defaultValue?: string[] | undefined;
disabled?: boolean | undefined;
onValueChange?: ((details: ValueChangeDetails) => void) | undefined;
onFocusChange?: ((details: FocusChangeDetails) => void) | undefined;
orientation?: "horizontal" | "vertical" | undefined;
}
type PropsWithDefault = "multiple" | "collapsible" | "orientation";
type AccordionSchema = {
state: "idle" | "focused";
props: RequiredBy<AccordionProps, PropsWithDefault>;
context: {
value: string[];
focusedValue: string | null;
};
computed: {
isHorizontal: boolean;
};
action: string;
guard: string;
effect: string;
event: EventObject;
};
type AccordionService = Service<AccordionSchema>;
type AccordionMachine = Machine<AccordionSchema>;
interface ItemProps {
value: string;
disabled?: boolean | undefined;
}
interface ItemState {
expanded: boolean;
focused: boolean;
disabled: boolean;
}
interface AccordionApi<T extends PropTypes = PropTypes> {
focusedValue: string | null;
value: string[];
setValue: (value: string[]) => void;
getItemState: (props: ItemProps) => ItemState;
getRootProps: () => T["element"];
getItemProps: (props: ItemProps) => T["element"];
getItemContentProps: (props: ItemProps) => T["element"];
getItemTriggerProps: (props: ItemProps) => T["button"];
getItemIndicatorProps: (props: ItemProps) => T["element"];
}
//#endregion
//#region src/machines/accordion/accordion.connect.d.ts
declare function connect<T extends PropTypes>(service: Service<AccordionSchema>, normalize: NormalizeProps<T>): AccordionApi<T>;
//#endregion
//#region src/machines/accordion/accordion.machine.d.ts
declare const machine: Machine<AccordionSchema>;
//#endregion
//#region src/machines/accordion/accordion.props.d.ts
declare const props: (keyof AccordionProps)[];
declare const splitProps: <Props extends Partial<AccordionProps>>(props: Props) => [Partial<AccordionProps>, Omit<Props, keyof AccordionProps>];
declare const itemProps: (keyof ItemProps)[];
declare const splitItemProps: <Props extends ItemProps>(props: Props) => [ItemProps, Omit<Props, keyof ItemProps>];
//#endregion
export { type AccordionApi as Api, type ElementIds, type FocusChangeDetails, type ItemProps, type ItemState, type AccordionMachine as Machine, type AccordionProps as Props, type AccordionService as Service, type ValueChangeDetails, anatomy, connect, itemProps, machine, props, splitItemProps, splitProps };
import { n as AnatomyInstance } from "../../anatomy-C9pDRrRN.mjs";
import { b as NormalizeProps, g as RequiredBy, r as DirectionProperty, t as CommonProperties, x as PropTypes } from "../../index-Cq2OwLf_.mjs";
import { M as Service, S as EventObject, T as Machine } from "../../index-g2S6NCuN.mjs";
//#region src/machines/accordion/accordion.anatomy.d.ts
declare const anatomy: AnatomyInstance<"root" | "item" | "itemTrigger" | "itemContent" | "itemIndicator">;
//#endregion
//#region src/machines/accordion/accordion.types.d.ts
interface ValueChangeDetails {
value: string[];
}
interface FocusChangeDetails {
value: string | null;
}
type ElementIds = Partial<{
root: string;
item: (value: string) => string;
itemContent: (value: string) => string;
itemTrigger: (value: string) => string;
}>;
interface AccordionProps extends DirectionProperty, CommonProperties {
ids?: ElementIds | undefined;
multiple?: boolean | undefined;
collapsible?: boolean | undefined;
value?: string[] | undefined;
defaultValue?: string[] | undefined;
disabled?: boolean | undefined;
onValueChange?: ((details: ValueChangeDetails) => void) | undefined;
onFocusChange?: ((details: FocusChangeDetails) => void) | undefined;
orientation?: "horizontal" | "vertical" | undefined;
}
type PropsWithDefault = "multiple" | "collapsible" | "orientation";
type AccordionSchema = {
state: "idle" | "focused";
props: RequiredBy<AccordionProps, PropsWithDefault>;
context: {
value: string[];
focusedValue: string | null;
};
computed: {
isHorizontal: boolean;
};
action: string;
guard: string;
effect: string;
event: EventObject;
};
type AccordionService = Service<AccordionSchema>;
type AccordionMachine = Machine<AccordionSchema>;
interface ItemProps {
value: string;
disabled?: boolean | undefined;
}
interface ItemState {
expanded: boolean;
focused: boolean;
disabled: boolean;
}
interface AccordionApi<T extends PropTypes = PropTypes> {
focusedValue: string | null;
value: string[];
setValue: (value: string[]) => void;
getItemState: (props: ItemProps) => ItemState;
getRootProps: () => T["element"];
getItemProps: (props: ItemProps) => T["element"];
getItemContentProps: (props: ItemProps) => T["element"];
getItemTriggerProps: (props: ItemProps) => T["button"];
getItemIndicatorProps: (props: ItemProps) => T["element"];
}
//#endregion
//#region src/machines/accordion/accordion.connect.d.ts
declare function connect<T extends PropTypes>(service: Service<AccordionSchema>, normalize: NormalizeProps<T>): AccordionApi<T>;
//#endregion
//#region src/machines/accordion/accordion.machine.d.ts
declare const machine: Machine<AccordionSchema>;
//#endregion
//#region src/machines/accordion/accordion.props.d.ts
declare const props: (keyof AccordionProps)[];
declare const splitProps: <Props extends Partial<AccordionProps>>(props: Props) => [Partial<AccordionProps>, Omit<Props, keyof AccordionProps>];
declare const itemProps: (keyof ItemProps)[];
declare const splitItemProps: <Props extends ItemProps>(props: Props) => [ItemProps, Omit<Props, keyof ItemProps>];
//#endregion
export { type AccordionApi as Api, type ElementIds, type FocusChangeDetails, type ItemProps, type ItemState, type AccordionMachine as Machine, type AccordionProps as Props, type AccordionService as Service, type ValueChangeDetails, anatomy, connect, itemProps, machine, props, splitItemProps, splitProps };
import { t as createAnatomy } from "../../create-anatomy-tqxVmw3d.mjs";
import { Ht as isSafari, S as prevById, Tn as dataAttr, pt as getEventKey, w as queryAll, x as nextById } from "../../dom-query-BgxIO7_X.mjs";
import { a as createMachine, i as createGuards } from "../../core-D3PQ0tSv.mjs";
import { t as createProps } from "../../create-props-Bi7oeFLF.mjs";
import { add, createSplitProps, first, last, remove, warn } from "@ginxjs/core/utils";
//#region src/machines/accordion/accordion.anatomy.ts
const anatomy = createAnatomy("accordion").parts("root", "item", "itemTrigger", "itemContent", "itemIndicator");
const parts = anatomy.build();
//#endregion
//#region src/machines/accordion/accordion.dom.ts
const getRootId = (ctx) => ctx.ids?.root ?? `accordion:${ctx.id}`;
const getItemId = (ctx, value) => ctx.ids?.item?.(value) ?? `accordion:${ctx.id}:item:${value}`;
const getItemContentId = (ctx, value) => ctx.ids?.itemContent?.(value) ?? `accordion:${ctx.id}:content:${value}`;
const getItemTriggerId = (ctx, value) => ctx.ids?.itemTrigger?.(value) ?? `accordion:${ctx.id}:trigger:${value}`;
const getRootEl = (ctx) => ctx.getById(getRootId(ctx));
const getTriggerEls = (ctx) => {
const selector = `[data-controls][data-ownedby='${CSS.escape(getRootId(ctx))}']:not([disabled])`;
return queryAll(getRootEl(ctx), selector);
};
const getFirstTriggerEl = (ctx) => first(getTriggerEls(ctx));
const getLastTriggerEl = (ctx) => last(getTriggerEls(ctx));
const getNextTriggerEl = (ctx, id) => nextById(getTriggerEls(ctx), getItemTriggerId(ctx, id));
const getPrevTriggerEl = (ctx, id) => prevById(getTriggerEls(ctx), getItemTriggerId(ctx, id));
//#endregion
//#region src/machines/accordion/accordion.connect.ts
function connect(service, normalize) {
const { send, context, prop, scope, computed } = service;
const focusedValue = context.get("focusedValue");
const value = context.get("value");
const multiple = prop("multiple");
function setValue(value) {
let nextValue = value;
if (!multiple && nextValue.length > 1) nextValue = [nextValue[0]];
send({
type: "VALUE.SET",
value: nextValue
});
}
function getItemState(props) {
return {
expanded: value.includes(props.value),
focused: focusedValue === props.value,
disabled: Boolean(props.disabled ?? prop("disabled"))
};
}
return {
focusedValue,
value,
setValue,
getItemState,
getRootProps() {
return normalize.element({
...parts.root.attrs,
dir: prop("dir"),
id: getRootId(scope),
"data-orientation": prop("orientation")
});
},
getItemProps(props) {
const itemState = getItemState(props);
return normalize.element({
...parts.item.attrs,
dir: prop("dir"),
id: getItemId(scope, props.value),
"data-state": itemState.expanded ? "open" : "closed",
"data-focus": dataAttr(itemState.focused),
"data-disabled": dataAttr(itemState.disabled),
"data-orientation": prop("orientation")
});
},
getItemContentProps(props) {
const itemState = getItemState(props);
return normalize.element({
...parts.itemContent.attrs,
dir: prop("dir"),
role: "region",
id: getItemContentId(scope, props.value),
"aria-labelledby": getItemTriggerId(scope, props.value),
hidden: !itemState.expanded,
"data-state": itemState.expanded ? "open" : "closed",
"data-disabled": dataAttr(itemState.disabled),
"data-focus": dataAttr(itemState.focused),
"data-orientation": prop("orientation")
});
},
getItemIndicatorProps(props) {
const itemState = getItemState(props);
return normalize.element({
...parts.itemIndicator.attrs,
dir: prop("dir"),
"aria-hidden": true,
"data-state": itemState.expanded ? "open" : "closed",
"data-disabled": dataAttr(itemState.disabled),
"data-focus": dataAttr(itemState.focused),
"data-orientation": prop("orientation")
});
},
getItemTriggerProps(props) {
const { value } = props;
const itemState = getItemState(props);
return normalize.button({
...parts.itemTrigger.attrs,
type: "button",
dir: prop("dir"),
id: getItemTriggerId(scope, value),
"aria-controls": getItemContentId(scope, value),
"data-controls": getItemContentId(scope, value),
"aria-expanded": itemState.expanded,
disabled: itemState.disabled,
"data-orientation": prop("orientation"),
"aria-disabled": itemState.disabled,
"data-state": itemState.expanded ? "open" : "closed",
"data-focus": dataAttr(itemState.focused),
"data-ownedby": getRootId(scope),
onFocus() {
if (itemState.disabled) return;
send({
type: "TRIGGER.FOCUS",
value
});
},
onBlur() {
if (itemState.disabled) return;
send({ type: "TRIGGER.BLUR" });
},
onClick(event) {
if (itemState.disabled) return;
if (isSafari()) event.currentTarget.focus();
send({
type: "TRIGGER.CLICK",
value
});
},
onKeyDown(event) {
if (event.defaultPrevented) return;
if (itemState.disabled) return;
const exec = {
ArrowDown() {
if (computed("isHorizontal")) return;
send({
type: "GOTO.NEXT",
value
});
},
ArrowUp() {
if (computed("isHorizontal")) return;
send({
type: "GOTO.PREV",
value
});
},
ArrowRight() {
if (!computed("isHorizontal")) return;
send({
type: "GOTO.NEXT",
value
});
},
ArrowLeft() {
if (!computed("isHorizontal")) return;
send({
type: "GOTO.PREV",
value
});
},
Home() {
send({
type: "GOTO.FIRST",
value
});
},
End() {
send({
type: "GOTO.LAST",
value
});
}
}[getEventKey(event, {
dir: prop("dir"),
orientation: prop("orientation")
})];
if (exec) {
exec(event);
event.preventDefault();
}
}
});
}
};
}
//#endregion
//#region src/machines/accordion/accordion.machine.ts
const { and, not } = createGuards();
const machine = createMachine({
props({ props }) {
return {
collapsible: false,
multiple: false,
orientation: "vertical",
defaultValue: [],
...props
};
},
initialState() {
return "idle";
},
context({ prop, bindable }) {
return {
focusedValue: bindable(() => ({
defaultValue: null,
sync: true,
onChange(value) {
prop("onFocusChange")?.({ value });
}
})),
value: bindable(() => ({
defaultValue: prop("defaultValue"),
value: prop("value"),
onChange(value) {
prop("onValueChange")?.({ value });
}
}))
};
},
computed: { isHorizontal: ({ prop }) => prop("orientation") === "horizontal" },
on: { "VALUE.SET": { actions: ["setValue"] } },
states: {
idle: { on: { "TRIGGER.FOCUS": {
target: "focused",
actions: ["setFocusedValue"]
} } },
focused: { on: {
"GOTO.NEXT": { actions: ["focusNextTrigger"] },
"GOTO.PREV": { actions: ["focusPrevTrigger"] },
"TRIGGER.CLICK": [{
guard: and("isExpanded", "canToggle"),
actions: ["collapse"]
}, {
guard: not("isExpanded"),
actions: ["expand"]
}],
"GOTO.FIRST": { actions: ["focusFirstTrigger"] },
"GOTO.LAST": { actions: ["focusLastTrigger"] },
"TRIGGER.BLUR": {
target: "idle",
actions: ["clearFocusedValue"]
}
} }
},
implementations: {
guards: {
canToggle: ({ prop }) => !!prop("collapsible") || !!prop("multiple"),
isExpanded: ({ context, event }) => context.get("value").includes(event.value)
},
actions: {
collapse({ context, prop, event }) {
const next = prop("multiple") ? remove(context.get("value"), event.value) : [];
context.set("value", next);
},
expand({ context, prop, event }) {
const next = prop("multiple") ? add(context.get("value"), event.value) : [event.value];
context.set("value", next);
},
focusFirstTrigger({ scope }) {
getFirstTriggerEl(scope)?.focus();
},
focusLastTrigger({ scope }) {
getLastTriggerEl(scope)?.focus();
},
focusNextTrigger({ context, scope }) {
const focusedValue = context.get("focusedValue");
if (!focusedValue) return;
getNextTriggerEl(scope, focusedValue)?.focus();
},
focusPrevTrigger({ context, scope }) {
const focusedValue = context.get("focusedValue");
if (!focusedValue) return;
getPrevTriggerEl(scope, focusedValue)?.focus();
},
setFocusedValue({ context, event }) {
context.set("focusedValue", event.value);
},
clearFocusedValue({ context }) {
context.set("focusedValue", null);
},
setValue({ context, event }) {
context.set("value", event.value);
},
coarseValue({ context, prop }) {
if (!prop("multiple") && context.get("value").length > 1) {
warn(`The value of accordion should be a single value when multiple is false.`);
context.set("value", [context.get("value")[0]]);
}
}
}
}
});
//#endregion
//#region src/machines/accordion/accordion.props.ts
const props = createProps()([
"collapsible",
"dir",
"disabled",
"getRootNode",
"id",
"ids",
"multiple",
"onFocusChange",
"onValueChange",
"orientation",
"value",
"defaultValue"
]);
const splitProps = createSplitProps(props);
const itemProps = createProps()(["value", "disabled"]);
const splitItemProps = createSplitProps(itemProps);
//#endregion
export { anatomy, connect, itemProps, machine, props, splitItemProps, splitProps };
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_core = require("../../core-DH_mBI7F.cjs");
let _ginxjs_core_utils = require("@ginxjs/core/utils");
//#region src/machines/async-list/async-list.connect.ts
function connect(service) {
const { state, context, send } = service;
const loading = state.matches("loading", "sorting");
const sorting = state.matches("sorting");
const items = context.get("items");
const cursor = context.get("cursor");
const empty = items.length === 0;
const hasMore = cursor != null;
return {
items,
sortDescriptor: context.get("sortDescriptor"),
loading,
sorting,
empty,
hasMore,
error: context.get("error"),
filterText: context.get("filterText"),
cursor,
abort() {
send({ type: "ABORT" });
},
reload() {
send({ type: "RELOAD" });
},
loadMore() {
send({ type: "LOAD_MORE" });
},
sort(sortDescriptor) {
send({
type: "SORT",
sortDescriptor
});
},
setFilterText(filterText) {
send({
type: "FILTER",
filterText
});
},
clearFilter() {
send({
type: "FILTER",
filterText: ""
});
}
};
}
//#endregion
//#region src/machines/async-list/async-list.machine.ts
const machine = require_core.createMachine({
props({ props }) {
(0, _ginxjs_core_utils.ensureProps)(props, ["load"], "load is required");
return props;
},
context({ prop, bindable }) {
return {
items: bindable(() => ({ defaultValue: prop("initialItems") ?? [] })),
cursor: bindable(() => ({ defaultValue: null })),
filterText: bindable(() => ({ defaultValue: prop("initialFilterText") ?? "" })),
sortDescriptor: bindable(() => ({ defaultValue: prop("initialSortDescriptor") })),
error: bindable(() => ({ defaultValue: void 0 }))
};
},
refs() {
return {
abort: null,
seq: 0
};
},
watch({ prop, track, send }) {
track([() => hashDeps(prop("dependencies"))], () => {
send({ type: "RELOAD" });
});
},
initialState() {
return "idle";
},
on: { RELOAD: {
target: "loading",
reenter: true,
actions: ["clearItems"]
} },
entry: ["loadIfNeeded"],
states: {
idle: { on: {
LOAD_MORE: {
guard: "hasCursor",
target: "loading"
},
SORT: [{
guard: "hasSortFn",
target: "sorting",
actions: [
"setSortDescriptor",
"clearCursor",
"performSort"
]
}, {
target: "loading",
actions: ["setSortDescriptor", "clearCursor"]
}],
FILTER: {
target: "loading",
actions: ["setFilterText", "clearCursor"]
}
} },
loading: {
entry: ["performFetch"],
exit: ["cancelFetch"],
on: {
SUCCESS: {
target: "idle",
actions: [
"setItems",
"setCursor",
"clearError",
"invokeOnSuccess"
]
},
ERROR: {
target: "idle",
actions: ["setError", "invokeOnError"]
},
ABORT: {
target: "idle",
actions: ["cancelFetch"]
},
FILTER: {
reenter: true,
target: "loading",
actions: ["setFilterText", "clearCursor"]
}
}
},
sorting: { on: {
SUCCESS: {
target: "idle",
actions: [
"setItems",
"setCursor",
"clearError",
"invokeOnSuccess"
]
},
ERROR: {
target: "idle",
actions: ["setError", "invokeOnError"]
},
ABORT: {
target: "idle",
actions: ["cancelSort"]
},
FILTER: {
target: "loading",
actions: [
"setFilterText",
"clearCursor",
"cancelSort"
]
},
RELOAD: {
target: "loading",
actions: ["clearItems", "cancelSort"]
},
SORT: [{
guard: "hasSortFn",
target: "sorting",
reenter: true,
actions: [
"setSortDescriptor",
"clearCursor",
"cancelSort",
"performSort"
]
}, {
target: "loading",
actions: [
"setSortDescriptor",
"clearCursor",
"cancelSort"
]
}]
} }
},
implementations: {
guards: {
hasCursor({ context }) {
return context.get("cursor") != null;
},
hasSortFn({ prop }) {
return prop("sort") != null;
}
},
actions: {
loadIfNeeded({ prop, send }) {
if (!prop("autoReload")) return;
send({ type: "RELOAD" });
},
performFetch({ context, prop, refs, send, event }) {
refs.set("abort", new AbortController());
const abort = refs.get("abort");
context.set("error", void 0);
const seq = refs.get("seq") + 1;
refs.set("seq", seq);
const isLoadMore = event.type === "LOAD_MORE";
prop("load")({
signal: abort?.signal,
cursor: isLoadMore ? context.get("cursor") : null,
filterText: event.filterText ?? context.get("filterText"),
sortDescriptor: event.sortDescriptor ?? context.get("sortDescriptor")
}).then(({ items, cursor }) => {
if (seq !== refs.get("seq")) return;
send({
type: "SUCCESS",
items,
cursor,
append: isLoadMore
});
}).catch((error) => {
if (seq !== refs.get("seq")) return;
if (isAbortError(error)) return;
send({
type: "ERROR",
error
});
});
},
performSort({ context, prop, send, event, refs }) {
const sortFn = prop("sort");
(0, _ginxjs_core_utils.ensure)(sortFn, () => "[ginxjs/async-list] sort is required");
const currentItems = context.get("items");
const filterText = context.get("filterText");
const seq = refs.get("seq") + 1;
refs.set("seq", seq);
Promise.resolve(sortFn({
items: currentItems,
descriptor: event.sortDescriptor,
filterText
})).then((r) => {
if (seq !== refs.get("seq")) return;
send({
type: "SUCCESS",
items: r?.items ?? currentItems,
cursor: void 0,
append: false
});
}).catch((e) => {
if (seq !== refs.get("seq")) return;
send({
type: "ERROR",
error: e
});
});
},
setSortDescriptor({ context, event }) {
context.set("sortDescriptor", event.sortDescriptor);
},
setFilterText({ context, event }) {
context.set("filterText", event.filterText);
},
invokeOnSuccess({ prop, event }) {
prop("onSuccess")?.({ items: event.items });
},
invokeOnError({ prop, event }) {
prop("onError")?.({ error: event.error });
},
clearItems({ context }) {
context.set("items", []);
},
setItems({ context, event }) {
context.set("items", (prev) => event.append ? [...prev, ...event.items] : event.items);
},
setCursor({ context, event }) {
context.set("cursor", event.cursor);
},
setError({ context, event }) {
context.set("error", event.error);
},
clearError({ context }) {
context.set("error", void 0);
},
clearCursor({ context }) {
context.set("cursor", null);
},
cancelFetch({ refs }) {
refs.get("abort")?.abort();
refs.set("abort", null);
},
cancelSort({ refs }) {
const seq = refs.get("seq") + 1;
refs.set("seq", seq);
}
}
}
});
function isAbortError(err) {
return err instanceof Error && err.name === "AbortError";
}
function hashDeps(deps = []) {
return deps.filter(Boolean).join(",");
}
//#endregion
exports.connect = connect;
exports.machine = machine;
import { M as Service, S as EventObject, T as Machine } from "../../index-BNaxg4iu.cjs";
//#region src/machines/async-list/async-list.types.d.ts
type SortDirection = "ascending" | "descending";
interface SortDescriptor<T> {
column: keyof T;
direction: SortDirection;
}
interface LoadDetails<T, C> {
signal: AbortSignal | undefined;
filterText: string;
cursor?: C | undefined;
sortDescriptor?: SortDescriptor<T> | undefined;
}
interface LoadResult<T, C> {
items: T[];
cursor?: C | undefined;
}
interface SortDetails<T> {
items: T[];
descriptor: SortDescriptor<T>;
filterText: string;
}
type LoadDependency = string | number | boolean | undefined | null;
interface AsyncListProps<T, C> {
load: (args: LoadDetails<T, C>) => Promise<LoadResult<T, C>>;
sort?: ((args: SortDetails<T>) => Promise<{
items: T[];
}> | {
items: T[];
} | undefined) | undefined;
initialItems?: T[] | undefined;
initialSortDescriptor?: SortDescriptor<T> | undefined;
initialFilterText?: string | undefined;
dependencies?: LoadDependency[] | undefined;
autoReload?: boolean | undefined;
onSuccess?: ((details: {
items: T[];
}) => void | undefined) | undefined;
onError?: ((details: {
error: Error;
}) => void | undefined) | undefined;
}
interface AsyncListSchema<T, C> {
state: "idle" | "loading" | "sorting";
props: AsyncListProps<T, C>;
context: {
items: T[];
filterText: string;
cursor?: C | undefined;
sortDescriptor?: SortDescriptor<T> | undefined;
error?: any | undefined;
};
refs: {
abort: AbortController | null;
seq: number;
};
event: EventObject;
action: string;
guard: string;
effect: string;
}
type AsyncListService<T, C> = Service<AsyncListSchema<T, C>>;
type AsyncListMachine<T, C> = Machine<AsyncListSchema<T, C>>;
interface AsyncListApi<T, C> {
items: T[];
filterText: string;
cursor: C | undefined;
sortDescriptor: SortDescriptor<T> | undefined;
loading: boolean;
sorting: boolean;
empty: boolean;
hasMore: boolean;
error: any | undefined;
abort: VoidFunction;
reload: VoidFunction;
loadMore: VoidFunction;
sort: (sortDescriptor: SortDescriptor<T>) => void;
setFilterText: (filterText: string) => void;
clearFilter: VoidFunction;
}
//#endregion
//#region src/machines/async-list/async-list.connect.d.ts
declare function connect<T, C>(service: AsyncListService<T, C>): AsyncListApi<T, C>;
//#endregion
//#region src/machines/async-list/async-list.machine.d.ts
declare const machine: Machine<AsyncListSchema<any, any>>;
//#endregion
export { type AsyncListApi as Api, type LoadDependency, type LoadDetails, type LoadResult, type AsyncListMachine as Machine, type AsyncListProps as Props, type AsyncListService as Service, type SortDescriptor, type SortDetails, type SortDirection, connect, machine };
import { M as Service, S as EventObject, T as Machine } from "../../index-g2S6NCuN.mjs";
//#region src/machines/async-list/async-list.types.d.ts
type SortDirection = "ascending" | "descending";
interface SortDescriptor<T> {
column: keyof T;
direction: SortDirection;
}
interface LoadDetails<T, C> {
signal: AbortSignal | undefined;
filterText: string;
cursor?: C | undefined;
sortDescriptor?: SortDescriptor<T> | undefined;
}
interface LoadResult<T, C> {
items: T[];
cursor?: C | undefined;
}
interface SortDetails<T> {
items: T[];
descriptor: SortDescriptor<T>;
filterText: string;
}
type LoadDependency = string | number | boolean | undefined | null;
interface AsyncListProps<T, C> {
load: (args: LoadDetails<T, C>) => Promise<LoadResult<T, C>>;
sort?: ((args: SortDetails<T>) => Promise<{
items: T[];
}> | {
items: T[];
} | undefined) | undefined;
initialItems?: T[] | undefined;
initialSortDescriptor?: SortDescriptor<T> | undefined;
initialFilterText?: string | undefined;
dependencies?: LoadDependency[] | undefined;
autoReload?: boolean | undefined;
onSuccess?: ((details: {
items: T[];
}) => void | undefined) | undefined;
onError?: ((details: {
error: Error;
}) => void | undefined) | undefined;
}
interface AsyncListSchema<T, C> {
state: "idle" | "loading" | "sorting";
props: AsyncListProps<T, C>;
context: {
items: T[];
filterText: string;
cursor?: C | undefined;
sortDescriptor?: SortDescriptor<T> | undefined;
error?: any | undefined;
};
refs: {
abort: AbortController | null;
seq: number;
};
event: EventObject;
action: string;
guard: string;
effect: string;
}
type AsyncListService<T, C> = Service<AsyncListSchema<T, C>>;
type AsyncListMachine<T, C> = Machine<AsyncListSchema<T, C>>;
interface AsyncListApi<T, C> {
items: T[];
filterText: string;
cursor: C | undefined;
sortDescriptor: SortDescriptor<T> | undefined;
loading: boolean;
sorting: boolean;
empty: boolean;
hasMore: boolean;
error: any | undefined;
abort: VoidFunction;
reload: VoidFunction;
loadMore: VoidFunction;
sort: (sortDescriptor: SortDescriptor<T>) => void;
setFilterText: (filterText: string) => void;
clearFilter: VoidFunction;
}
//#endregion
//#region src/machines/async-list/async-list.connect.d.ts
declare function connect<T, C>(service: AsyncListService<T, C>): AsyncListApi<T, C>;
//#endregion
//#region src/machines/async-list/async-list.machine.d.ts
declare const machine: Machine<AsyncListSchema<any, any>>;
//#endregion
export { type AsyncListApi as Api, type LoadDependency, type LoadDetails, type LoadResult, type AsyncListMachine as Machine, type AsyncListProps as Props, type AsyncListService as Service, type SortDescriptor, type SortDetails, type SortDirection, connect, machine };
import { a as createMachine } from "../../core-D3PQ0tSv.mjs";
import { ensure, ensureProps } from "@ginxjs/core/utils";
//#region src/machines/async-list/async-list.connect.ts
function connect(service) {
const { state, context, send } = service;
const loading = state.matches("loading", "sorting");
const sorting = state.matches("sorting");
const items = context.get("items");
const cursor = context.get("cursor");
const empty = items.length === 0;
const hasMore = cursor != null;
return {
items,
sortDescriptor: context.get("sortDescriptor"),
loading,
sorting,
empty,
hasMore,
error: context.get("error"),
filterText: context.get("filterText"),
cursor,
abort() {
send({ type: "ABORT" });
},
reload() {
send({ type: "RELOAD" });
},
loadMore() {
send({ type: "LOAD_MORE" });
},
sort(sortDescriptor) {
send({
type: "SORT",
sortDescriptor
});
},
setFilterText(filterText) {
send({
type: "FILTER",
filterText
});
},
clearFilter() {
send({
type: "FILTER",
filterText: ""
});
}
};
}
//#endregion
//#region src/machines/async-list/async-list.machine.ts
const machine = createMachine({
props({ props }) {
ensureProps(props, ["load"], "load is required");
return props;
},
context({ prop, bindable }) {
return {
items: bindable(() => ({ defaultValue: prop("initialItems") ?? [] })),
cursor: bindable(() => ({ defaultValue: null })),
filterText: bindable(() => ({ defaultValue: prop("initialFilterText") ?? "" })),
sortDescriptor: bindable(() => ({ defaultValue: prop("initialSortDescriptor") })),
error: bindable(() => ({ defaultValue: void 0 }))
};
},
refs() {
return {
abort: null,
seq: 0
};
},
watch({ prop, track, send }) {
track([() => hashDeps(prop("dependencies"))], () => {
send({ type: "RELOAD" });
});
},
initialState() {
return "idle";
},
on: { RELOAD: {
target: "loading",
reenter: true,
actions: ["clearItems"]
} },
entry: ["loadIfNeeded"],
states: {
idle: { on: {
LOAD_MORE: {
guard: "hasCursor",
target: "loading"
},
SORT: [{
guard: "hasSortFn",
target: "sorting",
actions: [
"setSortDescriptor",
"clearCursor",
"performSort"
]
}, {
target: "loading",
actions: ["setSortDescriptor", "clearCursor"]
}],
FILTER: {
target: "loading",
actions: ["setFilterText", "clearCursor"]
}
} },
loading: {
entry: ["performFetch"],
exit: ["cancelFetch"],
on: {
SUCCESS: {
target: "idle",
actions: [
"setItems",
"setCursor",
"clearError",
"invokeOnSuccess"
]
},
ERROR: {
target: "idle",
actions: ["setError", "invokeOnError"]
},
ABORT: {
target: "idle",
actions: ["cancelFetch"]
},
FILTER: {
reenter: true,
target: "loading",
actions: ["setFilterText", "clearCursor"]
}
}
},
sorting: { on: {
SUCCESS: {
target: "idle",
actions: [
"setItems",
"setCursor",
"clearError",
"invokeOnSuccess"
]
},
ERROR: {
target: "idle",
actions: ["setError", "invokeOnError"]
},
ABORT: {
target: "idle",
actions: ["cancelSort"]
},
FILTER: {
target: "loading",
actions: [
"setFilterText",
"clearCursor",
"cancelSort"
]
},
RELOAD: {
target: "loading",
actions: ["clearItems", "cancelSort"]
},
SORT: [{
guard: "hasSortFn",
target: "sorting",
reenter: true,
actions: [
"setSortDescriptor",
"clearCursor",
"cancelSort",
"performSort"
]
}, {
target: "loading",
actions: [
"setSortDescriptor",
"clearCursor",
"cancelSort"
]
}]
} }
},
implementations: {
guards: {
hasCursor({ context }) {
return context.get("cursor") != null;
},
hasSortFn({ prop }) {
return prop("sort") != null;
}
},
actions: {
loadIfNeeded({ prop, send }) {
if (!prop("autoReload")) return;
send({ type: "RELOAD" });
},
performFetch({ context, prop, refs, send, event }) {
refs.set("abort", new AbortController());
const abort = refs.get("abort");
context.set("error", void 0);
const seq = refs.get("seq") + 1;
refs.set("seq", seq);
const isLoadMore = event.type === "LOAD_MORE";
prop("load")({
signal: abort?.signal,
cursor: isLoadMore ? context.get("cursor") : null,
filterText: event.filterText ?? context.get("filterText"),
sortDescriptor: event.sortDescriptor ?? context.get("sortDescriptor")
}).then(({ items, cursor }) => {
if (seq !== refs.get("seq")) return;
send({
type: "SUCCESS",
items,
cursor,
append: isLoadMore
});
}).catch((error) => {
if (seq !== refs.get("seq")) return;
if (isAbortError(error)) return;
send({
type: "ERROR",
error
});
});
},
performSort({ context, prop, send, event, refs }) {
const sortFn = prop("sort");
ensure(sortFn, () => "[ginxjs/async-list] sort is required");
const currentItems = context.get("items");
const filterText = context.get("filterText");
const seq = refs.get("seq") + 1;
refs.set("seq", seq);
Promise.resolve(sortFn({
items: currentItems,
descriptor: event.sortDescriptor,
filterText
})).then((r) => {
if (seq !== refs.get("seq")) return;
send({
type: "SUCCESS",
items: r?.items ?? currentItems,
cursor: void 0,
append: false
});
}).catch((e) => {
if (seq !== refs.get("seq")) return;
send({
type: "ERROR",
error: e
});
});
},
setSortDescriptor({ context, event }) {
context.set("sortDescriptor", event.sortDescriptor);
},
setFilterText({ context, event }) {
context.set("filterText", event.filterText);
},
invokeOnSuccess({ prop, event }) {
prop("onSuccess")?.({ items: event.items });
},
invokeOnError({ prop, event }) {
prop("onError")?.({ error: event.error });
},
clearItems({ context }) {
context.set("items", []);
},
setItems({ context, event }) {
context.set("items", (prev) => event.append ? [...prev, ...event.items] : event.items);
},
setCursor({ context, event }) {
context.set("cursor", event.cursor);
},
setError({ context, event }) {
context.set("error", event.error);
},
clearError({ context }) {
context.set("error", void 0);
},
clearCursor({ context }) {
context.set("cursor", null);
},
cancelFetch({ refs }) {
refs.get("abort")?.abort();
refs.set("abort", null);
},
cancelSort({ refs }) {
const seq = refs.get("seq") + 1;
refs.set("seq", seq);
}
}
}
});
function isAbortError(err) {
return err instanceof Error && err.name === "AbortError";
}
function hashDeps(deps = []) {
return deps.filter(Boolean).join(",");
}
//#endregion
export { connect, machine };
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_create_anatomy = require("../../create-anatomy-CpViYTjA.cjs");
const require_dom_query = require("../../dom-query-BT6fffRP.cjs");
const require_core = require("../../core-DH_mBI7F.cjs");
const require_create_props = require("../../create-props-MMZJXgtK.cjs");
let _ginxjs_core_utils = require("@ginxjs/core/utils");
//#region src/machines/avatar/avatar.anatomy.ts
const anatomy = require_create_anatomy.createAnatomy("avatar").parts("root", "image", "fallback");
const parts = anatomy.build();
//#endregion
//#region src/machines/avatar/avatar.dom.ts
const getRootId = (ctx) => ctx.ids?.root ?? `avatar:${ctx.id}`;
const getImageId = (ctx) => ctx.ids?.image ?? `avatar:${ctx.id}:image`;
const getFallbackId = (ctx) => ctx.ids?.fallback ?? `avatar:${ctx.id}:fallback`;
const getRootEl = (ctx) => ctx.getById(getRootId(ctx));
const getImageEl = (ctx) => ctx.getById(getImageId(ctx));
//#endregion
//#region src/machines/avatar/avatar.connect.ts
function connect(service, normalize) {
const { state, send, prop, scope } = service;
const loaded = state.matches("loaded");
return {
loaded,
setSrc(src) {
getImageEl(scope)?.setAttribute("src", src);
},
setLoaded() {
send({
type: "img.loaded",
src: "api"
});
},
setError() {
send({
type: "img.error",
src: "api"
});
},
getRootProps() {
return normalize.element({
...parts.root.attrs,
dir: prop("dir"),
id: getRootId(scope)
});
},
getImageProps() {
return normalize.img({
...parts.image.attrs,
hidden: !loaded,
dir: prop("dir"),
id: getImageId(scope),
"data-state": loaded ? "visible" : "hidden",
onLoad() {
send({
type: "img.loaded",
src: "element"
});
},
onError() {
send({
type: "img.error",
src: "element"
});
}
});
},
getFallbackProps() {
return normalize.element({
...parts.fallback.attrs,
dir: prop("dir"),
id: getFallbackId(scope),
hidden: loaded,
"data-state": loaded ? "hidden" : "visible"
});
}
};
}
//#endregion
//#region src/machines/avatar/avatar.machine.ts
const machine = require_core.createMachine({
initialState() {
return "loading";
},
effects: ["trackImageRemoval", "trackSrcChange"],
on: {
"src.change": { target: "loading" },
"img.unmount": { target: "error" }
},
states: {
loading: {
entry: ["checkImageStatus"],
on: {
"img.loaded": {
target: "loaded",
actions: ["invokeOnLoad"]
},
"img.error": {
target: "error",
actions: ["invokeOnError"]
}
}
},
error: { on: { "img.loaded": {
target: "loaded",
actions: ["invokeOnLoad"]
} } },
loaded: { on: { "img.error": {
target: "error",
actions: ["invokeOnError"]
} } }
},
implementations: {
actions: {
invokeOnLoad({ prop }) {
prop("onStatusChange")?.({ status: "loaded" });
},
invokeOnError({ prop }) {
prop("onStatusChange")?.({ status: "error" });
},
checkImageStatus({ send, scope }) {
const imageEl = getImageEl(scope);
if (!imageEl?.complete) return;
send({
type: hasLoaded(imageEl) ? "img.loaded" : "img.error",
src: "ssr"
});
}
},
effects: {
trackImageRemoval({ send, scope }) {
return require_dom_query.observeChildren(getRootEl(scope), { callback(records) {
if (Array.from(records[0].removedNodes).find((node) => node.nodeType === Node.ELEMENT_NODE && node.matches("[data-scope=avatar][data-part=image]"))) send({ type: "img.unmount" });
} });
},
trackSrcChange({ send, scope }) {
return require_dom_query.observeAttributes(getImageEl(scope), {
attributes: ["src", "srcset"],
callback() {
send({ type: "src.change" });
}
});
}
}
}
});
function hasLoaded(image) {
return image.complete && image.naturalWidth !== 0 && image.naturalHeight !== 0;
}
//#endregion
//#region src/machines/avatar/avatar.props.ts
const props = require_create_props.createProps()([
"dir",
"id",
"ids",
"onStatusChange",
"getRootNode"
]);
const splitProps = (0, _ginxjs_core_utils.createSplitProps)(props);
//#endregion
exports.anatomy = anatomy;
exports.connect = connect;
exports.machine = machine;
exports.props = props;
exports.splitProps = splitProps;
import { n as AnatomyInstance } from "../../anatomy-DFl8j10C.cjs";
import { b as NormalizeProps, r as DirectionProperty, t as CommonProperties, x as PropTypes } from "../../index-DFJGBSAc.cjs";
import { M as Service, T as Machine } from "../../index-BNaxg4iu.cjs";
//#region src/machines/avatar/avatar.anatomy.d.ts
declare const anatomy: AnatomyInstance<"root" | "image" | "fallback">;
//#endregion
//#region src/machines/avatar/avatar.types.d.ts
type LoadStatus = "error" | "loaded";
interface StatusChangeDetails {
status: LoadStatus;
}
type ElementIds = Partial<{
root: string;
image: string;
fallback: string;
}>;
interface AvatarProps extends CommonProperties, DirectionProperty {
onStatusChange?: ((details: StatusChangeDetails) => void) | undefined;
ids?: ElementIds | undefined;
}
interface AvatarSchema {
props: AvatarProps;
context: any;
initial: "loading";
effect: "trackImageRemoval" | "trackSrcChange";
action: "invokeOnLoad" | "invokeOnError" | "checkImageStatus";
event: {
type: "img.loaded";
src?: string | undefined;
} | {
type: "img.error";
src?: string | undefined;
} | {
type: "img.unmount";
} | {
type: "src.change";
};
state: "loading" | "error" | "loaded";
}
type AvatarService = Service<AvatarSchema>;
type AvatarMachine = Machine<AvatarSchema>;
interface AvatarApi<T extends PropTypes = PropTypes> {
loaded: boolean;
setSrc: (src: string) => void;
setLoaded: VoidFunction;
setError: VoidFunction;
getRootProps: () => T["element"];
getImageProps: () => T["img"];
getFallbackProps: () => T["element"];
}
//#endregion
//#region src/machines/avatar/avatar.connect.d.ts
declare function connect<T extends PropTypes>(service: Service<AvatarSchema>, normalize: NormalizeProps<T>): AvatarApi<T>;
//#endregion
//#region src/machines/avatar/avatar.machine.d.ts
declare const machine: Machine<AvatarSchema>;
//#endregion
//#region src/machines/avatar/avatar.props.d.ts
declare const props: (keyof AvatarProps)[];
declare const splitProps: <Props extends Partial<AvatarProps>>(props: Props) => [Partial<AvatarProps>, Omit<Props, keyof AvatarProps>];
//#endregion
export { type AvatarApi as Api, type ElementIds, type LoadStatus, type AvatarMachine as Machine, type AvatarProps as Props, type AvatarService as Service, type StatusChangeDetails, anatomy, connect, machine, props, splitProps };
import { n as AnatomyInstance } from "../../anatomy-C9pDRrRN.mjs";
import { b as NormalizeProps, r as DirectionProperty, t as CommonProperties, x as PropTypes } from "../../index-Cq2OwLf_.mjs";
import { M as Service, T as Machine } from "../../index-g2S6NCuN.mjs";
//#region src/machines/avatar/avatar.anatomy.d.ts
declare const anatomy: AnatomyInstance<"root" | "image" | "fallback">;
//#endregion
//#region src/machines/avatar/avatar.types.d.ts
type LoadStatus = "error" | "loaded";
interface StatusChangeDetails {
status: LoadStatus;
}
type ElementIds = Partial<{
root: string;
image: string;
fallback: string;
}>;
interface AvatarProps extends CommonProperties, DirectionProperty {
onStatusChange?: ((details: StatusChangeDetails) => void) | undefined;
ids?: ElementIds | undefined;
}
interface AvatarSchema {
props: AvatarProps;
context: any;
initial: "loading";
effect: "trackImageRemoval" | "trackSrcChange";
action: "invokeOnLoad" | "invokeOnError" | "checkImageStatus";
event: {
type: "img.loaded";
src?: string | undefined;
} | {
type: "img.error";
src?: string | undefined;
} | {
type: "img.unmount";
} | {
type: "src.change";
};
state: "loading" | "error" | "loaded";
}
type AvatarService = Service<AvatarSchema>;
type AvatarMachine = Machine<AvatarSchema>;
interface AvatarApi<T extends PropTypes = PropTypes> {
loaded: boolean;
setSrc: (src: string) => void;
setLoaded: VoidFunction;
setError: VoidFunction;
getRootProps: () => T["element"];
getImageProps: () => T["img"];
getFallbackProps: () => T["element"];
}
//#endregion
//#region src/machines/avatar/avatar.connect.d.ts
declare function connect<T extends PropTypes>(service: Service<AvatarSchema>, normalize: NormalizeProps<T>): AvatarApi<T>;
//#endregion
//#region src/machines/avatar/avatar.machine.d.ts
declare const machine: Machine<AvatarSchema>;
//#endregion
//#region src/machines/avatar/avatar.props.d.ts
declare const props: (keyof AvatarProps)[];
declare const splitProps: <Props extends Partial<AvatarProps>>(props: Props) => [Partial<AvatarProps>, Omit<Props, keyof AvatarProps>];
//#endregion
export { type AvatarApi as Api, type ElementIds, type LoadStatus, type AvatarMachine as Machine, type AvatarProps as Props, type AvatarService as Service, type StatusChangeDetails, anatomy, connect, machine, props, splitProps };
import { t as createAnatomy } from "../../create-anatomy-tqxVmw3d.mjs";
import { B as observeAttributes, V as observeChildren } from "../../dom-query-BgxIO7_X.mjs";
import { a as createMachine } from "../../core-D3PQ0tSv.mjs";
import { t as createProps } from "../../create-props-Bi7oeFLF.mjs";
import { createSplitProps } from "@ginxjs/core/utils";
//#region src/machines/avatar/avatar.anatomy.ts
const anatomy = createAnatomy("avatar").parts("root", "image", "fallback");
const parts = anatomy.build();
//#endregion
//#region src/machines/avatar/avatar.dom.ts
const getRootId = (ctx) => ctx.ids?.root ?? `avatar:${ctx.id}`;
const getImageId = (ctx) => ctx.ids?.image ?? `avatar:${ctx.id}:image`;
const getFallbackId = (ctx) => ctx.ids?.fallback ?? `avatar:${ctx.id}:fallback`;
const getRootEl = (ctx) => ctx.getById(getRootId(ctx));
const getImageEl = (ctx) => ctx.getById(getImageId(ctx));
//#endregion
//#region src/machines/avatar/avatar.connect.ts
function connect(service, normalize) {
const { state, send, prop, scope } = service;
const loaded = state.matches("loaded");
return {
loaded,
setSrc(src) {
getImageEl(scope)?.setAttribute("src", src);
},
setLoaded() {
send({
type: "img.loaded",
src: "api"
});
},
setError() {
send({
type: "img.error",
src: "api"
});
},
getRootProps() {
return normalize.element({
...parts.root.attrs,
dir: prop("dir"),
id: getRootId(scope)
});
},
getImageProps() {
return normalize.img({
...parts.image.attrs,
hidden: !loaded,
dir: prop("dir"),
id: getImageId(scope),
"data-state": loaded ? "visible" : "hidden",
onLoad() {
send({
type: "img.loaded",
src: "element"
});
},
onError() {
send({
type: "img.error",
src: "element"
});
}
});
},
getFallbackProps() {
return normalize.element({
...parts.fallback.attrs,
dir: prop("dir"),
id: getFallbackId(scope),
hidden: loaded,
"data-state": loaded ? "hidden" : "visible"
});
}
};
}
//#endregion
//#region src/machines/avatar/avatar.machine.ts
const machine = createMachine({
initialState() {
return "loading";
},
effects: ["trackImageRemoval", "trackSrcChange"],
on: {
"src.change": { target: "loading" },
"img.unmount": { target: "error" }
},
states: {
loading: {
entry: ["checkImageStatus"],
on: {
"img.loaded": {
target: "loaded",
actions: ["invokeOnLoad"]
},
"img.error": {
target: "error",
actions: ["invokeOnError"]
}
}
},
error: { on: { "img.loaded": {
target: "loaded",
actions: ["invokeOnLoad"]
} } },
loaded: { on: { "img.error": {
target: "error",
actions: ["invokeOnError"]
} } }
},
implementations: {
actions: {
invokeOnLoad({ prop }) {
prop("onStatusChange")?.({ status: "loaded" });
},
invokeOnError({ prop }) {
prop("onStatusChange")?.({ status: "error" });
},
checkImageStatus({ send, scope }) {
const imageEl = getImageEl(scope);
if (!imageEl?.complete) return;
send({
type: hasLoaded(imageEl) ? "img.loaded" : "img.error",
src: "ssr"
});
}
},
effects: {
trackImageRemoval({ send, scope }) {
return observeChildren(getRootEl(scope), { callback(records) {
if (Array.from(records[0].removedNodes).find((node) => node.nodeType === Node.ELEMENT_NODE && node.matches("[data-scope=avatar][data-part=image]"))) send({ type: "img.unmount" });
} });
},
trackSrcChange({ send, scope }) {
return observeAttributes(getImageEl(scope), {
attributes: ["src", "srcset"],
callback() {
send({ type: "src.change" });
}
});
}
}
}
});
function hasLoaded(image) {
return image.complete && image.naturalWidth !== 0 && image.naturalHeight !== 0;
}
//#endregion
//#region src/machines/avatar/avatar.props.ts
const props = createProps()([
"dir",
"id",
"ids",
"onStatusChange",
"getRootNode"
]);
const splitProps = createSplitProps(props);
//#endregion
export { anatomy, connect, machine, props, splitProps };
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_create_anatomy = require("../../create-anatomy-CpViYTjA.cjs");
const require_dom_query = require("../../dom-query-BT6fffRP.cjs");
const require_core = require("../../core-DH_mBI7F.cjs");
const require_scroll_snap = require("../../scroll-snap-Cbwgrr_p.cjs");
const require_create_props = require("../../create-props-MMZJXgtK.cjs");
let _ginxjs_core_utils = require("@ginxjs/core/utils");
//#region src/machines/carousel/carousel.anatomy.ts
const anatomy = require_create_anatomy.createAnatomy("carousel").parts("root", "itemGroup", "item", "control", "nextTrigger", "prevTrigger", "indicatorGroup", "indicator", "autoplayTrigger", "progressText");
const parts = anatomy.build();
//#endregion
//#region src/machines/carousel/carousel.dom.ts
const getRootId = (ctx) => ctx.ids?.root ?? `carousel:${ctx.id}`;
const getItemId = (ctx, index) => ctx.ids?.item?.(index) ?? `carousel:${ctx.id}:item:${index}`;
const getItemGroupId = (ctx) => ctx.ids?.itemGroup ?? `carousel:${ctx.id}:item-group`;
const getNextTriggerId = (ctx) => ctx.ids?.nextTrigger ?? `carousel:${ctx.id}:next-trigger`;
const getPrevTriggerId = (ctx) => ctx.ids?.prevTrigger ?? `carousel:${ctx.id}:prev-trigger`;
const getIndicatorGroupId = (ctx) => ctx.ids?.indicatorGroup ?? `carousel:${ctx.id}:indicator-group`;
const getIndicatorId = (ctx, index) => ctx.ids?.indicator?.(index) ?? `carousel:${ctx.id}:indicator:${index}`;
const getItemGroupEl = (ctx) => ctx.getById(getItemGroupId(ctx));
const getItemEls = (ctx) => require_dom_query.queryAll(getItemGroupEl(ctx), `[data-part=item]`);
const getIndicatorEl = (ctx, page) => ctx.getById(getIndicatorId(ctx, page));
const syncTabIndex = (ctx) => {
const el = getItemGroupEl(ctx);
if (!el) return;
const tabbables = require_dom_query.getTabbables(el);
el.setAttribute("tabindex", tabbables.length > 0 ? "-1" : "0");
};
//#endregion
//#region src/machines/carousel/carousel.connect.ts
function connect(service, normalize) {
const { state, context, computed, send, scope, prop } = service;
const isPlaying = state.matches("autoplay");
const isDragging = state.matches("dragging");
const canScrollNext = computed("canScrollNext");
const canScrollPrev = computed("canScrollPrev");
const horizontal = computed("isHorizontal");
const autoSize = prop("autoSize");
const pageSnapPoints = Array.from(context.get("pageSnapPoints"));
const page = context.get("page");
const activePage = pageSnapPoints.length ? (0, _ginxjs_core_utils.clampValue)(page, 0, pageSnapPoints.length - 1) : 0;
const slidesPerPage = prop("slidesPerPage");
const padding = prop("padding");
const translations = prop("translations");
return {
isPlaying,
isDragging,
page: activePage,
pageSnapPoints,
canScrollNext,
canScrollPrev,
getProgress() {
return activePage / pageSnapPoints.length;
},
getProgressText() {
const details = {
page: activePage + 1,
totalPages: pageSnapPoints.length
};
return translations.progressText?.(details) ?? "";
},
scrollToIndex(index, instant) {
send({
type: "INDEX.SET",
index,
instant
});
},
scrollTo(index, instant) {
send({
type: "PAGE.SET",
index,
instant
});
},
scrollNext(instant) {
send({
type: "PAGE.NEXT",
instant
});
},
scrollPrev(instant) {
send({
type: "PAGE.PREV",
instant
});
},
play() {
send({ type: "AUTOPLAY.START" });
},
pause() {
send({ type: "AUTOPLAY.PAUSE" });
},
isInView(index) {
return Array.from(context.get("slidesInView")).includes(index);
},
refresh() {
send({ type: "SNAP.REFRESH" });
},
getRootProps() {
return normalize.element({
...parts.root.attrs,
id: getRootId(scope),
role: "region",
"aria-roledescription": "carousel",
"data-orientation": prop("orientation"),
dir: prop("dir"),
style: {
"--slides-per-page": slidesPerPage,
"--slide-spacing": prop("spacing"),
"--slide-item-size": autoSize ? "auto" : "calc(100% / var(--slides-per-page) - var(--slide-spacing) * (var(--slides-per-page) - 1) / var(--slides-per-page))"
}
});
},
getItemGroupProps() {
return normalize.element({
...parts.itemGroup.attrs,
id: getItemGroupId(scope),
"data-orientation": prop("orientation"),
"data-dragging": require_dom_query.dataAttr(isDragging),
dir: prop("dir"),
"aria-live": isPlaying ? "off" : "polite",
onFocus(event) {
if (!require_dom_query.contains(event.currentTarget, require_dom_query.getEventTarget(event))) return;
send({ type: "VIEWPORT.FOCUS" });
},
onBlur(event) {
if (require_dom_query.contains(event.currentTarget, event.relatedTarget)) return;
send({ type: "VIEWPORT.BLUR" });
},
onMouseDown(event) {
if (event.defaultPrevented) return;
if (!prop("allowMouseDrag")) return;
if (!require_dom_query.isLeftClick(event)) return;
const target = require_dom_query.getEventTarget(event);
if (require_dom_query.isFocusable(target) && target !== event.currentTarget) return;
event.preventDefault();
send({ type: "DRAGGING.START" });
},
onWheel: (0, _ginxjs_core_utils.throttle)((event) => {
const axis = prop("orientation") === "horizontal" ? "deltaX" : "deltaY";
if (event[axis] < 0 && !computed("canScrollPrev")) return;
if (event[axis] > 0 && !computed("canScrollNext")) return;
send({ type: "USER.SCROLL" });
}, 150),
onTouchStart() {
send({ type: "USER.SCROLL" });
},
style: {
display: autoSize ? "flex" : "grid",
gap: "var(--slide-spacing)",
scrollSnapType: [horizontal ? "x" : "y", prop("snapType")].join(" "),
gridAutoFlow: horizontal ? "column" : "row",
scrollbarWidth: "none",
overscrollBehaviorX: "contain",
[horizontal ? "gridAutoColumns" : "gridAutoRows"]: autoSize ? void 0 : "var(--slide-item-size)",
[horizontal ? "scrollPaddingInline" : "scrollPaddingBlock"]: padding,
[horizontal ? "paddingInline" : "paddingBlock"]: padding,
[horizontal ? "overflowX" : "overflowY"]: "auto"
}
});
},
getItemProps(props) {
const isInView = context.get("slidesInView").includes(props.index);
return normalize.element({
...parts.item.attrs,
id: getItemId(scope, props.index),
dir: prop("dir"),
role: "group",
"data-index": props.index,
"data-inview": require_dom_query.dataAttr(isInView),
"aria-roledescription": "slide",
"data-orientation": prop("orientation"),
"aria-label": translations.item(props.index, prop("slideCount")),
"aria-hidden": require_dom_query.ariaAttr(!isInView),
style: {
flex: "0 0 auto",
[horizontal ? "maxWidth" : "maxHeight"]: "100%",
scrollSnapAlign: (() => {
const snapAlign = props.snapAlign ?? "start";
const slidesPerMove = prop("slidesPerMove");
const perMove = slidesPerMove === "auto" ? Math.floor(prop("slidesPerPage")) : slidesPerMove;
return (props.index + perMove) % perMove === 0 ? snapAlign : void 0;
})()
}
});
},
getControlProps() {
return normalize.element({
...parts.control.attrs,
"data-orientation": prop("orientation")
});
},
getPrevTriggerProps() {
return normalize.button({
...parts.prevTrigger.attrs,
id: getPrevTriggerId(scope),
type: "button",
disabled: !canScrollPrev,
dir: prop("dir"),
"aria-label": translations.prevTrigger,
"data-orientation": prop("orientation"),
"aria-controls": getItemGroupId(scope),
onClick(event) {
if (event.defaultPrevented) return;
send({
type: "PAGE.PREV",
src: "trigger"
});
}
});
},
getNextTriggerProps() {
return normalize.button({
...parts.nextTrigger.attrs,
dir: prop("dir"),
id: getNextTriggerId(scope),
type: "button",
"aria-label": translations.nextTrigger,
"data-orientation": prop("orientation"),
"aria-controls": getItemGroupId(scope),
disabled: !canScrollNext,
onClick(event) {
if (event.defaultPrevented) return;
send({
type: "PAGE.NEXT",
src: "trigger"
});
}
});
},
getIndicatorGroupProps() {
return normalize.element({
...parts.indicatorGroup.attrs,
dir: prop("dir"),
id: getIndicatorGroupId(scope),
"data-orientation": prop("orientation"),
onKeyDown(event) {
if (event.defaultPrevented) return;
const src = "indicator";
const exec = {
ArrowDown(event) {
if (horizontal) return;
send({
type: "PAGE.NEXT",
src
});
event.preventDefault();
},
ArrowUp(event) {
if (horizontal) return;
send({
type: "PAGE.PREV",
src
});
event.preventDefault();
},
ArrowRight(event) {
if (!horizontal) return;
send({
type: "PAGE.NEXT",
src
});
event.preventDefault();
},
ArrowLeft(event) {
if (!horizontal) return;
send({
type: "PAGE.PREV",
src
});
event.preventDefault();
},
Home(event) {
send({
type: "PAGE.SET",
index: 0,
src
});
event.preventDefault();
},
End(event) {
send({
type: "PAGE.SET",
index: pageSnapPoints.length - 1,
src
});
event.preventDefault();
}
}[require_dom_query.getEventKey(event, {
dir: prop("dir"),
orientation: prop("orientation")
})];
exec?.(event);
}
});
},
getIndicatorProps(props) {
return normalize.button({
...parts.indicator.attrs,
dir: prop("dir"),
id: getIndicatorId(scope, props.index),
type: "button",
"data-orientation": prop("orientation"),
"data-index": props.index,
"data-readonly": require_dom_query.dataAttr(props.readOnly),
"data-current": require_dom_query.dataAttr(props.index === activePage),
"aria-label": translations.indicator(props.index),
onClick(event) {
if (event.defaultPrevented) return;
if (props.readOnly) return;
send({
type: "PAGE.SET",
index: props.index,
src: "indicator"
});
}
});
},
getAutoplayTriggerProps() {
return normalize.button({
...parts.autoplayTrigger.attrs,
type: "button",
"data-orientation": prop("orientation"),
"data-pressed": require_dom_query.dataAttr(isPlaying),
"aria-label": isPlaying ? translations.autoplayStop : translations.autoplayStart,
onClick(event) {
if (event.defaultPrevented) return;
send({ type: isPlaying ? "AUTOPLAY.PAUSE" : "AUTOPLAY.START" });
}
});
},
getProgressTextProps() {
return normalize.element({ ...parts.progressText.attrs });
}
};
}
//#endregion
//#region src/machines/carousel/carousel.machine.ts
const DRIFT_THRESHOLD = 1;
const machine = require_core.createMachine({
props({ props }) {
(0, _ginxjs_core_utils.ensureProps)(props, ["slideCount"], "carousel");
return {
dir: "ltr",
defaultPage: 0,
orientation: "horizontal",
snapType: "mandatory",
loop: !!props.autoplay,
slidesPerPage: 1,
slidesPerMove: "auto",
spacing: "0px",
autoplay: false,
allowMouseDrag: false,
inViewThreshold: .6,
autoSize: false,
...props,
translations: {
nextTrigger: "Next slide",
prevTrigger: "Previous slide",
indicator: (index) => `Go to slide ${index + 1}`,
item: (index, count) => `${index + 1} of ${count}`,
autoplayStart: "Start slide rotation",
autoplayStop: "Stop slide rotation",
progressText: ({ page, totalPages }) => `${page} / ${totalPages}`,
...props.translations
}
};
},
refs() {
return { timeoutRef: void 0 };
},
initialState({ prop }) {
return prop("autoplay") ? "autoplay" : "idle";
},
context({ prop, bindable, getContext }) {
return {
page: bindable(() => ({
defaultValue: prop("defaultPage"),
value: prop("page"),
onChange(page) {
const pageSnapPoints = getContext().get("pageSnapPoints");
prop("onPageChange")?.({
page,
pageSnapPoint: pageSnapPoints[page]
});
}
})),
pageSnapPoints: bindable(() => {
return { defaultValue: prop("autoSize") ? Array.from({ length: prop("slideCount") }, (_, i) => i) : getPageSnapPoints(prop("slideCount"), prop("slidesPerMove"), prop("slidesPerPage")) };
}),
slidesInView: bindable(() => ({ defaultValue: [] }))
};
},
computed: {
isRtl: ({ prop }) => prop("dir") === "rtl",
isHorizontal: ({ prop }) => prop("orientation") === "horizontal",
canScrollNext: ({ prop, context }) => prop("loop") || context.get("page") < context.get("pageSnapPoints").length - 1,
canScrollPrev: ({ prop, context }) => prop("loop") || context.get("page") > 0,
autoplayInterval: ({ prop }) => {
const autoplay = prop("autoplay");
return (0, _ginxjs_core_utils.isObject)(autoplay) ? autoplay.delay : 4e3;
}
},
watch({ track, action, context, prop, send }) {
track([() => prop("slidesPerPage"), () => prop("slidesPerMove")], () => {
action(["setSnapPoints"]);
});
track([() => context.get("page")], () => {
action(["scrollToPage", "focusIndicatorEl"]);
});
track([
() => prop("orientation"),
() => prop("autoSize"),
() => prop("dir")
], () => {
action(["setSnapPoints", "scrollToPage"]);
});
track([() => prop("slideCount")], () => {
send({
type: "SNAP.REFRESH",
src: "slide.count"
});
});
track([() => !!prop("autoplay")], () => {
send({
type: prop("autoplay") ? "AUTOPLAY.START" : "AUTOPLAY.PAUSE",
src: "autoplay.prop.change"
});
});
},
on: {
"PAGE.NEXT": {
target: "idle",
actions: ["clearScrollEndTimer", "setNextPage"]
},
"PAGE.PREV": {
target: "idle",
actions: ["clearScrollEndTimer", "setPrevPage"]
},
"PAGE.SET": {
target: "idle",
actions: ["clearScrollEndTimer", "setPage"]
},
"INDEX.SET": {
target: "idle",
actions: ["clearScrollEndTimer", "setMatchingPage"]
},
"SNAP.REFRESH": { actions: ["setSnapPoints", "scrollToPageIfDrifted"] },
"PAGE.SCROLL": { actions: ["scrollToPage"] }
},
effects: [
"trackSlideMutation",
"trackSlideIntersections",
"trackSlideResize"
],
entry: ["setSnapPoints", "setPage"],
exit: ["clearScrollEndTimer"],
states: {
idle: { on: {
"DRAGGING.START": {
target: "dragging",
actions: ["invokeDragStart"]
},
"AUTOPLAY.START": {
target: "autoplay",
actions: ["invokeAutoplayStart"]
},
"USER.SCROLL": { target: "userScroll" },
"VIEWPORT.FOCUS": { target: "focus" }
} },
focus: {
effects: ["trackKeyboardScroll"],
on: {
"VIEWPORT.BLUR": { target: "idle" },
"PAGE.NEXT": { actions: ["clearScrollEndTimer", "setNextPage"] },
"PAGE.PREV": { actions: ["clearScrollEndTimer", "setPrevPage"] },
"PAGE.SET": { actions: ["clearScrollEndTimer", "setPage"] },
"INDEX.SET": { actions: ["clearScrollEndTimer", "setMatchingPage"] },
"USER.SCROLL": { target: "userScroll" }
}
},
dragging: {
effects: ["trackPointerMove"],
entry: ["disableScrollSnap"],
on: {
DRAGGING: { actions: ["scrollSlides", "invokeDragging"] },
"DRAGGING.END": {
target: "settling",
actions: ["endDragging"]
}
}
},
settling: {
effects: ["trackSettlingScroll"],
on: {
"DRAGGING.START": {
target: "dragging",
actions: ["clearScrollEndTimer", "invokeDragStart"]
},
"SCROLL.END": [{
guard: "isFocused",
target: "focus",
actions: [
"clearScrollEndTimer",
"setClosestPage",
"invokeDraggingEnd"
]
}, {
target: "idle",
actions: [
"clearScrollEndTimer",
"setClosestPage",
"invokeDraggingEnd"
]
}]
}
},
userScroll: {
effects: ["trackScroll"],
on: {
"DRAGGING.START": {
target: "dragging",
actions: ["invokeDragStart"]
},
"SCROLL.END": [{
guard: "isFocused",
target: "focus",
actions: ["setClosestPage"]
}, {
target: "idle",
actions: ["setClosestPage"]
}]
}
},
autoplay: {
effects: [
"trackDocumentVisibility",
"trackScroll",
"autoUpdateSlide"
],
exit: ["invokeAutoplayEnd"],
on: {
"AUTOPLAY.TICK": { actions: ["setNextPage", "invokeAutoplay"] },
"DRAGGING.START": {
target: "dragging",
actions: ["invokeDragStart"]
},
"AUTOPLAY.PAUSE": { target: "idle" }
}
}
},
implementations: {
guards: { isFocused: ({ scope }) => scope.isActiveElement(getItemGroupEl(scope)) },
effects: {
autoUpdateSlide({ computed, send }) {
const id = setInterval(() => {
send({
type: computed("canScrollNext") ? "AUTOPLAY.TICK" : "AUTOPLAY.PAUSE",
src: "autoplay.interval"
});
}, computed("autoplayInterval"));
return () => clearInterval(id);
},
trackSlideMutation({ scope, send }) {
const el = getItemGroupEl(scope);
if (!el) return;
const observer = new (scope.getWin()).MutationObserver(() => {
send({
type: "SNAP.REFRESH",
src: "slide.mutation"
});
syncTabIndex(scope);
});
syncTabIndex(scope);
observer.observe(el, {
childList: true,
subtree: true
});
return () => observer.disconnect();
},
trackSlideResize({ scope, send }) {
const el = getItemGroupEl(scope);
if (!el) return;
const exec = () => {
send({
type: "SNAP.REFRESH",
src: "slide.resize"
});
};
require_dom_query.raf(() => {
exec();
require_dom_query.raf(() => {
send({
type: "PAGE.SCROLL",
instant: true
});
});
});
const itemEls = getItemEls(scope);
itemEls.forEach(exec);
return (0, _ginxjs_core_utils.callAll)(...[require_dom_query.resizeObserverBorderBox.observe(el, exec), ...itemEls.map((el) => require_dom_query.resizeObserverBorderBox.observe(el, exec))]);
},
trackSlideIntersections({ scope, prop, context }) {
const el = getItemGroupEl(scope);
const observer = new (scope.getWin()).IntersectionObserver((entries) => {
const slidesInView = entries.reduce((acc, entry) => {
const target = entry.target;
const index = Number(target.dataset.index ?? "-1");
if (index == null || Number.isNaN(index) || index === -1) return acc;
return entry.isIntersecting ? (0, _ginxjs_core_utils.add)(acc, index) : (0, _ginxjs_core_utils.remove)(acc, index);
}, context.get("slidesInView"));
context.set("slidesInView", (0, _ginxjs_core_utils.uniq)(slidesInView));
}, {
root: el,
threshold: prop("inViewThreshold")
});
getItemEls(scope).forEach((slide) => observer.observe(slide));
return () => observer.disconnect();
},
trackScroll({ send, refs, scope }) {
const el = getItemGroupEl(scope);
if (!el) return;
const onScroll = () => {
clearTimeout(refs.get("timeoutRef"));
refs.set("timeoutRef", void 0);
refs.set("timeoutRef", setTimeout(() => {
send({ type: "SCROLL.END" });
}, 150));
};
return require_dom_query.addDomEvent(el, "scroll", onScroll, { passive: true });
},
trackSettlingScroll({ send, refs, scope }) {
const el = getItemGroupEl(scope);
if (!el) return;
const startTimer = () => {
clearTimeout(refs.get("timeoutRef"));
refs.set("timeoutRef", void 0);
refs.set("timeoutRef", setTimeout(() => {
send({ type: "SCROLL.END" });
}, 200));
};
startTimer();
const onScroll = () => {
startTimer();
};
const cleanup = require_dom_query.addDomEvent(el, "scroll", onScroll, { passive: true });
return () => {
cleanup();
clearTimeout(refs.get("timeoutRef"));
refs.set("timeoutRef", void 0);
};
},
trackDocumentVisibility({ scope, send }) {
const doc = scope.getDoc();
const onVisibilityChange = () => {
if (doc.visibilityState === "visible") return;
send({
type: "AUTOPLAY.PAUSE",
src: "doc.hidden"
});
};
return require_dom_query.addDomEvent(doc, "visibilitychange", onVisibilityChange);
},
trackPointerMove({ scope, send }) {
return require_dom_query.trackPointerMove(scope.getDoc(), {
onPointerMove({ event }) {
send({
type: "DRAGGING",
left: -event.movementX,
top: -event.movementY
});
},
onPointerUp() {
send({ type: "DRAGGING.END" });
}
});
},
trackKeyboardScroll({ scope, send, context }) {
const win = scope.getWin();
const onKeyDown = (event) => {
switch (event.key) {
case "ArrowRight":
event.preventDefault();
send({ type: "PAGE.NEXT" });
break;
case "ArrowLeft":
event.preventDefault();
send({ type: "PAGE.PREV" });
break;
case "Home":
event.preventDefault();
send({
type: "PAGE.SET",
index: 0
});
break;
case "End":
event.preventDefault();
send({
type: "PAGE.SET",
index: context.get("pageSnapPoints").length - 1
});
}
};
return require_dom_query.addDomEvent(win, "keydown", onKeyDown, { capture: true });
}
},
actions: {
clearScrollEndTimer({ refs }) {
if (refs.get("timeoutRef") == null) return;
clearTimeout(refs.get("timeoutRef"));
refs.set("timeoutRef", void 0);
},
scrollToPage({ context, event, scope, computed, flush }) {
const behavior = event.instant ? "instant" : "smooth";
const index = (0, _ginxjs_core_utils.clampValue)(event.index ?? context.get("page"), 0, context.get("pageSnapPoints").length - 1);
const el = getItemGroupEl(scope);
if (!el) return;
const axis = computed("isHorizontal") ? "left" : "top";
flush(() => {
el.scrollTo({
[axis]: context.get("pageSnapPoints")[index],
behavior
});
});
},
scrollToPageIfDrifted({ context, scope, computed }) {
const el = getItemGroupEl(scope);
if (!el) return;
const snapPoint = context.get("pageSnapPoints")[context.get("page")];
if (snapPoint == null) return;
const scrollPos = computed("isHorizontal") ? el.scrollLeft : el.scrollTop;
if (Math.abs(scrollPos - snapPoint) <= DRIFT_THRESHOLD) return;
const axis = computed("isHorizontal") ? "left" : "top";
el.scrollTo({
[axis]: snapPoint,
behavior: "instant"
});
},
setClosestPage({ context, scope, computed }) {
const el = getItemGroupEl(scope);
if (!el) return;
const scrollPosition = computed("isHorizontal") ? el.scrollLeft : el.scrollTop;
const snapPoints = context.get("pageSnapPoints");
if (!snapPoints.length) return;
const page = snapPoints.reduce((closestIndex, snapPoint, index) => {
return Math.abs(snapPoint - scrollPosition) < Math.abs(snapPoints[closestIndex] - scrollPosition) ? index : closestIndex;
}, 0);
context.set("page", page);
},
setNextPage({ context, prop, state }) {
const loop = state.matches("autoplay") || prop("loop");
const page = (0, _ginxjs_core_utils.nextIndex)(context.get("pageSnapPoints"), context.get("page"), { loop });
context.set("page", page);
},
setPrevPage({ context, prop, state }) {
const loop = state.matches("autoplay") || prop("loop");
const page = (0, _ginxjs_core_utils.prevIndex)(context.get("pageSnapPoints"), context.get("page"), { loop });
context.set("page", page);
},
setMatchingPage({ context, event, computed, scope }) {
const el = getItemGroupEl(scope);
if (!el) return;
const snapPoint = require_scroll_snap.findSnapPoint(el, computed("isHorizontal") ? "x" : "y", (node) => node.dataset.index === event.index.toString());
if (snapPoint == null) return;
const page = context.get("pageSnapPoints").findIndex((point) => Math.abs(point - snapPoint) < 1);
context.set("page", page);
},
setPage({ context, event }) {
const page = event.index ?? context.get("page");
context.set("page", page);
},
setSnapPoints({ context, computed, scope }) {
const el = getItemGroupEl(scope);
if (!el) return;
const scrollSnapPoints = require_scroll_snap.getScrollSnapPositions(el);
const pageSnapPoints = computed("isHorizontal") ? scrollSnapPoints.x : scrollSnapPoints.y;
context.set("pageSnapPoints", pageSnapPoints);
if (!pageSnapPoints.length) return;
const index = (0, _ginxjs_core_utils.clampValue)(context.get("page"), 0, pageSnapPoints.length - 1);
context.set("page", index);
},
disableScrollSnap({ scope }) {
const el = getItemGroupEl(scope);
if (!el) return;
const styles = getComputedStyle(el);
el.dataset.scrollSnapType = styles.getPropertyValue("scroll-snap-type");
el.style.setProperty("scroll-snap-type", "none");
},
scrollSlides({ scope, event }) {
getItemGroupEl(scope)?.scrollBy({
left: event.left,
top: event.top,
behavior: "instant"
});
},
endDragging({ scope, context, computed }) {
const el = getItemGroupEl(scope);
if (!el) return;
const isHorizontal = computed("isHorizontal");
const scrollPos = isHorizontal ? el.scrollLeft : el.scrollTop;
const snapPoints = context.get("pageSnapPoints");
if (!snapPoints.length) return;
const closest = snapPoints.reduce((closest, curr) => {
return Math.abs(curr - scrollPos) < Math.abs(closest - scrollPos) ? curr : closest;
}, snapPoints[0]);
require_dom_query.raf(() => {
el.scrollTo({
left: isHorizontal ? closest : el.scrollLeft,
top: isHorizontal ? el.scrollTop : closest,
behavior: "smooth"
});
const scrollSnapType = el.dataset.scrollSnapType;
if (scrollSnapType) {
el.style.setProperty("scroll-snap-type", scrollSnapType);
delete el.dataset.scrollSnapType;
}
});
},
focusIndicatorEl({ context, event, scope }) {
if (event.src !== "indicator") return;
const el = getIndicatorEl(scope, context.get("page"));
if (!el) return;
require_dom_query.raf(() => el.focus({ preventScroll: true }));
},
invokeDragStart({ context, prop }) {
prop("onDragStatusChange")?.({
type: "dragging.start",
isDragging: true,
page: context.get("page")
});
},
invokeDragging({ context, prop }) {
prop("onDragStatusChange")?.({
type: "dragging",
isDragging: true,
page: context.get("page")
});
},
invokeDraggingEnd({ context, prop }) {
prop("onDragStatusChange")?.({
type: "dragging.end",
isDragging: false,
page: context.get("page")
});
},
invokeAutoplay({ context, prop }) {
prop("onAutoplayStatusChange")?.({
type: "autoplay",
isPlaying: true,
page: context.get("page")
});
},
invokeAutoplayStart({ context, prop }) {
prop("onAutoplayStatusChange")?.({
type: "autoplay.start",
isPlaying: true,
page: context.get("page")
});
},
invokeAutoplayEnd({ context, prop }) {
prop("onAutoplayStatusChange")?.({
type: "autoplay.stop",
isPlaying: false,
page: context.get("page")
});
}
}
}
});
function getPageSnapPoints(totalSlides, slidesPerMove, slidesPerPage) {
if (totalSlides == null || slidesPerPage <= 0) return [];
const snapPoints = [];
const perMove = slidesPerMove === "auto" ? Math.floor(slidesPerPage) : slidesPerMove;
if (perMove <= 0) return [];
for (let i = 0; i < totalSlides; i += perMove) {
if (i + slidesPerPage > totalSlides) break;
snapPoints.push(i);
}
return snapPoints;
}
//#endregion
//#region src/machines/carousel/carousel.props.ts
const props = require_create_props.createProps()([
"dir",
"getRootNode",
"id",
"ids",
"loop",
"page",
"defaultPage",
"onPageChange",
"orientation",
"slideCount",
"slidesPerPage",
"slidesPerMove",
"spacing",
"padding",
"autoplay",
"allowMouseDrag",
"inViewThreshold",
"translations",
"snapType",
"autoSize",
"onDragStatusChange",
"onAutoplayStatusChange"
]);
const splitProps = (0, _ginxjs_core_utils.createSplitProps)(props);
const indicatorProps = require_create_props.createProps()(["index", "readOnly"]);
const splitIndicatorProps = (0, _ginxjs_core_utils.createSplitProps)(indicatorProps);
const itemProps = require_create_props.createProps()(["index", "snapAlign"]);
const splitItemProps = (0, _ginxjs_core_utils.createSplitProps)(itemProps);
//#endregion
exports.anatomy = anatomy;
exports.connect = connect;
exports.indicatorProps = indicatorProps;
exports.itemProps = itemProps;
exports.machine = machine;
exports.props = props;
exports.splitIndicatorProps = splitIndicatorProps;
exports.splitItemProps = splitItemProps;
exports.splitProps = splitProps;
import { n as AnatomyInstance } from "../../anatomy-DFl8j10C.cjs";
import { b as NormalizeProps, d as Orientation, f as OrientationProperty, g as RequiredBy, r as DirectionProperty, t as CommonProperties, x as PropTypes } from "../../index-DFJGBSAc.cjs";
import { M as Service, S as EventObject, T as Machine } from "../../index-BNaxg4iu.cjs";
//#region src/machines/carousel/carousel.anatomy.d.ts
declare const anatomy: AnatomyInstance<"root" | "itemGroup" | "item" | "control" | "nextTrigger" | "prevTrigger" | "indicatorGroup" | "indicator" | "autoplayTrigger" | "progressText">;
//#endregion
//#region src/machines/carousel/carousel.types.d.ts
interface PageChangeDetails {
page: number;
pageSnapPoint: number;
}
interface DragStatusDetails {
type: "dragging.start" | "dragging" | "dragging.end";
page: number;
isDragging: boolean;
}
interface AutoplayStatusDetails {
type: "autoplay.start" | "autoplay" | "autoplay.stop";
page: number;
isPlaying: boolean;
}
interface ProgressTextDetails {
page: number;
totalPages: number;
}
interface IntlTranslations {
nextTrigger: string;
prevTrigger: string;
indicator: (index: number) => string;
item: (index: number, count: number) => string;
autoplayStart: string;
autoplayStop: string;
progressText?: ((details: ProgressTextDetails) => string) | undefined;
}
type ElementIds = Partial<{
root: string;
item: (index: number) => string;
itemGroup: string;
nextTrigger: string;
prevTrigger: string;
indicatorGroup: string;
indicator: (index: number) => string;
}>;
interface CarouselProps extends DirectionProperty, CommonProperties, OrientationProperty {
ids?: ElementIds | undefined;
translations?: IntlTranslations | undefined;
slidesPerPage?: number | undefined;
autoSize?: boolean | undefined;
slidesPerMove?: number | "auto" | undefined;
autoplay?: boolean | {
delay: number;
} | undefined;
allowMouseDrag?: boolean | undefined;
loop?: boolean | undefined;
page?: number | undefined;
defaultPage?: number | undefined;
spacing?: string | undefined;
padding?: string | undefined;
onPageChange?: ((details: PageChangeDetails) => void) | undefined;
inViewThreshold?: number | number[] | undefined;
snapType?: "proximity" | "mandatory" | undefined;
slideCount: number;
onDragStatusChange?: ((details: DragStatusDetails) => void) | undefined;
onAutoplayStatusChange?: ((details: AutoplayStatusDetails) => void) | undefined;
}
type PropsWithDefault = "dir" | "defaultPage" | "orientation" | "snapType" | "loop" | "slidesPerPage" | "slidesPerMove" | "spacing" | "autoplay" | "allowMouseDrag" | "inViewThreshold" | "translations" | "slideCount" | "autoSize";
interface PrivateContext {
pageSnapPoints: number[];
slidesInView: number[];
page: number;
}
interface ComputedContext {
isRtl: boolean;
isHorizontal: boolean;
canScrollNext: boolean;
canScrollPrev: boolean;
autoplayInterval: number;
}
type CarouselService = Service<CarouselSchema>;
type CarouselMachine = Machine<CarouselSchema>;
interface CarouselSchema {
props: RequiredBy<CarouselProps, PropsWithDefault>;
context: PrivateContext;
computed: ComputedContext;
refs: {
timeoutRef: any;
};
state: "idle" | "dragging" | "settling" | "autoplay" | "userScroll" | "focus";
effect: string;
action: string;
guard: string;
event: EventObject;
}
interface ItemProps {
index: number;
snapAlign?: "start" | "end" | "center" | undefined;
}
interface IndicatorProps {
index: number;
readOnly?: boolean | undefined;
}
interface CarouselApi<T extends PropTypes = PropTypes> {
page: number;
pageSnapPoints: number[];
isPlaying: boolean;
isDragging: boolean;
canScrollNext: boolean;
canScrollPrev: boolean;
scrollToIndex: (index: number, instant?: boolean) => void;
scrollTo: (page: number, instant?: boolean) => void;
scrollNext: (instant?: boolean) => void;
scrollPrev: (instant?: boolean) => void;
getProgress: () => number;
getProgressText: () => string;
play: VoidFunction;
pause: VoidFunction;
isInView: (index: number) => boolean;
refresh: VoidFunction;
getRootProps: () => T["element"];
getControlProps: () => T["element"];
getItemGroupProps: () => T["element"];
getItemProps: (props: ItemProps) => T["element"];
getPrevTriggerProps: () => T["button"];
getNextTriggerProps: () => T["button"];
getAutoplayTriggerProps: () => T["button"];
getIndicatorGroupProps: () => T["element"];
getIndicatorProps: (props: IndicatorProps) => T["button"];
getProgressTextProps: () => T["element"];
}
//#endregion
//#region src/machines/carousel/carousel.connect.d.ts
declare function connect<T extends PropTypes>(service: CarouselService, normalize: NormalizeProps<T>): CarouselApi<T>;
//#endregion
//#region src/machines/carousel/carousel.machine.d.ts
declare const machine: Machine<CarouselSchema>;
//#endregion
//#region src/machines/carousel/carousel.props.d.ts
declare const props: (keyof CarouselProps)[];
declare const splitProps: <Props extends Partial<CarouselProps>>(props: Props) => [Partial<CarouselProps>, Omit<Props, keyof CarouselProps>];
declare const indicatorProps: (keyof IndicatorProps)[];
declare const splitIndicatorProps: <Props extends IndicatorProps>(props: Props) => [IndicatorProps, Omit<Props, keyof IndicatorProps>];
declare const itemProps: (keyof ItemProps)[];
declare const splitItemProps: <Props extends ItemProps>(props: Props) => [ItemProps, Omit<Props, keyof ItemProps>];
//#endregion
export { type CarouselApi as Api, type AutoplayStatusDetails, type DragStatusDetails, type ElementIds, type IndicatorProps, type IntlTranslations, type ItemProps, type CarouselMachine as Machine, type Orientation, type PageChangeDetails, type ProgressTextDetails, type CarouselProps as Props, type CarouselService as Service, anatomy, connect, indicatorProps, itemProps, machine, props, splitIndicatorProps, splitItemProps, splitProps };
import { n as AnatomyInstance } from "../../anatomy-C9pDRrRN.mjs";
import { b as NormalizeProps, d as Orientation, f as OrientationProperty, g as RequiredBy, r as DirectionProperty, t as CommonProperties, x as PropTypes } from "../../index-Cq2OwLf_.mjs";
import { M as Service, S as EventObject, T as Machine } from "../../index-g2S6NCuN.mjs";
//#region src/machines/carousel/carousel.anatomy.d.ts
declare const anatomy: AnatomyInstance<"root" | "itemGroup" | "item" | "control" | "nextTrigger" | "prevTrigger" | "indicatorGroup" | "indicator" | "autoplayTrigger" | "progressText">;
//#endregion
//#region src/machines/carousel/carousel.types.d.ts
interface PageChangeDetails {
page: number;
pageSnapPoint: number;
}
interface DragStatusDetails {
type: "dragging.start" | "dragging" | "dragging.end";
page: number;
isDragging: boolean;
}
interface AutoplayStatusDetails {
type: "autoplay.start" | "autoplay" | "autoplay.stop";
page: number;
isPlaying: boolean;
}
interface ProgressTextDetails {
page: number;
totalPages: number;
}
interface IntlTranslations {
nextTrigger: string;
prevTrigger: string;
indicator: (index: number) => string;
item: (index: number, count: number) => string;
autoplayStart: string;
autoplayStop: string;
progressText?: ((details: ProgressTextDetails) => string) | undefined;
}
type ElementIds = Partial<{
root: string;
item: (index: number) => string;
itemGroup: string;
nextTrigger: string;
prevTrigger: string;
indicatorGroup: string;
indicator: (index: number) => string;
}>;
interface CarouselProps extends DirectionProperty, CommonProperties, OrientationProperty {
ids?: ElementIds | undefined;
translations?: IntlTranslations | undefined;
slidesPerPage?: number | undefined;
autoSize?: boolean | undefined;
slidesPerMove?: number | "auto" | undefined;
autoplay?: boolean | {
delay: number;
} | undefined;
allowMouseDrag?: boolean | undefined;
loop?: boolean | undefined;
page?: number | undefined;
defaultPage?: number | undefined;
spacing?: string | undefined;
padding?: string | undefined;
onPageChange?: ((details: PageChangeDetails) => void) | undefined;
inViewThreshold?: number | number[] | undefined;
snapType?: "proximity" | "mandatory" | undefined;
slideCount: number;
onDragStatusChange?: ((details: DragStatusDetails) => void) | undefined;
onAutoplayStatusChange?: ((details: AutoplayStatusDetails) => void) | undefined;
}
type PropsWithDefault = "dir" | "defaultPage" | "orientation" | "snapType" | "loop" | "slidesPerPage" | "slidesPerMove" | "spacing" | "autoplay" | "allowMouseDrag" | "inViewThreshold" | "translations" | "slideCount" | "autoSize";
interface PrivateContext {
pageSnapPoints: number[];
slidesInView: number[];
page: number;
}
interface ComputedContext {
isRtl: boolean;
isHorizontal: boolean;
canScrollNext: boolean;
canScrollPrev: boolean;
autoplayInterval: number;
}
type CarouselService = Service<CarouselSchema>;
type CarouselMachine = Machine<CarouselSchema>;
interface CarouselSchema {
props: RequiredBy<CarouselProps, PropsWithDefault>;
context: PrivateContext;
computed: ComputedContext;
refs: {
timeoutRef: any;
};
state: "idle" | "dragging" | "settling" | "autoplay" | "userScroll" | "focus";
effect: string;
action: string;
guard: string;
event: EventObject;
}
interface ItemProps {
index: number;
snapAlign?: "start" | "end" | "center" | undefined;
}
interface IndicatorProps {
index: number;
readOnly?: boolean | undefined;
}
interface CarouselApi<T extends PropTypes = PropTypes> {
page: number;
pageSnapPoints: number[];
isPlaying: boolean;
isDragging: boolean;
canScrollNext: boolean;
canScrollPrev: boolean;
scrollToIndex: (index: number, instant?: boolean) => void;
scrollTo: (page: number, instant?: boolean) => void;
scrollNext: (instant?: boolean) => void;
scrollPrev: (instant?: boolean) => void;
getProgress: () => number;
getProgressText: () => string;
play: VoidFunction;
pause: VoidFunction;
isInView: (index: number) => boolean;
refresh: VoidFunction;
getRootProps: () => T["element"];
getControlProps: () => T["element"];
getItemGroupProps: () => T["element"];
getItemProps: (props: ItemProps) => T["element"];
getPrevTriggerProps: () => T["button"];
getNextTriggerProps: () => T["button"];
getAutoplayTriggerProps: () => T["button"];
getIndicatorGroupProps: () => T["element"];
getIndicatorProps: (props: IndicatorProps) => T["button"];
getProgressTextProps: () => T["element"];
}
//#endregion
//#region src/machines/carousel/carousel.connect.d.ts
declare function connect<T extends PropTypes>(service: CarouselService, normalize: NormalizeProps<T>): CarouselApi<T>;
//#endregion
//#region src/machines/carousel/carousel.machine.d.ts
declare const machine: Machine<CarouselSchema>;
//#endregion
//#region src/machines/carousel/carousel.props.d.ts
declare const props: (keyof CarouselProps)[];
declare const splitProps: <Props extends Partial<CarouselProps>>(props: Props) => [Partial<CarouselProps>, Omit<Props, keyof CarouselProps>];
declare const indicatorProps: (keyof IndicatorProps)[];
declare const splitIndicatorProps: <Props extends IndicatorProps>(props: Props) => [IndicatorProps, Omit<Props, keyof IndicatorProps>];
declare const itemProps: (keyof ItemProps)[];
declare const splitItemProps: <Props extends ItemProps>(props: Props) => [ItemProps, Omit<Props, keyof ItemProps>];
//#endregion
export { type CarouselApi as Api, type AutoplayStatusDetails, type DragStatusDetails, type ElementIds, type IndicatorProps, type IntlTranslations, type ItemProps, type CarouselMachine as Machine, type Orientation, type PageChangeDetails, type ProgressTextDetails, type CarouselProps as Props, type CarouselService as Service, anatomy, connect, indicatorProps, itemProps, machine, props, splitIndicatorProps, splitItemProps, splitProps };
import { t as createAnatomy } from "../../create-anatomy-tqxVmw3d.mjs";
import { Ct as isLeftClick, D as trackPointerMove, G as raf, Tn as dataAttr, dt as addDomEvent, en as contains, gt as getEventTarget, h as resizeObserverBorderBox, nt as isFocusable, pt as getEventKey, tt as getTabbables, w as queryAll, wn as ariaAttr } from "../../dom-query-BgxIO7_X.mjs";
import { a as createMachine } from "../../core-D3PQ0tSv.mjs";
import { n as getScrollSnapPositions, t as findSnapPoint } from "../../scroll-snap-D5nbf4fC.mjs";
import { t as createProps } from "../../create-props-Bi7oeFLF.mjs";
import { add, callAll, clampValue, createSplitProps, ensureProps, isObject, nextIndex, prevIndex, remove, throttle, uniq } from "@ginxjs/core/utils";
//#region src/machines/carousel/carousel.anatomy.ts
const anatomy = createAnatomy("carousel").parts("root", "itemGroup", "item", "control", "nextTrigger", "prevTrigger", "indicatorGroup", "indicator", "autoplayTrigger", "progressText");
const parts = anatomy.build();
//#endregion
//#region src/machines/carousel/carousel.dom.ts
const getRootId = (ctx) => ctx.ids?.root ?? `carousel:${ctx.id}`;
const getItemId = (ctx, index) => ctx.ids?.item?.(index) ?? `carousel:${ctx.id}:item:${index}`;
const getItemGroupId = (ctx) => ctx.ids?.itemGroup ?? `carousel:${ctx.id}:item-group`;
const getNextTriggerId = (ctx) => ctx.ids?.nextTrigger ?? `carousel:${ctx.id}:next-trigger`;
const getPrevTriggerId = (ctx) => ctx.ids?.prevTrigger ?? `carousel:${ctx.id}:prev-trigger`;
const getIndicatorGroupId = (ctx) => ctx.ids?.indicatorGroup ?? `carousel:${ctx.id}:indicator-group`;
const getIndicatorId = (ctx, index) => ctx.ids?.indicator?.(index) ?? `carousel:${ctx.id}:indicator:${index}`;
const getItemGroupEl = (ctx) => ctx.getById(getItemGroupId(ctx));
const getItemEls = (ctx) => queryAll(getItemGroupEl(ctx), `[data-part=item]`);
const getIndicatorEl = (ctx, page) => ctx.getById(getIndicatorId(ctx, page));
const syncTabIndex = (ctx) => {
const el = getItemGroupEl(ctx);
if (!el) return;
const tabbables = getTabbables(el);
el.setAttribute("tabindex", tabbables.length > 0 ? "-1" : "0");
};
//#endregion
//#region src/machines/carousel/carousel.connect.ts
function connect(service, normalize) {
const { state, context, computed, send, scope, prop } = service;
const isPlaying = state.matches("autoplay");
const isDragging = state.matches("dragging");
const canScrollNext = computed("canScrollNext");
const canScrollPrev = computed("canScrollPrev");
const horizontal = computed("isHorizontal");
const autoSize = prop("autoSize");
const pageSnapPoints = Array.from(context.get("pageSnapPoints"));
const page = context.get("page");
const activePage = pageSnapPoints.length ? clampValue(page, 0, pageSnapPoints.length - 1) : 0;
const slidesPerPage = prop("slidesPerPage");
const padding = prop("padding");
const translations = prop("translations");
return {
isPlaying,
isDragging,
page: activePage,
pageSnapPoints,
canScrollNext,
canScrollPrev,
getProgress() {
return activePage / pageSnapPoints.length;
},
getProgressText() {
const details = {
page: activePage + 1,
totalPages: pageSnapPoints.length
};
return translations.progressText?.(details) ?? "";
},
scrollToIndex(index, instant) {
send({
type: "INDEX.SET",
index,
instant
});
},
scrollTo(index, instant) {
send({
type: "PAGE.SET",
index,
instant
});
},
scrollNext(instant) {
send({
type: "PAGE.NEXT",
instant
});
},
scrollPrev(instant) {
send({
type: "PAGE.PREV",
instant
});
},
play() {
send({ type: "AUTOPLAY.START" });
},
pause() {
send({ type: "AUTOPLAY.PAUSE" });
},
isInView(index) {
return Array.from(context.get("slidesInView")).includes(index);
},
refresh() {
send({ type: "SNAP.REFRESH" });
},
getRootProps() {
return normalize.element({
...parts.root.attrs,
id: getRootId(scope),
role: "region",
"aria-roledescription": "carousel",
"data-orientation": prop("orientation"),
dir: prop("dir"),
style: {
"--slides-per-page": slidesPerPage,
"--slide-spacing": prop("spacing"),
"--slide-item-size": autoSize ? "auto" : "calc(100% / var(--slides-per-page) - var(--slide-spacing) * (var(--slides-per-page) - 1) / var(--slides-per-page))"
}
});
},
getItemGroupProps() {
return normalize.element({
...parts.itemGroup.attrs,
id: getItemGroupId(scope),
"data-orientation": prop("orientation"),
"data-dragging": dataAttr(isDragging),
dir: prop("dir"),
"aria-live": isPlaying ? "off" : "polite",
onFocus(event) {
if (!contains(event.currentTarget, getEventTarget(event))) return;
send({ type: "VIEWPORT.FOCUS" });
},
onBlur(event) {
if (contains(event.currentTarget, event.relatedTarget)) return;
send({ type: "VIEWPORT.BLUR" });
},
onMouseDown(event) {
if (event.defaultPrevented) return;
if (!prop("allowMouseDrag")) return;
if (!isLeftClick(event)) return;
const target = getEventTarget(event);
if (isFocusable(target) && target !== event.currentTarget) return;
event.preventDefault();
send({ type: "DRAGGING.START" });
},
onWheel: throttle((event) => {
const axis = prop("orientation") === "horizontal" ? "deltaX" : "deltaY";
if (event[axis] < 0 && !computed("canScrollPrev")) return;
if (event[axis] > 0 && !computed("canScrollNext")) return;
send({ type: "USER.SCROLL" });
}, 150),
onTouchStart() {
send({ type: "USER.SCROLL" });
},
style: {
display: autoSize ? "flex" : "grid",
gap: "var(--slide-spacing)",
scrollSnapType: [horizontal ? "x" : "y", prop("snapType")].join(" "),
gridAutoFlow: horizontal ? "column" : "row",
scrollbarWidth: "none",
overscrollBehaviorX: "contain",
[horizontal ? "gridAutoColumns" : "gridAutoRows"]: autoSize ? void 0 : "var(--slide-item-size)",
[horizontal ? "scrollPaddingInline" : "scrollPaddingBlock"]: padding,
[horizontal ? "paddingInline" : "paddingBlock"]: padding,
[horizontal ? "overflowX" : "overflowY"]: "auto"
}
});
},
getItemProps(props) {
const isInView = context.get("slidesInView").includes(props.index);
return normalize.element({
...parts.item.attrs,
id: getItemId(scope, props.index),
dir: prop("dir"),
role: "group",
"data-index": props.index,
"data-inview": dataAttr(isInView),
"aria-roledescription": "slide",
"data-orientation": prop("orientation"),
"aria-label": translations.item(props.index, prop("slideCount")),
"aria-hidden": ariaAttr(!isInView),
style: {
flex: "0 0 auto",
[horizontal ? "maxWidth" : "maxHeight"]: "100%",
scrollSnapAlign: (() => {
const snapAlign = props.snapAlign ?? "start";
const slidesPerMove = prop("slidesPerMove");
const perMove = slidesPerMove === "auto" ? Math.floor(prop("slidesPerPage")) : slidesPerMove;
return (props.index + perMove) % perMove === 0 ? snapAlign : void 0;
})()
}
});
},
getControlProps() {
return normalize.element({
...parts.control.attrs,
"data-orientation": prop("orientation")
});
},
getPrevTriggerProps() {
return normalize.button({
...parts.prevTrigger.attrs,
id: getPrevTriggerId(scope),
type: "button",
disabled: !canScrollPrev,
dir: prop("dir"),
"aria-label": translations.prevTrigger,
"data-orientation": prop("orientation"),
"aria-controls": getItemGroupId(scope),
onClick(event) {
if (event.defaultPrevented) return;
send({
type: "PAGE.PREV",
src: "trigger"
});
}
});
},
getNextTriggerProps() {
return normalize.button({
...parts.nextTrigger.attrs,
dir: prop("dir"),
id: getNextTriggerId(scope),
type: "button",
"aria-label": translations.nextTrigger,
"data-orientation": prop("orientation"),
"aria-controls": getItemGroupId(scope),
disabled: !canScrollNext,
onClick(event) {
if (event.defaultPrevented) return;
send({
type: "PAGE.NEXT",
src: "trigger"
});
}
});
},
getIndicatorGroupProps() {
return normalize.element({
...parts.indicatorGroup.attrs,
dir: prop("dir"),
id: getIndicatorGroupId(scope),
"data-orientation": prop("orientation"),
onKeyDown(event) {
if (event.defaultPrevented) return;
const src = "indicator";
const exec = {
ArrowDown(event) {
if (horizontal) return;
send({
type: "PAGE.NEXT",
src
});
event.preventDefault();
},
ArrowUp(event) {
if (horizontal) return;
send({
type: "PAGE.PREV",
src
});
event.preventDefault();
},
ArrowRight(event) {
if (!horizontal) return;
send({
type: "PAGE.NEXT",
src
});
event.preventDefault();
},
ArrowLeft(event) {
if (!horizontal) return;
send({
type: "PAGE.PREV",
src
});
event.preventDefault();
},
Home(event) {
send({
type: "PAGE.SET",
index: 0,
src
});
event.preventDefault();
},
End(event) {
send({
type: "PAGE.SET",
index: pageSnapPoints.length - 1,
src
});
event.preventDefault();
}
}[getEventKey(event, {
dir: prop("dir"),
orientation: prop("orientation")
})];
exec?.(event);
}
});
},
getIndicatorProps(props) {
return normalize.button({
...parts.indicator.attrs,
dir: prop("dir"),
id: getIndicatorId(scope, props.index),
type: "button",
"data-orientation": prop("orientation"),
"data-index": props.index,
"data-readonly": dataAttr(props.readOnly),
"data-current": dataAttr(props.index === activePage),
"aria-label": translations.indicator(props.index),
onClick(event) {
if (event.defaultPrevented) return;
if (props.readOnly) return;
send({
type: "PAGE.SET",
index: props.index,
src: "indicator"
});
}
});
},
getAutoplayTriggerProps() {
return normalize.button({
...parts.autoplayTrigger.attrs,
type: "button",
"data-orientation": prop("orientation"),
"data-pressed": dataAttr(isPlaying),
"aria-label": isPlaying ? translations.autoplayStop : translations.autoplayStart,
onClick(event) {
if (event.defaultPrevented) return;
send({ type: isPlaying ? "AUTOPLAY.PAUSE" : "AUTOPLAY.START" });
}
});
},
getProgressTextProps() {
return normalize.element({ ...parts.progressText.attrs });
}
};
}
//#endregion
//#region src/machines/carousel/carousel.machine.ts
const DRIFT_THRESHOLD = 1;
const machine = createMachine({
props({ props }) {
ensureProps(props, ["slideCount"], "carousel");
return {
dir: "ltr",
defaultPage: 0,
orientation: "horizontal",
snapType: "mandatory",
loop: !!props.autoplay,
slidesPerPage: 1,
slidesPerMove: "auto",
spacing: "0px",
autoplay: false,
allowMouseDrag: false,
inViewThreshold: .6,
autoSize: false,
...props,
translations: {
nextTrigger: "Next slide",
prevTrigger: "Previous slide",
indicator: (index) => `Go to slide ${index + 1}`,
item: (index, count) => `${index + 1} of ${count}`,
autoplayStart: "Start slide rotation",
autoplayStop: "Stop slide rotation",
progressText: ({ page, totalPages }) => `${page} / ${totalPages}`,
...props.translations
}
};
},
refs() {
return { timeoutRef: void 0 };
},
initialState({ prop }) {
return prop("autoplay") ? "autoplay" : "idle";
},
context({ prop, bindable, getContext }) {
return {
page: bindable(() => ({
defaultValue: prop("defaultPage"),
value: prop("page"),
onChange(page) {
const pageSnapPoints = getContext().get("pageSnapPoints");
prop("onPageChange")?.({
page,
pageSnapPoint: pageSnapPoints[page]
});
}
})),
pageSnapPoints: bindable(() => {
return { defaultValue: prop("autoSize") ? Array.from({ length: prop("slideCount") }, (_, i) => i) : getPageSnapPoints(prop("slideCount"), prop("slidesPerMove"), prop("slidesPerPage")) };
}),
slidesInView: bindable(() => ({ defaultValue: [] }))
};
},
computed: {
isRtl: ({ prop }) => prop("dir") === "rtl",
isHorizontal: ({ prop }) => prop("orientation") === "horizontal",
canScrollNext: ({ prop, context }) => prop("loop") || context.get("page") < context.get("pageSnapPoints").length - 1,
canScrollPrev: ({ prop, context }) => prop("loop") || context.get("page") > 0,
autoplayInterval: ({ prop }) => {
const autoplay = prop("autoplay");
return isObject(autoplay) ? autoplay.delay : 4e3;
}
},
watch({ track, action, context, prop, send }) {
track([() => prop("slidesPerPage"), () => prop("slidesPerMove")], () => {
action(["setSnapPoints"]);
});
track([() => context.get("page")], () => {
action(["scrollToPage", "focusIndicatorEl"]);
});
track([
() => prop("orientation"),
() => prop("autoSize"),
() => prop("dir")
], () => {
action(["setSnapPoints", "scrollToPage"]);
});
track([() => prop("slideCount")], () => {
send({
type: "SNAP.REFRESH",
src: "slide.count"
});
});
track([() => !!prop("autoplay")], () => {
send({
type: prop("autoplay") ? "AUTOPLAY.START" : "AUTOPLAY.PAUSE",
src: "autoplay.prop.change"
});
});
},
on: {
"PAGE.NEXT": {
target: "idle",
actions: ["clearScrollEndTimer", "setNextPage"]
},
"PAGE.PREV": {
target: "idle",
actions: ["clearScrollEndTimer", "setPrevPage"]
},
"PAGE.SET": {
target: "idle",
actions: ["clearScrollEndTimer", "setPage"]
},
"INDEX.SET": {
target: "idle",
actions: ["clearScrollEndTimer", "setMatchingPage"]
},
"SNAP.REFRESH": { actions: ["setSnapPoints", "scrollToPageIfDrifted"] },
"PAGE.SCROLL": { actions: ["scrollToPage"] }
},
effects: [
"trackSlideMutation",
"trackSlideIntersections",
"trackSlideResize"
],
entry: ["setSnapPoints", "setPage"],
exit: ["clearScrollEndTimer"],
states: {
idle: { on: {
"DRAGGING.START": {
target: "dragging",
actions: ["invokeDragStart"]
},
"AUTOPLAY.START": {
target: "autoplay",
actions: ["invokeAutoplayStart"]
},
"USER.SCROLL": { target: "userScroll" },
"VIEWPORT.FOCUS": { target: "focus" }
} },
focus: {
effects: ["trackKeyboardScroll"],
on: {
"VIEWPORT.BLUR": { target: "idle" },
"PAGE.NEXT": { actions: ["clearScrollEndTimer", "setNextPage"] },
"PAGE.PREV": { actions: ["clearScrollEndTimer", "setPrevPage"] },
"PAGE.SET": { actions: ["clearScrollEndTimer", "setPage"] },
"INDEX.SET": { actions: ["clearScrollEndTimer", "setMatchingPage"] },
"USER.SCROLL": { target: "userScroll" }
}
},
dragging: {
effects: ["trackPointerMove"],
entry: ["disableScrollSnap"],
on: {
DRAGGING: { actions: ["scrollSlides", "invokeDragging"] },
"DRAGGING.END": {
target: "settling",
actions: ["endDragging"]
}
}
},
settling: {
effects: ["trackSettlingScroll"],
on: {
"DRAGGING.START": {
target: "dragging",
actions: ["clearScrollEndTimer", "invokeDragStart"]
},
"SCROLL.END": [{
guard: "isFocused",
target: "focus",
actions: [
"clearScrollEndTimer",
"setClosestPage",
"invokeDraggingEnd"
]
}, {
target: "idle",
actions: [
"clearScrollEndTimer",
"setClosestPage",
"invokeDraggingEnd"
]
}]
}
},
userScroll: {
effects: ["trackScroll"],
on: {
"DRAGGING.START": {
target: "dragging",
actions: ["invokeDragStart"]
},
"SCROLL.END": [{
guard: "isFocused",
target: "focus",
actions: ["setClosestPage"]
}, {
target: "idle",
actions: ["setClosestPage"]
}]
}
},
autoplay: {
effects: [
"trackDocumentVisibility",
"trackScroll",
"autoUpdateSlide"
],
exit: ["invokeAutoplayEnd"],
on: {
"AUTOPLAY.TICK": { actions: ["setNextPage", "invokeAutoplay"] },
"DRAGGING.START": {
target: "dragging",
actions: ["invokeDragStart"]
},
"AUTOPLAY.PAUSE": { target: "idle" }
}
}
},
implementations: {
guards: { isFocused: ({ scope }) => scope.isActiveElement(getItemGroupEl(scope)) },
effects: {
autoUpdateSlide({ computed, send }) {
const id = setInterval(() => {
send({
type: computed("canScrollNext") ? "AUTOPLAY.TICK" : "AUTOPLAY.PAUSE",
src: "autoplay.interval"
});
}, computed("autoplayInterval"));
return () => clearInterval(id);
},
trackSlideMutation({ scope, send }) {
const el = getItemGroupEl(scope);
if (!el) return;
const observer = new (scope.getWin()).MutationObserver(() => {
send({
type: "SNAP.REFRESH",
src: "slide.mutation"
});
syncTabIndex(scope);
});
syncTabIndex(scope);
observer.observe(el, {
childList: true,
subtree: true
});
return () => observer.disconnect();
},
trackSlideResize({ scope, send }) {
const el = getItemGroupEl(scope);
if (!el) return;
const exec = () => {
send({
type: "SNAP.REFRESH",
src: "slide.resize"
});
};
raf(() => {
exec();
raf(() => {
send({
type: "PAGE.SCROLL",
instant: true
});
});
});
const itemEls = getItemEls(scope);
itemEls.forEach(exec);
return callAll(...[resizeObserverBorderBox.observe(el, exec), ...itemEls.map((el) => resizeObserverBorderBox.observe(el, exec))]);
},
trackSlideIntersections({ scope, prop, context }) {
const el = getItemGroupEl(scope);
const observer = new (scope.getWin()).IntersectionObserver((entries) => {
const slidesInView = entries.reduce((acc, entry) => {
const target = entry.target;
const index = Number(target.dataset.index ?? "-1");
if (index == null || Number.isNaN(index) || index === -1) return acc;
return entry.isIntersecting ? add(acc, index) : remove(acc, index);
}, context.get("slidesInView"));
context.set("slidesInView", uniq(slidesInView));
}, {
root: el,
threshold: prop("inViewThreshold")
});
getItemEls(scope).forEach((slide) => observer.observe(slide));
return () => observer.disconnect();
},
trackScroll({ send, refs, scope }) {
const el = getItemGroupEl(scope);
if (!el) return;
const onScroll = () => {
clearTimeout(refs.get("timeoutRef"));
refs.set("timeoutRef", void 0);
refs.set("timeoutRef", setTimeout(() => {
send({ type: "SCROLL.END" });
}, 150));
};
return addDomEvent(el, "scroll", onScroll, { passive: true });
},
trackSettlingScroll({ send, refs, scope }) {
const el = getItemGroupEl(scope);
if (!el) return;
const startTimer = () => {
clearTimeout(refs.get("timeoutRef"));
refs.set("timeoutRef", void 0);
refs.set("timeoutRef", setTimeout(() => {
send({ type: "SCROLL.END" });
}, 200));
};
startTimer();
const onScroll = () => {
startTimer();
};
const cleanup = addDomEvent(el, "scroll", onScroll, { passive: true });
return () => {
cleanup();
clearTimeout(refs.get("timeoutRef"));
refs.set("timeoutRef", void 0);
};
},
trackDocumentVisibility({ scope, send }) {
const doc = scope.getDoc();
const onVisibilityChange = () => {
if (doc.visibilityState === "visible") return;
send({
type: "AUTOPLAY.PAUSE",
src: "doc.hidden"
});
};
return addDomEvent(doc, "visibilitychange", onVisibilityChange);
},
trackPointerMove({ scope, send }) {
return trackPointerMove(scope.getDoc(), {
onPointerMove({ event }) {
send({
type: "DRAGGING",
left: -event.movementX,
top: -event.movementY
});
},
onPointerUp() {
send({ type: "DRAGGING.END" });
}
});
},
trackKeyboardScroll({ scope, send, context }) {
const win = scope.getWin();
const onKeyDown = (event) => {
switch (event.key) {
case "ArrowRight":
event.preventDefault();
send({ type: "PAGE.NEXT" });
break;
case "ArrowLeft":
event.preventDefault();
send({ type: "PAGE.PREV" });
break;
case "Home":
event.preventDefault();
send({
type: "PAGE.SET",
index: 0
});
break;
case "End":
event.preventDefault();
send({
type: "PAGE.SET",
index: context.get("pageSnapPoints").length - 1
});
}
};
return addDomEvent(win, "keydown", onKeyDown, { capture: true });
}
},
actions: {
clearScrollEndTimer({ refs }) {
if (refs.get("timeoutRef") == null) return;
clearTimeout(refs.get("timeoutRef"));
refs.set("timeoutRef", void 0);
},
scrollToPage({ context, event, scope, computed, flush }) {
const behavior = event.instant ? "instant" : "smooth";
const index = clampValue(event.index ?? context.get("page"), 0, context.get("pageSnapPoints").length - 1);
const el = getItemGroupEl(scope);
if (!el) return;
const axis = computed("isHorizontal") ? "left" : "top";
flush(() => {
el.scrollTo({
[axis]: context.get("pageSnapPoints")[index],
behavior
});
});
},
scrollToPageIfDrifted({ context, scope, computed }) {
const el = getItemGroupEl(scope);
if (!el) return;
const snapPoint = context.get("pageSnapPoints")[context.get("page")];
if (snapPoint == null) return;
const scrollPos = computed("isHorizontal") ? el.scrollLeft : el.scrollTop;
if (Math.abs(scrollPos - snapPoint) <= DRIFT_THRESHOLD) return;
const axis = computed("isHorizontal") ? "left" : "top";
el.scrollTo({
[axis]: snapPoint,
behavior: "instant"
});
},
setClosestPage({ context, scope, computed }) {
const el = getItemGroupEl(scope);
if (!el) return;
const scrollPosition = computed("isHorizontal") ? el.scrollLeft : el.scrollTop;
const snapPoints = context.get("pageSnapPoints");
if (!snapPoints.length) return;
const page = snapPoints.reduce((closestIndex, snapPoint, index) => {
return Math.abs(snapPoint - scrollPosition) < Math.abs(snapPoints[closestIndex] - scrollPosition) ? index : closestIndex;
}, 0);
context.set("page", page);
},
setNextPage({ context, prop, state }) {
const loop = state.matches("autoplay") || prop("loop");
const page = nextIndex(context.get("pageSnapPoints"), context.get("page"), { loop });
context.set("page", page);
},
setPrevPage({ context, prop, state }) {
const loop = state.matches("autoplay") || prop("loop");
const page = prevIndex(context.get("pageSnapPoints"), context.get("page"), { loop });
context.set("page", page);
},
setMatchingPage({ context, event, computed, scope }) {
const el = getItemGroupEl(scope);
if (!el) return;
const snapPoint = findSnapPoint(el, computed("isHorizontal") ? "x" : "y", (node) => node.dataset.index === event.index.toString());
if (snapPoint == null) return;
const page = context.get("pageSnapPoints").findIndex((point) => Math.abs(point - snapPoint) < 1);
context.set("page", page);
},
setPage({ context, event }) {
const page = event.index ?? context.get("page");
context.set("page", page);
},
setSnapPoints({ context, computed, scope }) {
const el = getItemGroupEl(scope);
if (!el) return;
const scrollSnapPoints = getScrollSnapPositions(el);
const pageSnapPoints = computed("isHorizontal") ? scrollSnapPoints.x : scrollSnapPoints.y;
context.set("pageSnapPoints", pageSnapPoints);
if (!pageSnapPoints.length) return;
const index = clampValue(context.get("page"), 0, pageSnapPoints.length - 1);
context.set("page", index);
},
disableScrollSnap({ scope }) {
const el = getItemGroupEl(scope);
if (!el) return;
const styles = getComputedStyle(el);
el.dataset.scrollSnapType = styles.getPropertyValue("scroll-snap-type");
el.style.setProperty("scroll-snap-type", "none");
},
scrollSlides({ scope, event }) {
getItemGroupEl(scope)?.scrollBy({
left: event.left,
top: event.top,
behavior: "instant"
});
},
endDragging({ scope, context, computed }) {
const el = getItemGroupEl(scope);
if (!el) return;
const isHorizontal = computed("isHorizontal");
const scrollPos = isHorizontal ? el.scrollLeft : el.scrollTop;
const snapPoints = context.get("pageSnapPoints");
if (!snapPoints.length) return;
const closest = snapPoints.reduce((closest, curr) => {
return Math.abs(curr - scrollPos) < Math.abs(closest - scrollPos) ? curr : closest;
}, snapPoints[0]);
raf(() => {
el.scrollTo({
left: isHorizontal ? closest : el.scrollLeft,
top: isHorizontal ? el.scrollTop : closest,
behavior: "smooth"
});
const scrollSnapType = el.dataset.scrollSnapType;
if (scrollSnapType) {
el.style.setProperty("scroll-snap-type", scrollSnapType);
delete el.dataset.scrollSnapType;
}
});
},
focusIndicatorEl({ context, event, scope }) {
if (event.src !== "indicator") return;
const el = getIndicatorEl(scope, context.get("page"));
if (!el) return;
raf(() => el.focus({ preventScroll: true }));
},
invokeDragStart({ context, prop }) {
prop("onDragStatusChange")?.({
type: "dragging.start",
isDragging: true,
page: context.get("page")
});
},
invokeDragging({ context, prop }) {
prop("onDragStatusChange")?.({
type: "dragging",
isDragging: true,
page: context.get("page")
});
},
invokeDraggingEnd({ context, prop }) {
prop("onDragStatusChange")?.({
type: "dragging.end",
isDragging: false,
page: context.get("page")
});
},
invokeAutoplay({ context, prop }) {
prop("onAutoplayStatusChange")?.({
type: "autoplay",
isPlaying: true,
page: context.get("page")
});
},
invokeAutoplayStart({ context, prop }) {
prop("onAutoplayStatusChange")?.({
type: "autoplay.start",
isPlaying: true,
page: context.get("page")
});
},
invokeAutoplayEnd({ context, prop }) {
prop("onAutoplayStatusChange")?.({
type: "autoplay.stop",
isPlaying: false,
page: context.get("page")
});
}
}
}
});
function getPageSnapPoints(totalSlides, slidesPerMove, slidesPerPage) {
if (totalSlides == null || slidesPerPage <= 0) return [];
const snapPoints = [];
const perMove = slidesPerMove === "auto" ? Math.floor(slidesPerPage) : slidesPerMove;
if (perMove <= 0) return [];
for (let i = 0; i < totalSlides; i += perMove) {
if (i + slidesPerPage > totalSlides) break;
snapPoints.push(i);
}
return snapPoints;
}
//#endregion
//#region src/machines/carousel/carousel.props.ts
const props = createProps()([
"dir",
"getRootNode",
"id",
"ids",
"loop",
"page",
"defaultPage",
"onPageChange",
"orientation",
"slideCount",
"slidesPerPage",
"slidesPerMove",
"spacing",
"padding",
"autoplay",
"allowMouseDrag",
"inViewThreshold",
"translations",
"snapType",
"autoSize",
"onDragStatusChange",
"onAutoplayStatusChange"
]);
const splitProps = createSplitProps(props);
const indicatorProps = createProps()(["index", "readOnly"]);
const splitIndicatorProps = createSplitProps(indicatorProps);
const itemProps = createProps()(["index", "snapAlign"]);
const splitItemProps = createSplitProps(itemProps);
//#endregion
export { anatomy, connect, indicatorProps, itemProps, machine, props, splitIndicatorProps, splitItemProps, splitProps };
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_create_anatomy = require("../../create-anatomy-CpViYTjA.cjs");
const require_dom_query = require("../../dom-query-BT6fffRP.cjs");
const require_dismissable = require("../../dismissable-BxNRrW5W.cjs");
const require_focus_visible = require("../../focus-visible-B0GjxLkR.cjs");
const require_core = require("../../core-DH_mBI7F.cjs");
const require_popper = require("../../popper-CiXiA2V2.cjs");
const require_rect = require("../../rect-CmICnPlW.cjs");
const require_create_props = require("../../create-props-MMZJXgtK.cjs");
let _ginxjs_core_utils = require("@ginxjs/core/utils");
let _ginxjs_core_collection = require("@ginxjs/core/collection");
//#region src/machines/cascade-select/cascade-select.anatomy.ts
const anatomy = require_create_anatomy.createAnatomy("cascade-select").parts("root", "label", "control", "trigger", "indicator", "valueText", "clearTrigger", "positioner", "content", "list", "item", "itemText", "itemIndicator");
const parts = anatomy.build();
//#endregion
//#region src/machines/cascade-select/cascade-select.collection.ts
const collection = (options) => {
return new _ginxjs_core_collection.TreeCollection(options);
};
collection.empty = () => {
return new _ginxjs_core_collection.TreeCollection({ rootNode: {
value: "ROOT",
children: []
} });
};
//#endregion
//#region src/machines/cascade-select/cascade-select.dom.ts
const dom = require_dom_query.createScope({
getRootId: (ctx) => ctx.ids?.root ?? `cascade-select:${ctx.id}`,
getLabelId: (ctx) => ctx.ids?.label ?? `cascade-select:${ctx.id}:label`,
getControlId: (ctx) => ctx.ids?.control ?? `cascade-select:${ctx.id}:control`,
getTriggerId: (ctx) => ctx.ids?.trigger ?? `cascade-select:${ctx.id}:trigger`,
getIndicatorId: (ctx) => ctx.ids?.indicator ?? `cascade-select:${ctx.id}:indicator`,
getClearTriggerId: (ctx) => ctx.ids?.clearTrigger ?? `cascade-select:${ctx.id}:clear-trigger`,
getPositionerId: (ctx) => ctx.ids?.positioner ?? `cascade-select:${ctx.id}:positioner`,
getContentId: (ctx) => ctx.ids?.content ?? `cascade-select:${ctx.id}:content`,
getHiddenInputId: (ctx) => ctx.ids?.hiddenInput ?? `cascade-select:${ctx.id}:hidden-input`,
getListId: (ctx, value) => ctx.ids?.list?.(value) ?? `cascade-select:${ctx.id}:list:${value}`,
getItemId: (ctx, value) => ctx.ids?.item?.(value) ?? `cascade-select:${ctx.id}:item:${value}`,
getRootEl: (ctx) => dom.getById(ctx, dom.getRootId(ctx)),
getLabelEl: (ctx) => dom.getById(ctx, dom.getLabelId(ctx)),
getControlEl: (ctx) => dom.getById(ctx, dom.getControlId(ctx)),
getTriggerEl: (ctx) => dom.getById(ctx, dom.getTriggerId(ctx)),
getIndicatorEl: (ctx) => dom.getById(ctx, dom.getIndicatorId(ctx)),
getClearTriggerEl: (ctx) => dom.getById(ctx, dom.getClearTriggerId(ctx)),
getPositionerEl: (ctx) => dom.getById(ctx, dom.getPositionerId(ctx)),
getContentEl: (ctx) => dom.getById(ctx, dom.getContentId(ctx)),
getHiddenInputEl: (ctx) => dom.getById(ctx, dom.getHiddenInputId(ctx)),
getListEl: (ctx, value) => dom.getById(ctx, dom.getListId(ctx, value)),
getListEls: (ctx) => require_dom_query.queryAll(dom.getContentEl(ctx), `[data-part="list"]`),
getItemEl: (ctx, value) => dom.getById(ctx, dom.getItemId(ctx, value)),
dispatchInputEvent: (ctx, value) => {
const inputEl = dom.getHiddenInputEl(ctx);
if (!inputEl) return;
require_dom_query.dispatchInputValueEvent(inputEl, { value });
}
});
//#endregion
//#region src/machines/cascade-select/cascade-select.connect.ts
function connect(service, normalize) {
const { send, context, prop, scope, computed, state } = service;
const collection = prop("collection");
const value = context.get("value");
const open = state.hasTag("open");
const focused = state.matches("focused");
const highlightedIndexPath = context.get("highlightedIndexPath");
const highlightedValue = context.get("highlightedValue");
const currentPlacement = context.get("currentPlacement");
const disabled = prop("disabled") || context.get("fieldsetDisabled");
const interactive = computed("isInteractive");
const valueAsString = computed("valueAsString");
const highlightedItems = context.get("highlightedItems");
const selectedItems = context.get("selectedItems");
const popperStyles = require_popper.getPlacementStyles({
...prop("positioning"),
placement: currentPlacement
});
const getItemState = (props) => {
const { item, indexPath, value: itemValue } = props;
const depth = indexPath ? indexPath.length : 0;
const highlighted = itemValue.every((v, i) => v === highlightedValue[i]);
const selected = value.some((v) => (0, _ginxjs_core_utils.isEqual)(v, itemValue));
const highlightedChild = collection.getNodeChildren(collection.at(indexPath))[highlightedIndexPath[depth]];
const highlightedIndex = highlightedIndexPath[depth];
return {
value: itemValue,
disabled: collection.getNodeDisabled(item),
highlighted,
selected,
hasChildren: collection.isBranchNode(item),
depth,
highlightedChild,
highlightedIndex
};
};
const hasSelectedItems = value.length > 0;
const empty = value.length === 0;
return {
collection,
open,
focused,
multiple: !!prop("multiple"),
disabled,
value,
highlightedValue,
highlightedItems,
selectedItems,
hasSelectedItems,
empty,
valueAsString,
reposition(options = {}) {
send({
type: "POSITIONING.SET",
options
});
},
focus() {
dom.getTriggerEl(scope)?.focus({ preventScroll: true });
},
setOpen(nextOpen) {
if (nextOpen === open) return;
send({ type: nextOpen ? "OPEN" : "CLOSE" });
},
setHighlightValue(value) {
send({
type: "HIGHLIGHTED_VALUE.SET",
value
});
},
clearHighlightValue() {
send({ type: "HIGHLIGHTED_VALUE.CLEAR" });
},
setValue(value) {
send({
type: "VALUE.SET",
value
});
},
selectValue(value) {
send({
type: "ITEM.SELECT",
value
});
},
clearValue(value) {
if (value) send({
type: "ITEM.CLEAR",
value
});
else send({ type: "VALUE.CLEAR" });
},
getItemState,
getRootProps() {
return normalize.element({
...parts.root.attrs,
id: dom.getRootId(scope),
dir: prop("dir"),
"data-disabled": require_dom_query.dataAttr(disabled),
"data-readonly": require_dom_query.dataAttr(prop("readOnly")),
"data-invalid": require_dom_query.dataAttr(prop("invalid")),
"data-state": open ? "open" : "closed"
});
},
getLabelProps() {
return normalize.label({
...parts.label.attrs,
id: dom.getLabelId(scope),
dir: prop("dir"),
htmlFor: dom.getHiddenInputId(scope),
"data-disabled": require_dom_query.dataAttr(disabled),
"data-readonly": require_dom_query.dataAttr(prop("readOnly")),
"data-invalid": require_dom_query.dataAttr(prop("invalid")),
onClick(event) {
if (event.defaultPrevented) return;
if (disabled) return;
dom.getTriggerEl(scope)?.focus({ preventScroll: true });
}
});
},
getControlProps() {
return normalize.element({
...parts.control.attrs,
dir: prop("dir"),
id: dom.getControlId(scope),
"data-disabled": require_dom_query.dataAttr(disabled),
"data-focus": require_dom_query.dataAttr(focused),
"data-readonly": require_dom_query.dataAttr(prop("readOnly")),
"data-invalid": require_dom_query.dataAttr(prop("invalid")),
"data-state": open ? "open" : "closed"
});
},
getTriggerProps() {
return normalize.button({
...parts.trigger.attrs,
dir: prop("dir"),
id: dom.getTriggerId(scope),
type: "button",
role: "combobox",
"aria-controls": dom.getContentId(scope),
"aria-expanded": open,
"aria-haspopup": "listbox",
"aria-labelledby": dom.getLabelId(scope),
"data-state": open ? "open" : "closed",
"data-disabled": require_dom_query.dataAttr(disabled),
"data-readonly": require_dom_query.dataAttr(prop("readOnly")),
"data-invalid": require_dom_query.dataAttr(prop("invalid")),
"data-focus": require_dom_query.dataAttr(focused),
"data-placement": currentPlacement,
"data-placeholder-shown": require_dom_query.dataAttr(!hasSelectedItems),
disabled,
onClick(event) {
if (event.defaultPrevented) return;
if (!interactive) return;
send({ type: "TRIGGER.CLICK" });
},
onFocus() {
send({ type: "TRIGGER.FOCUS" });
},
onBlur() {
send({ type: "TRIGGER.BLUR" });
},
onKeyDown(event) {
if (event.defaultPrevented) return;
if (!interactive) return;
const exec = {
ArrowUp() {
send({ type: "TRIGGER.ARROW_UP" });
},
ArrowDown(event) {
send({ type: event.altKey ? "OPEN" : "TRIGGER.ARROW_DOWN" });
},
ArrowLeft() {
send({ type: "TRIGGER.ARROW_LEFT" });
},
ArrowRight() {
send({ type: "TRIGGER.ARROW_RIGHT" });
},
Enter() {
send({ type: "TRIGGER.ENTER" });
},
Space() {
send({ type: "TRIGGER.ENTER" });
}
}[require_dom_query.getEventKey(event, { dir: prop("dir") })];
if (exec) {
exec(event);
event.preventDefault();
}
}
});
},
getClearTriggerProps() {
return normalize.button({
...parts.clearTrigger.attrs,
dir: prop("dir"),
id: dom.getClearTriggerId(scope),
type: "button",
"aria-label": "Clear value",
hidden: !hasSelectedItems,
"data-disabled": require_dom_query.dataAttr(disabled),
"data-readonly": require_dom_query.dataAttr(prop("readOnly")),
"data-invalid": require_dom_query.dataAttr(prop("invalid")),
disabled,
onClick(event) {
if (event.defaultPrevented) return;
send({ type: "CLEAR_TRIGGER.CLICK" });
}
});
},
getPositionerProps() {
return normalize.element({
...parts.positioner.attrs,
dir: prop("dir"),
id: dom.getPositionerId(scope),
style: popperStyles.floating
});
},
getContentProps() {
const highlightedItemId = highlightedValue ? dom.getItemId(scope, highlightedValue.toString()) : void 0;
return normalize.element({
...parts.content.attrs,
id: dom.getContentId(scope),
role: "listbox",
"aria-labelledby": dom.getLabelId(scope),
"aria-activedescendant": highlightedItemId,
"data-activedescendant": highlightedItemId,
"data-state": open ? "open" : "closed",
"aria-multiselectable": prop("multiple"),
"aria-required": prop("required"),
"aria-readonly": prop("readOnly"),
hidden: !open,
tabIndex: 0,
onKeyDown(event) {
if (!interactive) return;
if (!require_dom_query.isSelfTarget(event)) return;
if (event.key === "Tab") {
if (!require_dom_query.isValidTabEvent(event)) {
event.preventDefault();
return;
}
}
const exec = {
ArrowDown() {
send({ type: "CONTENT.ARROW_DOWN" });
},
ArrowUp() {
send({ type: "CONTENT.ARROW_UP" });
},
ArrowRight() {
send({ type: "CONTENT.ARROW_RIGHT" });
},
ArrowLeft() {
send({ type: "CONTENT.ARROW_LEFT" });
},
Home() {
send({ type: "CONTENT.HOME" });
},
End() {
send({ type: "CONTENT.END" });
},
Enter() {
send({ type: "CONTENT.ENTER" });
},
" "() {
send({ type: "CONTENT.ENTER" });
}
}[require_dom_query.getEventKey(event, { dir: prop("dir") })];
if (exec) {
exec();
event.preventDefault();
return;
}
if (require_dom_query.isEditableElement(event.target)) return;
},
onPointerMove(event) {
if (!interactive) return;
send({
type: "POINTER_MOVE",
clientX: event.clientX,
clientY: event.clientY,
target: event.target
});
}
});
},
getListProps(props) {
const itemState = getItemState(props);
return normalize.element({
...parts.list.attrs,
id: dom.getListId(scope, itemState.value.toString()),
dir: prop("dir"),
"data-depth": itemState.depth,
"aria-level": itemState.depth,
role: "group"
});
},
getIndicatorProps() {
return normalize.element({
...parts.indicator.attrs,
id: dom.getIndicatorId(scope),
dir: prop("dir"),
"aria-hidden": true,
"data-state": open ? "open" : "closed",
"data-disabled": require_dom_query.dataAttr(disabled),
"data-readonly": require_dom_query.dataAttr(prop("readOnly")),
"data-invalid": require_dom_query.dataAttr(prop("invalid"))
});
},
getItemProps(props) {
const { indexPath } = props;
const itemState = getItemState(props);
return normalize.element({
...parts.item.attrs,
id: dom.getItemId(scope, itemState.value.toString()),
dir: prop("dir"),
role: "treeitem",
"aria-haspopup": itemState.hasChildren ? "menu" : void 0,
"aria-expanded": itemState.hasChildren ? itemState.highlighted : false,
"aria-controls": itemState.hasChildren ? dom.getListId(scope, itemState.value.toString()) : void 0,
"aria-owns": itemState.hasChildren ? dom.getListId(scope, itemState.value.toString()) : void 0,
"aria-disabled": require_dom_query.ariaAttr(itemState.disabled),
"data-value": itemState.value.toString(),
"data-disabled": require_dom_query.dataAttr(itemState.disabled),
"data-highlighted": require_dom_query.dataAttr(itemState.highlighted),
"data-selected": require_dom_query.dataAttr(itemState.selected),
"data-depth": itemState.depth,
"data-state": itemState.selected ? "checked" : "unchecked",
"data-type": itemState.hasChildren ? "branch" : "leaf",
"data-index-path": indexPath.toString(),
onDoubleClick() {
if (itemState.disabled) return;
send({ type: "CLOSE" });
},
onClick(event) {
if (event.defaultPrevented) return;
if (!interactive) return;
if (itemState.disabled) return;
send({
type: "ITEM.CLICK",
value: itemState.value,
indexPath
});
},
onPointerEnter(event) {
if (!interactive) return;
if (itemState.disabled) return;
send({
type: "ITEM.POINTER_ENTER",
value: itemState.value,
indexPath,
clientX: event.clientX,
clientY: event.clientY
});
},
onPointerLeave(event) {
if (!interactive) return;
if (itemState.disabled) return;
if (event.pointerType !== "mouse") return;
if (!service.event.previous()?.type.includes("POINTER")) return;
send({
type: "ITEM.POINTER_LEAVE",
value: itemState.value,
indexPath,
clientX: event.clientX,
clientY: event.clientY
});
}
});
},
getItemTextProps(props) {
const { item } = props;
const itemValue = collection.getNodeValue(item);
const itemState = getItemState(props);
return normalize.element({
dir: prop("dir"),
...parts.itemText.attrs,
"data-value": itemValue,
"data-highlighted": require_dom_query.dataAttr(itemState.highlighted),
"data-state": itemState.selected ? "checked" : "unchecked",
"data-disabled": require_dom_query.dataAttr(itemState.disabled)
});
},
getItemIndicatorProps(props) {
const { item } = props;
const itemValue = collection.getNodeValue(item);
const itemState = getItemState(props);
return normalize.element({
...parts.itemIndicator.attrs,
dir: prop("dir"),
"data-value": itemValue,
"data-highlighted": require_dom_query.dataAttr(itemState.highlighted),
"data-type": itemState.hasChildren ? "branch" : "leaf",
"data-state": itemState.selected ? "checked" : "unchecked",
hidden: !itemState.selected
});
},
getValueTextProps() {
return normalize.element({
...parts.valueText.attrs,
dir: prop("dir"),
"data-disabled": require_dom_query.dataAttr(disabled),
"data-invalid": require_dom_query.dataAttr(prop("invalid")),
"data-focus": require_dom_query.dataAttr(focused)
});
},
getHiddenInputProps() {
const defaultValue = context.hash("value");
return normalize.input({
name: prop("name"),
form: prop("form"),
disabled,
multiple: prop("multiple"),
required: prop("required"),
readOnly: prop("readOnly"),
hidden: true,
"aria-hidden": true,
id: dom.getHiddenInputId(scope),
defaultValue,
"aria-labelledby": dom.getLabelId(scope)
});
}
};
}
//#endregion
//#region src/machines/cascade-select/cascade-select.utils.ts
function createGraceArea(exitPoint, triggerRect, targetRect, options = {}) {
const { padding = 5 } = options;
const paddedExitPoints = getPaddedExitPoints(exitPoint, require_rect.closestSideToPoint(require_rect.createRect({
x: triggerRect.left,
y: triggerRect.top,
width: triggerRect.width,
height: triggerRect.height
}), exitPoint), padding);
const targetPoints = domRectToPoints(targetRect);
return getConvexHull([...paddedExitPoints, ...targetPoints]);
}
function isPointerInGraceArea(point, graceArea) {
return require_rect.isPointInPolygon(graceArea, point);
}
function getPaddedExitPoints(exitPoint, exitSide, padding) {
const { x, y } = exitPoint;
switch (exitSide) {
case "top": return [require_rect.createPoint(x - padding, y + padding), require_rect.createPoint(x + padding, y + padding)];
case "bottom": return [require_rect.createPoint(x - padding, y - padding), require_rect.createPoint(x + padding, y - padding)];
case "left": return [require_rect.createPoint(x + padding, y - padding), require_rect.createPoint(x + padding, y + padding)];
case "right": return [require_rect.createPoint(x - padding, y - padding), require_rect.createPoint(x - padding, y + padding)];
default: return [];
}
}
function domRectToPoints(rect) {
const corners = require_rect.getRectCorners(require_rect.createRect({
x: rect.left,
y: rect.top,
width: rect.width,
height: rect.height
}));
return [
corners.top,
corners.right,
corners.bottom,
corners.left
];
}
function getConvexHull(points) {
if (points.length <= 1) return points.slice();
const sortedPoints = points.slice().sort((a, b) => {
if (a.x !== b.x) return a.x - b.x;
return a.y - b.y;
});
const lower = [];
for (const point of sortedPoints) {
while (lower.length >= 2 && crossProduct(lower[lower.length - 2], lower[lower.length - 1], point) <= 0) lower.pop();
lower.push(point);
}
const upper = [];
for (let i = sortedPoints.length - 1; i >= 0; i--) {
const point = sortedPoints[i];
while (upper.length >= 2 && crossProduct(upper[upper.length - 2], upper[upper.length - 1], point) <= 0) upper.pop();
upper.push(point);
}
lower.pop();
upper.pop();
return lower.concat(upper);
}
function crossProduct(o, a, b) {
return (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x);
}
//#endregion
//#region src/machines/cascade-select/cascade-select.machine.ts
const { or, and, not } = require_core.createGuards();
const machine = require_core.createMachine({
props({ props }) {
return {
closeOnSelect: true,
loopFocus: false,
defaultValue: [],
defaultHighlightedValue: [],
defaultOpen: false,
multiple: false,
highlightTrigger: "click",
allowParentSelection: false,
positioning: {
placement: "bottom-start",
gutter: 8,
...props.positioning
},
...props,
collection: props.collection ?? collection.empty()
};
},
context({ prop, bindable }) {
return {
value: bindable(() => ({
defaultValue: prop("defaultValue"),
value: prop("value"),
isEqual: _ginxjs_core_utils.isEqual,
hash(value) {
return value.join(", ");
}
})),
highlightedValue: bindable(() => ({
defaultValue: prop("defaultHighlightedValue"),
value: prop("highlightedValue"),
isEqual: _ginxjs_core_utils.isEqual
})),
valueIndexPath: bindable(() => {
return { defaultValue: (prop("value") ?? prop("defaultValue") ?? []).map((v) => prop("collection").getIndexPath(v)) };
}),
highlightedIndexPath: bindable(() => {
const value = prop("highlightedValue") ?? prop("defaultHighlightedValue") ?? null;
return { defaultValue: value ? prop("collection").getIndexPath(value) : [] };
}),
highlightedItems: bindable(() => ({ defaultValue: [] })),
selectedItems: bindable(() => ({ defaultValue: [] })),
currentPlacement: bindable(() => ({ defaultValue: void 0 })),
fieldsetDisabled: bindable(() => ({ defaultValue: false })),
graceArea: bindable(() => ({ defaultValue: null })),
isPointerInTransit: bindable(() => ({ defaultValue: false }))
};
},
computed: {
isInteractive: ({ prop }) => !(prop("disabled") || prop("readOnly")),
valueAsString: ({ prop, context }) => {
const collection = prop("collection");
const items = context.get("selectedItems");
const multiple = prop("multiple");
const formatMultipleMode = (items) => collection.stringifyNode(items.at(-1)) ?? collection.getNodeValue(items.at(-1));
const formatSingleMode = (items) => {
return items.map((item) => {
return collection.stringifyNode(item) ?? collection.getNodeValue(item);
}).join(" / ");
};
const defaultFormatValue = (items) => items.map(multiple ? formatMultipleMode : formatSingleMode).join(", ");
return (prop("formatValue") ?? defaultFormatValue)(items);
}
},
initialState({ prop }) {
return prop("open") || prop("defaultOpen") ? "open" : "idle";
},
watch({ context, prop, track, action }) {
track([() => context.get("value")?.toString()], () => {
action(["syncInputValue", "dispatchChangeEvent"]);
});
track([() => prop("open")], () => {
action(["toggleVisibility"]);
});
},
on: {
"VALUE.SET": { actions: ["setValue"] },
"VALUE.CLEAR": { actions: ["clearValue"] },
"CLEAR_TRIGGER.CLICK": { actions: ["clearValue", "focusTriggerEl"] },
"HIGHLIGHTED_VALUE.SET": { actions: ["setHighlightedValue"] },
"HIGHLIGHTED_VALUE.CLEAR": { actions: ["clearHighlightedValue"] },
"ITEM.SELECT": { actions: ["selectItem"] },
"ITEM.CLEAR": { actions: ["clearItem"] }
},
effects: ["trackFormControlState"],
states: {
idle: {
tags: ["closed"],
on: {
"CONTROLLED.OPEN": [{
guard: "isTriggerClickEvent",
target: "open",
actions: ["setInitialFocus", "highlightFirstSelectedItem"]
}, {
target: "open",
actions: ["setInitialFocus"]
}],
"TRIGGER.CLICK": [{
guard: "isOpenControlled",
actions: ["invokeOnOpen"]
}, {
target: "open",
actions: [
"invokeOnOpen",
"setInitialFocus",
"highlightFirstSelectedItem"
]
}],
"TRIGGER.FOCUS": { target: "focused" },
OPEN: [{
guard: "isOpenControlled",
actions: ["invokeOnOpen"]
}, {
target: "open",
actions: ["setInitialFocus", "invokeOnOpen"]
}]
}
},
focused: {
tags: ["closed"],
on: {
"CONTROLLED.OPEN": [
{
guard: "isTriggerClickEvent",
target: "open",
actions: ["setInitialFocus", "highlightFirstSelectedItem"]
},
{
guard: "isTriggerArrowUpEvent",
target: "open",
actions: ["setInitialFocus", "highlightLastItem"]
},
{
guard: or("isTriggerArrowDownEvent", "isTriggerEnterEvent", ""),
target: "open",
actions: ["setInitialFocus", "highlightFirstItem"]
},
{
target: "open",
actions: ["setInitialFocus"]
}
],
OPEN: [{
guard: "isOpenControlled",
actions: ["invokeOnOpen"]
}, {
target: "open",
actions: ["setInitialFocus", "invokeOnOpen"]
}],
"TRIGGER.BLUR": { target: "idle" },
"TRIGGER.CLICK": [{
guard: "isOpenControlled",
actions: ["invokeOnOpen"]
}, {
target: "open",
actions: [
"setInitialFocus",
"invokeOnOpen",
"highlightFirstSelectedItem"
]
}],
"TRIGGER.ENTER": [{
guard: "isOpenControlled",
actions: ["invokeOnOpen"]
}, {
target: "open",
actions: [
"setInitialFocus",
"invokeOnOpen",
"highlightFirstItem"
]
}],
"TRIGGER.ARROW_UP": [{
guard: "isOpenControlled",
actions: ["invokeOnOpen"]
}, {
target: "open",
actions: [
"setInitialFocus",
"invokeOnOpen",
"highlightLastItem"
]
}],
"TRIGGER.ARROW_DOWN": [{
guard: "isOpenControlled",
actions: ["invokeOnOpen"]
}, {
target: "open",
actions: [
"setInitialFocus",
"invokeOnOpen",
"highlightFirstItem"
]
}],
"TRIGGER.ARROW_LEFT": [{
guard: "isOpenControlled",
actions: ["invokeOnOpen"]
}, {
target: "open",
actions: ["invokeOnOpen"]
}],
"TRIGGER.ARROW_RIGHT": [{
guard: "isOpenControlled",
actions: ["invokeOnOpen"]
}, {
target: "open",
actions: ["invokeOnOpen", "highlightFirstItem"]
}]
}
},
open: {
tags: ["open"],
exit: ["clearHighlightedValue", "scrollContentToTop"],
effects: [
"trackDismissableElement",
"trackFocusVisible",
"computePlacement",
"scrollToHighlightedItems"
],
on: {
"CONTROLLED.CLOSE": [{
guard: "restoreFocus",
target: "focused",
actions: ["focusTriggerEl"]
}, { target: "idle" }],
CLOSE: [
{
guard: "isOpenControlled",
actions: ["invokeOnClose"]
},
{
guard: "restoreFocus",
target: "focused",
actions: ["invokeOnClose", "focusTriggerEl"]
},
{
target: "idle",
actions: ["invokeOnClose"]
}
],
"TRIGGER.CLICK": [{
guard: "isOpenControlled",
actions: ["invokeOnClose"]
}, {
target: "focused",
actions: ["invokeOnClose", "focusTriggerEl"]
}],
"ITEM.CLICK": [
{
guard: and("canSelectItem", and("shouldCloseOnSelect", not("multiple")), "isOpenControlled"),
actions: ["selectItem", "invokeOnClose"]
},
{
guard: and("canSelectItem", and("shouldCloseOnSelect", not("multiple"))),
target: "focused",
actions: [
"selectItem",
"invokeOnClose",
"focusTriggerEl"
]
},
{
guard: "canSelectItem",
actions: ["selectItem"]
},
{ actions: ["setHighlightedValue"] }
],
"ITEM.POINTER_ENTER": [{
guard: "isHoverHighlight",
actions: ["setHighlightingForHoveredItem"]
}],
"ITEM.POINTER_LEAVE": [{
guard: and("isHoverHighlight", "shouldHighlightOnHover"),
actions: ["createGraceArea"]
}],
POINTER_MOVE: [{
guard: and("isHoverHighlight", "hasGraceArea", "isPointerOutsideGraceArea", "isPointerNotInAnyItem", "hasHighlightedValue"),
actions: ["clearGraceArea"]
}],
"GRACE_AREA.CLEAR": [{
guard: "isHoverHighlight",
actions: ["clearGraceArea"]
}],
"CONTENT.HOME": { actions: ["highlightFirstItem"] },
"CONTENT.END": { actions: ["highlightLastItem"] },
"CONTENT.ARROW_DOWN": [{
guard: or(not("hasHighlightedValue"), and("loop", "isHighlightedLastItem")),
actions: ["highlightFirstItem"]
}, { actions: ["highlightNextItem"] }],
"CONTENT.ARROW_UP": [{
guard: or(not("hasHighlightedValue"), and("loop", "isHighlightedFirstItem")),
actions: ["highlightLastItem"]
}, { actions: ["highlightPreviousItem"] }],
"CONTENT.ARROW_RIGHT": [{
guard: "canNavigateToChild",
actions: ["highlightFirstChild"]
}],
"CONTENT.ARROW_LEFT": [
{
guard: and("isAtRootLevel", "isOpenControlled"),
actions: ["invokeOnClose", "focusTriggerEl"]
},
{
guard: and("isAtRootLevel", "restoreFocus"),
target: "focused",
actions: ["invokeOnClose", "focusTriggerEl"]
},
{
guard: "isAtRootLevel",
target: "idle",
actions: ["invokeOnClose"]
},
{
guard: "canNavigateToParent",
actions: ["highlightParent"]
}
],
"CONTENT.ENTER": [
{
guard: and("canSelectHighlightedItem", and("shouldCloseOnSelectHighlighted", not("multiple")), "isOpenControlled"),
actions: ["selectHighlightedItem", "invokeOnClose"]
},
{
guard: and("canSelectHighlightedItem", and("shouldCloseOnSelectHighlighted", not("multiple"))),
target: "focused",
actions: [
"selectHighlightedItem",
"invokeOnClose",
"focusTriggerEl"
]
},
{
guard: "canSelectHighlightedItem",
actions: ["selectHighlightedItem"]
}
],
"POSITIONING.SET": { actions: ["reposition"] }
}
}
},
implementations: {
guards: {
restoreFocus: ({ event }) => restoreFocusFn(event),
multiple: ({ prop }) => !!prop("multiple"),
loop: ({ prop }) => !!prop("loopFocus"),
isOpenControlled: ({ prop }) => !!prop("open"),
isTriggerClickEvent: ({ event }) => event.previousEvent?.type === "TRIGGER.CLICK",
isTriggerArrowUpEvent: ({ event }) => event.previousEvent?.type === "TRIGGER.ARROW_UP",
isTriggerArrowDownEvent: ({ event }) => event.previousEvent?.type === "TRIGGER.ARROW_DOWN",
isTriggerEnterEvent: ({ event }) => event.previousEvent?.type === "TRIGGER.ENTER",
isTriggerArrowRightEvent: ({ event }) => event.previousEvent?.type === "TRIGGER.ARROW_RIGHT",
hasHighlightedValue: ({ context }) => context.get("highlightedValue").length > 0,
isHighlightedFirstItem: ({ context }) => context.get("highlightedIndexPath").at(-1) === 0,
isHighlightedLastItem: ({ prop, context }) => {
const path = context.get("highlightedIndexPath");
const itemIndex = path.at(-1);
if (!itemIndex && itemIndex !== 0) return false;
const parentIndexPath = path.slice(0, -1);
return !prop("collection").at([...parentIndexPath, itemIndex + 1]);
},
shouldCloseOnSelect: ({ prop, event }) => {
const collection = prop("collection");
const node = collection.at(event.indexPath);
return prop("closeOnSelect") && node && !collection.isBranchNode(node);
},
shouldCloseOnSelectHighlighted: ({ prop, context }) => {
const collection = prop("collection");
const node = (0, _ginxjs_core_utils.last)(context.get("highlightedItems"));
return prop("closeOnSelect") && node != null && !collection.isBranchNode(node);
},
canSelectItem: ({ prop, event }) => {
const collection = prop("collection");
const node = collection.at(event.indexPath);
if (!node) return false;
return prop("allowParentSelection") || !collection.isBranchNode(node);
},
canSelectHighlightedItem: ({ prop, context }) => {
const collection = prop("collection");
const node = collection.at(context.get("highlightedIndexPath"));
if (!node) return false;
return prop("allowParentSelection") || !collection.isBranchNode(node);
},
canNavigateToChild: ({ prop, context }) => {
const highlightedIndexPath = context.get("highlightedIndexPath");
if (!highlightedIndexPath.length) return false;
const collection = prop("collection");
const node = collection.at(highlightedIndexPath);
return node && collection.isBranchNode(node);
},
canNavigateToParent: ({ context }) => context.get("highlightedIndexPath").length > 1,
isAtRootLevel: ({ context }) => context.get("highlightedIndexPath").length <= 1,
isHoverHighlight: ({ prop }) => prop("highlightTrigger") === "hover",
shouldHighlightOnHover: ({ prop, event }) => {
const collection = prop("collection");
const node = collection.at(event.indexPath);
return node && collection.isBranchNode(node);
},
shouldUpdateHighlightedIndexPath: ({ prop, context, event }) => {
const collection = prop("collection");
const currentHighlightedIndexPath = context.get("highlightedIndexPath");
if (!currentHighlightedIndexPath || currentHighlightedIndexPath.length === 0) return false;
const node = collection.at(event.indexPath);
if (!node || collection.isBranchNode(node)) return false;
const indexPath = event.indexPath;
if (!indexPath) return false;
const minLength = Math.min(indexPath.length, currentHighlightedIndexPath.length);
let commonPrefixLength = 0;
for (let i = 0; i < minLength; i++) if (indexPath[i] === currentHighlightedIndexPath[i]) commonPrefixLength = i + 1;
else break;
return commonPrefixLength > 0 && (commonPrefixLength < currentHighlightedIndexPath.length || commonPrefixLength < indexPath.length);
},
hasGraceArea: ({ context }) => {
return context.get("graceArea") != null;
},
isPointerOutsideGraceArea: ({ context, event }) => {
const graceArea = context.get("graceArea");
if (!graceArea) return false;
return !isPointerInGraceArea({
x: event.clientX,
y: event.clientY
}, graceArea);
},
isPointerNotInAnyItem: ({ event }) => {
const target = event.target;
const itemElement = target.closest("[data-part=\"item\"]");
const contentElement = target.closest("[data-part=\"content\"]");
return !contentElement || !itemElement && !!contentElement;
}
},
effects: {
trackFormControlState({ context, scope, prop }) {
return require_dom_query.trackFormControl(dom.getTriggerEl(scope), {
onFieldsetDisabledChange(disabled) {
context.set("fieldsetDisabled", disabled);
},
onFormReset() {
context.set("value", prop("defaultValue") ?? []);
}
});
},
trackFocusVisible({ scope }) {
return require_focus_visible.trackFocusVisible({ root: scope.getRootNode?.() });
},
trackDismissableElement({ scope, send, prop }) {
const contentEl = () => dom.getContentEl(scope);
let restoreFocus = true;
return require_dismissable.trackDismissableElement(contentEl, {
defer: true,
exclude: [dom.getTriggerEl(scope), dom.getClearTriggerEl(scope)],
onFocusOutside: prop("onFocusOutside"),
onPointerDownOutside: prop("onPointerDownOutside"),
onInteractOutside(event) {
prop("onInteractOutside")?.(event);
restoreFocus = !(event.detail.focusable || event.detail.contextmenu);
},
onDismiss() {
send({
type: "CLOSE",
src: "interact-outside",
restoreFocus
});
}
});
},
computePlacement({ context, prop, scope }) {
const triggerEl = () => dom.getTriggerEl(scope);
const positionerEl = () => dom.getPositionerEl(scope);
return require_popper.getPlacement(triggerEl, positionerEl, {
...prop("positioning"),
onComplete(data) {
context.set("currentPlacement", data.placement);
}
});
},
scrollToHighlightedItems({ context, prop, scope }) {
let cleanups = [];
const exec = (immediate) => {
const highlightedValue = context.get("highlightedValue");
const highlightedIndexPath = context.get("highlightedIndexPath");
if (!highlightedIndexPath.length) return;
if (require_focus_visible.getInteractionModality() === "pointer") return;
dom.getListEls(scope).forEach((listEl, index) => {
const itemPath = highlightedIndexPath.slice(0, index + 1);
const itemEl = dom.getItemEl(scope, highlightedValue.toString());
const scrollToIndexFn = prop("scrollToIndexFn");
if (scrollToIndexFn) {
const itemIndexInList = itemPath[itemPath.length - 1];
scrollToIndexFn({
index: itemIndexInList,
immediate,
depth: index
});
return;
}
const raf_cleanup = require_dom_query.raf(() => {
require_dom_query.scrollIntoView(itemEl, {
rootEl: listEl,
block: "nearest"
});
});
cleanups.push(raf_cleanup);
});
};
require_dom_query.raf(() => {
require_focus_visible.setInteractionModality("virtual");
exec(true);
});
const rafCleanup = require_dom_query.raf(() => exec(true));
cleanups.push(rafCleanup);
const observerCleanup = require_dom_query.observeAttributes(dom.getContentEl(scope), {
attributes: ["data-activedescendant"],
callback: () => exec(false)
});
cleanups.push(observerCleanup);
return () => {
cleanups.forEach((cleanup) => cleanup());
};
}
},
actions: {
setValue(params) {
set.value(params, params.event.value);
},
clearValue(params) {
set.value(params, []);
},
setHighlightedValue(params) {
const { event } = params;
set.highlightedValue(params, event.value);
},
clearHighlightedValue(params) {
set.highlightedValue(params, []);
},
reposition({ context, prop, scope, event }) {
const positionerEl = () => dom.getPositionerEl(scope);
require_popper.getPlacement(dom.getTriggerEl(scope), positionerEl, {
...prop("positioning"),
...event.options,
defer: true,
listeners: false,
onComplete(data) {
context.set("currentPlacement", data.placement);
}
});
},
selectItem(params) {
const { context, prop, event } = params;
const collection = prop("collection");
const multiple = prop("multiple");
const value = context.get("value");
const itemValue = event.value;
const indexPath = event.indexPath ?? collection.getIndexPath(itemValue);
const node = collection.at(indexPath);
const hasChildren = collection.isBranchNode(node);
if (prop("allowParentSelection")) {
if (multiple) {
const filteredValue = value.filter((v) => {
const shortPath = v.length < itemValue.length ? v : itemValue;
return !(v.length < itemValue.length ? itemValue : v).slice(0, shortPath.length).every((val, i) => val === shortPath[i]) && !(0, _ginxjs_core_utils.isEqual)(v, itemValue);
});
set.value(params, [...filteredValue, itemValue]);
} else set.value(params, [itemValue]);
if (hasChildren) set.highlightedValue(params, itemValue);
} else if (hasChildren) {
if (multiple && value.length > 0) set.value(params, [...value.slice(0, -1), itemValue]);
else set.value(params, [itemValue]);
set.highlightedValue(params, itemValue);
} else if (multiple) {
const existingIndex = value.findIndex((path) => (0, _ginxjs_core_utils.isEqual)(path, itemValue));
if (existingIndex >= 0) {
const newValues = [...value];
newValues.splice(existingIndex, 1);
set.value(params, newValues);
} else set.value(params, [...value, itemValue]);
} else set.value(params, [itemValue]);
},
clearItem(params) {
const { context, event } = params;
const newValue = context.get("value").filter((v) => !(0, _ginxjs_core_utils.isEqual)(v, event.value));
set.value(params, newValue);
},
selectHighlightedItem({ context, send }) {
const indexPath = context.get("highlightedIndexPath");
const value = context.get("highlightedValue");
if (value) send({
type: "ITEM.SELECT",
value,
indexPath
});
},
highlightFirstItem(params) {
const { context, prop } = params;
const collection = prop("collection");
const highlightedValue = context.get("highlightedValue");
let parentNode;
if (!highlightedValue.length) parentNode = collection.rootNode;
else {
const indexPath = context.get("highlightedIndexPath");
parentNode = collection.getParentNode(indexPath) ?? collection.rootNode;
}
const firstChild = collection.getNodeChildren(parentNode).find((child) => !collection.getNodeDisabled(child));
if (!firstChild) return;
const firstValue = collection.getNodeValue(firstChild);
if (!highlightedValue.length) set.highlightedValue(params, [firstValue]);
else {
const parentPath = highlightedValue.slice(0, -1);
set.highlightedValue(params, [...parentPath, firstValue]);
}
},
highlightLastItem(params) {
const { context, prop } = params;
const collection = prop("collection");
const highlightedValue = context.get("highlightedValue");
let parentNode;
if (!highlightedValue.length) parentNode = collection.rootNode;
else {
const indexPath = context.get("highlightedIndexPath");
parentNode = collection.getParentNode(indexPath) ?? collection.rootNode;
}
const lastChild = collection.getNodeChildren(parentNode).findLast((child) => !collection.getNodeDisabled(child));
if (!lastChild) return;
const lastValue = collection.getNodeValue(lastChild);
if (!highlightedValue.length) set.highlightedValue(params, [lastValue]);
else {
const parentPath = highlightedValue.slice(0, -1);
set.highlightedValue(params, [...parentPath, lastValue]);
}
},
highlightNextItem(params) {
const { context, prop } = params;
const collection = prop("collection");
const highlightedValue = context.get("highlightedValue");
if (!highlightedValue.length) return;
const indexPath = context.get("highlightedIndexPath");
const nextSibling = collection.getNextSibling(indexPath);
if (!nextSibling) return;
const nextValue = collection.getNodeValue(nextSibling);
if (highlightedValue.length === 1) set.highlightedValue(params, [nextValue]);
else {
const parentPath = highlightedValue.slice(0, -1);
set.highlightedValue(params, [...parentPath, nextValue]);
}
},
highlightPreviousItem(params) {
const { context, prop } = params;
const collection = prop("collection");
const highlightedValue = context.get("highlightedValue");
if (!highlightedValue.length) return;
const indexPath = context.get("highlightedIndexPath");
const previousSibling = collection.getPreviousSibling(indexPath);
if (!previousSibling) return;
const prevValue = collection.getNodeValue(previousSibling);
if (highlightedValue.length === 1) set.highlightedValue(params, [prevValue]);
else {
const parentPath = highlightedValue.slice(0, -1);
set.highlightedValue(params, [...parentPath, prevValue]);
}
},
highlightFirstChild(params) {
const { context, prop } = params;
const collection = prop("collection");
const highlightedValue = context.get("highlightedValue");
if (!highlightedValue.length) return;
const indexPath = context.get("highlightedIndexPath");
const node = collection.getFirstNode(collection.at(indexPath));
if (!node) return;
const childValue = collection.getNodeValue(node);
set.highlightedValue(params, [...highlightedValue, childValue]);
},
highlightParent(params) {
const { context } = params;
const highlightedValue = context.get("highlightedValue");
if (!highlightedValue.length) return;
const parentPath = highlightedValue.slice(0, -1);
set.highlightedValue(params, parentPath);
},
setInitialFocus({ scope }) {
require_dom_query.raf(() => {
dom.getContentEl(scope)?.focus({ preventScroll: true });
});
},
focusTriggerEl({ event, scope }) {
if (!restoreFocusFn(event)) return;
require_dom_query.raf(() => {
dom.getTriggerEl(scope)?.focus({ preventScroll: true });
});
},
invokeOnOpen({ prop, context }) {
prop("onOpenChange")?.({
open: true,
value: context.get("value")
});
},
invokeOnClose({ prop, context }) {
prop("onOpenChange")?.({
open: false,
value: context.get("value")
});
},
toggleVisibility({ send, prop }) {
if (prop("open") != null) send({ type: prop("open") ? "CONTROLLED.OPEN" : "CONTROLLED.CLOSE" });
},
highlightFirstSelectedItem(params) {
const { context } = params;
const value = context.get("value");
if ((0, _ginxjs_core_utils.isEmpty)(value)) return;
const mostRecentSelection = (0, _ginxjs_core_utils.last)(value);
if (mostRecentSelection) set.highlightedValue(params, mostRecentSelection);
},
createGraceArea({ context, event, scope }) {
const value = event.value.toString();
const triggerElement = dom.getItemEl(scope, value);
if (!triggerElement) return;
const exitPoint = {
x: event.clientX,
y: event.clientY
};
const triggerRect = triggerElement.getBoundingClientRect();
const nextLevelEl = dom.getListEl(scope, value);
if (!nextLevelEl) return;
const graceArea = createGraceArea(exitPoint, triggerRect, nextLevelEl.getBoundingClientRect());
context.set("graceArea", graceArea);
setTimeout(() => {
context.set("graceArea", null);
}, 300);
},
clearGraceArea({ context }) {
context.set("graceArea", null);
},
setHighlightingForHoveredItem(params) {
const { prop, event } = params;
const collection = prop("collection");
const node = collection.at(event.indexPath);
let newHighlightedValue;
if (node && collection.isBranchNode(node)) newHighlightedValue = event.value;
else newHighlightedValue = event.value.slice(0, -1);
set.highlightedValue(params, newHighlightedValue);
},
syncInputValue({ context, scope }) {
const inputEl = dom.getHiddenInputEl(scope);
if (!inputEl) return;
require_dom_query.setElementValue(inputEl, context.hash("value"));
},
dispatchChangeEvent({ scope, context }) {
require_dom_query.dispatchInputValueEvent(dom.getHiddenInputEl(scope), { value: context.hash("value") });
},
scrollContentToTop({ scope, prop }) {
const scrollToIndexFn = prop("scrollToIndexFn");
require_dom_query.raf(() => {
(dom.getContentEl(scope)?.querySelectorAll("[data-part=\"list\"]"))?.forEach((listEl, index) => {
if (scrollToIndexFn) scrollToIndexFn({
index: 0,
immediate: true,
depth: index
});
else listEl.scrollTop = 0;
});
});
}
}
}
});
const set = {
value({ context, prop }, value) {
const collection = prop("collection");
context.set("value", value);
const valueIndexPath = value.map((v) => collection.getIndexPath(v));
context.set("valueIndexPath", valueIndexPath);
const selectedItems = valueIndexPath.map((indexPath) => {
return indexPath.map((_, index) => {
const partialPath = indexPath.slice(0, index + 1);
return collection.at(partialPath);
});
});
context.set("selectedItems", selectedItems);
prop("onValueChange")?.({
value,
items: selectedItems
});
},
highlightedValue({ context, prop }, value) {
const collection = prop("collection");
context.set("highlightedValue", value);
const highlightedIndexPath = (value == null ? [] : collection.getIndexPath(value)) ?? [];
context.set("highlightedIndexPath", highlightedIndexPath);
const highlightedItems = highlightedIndexPath.map((_, index) => {
const partialPath = highlightedIndexPath.slice(0, index + 1);
return collection.at(partialPath);
});
context.set("highlightedItems", highlightedItems);
prop("onHighlightChange")?.({
highlightedValue: value,
highlightedItems
});
}
};
function restoreFocusFn(event) {
const v = event.restoreFocus ?? event.previousEvent?.restoreFocus;
return v == null || !!v;
}
//#endregion
//#region src/machines/cascade-select/cascade-select.props.ts
const props = require_create_props.createProps()([
"allowParentSelection",
"closeOnSelect",
"collection",
"defaultOpen",
"defaultValue",
"defaultHighlightedValue",
"dir",
"disabled",
"formatValue",
"form",
"getRootNode",
"highlightedValue",
"highlightTrigger",
"id",
"ids",
"invalid",
"loopFocus",
"multiple",
"name",
"onFocusOutside",
"onHighlightChange",
"onInteractOutside",
"onOpenChange",
"onPointerDownOutside",
"onValueChange",
"open",
"positioning",
"readOnly",
"required",
"scrollToIndexFn",
"value"
]);
const splitProps = (0, _ginxjs_core_utils.createSplitProps)(props);
//#endregion
exports.anatomy = anatomy;
exports.collection = collection;
exports.connect = connect;
exports.machine = machine;
exports.parts = parts;
exports.props = props;
exports.splitProps = splitProps;
import { n as AnatomyInstance, r as AnatomyPart } from "../../anatomy-DFl8j10C.cjs";
import { i as InteractOutsideHandlers } from "../../index-jO45BUcW.cjs";
import { b as NormalizeProps, g as RequiredBy, r as DirectionProperty, t as CommonProperties, x as PropTypes } from "../../index-DFJGBSAc.cjs";
import { M as Service, S as EventObject, T as Machine } from "../../index-BNaxg4iu.cjs";
import { p as PositioningOptions, u as Placement } from "../../index-C5hisChz.cjs";
import { a as Point } from "../../types-B9xonIdT.cjs";
import { IndexPath, TreeCollection, TreeCollectionOptions, TreeNode } from "@ginxjs/core/collection";
//#region src/machines/cascade-select/cascade-select.anatomy.d.ts
declare const anatomy: AnatomyInstance<"root" | "item" | "control" | "indicator" | "label" | "itemIndicator" | "valueText" | "trigger" | "clearTrigger" | "positioner" | "content" | "list" | "itemText">;
declare const parts: Record<"root" | "item" | "control" | "indicator" | "label" | "itemIndicator" | "valueText" | "trigger" | "clearTrigger" | "positioner" | "content" | "list" | "itemText", AnatomyPart>;
//#endregion
//#region src/machines/cascade-select/cascade-select.collection.d.ts
declare const collection: {
<T extends unknown = any>(options: TreeCollectionOptions<T>): TreeCollection<T>;
empty<T extends unknown = any>(): TreeCollection<T>;
};
//#endregion
//#region src/machines/cascade-select/cascade-select.types.d.ts
interface ValueChangeDetails<T = TreeNode> {
value: string[][];
items: T[][];
}
interface HighlightChangeDetails<T = TreeNode> {
highlightedValue: string[];
highlightedItems: T[];
}
interface OpenChangeDetails {
open: boolean;
value: string[][];
}
interface ScrollToIndexDetails {
index: number;
immediate?: boolean | undefined;
depth: number;
}
type ElementIds = Partial<{
root: string;
label: string;
control: string;
trigger: string;
indicator: string;
clearTrigger: string;
positioner: string;
content: string;
hiddenInput: string;
list(valuePath: string): string;
item(valuePath: string): string;
}>;
interface CascadeSelectProps<T = any> extends DirectionProperty, CommonProperties, InteractOutsideHandlers {
collection?: TreeCollection<T> | undefined;
ids?: ElementIds | undefined;
name?: string | undefined;
form?: string | undefined;
value?: string[][] | undefined;
defaultValue?: string[][] | undefined;
highlightedValue?: string[] | undefined;
defaultHighlightedValue?: string[] | undefined;
multiple?: boolean | undefined;
open?: boolean | undefined;
defaultOpen?: boolean | undefined;
highlightTrigger?: "click" | "hover" | undefined;
closeOnSelect?: boolean | undefined;
loopFocus?: boolean | undefined;
disabled?: boolean | undefined;
readOnly?: boolean | undefined;
required?: boolean | undefined;
invalid?: boolean | undefined;
positioning?: PositioningOptions | undefined;
scrollToIndexFn?: ((details: ScrollToIndexDetails) => void) | undefined;
formatValue?: ((selectedItems: T[][]) => string) | undefined;
onValueChange?: ((details: ValueChangeDetails<T>) => void) | undefined;
onHighlightChange?: ((details: HighlightChangeDetails<T>) => void) | undefined;
onOpenChange?: ((details: OpenChangeDetails) => void) | undefined;
allowParentSelection?: boolean;
}
type PropsWithDefault = "collection" | "closeOnSelect" | "loopFocus" | "highlightTrigger";
interface CascadeSelectSchema<T extends TreeNode = TreeNode> {
state: "idle" | "focused" | "open";
props: RequiredBy<CascadeSelectProps<T>, PropsWithDefault>;
context: {
value: string[][];
highlightedValue: string[];
currentPlacement: Placement | undefined;
fieldsetDisabled: boolean;
graceArea: Point[] | null;
valueIndexPath: IndexPath[];
highlightedIndexPath: IndexPath;
highlightedItems: T[];
selectedItems: T[][];
};
computed: {
isInteractive: boolean;
valueAsString: string;
};
action: string;
effect: string;
guard: string;
event: EventObject;
}
type CascadeSelectService<T extends TreeNode = TreeNode> = Service<CascadeSelectSchema<T>>;
type CascadeSelectMachine<T extends TreeNode = TreeNode> = Machine<CascadeSelectSchema<T>>;
interface ItemProps<T = TreeNode> {
item: T;
indexPath: IndexPath;
value: string[];
}
interface ItemState<T = TreeNode> {
value: string[];
disabled: boolean;
highlighted: boolean;
selected: boolean;
hasChildren: boolean;
depth: number;
highlightedChild: T | undefined;
highlightedIndex: number;
}
interface CascadeSelectApi<T extends PropTypes = PropTypes, V = TreeNode> {
collection: TreeCollection<V>;
open: boolean;
focused: boolean;
multiple: boolean;
disabled: boolean;
highlightedValue: string[];
highlightedItems: V[];
selectedItems: V[][];
hasSelectedItems: boolean;
empty: boolean;
value: string[][];
valueAsString: string;
focus(): void;
reposition(options?: Partial<PositioningOptions>): void;
setOpen(open: boolean): void;
setHighlightValue(value: string | string[]): void;
clearHighlightValue(): void;
selectValue(value: string[]): void;
setValue(value: string[][]): void;
clearValue(value?: string[]): void;
getItemState(props: ItemProps<V>): ItemState<V>;
getRootProps(): T["element"];
getLabelProps(): T["element"];
getControlProps(): T["element"];
getTriggerProps(): T["element"];
getIndicatorProps(): T["element"];
getClearTriggerProps(): T["element"];
getPositionerProps(): T["element"];
getContentProps(): T["element"];
getListProps(props: ItemProps<V>): T["element"];
getItemProps(props: ItemProps<V>): T["element"];
getItemTextProps(props: ItemProps<V>): T["element"];
getItemIndicatorProps(props: ItemProps<V>): T["element"];
getValueTextProps(): T["element"];
getHiddenInputProps(): T["input"];
}
//#endregion
//#region src/machines/cascade-select/cascade-select.connect.d.ts
declare function connect<T extends PropTypes, V = TreeNode>(service: Service<CascadeSelectSchema>, normalize: NormalizeProps<T>): CascadeSelectApi<T, V>;
//#endregion
//#region src/machines/cascade-select/cascade-select.machine.d.ts
declare const machine: Machine<CascadeSelectSchema<any>>;
//#endregion
//#region src/machines/cascade-select/cascade-select.props.d.ts
declare const props: (keyof CascadeSelectProps<any>)[];
declare const splitProps: <Props extends Partial<CascadeSelectProps<any>>>(props: Props) => [Partial<CascadeSelectProps<any>>, Omit<Props, keyof CascadeSelectProps<any>>];
//#endregion
export { type CascadeSelectApi as Api, type ElementIds, type HighlightChangeDetails, type IndexPath, type ItemProps, type ItemState, type CascadeSelectMachine as Machine, type OpenChangeDetails, type Placement, type PositioningOptions, type CascadeSelectProps as Props, type ScrollToIndexDetails, type CascadeSelectService as Service, type TreeNode, type ValueChangeDetails, anatomy, collection, connect, machine, parts, props, splitProps };
import { n as AnatomyInstance, r as AnatomyPart } from "../../anatomy-C9pDRrRN.mjs";
import { i as InteractOutsideHandlers } from "../../index-C3Jj4aYp.mjs";
import { b as NormalizeProps, g as RequiredBy, r as DirectionProperty, t as CommonProperties, x as PropTypes } from "../../index-Cq2OwLf_.mjs";
import { M as Service, S as EventObject, T as Machine } from "../../index-g2S6NCuN.mjs";
import { p as PositioningOptions, u as Placement } from "../../index-r24gWw_v.mjs";
import { a as Point } from "../../types-CSqOdFYb.mjs";
import { IndexPath, TreeCollection, TreeCollectionOptions, TreeNode } from "@ginxjs/core/collection";
//#region src/machines/cascade-select/cascade-select.anatomy.d.ts
declare const anatomy: AnatomyInstance<"root" | "item" | "control" | "indicator" | "label" | "itemIndicator" | "valueText" | "trigger" | "clearTrigger" | "positioner" | "content" | "list" | "itemText">;
declare const parts: Record<"root" | "item" | "control" | "indicator" | "label" | "itemIndicator" | "valueText" | "trigger" | "clearTrigger" | "positioner" | "content" | "list" | "itemText", AnatomyPart>;
//#endregion
//#region src/machines/cascade-select/cascade-select.collection.d.ts
declare const collection: {
<T extends unknown = any>(options: TreeCollectionOptions<T>): TreeCollection<T>;
empty<T extends unknown = any>(): TreeCollection<T>;
};
//#endregion
//#region src/machines/cascade-select/cascade-select.types.d.ts
interface ValueChangeDetails<T = TreeNode> {
value: string[][];
items: T[][];
}
interface HighlightChangeDetails<T = TreeNode> {
highlightedValue: string[];
highlightedItems: T[];
}
interface OpenChangeDetails {
open: boolean;
value: string[][];
}
interface ScrollToIndexDetails {
index: number;
immediate?: boolean | undefined;
depth: number;
}
type ElementIds = Partial<{
root: string;
label: string;
control: string;
trigger: string;
indicator: string;
clearTrigger: string;
positioner: string;
content: string;
hiddenInput: string;
list(valuePath: string): string;
item(valuePath: string): string;
}>;
interface CascadeSelectProps<T = any> extends DirectionProperty, CommonProperties, InteractOutsideHandlers {
collection?: TreeCollection<T> | undefined;
ids?: ElementIds | undefined;
name?: string | undefined;
form?: string | undefined;
value?: string[][] | undefined;
defaultValue?: string[][] | undefined;
highlightedValue?: string[] | undefined;
defaultHighlightedValue?: string[] | undefined;
multiple?: boolean | undefined;
open?: boolean | undefined;
defaultOpen?: boolean | undefined;
highlightTrigger?: "click" | "hover" | undefined;
closeOnSelect?: boolean | undefined;
loopFocus?: boolean | undefined;
disabled?: boolean | undefined;
readOnly?: boolean | undefined;
required?: boolean | undefined;
invalid?: boolean | undefined;
positioning?: PositioningOptions | undefined;
scrollToIndexFn?: ((details: ScrollToIndexDetails) => void) | undefined;
formatValue?: ((selectedItems: T[][]) => string) | undefined;
onValueChange?: ((details: ValueChangeDetails<T>) => void) | undefined;
onHighlightChange?: ((details: HighlightChangeDetails<T>) => void) | undefined;
onOpenChange?: ((details: OpenChangeDetails) => void) | undefined;
allowParentSelection?: boolean;
}
type PropsWithDefault = "collection" | "closeOnSelect" | "loopFocus" | "highlightTrigger";
interface CascadeSelectSchema<T extends TreeNode = TreeNode> {
state: "idle" | "focused" | "open";
props: RequiredBy<CascadeSelectProps<T>, PropsWithDefault>;
context: {
value: string[][];
highlightedValue: string[];
currentPlacement: Placement | undefined;
fieldsetDisabled: boolean;
graceArea: Point[] | null;
valueIndexPath: IndexPath[];
highlightedIndexPath: IndexPath;
highlightedItems: T[];
selectedItems: T[][];
};
computed: {
isInteractive: boolean;
valueAsString: string;
};
action: string;
effect: string;
guard: string;
event: EventObject;
}
type CascadeSelectService<T extends TreeNode = TreeNode> = Service<CascadeSelectSchema<T>>;
type CascadeSelectMachine<T extends TreeNode = TreeNode> = Machine<CascadeSelectSchema<T>>;
interface ItemProps<T = TreeNode> {
item: T;
indexPath: IndexPath;
value: string[];
}
interface ItemState<T = TreeNode> {
value: string[];
disabled: boolean;
highlighted: boolean;
selected: boolean;
hasChildren: boolean;
depth: number;
highlightedChild: T | undefined;
highlightedIndex: number;
}
interface CascadeSelectApi<T extends PropTypes = PropTypes, V = TreeNode> {
collection: TreeCollection<V>;
open: boolean;
focused: boolean;
multiple: boolean;
disabled: boolean;
highlightedValue: string[];
highlightedItems: V[];
selectedItems: V[][];
hasSelectedItems: boolean;
empty: boolean;
value: string[][];
valueAsString: string;
focus(): void;
reposition(options?: Partial<PositioningOptions>): void;
setOpen(open: boolean): void;
setHighlightValue(value: string | string[]): void;
clearHighlightValue(): void;
selectValue(value: string[]): void;
setValue(value: string[][]): void;
clearValue(value?: string[]): void;
getItemState(props: ItemProps<V>): ItemState<V>;
getRootProps(): T["element"];
getLabelProps(): T["element"];
getControlProps(): T["element"];
getTriggerProps(): T["element"];
getIndicatorProps(): T["element"];
getClearTriggerProps(): T["element"];
getPositionerProps(): T["element"];
getContentProps(): T["element"];
getListProps(props: ItemProps<V>): T["element"];
getItemProps(props: ItemProps<V>): T["element"];
getItemTextProps(props: ItemProps<V>): T["element"];
getItemIndicatorProps(props: ItemProps<V>): T["element"];
getValueTextProps(): T["element"];
getHiddenInputProps(): T["input"];
}
//#endregion
//#region src/machines/cascade-select/cascade-select.connect.d.ts
declare function connect<T extends PropTypes, V = TreeNode>(service: Service<CascadeSelectSchema>, normalize: NormalizeProps<T>): CascadeSelectApi<T, V>;
//#endregion
//#region src/machines/cascade-select/cascade-select.machine.d.ts
declare const machine: Machine<CascadeSelectSchema<any>>;
//#endregion
//#region src/machines/cascade-select/cascade-select.props.d.ts
declare const props: (keyof CascadeSelectProps<any>)[];
declare const splitProps: <Props extends Partial<CascadeSelectProps<any>>>(props: Props) => [Partial<CascadeSelectProps<any>>, Omit<Props, keyof CascadeSelectProps<any>>];
//#endregion
export { type CascadeSelectApi as Api, type ElementIds, type HighlightChangeDetails, type IndexPath, type ItemProps, type ItemState, type CascadeSelectMachine as Machine, type OpenChangeDetails, type Placement, type PositioningOptions, type CascadeSelectProps as Props, type ScrollToIndexDetails, type CascadeSelectService as Service, type TreeNode, type ValueChangeDetails, anatomy, collection, connect, machine, parts, props, splitProps };
import { t as createAnatomy } from "../../create-anatomy-tqxVmw3d.mjs";
import { B as observeAttributes, Dt as isSelfTarget, G as raf, L as scrollIntoView, Tn as dataAttr, at as dispatchInputValueEvent, lt as setElementValue, p as createScope, pn as isEditableElement, pt as getEventKey, q as isValidTabEvent, ut as trackFormControl, w as queryAll, wn as ariaAttr } from "../../dom-query-BgxIO7_X.mjs";
import { n as trackDismissableElement } from "../../dismissable-BR1e7NIW.mjs";
import { a as setInteractionModality, o as trackFocusVisible, t as getInteractionModality } from "../../focus-visible-CEAbLeAJ.mjs";
import { a as createMachine, i as createGuards } from "../../core-D3PQ0tSv.mjs";
import { n as getPlacement, t as getPlacementStyles } from "../../popper-D_zaMhQo.mjs";
import { B as getRectCorners, D as closestSideToPoint, L as createPoint, R as createRect, i as isPointInPolygon } from "../../rect-JcwJCZkp.mjs";
import { t as createProps } from "../../create-props-Bi7oeFLF.mjs";
import { createSplitProps, isEmpty, isEqual, last } from "@ginxjs/core/utils";
import { TreeCollection } from "@ginxjs/core/collection";
//#region src/machines/cascade-select/cascade-select.anatomy.ts
const anatomy = createAnatomy("cascade-select").parts("root", "label", "control", "trigger", "indicator", "valueText", "clearTrigger", "positioner", "content", "list", "item", "itemText", "itemIndicator");
const parts = anatomy.build();
//#endregion
//#region src/machines/cascade-select/cascade-select.collection.ts
const collection = (options) => {
return new TreeCollection(options);
};
collection.empty = () => {
return new TreeCollection({ rootNode: {
value: "ROOT",
children: []
} });
};
//#endregion
//#region src/machines/cascade-select/cascade-select.dom.ts
const dom = createScope({
getRootId: (ctx) => ctx.ids?.root ?? `cascade-select:${ctx.id}`,
getLabelId: (ctx) => ctx.ids?.label ?? `cascade-select:${ctx.id}:label`,
getControlId: (ctx) => ctx.ids?.control ?? `cascade-select:${ctx.id}:control`,
getTriggerId: (ctx) => ctx.ids?.trigger ?? `cascade-select:${ctx.id}:trigger`,
getIndicatorId: (ctx) => ctx.ids?.indicator ?? `cascade-select:${ctx.id}:indicator`,
getClearTriggerId: (ctx) => ctx.ids?.clearTrigger ?? `cascade-select:${ctx.id}:clear-trigger`,
getPositionerId: (ctx) => ctx.ids?.positioner ?? `cascade-select:${ctx.id}:positioner`,
getContentId: (ctx) => ctx.ids?.content ?? `cascade-select:${ctx.id}:content`,
getHiddenInputId: (ctx) => ctx.ids?.hiddenInput ?? `cascade-select:${ctx.id}:hidden-input`,
getListId: (ctx, value) => ctx.ids?.list?.(value) ?? `cascade-select:${ctx.id}:list:${value}`,
getItemId: (ctx, value) => ctx.ids?.item?.(value) ?? `cascade-select:${ctx.id}:item:${value}`,
getRootEl: (ctx) => dom.getById(ctx, dom.getRootId(ctx)),
getLabelEl: (ctx) => dom.getById(ctx, dom.getLabelId(ctx)),
getControlEl: (ctx) => dom.getById(ctx, dom.getControlId(ctx)),
getTriggerEl: (ctx) => dom.getById(ctx, dom.getTriggerId(ctx)),
getIndicatorEl: (ctx) => dom.getById(ctx, dom.getIndicatorId(ctx)),
getClearTriggerEl: (ctx) => dom.getById(ctx, dom.getClearTriggerId(ctx)),
getPositionerEl: (ctx) => dom.getById(ctx, dom.getPositionerId(ctx)),
getContentEl: (ctx) => dom.getById(ctx, dom.getContentId(ctx)),
getHiddenInputEl: (ctx) => dom.getById(ctx, dom.getHiddenInputId(ctx)),
getListEl: (ctx, value) => dom.getById(ctx, dom.getListId(ctx, value)),
getListEls: (ctx) => queryAll(dom.getContentEl(ctx), `[data-part="list"]`),
getItemEl: (ctx, value) => dom.getById(ctx, dom.getItemId(ctx, value)),
dispatchInputEvent: (ctx, value) => {
const inputEl = dom.getHiddenInputEl(ctx);
if (!inputEl) return;
dispatchInputValueEvent(inputEl, { value });
}
});
//#endregion
//#region src/machines/cascade-select/cascade-select.connect.ts
function connect(service, normalize) {
const { send, context, prop, scope, computed, state } = service;
const collection = prop("collection");
const value = context.get("value");
const open = state.hasTag("open");
const focused = state.matches("focused");
const highlightedIndexPath = context.get("highlightedIndexPath");
const highlightedValue = context.get("highlightedValue");
const currentPlacement = context.get("currentPlacement");
const disabled = prop("disabled") || context.get("fieldsetDisabled");
const interactive = computed("isInteractive");
const valueAsString = computed("valueAsString");
const highlightedItems = context.get("highlightedItems");
const selectedItems = context.get("selectedItems");
const popperStyles = getPlacementStyles({
...prop("positioning"),
placement: currentPlacement
});
const getItemState = (props) => {
const { item, indexPath, value: itemValue } = props;
const depth = indexPath ? indexPath.length : 0;
const highlighted = itemValue.every((v, i) => v === highlightedValue[i]);
const selected = value.some((v) => isEqual(v, itemValue));
const highlightedChild = collection.getNodeChildren(collection.at(indexPath))[highlightedIndexPath[depth]];
const highlightedIndex = highlightedIndexPath[depth];
return {
value: itemValue,
disabled: collection.getNodeDisabled(item),
highlighted,
selected,
hasChildren: collection.isBranchNode(item),
depth,
highlightedChild,
highlightedIndex
};
};
const hasSelectedItems = value.length > 0;
const empty = value.length === 0;
return {
collection,
open,
focused,
multiple: !!prop("multiple"),
disabled,
value,
highlightedValue,
highlightedItems,
selectedItems,
hasSelectedItems,
empty,
valueAsString,
reposition(options = {}) {
send({
type: "POSITIONING.SET",
options
});
},
focus() {
dom.getTriggerEl(scope)?.focus({ preventScroll: true });
},
setOpen(nextOpen) {
if (nextOpen === open) return;
send({ type: nextOpen ? "OPEN" : "CLOSE" });
},
setHighlightValue(value) {
send({
type: "HIGHLIGHTED_VALUE.SET",
value
});
},
clearHighlightValue() {
send({ type: "HIGHLIGHTED_VALUE.CLEAR" });
},
setValue(value) {
send({
type: "VALUE.SET",
value
});
},
selectValue(value) {
send({
type: "ITEM.SELECT",
value
});
},
clearValue(value) {
if (value) send({
type: "ITEM.CLEAR",
value
});
else send({ type: "VALUE.CLEAR" });
},
getItemState,
getRootProps() {
return normalize.element({
...parts.root.attrs,
id: dom.getRootId(scope),
dir: prop("dir"),
"data-disabled": dataAttr(disabled),
"data-readonly": dataAttr(prop("readOnly")),
"data-invalid": dataAttr(prop("invalid")),
"data-state": open ? "open" : "closed"
});
},
getLabelProps() {
return normalize.label({
...parts.label.attrs,
id: dom.getLabelId(scope),
dir: prop("dir"),
htmlFor: dom.getHiddenInputId(scope),
"data-disabled": dataAttr(disabled),
"data-readonly": dataAttr(prop("readOnly")),
"data-invalid": dataAttr(prop("invalid")),
onClick(event) {
if (event.defaultPrevented) return;
if (disabled) return;
dom.getTriggerEl(scope)?.focus({ preventScroll: true });
}
});
},
getControlProps() {
return normalize.element({
...parts.control.attrs,
dir: prop("dir"),
id: dom.getControlId(scope),
"data-disabled": dataAttr(disabled),
"data-focus": dataAttr(focused),
"data-readonly": dataAttr(prop("readOnly")),
"data-invalid": dataAttr(prop("invalid")),
"data-state": open ? "open" : "closed"
});
},
getTriggerProps() {
return normalize.button({
...parts.trigger.attrs,
dir: prop("dir"),
id: dom.getTriggerId(scope),
type: "button",
role: "combobox",
"aria-controls": dom.getContentId(scope),
"aria-expanded": open,
"aria-haspopup": "listbox",
"aria-labelledby": dom.getLabelId(scope),
"data-state": open ? "open" : "closed",
"data-disabled": dataAttr(disabled),
"data-readonly": dataAttr(prop("readOnly")),
"data-invalid": dataAttr(prop("invalid")),
"data-focus": dataAttr(focused),
"data-placement": currentPlacement,
"data-placeholder-shown": dataAttr(!hasSelectedItems),
disabled,
onClick(event) {
if (event.defaultPrevented) return;
if (!interactive) return;
send({ type: "TRIGGER.CLICK" });
},
onFocus() {
send({ type: "TRIGGER.FOCUS" });
},
onBlur() {
send({ type: "TRIGGER.BLUR" });
},
onKeyDown(event) {
if (event.defaultPrevented) return;
if (!interactive) return;
const exec = {
ArrowUp() {
send({ type: "TRIGGER.ARROW_UP" });
},
ArrowDown(event) {
send({ type: event.altKey ? "OPEN" : "TRIGGER.ARROW_DOWN" });
},
ArrowLeft() {
send({ type: "TRIGGER.ARROW_LEFT" });
},
ArrowRight() {
send({ type: "TRIGGER.ARROW_RIGHT" });
},
Enter() {
send({ type: "TRIGGER.ENTER" });
},
Space() {
send({ type: "TRIGGER.ENTER" });
}
}[getEventKey(event, { dir: prop("dir") })];
if (exec) {
exec(event);
event.preventDefault();
}
}
});
},
getClearTriggerProps() {
return normalize.button({
...parts.clearTrigger.attrs,
dir: prop("dir"),
id: dom.getClearTriggerId(scope),
type: "button",
"aria-label": "Clear value",
hidden: !hasSelectedItems,
"data-disabled": dataAttr(disabled),
"data-readonly": dataAttr(prop("readOnly")),
"data-invalid": dataAttr(prop("invalid")),
disabled,
onClick(event) {
if (event.defaultPrevented) return;
send({ type: "CLEAR_TRIGGER.CLICK" });
}
});
},
getPositionerProps() {
return normalize.element({
...parts.positioner.attrs,
dir: prop("dir"),
id: dom.getPositionerId(scope),
style: popperStyles.floating
});
},
getContentProps() {
const highlightedItemId = highlightedValue ? dom.getItemId(scope, highlightedValue.toString()) : void 0;
return normalize.element({
...parts.content.attrs,
id: dom.getContentId(scope),
role: "listbox",
"aria-labelledby": dom.getLabelId(scope),
"aria-activedescendant": highlightedItemId,
"data-activedescendant": highlightedItemId,
"data-state": open ? "open" : "closed",
"aria-multiselectable": prop("multiple"),
"aria-required": prop("required"),
"aria-readonly": prop("readOnly"),
hidden: !open,
tabIndex: 0,
onKeyDown(event) {
if (!interactive) return;
if (!isSelfTarget(event)) return;
if (event.key === "Tab") {
if (!isValidTabEvent(event)) {
event.preventDefault();
return;
}
}
const exec = {
ArrowDown() {
send({ type: "CONTENT.ARROW_DOWN" });
},
ArrowUp() {
send({ type: "CONTENT.ARROW_UP" });
},
ArrowRight() {
send({ type: "CONTENT.ARROW_RIGHT" });
},
ArrowLeft() {
send({ type: "CONTENT.ARROW_LEFT" });
},
Home() {
send({ type: "CONTENT.HOME" });
},
End() {
send({ type: "CONTENT.END" });
},
Enter() {
send({ type: "CONTENT.ENTER" });
},
" "() {
send({ type: "CONTENT.ENTER" });
}
}[getEventKey(event, { dir: prop("dir") })];
if (exec) {
exec();
event.preventDefault();
return;
}
if (isEditableElement(event.target)) return;
},
onPointerMove(event) {
if (!interactive) return;
send({
type: "POINTER_MOVE",
clientX: event.clientX,
clientY: event.clientY,
target: event.target
});
}
});
},
getListProps(props) {
const itemState = getItemState(props);
return normalize.element({
...parts.list.attrs,
id: dom.getListId(scope, itemState.value.toString()),
dir: prop("dir"),
"data-depth": itemState.depth,
"aria-level": itemState.depth,
role: "group"
});
},
getIndicatorProps() {
return normalize.element({
...parts.indicator.attrs,
id: dom.getIndicatorId(scope),
dir: prop("dir"),
"aria-hidden": true,
"data-state": open ? "open" : "closed",
"data-disabled": dataAttr(disabled),
"data-readonly": dataAttr(prop("readOnly")),
"data-invalid": dataAttr(prop("invalid"))
});
},
getItemProps(props) {
const { indexPath } = props;
const itemState = getItemState(props);
return normalize.element({
...parts.item.attrs,
id: dom.getItemId(scope, itemState.value.toString()),
dir: prop("dir"),
role: "treeitem",
"aria-haspopup": itemState.hasChildren ? "menu" : void 0,
"aria-expanded": itemState.hasChildren ? itemState.highlighted : false,
"aria-controls": itemState.hasChildren ? dom.getListId(scope, itemState.value.toString()) : void 0,
"aria-owns": itemState.hasChildren ? dom.getListId(scope, itemState.value.toString()) : void 0,
"aria-disabled": ariaAttr(itemState.disabled),
"data-value": itemState.value.toString(),
"data-disabled": dataAttr(itemState.disabled),
"data-highlighted": dataAttr(itemState.highlighted),
"data-selected": dataAttr(itemState.selected),
"data-depth": itemState.depth,
"data-state": itemState.selected ? "checked" : "unchecked",
"data-type": itemState.hasChildren ? "branch" : "leaf",
"data-index-path": indexPath.toString(),
onDoubleClick() {
if (itemState.disabled) return;
send({ type: "CLOSE" });
},
onClick(event) {
if (event.defaultPrevented) return;
if (!interactive) return;
if (itemState.disabled) return;
send({
type: "ITEM.CLICK",
value: itemState.value,
indexPath
});
},
onPointerEnter(event) {
if (!interactive) return;
if (itemState.disabled) return;
send({
type: "ITEM.POINTER_ENTER",
value: itemState.value,
indexPath,
clientX: event.clientX,
clientY: event.clientY
});
},
onPointerLeave(event) {
if (!interactive) return;
if (itemState.disabled) return;
if (event.pointerType !== "mouse") return;
if (!service.event.previous()?.type.includes("POINTER")) return;
send({
type: "ITEM.POINTER_LEAVE",
value: itemState.value,
indexPath,
clientX: event.clientX,
clientY: event.clientY
});
}
});
},
getItemTextProps(props) {
const { item } = props;
const itemValue = collection.getNodeValue(item);
const itemState = getItemState(props);
return normalize.element({
dir: prop("dir"),
...parts.itemText.attrs,
"data-value": itemValue,
"data-highlighted": dataAttr(itemState.highlighted),
"data-state": itemState.selected ? "checked" : "unchecked",
"data-disabled": dataAttr(itemState.disabled)
});
},
getItemIndicatorProps(props) {
const { item } = props;
const itemValue = collection.getNodeValue(item);
const itemState = getItemState(props);
return normalize.element({
...parts.itemIndicator.attrs,
dir: prop("dir"),
"data-value": itemValue,
"data-highlighted": dataAttr(itemState.highlighted),
"data-type": itemState.hasChildren ? "branch" : "leaf",
"data-state": itemState.selected ? "checked" : "unchecked",
hidden: !itemState.selected
});
},
getValueTextProps() {
return normalize.element({
...parts.valueText.attrs,
dir: prop("dir"),
"data-disabled": dataAttr(disabled),
"data-invalid": dataAttr(prop("invalid")),
"data-focus": dataAttr(focused)
});
},
getHiddenInputProps() {
const defaultValue = context.hash("value");
return normalize.input({
name: prop("name"),
form: prop("form"),
disabled,
multiple: prop("multiple"),
required: prop("required"),
readOnly: prop("readOnly"),
hidden: true,
"aria-hidden": true,
id: dom.getHiddenInputId(scope),
defaultValue,
"aria-labelledby": dom.getLabelId(scope)
});
}
};
}
//#endregion
//#region src/machines/cascade-select/cascade-select.utils.ts
function createGraceArea(exitPoint, triggerRect, targetRect, options = {}) {
const { padding = 5 } = options;
const paddedExitPoints = getPaddedExitPoints(exitPoint, closestSideToPoint(createRect({
x: triggerRect.left,
y: triggerRect.top,
width: triggerRect.width,
height: triggerRect.height
}), exitPoint), padding);
const targetPoints = domRectToPoints(targetRect);
return getConvexHull([...paddedExitPoints, ...targetPoints]);
}
function isPointerInGraceArea(point, graceArea) {
return isPointInPolygon(graceArea, point);
}
function getPaddedExitPoints(exitPoint, exitSide, padding) {
const { x, y } = exitPoint;
switch (exitSide) {
case "top": return [createPoint(x - padding, y + padding), createPoint(x + padding, y + padding)];
case "bottom": return [createPoint(x - padding, y - padding), createPoint(x + padding, y - padding)];
case "left": return [createPoint(x + padding, y - padding), createPoint(x + padding, y + padding)];
case "right": return [createPoint(x - padding, y - padding), createPoint(x - padding, y + padding)];
default: return [];
}
}
function domRectToPoints(rect) {
const corners = getRectCorners(createRect({
x: rect.left,
y: rect.top,
width: rect.width,
height: rect.height
}));
return [
corners.top,
corners.right,
corners.bottom,
corners.left
];
}
function getConvexHull(points) {
if (points.length <= 1) return points.slice();
const sortedPoints = points.slice().sort((a, b) => {
if (a.x !== b.x) return a.x - b.x;
return a.y - b.y;
});
const lower = [];
for (const point of sortedPoints) {
while (lower.length >= 2 && crossProduct(lower[lower.length - 2], lower[lower.length - 1], point) <= 0) lower.pop();
lower.push(point);
}
const upper = [];
for (let i = sortedPoints.length - 1; i >= 0; i--) {
const point = sortedPoints[i];
while (upper.length >= 2 && crossProduct(upper[upper.length - 2], upper[upper.length - 1], point) <= 0) upper.pop();
upper.push(point);
}
lower.pop();
upper.pop();
return lower.concat(upper);
}
function crossProduct(o, a, b) {
return (a.x - o.x) * (b.y - o.y) - (a.y - o.y) * (b.x - o.x);
}
//#endregion
//#region src/machines/cascade-select/cascade-select.machine.ts
const { or, and, not } = createGuards();
const machine = createMachine({
props({ props }) {
return {
closeOnSelect: true,
loopFocus: false,
defaultValue: [],
defaultHighlightedValue: [],
defaultOpen: false,
multiple: false,
highlightTrigger: "click",
allowParentSelection: false,
positioning: {
placement: "bottom-start",
gutter: 8,
...props.positioning
},
...props,
collection: props.collection ?? collection.empty()
};
},
context({ prop, bindable }) {
return {
value: bindable(() => ({
defaultValue: prop("defaultValue"),
value: prop("value"),
isEqual,
hash(value) {
return value.join(", ");
}
})),
highlightedValue: bindable(() => ({
defaultValue: prop("defaultHighlightedValue"),
value: prop("highlightedValue"),
isEqual
})),
valueIndexPath: bindable(() => {
return { defaultValue: (prop("value") ?? prop("defaultValue") ?? []).map((v) => prop("collection").getIndexPath(v)) };
}),
highlightedIndexPath: bindable(() => {
const value = prop("highlightedValue") ?? prop("defaultHighlightedValue") ?? null;
return { defaultValue: value ? prop("collection").getIndexPath(value) : [] };
}),
highlightedItems: bindable(() => ({ defaultValue: [] })),
selectedItems: bindable(() => ({ defaultValue: [] })),
currentPlacement: bindable(() => ({ defaultValue: void 0 })),
fieldsetDisabled: bindable(() => ({ defaultValue: false })),
graceArea: bindable(() => ({ defaultValue: null })),
isPointerInTransit: bindable(() => ({ defaultValue: false }))
};
},
computed: {
isInteractive: ({ prop }) => !(prop("disabled") || prop("readOnly")),
valueAsString: ({ prop, context }) => {
const collection = prop("collection");
const items = context.get("selectedItems");
const multiple = prop("multiple");
const formatMultipleMode = (items) => collection.stringifyNode(items.at(-1)) ?? collection.getNodeValue(items.at(-1));
const formatSingleMode = (items) => {
return items.map((item) => {
return collection.stringifyNode(item) ?? collection.getNodeValue(item);
}).join(" / ");
};
const defaultFormatValue = (items) => items.map(multiple ? formatMultipleMode : formatSingleMode).join(", ");
return (prop("formatValue") ?? defaultFormatValue)(items);
}
},
initialState({ prop }) {
return prop("open") || prop("defaultOpen") ? "open" : "idle";
},
watch({ context, prop, track, action }) {
track([() => context.get("value")?.toString()], () => {
action(["syncInputValue", "dispatchChangeEvent"]);
});
track([() => prop("open")], () => {
action(["toggleVisibility"]);
});
},
on: {
"VALUE.SET": { actions: ["setValue"] },
"VALUE.CLEAR": { actions: ["clearValue"] },
"CLEAR_TRIGGER.CLICK": { actions: ["clearValue", "focusTriggerEl"] },
"HIGHLIGHTED_VALUE.SET": { actions: ["setHighlightedValue"] },
"HIGHLIGHTED_VALUE.CLEAR": { actions: ["clearHighlightedValue"] },
"ITEM.SELECT": { actions: ["selectItem"] },
"ITEM.CLEAR": { actions: ["clearItem"] }
},
effects: ["trackFormControlState"],
states: {
idle: {
tags: ["closed"],
on: {
"CONTROLLED.OPEN": [{
guard: "isTriggerClickEvent",
target: "open",
actions: ["setInitialFocus", "highlightFirstSelectedItem"]
}, {
target: "open",
actions: ["setInitialFocus"]
}],
"TRIGGER.CLICK": [{
guard: "isOpenControlled",
actions: ["invokeOnOpen"]
}, {
target: "open",
actions: [
"invokeOnOpen",
"setInitialFocus",
"highlightFirstSelectedItem"
]
}],
"TRIGGER.FOCUS": { target: "focused" },
OPEN: [{
guard: "isOpenControlled",
actions: ["invokeOnOpen"]
}, {
target: "open",
actions: ["setInitialFocus", "invokeOnOpen"]
}]
}
},
focused: {
tags: ["closed"],
on: {
"CONTROLLED.OPEN": [
{
guard: "isTriggerClickEvent",
target: "open",
actions: ["setInitialFocus", "highlightFirstSelectedItem"]
},
{
guard: "isTriggerArrowUpEvent",
target: "open",
actions: ["setInitialFocus", "highlightLastItem"]
},
{
guard: or("isTriggerArrowDownEvent", "isTriggerEnterEvent", ""),
target: "open",
actions: ["setInitialFocus", "highlightFirstItem"]
},
{
target: "open",
actions: ["setInitialFocus"]
}
],
OPEN: [{
guard: "isOpenControlled",
actions: ["invokeOnOpen"]
}, {
target: "open",
actions: ["setInitialFocus", "invokeOnOpen"]
}],
"TRIGGER.BLUR": { target: "idle" },
"TRIGGER.CLICK": [{
guard: "isOpenControlled",
actions: ["invokeOnOpen"]
}, {
target: "open",
actions: [
"setInitialFocus",
"invokeOnOpen",
"highlightFirstSelectedItem"
]
}],
"TRIGGER.ENTER": [{
guard: "isOpenControlled",
actions: ["invokeOnOpen"]
}, {
target: "open",
actions: [
"setInitialFocus",
"invokeOnOpen",
"highlightFirstItem"
]
}],
"TRIGGER.ARROW_UP": [{
guard: "isOpenControlled",
actions: ["invokeOnOpen"]
}, {
target: "open",
actions: [
"setInitialFocus",
"invokeOnOpen",
"highlightLastItem"
]
}],
"TRIGGER.ARROW_DOWN": [{
guard: "isOpenControlled",
actions: ["invokeOnOpen"]
}, {
target: "open",
actions: [
"setInitialFocus",
"invokeOnOpen",
"highlightFirstItem"
]
}],
"TRIGGER.ARROW_LEFT": [{
guard: "isOpenControlled",
actions: ["invokeOnOpen"]
}, {
target: "open",
actions: ["invokeOnOpen"]
}],
"TRIGGER.ARROW_RIGHT": [{
guard: "isOpenControlled",
actions: ["invokeOnOpen"]
}, {
target: "open",
actions: ["invokeOnOpen", "highlightFirstItem"]
}]
}
},
open: {
tags: ["open"],
exit: ["clearHighlightedValue", "scrollContentToTop"],
effects: [
"trackDismissableElement",
"trackFocusVisible",
"computePlacement",
"scrollToHighlightedItems"
],
on: {
"CONTROLLED.CLOSE": [{
guard: "restoreFocus",
target: "focused",
actions: ["focusTriggerEl"]
}, { target: "idle" }],
CLOSE: [
{
guard: "isOpenControlled",
actions: ["invokeOnClose"]
},
{
guard: "restoreFocus",
target: "focused",
actions: ["invokeOnClose", "focusTriggerEl"]
},
{
target: "idle",
actions: ["invokeOnClose"]
}
],
"TRIGGER.CLICK": [{
guard: "isOpenControlled",
actions: ["invokeOnClose"]
}, {
target: "focused",
actions: ["invokeOnClose", "focusTriggerEl"]
}],
"ITEM.CLICK": [
{
guard: and("canSelectItem", and("shouldCloseOnSelect", not("multiple")), "isOpenControlled"),
actions: ["selectItem", "invokeOnClose"]
},
{
guard: and("canSelectItem", and("shouldCloseOnSelect", not("multiple"))),
target: "focused",
actions: [
"selectItem",
"invokeOnClose",
"focusTriggerEl"
]
},
{
guard: "canSelectItem",
actions: ["selectItem"]
},
{ actions: ["setHighlightedValue"] }
],
"ITEM.POINTER_ENTER": [{
guard: "isHoverHighlight",
actions: ["setHighlightingForHoveredItem"]
}],
"ITEM.POINTER_LEAVE": [{
guard: and("isHoverHighlight", "shouldHighlightOnHover"),
actions: ["createGraceArea"]
}],
POINTER_MOVE: [{
guard: and("isHoverHighlight", "hasGraceArea", "isPointerOutsideGraceArea", "isPointerNotInAnyItem", "hasHighlightedValue"),
actions: ["clearGraceArea"]
}],
"GRACE_AREA.CLEAR": [{
guard: "isHoverHighlight",
actions: ["clearGraceArea"]
}],
"CONTENT.HOME": { actions: ["highlightFirstItem"] },
"CONTENT.END": { actions: ["highlightLastItem"] },
"CONTENT.ARROW_DOWN": [{
guard: or(not("hasHighlightedValue"), and("loop", "isHighlightedLastItem")),
actions: ["highlightFirstItem"]
}, { actions: ["highlightNextItem"] }],
"CONTENT.ARROW_UP": [{
guard: or(not("hasHighlightedValue"), and("loop", "isHighlightedFirstItem")),
actions: ["highlightLastItem"]
}, { actions: ["highlightPreviousItem"] }],
"CONTENT.ARROW_RIGHT": [{
guard: "canNavigateToChild",
actions: ["highlightFirstChild"]
}],
"CONTENT.ARROW_LEFT": [
{
guard: and("isAtRootLevel", "isOpenControlled"),
actions: ["invokeOnClose", "focusTriggerEl"]
},
{
guard: and("isAtRootLevel", "restoreFocus"),
target: "focused",
actions: ["invokeOnClose", "focusTriggerEl"]
},
{
guard: "isAtRootLevel",
target: "idle",
actions: ["invokeOnClose"]
},
{
guard: "canNavigateToParent",
actions: ["highlightParent"]
}
],
"CONTENT.ENTER": [
{
guard: and("canSelectHighlightedItem", and("shouldCloseOnSelectHighlighted", not("multiple")), "isOpenControlled"),
actions: ["selectHighlightedItem", "invokeOnClose"]
},
{
guard: and("canSelectHighlightedItem", and("shouldCloseOnSelectHighlighted", not("multiple"))),
target: "focused",
actions: [
"selectHighlightedItem",
"invokeOnClose",
"focusTriggerEl"
]
},
{
guard: "canSelectHighlightedItem",
actions: ["selectHighlightedItem"]
}
],
"POSITIONING.SET": { actions: ["reposition"] }
}
}
},
implementations: {
guards: {
restoreFocus: ({ event }) => restoreFocusFn(event),
multiple: ({ prop }) => !!prop("multiple"),
loop: ({ prop }) => !!prop("loopFocus"),
isOpenControlled: ({ prop }) => !!prop("open"),
isTriggerClickEvent: ({ event }) => event.previousEvent?.type === "TRIGGER.CLICK",
isTriggerArrowUpEvent: ({ event }) => event.previousEvent?.type === "TRIGGER.ARROW_UP",
isTriggerArrowDownEvent: ({ event }) => event.previousEvent?.type === "TRIGGER.ARROW_DOWN",
isTriggerEnterEvent: ({ event }) => event.previousEvent?.type === "TRIGGER.ENTER",
isTriggerArrowRightEvent: ({ event }) => event.previousEvent?.type === "TRIGGER.ARROW_RIGHT",
hasHighlightedValue: ({ context }) => context.get("highlightedValue").length > 0,
isHighlightedFirstItem: ({ context }) => context.get("highlightedIndexPath").at(-1) === 0,
isHighlightedLastItem: ({ prop, context }) => {
const path = context.get("highlightedIndexPath");
const itemIndex = path.at(-1);
if (!itemIndex && itemIndex !== 0) return false;
const parentIndexPath = path.slice(0, -1);
return !prop("collection").at([...parentIndexPath, itemIndex + 1]);
},
shouldCloseOnSelect: ({ prop, event }) => {
const collection = prop("collection");
const node = collection.at(event.indexPath);
return prop("closeOnSelect") && node && !collection.isBranchNode(node);
},
shouldCloseOnSelectHighlighted: ({ prop, context }) => {
const collection = prop("collection");
const node = last(context.get("highlightedItems"));
return prop("closeOnSelect") && node != null && !collection.isBranchNode(node);
},
canSelectItem: ({ prop, event }) => {
const collection = prop("collection");
const node = collection.at(event.indexPath);
if (!node) return false;
return prop("allowParentSelection") || !collection.isBranchNode(node);
},
canSelectHighlightedItem: ({ prop, context }) => {
const collection = prop("collection");
const node = collection.at(context.get("highlightedIndexPath"));
if (!node) return false;
return prop("allowParentSelection") || !collection.isBranchNode(node);
},
canNavigateToChild: ({ prop, context }) => {
const highlightedIndexPath = context.get("highlightedIndexPath");
if (!highlightedIndexPath.length) return false;
const collection = prop("collection");
const node = collection.at(highlightedIndexPath);
return node && collection.isBranchNode(node);
},
canNavigateToParent: ({ context }) => context.get("highlightedIndexPath").length > 1,
isAtRootLevel: ({ context }) => context.get("highlightedIndexPath").length <= 1,
isHoverHighlight: ({ prop }) => prop("highlightTrigger") === "hover",
shouldHighlightOnHover: ({ prop, event }) => {
const collection = prop("collection");
const node = collection.at(event.indexPath);
return node && collection.isBranchNode(node);
},
shouldUpdateHighlightedIndexPath: ({ prop, context, event }) => {
const collection = prop("collection");
const currentHighlightedIndexPath = context.get("highlightedIndexPath");
if (!currentHighlightedIndexPath || currentHighlightedIndexPath.length === 0) return false;
const node = collection.at(event.indexPath);
if (!node || collection.isBranchNode(node)) return false;
const indexPath = event.indexPath;
if (!indexPath) return false;
const minLength = Math.min(indexPath.length, currentHighlightedIndexPath.length);
let commonPrefixLength = 0;
for (let i = 0; i < minLength; i++) if (indexPath[i] === currentHighlightedIndexPath[i]) commonPrefixLength = i + 1;
else break;
return commonPrefixLength > 0 && (commonPrefixLength < currentHighlightedIndexPath.length || commonPrefixLength < indexPath.length);
},
hasGraceArea: ({ context }) => {
return context.get("graceArea") != null;
},
isPointerOutsideGraceArea: ({ context, event }) => {
const graceArea = context.get("graceArea");
if (!graceArea) return false;
return !isPointerInGraceArea({
x: event.clientX,
y: event.clientY
}, graceArea);
},
isPointerNotInAnyItem: ({ event }) => {
const target = event.target;
const itemElement = target.closest("[data-part=\"item\"]");
const contentElement = target.closest("[data-part=\"content\"]");
return !contentElement || !itemElement && !!contentElement;
}
},
effects: {
trackFormControlState({ context, scope, prop }) {
return trackFormControl(dom.getTriggerEl(scope), {
onFieldsetDisabledChange(disabled) {
context.set("fieldsetDisabled", disabled);
},
onFormReset() {
context.set("value", prop("defaultValue") ?? []);
}
});
},
trackFocusVisible({ scope }) {
return trackFocusVisible({ root: scope.getRootNode?.() });
},
trackDismissableElement({ scope, send, prop }) {
const contentEl = () => dom.getContentEl(scope);
let restoreFocus = true;
return trackDismissableElement(contentEl, {
defer: true,
exclude: [dom.getTriggerEl(scope), dom.getClearTriggerEl(scope)],
onFocusOutside: prop("onFocusOutside"),
onPointerDownOutside: prop("onPointerDownOutside"),
onInteractOutside(event) {
prop("onInteractOutside")?.(event);
restoreFocus = !(event.detail.focusable || event.detail.contextmenu);
},
onDismiss() {
send({
type: "CLOSE",
src: "interact-outside",
restoreFocus
});
}
});
},
computePlacement({ context, prop, scope }) {
const triggerEl = () => dom.getTriggerEl(scope);
const positionerEl = () => dom.getPositionerEl(scope);
return getPlacement(triggerEl, positionerEl, {
...prop("positioning"),
onComplete(data) {
context.set("currentPlacement", data.placement);
}
});
},
scrollToHighlightedItems({ context, prop, scope }) {
let cleanups = [];
const exec = (immediate) => {
const highlightedValue = context.get("highlightedValue");
const highlightedIndexPath = context.get("highlightedIndexPath");
if (!highlightedIndexPath.length) return;
if (getInteractionModality() === "pointer") return;
dom.getListEls(scope).forEach((listEl, index) => {
const itemPath = highlightedIndexPath.slice(0, index + 1);
const itemEl = dom.getItemEl(scope, highlightedValue.toString());
const scrollToIndexFn = prop("scrollToIndexFn");
if (scrollToIndexFn) {
const itemIndexInList = itemPath[itemPath.length - 1];
scrollToIndexFn({
index: itemIndexInList,
immediate,
depth: index
});
return;
}
const raf_cleanup = raf(() => {
scrollIntoView(itemEl, {
rootEl: listEl,
block: "nearest"
});
});
cleanups.push(raf_cleanup);
});
};
raf(() => {
setInteractionModality("virtual");
exec(true);
});
const rafCleanup = raf(() => exec(true));
cleanups.push(rafCleanup);
const observerCleanup = observeAttributes(dom.getContentEl(scope), {
attributes: ["data-activedescendant"],
callback: () => exec(false)
});
cleanups.push(observerCleanup);
return () => {
cleanups.forEach((cleanup) => cleanup());
};
}
},
actions: {
setValue(params) {
set.value(params, params.event.value);
},
clearValue(params) {
set.value(params, []);
},
setHighlightedValue(params) {
const { event } = params;
set.highlightedValue(params, event.value);
},
clearHighlightedValue(params) {
set.highlightedValue(params, []);
},
reposition({ context, prop, scope, event }) {
const positionerEl = () => dom.getPositionerEl(scope);
getPlacement(dom.getTriggerEl(scope), positionerEl, {
...prop("positioning"),
...event.options,
defer: true,
listeners: false,
onComplete(data) {
context.set("currentPlacement", data.placement);
}
});
},
selectItem(params) {
const { context, prop, event } = params;
const collection = prop("collection");
const multiple = prop("multiple");
const value = context.get("value");
const itemValue = event.value;
const indexPath = event.indexPath ?? collection.getIndexPath(itemValue);
const node = collection.at(indexPath);
const hasChildren = collection.isBranchNode(node);
if (prop("allowParentSelection")) {
if (multiple) {
const filteredValue = value.filter((v) => {
const shortPath = v.length < itemValue.length ? v : itemValue;
return !(v.length < itemValue.length ? itemValue : v).slice(0, shortPath.length).every((val, i) => val === shortPath[i]) && !isEqual(v, itemValue);
});
set.value(params, [...filteredValue, itemValue]);
} else set.value(params, [itemValue]);
if (hasChildren) set.highlightedValue(params, itemValue);
} else if (hasChildren) {
if (multiple && value.length > 0) set.value(params, [...value.slice(0, -1), itemValue]);
else set.value(params, [itemValue]);
set.highlightedValue(params, itemValue);
} else if (multiple) {
const existingIndex = value.findIndex((path) => isEqual(path, itemValue));
if (existingIndex >= 0) {
const newValues = [...value];
newValues.splice(existingIndex, 1);
set.value(params, newValues);
} else set.value(params, [...value, itemValue]);
} else set.value(params, [itemValue]);
},
clearItem(params) {
const { context, event } = params;
const newValue = context.get("value").filter((v) => !isEqual(v, event.value));
set.value(params, newValue);
},
selectHighlightedItem({ context, send }) {
const indexPath = context.get("highlightedIndexPath");
const value = context.get("highlightedValue");
if (value) send({
type: "ITEM.SELECT",
value,
indexPath
});
},
highlightFirstItem(params) {
const { context, prop } = params;
const collection = prop("collection");
const highlightedValue = context.get("highlightedValue");
let parentNode;
if (!highlightedValue.length) parentNode = collection.rootNode;
else {
const indexPath = context.get("highlightedIndexPath");
parentNode = collection.getParentNode(indexPath) ?? collection.rootNode;
}
const firstChild = collection.getNodeChildren(parentNode).find((child) => !collection.getNodeDisabled(child));
if (!firstChild) return;
const firstValue = collection.getNodeValue(firstChild);
if (!highlightedValue.length) set.highlightedValue(params, [firstValue]);
else {
const parentPath = highlightedValue.slice(0, -1);
set.highlightedValue(params, [...parentPath, firstValue]);
}
},
highlightLastItem(params) {
const { context, prop } = params;
const collection = prop("collection");
const highlightedValue = context.get("highlightedValue");
let parentNode;
if (!highlightedValue.length) parentNode = collection.rootNode;
else {
const indexPath = context.get("highlightedIndexPath");
parentNode = collection.getParentNode(indexPath) ?? collection.rootNode;
}
const lastChild = collection.getNodeChildren(parentNode).findLast((child) => !collection.getNodeDisabled(child));
if (!lastChild) return;
const lastValue = collection.getNodeValue(lastChild);
if (!highlightedValue.length) set.highlightedValue(params, [lastValue]);
else {
const parentPath = highlightedValue.slice(0, -1);
set.highlightedValue(params, [...parentPath, lastValue]);
}
},
highlightNextItem(params) {
const { context, prop } = params;
const collection = prop("collection");
const highlightedValue = context.get("highlightedValue");
if (!highlightedValue.length) return;
const indexPath = context.get("highlightedIndexPath");
const nextSibling = collection.getNextSibling(indexPath);
if (!nextSibling) return;
const nextValue = collection.getNodeValue(nextSibling);
if (highlightedValue.length === 1) set.highlightedValue(params, [nextValue]);
else {
const parentPath = highlightedValue.slice(0, -1);
set.highlightedValue(params, [...parentPath, nextValue]);
}
},
highlightPreviousItem(params) {
const { context, prop } = params;
const collection = prop("collection");
const highlightedValue = context.get("highlightedValue");
if (!highlightedValue.length) return;
const indexPath = context.get("highlightedIndexPath");
const previousSibling = collection.getPreviousSibling(indexPath);
if (!previousSibling) return;
const prevValue = collection.getNodeValue(previousSibling);
if (highlightedValue.length === 1) set.highlightedValue(params, [prevValue]);
else {
const parentPath = highlightedValue.slice(0, -1);
set.highlightedValue(params, [...parentPath, prevValue]);
}
},
highlightFirstChild(params) {
const { context, prop } = params;
const collection = prop("collection");
const highlightedValue = context.get("highlightedValue");
if (!highlightedValue.length) return;
const indexPath = context.get("highlightedIndexPath");
const node = collection.getFirstNode(collection.at(indexPath));
if (!node) return;
const childValue = collection.getNodeValue(node);
set.highlightedValue(params, [...highlightedValue, childValue]);
},
highlightParent(params) {
const { context } = params;
const highlightedValue = context.get("highlightedValue");
if (!highlightedValue.length) return;
const parentPath = highlightedValue.slice(0, -1);
set.highlightedValue(params, parentPath);
},
setInitialFocus({ scope }) {
raf(() => {
dom.getContentEl(scope)?.focus({ preventScroll: true });
});
},
focusTriggerEl({ event, scope }) {
if (!restoreFocusFn(event)) return;
raf(() => {
dom.getTriggerEl(scope)?.focus({ preventScroll: true });
});
},
invokeOnOpen({ prop, context }) {
prop("onOpenChange")?.({
open: true,
value: context.get("value")
});
},
invokeOnClose({ prop, context }) {
prop("onOpenChange")?.({
open: false,
value: context.get("value")
});
},
toggleVisibility({ send, prop }) {
if (prop("open") != null) send({ type: prop("open") ? "CONTROLLED.OPEN" : "CONTROLLED.CLOSE" });
},
highlightFirstSelectedItem(params) {
const { context } = params;
const value = context.get("value");
if (isEmpty(value)) return;
const mostRecentSelection = last(value);
if (mostRecentSelection) set.highlightedValue(params, mostRecentSelection);
},
createGraceArea({ context, event, scope }) {
const value = event.value.toString();
const triggerElement = dom.getItemEl(scope, value);
if (!triggerElement) return;
const exitPoint = {
x: event.clientX,
y: event.clientY
};
const triggerRect = triggerElement.getBoundingClientRect();
const nextLevelEl = dom.getListEl(scope, value);
if (!nextLevelEl) return;
const graceArea = createGraceArea(exitPoint, triggerRect, nextLevelEl.getBoundingClientRect());
context.set("graceArea", graceArea);
setTimeout(() => {
context.set("graceArea", null);
}, 300);
},
clearGraceArea({ context }) {
context.set("graceArea", null);
},
setHighlightingForHoveredItem(params) {
const { prop, event } = params;
const collection = prop("collection");
const node = collection.at(event.indexPath);
let newHighlightedValue;
if (node && collection.isBranchNode(node)) newHighlightedValue = event.value;
else newHighlightedValue = event.value.slice(0, -1);
set.highlightedValue(params, newHighlightedValue);
},
syncInputValue({ context, scope }) {
const inputEl = dom.getHiddenInputEl(scope);
if (!inputEl) return;
setElementValue(inputEl, context.hash("value"));
},
dispatchChangeEvent({ scope, context }) {
dispatchInputValueEvent(dom.getHiddenInputEl(scope), { value: context.hash("value") });
},
scrollContentToTop({ scope, prop }) {
const scrollToIndexFn = prop("scrollToIndexFn");
raf(() => {
(dom.getContentEl(scope)?.querySelectorAll("[data-part=\"list\"]"))?.forEach((listEl, index) => {
if (scrollToIndexFn) scrollToIndexFn({
index: 0,
immediate: true,
depth: index
});
else listEl.scrollTop = 0;
});
});
}
}
}
});
const set = {
value({ context, prop }, value) {
const collection = prop("collection");
context.set("value", value);
const valueIndexPath = value.map((v) => collection.getIndexPath(v));
context.set("valueIndexPath", valueIndexPath);
const selectedItems = valueIndexPath.map((indexPath) => {
return indexPath.map((_, index) => {
const partialPath = indexPath.slice(0, index + 1);
return collection.at(partialPath);
});
});
context.set("selectedItems", selectedItems);
prop("onValueChange")?.({
value,
items: selectedItems
});
},
highlightedValue({ context, prop }, value) {
const collection = prop("collection");
context.set("highlightedValue", value);
const highlightedIndexPath = (value == null ? [] : collection.getIndexPath(value)) ?? [];
context.set("highlightedIndexPath", highlightedIndexPath);
const highlightedItems = highlightedIndexPath.map((_, index) => {
const partialPath = highlightedIndexPath.slice(0, index + 1);
return collection.at(partialPath);
});
context.set("highlightedItems", highlightedItems);
prop("onHighlightChange")?.({
highlightedValue: value,
highlightedItems
});
}
};
function restoreFocusFn(event) {
const v = event.restoreFocus ?? event.previousEvent?.restoreFocus;
return v == null || !!v;
}
//#endregion
//#region src/machines/cascade-select/cascade-select.props.ts
const props = createProps()([
"allowParentSelection",
"closeOnSelect",
"collection",
"defaultOpen",
"defaultValue",
"defaultHighlightedValue",
"dir",
"disabled",
"formatValue",
"form",
"getRootNode",
"highlightedValue",
"highlightTrigger",
"id",
"ids",
"invalid",
"loopFocus",
"multiple",
"name",
"onFocusOutside",
"onHighlightChange",
"onInteractOutside",
"onOpenChange",
"onPointerDownOutside",
"onValueChange",
"open",
"positioning",
"readOnly",
"required",
"scrollToIndexFn",
"value"
]);
const splitProps = createSplitProps(props);
//#endregion
export { anatomy, collection, connect, machine, parts, props, splitProps };
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_create_anatomy = require("../../create-anatomy-CpViYTjA.cjs");
const require_dom_query = require("../../dom-query-BT6fffRP.cjs");
const require_core = require("../../core-DH_mBI7F.cjs");
const require_rect = require("../../rect-CmICnPlW.cjs");
const require_create_props = require("../../create-props-MMZJXgtK.cjs");
let _ginxjs_core_utils = require("@ginxjs/core/utils");
//#region src/machines/knob/knob.anatomy.ts
const anatomy = require_create_anatomy.createAnatomy("knob").parts("root", "label", "thumb", "valueText", "control", "track", "markerGroup", "marker");
const parts = anatomy.build();
//#endregion
//#region src/machines/knob/knob.dom.ts
const getRootId = (ctx) => ctx.ids?.root ?? `knob:${ctx.id}`;
const getThumbId = (ctx) => ctx.ids?.thumb ?? `knob:${ctx.id}:thumb`;
const getHiddenInputId = (ctx) => ctx.ids?.hiddenInput ?? `knob:${ctx.id}:input`;
const getControlId = (ctx) => ctx.ids?.control ?? `knob:${ctx.id}:control`;
const getValueTextId = (ctx) => ctx.ids?.valueText ?? `knob:${ctx.id}:value-text`;
const getLabelId = (ctx) => ctx.ids?.label ?? `knob:${ctx.id}:label`;
const getHiddenInputEl = (ctx) => ctx.getById(getHiddenInputId(ctx));
const getControlEl = (ctx) => ctx.getById(getControlId(ctx));
const getThumbEl = (ctx) => ctx.getById(getThumbId(ctx));
function mirrorAngle(angle) {
return (360 - angle) % 360;
}
function getAngle(controlEl, point, angularOffset, dir) {
let angle = require_rect.getPointAngle(require_rect.createRect(controlEl.getBoundingClientRect()), point);
if (angularOffset != null) return angle - angularOffset;
if (dir === "rtl") angle = mirrorAngle(angle);
return angle;
}
function getPointerValue(controlEl, point, angularOffset, value, dir) {
if (angularOffset == null) return getAngle(controlEl, point, null, dir);
const angle = getAngle(controlEl, point);
const clickAngle = value + angularOffset;
return dir === "rtl" ? value + clickAngle - angle : angle - angularOffset;
}
function getDisplayAngle(value, dir) {
return dir === "rtl" ? mirrorAngle(value) : value;
}
function clampAngle(degree) {
return Math.min(Math.max(degree, 0), 359);
}
function constrainAngle(degree, step) {
const clampedDegree = clampAngle(degree);
const upperStep = Math.ceil(clampedDegree / step);
const nearestStep = Math.round(clampedDegree / step);
return upperStep >= clampedDegree / step ? upperStep * step === 359 ? 0 : upperStep * step : nearestStep * step;
}
function snapAngleToStep(value, step) {
return (0, _ginxjs_core_utils.snapValueToStep)(value, 0, 359, step);
}
//#endregion
//#region src/machines/knob/knob.connect.ts
function connect(service, normalize) {
const { state, send, context, prop, computed, scope } = service;
const dragging = state.matches("dragging");
const value = context.get("value");
const valueAsDegree = computed("valueAsDegree");
const dir = prop("dir");
const displayAngle = getDisplayAngle(value, dir);
const disabled = prop("disabled");
const invalid = prop("invalid");
const readOnly = prop("readOnly");
const interactive = computed("interactive");
const ariaLabel = prop("aria-label");
const ariaLabelledBy = prop("aria-labelledby");
return {
value,
valueAsDegree,
dragging,
setValue(value) {
send({
type: "VALUE.SET",
value
});
},
getRootProps() {
return normalize.element({
...parts.root.attrs,
id: getRootId(scope),
dir: prop("dir"),
"data-disabled": require_dom_query.dataAttr(disabled),
"data-invalid": require_dom_query.dataAttr(invalid),
"data-readonly": require_dom_query.dataAttr(readOnly),
style: {
"--value": value,
"--angle": `${displayAngle}deg`
}
});
},
getLabelProps() {
return normalize.label({
...parts.label.attrs,
id: getLabelId(scope),
htmlFor: getHiddenInputId(scope),
dir: prop("dir"),
"data-disabled": require_dom_query.dataAttr(disabled),
"data-invalid": require_dom_query.dataAttr(invalid),
"data-readonly": require_dom_query.dataAttr(readOnly),
onClick(event) {
if (!interactive) return;
event.preventDefault();
getThumbEl(scope)?.focus();
}
});
},
getHiddenInputProps() {
return normalize.element({
type: "hidden",
value,
name: prop("name"),
id: getHiddenInputId(scope),
dir: prop("dir")
});
},
getControlProps() {
return normalize.element({
...parts.control.attrs,
role: "presentation",
id: getControlId(scope),
dir: prop("dir"),
"data-disabled": require_dom_query.dataAttr(disabled),
"data-invalid": require_dom_query.dataAttr(invalid),
"data-readonly": require_dom_query.dataAttr(readOnly),
onPointerDown(event) {
if (!interactive) return;
if (!require_dom_query.isLeftClick(event)) return;
const point = require_dom_query.getEventPoint(event);
const controlEl = event.currentTarget;
const thumbEl = getThumbEl(scope);
const composedPath = require_dom_query.getNativeEvent(event).composedPath();
const isOverThumb = thumbEl && composedPath.includes(thumbEl);
let angularOffset = null;
if (isOverThumb) angularOffset = getAngle(controlEl, point) - value;
send({
type: "CONTROL.POINTER_DOWN",
point,
angularOffset
});
event.stopPropagation();
},
style: {
touchAction: "none",
userSelect: "none",
WebkitUserSelect: "none"
}
});
},
getThumbProps() {
return normalize.element({
...parts.thumb.attrs,
id: getThumbId(scope),
role: "slider",
dir: prop("dir"),
"aria-label": ariaLabel,
"aria-labelledby": ariaLabelledBy ?? getLabelId(scope),
"aria-valuemax": 360,
"aria-valuemin": 0,
"aria-valuenow": value,
tabIndex: readOnly || interactive ? 0 : void 0,
"data-disabled": require_dom_query.dataAttr(disabled),
"data-invalid": require_dom_query.dataAttr(invalid),
"data-readonly": require_dom_query.dataAttr(readOnly),
onFocus() {
send({ type: "THUMB.FOCUS" });
},
onBlur() {
send({ type: "THUMB.BLUR" });
},
onKeyDown(event) {
if (!interactive) return;
const step = require_dom_query.getEventStep(event) * prop("step");
const exec = {
ArrowLeft() {
send({
type: "THUMB.ARROW_DEC",
step
});
},
ArrowUp() {
send({
type: "THUMB.ARROW_DEC",
step
});
},
ArrowRight() {
send({
type: "THUMB.ARROW_INC",
step
});
},
ArrowDown() {
send({
type: "THUMB.ARROW_INC",
step
});
},
Home() {
send({ type: "THUMB.HOME" });
},
End() {
send({ type: "THUMB.END" });
}
}[require_dom_query.getEventKey(event, {
dir: prop("dir"),
orientation: "horizontal"
})];
if (exec) {
exec(event);
event.preventDefault();
}
},
style: { rotate: `var(--angle)` }
});
},
getValueTextProps() {
return normalize.element({
...parts.valueText.attrs,
id: getValueTextId(scope),
dir: prop("dir")
});
},
getMarkerGroupProps() {
return normalize.element({
...parts.markerGroup.attrs,
dir: prop("dir")
});
},
getMarkerProps(props) {
let markerState;
if (props.value < value) markerState = "under-value";
else if (props.value > value) markerState = "over-value";
else markerState = "at-value";
const markerDisplayAngle = getDisplayAngle(props.value, dir);
return normalize.element({
...parts.marker.attrs,
dir: prop("dir"),
"data-value": props.value,
"data-state": markerState,
"data-disabled": require_dom_query.dataAttr(disabled),
style: {
"--marker-value": props.value,
"--marker-display-value": markerDisplayAngle,
rotate: `calc(var(--marker-display-value) * 1deg)`
}
});
}
};
}
//#endregion
//#region src/machines/knob/knob.machine.ts
const machine = require_core.createMachine({
props({ props }) {
return {
step: 1,
defaultValue: 0,
...props
};
},
context({ prop, bindable }) {
return { value: bindable(() => ({
defaultValue: prop("defaultValue"),
value: prop("value"),
onChange(value) {
prop("onValueChange")?.({
value,
valueAsDegree: `${value}deg`
});
}
})) };
},
refs() {
return { thumbDragOffset: null };
},
computed: {
interactive: ({ prop }) => !(prop("disabled") || prop("readOnly")),
valueAsDegree: ({ context }) => `${context.get("value")}deg`
},
watch({ track, context, action }) {
track([() => context.get("value")], () => {
action(["syncInputElement"]);
});
},
initialState() {
return "idle";
},
on: { "VALUE.SET": { actions: ["setValue"] } },
states: {
idle: { on: {
"CONTROL.POINTER_DOWN": {
target: "dragging",
actions: [
"setThumbDragOffset",
"setPointerValue",
"focusThumb"
]
},
"THUMB.FOCUS": { target: "focused" }
} },
focused: { on: {
"CONTROL.POINTER_DOWN": {
target: "dragging",
actions: [
"setThumbDragOffset",
"setPointerValue",
"focusThumb"
]
},
"THUMB.ARROW_DEC": { actions: ["decrementValue", "invokeOnChangeEnd"] },
"THUMB.ARROW_INC": { actions: ["incrementValue", "invokeOnChangeEnd"] },
"THUMB.HOME": { actions: ["setValueToMin", "invokeOnChangeEnd"] },
"THUMB.END": { actions: ["setValueToMax", "invokeOnChangeEnd"] },
"THUMB.BLUR": { target: "idle" }
} },
dragging: {
entry: ["focusThumb"],
effects: ["trackPointerMove"],
on: {
"DOC.POINTER_UP": {
target: "focused",
actions: ["invokeOnChangeEnd", "clearThumbDragOffset"]
},
"DOC.POINTER_MOVE": { actions: ["setPointerValue"] }
}
}
},
implementations: {
effects: { trackPointerMove({ scope, send }) {
return require_dom_query.trackPointerMove(scope.getDoc(), {
onPointerMove(info) {
send({
type: "DOC.POINTER_MOVE",
point: info.point
});
},
onPointerUp() {
send({ type: "DOC.POINTER_UP" });
}
});
} },
actions: {
syncInputElement({ scope, context }) {
require_dom_query.setElementValue(getHiddenInputEl(scope), context.get("value").toString());
},
invokeOnChangeEnd({ context, prop, computed }) {
prop("onValueChangeEnd")?.({
value: context.get("value"),
valueAsDegree: computed("valueAsDegree")
});
},
setPointerValue({ scope, event, context, prop, refs }) {
const controlEl = getControlEl(scope);
if (!controlEl) return;
const angularOffset = refs.get("thumbDragOffset");
const value = context.get("value");
const deg = getPointerValue(controlEl, event.point, angularOffset, value, prop("dir"));
context.set("value", constrainAngle(deg, prop("step")));
},
setValueToMin({ context }) {
context.set("value", 0);
},
setValueToMax({ context }) {
context.set("value", 359);
},
setValue({ context, event }) {
context.set("value", clampAngle(event.value));
},
decrementValue({ context, event, prop }) {
const value = snapAngleToStep(context.get("value") - event.step, event.step ?? prop("step"));
context.set("value", value);
},
incrementValue({ context, event, prop }) {
const value = snapAngleToStep(context.get("value") + event.step, event.step ?? prop("step"));
context.set("value", value);
},
focusThumb({ scope }) {
require_dom_query.raf(() => {
getThumbEl(scope)?.focus({ preventScroll: true });
});
},
setThumbDragOffset({ refs, event }) {
refs.set("thumbDragOffset", event.angularOffset ?? null);
},
clearThumbDragOffset({ refs }) {
refs.set("thumbDragOffset", null);
}
}
}
});
//#endregion
//#region src/machines/knob/knob.props.ts
const props = require_create_props.createProps()([
"aria-label",
"aria-labelledby",
"dir",
"disabled",
"getRootNode",
"id",
"ids",
"invalid",
"name",
"onValueChange",
"onValueChangeEnd",
"readOnly",
"step",
"value",
"defaultValue"
]);
const splitProps = (0, _ginxjs_core_utils.createSplitProps)(props);
//#endregion
exports.anatomy = anatomy;
exports.connect = connect;
exports.machine = machine;
exports.props = props;
exports.splitProps = splitProps;
import { n as AnatomyInstance } from "../../anatomy-DFl8j10C.cjs";
import { b as NormalizeProps, g as RequiredBy, r as DirectionProperty, t as CommonProperties, x as PropTypes } from "../../index-DFJGBSAc.cjs";
import { M as Service, S as EventObject, T as Machine } from "../../index-BNaxg4iu.cjs";
//#region src/machines/knob/knob.anatomy.d.ts
declare const anatomy: AnatomyInstance<"root" | "control" | "track" | "label" | "marker" | "thumb" | "valueText" | "markerGroup">;
//#endregion
//#region src/machines/knob/knob.types.d.ts
interface ValueChangeDetails {
value: number;
valueAsDegree: string;
}
type ElementIds = Partial<{
root: string;
thumb: string;
hiddenInput: string;
control: string;
valueText: string;
label: string;
}>;
interface AngleSliderProps extends DirectionProperty, CommonProperties {
ids?: ElementIds | undefined;
step?: number | undefined;
value?: number | undefined;
defaultValue?: number | undefined;
onValueChange?: ((details: ValueChangeDetails) => void) | undefined;
onValueChangeEnd?: ((details: ValueChangeDetails) => void) | undefined;
disabled?: boolean | undefined;
readOnly?: boolean | undefined;
invalid?: boolean | undefined;
name?: string | undefined;
"aria-label"?: string | undefined;
"aria-labelledby"?: string | undefined;
}
type PropsWithDefault = "step" | "defaultValue";
interface AngleSliderSchema {
state: "idle" | "focused" | "dragging";
props: RequiredBy<AngleSliderProps, PropsWithDefault>;
computed: {
interactive: boolean;
valueAsDegree: string;
};
context: {
value: number;
};
refs: {
thumbDragOffset: number | null;
};
action: string;
event: EventObject;
effect: string;
guard: string;
}
type AngleSliderService = Service<AngleSliderSchema>;
type AngleSliderMachine = Machine<AngleSliderSchema>;
interface MarkerProps {
value: number;
}
interface AngleSliderApi<T extends PropTypes = PropTypes> {
value: number;
valueAsDegree: string;
setValue: (value: number) => void;
dragging: boolean;
getRootProps: () => T["element"];
getLabelProps: () => T["label"];
getHiddenInputProps: () => T["element"];
getControlProps: () => T["element"];
getThumbProps: () => T["element"];
getValueTextProps: () => T["element"];
getMarkerGroupProps: () => T["element"];
getMarkerProps: (props: MarkerProps) => T["element"];
}
//#endregion
//#region src/machines/knob/knob.connect.d.ts
declare function connect<T extends PropTypes>(service: AngleSliderService, normalize: NormalizeProps<T>): AngleSliderApi<T>;
//#endregion
//#region src/machines/knob/knob.machine.d.ts
declare const machine: Machine<AngleSliderSchema>;
//#endregion
//#region src/machines/knob/knob.props.d.ts
declare const props: (keyof AngleSliderProps)[];
declare const splitProps: <Props extends Partial<AngleSliderProps>>(props: Props) => [Partial<AngleSliderProps>, Omit<Props, keyof AngleSliderProps>];
//#endregion
export { type AngleSliderApi as Api, type ElementIds, type AngleSliderMachine as Machine, type MarkerProps, type AngleSliderProps as Props, type AngleSliderService as Service, type ValueChangeDetails, anatomy, connect, machine, props, splitProps };
import { n as AnatomyInstance } from "../../anatomy-C9pDRrRN.mjs";
import { b as NormalizeProps, g as RequiredBy, r as DirectionProperty, t as CommonProperties, x as PropTypes } from "../../index-Cq2OwLf_.mjs";
import { M as Service, S as EventObject, T as Machine } from "../../index-g2S6NCuN.mjs";
//#region src/machines/knob/knob.anatomy.d.ts
declare const anatomy: AnatomyInstance<"root" | "control" | "track" | "label" | "marker" | "thumb" | "valueText" | "markerGroup">;
//#endregion
//#region src/machines/knob/knob.types.d.ts
interface ValueChangeDetails {
value: number;
valueAsDegree: string;
}
type ElementIds = Partial<{
root: string;
thumb: string;
hiddenInput: string;
control: string;
valueText: string;
label: string;
}>;
interface AngleSliderProps extends DirectionProperty, CommonProperties {
ids?: ElementIds | undefined;
step?: number | undefined;
value?: number | undefined;
defaultValue?: number | undefined;
onValueChange?: ((details: ValueChangeDetails) => void) | undefined;
onValueChangeEnd?: ((details: ValueChangeDetails) => void) | undefined;
disabled?: boolean | undefined;
readOnly?: boolean | undefined;
invalid?: boolean | undefined;
name?: string | undefined;
"aria-label"?: string | undefined;
"aria-labelledby"?: string | undefined;
}
type PropsWithDefault = "step" | "defaultValue";
interface AngleSliderSchema {
state: "idle" | "focused" | "dragging";
props: RequiredBy<AngleSliderProps, PropsWithDefault>;
computed: {
interactive: boolean;
valueAsDegree: string;
};
context: {
value: number;
};
refs: {
thumbDragOffset: number | null;
};
action: string;
event: EventObject;
effect: string;
guard: string;
}
type AngleSliderService = Service<AngleSliderSchema>;
type AngleSliderMachine = Machine<AngleSliderSchema>;
interface MarkerProps {
value: number;
}
interface AngleSliderApi<T extends PropTypes = PropTypes> {
value: number;
valueAsDegree: string;
setValue: (value: number) => void;
dragging: boolean;
getRootProps: () => T["element"];
getLabelProps: () => T["label"];
getHiddenInputProps: () => T["element"];
getControlProps: () => T["element"];
getThumbProps: () => T["element"];
getValueTextProps: () => T["element"];
getMarkerGroupProps: () => T["element"];
getMarkerProps: (props: MarkerProps) => T["element"];
}
//#endregion
//#region src/machines/knob/knob.connect.d.ts
declare function connect<T extends PropTypes>(service: AngleSliderService, normalize: NormalizeProps<T>): AngleSliderApi<T>;
//#endregion
//#region src/machines/knob/knob.machine.d.ts
declare const machine: Machine<AngleSliderSchema>;
//#endregion
//#region src/machines/knob/knob.props.d.ts
declare const props: (keyof AngleSliderProps)[];
declare const splitProps: <Props extends Partial<AngleSliderProps>>(props: Props) => [Partial<AngleSliderProps>, Omit<Props, keyof AngleSliderProps>];
//#endregion
export { type AngleSliderApi as Api, type ElementIds, type AngleSliderMachine as Machine, type MarkerProps, type AngleSliderProps as Props, type AngleSliderService as Service, type ValueChangeDetails, anatomy, connect, machine, props, splitProps };
import { t as createAnatomy } from "../../create-anatomy-tqxVmw3d.mjs";
import { Ct as isLeftClick, D as trackPointerMove, G as raf, Tn as dataAttr, _t as getNativeEvent, ht as getEventStep, lt as setElementValue, mt as getEventPoint, pt as getEventKey } from "../../dom-query-BgxIO7_X.mjs";
import { a as createMachine } from "../../core-D3PQ0tSv.mjs";
import { R as createRect, q as getPointAngle } from "../../rect-JcwJCZkp.mjs";
import { t as createProps } from "../../create-props-Bi7oeFLF.mjs";
import { createSplitProps, snapValueToStep } from "@ginxjs/core/utils";
//#region src/machines/knob/knob.anatomy.ts
const anatomy = createAnatomy("knob").parts("root", "label", "thumb", "valueText", "control", "track", "markerGroup", "marker");
const parts = anatomy.build();
//#endregion
//#region src/machines/knob/knob.dom.ts
const getRootId = (ctx) => ctx.ids?.root ?? `knob:${ctx.id}`;
const getThumbId = (ctx) => ctx.ids?.thumb ?? `knob:${ctx.id}:thumb`;
const getHiddenInputId = (ctx) => ctx.ids?.hiddenInput ?? `knob:${ctx.id}:input`;
const getControlId = (ctx) => ctx.ids?.control ?? `knob:${ctx.id}:control`;
const getValueTextId = (ctx) => ctx.ids?.valueText ?? `knob:${ctx.id}:value-text`;
const getLabelId = (ctx) => ctx.ids?.label ?? `knob:${ctx.id}:label`;
const getHiddenInputEl = (ctx) => ctx.getById(getHiddenInputId(ctx));
const getControlEl = (ctx) => ctx.getById(getControlId(ctx));
const getThumbEl = (ctx) => ctx.getById(getThumbId(ctx));
function mirrorAngle(angle) {
return (360 - angle) % 360;
}
function getAngle(controlEl, point, angularOffset, dir) {
let angle = getPointAngle(createRect(controlEl.getBoundingClientRect()), point);
if (angularOffset != null) return angle - angularOffset;
if (dir === "rtl") angle = mirrorAngle(angle);
return angle;
}
function getPointerValue(controlEl, point, angularOffset, value, dir) {
if (angularOffset == null) return getAngle(controlEl, point, null, dir);
const angle = getAngle(controlEl, point);
const clickAngle = value + angularOffset;
return dir === "rtl" ? value + clickAngle - angle : angle - angularOffset;
}
function getDisplayAngle(value, dir) {
return dir === "rtl" ? mirrorAngle(value) : value;
}
function clampAngle(degree) {
return Math.min(Math.max(degree, 0), 359);
}
function constrainAngle(degree, step) {
const clampedDegree = clampAngle(degree);
const upperStep = Math.ceil(clampedDegree / step);
const nearestStep = Math.round(clampedDegree / step);
return upperStep >= clampedDegree / step ? upperStep * step === 359 ? 0 : upperStep * step : nearestStep * step;
}
function snapAngleToStep(value, step) {
return snapValueToStep(value, 0, 359, step);
}
//#endregion
//#region src/machines/knob/knob.connect.ts
function connect(service, normalize) {
const { state, send, context, prop, computed, scope } = service;
const dragging = state.matches("dragging");
const value = context.get("value");
const valueAsDegree = computed("valueAsDegree");
const dir = prop("dir");
const displayAngle = getDisplayAngle(value, dir);
const disabled = prop("disabled");
const invalid = prop("invalid");
const readOnly = prop("readOnly");
const interactive = computed("interactive");
const ariaLabel = prop("aria-label");
const ariaLabelledBy = prop("aria-labelledby");
return {
value,
valueAsDegree,
dragging,
setValue(value) {
send({
type: "VALUE.SET",
value
});
},
getRootProps() {
return normalize.element({
...parts.root.attrs,
id: getRootId(scope),
dir: prop("dir"),
"data-disabled": dataAttr(disabled),
"data-invalid": dataAttr(invalid),
"data-readonly": dataAttr(readOnly),
style: {
"--value": value,
"--angle": `${displayAngle}deg`
}
});
},
getLabelProps() {
return normalize.label({
...parts.label.attrs,
id: getLabelId(scope),
htmlFor: getHiddenInputId(scope),
dir: prop("dir"),
"data-disabled": dataAttr(disabled),
"data-invalid": dataAttr(invalid),
"data-readonly": dataAttr(readOnly),
onClick(event) {
if (!interactive) return;
event.preventDefault();
getThumbEl(scope)?.focus();
}
});
},
getHiddenInputProps() {
return normalize.element({
type: "hidden",
value,
name: prop("name"),
id: getHiddenInputId(scope),
dir: prop("dir")
});
},
getControlProps() {
return normalize.element({
...parts.control.attrs,
role: "presentation",
id: getControlId(scope),
dir: prop("dir"),
"data-disabled": dataAttr(disabled),
"data-invalid": dataAttr(invalid),
"data-readonly": dataAttr(readOnly),
onPointerDown(event) {
if (!interactive) return;
if (!isLeftClick(event)) return;
const point = getEventPoint(event);
const controlEl = event.currentTarget;
const thumbEl = getThumbEl(scope);
const composedPath = getNativeEvent(event).composedPath();
const isOverThumb = thumbEl && composedPath.includes(thumbEl);
let angularOffset = null;
if (isOverThumb) angularOffset = getAngle(controlEl, point) - value;
send({
type: "CONTROL.POINTER_DOWN",
point,
angularOffset
});
event.stopPropagation();
},
style: {
touchAction: "none",
userSelect: "none",
WebkitUserSelect: "none"
}
});
},
getThumbProps() {
return normalize.element({
...parts.thumb.attrs,
id: getThumbId(scope),
role: "slider",
dir: prop("dir"),
"aria-label": ariaLabel,
"aria-labelledby": ariaLabelledBy ?? getLabelId(scope),
"aria-valuemax": 360,
"aria-valuemin": 0,
"aria-valuenow": value,
tabIndex: readOnly || interactive ? 0 : void 0,
"data-disabled": dataAttr(disabled),
"data-invalid": dataAttr(invalid),
"data-readonly": dataAttr(readOnly),
onFocus() {
send({ type: "THUMB.FOCUS" });
},
onBlur() {
send({ type: "THUMB.BLUR" });
},
onKeyDown(event) {
if (!interactive) return;
const step = getEventStep(event) * prop("step");
const exec = {
ArrowLeft() {
send({
type: "THUMB.ARROW_DEC",
step
});
},
ArrowUp() {
send({
type: "THUMB.ARROW_DEC",
step
});
},
ArrowRight() {
send({
type: "THUMB.ARROW_INC",
step
});
},
ArrowDown() {
send({
type: "THUMB.ARROW_INC",
step
});
},
Home() {
send({ type: "THUMB.HOME" });
},
End() {
send({ type: "THUMB.END" });
}
}[getEventKey(event, {
dir: prop("dir"),
orientation: "horizontal"
})];
if (exec) {
exec(event);
event.preventDefault();
}
},
style: { rotate: `var(--angle)` }
});
},
getValueTextProps() {
return normalize.element({
...parts.valueText.attrs,
id: getValueTextId(scope),
dir: prop("dir")
});
},
getMarkerGroupProps() {
return normalize.element({
...parts.markerGroup.attrs,
dir: prop("dir")
});
},
getMarkerProps(props) {
let markerState;
if (props.value < value) markerState = "under-value";
else if (props.value > value) markerState = "over-value";
else markerState = "at-value";
const markerDisplayAngle = getDisplayAngle(props.value, dir);
return normalize.element({
...parts.marker.attrs,
dir: prop("dir"),
"data-value": props.value,
"data-state": markerState,
"data-disabled": dataAttr(disabled),
style: {
"--marker-value": props.value,
"--marker-display-value": markerDisplayAngle,
rotate: `calc(var(--marker-display-value) * 1deg)`
}
});
}
};
}
//#endregion
//#region src/machines/knob/knob.machine.ts
const machine = createMachine({
props({ props }) {
return {
step: 1,
defaultValue: 0,
...props
};
},
context({ prop, bindable }) {
return { value: bindable(() => ({
defaultValue: prop("defaultValue"),
value: prop("value"),
onChange(value) {
prop("onValueChange")?.({
value,
valueAsDegree: `${value}deg`
});
}
})) };
},
refs() {
return { thumbDragOffset: null };
},
computed: {
interactive: ({ prop }) => !(prop("disabled") || prop("readOnly")),
valueAsDegree: ({ context }) => `${context.get("value")}deg`
},
watch({ track, context, action }) {
track([() => context.get("value")], () => {
action(["syncInputElement"]);
});
},
initialState() {
return "idle";
},
on: { "VALUE.SET": { actions: ["setValue"] } },
states: {
idle: { on: {
"CONTROL.POINTER_DOWN": {
target: "dragging",
actions: [
"setThumbDragOffset",
"setPointerValue",
"focusThumb"
]
},
"THUMB.FOCUS": { target: "focused" }
} },
focused: { on: {
"CONTROL.POINTER_DOWN": {
target: "dragging",
actions: [
"setThumbDragOffset",
"setPointerValue",
"focusThumb"
]
},
"THUMB.ARROW_DEC": { actions: ["decrementValue", "invokeOnChangeEnd"] },
"THUMB.ARROW_INC": { actions: ["incrementValue", "invokeOnChangeEnd"] },
"THUMB.HOME": { actions: ["setValueToMin", "invokeOnChangeEnd"] },
"THUMB.END": { actions: ["setValueToMax", "invokeOnChangeEnd"] },
"THUMB.BLUR": { target: "idle" }
} },
dragging: {
entry: ["focusThumb"],
effects: ["trackPointerMove"],
on: {
"DOC.POINTER_UP": {
target: "focused",
actions: ["invokeOnChangeEnd", "clearThumbDragOffset"]
},
"DOC.POINTER_MOVE": { actions: ["setPointerValue"] }
}
}
},
implementations: {
effects: { trackPointerMove({ scope, send }) {
return trackPointerMove(scope.getDoc(), {
onPointerMove(info) {
send({
type: "DOC.POINTER_MOVE",
point: info.point
});
},
onPointerUp() {
send({ type: "DOC.POINTER_UP" });
}
});
} },
actions: {
syncInputElement({ scope, context }) {
setElementValue(getHiddenInputEl(scope), context.get("value").toString());
},
invokeOnChangeEnd({ context, prop, computed }) {
prop("onValueChangeEnd")?.({
value: context.get("value"),
valueAsDegree: computed("valueAsDegree")
});
},
setPointerValue({ scope, event, context, prop, refs }) {
const controlEl = getControlEl(scope);
if (!controlEl) return;
const angularOffset = refs.get("thumbDragOffset");
const value = context.get("value");
const deg = getPointerValue(controlEl, event.point, angularOffset, value, prop("dir"));
context.set("value", constrainAngle(deg, prop("step")));
},
setValueToMin({ context }) {
context.set("value", 0);
},
setValueToMax({ context }) {
context.set("value", 359);
},
setValue({ context, event }) {
context.set("value", clampAngle(event.value));
},
decrementValue({ context, event, prop }) {
const value = snapAngleToStep(context.get("value") - event.step, event.step ?? prop("step"));
context.set("value", value);
},
incrementValue({ context, event, prop }) {
const value = snapAngleToStep(context.get("value") + event.step, event.step ?? prop("step"));
context.set("value", value);
},
focusThumb({ scope }) {
raf(() => {
getThumbEl(scope)?.focus({ preventScroll: true });
});
},
setThumbDragOffset({ refs, event }) {
refs.set("thumbDragOffset", event.angularOffset ?? null);
},
clearThumbDragOffset({ refs }) {
refs.set("thumbDragOffset", null);
}
}
}
});
//#endregion
//#region src/machines/knob/knob.props.ts
const props = createProps()([
"aria-label",
"aria-labelledby",
"dir",
"disabled",
"getRootNode",
"id",
"ids",
"invalid",
"name",
"onValueChange",
"onValueChangeEnd",
"readOnly",
"step",
"value",
"defaultValue"
]);
const splitProps = createSplitProps(props);
//#endregion
export { anatomy, connect, machine, props, splitProps };
const require_dom_query = require("./dom-query-BT6fffRP.cjs");
let _ginxjs_core_utils = require("@ginxjs/core/utils");
let _floating_ui_dom = require("@floating-ui/dom");
//#region src/shared/popper/get-anchor.ts
function createDOMRect(x = 0, y = 0, width = 0, height = 0) {
if (typeof DOMRect === "function") return new DOMRect(x, y, width, height);
const rect = {
x,
y,
width,
height,
top: y,
right: x + width,
bottom: y + height,
left: x
};
return {
...rect,
toJSON: () => rect
};
}
function getDOMRect(anchorRect) {
if (!anchorRect) return createDOMRect();
const { x, y, width, height } = anchorRect;
return createDOMRect(x, y, width, height);
}
function getAnchorElement(anchorElement, getAnchorRect) {
return {
contextElement: require_dom_query.isHTMLElement(anchorElement) ? anchorElement : anchorElement?.contextElement,
getBoundingClientRect: () => {
const anchor = anchorElement;
const anchorRect = getAnchorRect?.(anchor);
if (anchorRect || !anchor) return getDOMRect(anchorRect);
return anchor.getBoundingClientRect();
}
};
}
//#endregion
//#region src/shared/popper/middleware.ts
const toVar = (value) => ({
variable: value,
reference: `var(${value})`
});
const cssVars = {
arrowSize: toVar("--arrow-size"),
arrowSizeHalf: toVar("--arrow-size-half"),
arrowBg: toVar("--arrow-background"),
transformOrigin: toVar("--transform-origin"),
arrowOffset: toVar("--arrow-offset")
};
const getSideAxis = (side) => side === "top" || side === "bottom" ? "y" : "x";
function createTransformOriginMiddleware(opts, arrowEl) {
return {
name: "transformOrigin",
fn(state) {
const { elements, middlewareData, placement, rects, y } = state;
const side = placement.split("-")[0];
const axis = getSideAxis(side);
const arrowX = middlewareData.arrow?.x || 0;
const arrowY = middlewareData.arrow?.y || 0;
const arrowWidth = arrowEl?.clientWidth || 0;
const arrowHeight = arrowEl?.clientHeight || 0;
const transformX = arrowX + arrowWidth / 2;
const transformY = arrowY + arrowHeight / 2;
const shiftY = Math.abs(middlewareData.shift?.y || 0);
const halfAnchorHeight = rects.reference.height / 2;
const arrowOffset = arrowHeight / 2;
const gutter = opts.offset?.mainAxis ?? opts.gutter;
const sideOffsetValue = typeof gutter === "number" ? gutter + arrowOffset : gutter ?? arrowOffset;
const isOverlappingAnchor = shiftY > sideOffsetValue;
const adjacentTransformOrigin = {
top: `${transformX}px calc(100% + ${sideOffsetValue}px)`,
bottom: `${transformX}px ${-sideOffsetValue}px`,
left: `calc(100% + ${sideOffsetValue}px) ${transformY}px`,
right: `${-sideOffsetValue}px ${transformY}px`
}[side];
const overlapTransformOrigin = `${transformX}px ${rects.reference.y + halfAnchorHeight - y}px`;
const useOverlap = Boolean(opts.overlap) && axis === "y" && isOverlappingAnchor;
elements.floating.style.setProperty(cssVars.transformOrigin.variable, useOverlap ? overlapTransformOrigin : adjacentTransformOrigin);
return { data: { transformOrigin: useOverlap ? overlapTransformOrigin : adjacentTransformOrigin } };
}
};
}
const rectMiddleware = {
name: "rects",
fn({ rects }) {
return { data: rects };
}
};
const shiftArrowMiddleware = (arrowEl) => {
if (!arrowEl) return;
return {
name: "shiftArrow",
fn({ placement, middlewareData }) {
if (!middlewareData.arrow) return {};
const { x, y } = middlewareData.arrow;
const dir = placement.split("-")[0];
Object.assign(arrowEl.style, {
left: x != null ? `${x}px` : "",
top: y != null ? `${y}px` : "",
[dir]: `calc(100% + ${cssVars.arrowOffset.reference})`
});
return {};
}
};
};
//#endregion
//#region src/shared/popper/placement.ts
function isValidPlacement(v) {
return /^(?:top|bottom|left|right)(?:-(?:start|end))?$/.test(v);
}
function getPlacementDetails(placement) {
const [side, align] = placement.split("-");
return {
side,
align,
hasAlign: align != null
};
}
function getPlacementSide(placement) {
return placement.split("-")[0];
}
//#endregion
//#region src/shared/popper/get-placement.ts
const defaultOptions = {
strategy: "absolute",
placement: "bottom",
listeners: true,
restoreStyles: false,
gutter: 8,
flip: true,
slide: true,
overlap: false,
sameWidth: false,
fitViewport: false,
overflowPadding: 8,
arrowPadding: 4
};
function roundByDpr(win, value) {
const dpr = win.devicePixelRatio || 1;
return Math.round(value * dpr) / dpr;
}
function isApproximatelyEqual(a, b) {
return a != null && Math.abs(a - b) < .5;
}
function resolveBoundaryOption(boundary) {
if (typeof boundary === "function") return boundary();
if (boundary === "clipping-ancestors") return "clippingAncestors";
return boundary;
}
function getArrowMiddleware(arrowElement, doc, opts) {
return (0, _floating_ui_dom.arrow)({
element: arrowElement || doc.createElement("div"),
padding: opts.arrowPadding
});
}
function getOffsetMiddleware(arrowElement, opts) {
if ((0, _ginxjs_core_utils.isNull)(opts.offset ?? opts.gutter)) return;
return (0, _floating_ui_dom.offset)(({ placement }) => {
const arrowOffset = (arrowElement?.clientHeight || 0) / 2;
const gutter = opts.offset?.mainAxis ?? opts.gutter;
const mainAxis = typeof gutter === "number" ? gutter + arrowOffset : gutter ?? arrowOffset;
const { hasAlign } = getPlacementDetails(placement);
const shift = !hasAlign ? opts.shift : void 0;
return (0, _ginxjs_core_utils.compact)({
crossAxis: opts.offset?.crossAxis ?? shift,
mainAxis,
alignmentAxis: opts.shift
});
});
}
function getFlipMiddleware(opts) {
if (!opts.flip) return;
const boundary = resolveBoundaryOption(opts.boundary);
return (0, _floating_ui_dom.flip)({
...boundary ? { boundary } : void 0,
padding: opts.overflowPadding,
fallbackPlacements: opts.flip === true ? void 0 : opts.flip
});
}
function getShiftMiddleware(opts) {
if (!opts.slide && !opts.overlap) return;
const boundary = resolveBoundaryOption(opts.boundary);
return (0, _floating_ui_dom.shift)({
...boundary ? { boundary } : void 0,
mainAxis: opts.slide,
crossAxis: opts.overlap,
padding: opts.overflowPadding,
limiter: (0, _floating_ui_dom.limitShift)()
});
}
function getSizeMiddleware(opts) {
if (opts.sizeMiddleware === false && !opts.sameWidth && !opts.fitViewport) return;
let lastReferenceWidth;
let lastReferenceHeight;
let lastAvailableWidth;
let lastAvailableHeight;
return (0, _floating_ui_dom.size)({
padding: opts.overflowPadding,
apply({ elements, rects, availableHeight, availableWidth }) {
const floating = elements.floating;
const referenceWidth = Math.round(rects.reference.width);
const referenceHeight = Math.round(rects.reference.height);
availableWidth = Math.floor(availableWidth);
availableHeight = Math.floor(availableHeight);
if (!isApproximatelyEqual(lastReferenceWidth, referenceWidth)) {
floating.style.setProperty("--reference-width", `${referenceWidth}px`);
lastReferenceWidth = referenceWidth;
}
if (!isApproximatelyEqual(lastReferenceHeight, referenceHeight)) {
floating.style.setProperty("--reference-height", `${referenceHeight}px`);
lastReferenceHeight = referenceHeight;
}
if (!isApproximatelyEqual(lastAvailableWidth, availableWidth)) {
floating.style.setProperty("--available-width", `${availableWidth}px`);
lastAvailableWidth = availableWidth;
}
if (!isApproximatelyEqual(lastAvailableHeight, availableHeight)) {
floating.style.setProperty("--available-height", `${availableHeight}px`);
lastAvailableHeight = availableHeight;
}
}
});
}
function hideWhenDetachedMiddleware(opts) {
if (!opts.hideWhenDetached) return;
return (0, _floating_ui_dom.hide)({
strategy: "referenceHidden",
boundary: resolveBoundaryOption(opts.boundary) ?? "clippingAncestors"
});
}
function getAutoUpdateOptions(opts) {
if (!opts) return {};
if (opts === true) return {
ancestorResize: true,
ancestorScroll: true,
elementResize: true,
layoutShift: true
};
return opts;
}
const floatingStyleProps = [
"transform",
"visibility",
"pointer-events",
"--x",
"--y",
"--z-index",
"--reference-width",
"--reference-height",
"--available-width",
"--available-height",
"--transform-origin"
];
const arrowStyleProps = [
"top",
"right",
"bottom",
"left"
];
function createStyleCleanup(el, props) {
if (!el) return _ginxjs_core_utils.noop;
const prev = new Map(props.map((prop) => [prop, el.style.getPropertyValue(prop)]));
return () => {
prev.forEach((value, prop) => {
if (value) el.style.setProperty(prop, value);
else el.style.removeProperty(prop);
});
if (el.style.length === 0) el.removeAttribute("style");
};
}
function anchorIdentity(anchor) {
if (anchor == null) return null;
if (require_dom_query.isHTMLElement(anchor)) return anchor;
if (typeof anchor === "object" && anchor && "contextElement" in anchor && anchor.contextElement) return anchor.contextElement;
return anchor;
}
function getPlacementImpl(referenceOrVirtual, floatingOrVirtual, opts = {}) {
const resolveFloating = () => {
return (typeof floatingOrVirtual === "function" ? floatingOrVirtual() : floatingOrVirtual) ?? null;
};
const resolveAnchor = () => {
const raw = typeof referenceOrVirtual === "function" ? referenceOrVirtual() : referenceOrVirtual;
return opts.getAnchorElement?.() ?? raw;
};
const resolveReference = () => {
const anchor = resolveAnchor();
if (!anchor && !opts.getAnchorRect) return null;
return getAnchorElement(anchor, opts.getAnchorRect);
};
const options = Object.assign({}, defaultOptions, opts);
let middleware = [];
let cachedMiddlewareFloating = null;
let restoreFloatingStyles;
let restoreArrowStyles;
function rebuildMiddlewareForFloating(floating) {
restoreFloatingStyles?.();
restoreArrowStyles?.();
cachedMiddlewareFloating = floating;
restoreFloatingStyles = options.restoreStyles ? createStyleCleanup(floating, floatingStyleProps) : void 0;
const arrowEl = floating.querySelector("[data-part=arrow]");
restoreArrowStyles = options.restoreStyles ? createStyleCleanup(arrowEl, arrowStyleProps) : void 0;
middleware = [
getOffsetMiddleware(arrowEl, options),
getFlipMiddleware(options),
getShiftMiddleware(options),
getArrowMiddleware(arrowEl, floating.ownerDocument, options),
shiftArrowMiddleware(arrowEl),
createTransformOriginMiddleware({
gutter: options.gutter,
offset: options.offset,
overlap: options.overlap
}, arrowEl),
getSizeMiddleware(options),
hideWhenDetachedMiddleware(options),
rectMiddleware
];
}
const { placement, strategy, onComplete, onPositioned } = options;
let lastX;
let lastY;
let zIndexComputed = false;
let lastAnchorForObserve = void 0;
let lastFloatingForObserve = void 0;
let cancelAutoUpdate = _ginxjs_core_utils.noop;
const autoUpdateOptions = getAutoUpdateOptions(options.listeners);
function syncAutoUpdateObservers() {
if (!options.listeners) return;
const anchor = resolveAnchor();
const reference = resolveReference();
const floating = resolveFloating();
if (!reference || !floating) return;
if (anchorIdentity(anchor) !== anchorIdentity(lastAnchorForObserve) || floating !== lastFloatingForObserve) {
cancelAutoUpdate();
lastAnchorForObserve = anchor;
lastFloatingForObserve = floating;
cancelAutoUpdate = (0, _floating_ui_dom.autoUpdate)(reference, floating, runUpdate, autoUpdateOptions);
}
}
async function updatePosition() {
syncAutoUpdateObservers();
const floating = resolveFloating();
if (!floating) return;
if (floating !== cachedMiddlewareFloating) {
rebuildMiddlewareForFloating(floating);
zIndexComputed = false;
}
const reference = resolveReference();
if (!reference) return;
const pos = await (0, _floating_ui_dom.computePosition)(reference, floating, {
placement,
middleware,
strategy
});
onComplete?.(pos);
const win = require_dom_query.getWindow(floating);
const x = roundByDpr(win, pos.x);
const y = roundByDpr(win, pos.y);
if (!isApproximatelyEqual(lastX, x)) {
floating.style.setProperty("--x", `${x}px`);
lastX = x;
}
if (!isApproximatelyEqual(lastY, y)) {
floating.style.setProperty("--y", `${y}px`);
lastY = y;
}
if (options.hideWhenDetached) if (pos.middlewareData.hide?.referenceHidden) {
floating.style.setProperty("visibility", "hidden");
floating.style.setProperty("pointer-events", "none");
} else {
floating.style.removeProperty("visibility");
floating.style.removeProperty("pointer-events");
}
if (!zIndexComputed) {
const contentEl = floating.firstElementChild;
if (contentEl) {
floating.style.setProperty("--z-index", require_dom_query.getComputedStyle(contentEl).zIndex);
zIndexComputed = true;
}
}
}
async function runUpdate() {
if (opts.updatePosition) {
await opts.updatePosition({
updatePosition,
floatingElement: resolveFloating()
});
onPositioned?.({ placed: true });
} else await updatePosition();
}
runUpdate();
return () => {
cancelAutoUpdate();
restoreArrowStyles?.();
restoreFloatingStyles?.();
onPositioned?.({ placed: false });
};
}
function getPlacement(referenceOrFn, floatingOrFn, opts = {}) {
const { defer, ...options } = opts;
const func = defer ? require_dom_query.raf : (v) => v();
const cleanups = [];
cleanups.push(func(() => {
cleanups.push(getPlacementImpl(referenceOrFn, floatingOrFn, options));
}));
return () => {
cleanups.forEach((fn) => fn?.());
};
}
//#endregion
//#region src/shared/popper/get-styles.ts
const ARROW_FLOATING_STYLE = {
bottom: "rotate(45deg)",
left: "rotate(135deg)",
top: "rotate(225deg)",
right: "rotate(315deg)"
};
function getPlacementStyles(options = {}) {
const { placement, sameWidth, fitViewport, strategy = "absolute" } = options;
return {
arrow: {
position: "absolute",
width: cssVars.arrowSize.reference,
height: cssVars.arrowSize.reference,
[cssVars.arrowSizeHalf.variable]: `calc(${cssVars.arrowSize.reference} / 2)`,
[cssVars.arrowOffset.variable]: `calc(${cssVars.arrowSizeHalf.reference} * -1)`
},
arrowTip: {
transform: placement ? ARROW_FLOATING_STYLE[placement.split("-")[0]] : void 0,
background: cssVars.arrowBg.reference,
top: "0",
left: "0",
width: "100%",
height: "100%",
position: "absolute",
zIndex: "inherit"
},
floating: {
position: strategy,
isolation: "isolate",
minWidth: sameWidth ? void 0 : "max-content",
width: sameWidth ? "var(--reference-width)" : void 0,
maxWidth: fitViewport ? "var(--available-width)" : void 0,
maxHeight: fitViewport ? "var(--available-height)" : void 0,
pointerEvents: !placement ? "none" : void 0,
top: "0px",
left: "0px",
transform: placement ? "translate3d(var(--x), var(--y), 0)" : "translate3d(0, -100vh, 0)",
zIndex: "var(--z-index)"
}
};
}
//#endregion
Object.defineProperty(exports, "getPlacement", {
enumerable: true,
get: function() {
return getPlacement;
}
});
Object.defineProperty(exports, "getPlacementSide", {
enumerable: true,
get: function() {
return getPlacementSide;
}
});
Object.defineProperty(exports, "getPlacementStyles", {
enumerable: true,
get: function() {
return getPlacementStyles;
}
});
Object.defineProperty(exports, "isValidPlacement", {
enumerable: true,
get: function() {
return isValidPlacement;
}
});
import { $t as getComputedStyle, G as raf, gn as isHTMLElement, ln as getWindow } from "./dom-query-BgxIO7_X.mjs";
import { compact, isNull, noop } from "@ginxjs/core/utils";
import { arrow, autoUpdate, computePosition, flip, hide, limitShift, offset, shift, size } from "@floating-ui/dom";
//#region src/shared/popper/get-anchor.ts
function createDOMRect(x = 0, y = 0, width = 0, height = 0) {
if (typeof DOMRect === "function") return new DOMRect(x, y, width, height);
const rect = {
x,
y,
width,
height,
top: y,
right: x + width,
bottom: y + height,
left: x
};
return {
...rect,
toJSON: () => rect
};
}
function getDOMRect(anchorRect) {
if (!anchorRect) return createDOMRect();
const { x, y, width, height } = anchorRect;
return createDOMRect(x, y, width, height);
}
function getAnchorElement(anchorElement, getAnchorRect) {
return {
contextElement: isHTMLElement(anchorElement) ? anchorElement : anchorElement?.contextElement,
getBoundingClientRect: () => {
const anchor = anchorElement;
const anchorRect = getAnchorRect?.(anchor);
if (anchorRect || !anchor) return getDOMRect(anchorRect);
return anchor.getBoundingClientRect();
}
};
}
//#endregion
//#region src/shared/popper/middleware.ts
const toVar = (value) => ({
variable: value,
reference: `var(${value})`
});
const cssVars = {
arrowSize: toVar("--arrow-size"),
arrowSizeHalf: toVar("--arrow-size-half"),
arrowBg: toVar("--arrow-background"),
transformOrigin: toVar("--transform-origin"),
arrowOffset: toVar("--arrow-offset")
};
const getSideAxis = (side) => side === "top" || side === "bottom" ? "y" : "x";
function createTransformOriginMiddleware(opts, arrowEl) {
return {
name: "transformOrigin",
fn(state) {
const { elements, middlewareData, placement, rects, y } = state;
const side = placement.split("-")[0];
const axis = getSideAxis(side);
const arrowX = middlewareData.arrow?.x || 0;
const arrowY = middlewareData.arrow?.y || 0;
const arrowWidth = arrowEl?.clientWidth || 0;
const arrowHeight = arrowEl?.clientHeight || 0;
const transformX = arrowX + arrowWidth / 2;
const transformY = arrowY + arrowHeight / 2;
const shiftY = Math.abs(middlewareData.shift?.y || 0);
const halfAnchorHeight = rects.reference.height / 2;
const arrowOffset = arrowHeight / 2;
const gutter = opts.offset?.mainAxis ?? opts.gutter;
const sideOffsetValue = typeof gutter === "number" ? gutter + arrowOffset : gutter ?? arrowOffset;
const isOverlappingAnchor = shiftY > sideOffsetValue;
const adjacentTransformOrigin = {
top: `${transformX}px calc(100% + ${sideOffsetValue}px)`,
bottom: `${transformX}px ${-sideOffsetValue}px`,
left: `calc(100% + ${sideOffsetValue}px) ${transformY}px`,
right: `${-sideOffsetValue}px ${transformY}px`
}[side];
const overlapTransformOrigin = `${transformX}px ${rects.reference.y + halfAnchorHeight - y}px`;
const useOverlap = Boolean(opts.overlap) && axis === "y" && isOverlappingAnchor;
elements.floating.style.setProperty(cssVars.transformOrigin.variable, useOverlap ? overlapTransformOrigin : adjacentTransformOrigin);
return { data: { transformOrigin: useOverlap ? overlapTransformOrigin : adjacentTransformOrigin } };
}
};
}
const rectMiddleware = {
name: "rects",
fn({ rects }) {
return { data: rects };
}
};
const shiftArrowMiddleware = (arrowEl) => {
if (!arrowEl) return;
return {
name: "shiftArrow",
fn({ placement, middlewareData }) {
if (!middlewareData.arrow) return {};
const { x, y } = middlewareData.arrow;
const dir = placement.split("-")[0];
Object.assign(arrowEl.style, {
left: x != null ? `${x}px` : "",
top: y != null ? `${y}px` : "",
[dir]: `calc(100% + ${cssVars.arrowOffset.reference})`
});
return {};
}
};
};
//#endregion
//#region src/shared/popper/placement.ts
function isValidPlacement(v) {
return /^(?:top|bottom|left|right)(?:-(?:start|end))?$/.test(v);
}
function getPlacementDetails(placement) {
const [side, align] = placement.split("-");
return {
side,
align,
hasAlign: align != null
};
}
function getPlacementSide(placement) {
return placement.split("-")[0];
}
//#endregion
//#region src/shared/popper/get-placement.ts
const defaultOptions = {
strategy: "absolute",
placement: "bottom",
listeners: true,
restoreStyles: false,
gutter: 8,
flip: true,
slide: true,
overlap: false,
sameWidth: false,
fitViewport: false,
overflowPadding: 8,
arrowPadding: 4
};
function roundByDpr(win, value) {
const dpr = win.devicePixelRatio || 1;
return Math.round(value * dpr) / dpr;
}
function isApproximatelyEqual(a, b) {
return a != null && Math.abs(a - b) < .5;
}
function resolveBoundaryOption(boundary) {
if (typeof boundary === "function") return boundary();
if (boundary === "clipping-ancestors") return "clippingAncestors";
return boundary;
}
function getArrowMiddleware(arrowElement, doc, opts) {
return arrow({
element: arrowElement || doc.createElement("div"),
padding: opts.arrowPadding
});
}
function getOffsetMiddleware(arrowElement, opts) {
if (isNull(opts.offset ?? opts.gutter)) return;
return offset(({ placement }) => {
const arrowOffset = (arrowElement?.clientHeight || 0) / 2;
const gutter = opts.offset?.mainAxis ?? opts.gutter;
const mainAxis = typeof gutter === "number" ? gutter + arrowOffset : gutter ?? arrowOffset;
const { hasAlign } = getPlacementDetails(placement);
const shift = !hasAlign ? opts.shift : void 0;
return compact({
crossAxis: opts.offset?.crossAxis ?? shift,
mainAxis,
alignmentAxis: opts.shift
});
});
}
function getFlipMiddleware(opts) {
if (!opts.flip) return;
const boundary = resolveBoundaryOption(opts.boundary);
return flip({
...boundary ? { boundary } : void 0,
padding: opts.overflowPadding,
fallbackPlacements: opts.flip === true ? void 0 : opts.flip
});
}
function getShiftMiddleware(opts) {
if (!opts.slide && !opts.overlap) return;
const boundary = resolveBoundaryOption(opts.boundary);
return shift({
...boundary ? { boundary } : void 0,
mainAxis: opts.slide,
crossAxis: opts.overlap,
padding: opts.overflowPadding,
limiter: limitShift()
});
}
function getSizeMiddleware(opts) {
if (opts.sizeMiddleware === false && !opts.sameWidth && !opts.fitViewport) return;
let lastReferenceWidth;
let lastReferenceHeight;
let lastAvailableWidth;
let lastAvailableHeight;
return size({
padding: opts.overflowPadding,
apply({ elements, rects, availableHeight, availableWidth }) {
const floating = elements.floating;
const referenceWidth = Math.round(rects.reference.width);
const referenceHeight = Math.round(rects.reference.height);
availableWidth = Math.floor(availableWidth);
availableHeight = Math.floor(availableHeight);
if (!isApproximatelyEqual(lastReferenceWidth, referenceWidth)) {
floating.style.setProperty("--reference-width", `${referenceWidth}px`);
lastReferenceWidth = referenceWidth;
}
if (!isApproximatelyEqual(lastReferenceHeight, referenceHeight)) {
floating.style.setProperty("--reference-height", `${referenceHeight}px`);
lastReferenceHeight = referenceHeight;
}
if (!isApproximatelyEqual(lastAvailableWidth, availableWidth)) {
floating.style.setProperty("--available-width", `${availableWidth}px`);
lastAvailableWidth = availableWidth;
}
if (!isApproximatelyEqual(lastAvailableHeight, availableHeight)) {
floating.style.setProperty("--available-height", `${availableHeight}px`);
lastAvailableHeight = availableHeight;
}
}
});
}
function hideWhenDetachedMiddleware(opts) {
if (!opts.hideWhenDetached) return;
return hide({
strategy: "referenceHidden",
boundary: resolveBoundaryOption(opts.boundary) ?? "clippingAncestors"
});
}
function getAutoUpdateOptions(opts) {
if (!opts) return {};
if (opts === true) return {
ancestorResize: true,
ancestorScroll: true,
elementResize: true,
layoutShift: true
};
return opts;
}
const floatingStyleProps = [
"transform",
"visibility",
"pointer-events",
"--x",
"--y",
"--z-index",
"--reference-width",
"--reference-height",
"--available-width",
"--available-height",
"--transform-origin"
];
const arrowStyleProps = [
"top",
"right",
"bottom",
"left"
];
function createStyleCleanup(el, props) {
if (!el) return noop;
const prev = new Map(props.map((prop) => [prop, el.style.getPropertyValue(prop)]));
return () => {
prev.forEach((value, prop) => {
if (value) el.style.setProperty(prop, value);
else el.style.removeProperty(prop);
});
if (el.style.length === 0) el.removeAttribute("style");
};
}
function anchorIdentity(anchor) {
if (anchor == null) return null;
if (isHTMLElement(anchor)) return anchor;
if (typeof anchor === "object" && anchor && "contextElement" in anchor && anchor.contextElement) return anchor.contextElement;
return anchor;
}
function getPlacementImpl(referenceOrVirtual, floatingOrVirtual, opts = {}) {
const resolveFloating = () => {
return (typeof floatingOrVirtual === "function" ? floatingOrVirtual() : floatingOrVirtual) ?? null;
};
const resolveAnchor = () => {
const raw = typeof referenceOrVirtual === "function" ? referenceOrVirtual() : referenceOrVirtual;
return opts.getAnchorElement?.() ?? raw;
};
const resolveReference = () => {
const anchor = resolveAnchor();
if (!anchor && !opts.getAnchorRect) return null;
return getAnchorElement(anchor, opts.getAnchorRect);
};
const options = Object.assign({}, defaultOptions, opts);
let middleware = [];
let cachedMiddlewareFloating = null;
let restoreFloatingStyles;
let restoreArrowStyles;
function rebuildMiddlewareForFloating(floating) {
restoreFloatingStyles?.();
restoreArrowStyles?.();
cachedMiddlewareFloating = floating;
restoreFloatingStyles = options.restoreStyles ? createStyleCleanup(floating, floatingStyleProps) : void 0;
const arrowEl = floating.querySelector("[data-part=arrow]");
restoreArrowStyles = options.restoreStyles ? createStyleCleanup(arrowEl, arrowStyleProps) : void 0;
middleware = [
getOffsetMiddleware(arrowEl, options),
getFlipMiddleware(options),
getShiftMiddleware(options),
getArrowMiddleware(arrowEl, floating.ownerDocument, options),
shiftArrowMiddleware(arrowEl),
createTransformOriginMiddleware({
gutter: options.gutter,
offset: options.offset,
overlap: options.overlap
}, arrowEl),
getSizeMiddleware(options),
hideWhenDetachedMiddleware(options),
rectMiddleware
];
}
const { placement, strategy, onComplete, onPositioned } = options;
let lastX;
let lastY;
let zIndexComputed = false;
let lastAnchorForObserve = void 0;
let lastFloatingForObserve = void 0;
let cancelAutoUpdate = noop;
const autoUpdateOptions = getAutoUpdateOptions(options.listeners);
function syncAutoUpdateObservers() {
if (!options.listeners) return;
const anchor = resolveAnchor();
const reference = resolveReference();
const floating = resolveFloating();
if (!reference || !floating) return;
if (anchorIdentity(anchor) !== anchorIdentity(lastAnchorForObserve) || floating !== lastFloatingForObserve) {
cancelAutoUpdate();
lastAnchorForObserve = anchor;
lastFloatingForObserve = floating;
cancelAutoUpdate = autoUpdate(reference, floating, runUpdate, autoUpdateOptions);
}
}
async function updatePosition() {
syncAutoUpdateObservers();
const floating = resolveFloating();
if (!floating) return;
if (floating !== cachedMiddlewareFloating) {
rebuildMiddlewareForFloating(floating);
zIndexComputed = false;
}
const reference = resolveReference();
if (!reference) return;
const pos = await computePosition(reference, floating, {
placement,
middleware,
strategy
});
onComplete?.(pos);
const win = getWindow(floating);
const x = roundByDpr(win, pos.x);
const y = roundByDpr(win, pos.y);
if (!isApproximatelyEqual(lastX, x)) {
floating.style.setProperty("--x", `${x}px`);
lastX = x;
}
if (!isApproximatelyEqual(lastY, y)) {
floating.style.setProperty("--y", `${y}px`);
lastY = y;
}
if (options.hideWhenDetached) if (pos.middlewareData.hide?.referenceHidden) {
floating.style.setProperty("visibility", "hidden");
floating.style.setProperty("pointer-events", "none");
} else {
floating.style.removeProperty("visibility");
floating.style.removeProperty("pointer-events");
}
if (!zIndexComputed) {
const contentEl = floating.firstElementChild;
if (contentEl) {
floating.style.setProperty("--z-index", getComputedStyle(contentEl).zIndex);
zIndexComputed = true;
}
}
}
async function runUpdate() {
if (opts.updatePosition) {
await opts.updatePosition({
updatePosition,
floatingElement: resolveFloating()
});
onPositioned?.({ placed: true });
} else await updatePosition();
}
runUpdate();
return () => {
cancelAutoUpdate();
restoreArrowStyles?.();
restoreFloatingStyles?.();
onPositioned?.({ placed: false });
};
}
function getPlacement(referenceOrFn, floatingOrFn, opts = {}) {
const { defer, ...options } = opts;
const func = defer ? raf : (v) => v();
const cleanups = [];
cleanups.push(func(() => {
cleanups.push(getPlacementImpl(referenceOrFn, floatingOrFn, options));
}));
return () => {
cleanups.forEach((fn) => fn?.());
};
}
//#endregion
//#region src/shared/popper/get-styles.ts
const ARROW_FLOATING_STYLE = {
bottom: "rotate(45deg)",
left: "rotate(135deg)",
top: "rotate(225deg)",
right: "rotate(315deg)"
};
function getPlacementStyles(options = {}) {
const { placement, sameWidth, fitViewport, strategy = "absolute" } = options;
return {
arrow: {
position: "absolute",
width: cssVars.arrowSize.reference,
height: cssVars.arrowSize.reference,
[cssVars.arrowSizeHalf.variable]: `calc(${cssVars.arrowSize.reference} / 2)`,
[cssVars.arrowOffset.variable]: `calc(${cssVars.arrowSizeHalf.reference} * -1)`
},
arrowTip: {
transform: placement ? ARROW_FLOATING_STYLE[placement.split("-")[0]] : void 0,
background: cssVars.arrowBg.reference,
top: "0",
left: "0",
width: "100%",
height: "100%",
position: "absolute",
zIndex: "inherit"
},
floating: {
position: strategy,
isolation: "isolate",
minWidth: sameWidth ? void 0 : "max-content",
width: sameWidth ? "var(--reference-width)" : void 0,
maxWidth: fitViewport ? "var(--available-width)" : void 0,
maxHeight: fitViewport ? "var(--available-height)" : void 0,
pointerEvents: !placement ? "none" : void 0,
top: "0px",
left: "0px",
transform: placement ? "translate3d(var(--x), var(--y), 0)" : "translate3d(0, -100vh, 0)",
zIndex: "var(--z-index)"
}
};
}
//#endregion
export { isValidPlacement as i, getPlacement as n, getPlacementSide as r, getPlacementStyles as t };
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_popper = require("./popper-CiXiA2V2.cjs");
exports.getPlacement = require_popper.getPlacement;
exports.getPlacementSide = require_popper.getPlacementSide;
exports.getPlacementStyles = require_popper.getPlacementStyles;
exports.isValidPlacement = require_popper.isValidPlacement;
import { a as getPlacement, c as Boundary, d as PlacementAlign, f as PlacementSide, i as getPlacementStyles, l as ComputePositionReturn, n as isValidPlacement, o as AnchorRect, p as PositioningOptions, r as GetPlacementStylesOptions, s as AutoUpdateOptions, t as getPlacementSide, u as Placement } from "./index-C5hisChz.cjs";
export { AnchorRect, AutoUpdateOptions, Boundary, ComputePositionReturn, GetPlacementStylesOptions, Placement, PlacementAlign, PlacementSide, PositioningOptions, getPlacement, getPlacementSide, getPlacementStyles, isValidPlacement };
import { a as getPlacement, c as Boundary, d as PlacementAlign, f as PlacementSide, i as getPlacementStyles, l as ComputePositionReturn, n as isValidPlacement, o as AnchorRect, p as PositioningOptions, r as GetPlacementStylesOptions, s as AutoUpdateOptions, t as getPlacementSide, u as Placement } from "./index-r24gWw_v.mjs";
export { AnchorRect, AutoUpdateOptions, Boundary, ComputePositionReturn, GetPlacementStylesOptions, Placement, PlacementAlign, PlacementSide, PositioningOptions, getPlacement, getPlacementSide, getPlacementStyles, isValidPlacement };
import { i as isValidPlacement, n as getPlacement, r as getPlacementSide, t as getPlacementStyles } from "./popper-D_zaMhQo.mjs";
export { getPlacement, getPlacementSide, getPlacementStyles, isValidPlacement };
//#region src/shared/rect/affine-transform.ts
var AffineTransform = class AffineTransform {
m00;
m01;
m02;
m10;
m11;
m12;
constructor([m00, m01, m02, m10, m11, m12] = [
0,
0,
0,
0,
0,
0
]) {
this.m00 = m00;
this.m01 = m01;
this.m02 = m02;
this.m10 = m10;
this.m11 = m11;
this.m12 = m12;
}
applyTo(point) {
const { x, y } = point;
const { m00, m01, m02, m10, m11, m12 } = this;
return {
x: m00 * x + m01 * y + m02,
y: m10 * x + m11 * y + m12
};
}
prepend(other) {
return new AffineTransform([
this.m00 * other.m00 + this.m01 * other.m10,
this.m00 * other.m01 + this.m01 * other.m11,
this.m00 * other.m02 + this.m01 * other.m12 + this.m02,
this.m10 * other.m00 + this.m11 * other.m10,
this.m10 * other.m01 + this.m11 * other.m11,
this.m10 * other.m02 + this.m11 * other.m12 + this.m12
]);
}
append(other) {
return new AffineTransform([
other.m00 * this.m00 + other.m01 * this.m10,
other.m00 * this.m01 + other.m01 * this.m11,
other.m00 * this.m02 + other.m01 * this.m12 + other.m02,
other.m10 * this.m00 + other.m11 * this.m10,
other.m10 * this.m01 + other.m11 * this.m11,
other.m10 * this.m02 + other.m11 * this.m12 + other.m12
]);
}
get determinant() {
return this.m00 * this.m11 - this.m01 * this.m10;
}
get isInvertible() {
const det = this.determinant;
return isFinite(det) && isFinite(this.m02) && isFinite(this.m12) && det !== 0;
}
invert() {
const det = this.determinant;
return new AffineTransform([
this.m11 / det,
-this.m01 / det,
(this.m01 * this.m12 - this.m11 * this.m02) / det,
-this.m10 / det,
this.m00 / det,
(this.m10 * this.m02 - this.m00 * this.m12) / det
]);
}
get array() {
return [
this.m00,
this.m01,
this.m02,
this.m10,
this.m11,
this.m12,
0,
0,
1
];
}
get float32Array() {
return new Float32Array(this.array);
}
static get identity() {
return new AffineTransform([
1,
0,
0,
0,
1,
0
]);
}
static rotate(theta, origin) {
const rotation = new AffineTransform([
Math.cos(theta),
-Math.sin(theta),
0,
Math.sin(theta),
Math.cos(theta),
0
]);
if (origin && (origin.x !== 0 || origin.y !== 0)) return AffineTransform.multiply(AffineTransform.translate(origin.x, origin.y), rotation, AffineTransform.translate(-origin.x, -origin.y));
return rotation;
}
rotate = (...args) => {
return this.prepend(AffineTransform.rotate(...args));
};
static scale(sx, sy = sx, origin = {
x: 0,
y: 0
}) {
const scale = new AffineTransform([
sx,
0,
0,
0,
sy,
0
]);
if (origin.x !== 0 || origin.y !== 0) return AffineTransform.multiply(AffineTransform.translate(origin.x, origin.y), scale, AffineTransform.translate(-origin.x, -origin.y));
return scale;
}
scale = (...args) => {
return this.prepend(AffineTransform.scale(...args));
};
static translate(tx, ty) {
return new AffineTransform([
1,
0,
tx,
0,
1,
ty
]);
}
translate = (...args) => {
return this.prepend(AffineTransform.translate(...args));
};
static multiply(...[first, ...rest]) {
if (!first) return AffineTransform.identity;
return rest.reduce((result, item) => result.prepend(item), first);
}
get a() {
return this.m00;
}
get b() {
return this.m10;
}
get c() {
return this.m01;
}
get d() {
return this.m11;
}
get tx() {
return this.m02;
}
get ty() {
return this.m12;
}
get scaleComponents() {
return {
x: this.a,
y: this.d
};
}
get translationComponents() {
return {
x: this.tx,
y: this.ty
};
}
get skewComponents() {
return {
x: this.c,
y: this.b
};
}
toString() {
return `matrix(${this.a}, ${this.b}, ${this.c}, ${this.d}, ${this.tx}, ${this.ty})`;
}
};
//#endregion
//#region src/shared/rect/align.ts
function hAlign(a, ref, h) {
let x = ref.minX;
if (h === "left-inside") x = ref.minX;
if (h === "left-outside") x = ref.minX - ref.width;
if (h === "right-inside") x = ref.maxX - ref.width;
if (h === "right-outside") x = ref.maxX;
if (h === "center") x = ref.midX - ref.width / 2;
return {
...a,
x
};
}
function vAlign(a, ref, v) {
let y = ref.minY;
if (v === "top-inside") y = ref.minY;
if (v === "top-outside") y = ref.minY - a.height;
if (v === "bottom-inside") y = ref.maxY - a.height;
if (v === "bottom-outside") y = ref.maxY;
if (v === "center") y = ref.midY - a.height / 2;
return {
...a,
y
};
}
function alignRect(a, ref, options) {
const { h, v } = options;
return vAlign(hAlign(a, ref, h), ref, v);
}
//#endregion
//#region src/shared/rect/angle.ts
function getPointAngle(rect, point, reference = rect.center) {
const x = point.x - reference.x;
const y = point.y - reference.y;
return 360 - (Math.atan2(x, y) * (180 / Math.PI) + 180);
}
//#endregion
//#region src/shared/rect/clamp.ts
const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
const clampPoint = (position, size, boundaryRect) => {
return {
x: clamp(position.x, boundaryRect.x, boundaryRect.x + boundaryRect.width - size.width),
y: clamp(position.y, boundaryRect.y, boundaryRect.y + boundaryRect.height - size.height)
};
};
const defaultMinSize = {
width: 0,
height: 0
};
const defaultMaxSize = {
width: Infinity,
height: Infinity
};
const clampSize = (size, minSize = defaultMinSize, maxSize = defaultMaxSize) => {
return {
width: Math.min(Math.max(size.width, minSize.width), maxSize.width),
height: Math.min(Math.max(size.height, minSize.height), maxSize.height)
};
};
//#endregion
//#region src/shared/rect/rect.ts
const createPoint = (x, y) => ({
x,
y
});
const subtractPoints = (a, b) => {
if (!b) return a;
return createPoint(a.x - b.x, a.y - b.y);
};
const addPoints = (a, b) => createPoint(a.x + b.x, a.y + b.y);
function isPoint(v) {
return Reflect.has(v, "x") && Reflect.has(v, "y");
}
function createRect(r) {
const { x, y, width, height } = r;
const midX = x + width / 2;
const midY = y + height / 2;
return {
x,
y,
width,
height,
minX: x,
minY: y,
maxX: x + width,
maxY: y + height,
midX,
midY,
center: createPoint(midX, midY)
};
}
function isRect(v) {
return Reflect.has(v, "x") && Reflect.has(v, "y") && Reflect.has(v, "width") && Reflect.has(v, "height");
}
function getRectCenters(v) {
return {
top: createPoint(v.midX, v.minY),
right: createPoint(v.maxX, v.midY),
bottom: createPoint(v.midX, v.maxY),
left: createPoint(v.minX, v.midY)
};
}
function getRectCorners(v) {
return {
top: createPoint(v.minX, v.minY),
right: createPoint(v.maxX, v.minY),
bottom: createPoint(v.maxX, v.maxY),
left: createPoint(v.minX, v.maxY)
};
}
function getRectEdges(v) {
const c = getRectCorners(v);
return {
top: [c.top, c.right],
right: [c.right, c.bottom],
bottom: [c.left, c.bottom],
left: [c.top, c.left]
};
}
//#endregion
//#region src/shared/rect/intersection.ts
function intersects(a, b) {
return a.x < b.maxX && a.y < b.maxY && a.maxX > b.x && a.maxY > b.y;
}
function intersection(a, b) {
const x = Math.max(a.x, b.x);
const y = Math.max(a.y, b.y);
const x2 = Math.min(a.x + a.width, b.x + b.width);
const y2 = Math.min(a.y + a.height, b.y + b.height);
return createRect({
x,
y,
width: x2 - x,
height: y2 - y
});
}
function collisions(a, b) {
return {
top: a.minY <= b.minY,
right: a.maxX >= b.maxX,
bottom: a.maxY >= b.maxY,
left: a.minX <= b.minX
};
}
//#endregion
//#region src/shared/rect/distance.ts
function distance(a, b = {
x: 0,
y: 0
}) {
return Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2));
}
function distanceFromPoint(r, p) {
let x = 0;
let y = 0;
if (p.x < r.x) x = r.x - p.x;
else if (p.x > r.maxX) x = p.x - r.maxX;
if (p.y < r.y) y = r.y - p.y;
else if (p.y > r.maxY) y = p.y - r.maxY;
return {
x,
y,
value: distance({
x,
y
})
};
}
function distanceFromRect(a, b) {
if (intersects(a, b)) return {
x: 0,
y: 0,
value: 0
};
const left = a.x < b.x ? a : b;
const right = b.x < a.x ? a : b;
const upper = a.y < b.y ? a : b;
const lower = b.y < a.y ? a : b;
let x = left.x === right.x ? 0 : right.x - left.maxX;
x = Math.max(0, x);
let y = upper.y === lower.y ? 0 : lower.y - upper.maxY;
y = Math.max(0, y);
return {
x,
y,
value: distance({
x,
y
})
};
}
function distanceBtwEdges(a, b) {
return {
left: b.x - a.x,
top: b.y - a.y,
right: a.maxX - b.maxX,
bottom: a.maxY - b.maxY
};
}
//#endregion
//#region src/shared/rect/closest.ts
function closest(...pts) {
return (a) => {
const ds = pts.map((b) => distance(b, a));
const c = Math.min.apply(Math, ds);
return pts[ds.indexOf(c)];
};
}
function closestSideToRect(ref, r) {
if (r.maxX <= ref.minX) return "left";
if (r.minX >= ref.maxX) return "right";
if (r.maxY <= ref.minY) return "top";
if (r.minY >= ref.maxY) return "bottom";
return "left";
}
function closestSideToPoint(ref, p) {
const { x, y } = p;
const dl = x - ref.minX;
const dr = ref.maxX - x;
const dt = y - ref.minY;
const db = ref.maxY - y;
let closest = dl;
let side = "left";
if (dr < closest) {
closest = dr;
side = "right";
}
if (dt < closest) {
closest = dt;
side = "top";
}
if (db < closest) side = "bottom";
return side;
}
//#endregion
//#region src/shared/rect/constrain.ts
const constrainRect = (rect, boundary) => {
return {
x: Math.max(boundary.x, Math.min(rect.x, boundary.x + boundary.width - rect.width)),
y: Math.max(boundary.y, Math.min(rect.y, boundary.y + boundary.height - rect.height)),
width: Math.min(rect.width, boundary.width),
height: Math.min(rect.height, boundary.height)
};
};
//#endregion
//#region src/shared/rect/contains.ts
function containsPoint(r, p) {
return r.minX <= p.x && p.x <= r.maxX && r.minY <= p.y && p.y <= r.maxY;
}
function containsRect(a, b) {
return Object.values(getRectCorners(b)).every((c) => containsPoint(a, c));
}
function contains(r, v) {
return isRect(v) ? containsRect(r, v) : containsPoint(r, v);
}
//#endregion
//#region src/shared/rect/equality.ts
const isSizeEqual = (a, b) => {
return a.width === b?.width && a.height === b?.height;
};
const isPointEqual = (a, b) => {
return a.x === b?.x && a.y === b?.y;
};
const isRectEqual = (a, b) => {
return isPointEqual(a, b) && isSizeEqual(a, b);
};
//#endregion
//#region src/shared/rect/from-element.ts
const styleCache = /* @__PURE__ */ new WeakMap();
function getCacheComputedStyle(el) {
if (!styleCache.has(el)) {
const win = el.ownerDocument.defaultView || window;
styleCache.set(el, win.getComputedStyle(el));
}
return styleCache.get(el);
}
function getElementRect(el, opts = {}) {
return createRect(getClientRect(el, opts));
}
function getClientRect(el, opts = {}) {
const { excludeScrollbar = false, excludeBorders = false } = opts;
const { x, y, width, height } = el.getBoundingClientRect();
const r = {
x,
y,
width,
height
};
const { borderLeftWidth, borderTopWidth, borderRightWidth, borderBottomWidth } = getCacheComputedStyle(el);
const borderXWidth = sum(borderLeftWidth, borderRightWidth);
const borderYWidth = sum(borderTopWidth, borderBottomWidth);
if (excludeBorders) {
r.width -= borderXWidth;
r.height -= borderYWidth;
r.x += px(borderLeftWidth);
r.y += px(borderTopWidth);
}
if (excludeScrollbar) {
const scrollbarWidth = el.offsetWidth - el.clientWidth - borderXWidth;
const scrollbarHeight = el.offsetHeight - el.clientHeight - borderYWidth;
r.width -= scrollbarWidth;
r.height -= scrollbarHeight;
}
return r;
}
const px = (v) => parseFloat(v.replace("px", ""));
const sum = (...vals) => vals.reduce((sum, v) => sum + (v ? px(v) : 0), 0);
//#endregion
//#region src/shared/rect/from-points.ts
function getRectFromPoints(...pts) {
const xs = pts.map((p) => p.x);
const ys = pts.map((p) => p.y);
const x = Math.min(...xs);
const y = Math.min(...ys);
return createRect({
x,
y,
width: Math.max(...xs) - x,
height: Math.max(...ys) - y
});
}
//#endregion
//#region src/shared/rect/union.ts
const { min: min$1, max } = Math;
function union(...rs) {
return getRectFromPoints({
x: min$1(...rs.map((r) => r.minX)),
y: min$1(...rs.map((r) => r.minY))
}, {
x: max(...rs.map((r) => r.maxX)),
y: max(...rs.map((r) => r.maxY))
});
}
//#endregion
//#region src/shared/rect/from-range.ts
function fromRange(range) {
let rs = [];
const rects = Array.from(range.getClientRects());
if (rects.length) {
rs = rs.concat(rects.map(createRect));
return union.apply(void 0, rs);
}
let start = range.startContainer;
if (start.nodeType === Node.TEXT_NODE) start = start.parentNode;
if (start instanceof HTMLElement) {
const r = getElementRect(start);
rs.push({
...r,
x: r.maxX,
width: 0
});
}
return union.apply(void 0, rs);
}
//#endregion
//#region src/shared/rect/from-rotation.ts
function toRad(d) {
return d % 360 * Math.PI / 180;
}
function rotate(a, d, c) {
const r = toRad(d);
const sin = Math.sin(r);
const cos = Math.cos(r);
const x = a.x - c.x;
const y = a.y - c.y;
return {
x: c.x + x * cos - y * sin,
y: c.y + x * sin + y * cos
};
}
function getRotationRect(r, deg) {
const rr = Object.values(getRectCorners(r)).map((p) => rotate(p, deg, r.center));
const xs = rr.map((p) => p.x);
const ys = rr.map((p) => p.y);
const minX = Math.min(...xs);
const minY = Math.min(...ys);
const maxX = Math.max(...xs);
const maxY = Math.max(...ys);
return createRect({
x: minX,
y: minY,
width: maxX - minX,
height: maxY - minY
});
}
//#endregion
//#region src/shared/rect/from-window.ts
function getWindowRect(win, opts = {}) {
return createRect(getViewportRect(win, opts));
}
function getViewportRect(win, opts) {
const { excludeScrollbar = false } = opts;
const { innerWidth, innerHeight, document: doc, visualViewport } = win;
const rect = {
x: 0,
y: 0,
width: visualViewport?.width || innerWidth,
height: visualViewport?.height || innerHeight
};
if (excludeScrollbar) {
const scrollbarWidth = innerWidth - doc.documentElement.clientWidth;
const scrollbarHeight = innerHeight - doc.documentElement.clientHeight;
rect.width -= scrollbarWidth;
rect.height -= scrollbarHeight;
}
return rect;
}
//#endregion
//#region src/shared/rect/operations.ts
const isSymmetric = (v) => "dx" in v || "dy" in v;
function inset(r, i) {
const { top = 0, right = 0, bottom = 0, left = 0 } = isSymmetric(i) ? {
left: i.dx,
right: i.dx,
top: i.dy,
bottom: i.dy
} : i;
return createRect({
x: r.x + left,
y: r.y + top,
width: r.width - left - right,
height: r.height - top - bottom
});
}
function expand(r, v) {
return inset(r, typeof v === "number" ? {
dx: -v,
dy: -v
} : v);
}
function shrink(r, v) {
return inset(r, typeof v === "number" ? {
dx: -v,
dy: -v
} : v);
}
function shift(r, o) {
const { x = 0, y = 0 } = o;
return createRect({
x: r.x + x,
y: r.y + y,
width: r.width,
height: r.height
});
}
//#endregion
//#region src/shared/rect/polygon.ts
function getElementPolygon(rectValue, placement) {
const { top, right, left, bottom } = getRectCorners(createRect(rectValue));
const [base] = placement.split("-");
return {
top: [
left,
top,
right,
bottom
],
right: [
top,
right,
bottom,
left
],
bottom: [
top,
left,
bottom,
right
],
left: [
right,
top,
left,
bottom
]
}[base];
}
function isPointInPolygon(polygon, point) {
const { x, y } = point;
let c = false;
for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
const xi = polygon[i].x;
const yi = polygon[i].y;
const xj = polygon[j].x;
const yj = polygon[j].y;
if (yi > y !== yj > y && x < (xj - xi) * (y - yi) / (yj - yi) + xi) c = !c;
}
return c;
}
function createPolygonElement() {
const id = "debug-polygon";
const existingPolygon = document.getElementById(id);
if (existingPolygon) return existingPolygon;
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
Object.assign(svg.style, {
top: "0",
left: "0",
width: "100%",
height: "100%",
opacity: "0.15",
position: "fixed",
pointerEvents: "none",
fill: "red"
});
const polygon = document.createElementNS("http://www.w3.org/2000/svg", "polygon");
polygon.setAttribute("id", id);
polygon.setAttribute("points", "0,0 0,0");
svg.appendChild(polygon);
document.body.appendChild(svg);
return polygon;
}
function debugPolygon(polygon) {
const el = createPolygonElement();
const points = polygon.map((point) => `${point.x},${point.y}`).join(" ");
el.setAttribute("points", points);
return () => {
el.remove();
};
}
//#endregion
//#region src/shared/rect/compass.ts
const compassDirectionMap = {
n: {
x: .5,
y: 0
},
ne: {
x: 1,
y: 0
},
e: {
x: 1,
y: .5
},
se: {
x: 1,
y: 1
},
s: {
x: .5,
y: 1
},
sw: {
x: 0,
y: 1
},
w: {
x: 0,
y: .5
},
nw: {
x: 0,
y: 0
}
};
const oppositeDirectionMap = {
n: "s",
ne: "sw",
e: "w",
se: "nw",
s: "n",
sw: "ne",
w: "e",
nw: "se"
};
//#endregion
//#region src/shared/rect/resize.ts
const { sign, abs, min } = Math;
function getRectExtentPoint(rect, direction) {
const { minX, minY, maxX, maxY, midX, midY } = rect;
return {
x: direction.includes("w") ? minX : direction.includes("e") ? maxX : midX,
y: direction.includes("n") ? minY : direction.includes("s") ? maxY : midY
};
}
function getOppositeDirection(direction) {
return oppositeDirectionMap[direction];
}
function resizeRect(rect, offset, direction, opts) {
const { scalingOriginMode, lockAspectRatio } = opts;
const extent = getRectExtentPoint(rect, direction);
const oppositeExtent = getRectExtentPoint(rect, getOppositeDirection(direction));
if (scalingOriginMode === "center") offset = {
x: offset.x * 2,
y: offset.y * 2
};
const newExtent = {
x: extent.x + offset.x,
y: extent.y + offset.y
};
const multiplier = {
x: compassDirectionMap[direction].x * 2 - 1,
y: compassDirectionMap[direction].y * 2 - 1
};
const newSize = {
width: newExtent.x - oppositeExtent.x,
height: newExtent.y - oppositeExtent.y
};
const scaleX = multiplier.x * newSize.width / rect.width;
const scaleY = multiplier.y * newSize.height / rect.height;
const largestMagnitude = abs(scaleX) > abs(scaleY) ? scaleX : scaleY;
const scale = lockAspectRatio ? {
x: largestMagnitude,
y: largestMagnitude
} : {
x: extent.x === oppositeExtent.x ? 1 : scaleX,
y: extent.y === oppositeExtent.y ? 1 : scaleY
};
if (extent.y === oppositeExtent.y) scale.y = abs(scale.y);
else if (sign(scale.y) !== sign(scaleY)) scale.y *= -1;
if (extent.x === oppositeExtent.x) scale.x = abs(scale.x);
else if (sign(scale.x) !== sign(scaleX)) scale.x *= -1;
switch (scalingOriginMode) {
case "extent": return transformRect(rect, AffineTransform.scale(scale.x, scale.y, oppositeExtent), false);
case "center": return transformRect(rect, AffineTransform.scale(scale.x, scale.y, {
x: rect.midX,
y: rect.midY
}), false);
}
}
function createRectFromPoints(initialPoint, finalPoint, normalized = true) {
if (normalized) return {
x: min(finalPoint.x, initialPoint.x),
y: min(finalPoint.y, initialPoint.y),
width: abs(finalPoint.x - initialPoint.x),
height: abs(finalPoint.y - initialPoint.y)
};
return {
x: initialPoint.x,
y: initialPoint.y,
width: finalPoint.x - initialPoint.x,
height: finalPoint.y - initialPoint.y
};
}
function transformRect(rect, transform, normalized = true) {
return createRectFromPoints(transform.applyTo({
x: rect.minX,
y: rect.minY
}), transform.applyTo({
x: rect.maxX,
y: rect.maxY
}), normalized);
}
//#endregion
Object.defineProperty(exports, "AffineTransform", {
enumerable: true,
get: function() {
return AffineTransform;
}
});
Object.defineProperty(exports, "addPoints", {
enumerable: true,
get: function() {
return addPoints;
}
});
Object.defineProperty(exports, "alignRect", {
enumerable: true,
get: function() {
return alignRect;
}
});
Object.defineProperty(exports, "clampPoint", {
enumerable: true,
get: function() {
return clampPoint;
}
});
Object.defineProperty(exports, "clampSize", {
enumerable: true,
get: function() {
return clampSize;
}
});
Object.defineProperty(exports, "closest", {
enumerable: true,
get: function() {
return closest;
}
});
Object.defineProperty(exports, "closestSideToPoint", {
enumerable: true,
get: function() {
return closestSideToPoint;
}
});
Object.defineProperty(exports, "closestSideToRect", {
enumerable: true,
get: function() {
return closestSideToRect;
}
});
Object.defineProperty(exports, "collisions", {
enumerable: true,
get: function() {
return collisions;
}
});
Object.defineProperty(exports, "constrainRect", {
enumerable: true,
get: function() {
return constrainRect;
}
});
Object.defineProperty(exports, "contains", {
enumerable: true,
get: function() {
return contains;
}
});
Object.defineProperty(exports, "containsPoint", {
enumerable: true,
get: function() {
return containsPoint;
}
});
Object.defineProperty(exports, "containsRect", {
enumerable: true,
get: function() {
return containsRect;
}
});
Object.defineProperty(exports, "createPoint", {
enumerable: true,
get: function() {
return createPoint;
}
});
Object.defineProperty(exports, "createRect", {
enumerable: true,
get: function() {
return createRect;
}
});
Object.defineProperty(exports, "debugPolygon", {
enumerable: true,
get: function() {
return debugPolygon;
}
});
Object.defineProperty(exports, "distance", {
enumerable: true,
get: function() {
return distance;
}
});
Object.defineProperty(exports, "distanceBtwEdges", {
enumerable: true,
get: function() {
return distanceBtwEdges;
}
});
Object.defineProperty(exports, "distanceFromPoint", {
enumerable: true,
get: function() {
return distanceFromPoint;
}
});
Object.defineProperty(exports, "distanceFromRect", {
enumerable: true,
get: function() {
return distanceFromRect;
}
});
Object.defineProperty(exports, "expand", {
enumerable: true,
get: function() {
return expand;
}
});
Object.defineProperty(exports, "fromRange", {
enumerable: true,
get: function() {
return fromRange;
}
});
Object.defineProperty(exports, "getElementPolygon", {
enumerable: true,
get: function() {
return getElementPolygon;
}
});
Object.defineProperty(exports, "getElementRect", {
enumerable: true,
get: function() {
return getElementRect;
}
});
Object.defineProperty(exports, "getPointAngle", {
enumerable: true,
get: function() {
return getPointAngle;
}
});
Object.defineProperty(exports, "getRectCenters", {
enumerable: true,
get: function() {
return getRectCenters;
}
});
Object.defineProperty(exports, "getRectCorners", {
enumerable: true,
get: function() {
return getRectCorners;
}
});
Object.defineProperty(exports, "getRectEdges", {
enumerable: true,
get: function() {
return getRectEdges;
}
});
Object.defineProperty(exports, "getRectFromPoints", {
enumerable: true,
get: function() {
return getRectFromPoints;
}
});
Object.defineProperty(exports, "getRotationRect", {
enumerable: true,
get: function() {
return getRotationRect;
}
});
Object.defineProperty(exports, "getViewportRect", {
enumerable: true,
get: function() {
return getViewportRect;
}
});
Object.defineProperty(exports, "getWindowRect", {
enumerable: true,
get: function() {
return getWindowRect;
}
});
Object.defineProperty(exports, "inset", {
enumerable: true,
get: function() {
return inset;
}
});
Object.defineProperty(exports, "intersection", {
enumerable: true,
get: function() {
return intersection;
}
});
Object.defineProperty(exports, "intersects", {
enumerable: true,
get: function() {
return intersects;
}
});
Object.defineProperty(exports, "isPoint", {
enumerable: true,
get: function() {
return isPoint;
}
});
Object.defineProperty(exports, "isPointEqual", {
enumerable: true,
get: function() {
return isPointEqual;
}
});
Object.defineProperty(exports, "isPointInPolygon", {
enumerable: true,
get: function() {
return isPointInPolygon;
}
});
Object.defineProperty(exports, "isRect", {
enumerable: true,
get: function() {
return isRect;
}
});
Object.defineProperty(exports, "isRectEqual", {
enumerable: true,
get: function() {
return isRectEqual;
}
});
Object.defineProperty(exports, "isSizeEqual", {
enumerable: true,
get: function() {
return isSizeEqual;
}
});
Object.defineProperty(exports, "isSymmetric", {
enumerable: true,
get: function() {
return isSymmetric;
}
});
Object.defineProperty(exports, "resizeRect", {
enumerable: true,
get: function() {
return resizeRect;
}
});
Object.defineProperty(exports, "rotate", {
enumerable: true,
get: function() {
return rotate;
}
});
Object.defineProperty(exports, "shift", {
enumerable: true,
get: function() {
return shift;
}
});
Object.defineProperty(exports, "shrink", {
enumerable: true,
get: function() {
return shrink;
}
});
Object.defineProperty(exports, "subtractPoints", {
enumerable: true,
get: function() {
return subtractPoints;
}
});
Object.defineProperty(exports, "toRad", {
enumerable: true,
get: function() {
return toRad;
}
});
Object.defineProperty(exports, "union", {
enumerable: true,
get: function() {
return union;
}
});
//#region src/shared/rect/affine-transform.ts
var AffineTransform = class AffineTransform {
m00;
m01;
m02;
m10;
m11;
m12;
constructor([m00, m01, m02, m10, m11, m12] = [
0,
0,
0,
0,
0,
0
]) {
this.m00 = m00;
this.m01 = m01;
this.m02 = m02;
this.m10 = m10;
this.m11 = m11;
this.m12 = m12;
}
applyTo(point) {
const { x, y } = point;
const { m00, m01, m02, m10, m11, m12 } = this;
return {
x: m00 * x + m01 * y + m02,
y: m10 * x + m11 * y + m12
};
}
prepend(other) {
return new AffineTransform([
this.m00 * other.m00 + this.m01 * other.m10,
this.m00 * other.m01 + this.m01 * other.m11,
this.m00 * other.m02 + this.m01 * other.m12 + this.m02,
this.m10 * other.m00 + this.m11 * other.m10,
this.m10 * other.m01 + this.m11 * other.m11,
this.m10 * other.m02 + this.m11 * other.m12 + this.m12
]);
}
append(other) {
return new AffineTransform([
other.m00 * this.m00 + other.m01 * this.m10,
other.m00 * this.m01 + other.m01 * this.m11,
other.m00 * this.m02 + other.m01 * this.m12 + other.m02,
other.m10 * this.m00 + other.m11 * this.m10,
other.m10 * this.m01 + other.m11 * this.m11,
other.m10 * this.m02 + other.m11 * this.m12 + other.m12
]);
}
get determinant() {
return this.m00 * this.m11 - this.m01 * this.m10;
}
get isInvertible() {
const det = this.determinant;
return isFinite(det) && isFinite(this.m02) && isFinite(this.m12) && det !== 0;
}
invert() {
const det = this.determinant;
return new AffineTransform([
this.m11 / det,
-this.m01 / det,
(this.m01 * this.m12 - this.m11 * this.m02) / det,
-this.m10 / det,
this.m00 / det,
(this.m10 * this.m02 - this.m00 * this.m12) / det
]);
}
get array() {
return [
this.m00,
this.m01,
this.m02,
this.m10,
this.m11,
this.m12,
0,
0,
1
];
}
get float32Array() {
return new Float32Array(this.array);
}
static get identity() {
return new AffineTransform([
1,
0,
0,
0,
1,
0
]);
}
static rotate(theta, origin) {
const rotation = new AffineTransform([
Math.cos(theta),
-Math.sin(theta),
0,
Math.sin(theta),
Math.cos(theta),
0
]);
if (origin && (origin.x !== 0 || origin.y !== 0)) return AffineTransform.multiply(AffineTransform.translate(origin.x, origin.y), rotation, AffineTransform.translate(-origin.x, -origin.y));
return rotation;
}
rotate = (...args) => {
return this.prepend(AffineTransform.rotate(...args));
};
static scale(sx, sy = sx, origin = {
x: 0,
y: 0
}) {
const scale = new AffineTransform([
sx,
0,
0,
0,
sy,
0
]);
if (origin.x !== 0 || origin.y !== 0) return AffineTransform.multiply(AffineTransform.translate(origin.x, origin.y), scale, AffineTransform.translate(-origin.x, -origin.y));
return scale;
}
scale = (...args) => {
return this.prepend(AffineTransform.scale(...args));
};
static translate(tx, ty) {
return new AffineTransform([
1,
0,
tx,
0,
1,
ty
]);
}
translate = (...args) => {
return this.prepend(AffineTransform.translate(...args));
};
static multiply(...[first, ...rest]) {
if (!first) return AffineTransform.identity;
return rest.reduce((result, item) => result.prepend(item), first);
}
get a() {
return this.m00;
}
get b() {
return this.m10;
}
get c() {
return this.m01;
}
get d() {
return this.m11;
}
get tx() {
return this.m02;
}
get ty() {
return this.m12;
}
get scaleComponents() {
return {
x: this.a,
y: this.d
};
}
get translationComponents() {
return {
x: this.tx,
y: this.ty
};
}
get skewComponents() {
return {
x: this.c,
y: this.b
};
}
toString() {
return `matrix(${this.a}, ${this.b}, ${this.c}, ${this.d}, ${this.tx}, ${this.ty})`;
}
};
//#endregion
//#region src/shared/rect/align.ts
function hAlign(a, ref, h) {
let x = ref.minX;
if (h === "left-inside") x = ref.minX;
if (h === "left-outside") x = ref.minX - ref.width;
if (h === "right-inside") x = ref.maxX - ref.width;
if (h === "right-outside") x = ref.maxX;
if (h === "center") x = ref.midX - ref.width / 2;
return {
...a,
x
};
}
function vAlign(a, ref, v) {
let y = ref.minY;
if (v === "top-inside") y = ref.minY;
if (v === "top-outside") y = ref.minY - a.height;
if (v === "bottom-inside") y = ref.maxY - a.height;
if (v === "bottom-outside") y = ref.maxY;
if (v === "center") y = ref.midY - a.height / 2;
return {
...a,
y
};
}
function alignRect(a, ref, options) {
const { h, v } = options;
return vAlign(hAlign(a, ref, h), ref, v);
}
//#endregion
//#region src/shared/rect/angle.ts
function getPointAngle(rect, point, reference = rect.center) {
const x = point.x - reference.x;
const y = point.y - reference.y;
return 360 - (Math.atan2(x, y) * (180 / Math.PI) + 180);
}
//#endregion
//#region src/shared/rect/clamp.ts
const clamp = (value, min, max) => Math.min(Math.max(value, min), max);
const clampPoint = (position, size, boundaryRect) => {
return {
x: clamp(position.x, boundaryRect.x, boundaryRect.x + boundaryRect.width - size.width),
y: clamp(position.y, boundaryRect.y, boundaryRect.y + boundaryRect.height - size.height)
};
};
const defaultMinSize = {
width: 0,
height: 0
};
const defaultMaxSize = {
width: Infinity,
height: Infinity
};
const clampSize = (size, minSize = defaultMinSize, maxSize = defaultMaxSize) => {
return {
width: Math.min(Math.max(size.width, minSize.width), maxSize.width),
height: Math.min(Math.max(size.height, minSize.height), maxSize.height)
};
};
//#endregion
//#region src/shared/rect/rect.ts
const createPoint = (x, y) => ({
x,
y
});
const subtractPoints = (a, b) => {
if (!b) return a;
return createPoint(a.x - b.x, a.y - b.y);
};
const addPoints = (a, b) => createPoint(a.x + b.x, a.y + b.y);
function isPoint(v) {
return Reflect.has(v, "x") && Reflect.has(v, "y");
}
function createRect(r) {
const { x, y, width, height } = r;
const midX = x + width / 2;
const midY = y + height / 2;
return {
x,
y,
width,
height,
minX: x,
minY: y,
maxX: x + width,
maxY: y + height,
midX,
midY,
center: createPoint(midX, midY)
};
}
function isRect(v) {
return Reflect.has(v, "x") && Reflect.has(v, "y") && Reflect.has(v, "width") && Reflect.has(v, "height");
}
function getRectCenters(v) {
return {
top: createPoint(v.midX, v.minY),
right: createPoint(v.maxX, v.midY),
bottom: createPoint(v.midX, v.maxY),
left: createPoint(v.minX, v.midY)
};
}
function getRectCorners(v) {
return {
top: createPoint(v.minX, v.minY),
right: createPoint(v.maxX, v.minY),
bottom: createPoint(v.maxX, v.maxY),
left: createPoint(v.minX, v.maxY)
};
}
function getRectEdges(v) {
const c = getRectCorners(v);
return {
top: [c.top, c.right],
right: [c.right, c.bottom],
bottom: [c.left, c.bottom],
left: [c.top, c.left]
};
}
//#endregion
//#region src/shared/rect/intersection.ts
function intersects(a, b) {
return a.x < b.maxX && a.y < b.maxY && a.maxX > b.x && a.maxY > b.y;
}
function intersection(a, b) {
const x = Math.max(a.x, b.x);
const y = Math.max(a.y, b.y);
const x2 = Math.min(a.x + a.width, b.x + b.width);
const y2 = Math.min(a.y + a.height, b.y + b.height);
return createRect({
x,
y,
width: x2 - x,
height: y2 - y
});
}
function collisions(a, b) {
return {
top: a.minY <= b.minY,
right: a.maxX >= b.maxX,
bottom: a.maxY >= b.maxY,
left: a.minX <= b.minX
};
}
//#endregion
//#region src/shared/rect/distance.ts
function distance(a, b = {
x: 0,
y: 0
}) {
return Math.sqrt(Math.pow(a.x - b.x, 2) + Math.pow(a.y - b.y, 2));
}
function distanceFromPoint(r, p) {
let x = 0;
let y = 0;
if (p.x < r.x) x = r.x - p.x;
else if (p.x > r.maxX) x = p.x - r.maxX;
if (p.y < r.y) y = r.y - p.y;
else if (p.y > r.maxY) y = p.y - r.maxY;
return {
x,
y,
value: distance({
x,
y
})
};
}
function distanceFromRect(a, b) {
if (intersects(a, b)) return {
x: 0,
y: 0,
value: 0
};
const left = a.x < b.x ? a : b;
const right = b.x < a.x ? a : b;
const upper = a.y < b.y ? a : b;
const lower = b.y < a.y ? a : b;
let x = left.x === right.x ? 0 : right.x - left.maxX;
x = Math.max(0, x);
let y = upper.y === lower.y ? 0 : lower.y - upper.maxY;
y = Math.max(0, y);
return {
x,
y,
value: distance({
x,
y
})
};
}
function distanceBtwEdges(a, b) {
return {
left: b.x - a.x,
top: b.y - a.y,
right: a.maxX - b.maxX,
bottom: a.maxY - b.maxY
};
}
//#endregion
//#region src/shared/rect/closest.ts
function closest(...pts) {
return (a) => {
const ds = pts.map((b) => distance(b, a));
const c = Math.min.apply(Math, ds);
return pts[ds.indexOf(c)];
};
}
function closestSideToRect(ref, r) {
if (r.maxX <= ref.minX) return "left";
if (r.minX >= ref.maxX) return "right";
if (r.maxY <= ref.minY) return "top";
if (r.minY >= ref.maxY) return "bottom";
return "left";
}
function closestSideToPoint(ref, p) {
const { x, y } = p;
const dl = x - ref.minX;
const dr = ref.maxX - x;
const dt = y - ref.minY;
const db = ref.maxY - y;
let closest = dl;
let side = "left";
if (dr < closest) {
closest = dr;
side = "right";
}
if (dt < closest) {
closest = dt;
side = "top";
}
if (db < closest) side = "bottom";
return side;
}
//#endregion
//#region src/shared/rect/constrain.ts
const constrainRect = (rect, boundary) => {
return {
x: Math.max(boundary.x, Math.min(rect.x, boundary.x + boundary.width - rect.width)),
y: Math.max(boundary.y, Math.min(rect.y, boundary.y + boundary.height - rect.height)),
width: Math.min(rect.width, boundary.width),
height: Math.min(rect.height, boundary.height)
};
};
//#endregion
//#region src/shared/rect/contains.ts
function containsPoint(r, p) {
return r.minX <= p.x && p.x <= r.maxX && r.minY <= p.y && p.y <= r.maxY;
}
function containsRect(a, b) {
return Object.values(getRectCorners(b)).every((c) => containsPoint(a, c));
}
function contains(r, v) {
return isRect(v) ? containsRect(r, v) : containsPoint(r, v);
}
//#endregion
//#region src/shared/rect/equality.ts
const isSizeEqual = (a, b) => {
return a.width === b?.width && a.height === b?.height;
};
const isPointEqual = (a, b) => {
return a.x === b?.x && a.y === b?.y;
};
const isRectEqual = (a, b) => {
return isPointEqual(a, b) && isSizeEqual(a, b);
};
//#endregion
//#region src/shared/rect/from-element.ts
const styleCache = /* @__PURE__ */ new WeakMap();
function getCacheComputedStyle(el) {
if (!styleCache.has(el)) {
const win = el.ownerDocument.defaultView || window;
styleCache.set(el, win.getComputedStyle(el));
}
return styleCache.get(el);
}
function getElementRect(el, opts = {}) {
return createRect(getClientRect(el, opts));
}
function getClientRect(el, opts = {}) {
const { excludeScrollbar = false, excludeBorders = false } = opts;
const { x, y, width, height } = el.getBoundingClientRect();
const r = {
x,
y,
width,
height
};
const { borderLeftWidth, borderTopWidth, borderRightWidth, borderBottomWidth } = getCacheComputedStyle(el);
const borderXWidth = sum(borderLeftWidth, borderRightWidth);
const borderYWidth = sum(borderTopWidth, borderBottomWidth);
if (excludeBorders) {
r.width -= borderXWidth;
r.height -= borderYWidth;
r.x += px(borderLeftWidth);
r.y += px(borderTopWidth);
}
if (excludeScrollbar) {
const scrollbarWidth = el.offsetWidth - el.clientWidth - borderXWidth;
const scrollbarHeight = el.offsetHeight - el.clientHeight - borderYWidth;
r.width -= scrollbarWidth;
r.height -= scrollbarHeight;
}
return r;
}
const px = (v) => parseFloat(v.replace("px", ""));
const sum = (...vals) => vals.reduce((sum, v) => sum + (v ? px(v) : 0), 0);
//#endregion
//#region src/shared/rect/from-points.ts
function getRectFromPoints(...pts) {
const xs = pts.map((p) => p.x);
const ys = pts.map((p) => p.y);
const x = Math.min(...xs);
const y = Math.min(...ys);
return createRect({
x,
y,
width: Math.max(...xs) - x,
height: Math.max(...ys) - y
});
}
//#endregion
//#region src/shared/rect/union.ts
const { min: min$1, max } = Math;
function union(...rs) {
return getRectFromPoints({
x: min$1(...rs.map((r) => r.minX)),
y: min$1(...rs.map((r) => r.minY))
}, {
x: max(...rs.map((r) => r.maxX)),
y: max(...rs.map((r) => r.maxY))
});
}
//#endregion
//#region src/shared/rect/from-range.ts
function fromRange(range) {
let rs = [];
const rects = Array.from(range.getClientRects());
if (rects.length) {
rs = rs.concat(rects.map(createRect));
return union.apply(void 0, rs);
}
let start = range.startContainer;
if (start.nodeType === Node.TEXT_NODE) start = start.parentNode;
if (start instanceof HTMLElement) {
const r = getElementRect(start);
rs.push({
...r,
x: r.maxX,
width: 0
});
}
return union.apply(void 0, rs);
}
//#endregion
//#region src/shared/rect/from-rotation.ts
function toRad(d) {
return d % 360 * Math.PI / 180;
}
function rotate(a, d, c) {
const r = toRad(d);
const sin = Math.sin(r);
const cos = Math.cos(r);
const x = a.x - c.x;
const y = a.y - c.y;
return {
x: c.x + x * cos - y * sin,
y: c.y + x * sin + y * cos
};
}
function getRotationRect(r, deg) {
const rr = Object.values(getRectCorners(r)).map((p) => rotate(p, deg, r.center));
const xs = rr.map((p) => p.x);
const ys = rr.map((p) => p.y);
const minX = Math.min(...xs);
const minY = Math.min(...ys);
const maxX = Math.max(...xs);
const maxY = Math.max(...ys);
return createRect({
x: minX,
y: minY,
width: maxX - minX,
height: maxY - minY
});
}
//#endregion
//#region src/shared/rect/from-window.ts
function getWindowRect(win, opts = {}) {
return createRect(getViewportRect(win, opts));
}
function getViewportRect(win, opts) {
const { excludeScrollbar = false } = opts;
const { innerWidth, innerHeight, document: doc, visualViewport } = win;
const rect = {
x: 0,
y: 0,
width: visualViewport?.width || innerWidth,
height: visualViewport?.height || innerHeight
};
if (excludeScrollbar) {
const scrollbarWidth = innerWidth - doc.documentElement.clientWidth;
const scrollbarHeight = innerHeight - doc.documentElement.clientHeight;
rect.width -= scrollbarWidth;
rect.height -= scrollbarHeight;
}
return rect;
}
//#endregion
//#region src/shared/rect/operations.ts
const isSymmetric = (v) => "dx" in v || "dy" in v;
function inset(r, i) {
const { top = 0, right = 0, bottom = 0, left = 0 } = isSymmetric(i) ? {
left: i.dx,
right: i.dx,
top: i.dy,
bottom: i.dy
} : i;
return createRect({
x: r.x + left,
y: r.y + top,
width: r.width - left - right,
height: r.height - top - bottom
});
}
function expand(r, v) {
return inset(r, typeof v === "number" ? {
dx: -v,
dy: -v
} : v);
}
function shrink(r, v) {
return inset(r, typeof v === "number" ? {
dx: -v,
dy: -v
} : v);
}
function shift(r, o) {
const { x = 0, y = 0 } = o;
return createRect({
x: r.x + x,
y: r.y + y,
width: r.width,
height: r.height
});
}
//#endregion
//#region src/shared/rect/polygon.ts
function getElementPolygon(rectValue, placement) {
const { top, right, left, bottom } = getRectCorners(createRect(rectValue));
const [base] = placement.split("-");
return {
top: [
left,
top,
right,
bottom
],
right: [
top,
right,
bottom,
left
],
bottom: [
top,
left,
bottom,
right
],
left: [
right,
top,
left,
bottom
]
}[base];
}
function isPointInPolygon(polygon, point) {
const { x, y } = point;
let c = false;
for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
const xi = polygon[i].x;
const yi = polygon[i].y;
const xj = polygon[j].x;
const yj = polygon[j].y;
if (yi > y !== yj > y && x < (xj - xi) * (y - yi) / (yj - yi) + xi) c = !c;
}
return c;
}
function createPolygonElement() {
const id = "debug-polygon";
const existingPolygon = document.getElementById(id);
if (existingPolygon) return existingPolygon;
const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
Object.assign(svg.style, {
top: "0",
left: "0",
width: "100%",
height: "100%",
opacity: "0.15",
position: "fixed",
pointerEvents: "none",
fill: "red"
});
const polygon = document.createElementNS("http://www.w3.org/2000/svg", "polygon");
polygon.setAttribute("id", id);
polygon.setAttribute("points", "0,0 0,0");
svg.appendChild(polygon);
document.body.appendChild(svg);
return polygon;
}
function debugPolygon(polygon) {
const el = createPolygonElement();
const points = polygon.map((point) => `${point.x},${point.y}`).join(" ");
el.setAttribute("points", points);
return () => {
el.remove();
};
}
//#endregion
//#region src/shared/rect/compass.ts
const compassDirectionMap = {
n: {
x: .5,
y: 0
},
ne: {
x: 1,
y: 0
},
e: {
x: 1,
y: .5
},
se: {
x: 1,
y: 1
},
s: {
x: .5,
y: 1
},
sw: {
x: 0,
y: 1
},
w: {
x: 0,
y: .5
},
nw: {
x: 0,
y: 0
}
};
const oppositeDirectionMap = {
n: "s",
ne: "sw",
e: "w",
se: "nw",
s: "n",
sw: "ne",
w: "e",
nw: "se"
};
//#endregion
//#region src/shared/rect/resize.ts
const { sign, abs, min } = Math;
function getRectExtentPoint(rect, direction) {
const { minX, minY, maxX, maxY, midX, midY } = rect;
return {
x: direction.includes("w") ? minX : direction.includes("e") ? maxX : midX,
y: direction.includes("n") ? minY : direction.includes("s") ? maxY : midY
};
}
function getOppositeDirection(direction) {
return oppositeDirectionMap[direction];
}
function resizeRect(rect, offset, direction, opts) {
const { scalingOriginMode, lockAspectRatio } = opts;
const extent = getRectExtentPoint(rect, direction);
const oppositeExtent = getRectExtentPoint(rect, getOppositeDirection(direction));
if (scalingOriginMode === "center") offset = {
x: offset.x * 2,
y: offset.y * 2
};
const newExtent = {
x: extent.x + offset.x,
y: extent.y + offset.y
};
const multiplier = {
x: compassDirectionMap[direction].x * 2 - 1,
y: compassDirectionMap[direction].y * 2 - 1
};
const newSize = {
width: newExtent.x - oppositeExtent.x,
height: newExtent.y - oppositeExtent.y
};
const scaleX = multiplier.x * newSize.width / rect.width;
const scaleY = multiplier.y * newSize.height / rect.height;
const largestMagnitude = abs(scaleX) > abs(scaleY) ? scaleX : scaleY;
const scale = lockAspectRatio ? {
x: largestMagnitude,
y: largestMagnitude
} : {
x: extent.x === oppositeExtent.x ? 1 : scaleX,
y: extent.y === oppositeExtent.y ? 1 : scaleY
};
if (extent.y === oppositeExtent.y) scale.y = abs(scale.y);
else if (sign(scale.y) !== sign(scaleY)) scale.y *= -1;
if (extent.x === oppositeExtent.x) scale.x = abs(scale.x);
else if (sign(scale.x) !== sign(scaleX)) scale.x *= -1;
switch (scalingOriginMode) {
case "extent": return transformRect(rect, AffineTransform.scale(scale.x, scale.y, oppositeExtent), false);
case "center": return transformRect(rect, AffineTransform.scale(scale.x, scale.y, {
x: rect.midX,
y: rect.midY
}), false);
}
}
function createRectFromPoints(initialPoint, finalPoint, normalized = true) {
if (normalized) return {
x: min(finalPoint.x, initialPoint.x),
y: min(finalPoint.y, initialPoint.y),
width: abs(finalPoint.x - initialPoint.x),
height: abs(finalPoint.y - initialPoint.y)
};
return {
x: initialPoint.x,
y: initialPoint.y,
width: finalPoint.x - initialPoint.x,
height: finalPoint.y - initialPoint.y
};
}
function transformRect(rect, transform, normalized = true) {
return createRectFromPoints(transform.applyTo({
x: rect.minX,
y: rect.minY
}), transform.applyTo({
x: rect.maxX,
y: rect.maxY
}), normalized);
}
//#endregion
export { distanceBtwEdges as A, getRectCorners as B, containsPoint as C, closestSideToPoint as D, closest as E, intersects as F, clampPoint as G, isPoint as H, addPoints as I, alignRect as J, clampSize as K, createPoint as L, distanceFromRect as M, collisions as N, closestSideToRect as O, intersection as P, createRect as R, contains as S, constrainRect as T, isRect as U, getRectEdges as V, subtractPoints as W, AffineTransform as Y, getRectFromPoints as _, expand as a, isRectEqual as b, shift as c, getWindowRect as d, getRotationRect as f, union as g, fromRange as h, isPointInPolygon as i, distanceFromPoint as j, distance as k, shrink as l, toRad as m, debugPolygon as n, inset as o, rotate as p, getPointAngle as q, getElementPolygon as r, isSymmetric as s, resizeRect as t, getViewportRect as u, getElementRect as v, containsRect as w, isSizeEqual as x, isPointEqual as y, getRectCenters as z };
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_rect = require("./rect-CmICnPlW.cjs");
exports.AffineTransform = require_rect.AffineTransform;
exports.addPoints = require_rect.addPoints;
exports.alignRect = require_rect.alignRect;
exports.clampPoint = require_rect.clampPoint;
exports.clampSize = require_rect.clampSize;
exports.closest = require_rect.closest;
exports.closestSideToPoint = require_rect.closestSideToPoint;
exports.closestSideToRect = require_rect.closestSideToRect;
exports.collisions = require_rect.collisions;
exports.constrainRect = require_rect.constrainRect;
exports.contains = require_rect.contains;
exports.containsPoint = require_rect.containsPoint;
exports.containsRect = require_rect.containsRect;
exports.createPoint = require_rect.createPoint;
exports.createRect = require_rect.createRect;
exports.debugPolygon = require_rect.debugPolygon;
exports.distance = require_rect.distance;
exports.distanceBtwEdges = require_rect.distanceBtwEdges;
exports.distanceFromPoint = require_rect.distanceFromPoint;
exports.distanceFromRect = require_rect.distanceFromRect;
exports.expand = require_rect.expand;
exports.fromRange = require_rect.fromRange;
exports.getElementPolygon = require_rect.getElementPolygon;
exports.getElementRect = require_rect.getElementRect;
exports.getPointAngle = require_rect.getPointAngle;
exports.getRectCenters = require_rect.getRectCenters;
exports.getRectCorners = require_rect.getRectCorners;
exports.getRectEdges = require_rect.getRectEdges;
exports.getRectFromPoints = require_rect.getRectFromPoints;
exports.getRotationRect = require_rect.getRotationRect;
exports.getViewportRect = require_rect.getViewportRect;
exports.getWindowRect = require_rect.getWindowRect;
exports.inset = require_rect.inset;
exports.intersection = require_rect.intersection;
exports.intersects = require_rect.intersects;
exports.isPoint = require_rect.isPoint;
exports.isPointEqual = require_rect.isPointEqual;
exports.isPointInPolygon = require_rect.isPointInPolygon;
exports.isRect = require_rect.isRect;
exports.isRectEqual = require_rect.isRectEqual;
exports.isSizeEqual = require_rect.isSizeEqual;
exports.isSymmetric = require_rect.isSymmetric;
exports.resizeRect = require_rect.resizeRect;
exports.rotate = require_rect.rotate;
exports.shift = require_rect.shift;
exports.shrink = require_rect.shrink;
exports.subtractPoints = require_rect.subtractPoints;
exports.toRad = require_rect.toRad;
exports.union = require_rect.union;
import { _ as RectSide, a as Point, b as SymmetricRectInset, c as RectCenters, d as RectEdge, f as RectEdges, g as RectPoints, h as RectPoint, i as HAlign, l as RectCorner, m as RectInset, n as Bounds, o as Rect, p as RectInit, r as CenterPoint, s as RectCenter, t as AlignOptions, u as RectCorners, v as ScalingOptions, x as VAlign, y as Size } from "./types-B9xonIdT.cjs";
//#region src/shared/rect/affine-transform.d.ts
declare class AffineTransform {
m00: number;
m01: number;
m02: number;
m10: number;
m11: number;
m12: number;
constructor([m00, m01, m02, m10, m11, m12]?: Iterable<number>);
applyTo(point: Point): Point;
prepend(other: AffineTransform): AffineTransform;
append(other: AffineTransform): AffineTransform;
get determinant(): number;
get isInvertible(): boolean;
invert(): AffineTransform;
get array(): number[];
get float32Array(): Float32Array;
static get identity(): AffineTransform;
static rotate(theta: number, origin?: Point): AffineTransform;
rotate: (typeof AffineTransform)["rotate"];
static scale(sx: number, sy?: number, origin?: Point): AffineTransform;
scale: (typeof AffineTransform)["scale"];
static translate(tx: number, ty: number): AffineTransform;
translate: (typeof AffineTransform)["translate"];
static multiply(...[first, ...rest]: AffineTransform[]): AffineTransform;
get a(): number;
get b(): number;
get c(): number;
get d(): number;
get tx(): number;
get ty(): number;
get scaleComponents(): Point;
get translationComponents(): Point;
get skewComponents(): Point;
toString(): string;
}
//#endregion
//#region src/shared/rect/align.d.ts
declare function alignRect(a: Rect, ref: Rect, options: AlignOptions): Rect;
//#endregion
//#region src/shared/rect/angle.d.ts
declare function getPointAngle(rect: Rect, point: Point, reference?: Point): number;
//#endregion
//#region src/shared/rect/clamp.d.ts
declare const clampPoint: (position: Point, size: Size, boundaryRect: RectInit) => {
x: number;
y: number;
};
declare const clampSize: (size: Size, minSize?: Size, maxSize?: Size) => {
width: number;
height: number;
};
//#endregion
//#region src/shared/rect/closest.d.ts
declare function closest(...pts: Point[]): (a: Point) => Point;
declare function closestSideToRect(ref: Rect, r: Rect): RectSide;
declare function closestSideToPoint(ref: Rect, p: Point): RectSide;
//#endregion
//#region src/shared/rect/constrain.d.ts
declare const constrainRect: (rect: RectInit, boundary: RectInit) => RectInit;
//#endregion
//#region src/shared/rect/contains.d.ts
declare function containsPoint(r: Rect, p: Point): boolean;
declare function containsRect(a: Rect, b: Rect): boolean;
declare function contains(r: Rect, v: Rect | Point): boolean;
//#endregion
//#region src/shared/rect/distance.d.ts
interface DistanceValue extends Point {
value: number;
}
declare function distance(a: Point, b?: Point): number;
declare function distanceFromPoint(r: Rect, p: Point): DistanceValue;
declare function distanceFromRect(a: Rect, b: Rect): DistanceValue;
declare function distanceBtwEdges(a: Rect, b: Rect): Record<RectSide, number>;
//#endregion
//#region src/shared/rect/equality.d.ts
declare const isSizeEqual: (a: Size, b: Size | undefined) => boolean;
declare const isPointEqual: (a: Point, b: Point | undefined) => boolean;
declare const isRectEqual: (a: RectInit, b: RectInit | undefined) => boolean;
//#endregion
//#region src/shared/rect/from-element.d.ts
declare function getElementRect(el: HTMLElement, opts?: ElementRectOptions): Rect;
type ElementRectOptions = {
excludeScrollbar?: boolean | undefined;
excludeBorders?: boolean | undefined;
};
//#endregion
//#region src/shared/rect/from-points.d.ts
declare function getRectFromPoints(...pts: Point[]): Rect;
//#endregion
//#region src/shared/rect/from-range.d.ts
declare function fromRange(range: Range): Rect;
//#endregion
//#region src/shared/rect/from-rotation.d.ts
declare function toRad(d: number): number;
declare function rotate(a: Point, d: number, c: Point): Point;
declare function getRotationRect(r: Rect, deg: number): Rect;
//#endregion
//#region src/shared/rect/from-window.d.ts
type WindowRectOptions = {
excludeScrollbar?: boolean | undefined;
};
declare function getWindowRect(win: Window, opts?: WindowRectOptions): Rect;
declare function getViewportRect(win: Window, opts: WindowRectOptions): {
x: number;
y: number;
width: number;
height: number;
};
//#endregion
//#region src/shared/rect/intersection.d.ts
declare function intersects(a: Rect, b: Rect): boolean;
declare function intersection(a: Rect, b: Rect): Rect;
declare function collisions(a: Rect, b: Rect): Record<RectSide, boolean>;
//#endregion
//#region src/shared/rect/operations.d.ts
declare const isSymmetric: (v: any) => v is SymmetricRectInset;
declare function inset(r: Rect, i: RectInset | SymmetricRectInset): Rect;
declare function expand(r: Rect, v: number | SymmetricRectInset): Rect;
declare function shrink(r: Rect, v: number | SymmetricRectInset): Rect;
declare function shift(r: Rect, o: Partial<Point>): Rect;
//#endregion
//#region src/shared/rect/polygon.d.ts
declare function getElementPolygon(rectValue: RectInit, placement: string): {
x: number;
y: number;
}[] | undefined;
declare function isPointInPolygon(polygon: Point[], point: Point): boolean;
declare function debugPolygon(polygon: Point[]): () => void;
//#endregion
//#region src/shared/rect/rect.d.ts
declare const createPoint: (x: number, y: number) => {
x: number;
y: number;
};
declare const subtractPoints: (a: Point, b: Point | null) => Point;
declare const addPoints: (a: Point, b: Point) => {
x: number;
y: number;
};
declare function isPoint(v: any): v is Point;
declare function createRect(r: RectInit): Rect;
declare function isRect(v: any): v is Rect;
declare function getRectCenters(v: Rect): {
top: {
x: number;
y: number;
};
right: {
x: number;
y: number;
};
bottom: {
x: number;
y: number;
};
left: {
x: number;
y: number;
};
};
declare function getRectCorners(v: Rect): {
top: {
x: number;
y: number;
};
right: {
x: number;
y: number;
};
bottom: {
x: number;
y: number;
};
left: {
x: number;
y: number;
};
};
declare function getRectEdges(v: Rect): {
top: RectEdge;
right: RectEdge;
bottom: RectEdge;
left: RectEdge;
};
//#endregion
//#region src/shared/rect/compass.d.ts
type CompassDirection = "n" | "ne" | "e" | "se" | "s" | "sw" | "w" | "nw";
//#endregion
//#region src/shared/rect/resize.d.ts
declare function resizeRect(rect: Rect, offset: Point, direction: CompassDirection, opts: ScalingOptions): RectInit;
//#endregion
//#region src/shared/rect/union.d.ts
declare function union(...rs: Rect[]): Rect;
//#endregion
export { AffineTransform, AlignOptions, Bounds, CenterPoint, DistanceValue, ElementRectOptions, HAlign, Point, Rect, RectCenter, RectCenters, RectCorner, RectCorners, RectEdge, RectEdges, RectInit, RectInset, RectPoint, RectPoints, RectSide, ScalingOptions, Size, SymmetricRectInset, VAlign, WindowRectOptions, addPoints, alignRect, clampPoint, clampSize, closest, closestSideToPoint, closestSideToRect, collisions, constrainRect, contains, containsPoint, containsRect, createPoint, createRect, debugPolygon, distance, distanceBtwEdges, distanceFromPoint, distanceFromRect, expand, fromRange, getElementPolygon, getElementRect, getPointAngle, getRectCenters, getRectCorners, getRectEdges, getRectFromPoints, getRotationRect, getViewportRect, getWindowRect, inset, intersection, intersects, isPoint, isPointEqual, isPointInPolygon, isRect, isRectEqual, isSizeEqual, isSymmetric, resizeRect, rotate, shift, shrink, subtractPoints, toRad, union };
import { _ as RectSide, a as Point, b as SymmetricRectInset, c as RectCenters, d as RectEdge, f as RectEdges, g as RectPoints, h as RectPoint, i as HAlign, l as RectCorner, m as RectInset, n as Bounds, o as Rect, p as RectInit, r as CenterPoint, s as RectCenter, t as AlignOptions, u as RectCorners, v as ScalingOptions, x as VAlign, y as Size } from "./types-CSqOdFYb.mjs";
//#region src/shared/rect/affine-transform.d.ts
declare class AffineTransform {
m00: number;
m01: number;
m02: number;
m10: number;
m11: number;
m12: number;
constructor([m00, m01, m02, m10, m11, m12]?: Iterable<number>);
applyTo(point: Point): Point;
prepend(other: AffineTransform): AffineTransform;
append(other: AffineTransform): AffineTransform;
get determinant(): number;
get isInvertible(): boolean;
invert(): AffineTransform;
get array(): number[];
get float32Array(): Float32Array;
static get identity(): AffineTransform;
static rotate(theta: number, origin?: Point): AffineTransform;
rotate: (typeof AffineTransform)["rotate"];
static scale(sx: number, sy?: number, origin?: Point): AffineTransform;
scale: (typeof AffineTransform)["scale"];
static translate(tx: number, ty: number): AffineTransform;
translate: (typeof AffineTransform)["translate"];
static multiply(...[first, ...rest]: AffineTransform[]): AffineTransform;
get a(): number;
get b(): number;
get c(): number;
get d(): number;
get tx(): number;
get ty(): number;
get scaleComponents(): Point;
get translationComponents(): Point;
get skewComponents(): Point;
toString(): string;
}
//#endregion
//#region src/shared/rect/align.d.ts
declare function alignRect(a: Rect, ref: Rect, options: AlignOptions): Rect;
//#endregion
//#region src/shared/rect/angle.d.ts
declare function getPointAngle(rect: Rect, point: Point, reference?: Point): number;
//#endregion
//#region src/shared/rect/clamp.d.ts
declare const clampPoint: (position: Point, size: Size, boundaryRect: RectInit) => {
x: number;
y: number;
};
declare const clampSize: (size: Size, minSize?: Size, maxSize?: Size) => {
width: number;
height: number;
};
//#endregion
//#region src/shared/rect/closest.d.ts
declare function closest(...pts: Point[]): (a: Point) => Point;
declare function closestSideToRect(ref: Rect, r: Rect): RectSide;
declare function closestSideToPoint(ref: Rect, p: Point): RectSide;
//#endregion
//#region src/shared/rect/constrain.d.ts
declare const constrainRect: (rect: RectInit, boundary: RectInit) => RectInit;
//#endregion
//#region src/shared/rect/contains.d.ts
declare function containsPoint(r: Rect, p: Point): boolean;
declare function containsRect(a: Rect, b: Rect): boolean;
declare function contains(r: Rect, v: Rect | Point): boolean;
//#endregion
//#region src/shared/rect/distance.d.ts
interface DistanceValue extends Point {
value: number;
}
declare function distance(a: Point, b?: Point): number;
declare function distanceFromPoint(r: Rect, p: Point): DistanceValue;
declare function distanceFromRect(a: Rect, b: Rect): DistanceValue;
declare function distanceBtwEdges(a: Rect, b: Rect): Record<RectSide, number>;
//#endregion
//#region src/shared/rect/equality.d.ts
declare const isSizeEqual: (a: Size, b: Size | undefined) => boolean;
declare const isPointEqual: (a: Point, b: Point | undefined) => boolean;
declare const isRectEqual: (a: RectInit, b: RectInit | undefined) => boolean;
//#endregion
//#region src/shared/rect/from-element.d.ts
declare function getElementRect(el: HTMLElement, opts?: ElementRectOptions): Rect;
type ElementRectOptions = {
excludeScrollbar?: boolean | undefined;
excludeBorders?: boolean | undefined;
};
//#endregion
//#region src/shared/rect/from-points.d.ts
declare function getRectFromPoints(...pts: Point[]): Rect;
//#endregion
//#region src/shared/rect/from-range.d.ts
declare function fromRange(range: Range): Rect;
//#endregion
//#region src/shared/rect/from-rotation.d.ts
declare function toRad(d: number): number;
declare function rotate(a: Point, d: number, c: Point): Point;
declare function getRotationRect(r: Rect, deg: number): Rect;
//#endregion
//#region src/shared/rect/from-window.d.ts
type WindowRectOptions = {
excludeScrollbar?: boolean | undefined;
};
declare function getWindowRect(win: Window, opts?: WindowRectOptions): Rect;
declare function getViewportRect(win: Window, opts: WindowRectOptions): {
x: number;
y: number;
width: number;
height: number;
};
//#endregion
//#region src/shared/rect/intersection.d.ts
declare function intersects(a: Rect, b: Rect): boolean;
declare function intersection(a: Rect, b: Rect): Rect;
declare function collisions(a: Rect, b: Rect): Record<RectSide, boolean>;
//#endregion
//#region src/shared/rect/operations.d.ts
declare const isSymmetric: (v: any) => v is SymmetricRectInset;
declare function inset(r: Rect, i: RectInset | SymmetricRectInset): Rect;
declare function expand(r: Rect, v: number | SymmetricRectInset): Rect;
declare function shrink(r: Rect, v: number | SymmetricRectInset): Rect;
declare function shift(r: Rect, o: Partial<Point>): Rect;
//#endregion
//#region src/shared/rect/polygon.d.ts
declare function getElementPolygon(rectValue: RectInit, placement: string): {
x: number;
y: number;
}[] | undefined;
declare function isPointInPolygon(polygon: Point[], point: Point): boolean;
declare function debugPolygon(polygon: Point[]): () => void;
//#endregion
//#region src/shared/rect/rect.d.ts
declare const createPoint: (x: number, y: number) => {
x: number;
y: number;
};
declare const subtractPoints: (a: Point, b: Point | null) => Point;
declare const addPoints: (a: Point, b: Point) => {
x: number;
y: number;
};
declare function isPoint(v: any): v is Point;
declare function createRect(r: RectInit): Rect;
declare function isRect(v: any): v is Rect;
declare function getRectCenters(v: Rect): {
top: {
x: number;
y: number;
};
right: {
x: number;
y: number;
};
bottom: {
x: number;
y: number;
};
left: {
x: number;
y: number;
};
};
declare function getRectCorners(v: Rect): {
top: {
x: number;
y: number;
};
right: {
x: number;
y: number;
};
bottom: {
x: number;
y: number;
};
left: {
x: number;
y: number;
};
};
declare function getRectEdges(v: Rect): {
top: RectEdge;
right: RectEdge;
bottom: RectEdge;
left: RectEdge;
};
//#endregion
//#region src/shared/rect/compass.d.ts
type CompassDirection = "n" | "ne" | "e" | "se" | "s" | "sw" | "w" | "nw";
//#endregion
//#region src/shared/rect/resize.d.ts
declare function resizeRect(rect: Rect, offset: Point, direction: CompassDirection, opts: ScalingOptions): RectInit;
//#endregion
//#region src/shared/rect/union.d.ts
declare function union(...rs: Rect[]): Rect;
//#endregion
export { AffineTransform, AlignOptions, Bounds, CenterPoint, DistanceValue, ElementRectOptions, HAlign, Point, Rect, RectCenter, RectCenters, RectCorner, RectCorners, RectEdge, RectEdges, RectInit, RectInset, RectPoint, RectPoints, RectSide, ScalingOptions, Size, SymmetricRectInset, VAlign, WindowRectOptions, addPoints, alignRect, clampPoint, clampSize, closest, closestSideToPoint, closestSideToRect, collisions, constrainRect, contains, containsPoint, containsRect, createPoint, createRect, debugPolygon, distance, distanceBtwEdges, distanceFromPoint, distanceFromRect, expand, fromRange, getElementPolygon, getElementRect, getPointAngle, getRectCenters, getRectCorners, getRectEdges, getRectFromPoints, getRotationRect, getViewportRect, getWindowRect, inset, intersection, intersects, isPoint, isPointEqual, isPointInPolygon, isRect, isRectEqual, isSizeEqual, isSymmetric, resizeRect, rotate, shift, shrink, subtractPoints, toRad, union };
import { A as distanceBtwEdges, B as getRectCorners, C as containsPoint, D as closestSideToPoint, E as closest, F as intersects, G as clampPoint, H as isPoint, I as addPoints, J as alignRect, K as clampSize, L as createPoint, M as distanceFromRect, N as collisions, O as closestSideToRect, P as intersection, R as createRect, S as contains, T as constrainRect, U as isRect, V as getRectEdges, W as subtractPoints, Y as AffineTransform, _ as getRectFromPoints, a as expand, b as isRectEqual, c as shift, d as getWindowRect, f as getRotationRect, g as union, h as fromRange, i as isPointInPolygon, j as distanceFromPoint, k as distance, l as shrink, m as toRad, n as debugPolygon, o as inset, p as rotate, q as getPointAngle, r as getElementPolygon, s as isSymmetric, t as resizeRect, u as getViewportRect, v as getElementRect, w as containsRect, x as isSizeEqual, y as isPointEqual, z as getRectCenters } from "./rect-JcwJCZkp.mjs";
export { AffineTransform, addPoints, alignRect, clampPoint, clampSize, closest, closestSideToPoint, closestSideToRect, collisions, constrainRect, contains, containsPoint, containsRect, createPoint, createRect, debugPolygon, distance, distanceBtwEdges, distanceFromPoint, distanceFromRect, expand, fromRange, getElementPolygon, getElementRect, getPointAngle, getRectCenters, getRectCorners, getRectEdges, getRectFromPoints, getRotationRect, getViewportRect, getWindowRect, inset, intersection, intersects, isPoint, isPointEqual, isPointInPolygon, isRect, isRectEqual, isSizeEqual, isSymmetric, resizeRect, rotate, shift, shrink, subtractPoints, toRad, union };
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_dom_query = require("./dom-query-BT6fffRP.cjs");
//#region src/shared/remove-scroll/index.ts
const LOCK_CLASSNAME = "data-scroll-lock";
const lockMap = /* @__PURE__ */ new WeakMap();
function getPaddingProperty(documentElement) {
const documentLeft = documentElement.getBoundingClientRect().left;
return Math.round(documentLeft) + documentElement.scrollLeft ? "paddingLeft" : "paddingRight";
}
function hasStableScrollbarGutter(element) {
const scrollbarGutter = require_dom_query.getComputedStyle(element)?.scrollbarGutter;
return scrollbarGutter === "stable" || scrollbarGutter?.startsWith("stable ") === true;
}
function applyLock(doc) {
const win = doc.defaultView ?? window;
const { documentElement, body } = doc;
const hasStableGutter = hasStableScrollbarGutter(documentElement) || hasStableScrollbarGutter(body);
const scrollbarWidth = win.innerWidth - documentElement.clientWidth;
body.setAttribute(LOCK_CLASSNAME, "");
const setScrollbarWidthProperty = () => require_dom_query.setStyleProperty(documentElement, "--scrollbar-width", `${scrollbarWidth}px`);
const paddingProperty = getPaddingProperty(documentElement);
const setBodyStyle = () => {
const styles = { overflow: "hidden" };
if (!hasStableGutter && scrollbarWidth > 0) styles[paddingProperty] = `${scrollbarWidth}px`;
return require_dom_query.setStyle(body, styles);
};
const setBodyStyleIOS = () => {
const { scrollX, scrollY, visualViewport } = win;
const offsetLeft = visualViewport?.offsetLeft ?? 0;
const offsetTop = visualViewport?.offsetTop ?? 0;
const styles = {
position: "fixed",
overflow: "hidden",
top: `${-(scrollY - Math.floor(offsetTop))}px`,
left: `${-(scrollX - Math.floor(offsetLeft))}px`,
right: "0"
};
if (!hasStableGutter && scrollbarWidth > 0) styles[paddingProperty] = `${scrollbarWidth}px`;
const restoreStyle = require_dom_query.setStyle(body, styles);
return () => {
restoreStyle?.();
win.scrollTo({
left: scrollX,
top: scrollY,
behavior: "instant"
});
};
};
const cleanups = [setScrollbarWidthProperty(), require_dom_query.isIos() ? setBodyStyleIOS() : setBodyStyle()];
return () => {
cleanups.forEach((fn) => fn?.());
body.removeAttribute(LOCK_CLASSNAME);
};
}
function preventBodyScroll(_document) {
const doc = _document ?? document;
let state = lockMap.get(doc);
if (!state) {
state = {
count: 0,
cleanup: applyLock(doc)
};
lockMap.set(doc, state);
}
state.count++;
const lockState = state;
let released = false;
return () => {
if (released) return;
released = true;
lockState.count--;
if (lockState.count === 0) {
lockState.cleanup();
lockMap.delete(doc);
}
};
}
//#endregion
exports.preventBodyScroll = preventBodyScroll;
//#region src/shared/remove-scroll/index.d.ts
declare function preventBodyScroll(_document?: Document): VoidFunction;
//#endregion
export { preventBodyScroll };
//#region src/shared/remove-scroll/index.d.ts
declare function preventBodyScroll(_document?: Document): VoidFunction;
//#endregion
export { preventBodyScroll };
import { $t as getComputedStyle, Bt as isIos, d as setStyleProperty, u as setStyle } from "./dom-query-BgxIO7_X.mjs";
//#region src/shared/remove-scroll/index.ts
const LOCK_CLASSNAME = "data-scroll-lock";
const lockMap = /* @__PURE__ */ new WeakMap();
function getPaddingProperty(documentElement) {
const documentLeft = documentElement.getBoundingClientRect().left;
return Math.round(documentLeft) + documentElement.scrollLeft ? "paddingLeft" : "paddingRight";
}
function hasStableScrollbarGutter(element) {
const scrollbarGutter = getComputedStyle(element)?.scrollbarGutter;
return scrollbarGutter === "stable" || scrollbarGutter?.startsWith("stable ") === true;
}
function applyLock(doc) {
const win = doc.defaultView ?? window;
const { documentElement, body } = doc;
const hasStableGutter = hasStableScrollbarGutter(documentElement) || hasStableScrollbarGutter(body);
const scrollbarWidth = win.innerWidth - documentElement.clientWidth;
body.setAttribute(LOCK_CLASSNAME, "");
const setScrollbarWidthProperty = () => setStyleProperty(documentElement, "--scrollbar-width", `${scrollbarWidth}px`);
const paddingProperty = getPaddingProperty(documentElement);
const setBodyStyle = () => {
const styles = { overflow: "hidden" };
if (!hasStableGutter && scrollbarWidth > 0) styles[paddingProperty] = `${scrollbarWidth}px`;
return setStyle(body, styles);
};
const setBodyStyleIOS = () => {
const { scrollX, scrollY, visualViewport } = win;
const offsetLeft = visualViewport?.offsetLeft ?? 0;
const offsetTop = visualViewport?.offsetTop ?? 0;
const styles = {
position: "fixed",
overflow: "hidden",
top: `${-(scrollY - Math.floor(offsetTop))}px`,
left: `${-(scrollX - Math.floor(offsetLeft))}px`,
right: "0"
};
if (!hasStableGutter && scrollbarWidth > 0) styles[paddingProperty] = `${scrollbarWidth}px`;
const restoreStyle = setStyle(body, styles);
return () => {
restoreStyle?.();
win.scrollTo({
left: scrollX,
top: scrollY,
behavior: "instant"
});
};
};
const cleanups = [setScrollbarWidthProperty(), isIos() ? setBodyStyleIOS() : setBodyStyle()];
return () => {
cleanups.forEach((fn) => fn?.());
body.removeAttribute(LOCK_CLASSNAME);
};
}
function preventBodyScroll(_document) {
const doc = _document ?? document;
let state = lockMap.get(doc);
if (!state) {
state = {
count: 0,
cleanup: applyLock(doc)
};
lockMap.set(doc, state);
}
state.count++;
const lockState = state;
let released = false;
return () => {
if (released) return;
released = true;
lockState.count--;
if (lockState.count === 0) {
lockState.cleanup();
lockMap.delete(doc);
}
};
}
//#endregion
export { preventBodyScroll };
const require_dom_query = require("./dom-query-BT6fffRP.cjs");
//#region src/shared/scroll-snap/index.ts
const getDirection = (element) => require_dom_query.getComputedStyle(element).direction;
const convert = (raw, size) => {
let n = parseFloat(raw);
if (/%/.test(raw)) {
n /= 100;
n *= size;
}
return Number.isNaN(n) ? 0 : n;
};
function getScrollPadding(element) {
const style = require_dom_query.getComputedStyle(element);
const layoutWidth = element.offsetWidth;
const layoutHeight = element.offsetHeight;
let xBeforeRaw = style.getPropertyValue("scroll-padding-left").replace("auto", "0px");
let yBeforeRaw = style.getPropertyValue("scroll-padding-top").replace("auto", "0px");
let xAfterRaw = style.getPropertyValue("scroll-padding-right").replace("auto", "0px");
let yAfterRaw = style.getPropertyValue("scroll-padding-bottom").replace("auto", "0px");
let xBefore = convert(xBeforeRaw, layoutWidth);
let yBefore = convert(yBeforeRaw, layoutHeight);
let xAfter = convert(xAfterRaw, layoutWidth);
let yAfter = convert(yAfterRaw, layoutHeight);
return {
x: {
before: xBefore,
after: xAfter
},
y: {
before: yBefore,
after: yAfter
}
};
}
function isRectIntersecting(a, b, axis = "both") {
return axis === "x" && a.right >= b.left && a.left <= b.right || axis === "y" && a.bottom >= b.top && a.top <= b.bottom || axis === "both" && a.right >= b.left && a.left <= b.right && a.bottom >= b.top && a.top <= b.bottom;
}
function getDescendants(parent) {
let children = [];
for (const child of parent.children) children = children.concat(child, getDescendants(child));
return children;
}
function getSnapPositions(parent, subtree = false) {
const parentRect = parent.getBoundingClientRect();
const isRtl = getDirection(parent) === "rtl";
const scale = require_dom_query.getScale(parent);
const positions = {
x: {
start: [],
center: [],
end: []
},
y: {
start: [],
center: [],
end: []
}
};
const children = subtree ? getDescendants(parent) : parent.children;
for (const axis of ["x", "y"]) {
const orthogonalAxis = axis === "x" ? "y" : "x";
const axisStart = axis === "x" ? "left" : "top";
const axisEnd = axis === "x" ? "right" : "bottom";
const axisSize = axis === "x" ? "width" : "height";
const axisScroll = axis === "x" ? "scrollLeft" : "scrollTop";
const axisScale = axis === "x" ? scale.x : scale.y;
const useRtlCalc = isRtl && axis === "x";
for (const child of children) {
const childRect = child.getBoundingClientRect();
if (!isRectIntersecting(parentRect, childRect, orthogonalAxis)) continue;
let [childAlignY, childAlignX] = require_dom_query.getComputedStyle(child).getPropertyValue("scroll-snap-align").split(" ");
if (typeof childAlignX === "undefined") childAlignX = childAlignY;
const childAlign = axis === "x" ? childAlignX : childAlignY;
let childOffsetStart;
let childOffsetEnd;
let childOffsetCenter;
if (useRtlCalc) {
const scrollOffset = Math.abs(parent[axisScroll]);
const rightOffset = (parentRect[axisEnd] - childRect[axisEnd]) / axisScale + scrollOffset;
childOffsetStart = rightOffset;
childOffsetEnd = rightOffset + childRect[axisSize] / axisScale;
childOffsetCenter = rightOffset + childRect[axisSize] / (2 * axisScale);
} else {
childOffsetStart = (childRect[axisStart] - parentRect[axisStart]) / axisScale + parent[axisScroll];
childOffsetEnd = childOffsetStart + childRect[axisSize] / axisScale;
childOffsetCenter = childOffsetStart + childRect[axisSize] / (2 * axisScale);
}
switch (childAlign) {
case "none": break;
case "start":
positions[axis].start.push({
node: child,
position: childOffsetStart
});
break;
case "center":
positions[axis].center.push({
node: child,
position: childOffsetCenter
});
break;
case "end":
positions[axis].end.push({
node: child,
position: childOffsetEnd
});
break;
}
}
}
return positions;
}
function getScrollSnapPositions(element) {
const dir = getDirection(element);
const scrollPadding = getScrollPadding(element);
const snapPositions = getSnapPositions(element);
const layoutWidth = element.offsetWidth;
const layoutHeight = element.offsetHeight;
const maxScroll = {
x: element.scrollWidth - element.offsetWidth,
y: element.scrollHeight - element.offsetHeight
};
const isRtl = dir === "rtl";
const usesNegativeScrollLeft = isRtl && element.scrollLeft <= 0;
let xPositions;
if (isRtl) {
xPositions = uniq([
...snapPositions.x.start.map((v) => v.position - scrollPadding.x.after),
...snapPositions.x.center.map((v) => v.position - layoutWidth / 2),
...snapPositions.x.end.map((v) => v.position - layoutWidth + scrollPadding.x.before)
].map(clamp(0, maxScroll.x)));
if (usesNegativeScrollLeft) xPositions = xPositions.map((pos) => -pos);
} else xPositions = uniq([
...snapPositions.x.start.map((v) => v.position - scrollPadding.x.before),
...snapPositions.x.center.map((v) => v.position - layoutWidth / 2),
...snapPositions.x.end.map((v) => v.position - layoutWidth + scrollPadding.x.after)
].map(clamp(0, maxScroll.x)));
return {
x: xPositions,
y: uniq([
...snapPositions.y.start.map((v) => v.position - scrollPadding.y.before),
...snapPositions.y.center.map((v) => v.position - layoutHeight / 2),
...snapPositions.y.end.map((v) => v.position - layoutHeight + scrollPadding.y.after)
].map(clamp(0, maxScroll.y)))
};
}
function findSnapPoint(parent, axis, predicate) {
const dir = getDirection(parent);
const scrollPadding = getScrollPadding(parent);
const snapPositions = getSnapPositions(parent);
const items = [
...snapPositions[axis].start,
...snapPositions[axis].center,
...snapPositions[axis].end
];
const isRtl = dir === "rtl";
const usesNegativeScrollLeft = isRtl && axis === "x" && parent.scrollLeft <= 0;
for (const item of items) if (predicate(item.node)) {
let position;
if (axis === "x" && isRtl) {
position = item.position - scrollPadding.x.after;
if (usesNegativeScrollLeft) position = -position;
} else position = item.position - (axis === "x" ? scrollPadding.x.before : scrollPadding.y.before);
return position;
}
}
function getSnapPointTarget(parent, snapPoint) {
const rect = parent.getBoundingClientRect();
const scale = require_dom_query.getScale(parent);
const scrollPadding = getScrollPadding(parent);
const children = Array.from(parent.children);
const layoutWidth = parent.offsetWidth;
const layoutHeight = parent.offsetHeight;
for (const child of children) {
const childRect = child.getBoundingClientRect();
const childOffsetStart = {
x: (childRect.left - rect.left) / scale.x + parent.scrollLeft,
y: (childRect.top - rect.top) / scale.y + parent.scrollTop
};
const childLayoutWidth = childRect.width / scale.x;
const childLayoutHeight = childRect.height / scale.y;
const matchesX = [
childOffsetStart.x - scrollPadding.x.before,
childOffsetStart.x + childLayoutWidth / 2 - layoutWidth / 2,
childOffsetStart.x + childLayoutWidth - layoutWidth + scrollPadding.x.after
].some((pos) => Math.abs(pos - snapPoint) < 1);
const matchesY = [
childOffsetStart.y - scrollPadding.y.before,
childOffsetStart.y + childLayoutHeight / 2 - layoutHeight / 2,
childOffsetStart.y + childLayoutHeight - layoutHeight + scrollPadding.y.after
].some((pos) => Math.abs(pos - snapPoint) < 1);
if (matchesX || matchesY) return child;
}
return children[0];
}
const uniq = (arr) => [...new Set(arr)];
const clamp = (min, max) => (value) => Math.max(min, Math.min(max, value));
//#endregion
Object.defineProperty(exports, "findSnapPoint", {
enumerable: true,
get: function() {
return findSnapPoint;
}
});
Object.defineProperty(exports, "getScrollSnapPositions", {
enumerable: true,
get: function() {
return getScrollSnapPositions;
}
});
Object.defineProperty(exports, "getSnapPointTarget", {
enumerable: true,
get: function() {
return getSnapPointTarget;
}
});
Object.defineProperty(exports, "getSnapPositions", {
enumerable: true,
get: function() {
return getSnapPositions;
}
});
import { $t as getComputedStyle, m as getScale } from "./dom-query-BgxIO7_X.mjs";
//#region src/shared/scroll-snap/index.ts
const getDirection = (element) => getComputedStyle(element).direction;
const convert = (raw, size) => {
let n = parseFloat(raw);
if (/%/.test(raw)) {
n /= 100;
n *= size;
}
return Number.isNaN(n) ? 0 : n;
};
function getScrollPadding(element) {
const style = getComputedStyle(element);
const layoutWidth = element.offsetWidth;
const layoutHeight = element.offsetHeight;
let xBeforeRaw = style.getPropertyValue("scroll-padding-left").replace("auto", "0px");
let yBeforeRaw = style.getPropertyValue("scroll-padding-top").replace("auto", "0px");
let xAfterRaw = style.getPropertyValue("scroll-padding-right").replace("auto", "0px");
let yAfterRaw = style.getPropertyValue("scroll-padding-bottom").replace("auto", "0px");
let xBefore = convert(xBeforeRaw, layoutWidth);
let yBefore = convert(yBeforeRaw, layoutHeight);
let xAfter = convert(xAfterRaw, layoutWidth);
let yAfter = convert(yAfterRaw, layoutHeight);
return {
x: {
before: xBefore,
after: xAfter
},
y: {
before: yBefore,
after: yAfter
}
};
}
function isRectIntersecting(a, b, axis = "both") {
return axis === "x" && a.right >= b.left && a.left <= b.right || axis === "y" && a.bottom >= b.top && a.top <= b.bottom || axis === "both" && a.right >= b.left && a.left <= b.right && a.bottom >= b.top && a.top <= b.bottom;
}
function getDescendants(parent) {
let children = [];
for (const child of parent.children) children = children.concat(child, getDescendants(child));
return children;
}
function getSnapPositions(parent, subtree = false) {
const parentRect = parent.getBoundingClientRect();
const isRtl = getDirection(parent) === "rtl";
const scale = getScale(parent);
const positions = {
x: {
start: [],
center: [],
end: []
},
y: {
start: [],
center: [],
end: []
}
};
const children = subtree ? getDescendants(parent) : parent.children;
for (const axis of ["x", "y"]) {
const orthogonalAxis = axis === "x" ? "y" : "x";
const axisStart = axis === "x" ? "left" : "top";
const axisEnd = axis === "x" ? "right" : "bottom";
const axisSize = axis === "x" ? "width" : "height";
const axisScroll = axis === "x" ? "scrollLeft" : "scrollTop";
const axisScale = axis === "x" ? scale.x : scale.y;
const useRtlCalc = isRtl && axis === "x";
for (const child of children) {
const childRect = child.getBoundingClientRect();
if (!isRectIntersecting(parentRect, childRect, orthogonalAxis)) continue;
let [childAlignY, childAlignX] = getComputedStyle(child).getPropertyValue("scroll-snap-align").split(" ");
if (typeof childAlignX === "undefined") childAlignX = childAlignY;
const childAlign = axis === "x" ? childAlignX : childAlignY;
let childOffsetStart;
let childOffsetEnd;
let childOffsetCenter;
if (useRtlCalc) {
const scrollOffset = Math.abs(parent[axisScroll]);
const rightOffset = (parentRect[axisEnd] - childRect[axisEnd]) / axisScale + scrollOffset;
childOffsetStart = rightOffset;
childOffsetEnd = rightOffset + childRect[axisSize] / axisScale;
childOffsetCenter = rightOffset + childRect[axisSize] / (2 * axisScale);
} else {
childOffsetStart = (childRect[axisStart] - parentRect[axisStart]) / axisScale + parent[axisScroll];
childOffsetEnd = childOffsetStart + childRect[axisSize] / axisScale;
childOffsetCenter = childOffsetStart + childRect[axisSize] / (2 * axisScale);
}
switch (childAlign) {
case "none": break;
case "start":
positions[axis].start.push({
node: child,
position: childOffsetStart
});
break;
case "center":
positions[axis].center.push({
node: child,
position: childOffsetCenter
});
break;
case "end":
positions[axis].end.push({
node: child,
position: childOffsetEnd
});
break;
}
}
}
return positions;
}
function getScrollSnapPositions(element) {
const dir = getDirection(element);
const scrollPadding = getScrollPadding(element);
const snapPositions = getSnapPositions(element);
const layoutWidth = element.offsetWidth;
const layoutHeight = element.offsetHeight;
const maxScroll = {
x: element.scrollWidth - element.offsetWidth,
y: element.scrollHeight - element.offsetHeight
};
const isRtl = dir === "rtl";
const usesNegativeScrollLeft = isRtl && element.scrollLeft <= 0;
let xPositions;
if (isRtl) {
xPositions = uniq([
...snapPositions.x.start.map((v) => v.position - scrollPadding.x.after),
...snapPositions.x.center.map((v) => v.position - layoutWidth / 2),
...snapPositions.x.end.map((v) => v.position - layoutWidth + scrollPadding.x.before)
].map(clamp(0, maxScroll.x)));
if (usesNegativeScrollLeft) xPositions = xPositions.map((pos) => -pos);
} else xPositions = uniq([
...snapPositions.x.start.map((v) => v.position - scrollPadding.x.before),
...snapPositions.x.center.map((v) => v.position - layoutWidth / 2),
...snapPositions.x.end.map((v) => v.position - layoutWidth + scrollPadding.x.after)
].map(clamp(0, maxScroll.x)));
return {
x: xPositions,
y: uniq([
...snapPositions.y.start.map((v) => v.position - scrollPadding.y.before),
...snapPositions.y.center.map((v) => v.position - layoutHeight / 2),
...snapPositions.y.end.map((v) => v.position - layoutHeight + scrollPadding.y.after)
].map(clamp(0, maxScroll.y)))
};
}
function findSnapPoint(parent, axis, predicate) {
const dir = getDirection(parent);
const scrollPadding = getScrollPadding(parent);
const snapPositions = getSnapPositions(parent);
const items = [
...snapPositions[axis].start,
...snapPositions[axis].center,
...snapPositions[axis].end
];
const isRtl = dir === "rtl";
const usesNegativeScrollLeft = isRtl && axis === "x" && parent.scrollLeft <= 0;
for (const item of items) if (predicate(item.node)) {
let position;
if (axis === "x" && isRtl) {
position = item.position - scrollPadding.x.after;
if (usesNegativeScrollLeft) position = -position;
} else position = item.position - (axis === "x" ? scrollPadding.x.before : scrollPadding.y.before);
return position;
}
}
function getSnapPointTarget(parent, snapPoint) {
const rect = parent.getBoundingClientRect();
const scale = getScale(parent);
const scrollPadding = getScrollPadding(parent);
const children = Array.from(parent.children);
const layoutWidth = parent.offsetWidth;
const layoutHeight = parent.offsetHeight;
for (const child of children) {
const childRect = child.getBoundingClientRect();
const childOffsetStart = {
x: (childRect.left - rect.left) / scale.x + parent.scrollLeft,
y: (childRect.top - rect.top) / scale.y + parent.scrollTop
};
const childLayoutWidth = childRect.width / scale.x;
const childLayoutHeight = childRect.height / scale.y;
const matchesX = [
childOffsetStart.x - scrollPadding.x.before,
childOffsetStart.x + childLayoutWidth / 2 - layoutWidth / 2,
childOffsetStart.x + childLayoutWidth - layoutWidth + scrollPadding.x.after
].some((pos) => Math.abs(pos - snapPoint) < 1);
const matchesY = [
childOffsetStart.y - scrollPadding.y.before,
childOffsetStart.y + childLayoutHeight / 2 - layoutHeight / 2,
childOffsetStart.y + childLayoutHeight - layoutHeight + scrollPadding.y.after
].some((pos) => Math.abs(pos - snapPoint) < 1);
if (matchesX || matchesY) return child;
}
return children[0];
}
const uniq = (arr) => [...new Set(arr)];
const clamp = (min, max) => (value) => Math.max(min, Math.min(max, value));
//#endregion
export { getSnapPositions as i, getScrollSnapPositions as n, getSnapPointTarget as r, findSnapPoint as t };
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_scroll_snap = require("./scroll-snap-Cbwgrr_p.cjs");
exports.findSnapPoint = require_scroll_snap.findSnapPoint;
exports.getScrollSnapPositions = require_scroll_snap.getScrollSnapPositions;
exports.getSnapPointTarget = require_scroll_snap.getSnapPointTarget;
exports.getSnapPositions = require_scroll_snap.getSnapPositions;
//#region src/shared/scroll-snap/index.d.ts
type ScrollAxis = "x" | "y";
type ScrollDirection = "left" | "right" | "up" | "down";
type ScrollSnapAlignment = "start" | "end" | "center" | "none";
type SnapPositionList = Record<Exclude<ScrollSnapAlignment, "none">, Array<{
node: Element;
position: number;
}>>;
declare function getSnapPositions(parent: HTMLElement, subtree?: boolean): Record<ScrollAxis, SnapPositionList>;
declare function getScrollSnapPositions(element: HTMLElement): Record<ScrollAxis, number[]>;
declare function findSnapPoint(parent: HTMLElement, axis: ScrollAxis, predicate: (node: HTMLElement) => boolean): number | undefined;
declare function getSnapPointTarget(parent: HTMLElement, snapPoint: number): HTMLElement;
//#endregion
export { ScrollAxis, ScrollDirection, ScrollSnapAlignment, SnapPositionList, findSnapPoint, getScrollSnapPositions, getSnapPointTarget, getSnapPositions };
//#region src/shared/scroll-snap/index.d.ts
type ScrollAxis = "x" | "y";
type ScrollDirection = "left" | "right" | "up" | "down";
type ScrollSnapAlignment = "start" | "end" | "center" | "none";
type SnapPositionList = Record<Exclude<ScrollSnapAlignment, "none">, Array<{
node: Element;
position: number;
}>>;
declare function getSnapPositions(parent: HTMLElement, subtree?: boolean): Record<ScrollAxis, SnapPositionList>;
declare function getScrollSnapPositions(element: HTMLElement): Record<ScrollAxis, number[]>;
declare function findSnapPoint(parent: HTMLElement, axis: ScrollAxis, predicate: (node: HTMLElement) => boolean): number | undefined;
declare function getSnapPointTarget(parent: HTMLElement, snapPoint: number): HTMLElement;
//#endregion
export { ScrollAxis, ScrollDirection, ScrollSnapAlignment, SnapPositionList, findSnapPoint, getScrollSnapPositions, getSnapPointTarget, getSnapPositions };
import { i as getSnapPositions, n as getScrollSnapPositions, r as getSnapPointTarget, t as findSnapPoint } from "./scroll-snap-D5nbf4fC.mjs";
export { findSnapPoint, getScrollSnapPositions, getSnapPointTarget, getSnapPositions };
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
let proxy_compare = require("proxy-compare");
//#region src/shared/store/global.ts
function glob() {
if (typeof globalThis !== "undefined") return globalThis;
if (typeof self !== "undefined") return self;
if (typeof window !== "undefined") return window;
if (typeof global !== "undefined") return global;
}
function globalRef(key, value) {
const g = glob();
if (!g) return value();
g[key] ||= value();
return g[key];
}
const refSet = globalRef("__ginx__refSet", () => /* @__PURE__ */ new WeakSet());
//#endregion
//#region src/shared/store/utils.ts
const isReactElement = (x) => typeof x === "object" && x !== null && "$$typeof" in x && "props" in x;
const isVueElement = (x) => typeof x === "object" && x !== null && "__v_isVNode" in x;
const isDOMElement = (x) => typeof x === "object" && x !== null && "nodeType" in x && typeof x.nodeName === "string";
const isElement = (x) => isReactElement(x) || isVueElement(x) || isDOMElement(x);
const isObject = (x) => x !== null && typeof x === "object";
const canProxy = (x) => isObject(x) && !refSet.has(x) && (Array.isArray(x) || !(Symbol.iterator in x)) && !isElement(x) && !(x instanceof WeakMap) && !(x instanceof WeakSet) && !(x instanceof Error) && !(x instanceof Number) && !(x instanceof Date) && !(x instanceof String) && !(x instanceof RegExp) && !(x instanceof ArrayBuffer) && !(x instanceof Promise) && !(x instanceof File) && !(x instanceof Blob) && !(x instanceof AbortController);
const isDev = () => process.env.NODE_ENV !== "production";
//#endregion
//#region src/shared/store/clone.ts
function set(obj, key, val) {
if (typeof val.value === "object" && !canProxy(val.value)) val.value = clone(val.value);
if (!val.enumerable || val.get || val.set || !val.configurable || !val.writable || key === "__proto__") Object.defineProperty(obj, key, val);
else obj[key] = val.value;
}
function clone(x) {
if (typeof x !== "object") return x;
let i = 0, k, list, tmp, str = Object.prototype.toString.call(x);
if (str === "[object Object]") tmp = Object.create(Object.getPrototypeOf(x) || null);
else if (str === "[object Array]") tmp = Array(x.length);
else if (str === "[object Set]") {
tmp = /* @__PURE__ */ new Set();
x.forEach(function(val) {
tmp.add(clone(val));
});
} else if (str === "[object Map]") {
tmp = /* @__PURE__ */ new Map();
x.forEach(function(val, key) {
tmp.set(clone(key), clone(val));
});
} else if (str === "[object Date]") tmp = /* @__PURE__ */ new Date(+x);
else if (str === "[object RegExp]") tmp = new RegExp(x.source, x.flags);
else if (str === "[object DataView]") tmp = new x.constructor(clone(x.buffer));
else if (str === "[object ArrayBuffer]") tmp = x.slice(0);
else if (str === "[object Blob]") tmp = x.slice();
else if (str.slice(-6) === "Array]") tmp = new x.constructor(x);
if (tmp) {
for (list = Object.getOwnPropertySymbols(x); i < list.length; i++) set(tmp, list[i], Object.getOwnPropertyDescriptor(x, list[i]));
for (i = 0, list = Object.getOwnPropertyNames(x); i < list.length; i++) {
if (Object.hasOwnProperty.call(tmp, k = list[i]) && tmp[k] === x[k]) continue;
set(tmp, k, Object.getOwnPropertyDescriptor(x, k));
}
}
return tmp || x;
}
//#endregion
//#region src/shared/store/proxy.ts
const proxyStateMap = globalRef("__ginx__proxyStateMap", () => /* @__PURE__ */ new WeakMap());
const buildProxyFunction = (objectIs = Object.is, newProxy = (target, handler) => new Proxy(target, handler), snapCache = /* @__PURE__ */ new WeakMap(), createSnapshot = (target, version) => {
const cache = snapCache.get(target);
if (cache?.[0] === version) return cache[1];
const snap = Array.isArray(target) ? [] : Object.create(Object.getPrototypeOf(target));
(0, proxy_compare.markToTrack)(snap, true);
snapCache.set(target, [version, snap]);
Reflect.ownKeys(target).forEach((key) => {
const value = Reflect.get(target, key);
if (refSet.has(value)) {
(0, proxy_compare.markToTrack)(value, false);
snap[key] = value;
} else if (proxyStateMap.has(value)) snap[key] = snapshot(value);
else snap[key] = value;
});
return Object.freeze(snap);
}, proxyCache = /* @__PURE__ */ new WeakMap(), versionHolder = [1, 1], proxyFunction = (initialObject) => {
if (!isObject(initialObject)) throw new Error("object required");
const found = proxyCache.get(initialObject);
if (found) return found;
let version = versionHolder[0];
const listeners = /* @__PURE__ */ new Set();
const notifyUpdate = (op, nextVersion = ++versionHolder[0]) => {
if (version !== nextVersion) {
version = nextVersion;
listeners.forEach((listener) => listener(op, nextVersion));
}
};
let checkVersion = versionHolder[1];
const ensureVersion = (nextCheckVersion = ++versionHolder[1]) => {
if (checkVersion !== nextCheckVersion && !listeners.size) {
checkVersion = nextCheckVersion;
propProxyStates.forEach(([propProxyState]) => {
const propVersion = propProxyState[1](nextCheckVersion);
if (propVersion > version) version = propVersion;
});
}
return version;
};
const createPropListener = (prop) => (op, nextVersion) => {
const newOp = [...op];
newOp[1] = [prop, ...newOp[1]];
notifyUpdate(newOp, nextVersion);
};
const propProxyStates = /* @__PURE__ */ new Map();
const addPropListener = (prop, propProxyState) => {
if (isDev() && propProxyStates.has(prop)) throw new Error("prop listener already exists");
if (listeners.size) {
const remove = propProxyState[3](createPropListener(prop));
propProxyStates.set(prop, [propProxyState, remove]);
} else propProxyStates.set(prop, [propProxyState]);
};
const removePropListener = (prop) => {
const entry = propProxyStates.get(prop);
if (entry) {
propProxyStates.delete(prop);
entry[1]?.();
}
};
const addListener = (listener) => {
listeners.add(listener);
if (listeners.size === 1) propProxyStates.forEach(([propProxyState, prevRemove], prop) => {
if (isDev() && prevRemove) throw new Error("remove already exists");
const remove = propProxyState[3](createPropListener(prop));
propProxyStates.set(prop, [propProxyState, remove]);
});
const removeListener = () => {
listeners.delete(listener);
if (listeners.size === 0) propProxyStates.forEach(([propProxyState, remove], prop) => {
if (remove) {
remove();
propProxyStates.set(prop, [propProxyState]);
}
});
};
return removeListener;
};
const baseObject = Array.isArray(initialObject) ? [] : Object.create(Object.getPrototypeOf(initialObject));
const proxyObject = newProxy(baseObject, {
deleteProperty(target, prop) {
const prevValue = Reflect.get(target, prop);
removePropListener(prop);
const deleted = Reflect.deleteProperty(target, prop);
if (deleted) notifyUpdate([
"delete",
[prop],
prevValue
]);
return deleted;
},
set(target, prop, value, receiver) {
const hasPrevValue = Reflect.has(target, prop);
const prevValue = Reflect.get(target, prop, receiver);
if (hasPrevValue && (objectIs(prevValue, value) || proxyCache.has(value) && objectIs(prevValue, proxyCache.get(value)))) return true;
removePropListener(prop);
if (isObject(value)) value = (0, proxy_compare.getUntracked)(value) || value;
let nextValue = value;
if (Object.getOwnPropertyDescriptor(target, prop)?.set) {} else {
if (!proxyStateMap.has(value) && canProxy(value)) nextValue = proxy(value);
const childProxyState = !refSet.has(nextValue) && proxyStateMap.get(nextValue);
if (childProxyState) addPropListener(prop, childProxyState);
}
Reflect.set(target, prop, nextValue, receiver);
notifyUpdate([
"set",
[prop],
value,
prevValue
]);
return true;
}
});
proxyCache.set(initialObject, proxyObject);
const proxyState = [
baseObject,
ensureVersion,
createSnapshot,
addListener
];
proxyStateMap.set(proxyObject, proxyState);
Reflect.ownKeys(initialObject).forEach((key) => {
const desc = Object.getOwnPropertyDescriptor(initialObject, key);
if (desc.get || desc.set) Object.defineProperty(baseObject, key, desc);
else proxyObject[key] = initialObject[key];
});
return proxyObject;
}) => [
proxyFunction,
proxyStateMap,
refSet,
objectIs,
newProxy,
canProxy,
snapCache,
createSnapshot,
proxyCache,
versionHolder
];
const [proxyFunction] = buildProxyFunction();
function proxy(initialObject = {}) {
return proxyFunction(initialObject);
}
function subscribe(proxyObject, callback, notifyInSync) {
const proxyState = proxyStateMap.get(proxyObject);
if (isDev() && !proxyState) console.warn("Please use proxy object");
let promise;
const ops = [];
const addListener = proxyState[3];
let isListenerActive = false;
const listener = (op) => {
ops.push(op);
if (notifyInSync) {
callback(ops.splice(0));
return;
}
if (!promise) promise = Promise.resolve().then(() => {
promise = void 0;
if (isListenerActive) callback(ops.splice(0));
});
};
const removeListener = addListener(listener);
isListenerActive = true;
return () => {
isListenerActive = false;
removeListener();
};
}
function snapshot(proxyObject) {
const proxyState = proxyStateMap.get(proxyObject);
if (isDev() && !proxyState) console.warn("Please use proxy object");
const [target, ensureVersion, createSnapshot] = proxyState;
return createSnapshot(target, ensureVersion());
}
function ref(obj) {
refSet.add(obj);
return obj;
}
//#endregion
//#region src/shared/store/proxy-computed.ts
function proxyWithComputed(initialObject, computedFns) {
Object.keys(computedFns).forEach((key) => {
if (Object.getOwnPropertyDescriptor(initialObject, key)) throw new Error("object property already defined");
const computedFn = computedFns[key];
const { get, set } = typeof computedFn === "function" ? { get: computedFn } : computedFn;
const desc = {};
desc.get = () => get(snapshot(proxyObject));
if (set) desc.set = (newValue) => set(proxyObject, newValue);
Object.defineProperty(initialObject, key, desc);
});
const proxyObject = proxy(initialObject);
return proxyObject;
}
//#endregion
exports.clone = clone;
exports.globalRef = globalRef;
exports.proxy = proxy;
exports.proxyWithComputed = proxyWithComputed;
exports.ref = ref;
exports.snapshot = snapshot;
exports.subscribe = subscribe;
//#region src/shared/store/clone.d.ts
declare function clone<T>(x: T): T;
//#endregion
//#region src/shared/store/global.d.ts
declare function globalRef<T>(key: string, value: () => T): T;
//#endregion
//#region src/shared/store/proxy.d.ts
type AsRef = {
$$valtioRef: true;
};
type Path = (string | symbol)[];
type Op = [op: "set", path: Path, value: unknown, prevValue: unknown] | [op: "delete", path: Path, prevValue: unknown];
type Snapshot<T> = T;
declare function proxy<T extends object>(initialObject?: T): T;
declare function subscribe<T extends object>(proxyObject: T, callback: (ops: Op[]) => void, notifyInSync?: boolean): () => void;
declare function snapshot<T extends object>(proxyObject: T): T;
declare function ref<T extends object>(obj: T): Ref<T>;
type Ref<T> = T & AsRef;
//#endregion
//#region src/shared/store/proxy-computed.d.ts
declare function proxyWithComputed<T extends object, U extends object>(initialObject: T, computedFns: { [K in keyof U]: ((snap: Snapshot<T>) => U[K]) | {
get: (snap: Snapshot<T>) => U[K];
set?: ((state: T, newValue: U[K]) => void) | undefined;
} }): T & U;
//#endregion
export { Ref, Snapshot, clone, globalRef, proxy, proxyWithComputed, ref, snapshot, subscribe };
//#region src/shared/store/clone.d.ts
declare function clone<T>(x: T): T;
//#endregion
//#region src/shared/store/global.d.ts
declare function globalRef<T>(key: string, value: () => T): T;
//#endregion
//#region src/shared/store/proxy.d.ts
type AsRef = {
$$valtioRef: true;
};
type Path = (string | symbol)[];
type Op = [op: "set", path: Path, value: unknown, prevValue: unknown] | [op: "delete", path: Path, prevValue: unknown];
type Snapshot<T> = T;
declare function proxy<T extends object>(initialObject?: T): T;
declare function subscribe<T extends object>(proxyObject: T, callback: (ops: Op[]) => void, notifyInSync?: boolean): () => void;
declare function snapshot<T extends object>(proxyObject: T): T;
declare function ref<T extends object>(obj: T): Ref<T>;
type Ref<T> = T & AsRef;
//#endregion
//#region src/shared/store/proxy-computed.d.ts
declare function proxyWithComputed<T extends object, U extends object>(initialObject: T, computedFns: { [K in keyof U]: ((snap: Snapshot<T>) => U[K]) | {
get: (snap: Snapshot<T>) => U[K];
set?: ((state: T, newValue: U[K]) => void) | undefined;
} }): T & U;
//#endregion
export { Ref, Snapshot, clone, globalRef, proxy, proxyWithComputed, ref, snapshot, subscribe };
import { getUntracked, markToTrack } from "proxy-compare";
//#region src/shared/store/global.ts
function glob() {
if (typeof globalThis !== "undefined") return globalThis;
if (typeof self !== "undefined") return self;
if (typeof window !== "undefined") return window;
if (typeof global !== "undefined") return global;
}
function globalRef(key, value) {
const g = glob();
if (!g) return value();
g[key] ||= value();
return g[key];
}
const refSet = globalRef("__ginx__refSet", () => /* @__PURE__ */ new WeakSet());
//#endregion
//#region src/shared/store/utils.ts
const isReactElement = (x) => typeof x === "object" && x !== null && "$$typeof" in x && "props" in x;
const isVueElement = (x) => typeof x === "object" && x !== null && "__v_isVNode" in x;
const isDOMElement = (x) => typeof x === "object" && x !== null && "nodeType" in x && typeof x.nodeName === "string";
const isElement = (x) => isReactElement(x) || isVueElement(x) || isDOMElement(x);
const isObject = (x) => x !== null && typeof x === "object";
const canProxy = (x) => isObject(x) && !refSet.has(x) && (Array.isArray(x) || !(Symbol.iterator in x)) && !isElement(x) && !(x instanceof WeakMap) && !(x instanceof WeakSet) && !(x instanceof Error) && !(x instanceof Number) && !(x instanceof Date) && !(x instanceof String) && !(x instanceof RegExp) && !(x instanceof ArrayBuffer) && !(x instanceof Promise) && !(x instanceof File) && !(x instanceof Blob) && !(x instanceof AbortController);
const isDev = () => process.env.NODE_ENV !== "production";
//#endregion
//#region src/shared/store/clone.ts
function set(obj, key, val) {
if (typeof val.value === "object" && !canProxy(val.value)) val.value = clone(val.value);
if (!val.enumerable || val.get || val.set || !val.configurable || !val.writable || key === "__proto__") Object.defineProperty(obj, key, val);
else obj[key] = val.value;
}
function clone(x) {
if (typeof x !== "object") return x;
let i = 0, k, list, tmp, str = Object.prototype.toString.call(x);
if (str === "[object Object]") tmp = Object.create(Object.getPrototypeOf(x) || null);
else if (str === "[object Array]") tmp = Array(x.length);
else if (str === "[object Set]") {
tmp = /* @__PURE__ */ new Set();
x.forEach(function(val) {
tmp.add(clone(val));
});
} else if (str === "[object Map]") {
tmp = /* @__PURE__ */ new Map();
x.forEach(function(val, key) {
tmp.set(clone(key), clone(val));
});
} else if (str === "[object Date]") tmp = /* @__PURE__ */ new Date(+x);
else if (str === "[object RegExp]") tmp = new RegExp(x.source, x.flags);
else if (str === "[object DataView]") tmp = new x.constructor(clone(x.buffer));
else if (str === "[object ArrayBuffer]") tmp = x.slice(0);
else if (str === "[object Blob]") tmp = x.slice();
else if (str.slice(-6) === "Array]") tmp = new x.constructor(x);
if (tmp) {
for (list = Object.getOwnPropertySymbols(x); i < list.length; i++) set(tmp, list[i], Object.getOwnPropertyDescriptor(x, list[i]));
for (i = 0, list = Object.getOwnPropertyNames(x); i < list.length; i++) {
if (Object.hasOwnProperty.call(tmp, k = list[i]) && tmp[k] === x[k]) continue;
set(tmp, k, Object.getOwnPropertyDescriptor(x, k));
}
}
return tmp || x;
}
//#endregion
//#region src/shared/store/proxy.ts
const proxyStateMap = globalRef("__ginx__proxyStateMap", () => /* @__PURE__ */ new WeakMap());
const buildProxyFunction = (objectIs = Object.is, newProxy = (target, handler) => new Proxy(target, handler), snapCache = /* @__PURE__ */ new WeakMap(), createSnapshot = (target, version) => {
const cache = snapCache.get(target);
if (cache?.[0] === version) return cache[1];
const snap = Array.isArray(target) ? [] : Object.create(Object.getPrototypeOf(target));
markToTrack(snap, true);
snapCache.set(target, [version, snap]);
Reflect.ownKeys(target).forEach((key) => {
const value = Reflect.get(target, key);
if (refSet.has(value)) {
markToTrack(value, false);
snap[key] = value;
} else if (proxyStateMap.has(value)) snap[key] = snapshot(value);
else snap[key] = value;
});
return Object.freeze(snap);
}, proxyCache = /* @__PURE__ */ new WeakMap(), versionHolder = [1, 1], proxyFunction = (initialObject) => {
if (!isObject(initialObject)) throw new Error("object required");
const found = proxyCache.get(initialObject);
if (found) return found;
let version = versionHolder[0];
const listeners = /* @__PURE__ */ new Set();
const notifyUpdate = (op, nextVersion = ++versionHolder[0]) => {
if (version !== nextVersion) {
version = nextVersion;
listeners.forEach((listener) => listener(op, nextVersion));
}
};
let checkVersion = versionHolder[1];
const ensureVersion = (nextCheckVersion = ++versionHolder[1]) => {
if (checkVersion !== nextCheckVersion && !listeners.size) {
checkVersion = nextCheckVersion;
propProxyStates.forEach(([propProxyState]) => {
const propVersion = propProxyState[1](nextCheckVersion);
if (propVersion > version) version = propVersion;
});
}
return version;
};
const createPropListener = (prop) => (op, nextVersion) => {
const newOp = [...op];
newOp[1] = [prop, ...newOp[1]];
notifyUpdate(newOp, nextVersion);
};
const propProxyStates = /* @__PURE__ */ new Map();
const addPropListener = (prop, propProxyState) => {
if (isDev() && propProxyStates.has(prop)) throw new Error("prop listener already exists");
if (listeners.size) {
const remove = propProxyState[3](createPropListener(prop));
propProxyStates.set(prop, [propProxyState, remove]);
} else propProxyStates.set(prop, [propProxyState]);
};
const removePropListener = (prop) => {
const entry = propProxyStates.get(prop);
if (entry) {
propProxyStates.delete(prop);
entry[1]?.();
}
};
const addListener = (listener) => {
listeners.add(listener);
if (listeners.size === 1) propProxyStates.forEach(([propProxyState, prevRemove], prop) => {
if (isDev() && prevRemove) throw new Error("remove already exists");
const remove = propProxyState[3](createPropListener(prop));
propProxyStates.set(prop, [propProxyState, remove]);
});
const removeListener = () => {
listeners.delete(listener);
if (listeners.size === 0) propProxyStates.forEach(([propProxyState, remove], prop) => {
if (remove) {
remove();
propProxyStates.set(prop, [propProxyState]);
}
});
};
return removeListener;
};
const baseObject = Array.isArray(initialObject) ? [] : Object.create(Object.getPrototypeOf(initialObject));
const proxyObject = newProxy(baseObject, {
deleteProperty(target, prop) {
const prevValue = Reflect.get(target, prop);
removePropListener(prop);
const deleted = Reflect.deleteProperty(target, prop);
if (deleted) notifyUpdate([
"delete",
[prop],
prevValue
]);
return deleted;
},
set(target, prop, value, receiver) {
const hasPrevValue = Reflect.has(target, prop);
const prevValue = Reflect.get(target, prop, receiver);
if (hasPrevValue && (objectIs(prevValue, value) || proxyCache.has(value) && objectIs(prevValue, proxyCache.get(value)))) return true;
removePropListener(prop);
if (isObject(value)) value = getUntracked(value) || value;
let nextValue = value;
if (Object.getOwnPropertyDescriptor(target, prop)?.set) {} else {
if (!proxyStateMap.has(value) && canProxy(value)) nextValue = proxy(value);
const childProxyState = !refSet.has(nextValue) && proxyStateMap.get(nextValue);
if (childProxyState) addPropListener(prop, childProxyState);
}
Reflect.set(target, prop, nextValue, receiver);
notifyUpdate([
"set",
[prop],
value,
prevValue
]);
return true;
}
});
proxyCache.set(initialObject, proxyObject);
const proxyState = [
baseObject,
ensureVersion,
createSnapshot,
addListener
];
proxyStateMap.set(proxyObject, proxyState);
Reflect.ownKeys(initialObject).forEach((key) => {
const desc = Object.getOwnPropertyDescriptor(initialObject, key);
if (desc.get || desc.set) Object.defineProperty(baseObject, key, desc);
else proxyObject[key] = initialObject[key];
});
return proxyObject;
}) => [
proxyFunction,
proxyStateMap,
refSet,
objectIs,
newProxy,
canProxy,
snapCache,
createSnapshot,
proxyCache,
versionHolder
];
const [proxyFunction] = buildProxyFunction();
function proxy(initialObject = {}) {
return proxyFunction(initialObject);
}
function subscribe(proxyObject, callback, notifyInSync) {
const proxyState = proxyStateMap.get(proxyObject);
if (isDev() && !proxyState) console.warn("Please use proxy object");
let promise;
const ops = [];
const addListener = proxyState[3];
let isListenerActive = false;
const listener = (op) => {
ops.push(op);
if (notifyInSync) {
callback(ops.splice(0));
return;
}
if (!promise) promise = Promise.resolve().then(() => {
promise = void 0;
if (isListenerActive) callback(ops.splice(0));
});
};
const removeListener = addListener(listener);
isListenerActive = true;
return () => {
isListenerActive = false;
removeListener();
};
}
function snapshot(proxyObject) {
const proxyState = proxyStateMap.get(proxyObject);
if (isDev() && !proxyState) console.warn("Please use proxy object");
const [target, ensureVersion, createSnapshot] = proxyState;
return createSnapshot(target, ensureVersion());
}
function ref(obj) {
refSet.add(obj);
return obj;
}
//#endregion
//#region src/shared/store/proxy-computed.ts
function proxyWithComputed(initialObject, computedFns) {
Object.keys(computedFns).forEach((key) => {
if (Object.getOwnPropertyDescriptor(initialObject, key)) throw new Error("object property already defined");
const computedFn = computedFns[key];
const { get, set } = typeof computedFn === "function" ? { get: computedFn } : computedFn;
const desc = {};
desc.get = () => get(snapshot(proxyObject));
if (set) desc.set = (newValue) => set(proxyObject, newValue);
Object.defineProperty(initialObject, key, desc);
});
const proxyObject = proxy(initialObject);
return proxyObject;
}
//#endregion
export { clone, globalRef, proxy, proxyWithComputed, ref, snapshot, subscribe };
//#region src/shared/rect/types.d.ts
interface Point {
x: number;
y: number;
}
interface Size {
width: number;
height: number;
}
interface Bounds {
minX: number;
midX: number;
maxX: number;
minY: number;
midY: number;
maxY: number;
}
interface CenterPoint {
center: Point;
}
interface RectInit extends Point, Size {}
interface Rect extends Point, Size, Bounds, CenterPoint {}
type RectSide = "top" | "right" | "bottom" | "left";
type RectPoint = "top-left" | "top-center" | "top-right" | "right-center" | "left-center" | "bottom-left" | "bottom-right" | "bottom-center" | "center";
type RectEdge = [Point, Point];
type RectPoints = [Point, Point, Point, Point];
type RectEdges = Record<RectSide, RectEdge> & {
value: RectEdge[];
};
type RectCorner = "topLeft" | "topRight" | "bottomLeft" | "bottomRight";
type RectCorners = Record<RectCorner, Point> & {
value: RectPoints;
};
type RectCenter = "topCenter" | "rightCenter" | "leftCenter" | "bottomCenter";
type RectCenters = Record<RectCenter, Point> & {
value: RectPoints;
};
type RectInset = Partial<Record<RectSide, number>>;
interface SymmetricRectInset {
dx?: number | undefined;
dy?: number | undefined;
}
interface ScalingOptions {
scalingOriginMode: "center" | "extent";
lockAspectRatio: boolean;
}
interface AlignOptions {
h: HAlign;
v: VAlign;
}
type HAlign = "left-inside" | "left-outside" | "center" | "right-inside" | "right-outside";
type VAlign = "top-inside" | "top-outside" | "center" | "bottom-inside" | "bottom-outside";
//#endregion
export { RectSide as _, Point as a, SymmetricRectInset as b, RectCenters as c, RectEdge as d, RectEdges as f, RectPoints as g, RectPoint as h, HAlign as i, RectCorner as l, RectInset as m, Bounds as n, Rect as o, RectInit as p, CenterPoint as r, RectCenter as s, AlignOptions as t, RectCorners as u, ScalingOptions as v, VAlign as x, Size as y };
//#region src/shared/rect/types.d.ts
interface Point {
x: number;
y: number;
}
interface Size {
width: number;
height: number;
}
interface Bounds {
minX: number;
midX: number;
maxX: number;
minY: number;
midY: number;
maxY: number;
}
interface CenterPoint {
center: Point;
}
interface RectInit extends Point, Size {}
interface Rect extends Point, Size, Bounds, CenterPoint {}
type RectSide = "top" | "right" | "bottom" | "left";
type RectPoint = "top-left" | "top-center" | "top-right" | "right-center" | "left-center" | "bottom-left" | "bottom-right" | "bottom-center" | "center";
type RectEdge = [Point, Point];
type RectPoints = [Point, Point, Point, Point];
type RectEdges = Record<RectSide, RectEdge> & {
value: RectEdge[];
};
type RectCorner = "topLeft" | "topRight" | "bottomLeft" | "bottomRight";
type RectCorners = Record<RectCorner, Point> & {
value: RectPoints;
};
type RectCenter = "topCenter" | "rightCenter" | "leftCenter" | "bottomCenter";
type RectCenters = Record<RectCenter, Point> & {
value: RectPoints;
};
type RectInset = Partial<Record<RectSide, number>>;
interface SymmetricRectInset {
dx?: number | undefined;
dy?: number | undefined;
}
interface ScalingOptions {
scalingOriginMode: "center" | "extent";
lockAspectRatio: boolean;
}
interface AlignOptions {
h: HAlign;
v: VAlign;
}
type HAlign = "left-inside" | "left-outside" | "center" | "right-inside" | "right-outside";
type VAlign = "top-inside" | "top-outside" | "center" | "bottom-inside" | "bottom-outside";
//#endregion
export { RectSide as _, Point as a, SymmetricRectInset as b, RectCenters as c, RectEdge as d, RectEdges as f, RectPoints as g, RectPoint as h, HAlign as i, RectCorner as l, RectInset as m, Bounds as n, Rect as o, RectInit as p, CenterPoint as r, RectCenter as s, AlignOptions as t, RectCorners as u, ScalingOptions as v, VAlign as x, Size as y };
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const require_create_props = require("./create-props-MMZJXgtK.cjs");
//#region src/shared/types/prop-types.ts
function createNormalizer(fn) {
return new Proxy({}, { get(_target, key) {
if (key === "style") return (props) => {
return fn({ style: props }).style;
};
return fn;
} });
}
//#endregion
exports.createNormalizer = createNormalizer;
exports.createProps = require_create_props.createProps;
import { C as JSX, S as createNormalizer, _ as Size, a as EventKeyMap, b as NormalizeProps, c as MaybeFn, d as Orientation, f as OrientationProperty, g as RequiredBy, h as Required, i as EventKey, l as NonNullable, m as Rect, n as Direction, o as LocaleProperties, p as Point, r as DirectionProperty, s as MaybeElement, t as CommonProperties, u as Nullable, v as Style, x as PropTypes, y as createProps } from "./index-DFJGBSAc.cjs";
export { CommonProperties, Direction, DirectionProperty, EventKey, EventKeyMap, JSX, LocaleProperties, MaybeElement, MaybeFn, NonNullable, NormalizeProps, Nullable, Orientation, OrientationProperty, Point, PropTypes, Rect, Required, RequiredBy, Size, Style, createNormalizer, createProps };
import { C as JSX, S as createNormalizer, _ as Size, a as EventKeyMap, b as NormalizeProps, c as MaybeFn, d as Orientation, f as OrientationProperty, g as RequiredBy, h as Required, i as EventKey, l as NonNullable, m as Rect, n as Direction, o as LocaleProperties, p as Point, r as DirectionProperty, s as MaybeElement, t as CommonProperties, u as Nullable, v as Style, x as PropTypes, y as createProps } from "./index-Cq2OwLf_.mjs";
export { CommonProperties, Direction, DirectionProperty, EventKey, EventKeyMap, JSX, LocaleProperties, MaybeElement, MaybeFn, NonNullable, NormalizeProps, Nullable, Orientation, OrientationProperty, Point, PropTypes, Rect, Required, RequiredBy, Size, Style, createNormalizer, createProps };
import { t as createProps } from "./create-props-Bi7oeFLF.mjs";
//#region src/shared/types/prop-types.ts
function createNormalizer(fn) {
return new Proxy({}, { get(_target, key) {
if (key === "style") return (props) => {
return fn({ style: props }).style;
};
return fn;
} });
}
//#endregion
export { createNormalizer, createProps };
+146
-2
{
"name": "@ginxjs/dom",
"version": "0.0.1",
"version": "0.0.4",
"description": "DOM utilities for the @ginxjs/core primitives.",
"homepage": "https://github.com/ginxjs/primitives#readme",
"bugs": {
"url": "https://github.com/ginxjs/primitives/issues"
},
"license": "MIT",
"author": "ginxjs <npm@ginxjs.com>",
"repository": {
"type": "git",
"url": "git+https://github.com/ginxjs/primitives.git"
},
"files": [
"dist"
],
"type": "module",
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.cts",
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
},
"./anatomy": {
"import": "./dist/anatomy.mjs",
"require": "./dist/anatomy.cjs"
},
"./aria-hidden": {
"import": "./dist/aria-hidden.mjs",
"require": "./dist/aria-hidden.cjs"
},
"./auto-resize": {
"import": "./dist/auto-resize.mjs",
"require": "./dist/auto-resize.cjs"
},
"./color-utils": {
"import": "./dist/color-utils.mjs",
"require": "./dist/color-utils.cjs"
},
"./dismissable": {
"import": "./dist/dismissable.mjs",
"require": "./dist/dismissable.cjs"
},
"./dom-query": {
"import": "./dist/dom-query.mjs",
"require": "./dist/dom-query.cjs"
},
"./file-utils": {
"import": "./dist/file-utils.mjs",
"require": "./dist/file-utils.cjs"
},
"./focus-trap": {
"import": "./dist/focus-trap.mjs",
"require": "./dist/focus-trap.cjs"
},
"./focus-visible": {
"import": "./dist/focus-visible.mjs",
"require": "./dist/focus-visible.cjs"
},
"./hotkeys": {
"import": "./dist/hotkeys.mjs",
"require": "./dist/hotkeys.cjs"
},
"./i18n-utils": {
"import": "./dist/i18n-utils.mjs",
"require": "./dist/i18n-utils.cjs"
},
"./interact-outside": {
"import": "./dist/interact-outside.mjs",
"require": "./dist/interact-outside.cjs"
},
"./json-tree-utils": {
"import": "./dist/json-tree-utils.mjs",
"require": "./dist/json-tree-utils.cjs"
},
"./live-region": {
"import": "./dist/live-region.mjs",
"require": "./dist/live-region.cjs"
},
"./machines/accordion": {
"import": "./dist/machines/accordion/index.mjs",
"require": "./dist/machines/accordion/index.cjs"
},
"./machines/async-list": {
"import": "./dist/machines/async-list/index.mjs",
"require": "./dist/machines/async-list/index.cjs"
},
"./machines/avatar": {
"import": "./dist/machines/avatar/index.mjs",
"require": "./dist/machines/avatar/index.cjs"
},
"./machines/carousel": {
"import": "./dist/machines/carousel/index.mjs",
"require": "./dist/machines/carousel/index.cjs"
},
"./machines/cascade-select": {
"import": "./dist/machines/cascade-select/index.mjs",
"require": "./dist/machines/cascade-select/index.cjs"
},
"./machines/knob": {
"import": "./dist/machines/knob/index.mjs",
"require": "./dist/machines/knob/index.cjs"
},
"./popper": {
"import": "./dist/popper.mjs",
"require": "./dist/popper.cjs"
},
"./rect": {
"import": "./dist/rect.mjs",
"require": "./dist/rect.cjs"
},
"./remove-scroll": {
"import": "./dist/remove-scroll.mjs",
"require": "./dist/remove-scroll.cjs"
},
"./scroll-snap": {
"import": "./dist/scroll-snap.mjs",
"require": "./dist/scroll-snap.cjs"
},
"./store": {
"import": "./dist/store.mjs",
"require": "./dist/store.cjs"
},
"./types": {
"import": "./dist/types.mjs",
"require": "./dist/types.cjs"
},
"./package.json": "./package.json"
},
"publishConfig": {
"access": "public"
},
"dependencies": {
"@floating-ui/dom": "^1.7.6",
"csstype": "^3.2.3",
"proxy-compare": "^3.0.1",
"@ginxjs/core": "0.0.4"
},
"peerDependencies": {
"@ginxjs/core": "0.0.4"
},
"scripts": {
"build": "tsdown",
"typecheck": "tsc --noEmit",
"lint": "oxlint",
"format": "oxfmt"
}
}
}