use-frontbacked 5.1.5 → 5.1.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.
Files changed (101) hide show
  1. package/dist/cjs/index.js +416 -210
  2. package/dist/cjs/index.js.map +1 -1
  3. package/dist/cjs/types/components/DownloadType/index.d.ts +12 -12
  4. package/dist/cjs/types/components/Firebase/AccessTokenDoor.d.ts +12 -12
  5. package/dist/cjs/types/components/Firebase/AuthView.d.ts +15 -15
  6. package/dist/cjs/types/components/Firebase/SignInView.d.ts +11 -11
  7. package/dist/cjs/types/components/Firebase/SignUpView.d.ts +10 -10
  8. package/dist/cjs/types/components/Firebase/data.type.d.ts +23 -23
  9. package/dist/cjs/types/components/Firebase/index.d.ts +14 -14
  10. package/dist/cjs/types/components/FrontbackedProvider/index.d.ts +55 -55
  11. package/dist/cjs/types/components/hooks/useReferralId.d.ts +5 -5
  12. package/dist/cjs/types/components/hooks/useSdkConfig.d.ts +10 -10
  13. package/dist/cjs/types/components/hooks/useTools/index.d.ts +14 -14
  14. package/dist/cjs/types/components/hooks/useTools/types.d.ts +62 -62
  15. package/dist/cjs/types/components/hooks/useTools/utils.d.ts +23 -23
  16. package/dist/cjs/types/components/index.d.ts +2 -2
  17. package/dist/cjs/types/components/types.d.ts +214 -214
  18. package/dist/cjs/types/components/widgets/AppButton.d.ts +17 -17
  19. package/dist/cjs/types/components/widgets/CopyView.d.ts +24 -24
  20. package/dist/cjs/types/components/widgets/DrawerPop/index.d.ts +25 -25
  21. package/dist/cjs/types/components/widgets/InfoLabel.d.ts +11 -11
  22. package/dist/cjs/types/components/widgets/InputBox/index.d.ts +94 -94
  23. package/dist/cjs/types/components/widgets/InputBox/utils.d.ts +1 -1
  24. package/dist/cjs/types/components/widgets/Link.d.ts +9 -9
  25. package/dist/cjs/types/components/widgets/Loading.d.ts +27 -27
  26. package/dist/cjs/types/components/widgets/ModalPop/index.d.ts +26 -26
  27. package/dist/cjs/types/components/widgets/PleaseWaitForX.d.ts +3 -3
  28. package/dist/cjs/types/index.d.ts +1 -1
  29. package/dist/cjs/types/theme.d.ts +3 -3
  30. package/dist/cjs/types/theme.type.d.ts +19 -19
  31. package/dist/cjs/types/utils/CustomError.d.ts +5 -5
  32. package/dist/cjs/types/utils/base64Images.d.ts +4 -4
  33. package/dist/cjs/types/utils/c.d.ts +33 -33
  34. package/dist/cjs/types/utils/f.d.ts +23 -23
  35. package/dist/components/DownloadType/index.d.ts +12 -12
  36. package/dist/components/Firebase/AccessTokenDoor.d.ts +12 -12
  37. package/dist/components/Firebase/AuthView.d.ts +15 -15
  38. package/dist/components/Firebase/SignInView.d.ts +11 -11
  39. package/dist/components/Firebase/SignUpView.d.ts +10 -10
  40. package/dist/components/Firebase/data.type.d.ts +23 -23
  41. package/dist/components/Firebase/index.d.ts +14 -14
  42. package/dist/components/FrontbackedProvider/index.d.ts +55 -55
  43. package/dist/components/hooks/useReferralId.d.ts +5 -5
  44. package/dist/components/hooks/useSdkConfig.d.ts +10 -10
  45. package/dist/components/hooks/useTools/index.d.ts +14 -14
  46. package/dist/components/hooks/useTools/types.d.ts +62 -62
  47. package/dist/components/hooks/useTools/utils.d.ts +23 -23
  48. package/dist/components/index.d.ts +2 -2
  49. package/dist/components/types.d.ts +214 -214
  50. package/dist/components/widgets/AppButton.d.ts +17 -17
  51. package/dist/components/widgets/CopyView.d.ts +24 -24
  52. package/dist/components/widgets/DrawerPop/index.d.ts +25 -25
  53. package/dist/components/widgets/InfoLabel.d.ts +11 -11
  54. package/dist/components/widgets/InputBox/index.d.ts +94 -94
  55. package/dist/components/widgets/InputBox/utils.d.ts +1 -1
  56. package/dist/components/widgets/Link.d.ts +9 -9
  57. package/dist/components/widgets/Loading.d.ts +27 -27
  58. package/dist/components/widgets/ModalPop/index.d.ts +26 -26
  59. package/dist/components/widgets/PleaseWaitForX.d.ts +3 -3
  60. package/dist/esm/index.es.js +416 -210
  61. package/dist/esm/index.es.js.map +1 -1
  62. package/dist/esm/types/components/DownloadType/index.d.ts +12 -12
  63. package/dist/esm/types/components/Firebase/AccessTokenDoor.d.ts +12 -12
  64. package/dist/esm/types/components/Firebase/AuthView.d.ts +15 -15
  65. package/dist/esm/types/components/Firebase/SignInView.d.ts +11 -11
  66. package/dist/esm/types/components/Firebase/SignUpView.d.ts +10 -10
  67. package/dist/esm/types/components/Firebase/data.type.d.ts +23 -23
  68. package/dist/esm/types/components/Firebase/index.d.ts +14 -14
  69. package/dist/esm/types/components/FrontbackedProvider/index.d.ts +55 -55
  70. package/dist/esm/types/components/hooks/useReferralId.d.ts +5 -5
  71. package/dist/esm/types/components/hooks/useSdkConfig.d.ts +10 -10
  72. package/dist/esm/types/components/hooks/useTools/index.d.ts +14 -14
  73. package/dist/esm/types/components/hooks/useTools/types.d.ts +62 -62
  74. package/dist/esm/types/components/hooks/useTools/utils.d.ts +23 -23
  75. package/dist/esm/types/components/index.d.ts +2 -2
  76. package/dist/esm/types/components/types.d.ts +214 -214
  77. package/dist/esm/types/components/widgets/AppButton.d.ts +17 -17
  78. package/dist/esm/types/components/widgets/CopyView.d.ts +24 -24
  79. package/dist/esm/types/components/widgets/DrawerPop/index.d.ts +25 -25
  80. package/dist/esm/types/components/widgets/InfoLabel.d.ts +11 -11
  81. package/dist/esm/types/components/widgets/InputBox/index.d.ts +94 -94
  82. package/dist/esm/types/components/widgets/InputBox/utils.d.ts +1 -1
  83. package/dist/esm/types/components/widgets/Link.d.ts +9 -9
  84. package/dist/esm/types/components/widgets/Loading.d.ts +27 -27
  85. package/dist/esm/types/components/widgets/ModalPop/index.d.ts +26 -26
  86. package/dist/esm/types/components/widgets/PleaseWaitForX.d.ts +3 -3
  87. package/dist/esm/types/index.d.ts +1 -1
  88. package/dist/esm/types/theme.d.ts +3 -3
  89. package/dist/esm/types/theme.type.d.ts +19 -19
  90. package/dist/esm/types/utils/CustomError.d.ts +5 -5
  91. package/dist/esm/types/utils/base64Images.d.ts +4 -4
  92. package/dist/esm/types/utils/c.d.ts +33 -33
  93. package/dist/esm/types/utils/f.d.ts +23 -23
  94. package/dist/index.d.ts +1 -1
  95. package/dist/theme.d.ts +3 -3
  96. package/dist/theme.type.d.ts +19 -19
  97. package/dist/utils/CustomError.d.ts +5 -5
  98. package/dist/utils/base64Images.d.ts +4 -4
  99. package/dist/utils/c.d.ts +33 -33
  100. package/dist/utils/f.d.ts +23 -23
  101. package/package.json +84 -83
