react-better-html 1.1.157 → 1.1.159

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -59,17 +59,21 @@ __export(index_exports, {
59
59
  countries: () => countries,
60
60
  darkenColor: () => darkenColor,
61
61
  defaultAlertsPluginOptions: () => defaultAlertsPluginOptions,
62
+ defaultLocalStoragePluginOptions: () => defaultLocalStoragePluginOptions,
63
+ defaultReactRouterDomPluginOptions: () => defaultReactRouterDomPluginOptions,
62
64
  desaturateColor: () => desaturateColor,
63
65
  eventPreventDefault: () => eventPreventDefault,
64
66
  eventPreventStop: () => eventPreventStop,
65
67
  eventStopPropagation: () => eventStopPropagation,
66
68
  formatPhoneNumber: () => formatPhoneNumber,
69
+ generateLocalStorage: () => generateLocalStorage,
67
70
  generateRandomString: () => generateRandomString,
68
71
  getBrowser: () => getBrowser,
69
72
  getFormErrorObject: () => getFormErrorObject,
70
73
  isMobileDevice: () => isMobileDevice,
71
74
  lightenColor: () => lightenColor,
72
75
  loaderControls: () => loaderControls,
76
+ localStoragePlugin: () => localStoragePlugin,
73
77
  reactRouterDomPlugin: () => reactRouterDomPlugin,
74
78
  saturateColor: () => saturateColor,
75
79
  useAlertControls: () => useAlertControls,
@@ -1615,19 +1619,6 @@ var import_react8 = require("react");
1615
1619
  var import_react7 = require("react");
1616
1620
  var import_styled_components6 = __toESM(require("styled-components"));
1617
1621
 
1618
- // src/plugins/react-router-dom.ts
1619
- var import_react_router_dom = require("react-router-dom");
1620
- var reactRouterDomPlugin = () => ({
1621
- name: "react-router-dom",
1622
- components: {
1623
- Link: import_react_router_dom.Link,
1624
- NavLink: import_react_router_dom.NavLink
1625
- },
1626
- initialize: () => {
1627
- console.log("react-router-dom plugin initialized");
1628
- }
1629
- });
1630
-
1631
1622
  // src/plugins/alerts.ts
1632
1623
  var defaultAlertsPluginOptions = {
1633
1624
  position: "bottom",
@@ -1648,6 +1639,39 @@ var alertsPlugin = (options) => ({
1648
1639
  })
1649
1640
  });
1650
1641
 
1642
+ // src/plugins/reactRouterDom.ts
1643
+ var import_react_router_dom = require("react-router-dom");
1644
+ var defaultReactRouterDomPluginOptions = {};
1645
+ var reactRouterDomPlugin = (options) => ({
1646
+ name: "react-router-dom",
1647
+ components: {
1648
+ Link: import_react_router_dom.Link,
1649
+ NavLink: import_react_router_dom.NavLink
1650
+ },
1651
+ initialize: () => {
1652
+ console.log("react-router-dom plugin initialized");
1653
+ },
1654
+ getConfig: () => ({
1655
+ ...defaultReactRouterDomPluginOptions,
1656
+ ...options
1657
+ })
1658
+ });
1659
+
1660
+ // src/plugins/localStorage.ts
1661
+ var defaultLocalStoragePluginOptions = {
1662
+ encryption: {}
1663
+ };
1664
+ var localStoragePlugin = (options) => ({
1665
+ name: "localStorage",
1666
+ initialize: () => {
1667
+ console.log("localStorage plugin initialized");
1668
+ },
1669
+ getConfig: () => ({
1670
+ ...defaultLocalStoragePluginOptions,
1671
+ ...options
1672
+ })
1673
+ });
1674
+
1651
1675
  // src/components/Icon.tsx
1652
1676
  var import_react = require("react");
1653
1677
  var import_styled_components = __toESM(require("styled-components"));
@@ -2726,12 +2750,17 @@ function useStyledComponentStyles(props, theme2, excludeProps) {
2726
2750
  haveHover = true;
2727
2751
  const normalKey = key.slice(0, -5);
2728
2752
  hoverStyle[normalKey] = props[key];
2753
+ if (normalKey === "transition") hoverStyle.WebkitTransition = hoverStyle.transition;
2729
2754
  } else {
2730
2755
  if (!cssProps[key.toLowerCase()]) continue;
2731
2756
  normalStyle[key] = props[key];
2757
+ if (key === "transition") normalStyle.WebkitTransition = normalStyle.transition;
2732
2758
  }
2733
2759
  }
