viconic-react-icons 1.5.0 → 1.5.2

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/dist/index.js CHANGED
@@ -2003,20 +2003,39 @@ 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
+ }
2006
2014
  var _kitMissQueues = {};
2007
2015
  var _kitMissTimers = {};
2008
- function _queueKitMiss(prefix, iconBaseName) {
2009
- if (typeof window === "undefined") return;
2016
+ function _resolveRegistry(prefix) {
2017
+ if (_kitRegistry[prefix]) return _kitRegistry[prefix];
2010
2018
  const kits = window.CopyIconsKit || {};
2011
- let kitId = null;
2012
2019
  for (const kId in kits) {
2013
2020
  const kit = kits[kId];
2014
2021
  if (kit.config && kit.config.prefix === prefix) {
2015
- kitId = kId;
2016
- break;
2022
+ const entry = { kitId: kId, api: kit.config.api || "https://api.viconic.dev" };
2023
+ _kitRegistry[prefix] = entry;
2024
+ return entry;
2017
2025
  }
2018
2026
  }
2019
- if (!kitId) return;
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;
2020
2039
  if (!_kitMissQueues[kitId]) _kitMissQueues[kitId] = /* @__PURE__ */ new Set();
2021
2040
  _kitMissQueues[kitId].add(iconBaseName);
2022
2041
  if (_kitMissTimers[kitId]) return;
@@ -2025,34 +2044,40 @@ function _queueKitMiss(prefix, iconBaseName) {
2025
2044
  const names = [..._kitMissQueues[kitId] || []];
2026
2045
  delete _kitMissQueues[kitId];
2027
2046
  if (!names.length) return;
2028
- const kit = (window.CopyIconsKit || {})[kitId];
2029
- if (!kit || !kit.config) return;
2030
- const api = kit.config.api || "https://api.viconic.dev";
2031
2047
  fetch(`${api}/api/v1/kits/${kitId}/icons/?icons=${names.join(",")}`).then((r) => r.ok ? r.json() : null).then((bj) => {
2032
2048
  if (!bj || !bj.icons) return;
2033
2049
  const W = window.__viconic = window.__viconic || {};
2034
2050
  W.icons = W.icons || {};
2035
- const pfx = kit.config.prefix;
2036
2051
  for (const n in bj.icons) {
2037
2052
  if (!Object.prototype.hasOwnProperty.call(bj.icons, n)) continue;
2038
2053
  const d = bj.icons[n];
2039
2054
  const svg = d.svg || "";
2040
2055
  if (!svg || !svg.includes("<")) continue;
2041
- W.icons[`@${pfx}/${n}`] = svg;
2042
- W.icons[`${pfx}:${n}`] = svg;
2043
- W.icons[`${pfx}/${n}`] = svg;
2056
+ W.icons[`@${prefix}/${n}`] = svg;
2057
+ W.icons[`${prefix}:${n}`] = svg;
2058
+ W.icons[`${prefix}/${n}`] = svg;
2044
2059
  W.icons[n] = W.icons[n] || svg;
2045
2060
  }
2046
2061
  try {
2047
- document.dispatchEvent(new CustomEvent("viconic:ready", { detail: { prefix: pfx, kitId } }));
2062
+ document.dispatchEvent(new CustomEvent("viconic:ready", { detail: { prefix, kitId } }));
2048
2063
  } catch (e) {
2049
2064
  }
2050
2065
  }).catch(() => {
2051
2066
  });
2052
- }, 0);
2067
+ }, 150);
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
+ }
2053
2078
  }
