iconly 4.0.0 → 4.1.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/README.md +63 -6
- package/dist/dom-Bqsr32nW.cjs +86 -0
- package/dist/dom-Bqsr32nW.cjs.map +1 -0
- package/dist/dom-senQJ1VA.js +56 -0
- package/dist/dom-senQJ1VA.js.map +1 -0
- package/dist/index.cjs +28 -81
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -45
- package/dist/index.d.ts +2 -45
- package/dist/index.js +2 -54
- package/dist/index.js.map +1 -1
- package/dist/sprite.cjs +21 -0
- package/dist/sprite.cjs.map +1 -0
- package/dist/sprite.d.cts +8 -0
- package/dist/sprite.d.ts +8 -0
- package/dist/sprite.js +19 -0
- package/dist/sprite.js.map +1 -0
- package/dist/types-Byzu8V49.d.cts +59 -0
- package/dist/types-Byzu8V49.d.ts +59 -0
- package/package.json +11 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# iconly
|
|
2
2
|
|
|
3
|
-
A lightweight utility
|
|
3
|
+
A lightweight utility for SVG icon sprites in the browser. Load and cache an external sprite file (`iconly`), or build one from your own icon objects with tree-shaking (`iconly/sprite`).
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/iconly)
|
|
6
6
|
[](https://www.npmjs.com/package/iconly)
|
|
@@ -11,10 +11,10 @@ A lightweight utility to load and cache SVG icons in the browser, using IndexedD
|
|
|
11
11
|
|
|
12
12
|
## Features
|
|
13
13
|
|
|
14
|
-
- Factory-based API with `createIconly()
|
|
14
|
+
- Factory-based API with `createIconly()` — fetch and cache an external sprite file.
|
|
15
15
|
- IndexedDB, memory, or session storage strategies.
|
|
16
|
-
- `
|
|
17
|
-
-
|
|
16
|
+
- `iconly/sprite` — build a sprite from icon objects; no fetch, no storage, zero extra runtime deps.
|
|
17
|
+
- `init()` and `render()` return a `Result` and never throw.
|
|
18
18
|
|
|
19
19
|
---
|
|
20
20
|
|
|
@@ -26,7 +26,7 @@ npm install iconly
|
|
|
26
26
|
|
|
27
27
|
---
|
|
28
28
|
|
|
29
|
-
## Quick Start
|
|
29
|
+
## Quick Start: external sprite file
|
|
30
30
|
|
|
31
31
|
```ts
|
|
32
32
|
import { createIconly } from 'iconly';
|
|
@@ -65,16 +65,66 @@ Sprite file format:
|
|
|
65
65
|
|
|
66
66
|
---
|
|
67
67
|
|
|
68
|
+
## Quick Start: icon objects
|
|
69
|
+
|
|
70
|
+
Import icons as ESM modules — your bundler tree-shakes unused ones. iconly only assembles the sprite string and injects it into the DOM.
|
|
71
|
+
|
|
72
|
+
```ts
|
|
73
|
+
import { createSprite } from 'iconly/sprite';
|
|
74
|
+
import { search, user, trash } from './icons';
|
|
75
|
+
|
|
76
|
+
const sprite = createSprite({
|
|
77
|
+
icons: [search, user, trash],
|
|
78
|
+
container: '#app', // string | HTMLElement, defaults to document.body
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
const result = sprite.render();
|
|
82
|
+
|
|
83
|
+
if (!result.ok) {
|
|
84
|
+
console.error(result.error);
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Icon object format (bring your own):
|
|
89
|
+
|
|
90
|
+
```ts
|
|
91
|
+
export const search = {
|
|
92
|
+
name: 'search', // id for <use href="#search">
|
|
93
|
+
viewBox: '0 0 24 24',
|
|
94
|
+
body: '<path d="..."/>',
|
|
95
|
+
};
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
For SSR or tests — build the string without touching the DOM:
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
import { buildSpriteString } from 'iconly/sprite';
|
|
102
|
+
|
|
103
|
+
const svg = buildSpriteString([search, user, trash]);
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
68
108
|
## API
|
|
69
109
|
|
|
110
|
+
### `iconly`
|
|
111
|
+
|
|
70
112
|
- `createIconly(config?)` — creates an icon loader instance.
|
|
71
113
|
- `iconLoader.init()` — fetches (or loads from cache) the sprite and injects it into the DOM; returns `Result<void>`.
|
|
72
114
|
- `iconLoader.abort()` — cancels an in-flight fetch.
|
|
73
115
|
|
|
116
|
+
### `iconly/sprite`
|
|
117
|
+
|
|
118
|
+
- `createSprite(config)` — creates a sprite builder instance.
|
|
119
|
+
- `sprite.render()` — builds the sprite from `icons` and injects it into the DOM; returns `Result<void>` synchronously.
|
|
120
|
+
- `buildSpriteString(icons)` — returns the SVG sprite string without DOM access.
|
|
121
|
+
|
|
74
122
|
---
|
|
75
123
|
|
|
76
124
|
## Options
|
|
77
125
|
|
|
126
|
+
### `createIconly`
|
|
127
|
+
|
|
78
128
|
| Option | Type | Default | Description |
|
|
79
129
|
| --- | --- | --- | --- |
|
|
80
130
|
| `file` | `string` | `'./icons.svg'` | URL of the SVG file containing the icons. |
|
|
@@ -89,11 +139,18 @@ Sprite file format:
|
|
|
89
139
|
| `onError` | `(error) => void` | `undefined` | Callback invoked on errors. |
|
|
90
140
|
| `onDebug` | `(...args) => void` | `undefined` | Callback invoked for debug messages. |
|
|
91
141
|
|
|
142
|
+
### `createSprite`
|
|
143
|
+
|
|
144
|
+
| Option | Type | Default | Description |
|
|
145
|
+
| --- | --- | --- | --- |
|
|
146
|
+
| `icons` | `IconlyIcon[]` | — | Icon objects to include in the sprite. |
|
|
147
|
+
| `container` | `string \| HTMLElement` | `document.body` | Container where the sprite is injected. |
|
|
148
|
+
|
|
92
149
|
---
|
|
93
150
|
|
|
94
151
|
## Error handling
|
|
95
152
|
|
|
96
|
-
- `init()` never
|
|
153
|
+
- `init()` and `render()` never throw; they return a `Result` with `ok: false` and `error` details.
|
|
97
154
|
- When `debug` is `false`, debug messages are suppressed.
|
|
98
155
|
- Errors still trigger `onError` and `logger.error` (if provided), even when `debug` is `false`.
|
|
99
156
|
- Call `iconLoader.abort()` to cancel a fetch (`fetch_aborted` error code).
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/errors.ts
|
|
3
|
+
const createIconlyError = (code, message, cause) => ({
|
|
4
|
+
code,
|
|
5
|
+
message,
|
|
6
|
+
cause
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
//#endregion
|
|
10
|
+
//#region src/result.ts
|
|
11
|
+
const ok = (value) => ({
|
|
12
|
+
ok: true,
|
|
13
|
+
value
|
|
14
|
+
});
|
|
15
|
+
const err = (error) => ({
|
|
16
|
+
ok: false,
|
|
17
|
+
error
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/dom.ts
|
|
22
|
+
const resolveContainer = (container) => {
|
|
23
|
+
if (typeof document === "undefined") return err(createIconlyError("container_invalid", "Document is not available in this environment."));
|
|
24
|
+
if (typeof container === "string") {
|
|
25
|
+
const found = document.querySelector(container);
|
|
26
|
+
if (!found || !(found instanceof HTMLElement)) return err(createIconlyError("container_invalid", `Invalid container selector: "${container}".`));
|
|
27
|
+
return ok(found);
|
|
28
|
+
}
|
|
29
|
+
if (container instanceof HTMLElement) return ok(container);
|
|
30
|
+
const fallback = document.body ?? document.documentElement;
|
|
31
|
+
if (!fallback) return err(createIconlyError("container_invalid", "No valid container element found."));
|
|
32
|
+
return ok(fallback);
|
|
33
|
+
};
|
|
34
|
+
const insertSvg = (container, data) => {
|
|
35
|
+
const found = container.querySelector("[data-iconly=\"iconset\"]");
|
|
36
|
+
let iconSetDiv = found instanceof HTMLElement ? found : null;
|
|
37
|
+
if (!iconSetDiv) {
|
|
38
|
+
iconSetDiv = document.createElement("div");
|
|
39
|
+
iconSetDiv.setAttribute("data-iconly", "iconset");
|
|
40
|
+
iconSetDiv.setAttribute("aria-hidden", "true");
|
|
41
|
+
iconSetDiv.style.cssText = "width: 0; height: 0; position: absolute; left: -9999px;";
|
|
42
|
+
container.appendChild(iconSetDiv);
|
|
43
|
+
}
|
|
44
|
+
const svgDoc = new DOMParser().parseFromString(data, "image/svg+xml");
|
|
45
|
+
const parserError = svgDoc.querySelector("parsererror");
|
|
46
|
+
if (parserError) return err(createIconlyError("parse_error", `SVG parsing error: ${parserError.textContent ?? "Unknown error"}`));
|
|
47
|
+
iconSetDiv.innerHTML = "";
|
|
48
|
+
const svgEl = svgDoc.documentElement;
|
|
49
|
+
if (!svgEl) return err(createIconlyError("parse_error", "No valid SVG content found."));
|
|
50
|
+
const imported = document.importNode(svgEl, true);
|
|
51
|
+
iconSetDiv.appendChild(imported);
|
|
52
|
+
return ok(void 0);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
//#endregion
|
|
56
|
+
Object.defineProperty(exports, 'createIconlyError', {
|
|
57
|
+
enumerable: true,
|
|
58
|
+
get: function () {
|
|
59
|
+
return createIconlyError;
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
Object.defineProperty(exports, 'err', {
|
|
63
|
+
enumerable: true,
|
|
64
|
+
get: function () {
|
|
65
|
+
return err;
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
Object.defineProperty(exports, 'insertSvg', {
|
|
69
|
+
enumerable: true,
|
|
70
|
+
get: function () {
|
|
71
|
+
return insertSvg;
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
Object.defineProperty(exports, 'ok', {
|
|
75
|
+
enumerable: true,
|
|
76
|
+
get: function () {
|
|
77
|
+
return ok;
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
Object.defineProperty(exports, 'resolveContainer', {
|
|
81
|
+
enumerable: true,
|
|
82
|
+
get: function () {
|
|
83
|
+
return resolveContainer;
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
//# sourceMappingURL=dom-Bqsr32nW.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom-Bqsr32nW.cjs","names":[],"sources":["../src/errors.ts","../src/result.ts","../src/dom.ts"],"sourcesContent":["import type { IconlyError, IconlyErrorCode } from './types';\n\nexport const createIconlyError = (\n code: IconlyErrorCode,\n message: string,\n cause?: unknown,\n): IconlyError => ({\n code,\n message,\n cause,\n});\n","import type { IconlyError, Result } from './types';\n\nexport const ok = <T>(value: T): Result<T> => ({ ok: true, value });\n\nexport const err = <T = never>(error: IconlyError): Result<T> => ({ ok: false, error });\n","import { createIconlyError } from './errors';\nimport { err, ok } from './result';\nimport type { Result } from './types';\n\nexport const resolveContainer = (container?: string | HTMLElement): Result<HTMLElement> => {\n if (typeof document === 'undefined') {\n return err(\n createIconlyError('container_invalid', 'Document is not available in this environment.'),\n );\n }\n\n if (typeof container === 'string') {\n const found = document.querySelector(container);\n\n if (!found || !(found instanceof HTMLElement)) {\n return err(\n createIconlyError('container_invalid', `Invalid container selector: \"${container}\".`),\n );\n }\n\n return ok(found);\n }\n\n if (container instanceof HTMLElement) {\n return ok(container);\n }\n\n const fallback = document.body ?? document.documentElement;\n\n if (!fallback) {\n return err(createIconlyError('container_invalid', 'No valid container element found.'));\n }\n\n return ok(fallback);\n};\n\nexport const insertSvg = (container: HTMLElement, data: string): Result<void> => {\n const found = container.querySelector('[data-iconly=\"iconset\"]');\n let iconSetDiv: HTMLElement | null = found instanceof HTMLElement ? found : null;\n\n if (!iconSetDiv) {\n iconSetDiv = document.createElement('div');\n iconSetDiv.setAttribute('data-iconly', 'iconset');\n iconSetDiv.setAttribute('aria-hidden', 'true');\n iconSetDiv.style.cssText = 'width: 0; height: 0; position: absolute; left: -9999px;';\n container.appendChild(iconSetDiv);\n }\n\n const parser = new DOMParser();\n const svgDoc = parser.parseFromString(data, 'image/svg+xml');\n const parserError = svgDoc.querySelector('parsererror');\n\n if (parserError) {\n return err(\n createIconlyError(\n 'parse_error',\n `SVG parsing error: ${parserError.textContent ?? 'Unknown error'}`,\n ),\n );\n }\n\n iconSetDiv.innerHTML = '';\n\n const svgEl = svgDoc.documentElement;\n\n if (!svgEl) {\n return err(createIconlyError('parse_error', 'No valid SVG content found.'));\n }\n\n const imported = document.importNode(svgEl, true);\n\n iconSetDiv.appendChild(imported);\n\n return ok(undefined);\n};\n"],"mappings":";;AAEA,MAAa,qBACX,MACA,SACA,WACiB;CACjB;CACA;CACA;AACF;;;;ACRA,MAAa,MAAS,WAAyB;CAAE,IAAI;CAAM;AAAM;AAEjE,MAAa,OAAkB,WAAmC;CAAE,IAAI;CAAO;AAAM;;;;ACArF,MAAa,oBAAoB,cAA0D;CACzF,IAAI,OAAO,aAAa,aACtB,OAAO,IACL,kBAAkB,qBAAqB,gDAAgD,CACzF;CAGF,IAAI,OAAO,cAAc,UAAU;EACjC,MAAM,QAAQ,SAAS,cAAc,SAAS;EAE9C,IAAI,CAAC,SAAS,EAAE,iBAAiB,cAC/B,OAAO,IACL,kBAAkB,qBAAqB,gCAAgC,UAAU,GAAG,CACtF;EAGF,OAAO,GAAG,KAAK;CACjB;CAEA,IAAI,qBAAqB,aACvB,OAAO,GAAG,SAAS;CAGrB,MAAM,WAAW,SAAS,QAAQ,SAAS;CAE3C,IAAI,CAAC,UACH,OAAO,IAAI,kBAAkB,qBAAqB,mCAAmC,CAAC;CAGxF,OAAO,GAAG,QAAQ;AACpB;AAEA,MAAa,aAAa,WAAwB,SAA+B;CAC/E,MAAM,QAAQ,UAAU,cAAc,2BAAyB;CAC/D,IAAI,aAAiC,iBAAiB,cAAc,QAAQ;CAE5E,IAAI,CAAC,YAAY;EACf,aAAa,SAAS,cAAc,KAAK;EACzC,WAAW,aAAa,eAAe,SAAS;EAChD,WAAW,aAAa,eAAe,MAAM;EAC7C,WAAW,MAAM,UAAU;EAC3B,UAAU,YAAY,UAAU;CAClC;CAGA,MAAM,SAAS,IADI,UACC,CAAC,CAAC,gBAAgB,MAAM,eAAe;CAC3D,MAAM,cAAc,OAAO,cAAc,aAAa;CAEtD,IAAI,aACF,OAAO,IACL,kBACE,eACA,sBAAsB,YAAY,eAAe,iBACnD,CACF;CAGF,WAAW,YAAY;CAEvB,MAAM,QAAQ,OAAO;CAErB,IAAI,CAAC,OACH,OAAO,IAAI,kBAAkB,eAAe,6BAA6B,CAAC;CAG5E,MAAM,WAAW,SAAS,WAAW,OAAO,IAAI;CAEhD,WAAW,YAAY,QAAQ;CAE/B,OAAO,GAAG,MAAS;AACrB"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
//#region src/errors.ts
|
|
2
|
+
const createIconlyError = (code, message, cause) => ({
|
|
3
|
+
code,
|
|
4
|
+
message,
|
|
5
|
+
cause
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
//#endregion
|
|
9
|
+
//#region src/result.ts
|
|
10
|
+
const ok = (value) => ({
|
|
11
|
+
ok: true,
|
|
12
|
+
value
|
|
13
|
+
});
|
|
14
|
+
const err = (error) => ({
|
|
15
|
+
ok: false,
|
|
16
|
+
error
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
//#endregion
|
|
20
|
+
//#region src/dom.ts
|
|
21
|
+
const resolveContainer = (container) => {
|
|
22
|
+
if (typeof document === "undefined") return err(createIconlyError("container_invalid", "Document is not available in this environment."));
|
|
23
|
+
if (typeof container === "string") {
|
|
24
|
+
const found = document.querySelector(container);
|
|
25
|
+
if (!found || !(found instanceof HTMLElement)) return err(createIconlyError("container_invalid", `Invalid container selector: "${container}".`));
|
|
26
|
+
return ok(found);
|
|
27
|
+
}
|
|
28
|
+
if (container instanceof HTMLElement) return ok(container);
|
|
29
|
+
const fallback = document.body ?? document.documentElement;
|
|
30
|
+
if (!fallback) return err(createIconlyError("container_invalid", "No valid container element found."));
|
|
31
|
+
return ok(fallback);
|
|
32
|
+
};
|
|
33
|
+
const insertSvg = (container, data) => {
|
|
34
|
+
const found = container.querySelector("[data-iconly=\"iconset\"]");
|
|
35
|
+
let iconSetDiv = found instanceof HTMLElement ? found : null;
|
|
36
|
+
if (!iconSetDiv) {
|
|
37
|
+
iconSetDiv = document.createElement("div");
|
|
38
|
+
iconSetDiv.setAttribute("data-iconly", "iconset");
|
|
39
|
+
iconSetDiv.setAttribute("aria-hidden", "true");
|
|
40
|
+
iconSetDiv.style.cssText = "width: 0; height: 0; position: absolute; left: -9999px;";
|
|
41
|
+
container.appendChild(iconSetDiv);
|
|
42
|
+
}
|
|
43
|
+
const svgDoc = new DOMParser().parseFromString(data, "image/svg+xml");
|
|
44
|
+
const parserError = svgDoc.querySelector("parsererror");
|
|
45
|
+
if (parserError) return err(createIconlyError("parse_error", `SVG parsing error: ${parserError.textContent ?? "Unknown error"}`));
|
|
46
|
+
iconSetDiv.innerHTML = "";
|
|
47
|
+
const svgEl = svgDoc.documentElement;
|
|
48
|
+
if (!svgEl) return err(createIconlyError("parse_error", "No valid SVG content found."));
|
|
49
|
+
const imported = document.importNode(svgEl, true);
|
|
50
|
+
iconSetDiv.appendChild(imported);
|
|
51
|
+
return ok(void 0);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
//#endregion
|
|
55
|
+
export { createIconlyError as a, ok as i, resolveContainer as n, err as r, insertSvg as t };
|
|
56
|
+
//# sourceMappingURL=dom-senQJ1VA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dom-senQJ1VA.js","names":[],"sources":["../src/errors.ts","../src/result.ts","../src/dom.ts"],"sourcesContent":["import type { IconlyError, IconlyErrorCode } from './types';\n\nexport const createIconlyError = (\n code: IconlyErrorCode,\n message: string,\n cause?: unknown,\n): IconlyError => ({\n code,\n message,\n cause,\n});\n","import type { IconlyError, Result } from './types';\n\nexport const ok = <T>(value: T): Result<T> => ({ ok: true, value });\n\nexport const err = <T = never>(error: IconlyError): Result<T> => ({ ok: false, error });\n","import { createIconlyError } from './errors';\nimport { err, ok } from './result';\nimport type { Result } from './types';\n\nexport const resolveContainer = (container?: string | HTMLElement): Result<HTMLElement> => {\n if (typeof document === 'undefined') {\n return err(\n createIconlyError('container_invalid', 'Document is not available in this environment.'),\n );\n }\n\n if (typeof container === 'string') {\n const found = document.querySelector(container);\n\n if (!found || !(found instanceof HTMLElement)) {\n return err(\n createIconlyError('container_invalid', `Invalid container selector: \"${container}\".`),\n );\n }\n\n return ok(found);\n }\n\n if (container instanceof HTMLElement) {\n return ok(container);\n }\n\n const fallback = document.body ?? document.documentElement;\n\n if (!fallback) {\n return err(createIconlyError('container_invalid', 'No valid container element found.'));\n }\n\n return ok(fallback);\n};\n\nexport const insertSvg = (container: HTMLElement, data: string): Result<void> => {\n const found = container.querySelector('[data-iconly=\"iconset\"]');\n let iconSetDiv: HTMLElement | null = found instanceof HTMLElement ? found : null;\n\n if (!iconSetDiv) {\n iconSetDiv = document.createElement('div');\n iconSetDiv.setAttribute('data-iconly', 'iconset');\n iconSetDiv.setAttribute('aria-hidden', 'true');\n iconSetDiv.style.cssText = 'width: 0; height: 0; position: absolute; left: -9999px;';\n container.appendChild(iconSetDiv);\n }\n\n const parser = new DOMParser();\n const svgDoc = parser.parseFromString(data, 'image/svg+xml');\n const parserError = svgDoc.querySelector('parsererror');\n\n if (parserError) {\n return err(\n createIconlyError(\n 'parse_error',\n `SVG parsing error: ${parserError.textContent ?? 'Unknown error'}`,\n ),\n );\n }\n\n iconSetDiv.innerHTML = '';\n\n const svgEl = svgDoc.documentElement;\n\n if (!svgEl) {\n return err(createIconlyError('parse_error', 'No valid SVG content found.'));\n }\n\n const imported = document.importNode(svgEl, true);\n\n iconSetDiv.appendChild(imported);\n\n return ok(undefined);\n};\n"],"mappings":";AAEA,MAAa,qBACX,MACA,SACA,WACiB;CACjB;CACA;CACA;AACF;;;;ACRA,MAAa,MAAS,WAAyB;CAAE,IAAI;CAAM;AAAM;AAEjE,MAAa,OAAkB,WAAmC;CAAE,IAAI;CAAO;AAAM;;;;ACArF,MAAa,oBAAoB,cAA0D;CACzF,IAAI,OAAO,aAAa,aACtB,OAAO,IACL,kBAAkB,qBAAqB,gDAAgD,CACzF;CAGF,IAAI,OAAO,cAAc,UAAU;EACjC,MAAM,QAAQ,SAAS,cAAc,SAAS;EAE9C,IAAI,CAAC,SAAS,EAAE,iBAAiB,cAC/B,OAAO,IACL,kBAAkB,qBAAqB,gCAAgC,UAAU,GAAG,CACtF;EAGF,OAAO,GAAG,KAAK;CACjB;CAEA,IAAI,qBAAqB,aACvB,OAAO,GAAG,SAAS;CAGrB,MAAM,WAAW,SAAS,QAAQ,SAAS;CAE3C,IAAI,CAAC,UACH,OAAO,IAAI,kBAAkB,qBAAqB,mCAAmC,CAAC;CAGxF,OAAO,GAAG,QAAQ;AACpB;AAEA,MAAa,aAAa,WAAwB,SAA+B;CAC/E,MAAM,QAAQ,UAAU,cAAc,2BAAyB;CAC/D,IAAI,aAAiC,iBAAiB,cAAc,QAAQ;CAE5E,IAAI,CAAC,YAAY;EACf,aAAa,SAAS,cAAc,KAAK;EACzC,WAAW,aAAa,eAAe,SAAS;EAChD,WAAW,aAAa,eAAe,MAAM;EAC7C,WAAW,MAAM,UAAU;EAC3B,UAAU,YAAY,UAAU;CAClC;CAGA,MAAM,SAAS,IADI,UACC,CAAC,CAAC,gBAAgB,MAAM,eAAe;CAC3D,MAAM,cAAc,OAAO,cAAc,aAAa;CAEtD,IAAI,aACF,OAAO,IACL,kBACE,eACA,sBAAsB,YAAY,eAAe,iBACnD,CACF;CAGF,WAAW,YAAY;CAEvB,MAAM,QAAQ,OAAO;CAErB,IAAI,CAAC,OACH,OAAO,IAAI,kBAAkB,eAAe,6BAA6B,CAAC;CAG5E,MAAM,WAAW,SAAS,WAAW,OAAO,IAAI;CAEhD,WAAW,YAAY,QAAQ;CAE/B,OAAO,GAAG,MAAS;AACrB"}
|
package/dist/index.cjs
CHANGED
|
@@ -1,56 +1,15 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
const require_dom = require('./dom-Bqsr32nW.cjs');
|
|
2
3
|
|
|
3
|
-
//#region src/errors.ts
|
|
4
|
-
const createIconlyError = (code, message, cause) => ({
|
|
5
|
-
code,
|
|
6
|
-
message,
|
|
7
|
-
cause
|
|
8
|
-
});
|
|
9
|
-
|
|
10
|
-
//#endregion
|
|
11
|
-
//#region src/result.ts
|
|
12
|
-
const ok = (value) => ({
|
|
13
|
-
ok: true,
|
|
14
|
-
value
|
|
15
|
-
});
|
|
16
|
-
const err = (error) => ({
|
|
17
|
-
ok: false,
|
|
18
|
-
error
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
//#endregion
|
|
22
|
-
//#region src/dom.ts
|
|
23
|
-
const insertSvg = (container, data) => {
|
|
24
|
-
const found = container.querySelector("[data-iconly=\"iconset\"]");
|
|
25
|
-
let iconSetDiv = found instanceof HTMLElement ? found : null;
|
|
26
|
-
if (!iconSetDiv) {
|
|
27
|
-
iconSetDiv = document.createElement("div");
|
|
28
|
-
iconSetDiv.setAttribute("data-iconly", "iconset");
|
|
29
|
-
iconSetDiv.setAttribute("aria-hidden", "true");
|
|
30
|
-
iconSetDiv.style.cssText = "width: 0; height: 0; position: absolute; left: -9999px;";
|
|
31
|
-
container.appendChild(iconSetDiv);
|
|
32
|
-
}
|
|
33
|
-
const svgDoc = new DOMParser().parseFromString(data, "image/svg+xml");
|
|
34
|
-
const parserError = svgDoc.querySelector("parsererror");
|
|
35
|
-
if (parserError) return err(createIconlyError("parse_error", `SVG parsing error: ${parserError.textContent ?? "Unknown error"}`));
|
|
36
|
-
iconSetDiv.innerHTML = "";
|
|
37
|
-
const svgEl = svgDoc.documentElement;
|
|
38
|
-
if (!svgEl) return err(createIconlyError("parse_error", "No valid SVG content found."));
|
|
39
|
-
const imported = document.importNode(svgEl, true);
|
|
40
|
-
iconSetDiv.appendChild(imported);
|
|
41
|
-
return ok(void 0);
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
//#endregion
|
|
45
4
|
//#region src/fetcher.ts
|
|
46
5
|
const fetchSvg = async (file, signal) => {
|
|
47
6
|
try {
|
|
48
7
|
const response = await fetch(file, { signal });
|
|
49
|
-
if (!response.ok) return err(createIconlyError("fetch_failed", `Failed to fetch icons from "${file}".`));
|
|
50
|
-
return ok(await response.text());
|
|
8
|
+
if (!response.ok) return require_dom.err(require_dom.createIconlyError("fetch_failed", `Failed to fetch icons from "${file}".`));
|
|
9
|
+
return require_dom.ok(await response.text());
|
|
51
10
|
} catch (error) {
|
|
52
|
-
if (error instanceof DOMException && error.name === "AbortError") return err(createIconlyError("fetch_aborted", "Fetch request was aborted.", error));
|
|
53
|
-
return err(createIconlyError("fetch_failed", "Failed to fetch icons.", error));
|
|
11
|
+
if (error instanceof DOMException && error.name === "AbortError") return require_dom.err(require_dom.createIconlyError("fetch_aborted", "Fetch request was aborted.", error));
|
|
12
|
+
return require_dom.err(require_dom.createIconlyError("fetch_failed", "Failed to fetch icons.", error));
|
|
54
13
|
}
|
|
55
14
|
};
|
|
56
15
|
|
|
@@ -62,11 +21,11 @@ const createIndexedDbStorage = (options = {}) => {
|
|
|
62
21
|
let dbPromise = null;
|
|
63
22
|
const openDb = async () => {
|
|
64
23
|
if (dbPromise) return dbPromise;
|
|
65
|
-
if (typeof indexedDB === "undefined") throw createIconlyError("indexeddb_not_supported", "IndexedDB is not supported.");
|
|
24
|
+
if (typeof indexedDB === "undefined") throw require_dom.createIconlyError("indexeddb_not_supported", "IndexedDB is not supported.");
|
|
66
25
|
dbPromise = new Promise((resolve, reject) => {
|
|
67
26
|
const request = indexedDB.open(dbName, 1);
|
|
68
27
|
request.onerror = () => {
|
|
69
|
-
reject(createIconlyError("indexeddb_open_failed", "Failed to open IndexedDB connection.", request.error));
|
|
28
|
+
reject(require_dom.createIconlyError("indexeddb_open_failed", "Failed to open IndexedDB connection.", request.error));
|
|
70
29
|
};
|
|
71
30
|
request.onupgradeneeded = (event) => {
|
|
72
31
|
const db = event.target.result;
|
|
@@ -79,18 +38,18 @@ const createIndexedDbStorage = (options = {}) => {
|
|
|
79
38
|
const getStore = (db, mode) => db.transaction(storeName, mode).objectStore(storeName);
|
|
80
39
|
const toIconlyError = (error, fallbackCode, message) => {
|
|
81
40
|
if (error && typeof error === "object" && "code" in error && "message" in error) return error;
|
|
82
|
-
return createIconlyError(fallbackCode, message, error);
|
|
41
|
+
return require_dom.createIconlyError(fallbackCode, message, error);
|
|
83
42
|
};
|
|
84
43
|
const get = async (version) => {
|
|
85
44
|
try {
|
|
86
45
|
const store = getStore(await openDb(), "readonly");
|
|
87
46
|
return await new Promise((resolve) => {
|
|
88
47
|
const request = store.get(version);
|
|
89
|
-
request.onsuccess = () => resolve(ok(request.result));
|
|
90
|
-
request.onerror = () => resolve(err(createIconlyError("indexeddb_request_failed", "Failed to read from IndexedDB.", request.error)));
|
|
48
|
+
request.onsuccess = () => resolve(require_dom.ok(request.result));
|
|
49
|
+
request.onerror = () => resolve(require_dom.err(require_dom.createIconlyError("indexeddb_request_failed", "Failed to read from IndexedDB.", request.error)));
|
|
91
50
|
});
|
|
92
51
|
} catch (error) {
|
|
93
|
-
return err(toIconlyError(error, "indexeddb_open_failed", "Failed to open IndexedDB."));
|
|
52
|
+
return require_dom.err(toIconlyError(error, "indexeddb_open_failed", "Failed to open IndexedDB."));
|
|
94
53
|
}
|
|
95
54
|
};
|
|
96
55
|
const set = async (record) => {
|
|
@@ -98,11 +57,11 @@ const createIndexedDbStorage = (options = {}) => {
|
|
|
98
57
|
const store = getStore(await openDb(), "readwrite");
|
|
99
58
|
return await new Promise((resolve) => {
|
|
100
59
|
const request = store.put(record);
|
|
101
|
-
request.onsuccess = () => resolve(ok(void 0));
|
|
102
|
-
request.onerror = () => resolve(err(createIconlyError("indexeddb_request_failed", "Failed to write to IndexedDB.", request.error)));
|
|
60
|
+
request.onsuccess = () => resolve(require_dom.ok(void 0));
|
|
61
|
+
request.onerror = () => resolve(require_dom.err(require_dom.createIconlyError("indexeddb_request_failed", "Failed to write to IndexedDB.", request.error)));
|
|
103
62
|
});
|
|
104
63
|
} catch (error) {
|
|
105
|
-
return err(createIconlyError("indexeddb_open_failed", "Failed to open IndexedDB.", error));
|
|
64
|
+
return require_dom.err(require_dom.createIconlyError("indexeddb_open_failed", "Failed to open IndexedDB.", error));
|
|
106
65
|
}
|
|
107
66
|
};
|
|
108
67
|
return {
|
|
@@ -116,15 +75,15 @@ const createIndexedDbStorage = (options = {}) => {
|
|
|
116
75
|
const createMemoryStorage = () => {
|
|
117
76
|
const store = /* @__PURE__ */ new Map();
|
|
118
77
|
const get = async (version) => {
|
|
119
|
-
if (!store.has(version)) return ok(void 0);
|
|
120
|
-
return ok({
|
|
78
|
+
if (!store.has(version)) return require_dom.ok(void 0);
|
|
79
|
+
return require_dom.ok({
|
|
121
80
|
version,
|
|
122
81
|
data: store.get(version) ?? ""
|
|
123
82
|
});
|
|
124
83
|
};
|
|
125
84
|
const set = async (record) => {
|
|
126
85
|
store.set(record.version, record.data);
|
|
127
|
-
return ok(void 0);
|
|
86
|
+
return require_dom.ok(void 0);
|
|
128
87
|
};
|
|
129
88
|
return {
|
|
130
89
|
get,
|
|
@@ -137,18 +96,18 @@ const createMemoryStorage = () => {
|
|
|
137
96
|
const createSessionStorage = (options = {}) => {
|
|
138
97
|
const keyPrefix = options.keyPrefix ?? "iconly";
|
|
139
98
|
const resolveStorage = () => {
|
|
140
|
-
if (typeof window === "undefined" || !window.sessionStorage) return err(createIconlyError("storage_unavailable", "SessionStorage is not available."));
|
|
141
|
-
return ok(window.sessionStorage);
|
|
99
|
+
if (typeof window === "undefined" || !window.sessionStorage) return require_dom.err(require_dom.createIconlyError("storage_unavailable", "SessionStorage is not available."));
|
|
100
|
+
return require_dom.ok(window.sessionStorage);
|
|
142
101
|
};
|
|
143
102
|
const get = async (version) => {
|
|
144
103
|
const storageResult = resolveStorage();
|
|
145
104
|
if (!storageResult.ok) return storageResult;
|
|
146
105
|
try {
|
|
147
106
|
const raw = storageResult.value.getItem(`${keyPrefix}:${version}`);
|
|
148
|
-
if (!raw) return ok(void 0);
|
|
149
|
-
return ok(JSON.parse(raw));
|
|
107
|
+
if (!raw) return require_dom.ok(void 0);
|
|
108
|
+
return require_dom.ok(JSON.parse(raw));
|
|
150
109
|
} catch (error) {
|
|
151
|
-
return err(createIconlyError("storage_read_failed", "Failed to read from SessionStorage.", error));
|
|
110
|
+
return require_dom.err(require_dom.createIconlyError("storage_read_failed", "Failed to read from SessionStorage.", error));
|
|
152
111
|
}
|
|
153
112
|
};
|
|
154
113
|
const set = async (record) => {
|
|
@@ -156,9 +115,9 @@ const createSessionStorage = (options = {}) => {
|
|
|
156
115
|
if (!storageResult.ok) return storageResult;
|
|
157
116
|
try {
|
|
158
117
|
storageResult.value.setItem(`${keyPrefix}:${record.version}`, JSON.stringify(record));
|
|
159
|
-
return ok(void 0);
|
|
118
|
+
return require_dom.ok(void 0);
|
|
160
119
|
} catch (error) {
|
|
161
|
-
return err(createIconlyError("storage_write_failed", "Failed to write to SessionStorage.", error));
|
|
120
|
+
return require_dom.err(require_dom.createIconlyError("storage_write_failed", "Failed to write to SessionStorage.", error));
|
|
162
121
|
}
|
|
163
122
|
};
|
|
164
123
|
return {
|
|
@@ -200,18 +159,6 @@ const createIconly = (config = {}) => {
|
|
|
200
159
|
const abort = () => {
|
|
201
160
|
controller?.abort();
|
|
202
161
|
};
|
|
203
|
-
const resolveContainer = () => {
|
|
204
|
-
if (typeof document === "undefined") return err(createIconlyError("container_invalid", "Document is not available in this environment."));
|
|
205
|
-
if (typeof resolved.container === "string") {
|
|
206
|
-
const found = document.querySelector(resolved.container);
|
|
207
|
-
if (!found || !(found instanceof HTMLElement)) return err(createIconlyError("container_invalid", `Invalid container selector: "${resolved.container}".`));
|
|
208
|
-
return ok(found);
|
|
209
|
-
}
|
|
210
|
-
if (resolved.container instanceof HTMLElement) return ok(resolved.container);
|
|
211
|
-
const fallback = document.body ?? document.documentElement;
|
|
212
|
-
if (!fallback) return err(createIconlyError("container_invalid", "No valid container element found."));
|
|
213
|
-
return ok(fallback);
|
|
214
|
-
};
|
|
215
162
|
const logDebug = (...messages) => {
|
|
216
163
|
if (!resolved.debug) return;
|
|
217
164
|
resolved.onDebug?.(...messages);
|
|
@@ -223,10 +170,10 @@ const createIconly = (config = {}) => {
|
|
|
223
170
|
};
|
|
224
171
|
const fail = (error) => {
|
|
225
172
|
logError(error);
|
|
226
|
-
return err(error);
|
|
173
|
+
return require_dom.err(error);
|
|
227
174
|
};
|
|
228
175
|
const init = async () => {
|
|
229
|
-
const containerResult = resolveContainer();
|
|
176
|
+
const containerResult = require_dom.resolveContainer(resolved.container);
|
|
230
177
|
if (!containerResult.ok) return fail(containerResult.error);
|
|
231
178
|
const cacheResult = await storage.get(resolved.version);
|
|
232
179
|
if (!cacheResult.ok) return fail(cacheResult.error);
|
|
@@ -242,10 +189,10 @@ const createIconly = (config = {}) => {
|
|
|
242
189
|
});
|
|
243
190
|
if (!storeResult.ok) return fail(storeResult.error);
|
|
244
191
|
} else logDebug("Using cached icon set", resolved.version);
|
|
245
|
-
const insertResult = insertSvg(containerResult.value, data);
|
|
192
|
+
const insertResult = require_dom.insertSvg(containerResult.value, data);
|
|
246
193
|
if (!insertResult.ok) return fail(insertResult.error);
|
|
247
194
|
logDebug("Iconly has successfully initialized.");
|
|
248
|
-
return ok(void 0);
|
|
195
|
+
return require_dom.ok(void 0);
|
|
249
196
|
};
|
|
250
197
|
return {
|
|
251
198
|
init,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":[],"sources":["../src/errors.ts","../src/result.ts","../src/dom.ts","../src/fetcher.ts","../src/storage/indexeddb.ts","../src/storage/memory.ts","../src/storage/session.ts","../src/storage/index.ts","../src/core.ts"],"sourcesContent":["import type { IconlyError, IconlyErrorCode } from './types';\n\nexport const createIconlyError = (\n code: IconlyErrorCode,\n message: string,\n cause?: unknown,\n): IconlyError => ({\n code,\n message,\n cause,\n});\n","import type { IconlyError, Result } from './types';\n\nexport const ok = <T>(value: T): Result<T> => ({ ok: true, value });\n\nexport const err = <T = never>(error: IconlyError): Result<T> => ({ ok: false, error });\n","import { createIconlyError } from './errors';\nimport { err, ok } from './result';\nimport type { Result } from './types';\n\nexport const insertSvg = (container: HTMLElement, data: string): Result<void> => {\n const found = container.querySelector('[data-iconly=\"iconset\"]');\n let iconSetDiv: HTMLElement | null = found instanceof HTMLElement ? found : null;\n\n if (!iconSetDiv) {\n iconSetDiv = document.createElement('div');\n iconSetDiv.setAttribute('data-iconly', 'iconset');\n iconSetDiv.setAttribute('aria-hidden', 'true');\n iconSetDiv.style.cssText = 'width: 0; height: 0; position: absolute; left: -9999px;';\n container.appendChild(iconSetDiv);\n }\n\n const parser = new DOMParser();\n const svgDoc = parser.parseFromString(data, 'image/svg+xml');\n const parserError = svgDoc.querySelector('parsererror');\n\n if (parserError) {\n return err(\n createIconlyError(\n 'parse_error',\n `SVG parsing error: ${parserError.textContent ?? 'Unknown error'}`,\n ),\n );\n }\n\n iconSetDiv.innerHTML = '';\n\n const svgEl = svgDoc.documentElement;\n\n if (!svgEl) {\n return err(createIconlyError('parse_error', 'No valid SVG content found.'));\n }\n\n const imported = document.importNode(svgEl, true);\n\n iconSetDiv.appendChild(imported);\n\n return ok(undefined);\n};\n","import { createIconlyError } from './errors';\nimport { err, ok } from './result';\nimport type { Result } from './types';\n\nexport const fetchSvg = async (file: string, signal?: AbortSignal): Promise<Result<string>> => {\n try {\n const response = await fetch(file, { signal });\n\n if (!response.ok) {\n return err(createIconlyError('fetch_failed', `Failed to fetch icons from \"${file}\".`));\n }\n\n const data = await response.text();\n\n return ok(data);\n } catch (error: unknown) {\n if (error instanceof DOMException && error.name === 'AbortError') {\n return err(createIconlyError('fetch_aborted', 'Fetch request was aborted.', error));\n }\n\n return err(createIconlyError('fetch_failed', 'Failed to fetch icons.', error));\n }\n};\n","import { createIconlyError } from '../errors';\nimport { err, ok } from '../result';\nimport type { IconlyError, IconRecord, IconStorage, Result } from '../types';\n\ninterface IndexedDbOptions {\n dbName?: string;\n storeName?: string;\n}\n\nexport const createIndexedDbStorage = (options: IndexedDbOptions = {}): IconStorage => {\n const dbName = options.dbName ?? 'iconlyDB';\n const storeName = options.storeName ?? 'icons';\n\n let dbPromise: Promise<IDBDatabase> | null = null;\n\n const openDb = async (): Promise<IDBDatabase> => {\n if (dbPromise) {\n return dbPromise;\n }\n\n if (typeof indexedDB === 'undefined') {\n throw createIconlyError('indexeddb_not_supported', 'IndexedDB is not supported.');\n }\n\n dbPromise = new Promise<IDBDatabase>((resolve, reject) => {\n const request = indexedDB.open(dbName, 1);\n\n request.onerror = (): void => {\n reject(\n createIconlyError(\n 'indexeddb_open_failed',\n 'Failed to open IndexedDB connection.',\n request.error,\n ),\n );\n };\n\n request.onupgradeneeded = (event): void => {\n const db = (event.target as IDBOpenDBRequest).result;\n\n if (!db.objectStoreNames.contains(storeName)) {\n db.createObjectStore(storeName, { keyPath: 'version' });\n }\n };\n\n request.onsuccess = (): void => resolve(request.result);\n });\n\n return dbPromise;\n };\n\n const getStore = (db: IDBDatabase, mode: IDBTransactionMode): IDBObjectStore =>\n db.transaction(storeName, mode).objectStore(storeName);\n\n const toIconlyError = (\n error: unknown,\n fallbackCode: IconlyError['code'],\n message: string,\n ): IconlyError => {\n if (error && typeof error === 'object' && 'code' in error && 'message' in error) {\n return error as IconlyError;\n }\n\n return createIconlyError(fallbackCode, message, error);\n };\n\n const get = async (version: string): Promise<Result<IconRecord | undefined>> => {\n try {\n const db = await openDb();\n const store = getStore(db, 'readonly');\n\n return await new Promise<Result<IconRecord | undefined>>((resolve) => {\n const request = store.get(version);\n\n request.onsuccess = (): void => resolve(ok(request.result as IconRecord | undefined));\n request.onerror = (): void =>\n resolve(\n err(\n createIconlyError(\n 'indexeddb_request_failed',\n 'Failed to read from IndexedDB.',\n request.error,\n ),\n ),\n );\n });\n } catch (error: unknown) {\n return err(toIconlyError(error, 'indexeddb_open_failed', 'Failed to open IndexedDB.'));\n }\n };\n\n const set = async (record: IconRecord): Promise<Result<void>> => {\n try {\n const db = await openDb();\n const store = getStore(db, 'readwrite');\n\n return await new Promise<Result<void>>((resolve) => {\n const request = store.put(record);\n\n request.onsuccess = (): void => resolve(ok(undefined));\n request.onerror = (): void =>\n resolve(\n err(\n createIconlyError(\n 'indexeddb_request_failed',\n 'Failed to write to IndexedDB.',\n request.error,\n ),\n ),\n );\n });\n } catch (error: unknown) {\n return err(createIconlyError('indexeddb_open_failed', 'Failed to open IndexedDB.', error));\n }\n };\n\n return { get, set };\n};\n","import { ok } from '../result';\nimport type { IconRecord, IconStorage, Result } from '../types';\n\nexport const createMemoryStorage = (): IconStorage => {\n const store = new Map<string, string>();\n\n const get = async (version: string): Promise<Result<IconRecord | undefined>> => {\n if (!store.has(version)) {\n return ok(undefined);\n }\n\n return ok({ version, data: store.get(version) ?? '' });\n };\n\n const set = async (record: IconRecord): Promise<Result<void>> => {\n store.set(record.version, record.data);\n\n return ok(undefined);\n };\n\n return { get, set };\n};\n","import { createIconlyError } from '../errors';\nimport { err, ok } from '../result';\nimport type { IconRecord, IconStorage, Result } from '../types';\n\ninterface SessionStorageOptions {\n keyPrefix?: string;\n}\n\nexport const createSessionStorage = (options: SessionStorageOptions = {}): IconStorage => {\n const keyPrefix = options.keyPrefix ?? 'iconly';\n\n const resolveStorage = (): Result<Storage> => {\n if (typeof window === 'undefined' || !window.sessionStorage) {\n return err(createIconlyError('storage_unavailable', 'SessionStorage is not available.'));\n }\n\n return ok(window.sessionStorage);\n };\n\n const get = async (version: string): Promise<Result<IconRecord | undefined>> => {\n const storageResult = resolveStorage();\n\n if (!storageResult.ok) {\n return storageResult;\n }\n\n try {\n const raw = storageResult.value.getItem(`${keyPrefix}:${version}`);\n\n if (!raw) {\n return ok(undefined);\n }\n\n const parsed = JSON.parse(raw) as IconRecord;\n\n return ok(parsed);\n } catch (error: unknown) {\n return err(\n createIconlyError('storage_read_failed', 'Failed to read from SessionStorage.', error),\n );\n }\n };\n\n const set = async (record: IconRecord): Promise<Result<void>> => {\n const storageResult = resolveStorage();\n\n if (!storageResult.ok) {\n return storageResult;\n }\n\n try {\n storageResult.value.setItem(`${keyPrefix}:${record.version}`, JSON.stringify(record));\n\n return ok(undefined);\n } catch (error: unknown) {\n return err(\n createIconlyError('storage_write_failed', 'Failed to write to SessionStorage.', error),\n );\n }\n };\n\n return { get, set };\n};\n","import type { IconStorage, StorageStrategy } from '../types';\nimport { createIndexedDbStorage } from './indexeddb';\nimport { createMemoryStorage } from './memory';\nimport { createSessionStorage } from './session';\n\nexport interface StorageFactoryOptions {\n dbName?: string;\n storeName?: string;\n sessionKeyPrefix?: string;\n}\n\nexport const resolveStorage = (\n strategy: StorageStrategy | undefined,\n options: StorageFactoryOptions,\n): IconStorage => {\n if (!strategy || strategy === 'indexeddb') {\n return createIndexedDbStorage({\n dbName: options.dbName,\n storeName: options.storeName,\n });\n }\n\n if (strategy === 'memory') {\n return createMemoryStorage();\n }\n\n if (strategy === 'session') {\n return createSessionStorage({ keyPrefix: options.sessionKeyPrefix });\n }\n\n return strategy;\n};\n","import { insertSvg } from './dom';\nimport { createIconlyError } from './errors';\nimport { fetchSvg } from './fetcher';\nimport { err, ok } from './result';\nimport { resolveStorage } from './storage';\nimport type { IconlyConfig, IconlyError, IconlyInstance, IconStorage, Result } from './types';\n\ninterface ResolvedIconlyConfig {\n file: string;\n version: string;\n debug: boolean;\n container?: string | HTMLElement;\n logger?: IconlyConfig['logger'];\n onError?: IconlyConfig['onError'];\n onDebug?: IconlyConfig['onDebug'];\n}\n\nexport const createIconly = (config: IconlyConfig = {}): IconlyInstance => {\n const resolved: ResolvedIconlyConfig = {\n file: config.file ?? './icons.svg',\n version: config.version ?? '1.0',\n debug: config.debug ?? false,\n container: config.container,\n logger: config.logger,\n onError: config.onError,\n onDebug: config.onDebug,\n };\n\n const storage: IconStorage = resolveStorage(config.storage, {\n dbName: config.dbName,\n storeName: config.storeName,\n sessionKeyPrefix: config.sessionKeyPrefix,\n });\n\n let controller: AbortController | null = null;\n\n const abort = (): void => {\n controller?.abort();\n };\n\n const resolveContainer = (): Result<HTMLElement> => {\n if (typeof document === 'undefined') {\n return err(\n createIconlyError('container_invalid', 'Document is not available in this environment.'),\n );\n }\n\n if (typeof resolved.container === 'string') {\n const found = document.querySelector(resolved.container);\n\n if (!found || !(found instanceof HTMLElement)) {\n return err(\n createIconlyError(\n 'container_invalid',\n `Invalid container selector: \"${resolved.container}\".`,\n ),\n );\n }\n\n return ok(found);\n }\n\n if (resolved.container instanceof HTMLElement) {\n return ok(resolved.container);\n }\n\n const fallback = document.body ?? document.documentElement;\n\n if (!fallback) {\n return err(createIconlyError('container_invalid', 'No valid container element found.'));\n }\n\n return ok(fallback);\n };\n\n const logDebug = (...messages: unknown[]): void => {\n if (!resolved.debug) {\n return;\n }\n\n resolved.onDebug?.(...messages);\n resolved.logger?.debug?.('[Iconly debug]', ...messages);\n };\n\n const logError = (error: IconlyError): void => {\n resolved.onError?.(error);\n resolved.logger?.error?.('[Iconly error]', error);\n };\n\n const fail = (error: IconlyError): Result<void> => {\n logError(error);\n\n return err(error);\n };\n\n const init = async (): Promise<Result<void>> => {\n const containerResult = resolveContainer();\n\n if (!containerResult.ok) {\n return fail(containerResult.error);\n }\n\n const cacheResult = await storage.get(resolved.version);\n\n if (!cacheResult.ok) {\n return fail(cacheResult.error);\n }\n\n let data = cacheResult.value?.data;\n\n if (!data) {\n controller = new AbortController();\n\n const fetchResult = await fetchSvg(resolved.file, controller.signal);\n\n if (!fetchResult.ok) {\n return fail(fetchResult.error);\n }\n\n data = fetchResult.value;\n\n const storeResult = await storage.set({\n version: resolved.version,\n data,\n });\n\n if (!storeResult.ok) {\n return fail(storeResult.error);\n }\n } else {\n logDebug('Using cached icon set', resolved.version);\n }\n\n const insertResult = insertSvg(containerResult.value, data);\n\n if (!insertResult.ok) {\n return fail(insertResult.error);\n }\n\n logDebug('Iconly has successfully initialized.');\n\n return ok(undefined);\n };\n\n return { init, abort };\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["err","createIconlyError","ok","createIconlyError","ok","err","ok","err","createIconlyError","ok","err","resolveContainer","insertSvg","ok"],"sources":["../src/fetcher.ts","../src/storage/indexeddb.ts","../src/storage/memory.ts","../src/storage/session.ts","../src/storage/index.ts","../src/core.ts"],"sourcesContent":["import { createIconlyError } from './errors';\nimport { err, ok } from './result';\nimport type { Result } from './types';\n\nexport const fetchSvg = async (file: string, signal?: AbortSignal): Promise<Result<string>> => {\n try {\n const response = await fetch(file, { signal });\n\n if (!response.ok) {\n return err(createIconlyError('fetch_failed', `Failed to fetch icons from \"${file}\".`));\n }\n\n const data = await response.text();\n\n return ok(data);\n } catch (error: unknown) {\n if (error instanceof DOMException && error.name === 'AbortError') {\n return err(createIconlyError('fetch_aborted', 'Fetch request was aborted.', error));\n }\n\n return err(createIconlyError('fetch_failed', 'Failed to fetch icons.', error));\n }\n};\n","import { createIconlyError } from '../errors';\nimport { err, ok } from '../result';\nimport type { IconlyError, IconRecord, IconStorage, Result } from '../types';\n\ninterface IndexedDbOptions {\n dbName?: string;\n storeName?: string;\n}\n\nexport const createIndexedDbStorage = (options: IndexedDbOptions = {}): IconStorage => {\n const dbName = options.dbName ?? 'iconlyDB';\n const storeName = options.storeName ?? 'icons';\n\n let dbPromise: Promise<IDBDatabase> | null = null;\n\n const openDb = async (): Promise<IDBDatabase> => {\n if (dbPromise) {\n return dbPromise;\n }\n\n if (typeof indexedDB === 'undefined') {\n throw createIconlyError('indexeddb_not_supported', 'IndexedDB is not supported.');\n }\n\n dbPromise = new Promise<IDBDatabase>((resolve, reject) => {\n const request = indexedDB.open(dbName, 1);\n\n request.onerror = (): void => {\n reject(\n createIconlyError(\n 'indexeddb_open_failed',\n 'Failed to open IndexedDB connection.',\n request.error,\n ),\n );\n };\n\n request.onupgradeneeded = (event): void => {\n const db = (event.target as IDBOpenDBRequest).result;\n\n if (!db.objectStoreNames.contains(storeName)) {\n db.createObjectStore(storeName, { keyPath: 'version' });\n }\n };\n\n request.onsuccess = (): void => resolve(request.result);\n });\n\n return dbPromise;\n };\n\n const getStore = (db: IDBDatabase, mode: IDBTransactionMode): IDBObjectStore =>\n db.transaction(storeName, mode).objectStore(storeName);\n\n const toIconlyError = (\n error: unknown,\n fallbackCode: IconlyError['code'],\n message: string,\n ): IconlyError => {\n if (error && typeof error === 'object' && 'code' in error && 'message' in error) {\n return error as IconlyError;\n }\n\n return createIconlyError(fallbackCode, message, error);\n };\n\n const get = async (version: string): Promise<Result<IconRecord | undefined>> => {\n try {\n const db = await openDb();\n const store = getStore(db, 'readonly');\n\n return await new Promise<Result<IconRecord | undefined>>((resolve) => {\n const request = store.get(version);\n\n request.onsuccess = (): void => resolve(ok(request.result as IconRecord | undefined));\n request.onerror = (): void =>\n resolve(\n err(\n createIconlyError(\n 'indexeddb_request_failed',\n 'Failed to read from IndexedDB.',\n request.error,\n ),\n ),\n );\n });\n } catch (error: unknown) {\n return err(toIconlyError(error, 'indexeddb_open_failed', 'Failed to open IndexedDB.'));\n }\n };\n\n const set = async (record: IconRecord): Promise<Result<void>> => {\n try {\n const db = await openDb();\n const store = getStore(db, 'readwrite');\n\n return await new Promise<Result<void>>((resolve) => {\n const request = store.put(record);\n\n request.onsuccess = (): void => resolve(ok(undefined));\n request.onerror = (): void =>\n resolve(\n err(\n createIconlyError(\n 'indexeddb_request_failed',\n 'Failed to write to IndexedDB.',\n request.error,\n ),\n ),\n );\n });\n } catch (error: unknown) {\n return err(createIconlyError('indexeddb_open_failed', 'Failed to open IndexedDB.', error));\n }\n };\n\n return { get, set };\n};\n","import { ok } from '../result';\nimport type { IconRecord, IconStorage, Result } from '../types';\n\nexport const createMemoryStorage = (): IconStorage => {\n const store = new Map<string, string>();\n\n const get = async (version: string): Promise<Result<IconRecord | undefined>> => {\n if (!store.has(version)) {\n return ok(undefined);\n }\n\n return ok({ version, data: store.get(version) ?? '' });\n };\n\n const set = async (record: IconRecord): Promise<Result<void>> => {\n store.set(record.version, record.data);\n\n return ok(undefined);\n };\n\n return { get, set };\n};\n","import { createIconlyError } from '../errors';\nimport { err, ok } from '../result';\nimport type { IconRecord, IconStorage, Result } from '../types';\n\ninterface SessionStorageOptions {\n keyPrefix?: string;\n}\n\nexport const createSessionStorage = (options: SessionStorageOptions = {}): IconStorage => {\n const keyPrefix = options.keyPrefix ?? 'iconly';\n\n const resolveStorage = (): Result<Storage> => {\n if (typeof window === 'undefined' || !window.sessionStorage) {\n return err(createIconlyError('storage_unavailable', 'SessionStorage is not available.'));\n }\n\n return ok(window.sessionStorage);\n };\n\n const get = async (version: string): Promise<Result<IconRecord | undefined>> => {\n const storageResult = resolveStorage();\n\n if (!storageResult.ok) {\n return storageResult;\n }\n\n try {\n const raw = storageResult.value.getItem(`${keyPrefix}:${version}`);\n\n if (!raw) {\n return ok(undefined);\n }\n\n const parsed = JSON.parse(raw) as IconRecord;\n\n return ok(parsed);\n } catch (error: unknown) {\n return err(\n createIconlyError('storage_read_failed', 'Failed to read from SessionStorage.', error),\n );\n }\n };\n\n const set = async (record: IconRecord): Promise<Result<void>> => {\n const storageResult = resolveStorage();\n\n if (!storageResult.ok) {\n return storageResult;\n }\n\n try {\n storageResult.value.setItem(`${keyPrefix}:${record.version}`, JSON.stringify(record));\n\n return ok(undefined);\n } catch (error: unknown) {\n return err(\n createIconlyError('storage_write_failed', 'Failed to write to SessionStorage.', error),\n );\n }\n };\n\n return { get, set };\n};\n","import type { IconStorage, StorageStrategy } from '../types';\nimport { createIndexedDbStorage } from './indexeddb';\nimport { createMemoryStorage } from './memory';\nimport { createSessionStorage } from './session';\n\nexport interface StorageFactoryOptions {\n dbName?: string;\n storeName?: string;\n sessionKeyPrefix?: string;\n}\n\nexport const resolveStorage = (\n strategy: StorageStrategy | undefined,\n options: StorageFactoryOptions,\n): IconStorage => {\n if (!strategy || strategy === 'indexeddb') {\n return createIndexedDbStorage({\n dbName: options.dbName,\n storeName: options.storeName,\n });\n }\n\n if (strategy === 'memory') {\n return createMemoryStorage();\n }\n\n if (strategy === 'session') {\n return createSessionStorage({ keyPrefix: options.sessionKeyPrefix });\n }\n\n return strategy;\n};\n","import { insertSvg, resolveContainer } from './dom';\nimport { fetchSvg } from './fetcher';\nimport { err, ok } from './result';\nimport { resolveStorage } from './storage';\nimport type { IconlyConfig, IconlyError, IconlyInstance, IconStorage, Result } from './types';\n\ninterface ResolvedIconlyConfig {\n file: string;\n version: string;\n debug: boolean;\n container?: string | HTMLElement;\n logger?: IconlyConfig['logger'];\n onError?: IconlyConfig['onError'];\n onDebug?: IconlyConfig['onDebug'];\n}\n\nexport const createIconly = (config: IconlyConfig = {}): IconlyInstance => {\n const resolved: ResolvedIconlyConfig = {\n file: config.file ?? './icons.svg',\n version: config.version ?? '1.0',\n debug: config.debug ?? false,\n container: config.container,\n logger: config.logger,\n onError: config.onError,\n onDebug: config.onDebug,\n };\n\n const storage: IconStorage = resolveStorage(config.storage, {\n dbName: config.dbName,\n storeName: config.storeName,\n sessionKeyPrefix: config.sessionKeyPrefix,\n });\n\n let controller: AbortController | null = null;\n\n const abort = (): void => {\n controller?.abort();\n };\n\n const logDebug = (...messages: unknown[]): void => {\n if (!resolved.debug) {\n return;\n }\n\n resolved.onDebug?.(...messages);\n resolved.logger?.debug?.('[Iconly debug]', ...messages);\n };\n\n const logError = (error: IconlyError): void => {\n resolved.onError?.(error);\n resolved.logger?.error?.('[Iconly error]', error);\n };\n\n const fail = (error: IconlyError): Result<void> => {\n logError(error);\n\n return err(error);\n };\n\n const init = async (): Promise<Result<void>> => {\n const containerResult = resolveContainer(resolved.container);\n\n if (!containerResult.ok) {\n return fail(containerResult.error);\n }\n\n const cacheResult = await storage.get(resolved.version);\n\n if (!cacheResult.ok) {\n return fail(cacheResult.error);\n }\n\n let data = cacheResult.value?.data;\n\n if (!data) {\n controller = new AbortController();\n\n const fetchResult = await fetchSvg(resolved.file, controller.signal);\n\n if (!fetchResult.ok) {\n return fail(fetchResult.error);\n }\n\n data = fetchResult.value;\n\n const storeResult = await storage.set({\n version: resolved.version,\n data,\n });\n\n if (!storeResult.ok) {\n return fail(storeResult.error);\n }\n } else {\n logDebug('Using cached icon set', resolved.version);\n }\n\n const insertResult = insertSvg(containerResult.value, data);\n\n if (!insertResult.ok) {\n return fail(insertResult.error);\n }\n\n logDebug('Iconly has successfully initialized.');\n\n return ok(undefined);\n };\n\n return { init, abort };\n};\n"],"mappings":";;;;AAIA,MAAa,WAAW,OAAO,MAAc,WAAkD;CAC7F,IAAI;EACF,MAAM,WAAW,MAAM,MAAM,MAAM,EAAE,OAAO,CAAC;EAE7C,IAAI,CAAC,SAAS,IACZ,OAAOA,gBAAIC,8BAAkB,gBAAgB,+BAA+B,KAAK,GAAG,CAAC;EAKvF,OAAOC,eAAG,MAFS,SAAS,KAAK,CAEnB;CAChB,SAAS,OAAgB;EACvB,IAAI,iBAAiB,gBAAgB,MAAM,SAAS,cAClD,OAAOF,gBAAIC,8BAAkB,iBAAiB,8BAA8B,KAAK,CAAC;EAGpF,OAAOD,gBAAIC,8BAAkB,gBAAgB,0BAA0B,KAAK,CAAC;CAC/E;AACF;;;;ACbA,MAAa,0BAA0B,UAA4B,CAAC,MAAmB;CACrF,MAAM,SAAS,QAAQ,UAAU;CACjC,MAAM,YAAY,QAAQ,aAAa;CAEvC,IAAI,YAAyC;CAE7C,MAAM,SAAS,YAAkC;EAC/C,IAAI,WACF,OAAO;EAGT,IAAI,OAAO,cAAc,aACvB,MAAME,8BAAkB,2BAA2B,6BAA6B;EAGlF,YAAY,IAAI,SAAsB,SAAS,WAAW;GACxD,MAAM,UAAU,UAAU,KAAK,QAAQ,CAAC;GAExC,QAAQ,gBAAsB;IAC5B,OACEA,8BACE,yBACA,wCACA,QAAQ,KACV,CACF;GACF;GAEA,QAAQ,mBAAmB,UAAgB;IACzC,MAAM,KAAM,MAAM,OAA4B;IAE9C,IAAI,CAAC,GAAG,iBAAiB,SAAS,SAAS,GACzC,GAAG,kBAAkB,WAAW,EAAE,SAAS,UAAU,CAAC;GAE1D;GAEA,QAAQ,kBAAwB,QAAQ,QAAQ,MAAM;EACxD,CAAC;EAED,OAAO;CACT;CAEA,MAAM,YAAY,IAAiB,SACjC,GAAG,YAAY,WAAW,IAAI,CAAC,CAAC,YAAY,SAAS;CAEvD,MAAM,iBACJ,OACA,cACA,YACgB;EAChB,IAAI,SAAS,OAAO,UAAU,YAAY,UAAU,SAAS,aAAa,OACxE,OAAO;EAGT,OAAOA,8BAAkB,cAAc,SAAS,KAAK;CACvD;CAEA,MAAM,MAAM,OAAO,YAA6D;EAC9E,IAAI;GAEF,MAAM,QAAQ,SAAS,MADN,OAAO,GACG,UAAU;GAErC,OAAO,MAAM,IAAI,SAAyC,YAAY;IACpE,MAAM,UAAU,MAAM,IAAI,OAAO;IAEjC,QAAQ,kBAAwB,QAAQC,eAAG,QAAQ,MAAgC,CAAC;IACpF,QAAQ,gBACN,QACEC,gBACEF,8BACE,4BACA,kCACA,QAAQ,KACV,CACF,CACF;GACJ,CAAC;EACH,SAAS,OAAgB;GACvB,OAAOE,gBAAI,cAAc,OAAO,yBAAyB,2BAA2B,CAAC;EACvF;CACF;CAEA,MAAM,MAAM,OAAO,WAA8C;EAC/D,IAAI;GAEF,MAAM,QAAQ,SAAS,MADN,OAAO,GACG,WAAW;GAEtC,OAAO,MAAM,IAAI,SAAuB,YAAY;IAClD,MAAM,UAAU,MAAM,IAAI,MAAM;IAEhC,QAAQ,kBAAwB,QAAQD,eAAG,MAAS,CAAC;IACrD,QAAQ,gBACN,QACEC,gBACEF,8BACE,4BACA,iCACA,QAAQ,KACV,CACF,CACF;GACJ,CAAC;EACH,SAAS,OAAgB;GACvB,OAAOE,gBAAIF,8BAAkB,yBAAyB,6BAA6B,KAAK,CAAC;EAC3F;CACF;CAEA,OAAO;EAAE;EAAK;CAAI;AACpB;;;;AClHA,MAAa,4BAAyC;CACpD,MAAM,wBAAQ,IAAI,IAAoB;CAEtC,MAAM,MAAM,OAAO,YAA6D;EAC9E,IAAI,CAAC,MAAM,IAAI,OAAO,GACpB,OAAOG,eAAG,MAAS;EAGrB,OAAOA,eAAG;GAAE;GAAS,MAAM,MAAM,IAAI,OAAO,KAAK;EAAG,CAAC;CACvD;CAEA,MAAM,MAAM,OAAO,WAA8C;EAC/D,MAAM,IAAI,OAAO,SAAS,OAAO,IAAI;EAErC,OAAOA,eAAG,MAAS;CACrB;CAEA,OAAO;EAAE;EAAK;CAAI;AACpB;;;;ACbA,MAAa,wBAAwB,UAAiC,CAAC,MAAmB;CACxF,MAAM,YAAY,QAAQ,aAAa;CAEvC,MAAM,uBAAwC;EAC5C,IAAI,OAAO,WAAW,eAAe,CAAC,OAAO,gBAC3C,OAAOC,gBAAIC,8BAAkB,uBAAuB,kCAAkC,CAAC;EAGzF,OAAOC,eAAG,OAAO,cAAc;CACjC;CAEA,MAAM,MAAM,OAAO,YAA6D;EAC9E,MAAM,gBAAgB,eAAe;EAErC,IAAI,CAAC,cAAc,IACjB,OAAO;EAGT,IAAI;GACF,MAAM,MAAM,cAAc,MAAM,QAAQ,GAAG,UAAU,GAAG,SAAS;GAEjE,IAAI,CAAC,KACH,OAAOA,eAAG,MAAS;GAKrB,OAAOA,eAFQ,KAAK,MAAM,GAEX,CAAC;EAClB,SAAS,OAAgB;GACvB,OAAOF,gBACLC,8BAAkB,uBAAuB,uCAAuC,KAAK,CACvF;EACF;CACF;CAEA,MAAM,MAAM,OAAO,WAA8C;EAC/D,MAAM,gBAAgB,eAAe;EAErC,IAAI,CAAC,cAAc,IACjB,OAAO;EAGT,IAAI;GACF,cAAc,MAAM,QAAQ,GAAG,UAAU,GAAG,OAAO,WAAW,KAAK,UAAU,MAAM,CAAC;GAEpF,OAAOC,eAAG,MAAS;EACrB,SAAS,OAAgB;GACvB,OAAOF,gBACLC,8BAAkB,wBAAwB,sCAAsC,KAAK,CACvF;EACF;CACF;CAEA,OAAO;EAAE;EAAK;CAAI;AACpB;;;;ACnDA,MAAa,kBACX,UACA,YACgB;CAChB,IAAI,CAAC,YAAY,aAAa,aAC5B,OAAO,uBAAuB;EAC5B,QAAQ,QAAQ;EAChB,WAAW,QAAQ;CACrB,CAAC;CAGH,IAAI,aAAa,UACf,OAAO,oBAAoB;CAG7B,IAAI,aAAa,WACf,OAAO,qBAAqB,EAAE,WAAW,QAAQ,iBAAiB,CAAC;CAGrE,OAAO;AACT;;;;ACfA,MAAa,gBAAgB,SAAuB,CAAC,MAAsB;CACzE,MAAM,WAAiC;EACrC,MAAM,OAAO,QAAQ;EACrB,SAAS,OAAO,WAAW;EAC3B,OAAO,OAAO,SAAS;EACvB,WAAW,OAAO;EAClB,QAAQ,OAAO;EACf,SAAS,OAAO;EAChB,SAAS,OAAO;CAClB;CAEA,MAAM,UAAuB,eAAe,OAAO,SAAS;EAC1D,QAAQ,OAAO;EACf,WAAW,OAAO;EAClB,kBAAkB,OAAO;CAC3B,CAAC;CAED,IAAI,aAAqC;CAEzC,MAAM,cAAoB;EACxB,YAAY,MAAM;CACpB;CAEA,MAAM,YAAY,GAAG,aAA8B;EACjD,IAAI,CAAC,SAAS,OACZ;EAGF,SAAS,UAAU,GAAG,QAAQ;EAC9B,SAAS,QAAQ,QAAQ,kBAAkB,GAAG,QAAQ;CACxD;CAEA,MAAM,YAAY,UAA6B;EAC7C,SAAS,UAAU,KAAK;EACxB,SAAS,QAAQ,QAAQ,kBAAkB,KAAK;CAClD;CAEA,MAAM,QAAQ,UAAqC;EACjD,SAAS,KAAK;EAEd,OAAOE,gBAAI,KAAK;CAClB;CAEA,MAAM,OAAO,YAAmC;EAC9C,MAAM,kBAAkBC,6BAAiB,SAAS,SAAS;EAE3D,IAAI,CAAC,gBAAgB,IACnB,OAAO,KAAK,gBAAgB,KAAK;EAGnC,MAAM,cAAc,MAAM,QAAQ,IAAI,SAAS,OAAO;EAEtD,IAAI,CAAC,YAAY,IACf,OAAO,KAAK,YAAY,KAAK;EAG/B,IAAI,OAAO,YAAY,OAAO;EAE9B,IAAI,CAAC,MAAM;GACT,aAAa,IAAI,gBAAgB;GAEjC,MAAM,cAAc,MAAM,SAAS,SAAS,MAAM,WAAW,MAAM;GAEnE,IAAI,CAAC,YAAY,IACf,OAAO,KAAK,YAAY,KAAK;GAG/B,OAAO,YAAY;GAEnB,MAAM,cAAc,MAAM,QAAQ,IAAI;IACpC,SAAS,SAAS;IAClB;GACF,CAAC;GAED,IAAI,CAAC,YAAY,IACf,OAAO,KAAK,YAAY,KAAK;EAEjC,OACE,SAAS,yBAAyB,SAAS,OAAO;EAGpD,MAAM,eAAeC,sBAAU,gBAAgB,OAAO,IAAI;EAE1D,IAAI,CAAC,aAAa,IAChB,OAAO,KAAK,aAAa,KAAK;EAGhC,SAAS,sCAAsC;EAE/C,OAAOC,eAAG,MAAS;CACrB;CAEA,OAAO;EAAE;EAAM;CAAM;AACvB"}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,48 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
ok: true;
|
|
4
|
-
value: T;
|
|
5
|
-
} | {
|
|
6
|
-
ok: false;
|
|
7
|
-
error: IconlyError;
|
|
8
|
-
};
|
|
9
|
-
type IconlyErrorCode = 'container_invalid' | 'fetch_aborted' | 'fetch_failed' | 'indexeddb_not_supported' | 'indexeddb_open_failed' | 'indexeddb_request_failed' | 'parse_error' | 'storage_read_failed' | 'storage_unavailable' | 'storage_write_failed';
|
|
10
|
-
interface IconlyError {
|
|
11
|
-
code: IconlyErrorCode;
|
|
12
|
-
message: string;
|
|
13
|
-
cause?: unknown;
|
|
14
|
-
}
|
|
15
|
-
interface Logger {
|
|
16
|
-
debug?: (...messages: unknown[]) => void;
|
|
17
|
-
error?: (...messages: unknown[]) => void;
|
|
18
|
-
}
|
|
19
|
-
interface IconRecord {
|
|
20
|
-
version: string;
|
|
21
|
-
data: string;
|
|
22
|
-
}
|
|
23
|
-
interface IconStorage {
|
|
24
|
-
get(version: string): Promise<Result<IconRecord | undefined>>;
|
|
25
|
-
set(record: IconRecord): Promise<Result<void>>;
|
|
26
|
-
}
|
|
27
|
-
interface IconlyInstance {
|
|
28
|
-
init: () => Promise<Result<void>>;
|
|
29
|
-
abort: () => void;
|
|
30
|
-
}
|
|
31
|
-
type StorageStrategy = 'indexeddb' | 'memory' | 'session' | IconStorage;
|
|
32
|
-
interface IconlyConfig {
|
|
33
|
-
file?: string;
|
|
34
|
-
version?: string;
|
|
35
|
-
debug?: boolean;
|
|
36
|
-
container?: string | HTMLElement;
|
|
37
|
-
storage?: StorageStrategy;
|
|
38
|
-
dbName?: string;
|
|
39
|
-
storeName?: string;
|
|
40
|
-
sessionKeyPrefix?: string;
|
|
41
|
-
logger?: Logger;
|
|
42
|
-
onError?: (error: IconlyError) => void;
|
|
43
|
-
onDebug?: (...messages: unknown[]) => void;
|
|
44
|
-
}
|
|
45
|
-
//#endregion
|
|
1
|
+
import { a as IconlyErrorCode, c as Logger, f as StorageStrategy, i as IconlyError, l as Result, n as IconStorage, r as IconlyConfig, s as IconlyInstance, t as IconRecord } from "./types-Byzu8V49.cjs";
|
|
2
|
+
|
|
46
3
|
//#region src/core.d.ts
|
|
47
4
|
declare const createIconly: (config?: IconlyConfig) => IconlyInstance;
|
|
48
5
|
//#endregion
|
package/dist/index.d.ts
CHANGED
|
@@ -1,48 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
ok: true;
|
|
4
|
-
value: T;
|
|
5
|
-
} | {
|
|
6
|
-
ok: false;
|
|
7
|
-
error: IconlyError;
|
|
8
|
-
};
|
|
9
|
-
type IconlyErrorCode = 'container_invalid' | 'fetch_aborted' | 'fetch_failed' | 'indexeddb_not_supported' | 'indexeddb_open_failed' | 'indexeddb_request_failed' | 'parse_error' | 'storage_read_failed' | 'storage_unavailable' | 'storage_write_failed';
|
|
10
|
-
interface IconlyError {
|
|
11
|
-
code: IconlyErrorCode;
|
|
12
|
-
message: string;
|
|
13
|
-
cause?: unknown;
|
|
14
|
-
}
|
|
15
|
-
interface Logger {
|
|
16
|
-
debug?: (...messages: unknown[]) => void;
|
|
17
|
-
error?: (...messages: unknown[]) => void;
|
|
18
|
-
}
|
|
19
|
-
interface IconRecord {
|
|
20
|
-
version: string;
|
|
21
|
-
data: string;
|
|
22
|
-
}
|
|
23
|
-
interface IconStorage {
|
|
24
|
-
get(version: string): Promise<Result<IconRecord | undefined>>;
|
|
25
|
-
set(record: IconRecord): Promise<Result<void>>;
|
|
26
|
-
}
|
|
27
|
-
interface IconlyInstance {
|
|
28
|
-
init: () => Promise<Result<void>>;
|
|
29
|
-
abort: () => void;
|
|
30
|
-
}
|
|
31
|
-
type StorageStrategy = 'indexeddb' | 'memory' | 'session' | IconStorage;
|
|
32
|
-
interface IconlyConfig {
|
|
33
|
-
file?: string;
|
|
34
|
-
version?: string;
|
|
35
|
-
debug?: boolean;
|
|
36
|
-
container?: string | HTMLElement;
|
|
37
|
-
storage?: StorageStrategy;
|
|
38
|
-
dbName?: string;
|
|
39
|
-
storeName?: string;
|
|
40
|
-
sessionKeyPrefix?: string;
|
|
41
|
-
logger?: Logger;
|
|
42
|
-
onError?: (error: IconlyError) => void;
|
|
43
|
-
onDebug?: (...messages: unknown[]) => void;
|
|
44
|
-
}
|
|
45
|
-
//#endregion
|
|
1
|
+
import { a as IconlyErrorCode, c as Logger, f as StorageStrategy, i as IconlyError, l as Result, n as IconStorage, r as IconlyConfig, s as IconlyInstance, t as IconRecord } from "./types-Byzu8V49.js";
|
|
2
|
+
|
|
46
3
|
//#region src/core.d.ts
|
|
47
4
|
declare const createIconly: (config?: IconlyConfig) => IconlyInstance;
|
|
48
5
|
//#endregion
|
package/dist/index.js
CHANGED
|
@@ -1,45 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
const createIconlyError = (code, message, cause) => ({
|
|
3
|
-
code,
|
|
4
|
-
message,
|
|
5
|
-
cause
|
|
6
|
-
});
|
|
1
|
+
import { a as createIconlyError, i as ok, n as resolveContainer, r as err, t as insertSvg } from "./dom-senQJ1VA.js";
|
|
7
2
|
|
|
8
|
-
//#endregion
|
|
9
|
-
//#region src/result.ts
|
|
10
|
-
const ok = (value) => ({
|
|
11
|
-
ok: true,
|
|
12
|
-
value
|
|
13
|
-
});
|
|
14
|
-
const err = (error) => ({
|
|
15
|
-
ok: false,
|
|
16
|
-
error
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
//#endregion
|
|
20
|
-
//#region src/dom.ts
|
|
21
|
-
const insertSvg = (container, data) => {
|
|
22
|
-
const found = container.querySelector("[data-iconly=\"iconset\"]");
|
|
23
|
-
let iconSetDiv = found instanceof HTMLElement ? found : null;
|
|
24
|
-
if (!iconSetDiv) {
|
|
25
|
-
iconSetDiv = document.createElement("div");
|
|
26
|
-
iconSetDiv.setAttribute("data-iconly", "iconset");
|
|
27
|
-
iconSetDiv.setAttribute("aria-hidden", "true");
|
|
28
|
-
iconSetDiv.style.cssText = "width: 0; height: 0; position: absolute; left: -9999px;";
|
|
29
|
-
container.appendChild(iconSetDiv);
|
|
30
|
-
}
|
|
31
|
-
const svgDoc = new DOMParser().parseFromString(data, "image/svg+xml");
|
|
32
|
-
const parserError = svgDoc.querySelector("parsererror");
|
|
33
|
-
if (parserError) return err(createIconlyError("parse_error", `SVG parsing error: ${parserError.textContent ?? "Unknown error"}`));
|
|
34
|
-
iconSetDiv.innerHTML = "";
|
|
35
|
-
const svgEl = svgDoc.documentElement;
|
|
36
|
-
if (!svgEl) return err(createIconlyError("parse_error", "No valid SVG content found."));
|
|
37
|
-
const imported = document.importNode(svgEl, true);
|
|
38
|
-
iconSetDiv.appendChild(imported);
|
|
39
|
-
return ok(void 0);
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
//#endregion
|
|
43
3
|
//#region src/fetcher.ts
|
|
44
4
|
const fetchSvg = async (file, signal) => {
|
|
45
5
|
try {
|
|
@@ -198,18 +158,6 @@ const createIconly = (config = {}) => {
|
|
|
198
158
|
const abort = () => {
|
|
199
159
|
controller?.abort();
|
|
200
160
|
};
|
|
201
|
-
const resolveContainer = () => {
|
|
202
|
-
if (typeof document === "undefined") return err(createIconlyError("container_invalid", "Document is not available in this environment."));
|
|
203
|
-
if (typeof resolved.container === "string") {
|
|
204
|
-
const found = document.querySelector(resolved.container);
|
|
205
|
-
if (!found || !(found instanceof HTMLElement)) return err(createIconlyError("container_invalid", `Invalid container selector: "${resolved.container}".`));
|
|
206
|
-
return ok(found);
|
|
207
|
-
}
|
|
208
|
-
if (resolved.container instanceof HTMLElement) return ok(resolved.container);
|
|
209
|
-
const fallback = document.body ?? document.documentElement;
|
|
210
|
-
if (!fallback) return err(createIconlyError("container_invalid", "No valid container element found."));
|
|
211
|
-
return ok(fallback);
|
|
212
|
-
};
|
|
213
161
|
const logDebug = (...messages) => {
|
|
214
162
|
if (!resolved.debug) return;
|
|
215
163
|
resolved.onDebug?.(...messages);
|
|
@@ -224,7 +172,7 @@ const createIconly = (config = {}) => {
|
|
|
224
172
|
return err(error);
|
|
225
173
|
};
|
|
226
174
|
const init = async () => {
|
|
227
|
-
const containerResult = resolveContainer();
|
|
175
|
+
const containerResult = resolveContainer(resolved.container);
|
|
228
176
|
if (!containerResult.ok) return fail(containerResult.error);
|
|
229
177
|
const cacheResult = await storage.get(resolved.version);
|
|
230
178
|
if (!cacheResult.ok) return fail(cacheResult.error);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/errors.ts","../src/result.ts","../src/dom.ts","../src/fetcher.ts","../src/storage/indexeddb.ts","../src/storage/memory.ts","../src/storage/session.ts","../src/storage/index.ts","../src/core.ts"],"sourcesContent":["import type { IconlyError, IconlyErrorCode } from './types';\n\nexport const createIconlyError = (\n code: IconlyErrorCode,\n message: string,\n cause?: unknown,\n): IconlyError => ({\n code,\n message,\n cause,\n});\n","import type { IconlyError, Result } from './types';\n\nexport const ok = <T>(value: T): Result<T> => ({ ok: true, value });\n\nexport const err = <T = never>(error: IconlyError): Result<T> => ({ ok: false, error });\n","import { createIconlyError } from './errors';\nimport { err, ok } from './result';\nimport type { Result } from './types';\n\nexport const insertSvg = (container: HTMLElement, data: string): Result<void> => {\n const found = container.querySelector('[data-iconly=\"iconset\"]');\n let iconSetDiv: HTMLElement | null = found instanceof HTMLElement ? found : null;\n\n if (!iconSetDiv) {\n iconSetDiv = document.createElement('div');\n iconSetDiv.setAttribute('data-iconly', 'iconset');\n iconSetDiv.setAttribute('aria-hidden', 'true');\n iconSetDiv.style.cssText = 'width: 0; height: 0; position: absolute; left: -9999px;';\n container.appendChild(iconSetDiv);\n }\n\n const parser = new DOMParser();\n const svgDoc = parser.parseFromString(data, 'image/svg+xml');\n const parserError = svgDoc.querySelector('parsererror');\n\n if (parserError) {\n return err(\n createIconlyError(\n 'parse_error',\n `SVG parsing error: ${parserError.textContent ?? 'Unknown error'}`,\n ),\n );\n }\n\n iconSetDiv.innerHTML = '';\n\n const svgEl = svgDoc.documentElement;\n\n if (!svgEl) {\n return err(createIconlyError('parse_error', 'No valid SVG content found.'));\n }\n\n const imported = document.importNode(svgEl, true);\n\n iconSetDiv.appendChild(imported);\n\n return ok(undefined);\n};\n","import { createIconlyError } from './errors';\nimport { err, ok } from './result';\nimport type { Result } from './types';\n\nexport const fetchSvg = async (file: string, signal?: AbortSignal): Promise<Result<string>> => {\n try {\n const response = await fetch(file, { signal });\n\n if (!response.ok) {\n return err(createIconlyError('fetch_failed', `Failed to fetch icons from \"${file}\".`));\n }\n\n const data = await response.text();\n\n return ok(data);\n } catch (error: unknown) {\n if (error instanceof DOMException && error.name === 'AbortError') {\n return err(createIconlyError('fetch_aborted', 'Fetch request was aborted.', error));\n }\n\n return err(createIconlyError('fetch_failed', 'Failed to fetch icons.', error));\n }\n};\n","import { createIconlyError } from '../errors';\nimport { err, ok } from '../result';\nimport type { IconlyError, IconRecord, IconStorage, Result } from '../types';\n\ninterface IndexedDbOptions {\n dbName?: string;\n storeName?: string;\n}\n\nexport const createIndexedDbStorage = (options: IndexedDbOptions = {}): IconStorage => {\n const dbName = options.dbName ?? 'iconlyDB';\n const storeName = options.storeName ?? 'icons';\n\n let dbPromise: Promise<IDBDatabase> | null = null;\n\n const openDb = async (): Promise<IDBDatabase> => {\n if (dbPromise) {\n return dbPromise;\n }\n\n if (typeof indexedDB === 'undefined') {\n throw createIconlyError('indexeddb_not_supported', 'IndexedDB is not supported.');\n }\n\n dbPromise = new Promise<IDBDatabase>((resolve, reject) => {\n const request = indexedDB.open(dbName, 1);\n\n request.onerror = (): void => {\n reject(\n createIconlyError(\n 'indexeddb_open_failed',\n 'Failed to open IndexedDB connection.',\n request.error,\n ),\n );\n };\n\n request.onupgradeneeded = (event): void => {\n const db = (event.target as IDBOpenDBRequest).result;\n\n if (!db.objectStoreNames.contains(storeName)) {\n db.createObjectStore(storeName, { keyPath: 'version' });\n }\n };\n\n request.onsuccess = (): void => resolve(request.result);\n });\n\n return dbPromise;\n };\n\n const getStore = (db: IDBDatabase, mode: IDBTransactionMode): IDBObjectStore =>\n db.transaction(storeName, mode).objectStore(storeName);\n\n const toIconlyError = (\n error: unknown,\n fallbackCode: IconlyError['code'],\n message: string,\n ): IconlyError => {\n if (error && typeof error === 'object' && 'code' in error && 'message' in error) {\n return error as IconlyError;\n }\n\n return createIconlyError(fallbackCode, message, error);\n };\n\n const get = async (version: string): Promise<Result<IconRecord | undefined>> => {\n try {\n const db = await openDb();\n const store = getStore(db, 'readonly');\n\n return await new Promise<Result<IconRecord | undefined>>((resolve) => {\n const request = store.get(version);\n\n request.onsuccess = (): void => resolve(ok(request.result as IconRecord | undefined));\n request.onerror = (): void =>\n resolve(\n err(\n createIconlyError(\n 'indexeddb_request_failed',\n 'Failed to read from IndexedDB.',\n request.error,\n ),\n ),\n );\n });\n } catch (error: unknown) {\n return err(toIconlyError(error, 'indexeddb_open_failed', 'Failed to open IndexedDB.'));\n }\n };\n\n const set = async (record: IconRecord): Promise<Result<void>> => {\n try {\n const db = await openDb();\n const store = getStore(db, 'readwrite');\n\n return await new Promise<Result<void>>((resolve) => {\n const request = store.put(record);\n\n request.onsuccess = (): void => resolve(ok(undefined));\n request.onerror = (): void =>\n resolve(\n err(\n createIconlyError(\n 'indexeddb_request_failed',\n 'Failed to write to IndexedDB.',\n request.error,\n ),\n ),\n );\n });\n } catch (error: unknown) {\n return err(createIconlyError('indexeddb_open_failed', 'Failed to open IndexedDB.', error));\n }\n };\n\n return { get, set };\n};\n","import { ok } from '../result';\nimport type { IconRecord, IconStorage, Result } from '../types';\n\nexport const createMemoryStorage = (): IconStorage => {\n const store = new Map<string, string>();\n\n const get = async (version: string): Promise<Result<IconRecord | undefined>> => {\n if (!store.has(version)) {\n return ok(undefined);\n }\n\n return ok({ version, data: store.get(version) ?? '' });\n };\n\n const set = async (record: IconRecord): Promise<Result<void>> => {\n store.set(record.version, record.data);\n\n return ok(undefined);\n };\n\n return { get, set };\n};\n","import { createIconlyError } from '../errors';\nimport { err, ok } from '../result';\nimport type { IconRecord, IconStorage, Result } from '../types';\n\ninterface SessionStorageOptions {\n keyPrefix?: string;\n}\n\nexport const createSessionStorage = (options: SessionStorageOptions = {}): IconStorage => {\n const keyPrefix = options.keyPrefix ?? 'iconly';\n\n const resolveStorage = (): Result<Storage> => {\n if (typeof window === 'undefined' || !window.sessionStorage) {\n return err(createIconlyError('storage_unavailable', 'SessionStorage is not available.'));\n }\n\n return ok(window.sessionStorage);\n };\n\n const get = async (version: string): Promise<Result<IconRecord | undefined>> => {\n const storageResult = resolveStorage();\n\n if (!storageResult.ok) {\n return storageResult;\n }\n\n try {\n const raw = storageResult.value.getItem(`${keyPrefix}:${version}`);\n\n if (!raw) {\n return ok(undefined);\n }\n\n const parsed = JSON.parse(raw) as IconRecord;\n\n return ok(parsed);\n } catch (error: unknown) {\n return err(\n createIconlyError('storage_read_failed', 'Failed to read from SessionStorage.', error),\n );\n }\n };\n\n const set = async (record: IconRecord): Promise<Result<void>> => {\n const storageResult = resolveStorage();\n\n if (!storageResult.ok) {\n return storageResult;\n }\n\n try {\n storageResult.value.setItem(`${keyPrefix}:${record.version}`, JSON.stringify(record));\n\n return ok(undefined);\n } catch (error: unknown) {\n return err(\n createIconlyError('storage_write_failed', 'Failed to write to SessionStorage.', error),\n );\n }\n };\n\n return { get, set };\n};\n","import type { IconStorage, StorageStrategy } from '../types';\nimport { createIndexedDbStorage } from './indexeddb';\nimport { createMemoryStorage } from './memory';\nimport { createSessionStorage } from './session';\n\nexport interface StorageFactoryOptions {\n dbName?: string;\n storeName?: string;\n sessionKeyPrefix?: string;\n}\n\nexport const resolveStorage = (\n strategy: StorageStrategy | undefined,\n options: StorageFactoryOptions,\n): IconStorage => {\n if (!strategy || strategy === 'indexeddb') {\n return createIndexedDbStorage({\n dbName: options.dbName,\n storeName: options.storeName,\n });\n }\n\n if (strategy === 'memory') {\n return createMemoryStorage();\n }\n\n if (strategy === 'session') {\n return createSessionStorage({ keyPrefix: options.sessionKeyPrefix });\n }\n\n return strategy;\n};\n","import { insertSvg } from './dom';\nimport { createIconlyError } from './errors';\nimport { fetchSvg } from './fetcher';\nimport { err, ok } from './result';\nimport { resolveStorage } from './storage';\nimport type { IconlyConfig, IconlyError, IconlyInstance, IconStorage, Result } from './types';\n\ninterface ResolvedIconlyConfig {\n file: string;\n version: string;\n debug: boolean;\n container?: string | HTMLElement;\n logger?: IconlyConfig['logger'];\n onError?: IconlyConfig['onError'];\n onDebug?: IconlyConfig['onDebug'];\n}\n\nexport const createIconly = (config: IconlyConfig = {}): IconlyInstance => {\n const resolved: ResolvedIconlyConfig = {\n file: config.file ?? './icons.svg',\n version: config.version ?? '1.0',\n debug: config.debug ?? false,\n container: config.container,\n logger: config.logger,\n onError: config.onError,\n onDebug: config.onDebug,\n };\n\n const storage: IconStorage = resolveStorage(config.storage, {\n dbName: config.dbName,\n storeName: config.storeName,\n sessionKeyPrefix: config.sessionKeyPrefix,\n });\n\n let controller: AbortController | null = null;\n\n const abort = (): void => {\n controller?.abort();\n };\n\n const resolveContainer = (): Result<HTMLElement> => {\n if (typeof document === 'undefined') {\n return err(\n createIconlyError('container_invalid', 'Document is not available in this environment.'),\n );\n }\n\n if (typeof resolved.container === 'string') {\n const found = document.querySelector(resolved.container);\n\n if (!found || !(found instanceof HTMLElement)) {\n return err(\n createIconlyError(\n 'container_invalid',\n `Invalid container selector: \"${resolved.container}\".`,\n ),\n );\n }\n\n return ok(found);\n }\n\n if (resolved.container instanceof HTMLElement) {\n return ok(resolved.container);\n }\n\n const fallback = document.body ?? document.documentElement;\n\n if (!fallback) {\n return err(createIconlyError('container_invalid', 'No valid container element found.'));\n }\n\n return ok(fallback);\n };\n\n const logDebug = (...messages: unknown[]): void => {\n if (!resolved.debug) {\n return;\n }\n\n resolved.onDebug?.(...messages);\n resolved.logger?.debug?.('[Iconly debug]', ...messages);\n };\n\n const logError = (error: IconlyError): void => {\n resolved.onError?.(error);\n resolved.logger?.error?.('[Iconly error]', error);\n };\n\n const fail = (error: IconlyError): Result<void> => {\n logError(error);\n\n return err(error);\n };\n\n const init = async (): Promise<Result<void>> => {\n const containerResult = resolveContainer();\n\n if (!containerResult.ok) {\n return fail(containerResult.error);\n }\n\n const cacheResult = await storage.get(resolved.version);\n\n if (!cacheResult.ok) {\n return fail(cacheResult.error);\n }\n\n let data = cacheResult.value?.data;\n\n if (!data) {\n controller = new AbortController();\n\n const fetchResult = await fetchSvg(resolved.file, controller.signal);\n\n if (!fetchResult.ok) {\n return fail(fetchResult.error);\n }\n\n data = fetchResult.value;\n\n const storeResult = await storage.set({\n version: resolved.version,\n data,\n });\n\n if (!storeResult.ok) {\n return fail(storeResult.error);\n }\n } else {\n logDebug('Using cached icon set', resolved.version);\n }\n\n const insertResult = insertSvg(containerResult.value, data);\n\n if (!insertResult.ok) {\n return fail(insertResult.error);\n }\n\n logDebug('Iconly has successfully initialized.');\n\n return ok(undefined);\n };\n\n return { init, abort };\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/fetcher.ts","../src/storage/indexeddb.ts","../src/storage/memory.ts","../src/storage/session.ts","../src/storage/index.ts","../src/core.ts"],"sourcesContent":["import { createIconlyError } from './errors';\nimport { err, ok } from './result';\nimport type { Result } from './types';\n\nexport const fetchSvg = async (file: string, signal?: AbortSignal): Promise<Result<string>> => {\n try {\n const response = await fetch(file, { signal });\n\n if (!response.ok) {\n return err(createIconlyError('fetch_failed', `Failed to fetch icons from \"${file}\".`));\n }\n\n const data = await response.text();\n\n return ok(data);\n } catch (error: unknown) {\n if (error instanceof DOMException && error.name === 'AbortError') {\n return err(createIconlyError('fetch_aborted', 'Fetch request was aborted.', error));\n }\n\n return err(createIconlyError('fetch_failed', 'Failed to fetch icons.', error));\n }\n};\n","import { createIconlyError } from '../errors';\nimport { err, ok } from '../result';\nimport type { IconlyError, IconRecord, IconStorage, Result } from '../types';\n\ninterface IndexedDbOptions {\n dbName?: string;\n storeName?: string;\n}\n\nexport const createIndexedDbStorage = (options: IndexedDbOptions = {}): IconStorage => {\n const dbName = options.dbName ?? 'iconlyDB';\n const storeName = options.storeName ?? 'icons';\n\n let dbPromise: Promise<IDBDatabase> | null = null;\n\n const openDb = async (): Promise<IDBDatabase> => {\n if (dbPromise) {\n return dbPromise;\n }\n\n if (typeof indexedDB === 'undefined') {\n throw createIconlyError('indexeddb_not_supported', 'IndexedDB is not supported.');\n }\n\n dbPromise = new Promise<IDBDatabase>((resolve, reject) => {\n const request = indexedDB.open(dbName, 1);\n\n request.onerror = (): void => {\n reject(\n createIconlyError(\n 'indexeddb_open_failed',\n 'Failed to open IndexedDB connection.',\n request.error,\n ),\n );\n };\n\n request.onupgradeneeded = (event): void => {\n const db = (event.target as IDBOpenDBRequest).result;\n\n if (!db.objectStoreNames.contains(storeName)) {\n db.createObjectStore(storeName, { keyPath: 'version' });\n }\n };\n\n request.onsuccess = (): void => resolve(request.result);\n });\n\n return dbPromise;\n };\n\n const getStore = (db: IDBDatabase, mode: IDBTransactionMode): IDBObjectStore =>\n db.transaction(storeName, mode).objectStore(storeName);\n\n const toIconlyError = (\n error: unknown,\n fallbackCode: IconlyError['code'],\n message: string,\n ): IconlyError => {\n if (error && typeof error === 'object' && 'code' in error && 'message' in error) {\n return error as IconlyError;\n }\n\n return createIconlyError(fallbackCode, message, error);\n };\n\n const get = async (version: string): Promise<Result<IconRecord | undefined>> => {\n try {\n const db = await openDb();\n const store = getStore(db, 'readonly');\n\n return await new Promise<Result<IconRecord | undefined>>((resolve) => {\n const request = store.get(version);\n\n request.onsuccess = (): void => resolve(ok(request.result as IconRecord | undefined));\n request.onerror = (): void =>\n resolve(\n err(\n createIconlyError(\n 'indexeddb_request_failed',\n 'Failed to read from IndexedDB.',\n request.error,\n ),\n ),\n );\n });\n } catch (error: unknown) {\n return err(toIconlyError(error, 'indexeddb_open_failed', 'Failed to open IndexedDB.'));\n }\n };\n\n const set = async (record: IconRecord): Promise<Result<void>> => {\n try {\n const db = await openDb();\n const store = getStore(db, 'readwrite');\n\n return await new Promise<Result<void>>((resolve) => {\n const request = store.put(record);\n\n request.onsuccess = (): void => resolve(ok(undefined));\n request.onerror = (): void =>\n resolve(\n err(\n createIconlyError(\n 'indexeddb_request_failed',\n 'Failed to write to IndexedDB.',\n request.error,\n ),\n ),\n );\n });\n } catch (error: unknown) {\n return err(createIconlyError('indexeddb_open_failed', 'Failed to open IndexedDB.', error));\n }\n };\n\n return { get, set };\n};\n","import { ok } from '../result';\nimport type { IconRecord, IconStorage, Result } from '../types';\n\nexport const createMemoryStorage = (): IconStorage => {\n const store = new Map<string, string>();\n\n const get = async (version: string): Promise<Result<IconRecord | undefined>> => {\n if (!store.has(version)) {\n return ok(undefined);\n }\n\n return ok({ version, data: store.get(version) ?? '' });\n };\n\n const set = async (record: IconRecord): Promise<Result<void>> => {\n store.set(record.version, record.data);\n\n return ok(undefined);\n };\n\n return { get, set };\n};\n","import { createIconlyError } from '../errors';\nimport { err, ok } from '../result';\nimport type { IconRecord, IconStorage, Result } from '../types';\n\ninterface SessionStorageOptions {\n keyPrefix?: string;\n}\n\nexport const createSessionStorage = (options: SessionStorageOptions = {}): IconStorage => {\n const keyPrefix = options.keyPrefix ?? 'iconly';\n\n const resolveStorage = (): Result<Storage> => {\n if (typeof window === 'undefined' || !window.sessionStorage) {\n return err(createIconlyError('storage_unavailable', 'SessionStorage is not available.'));\n }\n\n return ok(window.sessionStorage);\n };\n\n const get = async (version: string): Promise<Result<IconRecord | undefined>> => {\n const storageResult = resolveStorage();\n\n if (!storageResult.ok) {\n return storageResult;\n }\n\n try {\n const raw = storageResult.value.getItem(`${keyPrefix}:${version}`);\n\n if (!raw) {\n return ok(undefined);\n }\n\n const parsed = JSON.parse(raw) as IconRecord;\n\n return ok(parsed);\n } catch (error: unknown) {\n return err(\n createIconlyError('storage_read_failed', 'Failed to read from SessionStorage.', error),\n );\n }\n };\n\n const set = async (record: IconRecord): Promise<Result<void>> => {\n const storageResult = resolveStorage();\n\n if (!storageResult.ok) {\n return storageResult;\n }\n\n try {\n storageResult.value.setItem(`${keyPrefix}:${record.version}`, JSON.stringify(record));\n\n return ok(undefined);\n } catch (error: unknown) {\n return err(\n createIconlyError('storage_write_failed', 'Failed to write to SessionStorage.', error),\n );\n }\n };\n\n return { get, set };\n};\n","import type { IconStorage, StorageStrategy } from '../types';\nimport { createIndexedDbStorage } from './indexeddb';\nimport { createMemoryStorage } from './memory';\nimport { createSessionStorage } from './session';\n\nexport interface StorageFactoryOptions {\n dbName?: string;\n storeName?: string;\n sessionKeyPrefix?: string;\n}\n\nexport const resolveStorage = (\n strategy: StorageStrategy | undefined,\n options: StorageFactoryOptions,\n): IconStorage => {\n if (!strategy || strategy === 'indexeddb') {\n return createIndexedDbStorage({\n dbName: options.dbName,\n storeName: options.storeName,\n });\n }\n\n if (strategy === 'memory') {\n return createMemoryStorage();\n }\n\n if (strategy === 'session') {\n return createSessionStorage({ keyPrefix: options.sessionKeyPrefix });\n }\n\n return strategy;\n};\n","import { insertSvg, resolveContainer } from './dom';\nimport { fetchSvg } from './fetcher';\nimport { err, ok } from './result';\nimport { resolveStorage } from './storage';\nimport type { IconlyConfig, IconlyError, IconlyInstance, IconStorage, Result } from './types';\n\ninterface ResolvedIconlyConfig {\n file: string;\n version: string;\n debug: boolean;\n container?: string | HTMLElement;\n logger?: IconlyConfig['logger'];\n onError?: IconlyConfig['onError'];\n onDebug?: IconlyConfig['onDebug'];\n}\n\nexport const createIconly = (config: IconlyConfig = {}): IconlyInstance => {\n const resolved: ResolvedIconlyConfig = {\n file: config.file ?? './icons.svg',\n version: config.version ?? '1.0',\n debug: config.debug ?? false,\n container: config.container,\n logger: config.logger,\n onError: config.onError,\n onDebug: config.onDebug,\n };\n\n const storage: IconStorage = resolveStorage(config.storage, {\n dbName: config.dbName,\n storeName: config.storeName,\n sessionKeyPrefix: config.sessionKeyPrefix,\n });\n\n let controller: AbortController | null = null;\n\n const abort = (): void => {\n controller?.abort();\n };\n\n const logDebug = (...messages: unknown[]): void => {\n if (!resolved.debug) {\n return;\n }\n\n resolved.onDebug?.(...messages);\n resolved.logger?.debug?.('[Iconly debug]', ...messages);\n };\n\n const logError = (error: IconlyError): void => {\n resolved.onError?.(error);\n resolved.logger?.error?.('[Iconly error]', error);\n };\n\n const fail = (error: IconlyError): Result<void> => {\n logError(error);\n\n return err(error);\n };\n\n const init = async (): Promise<Result<void>> => {\n const containerResult = resolveContainer(resolved.container);\n\n if (!containerResult.ok) {\n return fail(containerResult.error);\n }\n\n const cacheResult = await storage.get(resolved.version);\n\n if (!cacheResult.ok) {\n return fail(cacheResult.error);\n }\n\n let data = cacheResult.value?.data;\n\n if (!data) {\n controller = new AbortController();\n\n const fetchResult = await fetchSvg(resolved.file, controller.signal);\n\n if (!fetchResult.ok) {\n return fail(fetchResult.error);\n }\n\n data = fetchResult.value;\n\n const storeResult = await storage.set({\n version: resolved.version,\n data,\n });\n\n if (!storeResult.ok) {\n return fail(storeResult.error);\n }\n } else {\n logDebug('Using cached icon set', resolved.version);\n }\n\n const insertResult = insertSvg(containerResult.value, data);\n\n if (!insertResult.ok) {\n return fail(insertResult.error);\n }\n\n logDebug('Iconly has successfully initialized.');\n\n return ok(undefined);\n };\n\n return { init, abort };\n};\n"],"mappings":"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"}
|
package/dist/sprite.cjs
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
const require_dom = require('./dom-Bqsr32nW.cjs');
|
|
3
|
+
|
|
4
|
+
//#region src/sprite.ts
|
|
5
|
+
const escapeAttr = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/"/g, """);
|
|
6
|
+
const buildSpriteString = (icons) => {
|
|
7
|
+
return `<svg xmlns="http://www.w3.org/2000/svg">${icons.map((icon) => `<symbol id="${escapeAttr(icon.name)}" viewBox="${escapeAttr(icon.viewBox)}">${icon.body}</symbol>`).join("")}</svg>`;
|
|
8
|
+
};
|
|
9
|
+
const createSprite = (config) => {
|
|
10
|
+
const { icons, container } = config;
|
|
11
|
+
return { render: () => {
|
|
12
|
+
const containerResult = require_dom.resolveContainer(container);
|
|
13
|
+
if (!containerResult.ok) return containerResult;
|
|
14
|
+
return require_dom.insertSvg(containerResult.value, buildSpriteString(icons));
|
|
15
|
+
} };
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
//#endregion
|
|
19
|
+
exports.buildSpriteString = buildSpriteString;
|
|
20
|
+
exports.createSprite = createSprite;
|
|
21
|
+
//# sourceMappingURL=sprite.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sprite.cjs","names":["resolveContainer","insertSvg"],"sources":["../src/sprite.ts"],"sourcesContent":["import { insertSvg, resolveContainer } from './dom';\nimport type { IconlyIcon, Result, SpriteConfig, SpriteInstance } from './types';\n\nconst escapeAttr = (value: string): string =>\n value.replace(/&/g, '&').replace(/</g, '<').replace(/\"/g, '"');\n\nexport const buildSpriteString = (icons: IconlyIcon[]): string => {\n const symbols = icons\n .map(\n (icon) =>\n `<symbol id=\"${escapeAttr(icon.name)}\" viewBox=\"${escapeAttr(icon.viewBox)}\">${icon.body}</symbol>`,\n )\n .join('');\n\n return `<svg xmlns=\"http://www.w3.org/2000/svg\">${symbols}</svg>`;\n};\n\nexport const createSprite = (config: SpriteConfig): SpriteInstance => {\n const { icons, container } = config;\n\n return {\n render: (): Result<void> => {\n const containerResult = resolveContainer(container);\n\n if (!containerResult.ok) {\n return containerResult;\n }\n\n return insertSvg(containerResult.value, buildSpriteString(icons));\n },\n };\n};\n\nexport type { IconlyIcon, SpriteConfig, SpriteInstance } from './types';\n"],"mappings":";;;;AAGA,MAAM,cAAc,UAClB,MAAM,QAAQ,MAAM,OAAO,CAAC,CAAC,QAAQ,MAAM,MAAM,CAAC,CAAC,QAAQ,MAAM,QAAQ;AAE3E,MAAa,qBAAqB,UAAgC;CAQhE,OAAO,2CAPS,MACb,KACE,SACC,eAAe,WAAW,KAAK,IAAI,EAAE,aAAa,WAAW,KAAK,OAAO,EAAE,IAAI,KAAK,KAAK,UAC7F,CAAC,CACA,KAAK,EAEgD,EAAE;AAC5D;AAEA,MAAa,gBAAgB,WAAyC;CACpE,MAAM,EAAE,OAAO,cAAc;CAE7B,OAAO,EACL,cAA4B;EAC1B,MAAM,kBAAkBA,6BAAiB,SAAS;EAElD,IAAI,CAAC,gBAAgB,IACnB,OAAO;EAGT,OAAOC,sBAAU,gBAAgB,OAAO,kBAAkB,KAAK,CAAC;CAClE,EACF;AACF"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { d as SpriteInstance, o as IconlyIcon, u as SpriteConfig } from "./types-Byzu8V49.cjs";
|
|
2
|
+
|
|
3
|
+
//#region src/sprite.d.ts
|
|
4
|
+
declare const buildSpriteString: (icons: IconlyIcon[]) => string;
|
|
5
|
+
declare const createSprite: (config: SpriteConfig) => SpriteInstance;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { type IconlyIcon, type SpriteConfig, type SpriteInstance, buildSpriteString, createSprite };
|
|
8
|
+
//# sourceMappingURL=sprite.d.cts.map
|
package/dist/sprite.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { d as SpriteInstance, o as IconlyIcon, u as SpriteConfig } from "./types-Byzu8V49.js";
|
|
2
|
+
|
|
3
|
+
//#region src/sprite.d.ts
|
|
4
|
+
declare const buildSpriteString: (icons: IconlyIcon[]) => string;
|
|
5
|
+
declare const createSprite: (config: SpriteConfig) => SpriteInstance;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { type IconlyIcon, type SpriteConfig, type SpriteInstance, buildSpriteString, createSprite };
|
|
8
|
+
//# sourceMappingURL=sprite.d.ts.map
|
package/dist/sprite.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { n as resolveContainer, t as insertSvg } from "./dom-senQJ1VA.js";
|
|
2
|
+
|
|
3
|
+
//#region src/sprite.ts
|
|
4
|
+
const escapeAttr = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/"/g, """);
|
|
5
|
+
const buildSpriteString = (icons) => {
|
|
6
|
+
return `<svg xmlns="http://www.w3.org/2000/svg">${icons.map((icon) => `<symbol id="${escapeAttr(icon.name)}" viewBox="${escapeAttr(icon.viewBox)}">${icon.body}</symbol>`).join("")}</svg>`;
|
|
7
|
+
};
|
|
8
|
+
const createSprite = (config) => {
|
|
9
|
+
const { icons, container } = config;
|
|
10
|
+
return { render: () => {
|
|
11
|
+
const containerResult = resolveContainer(container);
|
|
12
|
+
if (!containerResult.ok) return containerResult;
|
|
13
|
+
return insertSvg(containerResult.value, buildSpriteString(icons));
|
|
14
|
+
} };
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
//#endregion
|
|
18
|
+
export { buildSpriteString, createSprite };
|
|
19
|
+
//# sourceMappingURL=sprite.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sprite.js","names":[],"sources":["../src/sprite.ts"],"sourcesContent":["import { insertSvg, resolveContainer } from './dom';\nimport type { IconlyIcon, Result, SpriteConfig, SpriteInstance } from './types';\n\nconst escapeAttr = (value: string): string =>\n value.replace(/&/g, '&').replace(/</g, '<').replace(/\"/g, '"');\n\nexport const buildSpriteString = (icons: IconlyIcon[]): string => {\n const symbols = icons\n .map(\n (icon) =>\n `<symbol id=\"${escapeAttr(icon.name)}\" viewBox=\"${escapeAttr(icon.viewBox)}\">${icon.body}</symbol>`,\n )\n .join('');\n\n return `<svg xmlns=\"http://www.w3.org/2000/svg\">${symbols}</svg>`;\n};\n\nexport const createSprite = (config: SpriteConfig): SpriteInstance => {\n const { icons, container } = config;\n\n return {\n render: (): Result<void> => {\n const containerResult = resolveContainer(container);\n\n if (!containerResult.ok) {\n return containerResult;\n }\n\n return insertSvg(containerResult.value, buildSpriteString(icons));\n },\n };\n};\n\nexport type { IconlyIcon, SpriteConfig, SpriteInstance } from './types';\n"],"mappings":";;;AAGA,MAAM,cAAc,UAClB,MAAM,QAAQ,MAAM,OAAO,CAAC,CAAC,QAAQ,MAAM,MAAM,CAAC,CAAC,QAAQ,MAAM,QAAQ;AAE3E,MAAa,qBAAqB,UAAgC;CAQhE,OAAO,2CAPS,MACb,KACE,SACC,eAAe,WAAW,KAAK,IAAI,EAAE,aAAa,WAAW,KAAK,OAAO,EAAE,IAAI,KAAK,KAAK,UAC7F,CAAC,CACA,KAAK,EAEgD,EAAE;AAC5D;AAEA,MAAa,gBAAgB,WAAyC;CACpE,MAAM,EAAE,OAAO,cAAc;CAE7B,OAAO,EACL,cAA4B;EAC1B,MAAM,kBAAkB,iBAAiB,SAAS;EAElD,IAAI,CAAC,gBAAgB,IACnB,OAAO;EAGT,OAAO,UAAU,gBAAgB,OAAO,kBAAkB,KAAK,CAAC;CAClE,EACF;AACF"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
//#region src/types.d.ts
|
|
2
|
+
type Result<T> = {
|
|
3
|
+
ok: true;
|
|
4
|
+
value: T;
|
|
5
|
+
} | {
|
|
6
|
+
ok: false;
|
|
7
|
+
error: IconlyError;
|
|
8
|
+
};
|
|
9
|
+
type IconlyErrorCode = 'container_invalid' | 'fetch_aborted' | 'fetch_failed' | 'indexeddb_not_supported' | 'indexeddb_open_failed' | 'indexeddb_request_failed' | 'parse_error' | 'storage_read_failed' | 'storage_unavailable' | 'storage_write_failed';
|
|
10
|
+
interface IconlyError {
|
|
11
|
+
code: IconlyErrorCode;
|
|
12
|
+
message: string;
|
|
13
|
+
cause?: unknown;
|
|
14
|
+
}
|
|
15
|
+
interface Logger {
|
|
16
|
+
debug?: (...messages: unknown[]) => void;
|
|
17
|
+
error?: (...messages: unknown[]) => void;
|
|
18
|
+
}
|
|
19
|
+
interface IconRecord {
|
|
20
|
+
version: string;
|
|
21
|
+
data: string;
|
|
22
|
+
}
|
|
23
|
+
interface IconStorage {
|
|
24
|
+
get(version: string): Promise<Result<IconRecord | undefined>>;
|
|
25
|
+
set(record: IconRecord): Promise<Result<void>>;
|
|
26
|
+
}
|
|
27
|
+
interface IconlyInstance {
|
|
28
|
+
init: () => Promise<Result<void>>;
|
|
29
|
+
abort: () => void;
|
|
30
|
+
}
|
|
31
|
+
type StorageStrategy = 'indexeddb' | 'memory' | 'session' | IconStorage;
|
|
32
|
+
interface IconlyIcon {
|
|
33
|
+
name: string;
|
|
34
|
+
viewBox: string;
|
|
35
|
+
body: string;
|
|
36
|
+
}
|
|
37
|
+
interface SpriteConfig {
|
|
38
|
+
icons: IconlyIcon[];
|
|
39
|
+
container?: string | HTMLElement;
|
|
40
|
+
}
|
|
41
|
+
interface SpriteInstance {
|
|
42
|
+
render: () => Result<void>;
|
|
43
|
+
}
|
|
44
|
+
interface IconlyConfig {
|
|
45
|
+
file?: string;
|
|
46
|
+
version?: string;
|
|
47
|
+
debug?: boolean;
|
|
48
|
+
container?: string | HTMLElement;
|
|
49
|
+
storage?: StorageStrategy;
|
|
50
|
+
dbName?: string;
|
|
51
|
+
storeName?: string;
|
|
52
|
+
sessionKeyPrefix?: string;
|
|
53
|
+
logger?: Logger;
|
|
54
|
+
onError?: (error: IconlyError) => void;
|
|
55
|
+
onDebug?: (...messages: unknown[]) => void;
|
|
56
|
+
}
|
|
57
|
+
//#endregion
|
|
58
|
+
export { IconlyErrorCode as a, Logger as c, SpriteInstance as d, StorageStrategy as f, IconlyError as i, Result as l, IconStorage as n, IconlyIcon as o, IconlyConfig as r, IconlyInstance as s, IconRecord as t, SpriteConfig as u };
|
|
59
|
+
//# sourceMappingURL=types-Byzu8V49.d.cts.map
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
//#region src/types.d.ts
|
|
2
|
+
type Result<T> = {
|
|
3
|
+
ok: true;
|
|
4
|
+
value: T;
|
|
5
|
+
} | {
|
|
6
|
+
ok: false;
|
|
7
|
+
error: IconlyError;
|
|
8
|
+
};
|
|
9
|
+
type IconlyErrorCode = 'container_invalid' | 'fetch_aborted' | 'fetch_failed' | 'indexeddb_not_supported' | 'indexeddb_open_failed' | 'indexeddb_request_failed' | 'parse_error' | 'storage_read_failed' | 'storage_unavailable' | 'storage_write_failed';
|
|
10
|
+
interface IconlyError {
|
|
11
|
+
code: IconlyErrorCode;
|
|
12
|
+
message: string;
|
|
13
|
+
cause?: unknown;
|
|
14
|
+
}
|
|
15
|
+
interface Logger {
|
|
16
|
+
debug?: (...messages: unknown[]) => void;
|
|
17
|
+
error?: (...messages: unknown[]) => void;
|
|
18
|
+
}
|
|
19
|
+
interface IconRecord {
|
|
20
|
+
version: string;
|
|
21
|
+
data: string;
|
|
22
|
+
}
|
|
23
|
+
interface IconStorage {
|
|
24
|
+
get(version: string): Promise<Result<IconRecord | undefined>>;
|
|
25
|
+
set(record: IconRecord): Promise<Result<void>>;
|
|
26
|
+
}
|
|
27
|
+
interface IconlyInstance {
|
|
28
|
+
init: () => Promise<Result<void>>;
|
|
29
|
+
abort: () => void;
|
|
30
|
+
}
|
|
31
|
+
type StorageStrategy = 'indexeddb' | 'memory' | 'session' | IconStorage;
|
|
32
|
+
interface IconlyIcon {
|
|
33
|
+
name: string;
|
|
34
|
+
viewBox: string;
|
|
35
|
+
body: string;
|
|
36
|
+
}
|
|
37
|
+
interface SpriteConfig {
|
|
38
|
+
icons: IconlyIcon[];
|
|
39
|
+
container?: string | HTMLElement;
|
|
40
|
+
}
|
|
41
|
+
interface SpriteInstance {
|
|
42
|
+
render: () => Result<void>;
|
|
43
|
+
}
|
|
44
|
+
interface IconlyConfig {
|
|
45
|
+
file?: string;
|
|
46
|
+
version?: string;
|
|
47
|
+
debug?: boolean;
|
|
48
|
+
container?: string | HTMLElement;
|
|
49
|
+
storage?: StorageStrategy;
|
|
50
|
+
dbName?: string;
|
|
51
|
+
storeName?: string;
|
|
52
|
+
sessionKeyPrefix?: string;
|
|
53
|
+
logger?: Logger;
|
|
54
|
+
onError?: (error: IconlyError) => void;
|
|
55
|
+
onDebug?: (...messages: unknown[]) => void;
|
|
56
|
+
}
|
|
57
|
+
//#endregion
|
|
58
|
+
export { IconlyErrorCode as a, Logger as c, SpriteInstance as d, StorageStrategy as f, IconlyError as i, Result as l, IconStorage as n, IconlyIcon as o, IconlyConfig as r, IconlyInstance as s, IconRecord as t, SpriteConfig as u };
|
|
59
|
+
//# sourceMappingURL=types-Byzu8V49.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iconly",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.1.0",
|
|
4
4
|
"description": "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.",
|
|
5
5
|
"author": "ux-ui.pro",
|
|
6
6
|
"license": "MIT",
|
|
@@ -32,7 +32,6 @@
|
|
|
32
32
|
"pack:check": "npm pack --dry-run && publint && attw --pack . --profile node16",
|
|
33
33
|
"prepublishOnly": "npm run clean && npm run verify"
|
|
34
34
|
},
|
|
35
|
-
"source": "src/index.ts",
|
|
36
35
|
"main": "./dist/index.cjs",
|
|
37
36
|
"module": "./dist/index.js",
|
|
38
37
|
"types": "./dist/index.d.ts",
|
|
@@ -46,6 +45,16 @@
|
|
|
46
45
|
"types": "./dist/index.d.cts",
|
|
47
46
|
"default": "./dist/index.cjs"
|
|
48
47
|
}
|
|
48
|
+
},
|
|
49
|
+
"./sprite": {
|
|
50
|
+
"import": {
|
|
51
|
+
"types": "./dist/sprite.d.ts",
|
|
52
|
+
"default": "./dist/sprite.js"
|
|
53
|
+
},
|
|
54
|
+
"require": {
|
|
55
|
+
"types": "./dist/sprite.d.cts",
|
|
56
|
+
"default": "./dist/sprite.cjs"
|
|
57
|
+
}
|
|
49
58
|
}
|
|
50
59
|
},
|
|
51
60
|
"files": [
|