2734
- if (haveHover) normalStyle.transition = theme2?.styles.transition ?? "";
2760
+ if (haveHover) {
2761
+ normalStyle.transition = theme2?.styles.transition ?? "";
2762
+ normalStyle.WebkitTransition = normalStyle.transition;
2763
+ }
2735
2764
  return {
2736
2765
  normalStyle,
2737
2766
  hoverStyle
@@ -4396,13 +4425,15 @@ var countries = [
4396
4425
  name: "Finland",
4397
4426
  code: "FI",
4398
4427
  timeZone: "Europe/Helsinki",
4399
- phoneNumberExtension: "358"
4428
+ phoneNumberExtension: "358",
4429
+ phoneNumberFormat: "XX XXX XX XX"
4400
4430
  },
4401
4431
  {
4402
4432
  name: "France",
4403
4433
  code: "FR",
4404
4434
  timeZone: "Europe/Paris",
4405
- phoneNumberExtension: "33"
4435
+ phoneNumberExtension: "33",
4436
+ phoneNumberFormat: "X XX XX XX XX"
4406
4437
  },
4407
4438
  {
4408
4439
  name: "French Guiana",
@@ -4445,7 +4476,7 @@ var countries = [
4445
4476
  code: "DE",
4446
4477
  timeZone: "Europe/Berlin",
4447
4478
  phoneNumberExtension: "49",
4448
- phoneNumberFormat: "XXXX XXXXXX"
4479
+ phoneNumberFormat: "XXXX XXXXXXX"
4449
4480
  },
4450
4481
  {
4451
4482
  name: "Ghana",
@@ -5421,6 +5452,62 @@ var countries = [
5421
5452
  }
5422
5453
  ];
5423
5454
 
5455
+ // src/utils/functions.ts
5456
+ var import_crypto_js = __toESM(require("crypto-js"));
5457
+
5458
+ // src/utils/variableFunctions.ts
5459
+ var checkBetterHtmlContextValue = (value, functionsName) => {
5460
+ if (value === void 0) {
5461
+ throw new Error(
5462
+ `\`${functionsName}()\` must be used within a \`<BetterHtmlProvider>\`. Make sure to add one at the root of your component tree.`
5463
+ );
5464
+ }
5465
+ return value !== void 0;
5466
+ };
5467
+ var loaderControls = {
5468
+ startLoading: (loaderName) => {
5469
+ if (!checkBetterHtmlContextValue(externalBetterHtmlContextValue, "loaderControls.startLoading")) return;
5470
+ externalBetterHtmlContextValue.setLoaders((oldValue) => ({
5471
+ ...oldValue,
5472
+ [loaderName.toString()]: true
5473
+ }));
5474
+ },
5475
+ stopLoading: (loaderName) => {
5476
+ if (!checkBetterHtmlContextValue(externalBetterHtmlContextValue, "loaderControls.stopLoading")) return;
5477
+ externalBetterHtmlContextValue.setLoaders((oldValue) => ({
5478
+ ...oldValue,
5479
+ [loaderName.toString()]: false
5480
+ }));
5481
+ }
5482
+ };
5483
+ var alertControls = {
5484
+ createAlert: (alert) => {
5485
+ if (!checkBetterHtmlContextValue(externalBetterHtmlContextValue, "alertControls.createAlert"))
5486
+ return void 0;
5487
+ const readyAlert = {
5488
+ id: crypto.randomUUID(),
5489
+ ...alert
5490
+ };
5491
+ externalBetterHtmlContextValue.setAlerts((oldValue) => [...oldValue, readyAlert]);
5492
+ return readyAlert;
5493
+ },
5494
+ removeAlert: (alertId) => {
5495
+ if (!checkBetterHtmlContextValue(externalBetterHtmlContextValue, "alertControls.removeAlert")) return;
5496
+ externalBetterHtmlContextValue.setAlerts((oldValue) => oldValue.filter((alert) => alert.id !== alertId));
5497
+ }
5498
+ };
5499
+ var colorThemeControls = {
5500
+ toggleTheme: (theme2) => {
5501
+ if (!checkBetterHtmlContextValue(externalBetterHtmlContextValue, "colorThemeControls.toggleTheme")) return;
5502
+ const currentColorTheme = externalBetterHtmlContextValue.colorTheme;
5503
+ const newColorTheme = theme2 ?? (currentColorTheme === "dark" ? "light" : "dark");
5504
+ setTimeout(() => {
5505
+ window.document.body.parentElement?.setAttribute("data-theme", newColorTheme);
5506
+ localStorage.setItem("theme", newColorTheme);
5507
+ }, 0.01 * 1e3);
5508
+ }
5509
+ };
5510
+
5424
5511
  // src/utils/functions.ts
5425
5512
  var generateRandomString = (stringLength, options) => {
5426
5513
  const capitals = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
@@ -5492,6 +5579,40 @@ var eventPreventStop = (event) => {
5492
5579
  event.preventDefault();
5493
5580
  event.stopPropagation();
5494
5581
  };
5582
+ var encryptString = (text) => {
5583
+ if (!checkBetterHtmlContextValue(externalBetterHtmlContextValue, "encryptString")) return void 0;
5584
+ const localStoragePlugin2 = externalBetterHtmlContextValue.plugins.find((plugin) => plugin.name === "localStorage");
5585
+ if (!localStoragePlugin2) {
5586
+ throw new Error(
5587
+ "`encryptString` hook requires the `localStorage` plugin to be added to the `plugins` prop in `<BetterHtmlProvider>`."
5588
+ );
5589
+ }
5590
+ const pluginConfig = localStoragePlugin2.getConfig?.() ?? {};
5591
+ if (!pluginConfig?.encryption?.enabled) return text;
5592
+ const encrypted = import_crypto_js.default.AES.encrypt(text, import_crypto_js.default.enc.Hex.parse(pluginConfig.encryption.secretKey), {
5593
+ iv: import_crypto_js.default.enc.Hex.parse(pluginConfig.encryption.iv),
5594
+ mode: import_crypto_js.default.mode.CBC,
5595
+ padding: import_crypto_js.default.pad.Pkcs7
5596
+ }).toString();
5597
+ return encrypted;
5598
+ };
5599
+ var decryptString = (text) => {
5600
+ if (!checkBetterHtmlContextValue(externalBetterHtmlContextValue, "decryptString")) return void 0;
5601
+ const localStoragePlugin2 = externalBetterHtmlContextValue.plugins.find((plugin) => plugin.name === "localStorage");
5602
+ if (!localStoragePlugin2) {
5603
+ throw new Error(
5604
+ "`decryptString` hook requires the `localStorage` plugin to be added to the `plugins` prop in `<BetterHtmlProvider>`."
5605
+ );
5606
+ }
5607
+ const pluginConfig = localStoragePlugin2.getConfig?.() ?? {};
5608
+ if (!pluginConfig?.encryption?.enabled) return text;
5609
+ const decrypted = import_crypto_js.default.AES.decrypt(text, import_crypto_js.default.enc.Hex.parse(pluginConfig.encryption.secretKey), {
5610
+ iv: import_crypto_js.default.enc.Hex.parse(pluginConfig.encryption.iv),
5611
+ mode: import_crypto_js.default.mode.CBC,
5612
+ padding: import_crypto_js.default.pad.Pkcs7
5613
+ });
5614
+ return decrypted.toString(import_crypto_js.default.enc.Utf8);
5615
+ };
5495
5616
 
5496
5617
  // src/components/Label.tsx
5497
5618
  var import_react17 = require("react");
@@ -5894,8 +6015,18 @@ var getWeekDayName = (day, short = false) => {
5894
6015
  };
5895
6016
  var weekDaysIndex = [1, 2, 3, 4, 5, 6, 0];
5896
6017
  var yearsRange = Array.from({ length: 100 + 1 + 50 }, (_, index) => index + (/* @__PURE__ */ new Date()).getFullYear() - 100);
6018
+ var SelectWrapperComponent = import_styled_components10.default.div.withConfig({
6019
+ shouldForwardProp: (prop) => !["theme"].includes(prop)
6020
+ })`
6021
+ &:has(select:focus) {
6022
+ outline: auto;
6023
+ outline-color: -webkit-focus-ring-color;
6024
+ outline-style: auto;
6025
+ outline-offset: 2px;
6026
+ }
6027
+ `;
5897
6028
  var SelectComponent = import_styled_components10.default.select.withConfig({
5898
- shouldForwardProp: (prop) => !["normalStyle", "hoverStyle"].includes(prop)
6029
+ shouldForwardProp: (prop) => !["theme"].includes(prop)
5899
6030
  })`
5900
6031
  position: absolute;
5901
6032
  top: 50%;
@@ -5905,6 +6036,7 @@ var SelectComponent = import_styled_components10.default.select.withConfig({
5905
6036
  `;
5906
6037
  function Calendar({ value, minDate, maxDate, onChange }) {
5907
6038
  const theme2 = useTheme();
6039
+ const internalYearSelectId = (0, import_react19.useId)();
5908
6040
  const [currentDate, setCurrentDate] = (0, import_react19.useState)(value ? new Date(value) : void 0);
5909
6041
  const [currentMonth, setCurrentMonth] = (0, import_react19.useState)(currentDate?.getMonth() ?? (/* @__PURE__ */ new Date()).getMonth());
5910
6042
  const [currentYear, setCurrentYear] = (0, import_react19.useState)(currentDate?.getFullYear() ?? (/* @__PURE__ */ new Date()).getFullYear());
@@ -5972,11 +6104,20 @@ function Calendar({ value, minDate, maxDate, onChange }) {
5972
6104
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Button_default.icon, { icon: "chevronLeft", onClick: onClickPreviousMonthButton }),
5973
6105
  /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Div_default.row, { alignItems: "center", gap: 4, children: [
5974
6106
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text_default, { fontWeight: 700, children: getMonthName(currentMonth) }),
5975
- /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Div_default.row, { position: "relative", alignItems: "center", gap: 2, children: [
6107
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(SelectWrapperComponent, { children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(Div_default.row, { position: "relative", alignItems: "center", gap: 2, children: [
5976
6108
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Text_default, { fontWeight: 700, children: currentYear }),
5977
6109
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Icon_default, { name: "chevronDown", size: 12 }),
5978
- /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(SelectComponent, { theme: theme2, value: currentYear, onChange: onChangeYearSelect, children: yearsRange.map((year) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("option", { value: year, children: year }, year)) })
5979
- ] })
6110
+ /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
6111
+ SelectComponent,
6112
+ {
6113
+ theme: theme2,
6114
+ value: currentYear,
6115
+ onChange: onChangeYearSelect,
6116
+ id: internalYearSelectId,
6117
+ children: yearsRange.map((year) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("option", { value: year, children: year }, year))
6118
+ }
6119
+ )
6120
+ ] }) })
5980
6121
  ] }),
