@veracity/vui
Version:
Veracity UI is a React component library crafted for use within Veracity applications and pages. Based on Styled Components and @xstyled.
89 lines (87 loc) • 2.51 kB
JavaScript
import { cs } from "../utils/styles.js";
import styled, { css } from "../core/styled.js";
import vui from "../core/vui.js";
import cache from "./cache.js";
import { getAttributes, getSvgContent, initState, parseSvg } from "./helpers.js";
import { useEffect, useRef, useState } from "react";
import { jsx } from "react/jsx-runtime";
//#region src/svg/svg.tsx
const SvgBase = styled.svgBox(({ pathFill }) => {
return css`
${pathFill !== void 0 && (Array.isArray(pathFill) ? pathFill.map((fill, index) => `
& > path:nth-child(${index + 1}) {
fill: ${fill};
}
`).join() : `
& > path {
fill: ${pathFill};
}
`)}
`;
});
/**
* Displays an svg element based on provided children or 'src' prop.
*
* When using src, it loads the content from the given URL and saves in in cache.
*
* Loaded content is parsed with DOMParser (inert) and sanitized against an
* allowlist of SVG elements before being rendered via innerHTML.
*/
const Svg = vui((props, ref) => {
const { children, className, src, ...rest } = props;
const [svgState, setSvgState] = useState(() => initState());
const isMountedRef = useRef(false);
const srcRef = useRef(src);
const prevContentRef = useRef("");
const { content = "", svgAttributes = {} } = svgState;
const innerHTML = !children ? { __html: content } : void 0;
useEffect(() => {
isMountedRef.current = true;
return () => {
isMountedRef.current = false;
};
}, []);
useEffect(() => {
srcRef.current = src;
async function loadSvg(src) {
try {
const response = await cache.get(src);
const svgEl = parseSvg(response);
const content = getSvgContent(svgEl);
const svgAttributes = getAttributes(svgEl);
svgAttributes["data-src"] = src ?? "";
if (srcRef.current === src && isMountedRef.current) {
prevContentRef.current = content;
setSvgState({
content,
svgAttributes
});
}
} catch (error) {
console.error(error);
if (isMountedRef.current) setSvgState(initState());
}
}
if (src) {
setSvgState((prev) => ({
...prev,
content: prevContentRef.current
}));
loadSvg(src);
}
}, [src]);
return /* @__PURE__ */ jsx(SvgBase, {
className: cs("vui-svg", className),
dangerouslySetInnerHTML: innerHTML,
ref,
xmlns: "http://www.w3.org/2000/svg",
...svgAttributes,
...rest,
children
});
});
Svg.displayName = "Svg";
//#endregion
export { Svg, Svg as default, SvgBase };
globalThis.__vuiVersion__ = "5.3.1"
//# sourceMappingURL=svg.js.map