UNPKG

iconista

Version:

Thousands of SVG icons with one React component

67 lines (66 loc) 2.47 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const react_1 = tslib_1.__importDefault(require("react")); const getUrl_1 = require("./getUrl"); const useRefMounted_1 = tslib_1.__importDefault(require("react-use/lib/useRefMounted")); const { useEffect, useState, useRef } = react_1.default; const cache = {}; const loadDoc = (url) => new Promise((resolve, reject) => { const req = new XMLHttpRequest(); req.onreadystatechange = () => { const { readyState, status, responseXML: doc } = req; if (readyState !== 4) return; if (status !== 200) return reject(new Error(`SVG loading HTTP ${status} error: ${url}`)); if (!doc) return reject(new Error(`Could not load SVG Document: ${url}`)); resolve(doc); }; req.open('GET', url, true); req.send(); }); const Svg = ({ set, icon, getUrl = getUrl_1.getUrl, ...rest }) => { const ref = useRef(null); const refMounted = (0, useRefMounted_1.default)(); const [error, setError] = useState(); useEffect(() => { const applyDoc = (doc) => { const el = ref.current; if (!el) return; const svg = doc.getRootNode().childNodes[0]; const { childNodes } = svg; // Set SVG child nodes. for (let i = 0; i < childNodes.length; i++) el.appendChild(childNodes[i].cloneNode(true)); // Set SVG attributes. for (let i = 0; i < svg.attributes.length; i++) { const { name, value } = svg.attributes[i]; el.setAttribute(name, value); } }; const key = `${set}:${icon}`; if (cache[key]) applyDoc(cache[key]); else { const url = getUrl({ set, icon }); loadDoc(url).then((doc) => { if (!refMounted.current) return; applyDoc((cache[key] = doc)); }, (error) => { if (!refMounted.current) return; setError(error); }); } }, [set, icon]); if (error) { const url = getUrl({ set, icon }); return react_1.default.createElement("img", { ...rest, src: url, title: error.message }); } return react_1.default.createElement("svg", { ref: ref, ...rest }); }; exports.default = Svg;