2054
2079
  function initViconic(options = {}) {
2055
- const { kitId, cdnBase = "cdn.viconic.dev", version } = options;
2080
+ const { kitId, cdnBase = "cdn.viconic.dev", version, prefix: explicitPrefix, api = "https://api.viconic.dev" } = options;
2056
2081
  if (typeof window === "undefined") return;
2057
2082
  if (!kitId) {
2058
2083
  console.warn("[Viconic] initViconic requires a kitId");
@@ -2060,6 +2085,13 @@ function initViconic(options = {}) {
2060
2085
  }
2061
2086
  if (_initializedKits.has(kitId)) return;
2062
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
+ }
2063
2095
  const scriptId = `viconic-kit-${kitId}`;
2064
2096
  if (document.getElementById(scriptId)) return;
2065
2097
  const script = document.createElement("script");
@@ -2069,6 +2101,15 @@ function initViconic(options = {}) {
2069
2101
  const vQuery = version === "dev" ? Date.now() : version;
2070
2102
  url += `?v=${vQuery}`;
2071
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
+ };
2072
2113
  script.src = url;
2073
2114
  script.async = true;
2074
2115
  document.head.appendChild(script);
@@ -2127,18 +2168,13 @@ var ViconicIcon = ({ name, className, style, size, color, ...props }) => {
2127
2168
  }
2128
2169
  }
2129
2170
  document.addEventListener("viconic:ready", tryInjectFromEvent);
2130
- const fallbackTimer = setTimeout(() => {
2131
- if (isInjected()) return;
2132
- tryInjectFromEvent();
2133
- if (!isInjected() && isKitIcon && prefixMatch) {
2134
- const prefix = prefixMatch[1];
2135
- const iconBaseName = prefixMatch[2];
2136
- _queueKitMiss(prefix, iconBaseName);
2137
- }
2138
- }, 50);
2171
+ if (!isInjected() && isKitIcon && prefixMatch) {
2172
+ const prefix = prefixMatch[1];
2173
+ const iconBaseName = prefixMatch[2];
2174
+ _queueKitMiss(prefix, iconBaseName);
2175
+ }
2139
2176
  return () => {
2140
2177
  document.removeEventListener("viconic:ready", tryInjectFromEvent);
2141
- clearTimeout(fallbackTimer);
2142
2178
  };
2143
2179
  }, [name, className, size, color, style]);
2144
2180
  const combinedStyle = {
package/dist/index.mjs CHANGED
@@ -1968,20 +1968,39 @@ 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
+ }
1971
1979
  var _kitMissQueues = {};
1972
1980
  var _kitMissTimers = {};
1973
- function _queueKitMiss(prefix, iconBaseName) {
1974
- if (typeof window === "undefined") return;
1981
+ function _resolveRegistry(prefix) {
1982
+ if (_kitRegistry[prefix]) return _kitRegistry[prefix];
1975
1983
  const kits = window.CopyIconsKit || {};
1976
- let kitId = null;
1977
1984
  for (const kId in kits) {
1978
1985
  const kit = kits[kId];
1979
1986
  if (kit.config && kit.config.prefix === prefix) {
1980
- kitId = kId;
1981
- break;
1987
+ const entry = { kitId: kId, api: kit.config.api || "https://api.viconic.dev" };
1988
+ _kitRegistry[prefix] = entry;
1989
+ return entry;
1982
1990
  }
1983
1991
  }
1984
- if (!kitId) return;
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;
1985
2004
  if (!_kitMissQueues[kitId]) _kitMissQueues[kitId] = /* @__PURE__ */ new Set();
1986
2005
  _kitMissQueues[kitId].add(iconBaseName);
1987
2006
  if (_kitMissTimers[kitId]) return;
@@ -1990,34 +2009,40 @@ function _queueKitMiss(prefix, iconBaseName) {
1990
2009
  const names = [..._kitMissQueues[kitId] || []];
1991
2010
  delete _kitMissQueues[kitId];
1992
2011
  if (!names.length) return;
1993
- const kit = (window.CopyIconsKit || {})[kitId];
1994
- if (!kit || !kit.config) return;
1995
- const api = kit.config.api || "https://api.viconic.dev";
1996
2012
  fetch(`${api}/api/v1/kits/${kitId}/icons/?icons=${names.join(",")}`).then((r) => r.ok ? r.json() : null).then((bj) => {
1997
2013
  if (!bj || !bj.icons) return;
1998
2014
  const W = window.__viconic = window.__viconic || {};
1999
2015
  W.icons = W.icons || {};
2000
- const pfx = kit.config.prefix;
2001
2016
  for (const n in bj.icons) {
2002
2017
  if (!Object.prototype.hasOwnProperty.call(bj.icons, n)) continue;
2003
2018
  const d = bj.icons[n];
2004
2019
  const svg = d.svg || "";
2005
2020
  if (!svg || !svg.includes("<")) continue;
2006
- W.icons[`@${pfx}/${n}`] = svg;
2007
- W.icons[`${pfx}:${n}`] = svg;
2008
- W.icons[`${pfx}/${n}`] = svg;
2021
+ W.icons[`@${prefix}/${n}`] = svg;
2022
+ W.icons[`${prefix}:${n}`] = svg;
2023
+ W.icons[`${prefix}/${n}`] = svg;
2009
2024
  W.icons[n] = W.icons[n] || svg;
2010
2025
  }
2011
2026
  try {
2012
- document.dispatchEvent(new CustomEvent("viconic:ready", { detail: { prefix: pfx, kitId } }));
2027
+ document.dispatchEvent(new CustomEvent("viconic:ready", { detail: { prefix, kitId } }));
2013
2028
  } catch (e) {
2014
2029
  }
2015
2030
  }).catch(() => {
2016
2031
  });
2017
- }, 0);
2032
+ }, 150);
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
+ }
2018
2043
  }
