use-frontbacked 5.1.4 → 5.1.6

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 +396 -200
  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 +396 -200
  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 +83 -83
package/dist/cjs/index.js CHANGED
@@ -265,6 +265,152 @@ var consoleLog = function consoleLog() {
265
265
  console.log.apply(console, args);
266
266
  }
267
267
  };
268
+ var isAppleMobileDevice = function isAppleMobileDevice() {
269
+ if (typeof navigator === "undefined") return false;
270
+ var userAgent = navigator.userAgent || "";
271
+ var platform = navigator.platform || "";
272
+ var maxTouchPoints = navigator.maxTouchPoints || 0;
273
+ return /iPad|iPhone|iPod/i.test(userAgent) || platform === "MacIntel" && maxTouchPoints > 1;
274
+ };
275
+ var openBlobInBrowser = function openBlobInBrowser(blob, fileName, openInNewTab) {
276
+ if (openInNewTab === void 0) {
277
+ openInNewTab = false;
278
+ }
279
+ var objectUrl = URL.createObjectURL(blob);
280
+ var downloadLink = document.createElement("a");
281
+ downloadLink.href = objectUrl;
282
+ downloadLink.rel = "noopener";
283
+ downloadLink.style.display = "none";
284
+ if (openInNewTab) {
285
+ downloadLink.target = "_blank";
286
+ } else {
287
+ downloadLink.download = fileName;
288
+ }
289
+ document.body.appendChild(downloadLink);
290
+ downloadLink.click();
291
+ document.body.removeChild(downloadLink);
292
+ setTimeout(function () {
293
+ return URL.revokeObjectURL(objectUrl);
294
+ }, 30000);
295
+ };
296
+ var shareBlob = function shareBlob(blob, fileName) {
297
+ return __awaiter(void 0, void 0, void 0, function () {
298
+ var shareApi, canShare, file, shareData;
299
+ return __generator(this, function (_a) {
300
+ switch (_a.label) {
301
+ case 0:
302
+ shareApi = typeof navigator !== "undefined" ? navigator.share : null;
303
+ canShare = typeof navigator !== "undefined" ? navigator.canShare : null;
304
+ if (!shareApi || typeof File === "undefined") return [2 /*return*/, false];
305
+ file = new File([blob], fileName, {
306
+ type: blob.type || "application/octet-stream"
307
+ });
308
+ shareData = {
309
+ files: [file],
310
+ title: fileName
311
+ };
312
+ if (canShare && !canShare.call(navigator, shareData)) return [2 /*return*/, false];
313
+ return [4 /*yield*/, shareApi.call(navigator, shareData)];
314
+ case 1:
315
+ _a.sent();
316
+ return [2 /*return*/, true];
317
+ }
318
+ });
319
+ });
320
+ };
321
+ var promptAppleMobileSave = function promptAppleMobileSave(blob, fileName) {
322
+ return new Promise(function (resolve, reject) {
323
+ var overlay = document.createElement("div");
324
+ overlay.setAttribute("role", "dialog");
325
+ overlay.setAttribute("aria-modal", "true");
326
+ 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(";");
327
+ var dialog = document.createElement("div");
328
+ 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(";");
329
+ var title = document.createElement("div");
330
+ title.textContent = "File ready";
331
+ title.style.cssText = "font-size:17px;font-weight:700;margin-bottom:8px;";
332
+ var body = document.createElement("div");
333
+ body.textContent = "Choose where to save this file.";
334
+ body.style.cssText = "font-size:14px;line-height:1.45;color:#4b5563;margin-bottom:16px;";
335
+ var actions = document.createElement("div");
336
+ actions.style.cssText = "display:flex;gap:10px;justify-content:flex-end;";
337
+ var cancelButton = document.createElement("button");
338
+ cancelButton.type = "button";
339
+ cancelButton.textContent = "Cancel";
340
+ cancelButton.style.cssText = ["border:0", "border-radius:8px", "padding:10px 14px", "background:#f3f4f6", "color:#111827", "font-size:14px", "font-weight:600"].join(";");
341
+ var saveButton = document.createElement("button");
342
+ saveButton.type = "button";
343
+ saveButton.textContent = "Save File";
344
+ saveButton.style.cssText = ["border:0", "border-radius:8px", "padding:10px 14px", "background:#2563eb", "color:#fff", "font-size:14px", "font-weight:700"].join(";");
345
+ var cleanup = function cleanup() {
346
+ document.body.removeChild(overlay);
347
+ };
348
+ cancelButton.onclick = function () {
349
+ cleanup();
350
+ reject(new Error("File save was cancelled."));
351
+ };
352
+ saveButton.onclick = function () {
353
+ return __awaiter(void 0, void 0, void 0, function () {
354
+ var shared, error_1;
355
+ return __generator(this, function (_a) {
356
+ switch (_a.label) {
357
+ case 0:
358
+ saveButton.setAttribute("disabled", "true");
359
+ _a.label = 1;
360
+ case 1:
361
+ _a.trys.push([1, 3,, 4]);
362
+ return [4 /*yield*/, shareBlob(blob, fileName)];
363
+ case 2:
364
+ shared = _a.sent();
365
+ if (!shared) openBlobInBrowser(blob, fileName, true);
366
+ cleanup();
367
+ resolve();
368
+ return [3 /*break*/, 4];
369
+ case 3:
370
+ error_1 = _a.sent();
371
+ cleanup();
372
+ if ((error_1 === null || error_1 === void 0 ? void 0 : error_1.name) === "AbortError") {
373
+ reject(new Error("File save was cancelled."));
374
+ return [2 /*return*/];
375
+ }
376
+
377
+ openBlobInBrowser(blob, fileName, true);
378
+ resolve();
379
+ return [3 /*break*/, 4];
380
+ case 4:
381
+ return [2 /*return*/];
382
+ }
383
+ });
384
+ });
385
+ };
386
+
387
+ actions.appendChild(cancelButton);
388
+ actions.appendChild(saveButton);
389
+ dialog.appendChild(title);
390
+ dialog.appendChild(body);
391
+ dialog.appendChild(actions);
392
+ overlay.appendChild(dialog);
393
+ document.body.appendChild(overlay);
394
+ });
395
+ };
396
+ var downloadBlob = function downloadBlob(blob, fileName) {
397
+ return __awaiter(void 0, void 0, void 0, function () {
398
+ return __generator(this, function (_a) {
399
+ switch (_a.label) {
400
+ case 0:
401
+ if (!isAppleMobileDevice()) return [3 /*break*/, 2];
402
+ return [4 /*yield*/, promptAppleMobileSave(blob, fileName)];
403
+ case 1:
404
+ _a.sent();
405
+ return [2 /*return*/];
406
+ case 2:
407
+ openBlobInBrowser(blob, fileName);
408
+ return [2 /*return*/];
409
+ }
410
+ });
411
+ });
412
+ };
413
+
268
414
  var downloadSvgAsImage = function downloadSvgAsImage(svgString, format, fileName) {
269
415
  if (format === void 0) {
270
416
  format = 'png';
@@ -278,39 +424,48 @@ var downloadSvgAsImage = function downloadSvgAsImage(svgString, format, fileName
278
424
  });
279
425
  var svgUrl = URL.createObjectURL(svgBlob);
280
426
  var img = new Image();
427
+ img.crossOrigin = "anonymous";
281
428
  img.onload = function () {
282
- var canvas = document.createElement('canvas');
283
- canvas.width = img.width;
284
- canvas.height = img.height;
285
- var context = canvas.getContext('2d');
286
- if (context) {
287
- context.drawImage(img, 0, 0);
288
- var dataUrl = canvas.toDataURL("image/".concat(format));
289
- var imageBlob = dataURLToBlob(dataUrl);
290
- if (isiPhone()) {
291
- // Workaround for iPhone browsers
292
- var binaryData = [imageBlob];
293
- var iphoneBlob = new Blob(binaryData, {
294
- type: "image/".concat(format)
295
- });
296
- var iphoneUrl = URL.createObjectURL(iphoneBlob);
297
- var downloadLink = document.createElement('a');
298
- downloadLink.href = iphoneUrl;
299
- downloadLink.download = "".concat(fileName, ".").concat(format);
300
- downloadLink.click();
301
- URL.revokeObjectURL(iphoneUrl);
302
- resolve(iphoneUrl);
303
- } else {
304
- // For other browsers
305
- var downloadLink = document.createElement('a');
306
- downloadLink.href = dataUrl;
307
- downloadLink.download = "".concat(fileName, ".").concat(format);
308
- downloadLink.click();
309
- resolve(dataUrl);
310
- }
311
- } else {
312
- reject(new Error("Unsupported Browser. Please try to download from another browser."));
313
- }
429
+ return __awaiter(this, void 0, void 0, function () {
430
+ var canvas, context, dataUrl, imageBlob, error_2;
431
+ return __generator(this, function (_a) {
432
+ switch (_a.label) {
433
+ case 0:
434
+ _a.trys.push([0, 4,, 5]);
435
+ canvas = document.createElement('canvas');
436
+ canvas.width = img.width;
437
+ canvas.height = img.height;
438
+ context = canvas.getContext('2d');
439
+ if (!context) return [3 /*break*/, 2];
440
+ context.drawImage(img, 0, 0);
441
+ dataUrl = canvas.toDataURL("image/".concat(format));
442
+ imageBlob = dataURLToBlob(dataUrl);
443
+ URL.revokeObjectURL(svgUrl);
444
+ return [4 /*yield*/, downloadBlob(imageBlob, "".concat(fileName, ".").concat(format))];
445
+ case 1:
446
+ _a.sent();
447
+ resolve(dataUrl);
448
+ return [3 /*break*/, 3];
449
+ case 2:
450
+ reject(new Error("Unsupported Browser. Please try to download from another browser."));
451
+ _a.label = 3;
452
+ case 3:
453
+ return [3 /*break*/, 5];
454
+ case 4:
455
+ error_2 = _a.sent();
456
+ URL.revokeObjectURL(svgUrl);
457
+ reject(error_2);
458
+ return [3 /*break*/, 5];
459
+ case 5:
460
+ return [2 /*return*/];
461
+ }
462
+ });
463
+ });
464
+ };
465
+
466
+ img.onerror = function () {
467
+ URL.revokeObjectURL(svgUrl);
468
+ reject(new Error("Failed to render the SVG for download."));
314
469
  };
315
470
  img.src = svgUrl;
316
471
  });
