Skip to content
Snippets Groups Projects
Select Git revision
  • 56144d689100202e4d6996786c413bed514e69a9
  • main default protected
  • fix-textinput-label-styling
  • feature/add_tabs
  • v2.9.0
  • v2.8.0
  • v2.7.0
  • v2.6.0
  • v2.5.0
  • v2.4.0
  • v2.3.0
  • v2.2.0
  • v2.1.1
  • v2.1.0
  • v2.0.0
  • v1.10.0
  • v1.9.1
  • v1.9.0
  • v1.8.4
  • v1.8.3
  • v1.8.2
  • v1.8.1
  • v1.8.0
  • v1.7.0
24 results

baseComponents.tsx

Blame
  • Code owners
    Assign users and groups as approvers for specific file changes. Learn more.
    baseComponents.tsx 3.61 KiB
    import { Input } from "@nextui-org/react";
    import { Dispatch, ReactNode, SetStateAction } from "react";
    import { InputSlots } from "@nextui-org/theme";
    import { clsx } from "clsx";
    import Typography from "src/components/Typography.tsx";
    import { formFieldBg, cursorPointer } from "./classes.ts";
    
    export type LabelPlacement = "outside" | "outside-left";
    
    type BaseInputProps = {
      // basic info
      name?: string; // allow for FormData to work
      label: string;
      labelPlacement: LabelPlacement;
      labelClass: string;
      labelCustomColor: boolean;
      endContent: ReactNode; // such as units or icon
      // value and validation
      placeholder: string;
      isClearable?: boolean;
      value?: string;
      onValueChange?: Dispatch<SetStateAction<string>>;
      isInvalid: boolean;
      errorMessage: string;
      maxLength?: number;
      type?:
        | "text"
        | "search"
        | "url"
        | "tel"
        | "email"
        | "password"
        | (string & NonNullable<unknown>);
      // interaction
      isRequired?: boolean;
      isDisabled?: boolean;
      isReadOnly?: boolean;
      inputMode?:
        | "none"
        | "text"
        | "tel"
        | "url"
        | "email"
        | "numeric"
        | "decimal"
        | "search";
    };
    
    type baseInputClassNamesObj = { [key in InputSlots]: string };
    
    export const baseInputClassNames = (
      isDisabled: boolean,
      labelPlacement: LabelPlacement
    ): baseInputClassNamesObj => {
      // this is the border color (use text-*)
      const mainWrapperClass = (isDisabled: boolean) =>
        isDisabled
          ? "text-mediumGrey dark:text-darkModeBlue"
          : "text-grey dark:text-mediumGrey hover:text-baseBlack focus-within:!text-primary";
    
      const clearButtonClass = (isDisabled: boolean) => {
        if (isDisabled) return "";
    
        // we cannot do "[&>svg]:" + className because Tailwind does not support dynamic class names
        const clearButtonSvgClass: string =
          "[&>svg]:w-[30px] [&>svg]:h-[30px] [&>svg]:mt-[-4px] [&>svg]:ml-[-4px]";
        const clearButtonBaseClass: string =
          "bg-mediumGrey text-baseWhite dark:bg-baseWhite dark:text-mediumGrey w-[22px] h-[22px] p-0 !opacity-100";
        return clsx(clearButtonSvgClass, clearButtonBaseClass);
      };
    
      return {
        base: clsx("flex flex-row justify-between", cursorPointer(isDisabled)),
        input: "!text-foreground-body bg-default",
        inputWrapper: clsx(
          "px-2 rounded-[4px] min-h-[33px] max-h-[33px]",
          formFieldBg(isDisabled)
        ),
        mainWrapper: clsx(
          {
            "w-2/3": labelPlacement === "outside-left",
          },
          mainWrapperClass(isDisabled)
        ),
        clearButton: clearButtonClass(isDisabled),
      } as baseInputClassNamesObj;
    };
    
    export const BaseInput = ({
      name,
      label,
      labelPlacement = "outside",
      labelClass,
      labelCustomColor,
      endContent,
      placeholder,
      isClearable = false,
      value,
      onValueChange,
      isInvalid,
      errorMessage,
      maxLength,
      type = "text",
      isRequired = false,
      isDisabled = false,
      isReadOnly = false,
      inputMode = "text",
    }: BaseInputProps) => {
      return (
        <Input
          label={
            <Typography
              text={label}
              variant="paragraph"
              customClass={labelClass}
              customColor={labelCustomColor}
            />
          }
          name={name}
          endContent={endContent}
          placeholder={placeholder}
          value={value}
          isClearable={isClearable}
          onValueChange={onValueChange}
          isInvalid={isInvalid}
          errorMessage={errorMessage}
          maxLength={maxLength}
          type={type}
          isRequired={isRequired}
          isDisabled={isDisabled}
          isReadOnly={isReadOnly}
          inputMode={inputMode}
          // appearance
          labelPlacement={labelPlacement}
          variant="bordered"
          classNames={baseInputClassNames(isDisabled, labelPlacement)}
        />
      );
    };