@@ -254,6 +254,152 @@ var consoleLog = function consoleLog() {
254
254
  console.log.apply(console, args);
255
255
  }
256
256
  };
257
+ var isAppleMobileDevice = function isAppleMobileDevice() {
258
+ if (typeof navigator === "undefined") return false;
259
+ var userAgent = navigator.userAgent || "";
260
+ var platform = navigator.platform || "";
261
+ var maxTouchPoints = navigator.maxTouchPoints || 0;
262
+ return /iPad|iPhone|iPod/i.test(userAgent) || platform === "MacIntel" && maxTouchPoints > 1;
263
+ };
264
+ var openBlobInBrowser = function openBlobInBrowser(blob, fileName, openInNewTab) {
265
+ if (openInNewTab === void 0) {
266
+ openInNewTab = false;
267
+ }
268
+ var objectUrl = URL.createObjectURL(blob);
269
+ var downloadLink = document.createElement("a");
270
+ downloadLink.href = objectUrl;
271
+ downloadLink.rel = "noopener";
272
+ downloadLink.style.display = "none";
273
+ if (openInNewTab) {
274
+ downloadLink.target = "_blank";
275
+ } else {
276
+ downloadLink.download = fileName;
277
+ }
278
+ document.body.appendChild(downloadLink);
279
+ downloadLink.click();
280
+ document.body.removeChild(downloadLink);
281
+ setTimeout(function () {
282
+ return URL.revokeObjectURL(objectUrl);
283
+ }, 30000);
284
+ };
285
+ var shareBlob = function shareBlob(blob, fileName) {
286
+ return __awaiter(void 0, void 0, void 0, function () {
287
+ var shareApi, canShare, file, shareData;
288
+ return __generator(this, function (_a) {
289
+ switch (_a.label) {
290
+ case 0:
291
+ shareApi = typeof navigator !== "undefined" ? navigator.share : null;
292
+ canShare = typeof navigator !== "undefined" ? navigator.canShare : null;
293
+ if (!shareApi || typeof File === "undefined") return [2 /*return*/, false];
294
+ file = new File([blob], fileName, {
295
+ type: blob.type || "application/octet-stream"
296
+ });
297
+ shareData = {
298
+ files: [file],
299
+ title: fileName
300
+ };
301
+ if (canShare && !canShare.call(navigator, shareData)) return [2 /*return*/, false];
302
+ return [4 /*yield*/, shareApi.call(navigator, shareData)];
303
+ case 1:
304
+ _a.sent();
305
+ return [2 /*return*/, true];
306
+ }
307
+ });
308
+ });
309
+ };
310
+ var promptAppleMobileSave = function promptAppleMobileSave(blob, fileName) {
311
+ return new Promise(function (resolve, reject) {
312
+ var overlay = document.createElement("div");
313
+ overlay.setAttribute("role", "dialog");
314
+ overlay.setAttribute("aria-modal", "true");
315
+ overlay.style.cssText = ["position:fixed", "inset:0", "z-index:2147483647", "display:flex", "align-items:center", "justify-content:center", "padding:24px", "background:rgba(15,23,42,0.58)", "font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif"].join(";");
316
+ var dialog = document.createElement("div");
317
+ dialog.style.cssText = ["width:min(360px,100%)", "border-radius:12px", "background:#fff", "box-shadow:0 20px 60px rgba(15,23,42,0.3)", "padding:18px", "color:#111827", "text-align:left"].join(";");
318
+ var title = document.createElement("div");
319
+ title.textContent = "File ready";
320
+ title.style.cssText = "font-size:17px;font-weight:700;margin-bottom:8px;";
321
+ var body = document.createElement("div");
322
+ body.textContent = "Choose where to save this file.";
323
+ body.style.cssText = "font-size:14px;line-height:1.45;color:#4b5563;margin-bottom:16px;";
324
+ var actions = document.createElement("div");
325
+ actions.style.cssText = "display:flex;gap:10px;justify-content:flex-end;";
326
+ var cancelButton = document.createElement("button");
327
+ cancelButton.type = "button";
328
+ cancelButton.textContent = "Cancel";
329
+ cancelButton.style.cssText = ["border:0", "border-radius:8px", "padding:10px 14px", "background:#f3f4f6", "color:#111827", "font-size:14px", "font-weight:600"].join(";");
330
+ var saveButton = document.createElement("button");
331
+ saveButton.type = "button";
332
+ saveButton.textContent = "Save File";
333
+ saveButton.style.cssText = ["border:0", "border-radius:8px", "padding:10px 14px", "background:#2563eb", "color:#fff", "font-size:14px", "font-weight:700"].join(";");
334
+ var cleanup = function cleanup() {
335
+ document.body.removeChild(overlay);
336
+ };
337
+ cancelButton.onclick = function () {
338
+ cleanup();
339
+ reject(new Error("File save was cancelled."));
340
+ };
341
+ saveButton.onclick = function () {
342
+ return __awaiter(void 0, void 0, void 0, function () {
343
+ var shared, error_1;
344
+ return __generator(this, function (_a) {
345
+ switch (_a.label) {
346
+ case 0:
347
+ saveButton.setAttribute("disabled", "true");
348
+ _a.label = 1;
349
+ case 1:
350
+ _a.trys.push([1, 3,, 4]);
351
+ return [4 /*yield*/, shareBlob(blob, fileName)];
352
+ case 2:
353
+ shared = _a.sent();
354
+ if (!shared) openBlobInBrowser(blob, fileName, true);
355
+ cleanup();
356
+ resolve();
357
+ return [3 /*break*/, 4];
358
+ case 3:
359
+ error_1 = _a.sent();
360
+ cleanup();
361
+ if ((error_1 === null || error_1 === void 0 ? void 0 : error_1.name) === "AbortError") {
362
+ reject(new Error("File save was cancelled."));
363
+ return [2 /*return*/];
364
+ }
365
+
366
+ openBlobInBrowser(blob, fileName, true);
367
+ resolve();
368
+ return [3 /*break*/, 4];
369
+ case 4:
370
+ return [2 /*return*/];
371
+ }
372
+ });
373
+ });
374
+ };
375
+
376
+ actions.appendChild(cancelButton);
377
+ actions.appendChild(saveButton);
378
+ dialog.appendChild(title);
379
+ dialog.appendChild(body);
380
+ dialog.appendChild(actions);
381
+ overlay.appendChild(dialog);
382
+ document.body.appendChild(overlay);
383
+ });
384
+ };
385
+ var downloadBlob = function downloadBlob(blob, fileName) {
386
+ return __awaiter(void 0, void 0, void 0, function () {
387
+ return __generator(this, function (_a) {
388
+ switch (_a.label) {
389
+ case 0:
390
+ if (!isAppleMobileDevice()) return [3 /*break*/, 2];
391
+ return [4 /*yield*/, promptAppleMobileSave(blob, fileName)];
392
+ case 1:
393
+ _a.sent();
394
+ return [2 /*return*/];
395
+ case 2:
396
+ openBlobInBrowser(blob, fileName);
397
+ return [2 /*return*/];
398
+ }
399
+ });
400
+ });
401
+ };
402
+
257
403
  var downloadSvgAsImage = function downloadSvgAsImage(svgString, format, fileName) {
258
404
  if (format === void 0) {
259
405
  format = 'png';
@@ -267,39 +413,48 @@ var downloadSvgAsImage = function downloadSvgAsImage(svgString, format, fileName
267
413
  });
268
414
  var svgUrl = URL.createObjectURL(svgBlob);
269
415
  var img = new Image();
416
+ img.crossOrigin = "anonymous";
270
417
  img.onload = function () {
271
- var canvas = document.createElement('canvas');
272
- canvas.width = img.width;
273
- canvas.height = img.height;
274
- var context = canvas.getContext('2d');
275
- if (context) {
276
- context.drawImage(img, 0, 0);
277
- var dataUrl = canvas.toDataURL("image/".concat(format));
278
- var imageBlob = dataURLToBlob(dataUrl);
279
- if (isiPhone()) {
280
- // Workaround for iPhone browsers
281
- var binaryData = [imageBlob];
282
- var iphoneBlob = new Blob(binaryData, {
283
- type: "image/".concat(format)
284
- });
285
- var iphoneUrl = URL.createObjectURL(iphoneBlob);
286
- var downloadLink = document.createElement('a');
287
- downloadLink.href = iphoneUrl;
288
- downloadLink.download = "".concat(fileName, ".").concat(format);
289
- downloadLink.click();
290
- URL.revokeObjectURL(iphoneUrl);
291
- resolve(iphoneUrl);
292
- } else {
293
- // For other browsers
294
- var downloadLink = document.createElement('a');
295
- downloadLink.href = dataUrl;
296
- downloadLink.download = "".concat(fileName, ".").concat(format);
297
- downloadLink.click();
298
- resolve(dataUrl);
299
- }
300
- } else {
301
- reject(new Error("Unsupported Browser. Please try to download from another browser."));
302
- }
418
+ return __awaiter(this, void 0, void 0, function () {
419
+ var canvas, context, dataUrl, imageBlob, error_2;
420
+ return __generator(this, function (_a) {
421
+ switch (_a.label) {
422
+ case 0:
423
+ _a.trys.push([0, 4,, 5]);
424
+ canvas = document.createElement('canvas');
425
+ canvas.width = img.width;
426
+ canvas.height = img.height;
427
+ context = canvas.getContext('2d');
428
+ if (!context) return [3 /*break*/, 2];
429
+ context.drawImage(img, 0, 0);
430
+ dataUrl = canvas.toDataURL("image/".concat(format));
431
+ imageBlob = dataURLToBlob(dataUrl);
432
+ URL.revokeObjectURL(svgUrl);
433
+ return [4 /*yield*/, downloadBlob(imageBlob, "".concat(fileName, ".").concat(format))];
434
+ case 1:
435
+ _a.sent();
436
+ resolve(dataUrl);
437
+ return [3 /*break*/, 3];
438
+ case 2:
439
+ reject(new Error("Unsupported Browser. Please try to download from another browser."));
440
+ _a.label = 3;
441
+ case 3:
442
+ return [3 /*break*/, 5];
443
+ case 4:
444
+ error_2 = _a.sent();
445
+ URL.revokeObjectURL(svgUrl);
446
+ reject(error_2);
447
+ return [3 /*break*/, 5];
448
+ case 5:
449
+ return [2 /*return*/];
450
+ }
451
+ });
452
+ });
453
+ };
454
+
455
+ img.onerror = function () {
456
+ URL.revokeObjectURL(svgUrl);
457
+ reject(new Error("Failed to render the SVG for download."));
303
458
  };
304
459
  img.src = svgUrl;
305
460
  });