@@ -328,9 +483,6 @@ function dataURLToBlob(dataURL) {
328
483
  type: mime
329
484
  });
330
485
  }
331
- function isiPhone() {
332
- return /iPhone/i.test(navigator.userAgent);
333
- }
334
486
  var getColor = function getColor(isDarkMode, colorName) {
335
487
  var color = theme[colorName];
336
488
  if (color) {
@@ -1355,69 +1507,69 @@ var InputBox = function InputBox(_a) {
1355
1507
  return null;
1356
1508
  }
1357
1509
  }))) :
1358
- /*
1359
- type == TYPES.location?
1360
- <LocationPicker disabled={disabled} ref={inputRef} w="100%" h="100%"
1361
- apiKey={apiKey || ""} defaultLatlng={defaultLatlng} geotype={geotype}
1362
- mapToSearchRatio={mapToSearchRatio}
1363
- twoDigitCountryCode={twoDigitCountryCode}
1364
- searchPlaceholder={placeholder as string}
1365
- value={value? {
1366
- name: value.name,
1367
- formatted_address: value.address,
1368
- geometry: {
1369
- location: {lat: () => value.position.lat, lng: () => value.position.lng},
1370
- viewport: {}
1371
- }
1372
- } : null}
1373
- onChange={(l) => {
1374
- const v = {
1375
- name: l.name,
1376
- address: l.formatted_address,
1377
- position: {
1378
- lat: l.geometry.location.lat(),
1379
- lng: l.geometry.location.lng()
1380
- }
1381
- }
1382
- if(!disabled && onChange) {
1383
- onChange(v)
1384
- }
1385
- if(!disabled && onCheckInfo) {
1386
- const { checker, waitTime } = onCheckInfo(v)
1387
- //only check input in "onChange" if waitTime is greater than zero.
1388
- // This is good in searching a text results as a user types in a search bar,
1389
- // or saving an article on a server as the user types
1390
- if(waitTime > 0) {
1391
- handleInputCheck(() => v, (checkedValue) => {
1392
- return JSON.stringify(checkedValue) === JSON.stringify(v)
1393
- }, checker, waitTime)
1394
- }
1395
- }
1396
-
1397
- }}
1398
- onBlur={(l) => {
1399
- if(!disabled && onCheckInfo) {
1400
- const v = {
1401
- name: l.name,
1402
- address: l.formatted_address,
1403
- position: {
1404
- lat: l.geometry.location.lat(),
1405
- lng: l.geometry.location.lng()
1406
- }
1407
- }
1408
- const { checker, waitTime } = onCheckInfo(v)
1409
- //only check input in "onBlur" if waitTime is not set or equal to zero.
1410
- // This is good in validating an input as it looses focus when the user moves to another,
1411
- // input field
1412
- if(!waitTime) {
1413
- handleInputCheck(() => v, (checkedValue) => {
1414
- return JSON.stringify(checkedValue) === JSON.stringify(v)
1415
- }, checker, waitTime)
1416
- }
1417
- }
1418
- }}
1419
- errorMessage={errorMessage}
1420
- />
1510
+ /*
1511
+ type == TYPES.location?
1512
+ <LocationPicker disabled={disabled} ref={inputRef} w="100%" h="100%"
1513
+ apiKey={apiKey || ""} defaultLatlng={defaultLatlng} geotype={geotype}
1514
+ mapToSearchRatio={mapToSearchRatio}
1515
+ twoDigitCountryCode={twoDigitCountryCode}
1516
+ searchPlaceholder={placeholder as string}
1517
+ value={value? {
1518
+ name: value.name,
1519
+ formatted_address: value.address,
1520
+ geometry: {
1521
+ location: {lat: () => value.position.lat, lng: () => value.position.lng},
1522
+ viewport: {}
1523
+ }
1524
+ } : null}
1525
+ onChange={(l) => {
1526
+ const v = {
1527
+ name: l.name,
1528
+ address: l.formatted_address,
1529
+ position: {
1530
+ lat: l.geometry.location.lat(),
1531
+ lng: l.geometry.location.lng()
1532
+ }
1533
+ }
1534
+ if(!disabled && onChange) {
1535
+ onChange(v)
1536
+ }
1537
+ if(!disabled && onCheckInfo) {
1538
+ const { checker, waitTime } = onCheckInfo(v)
1539
+ //only check input in "onChange" if waitTime is greater than zero.
1540
+ // This is good in searching a text results as a user types in a search bar,
1541
+ // or saving an article on a server as the user types
1542
+ if(waitTime > 0) {
1543
+ handleInputCheck(() => v, (checkedValue) => {
1544
+ return JSON.stringify(checkedValue) === JSON.stringify(v)
1545
+ }, checker, waitTime)
1546
+ }
1547
+ }
1548
+
1549
+ }}
1550
+ onBlur={(l) => {
1551
+ if(!disabled && onCheckInfo) {
1552
+ const v = {
1553
+ name: l.name,
1554
+ address: l.formatted_address,
1555
+ position: {
1556
+ lat: l.geometry.location.lat(),
1557
+ lng: l.geometry.location.lng()
1558
+ }
1559
+ }
1560
+ const { checker, waitTime } = onCheckInfo(v)
1561
+ //only check input in "onBlur" if waitTime is not set or equal to zero.
1562
+ // This is good in validating an input as it looses focus when the user moves to another,
1563
+ // input field
1564
+ if(!waitTime) {
1565
+ handleInputCheck(() => v, (checkedValue) => {
1566
+ return JSON.stringify(checkedValue) === JSON.stringify(v)
1567
+ }, checker, waitTime)
1568
+ }
1569
+ }
1570
+ }}
1571
+ errorMessage={errorMessage}
1572
+ />
1421
1573
  :*/
