UNPKG

one

Version:

One is a React framework for web, iOS, and Android apps.

89 lines (86 loc) • 2.72 kB
import { isValidElement, useEffect, useRef, useState } from "react"; import { DomView } from "../web/DomView.mjs"; import { jsx, jsxs } from "react/jsx-runtime"; let warnedInvalidMask = false; function image(node, width, height) { const clone = node.cloneNode(true); const sources = [node, ...node.querySelectorAll("*")]; const copies = [clone, ...clone.querySelectorAll("*")]; sources.forEach((source, index) => { const style = getComputedStyle(source); const copy = copies[index]; for (const property of Array.from(style)) copy.style.setProperty(property, style.getPropertyValue(property)); }); clone.style.opacity = "1"; const content = new XMLSerializer().serializeToString(clone); return `url("data:image/svg+xml,${encodeURIComponent(`<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}"><foreignObject width="100%" height="100%">${content}</foreignObject></svg>`)}")`; } function Mask({ maskElement, children, ...props }) { const ref = useRef(null); const [mask, setMask] = useState(); const valid = isValidElement(maskElement); useEffect(() => { if (!valid) { if (!warnedInvalidMask) { warnedInvalidMask = true; console.warn("Mask: invalid `maskElement` prop was passed to Mask. expected a React element. no mask will render."); } return; } const node = ref.current; if (!node) return; const update = () => { const width = node.clientWidth, height = node.clientHeight; if (width && height) setMask(image(node, width, height)); }; const resize = new ResizeObserver(update); const mutations = new MutationObserver(update); resize.observe(node); mutations.observe(node, { subtree: true, attributes: true, characterData: true, childList: true }); node.addEventListener("load", update, true); update(); return () => { resize.disconnect(); mutations.disconnect(); node.removeEventListener("load", update, true); }; }, [valid, maskElement]); return /* @__PURE__ */ jsxs(DomView, { ...props, children: [valid && /* @__PURE__ */ jsx("div", { ref, "aria-hidden": true, style: { position: "absolute", inset: 0, pointerEvents: "none", opacity: 0, overflow: "hidden" }, children: maskElement }), /* @__PURE__ */ jsx("div", { style: { display: "flex", flexDirection: "column", flex: 1, minWidth: 0, minHeight: 0, ...valid && { maskImage: mask ?? "linear-gradient(transparent,transparent)", WebkitMaskImage: mask ?? "linear-gradient(transparent,transparent)", maskMode: "alpha", maskSize: "100% 100%", maskRepeat: "no-repeat" } }, children })] }); } export { Mask }; //# sourceMappingURL=Mask.mjs.map