2019
2044
  function initViconic(options = {}) {
2020
- const { kitId, cdnBase = "cdn.viconic.dev", version } = options;
2045
+ const { kitId, cdnBase = "cdn.viconic.dev", version, prefix: explicitPrefix, api = "https://api.viconic.dev" } = options;
2021
2046
  if (typeof window === "undefined") return;
2022
2047
  if (!kitId) {
2023
2048
  console.warn("[Viconic] initViconic requires a kitId");
@@ -2025,6 +2050,13 @@ function initViconic(options = {}) {
2025
2050
  }
2026
2051
  if (_initializedKits.has(kitId)) return;
2027
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
+ }
2028
2060
  const scriptId = `viconic-kit-${kitId}`;
2029
2061
  if (document.getElementById(scriptId)) return;
2030
2062
  const script = document.createElement("script");
@@ -2034,6 +2066,15 @@ function initViconic(options = {}) {
2034
2066
  const vQuery = version === "dev" ? Date.now() : version;
2035
2067
  url += `?v=${vQuery}`;
2036
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
+ };
2037
2078
  script.src = url;
2038
2079
  script.async = true;
2039
2080
  document.head.appendChild(script);
@@ -2092,18 +2133,13 @@ var ViconicIcon = ({ name, className, style, size, color, ...props }) => {
2092
2133
  }
2093
2134
  }
2094
2135
  document.addEventListener("viconic:ready", tryInjectFromEvent);
2095
- const fallbackTimer = setTimeout(() => {
2096
- if (isInjected()) return;
2097
- tryInjectFromEvent();
2098
- if (!isInjected() && isKitIcon && prefixMatch) {
2099
- const prefix = prefixMatch[1];
2100
- const iconBaseName = prefixMatch[2];
2101
- _queueKitMiss(prefix, iconBaseName);
2102
- }
2103
- }, 50);
2136
+ if (!isInjected() && isKitIcon && prefixMatch) {
2137
+ const prefix = prefixMatch[1];
2138
+ const iconBaseName = prefixMatch[2];
2139
+ _queueKitMiss(prefix, iconBaseName);
2140
+ }
2104
2141
  return () => {
2105
2142
  document.removeEventListener("viconic:ready", tryInjectFromEvent);
2106
- clearTimeout(fallbackTimer);
2107
2143
  };
2108
2144
  }, [name, className, size, color, style]);
2109
2145
  const combinedStyle = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "viconic-react-icons",
3
- "version": "1.5.0",
3
+ "version": "1.5.2",
4
4
  "description": "Viconic Smart Icons loader for React — supports Kit and 200k+ system icons",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
package/src/index.jsx CHANGED
@@ -36,58 +36,100 @@ 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
+
39
60
  // ============================================
40
61
  // DEBOUNCED BATCH FETCH for missing kit icons