1422
1574
  type == TYPES.price ? /*#__PURE__*/React__default["default"].createElement(react.VStack, {
1423
1575
  w: "100%",
@@ -1526,26 +1678,26 @@ var InputBox = function InputBox(_a) {
1526
1678
  }
1527
1679
  }, /*#__PURE__*/React__default["default"].createElement(fa.FaPlus, null)))
1528
1680
  }))) :
1529
- /*
1530
- type == TYPES.select_tree?
1531
- <SelectTree disabled={disabled} options={options as SelectTreeOptionWithChildren[]}
1532
- onChange={onChange}
1533
- onBlur={(e: SelectTreeEvent) => {
1534
- const { currentNode, selectedNodes } = e
1535
- if(!disabled && onCheckInfo) {
1536
- const v = "currentNode"
1537
- const { checker, waitTime } = onCheckInfo(v)
1538
- //only check input in "onBlur" if waitTime is not set or equal to zero.
1539
- // This is good in validating an input as it looses focus when the user moves to another,
1540
- // input field
1541
- if(!waitTime) {
1542
- handleInputCheck(() => v, (checkedValue) => {
1543
- return JSON.stringify(checkedValue) === JSON.stringify(v)
1544
- }, checker, waitTime)
1545
- }
1546
- }
1547
- }}
1548
- />
1681
+ /*
1682
+ type == TYPES.select_tree?
1683
+ <SelectTree disabled={disabled} options={options as SelectTreeOptionWithChildren[]}
1684
+ onChange={onChange}
1685
+ onBlur={(e: SelectTreeEvent) => {
1686
+ const { currentNode, selectedNodes } = e
1687
+ if(!disabled && onCheckInfo) {
1688
+ const v = "currentNode"
1689
+ const { checker, waitTime } = onCheckInfo(v)
1690
+ //only check input in "onBlur" if waitTime is not set or equal to zero.
1691
+ // This is good in validating an input as it looses focus when the user moves to another,
1692
+ // input field
1693
+ if(!waitTime) {
1694
+ handleInputCheck(() => v, (checkedValue) => {
1695
+ return JSON.stringify(checkedValue) === JSON.stringify(v)
1696
+ }, checker, waitTime)
1697
+ }
1698
+ }
1699
+ }}
1700
+ />
1549
1701
  :*/