5981
6122
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Button_default.icon, { icon: "chevronRight", onClick: onClickNextMonthButton })
5982
6123
  ] }),
@@ -6100,6 +6241,10 @@ var InputElement = import_styled_components11.default.input.withConfig({
6100
6241
  cursor: not-allowed;
6101
6242
  }
6102
6243
 
6244
+ &:read-only {
6245
+ caret-color: transparent;
6246
+ }
6247
+
6103
6248
  &::-webkit-outer-spin-button,
6104
6249
  &::-webkit-inner-spin-button {
6105
6250
  -webkit-appearance: none;
@@ -6756,6 +6901,7 @@ InputFieldComponent.dateTime = (0, import_react20.forwardRef)(function DateTime(
6756
6901
  width: buttonWidth,
6757
6902
  height: `calc(100% - ${16 + theme2.styles.gap / 2}px)`,
6758
6903
  overflowY: "auto",
6904
+ tabIndex: -1,
6759
6905
  children: hours.map((hour) => {
6760
6906
  const isSelected = hour.toString() === valueHour;
6761
6907
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
@@ -6789,6 +6935,7 @@ InputFieldComponent.dateTime = (0, import_react20.forwardRef)(function DateTime(
6789
6935
  width: buttonWidth,
6790
6936
  height: `calc(100% - ${16 + theme2.styles.gap / 2}px)`,
6791
6937
  overflowY: "auto",
6938
+ tabIndex: -1,
6792
6939
  children: minutes.map((minute) => {
6793
6940
  const isSelected = minute.toString() === valueMinute;
6794
6941
  return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
@@ -6877,46 +7024,66 @@ InputFieldComponent.time = (0, import_react20.forwardRef)(function Time({ ...pro
6877
7024
  userSelect: "none",
6878
7025
  ...insideInputFieldComponentProps,
6879
7026
  children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(Div_default.row, { height: "100%", children: [
6880
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Div_default, { className: "react-better-html-no-scrollbar", width: buttonWidth, height: "100%", overflowY: "auto", children: hours.map((hour) => {
6881
- const isSelected = hour.toString() === valueHour;
6882
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
6883
- Div_default.row,
6884
- {
6885
- alignItems: "center",
6886
- justifyContent: "center",
6887
- color: isSelected ? theme2.colors.base : theme2.colors.textPrimary,
6888
- backgroundColor: isSelected ? theme2.colors.primary : theme2.colors.backgroundContent,
6889
- filterHover: "brightness(0.9)",
6890
- cursor: "pointer",
6891
- padding: `${theme2.styles.space / 2}px ${theme2.styles.space + theme2.styles.gap}px`,
6892
- value: hour,
6893
- onClickWithValue: onClickHour,
6894
- ref: isSelected ? selectedHourRef : void 0,
6895
- children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Text_default, { textAlign: "center", children: hour.toString().padStart(2, "0") })
6896
- },
6897
- hour
6898
- );
6899
- }) }),
6900
- /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Div_default, { className: "react-better-html-no-scrollbar", width: buttonWidth, height: "100%", overflowY: "auto", children: minutes.map((minute) => {
6901
- const isSelected = minute.toString() === valueMinute;
6902
- return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
6903
- Div_default.row,
6904
- {
6905
- alignItems: "center",
6906
- justifyContent: "center",
6907
- color: isSelected ? theme2.colors.base : theme2.colors.textPrimary,
6908
- backgroundColor: isSelected ? theme2.colors.primary : theme2.colors.backgroundContent,
6909
- filterHover: "brightness(0.9)",
6910
- cursor: "pointer",
6911
- padding: `${theme2.styles.space / 2}px ${theme2.styles.space + theme2.styles.gap}px`,
6912
- value: minute,
6913
- onClickWithValue: onClickMinute,
6914
- ref: isSelected ? selectedMinuteRef : void 0,
6915
- children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Text_default, { textAlign: "center", children: minute.toString().padStart(2, "0") })
6916
- },
6917
- minute
6918
- );
6919
- }) })
7027
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
7028
+ Div_default,
7029
+ {
7030
+ className: "react-better-html-no-scrollbar",
7031
+ width: buttonWidth,
7032
+ height: "100%",
7033
+ overflowY: "auto",
7034
+ tabIndex: -1,
7035
+ children: hours.map((hour) => {
7036
+ const isSelected = hour.toString() === valueHour;
7037
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
7038
+ Div_default.row,
7039
+ {
7040
+ alignItems: "center",
7041
+ justifyContent: "center",
7042
+ color: isSelected ? theme2.colors.base : theme2.colors.textPrimary,
7043
+ backgroundColor: isSelected ? theme2.colors.primary : theme2.colors.backgroundContent,
7044
+ filterHover: "brightness(0.9)",
7045
+ cursor: "pointer",
7046
+ padding: `${theme2.styles.space / 2}px ${theme2.styles.space + theme2.styles.gap}px`,
7047
+ value: hour,
7048
+ onClickWithValue: onClickHour,
7049
+ ref: isSelected ? selectedHourRef : void 0,
7050
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Text_default, { textAlign: "center", children: hour.toString().padStart(2, "0") })
7051
+ },
7052
+ hour
7053
+ );
7054
+ })
7055
+ }
7056
+ ),
7057
+ /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
7058
+ Div_default,
7059
+ {
7060
+ className: "react-better-html-no-scrollbar",
7061
+ width: buttonWidth,
7062
+ height: "100%",
7063
+ overflowY: "auto",
7064
+ tabIndex: -1,
7065
+ children: minutes.map((minute) => {
7066
+ const isSelected = minute.toString() === valueMinute;
7067
+ return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
7068
+ Div_default.row,
7069
+ {
7070
+ alignItems: "center",
7071
+ justifyContent: "center",
7072
+ color: isSelected ? theme2.colors.base : theme2.colors.textPrimary,
7073
+ backgroundColor: isSelected ? theme2.colors.primary : theme2.colors.backgroundContent,
7074
+ filterHover: "brightness(0.9)",
7075
+ cursor: "pointer",
7076
+ padding: `${theme2.styles.space / 2}px ${theme2.styles.space + theme2.styles.gap}px`,
7077
+ value: minute,
7078
+ onClickWithValue: onClickMinute,
7079
+ ref: isSelected ? selectedMinuteRef : void 0,
7080
+ children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Text_default, { textAlign: "center", children: minute.toString().padStart(2, "0") })
7081
+ },
7082
+ minute
7083
+ );
7084
+ })
7085
+ }
7086
+ )
6920
7087
  ] })
6921
7088
  }