@@ -317,9 +472,6 @@ function dataURLToBlob(dataURL) {
317
472
  type: mime
318
473
  });
319
474
  }
320
- function isiPhone() {
321
- return /iPhone/i.test(navigator.userAgent);
322
- }
323
475
  var getColor = function getColor(isDarkMode, colorName) {
324
476
  var color = theme[colorName];
325
477
  if (color) {
@@ -1344,69 +1496,69 @@ var InputBox = function InputBox(_a) {
1344
1496
  return null;
1345
1497
  }
1346
1498
  }))) :
1347
- /*
1348
- type == TYPES.location?
1349
- <LocationPicker disabled={disabled} ref={inputRef} w="100%" h="100%"
1350
- apiKey={apiKey || ""} defaultLatlng={defaultLatlng} geotype={geotype}
1351
- mapToSearchRatio={mapToSearchRatio}
1352
- twoDigitCountryCode={twoDigitCountryCode}
1353
- searchPlaceholder={placeholder as string}
1354
- value={value? {
1355
- name: value.name,
1356
- formatted_address: value.address,
1357
- geometry: {
1358
- location: {lat: () => value.position.lat, lng: () => value.position.lng},
1359
- viewport: {}
1360
- }
1361
- } : null}
1362
- onChange={(l) => {
1363
- const v = {
1364
- name: l.name,
1365
- address: l.formatted_address,
1366
- position: {
1367
- lat: l.geometry.location.lat(),
1368
- lng: l.geometry.location.lng()
1369
- }
1370
- }
1371
- if(!disabled && onChange) {
1372
- onChange(v)
1373
- }
1374
- if(!disabled && onCheckInfo) {
1375
- const { checker, waitTime } = onCheckInfo(v)
1376
- //only check input in "onChange" if waitTime is greater than zero.
1377
- // This is good in searching a text results as a user types in a search bar,
1378
- // or saving an article on a server as the user types
1379
- if(waitTime > 0) {
1380
- handleInputCheck(() => v, (checkedValue) => {
1381
- return JSON.stringify(checkedValue) === JSON.stringify(v)
1382
- }, checker, waitTime)
1383
- }
1384
- }
1385
-
1386
- }}
1387
- onBlur={(l) => {
1388
- if(!disabled && onCheckInfo) {
1389
- const v = {
1390
- name: l.name,
1391
- address: l.formatted_address,
1392
- position: {
1393
- lat: l.geometry.location.lat(),
1394
- lng: l.geometry.location.lng()
1395
- }
1396
- }
1397
- const { checker, waitTime } = onCheckInfo(v)
1398
- //only check input in "onBlur" if waitTime is not set or equal to zero.
1399
- // This is good in validating an input as it looses focus when the user moves to another,
1400
- // input field
1401
- if(!waitTime) {
1402
- handleInputCheck(() => v, (checkedValue) => {
1403
- return JSON.stringify(checkedValue) === JSON.stringify(v)
1404
- }, checker, waitTime)
1405
- }
1406
- }
1407
- }}
1408
- errorMessage={errorMessage}
1409
- />
1499
+ /*
1500
+ type == TYPES.location?
1501
+ <LocationPicker disabled={disabled} ref={inputRef} w="100%" h="100%"
1502
+ apiKey={apiKey || ""} defaultLatlng={defaultLatlng} geotype={geotype}
1503
+ mapToSearchRatio={mapToSearchRatio}
1504
+ twoDigitCountryCode={twoDigitCountryCode}
1505
+ searchPlaceholder={placeholder as string}
1506
+ value={value? {
1507
+ name: value.name,
1508
+ formatted_address: value.address,
1509
+ geometry: {
1510
+ location: {lat: () => value.position.lat, lng: () => value.position.lng},
1511
+ viewport: {}
1512
+ }
1513
+ } : null}
1514
+ onChange={(l) => {
1515
+ const v = {
1516
+ name: l.name,
1517
+ address: l.formatted_address,
1518
+ position: {
1519
+ lat: l.geometry.location.lat(),
1520
+ lng: l.geometry.location.lng()
1521
+ }
1522
+ }
1523
+ if(!disabled && onChange) {
1524
+ onChange(v)
1525
+ }
1526
+ if(!disabled && onCheckInfo) {
1527
+ const { checker, waitTime } = onCheckInfo(v)
1528
+ //only check input in "onChange" if waitTime is greater than zero.
1529
+ // This is good in searching a text results as a user types in a search bar,
1530
+ // or saving an article on a server as the user types
1531
+ if(waitTime > 0) {
1532
+ handleInputCheck(() => v, (checkedValue) => {
1533
+ return JSON.stringify(checkedValue) === JSON.stringify(v)
1534
+ }, checker, waitTime)
1535
+ }
1536
+ }
1537
+
1538
+ }}
1539
+ onBlur={(l) => {
1540
+ if(!disabled && onCheckInfo) {
1541
+ const v = {
1542
+ name: l.name,
1543
+ address: l.formatted_address,
1544
+ position: {
1545
+ lat: l.geometry.location.lat(),
1546
+ lng: l.geometry.location.lng()
1547
+ }
1548
+ }
1549
+ const { checker, waitTime } = onCheckInfo(v)
1550
+ //only check input in "onBlur" if waitTime is not set or equal to zero.
1551
+ // This is good in validating an input as it looses focus when the user moves to another,
1552
+ // input field
1553
+ if(!waitTime) {
1554
+ handleInputCheck(() => v, (checkedValue) => {
1555
+ return JSON.stringify(checkedValue) === JSON.stringify(v)
1556
+ }, checker, waitTime)
1557
+ }
1558
+ }
1559
+ }}
1560
+ errorMessage={errorMessage}
1561
+ />
1410
1562
  :*/