1550
1702
  type == TYPES.none ? null : /*#__PURE__*/React__default["default"].createElement(react.InputGroup, null, iconLeft ? /*#__PURE__*/React__default["default"].createElement(react.InputLeftElement, {
1551
1703
  children: iconLeft
@@ -2166,7 +2318,7 @@ var AuthView = function AuthView(_a) {
2166
2318
  _a.isDarkMode;
2167
2319
  var setUser = _a.setUser,
2168
2320
  config = _a.config;
2169
- var _b = React.useState(true),
2321
+ var _b = React.useState(false),
2170
2322
  showSignIn = _b[0],
2171
2323
  setShowSignIn = _b[1];
2172
2324
  var handleAuthLinkClick = function handleAuthLinkClick(e) {
@@ -2203,7 +2355,7 @@ var AuthView = function AuthView(_a) {
2203
2355
  w: "auto"
2204
2356
  }), /*#__PURE__*/React__default["default"].createElement(react.Text, {
2205
2357
  as: "div",
2206
- fontSize: "14px",
2358
+ fontSize: "1.2rem",
2207
2359
  mb: "0.1rem !important",
2208
2360
  textAlign: "center"
2209
2361
  }, signInTitle), /*#__PURE__*/React__default["default"].createElement(react.Text, {
@@ -2211,12 +2363,12 @@ var AuthView = function AuthView(_a) {
2211
2363
  fontSize: "14px",
2212
2364
  mb: "1.5rem !important",
2213
2365
  textAlign: "center"
2214
- }, "If you don't have an account yet, ", /*#__PURE__*/React__default["default"].createElement(Link, {
2366
+ }, "If you have not registered, ", /*#__PURE__*/React__default["default"].createElement(Link, {
2215
2367
  color: "green.500",
2216
2368
  textDecoration: "underline",
2217
2369
  onClick: handleAuthLinkClick,
2218
2370
  fontWeight: "bold"
2219
- }, "Sign up here."))), /*#__PURE__*/React__default["default"].createElement(SignInView, {
2371
+ }, "click this link to Sign Up."))), /*#__PURE__*/React__default["default"].createElement(SignInView, {
2220
2372
  onAuthDone: onSuccess,
2221
2373
  setUser: setUser,
2222
2374
  config: config
@@ -2230,7 +2382,7 @@ var AuthView = function AuthView(_a) {
2230
2382
  w: "auto"
2231
2383
  }), /*#__PURE__*/React__default["default"].createElement(react.Text, {
2232
2384
  as: "div",
2233
- fontSize: "14px",
2385
+ fontSize: "1.2rem",
2234
2386
  mb: "0.1rem !important",
2235
2387
  textAlign: "center"
2236
2388
  }, signUpTitle), /*#__PURE__*/React__default["default"].createElement(react.Text, {
@@ -2243,7 +2395,7 @@ var AuthView = function AuthView(_a) {
2243
2395
  textDecoration: "underline",
2244
2396
  onClick: handleAuthLinkClick,
2245
2397
  fontWeight: "bold"
2246
- }, "Sign in here."))), /*#__PURE__*/React__default["default"].createElement(SignUpView, {
2398
+ }, "click this link to Sign In."))), /*#__PURE__*/React__default["default"].createElement(SignUpView, {
2247
2399
  onAuthDone: onSuccess,
2248
2400
  setUser: setUser,
2249
2401
  config: config
@@ -2251,15 +2403,15 @@ var AuthView = function AuthView(_a) {
2251
2403
  as: "div",
2252
2404
  textAlign: "center",
2253
2405
  fontSize: "14px"
2254
- }, showSignIn ? /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, "Don't have an account yet? ", /*#__PURE__*/React__default["default"].createElement(Link, {
2406
+ }, showSignIn ? /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, "If you have not registered, ", /*#__PURE__*/React__default["default"].createElement(Link, {
2255
2407
  color: "green.500",
2256
2408
  textDecoration: "underline",
2257
2409
  onClick: handleAuthLinkClick
2258
- }, "Sign up here.")) : /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, "Already have an account? ", /*#__PURE__*/React__default["default"].createElement(Link, {
2410
+ }, "click this link to Sign Up.")) : /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, "If you already have an account, ", /*#__PURE__*/React__default["default"].createElement(Link, {
2259
2411
  color: "green.500",
2260
2412
  textDecoration: "underline",
2261
2413
  onClick: handleAuthLinkClick
2262
- }, "Log in here.")))));
2414
+ }, "click this link to Sign In.")))));
2263
2415
  };
