react-better-html 1.1.78 → 1.1.80

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
@@ -37,6 +37,7 @@ __export(index_exports, {
37
37
  Div: () => Div_default,
38
38
  Divider: () => Divider_default,
39
39
  Dropdown: () => Dropdown_default,
40
+ Foldable: () => Foldable_default,
40
41
  Form: () => Form_default,
41
42
  FormRow: () => FormRow_default,
42
43
  Icon: () => Icon_default,
@@ -48,6 +49,7 @@ __export(index_exports, {
48
49
  PageHeader: () => PageHeader_default,
49
50
  PageHolder: () => PageHolder_default,
50
51
  Table: () => Table_default,
52
+ Tabs: () => Tabs_default,
51
53
  Text: () => Text_default,
52
54
  ToggleInput: () => ToggleInput_default,
53
55
  formatPhoneNumber: () => formatPhoneNumber,
@@ -1574,9 +1576,17 @@ var useBetterHtmlContext = () => {
1574
1576
  throw new Error(
1575
1577
  "`useBetterHtmlContext()` must be used within a `<BetterHtmlProvider>`. Make sure to add one at the root of your component tree."
1576
1578
  );
1577
- const { setLoaders, plugins, ...rest } = context;
1579
+ const { setLoaders, plugins, tabsComponentState, ...rest } = context;
1578
1580
  return rest;
1579
1581
  };
1582
+ var useBetterHtmlContextInternal = () => {
1583
+ const context = (0, import_react.useContext)(betterHtmlContext);
1584
+ if (context === void 0)
1585
+ throw new Error(
1586
+ "`useBetterHtmlContextInternal()` must be used within a `<BetterHtmlProvider>`. Make sure to add one at the root of your component tree."
1587
+ );
1588
+ return context;
1589
+ };
1580
1590
  var useTheme = () => {
1581
1591
  const context = (0, import_react.useContext)(betterHtmlContext);
1582
1592
  if (context === void 0)
@@ -1643,11 +1653,13 @@ function BetterHtmlProviderContent({ children }) {
1643
1653
  ] });
1644
1654
  }
1645
1655
  function BetterHtmlProvider({ value, plugins: pluginsToUse, children }) {
1646
- const [loaders, setLoaders] = (0, import_react.useState)(value?.loaders ?? {});
1647
- const [plugins] = (0, import_react.useState)(pluginsToUse ?? []);
1648
1656
  const [colorTheme, setColorTheme] = (0, import_react.useState)(
1649
1657
  localStorage.getItem("theme") === "dark" ? "dark" : value?.colorTheme ?? "light"
1650
1658
  );
1659
+ const [loaders, setLoaders] = (0, import_react.useState)(value?.loaders ?? {});
1660
+ const [plugins] = (0, import_react.useState)(pluginsToUse ?? []);
1661
+ const [tabGroups, setTabGroups] = (0, import_react.useState)([]);
1662
+ const [tabsWithDots, setTabsWithDots] = (0, import_react.useState)([]);
1651
1663
  const readyValue = (0, import_react.useMemo)(
1652
1664
  () => ({
1653
1665
  app: {
@@ -1684,9 +1696,15 @@ function BetterHtmlProvider({ value, plugins: pluginsToUse, children }) {
1684
1696
  components: {
1685
1697
  ...value?.components
1686
1698
  },
1687
- plugins
1699
+ plugins,
1700
+ tabsComponentState: {
1701
+ tabGroups,
1702
+ setTabGroups,
1703
+ tabsWithDots,
1704
+ setTabsWithDots
1705
+ }
1688
1706
  }),
1689
- [value, colorTheme, loaders, plugins]
1707
+ [value, colorTheme, loaders, plugins, tabGroups, tabsWithDots]
1690
1708
  );
1691
1709
  (0, import_react.useEffect)(() => {
1692
1710
  plugins.forEach((plugin) => {
@@ -2387,7 +2405,7 @@ var IconElement = import_styled_components5.default.svg.withConfig({
2387
2405
  `;
2388
2406
  var Icon = (0, import_react6.forwardRef)(function Icon2({ name, size = 16, ...props }, ref) {
2389
2407
  const theme2 = useTheme();
2390
- const { icons: icons2 } = useBetterHtmlContext();
2408
+ const { icons: icons2 } = useBetterHtmlContextInternal();
2391
2409
  const styledComponentStyles = useStyledComponentStyles(props, theme2);
2392
2410
  const dataProps = useComponentPropsWithPrefix(props, "data");
2393
2411
  const ariaProps = useComponentPropsWithPrefix(props, "aria");
@@ -2446,7 +2464,7 @@ var ImageElement = import_styled_components6.default.img.withConfig({
2446
2464
  `;
2447
2465
  var Image = (0, import_react8.forwardRef)(function Image2({ name, src, ...props }, ref) {
2448
2466
  const theme2 = useTheme();
2449
- const { assets: assets2 } = useBetterHtmlContext();
2467
+ const { assets: assets2 } = useBetterHtmlContextInternal();
2450
2468
  const styledComponentStyles = useStyledComponentStyles(props, theme2);
2451
2469
  const dataProps = useComponentPropsWithPrefix(props, "data");
2452
2470
  const ariaProps = useComponentPropsWithPrefix(props, "aria");
@@ -2483,7 +2501,7 @@ var import_react9 = require("react");
2483
2501
  var import_styled_components7 = __toESM(require("styled-components"));
2484
2502
  var import_jsx_runtime7 = require("react/jsx-runtime");
2485
2503
  var ButtonElement = import_styled_components7.default.button.withConfig({
2486
- shouldForwardProp: (prop) => !["theme", "normalStyle", "hoverStyle", "isSmall", "withText", "isLoading"].includes(prop)
2504
+ shouldForwardProp: (prop) => !["theme", "colorTheme", "normalStyle", "hoverStyle", "isSmall", "withText", "isLoading"].includes(prop)
2487
2505
  })`
2488
2506
  display: block;
2489
2507
  position: relative;
@@ -2505,15 +2523,11 @@ var ButtonElement = import_styled_components7.default.button.withConfig({
2505
2523
  ${(props) => props.disabled ? import_styled_components7.css`
2506
2524
  opacity: 0.6;
2507
2525
  cursor: not-allowed;
2508
-
2509
- &.secondary:disabled {
2510
- filter: brightness(0.9);
2511
- }
2512
2526
  ` : !props.isLoading ? import_styled_components7.css`
2513
2527
  cursor: pointer;
2514
2528
 
2515
2529
  &:not(.secondary):hover {
2516
- filter: brightness(0.9);
2530
+ filter: ${props.colorTheme === "dark" ? "brightness(1.2)" : "brightness(0.9)"};
2517
2531
  }
2518
2532
 
2519
2533
  &.secondary:hover {
@@ -2562,7 +2576,7 @@ var ButtonComponent = function Button({
2562
2576
  }) {
2563
2577
  const theme2 = useTheme();
2564
2578
  const isLoadingHook = useLoader(loaderName);
2565
- const betterHtmlContext2 = useBetterHtmlContext();
2579
+ const betterHtmlContext2 = useBetterHtmlContextInternal();
2566
2580
  const isLoadingElement = isLoading ?? isLoadingHook;
2567
2581
  const styledComponentStyles = useStyledComponentStyles(
2568
2582
  {
@@ -2603,6 +2617,7 @@ var ButtonComponent = function Button({
2603
2617
  {
2604
2618
  as: href ? "a" : "button",
2605
2619
  theme: theme2,
2620
+ colorTheme: betterHtmlContext2.colorTheme,
2606
2621
  isSmall,
2607
2622
  withText: text !== void 0,
2608
2623
  isLoading: isLoadingElement,
@@ -2664,7 +2679,7 @@ var ButtonComponent = function Button({
2664
2679
  };
2665
2680
  ButtonComponent.secondary = function Secondary({ className, ...props }) {
2666
2681
  const theme2 = useTheme();
2667
- const betterHtmlContext2 = useBetterHtmlContext();
2682
+ const betterHtmlContext2 = useBetterHtmlContextInternal();
2668
2683
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2669
2684
  ButtonComponent,
2670
2685
  {
@@ -2677,7 +2692,7 @@ ButtonComponent.secondary = function Secondary({ className, ...props }) {
2677
2692
  };
2678
2693
  ButtonComponent.destructive = function Destructive(props) {
2679
2694
  const theme2 = useTheme();
2680
- const betterHtmlContext2 = useBetterHtmlContext();
2695
+ const betterHtmlContext2 = useBetterHtmlContextInternal();
2681
2696
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2682
2697
  ButtonComponent,
2683
2698
  {
@@ -2690,7 +2705,7 @@ ButtonComponent.destructive = function Destructive(props) {
2690
2705
  };
2691
2706
  ButtonComponent.icon = function Icon3({ size = 16, backgroundButtonColor, ...props }) {
2692
2707
  const theme2 = useTheme();
2693
- const betterHtmlContext2 = useBetterHtmlContext();
2708
+ const betterHtmlContext2 = useBetterHtmlContextInternal();
2694
2709
  const buttonSize = size + theme2.styles.space;
2695
2710
  const backgroundButtonColorReady = backgroundButtonColor ?? theme2.colors.textPrimary;
2696
2711
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
@@ -2714,7 +2729,7 @@ ButtonComponent.icon = function Icon3({ size = 16, backgroundButtonColor, ...pro
2714
2729
  );
2715
2730
  };
2716
2731
  ButtonComponent.upload = function Upload({ accept, multiple, onUpload, ...props }) {
2717
- const betterHtmlContext2 = useBetterHtmlContext();
2732
+ const betterHtmlContext2 = useBetterHtmlContextInternal();
2718
2733
  const onClickElement = (0, import_react9.useCallback)(() => {
2719
2734
  const input = document.createElement("input");
2720
2735
  input.setAttribute("type", "file");
@@ -2836,7 +2851,7 @@ var ModalComponent = (0, import_react11.forwardRef)(function Modal({
2836
2851
  const reactRouterDomPlugin2 = usePlugin("react-router-dom");
2837
2852
  const urlQuery = reactRouterDomPlugin2 ? useUrlQuery() : void 0;
2838
2853
  const theme2 = useTheme();
2839
- const { app, colorTheme } = useBetterHtmlContext();
2854
+ const { app, colorTheme } = useBetterHtmlContextInternal();
2840
2855
  const dialogRef = (0, import_react11.useRef)(null);
2841
2856
  const [isOpened, setIsOpened] = (0, import_react11.useState)(false);
2842
2857
  const [isOpenedLate, setIsOpenedLate] = (0, import_react11.useState)(false);
@@ -2844,13 +2859,14 @@ var ModalComponent = (0, import_react11.forwardRef)(function Modal({
2844
2859
  dialogRef.current?.showModal();
2845
2860
  setIsOpened(true);
2846
2861
  setIsOpenedLate(true);
2847
- if (urlQuery && name)
2862
+ if (urlQuery && name) {
2848
2863
  urlQuery.setQuery(
2849
2864
  {
2850
2865
  [`${name}-modal`]: "opened"
2851
2866
  },
2852
2867
  false
2853
2868
  );
2869
+ }
2854
2870
  onOpen?.();
2855
2871
  }, [onOpen, urlQuery, name]);
2856
2872
  const onClickClose = (0, import_react11.useCallback)(() => {
@@ -3046,7 +3062,7 @@ var import_react12 = require("react");
3046
3062
  var import_jsx_runtime10 = require("react/jsx-runtime");
3047
3063
  function PageHolder({ noMaxContentWidth, children }) {
3048
3064
  const theme2 = useTheme();
3049
- const { app } = useBetterHtmlContext();
3065
+ const { app } = useBetterHtmlContextInternal();
3050
3066
  return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
3051
3067
  Div_default,
3052
3068
  {
@@ -3077,7 +3093,7 @@ function PageHeader({
3077
3093
  marginBottom
3078
3094
  }) {
3079
3095
  const theme2 = useTheme();
3080
- const { app } = useBetterHtmlContext();
3096
+ const { app } = useBetterHtmlContextInternal();
3081
3097
  const mediaQuery = useMediaQuery();
3082
3098
  return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(Div_default.row, { alignItems: "center", gap: theme2.styles.space, marginBottom: marginBottom ?? theme2.styles.space * 2, children: [
3083
3099
  imageUrl && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(Image_default.profileImage, { src: imageUrl, size: imageSize ?? (mediaQuery.size600 ? 46 : 60) }),
@@ -4750,7 +4766,7 @@ var DropdownComponent = (0, import_react16.forwardRef)(function Dropdown({
4750
4766
  ...props
4751
4767
  }, ref) {
4752
4768
  const theme2 = useTheme();
4753
- const dropdownHolderRef = (0, import_react16.useRef)(null);
4769
+ const inputFieldHolderRef = (0, import_react16.useRef)(null);
4754
4770
  const inputRef = (0, import_react16.useRef)(null);
4755
4771
  const [isOpen, setIsOpen] = useBooleanState();
4756
4772
  const [isOpenLate, setIsOpenLate] = useBooleanState();
@@ -4861,7 +4877,7 @@ var DropdownComponent = (0, import_react16.forwardRef)(function Dropdown({
4861
4877
  }, [filteredOptions]);
4862
4878
  (0, import_react16.useEffect)(() => {
4863
4879
  const handleClickOutside = (event) => {
4864
- if (dropdownHolderRef.current && !dropdownHolderRef.current.contains(event.target)) {
4880
+ if (inputFieldHolderRef.current && !inputFieldHolderRef.current.contains(event.target)) {
4865
4881
  setIsOpen.setFalse();
4866
4882
  setSearchQuery("");
4867
4883
  setFocusedOptionIndex(void 0);
@@ -4881,7 +4897,7 @@ var DropdownComponent = (0, import_react16.forwardRef)(function Dropdown({
4881
4897
  const displayValue = withSearch && isFocused ? searchQuery : selectedOption?.label ?? "";
4882
4898
  const withClearButton = isOpen && selectedOption;
4883
4899
  const readyPlaceholder = placeholder ? placeholder : `Select an ${label?.toLowerCase() ?? "option"}`;
4884
- return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Div_default.column, { width: "100%", position: "relative", userSelect: "none", ...props, ref: dropdownHolderRef, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Div_default.row, { position: "relative", width: "100%", children: [
4900
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(Div_default.column, { width: "100%", position: "relative", userSelect: "none", ...props, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(Div_default.row, { position: "relative", width: "100%", ref: inputFieldHolderRef, children: [
4885
4901
  /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
4886
4902
  InputField_default,
4887
4903
  {
@@ -5360,9 +5376,9 @@ var InputFieldComponent = (0, import_react18.forwardRef)(function InputField({
5360
5376
  if (!withDebounce) return;
5361
5377
  onChangeValue?.(debouncedValue);
5362
5378
  }, [withDebounce, onChangeValue, debouncedValue]);
5363
- return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Div_default.column, { width: "100%", gap: theme2.styles.gap, ...styledComponentStylesWithExcluded, ref: holderRef, children: [
5379
+ return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Div_default.column, { width: "100%", gap: theme2.styles.gap, ...styledComponentStylesWithExcluded, children: [
5364
5380
  label && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(Label_default, { text: label, color: labelColor, required, isError: !!errorText }),
5365
- /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Div_default, { position: "relative", width: "100%", children: [
5381
+ /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(Div_default, { position: "relative", width: "100%", ref: holderRef, children: [
5366
5382
  leftIcon && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
5367
5383
  Icon_default,
5368
5384
  {
@@ -5975,6 +5991,8 @@ var InputElement2 = import_styled_components10.default.input.withConfig({
5975
5991
  ${(props) => props.normalStyle}
5976
5992
 
5977
5993
  &:hover {
5994
+ border-color: ${(props) => props.theme.colors.primary};
5995
+
5978
5996
  ${(props) => props.hoverStyle}
5979
5997
  }
5980
5998
  `;
@@ -6460,7 +6478,7 @@ var TableComponent = (0, import_react23.forwardRef)(function Table({
6460
6478
  onClickAllCheckboxes,
6461
6479
  ...props
6462
6480
  }, ref) {
6463
- const { colorTheme } = useBetterHtmlContext();
6481
+ const { colorTheme } = useBetterHtmlContextInternal();
6464
6482
  const theme2 = useTheme();
6465
6483
  const [checkedItems, setCheckedItems] = (0, import_react23.useState)([]);
6466
6484
  const renderCellContent = (0, import_react23.useCallback)(
@@ -6570,6 +6588,301 @@ var TableComponent = (0, import_react23.forwardRef)(function Table({
6570
6588
  var Table2 = (0, import_react23.memo)(TableComponent);
6571
6589
  var Table_default = Table2;
6572
6590
 
6591
+ // src/components/Tabs.tsx
6592
+ var import_react24 = require("react");
6593
+ var import_jsx_runtime22 = require("react/jsx-runtime");
6594
+ var tabBottomLineWidth = 2;
6595
+ var tabDotSize = 6;
6596
+ var defaultTabName = "tab";
6597
+ var TabsComponent = function Tabs({
6598
+ tabs,
6599
+ name,
6600
+ accentColor,
6601
+ style = "default",
6602
+ children,
6603
+ ...props
6604
+ }) {
6605
+ const reactRouterDomPlugin2 = usePlugin("react-router-dom");
6606
+ const theme2 = useTheme();
6607
+ const urlQuery = reactRouterDomPlugin2 ? useUrlQuery() : void 0;
6608
+ const { colorTheme, tabsComponentState } = useBetterHtmlContextInternal();
6609
+ const tabsRef = (0, import_react24.useRef)({});
6610
+ const [selectedTab, setSelectedTab] = (0, import_react24.useState)(() => {
6611
+ const selectedTabValue = tabs[0] ?? "";
6612
+ if (urlQuery) {
6613
+ const tabQueryValue = urlQuery.getQuery(name ?? defaultTabName);
6614
+ if (!tabQueryValue) return selectedTabValue;
6615
+ if (tabs.includes(tabQueryValue)) return tabQueryValue;
6616
+ }
6617
+ return selectedTabValue;
6618
+ });
6619
+ const [rerenderState, setRerenderState] = (0, import_react24.useState)(0);
6620
+ const tabsGap = style === "box" ? theme2.styles.gap / 2 : 0;
6621
+ const onClickTab = (0, import_react24.useCallback)(
6622
+ (tab) => {
6623
+ setSelectedTab(tab);
6624
+ if (urlQuery) {
6625
+ urlQuery.setQuery({
6626
+ [name ?? defaultTabName]: tab
6627
+ });
6628
+ }
6629
+ },
6630
+ [name, urlQuery]
6631
+ );
6632
+ const width = (0, import_react24.useMemo)(
6633
+ () => tabsRef.current[selectedTab]?.getBoundingClientRect().width ?? 0,
6634
+ [rerenderState, selectedTab]
6635
+ );
6636
+ const leftSpacing = (0, import_react24.useMemo)(() => {
6637
+ const selectedTabIndex = tabs.findIndex((tab) => tab === selectedTab);
6638
+ let totalWidth = 0;
6639
+ Object.values(tabsRef.current).forEach((tab, index) => {
6640
+ if (index < selectedTabIndex) totalWidth += (tab?.getBoundingClientRect().width ?? 0) + tabsGap;
6641
+ });
6642
+ return totalWidth;
6643
+ }, [selectedTab, tabs, tabsGap]);
6644
+ (0, import_react24.useEffect)(() => {
6645
+ const timeout = setTimeout(() => setRerenderState(Math.random()), 0.01 * 1e3);
6646
+ return () => {
6647
+ clearTimeout(timeout);
6648
+ };
6649
+ }, []);
6650
+ (0, import_react24.useEffect)(() => {
6651
+ tabsComponentState.setTabGroups((oldValue) => {
6652
+ const thisTabGroup = oldValue.find((item) => item.name === (name ?? defaultTabName));
6653
+ if (thisTabGroup) {
6654
+ return oldValue.map(
6655
+ (item) => item.name === (name ?? defaultTabName) ? {
6656
+ ...item,
6657
+ selectedTab
6658
+ } : item
6659
+ );
6660
+ } else {
6661
+ return [
6662
+ ...oldValue,
6663
+ {
6664
+ name: name ?? defaultTabName,
6665
+ selectedTab
6666
+ }
6667
+ ];
6668
+ }
6669
+ });
6670
+ }, [selectedTab, name]);
6671
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Div_default.column, { width: "100%", gap: theme2.styles.space, ...props, children: [
6672
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(Div_default, { position: "relative", className: "react-better-html-no-scrollbar", overflowY: "auto", children: [
6673
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Div_default.row, { position: "relative", width: "fit-content", gap: tabsGap, userSelect: "none", children: tabs.map((tab) => {
6674
+ const selected = tab === selectedTab;
6675
+ return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(
6676
+ Div_default,
6677
+ {
6678
+ position: "relative",
6679
+ width: "fit-content",
6680
+ backgroundColor: style === "box" ? selected ? theme2.colors.primary : theme2.colors.backgroundContent : theme2.colors.backgroundBase,
6681
+ borderRadius: style === "box" ? theme2.styles.borderRadius : void 0,
6682
+ borderTopLeftRadius: style === "borderRadiusTop" ? theme2.styles.borderRadius : void 0,
6683
+ borderTopRightRadius: style === "borderRadiusTop" ? theme2.styles.borderRadius : void 0,
6684
+ border: style === "box" ? `1px solid ${selected ? "transparent" : theme2.colors.border}` : void 0,
6685
+ filterHover: colorTheme === "dark" ? style === "box" ? "brightness(1.2)" : "brightness(2)" : "brightness(0.9)",
6686
+ paddingInline: theme2.styles.space,
6687
+ paddingBlock: theme2.styles.gap,
6688
+ value: tab,
6689
+ cursor: "pointer",
6690
+ isTabAccessed: true,
6691
+ onClickWithValue: onClickTab,
6692
+ ref: (ref) => {
6693
+ tabsRef.current[tab] = ref;
6694
+ },
6695
+ children: [
6696
+ tabsComponentState.tabsWithDots.includes(tab) && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6697
+ Div_default,
6698
+ {
6699
+ position: "absolute",
6700
+ top: (theme2.styles.space - tabDotSize) / 2,
6701
+ right: (theme2.styles.space - tabDotSize) / 2,
6702
+ width: tabDotSize,
6703
+ height: tabDotSize,
6704
+ backgroundColor: style === "box" && selected ? theme2.colors.base : theme2.colors.primary,
6705
+ borderRadius: 999,
6706
+ transition: theme2.styles.transition
6707
+ }
6708
+ ),
6709
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6710
+ Text_default,
6711
+ {
6712
+ fontWeight: 700,
6713
+ color: !selected ? theme2.colors.textSecondary : style === "box" ? theme2.colors.base : void 0,
6714
+ transition: theme2.styles.transition,
6715
+ whiteSpace: "nowrap",
6716
+ children: tab
6717
+ }
6718
+ )
6719
+ ]
6720
+ },
6721
+ tab
6722
+ );
6723
+ }) }),
6724
+ style !== "box" && /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
6725
+ Div_default,
6726
+ {
6727
+ position: "absolute",
6728
+ width,
6729
+ height: tabBottomLineWidth,
6730
+ bottom: 0,
6731
+ left: leftSpacing,
6732
+ backgroundColor: accentColor ?? theme2.colors.primary,
6733
+ transition: theme2.styles.transition
6734
+ }
6735
+ )
6736
+ ] }),
6737
+ /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Div_default, { width: "100%", children })
6738
+ ] });
6739
+ };
6740
+ TabsComponent.content = function Content({ tab, tabWithDot, tabsGroupName, children }) {
6741
+ const { tabsComponentState } = useBetterHtmlContextInternal();
6742
+ const thisTabGroupData = (0, import_react24.useMemo)(
6743
+ () => tabsComponentState.tabGroups.find((item) => item.name === (tabsGroupName ?? defaultTabName)),
6744
+ [tabsComponentState, tabsGroupName]
6745
+ );
6746
+ (0, import_react24.useEffect)(() => {
6747
+ if (tabWithDot) {
6748
+ tabsComponentState.setTabsWithDots?.((oldValue) => oldValue.includes(tab) ? oldValue : [...oldValue, tab]);
6749
+ } else {
6750
+ tabsComponentState.setTabsWithDots?.(
6751
+ (oldValue) => oldValue.includes(tab) ? oldValue.filter((tab2) => tab2 !== tab2) : oldValue
6752
+ );
6753
+ }
6754
+ }, [tabWithDot]);
6755
+ return thisTabGroupData?.selectedTab === tab ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(Div_default, { width: "100%", children }) : void 0;
6756
+ };
6757
+ var Tabs2 = (0, import_react24.memo)(TabsComponent);
6758
+ Tabs2.content = TabsComponent.content;
6759
+ var Tabs_default = Tabs2;
6760
+
6761
+ // src/components/Foldable.tsx
6762
+ var import_react25 = require("react");
6763
+ var import_jsx_runtime23 = require("react/jsx-runtime");
6764
+ var animationDuration = 0.2;
6765
+ var FoldableComponent = (0, import_react25.forwardRef)(function Foldable({
6766
+ isOpen: controlledIsOpen,
6767
+ defaultOpen = false,
6768
+ title,
6769
+ description,
6770
+ icon,
6771
+ image,
6772
+ headerPaddingInline,
6773
+ renderHeader,
6774
+ onOpenChange,
6775
+ children,
6776
+ ...props
6777
+ }, ref) {
6778
+ const theme2 = useTheme();
6779
+ const bodyRef = (0, import_react25.useRef)(null);
6780
+ const [internalIsOpen, setInternalIsOpen] = useBooleanState(defaultOpen);
6781
+ const [bodyHeight, setBodyHeight] = (0, import_react25.useState)(defaultOpen ? void 0 : 0);
6782
+ const isOpen = controlledIsOpen !== void 0 ? controlledIsOpen : internalIsOpen;
6783
+ const open = (0, import_react25.useCallback)(() => {
6784
+ if (controlledIsOpen === void 0) setInternalIsOpen.setTrue();
6785
+ onOpenChange?.(true);
6786
+ }, [controlledIsOpen, onOpenChange]);
6787
+ const close = (0, import_react25.useCallback)(() => {
6788
+ if (controlledIsOpen === void 0) setInternalIsOpen.setFalse();
6789
+ onOpenChange?.(false);
6790
+ }, [controlledIsOpen, onOpenChange]);
6791
+ const toggleOpen = (0, import_react25.useCallback)(() => {
6792
+ if (controlledIsOpen === void 0) setInternalIsOpen.toggle();
6793
+ onOpenChange?.(!isOpen);
6794
+ }, [controlledIsOpen, isOpen, onOpenChange]);
6795
+ (0, import_react25.useEffect)(() => {
6796
+ if (!bodyRef.current) return;
6797
+ if (isOpen) {
6798
+ const height = bodyRef.current.scrollHeight;
6799
+ setBodyHeight(height);
6800
+ const timeout = setTimeout(() => {
6801
+ setBodyHeight(void 0);
6802
+ }, animationDuration * 1e3);
6803
+ return () => {
6804
+ clearTimeout(timeout);
6805
+ };
6806
+ } else {
6807
+ if (bodyHeight === void 0) {
6808
+ const height = bodyRef.current.scrollHeight;
6809
+ setBodyHeight(height);
6810
+ bodyRef.current.offsetHeight;
6811
+ }
6812
+ const timeout = setTimeout(() => {
6813
+ setBodyHeight(0);
6814
+ }, 0.01 * 1e3);
6815
+ return () => {
6816
+ clearTimeout(timeout);
6817
+ };
6818
+ }
6819
+ }, [isOpen, animationDuration, bodyHeight]);
6820
+ (0, import_react25.useImperativeHandle)(
6821
+ ref,
6822
+ () => {
6823
+ return {
6824
+ open,
6825
+ close,
6826
+ toggle: toggleOpen,
6827
+ isOpen
6828
+ };
6829
+ },
6830
+ [open, close, toggleOpen, isOpen]
6831
+ );
6832
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(Div_default.column, { width: "100%", overflow: "hidden", ...props, children: [
6833
+ renderHeader ? renderHeader(isOpen, toggleOpen) : /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(
6834
+ Div_default.row,
6835
+ {
6836
+ width: "100%",
6837
+ alignItems: "center",
6838
+ gap: theme2.styles.gap,
6839
+ paddingBlock: theme2.styles.gap,
6840
+ paddingInline: headerPaddingInline,
6841
+ cursor: "pointer",
6842
+ onClick: toggleOpen,
6843
+ userSelect: "none",
6844
+ children: [
6845
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(Div_default.row, { flex: 1, alignItems: "center", gap: theme2.styles.space, children: [
6846
+ icon && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Icon_default, { name: icon, size: 20, flexShrink: 0 }),
6847
+ image && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Image_default.profileImage, { name: image, size: 24, flexShrink: 0 }),
6848
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(Div_default.column, { gap: theme2.styles.gap / 2, children: [
6849
+ title && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Text_default, { as: "h3", fontWeight: 700, children: title }),
6850
+ description && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Text_default, { color: theme2.colors.textSecondary, children: description })
6851
+ ] })
6852
+ ] }),
6853
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6854
+ Icon_default,
6855
+ {
6856
+ name: "chevronDown",
6857
+ transform: `rotate(${isOpen ? 180 : 0}deg)`,
6858
+ transition: theme2.styles.transition
6859
+ }
6860
+ )
6861
+ ]
6862
+ }
6863
+ ),
6864
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Div_default, { height: isOpen ? 1 : 0, opacity: isOpen ? 1 : 0, transition: theme2.styles.transition, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Divider_default.horizontal, {}) }),
6865
+ /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Div_default, { height: bodyHeight, transition: `height ${animationDuration}s ease`, ref: bodyRef, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Div_default, { paddingBlock: theme2.styles.gap, paddingInline: headerPaddingInline, children }) })
6866
+ ] });
6867
+ });
6868
+ FoldableComponent.box = (0, import_react25.forwardRef)(function Box3({ ...props }, ref) {
6869
+ const theme2 = useTheme();
6870
+ return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
6871
+ FoldableComponent,
6872
+ {
6873
+ backgroundColor: theme2.colors.backgroundContent,
6874
+ border: `1px solid ${theme2.colors.border}`,
6875
+ borderRadius: theme2.styles.borderRadius,
6876
+ headerPaddingInline: theme2.styles.space,
6877
+ ...props,
6878
+ ref
6879
+ }
6880
+ );
6881
+ });
6882
+ var Foldable2 = (0, import_react25.memo)(FoldableComponent);
6883
+ Foldable2.box = FoldableComponent.box;
6884
+ var Foldable_default = Foldable2;
6885
+
6573
6886
  // src/utils/variableFunctions.ts
6574
6887
  var checkBetterHtmlContextValue = (value, functionsName) => {
6575
6888
  if (value === void 0) {
@@ -6617,6 +6930,7 @@ var reactRouterDomPlugin = {
6617
6930
  Div,
6618
6931
  Divider,
6619
6932
  Dropdown,
6933
+ Foldable,
6620
6934
  Form,
6621
6935
  FormRow,
6622
6936
  Icon,
@@ -6628,6 +6942,7 @@ var reactRouterDomPlugin = {
6628
6942
  PageHeader,
6629
6943
  PageHolder,
6630
6944
  Table,
6945
+ Tabs,
6631
6946
  Text,
6632
6947
  ToggleInput,
6633
6948
  formatPhoneNumber,