1411
1563
  type == TYPES.price ? /*#__PURE__*/React.createElement(VStack, {
1412
1564
  w: "100%",
@@ -1515,26 +1667,26 @@ var InputBox = function InputBox(_a) {
1515
1667
  }
1516
1668
  }, /*#__PURE__*/React.createElement(FaPlus, null)))
1517
1669
  }))) :
1518
- /*
1519
- type == TYPES.select_tree?
1520
- <SelectTree disabled={disabled} options={options as SelectTreeOptionWithChildren[]}
1521
- onChange={onChange}
1522
- onBlur={(e: SelectTreeEvent) => {
1523
- const { currentNode, selectedNodes } = e
1524
- if(!disabled && onCheckInfo) {
1525
- const v = "currentNode"
1526
- const { checker, waitTime } = onCheckInfo(v)
1527
- //only check input in "onBlur" if waitTime is not set or equal to zero.
1528
- // This is good in validating an input as it looses focus when the user moves to another,
1529
- // input field
1530
- if(!waitTime) {
1531
- handleInputCheck(() => v, (checkedValue) => {
1532
- return JSON.stringify(checkedValue) === JSON.stringify(v)
1533
- }, checker, waitTime)
1534
- }
1535
- }
1536
- }}
1537
- />
1670
+ /*
1671
+ type == TYPES.select_tree?
1672
+ <SelectTree disabled={disabled} options={options as SelectTreeOptionWithChildren[]}
1673
+ onChange={onChange}
1674
+ onBlur={(e: SelectTreeEvent) => {
1675
+ const { currentNode, selectedNodes } = e
1676
+ if(!disabled && onCheckInfo) {
1677
+ const v = "currentNode"
1678
+ const { checker, waitTime } = onCheckInfo(v)
1679
+ //only check input in "onBlur" if waitTime is not set or equal to zero.
1680
+ // This is good in validating an input as it looses focus when the user moves to another,
1681
+ // input field
1682
+ if(!waitTime) {
1683
+ handleInputCheck(() => v, (checkedValue) => {
1684
+ return JSON.stringify(checkedValue) === JSON.stringify(v)
1685
+ }, checker, waitTime)
1686
+ }
1687
+ }
1688
+ }}
1689
+ />
1538
1690
  :*/
1539
1691
  type == TYPES.none ? null : /*#__PURE__*/React.createElement(InputGroup, null, iconLeft ? /*#__PURE__*/React.createElement(InputLeftElement, {
1540
1692
  children: iconLeft
@@ -2410,17 +2562,52 @@ var AccessTokenDoor = function AccessTokenDoor(_a) {
2410
2562
  }, authenticating ? "Please wait..." : "Confirm Operation")));
2411
2563
  };
2412
2564
 
2565
+ function _typeof(o) {
2566
+ "@babel/helpers - typeof";
2567
+
2568
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
2569
+ return typeof o;
2570
+ } : function (o) {
2571
+ return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
2572
+ }, _typeof(o);
2573
+ }
2574
+
2413
2575
  var MAX_RETRIES$1 = 5;
2414
2576
  var CACHE_KEY$1 = "sdk_config-metadata";
2577
+ var CACHE_BUST_KEY$1 = "_fb_cache_bust";
2415
2578
  // let sdkConfigCache: SdkConfig | null = null;
2416
2579
  // let fetchPromise: Promise<SdkConfig | null> | null = null;
