UNPKG

react-lazy-svg

Version:

react-lazy-svg is a simple way to use SVGs with the performance benefits of a sprite-sheet and svg css styling possibilities. Without bloating the bundle. It automatically creates a sprite-sheet for all used SVGs on the client but also provides the option

272 lines (255 loc) 10.8 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var React = require('react'); var reactDom = require('react-dom'); function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } var React__default = /*#__PURE__*/_interopDefaultLegacy(React); /****************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ var __assign = function() { __assign = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; function __rest(s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; } function __values(o) { var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; if (m) return m.call(o); if (o && typeof o.length === "number") return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); } function __read(o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; } function __spreadArray(to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); } var defaultInternalSpriteSheetId = '__SVG_SPRITE_SHEET__'; var isSSR = typeof document === 'undefined'; var hidden = { height: 0, width: 0, position: 'absolute', visibility: 'hidden', }; function SpriteSheet(_a) { var icons = _a.icons, _b = _a.spriteSheetId, spriteSheetId = _b === void 0 ? defaultInternalSpriteSheetId : _b, embeddedSSR = _a.embeddedSSR; var spriteSheetContainer = React.useRef(!isSSR && !embeddedSSR ? document.getElementById(spriteSheetId) : null); var renderedIcons = icons.map(function (_a) { var id = _a.id, svgString = _a.svgString, _b = _a.attributes; _b.width; _b.height; var xmlnsXlink = _b["xmlns:xlink"], attributes = __rest(_b, ["width", "height", 'xmlns:xlink']); return (React__default["default"].createElement("symbol", __assign({ key: id, id: id, xmlnsXlink: xmlnsXlink }, attributes, { dangerouslySetInnerHTML: svgString }))); }); if (spriteSheetContainer.current) { return reactDom.createPortal(renderedIcons, spriteSheetContainer.current); } return (React__default["default"].createElement("svg", { id: spriteSheetId, style: hidden }, renderedIcons)); } var globalIconsCache = new Map(); var noop = function () { return undefined; }; var spriteContext = React.createContext({ registerSVG: noop }); var mapAttributes = function (rawAttributes) { var match = null; var attributes = {}; var attributesRegex = /(.*?)=["'](.*?)["']/gim; while ((match = attributesRegex.exec(rawAttributes))) { var _a = __read(match, 3), name_1 = _a[1], value = _a[2]; if (name_1 && value) { attributes[name_1.trim()] = value; } } return attributes; }; var localIconsList = []; var registeredListeners = new Set(); var addListener = function (listener) { registeredListeners.add(listener); listener(localIconsList); }; var addIcon = function (icon) { var e_1, _a; localIconsList = __spreadArray(__spreadArray([], __read(localIconsList), false), [icon], false); try { for (var registeredListeners_1 = __values(registeredListeners), registeredListeners_1_1 = registeredListeners_1.next(); !registeredListeners_1_1.done; registeredListeners_1_1 = registeredListeners_1.next()) { var listener = registeredListeners_1_1.value; listener(localIconsList); } } catch (e_1_1) { e_1 = { error: e_1_1 }; } finally { try { if (registeredListeners_1_1 && !registeredListeners_1_1.done && (_a = registeredListeners_1.return)) _a.call(registeredListeners_1); } finally { if (e_1) throw e_1.error; } } }; var parseSVG = function (url, svgString) { if (svgString) { var svgRegex = /<svg([\s\S]*?)>([\s\S]*?)<\/svg>/gim; var matches = svgRegex.exec(svgString); if (matches) { var _a = __read(matches, 3), attributesString = _a[1], htmlString = _a[2]; if (!attributesString || !htmlString) { return; } var attributes = mapAttributes(attributesString); var svgString_1 = { __html: htmlString.trim(), }; var id = url; return { id: id, svgString: svgString_1, attributes: attributes }; } } return undefined; }; var registerIconInCache = function (url, svgString, knownIcons) { var iconData = parseSVG(url, svgString); if (iconData) { if (!isSSR) { addIcon(iconData); } } else if (knownIcons.has(url)) { knownIcons.delete(url); } return iconData; }; var useIcons = function () { var _a = __read(React.useState(localIconsList), 2), icons = _a[0], setIcons = _a[1]; React.useEffect(function () { addListener(setIcons); return function () { registeredListeners.delete(setIcons); }; }, []); return icons; }; var SpriteContextProvider = function (_a) { var children = _a.children, loadSVG = _a.loadSVG, _b = _a.knownIcons, knownIcons = _b === void 0 ? globalIconsCache : _b, _c = _a.embeddedSSR, embeddedSSR = _c === void 0 ? false : _c; var icons = useIcons(); var registerSVG = React.useCallback(function (url) { if (knownIcons.has(url)) { return; } var iconPromise = loadSVG(url).then(function (svgString) { return registerIconInCache(url, svgString, knownIcons); }); knownIcons.set(url, iconPromise); }, [knownIcons, loadSVG]); var wrappingContextRegisterSVG = React.useContext(spriteContext).registerSVG; var contextValue = React.useMemo(function () { return ({ registerSVG: wrappingContextRegisterSVG === noop ? registerSVG : wrappingContextRegisterSVG, }); }, [registerSVG, wrappingContextRegisterSVG]); return (React__default["default"].createElement(spriteContext.Provider, { value: contextValue }, children, (!isSSR || embeddedSSR) && (React__default["default"].createElement(SpriteSheet, { embeddedSSR: embeddedSSR, icons: icons })))); }; var Icon = function (_a) { var url = _a.url, props = __rest(_a, ["url"]); var registerSVG = React.useContext(spriteContext).registerSVG; if (isSSR) { registerSVG(url); } else { // eslint-disable-next-line react-hooks/rules-of-hooks React.useEffect(function () { registerSVG(url); }, [registerSVG, url]); } return (React__default["default"].createElement("svg", __assign({}, props), React__default["default"].createElement("use", { xlinkHref: "#".concat(url) }))); }; var mapNodeAttributes = function (rawAttributes) { return Array.from(rawAttributes).reduce(function (attributes, current) { attributes[current.name] = current.value; return attributes; }, {}); }; var initOnClient = function (knownIcons, spriteSheetId) { var e_2, _a; if (knownIcons === void 0) { knownIcons = globalIconsCache; } if (spriteSheetId === void 0) { spriteSheetId = defaultInternalSpriteSheetId; } knownIcons.clear(); var spriteSheet = document.getElementById(spriteSheetId); if (spriteSheet) { var sprites = Array.from(spriteSheet.querySelectorAll('symbol')); var _loop_1 = function (node) { var innerHTML = node.innerHTML; var id = node.id, rawAttributes = node.attributes; var attributes = mapNodeAttributes(rawAttributes); var iconData = { id: id, attributes: attributes, svgString: { __html: innerHTML.trim() }, }; addIcon(iconData); knownIcons.set(id, new Promise(function (resolve) { return resolve(iconData); })); }; try { for (var sprites_1 = __values(sprites), sprites_1_1 = sprites_1.next(); !sprites_1_1.done; sprites_1_1 = sprites_1.next()) { var node = sprites_1_1.value; _loop_1(node); } } catch (e_2_1) { e_2 = { error: e_2_1 }; } finally { try { if (sprites_1_1 && !sprites_1_1.done && (_a = sprites_1.return)) _a.call(sprites_1); } finally { if (e_2) throw e_2.error; } } } }; exports.Icon = Icon; exports.SpriteContextProvider = SpriteContextProvider; exports.initOnClient = initOnClient;