6922
7089
  ) : void 0,
@@ -7410,61 +7577,6 @@ var FormRow_default = FormRow2;
7410
7577
 
7411
7578
  // src/components/ColorThemeSwitch.tsx
7412
7579
  var import_react24 = require("react");
7413
-
7414
- // src/utils/variableFunctions.ts
7415
- var checkBetterHtmlContextValue = (value, functionsName) => {
7416
- if (value === void 0) {
7417
- throw new Error(
7418
- `\`${functionsName}()\` must be used within a \`<BetterHtmlProvider>\`. Make sure to add one at the root of your component tree.`
7419
- );
7420
- }
7421
- return value !== void 0;
7422
- };
7423
- var loaderControls = {
7424
- startLoading: (loaderName) => {
7425
- if (!checkBetterHtmlContextValue(externalBetterHtmlContextValue, "loaderControls.startLoading")) return;
7426
- externalBetterHtmlContextValue.setLoaders((oldValue) => ({
7427
- ...oldValue,
7428
- [loaderName.toString()]: true
7429
- }));
7430
- },
7431
- stopLoading: (loaderName) => {
7432
- if (!checkBetterHtmlContextValue(externalBetterHtmlContextValue, "loaderControls.stopLoading")) return;
7433
- externalBetterHtmlContextValue.setLoaders((oldValue) => ({
7434
- ...oldValue,
7435
- [loaderName.toString()]: false
7436
- }));
7437
- }
7438
- };
7439
- var alertControls = {
7440
- createAlert: (alert) => {
7441
- if (!checkBetterHtmlContextValue(externalBetterHtmlContextValue, "alertControls.createAlert"))
7442
- return void 0;
7443
- const readyAlert = {
7444
- id: crypto.randomUUID(),
7445
- ...alert
7446
- };
7447
- externalBetterHtmlContextValue.setAlerts((oldValue) => [...oldValue, readyAlert]);
7448
- return readyAlert;
7449
- },
7450
- removeAlert: (alertId) => {
7451
- if (!checkBetterHtmlContextValue(externalBetterHtmlContextValue, "alertControls.removeAlert")) return;
7452
- externalBetterHtmlContextValue.setAlerts((oldValue) => oldValue.filter((alert) => alert.id !== alertId));
7453
- }
7454
- };
7455
- var colorThemeControls = {
7456
- toggleTheme: (theme2) => {
7457
- if (!checkBetterHtmlContextValue(externalBetterHtmlContextValue, "colorThemeControls.toggleTheme")) return;
7458
- const currentColorTheme = externalBetterHtmlContextValue.colorTheme;
7459
- const newColorTheme = theme2 ?? (currentColorTheme === "dark" ? "light" : "dark");
7460
- setTimeout(() => {
7461
- window.document.body.parentElement?.setAttribute("data-theme", newColorTheme);
7462
- localStorage.setItem("theme", newColorTheme);
7463
- }, 0.01 * 1e3);
7464
- }
7465
- };
7466
-
7467
- // src/components/ColorThemeSwitch.tsx
7468
7580
  var import_jsx_runtime22 = require("react/jsx-runtime");