2417
- var defaultFactoryData$1 = '{"etag":"W/\\"cfb2c25c60051f77c56bc81c008b2d80\\"","lastModified":"Thu, 15 May 2025 01:41:21 GMT","cachedData":{"aff_pct":10,"app_version_code":19,"contact_link":"https://t.me/frontbacked","group_link":"https://t.me/frontbacked","group_links":["https://t.me/frontbacked"],"min_deposit":7,"min_vendor_deposit":7,"parent_site_home":"https://hackbaker.com","ttl_days":2,"vendors":[{"name":"JinmiEx","number":"+2348130729216","freq":1}]}}';
2580
+ var addCacheBust$1 = function addCacheBust(url) {
2581
+ try {
2582
+ var parsedUrl = new URL(url);
2583
+ parsedUrl.searchParams.set(CACHE_BUST_KEY$1, Date.now().toString());
2584
+ return parsedUrl.toString();
2585
+ } catch (err) {
2586
+ return url;
2587
+ }
2588
+ };
2589
+ var readCachedMetadata$1 = function readCachedMetadata() {
2590
+ if (!isBrowser()) return null;
2591
+ try {
2592
+ var cachedMetadata = localStorage.getItem(CACHE_KEY$1);
2593
+ return cachedMetadata ? JSON.parse(cachedMetadata) : null;
2594
+ } catch (err) {
2595
+ localStorage.removeItem(CACHE_KEY$1);
2596
+ return null;
2597
+ }
2598
+ };
2418
2599
  var useSdkConfig = function useSdkConfig(appConfig) {
2419
2600
  var _a = useState(isBrowser() ? window.sdkConfigCache : null),
2420
2601
  sdkConfig = _a[0],
2421
2602
  setSdkConfig = _a[1];
2422
2603
  function parseVendors(vendorsAsTexts) {
2423
- return vendorsAsTexts.map(function (text) {
2604
+ if (vendorsAsTexts === void 0) {
2605
+ vendorsAsTexts = [];
2606
+ }
2607
+ if (!Array.isArray(vendorsAsTexts)) return [];
2608
+ return vendorsAsTexts.map(function (vendor) {
2609
+ if (typeof vendor !== "string") return vendor;
2610
+ var text = vendor;
2424
2611
  var _a = text.split(','),
2425
2612
  name = _a[0],
2426
2613
  number = _a[1],
@@ -2436,49 +2623,38 @@ var useSdkConfig = function useSdkConfig(appConfig) {
2436
2623
  if (!(appConfig === null || appConfig === void 0 ? void 0 : appConfig.r2Domain)) return;
2437
2624
  if (window.sdkConfigCache) {
2438
2625
  setSdkConfig(window.sdkConfigCache);
2439
- return;
2440
2626
  }
2441
2627
  if (!window.fetchPromise) {
2442
2628
  window.fetchPromise = function () {
2443
2629
  return __awaiter(void 0, void 0, void 0, function () {
2444
- var attempts, headers, cachedMetadata, _a, etag, lastModified, cachedData, response, config, err_1;
2445
- var _b;
2446
- return __generator(this, function (_c) {
2447
- switch (_c.label) {
2630
+ var attempts, cachedMetadata, cachedData, response, config, err_1;
2631
+ var _a;
2632
+ return __generator(this, function (_b) {
2633
+ switch (_b.label) {
2448
2634
  case 0:
2449
2635
  attempts = 0;
2450
- headers = {};
2451
- cachedMetadata = localStorage.getItem(CACHE_KEY$1) || defaultFactoryData$1;
2636
+ cachedMetadata = readCachedMetadata$1();
2452
2637
  if (cachedMetadata) {
2453
- _a = JSON.parse(cachedMetadata), etag = _a.etag, lastModified = _a.lastModified, cachedData = _a.cachedData;
2638
+ cachedData = cachedMetadata.cachedData;
2454
2639
  if (cachedData) {
2455
2640
  window.sdkConfigCache = cachedData;
2456
2641
  setSdkConfig(cachedData);
2457
2642
  //return cachedData;
2458
2643
  }
2459
-
2460
- if (etag) headers["If-None-Match"] = etag;
2461
- if (lastModified) headers["If-Modified-Since"] = lastModified;
2462
2644
  }
2463
- consoleLog("useSdkConfig.headers: ", headers);
2464
- _c.label = 1;
2645
+
2646
+ consoleLog("useSdkConfig.refreshing");
2647
+ _b.label = 1;
2465
2648
  case 1:
2466
2649
  if (!(attempts < MAX_RETRIES$1)) return [3 /*break*/, 6];
2467
- _c.label = 2;
2650
+ _b.label = 2;
2468
2651
  case 2:
2469
- _c.trys.push([2, 4,, 5]);
2470
- return [4 /*yield*/, axios.get("https://".concat(appConfig.r2Domain, "/sdk_config.json"), {
2471
- headers: headers,
2472
- validateStatus: function validateStatus(status) {
2473
- return status < 500;
2474
- } // Accept 304 Not Modified
2475
- })];
2476
-
2652
+ _b.trys.push([2, 4,, 5]);
2653
+ return [4 /*yield*/, axios.get(addCacheBust$1("https://".concat(appConfig.r2Domain, "/sdk_config.json")))];
2477
2654
  case 3:
2478
- response = _c.sent();
2479
- if (response.status === 304) {
2480
- consoleLog("useSdkConfig.notModied: ", response.status);
2481
- return [2 /*return*/, window.sdkConfigCache];
2655
+ response = _b.sent();
2656
+ if (_typeof(response.data) !== "object") {
2657
+ throw new Error("Invalid SDK config response");
2482
2658
  }
2483
2659
  config = response.data;
2484
2660
  config.vendors = parseVendors(response.data.vendors);
@@ -2488,13 +2664,14 @@ var useSdkConfig = function useSdkConfig(appConfig) {
2488
2664
  localStorage.setItem(CACHE_KEY$1, JSON.stringify({
2489
2665
  etag: response.headers["etag"],
2490
2666
  lastModified: response.headers["last-modified"],
2667
+ cachedAt: Date.now(),
2491
2668
  cachedData: config
2492
2669
  }));
2493
2670
  consoleLog("useSdkConfig.refreshed: ", response.data, " at ".concat(response.headers["last-modified"], ", with etag, ").concat(response.headers["etag"]));
2494
2671
  return [2 /*return*/, config];
2495
2672
  case 4:
2496
- err_1 = _c.sent();
2497
- if (((_b = err_1.response) === null || _b === void 0 ? void 0 : _b.status) === 404) {
2673
+ err_1 = _b.sent();
2674
+ if (((_a = err_1.response) === null || _a === void 0 ? void 0 : _a.status) === 404) {
2498
2675
  consoleLog("Error fetching SDK config: Resource not found (404): ", err_1);
2499
2676
  return [3 /*break*/, 6];
2500
2677
  }
@@ -2506,11 +2683,14 @@ var useSdkConfig = function useSdkConfig(appConfig) {
2506
2683
  case 5:
2507
2684
  return [3 /*break*/, 1];
2508
2685
  case 6:
2686
+ if (window.sdkConfigCache) return [2 /*return*/, window.sdkConfigCache];
2509
2687
  return [2 /*return*/, null];
2510
2688
  }
2511
2689
  });
2512
2690
  });
2513
- }();
2691
+ }()["finally"](function () {
2692
+ window.fetchPromise = null;
2693
+ });
2514
2694
  }
2515
2695
  window.fetchPromise.then(function (config) {
2516
2696
  if (config) setSdkConfig(config);
@@ -2752,17 +2932,20 @@ var DownloadType = function DownloadType(_a) {
2752
2932
  }
2753
2933
  }, [adminInfo]);
2754
2934
  useEffect(function () {
2935
+ var _a, _b, _c, _d;
2755
2936
  if (onGetTool && toolId) {
2756
2937
  var tool = onGetTool(toolId);
2757
2938
  consoleLog("DownloadType.setDocRules", tool);
2758
- setDocRules(!tool ? null : __assign(__assign({}, docRules || {}), {
2759
- allow_freemium: (tool === null || tool === void 0 ? void 0 : tool.allow_freemium) || true,
2760
- create_price: (tool === null || tool === void 0 ? void 0 : tool.create_price) || 0,
2761
- update_price: (tool === null || tool === void 0 ? void 0 : tool.update_price) || 0,
2762
- create_price_is_monthly: (tool === null || tool === void 0 ? void 0 : tool.create_price_is_monthly) || false,
2939
+ setDocRules(!tool ? null : {
2940
+ allow_freemium: (_a = tool === null || tool === void 0 ? void 0 : tool.allow_freemium) !== null && _a !== void 0 ? _a : true,
2941
+ create_price: (_b = tool === null || tool === void 0 ? void 0 : tool.create_price) !== null && _b !== void 0 ? _b : 0,
2942
+ update_price: (_c = tool === null || tool === void 0 ? void 0 : tool.update_price) !== null && _c !== void 0 ? _c : 0,
2943
+ create_price_is_monthly: (_d = tool === null || tool === void 0 ? void 0 : tool.create_price_is_monthly) !== null && _d !== void 0 ? _d : false,
2763
2944
  yearly_price: tool === null || tool === void 0 ? void 0 : tool.yearly_price,
2764
2945
  quarterly_price: tool === null || tool === void 0 ? void 0 : tool.quarterly_price
2765
- }));
2946
+ });
2947
+ } else {
2948
+ setDocRules(null);
2766
2949
  }
2767
2950
  }, [onGetTool, toolId]);
2768
2951
  var download = function download() {
@@ -2901,7 +3084,7 @@ var DownloadType = function DownloadType(_a) {
2901
3084
  setAutoProcessOn(false);
2902
3085
  }
2903
3086
  }
2904
- }, [docRules]);
3087
+ }, [docRules, permission.isToolsEditor, toolId, updateMessage, removeFreemiumBeforeUpdate, renewSubscription, isFreemium]);
2905
3088
  if (permission.isToolsEditor && toolId == "other_tools" || !toolId || !onGetTool || !freeTitle || !freeMessage || !paidTitle || !paidMessage) return null;
2906
3089
  return /*#__PURE__*/React.createElement(DrawerPop, {
2907
3090
  placement: "bottom",
@@ -2931,12 +3114,12 @@ var DownloadType = function DownloadType(_a) {
2931
3114
  //Or it's not an update(it's a create) but create price is 0
2932
3115
  //Or it's an update but update price is 0
2933
3116
  //Or it's an update for subscription renewal
2934
- /*!docRules ||*/ /*
2935
- (updateMessage && removeFreemiumBeforeUpdate && docRules.create_price > 0) ||
2936
- (!updateMessage && !docRules.allow_freemium) ||
2937
- (!updateMessage && docRules.create_price == 0) ||
2938
- (updateMessage && docRules.update_price == 0) ||
2939
- (updateMessage && renewSubscription) ||
3117
+ /*!docRules ||*/ /*
3118
+ (updateMessage && removeFreemiumBeforeUpdate && docRules.create_price > 0) ||
3119
+ (!updateMessage && !docRules.allow_freemium) ||
3120
+ (!updateMessage && docRules.create_price == 0) ||
3121
+ (updateMessage && docRules.update_price == 0) ||
3122
+ (updateMessage && renewSubscription) ||
2940
3123
  (updateMessage && renewSubscription)*/
2941
3124
  //(!updateMessage && docRules.create_price == 0) || (updateMessage && !docRules.yearly_price && !docRules.quarterly_price)?
2942
3125
  autoProcessOn || !docRules ? /*#__PURE__*/React.createElement(PleaseWaitForX, null) : /*#__PURE__*/React.createElement(React.Fragment, null, updateMessage && !docRules.yearly_price && !docRules.quarterly_price ? /*#__PURE__*/React.createElement(Text, {
@@ -2986,11 +3169,11 @@ var DownloadType = function DownloadType(_a) {
2986
3169
  }))));
2987
3170
  };
2988
3171
 
2989
- /**
2990
- * Removes a specific query string parameter from a URL.
2991
- * @param {string} url - The original URL.
2992
- * @param {string} queryString - The query string parameter to remove.
2993
- * @returns {string} - The updated URL without the specified query string parameter.
3172
+ /**
3173
+ * Removes a specific query string parameter from a URL.
3174
+ * @param {string} url - The original URL.
3175
+ * @param {string} queryString - The query string parameter to remove.
3176
+ * @returns {string} - The updated URL without the specified query string parameter.
2994
3177
  */
2995
3178
  function removeQueryString(url, queryString) {
2996
3179
  try {
@@ -3005,12 +3188,12 @@ function removeQueryString(url, queryString) {
3005
3188
  return url; // Return the original URL if there's an error
3006
3189
  }
3007
3190
  }
3008
- /**
3009
- * Converts an array of objects to a map using a specified attribute as the key.
3010
- *
3011
- * @param {Array<Object>} arr - The array of objects to be converted.
3012
- * @param {string} attr - The attribute to use as the key for the mapping.
3013
- * @returns {Object} - An object mapping each unique attribute value to its corresponding item.
3191
+ /**
3192
+ * Converts an array of objects to a map using a specified attribute as the key.
3193
+ *
3194
+ * @param {Array<Object>} arr - The array of objects to be converted.
3195
+ * @param {string} attr - The attribute to use as the key for the mapping.
3196
+ * @returns {Object} - An object mapping each unique attribute value to its corresponding item.
3014
3197
  */
3015
3198
  function arrayToMap(attr, arr, keyParser) {
3016
3199
  return arr.reduce(function (map, item) {
@@ -3036,9 +3219,9 @@ var rmUpdates = function rmUpdates(url) {
3036
3219
 
3037
3220
  var MAX_RETRIES = 5;
3038
3221
  var CACHE_KEY = "tools-cache-metadata";
3222
+ var CACHE_BUST_KEY = "_fb_cache_bust";
3039
3223
  // let toolsCache: ToolsData | null = null;
3040
3224
  // let toolsFetchPromise: Promise<ToolsData | null> | null = null;
3041
- var defaultFactoryData = '{"etag":"W/\\"97cce03e8c6f6c8092dfac11069679e7\\"","lastModified":"Fri, 23 May 2025 17:24:27 GMT","cachedData":{"totalUpdates":1,"lastUpdatedOn":"Fri, 23 May 2025 17:24:18 GMT","tools":[{"id":"U8SL1BvlIb1nxj4JNCNX","siteUrl":"/bank","mobileVideoUrl":null,"is_static":true,"desktopVideoUrl":null,"isActive":true,"isHidden":false,"update_price":0.1,"allow_freemium":true,"create_price_is_monthly":true,"rank":1,"icon":"Building","siteLogoUrl":"/templates/tool-U8SL1BvlIb1nxj4JNCNX.jpg","authorId":"f6dcBr3nBJQNLeRwN1ZeHYTZqGC2","youtube":null,"name":"Online Banking Website","chat_supported":true,"create_price":20000,"quarterly_price":50000,"yearly_price":150000,"create_price_discount":0,"description":"Create an online banking website for your content. No more building a custom online banking website from scratch every time you need to film a banking scene.","x":["authorId,uid,0,0,false,true,false","createdAt,current_time,0,0,false,true,false","updatedAt,current_time,0,0,true,true,true","profilePhoto,string,0,300,true,true,false","email,string,0,64,true,true,false","phone,string,0,32,true,true,false","accountType,string,0,64,true,true,false","gender,string,0,64,true,true,false","maritalStatus,string,0,64,true,true,false","dob,string,0,16,true,true,false","password,string,6,16,true,true,false","pin,number,1000,9999,true,true,false","address,string,0,128,true,true,false","occupation,string,0,64,true,true,false","accountNumber_username,number,9000000000,9999999999,false,true,false","fullname,string,0,64,true,true,false","currencySymbol,string,0,64,true,true,false","disableAccount,boolean,0,8,true,true,false","accountBalance,number,0,999999999999999,true,false,false","autoRenewSubscription,boolean,0,8,true,true,false","credits,array:string:1:200,0,10,true,false,false","debits,array:string:1:200,0,10,true,false,false","totalCredits,number,0,999999999999999,true,false,false","totalDebits,number,0,999999999999999,true,false,false","disableAccountError,string,1,500,true,false,false","noTxGeneration,boolean,0,8,false,false,false","isHidden,boolean,1,8,true,false,false","isActive,boolean,1,8,true,false,false","txProcessingDuration,string,1,64,true,true,false","isInActive,boolean,0,8,true,false,false"],"tool_version_code":7},{"id":"0QZLQQKVTRV3Q6SFAIEA","authorId":"f6dcBr3nBJQNLeRwN1ZeHYTZqGC2","createdAt":{"_seconds":1733770038,"_nanoseconds":796000000},"is_static":false,"isActive":true,"is_freemium":true,"icon":"ShippingFast","isHidden":false,"editables":"Shipping_Status@small.select, error_message.textarea, expected_arrival_date.date","templates_url":"/templates/templates-awsuv5ba.json?updates=23","youtube":null,"mobileVideoUrl":null,"desktopVideoUrl":null,"allow_freemium":true,"chat_supported":true,"create_price":10000,"message":"ID_TITLE == Tracking ID\\nLINK == zendcargo.com\\nCONTENT == Track your shipment using the tracking ID above at the tracking website: {LINK}.","description":"Create a shipping invoice with a tracking website for your content. No more building a custom shipping site from scratch every time you need to film a shipping scene.","update_price":200,"updatedAt":{"_seconds":1746816982,"_nanoseconds":404000000},"rank":2,"name":"Shipping","parent":"","x":["authorId,uid,0,0,false,true,false","createdAt,current_time,0,0,false,true,false","expectedArrivalDate,time,0,0,true,true,false","invoiceNumber,string,1,16,false,true,false","packageContent,string,1,64,false,true,false","packageDestinationAddress,string,1,64,false,true,false","packageDestinationEmail,string,1,256,false,true,false","packageDestinationPhone,string,1,16,false,true,false","packageRecipientName,string,1,128,false,true,false","packageWeight,string,1,32,false,true,false","senderEmail,string,1,256,false,true,false","senderName,string,1,128,false,true,false","shipmentDate,time,0,0,false,true,false","shipmentFee,string,0,32,false,true,false","shippingStatus,string,1,32,true,true,false","updatedAt,current_time,0,0,true,true,true","costCurrency,string,0,64,false,false,false","errorMessage,string,1,500,true,false,false"],"tool_version_code":7,"freemiumDownloadMessage":"The shipping invoice will have watermark. The tracking website will also have a \\"fake tracking\\" message.","premiumDownloadMessage":"The shipping invoice will be clean with no watermark. The tracking website will also be clean with no \\"fake tracking\\" message.","templates":[{"id":"hwd7x6ou","name":"Shipping Invoice with Tracking Website","logo":"https://r2.softbaker.com/templates/templates-awsuv5ba-hwd7x6ou-logo.jpeg","data_url":"https://r2.frontbacked.com/templates/templates-awsuv5ba-hwd7x6ou-data.json?updates=1","is_default":true,"split_on_download":false,"thumbnail":"https://r2.frontbacked.com/templates/tools-awsuv5ba-hwd7x6ou-thumbnail.jpg?updates=1&tct=1748021058263"}]},{"id":"5vCsgJJVsFYhV4dZYQdI","mobileVideoUrl":null,"is_static":true,"desktopVideoUrl":null,"name":"Invoice","isActive":true,"isHidden":false,"allow_freemium":true,"siteUrl":"/invoice","siteLogoUrl":"/templates/tool-5vCsgJJVsFYhV4dZYQdI.jpg","authorId":"f6dcBr3nBJQNLeRwN1ZeHYTZqGC2","youtube":null,"description":"Create a payment invoice easily.","rank":3,"update_price":200,"create_price":5000,"x":["authorId,uid,0,0,false,true,false","createdAt,current_time,0,0,false,true,false","updatedAt,current_time,0,0,true,true,true","companyName,string,2,64,false,true,false","companyAddress,string,2,64,false,true,false","customerName,string,2,64,false,true,false","customerAddress,string,2,64,false,true,false","invoiceNumber,string,2,64,false,true,false","date,time,0,0,false,true,false","currency,string,2,64,false,true,false","items,object_array:{description@string_1_90|quantity@number_1_1000000000000000|price@number_1_1000000000000000},1,6,false,true,false","paymentDetails,string,2,256,false,false,false","vat,number,0,99,false,true,false","logo,string,0,64,false,false,false","waterMarkWithLogo,boolean,0,64,false,true,false","grayScaleWaterMark,boolean,0,64,false,true,false"],"tool_version_code":2},{"id":"tDYsSHDnF58hFCf3nUTk","mobileVideoUrl":null,"is_static":true,"desktopVideoUrl":null,"icon":"Coins","authorId":"f6dcBr3nBJQNLeRwN1ZeHYTZqGC2","youtube":null,"name":"Face Swap Video Call","siteUrl":"/face-swap-video-call","isActive":false,"siteLogoUrl":"/templates/tool-tDYsSHDnF58hFCf3nUTk.jpg?v=2","rank":4,"isHidden":false},{"id":"XFXW1s8LlhiJnZKPbdWX","siteUrl":"/invest","mobileVideoUrl":null,"is_static":true,"desktopVideoUrl":null,"isActive":false,"icon":"MoneyBillAlt","siteLogoUrl":"/templates/tool-XFXW1s8LlhiJnZKPbdWX.jpg","authorId":"f6dcBr3nBJQNLeRwN1ZeHYTZqGC2","youtube":null,"name":"Investment Website","rank":5,"isHidden":false}]}}';
3042
3225
  var setR2Host = function setR2Host(url, r2Domain) {
3043
3226
  if (!url) return url;
3044
3227
  if (url.startsWith('/')) {
@@ -3055,11 +3238,42 @@ var setR2Host = function setR2Host(url, r2Domain) {
3055
3238
  }
3056
3239
  };
3057
3240
 
3241
+ var addCacheBust = function addCacheBust(url) {
3242
+ try {
3243
+ var parsedUrl = new URL(url);
3244
+ parsedUrl.searchParams.set(CACHE_BUST_KEY, Date.now().toString());
3245
+ return parsedUrl.toString();
3246
+ } catch (err) {
3247
+ return url;
3248
+ }
3249
+ };
3250
+ var readCachedMetadata = function readCachedMetadata() {
3251
+ if (!isBrowser()) return null;
3252
+ try {
3253
+ var cachedMetadata = localStorage.getItem(CACHE_KEY);
3254
+ return cachedMetadata ? JSON.parse(cachedMetadata) : null;
3255
+ } catch (err) {
3256
+ localStorage.removeItem(CACHE_KEY);
3257
+ return null;
3258
+ }
3259
+ };
3260
+ var readCachedToolsData = function readCachedToolsData() {
3261
+ if (!isBrowser()) return null;
3262
+ if (window.toolsCache) return window.toolsCache;
3263
+ var cachedMetadata = readCachedMetadata();
3264
+ var cachedData = cachedMetadata === null || cachedMetadata === void 0 ? void 0 : cachedMetadata.cachedData;
3265
+ if (cachedData) {
3266
+ window.toolsCache = cachedData;
3267
+ return cachedData;
3268
+ }
3269
+ return null;
3270
+ };
3058
3271
  var useTools = function useTools(config) {
3059
- var _a = useState(isBrowser() ? window.toolsCache : null),
3272
+ var cachedToolsData = readCachedToolsData();
3273
+ var _a = useState(cachedToolsData),
3060
3274
  data = _a[0],
3061
3275
  setData = _a[1];
3062
- var _b = useState(!isBrowser() || !window.toolsCache),
3276
+ var _b = useState(!cachedToolsData),
3063
3277
  loading = _b[0],
3064
3278
  setLoading = _b[1];
3065
3279
  var _c = useState(null),
@@ -3073,63 +3287,48 @@ var useTools = function useTools(config) {
3073
3287
  setToolsByTemplatesUrl = _e[1];
3074
3288
  useEffect(function () {
3075
3289
  if (!(config === null || config === void 0 ? void 0 : config.r2Domain)) return;
3076
- if (window.toolsCache) {
3077
- setData(window.toolsCache);
3290
+ var cachedToolsData = readCachedToolsData();
3291
+ if (cachedToolsData) {
3292
+ setData(cachedToolsData);
3078
3293
  setLoading(false);
3079
- consoleLog("useTools.returns as toolsCache already exist: ", window.toolsCache);
3080
- return;
3294
+ consoleLog("useTools.returns cached tools data: ", cachedToolsData);
3081
3295
  }
3082
3296
  if (!window.toolsFetchPromise) {
3083
3297
  window.toolsFetchPromise = function () {
3084
3298
  return __awaiter(void 0, void 0, void 0, function () {
3085
- var attempts, headers, cachedMetadata, _a, etag, lastModified, cachedData, response, err_1;
3086
- var _b;
3299
+ var attempts, cachedData, response, err_1;
3300
+ var _a, _b;
3087
3301
  return __generator(this, function (_c) {
3088
3302
  switch (_c.label) {
3089
3303
  case 0:
3090
3304
  attempts = 0;
3091
- headers = {};
3092
- cachedMetadata = localStorage.getItem(CACHE_KEY) || defaultFactoryData;
3093
- if (cachedMetadata) {
3094
- _a = JSON.parse(cachedMetadata), etag = _a.etag, lastModified = _a.lastModified, cachedData = _a.cachedData;
3095
- if (cachedData) {
3096
- window.toolsCache = cachedData;
3097
- setData(cachedData);
3098
- setLoading(false);
3099
- //return cachedData;
3100
- }
3101
-
3102
- if (etag) headers["If-None-Match"] = etag;
3103
- if (lastModified) headers["If-Modified-Since"] = lastModified;
3305
+ cachedData = readCachedToolsData();
3306
+ if (cachedData) {
3307
+ setData(cachedData);
3308
+ setLoading(false);
3104
3309
  }
3105
- consoleLog("useTools.headers: ", headers);
3310
+ consoleLog("useTools.refreshing");
3106
3311
  _c.label = 1;
3107
3312
  case 1:
3108
3313
  if (!(attempts < MAX_RETRIES)) return [3 /*break*/, 6];
3109
3314
  _c.label = 2;
3110
3315
  case 2:
3111
3316
  _c.trys.push([2, 4,, 5]);
3112
- return [4 /*yield*/, axios.get("https://".concat(config.r2Domain, "/templates/tools.json"), {
3113
- headers: headers,
3114
- validateStatus: function validateStatus(status) {
3115
- return status < 500;
3116
- } // Accept 304 Not Modified
3117
- })];
3118
-
3317
+ return [4 /*yield*/, axios.get(addCacheBust("https://".concat(config.r2Domain, "/templates/tools.json")))];
3119
3318
  case 3:
3120
3319
  response = _c.sent();
3121
- if (response.status === 304) {
3122
- setLoading(false);
3123
- consoleLog("useTools.notModied: ", response.status);
3124
- return [2 /*return*/, window.toolsCache];
3320
+ if (_typeof(response.data) !== "object" || !Array.isArray((_a = response.data) === null || _a === void 0 ? void 0 : _a.tools)) {
3321
+ throw new Error("Invalid tools response");
3125
3322
  }
3126
3323
  window.toolsCache = response.data;
3127
3324
  setData(response.data);
3128
3325
  setError(null);
3326
+ setLoading(false);
3129
3327
  // Save cache metadata
3130
3328
  localStorage.setItem(CACHE_KEY, JSON.stringify({
3131
3329
  etag: response.headers["etag"],
3132
3330
  lastModified: response.headers["last-modified"],
3331
+ cachedAt: Date.now(),
3133
3332
  cachedData: response.data
3134
3333
  }));
3135
3334
  consoleLog("useTools.refreshed: ", response.data, " at ".concat(response.headers["last-modified"], ", with etag, ").concat(response.headers["etag"]));
@@ -3137,23 +3336,30 @@ var useTools = function useTools(config) {
3137
3336
  case 4:
3138
3337
  err_1 = _c.sent();
3139
3338
  if (((_b = err_1.response) === null || _b === void 0 ? void 0 : _b.status) === 404) {
3140
- setError("Resource not found (404)");
3339
+ if (!window.toolsCache) setError("Resource not found (404)");
3141
3340
  return [3 /*break*/, 6];
3142
3341
  }
3143
3342
  attempts++;
3144
3343
  if (attempts === MAX_RETRIES) {
3145
- setError("Failed to fetch data after multiple attempts");
3344
+ if (!window.toolsCache) setError("Failed to fetch data after multiple attempts");
3146
3345
  }
3147
3346
  return [3 /*break*/, 5];
3148
3347
  case 5:
3149
3348
  return [3 /*break*/, 1];
3150
3349
  case 6:
3350
+ if (window.toolsCache) {
3351
+ setError(null);
3352
+ setLoading(false);
3353
+ return [2 /*return*/, window.toolsCache];
3354
+ }
3151
3355
  setLoading(false);
3152
3356
  return [2 /*return*/, null];
3153
3357
  }
3154
3358
  });
3155
3359
  });
3156
- }();
3360
+ }()["finally"](function () {
3361
+ window.toolsFetchPromise = null;
3362
+ });
3157
3363
  }
3158
3364
  window.toolsFetchPromise.then(function (result) {
3159
3365
  if (result) setData(result);