viconic-react-icons 1.5.6 → 1.5.7
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 +41 -145
- package/dist/index.mjs +41 -145
- package/package.json +1 -1
- package/src/index.jsx +69 -215
package/dist/index.js
CHANGED
|
@@ -1992,8 +1992,7 @@ var import_react = __toESM(require("react"));
|
|
|
1992
1992
|
if (c && c.d && Date.now() - c.t < TTL) {
|
|
1993
1993
|
for (const n in c.d) {
|
|
1994
1994
|
if (!Object.prototype.hasOwnProperty.call(c.d, n)) continue;
|
|
1995
|
-
|
|
1996
|
-
if (!W.icons[n]) W.icons[n] = svg;
|
|
1995
|
+
if (!W.icons[n]) W.icons[n] = c.d[n];
|
|
1997
1996
|
}
|
|
1998
1997
|
}
|
|
1999
1998
|
} catch (e) {
|
|
@@ -2003,101 +2002,16 @@ var import_react = __toESM(require("react"));
|
|
|
2003
2002
|
}
|
|
2004
2003
|
})();
|
|
2005
2004
|
var _initializedKits = /* @__PURE__ */ new Set();
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
}
|
|
2014
|
-
var _kitMissQueues = {};
|
|
2015
|
-
var _kitMissTimers = {};
|
|
2016
|
-
var _kitQueued = {};
|
|
2017
|
-
function _resolveRegistry(prefix) {
|
|
2018
|
-
if (_kitRegistry[prefix]) return _kitRegistry[prefix];
|
|
2019
|
-
const kits = window.CopyIconsKit || {};
|
|
2020
|
-
for (const kId in kits) {
|
|
2021
|
-
const kit = kits[kId];
|
|
2022
|
-
if (kit.config && kit.config.prefix === prefix) {
|
|
2023
|
-
const entry = { kitId: kId, api: kit.config.api || "https://api.viconic.dev" };
|
|
2024
|
-
_kitRegistry[prefix] = entry;
|
|
2025
|
-
return entry;
|
|
2026
|
-
}
|
|
2027
|
-
}
|
|
2028
|
-
return null;
|
|
2029
|
-
}
|
|
2030
|
-
function _flushPendingMisses(prefix) {
|
|
2031
|
-
const pending = _pendingMisses[prefix];
|
|
2032
|
-
if (!pending || !pending.size) return;
|
|
2033
|
-
const entry = _resolveRegistry(prefix);
|
|
2034
|
-
if (!entry) return;
|
|
2035
|
-
delete _pendingMisses[prefix];
|
|
2036
|
-
pending.forEach((name) => _dispatchBatchFetch(prefix, name, entry));
|
|
2037
|
-
}
|
|
2038
|
-
function _dispatchBatchFetch(prefix, iconBaseName, entry) {
|
|
2039
|
-
const { kitId, api } = entry;
|
|
2040
|
-
if (!_kitQueued[kitId]) _kitQueued[kitId] = /* @__PURE__ */ new Set();
|
|
2041
|
-
if (_kitQueued[kitId].has(iconBaseName)) return;
|
|
2042
|
-
_kitQueued[kitId].add(iconBaseName);
|
|
2043
|
-
if (!_kitMissQueues[kitId]) _kitMissQueues[kitId] = /* @__PURE__ */ new Set();
|
|
2044
|
-
_kitMissQueues[kitId].add(iconBaseName);
|
|
2045
|
-
if (_kitMissTimers[kitId]) return;
|
|
2046
|
-
_kitMissTimers[kitId] = setTimeout(() => {
|
|
2047
|
-
delete _kitMissTimers[kitId];
|
|
2048
|
-
const names = [..._kitMissQueues[kitId] || []];
|
|
2049
|
-
delete _kitMissQueues[kitId];
|
|
2050
|
-
if (!names.length) return;
|
|
2051
|
-
fetch(`${api}/api/v1/kits/${kitId}/icons/?icons=${names.join(",")}`).then((r) => r.ok ? r.json() : null).then((bj) => {
|
|
2052
|
-
if (!bj || !bj.icons) return;
|
|
2053
|
-
const W = window.__viconic = window.__viconic || {};
|
|
2054
|
-
W.icons = W.icons || {};
|
|
2055
|
-
const cdnFetches = [];
|
|
2056
|
-
for (const n in bj.icons) {
|
|
2057
|
-
if (!Object.prototype.hasOwnProperty.call(bj.icons, n)) continue;
|
|
2058
|
-
const d = bj.icons[n];
|
|
2059
|
-
const svg = d.svg || "";
|
|
2060
|
-
if (svg && svg.includes("<")) {
|
|
2061
|
-
W.icons[`@${prefix}/${n}`] = svg;
|
|
2062
|
-
W.icons[`${prefix}:${n}`] = svg;
|
|
2063
|
-
W.icons[`${prefix}/${n}`] = svg;
|
|
2064
|
-
W.icons[n] = W.icons[n] || svg;
|
|
2065
|
-
} else if (d.cdn_url) {
|
|
2066
|
-
cdnFetches.push(
|
|
2067
|
-
fetch(d.cdn_url).then((r) => r.ok ? r.text() : "").then((s) => {
|
|
2068
|
-
if (s && s.includes("<")) {
|
|
2069
|
-
W.icons[`@${prefix}/${n}`] = s;
|
|
2070
|
-
W.icons[`${prefix}:${n}`] = s;
|
|
2071
|
-
W.icons[`${prefix}/${n}`] = s;
|
|
2072
|
-
W.icons[n] = W.icons[n] || s;
|
|
2073
|
-
}
|
|
2074
|
-
}).catch(() => {
|
|
2075
|
-
})
|
|
2076
|
-
);
|
|
2077
|
-
}
|
|
2078
|
-
}
|
|
2079
|
-
Promise.all(cdnFetches).then(() => {
|
|
2080
|
-
try {
|
|
2081
|
-
document.dispatchEvent(new CustomEvent("viconic:ready", { detail: { prefix, kitId } }));
|
|
2082
|
-
} catch (e) {
|
|
2083
|
-
}
|
|
2084
|
-
});
|
|
2085
|
-
}).catch(() => {
|
|
2086
|
-
});
|
|
2087
|
-
}, 150);
|
|
2088
|
-
}
|
|
2089
|
-
function _queueKitMiss(prefix, iconBaseName) {
|
|
2090
|
-
if (typeof window === "undefined") return;
|
|
2091
|
-
const entry = _resolveRegistry(prefix);
|
|
2092
|
-
if (entry) {
|
|
2093
|
-
_dispatchBatchFetch(prefix, iconBaseName, entry);
|
|
2094
|
-
} else {
|
|
2095
|
-
if (!_pendingMisses[prefix]) _pendingMisses[prefix] = /* @__PURE__ */ new Set();
|
|
2096
|
-
_pendingMisses[prefix].add(iconBaseName);
|
|
2097
|
-
}
|
|
2005
|
+
function _isQueued(kitId, iconName) {
|
|
2006
|
+
if (typeof window === "undefined") return false;
|
|
2007
|
+
const q = window.__viconicQueued = window.__viconicQueued || {};
|
|
2008
|
+
const k = kitId + ":" + iconName;
|
|
2009
|
+
if (q[k]) return true;
|
|
2010
|
+
q[k] = 1;
|
|
2011
|
+
return false;
|
|
2098
2012
|
}
|
|
2099
2013
|
function initViconic(options = {}) {
|
|
2100
|
-
const { kitId, cdnBase = "cdn.viconic.dev", version
|
|
2014
|
+
const { kitId, cdnBase = "cdn.viconic.dev", version } = options;
|
|
2101
2015
|
if (typeof window === "undefined") return;
|
|
2102
2016
|
if (!kitId) {
|
|
2103
2017
|
console.warn("[Viconic] initViconic requires a kitId");
|
|
@@ -2105,31 +2019,14 @@ function initViconic(options = {}) {
|
|
|
2105
2019
|
}
|
|
2106
2020
|
if (_initializedKits.has(kitId)) return;
|
|
2107
2021
|
_initializedKits.add(kitId);
|
|
2108
|
-
if (explicitPrefix) {
|
|
2109
|
-
_kitRegistry[explicitPrefix] = { kitId, api };
|
|
2110
|
-
}
|
|
2111
|
-
if (typeof window !== "undefined") {
|
|
2112
|
-
window.__viconicKitIds = window.__viconicKitIds || {};
|
|
2113
|
-
window.__viconicKitIds[kitId] = { api };
|
|
2114
|
-
}
|
|
2115
2022
|
const scriptId = `viconic-kit-${kitId}`;
|
|
2116
2023
|
if (document.getElementById(scriptId)) return;
|
|
2117
2024
|
const script = document.createElement("script");
|
|
2118
2025
|
script.id = scriptId;
|
|
2119
2026
|
let url = `https://${cdnBase}/kits/${kitId}/loader.js`;
|
|
2120
2027
|
if (version) {
|
|
2121
|
-
|
|
2122
|
-
url += `?v=${vQuery}`;
|
|
2028
|
+
url += `?v=${version === "dev" ? Date.now() : version}`;
|
|
2123
2029
|
}
|
|
2124
|
-
script.onload = () => {
|
|
2125
|
-
const kits = window.CopyIconsKit || {};
|
|
2126
|
-
const kit = kits[kitId];
|
|
2127
|
-
if (kit && kit.config && kit.config.prefix) {
|
|
2128
|
-
const pfx = kit.config.prefix;
|
|
2129
|
-
_kitRegistry[pfx] = { kitId, api: kit.config.api || api };
|
|
2130
|
-
_flushPendingMisses(pfx);
|
|
2131
|
-
}
|
|
2132
|
-
};
|
|
2133
2030
|
script.src = url;
|
|
2134
2031
|
script.async = true;
|
|
2135
2032
|
document.head.appendChild(script);
|
|
@@ -2150,51 +2047,50 @@ var ViconicIcon = ({ name, className, style, size, color, ...props }) => {
|
|
|
2150
2047
|
function isInjected() {
|
|
2151
2048
|
return el.classList.contains("vi-ok") || el.classList.contains("svg-loaded");
|
|
2152
2049
|
}
|
|
2153
|
-
|
|
2050
|
+
function tryInjectFromCache() {
|
|
2051
|
+
if (isInjected()) return false;
|
|
2154
2052
|
const W = window.__viconic;
|
|
2155
|
-
if (W
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2053
|
+
if (!W || !W.icons) return false;
|
|
2054
|
+
const baseName = prefixMatch ? prefixMatch[2] : null;
|
|
2055
|
+
const svg = baseName && W.icons[baseName] || name && W.icons[name] || null;
|
|
2056
|
+
if (svg) {
|
|
2057
|
+
el.innerHTML = svg;
|
|
2058
|
+
el.classList.add("vi-ok", "svg-loaded");
|
|
2059
|
+
return true;
|
|
2162
2060
|
}
|
|
2061
|
+
return false;
|
|
2163
2062
|
}
|
|
2164
|
-
if (
|
|
2063
|
+
if (tryInjectFromCache()) return;
|
|
2064
|
+
if (!isKitIcon) {
|
|
2165
2065
|
if (window.CopyIcons && window.CopyIcons.forceProcess) {
|
|
2166
2066
|
window.CopyIcons.forceProcess(el);
|
|
2067
|
+
} else if (el._u) {
|
|
2068
|
+
el._u();
|
|
2167
2069
|
}
|
|
2168
2070
|
}
|
|
2169
|
-
if (!isInjected() && !isKitIcon && el._u) {
|
|
2170
|
-
el._u();
|
|
2171
|
-
}
|
|
2172
2071
|
if (isInjected()) return;
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2072
|
+
if (isKitIcon && prefixMatch) {
|
|
2073
|
+
const kitId = (() => {
|
|
2074
|
+
const kits = window.CopyIconsKit || {};
|
|
2075
|
+
for (const kId in kits) {
|
|
2076
|
+
if (kits[kId].config && kits[kId].config.prefix === prefixMatch[1]) return kId;
|
|
2077
|
+
}
|
|
2078
|
+
return prefixMatch[1];
|
|
2079
|
+
})();
|
|
2080
|
+
if (!_isQueued(kitId, prefixMatch[2])) {
|
|
2081
|
+
if (el._u) {
|
|
2082
|
+
el._u();
|
|
2183
2083
|
}
|
|
2184
|
-
}
|
|
2185
|
-
if (!isKitIcon && el._u) el._u();
|
|
2186
|
-
if (!isKitIcon && window.CopyIcons && window.CopyIcons.forceProcess) {
|
|
2187
|
-
window.CopyIcons.forceProcess(el);
|
|
2188
2084
|
}
|
|
2189
2085
|
}
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
_queueKitMiss(prefix, iconBaseName);
|
|
2086
|
+
function onReady() {
|
|
2087
|
+
if (tryInjectFromCache()) {
|
|
2088
|
+
document.removeEventListener("viconic:ready", onReady);
|
|
2089
|
+
}
|
|
2195
2090
|
}
|
|
2091
|
+
document.addEventListener("viconic:ready", onReady);
|
|
2196
2092
|
return () => {
|
|
2197
|
-
document.removeEventListener("viconic:ready",
|
|
2093
|
+
document.removeEventListener("viconic:ready", onReady);
|
|
2198
2094
|
};
|
|
2199
2095
|
}, [name, className, size, color, style]);
|
|
2200
2096
|
const combinedStyle = {
|
package/dist/index.mjs
CHANGED
|
@@ -1957,8 +1957,7 @@ import React, { useEffect, useRef } from "react";
|
|
|
1957
1957
|
if (c && c.d && Date.now() - c.t < TTL) {
|
|
1958
1958
|
for (const n in c.d) {
|
|
1959
1959
|
if (!Object.prototype.hasOwnProperty.call(c.d, n)) continue;
|
|
1960
|
-
|
|
1961
|
-
if (!W.icons[n]) W.icons[n] = svg;
|
|
1960
|
+
if (!W.icons[n]) W.icons[n] = c.d[n];
|
|
1962
1961
|
}
|
|
1963
1962
|
}
|
|
1964
1963
|
} catch (e) {
|
|
@@ -1968,101 +1967,16 @@ import React, { useEffect, useRef } from "react";
|
|
|
1968
1967
|
}
|
|
1969
1968
|
})();
|
|
1970
1969
|
var _initializedKits = /* @__PURE__ */ new Set();
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
}
|
|
1979
|
-
var _kitMissQueues = {};
|
|
1980
|
-
var _kitMissTimers = {};
|
|
1981
|
-
var _kitQueued = {};
|
|
1982
|
-
function _resolveRegistry(prefix) {
|
|
1983
|
-
if (_kitRegistry[prefix]) return _kitRegistry[prefix];
|
|
1984
|
-
const kits = window.CopyIconsKit || {};
|
|
1985
|
-
for (const kId in kits) {
|
|
1986
|
-
const kit = kits[kId];
|
|
1987
|
-
if (kit.config && kit.config.prefix === prefix) {
|
|
1988
|
-
const entry = { kitId: kId, api: kit.config.api || "https://api.viconic.dev" };
|
|
1989
|
-
_kitRegistry[prefix] = entry;
|
|
1990
|
-
return entry;
|
|
1991
|
-
}
|
|
1992
|
-
}
|
|
1993
|
-
return null;
|
|
1994
|
-
}
|
|
1995
|
-
function _flushPendingMisses(prefix) {
|
|
1996
|
-
const pending = _pendingMisses[prefix];
|
|
1997
|
-
if (!pending || !pending.size) return;
|
|
1998
|
-
const entry = _resolveRegistry(prefix);
|
|
1999
|
-
if (!entry) return;
|
|
2000
|
-
delete _pendingMisses[prefix];
|
|
2001
|
-
pending.forEach((name) => _dispatchBatchFetch(prefix, name, entry));
|
|
2002
|
-
}
|
|
2003
|
-
function _dispatchBatchFetch(prefix, iconBaseName, entry) {
|
|
2004
|
-
const { kitId, api } = entry;
|
|
2005
|
-
if (!_kitQueued[kitId]) _kitQueued[kitId] = /* @__PURE__ */ new Set();
|
|
2006
|
-
if (_kitQueued[kitId].has(iconBaseName)) return;
|
|
2007
|
-
_kitQueued[kitId].add(iconBaseName);
|
|
2008
|
-
if (!_kitMissQueues[kitId]) _kitMissQueues[kitId] = /* @__PURE__ */ new Set();
|
|
2009
|
-
_kitMissQueues[kitId].add(iconBaseName);
|
|
2010
|
-
if (_kitMissTimers[kitId]) return;
|
|
2011
|
-
_kitMissTimers[kitId] = setTimeout(() => {
|
|
2012
|
-
delete _kitMissTimers[kitId];
|
|
2013
|
-
const names = [..._kitMissQueues[kitId] || []];
|
|
2014
|
-
delete _kitMissQueues[kitId];
|
|
2015
|
-
if (!names.length) return;
|
|
2016
|
-
fetch(`${api}/api/v1/kits/${kitId}/icons/?icons=${names.join(",")}`).then((r) => r.ok ? r.json() : null).then((bj) => {
|
|
2017
|
-
if (!bj || !bj.icons) return;
|
|
2018
|
-
const W = window.__viconic = window.__viconic || {};
|
|
2019
|
-
W.icons = W.icons || {};
|
|
2020
|
-
const cdnFetches = [];
|
|
2021
|
-
for (const n in bj.icons) {
|
|
2022
|
-
if (!Object.prototype.hasOwnProperty.call(bj.icons, n)) continue;
|
|
2023
|
-
const d = bj.icons[n];
|
|
2024
|
-
const svg = d.svg || "";
|
|
2025
|
-
if (svg && svg.includes("<")) {
|
|
2026
|
-
W.icons[`@${prefix}/${n}`] = svg;
|
|
2027
|
-
W.icons[`${prefix}:${n}`] = svg;
|
|
2028
|
-
W.icons[`${prefix}/${n}`] = svg;
|
|
2029
|
-
W.icons[n] = W.icons[n] || svg;
|
|
2030
|
-
} else if (d.cdn_url) {
|
|
2031
|
-
cdnFetches.push(
|
|
2032
|
-
fetch(d.cdn_url).then((r) => r.ok ? r.text() : "").then((s) => {
|
|
2033
|
-
if (s && s.includes("<")) {
|
|
2034
|
-
W.icons[`@${prefix}/${n}`] = s;
|
|
2035
|
-
W.icons[`${prefix}:${n}`] = s;
|
|
2036
|
-
W.icons[`${prefix}/${n}`] = s;
|
|
2037
|
-
W.icons[n] = W.icons[n] || s;
|
|
2038
|
-
}
|
|
2039
|
-
}).catch(() => {
|
|
2040
|
-
})
|
|
2041
|
-
);
|
|
2042
|
-
}
|
|
2043
|
-
}
|
|
2044
|
-
Promise.all(cdnFetches).then(() => {
|
|
2045
|
-
try {
|
|
2046
|
-
document.dispatchEvent(new CustomEvent("viconic:ready", { detail: { prefix, kitId } }));
|
|
2047
|
-
} catch (e) {
|
|
2048
|
-
}
|
|
2049
|
-
});
|
|
2050
|
-
}).catch(() => {
|
|
2051
|
-
});
|
|
2052
|
-
}, 150);
|
|
2053
|
-
}
|
|
2054
|
-
function _queueKitMiss(prefix, iconBaseName) {
|
|
2055
|
-
if (typeof window === "undefined") return;
|
|
2056
|
-
const entry = _resolveRegistry(prefix);
|
|
2057
|
-
if (entry) {
|
|
2058
|
-
_dispatchBatchFetch(prefix, iconBaseName, entry);
|
|
2059
|
-
} else {
|
|
2060
|
-
if (!_pendingMisses[prefix]) _pendingMisses[prefix] = /* @__PURE__ */ new Set();
|
|
2061
|
-
_pendingMisses[prefix].add(iconBaseName);
|
|
2062
|
-
}
|
|
1970
|
+
function _isQueued(kitId, iconName) {
|
|
1971
|
+
if (typeof window === "undefined") return false;
|
|
1972
|
+
const q = window.__viconicQueued = window.__viconicQueued || {};
|
|
1973
|
+
const k = kitId + ":" + iconName;
|
|
1974
|
+
if (q[k]) return true;
|
|
1975
|
+
q[k] = 1;
|
|
1976
|
+
return false;
|
|
2063
1977
|
}
|
|
2064
1978
|
function initViconic(options = {}) {
|
|
2065
|
-
const { kitId, cdnBase = "cdn.viconic.dev", version
|
|
1979
|
+
const { kitId, cdnBase = "cdn.viconic.dev", version } = options;
|
|
2066
1980
|
if (typeof window === "undefined") return;
|
|
2067
1981
|
if (!kitId) {
|
|
2068
1982
|
console.warn("[Viconic] initViconic requires a kitId");
|
|
@@ -2070,31 +1984,14 @@ function initViconic(options = {}) {
|
|
|
2070
1984
|
}
|
|
2071
1985
|
if (_initializedKits.has(kitId)) return;
|
|
2072
1986
|
_initializedKits.add(kitId);
|
|
2073
|
-
if (explicitPrefix) {
|
|
2074
|
-
_kitRegistry[explicitPrefix] = { kitId, api };
|
|
2075
|
-
}
|
|
2076
|
-
if (typeof window !== "undefined") {
|
|
2077
|
-
window.__viconicKitIds = window.__viconicKitIds || {};
|
|
2078
|
-
window.__viconicKitIds[kitId] = { api };
|
|
2079
|
-
}
|
|
2080
1987
|
const scriptId = `viconic-kit-${kitId}`;
|
|
2081
1988
|
if (document.getElementById(scriptId)) return;
|
|
2082
1989
|
const script = document.createElement("script");
|
|
2083
1990
|
script.id = scriptId;
|
|
2084
1991
|
let url = `https://${cdnBase}/kits/${kitId}/loader.js`;
|
|
2085
1992
|
if (version) {
|
|
2086
|
-
|
|
2087
|
-
url += `?v=${vQuery}`;
|
|
1993
|
+
url += `?v=${version === "dev" ? Date.now() : version}`;
|
|
2088
1994
|
}
|
|
2089
|
-
script.onload = () => {
|
|
2090
|
-
const kits = window.CopyIconsKit || {};
|
|
2091
|
-
const kit = kits[kitId];
|
|
2092
|
-
if (kit && kit.config && kit.config.prefix) {
|
|
2093
|
-
const pfx = kit.config.prefix;
|
|
2094
|
-
_kitRegistry[pfx] = { kitId, api: kit.config.api || api };
|
|
2095
|
-
_flushPendingMisses(pfx);
|
|
2096
|
-
}
|
|
2097
|
-
};
|
|
2098
1995
|
script.src = url;
|
|
2099
1996
|
script.async = true;
|
|
2100
1997
|
document.head.appendChild(script);
|
|
@@ -2115,51 +2012,50 @@ var ViconicIcon = ({ name, className, style, size, color, ...props }) => {
|
|
|
2115
2012
|
function isInjected() {
|
|
2116
2013
|
return el.classList.contains("vi-ok") || el.classList.contains("svg-loaded");
|
|
2117
2014
|
}
|
|
2118
|
-
|
|
2015
|
+
function tryInjectFromCache() {
|
|
2016
|
+
if (isInjected()) return false;
|
|
2119
2017
|
const W = window.__viconic;
|
|
2120
|
-
if (W
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2018
|
+
if (!W || !W.icons) return false;
|
|
2019
|
+
const baseName = prefixMatch ? prefixMatch[2] : null;
|
|
2020
|
+
const svg = baseName && W.icons[baseName] || name && W.icons[name] || null;
|
|
2021
|
+
if (svg) {
|
|
2022
|
+
el.innerHTML = svg;
|
|
2023
|
+
el.classList.add("vi-ok", "svg-loaded");
|
|
2024
|
+
return true;
|
|
2127
2025
|
}
|
|
2026
|
+
return false;
|
|
2128
2027
|
}
|
|
2129
|
-
if (
|
|
2028
|
+
if (tryInjectFromCache()) return;
|
|
2029
|
+
if (!isKitIcon) {
|
|
2130
2030
|
if (window.CopyIcons && window.CopyIcons.forceProcess) {
|
|
2131
2031
|
window.CopyIcons.forceProcess(el);
|
|
2032
|
+
} else if (el._u) {
|
|
2033
|
+
el._u();
|
|
2132
2034
|
}
|
|
2133
2035
|
}
|
|
2134
|
-
if (!isInjected() && !isKitIcon && el._u) {
|
|
2135
|
-
el._u();
|
|
2136
|
-
}
|
|
2137
2036
|
if (isInjected()) return;
|
|
2138
|
-
|
|
2139
|
-
|
|
2140
|
-
|
|
2141
|
-
|
|
2142
|
-
|
|
2143
|
-
|
|
2144
|
-
|
|
2145
|
-
|
|
2146
|
-
|
|
2147
|
-
|
|
2037
|
+
if (isKitIcon && prefixMatch) {
|
|
2038
|
+
const kitId = (() => {
|
|
2039
|
+
const kits = window.CopyIconsKit || {};
|
|
2040
|
+
for (const kId in kits) {
|
|
2041
|
+
if (kits[kId].config && kits[kId].config.prefix === prefixMatch[1]) return kId;
|
|
2042
|
+
}
|
|
2043
|
+
return prefixMatch[1];
|
|
2044
|
+
})();
|
|
2045
|
+
if (!_isQueued(kitId, prefixMatch[2])) {
|
|
2046
|
+
if (el._u) {
|
|
2047
|
+
el._u();
|
|
2148
2048
|
}
|
|
2149
|
-
}
|
|
2150
|
-
if (!isKitIcon && el._u) el._u();
|
|
2151
|
-
if (!isKitIcon && window.CopyIcons && window.CopyIcons.forceProcess) {
|
|
2152
|
-
window.CopyIcons.forceProcess(el);
|
|
2153
2049
|
}
|
|
2154
2050
|
}
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
_queueKitMiss(prefix, iconBaseName);
|
|
2051
|
+
function onReady() {
|
|
2052
|
+
if (tryInjectFromCache()) {
|
|
2053
|
+
document.removeEventListener("viconic:ready", onReady);
|
|
2054
|
+
}
|
|
2160
2055
|
}
|
|
2056
|
+
document.addEventListener("viconic:ready", onReady);
|
|
2161
2057
|
return () => {
|
|
2162
|
-
document.removeEventListener("viconic:ready",
|
|
2058
|
+
document.removeEventListener("viconic:ready", onReady);
|
|
2163
2059
|
};
|
|
2164
2060
|
}, [name, className, size, color, style]);
|
|
2165
2061
|
const combinedStyle = {
|
package/package.json
CHANGED
package/src/index.jsx
CHANGED
|
@@ -3,32 +3,27 @@ import './copyicons-smart-loader.js';
|
|
|
3
3
|
|
|
4
4
|
// ============================================
|
|
5
5
|
// PRE-LOAD KIT CACHE SYNCHRONOUSLY AT MODULE LEVEL
|
|
6
|
-
// Same architecture as kit loader: read localStorage before any render
|
|
7
|
-
// so icons are available instantly when components mount.
|
|
8
6
|
// ============================================
|
|
9
7
|
(function _preloadKitCache() {
|
|
10
8
|
if (typeof window === 'undefined' || typeof localStorage === 'undefined') return;
|
|
11
9
|
try {
|
|
12
10
|
const W = (window.__viconic = window.__viconic || {});
|
|
13
11
|
W.icons = W.icons || {};
|
|
14
|
-
const TTL = 3 * 24 * 60 * 60 * 1000;
|
|
12
|
+
const TTL = 3 * 24 * 60 * 60 * 1000;
|
|
15
13
|
for (let i = 0; i < localStorage.length; i++) {
|
|
16
14
|
const key = localStorage.key(i);
|
|
17
15
|
if (!key || !key.startsWith('viconic:')) continue;
|
|
18
16
|
try {
|
|
19
17
|
const c = JSON.parse(localStorage.getItem(key));
|
|
20
18
|
if (c && c.d && Date.now() - c.t < TTL) {
|
|
21
|
-
// Register all icon name variants into W.icons
|
|
22
19
|
for (const n in c.d) {
|
|
23
20
|
if (!Object.prototype.hasOwnProperty.call(c.d, n)) continue;
|
|
24
|
-
|
|
25
|
-
// Store by plain name so _u() can find it regardless of prefix
|
|
26
|
-
if (!W.icons[n]) W.icons[n] = svg;
|
|
21
|
+
if (!W.icons[n]) W.icons[n] = c.d[n];
|
|
27
22
|
}
|
|
28
23
|
}
|
|
29
|
-
} catch (e) {
|
|
24
|
+
} catch (e) {}
|
|
30
25
|
}
|
|
31
|
-
} catch (e) {
|
|
26
|
+
} catch (e) {}
|
|
32
27
|
})();
|
|
33
28
|
|
|
34
29
|
// ============================================
|
|
@@ -37,189 +32,58 @@ import './copyicons-smart-loader.js';
|
|
|
37
32
|
const _initializedKits = new Set();
|
|
38
33
|
|
|
39
34
|
// ============================================
|
|
40
|
-
//
|
|
41
|
-
//
|
|
42
|
-
// and by viconic:ready event handler.
|
|
35
|
+
// Window-level dedup set: survives HMR module reloads and Strict Mode remounts.
|
|
36
|
+
// Keyed by iconKey = "kitId:iconName". Cleared after loader fires viconic:ready.
|
|
43
37
|
// ============================================
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
-
const _kitQueued = {}; // kitId -> Set of icon names already queued (prevents Strict Mode double-queue)
|
|
66
|
-
|
|
67
|
-
function _resolveRegistry(prefix) {
|
|
68
|
-
if (_kitRegistry[prefix]) return _kitRegistry[prefix];
|
|
69
|
-
// Fallback: check CopyIconsKit
|
|
70
|
-
const kits = window.CopyIconsKit || {};
|
|
71
|
-
for (const kId in kits) {
|
|
72
|
-
const kit = kits[kId];
|
|
73
|
-
if (kit.config && kit.config.prefix === prefix) {
|
|
74
|
-
const entry = { kitId: kId, api: kit.config.api || 'https://api.viconic.dev' };
|
|
75
|
-
_kitRegistry[prefix] = entry;
|
|
76
|
-
return entry;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
return null;
|
|
38
|
+
function _isQueued(kitId, iconName) {
|
|
39
|
+
if (typeof window === 'undefined') return false;
|
|
40
|
+
const q = (window.__viconicQueued = window.__viconicQueued || {});
|
|
41
|
+
const k = kitId + ':' + iconName;
|
|
42
|
+
if (q[k]) return true;
|
|
43
|
+
q[k] = 1;
|
|
44
|
+
return false;
|
|
80
45
|
}
|
|
81
46
|
|
|
82
|
-
function
|
|
83
|
-
const pending = _pendingMisses[prefix];
|
|
84
|
-
if (!pending || !pending.size) return;
|
|
85
|
-
const entry = _resolveRegistry(prefix);
|
|
86
|
-
if (!entry) return;
|
|
87
|
-
delete _pendingMisses[prefix];
|
|
88
|
-
pending.forEach(name => _dispatchBatchFetch(prefix, name, entry));
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function _dispatchBatchFetch(prefix, iconBaseName, entry) {
|
|
92
|
-
const { kitId, api } = entry;
|
|
93
|
-
// Skip if already queued — prevents React Strict Mode double-invoke from making 2 requests
|
|
94
|
-
if (!_kitQueued[kitId]) _kitQueued[kitId] = new Set();
|
|
95
|
-
if (_kitQueued[kitId].has(iconBaseName)) return;
|
|
96
|
-
_kitQueued[kitId].add(iconBaseName);
|
|
97
|
-
if (!_kitMissQueues[kitId]) _kitMissQueues[kitId] = new Set();
|
|
98
|
-
_kitMissQueues[kitId].add(iconBaseName);
|
|
99
|
-
if (_kitMissTimers[kitId]) return; // already scheduled, will pick up new additions
|
|
100
|
-
// 150ms debounce: collect all icons across the full React render cycle
|
|
101
|
-
_kitMissTimers[kitId] = setTimeout(() => {
|
|
102
|
-
delete _kitMissTimers[kitId];
|
|
103
|
-
const names = [...(_kitMissQueues[kitId] || [])];
|
|
104
|
-
delete _kitMissQueues[kitId];
|
|
105
|
-
if (!names.length) return;
|
|
106
|
-
fetch(`${api}/api/v1/kits/${kitId}/icons/?icons=${names.join(',')}`)
|
|
107
|
-
.then(r => r.ok ? r.json() : null)
|
|
108
|
-
.then(bj => {
|
|
109
|
-
if (!bj || !bj.icons) return;
|
|
110
|
-
const W = (window.__viconic = window.__viconic || {});
|
|
111
|
-
W.icons = W.icons || {};
|
|
112
|
-
const cdnFetches = [];
|
|
113
|
-
for (const n in bj.icons) {
|
|
114
|
-
if (!Object.prototype.hasOwnProperty.call(bj.icons, n)) continue;
|
|
115
|
-
const d = bj.icons[n];
|
|
116
|
-
const svg = d.svg || '';
|
|
117
|
-
if (svg && svg.includes('<')) {
|
|
118
|
-
W.icons[`@${prefix}/${n}`] = svg;
|
|
119
|
-
W.icons[`${prefix}:${n}`] = svg;
|
|
120
|
-
W.icons[`${prefix}/${n}`] = svg;
|
|
121
|
-
W.icons[n] = W.icons[n] || svg;
|
|
122
|
-
} else if (d.cdn_url) {
|
|
123
|
-
// User-uploaded icon: fetch SVG from CDN and store in W.icons
|
|
124
|
-
// so loader refresh() finds it and doesn't fetch individually
|
|
125
|
-
cdnFetches.push(
|
|
126
|
-
fetch(d.cdn_url)
|
|
127
|
-
.then(r => r.ok ? r.text() : '')
|
|
128
|
-
.then(s => {
|
|
129
|
-
if (s && s.includes('<')) {
|
|
130
|
-
W.icons[`@${prefix}/${n}`] = s;
|
|
131
|
-
W.icons[`${prefix}:${n}`] = s;
|
|
132
|
-
W.icons[`${prefix}/${n}`] = s;
|
|
133
|
-
W.icons[n] = W.icons[n] || s;
|
|
134
|
-
}
|
|
135
|
-
})
|
|
136
|
-
.catch(() => {})
|
|
137
|
-
);
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
Promise.all(cdnFetches).then(() => {
|
|
141
|
-
try { document.dispatchEvent(new CustomEvent('viconic:ready', { detail: { prefix, kitId } })); } catch(e) {}
|
|
142
|
-
});
|
|
143
|
-
})
|
|
144
|
-
.catch(() => {});
|
|
145
|
-
}, 150);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
function _queueKitMiss(prefix, iconBaseName) {
|
|
47
|
+
function _clearQueued(kitId) {
|
|
149
48
|
if (typeof window === 'undefined') return;
|
|
150
|
-
const
|
|
151
|
-
if (
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
if (!_pendingMisses[prefix]) _pendingMisses[prefix] = new Set();
|
|
156
|
-
_pendingMisses[prefix].add(iconBaseName);
|
|
49
|
+
const q = window.__viconicQueued;
|
|
50
|
+
if (!q) return;
|
|
51
|
+
const prefix = kitId + ':';
|
|
52
|
+
for (const k in q) {
|
|
53
|
+
if (k.startsWith(prefix)) delete q[k];
|
|
157
54
|
}
|
|
158
55
|
}
|
|
159
56
|
|
|
160
57
|
/**
|
|
161
58
|
* Initialize a Viconic Kit in your React app.
|
|
162
59
|
* Injects the kit's loader.js script into <head>.
|
|
163
|
-
* Supports multiple kits — call once per kit.
|
|
164
60
|
*
|
|
165
61
|
* @param {Object} options
|
|
166
62
|
* @param {string} options.kitId - UUID of the Kit (required)
|
|
167
63
|
* @param {string} [options.cdnBase] - Custom CDN domain (default: cdn.viconic.dev)
|
|
168
|
-
*
|
|
169
|
-
* @example
|
|
170
|
-
* import { initViconic } from 'viconic-react-icons';
|
|
171
|
-
*
|
|
172
|
-
* initViconic({ kitId: '387a6161-cb39-411f-8f13-29a5813e4efd' });
|
|
173
|
-
* // Multiple kits:
|
|
174
|
-
* initViconic({ kitId: 'another-kit-uuid', version: '1.0' });
|
|
64
|
+
* @param {string} [options.version] - Version string for cache busting
|
|
175
65
|
*/
|
|
176
66
|
export function initViconic(options = {}) {
|
|
177
|
-
const { kitId, cdnBase = 'cdn.viconic.dev', version
|
|
178
|
-
if (typeof window === 'undefined') return;
|
|
67
|
+
const { kitId, cdnBase = 'cdn.viconic.dev', version } = options;
|
|
68
|
+
if (typeof window === 'undefined') return;
|
|
179
69
|
if (!kitId) {
|
|
180
70
|
console.warn('[Viconic] initViconic requires a kitId');
|
|
181
71
|
return;
|
|
182
72
|
}
|
|
183
|
-
if (_initializedKits.has(kitId)) return;
|
|
73
|
+
if (_initializedKits.has(kitId)) return;
|
|
184
74
|
_initializedKits.add(kitId);
|
|
185
75
|
|
|
186
|
-
// Register synchronously so _queueKitMiss can find kitId immediately,
|
|
187
|
-
// even before the async loader.js script has loaded and populated CopyIconsKit.
|
|
188
|
-
// If prefix is not known yet, we'll also register once CopyIconsKit fires.
|
|
189
|
-
if (explicitPrefix) {
|
|
190
|
-
_kitRegistry[explicitPrefix] = { kitId, api };
|
|
191
|
-
}
|
|
192
|
-
// Also register by kitId so we can backfill prefix once loader fires
|
|
193
|
-
if (typeof window !== 'undefined') {
|
|
194
|
-
window.__viconicKitIds = window.__viconicKitIds || {};
|
|
195
|
-
window.__viconicKitIds[kitId] = { api };
|
|
196
|
-
}
|
|
197
|
-
|
|
198
76
|
const scriptId = `viconic-kit-${kitId}`;
|
|
199
|
-
if (document.getElementById(scriptId)) return;
|
|
77
|
+
if (document.getElementById(scriptId)) return;
|
|
200
78
|
|
|
201
79
|
const script = document.createElement('script');
|
|
202
80
|
script.id = scriptId;
|
|
203
81
|
|
|
204
|
-
// Add cache busting for development or specific version updates
|
|
205
82
|
let url = `https://${cdnBase}/kits/${kitId}/loader.js`;
|
|
206
83
|
if (version) {
|
|
207
|
-
|
|
208
|
-
url += `?v=${vQuery}`;
|
|
84
|
+
url += `?v=${version === 'dev' ? Date.now() : version}`;
|
|
209
85
|
}
|
|
210
86
|
|
|
211
|
-
// Once loader.js runs and registers CopyIconsKit, backfill _kitRegistry and flush pending misses
|
|
212
|
-
script.onload = () => {
|
|
213
|
-
const kits = window.CopyIconsKit || {};
|
|
214
|
-
const kit = kits[kitId];
|
|
215
|
-
if (kit && kit.config && kit.config.prefix) {
|
|
216
|
-
const pfx = kit.config.prefix;
|
|
217
|
-
_kitRegistry[pfx] = { kitId, api: kit.config.api || api };
|
|
218
|
-
// Flush any misses buffered before the loader was ready
|
|
219
|
-
_flushPendingMisses(pfx);
|
|
220
|
-
}
|
|
221
|
-
};
|
|
222
|
-
|
|
223
87
|
script.src = url;
|
|
224
88
|
script.async = true;
|
|
225
89
|
document.head.appendChild(script);
|
|
@@ -227,11 +91,7 @@ export function initViconic(options = {}) {
|
|
|
227
91
|
|
|
228
92
|
/**
|
|
229
93
|
* ViconicIcon — React component for rendering Viconic icons.
|
|
230
|
-
*
|
|
231
|
-
* Works with both:
|
|
232
|
-
* - System icons: <ViconicIcon name="lucide:home" />
|
|
233
|
-
* - Kit icons: <ViconicIcon name="@myprefix/home" /> (after initViconic)
|
|
234
|
-
*
|
|
94
|
+
*
|
|
235
95
|
* @param {string} name - Icon identifier (e.g., "lucide:home", "@prefix/name")
|
|
236
96
|
* @param {string} [className] - CSS class names
|
|
237
97
|
* @param {object} [style] - Inline styles
|
|
@@ -246,7 +106,6 @@ export const ViconicIcon = ({ name, className, style, size, color, ...props }) =
|
|
|
246
106
|
const el = iconRef.current;
|
|
247
107
|
if (!el) return;
|
|
248
108
|
|
|
249
|
-
// --- FIX DOM REUSE (Reconciliation) ---
|
|
250
109
|
if (prevNameRef.current !== name) {
|
|
251
110
|
el.innerHTML = '';
|
|
252
111
|
el.classList.remove('vi-ok', 'svg-loaded', 'vi-mono', 'ci-multicolor');
|
|
@@ -260,78 +119,73 @@ export const ViconicIcon = ({ name, className, style, size, color, ...props }) =
|
|
|
260
119
|
return el.classList.contains('vi-ok') || el.classList.contains('svg-loaded');
|
|
261
120
|
}
|
|
262
121
|
|
|
263
|
-
|
|
264
|
-
|
|
122
|
+
function tryInjectFromCache() {
|
|
123
|
+
if (isInjected()) return false;
|
|
265
124
|
const W = window.__viconic;
|
|
266
|
-
if (W
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
}
|
|
125
|
+
if (!W || !W.icons) return false;
|
|
126
|
+
const baseName = prefixMatch ? prefixMatch[2] : null;
|
|
127
|
+
const svg = (baseName && W.icons[baseName])
|
|
128
|
+
|| (name && W.icons[name])
|
|
129
|
+
|| null;
|
|
130
|
+
if (svg) {
|
|
131
|
+
el.innerHTML = svg;
|
|
132
|
+
el.classList.add('vi-ok', 'svg-loaded');
|
|
133
|
+
return true;
|
|
276
134
|
}
|
|
135
|
+
return false;
|
|
277
136
|
}
|
|
278
137
|
|
|
279
|
-
//
|
|
280
|
-
if (
|
|
138
|
+
// PATH 1: Already in W.icons (from localStorage preload or prior fetch)
|
|
139
|
+
if (tryInjectFromCache()) return;
|
|
140
|
+
|
|
141
|
+
// PATH 2: System icons — delegate to smart loader
|
|
142
|
+
if (!isKitIcon) {
|
|
281
143
|
if (window.CopyIcons && window.CopyIcons.forceProcess) {
|
|
282
144
|
window.CopyIcons.forceProcess(el);
|
|
145
|
+
} else if (el._u) {
|
|
146
|
+
el._u();
|
|
283
147
|
}
|
|
284
148
|
}
|
|
285
149
|
|
|
286
|
-
// --- PATH 3: Custom element _u() call (kit loader registered element, system icons only) ---
|
|
287
|
-
if (!isInjected() && !isKitIcon && el._u) {
|
|
288
|
-
el._u();
|
|
289
|
-
}
|
|
290
|
-
|
|
291
150
|
if (isInjected()) return;
|
|
292
151
|
|
|
293
|
-
//
|
|
294
|
-
//
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
const
|
|
300
|
-
const
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
152
|
+
// PATH 3: Kit icons — let loader.js handle batching via el._u()
|
|
153
|
+
// el._u() notifies the loader element to queue this icon.
|
|
154
|
+
// Loader already has its own debounced batch queue.
|
|
155
|
+
// Use window-level dedup to prevent Strict Mode / HMR double-calls.
|
|
156
|
+
if (isKitIcon && prefixMatch) {
|
|
157
|
+
const kitId = (() => {
|
|
158
|
+
const kits = window.CopyIconsKit || {};
|
|
159
|
+
for (const kId in kits) {
|
|
160
|
+
if (kits[kId].config && kits[kId].config.prefix === prefixMatch[1]) return kId;
|
|
161
|
+
}
|
|
162
|
+
return prefixMatch[1]; // fallback to prefix as key
|
|
163
|
+
})();
|
|
164
|
+
|
|
165
|
+
if (!_isQueued(kitId, prefixMatch[2])) {
|
|
166
|
+
if (el._u) {
|
|
167
|
+
el._u();
|
|
307
168
|
}
|
|
308
|
-
}
|
|
309
|
-
if (!isKitIcon && el._u) el._u();
|
|
310
|
-
if (!isKitIcon && window.CopyIcons && window.CopyIcons.forceProcess) {
|
|
311
|
-
window.CopyIcons.forceProcess(el);
|
|
312
169
|
}
|
|
313
170
|
}
|
|
314
171
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
if (!isInjected() && isKitIcon && prefixMatch) {
|
|
321
|
-
const prefix = prefixMatch[1];
|
|
322
|
-
const iconBaseName = prefixMatch[2];
|
|
323
|
-
_queueKitMiss(prefix, iconBaseName);
|
|
172
|
+
// PATH 4: Listen for viconic:ready to inject when loader finishes fetching
|
|
173
|
+
function onReady() {
|
|
174
|
+
if (tryInjectFromCache()) {
|
|
175
|
+
document.removeEventListener('viconic:ready', onReady);
|
|
176
|
+
}
|
|
324
177
|
}
|
|
178
|
+
document.addEventListener('viconic:ready', onReady);
|
|
325
179
|
|
|
326
180
|
return () => {
|
|
327
|
-
document.removeEventListener('viconic:ready',
|
|
181
|
+
document.removeEventListener('viconic:ready', onReady);
|
|
328
182
|
};
|
|
329
183
|
}, [name, className, size, color, style]);
|
|
330
184
|
|
|
331
185
|
const combinedStyle = {
|
|
332
186
|
...(size ? { fontSize: size } : {}),
|
|
333
187
|
...(color ? { color: color } : {}),
|
|
334
|
-
...style
|
|
188
|
+
...style,
|
|
335
189
|
};
|
|
336
190
|
|
|
337
191
|
return (
|