UNPKG

@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
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