UNPKG

iconly

Version:

Iconly is designed to load and cache SVG icons in the browser, using IndexedDB to store the data. It retrieves the icons from a given SVG file, stores them in IndexedDB, and inserts them into the DOM for easy access and use.

200 lines (199 loc) 6.46 kB
const i = (e, t, o) => ({ code: e, message: t, cause: o }), u = (e) => ({ ok: !0, value: e }), a = (e) => ({ ok: !1, error: e }), w = (e, t) => { const o = e.querySelector('[data-iconly="iconset"]'); let n = o instanceof HTMLElement ? o : null; n || (n = document.createElement("div"), n.setAttribute("data-iconly", "iconset"), n.setAttribute("aria-hidden", "true"), n.style.cssText = "width: 0; height: 0; position: absolute; left: -9999px;", e.appendChild(n)); const f = new DOMParser().parseFromString(t, "image/svg+xml"), c = f.querySelector("parsererror"); if (c) return a( i( "parse_error", `SVG parsing error: ${c.textContent ?? "Unknown error"}` ) ); n.innerHTML = ""; const g = f.documentElement; if (!g) return a(i("parse_error", "No valid SVG content found.")); const b = document.importNode(g, !0); return n.appendChild(b), u(void 0); }, x = async (e, t) => { try { const o = await fetch(e, { signal: t }); if (!o.ok) return a(i("fetch_failed", `Failed to fetch icons from "${e}".`)); const n = await o.text(); return u(n); } catch (o) { return o instanceof DOMException && o.name === "AbortError" ? a(i("fetch_aborted", "Fetch request was aborted.", o)) : a(i("fetch_failed", "Failed to fetch icons.", o)); } }, S = (e = {}) => { const t = e.dbName ?? "iconlyDB", o = e.storeName ?? "icons"; let n = null; const y = async () => { if (n) return n; if (typeof indexedDB > "u") throw i("indexeddb_not_supported", "IndexedDB is not supported."); return n = new Promise((d, r) => { const s = indexedDB.open(t, 1); s.onerror = () => { r( i( "indexeddb_open_failed", "Failed to open IndexedDB connection.", s.error ) ); }, s.onupgradeneeded = (m) => { const l = m.target.result; l.objectStoreNames.contains(o) || l.createObjectStore(o, { keyPath: "version" }); }, s.onsuccess = () => d(s.result); }), n; }, f = (d, r) => d.transaction(o, r).objectStore(o), c = (d, r, s) => d && typeof d == "object" && "code" in d && "message" in d ? d : i(r, s, d); return { get: async (d) => { try { const r = await y(), s = f(r, "readonly"); return await new Promise((m) => { const l = s.get(d); l.onsuccess = () => m(u(l.result)), l.onerror = () => m( a( i( "indexeddb_request_failed", "Failed to read from IndexedDB.", l.error ) ) ); }); } catch (r) { return a(c(r, "indexeddb_open_failed", "Failed to open IndexedDB.")); } }, set: async (d) => { try { const r = await y(), s = f(r, "readwrite"); return await new Promise((m) => { const l = s.put(d); l.onsuccess = () => m(u(void 0)), l.onerror = () => m( a( i( "indexeddb_request_failed", "Failed to write to IndexedDB.", l.error ) ) ); }); } catch (r) { return a(i("indexeddb_open_failed", "Failed to open IndexedDB.", r)); } } }; }, h = () => { const e = /* @__PURE__ */ new Map(); return { get: async (n) => e.has(n) ? u({ version: n, data: e.get(n) ?? "" }) : u(void 0), set: async (n) => (e.set(n.version, n.data), u(void 0)) }; }, _ = (e = {}) => { const t = e.keyPrefix ?? "iconly", o = () => typeof window > "u" || !window.sessionStorage ? a(i("storage_unavailable", "SessionStorage is not available.")) : u(window.sessionStorage); return { get: async (f) => { const c = o(); if (!c.ok) return c; try { const g = c.value.getItem(`${t}:${f}`); if (!g) return u(void 0); const b = JSON.parse(g); return u(b); } catch (g) { return a( i("storage_read_failed", "Failed to read from SessionStorage.", g) ); } }, set: async (f) => { const c = o(); if (!c.ok) return c; try { return c.value.setItem(`${t}:${f.version}`, JSON.stringify(f)), u(void 0); } catch (g) { return a( i("storage_write_failed", "Failed to write to SessionStorage.", g) ); } } }; }, D = (e, t) => !e || e === "indexeddb" ? S({ dbName: t.dbName, storeName: t.storeName }) : e === "memory" ? h() : e === "session" ? _({ keyPrefix: t.sessionKeyPrefix }) : e, N = (e = {}) => { const t = { file: e.file ?? "./icons.svg", version: e.version ?? "1.0", debug: e.debug ?? !1, container: e.container, logger: e.logger, onError: e.onError, onDebug: e.onDebug }, o = D(e.storage, { dbName: e.dbName, storeName: e.storeName, sessionKeyPrefix: e.sessionKeyPrefix }); let n = null; const y = () => { n?.abort(); }, f = () => { if (typeof document > "u") return a( i("container_invalid", "Document is not available in this environment.") ); if (typeof t.container == "string") { const s = document.querySelector(t.container); return !s || !(s instanceof HTMLElement) ? a( i( "container_invalid", `Invalid container selector: "${t.container}".` ) ) : u(s); } if (t.container instanceof HTMLElement) return u(t.container); const r = document.body ?? document.documentElement; return r ? u(r) : a(i("container_invalid", "No valid container element found.")); }, c = (...r) => { t.debug && (t.onDebug?.(...r), t.logger?.debug?.("[Iconly debug]", ...r)); }, g = (r) => { t.onError?.(r), t.logger?.error?.("[Iconly error]", r); }, b = (r) => (g(r), a(r)); return { init: async () => { const r = f(); if (!r.ok) return b(r.error); const s = await o.get(t.version); if (!s.ok) return b(s.error); let m = s.value?.data; if (m) c("Using cached icon set", t.version); else { n = new AbortController(); const v = await x(t.file, n.signal); if (!v.ok) return b(v.error); m = v.value; const p = await o.set({ version: t.version, data: m }); if (!p.ok) return b(p.error); } const l = w(r.value, m); return l.ok ? (c("Iconly has successfully initialized."), u(void 0)) : b(l.error); }, abort: y }; }; export { N as createIconly }; //# sourceMappingURL=index.es.js.map