7469
7581
  var ColorThemeSwitchComponent = function ColorThemeSwitch({
7470
7582
  withMoon,
@@ -9068,6 +9180,71 @@ FoldableComponent.box = (0, import_react28.forwardRef)(function Box3({ ...props
9068
9180
  var Foldable2 = (0, import_react28.memo)(FoldableComponent);
9069
9181
  Foldable2.box = FoldableComponent.box;
9070
9182
  var Foldable_default = Foldable2;
9183
+
9184
+ // src/utils/localStorage.ts
9185
+ function generateLocalStorage() {
9186
+ return {
9187
+ setItem: (name, value) => {
9188
+ if (!checkBetterHtmlContextValue(externalBetterHtmlContextValue, "generateLocalStorage"))
9189
+ return void 0;
9190
+ const localStoragePlugin2 = externalBetterHtmlContextValue.plugins.find(
9191
+ (plugin) => plugin.name === "localStorage"
9192
+ );
9193
+ if (!localStoragePlugin2) {
9194
+ throw new Error(
9195
+ "`generateLocalStorage` hook requires the `localStorage` plugin to be added to the `plugins` prop in `<BetterHtmlProvider>`."
9196
+ );
9197
+ }
9198
+ const pluginConfig = localStoragePlugin2.getConfig?.() ?? {};
9199
+ const encryptionEnabled = pluginConfig.encryption?.enabled ?? false;
9200
+ const readyName = encryptionEnabled ? encryptString(name.toString()) : name;
9201
+ const readyValue = encryptionEnabled ? encryptString(JSON.stringify(value)) : JSON.stringify(value);
9202
+ if (value) localStorage.setItem(readyName.toString(), readyValue);
9203
+ else localStorage.removeItem(readyName.toString());
9204
+ },
9205
+ getItem: (name) => {
9206
+ if (!checkBetterHtmlContextValue(externalBetterHtmlContextValue, "generateLocalStorage"))
9207
+ return void 0;
9208
+ const localStoragePlugin2 = externalBetterHtmlContextValue.plugins.find(
9209
+ (plugin) => plugin.name === "localStorage"
9210
+ );
9211
+ if (!localStoragePlugin2) {
9212
+ throw new Error(
9213
+ "`generateLocalStorage` hook requires the `localStorage` plugin to be added to the `plugins` prop in `<BetterHtmlProvider>`."
9214
+ );
9215
+ }
9216
+ const pluginConfig = localStoragePlugin2.getConfig?.() ?? {};
9217
+ const encryptionEnabled = pluginConfig.encryption?.enabled ?? false;
9218
+ const readyName = encryptionEnabled ? encryptString(name.toString()) : name;
9219
+ const item = localStorage.getItem(readyName.toString());
9220
+ if (item === null) return void 0;
9221
+ try {
9222
+ return encryptionEnabled ? JSON.parse(decryptString(item)) : JSON.parse(item);
9223
+ } catch (error) {
9224
+ return void 0;
9225
+ }
9226
+ },
9227
+ removeItem: (name) => {
9228
+ if (!checkBetterHtmlContextValue(externalBetterHtmlContextValue, "generateLocalStorage"))
9229
+ return void 0;
9230
+ const localStoragePlugin2 = externalBetterHtmlContextValue.plugins.find(
9231
+ (plugin) => plugin.name === "localStorage"
9232
+ );
9233
+ if (!localStoragePlugin2) {
9234
+ throw new Error(
9235
+ "`generateLocalStorage` hook requires the `localStorage` plugin to be added to the `plugins` prop in `<BetterHtmlProvider>`."
9236
+ );
9237
+ }
9238
+ const pluginConfig = localStoragePlugin2.getConfig?.() ?? {};
9239
+ const encryptionEnabled = pluginConfig.encryption?.enabled ?? false;
9240
+ const readyName = encryptionEnabled ? encryptString(name.toString()) : name;
9241
+ localStorage.removeItem(readyName.toString());
9242
+ },
9243
+ removeAllItems: () => {
9244
+ localStorage.clear();
9245
+ }
9246
+ };
9247
+ }
9071
9248
  // Annotate the CommonJS export names for ESM import in node:
9072
9249
  0 && (module.exports = {
9073
9250
  BetterHtmlProvider,
@@ -9099,17 +9276,21 @@ var Foldable_default = Foldable2;
9099
9276
  countries,
9100
9277
  darkenColor,
9101
9278
  defaultAlertsPluginOptions,
9279
+ defaultLocalStoragePluginOptions,
9280
+ defaultReactRouterDomPluginOptions,
9102
9281
  desaturateColor,
9103
9282
  eventPreventDefault,
9104
9283
  eventPreventStop,
9105
9284
  eventStopPropagation,
9106
9285
  formatPhoneNumber,
9286
+ generateLocalStorage,
9107
9287
  generateRandomString,
9108
9288
  getBrowser,
9109
9289
  getFormErrorObject,
9110
9290
  isMobileDevice,
9111
9291
  lightenColor,
9112
9292
  loaderControls,
9293
+ localStoragePlugin,
9113
9294
  reactRouterDomPlugin,
9114
9295
  saturateColor,
9115
9296
  useAlertControls,