iconista
Version:
Thousands of SVG icons with one React component
57 lines (56 loc) • 2.16 kB
JavaScript
;
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 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 });
fetch(url, { cache: 'force-cache' })
.then(r => r.text())
.then(text => {
if (!refMounted.current)
return;
const parser = new DOMParser();
const doc = parser.parseFromString(text, 'application/xml');
applyDoc((cache[key] = doc));
})
.catch((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;