2264
2416
 
2265
2417
  var ModalPop = function ModalPop(_a) {
@@ -2421,17 +2573,52 @@ var AccessTokenDoor = function AccessTokenDoor(_a) {
2421
2573
  }, authenticating ? "Please wait..." : "Confirm Operation")));
2422
2574
  };
2423
2575
 
2576
+ function _typeof(o) {
2577
+ "@babel/helpers - typeof";
2578
+
2579
+ return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) {
2580
+ return typeof o;
2581
+ } : function (o) {
2582
+ return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
2583
+ }, _typeof(o);
2584
+ }
2585
+
2424
2586
  var MAX_RETRIES$1 = 5;
2425
2587
  var CACHE_KEY$1 = "sdk_config-metadata";
2588
+ var CACHE_BUST_KEY$1 = "_fb_cache_bust";
2426
2589
  // let sdkConfigCache: SdkConfig | null = null;
2427
2590
  // let fetchPromise: Promise<SdkConfig | null> | null = null;
2428
- 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}]}}';
2591
+ var addCacheBust$1 = function addCacheBust(url) {
2592
+ try {
2593
+ var parsedUrl = new URL(url);
2594
+ parsedUrl.searchParams.set(CACHE_BUST_KEY$1, Date.now().toString());
2595
+ return parsedUrl.toString();
2596
+ } catch (err) {
2597
+ return url;
2598
+ }
2599
+ };
2600
+ var readCachedMetadata$1 = function readCachedMetadata() {
2601
+ if (!isBrowser()) return null;
2602
+ try {
2603
+ var cachedMetadata = localStorage.getItem(CACHE_KEY$1);
2604
+ return cachedMetadata ? JSON.parse(cachedMetadata) : null;
2605
+ } catch (err) {
2606
+ localStorage.removeItem(CACHE_KEY$1);
2607
+ return null;
2608
+ }
2609
+ };
2429
2610
  var useSdkConfig = function useSdkConfig(appConfig) {
2430
2611
  var _a = React.useState(isBrowser() ? window.sdkConfigCache : null),
2431
2612
  sdkConfig = _a[0],
2432
2613
  setSdkConfig = _a[1];
2433
2614
  function parseVendors(vendorsAsTexts) {
2434
- return vendorsAsTexts.map(function (text) {
2615
+ if (vendorsAsTexts === void 0) {
2616
+ vendorsAsTexts = [];
2617
+ }
2618
+ if (!Array.isArray(vendorsAsTexts)) return [];
2619
+ return vendorsAsTexts.map(function (vendor) {
2620
+ if (typeof vendor !== "string") return vendor;
2621
+ var text = vendor;
2435
2622
  var _a = text.split(','),
2436
2623
  name = _a[0],
2437
2624
  number = _a[1],
@@ -2447,49 +2634,38 @@ var useSdkConfig = function useSdkConfig(appConfig) {
2447
2634
  if (!(appConfig === null || appConfig === void 0 ? void 0 : appConfig.r2Domain)) return;
2448
2635
  if (window.sdkConfigCache) {
2449
2636
  setSdkConfig(window.sdkConfigCache);
2450
- return;
2451
2637
  }
2452
2638
  if (!window.fetchPromise) {
2453
2639
  window.fetchPromise = function () {
2454
2640
  return __awaiter(void 0, void 0, void 0, function () {
2455
- var attempts, headers, cachedMetadata, _a, etag, lastModified, cachedData, response, config, err_1;
2456
- var _b;
2457
- return __generator(this, function (_c) {
2458
- switch (_c.label) {
2641
+ var attempts, cachedMetadata, cachedData, response, config, err_1;
2642
+ var _a;
2643
+ return __generator(this, function (_b) {
2644
+ switch (_b.label) {
2459
2645
  case 0:
2460
2646
  attempts = 0;
2461
- headers = {};
2462
- cachedMetadata = localStorage.getItem(CACHE_KEY$1) || defaultFactoryData$1;
2647
+ cachedMetadata = readCachedMetadata$1();
2463
2648
  if (cachedMetadata) {
2464
- _a = JSON.parse(cachedMetadata), etag = _a.etag, lastModified = _a.lastModified, cachedData = _a.cachedData;
2649
+ cachedData = cachedMetadata.cachedData;
2465
2650
  if (cachedData) {
2466
2651
  window.sdkConfigCache = cachedData;
2467
2652
  setSdkConfig(cachedData);
2468
2653
  //return cachedData;
2469
2654
  }
2470
-
2471
- if (etag) headers["If-None-Match"] = etag;
2472
- if (lastModified) headers["If-Modified-Since"] = lastModified;
2473
2655
  }
2474
- consoleLog("useSdkConfig.headers: ", headers);
2475
- _c.label = 1;
2656
+
2657
+ consoleLog("useSdkConfig.refreshing");
2658
+ _b.label = 1;
2476
2659
  case 1:
2477
2660
  if (!(attempts < MAX_RETRIES$1)) return [3 /*break*/, 6];
2478
- _c.label = 2;
2661
+ _b.label = 2;
2479
2662
  case 2:
2480
- _c.trys.push([2, 4,, 5]);
2481
- return [4 /*yield*/, axios__default["default"].get("https://".concat(appConfig.r2Domain, "/sdk_config.json"), {
2482
- headers: headers,
2483
- validateStatus: function validateStatus(status) {
2484
- return status < 500;
2485
- } // Accept 304 Not Modified
2486
- })];
2487
-
2663
+ _b.trys.push([2, 4,, 5]);
2664
+ return [4 /*yield*/, axios__default["default"].get(addCacheBust$1("https://".concat(appConfig.r2Domain, "/sdk_config.json")))];
2488
2665
  case 3:
2489
- response = _c.sent();
2490
- if (response.status === 304) {
2491
- consoleLog("useSdkConfig.notModied: ", response.status);
2492
- return [2 /*return*/, window.sdkConfigCache];
2666
+ response = _b.sent();
2667
+ if (_typeof(response.data) !== "object") {
2668
+ throw new Error("Invalid SDK config response");
2493
2669
  }
2494
2670
  config = response.data;
2495
2671
  config.vendors = parseVendors(response.data.vendors);
@@ -2499,13 +2675,14 @@ var useSdkConfig = function useSdkConfig(appConfig) {
2499
2675
  localStorage.setItem(CACHE_KEY$1, JSON.stringify({
2500
2676
  etag: response.headers["etag"],
2501
2677
  lastModified: response.headers["last-modified"],
2678
+ cachedAt: Date.now(),
2502
2679
  cachedData: config
2503
2680
  }));
2504
2681
  consoleLog("useSdkConfig.refreshed: ", response.data, " at ".concat(response.headers["last-modified"], ", with etag, ").concat(response.headers["etag"]));
2505
2682
  return [2 /*return*/, config];
2506
2683
  case 4:
2507
- err_1 = _c.sent();
2508
- if (((_b = err_1.response) === null || _b === void 0 ? void 0 : _b.status) === 404) {
2684
+ err_1 = _b.sent();
2685
+ if (((_a = err_1.response) === null || _a === void 0 ? void 0 : _a.status) === 404) {
2509
2686
  consoleLog("Error fetching SDK config: Resource not found (404): ", err_1);
2510
2687
  return [3 /*break*/, 6];
2511
2688
  }
@@ -2517,11 +2694,14 @@ var useSdkConfig = function useSdkConfig(appConfig) {
2517
2694
  case 5:
2518
2695
  return [3 /*break*/, 1];
2519
2696
  case 6:
2697
+ if (window.sdkConfigCache) return [2 /*return*/, window.sdkConfigCache];
2520
2698
  return [2 /*return*/, null];
2521
2699
  }
2522
2700
  });
2523
2701
  });
2524
- }();
2702
+ }()["finally"](function () {
2703
+ window.fetchPromise = null;
2704
+ });
2525
2705
  }
2526
2706
  window.fetchPromise.then(function (config) {
2527
2707
  if (config) setSdkConfig(config);
@@ -2942,12 +3122,12 @@ var DownloadType = function DownloadType(_a) {
2942
3122
  //Or it's not an update(it's a create) but create price is 0
2943
3123
  //Or it's an update but update price is 0
2944
3124
  //Or it's an update for subscription renewal
2945
- /*!docRules ||*/ /*
2946
- (updateMessage && removeFreemiumBeforeUpdate && docRules.create_price > 0) ||
2947
- (!updateMessage && !docRules.allow_freemium) ||
2948
- (!updateMessage && docRules.create_price == 0) ||
2949
- (updateMessage && docRules.update_price == 0) ||
2950
- (updateMessage && renewSubscription) ||
3125
+ /*!docRules ||*/ /*
3126
+ (updateMessage && removeFreemiumBeforeUpdate && docRules.create_price > 0) ||
3127
+ (!updateMessage && !docRules.allow_freemium) ||
3128
+ (!updateMessage && docRules.create_price == 0) ||
3129
+ (updateMessage && docRules.update_price == 0) ||
3130
+ (updateMessage && renewSubscription) ||
2951
3131
  (updateMessage && renewSubscription)*/
2952
3132
  //(!updateMessage && docRules.create_price == 0) || (updateMessage && !docRules.yearly_price && !docRules.quarterly_price)?
2953
3133
  autoProcessOn || !docRules ? /*#__PURE__*/React__default["default"].createElement(PleaseWaitForX, null) : /*#__PURE__*/React__default["default"].createElement(React__default["default"].Fragment, null, updateMessage && !docRules.yearly_price && !docRules.quarterly_price ? /*#__PURE__*/React__default["default"].createElement(react.Text, {
@@ -2997,11 +3177,11 @@ var DownloadType = function DownloadType(_a) {
2997
3177
  }))));
2998
3178
  };
2999
3179
 
3000
- /**
3001
- * Removes a specific query string parameter from a URL.
3002
- * @param {string} url - The original URL.
3003
- * @param {string} queryString - The query string parameter to remove.
3004
- * @returns {string} - The updated URL without the specified query string parameter.
3180
+ /**
3181
+ * Removes a specific query string parameter from a URL.
3182
+ * @param {string} url - The original URL.
3183
+ * @param {string} queryString - The query string parameter to remove.
3184
+ * @returns {string} - The updated URL without the specified query string parameter.
3005
3185
  */
3006
3186
  function removeQueryString(url, queryString) {
3007
3187
  try {
@@ -3016,12 +3196,12 @@ function removeQueryString(url, queryString) {
3016
3196
  return url; // Return the original URL if there's an error
3017
3197
  }
3018
3198
  }
3019
- /**
3020
- * Converts an array of objects to a map using a specified attribute as the key.
3021
- *
3022
- * @param {Array<Object>} arr - The array of objects to be converted.
3023
- * @param {string} attr - The attribute to use as the key for the mapping.
3024
- * @returns {Object} - An object mapping each unique attribute value to its corresponding item.
3199
+ /**
3200
+ * Converts an array of objects to a map using a specified attribute as the key.
3201
+ *
3202
+ * @param {Array<Object>} arr - The array of objects to be converted.
3203
+ * @param {string} attr - The attribute to use as the key for the mapping.
3204
+ * @returns {Object} - An object mapping each unique attribute value to its corresponding item.
3025
3205
  */
3026
3206
  function arrayToMap(attr, arr, keyParser) {
3027
3207
  return arr.reduce(function (map, item) {
@@ -3047,9 +3227,9 @@ var rmUpdates = function rmUpdates(url) {
3047
3227
 
3048
3228
  var MAX_RETRIES = 5;
3049
3229
  var CACHE_KEY = "tools-cache-metadata";
3230
+ var CACHE_BUST_KEY = "_fb_cache_bust";
3050
3231
  // let toolsCache: ToolsData | null = null;
3051
3232
  // let toolsFetchPromise: Promise<ToolsData | null> | null = null;
3052
- 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}]}}';
3053
3233
  var setR2Host = function setR2Host(url, r2Domain) {
3054
3234
  if (!url) return url;
3055
3235
  if (url.startsWith('/')) {
@@ -3066,6 +3246,25 @@ var setR2Host = function setR2Host(url, r2Domain) {
3066
3246
  }
3067
3247
  };
3068
3248
 
3249
+ var addCacheBust = function addCacheBust(url) {
3250
+ try {
3251
+ var parsedUrl = new URL(url);
3252
+ parsedUrl.searchParams.set(CACHE_BUST_KEY, Date.now().toString());
3253
+ return parsedUrl.toString();
3254
+ } catch (err) {
3255
+ return url;
3256
+ }
3257
+ };
3258
+ var readCachedMetadata = function readCachedMetadata() {
3259
+ if (!isBrowser()) return null;
3260
+ try {
3261
+ var cachedMetadata = localStorage.getItem(CACHE_KEY);
3262
+ return cachedMetadata ? JSON.parse(cachedMetadata) : null;
3263
+ } catch (err) {
3264
+ localStorage.removeItem(CACHE_KEY);
3265
+ return null;
3266
+ }
3267
+ };
3069
3268
  var useTools = function useTools(config) {
3070
3269
  var _a = React.useState(isBrowser() ? window.toolsCache : null),
3071
3270
  data = _a[0],
@@ -3088,59 +3287,49 @@ var useTools = function useTools(config) {
3088
3287
  setData(window.toolsCache);
3089
3288
  setLoading(false);
3090
3289
  consoleLog("useTools.returns as toolsCache already exist: ", window.toolsCache);
3091
- return;
3092
3290
  }
3093
3291
  if (!window.toolsFetchPromise) {
3094
3292
  window.toolsFetchPromise = function () {
3095
3293
  return __awaiter(void 0, void 0, void 0, function () {
3096
- var attempts, headers, cachedMetadata, _a, etag, lastModified, cachedData, response, err_1;
3097
- var _b;
3294
+ var attempts, cachedMetadata, cachedData, response, err_1;
3295
+ var _a, _b;
3098
3296
  return __generator(this, function (_c) {
3099
3297
  switch (_c.label) {
3100
3298
  case 0:
3101
3299
  attempts = 0;
3102
- headers = {};
3103
- cachedMetadata = localStorage.getItem(CACHE_KEY) || defaultFactoryData;
3300
+ cachedMetadata = readCachedMetadata();
3104
3301
  if (cachedMetadata) {
3105
- _a = JSON.parse(cachedMetadata), etag = _a.etag, lastModified = _a.lastModified, cachedData = _a.cachedData;
3302
+ cachedData = cachedMetadata.cachedData;
3106
3303
  if (cachedData) {
3107
3304
  window.toolsCache = cachedData;
3108
3305
  setData(cachedData);
3109
3306
  setLoading(false);
3110
3307
  //return cachedData;
3111
3308
  }
3112
-
3113
- if (etag) headers["If-None-Match"] = etag;
3114
- if (lastModified) headers["If-Modified-Since"] = lastModified;
3115
3309
  }
3116
- consoleLog("useTools.headers: ", headers);
3310
+
3311
+ consoleLog("useTools.refreshing");
3117
3312
  _c.label = 1;
3118
3313
  case 1:
3119
3314
  if (!(attempts < MAX_RETRIES)) return [3 /*break*/, 6];
3120
3315
  _c.label = 2;
3121
3316
  case 2:
3122
3317
  _c.trys.push([2, 4,, 5]);
3123
- return [4 /*yield*/, axios__default["default"].get("https://".concat(config.r2Domain, "/templates/tools.json"), {
3124
- headers: headers,
3125
- validateStatus: function validateStatus(status) {
3126
- return status < 500;
3127
- } // Accept 304 Not Modified
3128
- })];
3129
-
3318
+ return [4 /*yield*/, axios__default["default"].get(addCacheBust("https://".concat(config.r2Domain, "/templates/tools.json")))];
3130
3319
  case 3:
3131
3320
  response = _c.sent();
3132
- if (response.status === 304) {
3133
- setLoading(false);
3134
- consoleLog("useTools.notModied: ", response.status);
3135
- return [2 /*return*/, window.toolsCache];
3321
+ if (_typeof(response.data) !== "object" || !Array.isArray((_a = response.data) === null || _a === void 0 ? void 0 : _a.tools)) {
3322
+ throw new Error("Invalid tools response");
3136
3323
  }
3137
3324
  window.toolsCache = response.data;
3138
3325
  setData(response.data);
3139
3326
  setError(null);
3327
+ setLoading(false);
3140
3328
  // Save cache metadata
3141
3329
  localStorage.setItem(CACHE_KEY, JSON.stringify({
3142
3330
  etag: response.headers["etag"],
3143
3331
  lastModified: response.headers["last-modified"],
3332
+ cachedAt: Date.now(),
3144
3333
  cachedData: response.data
3145
3334
  }));
3146
3335
  consoleLog("useTools.refreshed: ", response.data, " at ".concat(response.headers["last-modified"], ", with etag, ").concat(response.headers["etag"]));
@@ -3148,23 +3337,30 @@ var useTools = function useTools(config) {
3148
3337
  case 4:
3149
3338
  err_1 = _c.sent();
3150
3339
  if (((_b = err_1.response) === null || _b === void 0 ? void 0 : _b.status) === 404) {
3151
- setError("Resource not found (404)");
3340
+ if (!window.toolsCache) setError("Resource not found (404)");
3152
3341
  return [3 /*break*/, 6];
3153
3342
  }
3154
3343
  attempts++;
3155
3344
  if (attempts === MAX_RETRIES) {
3156
- setError("Failed to fetch data after multiple attempts");
3345
+ if (!window.toolsCache) setError("Failed to fetch data after multiple attempts");
3157
3346
  }
3158
3347
  return [3 /*break*/, 5];
3159
3348
  case 5:
3160
3349
  return [3 /*break*/, 1];
3161
3350
  case 6:
3351
+ if (window.toolsCache) {
3352
+ setError(null);
3353
+ setLoading(false);
3354
+ return [2 /*return*/, window.toolsCache];
3355
+ }
3162
3356
  setLoading(false);
3163
3357
  return [2 /*return*/, null];
3164
3358
  }
3165
3359
  });
3166
3360
  });
3167
- }();
3361
+ }()["finally"](function () {
3362
+ window.toolsFetchPromise = null;
3363
+ });
3168
3364
  }
3169
3365
  window.toolsFetchPromise.then(function (result) {
3170
3366
  if (result) setData(result);