41
- // All ViconicIcon mounts queue their miss here;
42
- // a single setTimeout(0) fires ONE batch request
43
- // per kit instead of N individual kit.reload() calls.
44
62
  // ============================================
45
63
  const _kitMissQueues = {}; // kitId -> Set of icon names
46
64
  const _kitMissTimers = {}; // kitId -> timer handle
47
65
 
48
- function _queueKitMiss(prefix, iconBaseName) {
49
- if (typeof window === 'undefined') return;
50
- // Find kit by prefix
66
+ function _resolveRegistry(prefix) {
67
+ if (_kitRegistry[prefix]) return _kitRegistry[prefix];
68
+ // Fallback: check CopyIconsKit
51
69
  const kits = window.CopyIconsKit || {};
52
- let kitId = null;
53
70
  for (const kId in kits) {
54
71
  const kit = kits[kId];
55
- if (kit.config && kit.config.prefix === prefix) { kitId = kId; break; }
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
+ }
56
77
  }
57
- if (!kitId) return;
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;
58
92
  if (!_kitMissQueues[kitId]) _kitMissQueues[kitId] = new Set();
59
93
  _kitMissQueues[kitId].add(iconBaseName);
60
- if (_kitMissTimers[kitId]) return; // already scheduled
94
+ if (_kitMissTimers[kitId]) return; // already scheduled, will pick up new additions
95
+ // 150ms debounce: long enough to collect all icons across a full React render cycle
61
96
  _kitMissTimers[kitId] = setTimeout(() => {
62
97
  delete _kitMissTimers[kitId];
63
98
  const names = [...(_kitMissQueues[kitId] || [])];
64
99
  delete _kitMissQueues[kitId];
65
100
  if (!names.length) return;
66
- const kit = (window.CopyIconsKit || {})[kitId];
67
- if (!kit || !kit.config) return;
68
- const api = kit.config.api || 'https://api.viconic.dev';
69
101
  fetch(`${api}/api/v1/kits/${kitId}/icons/?icons=${names.join(',')}`)
70
102
  .then(r => r.ok ? r.json() : null)
71
103
  .then(bj => {
72
104
  if (!bj || !bj.icons) return;
73
105
  const W = (window.__viconic = window.__viconic || {});
74
106
  W.icons = W.icons || {};
75
- const pfx = kit.config.prefix;
76
107
  for (const n in bj.icons) {
77
108
  if (!Object.prototype.hasOwnProperty.call(bj.icons, n)) continue;
78
109
  const d = bj.icons[n];
79
110
  const svg = d.svg || '';
80
111
  if (!svg || !svg.includes('<')) continue;
81
- W.icons[`@${pfx}/${n}`] = svg;
82
- W.icons[`${pfx}:${n}`] = svg;
83
- W.icons[`${pfx}/${n}`] = svg;
112
+ W.icons[`@${prefix}/${n}`] = svg;
113
+ W.icons[`${prefix}:${n}`] = svg;
114
+ W.icons[`${prefix}/${n}`] = svg;
84
115
  W.icons[n] = W.icons[n] || svg;
85
116
  }
86
- // Fire viconic:ready so all waiting ViconicIcon components inject
87
- try { document.dispatchEvent(new CustomEvent('viconic:ready', { detail: { prefix: pfx, kitId } })); } catch(e) {}
117
+ try { document.dispatchEvent(new CustomEvent('viconic:ready', { detail: { prefix, kitId } })); } catch(e) {}
88
118
  })
89
119
  .catch(() => {});
90
- }, 0); // setTimeout(0): collect ALL icon misses from current render cycle
120
+ }, 150);
121
+ }
122
+
123
+ function _queueKitMiss(prefix, iconBaseName) {
124
+ if (typeof window === 'undefined') return;
125
+ const entry = _resolveRegistry(prefix);
126
+ if (entry) {
127
+ _dispatchBatchFetch(prefix, iconBaseName, entry);
128
+ } else {
129
+ // Registry not ready yet — buffer until loader fires
130
+ if (!_pendingMisses[prefix]) _pendingMisses[prefix] = new Set();
131
+ _pendingMisses[prefix].add(iconBaseName);
132
+ }
91
133
  }
