penpot/frontend/packages/ui/eslint.config.mjs
Andrey Antukh 42ea5def4f Bootstrap @penpot/ui TypeScript component library with DS migrations
- Configure @penpot/ui package with full tooling: ESLint 9, Stylelint,
  Prettier, Vitest, Storybook (react-vite), vite-plugin-dts, React Compiler
- Add AGENTS.md with architecture overview, conventions, and migration table
- Fix Storybook react-docgen TypeScript parse error by removing empty .babelrc
  that disabled Babel's built-in typescript plugin
- Fix vite.config.mts for @vitejs/plugin-react v6 (reactCompilerPreset())
- Fix tsconfig.storybook.json (remove emitDecoratorMetadata without decorator)
- Add shared SCSS foundations: _borders, _sizes, _utils, typography
- Migrate Text, Heading (foundations/typography) with stories and tests
- Migrate Icon (foundations/assets) with full iconIds catalogue and stories
- Migrate Cta (product) with stories and tests
- Migrate Button (buttons) with polymorphic anchor/button rendering,
  4 variants, optional icon, and onRef callback; add _buttons.scss partial
- All checks passing: lint, check-fmt, typecheck, test (41 tests)
2026-04-08 15:46:13 +02:00

101 lines
2.7 KiB
JavaScript

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
//
// Copyright (c) KALEIDOS INC
import tseslint from "typescript-eslint";
import pluginReact from "eslint-plugin-react";
import pluginReactHooks from "eslint-plugin-react-hooks";
import pluginJsxA11y from "eslint-plugin-jsx-a11y";
import pluginImport from "eslint-plugin-import";
import globals from "globals";
/** @type {import("eslint").Linter.Config[]} */
export default [
{
ignores: ["dist/**", "node_modules/**", ".storybook/**"],
},
// TypeScript + TSX source files
...tseslint.config({
files: ["src/**/*.{ts,tsx}"],
extends: [
tseslint.configs.recommended,
pluginReact.configs.flat.recommended,
],
languageOptions: {
ecmaVersion: "latest",
sourceType: "module",
globals: {
...globals.browser,
...globals.es2022,
},
parserOptions: {
ecmaFeatures: { jsx: true },
},
},
plugins: {
"react-hooks": pluginReactHooks,
"jsx-a11y": pluginJsxA11y,
import: pluginImport,
},
settings: {
react: { version: "detect" },
},
rules: {
// React
"react/react-in-jsx-scope": "off", // Not needed with React 17+ JSX transform
"react/prop-types": "off", // TypeScript handles prop validation
"react/display-name": "off", // memo-wrapped inner functions don't need display names
// React Hooks
...pluginReactHooks.configs["recommended-latest"].rules,
// Imports
"import/no-duplicates": "error",
"import/no-unresolved": "off", // TypeScript handles resolution
"import/first": "error",
// TypeScript — relax rules that conflict with common patterns
"@typescript-eslint/no-unused-vars": [
"error",
{ argsIgnorePattern: "^_", varsIgnorePattern: "^_" },
],
// General
"no-console": ["warn", { allow: ["warn", "error"] }],
"prefer-const": "error",
"no-var": "error",
},
}),
// Vitest spec files — add test globals
...tseslint.config({
files: ["src/**/*.spec.{ts,tsx}"],
languageOptions: {
globals: {
...globals.browser,
...globals.es2022,
describe: "readonly",
it: "readonly",
expect: "readonly",
beforeEach: "readonly",
afterEach: "readonly",
beforeAll: "readonly",
afterAll: "readonly",
vi: "readonly",
},
},
}),
// Storybook story files — relax some rules
...tseslint.config({
files: ["src/**/*.stories.{ts,tsx}"],
rules: {
"import/first": "off",
"@typescript-eslint/no-unused-vars": "off",
},
}),
];