react-inlinesvg 4.2.0 → 4.3.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 +28 -34
- package/dist/cache-NLB60kAd.d.mts +142 -0
- package/dist/cache-NLB60kAd.d.ts +142 -0
- package/dist/index.d.mts +7 -73
- package/dist/index.d.ts +7 -73
- package/dist/index.js +258 -200
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +254 -204
- package/dist/index.mjs.map +1 -1
- package/dist/provider.d.mts +5 -3
- package/dist/provider.d.ts +5 -3
- package/dist/provider.js +187 -6
- package/dist/provider.js.map +1 -1
- package/dist/provider.mjs +176 -6
- package/dist/provider.mjs.map +1 -1
- package/package.json +25 -41
- package/src/index.tsx +29 -284
- package/src/modules/cache.ts +79 -59
- package/src/modules/helpers.ts +1 -9
- package/src/modules/hooks.tsx +6 -1
- package/src/modules/useInlineSVG.ts +272 -0
- package/src/modules/utils.ts +36 -1
- package/src/provider.tsx +10 -7
- package/src/types.ts +67 -1
- package/src/global.d.ts +0 -6
package/dist/index.js
CHANGED
|
@@ -31,14 +31,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
32
32
|
|
|
33
33
|
// src/index.tsx
|
|
34
|
-
var
|
|
35
|
-
__export(
|
|
34
|
+
var index_exports = {};
|
|
35
|
+
__export(index_exports, {
|
|
36
36
|
cacheStore: () => cacheStore,
|
|
37
37
|
default: () => InlineSVG
|
|
38
38
|
});
|
|
39
|
-
module.exports = __toCommonJS(
|
|
40
|
-
var
|
|
41
|
-
var import_react_from_dom2 = __toESM(require("react-from-dom"));
|
|
39
|
+
module.exports = __toCommonJS(index_exports);
|
|
40
|
+
var import_react4 = require("react");
|
|
42
41
|
|
|
43
42
|
// src/config.ts
|
|
44
43
|
var CACHE_NAME = "react-inlinesvg";
|
|
@@ -95,11 +94,6 @@ async function request(url, options) {
|
|
|
95
94
|
}
|
|
96
95
|
return response.text();
|
|
97
96
|
}
|
|
98
|
-
function sleep(seconds = 1) {
|
|
99
|
-
return new Promise((resolve) => {
|
|
100
|
-
setTimeout(resolve, seconds * 1e3);
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
97
|
function supportsInlineSVG() {
|
|
104
98
|
if (!document) {
|
|
105
99
|
return false;
|
|
@@ -112,20 +106,16 @@ function supportsInlineSVG() {
|
|
|
112
106
|
|
|
113
107
|
// src/modules/cache.ts
|
|
114
108
|
var CacheStore = class {
|
|
115
|
-
constructor() {
|
|
109
|
+
constructor(options = {}) {
|
|
116
110
|
__publicField(this, "cacheApi");
|
|
117
111
|
__publicField(this, "cacheStore");
|
|
118
112
|
__publicField(this, "subscribers", []);
|
|
119
113
|
__publicField(this, "isReady", false);
|
|
114
|
+
const { name = CACHE_NAME, persistent = false } = options;
|
|
120
115
|
this.cacheStore = /* @__PURE__ */ new Map();
|
|
121
|
-
|
|
122
|
-
let usePersistentCache = false;
|
|
123
|
-
if (canUseDOM()) {
|
|
124
|
-
cacheName = window.REACT_INLINESVG_CACHE_NAME ?? CACHE_NAME;
|
|
125
|
-
usePersistentCache = !!window.REACT_INLINESVG_PERSISTENT_CACHE && "caches" in window;
|
|
126
|
-
}
|
|
116
|
+
const usePersistentCache = persistent && canUseDOM() && "caches" in window;
|
|
127
117
|
if (usePersistentCache) {
|
|
128
|
-
caches.open(
|
|
118
|
+
caches.open(name).then((cache) => {
|
|
129
119
|
this.cacheApi = cache;
|
|
130
120
|
}).catch((error) => {
|
|
131
121
|
console.error(`Failed to open cache: ${error.message}`);
|
|
@@ -149,12 +139,30 @@ var CacheStore = class {
|
|
|
149
139
|
onReady(callback) {
|
|
150
140
|
if (this.isReady) {
|
|
151
141
|
callback();
|
|
152
|
-
|
|
153
|
-
|
|
142
|
+
return () => {
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
this.subscribers.push(callback);
|
|
146
|
+
return () => {
|
|
147
|
+
const index = this.subscribers.indexOf(callback);
|
|
148
|
+
if (index >= 0) {
|
|
149
|
+
this.subscribers.splice(index, 1);
|
|
150
|
+
}
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
waitForReady() {
|
|
154
|
+
if (this.isReady) {
|
|
155
|
+
return Promise.resolve();
|
|
154
156
|
}
|
|
157
|
+
return new Promise((resolve) => {
|
|
158
|
+
this.onReady(resolve);
|
|
159
|
+
});
|
|
155
160
|
}
|
|
156
161
|
async get(url, fetchOptions) {
|
|
157
|
-
await
|
|
162
|
+
await this.fetchAndCache(url, fetchOptions);
|
|
163
|
+
return this.cacheStore.get(url)?.content ?? "";
|
|
164
|
+
}
|
|
165
|
+
getContent(url) {
|
|
158
166
|
return this.cacheStore.get(url)?.content ?? "";
|
|
159
167
|
}
|
|
160
168
|
set(url, data) {
|
|
@@ -163,57 +171,44 @@ var CacheStore = class {
|
|
|
163
171
|
isCached(url) {
|
|
164
172
|
return this.cacheStore.get(url)?.status === STATUS.LOADED;
|
|
165
173
|
}
|
|
166
|
-
async
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
await this.handleLoading(url, async () => {
|
|
170
|
-
this.cacheStore.set(url, { content: "", status: STATUS.IDLE });
|
|
171
|
-
await this.fetchAndAddToInternalCache(url, fetchOptions);
|
|
172
|
-
});
|
|
173
|
-
return;
|
|
174
|
+
async fetchAndCache(url, fetchOptions) {
|
|
175
|
+
if (!this.isReady) {
|
|
176
|
+
await this.waitForReady();
|
|
174
177
|
}
|
|
175
|
-
if (!cache?.content) {
|
|
176
|
-
this.cacheStore.set(url, { content: "", status: STATUS.LOADING });
|
|
177
|
-
try {
|
|
178
|
-
const content = await request(url, fetchOptions);
|
|
179
|
-
this.cacheStore.set(url, { content, status: STATUS.LOADED });
|
|
180
|
-
} catch (error) {
|
|
181
|
-
this.cacheStore.set(url, { content: "", status: STATUS.FAILED });
|
|
182
|
-
throw error;
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
async fetchAndAddToPersistentCache(url, fetchOptions) {
|
|
187
178
|
const cache = this.cacheStore.get(url);
|
|
188
179
|
if (cache?.status === STATUS.LOADED) {
|
|
189
180
|
return;
|
|
190
181
|
}
|
|
191
182
|
if (cache?.status === STATUS.LOADING) {
|
|
192
|
-
await this.handleLoading(url, async () => {
|
|
183
|
+
await this.handleLoading(url, fetchOptions?.signal || void 0, async () => {
|
|
193
184
|
this.cacheStore.set(url, { content: "", status: STATUS.IDLE });
|
|
194
|
-
await this.
|
|
185
|
+
await this.fetchAndCache(url, fetchOptions);
|
|
195
186
|
});
|
|
196
187
|
return;
|
|
197
188
|
}
|
|
198
189
|
this.cacheStore.set(url, { content: "", status: STATUS.LOADING });
|
|
199
|
-
const data = await this.cacheApi?.match(url);
|
|
200
|
-
if (data) {
|
|
201
|
-
const content = await data.text();
|
|
202
|
-
this.cacheStore.set(url, { content, status: STATUS.LOADED });
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
190
|
try {
|
|
206
|
-
await this.
|
|
207
|
-
const response = await this.cacheApi?.match(url);
|
|
208
|
-
const content = await response?.text() ?? "";
|
|
191
|
+
const content = this.cacheApi ? await this.fetchFromPersistentCache(url, fetchOptions) : await request(url, fetchOptions);
|
|
209
192
|
this.cacheStore.set(url, { content, status: STATUS.LOADED });
|
|
210
193
|
} catch (error) {
|
|
211
194
|
this.cacheStore.set(url, { content: "", status: STATUS.FAILED });
|
|
212
195
|
throw error;
|
|
213
196
|
}
|
|
214
197
|
}
|
|
215
|
-
async
|
|
198
|
+
async fetchFromPersistentCache(url, fetchOptions) {
|
|
199
|
+
const data = await this.cacheApi?.match(url);
|
|
200
|
+
if (data) {
|
|
201
|
+
return data.text();
|
|
202
|
+
}
|
|
203
|
+
await this.cacheApi?.add(new Request(url, fetchOptions));
|
|
204
|
+
const response = await this.cacheApi?.match(url);
|
|
205
|
+
return await response?.text() ?? "";
|
|
206
|
+
}
|
|
207
|
+
async handleLoading(url, signal, callback) {
|
|
216
208
|
for (let retryCount = 0; retryCount < CACHE_MAX_RETRIES; retryCount++) {
|
|
209
|
+
if (signal?.aborted) {
|
|
210
|
+
throw signal.reason instanceof Error ? signal.reason : new DOMException("The operation was aborted.", "AbortError");
|
|
211
|
+
}
|
|
217
212
|
if (this.cacheStore.get(url)?.status !== STATUS.LOADING) {
|
|
218
213
|
return;
|
|
219
214
|
}
|
|
@@ -241,9 +236,21 @@ var CacheStore = class {
|
|
|
241
236
|
this.cacheStore.clear();
|
|
242
237
|
}
|
|
243
238
|
};
|
|
239
|
+
function sleep(seconds = 1) {
|
|
240
|
+
return new Promise((resolve) => {
|
|
241
|
+
setTimeout(resolve, seconds * 1e3);
|
|
242
|
+
});
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// src/modules/useInlineSVG.ts
|
|
246
|
+
var import_react2 = require("react");
|
|
247
|
+
var import_react_from_dom2 = __toESM(require("react-from-dom"));
|
|
244
248
|
|
|
245
249
|
// src/modules/hooks.tsx
|
|
246
250
|
var import_react = require("react");
|
|
251
|
+
function useMount(effect) {
|
|
252
|
+
(0, import_react.useEffect)(effect, []);
|
|
253
|
+
}
|
|
247
254
|
function usePrevious(state) {
|
|
248
255
|
const ref = (0, import_react.useRef)(void 0);
|
|
249
256
|
(0, import_react.useEffect)(() => {
|
|
@@ -254,6 +261,29 @@ function usePrevious(state) {
|
|
|
254
261
|
|
|
255
262
|
// src/modules/utils.ts
|
|
256
263
|
var import_react_from_dom = __toESM(require("react-from-dom"));
|
|
264
|
+
function uniquifyStyleIds(svgText, hash, baseURL) {
|
|
265
|
+
const idMatches = svgText.matchAll(/\bid=(["'])([^"']+)\1/g);
|
|
266
|
+
const ids = [...new Set([...idMatches].map((m) => m[2]))];
|
|
267
|
+
if (!ids.length) {
|
|
268
|
+
return svgText;
|
|
269
|
+
}
|
|
270
|
+
ids.sort((a, b) => b.length - a.length);
|
|
271
|
+
return svgText.replace(/<style[^>]*>([\S\s]*?)<\/style>/gi, (fullMatch, cssContent) => {
|
|
272
|
+
let modified = cssContent;
|
|
273
|
+
for (const id of ids) {
|
|
274
|
+
const escaped = id.replace(/[$()*+.?[\\\]^{|}]/g, "\\$&");
|
|
275
|
+
modified = modified.replace(
|
|
276
|
+
new RegExp(`url\\((['"]?)#${escaped}\\1\\)`, "g"),
|
|
277
|
+
`url($1${baseURL}#${id}__${hash}$1)`
|
|
278
|
+
);
|
|
279
|
+
modified = modified.replace(
|
|
280
|
+
new RegExp(`#${escaped}(?![a-zA-Z0-9_-])`, "g"),
|
|
281
|
+
`#${id}__${hash}`
|
|
282
|
+
);
|
|
283
|
+
}
|
|
284
|
+
return fullMatch.replace(cssContent, modified);
|
|
285
|
+
});
|
|
286
|
+
}
|
|
257
287
|
function getNode(options) {
|
|
258
288
|
const {
|
|
259
289
|
baseURL,
|
|
@@ -266,7 +296,10 @@ function getNode(options) {
|
|
|
266
296
|
uniquifyIDs = false
|
|
267
297
|
} = options;
|
|
268
298
|
try {
|
|
269
|
-
|
|
299
|
+
let svgText = processSVG(content, preProcessor);
|
|
300
|
+
if (uniquifyIDs) {
|
|
301
|
+
svgText = uniquifyStyleIds(svgText, hash, baseURL ?? "");
|
|
302
|
+
}
|
|
270
303
|
const node = (0, import_react_from_dom.default)(svgText, { nodeOnly: true });
|
|
271
304
|
if (!node || !(node instanceof SVGSVGElement)) {
|
|
272
305
|
throw new Error("Could not convert the src to a DOM Node");
|
|
@@ -336,22 +369,30 @@ function updateSVGAttributes(node, options) {
|
|
|
336
369
|
return node;
|
|
337
370
|
}
|
|
338
371
|
|
|
339
|
-
// src/
|
|
340
|
-
|
|
341
|
-
function ReactInlineSVG(props) {
|
|
372
|
+
// src/modules/useInlineSVG.ts
|
|
373
|
+
function useInlineSVG(props, cacheStore2) {
|
|
342
374
|
const {
|
|
375
|
+
baseURL,
|
|
343
376
|
cacheRequests = true,
|
|
344
|
-
children = null,
|
|
345
377
|
description,
|
|
346
378
|
fetchOptions,
|
|
347
|
-
innerRef,
|
|
348
|
-
loader = null,
|
|
349
379
|
onError,
|
|
350
380
|
onLoad,
|
|
381
|
+
preProcessor,
|
|
351
382
|
src,
|
|
352
383
|
title,
|
|
353
|
-
uniqueHash
|
|
384
|
+
uniqueHash,
|
|
385
|
+
uniquifyIDs
|
|
354
386
|
} = props;
|
|
387
|
+
const hash = (0, import_react2.useRef)(uniqueHash ?? randomString(8));
|
|
388
|
+
const fetchOptionsRef = (0, import_react2.useRef)(fetchOptions);
|
|
389
|
+
const onErrorRef = (0, import_react2.useRef)(onError);
|
|
390
|
+
const onLoadRef = (0, import_react2.useRef)(onLoad);
|
|
391
|
+
const preProcessorRef = (0, import_react2.useRef)(preProcessor);
|
|
392
|
+
fetchOptionsRef.current = fetchOptions;
|
|
393
|
+
onErrorRef.current = onError;
|
|
394
|
+
onLoadRef.current = onLoad;
|
|
395
|
+
preProcessorRef.current = preProcessor;
|
|
355
396
|
const [state, setState] = (0, import_react2.useReducer)(
|
|
356
397
|
(previousState2, nextState) => ({
|
|
357
398
|
...previousState2,
|
|
@@ -360,43 +401,71 @@ function ReactInlineSVG(props) {
|
|
|
360
401
|
{
|
|
361
402
|
content: "",
|
|
362
403
|
element: null,
|
|
363
|
-
isCached:
|
|
404
|
+
isCached: false,
|
|
364
405
|
status: STATUS.IDLE
|
|
406
|
+
},
|
|
407
|
+
(initial) => {
|
|
408
|
+
const cached = cacheRequests && cacheStore2.isCached(src);
|
|
409
|
+
if (!cached) {
|
|
410
|
+
return initial;
|
|
411
|
+
}
|
|
412
|
+
const cachedContent = cacheStore2.getContent(src);
|
|
413
|
+
try {
|
|
414
|
+
const node = getNode({
|
|
415
|
+
...props,
|
|
416
|
+
handleError: () => {
|
|
417
|
+
},
|
|
418
|
+
hash: hash.current,
|
|
419
|
+
content: cachedContent
|
|
420
|
+
});
|
|
421
|
+
if (!node) {
|
|
422
|
+
return { ...initial, content: cachedContent, isCached: true, status: STATUS.LOADED };
|
|
423
|
+
}
|
|
424
|
+
const convertedElement = (0, import_react_from_dom2.default)(node);
|
|
425
|
+
if (convertedElement && (0, import_react2.isValidElement)(convertedElement)) {
|
|
426
|
+
return {
|
|
427
|
+
content: cachedContent,
|
|
428
|
+
element: convertedElement,
|
|
429
|
+
isCached: true,
|
|
430
|
+
status: STATUS.READY
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
} catch {
|
|
434
|
+
}
|
|
435
|
+
return {
|
|
436
|
+
...initial,
|
|
437
|
+
content: cachedContent,
|
|
438
|
+
isCached: true,
|
|
439
|
+
status: STATUS.LOADED
|
|
440
|
+
};
|
|
365
441
|
}
|
|
366
442
|
);
|
|
367
443
|
const { content, element, isCached, status } = state;
|
|
368
444
|
const previousProps = usePrevious(props);
|
|
369
445
|
const previousState = usePrevious(state);
|
|
370
|
-
const hash = (0, import_react2.useRef)(uniqueHash ?? randomString(8));
|
|
371
446
|
const isActive = (0, import_react2.useRef)(false);
|
|
372
447
|
const isInitialized = (0, import_react2.useRef)(false);
|
|
373
|
-
const handleError = (0, import_react2.useCallback)(
|
|
374
|
-
(error) => {
|
|
375
|
-
if (isActive.current) {
|
|
376
|
-
setState({
|
|
377
|
-
status: error.message === "Browser does not support SVG" ? STATUS.UNSUPPORTED : STATUS.FAILED
|
|
378
|
-
});
|
|
379
|
-
onError?.(error);
|
|
380
|
-
}
|
|
381
|
-
},
|
|
382
|
-
[onError]
|
|
383
|
-
);
|
|
384
|
-
const handleLoad = (0, import_react2.useCallback)((loadedContent, hasCache = false) => {
|
|
448
|
+
const handleError = (0, import_react2.useCallback)((error) => {
|
|
385
449
|
if (isActive.current) {
|
|
386
450
|
setState({
|
|
387
|
-
|
|
388
|
-
isCached: hasCache,
|
|
389
|
-
status: STATUS.LOADED
|
|
451
|
+
status: error.message === "Browser does not support SVG" ? STATUS.UNSUPPORTED : STATUS.FAILED
|
|
390
452
|
});
|
|
453
|
+
onErrorRef.current?.(error);
|
|
391
454
|
}
|
|
392
455
|
}, []);
|
|
393
|
-
const fetchContent = (0, import_react2.useCallback)(async () => {
|
|
394
|
-
const responseContent = await request(src, fetchOptions);
|
|
395
|
-
handleLoad(responseContent);
|
|
396
|
-
}, [fetchOptions, handleLoad, src]);
|
|
397
456
|
const getElement = (0, import_react2.useCallback)(() => {
|
|
398
457
|
try {
|
|
399
|
-
const node = getNode({
|
|
458
|
+
const node = getNode({
|
|
459
|
+
baseURL,
|
|
460
|
+
content,
|
|
461
|
+
description,
|
|
462
|
+
handleError,
|
|
463
|
+
hash: hash.current,
|
|
464
|
+
preProcessor: preProcessorRef.current,
|
|
465
|
+
src,
|
|
466
|
+
title,
|
|
467
|
+
uniquifyIDs
|
|
468
|
+
});
|
|
400
469
|
const convertedElement = (0, import_react_from_dom2.default)(node);
|
|
401
470
|
if (!convertedElement || !(0, import_react2.isValidElement)(convertedElement)) {
|
|
402
471
|
throw new Error("Could not convert the src to a React element");
|
|
@@ -408,67 +477,32 @@ function ReactInlineSVG(props) {
|
|
|
408
477
|
} catch (error) {
|
|
409
478
|
handleError(error);
|
|
410
479
|
}
|
|
411
|
-
}, [content, handleError,
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
inlineSrc = dataURI[1] ? window.atob(dataURI[2]) : decodeURIComponent(dataURI[2]);
|
|
417
|
-
} else if (src.includes("<svg")) {
|
|
418
|
-
inlineSrc = src;
|
|
419
|
-
}
|
|
420
|
-
if (inlineSrc) {
|
|
421
|
-
handleLoad(inlineSrc);
|
|
422
|
-
return;
|
|
480
|
+
}, [baseURL, content, description, handleError, src, title, uniquifyIDs]);
|
|
481
|
+
useMount(() => {
|
|
482
|
+
isActive.current = true;
|
|
483
|
+
if (!canUseDOM() || isInitialized.current) {
|
|
484
|
+
return void 0;
|
|
423
485
|
}
|
|
424
486
|
try {
|
|
425
|
-
if (
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
487
|
+
if (status === STATUS.READY) {
|
|
488
|
+
onLoadRef.current?.(src, isCached);
|
|
489
|
+
} else if (status === STATUS.IDLE) {
|
|
490
|
+
if (!isSupportedEnvironment()) {
|
|
491
|
+
throw new Error("Browser does not support SVG");
|
|
492
|
+
}
|
|
493
|
+
if (!src) {
|
|
494
|
+
throw new Error("Missing src");
|
|
495
|
+
}
|
|
496
|
+
setState({ content: "", element: null, isCached: false, status: STATUS.LOADING });
|
|
430
497
|
}
|
|
431
498
|
} catch (error) {
|
|
432
499
|
handleError(error);
|
|
433
500
|
}
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
element: null,
|
|
440
|
-
isCached: false,
|
|
441
|
-
status: STATUS.LOADING
|
|
442
|
-
});
|
|
443
|
-
}
|
|
444
|
-
}, []);
|
|
445
|
-
(0, import_react2.useEffect)(
|
|
446
|
-
() => {
|
|
447
|
-
isActive.current = true;
|
|
448
|
-
if (!canUseDOM() || isInitialized.current) {
|
|
449
|
-
return void 0;
|
|
450
|
-
}
|
|
451
|
-
try {
|
|
452
|
-
if (status === STATUS.IDLE) {
|
|
453
|
-
if (!isSupportedEnvironment()) {
|
|
454
|
-
throw new Error("Browser does not support SVG");
|
|
455
|
-
}
|
|
456
|
-
if (!src) {
|
|
457
|
-
throw new Error("Missing src");
|
|
458
|
-
}
|
|
459
|
-
load();
|
|
460
|
-
}
|
|
461
|
-
} catch (error) {
|
|
462
|
-
handleError(error);
|
|
463
|
-
}
|
|
464
|
-
isInitialized.current = true;
|
|
465
|
-
return () => {
|
|
466
|
-
isActive.current = false;
|
|
467
|
-
};
|
|
468
|
-
},
|
|
469
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
470
|
-
[]
|
|
471
|
-
);
|
|
501
|
+
isInitialized.current = true;
|
|
502
|
+
return () => {
|
|
503
|
+
isActive.current = false;
|
|
504
|
+
};
|
|
505
|
+
});
|
|
472
506
|
(0, import_react2.useEffect)(() => {
|
|
473
507
|
if (!canUseDOM() || !previousProps) {
|
|
474
508
|
return;
|
|
@@ -478,14 +512,58 @@ function ReactInlineSVG(props) {
|
|
|
478
512
|
handleError(new Error("Missing src"));
|
|
479
513
|
return;
|
|
480
514
|
}
|
|
481
|
-
|
|
515
|
+
setState({ content: "", element: null, isCached: false, status: STATUS.LOADING });
|
|
482
516
|
}
|
|
483
|
-
}, [handleError,
|
|
517
|
+
}, [handleError, previousProps, src]);
|
|
484
518
|
(0, import_react2.useEffect)(() => {
|
|
485
|
-
if (status
|
|
519
|
+
if (status !== STATUS.LOADING) {
|
|
520
|
+
return void 0;
|
|
521
|
+
}
|
|
522
|
+
const controller = new AbortController();
|
|
523
|
+
let active = true;
|
|
524
|
+
(async () => {
|
|
525
|
+
try {
|
|
526
|
+
const dataURI = /^data:image\/svg[^,]*?(;base64)?,(.*)/.exec(src);
|
|
527
|
+
let inlineSrc;
|
|
528
|
+
if (dataURI) {
|
|
529
|
+
inlineSrc = dataURI[1] ? window.atob(dataURI[2]) : decodeURIComponent(dataURI[2]);
|
|
530
|
+
} else if (src.includes("<svg")) {
|
|
531
|
+
inlineSrc = src;
|
|
532
|
+
}
|
|
533
|
+
if (inlineSrc) {
|
|
534
|
+
if (active) {
|
|
535
|
+
setState({ content: inlineSrc, isCached: false, status: STATUS.LOADED });
|
|
536
|
+
}
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
const fetchParameters = { ...fetchOptionsRef.current, signal: controller.signal };
|
|
540
|
+
let loadedContent;
|
|
541
|
+
let hasCache = false;
|
|
542
|
+
if (cacheRequests) {
|
|
543
|
+
hasCache = cacheStore2.isCached(src);
|
|
544
|
+
loadedContent = await cacheStore2.get(src, fetchParameters);
|
|
545
|
+
} else {
|
|
546
|
+
loadedContent = await request(src, fetchParameters);
|
|
547
|
+
}
|
|
548
|
+
if (active) {
|
|
549
|
+
setState({ content: loadedContent, isCached: hasCache, status: STATUS.LOADED });
|
|
550
|
+
}
|
|
551
|
+
} catch (error) {
|
|
552
|
+
if (active && error.name !== "AbortError") {
|
|
553
|
+
handleError(error);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
})();
|
|
557
|
+
return () => {
|
|
558
|
+
active = false;
|
|
559
|
+
controller.abort();
|
|
560
|
+
};
|
|
561
|
+
}, [cacheRequests, cacheStore2, handleError, src, status]);
|
|
562
|
+
(0, import_react2.useEffect)(() => {
|
|
563
|
+
if (status === STATUS.LOADED && content) {
|
|
486
564
|
getElement();
|
|
487
565
|
}
|
|
488
|
-
}, [
|
|
566
|
+
}, [content, getElement, status]);
|
|
489
567
|
(0, import_react2.useEffect)(() => {
|
|
490
568
|
if (!canUseDOM() || !previousProps || previousProps.src !== src) {
|
|
491
569
|
return;
|
|
@@ -498,51 +576,50 @@ function ReactInlineSVG(props) {
|
|
|
498
576
|
if (!previousState) {
|
|
499
577
|
return;
|
|
500
578
|
}
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
if (previousState.status !== STATUS.LOADING) {
|
|
504
|
-
getContent();
|
|
505
|
-
}
|
|
506
|
-
break;
|
|
507
|
-
}
|
|
508
|
-
case STATUS.LOADED: {
|
|
509
|
-
if (previousState.status !== STATUS.LOADED) {
|
|
510
|
-
getElement();
|
|
511
|
-
}
|
|
512
|
-
break;
|
|
513
|
-
}
|
|
514
|
-
case STATUS.READY: {
|
|
515
|
-
if (previousState.status !== STATUS.READY) {
|
|
516
|
-
onLoad?.(src, isCached);
|
|
517
|
-
}
|
|
518
|
-
break;
|
|
519
|
-
}
|
|
579
|
+
if (status === STATUS.READY && previousState.status !== STATUS.READY) {
|
|
580
|
+
onLoadRef.current?.(src, isCached);
|
|
520
581
|
}
|
|
521
|
-
}, [
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
);
|
|
582
|
+
}, [isCached, previousState, src, status]);
|
|
583
|
+
return { element, status };
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
// src/provider.tsx
|
|
587
|
+
var import_react3 = __toESM(require("react"));
|
|
588
|
+
var CacheContext = (0, import_react3.createContext)(null);
|
|
589
|
+
function useCacheStore() {
|
|
590
|
+
return (0, import_react3.useContext)(CacheContext);
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
// src/index.tsx
|
|
594
|
+
var cacheStore = new CacheStore();
|
|
595
|
+
function InlineSVG(props) {
|
|
596
|
+
const { children = null, innerRef, loader = null } = props;
|
|
597
|
+
const contextStore = useCacheStore();
|
|
598
|
+
const store = contextStore ?? cacheStore;
|
|
599
|
+
const { element, status } = useInlineSVG(props, store);
|
|
539
600
|
if (!canUseDOM()) {
|
|
540
601
|
return loader;
|
|
541
602
|
}
|
|
542
603
|
if (element) {
|
|
543
|
-
return (0,
|
|
604
|
+
return (0, import_react4.cloneElement)(element, {
|
|
544
605
|
ref: innerRef,
|
|
545
|
-
...
|
|
606
|
+
...omit(
|
|
607
|
+
props,
|
|
608
|
+
"baseURL",
|
|
609
|
+
"cacheRequests",
|
|
610
|
+
"children",
|
|
611
|
+
"description",
|
|
612
|
+
"fetchOptions",
|
|
613
|
+
"innerRef",
|
|
614
|
+
"loader",
|
|
615
|
+
"onError",
|
|
616
|
+
"onLoad",
|
|
617
|
+
"preProcessor",
|
|
618
|
+
"src",
|
|
619
|
+
"title",
|
|
620
|
+
"uniqueHash",
|
|
621
|
+
"uniquifyIDs"
|
|
622
|
+
)
|
|
546
623
|
});
|
|
547
624
|
}
|
|
548
625
|
if ([STATUS.UNSUPPORTED, STATUS.FAILED].includes(status)) {
|
|
@@ -550,25 +627,6 @@ function ReactInlineSVG(props) {
|
|
|
550
627
|
}
|
|
551
628
|
return loader;
|
|
552
629
|
}
|
|
553
|
-
function InlineSVG(props) {
|
|
554
|
-
if (!cacheStore) {
|
|
555
|
-
cacheStore = new CacheStore();
|
|
556
|
-
}
|
|
557
|
-
const { loader } = props;
|
|
558
|
-
const [isReady, setReady] = (0, import_react2.useState)(cacheStore.isReady);
|
|
559
|
-
(0, import_react2.useEffect)(() => {
|
|
560
|
-
if (isReady) {
|
|
561
|
-
return;
|
|
562
|
-
}
|
|
563
|
-
cacheStore.onReady(() => {
|
|
564
|
-
setReady(true);
|
|
565
|
-
});
|
|
566
|
-
}, [isReady]);
|
|
567
|
-
if (!isReady) {
|
|
568
|
-
return loader;
|
|
569
|
-
}
|
|
570
|
-
return /* @__PURE__ */ import_react2.default.createElement(ReactInlineSVG, { ...props });
|
|
571
|
-
}
|
|
572
630
|
// Annotate the CommonJS export names for ESM import in node:
|
|
573
631
|
0 && (module.exports = {
|
|
574
632
|
cacheStore
|