viconic-react-icons 1.4.2 → 1.5.1
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 +10 -3
- package/dist/index.js +93 -11
- package/dist/index.mjs +93 -11
- package/package.json +1 -1
- package/src/index.jsx +125 -13
package/README.md
CHANGED
|
@@ -112,15 +112,22 @@ Inject a kit's smart loader script into `<head>`. Call once per kit at app start
|
|
|
112
112
|
| :--- | :--- | :--- | :--- |
|
|
113
113
|
| `kitId` | `string` | — | **Required.** UUID of your Viconic Kit. |
|
|
114
114
|
| `cdnBase` | `string` | `"cdn.viconic.dev"` | Custom CDN domain. |
|
|
115
|
-
| `version` | `string` | `undefined` |
|
|
115
|
+
| `version` | `string` | `undefined` | Cache-bust version. **Update this every time you add/remove icons in your kit.** |
|
|
116
116
|
|
|
117
117
|
```jsx
|
|
118
118
|
// In your main.jsx or App.jsx
|
|
119
119
|
import { initViconic } from "viconic-react-icons";
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
// Copy the exact snippet from the "Usage & Setup" tab in your Kit Editor
|
|
122
|
+
// It already includes the correct version timestamp for your kit.
|
|
123
|
+
initViconic({ kitId: "387a6161-cb39-411f-8f13-29a5813e4efd", version: "1774867419" });
|
|
122
124
|
```
|
|
123
125
|
|
|
126
|
+
> **⚠️ Important — Cache Busting:**
|
|
127
|
+
> Every time you update your kit on [viconic.dev](https://viconic.dev) (add/remove icons, click **"Update Kit"**), you must update the `version` value in `initViconic()` to the new timestamp shown in the **Usage & Setup** tab.
|
|
128
|
+
> This ensures your users always load the latest kit instead of a stale cached version.
|
|
129
|
+
> The **Usage & Setup** tab always shows the ready-to-copy snippet with the current version pre-filled.
|
|
130
|
+
|
|
124
131
|
---
|
|
125
132
|
|
|
126
133
|
## 🧠 Architecture
|
|
@@ -135,4 +142,4 @@ Because we fetch SVGs in parallel and cache them heavily via LocalStorage across
|
|
|
135
142
|
|
|
136
143
|
## 📄 License
|
|
137
144
|
|
|
138
|
-
This project is licensed under the MIT License. Icon licenses depend on the specific icon families you use.
|
|
145
|
+
This project is licensed under the MIT License. Icon licenses depend on the specific icon families you use.
|
package/dist/index.js
CHANGED
|
@@ -2003,8 +2003,81 @@ var import_react = __toESM(require("react"));
|
|
|
2003
2003
|
}
|
|
2004
2004
|
})();
|
|
2005
2005
|
var _initializedKits = /* @__PURE__ */ new Set();
|
|
2006
|
+
var _kitRegistry = {};
|
|
2007
|
+
var _pendingMisses = {};
|
|
2008
|
+
if (typeof document !== "undefined") {
|
|
2009
|
+
document.addEventListener("viconic:ready", (e) => {
|
|
2010
|
+
const prefix = e && e.detail && e.detail.prefix;
|
|
2011
|
+
if (prefix) _flushPendingMisses(prefix);
|
|
2012
|
+
});
|
|
2013
|
+
}
|
|
2014
|
+
var _kitMissQueues = {};
|
|
2015
|
+
var _kitMissTimers = {};
|
|
2016
|
+
function _resolveRegistry(prefix) {
|
|
2017
|
+
if (_kitRegistry[prefix]) return _kitRegistry[prefix];
|
|
2018
|
+
const kits = window.CopyIconsKit || {};
|
|
2019
|
+
for (const kId in kits) {
|
|
2020
|
+
const kit = kits[kId];
|
|
2021
|
+
if (kit.config && kit.config.prefix === prefix) {
|
|
2022
|
+
const entry = { kitId: kId, api: kit.config.api || "https://api.viconic.dev" };
|
|
2023
|
+
_kitRegistry[prefix] = entry;
|
|
2024
|
+
return entry;
|
|
2025
|
+
}
|
|
2026
|
+
}
|
|
2027
|
+
return null;
|
|
2028
|
+
}
|
|
2029
|
+
function _flushPendingMisses(prefix) {
|
|
2030
|
+
const pending = _pendingMisses[prefix];
|
|
2031
|
+
if (!pending || !pending.size) return;
|
|
2032
|
+
const entry = _resolveRegistry(prefix);
|
|
2033
|
+
if (!entry) return;
|
|
2034
|
+
delete _pendingMisses[prefix];
|
|
2035
|
+
pending.forEach((name) => _dispatchBatchFetch(prefix, name, entry));
|
|
2036
|
+
}
|
|
2037
|
+
function _dispatchBatchFetch(prefix, iconBaseName, entry) {
|
|
2038
|
+
const { kitId, api } = entry;
|
|
2039
|
+
if (!_kitMissQueues[kitId]) _kitMissQueues[kitId] = /* @__PURE__ */ new Set();
|
|
2040
|
+
_kitMissQueues[kitId].add(iconBaseName);
|
|
2041
|
+
if (_kitMissTimers[kitId]) return;
|
|
2042
|
+
_kitMissTimers[kitId] = setTimeout(() => {
|
|
2043
|
+
delete _kitMissTimers[kitId];
|
|
2044
|
+
const names = [..._kitMissQueues[kitId] || []];
|
|
2045
|
+
delete _kitMissQueues[kitId];
|
|
2046
|
+
if (!names.length) return;
|
|
2047
|
+
fetch(`${api}/api/v1/kits/${kitId}/icons/?icons=${names.join(",")}`).then((r) => r.ok ? r.json() : null).then((bj) => {
|
|
2048
|
+
if (!bj || !bj.icons) return;
|
|
2049
|
+
const W = window.__viconic = window.__viconic || {};
|
|
2050
|
+
W.icons = W.icons || {};
|
|
2051
|
+
for (const n in bj.icons) {
|
|
2052
|
+
if (!Object.prototype.hasOwnProperty.call(bj.icons, n)) continue;
|
|
2053
|
+
const d = bj.icons[n];
|
|
2054
|
+
const svg = d.svg || "";
|
|
2055
|
+
if (!svg || !svg.includes("<")) continue;
|
|
2056
|
+
W.icons[`@${prefix}/${n}`] = svg;
|
|
2057
|
+
W.icons[`${prefix}:${n}`] = svg;
|
|
2058
|
+
W.icons[`${prefix}/${n}`] = svg;
|
|
2059
|
+
W.icons[n] = W.icons[n] || svg;
|
|
2060
|
+
}
|
|
2061
|
+
try {
|
|
2062
|
+
document.dispatchEvent(new CustomEvent("viconic:ready", { detail: { prefix, kitId } }));
|
|
2063
|
+
} catch (e) {
|
|
2064
|
+
}
|
|
2065
|
+
}).catch(() => {
|
|
2066
|
+
});
|
|
2067
|
+
}, 0);
|
|
2068
|
+
}
|
|
2069
|
+
function _queueKitMiss(prefix, iconBaseName) {
|
|
2070
|
+
if (typeof window === "undefined") return;
|
|
2071
|
+
const entry = _resolveRegistry(prefix);
|
|
2072
|
+
if (entry) {
|
|
2073
|
+
_dispatchBatchFetch(prefix, iconBaseName, entry);
|
|
2074
|
+
} else {
|
|
2075
|
+
if (!_pendingMisses[prefix]) _pendingMisses[prefix] = /* @__PURE__ */ new Set();
|
|
2076
|
+
_pendingMisses[prefix].add(iconBaseName);
|
|
2077
|
+
}
|
|
2078
|
+
}
|
|
2006
2079
|
function initViconic(options = {}) {
|
|
2007
|
-
const { kitId, cdnBase = "cdn.viconic.dev", version } = options;
|
|
2080
|
+
const { kitId, cdnBase = "cdn.viconic.dev", version, prefix: explicitPrefix, api = "https://api.viconic.dev" } = options;
|
|
2008
2081
|
if (typeof window === "undefined") return;
|
|
2009
2082
|
if (!kitId) {
|
|
2010
2083
|
console.warn("[Viconic] initViconic requires a kitId");
|
|
@@ -2012,6 +2085,13 @@ function initViconic(options = {}) {
|
|
|
2012
2085
|
}
|
|
2013
2086
|
if (_initializedKits.has(kitId)) return;
|
|
2014
2087
|
_initializedKits.add(kitId);
|
|
2088
|
+
if (explicitPrefix) {
|
|
2089
|
+
_kitRegistry[explicitPrefix] = { kitId, api };
|
|
2090
|
+
}
|
|
2091
|
+
if (typeof window !== "undefined") {
|
|
2092
|
+
window.__viconicKitIds = window.__viconicKitIds || {};
|
|
2093
|
+
window.__viconicKitIds[kitId] = { api };
|
|
2094
|
+
}
|
|
2015
2095
|
const scriptId = `viconic-kit-${kitId}`;
|
|
2016
2096
|
if (document.getElementById(scriptId)) return;
|
|
2017
2097
|
const script = document.createElement("script");
|
|
@@ -2021,6 +2101,15 @@ function initViconic(options = {}) {
|
|
|
2021
2101
|
const vQuery = version === "dev" ? Date.now() : version;
|
|
2022
2102
|
url += `?v=${vQuery}`;
|
|
2023
2103
|
}
|
|
2104
|
+
script.onload = () => {
|
|
2105
|
+
const kits = window.CopyIconsKit || {};
|
|
2106
|
+
const kit = kits[kitId];
|
|
2107
|
+
if (kit && kit.config && kit.config.prefix) {
|
|
2108
|
+
const pfx = kit.config.prefix;
|
|
2109
|
+
_kitRegistry[pfx] = { kitId, api: kit.config.api || api };
|
|
2110
|
+
_flushPendingMisses(pfx);
|
|
2111
|
+
}
|
|
2112
|
+
};
|
|
2024
2113
|
script.src = url;
|
|
2025
2114
|
script.async = true;
|
|
2026
2115
|
document.head.appendChild(script);
|
|
@@ -2084,17 +2173,10 @@ var ViconicIcon = ({ name, className, style, size, color, ...props }) => {
|
|
|
2084
2173
|
tryInjectFromEvent();
|
|
2085
2174
|
if (!isInjected() && isKitIcon && prefixMatch) {
|
|
2086
2175
|
const prefix = prefixMatch[1];
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
const kit = window.CopyIconsKit[kId];
|
|
2090
|
-
if (kit.config && kit.config.prefix === prefix && typeof kit.reload === "function") {
|
|
2091
|
-
kit.reload();
|
|
2092
|
-
break;
|
|
2093
|
-
}
|
|
2094
|
-
}
|
|
2095
|
-
}
|
|
2176
|
+
const iconBaseName = prefixMatch[2];
|
|
2177
|
+
_queueKitMiss(prefix, iconBaseName);
|
|
2096
2178
|
}
|
|
2097
|
-
},
|
|
2179
|
+
}, 50);
|
|
2098
2180
|
return () => {
|
|
2099
2181
|
document.removeEventListener("viconic:ready", tryInjectFromEvent);
|
|
2100
2182
|
clearTimeout(fallbackTimer);
|
package/dist/index.mjs
CHANGED
|
@@ -1968,8 +1968,81 @@ import React, { useEffect, useRef } from "react";
|
|
|
1968
1968
|
}
|
|
1969
1969
|
})();
|
|
1970
1970
|
var _initializedKits = /* @__PURE__ */ new Set();
|
|
1971
|
+
var _kitRegistry = {};
|
|
1972
|
+
var _pendingMisses = {};
|
|
1973
|
+
if (typeof document !== "undefined") {
|
|
1974
|
+
document.addEventListener("viconic:ready", (e) => {
|
|
1975
|
+
const prefix = e && e.detail && e.detail.prefix;
|
|
1976
|
+
if (prefix) _flushPendingMisses(prefix);
|
|
1977
|
+
});
|
|
1978
|
+
}
|
|
1979
|
+
var _kitMissQueues = {};
|
|
1980
|
+
var _kitMissTimers = {};
|
|
1981
|
+
function _resolveRegistry(prefix) {
|
|
1982
|
+
if (_kitRegistry[prefix]) return _kitRegistry[prefix];
|
|
1983
|
+
const kits = window.CopyIconsKit || {};
|
|
1984
|
+
for (const kId in kits) {
|
|
1985
|
+
const kit = kits[kId];
|
|
1986
|
+
if (kit.config && kit.config.prefix === prefix) {
|
|
1987
|
+
const entry = { kitId: kId, api: kit.config.api || "https://api.viconic.dev" };
|
|
1988
|
+
_kitRegistry[prefix] = entry;
|
|
1989
|
+
return entry;
|
|
1990
|
+
}
|
|
1991
|
+
}
|
|
1992
|
+
return null;
|
|
1993
|
+
}
|
|
1994
|
+
function _flushPendingMisses(prefix) {
|
|
1995
|
+
const pending = _pendingMisses[prefix];
|
|
1996
|
+
if (!pending || !pending.size) return;
|
|
1997
|
+
const entry = _resolveRegistry(prefix);
|
|
1998
|
+
if (!entry) return;
|
|
1999
|
+
delete _pendingMisses[prefix];
|
|
2000
|
+
pending.forEach((name) => _dispatchBatchFetch(prefix, name, entry));
|
|
2001
|
+
}
|
|
2002
|
+
function _dispatchBatchFetch(prefix, iconBaseName, entry) {
|
|
2003
|
+
const { kitId, api } = entry;
|
|
2004
|
+
if (!_kitMissQueues[kitId]) _kitMissQueues[kitId] = /* @__PURE__ */ new Set();
|
|
2005
|
+
_kitMissQueues[kitId].add(iconBaseName);
|
|
2006
|
+
if (_kitMissTimers[kitId]) return;
|
|
2007
|
+
_kitMissTimers[kitId] = setTimeout(() => {
|
|
2008
|
+
delete _kitMissTimers[kitId];
|
|
2009
|
+
const names = [..._kitMissQueues[kitId] || []];
|
|
2010
|
+
delete _kitMissQueues[kitId];
|
|
2011
|
+
if (!names.length) return;
|
|
2012
|
+
fetch(`${api}/api/v1/kits/${kitId}/icons/?icons=${names.join(",")}`).then((r) => r.ok ? r.json() : null).then((bj) => {
|
|
2013
|
+
if (!bj || !bj.icons) return;
|
|
2014
|
+
const W = window.__viconic = window.__viconic || {};
|
|
2015
|
+
W.icons = W.icons || {};
|
|
2016
|
+
for (const n in bj.icons) {
|
|
2017
|
+
if (!Object.prototype.hasOwnProperty.call(bj.icons, n)) continue;
|
|
2018
|
+
const d = bj.icons[n];
|
|
2019
|
+
const svg = d.svg || "";
|
|
2020
|
+
if (!svg || !svg.includes("<")) continue;
|
|
2021
|
+
W.icons[`@${prefix}/${n}`] = svg;
|
|
2022
|
+
W.icons[`${prefix}:${n}`] = svg;
|
|
2023
|
+
W.icons[`${prefix}/${n}`] = svg;
|
|
2024
|
+
W.icons[n] = W.icons[n] || svg;
|
|
2025
|
+
}
|
|
2026
|
+
try {
|
|
2027
|
+
document.dispatchEvent(new CustomEvent("viconic:ready", { detail: { prefix, kitId } }));
|
|
2028
|
+
} catch (e) {
|
|
2029
|
+
}
|
|
2030
|
+
}).catch(() => {
|
|
2031
|
+
});
|
|
2032
|
+
}, 0);
|
|
2033
|
+
}
|
|
2034
|
+
function _queueKitMiss(prefix, iconBaseName) {
|
|
2035
|
+
if (typeof window === "undefined") return;
|
|
2036
|
+
const entry = _resolveRegistry(prefix);
|
|
2037
|
+
if (entry) {
|
|
2038
|
+
_dispatchBatchFetch(prefix, iconBaseName, entry);
|
|
2039
|
+
} else {
|
|
2040
|
+
if (!_pendingMisses[prefix]) _pendingMisses[prefix] = /* @__PURE__ */ new Set();
|
|
2041
|
+
_pendingMisses[prefix].add(iconBaseName);
|
|
2042
|
+
}
|
|
2043
|
+
}
|
|
1971
2044
|
function initViconic(options = {}) {
|
|
1972
|
-
const { kitId, cdnBase = "cdn.viconic.dev", version } = options;
|
|
2045
|
+
const { kitId, cdnBase = "cdn.viconic.dev", version, prefix: explicitPrefix, api = "https://api.viconic.dev" } = options;
|
|
1973
2046
|
if (typeof window === "undefined") return;
|
|
1974
2047
|
if (!kitId) {
|
|
1975
2048
|
console.warn("[Viconic] initViconic requires a kitId");
|
|
@@ -1977,6 +2050,13 @@ function initViconic(options = {}) {
|
|
|
1977
2050
|
}
|
|
1978
2051
|
if (_initializedKits.has(kitId)) return;
|
|
1979
2052
|
_initializedKits.add(kitId);
|
|
2053
|
+
if (explicitPrefix) {
|
|
2054
|
+
_kitRegistry[explicitPrefix] = { kitId, api };
|
|
2055
|
+
}
|
|
2056
|
+
if (typeof window !== "undefined") {
|
|
2057
|
+
window.__viconicKitIds = window.__viconicKitIds || {};
|
|
2058
|
+
window.__viconicKitIds[kitId] = { api };
|
|
2059
|
+
}
|
|
1980
2060
|
const scriptId = `viconic-kit-${kitId}`;
|
|
1981
2061
|
if (document.getElementById(scriptId)) return;
|
|
1982
2062
|
const script = document.createElement("script");
|
|
@@ -1986,6 +2066,15 @@ function initViconic(options = {}) {
|
|
|
1986
2066
|
const vQuery = version === "dev" ? Date.now() : version;
|
|
1987
2067
|
url += `?v=${vQuery}`;
|
|
1988
2068
|
}
|
|
2069
|
+
script.onload = () => {
|
|
2070
|
+
const kits = window.CopyIconsKit || {};
|
|
2071
|
+
const kit = kits[kitId];
|
|
2072
|
+
if (kit && kit.config && kit.config.prefix) {
|
|
2073
|
+
const pfx = kit.config.prefix;
|
|
2074
|
+
_kitRegistry[pfx] = { kitId, api: kit.config.api || api };
|
|
2075
|
+
_flushPendingMisses(pfx);
|
|
2076
|
+
}
|
|
2077
|
+
};
|
|
1989
2078
|
script.src = url;
|
|
1990
2079
|
script.async = true;
|
|
1991
2080
|
document.head.appendChild(script);
|
|
@@ -2049,17 +2138,10 @@ var ViconicIcon = ({ name, className, style, size, color, ...props }) => {
|
|
|
2049
2138
|
tryInjectFromEvent();
|
|
2050
2139
|
if (!isInjected() && isKitIcon && prefixMatch) {
|
|
2051
2140
|
const prefix = prefixMatch[1];
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
const kit = window.CopyIconsKit[kId];
|
|
2055
|
-
if (kit.config && kit.config.prefix === prefix && typeof kit.reload === "function") {
|
|
2056
|
-
kit.reload();
|
|
2057
|
-
break;
|
|
2058
|
-
}
|
|
2059
|
-
}
|
|
2060
|
-
}
|
|
2141
|
+
const iconBaseName = prefixMatch[2];
|
|
2142
|
+
_queueKitMiss(prefix, iconBaseName);
|
|
2061
2143
|
}
|
|
2062
|
-
},
|
|
2144
|
+
}, 50);
|
|
2063
2145
|
return () => {
|
|
2064
2146
|
document.removeEventListener("viconic:ready", tryInjectFromEvent);
|
|
2065
2147
|
clearTimeout(fallbackTimer);
|
package/package.json
CHANGED
package/src/index.jsx
CHANGED
|
@@ -36,6 +36,101 @@ import './copyicons-smart-loader.js';
|
|
|
36
36
|
// ============================================
|
|
37
37
|
const _initializedKits = new Set();
|
|
38
38
|
|
|
39
|
+
// ============================================
|
|
40
|
+
// Kit registry: prefix -> { kitId, api }
|
|
41
|
+
// Populated by initViconic() via script.onload
|
|
42
|
+
// and by viconic:ready event handler.
|
|
43
|
+
// ============================================
|
|
44
|
+
const _kitRegistry = {}; // prefix -> { kitId, api }
|
|
45
|
+
|
|
46
|
+
// Pending misses buffered before registry is ready
|
|
47
|
+
// prefix -> Set of icon names
|
|
48
|
+
const _pendingMisses = {};
|
|
49
|
+
|
|
50
|
+
// Global viconic:ready listener — fires when kit loader calls register()
|
|
51
|
+
// This is the main trigger for flushing pending misses when loader.js
|
|
52
|
+
// completes its first batch fetch (which happens after script.onload).
|
|
53
|
+
if (typeof document !== 'undefined') {
|
|
54
|
+
document.addEventListener('viconic:ready', (e) => {
|
|
55
|
+
const prefix = e && e.detail && e.detail.prefix;
|
|
56
|
+
if (prefix) _flushPendingMisses(prefix);
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// ============================================
|
|
61
|
+
// DEBOUNCED BATCH FETCH for missing kit icons
|
|
62
|
+
// ============================================
|
|
63
|
+
const _kitMissQueues = {}; // kitId -> Set of icon names
|
|
64
|
+
const _kitMissTimers = {}; // kitId -> timer handle
|
|
65
|
+
|
|
66
|
+
function _resolveRegistry(prefix) {
|
|
67
|
+
if (_kitRegistry[prefix]) return _kitRegistry[prefix];
|
|
68
|
+
// Fallback: check CopyIconsKit
|
|
69
|
+
const kits = window.CopyIconsKit || {};
|
|
70
|
+
for (const kId in kits) {
|
|
71
|
+
const kit = kits[kId];
|
|
72
|
+
if (kit.config && kit.config.prefix === prefix) {
|
|
73
|
+
const entry = { kitId: kId, api: kit.config.api || 'https://api.viconic.dev' };
|
|
74
|
+
_kitRegistry[prefix] = entry;
|
|
75
|
+
return entry;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function _flushPendingMisses(prefix) {
|
|
82
|
+
const pending = _pendingMisses[prefix];
|
|
83
|
+
if (!pending || !pending.size) return;
|
|
84
|
+
const entry = _resolveRegistry(prefix);
|
|
85
|
+
if (!entry) return;
|
|
86
|
+
delete _pendingMisses[prefix];
|
|
87
|
+
pending.forEach(name => _dispatchBatchFetch(prefix, name, entry));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function _dispatchBatchFetch(prefix, iconBaseName, entry) {
|
|
91
|
+
const { kitId, api } = entry;
|
|
92
|
+
if (!_kitMissQueues[kitId]) _kitMissQueues[kitId] = new Set();
|
|
93
|
+
_kitMissQueues[kitId].add(iconBaseName);
|
|
94
|
+
if (_kitMissTimers[kitId]) return;
|
|
95
|
+
_kitMissTimers[kitId] = setTimeout(() => {
|
|
96
|
+
delete _kitMissTimers[kitId];
|
|
97
|
+
const names = [...(_kitMissQueues[kitId] || [])];
|
|
98
|
+
delete _kitMissQueues[kitId];
|
|
99
|
+
if (!names.length) return;
|
|
100
|
+
fetch(`${api}/api/v1/kits/${kitId}/icons/?icons=${names.join(',')}`)
|
|
101
|
+
.then(r => r.ok ? r.json() : null)
|
|
102
|
+
.then(bj => {
|
|
103
|
+
if (!bj || !bj.icons) return;
|
|
104
|
+
const W = (window.__viconic = window.__viconic || {});
|
|
105
|
+
W.icons = W.icons || {};
|
|
106
|
+
for (const n in bj.icons) {
|
|
107
|
+
if (!Object.prototype.hasOwnProperty.call(bj.icons, n)) continue;
|
|
108
|
+
const d = bj.icons[n];
|
|
109
|
+
const svg = d.svg || '';
|
|
110
|
+
if (!svg || !svg.includes('<')) continue;
|
|
111
|
+
W.icons[`@${prefix}/${n}`] = svg;
|
|
112
|
+
W.icons[`${prefix}:${n}`] = svg;
|
|
113
|
+
W.icons[`${prefix}/${n}`] = svg;
|
|
114
|
+
W.icons[n] = W.icons[n] || svg;
|
|
115
|
+
}
|
|
116
|
+
try { document.dispatchEvent(new CustomEvent('viconic:ready', { detail: { prefix, kitId } })); } catch(e) {}
|
|
117
|
+
})
|
|
118
|
+
.catch(() => {});
|
|
119
|
+
}, 0);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function _queueKitMiss(prefix, iconBaseName) {
|
|
123
|
+
if (typeof window === 'undefined') return;
|
|
124
|
+
const entry = _resolveRegistry(prefix);
|
|
125
|
+
if (entry) {
|
|
126
|
+
_dispatchBatchFetch(prefix, iconBaseName, entry);
|
|
127
|
+
} else {
|
|
128
|
+
// Registry not ready yet — buffer until loader fires
|
|
129
|
+
if (!_pendingMisses[prefix]) _pendingMisses[prefix] = new Set();
|
|
130
|
+
_pendingMisses[prefix].add(iconBaseName);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
39
134
|
/**
|
|
40
135
|
* Initialize a Viconic Kit in your React app.
|
|
41
136
|
* Injects the kit's loader.js script into <head>.
|
|
@@ -53,7 +148,7 @@ const _initializedKits = new Set();
|
|
|
53
148
|
* initViconic({ kitId: 'another-kit-uuid', version: '1.0' });
|
|
54
149
|
*/
|
|
55
150
|
export function initViconic(options = {}) {
|
|
56
|
-
const { kitId, cdnBase = 'cdn.viconic.dev', version } = options;
|
|
151
|
+
const { kitId, cdnBase = 'cdn.viconic.dev', version, prefix: explicitPrefix, api = 'https://api.viconic.dev' } = options;
|
|
57
152
|
if (typeof window === 'undefined') return; // SSR guard
|
|
58
153
|
if (!kitId) {
|
|
59
154
|
console.warn('[Viconic] initViconic requires a kitId');
|
|
@@ -62,6 +157,18 @@ export function initViconic(options = {}) {
|
|
|
62
157
|
if (_initializedKits.has(kitId)) return; // Already initialized
|
|
63
158
|
_initializedKits.add(kitId);
|
|
64
159
|
|
|
160
|
+
// Register synchronously so _queueKitMiss can find kitId immediately,
|
|
161
|
+
// even before the async loader.js script has loaded and populated CopyIconsKit.
|
|
162
|
+
// If prefix is not known yet, we'll also register once CopyIconsKit fires.
|
|
163
|
+
if (explicitPrefix) {
|
|
164
|
+
_kitRegistry[explicitPrefix] = { kitId, api };
|
|
165
|
+
}
|
|
166
|
+
// Also register by kitId so we can backfill prefix once loader fires
|
|
167
|
+
if (typeof window !== 'undefined') {
|
|
168
|
+
window.__viconicKitIds = window.__viconicKitIds || {};
|
|
169
|
+
window.__viconicKitIds[kitId] = { api };
|
|
170
|
+
}
|
|
171
|
+
|
|
65
172
|
const scriptId = `viconic-kit-${kitId}`;
|
|
66
173
|
if (document.getElementById(scriptId)) return; // Script already in DOM
|
|
67
174
|
|
|
@@ -75,6 +182,18 @@ export function initViconic(options = {}) {
|
|
|
75
182
|
url += `?v=${vQuery}`;
|
|
76
183
|
}
|
|
77
184
|
|
|
185
|
+
// Once loader.js runs and registers CopyIconsKit, backfill _kitRegistry and flush pending misses
|
|
186
|
+
script.onload = () => {
|
|
187
|
+
const kits = window.CopyIconsKit || {};
|
|
188
|
+
const kit = kits[kitId];
|
|
189
|
+
if (kit && kit.config && kit.config.prefix) {
|
|
190
|
+
const pfx = kit.config.prefix;
|
|
191
|
+
_kitRegistry[pfx] = { kitId, api: kit.config.api || api };
|
|
192
|
+
// Flush any misses buffered before the loader was ready
|
|
193
|
+
_flushPendingMisses(pfx);
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
|
|
78
197
|
script.src = url;
|
|
79
198
|
script.async = true;
|
|
80
199
|
document.head.appendChild(script);
|
|
@@ -169,24 +288,17 @@ export const ViconicIcon = ({ name, className, style, size, color, ...props }) =
|
|
|
169
288
|
|
|
170
289
|
document.addEventListener('viconic:ready', tryInjectFromEvent);
|
|
171
290
|
|
|
172
|
-
// --- PATH 5: Short-deadline fallback (
|
|
291
|
+
// --- PATH 5: Short-deadline fallback (50ms) — queue a batch fetch for all missing kit icons ---
|
|
173
292
|
const fallbackTimer = setTimeout(() => {
|
|
174
293
|
if (isInjected()) return;
|
|
175
294
|
tryInjectFromEvent();
|
|
176
|
-
// If still not loaded after 500ms, trigger kit reload once
|
|
177
295
|
if (!isInjected() && isKitIcon && prefixMatch) {
|
|
178
296
|
const prefix = prefixMatch[1];
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
if (kit.config && kit.config.prefix === prefix && typeof kit.reload === 'function') {
|
|
183
|
-
kit.reload();
|
|
184
|
-
break;
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
|
297
|
+
const iconBaseName = prefixMatch[2];
|
|
298
|
+
// Use batch queue instead of kit.reload() to avoid N separate API calls
|
|
299
|
+
_queueKitMiss(prefix, iconBaseName);
|
|
188
300
|
}
|
|
189
|
-
},
|
|
301
|
+
}, 50);
|
|
190
302
|
|
|
191
303
|
return () => {
|
|
192
304
|
document.removeEventListener('viconic:ready', tryInjectFromEvent);
|