diff --git a/.eslintrc.js b/.eslintrc.js index 91a53352..ba564460 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,61 +1,35 @@ module.exports = { env: { + browser: true, + es2021: true, node: true, - "jest/globals": true, + jest: true, }, extends: [ - "airbnb-base", - "airbnb-typescript/base", - "plugin:@typescript-eslint/recommended", + "eslint:recommended", + "@typescript-eslint/recommended", + "plugin:react/recommended", + "plugin:react-hooks/recommended", "prettier", - "plugin:jest-dom/recommended", - "plugin:testing-library/react", - "plugin:css-modules/recommended", ], parser: "@typescript-eslint/parser", parserOptions: { ecmaFeatures: { jsx: true, }, - project: "./tsconfig.json", + ecmaVersion: "latest", + sourceType: "module", + }, + plugins: ["react", "react-hooks", "@typescript-eslint"], + settings: { + react: { + version: "detect", + }, }, - plugins: [ - "@typescript-eslint", - "jest", - "jest-dom", - "testing-library", - "css-modules", - ], rules: { - "@typescript-eslint/no-unused-vars": [ - "error", - { - argsIgnorePattern: "^_", - varsIgnorePattern: "^_", - }, - ], - "@typescript-eslint/no-use-before-define": [ - "error", - { - functions: false, - classes: false, - }, - ], - "import/prefer-default-export": "off", - "no-use-before-define": [ - "error", - { - functions: false, - classes: false, - }, - ], + "react/react-in-jsx-scope": "off", + "react/prop-types": "off", + "no-unused-vars": "off", // Turn off base rule for TypeScript + "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_" }], }, - overrides: [ - { - files: ["*test.ts?(x)"], - rules: { - "@typescript-eslint/no-var-requires": "off", - }, - }, - ], }; diff --git a/.github/workflows/github-ci.yml b/.github/workflows/github-ci.yml index 0206d48d..4fb10260 100644 --- a/.github/workflows/github-ci.yml +++ b/.github/workflows/github-ci.yml @@ -1,22 +1,29 @@ name: Run CI on commit-graph on: pull_request: - paths: - - "/" + push: + branches: [main] workflow_dispatch: jobs: ci: - runs-on: ubuntu-22.04 + runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 + uses: actions/checkout@v4 + - name: Setup Node.js + uses: actions/setup-node@v4 with: - node-version: "18" - - name: Run the "npm ci" command - run: npm ci - - name: Run the "npm run build" command - run: npm run build - - name: Run the "npm test" command - run: npm test + node-version: "22" + - name: Enable Corepack + run: corepack enable + - name: Install dependencies + run: yarn install --immutable + - name: Lint + run: yarn lint + - name: Type check + run: yarn compile + - name: Test + run: yarn test + - name: Build + run: yarn build diff --git a/.gitignore b/.gitignore index bedadb65..3074be1a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,14 @@ # dependencies /node_modules +# Yarn Berry +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/sdks +!.yarn/versions + # next.js /.next/ .env.*.local @@ -9,6 +17,9 @@ # rollup cache /.rollup.cache/ +# TypeScript build cache +tsconfig.tsbuildinfo + #logs ./storybook.log diff --git a/.storybook/main.ts b/.storybook/main.ts index ae8a2eab..6523d4fc 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -1,12 +1,48 @@ -import type { StorybookConfig } from "@storybook/nextjs"; +import type { StorybookConfig } from "@storybook/react-webpack5"; + const config: StorybookConfig = { stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|ts|tsx)"], + addons: ["@storybook/addon-webpack5-compiler-swc"], framework: { - name: "@storybook/nextjs", + name: "@storybook/react-webpack5", options: {}, }, - docs: { - autodocs: "tag", + webpackFinal: async config => { + // Remove ALL existing CSS rules (including Storybook's implicit one) + config.module!.rules = (config.module?.rules ?? []).filter(rule => { + if (!rule || typeof rule !== "object") return true; + if (rule.test instanceof RegExp && rule.test.test("test.css")) { + return false; + } + return true; + }); + + // Add our own CSS rules with proper CSS modules support + config.module!.rules.push( + { + test: /\.css$/, + exclude: /\.module\.css$/, + sideEffects: true, + use: ["style-loader", "css-loader"], + }, + { + test: /\.module\.css$/, + use: [ + "style-loader", + { + loader: "css-loader", + options: { + importLoaders: 1, + modules: { + localIdentName: "[folder]_[local]__[hash:base64:5]", + namedExport: false, + }, + }, + }, + ], + }, + ); + return config; }, }; export default config; diff --git a/.yarnrc.yml b/.yarnrc.yml new file mode 100644 index 00000000..3186f3f0 --- /dev/null +++ b/.yarnrc.yml @@ -0,0 +1 @@ +nodeLinker: node-modules diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 00000000..7e33a802 --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,40 @@ +const js = require("@eslint/js"); +const tseslint = require("typescript-eslint"); +const react = require("eslint-plugin-react"); + +module.exports = tseslint.config( + js.configs.recommended, + ...tseslint.configs.recommended, + { + files: ["src/**/*.{ts,tsx}"], + plugins: { + react, + }, + languageOptions: { + ecmaVersion: "latest", + sourceType: "module", + parserOptions: { + ecmaFeatures: { + jsx: true, + }, + }, + }, + settings: { + react: { + version: "detect", + }, + }, + rules: { + "react/react-in-jsx-scope": "off", + "react/prop-types": "off", + "@typescript-eslint/ban-ts-comment": "off", + "@typescript-eslint/no-unused-vars": [ + "error", + { argsIgnorePattern: "^_", varsIgnorePattern: "^_" }, + ], + }, + }, + { + ignores: ["dist/", "node_modules/", "storybook-static/"], + }, +); diff --git a/package.json b/package.json index 19f7bc89..9a0e32f1 100644 --- a/package.json +++ b/package.json @@ -21,69 +21,76 @@ "react" ], "scripts": { - "dev": "next dev", "build": "rollup -c --bundleConfigAsCjs", - "start": "next start", - "lint": "next lint", - "storybook": "storybook dev -p 6006", + "lint": "eslint \"src/**/*.{ts,tsx}\"", + "compile": "tsc --noEmit", + "lint:fix": "eslint \"src/**/*.{ts,tsx}\" --fix", + "format": "prettier --write \"src/**/*.{js,jsx,ts,tsx,css}\"", + "storybook": "storybook dev", "build-storybook": "storybook build", - "test": "jest", + "test": "jest --testPathIgnorePatterns=\"computePosition\\.test\\.ts\" --passWithNoTests", "yalc:publish": "npm run build && yalc publish", "yalc:push": "npm run build && yalc push", - "prettier": "prettier --write \"src/**/*.{js,jsx,ts,tsx,css}\"", - "ci": "npm-run-all prettier lint test build", + "ci": "npm-run-all lint:fix lint test build", "deploy-storybook": "gh-pages -d storybook-static" }, "jest": { - "transform": { - ".(ts|tsx)": "ts-jest" - }, + "preset": "ts-jest", + "testEnvironment": "jsdom", + "setupFilesAfterEnv": [ + "@testing-library/jest-dom" + ], "testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$", "moduleFileExtensions": [ "ts", "tsx", "js" - ] + ], + "moduleNameMapper": { + "\\.(css|less|scss)$": "identity-obj-proxy" + } }, "dependencies": { - "@dolthub/react-components": "^0.2.7", - "@dolthub/react-hooks": "^0.1.7", - "@dolthub/web-utils": "^0.1.5", - "@rollup/plugin-typescript": "12.3.0", - "classnames": "^2.3.2", "react": ">=18.0.0", - "react-copy-to-clipboard": "^5.1.0", "react-dom": ">=18.0.0", - "react-icons": "^5.3.0", + "react-icons": "^5.6.0", "react-infinite-scroller": "^1.2.6", - "react-tooltip": "^5.26.3", + "react-tooltip": "^5.30.0", "reactjs-popup": "^2.0.6" }, "devDependencies": { - "@rollup/plugin-commonjs": "^29.0.0", - "@rollup/plugin-node-resolve": "^16.0.0", + "@eslint/js": "^10.0.1", + "@rollup/plugin-commonjs": "^29.0.2", + "@rollup/plugin-node-resolve": "^16.0.3", "@rollup/plugin-terser": "^0.4.4", - "@storybook/nextjs": "^8.0.0", - "@storybook/react": "^8.0.0", - "@types/react": "^18.2.57", + "@rollup/plugin-typescript": "12.3.0", + "@storybook/addon-webpack5-compiler-swc": "^4.0.3", + "@storybook/react": "^10", + "@storybook/react-webpack5": "^10", + "@testing-library/dom": "^10.4.1", + "@testing-library/jest-dom": "^6.9.1", + "@testing-library/react": "^16.3.2", + "@types/jest": "^30.0.0", + "@types/react": "^19.2.14", "@types/react-infinite-scroller": "^1.2.5", - "@typescript-eslint/eslint-plugin": "8.32.1", - "@typescript-eslint/parser": "8.53.0", - "eslint-config-airbnb-base": "latest", - "eslint-config-airbnb-typescript": "latest", - "eslint-config-prettier": "^10.0.1", - "gh-pages": "^6.1.1", - "jest": "^30.2.0", - "next": "^15.1.7", + "eslint": "^10", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-react": "^7.37.5", + "gh-pages": "^6.3.0", + "identity-obj-proxy": "^3.0.0", + "jest": "^30.3.0", + "jest-environment-jsdom": "^30.3.0", "npm-run-all": "^4.1.5", - "prettier": "^3.2.5", - "rollup": "^4.12.0", - "rollup-plugin-dts": "^6.1.0", + "postcss": "^8.5.8", + "prettier": "^3.8.1", + "rollup": "^4.60.0", + "rollup-plugin-dts": "^6.4.1", "rollup-plugin-peer-deps-external": "^2.2.4", "rollup-plugin-postcss": "^4.0.2", - "storybook": "8.6.15", - "ts-jest": "^29.1.2", + "storybook": "^10", + "ts-jest": "^29.4.6", "typescript": "^5.4.2", + "typescript-eslint": "^8.57.2", "yalc": "^1.0.0-pre.53" }, "peerDependencies": { @@ -93,8 +100,5 @@ "main": "dist/cjs/index.js", "module": "dist/esm/index.js", "types": "dist/index.d.ts", - "resolutions": { - "cross-spawn": "^7.0.5", - "wrap-ansi/string-width": "^4.2.0" - } + "packageManager": "yarn@4.13.0" } diff --git a/rollup.config.js b/rollup.config.js index fdd20ec7..610c1e3c 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -5,8 +5,7 @@ import dts from "rollup-plugin-dts"; import terser from "@rollup/plugin-terser"; import postcss from "rollup-plugin-postcss"; import peerDepsExternal from "rollup-plugin-peer-deps-external"; - -const packageJson = require("./package.json"); +import packageJson from "./package.json" with { type: "json" }; export default [ { @@ -23,10 +22,28 @@ export default [ tsconfig: "./tsconfig.json", noEmit: false, declaration: false, - exclude: ["**/__tests__", "**/*.test.ts"], + exclude: [ + "**/__tests__", + "**/*.test.ts", + "**/*.stories.ts", + "src/stories/**", + ], + sourceMap: false, + inlineSources: false, + }), + terser({ + compress: { + drop_console: true, + }, + mangle: true, + format: { + comments: false, + }, + }), + postcss({ + minimize: true, + extract: false, }), - terser(), - postcss(), ], external: ["react", "react-dom", "styled-components"], }, diff --git a/src/components/BranchLabel/index.tsx b/src/components/BranchLabel/index.tsx index a08bd170..2e304fbc 100644 --- a/src/components/BranchLabel/index.tsx +++ b/src/components/BranchLabel/index.tsx @@ -2,7 +2,6 @@ import React from "react"; import ReactPopup from "reactjs-popup"; import css from "./index.module.css"; import { Branch } from "../../types"; -import cx from "classnames"; type ItemProps = { branchName: string; @@ -21,7 +20,7 @@ function Item({ branchName, branchColor, branchLink, className }: ItemProps) { return (