92
134
 
93
135
  /**
@@ -107,7 +149,7 @@ function _queueKitMiss(prefix, iconBaseName) {
107
149
  * initViconic({ kitId: 'another-kit-uuid', version: '1.0' });
108
150
  */
109
151
  export function initViconic(options = {}) {
110
- const { kitId, cdnBase = 'cdn.viconic.dev', version } = options;
152
+ const { kitId, cdnBase = 'cdn.viconic.dev', version, prefix: explicitPrefix, api = 'https://api.viconic.dev' } = options;
111
153
  if (typeof window === 'undefined') return; // SSR guard
112
154
  if (!kitId) {
113
155
  console.warn('[Viconic] initViconic requires a kitId');
@@ -116,6 +158,18 @@ export function initViconic(options = {}) {
116
158
  if (_initializedKits.has(kitId)) return; // Already initialized
117
159
  _initializedKits.add(kitId);
118
160
 
161
+ // Register synchronously so _queueKitMiss can find kitId immediately,
162
+ // even before the async loader.js script has loaded and populated CopyIconsKit.
163
+ // If prefix is not known yet, we'll also register once CopyIconsKit fires.
164
+ if (explicitPrefix) {
165
+ _kitRegistry[explicitPrefix] = { kitId, api };
166
+ }
167
+ // Also register by kitId so we can backfill prefix once loader fires
168
+ if (typeof window !== 'undefined') {
169
+ window.__viconicKitIds = window.__viconicKitIds || {};
170
+ window.__viconicKitIds[kitId] = { api };
171
+ }
172
+
119
173
  const scriptId = `viconic-kit-${kitId}`;
120
174
  if (document.getElementById(scriptId)) return; // Script already in DOM
121
175
 
@@ -129,6 +183,18 @@ export function initViconic(options = {}) {
129
183
  url += `?v=${vQuery}`;
130
184
  }
131
185
 
186
+ // Once loader.js runs and registers CopyIconsKit, backfill _kitRegistry and flush pending misses
187
+ script.onload = () => {
188
+ const kits = window.CopyIconsKit || {};
189
+ const kit = kits[kitId];
190
+ if (kit && kit.config && kit.config.prefix) {
191
+ const pfx = kit.config.prefix;
192
+ _kitRegistry[pfx] = { kitId, api: kit.config.api || api };
193
+ // Flush any misses buffered before the loader was ready
194
+ _flushPendingMisses(pfx);
195
+ }
196
+ };
197
+
132
198
  script.src = url;
133
199
  script.async = true;
134
200
  document.head.appendChild(script);
@@ -223,21 +289,17 @@ export const ViconicIcon = ({ name, className, style, size, color, ...props }) =
223
289
 
224
290
  document.addEventListener('viconic:ready', tryInjectFromEvent);
225
291
 
226
- // --- PATH 5: Short-deadline fallback (50ms) — queue a batch fetch for all missing kit icons ---
227
- const fallbackTimer = setTimeout(() => {
228
- if (isInjected()) return;
229
- tryInjectFromEvent();
230
- if (!isInjected() && isKitIcon && prefixMatch) {
231
- const prefix = prefixMatch[1];
232
- const iconBaseName = prefixMatch[2];
233
- // Use batch queue instead of kit.reload() to avoid N separate API calls
234
- _queueKitMiss(prefix, iconBaseName);
235
- }
236
- }, 50);
292
+ // --- PATH 5: Immediate queue for missing kit icons ---
293
+ // Call _queueKitMiss immediately (no per-component delay) so all icons from
294
+ // the same render cycle are collected into the same debounced batch request.
295
+ if (!isInjected() && isKitIcon && prefixMatch) {
296
+ const prefix = prefixMatch[1];
297
+ const iconBaseName = prefixMatch[2];
298
+ _queueKitMiss(prefix, iconBaseName);
299
+ }
237
300
 
238
301
  return () => {
239
302
  document.removeEventListener('viconic:ready', tryInjectFromEvent);
240
- clearTimeout(fallbackTimer);
241
303
  };
242
304
  }, [name, className, size, color, style]);
243
305