How to use ThemeProvider from styled-components in React / Vite build to create a UI components library

49 Views Asked by At

I'm trying to create a React components UI library, but I'm getting some trouble. I'm building the library and importing it, but when I try to use, I get errors like Cannot read white of undefined. Because on my styles I'm using the object theme.colors.white, but I think the <ThemeProvider> that is on my component is not working. How can I solve it?

My Datepicker.tsx

import { useState } from "react";
import InputMask from "react-input-mask";
import { setDefaultOptions } from "date-fns";
import { ThemeProvider } from "styled-components";
import theme from "../../styles/theme";
import GlobalStyles from "../../styles/global";

import {
  DatepickerInputProps,
  ViewModeEnum,
  DateObject,
} from "./Datepicker.types";
import { DatepickerContent } from "./elements/DatepickerContent";
import { DatepickerHelper } from "./Datepicker.helper";

import * as S from "./Datepicker.styles";

export function Datepicker({
  variant = "light",
  isDisabled,
  placeholder,
  isRange = false,
  config,
}: DatepickerInputProps) {
  const initialState = isRange
    ? { startDate: new Date(), endDate: null }
    : new Date();
  const maskValue = DatepickerHelper.getMaskValue(isRange, config?.dateFormat);

  const [selectedDate, setSelectedDate] = useState<Date | DateObject>(
    initialState
  );
  const [activeDate, setActiveDate] = useState(new Date());
  const [dateValue, setDateValue] = useState("");
  const [isOpen, setIsOpen] = useState(false);
  const [viewMode, setViewMode] = useState(ViewModeEnum.DAYS);
  const [error, setError] = useState(false);

  const locale = config?.locale || "en-US";
  const language = DatepickerHelper.getLanguage(locale);
  const errorMessage =
    config?.inputStyles?.errorConfig?.errorText || "Invalid Date";

  setDefaultOptions({ locale: language });

  const handleOpenCalendar = () => {
    setViewMode(ViewModeEnum.DAYS);

    let parsedDate;

    if (isRange) {
      parsedDate = DatepickerHelper.stringToRangeDateOrNewDate(
        dateValue,
        config?.dateFormat
      );
      setActiveDate(parsedDate.startDate);
    } else {
      parsedDate = DatepickerHelper.stringToDateOrNewDate(
        dateValue,
        config?.dateFormat
      );
      setActiveDate(parsedDate);
    }

    setSelectedDate(parsedDate);
    setIsOpen(!isOpen);
  };

  return (
    <ThemeProvider theme={theme}>
      <GlobalStyles />

      <S.Wrapper
        isDisabled={isDisabled}
        config={config}
        variant={variant}
        error={error}
      >
        <S.InputWrapper>
          <InputMask
            mask={maskValue}
            maskChar=""
            disabled={isDisabled}
            value={dateValue}
            onBlur={() =>
              DatepickerHelper.checkIfDateIsValid(
                dateValue,
                isRange,
                setError,
                config?.dateFormat
              )
            }
            onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
              setDateValue(e.target.value)
            }
          >
            {/* @ts-expect-error external lib */}
            {(inputProps) => (
              <S.Input
                type="text"
                placeholder={placeholder}
                disabled={isDisabled}
                {...inputProps}
              />
            )}
          </InputMask>

          <S.DatepickerWrapper
            onBlur={() => {
              setIsOpen(false);
              DatepickerHelper.checkIfDateIsValid(
                dateValue,
                isRange,
                setError,
                config?.dateFormat
              );
            }}
            disabled={isDisabled}
          >
            <S.Icon
              className="fi fi-rr-calendar"
              onClick={() => handleOpenCalendar()}
            />
            {isOpen && (
              <DatepickerContent
                config={config}
                variant={variant}
                viewMode={viewMode}
                activeDate={activeDate}
                selectedDate={selectedDate}
                dateValue={dateValue}
                isRange={isRange}
                onChangeViewMode={setViewMode}
                onChangeActiveDate={setActiveDate}
                onChangeSelectedDate={setSelectedDate}
                onChangeDateValue={setDateValue}
                onOpen={setIsOpen}
                onError={setError}
              />
            )}
          </S.DatepickerWrapper>
        </S.InputWrapper>
        {error && (
          <S.Error>
            <S.ErrorIcon className="fi fi-rr-exclamation" />
            <span>{errorMessage}</span>
          </S.Error>
        )}
      </S.Wrapper>
    </ThemeProvider>
  );
}

package.json

{
  "name": "react-lib-ui",
  "private": false,
  "version": "0.0.0",
  "type": "module",
  "main": "dist/main.js",
  "types": "dist/main.d.ts",
  "files": [
    "dist"
  ],
  "scripts": {
    "dev": "vite",
    "build": "tsc --p ./tsconfig-build.json && vite build",
    "prepublishOnly": "npm run build",
    "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
    "preview": "vite preview"
  },
  "peerDependencies": {
    "react": ">= 16.8.0",
    "react-dom": ">= 16.8.0"
  },
  "dependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "@flaticon/flaticon-uicons": "^3.1.0",
    "date-fns": "^3.3.1",
    "react-input-mask": "^2.0.4",
    "styled-components": "^6.1.8"
  },
  "devDependencies": {
    "@types/node": "^20.11.19",
    "@types/react": "^18.2.55",
    "@types/react-input-mask": "^3.0.5",
    "@typescript-eslint/eslint-plugin": "^6.21.0",
    "@typescript-eslint/parser": "^6.21.0",
    "@vitejs/plugin-react": "^4.2.1",
    "eslint": "^8.56.0",
    "eslint-plugin-react-hooks": "^4.6.0",
    "eslint-plugin-react-refresh": "^0.4.5",
    "glob": "^10.3.10",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "typescript": "^5.2.2",
    "vite": "^5.1.0",
    "vite-plugin-dts": "^3.7.2",
    "vite-plugin-lib-inject-css": "^1.3.0"
  },
  "sideEffects": [
    "**/*.css"
  ]
}

App.tsx trying to use the lib

import "./App.css";
import { Datepicker } from "../";

function App() {
  return (
    <>
      <Datepicker />
    </>
  );
}

export default App;

Error: App.tsx error enter image description here

Probabily not recognizing the theme from theme provider after the

npm run build
0

There are 0 best solutions below