UNPKG

react-svg

Version:

A React component that injects SVG into the DOM.

205 lines (204 loc) 7.18 kB
"use client"; Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" }); //#region \0rolldown/runtime.js var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) { key = keys[i]; if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: ((k) => from[k]).bind(null, key), enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod)); //#endregion let _tanem_svg_injector = require("@tanem/svg-injector"); let react = require("react"); react = __toESM(react); //#region src/owner-window.ts const ownerWindow = (node) => { return ((node === null || node === void 0 ? void 0 : node.ownerDocument) || document).defaultView || window; }; //#endregion //#region src/ReactSVG.tsx const svgNamespace = "http://www.w3.org/2000/svg"; const xlinkNamespace = "http://www.w3.org/1999/xlink"; const idPrefix = `react-svg-${Math.random().toString(36).slice(2, 6)}`; let idCounter = 0; const ReactSVG = react.forwardRef(({ afterInjection = () => void 0, beforeInjection = () => void 0, desc = "", evalScripts = "never", fallback: Fallback, httpRequestWithCredentials = false, loading: Loading, loadingDelay = 0, onError = () => void 0, renumerateIRIElements = true, src, title = "", useRequestCache = true, wrapper = "div", ...rest }, forwardedRef) => { const [hasError, setHasError] = react.useState(false); const [isLoading, setIsLoading] = react.useState(true); const [hasLoadingDelayElapsed, setHasLoadingDelayElapsed] = react.useState(loadingDelay <= 0); const [injectionId, setInjectionId] = react.useState(0); const hasInjectedRef = react.useRef(false); const reactWrapperRef = react.useRef(null); const callbacksRef = react.useRef({ afterInjection, beforeInjection, onError }); react.useEffect(() => { callbacksRef.current = { afterInjection, beforeInjection, onError }; }); const loadingDelayRef = react.useRef(loadingDelay); react.useEffect(() => { loadingDelayRef.current = loadingDelay; }); const refCallback = react.useCallback((reactWrapper) => { reactWrapperRef.current = reactWrapper; if (typeof forwardedRef === "function") forwardedRef(reactWrapper); else if (forwardedRef) forwardedRef.current = reactWrapper; }, [forwardedRef]); react.useEffect(() => { const reactWrapper = reactWrapperRef.current; /* istanbul ignore next */ if (!(reactWrapper instanceof ownerWindow(reactWrapper).Node)) return; let isActive = true; let nonReactWrapper = null; const removeSVG = () => { if (nonReactWrapper === null || nonReactWrapper === void 0 ? void 0 : nonReactWrapper.parentNode) { nonReactWrapper.parentNode.removeChild(nonReactWrapper); nonReactWrapper = null; } }; setHasError(false); setIsLoading(true); setHasLoadingDelayElapsed(loadingDelayRef.current <= 0); if (hasInjectedRef.current) setInjectionId((id) => id + 1); else hasInjectedRef.current = true; let nonReactTarget; if (wrapper === "svg") { nonReactWrapper = document.createElementNS(svgNamespace, wrapper); nonReactWrapper.setAttribute("xmlns", svgNamespace); nonReactWrapper.setAttribute("xmlns:xlink", xlinkNamespace); nonReactTarget = document.createElementNS(svgNamespace, wrapper); } else { nonReactWrapper = document.createElement(wrapper); nonReactTarget = document.createElement(wrapper); } nonReactWrapper.appendChild(nonReactTarget); nonReactTarget.dataset.src = src; reactWrapper.appendChild(nonReactWrapper); const handleError = (error) => { removeSVG(); if (isActive) { setHasError(true); setIsLoading(false); } callbacksRef.current.onError(error); }; const afterEach = (error, svg) => { if (error) { handleError(error); return; } if (!isActive) return; setIsLoading(false); try { callbacksRef.current.afterInjection(svg); } catch (afterInjectionError) { handleError(afterInjectionError); } }; const beforeEach = (svg) => { svg.setAttribute("role", "img"); const ariaLabelledBy = []; const ariaDescribedBy = []; if (title) { const originalTitle = svg.querySelector(":scope > title"); if (originalTitle) svg.removeChild(originalTitle); const titleId = `${idPrefix}-title-${++idCounter}`; const newTitle = document.createElementNS(svgNamespace, "title"); newTitle.id = titleId; newTitle.textContent = title; svg.prepend(newTitle); ariaLabelledBy.push(titleId); } if (desc) { const originalDesc = svg.querySelector(":scope > desc"); if (originalDesc) svg.removeChild(originalDesc); const descId = `${idPrefix}-desc-${++idCounter}`; const newDesc = document.createElementNS(svgNamespace, "desc"); newDesc.id = descId; newDesc.textContent = desc; const existingTitle = svg.querySelector(":scope > title"); if (existingTitle) existingTitle.after(newDesc); else svg.prepend(newDesc); ariaDescribedBy.push(descId); } if (ariaLabelledBy.length > 0) svg.setAttribute("aria-labelledby", ariaLabelledBy.join(" ")); if (ariaDescribedBy.length > 0) svg.setAttribute("aria-describedby", ariaDescribedBy.join(" ")); try { callbacksRef.current.beforeInjection(svg); } catch (error) { handleError(error); } }; (0, _tanem_svg_injector.SVGInjector)(nonReactTarget, { afterEach, beforeEach, cacheRequests: useRequestCache, evalScripts, httpRequestWithCredentials, renumerateIRIElements }); return () => { isActive = false; removeSVG(); }; }, [ desc, evalScripts, httpRequestWithCredentials, renumerateIRIElements, src, title, useRequestCache, wrapper ]); react.useEffect(() => { if (!isLoading) return; if (loadingDelay <= 0) { setHasLoadingDelayElapsed(true); return; } setHasLoadingDelayElapsed(false); const timeoutId = setTimeout(() => { setHasLoadingDelayElapsed(true); }, loadingDelay); return () => { clearTimeout(timeoutId); }; }, [ injectionId, isLoading, loadingDelay ]); const Wrapper = wrapper; return /* @__PURE__ */ react.createElement(Wrapper, { ...rest, ref: refCallback, ...wrapper === "svg" ? { xmlns: svgNamespace, xmlnsXlink: xlinkNamespace } : {} }, isLoading && hasLoadingDelayElapsed && Loading && /* @__PURE__ */ react.createElement(Loading, null), hasError && Fallback && /* @__PURE__ */ react.createElement(Fallback, null)); }); ReactSVG.displayName = "ReactSVG"; //#endregion exports.ReactSVG = ReactSVG; //# sourceMappingURL=react-svg.cjs.map