All files / src/ahuora-design-system/ui tabs-content.tsx

86.79% Statements 46/53
53.7% Branches 29/54
50% Functions 3/6
85.71% Lines 30/35

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176                                                        222x             222x 332x 332x 442x     110x         110x                                   442x 442x                           27x         27x 27x   216x   27x             27x 81x 81x                           135x 162x                                           222x       74x       148x     74x                   296x   92x 74x 222x                 148x 222x 296x        
import { TabsListProps } from "@radix-ui/react-tabs";
import * as React from "react";
import { ReactNode } from "react";
import { cn } from "@/lib/utils";
import {
  AccessControlledProps,
  AccessControlledTabsTrigger,
} from "./accessControlled";
import { ScrollArea } from "./scroll-area";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "./tabs";
 
type TabItem = string | { value: string; label: string };
export interface TabsContentUIProps {
  header?: ReactNode | (() => ReactNode);
  tabTriggerValue: string;
  value: ReactNode | (() => ReactNode);
  subTabHeader?: TabListComponentProps;
}
export type TabsConfig = Record<string, TabsContentUIProps>;
//These tabs are mainly used in sidebars
//TODO: make this more dynamic
/**
 * @header - these could be specific controls for that tab
 * @tabtriggervalue - this is the value of the tab
 * @value - this is the content of the tab
 * @subtabheader - Use this when there is a tab within a tab e.g., flowsheet panel
 * @returns a tab content
 */
const TabsContentComponent: React.FC<TabsContentUIProps> = ({
  header,
  tabTriggerValue,
  value,
  subTabHeader,
}) => {
  const mainContent = (
    <div className="flex flex-col gap-2 flex-1 min-h-full">
      {header && <div>{header}</div>}
      <ScrollArea className="h-full">{value}</ScrollArea>
    </div>
  );
  return (
    <TabsContent
      key={tabTriggerValue}
      value={tabTriggerValue}
      className="h-full shrink w-full"
    >
      {subTabHeader ? (
        <Tabs
          defaultValue={subTabHeader.tabValues[0].toLowerCase()}
          onValueChange={subTabHeader.onChangeValue}
          className="h-full flex flex-col"
        >
          <div>
            <TabListComponent
              tabValues={subTabHeader.tabValues}
              bg={subTabHeader.bg}
              rounded={subTabHeader.rounded}
              type={subTabHeader.type}
            />
          </div>
          {mainContent}
        </Tabs>
      ) : (
        mainContent
      )}
    </TabsContent>
  );
};
export { TabsContentComponent };
 
interface TabListComponentProps extends TabsListProps, AccessControlledProps {
  tabValues: TabItem[];
  bg?: "default" | "blend" | null | undefined;
  rounded?: "yes" | "no" | null | undefined;
  type?: "vFull" | "vShort" | "hFull" | "hShort" | null | undefined;
 
  onChangeValue?: (value: string) => void;
}
 
const TabListComponent: React.FC<TabListComponentProps> = ({
  tabValues,
  bg,
  rounded,
  type,
  writeAccessOnly = true,
  hideIfNoAccess = false,
  ...props
}) => {
  return (
    <TabsList
      bg={bg}
      rounded={rounded}
      type={type}
      className="w-full p-0 flex justify-between"
      {...props}
    >
      {tabValues.map((tab, index) => {
        const value = typeof tab === "string" ? tab : tab.value;
        const label = typeof tab === "string" ? tab : tab.label;
 
        return (
          <AccessControlledTabsTrigger
            key={`tab-trigger-${index}`}
            value={value.toLowerCase()} // if your values are expected to be lowercased
            className="capitalize bg-muted p-1"
            bg={bg}
            writeAccessOnly={writeAccessOnly}
            hideIfNoAccess={hideIfNoAccess}
          >
            {label}
          </AccessControlledTabsTrigger>
        );
      })}
    </TabsList>
  );
};
 
export { TabListComponent };
interface TabsComponentProps {
  tabData: TabsConfig;
  hideTrigger?: boolean;
  tabSize?: "vFull" | "vShort" | "hFull" | "hShort";
  tabBackGround?: "default" | "blend";
  className?: string;
}
 
/**
 * Utilise this component instead of TabsPrimitive.Root
 * This minimises issues in regards to scolling and just simplifies tab creation
 * Example usage are in flowsheetobjectpanel and RightSideBarData
 * @param tabData
 * @param hideTrigger
 * @returns tabs
 */
 
const TabsComponent: React.FC<TabsComponentProps> = ({
  tabData,
  hideTrigger,
  tabSize,
  className = "",
}) => {
  return (
    <Tabs
      defaultValue={Object.keys(tabData)[0]}
      className="w-full flex flex-col flex-1"
    >
      {!hideTrigger && (
        <TabsList type={tabSize}>
          {Object.keys(tabData).map((key) => {
            return (
              <TabsTrigger key={key} value={key}>
                {key}
              </TabsTrigger>
            );
          })}
        </TabsList>
      )}
 
      <div className={cn("flex-1", className)}>
        {Object.entries(tabData).map(
          ([key, { header, value, subTabHeader }]) => (
            <TabsContentComponent
              key={key}
              tabTriggerValue={key}
              value={value}
              header={header}
              subTabHeader={subTabHeader}
            />
          ),
        )}
      </div>
    </Tabs>
  );
};
export { TabsComponent };