iconly 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2023 ux-ui.pro
3
+ Copyright (c) 2024 ux-ui.pro
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  [![GitHub package version](https://img.shields.io/github/package-json/v/ux-ui-pro/iconly.svg)](https://github.com/ux-ui-pro/iconly)
8
8
  [![NPM Downloads](https://img.shields.io/npm/dm/iconly.svg?style=flat)](https://www.npmjs.org/package/iconly)
9
9
 
10
- <sup>500B gzipped</sup>
10
+ <p>The Iconly class is designed to manage icons in a web application</p>
11
11
  <h3><a href="https://codepen.io/ux-ui/pen/zYmyqWR">Demo</a></h3>
12
12
 
13
13
  </div>
@@ -26,11 +26,13 @@ import Iconly from 'iconly';
26
26
  ```
27
27
 
28
28
  ```javascript
29
- const icons = new Iconly({
30
- file: '/sprite.svg',
29
+ const iconly = new Iconly({
30
+ file: './sprite.svg',
31
+ version: '1.0',
32
+ debug: true,
31
33
  });
32
34
 
33
- icons.init();
35
+ iconly.init().then(() => console.log('Iconly is initialized and icons are loaded.'));
34
36
  ```
35
37
  <br>
36
38
 
@@ -38,7 +40,7 @@ icons.init();
38
40
  <sub>icons.svg</sub>
39
41
 
40
42
  ```HTML
41
- <svg id="iconset" aria-hidden="true" style="width: 0; height: 0; position: absolute;">
43
+ <svg>
42
44
  <symbol id="icon-one" viewBox="0 0 100 100">
43
45
  <path ... />
44
46
  </symbol>
@@ -53,7 +55,7 @@ icons.init();
53
55
  ### Usage
54
56
  ```HTML
55
57
  <svg>
56
- <use xlink:href="#icon-name"></use>
58
+ <use href="#icon-name"></use>
57
59
  </svg>
58
60
  ```
59
61
  <br>
package/dist/index.js CHANGED
@@ -11,43 +11,95 @@ $parcel$defineInteropFlag(module.exports);
11
11
 
12
12
  $parcel$export(module.exports, "default", () => $4fa36e821943b400$export$2e2bcd8739ae039);
13
13
  class $4fa36e821943b400$var$Iconly {
14
+ static #dbInstance;
15
+ #options;
16
+ #container;
14
17
  constructor(options){
15
- this.options = {
18
+ this.#options = {
16
19
  file: "./icons.svg",
20
+ version: "1.0",
21
+ debug: false,
22
+ container: document.body || document.documentElement,
17
23
  ...options
18
24
  };
19
- this.isLocalStorage = typeof window.localStorage !== "undefined";
20
- this.body = document.body;
25
+ this.#container = typeof this.#options.container === "string" ? document.querySelector(this.#options.container) : this.#options.container;
26
+ if (!$4fa36e821943b400$var$Iconly.#dbInstance) $4fa36e821943b400$var$Iconly.#dbInstance = this.#openDB("iconlyDB", 1);
21
27
  }
22
- async init() {
23
- const { file: file } = this.options;
24
- if (this.isLocalStorage) {
25
- const storedSize = localStorage.getItem("inlineSVGsize");
26
- const storedData = localStorage.getItem("inlineSVGdata");
27
- const response = await fetch(file);
28
- if (!response.ok) throw new Error("Network response was not ok");
29
- const data = await response.text();
30
- if (storedSize && storedSize === data.length.toString()) this.insert(storedData);
31
- else {
32
- this.insert(data);
33
- localStorage.setItem("inlineSVGdata", data);
34
- localStorage.setItem("inlineSVGsize", data.length.toString());
35
- }
36
- } else {
28
+ async #openDB(name, version) {
29
+ if (!("indexedDB" in window)) {
30
+ this.#logError("This browser doesn't support IndexedDB");
31
+ return;
32
+ }
33
+ let db;
34
+ try {
35
+ db = await new Promise((resolve, reject)=>{
36
+ const request = indexedDB.open(name, version);
37
+ request.onerror = ()=>reject(`IndexedDB error: ${request.error}`);
38
+ request.onupgradeneeded = (event)=>{
39
+ const db = event.target.result;
40
+ if (!db.objectStoreNames.contains("icons")) db.createObjectStore("icons", {
41
+ keyPath: "version"
42
+ });
43
+ };
44
+ request.onsuccess = ()=>resolve(request.result);
45
+ });
46
+ } catch (error) {
47
+ this.#logError(error);
48
+ throw error;
49
+ }
50
+ return db;
51
+ }
52
+ async #fetchData(file) {
53
+ try {
37
54
  const response = await fetch(file);
38
55
  if (!response.ok) throw new Error("Network response was not ok");
39
- const data = await response.text();
40
- this.insert(data);
56
+ return response.text();
57
+ } catch (error) {
58
+ this.#logError(error);
59
+ throw error;
60
+ }
61
+ }
62
+ async #insert(data) {
63
+ let iconSetDiv = document.getElementById("iconset");
64
+ if (!iconSetDiv) {
65
+ iconSetDiv = document.createElement("div");
66
+ iconSetDiv.id = "iconset";
67
+ iconSetDiv.setAttribute("aria-hidden", "true");
68
+ iconSetDiv.style.cssText = "width: 0; height: 0; position: absolute;";
69
+ this.#container.appendChild(iconSetDiv);
41
70
  }
71
+ iconSetDiv.innerHTML = data;
42
72
  }
43
- insert(data) {
44
- if (!document.getElementById("iconset")) {
45
- if (this.body) this.body.insertAdjacentHTML("beforeend", data);
46
- else document.addEventListener("DOMContentLoaded", ()=>{
47
- this.body.insertAdjacentHTML("beforeend", data);
73
+ async init() {
74
+ const { file: file, version: version } = this.#options;
75
+ try {
76
+ let data = await this.#fetchData(file);
77
+ const db = await $4fa36e821943b400$var$Iconly.#dbInstance;
78
+ const tx = db.transaction("icons", "readwrite");
79
+ const store = tx.objectStore("icons");
80
+ const dbVersion = await new Promise((resolve, reject)=>{
81
+ const request = store.get(version);
82
+ request.onsuccess = ()=>resolve(request.result);
83
+ request.onerror = ()=>reject(request.error);
84
+ });
85
+ if (!(dbVersion && dbVersion.data)) await new Promise((resolve, reject)=>{
86
+ const request = store.put({
87
+ version: version,
88
+ data: data
89
+ });
90
+ request.onsuccess = ()=>resolve();
91
+ request.onerror = ()=>reject(request.error);
48
92
  });
93
+ else data = dbVersion.data;
94
+ await tx.complete;
95
+ await this.#insert(data);
96
+ } catch (error) {
97
+ this.#logError("Error initializing Iconly:", error);
49
98
  }
50
99
  }
100
+ #logError(...messages) {
101
+ if (this.#options.debug) console.error(...messages);
102
+ }
51
103
  }
52
104
  var $4fa36e821943b400$export$2e2bcd8739ae039 = $4fa36e821943b400$var$Iconly;
53
105
 
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"mappings":";;;;;;;;;;;;AAAA,MAAM;IACL,YAAY,OAAO,CAAE;QACpB,IAAI,CAAC,OAAO,GAAG;YAAE,MAAM;YAAe,GAAG,OAAO;QAAC;QACjD,IAAI,CAAC,cAAc,GAAG,OAAO,OAAO,YAAY,KAAK;QACrD,IAAI,CAAC,IAAI,GAAG,SAAS,IAAI;IAC1B;IAEA,MAAM,OAAO;QACZ,MAAM,QAAE,IAAI,EAAE,GAAG,IAAI,CAAC,OAAO;QAE7B,IAAI,IAAI,CAAC,cAAc,EAAE;YACxB,MAAM,aAAa,aAAa,OAAO,CAAC;YACxC,MAAM,aAAa,aAAa,OAAO,CAAC;YACxC,MAAM,WAAW,MAAM,MAAM;YAE7B,IAAI,CAAC,SAAS,EAAE,EAAE,MAAM,IAAI,MAAM;YAElC,MAAM,OAAO,MAAM,SAAS,IAAI;YAEhC,IAAI,cAAc,eAAe,KAAK,MAAM,CAAC,QAAQ,IACpD,IAAI,CAAC,MAAM,CAAC;iBACN;gBACN,IAAI,CAAC,MAAM,CAAC;gBAEZ,aAAa,OAAO,CAAC,iBAAiB;gBACtC,aAAa,OAAO,CAAC,iBAAiB,KAAK,MAAM,CAAC,QAAQ;YAC3D;QACD,OAAO;YACN,MAAM,WAAW,MAAM,MAAM;YAE7B,IAAI,CAAC,SAAS,EAAE,EAAE,MAAM,IAAI,MAAM;YAElC,MAAM,OAAO,MAAM,SAAS,IAAI;YAEhC,IAAI,CAAC,MAAM,CAAC;QACb;IACD;IAEA,OAAO,IAAI,EAAE;QACZ,IAAI,CAAC,SAAS,cAAc,CAAC;YAC5B,IAAI,IAAI,CAAC,IAAI,EACZ,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,aAAa;iBAE1C,SAAS,gBAAgB,CAAC,oBAAoB;gBAC7C,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,aAAa;YAC3C;;IAGH;AACD;IAEA,2CAAe","sources":["src/index.js"],"sourcesContent":["class Iconly {\r\n\tconstructor(options) {\r\n\t\tthis.options = { file: './icons.svg', ...options };\r\n\t\tthis.isLocalStorage = typeof window.localStorage !== 'undefined';\r\n\t\tthis.body = document.body;\r\n\t}\r\n\r\n\tasync init() {\r\n\t\tconst { file } = this.options;\r\n\r\n\t\tif (this.isLocalStorage) {\r\n\t\t\tconst storedSize = localStorage.getItem('inlineSVGsize');\r\n\t\t\tconst storedData = localStorage.getItem('inlineSVGdata');\r\n\t\t\tconst response = await fetch(file);\r\n\r\n\t\t\tif (!response.ok) throw new Error('Network response was not ok');\r\n\r\n\t\t\tconst data = await response.text();\r\n\r\n\t\t\tif (storedSize && storedSize === data.length.toString()) {\r\n\t\t\t\tthis.insert(storedData);\r\n\t\t\t} else {\r\n\t\t\t\tthis.insert(data);\r\n\r\n\t\t\t\tlocalStorage.setItem('inlineSVGdata', data);\r\n\t\t\t\tlocalStorage.setItem('inlineSVGsize', data.length.toString());\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tconst response = await fetch(file);\r\n\r\n\t\t\tif (!response.ok) throw new Error('Network response was not ok');\r\n\r\n\t\t\tconst data = await response.text();\r\n\r\n\t\t\tthis.insert(data);\r\n\t\t}\r\n\t}\r\n\r\n\tinsert(data) {\r\n\t\tif (!document.getElementById('iconset')) {\r\n\t\t\tif (this.body) {\r\n\t\t\t\tthis.body.insertAdjacentHTML('beforeend', data);\r\n\t\t\t} else {\r\n\t\t\t\tdocument.addEventListener('DOMContentLoaded', () => {\r\n\t\t\t\t\tthis.body.insertAdjacentHTML('beforeend', data);\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nexport default Iconly;\r\n"],"names":[],"version":3,"file":"index.js.map"}
1
+ {"mappings":"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","sources":["src/index.js"],"sourcesContent":["class Iconly {\r\n\tstatic #dbInstance;\r\n\r\n\t#options;\r\n\r\n\t#container;\r\n\r\n\tconstructor(options) {\r\n\t\tthis.#options = {\r\n\t\t\tfile: './icons.svg',\r\n\t\t\tversion: '1.0',\r\n\t\t\tdebug: false,\r\n\t\t\tcontainer: document.body || document.documentElement,\r\n\t\t\t...options\r\n\t\t};\r\n\t\tthis.#container = typeof this.#options.container === 'string' ? document.querySelector(this.#options.container) : this.#options.container;\r\n\r\n\t\tif (!Iconly.#dbInstance) {\r\n\t\t\tIconly.#dbInstance = this.#openDB('iconlyDB', 1);\r\n\t\t}\r\n\t}\r\n\r\n\tasync #openDB(name, version) {\r\n\t\tif (!('indexedDB' in window)) {\r\n\t\t\tthis.#logError('This browser doesn\\'t support IndexedDB');\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tlet db;\r\n\r\n\t\ttry {\r\n\t\t\tdb = await new Promise((resolve, reject) => {\r\n\t\t\t\tconst request = indexedDB.open(name, version);\r\n\r\n\t\t\t\trequest.onerror = () => reject(`IndexedDB error: ${request.error}`);\r\n\t\t\t\trequest.onupgradeneeded = (event) => {\r\n\t\t\t\t\tconst db = event.target.result;\r\n\t\t\t\t\tif (!db.objectStoreNames.contains('icons')) {\r\n\t\t\t\t\t\tdb.createObjectStore('icons', { keyPath: 'version' });\r\n\t\t\t\t\t}\r\n\t\t\t\t};\r\n\t\t\t\trequest.onsuccess = () => resolve(request.result);\r\n\t\t\t});\r\n\t\t} catch (error) {\r\n\t\t\tthis.#logError(error);\r\n\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t\treturn db;\r\n\t}\r\n\r\n\tasync #fetchData(file) {\r\n\t\ttry {\r\n\t\t\tconst response = await fetch(file);\r\n\r\n\t\t\tif (!response.ok) throw new Error('Network response was not ok');\r\n\r\n\t\t\treturn response.text();\r\n\t\t} catch (error) {\r\n\t\t\tthis.#logError(error);\r\n\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t}\r\n\r\n\tasync #insert(data) {\r\n\t\tlet iconSetDiv = document.getElementById('iconset');\r\n\r\n\t\tif (!iconSetDiv) {\r\n\t\t\ticonSetDiv = document.createElement('div');\r\n\t\t\ticonSetDiv.id = 'iconset';\r\n\t\t\ticonSetDiv.setAttribute('aria-hidden', 'true');\r\n\t\t\ticonSetDiv.style.cssText = 'width: 0; height: 0; position: absolute;';\r\n\r\n\t\t\tthis.#container.appendChild(iconSetDiv);\r\n\t\t}\r\n\r\n\t\ticonSetDiv.innerHTML = data;\r\n\t}\r\n\r\n\tasync init() {\r\n\t\tconst { file, version } = this.#options;\r\n\r\n\t\ttry {\r\n\t\t\tlet data = await this.#fetchData(file);\r\n\r\n\t\t\tconst db = await Iconly.#dbInstance;\r\n\t\t\tconst tx = db.transaction('icons', 'readwrite');\r\n\t\t\tconst store = tx.objectStore('icons');\r\n\r\n\t\t\tconst dbVersion = await new Promise((resolve, reject) => {\r\n\t\t\t\tconst request = store.get(version);\r\n\r\n\t\t\t\trequest.onsuccess = () => resolve(request.result);\r\n\t\t\t\trequest.onerror = () => reject(request.error);\r\n\t\t\t});\r\n\r\n\t\t\tif (!(dbVersion && dbVersion.data)) {\r\n\t\t\t\tawait new Promise((resolve, reject) => {\r\n\t\t\t\t\tconst request = store.put({ version, data });\r\n\r\n\t\t\t\t\trequest.onsuccess = () => resolve();\r\n\t\t\t\t\trequest.onerror = () => reject(request.error);\r\n\t\t\t\t});\r\n\t\t\t} else {\r\n\t\t\t\tdata = dbVersion.data;\r\n\t\t\t}\r\n\r\n\t\t\tawait tx.complete;\r\n\t\t\tawait this.#insert(data);\r\n\t\t} catch (error) {\r\n\t\t\tthis.#logError('Error initializing Iconly:', error);\r\n\t\t}\r\n\t}\r\n\r\n\t#logError(...messages) {\r\n\t\tif (this.#options.debug) {\r\n\t\t\tconsole.error(...messages);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nexport default Iconly;\r\n"],"names":[],"version":3,"file":"index.js.map"}
@@ -1,41 +1,93 @@
1
1
  class $cf838c15c8b009ba$var$Iconly {
2
+ static #dbInstance;
3
+ #options;
4
+ #container;
2
5
  constructor(options){
3
- this.options = {
6
+ this.#options = {
4
7
  file: "./icons.svg",
8
+ version: "1.0",
9
+ debug: false,
10
+ container: document.body || document.documentElement,
5
11
  ...options
6
12
  };
7
- this.isLocalStorage = typeof window.localStorage !== "undefined";
8
- this.body = document.body;
13
+ this.#container = typeof this.#options.container === "string" ? document.querySelector(this.#options.container) : this.#options.container;
14
+ if (!$cf838c15c8b009ba$var$Iconly.#dbInstance) $cf838c15c8b009ba$var$Iconly.#dbInstance = this.#openDB("iconlyDB", 1);
9
15
  }
10
- async init() {
11
- const { file: file } = this.options;
12
- if (this.isLocalStorage) {
13
- const storedSize = localStorage.getItem("inlineSVGsize");
14
- const storedData = localStorage.getItem("inlineSVGdata");
15
- const response = await fetch(file);
16
- if (!response.ok) throw new Error("Network response was not ok");
17
- const data = await response.text();
18
- if (storedSize && storedSize === data.length.toString()) this.insert(storedData);
19
- else {
20
- this.insert(data);
21
- localStorage.setItem("inlineSVGdata", data);
22
- localStorage.setItem("inlineSVGsize", data.length.toString());
23
- }
24
- } else {
16
+ async #openDB(name, version) {
17
+ if (!("indexedDB" in window)) {
18
+ this.#logError("This browser doesn't support IndexedDB");
19
+ return;
20
+ }
21
+ let db;
22
+ try {
23
+ db = await new Promise((resolve, reject)=>{
24
+ const request = indexedDB.open(name, version);
25
+ request.onerror = ()=>reject(`IndexedDB error: ${request.error}`);
26
+ request.onupgradeneeded = (event)=>{
27
+ const db = event.target.result;
28
+ if (!db.objectStoreNames.contains("icons")) db.createObjectStore("icons", {
29
+ keyPath: "version"
30
+ });
31
+ };
32
+ request.onsuccess = ()=>resolve(request.result);
33
+ });
34
+ } catch (error) {
35
+ this.#logError(error);
36
+ throw error;
37
+ }
38
+ return db;
39
+ }
40
+ async #fetchData(file) {
41
+ try {
25
42
  const response = await fetch(file);
26
43
  if (!response.ok) throw new Error("Network response was not ok");
27
- const data = await response.text();
28
- this.insert(data);
44
+ return response.text();
45
+ } catch (error) {
46
+ this.#logError(error);
47
+ throw error;
48
+ }
49
+ }
50
+ async #insert(data) {
51
+ let iconSetDiv = document.getElementById("iconset");
52
+ if (!iconSetDiv) {
53
+ iconSetDiv = document.createElement("div");
54
+ iconSetDiv.id = "iconset";
55
+ iconSetDiv.setAttribute("aria-hidden", "true");
56
+ iconSetDiv.style.cssText = "width: 0; height: 0; position: absolute;";
57
+ this.#container.appendChild(iconSetDiv);
29
58
  }
59
+ iconSetDiv.innerHTML = data;
30
60
  }
31
- insert(data) {
32
- if (!document.getElementById("iconset")) {
33
- if (this.body) this.body.insertAdjacentHTML("beforeend", data);
34
- else document.addEventListener("DOMContentLoaded", ()=>{
35
- this.body.insertAdjacentHTML("beforeend", data);
61
+ async init() {
62
+ const { file: file, version: version } = this.#options;
63
+ try {
64
+ let data = await this.#fetchData(file);
65
+ const db = await $cf838c15c8b009ba$var$Iconly.#dbInstance;
66
+ const tx = db.transaction("icons", "readwrite");
67
+ const store = tx.objectStore("icons");
68
+ const dbVersion = await new Promise((resolve, reject)=>{
69
+ const request = store.get(version);
70
+ request.onsuccess = ()=>resolve(request.result);
71
+ request.onerror = ()=>reject(request.error);
72
+ });
73
+ if (!(dbVersion && dbVersion.data)) await new Promise((resolve, reject)=>{
74
+ const request = store.put({
75
+ version: version,
76
+ data: data
77
+ });
78
+ request.onsuccess = ()=>resolve();
79
+ request.onerror = ()=>reject(request.error);
36
80
  });
81
+ else data = dbVersion.data;
82
+ await tx.complete;
83
+ await this.#insert(data);
84
+ } catch (error) {
85
+ this.#logError("Error initializing Iconly:", error);
37
86
  }
38
87
  }
88
+ #logError(...messages) {
89
+ if (this.#options.debug) console.error(...messages);
90
+ }
39
91
  }
40
92
  var $cf838c15c8b009ba$export$2e2bcd8739ae039 = $cf838c15c8b009ba$var$Iconly;
41
93
 
@@ -1 +1 @@
1
- {"mappings":"AAAA,MAAM;IACL,YAAY,OAAO,CAAE;QACpB,IAAI,CAAC,OAAO,GAAG;YAAE,MAAM;YAAe,GAAG,OAAO;QAAC;QACjD,IAAI,CAAC,cAAc,GAAG,OAAO,OAAO,YAAY,KAAK;QACrD,IAAI,CAAC,IAAI,GAAG,SAAS,IAAI;IAC1B;IAEA,MAAM,OAAO;QACZ,MAAM,QAAE,IAAI,EAAE,GAAG,IAAI,CAAC,OAAO;QAE7B,IAAI,IAAI,CAAC,cAAc,EAAE;YACxB,MAAM,aAAa,aAAa,OAAO,CAAC;YACxC,MAAM,aAAa,aAAa,OAAO,CAAC;YACxC,MAAM,WAAW,MAAM,MAAM;YAE7B,IAAI,CAAC,SAAS,EAAE,EAAE,MAAM,IAAI,MAAM;YAElC,MAAM,OAAO,MAAM,SAAS,IAAI;YAEhC,IAAI,cAAc,eAAe,KAAK,MAAM,CAAC,QAAQ,IACpD,IAAI,CAAC,MAAM,CAAC;iBACN;gBACN,IAAI,CAAC,MAAM,CAAC;gBAEZ,aAAa,OAAO,CAAC,iBAAiB;gBACtC,aAAa,OAAO,CAAC,iBAAiB,KAAK,MAAM,CAAC,QAAQ;YAC3D;QACD,OAAO;YACN,MAAM,WAAW,MAAM,MAAM;YAE7B,IAAI,CAAC,SAAS,EAAE,EAAE,MAAM,IAAI,MAAM;YAElC,MAAM,OAAO,MAAM,SAAS,IAAI;YAEhC,IAAI,CAAC,MAAM,CAAC;QACb;IACD;IAEA,OAAO,IAAI,EAAE;QACZ,IAAI,CAAC,SAAS,cAAc,CAAC;YAC5B,IAAI,IAAI,CAAC,IAAI,EACZ,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,aAAa;iBAE1C,SAAS,gBAAgB,CAAC,oBAAoB;gBAC7C,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,aAAa;YAC3C;;IAGH;AACD;IAEA,2CAAe","sources":["src/index.js"],"sourcesContent":["class Iconly {\r\n\tconstructor(options) {\r\n\t\tthis.options = { file: './icons.svg', ...options };\r\n\t\tthis.isLocalStorage = typeof window.localStorage !== 'undefined';\r\n\t\tthis.body = document.body;\r\n\t}\r\n\r\n\tasync init() {\r\n\t\tconst { file } = this.options;\r\n\r\n\t\tif (this.isLocalStorage) {\r\n\t\t\tconst storedSize = localStorage.getItem('inlineSVGsize');\r\n\t\t\tconst storedData = localStorage.getItem('inlineSVGdata');\r\n\t\t\tconst response = await fetch(file);\r\n\r\n\t\t\tif (!response.ok) throw new Error('Network response was not ok');\r\n\r\n\t\t\tconst data = await response.text();\r\n\r\n\t\t\tif (storedSize && storedSize === data.length.toString()) {\r\n\t\t\t\tthis.insert(storedData);\r\n\t\t\t} else {\r\n\t\t\t\tthis.insert(data);\r\n\r\n\t\t\t\tlocalStorage.setItem('inlineSVGdata', data);\r\n\t\t\t\tlocalStorage.setItem('inlineSVGsize', data.length.toString());\r\n\t\t\t}\r\n\t\t} else {\r\n\t\t\tconst response = await fetch(file);\r\n\r\n\t\t\tif (!response.ok) throw new Error('Network response was not ok');\r\n\r\n\t\t\tconst data = await response.text();\r\n\r\n\t\t\tthis.insert(data);\r\n\t\t}\r\n\t}\r\n\r\n\tinsert(data) {\r\n\t\tif (!document.getElementById('iconset')) {\r\n\t\t\tif (this.body) {\r\n\t\t\t\tthis.body.insertAdjacentHTML('beforeend', data);\r\n\t\t\t} else {\r\n\t\t\t\tdocument.addEventListener('DOMContentLoaded', () => {\r\n\t\t\t\t\tthis.body.insertAdjacentHTML('beforeend', data);\r\n\t\t\t\t});\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n}\r\n\r\nexport default Iconly;\r\n"],"names":[],"version":3,"file":"index.module.js.map"}
1
+ {"mappings":"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","sources":["src/index.js"],"sourcesContent":["class Iconly {\r\n\tstatic #dbInstance;\r\n\r\n\t#options;\r\n\r\n\t#container;\r\n\r\n\tconstructor(options) {\r\n\t\tthis.#options = {\r\n\t\t\tfile: './icons.svg',\r\n\t\t\tversion: '1.0',\r\n\t\t\tdebug: false,\r\n\t\t\tcontainer: document.body || document.documentElement,\r\n\t\t\t...options\r\n\t\t};\r\n\t\tthis.#container = typeof this.#options.container === 'string' ? document.querySelector(this.#options.container) : this.#options.container;\r\n\r\n\t\tif (!Iconly.#dbInstance) {\r\n\t\t\tIconly.#dbInstance = this.#openDB('iconlyDB', 1);\r\n\t\t}\r\n\t}\r\n\r\n\tasync #openDB(name, version) {\r\n\t\tif (!('indexedDB' in window)) {\r\n\t\t\tthis.#logError('This browser doesn\\'t support IndexedDB');\r\n\t\t\treturn;\r\n\t\t}\r\n\r\n\t\tlet db;\r\n\r\n\t\ttry {\r\n\t\t\tdb = await new Promise((resolve, reject) => {\r\n\t\t\t\tconst request = indexedDB.open(name, version);\r\n\r\n\t\t\t\trequest.onerror = () => reject(`IndexedDB error: ${request.error}`);\r\n\t\t\t\trequest.onupgradeneeded = (event) => {\r\n\t\t\t\t\tconst db = event.target.result;\r\n\t\t\t\t\tif (!db.objectStoreNames.contains('icons')) {\r\n\t\t\t\t\t\tdb.createObjectStore('icons', { keyPath: 'version' });\r\n\t\t\t\t\t}\r\n\t\t\t\t};\r\n\t\t\t\trequest.onsuccess = () => resolve(request.result);\r\n\t\t\t});\r\n\t\t} catch (error) {\r\n\t\t\tthis.#logError(error);\r\n\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t\treturn db;\r\n\t}\r\n\r\n\tasync #fetchData(file) {\r\n\t\ttry {\r\n\t\t\tconst response = await fetch(file);\r\n\r\n\t\t\tif (!response.ok) throw new Error('Network response was not ok');\r\n\r\n\t\t\treturn response.text();\r\n\t\t} catch (error) {\r\n\t\t\tthis.#logError(error);\r\n\r\n\t\t\tthrow error;\r\n\t\t}\r\n\t}\r\n\r\n\tasync #insert(data) {\r\n\t\tlet iconSetDiv = document.getElementById('iconset');\r\n\r\n\t\tif (!iconSetDiv) {\r\n\t\t\ticonSetDiv = document.createElement('div');\r\n\t\t\ticonSetDiv.id = 'iconset';\r\n\t\t\ticonSetDiv.setAttribute('aria-hidden', 'true');\r\n\t\t\ticonSetDiv.style.cssText = 'width: 0; height: 0; position: absolute;';\r\n\r\n\t\t\tthis.#container.appendChild(iconSetDiv);\r\n\t\t}\r\n\r\n\t\ticonSetDiv.innerHTML = data;\r\n\t}\r\n\r\n\tasync init() {\r\n\t\tconst { file, version } = this.#options;\r\n\r\n\t\ttry {\r\n\t\t\tlet data = await this.#fetchData(file);\r\n\r\n\t\t\tconst db = await Iconly.#dbInstance;\r\n\t\t\tconst tx = db.transaction('icons', 'readwrite');\r\n\t\t\tconst store = tx.objectStore('icons');\r\n\r\n\t\t\tconst dbVersion = await new Promise((resolve, reject) => {\r\n\t\t\t\tconst request = store.get(version);\r\n\r\n\t\t\t\trequest.onsuccess = () => resolve(request.result);\r\n\t\t\t\trequest.onerror = () => reject(request.error);\r\n\t\t\t});\r\n\r\n\t\t\tif (!(dbVersion && dbVersion.data)) {\r\n\t\t\t\tawait new Promise((resolve, reject) => {\r\n\t\t\t\t\tconst request = store.put({ version, data });\r\n\r\n\t\t\t\t\trequest.onsuccess = () => resolve();\r\n\t\t\t\t\trequest.onerror = () => reject(request.error);\r\n\t\t\t\t});\r\n\t\t\t} else {\r\n\t\t\t\tdata = dbVersion.data;\r\n\t\t\t}\r\n\r\n\t\t\tawait tx.complete;\r\n\t\t\tawait this.#insert(data);\r\n\t\t} catch (error) {\r\n\t\t\tthis.#logError('Error initializing Iconly:', error);\r\n\t\t}\r\n\t}\r\n\r\n\t#logError(...messages) {\r\n\t\tif (this.#options.debug) {\r\n\t\t\tconsole.error(...messages);\r\n\t\t}\r\n\t}\r\n}\r\n\r\nexport default Iconly;\r\n"],"names":[],"version":3,"file":"index.module.js.map"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iconly",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "SVG Sprite",
5
5
  "author": "ux-ui.pro",
6
6
  "license": "MIT",
@@ -30,15 +30,13 @@
30
30
  "devDependencies": {
31
31
  "eslint": "^7.32.0 || ^8.56.0",
32
32
  "eslint-config-airbnb-base": "^15.0.0",
33
- "eslint-plugin-import": "^2.29.1",
34
- "parcel": "^2.11.0",
35
- "postcss-html": "^1.6.0"
33
+ "parcel": "^2.11.0"
36
34
  },
37
35
  "keywords": [
38
36
  "svg",
39
37
  "icon",
40
38
  "icons",
41
39
  "sprite",
42
- "localStorage"
40
+ "IndexedDB"
43
41
  ]
44
42
  }
package/src/index.js CHANGED
@@ -1,50 +1,121 @@
1
1
  class Iconly {
2
+ static #dbInstance;
3
+
4
+ #options;
5
+
6
+ #container;
7
+
2
8
  constructor(options) {
3
- this.options = { file: './icons.svg', ...options };
4
- this.isLocalStorage = typeof window.localStorage !== 'undefined';
5
- this.body = document.body;
9
+ this.#options = {
10
+ file: './icons.svg',
11
+ version: '1.0',
12
+ debug: false,
13
+ container: document.body || document.documentElement,
14
+ ...options
15
+ };
16
+ this.#container = typeof this.#options.container === 'string' ? document.querySelector(this.#options.container) : this.#options.container;
17
+
18
+ if (!Iconly.#dbInstance) {
19
+ Iconly.#dbInstance = this.#openDB('iconlyDB', 1);
20
+ }
6
21
  }
7
22
 
8
- async init() {
9
- const { file } = this.options;
23
+ async #openDB(name, version) {
24
+ if (!('indexedDB' in window)) {
25
+ this.#logError('This browser doesn\'t support IndexedDB');
26
+ return;
27
+ }
10
28
 
11
- if (this.isLocalStorage) {
12
- const storedSize = localStorage.getItem('inlineSVGsize');
13
- const storedData = localStorage.getItem('inlineSVGdata');
14
- const response = await fetch(file);
29
+ let db;
15
30
 
16
- if (!response.ok) throw new Error('Network response was not ok');
31
+ try {
32
+ db = await new Promise((resolve, reject) => {
33
+ const request = indexedDB.open(name, version);
17
34
 
18
- const data = await response.text();
35
+ request.onerror = () => reject(`IndexedDB error: ${request.error}`);
36
+ request.onupgradeneeded = (event) => {
37
+ const db = event.target.result;
38
+ if (!db.objectStoreNames.contains('icons')) {
39
+ db.createObjectStore('icons', { keyPath: 'version' });
40
+ }
41
+ };
42
+ request.onsuccess = () => resolve(request.result);
43
+ });
44
+ } catch (error) {
45
+ this.#logError(error);
19
46
 
20
- if (storedSize && storedSize === data.length.toString()) {
21
- this.insert(storedData);
22
- } else {
23
- this.insert(data);
47
+ throw error;
48
+ }
49
+ return db;
50
+ }
24
51
 
25
- localStorage.setItem('inlineSVGdata', data);
26
- localStorage.setItem('inlineSVGsize', data.length.toString());
27
- }
28
- } else {
52
+ async #fetchData(file) {
53
+ try {
29
54
  const response = await fetch(file);
30
55
 
31
56
  if (!response.ok) throw new Error('Network response was not ok');
32
57
 
33
- const data = await response.text();
58
+ return response.text();
59
+ } catch (error) {
60
+ this.#logError(error);
34
61
 
35
- this.insert(data);
62
+ throw error;
36
63
  }
37
64
  }
38
65
 
39
- insert(data) {
40
- if (!document.getElementById('iconset')) {
41
- if (this.body) {
42
- this.body.insertAdjacentHTML('beforeend', data);
43
- } else {
44
- document.addEventListener('DOMContentLoaded', () => {
45
- this.body.insertAdjacentHTML('beforeend', data);
66
+ async #insert(data) {
67
+ let iconSetDiv = document.getElementById('iconset');
68
+
69
+ if (!iconSetDiv) {
70
+ iconSetDiv = document.createElement('div');
71
+ iconSetDiv.id = 'iconset';
72
+ iconSetDiv.setAttribute('aria-hidden', 'true');
73
+ iconSetDiv.style.cssText = 'width: 0; height: 0; position: absolute;';
74
+
75
+ this.#container.appendChild(iconSetDiv);
76
+ }
77
+
78
+ iconSetDiv.innerHTML = data;
79
+ }
80
+
81
+ async init() {
82
+ const { file, version } = this.#options;
83
+
84
+ try {
85
+ let data = await this.#fetchData(file);
86
+
87
+ const db = await Iconly.#dbInstance;
88
+ const tx = db.transaction('icons', 'readwrite');
89
+ const store = tx.objectStore('icons');
90
+
91
+ const dbVersion = await new Promise((resolve, reject) => {
92
+ const request = store.get(version);
93
+
94
+ request.onsuccess = () => resolve(request.result);
95
+ request.onerror = () => reject(request.error);
96
+ });
97
+
98
+ if (!(dbVersion && dbVersion.data)) {
99
+ await new Promise((resolve, reject) => {
100
+ const request = store.put({ version, data });
101
+
102
+ request.onsuccess = () => resolve();
103
+ request.onerror = () => reject(request.error);
46
104
  });
105
+ } else {
106
+ data = dbVersion.data;
47
107
  }
108
+
109
+ await tx.complete;
110
+ await this.#insert(data);
111
+ } catch (error) {
112
+ this.#logError('Error initializing Iconly:', error);
113
+ }
114
+ }
115
+
116
+ #logError(...messages) {
117
+ if (this.#options.debug) {
118
+ console.error(...messages);
48
119
  }
49
120
  }
50
121
  }
package/src/sprite.svg ADDED
@@ -0,0 +1,17 @@
1
+ <svg id="sprite" preserveAspectRatio="none" fill="none">
2
+ <symbol id="i-dangerous" viewBox="0 0 24 24">
3
+ <path d="M14.9,3H9.1C8.57,3,8.06,3.21,7.68,3.59l-4.1,4.1C3.21,8.06,3,8.57,3,9.1v5.8c0,0.53,0.21,1.04,0.59,1.41l4.1,4.1 C8.06,20.79,8.57,21,9.1,21h5.8c0.53,0,1.04-0.21,1.41-0.59l4.1-4.1C20.79,15.94,21,15.43,21,14.9V9.1c0-0.53-0.21-1.04-0.59-1.41 l-4.1-4.1C15.94,3.21,15.43,3,14.9,3z M15.54,15.54L15.54,15.54c-0.39,0.39-1.02,0.39-1.41,0L12,13.41l-2.12,2.12 c-0.39,0.39-1.02,0.39-1.41,0l0,0c-0.39-0.39-0.39-1.02,0-1.41L10.59,12L8.46,9.88c-0.39-0.39-0.39-1.02,0-1.41l0,0 c0.39-0.39,1.02-0.39,1.41,0L12,10.59l2.12-2.12c0.39-0.39,1.02-0.39,1.41,0l0,0c0.39,0.39,0.39,1.02,0,1.41L13.41,12l2.12,2.12 C15.93,14.51,15.93,15.15,15.54,15.54z"/>
4
+ </symbol>
5
+ <symbol id="i-shopping" viewBox="0 0 24 24">
6
+ <path d="M7,18c-1.1,0-1.99,0.9-1.99,2S5.9,22,7,22s2-0.9,2-2S8.1,18,7,18z M17,18c-1.1,0-1.99,0.9-1.99,2s0.89,2,1.99,2s2-0.9,2-2 S18.1,18,17,18z M19,16c0-0.55-0.45-1-1-1H7l1.1-2h7.45c0.75,0,1.41-0.41,1.75-1.03l3.24-6.14c0.25-0.48,0.08-1.08-0.4-1.34 c-0.49-0.27-1.1-0.08-1.36,0.41L15.55,11H8.53L4.54,2.57C4.38,2.22,4.02,2,3.64,2H2C1.45,2,1,2.45,1,3s0.45,1,1,1h1l3.6,7.59 l-1.35,2.44C4.52,15.37,5.48,17,7,17h11C18.55,17,19,16.55,19,16z M11.29,2.71c0.39-0.39,1.02-0.39,1.41,0l2.59,2.59 c0.39,0.39,0.39,1.02,0,1.41l-2.59,2.59c-0.39,0.39-1.02,0.39-1.41,0c-0.39-0.39-0.39-1.02,0-1.41L12.17,7L9,7C8.45,7,8,6.55,8,6 c0-0.55,0.45-1,1-1l3.17,0l-0.88-0.88C10.9,3.73,10.9,3.1,11.29,2.71z"/>
7
+ </symbol>
8
+ <symbol id="i-percent" viewBox="0 0 24 24">
9
+ <path d="M7.5,4C5.57,4,4,5.57,4,7.5S5.57,11,7.5,11S11,9.43,11,7.5S9.43,4,7.5,4z M7.5,9C6.67,9,6,8.33,6,7.5S6.67,6,7.5,6 S9,6.67,9,7.5S8.33,9,7.5,9z M16.5,13c-1.93,0-3.5,1.57-3.5,3.5s1.57,3.5,3.5,3.5s3.5-1.57,3.5-3.5S18.43,13,16.5,13z M16.5,18 c-0.83,0-1.5-0.67-1.5-1.5s0.67-1.5,1.5-1.5s1.5,0.67,1.5,1.5S17.33,18,16.5,18z M19.29,4.71c0.39,0.39,0.39,1.02,0,1.41 L6.12,19.29c-0.39,0.39-1.02,0.39-1.41,0s-0.39-1.02,0-1.41L17.88,4.71C18.27,4.32,18.9,4.32,19.29,4.71z"/>
10
+ </symbol>
11
+ <symbol id="i-rocket" viewBox="0 0 24 24">
12
+ <path d="M9.19,6.35c-2.04,2.29-3.44,5.58-3.57,5.89l-2.26-0.97c-0.65-0.28-0.81-1.13-0.31-1.63l3.01-3.01 c0.47-0.47,1.15-0.68,1.81-0.55L9.19,6.35L9.19,6.35z M10.68,16.51c0.3,0.3,0.74,0.38,1.12,0.2c1.16-0.54,3.65-1.81,5.26-3.42 c4.59-4.59,4.63-8.33,4.36-9.93c-0.07-0.4-0.39-0.72-0.79-0.79c-1.6-0.27-5.34-0.23-9.93,4.36c-1.61,1.61-2.87,4.1-3.42,5.26 c-0.18,0.38-0.09,0.83,0.2,1.12L10.68,16.51z M17.65,14.81c-2.29,2.04-5.58,3.44-5.89,3.57l0.97,2.26 c0.28,0.65,1.13,0.81,1.63,0.31l3.01-3.01c0.47-0.47,0.68-1.15,0.55-1.81L17.65,14.81L17.65,14.81z M8.94,17.41 c0.2,1.06-0.15,2.04-0.82,2.71c-0.77,0.77-3.16,1.34-4.71,1.64c-0.69,0.13-1.3-0.48-1.17-1.17c0.3-1.55,0.86-3.94,1.64-4.71 c0.67-0.67,1.65-1.02,2.71-0.82C7.76,15.28,8.72,16.24,8.94,17.41z M13,9c0-1.1,0.9-2,2-2s2,0.9,2,2s-0.9,2-2,2S13,10.1,13,9z"/>
13
+ </symbol>
14
+ <symbol id="i-phone" viewBox="0 0 24 24">
15
+ <path d="M12.88 5.05c3.18.4 5.67 2.89 6.07 6.07.06.51.49.88.99.88.04 0 .08 0 .12-.01.55-.07.94-.57.87-1.12-.51-4.09-3.72-7.3-7.81-7.81-.55-.06-1.05.33-1.11.88-.07.55.32 1.05.87 1.11zm.38 2.11c-.53-.14-1.08.18-1.22.72s.18 1.08.72 1.22c1.05.27 1.87 1.09 2.15 2.15.12.45.52.75.97.75.08 0 .17-.01.25-.03.53-.14.85-.69.72-1.22-.47-1.77-1.84-3.14-3.59-3.59zm5.97 8.1l-2.54-.29c-.61-.07-1.21.14-1.64.57l-1.84 1.84c-2.83-1.44-5.15-3.75-6.59-6.59l1.85-1.85c.43-.43.64-1.03.57-1.64l-.29-2.52c-.12-1.01-.97-1.77-1.99-1.77H5.03c-1.13 0-2.07.94-2 2.07.53 8.54 7.36 15.36 15.89 15.89 1.13.07 2.07-.87 2.07-2v-1.73c.01-1.01-.75-1.86-1.76-1.98z"/>
16
+ </symbol>
17
+ </svg>