import js from '@eslint/js' import globals from 'globals' import reactHooks from 'eslint-plugin-react-hooks' import reactRefresh from 'eslint-plugin-react-refresh' import tseslint from 'typescript-eslint' import { defineConfig, globalIgnores } from 'eslint/config' export default defineConfig([ globalIgnores(['dist', 'coverage', 'node_modules']), // ── Production source ──────────────────────────────────────────────────── // Using `recommended` (not `recommendedTypeChecked`) — the codebase uses // `any` types broadly. Type-safety rules are aspirational; enable them // incrementally as types improve. { files: ['src/**/*.{ts,tsx}'], ignores: ['src/test/**'], extends: [ js.configs.recommended, ...tseslint.configs.recommended, reactHooks.configs.flat.recommended, reactRefresh.configs.vite, ], languageOptions: { ecmaVersion: 2020, globals: globals.browser, }, rules: { '@typescript-eslint/no-unused-vars': [ 'error', { argsIgnorePattern: '^_', varsIgnorePattern: '^_', caughtErrorsIgnorePattern: '^_' }, ], '@typescript-eslint/no-explicit-any': 'warn', '@typescript-eslint/explicit-function-return-type': 'off', '@typescript-eslint/explicit-module-boundary-types': 'off', 'react-hooks/exhaustive-deps': 'warn', // React Compiler rules (react-hooks v5+) — codebase not yet Compiler-compatible 'react-hooks/set-state-in-effect': 'off', 'react-hooks/refs': 'off', 'react-hooks/preserve-manual-memoization': 'off', 'react-refresh/only-export-components': ['warn', { allowConstantExport: true }], 'no-console': ['warn', { allow: ['warn', 'error'] }], 'no-debugger': 'warn', 'no-empty': ['error', { allowEmptyCatch: true }], // Pure-Tailwind policy (adopted 2026-04-18) — warn on inline `style={{...}}` // with object-literal values. Dynamic values (template strings, identifiers, // conditionals) can be suppressed with `// eslint-disable-next-line no-restricted-syntax`. // See Sublarr/CLAUDE.md > Frontend Styling Policy for migration guidance. // Tool: `python tools/migrate_inline_styles.py `. 'no-restricted-syntax': [ 'warn', { selector: 'JSXAttribute[name.name="style"] > JSXExpressionContainer > ObjectExpression', message: 'Inline `style={{...}}` — prefer Tailwind utility classes. Allowed only for runtime-computed values (dynamic widths, transforms, data-dependent colors).', }, ], }, }, // ── Tests, E2E, config files ── syntax-only, no type-inference rules ────── { files: [ 'src/test/**/*.{ts,tsx}', 'e2e/**/*.ts', 'vite.config.ts', 'vitest.config.ts', 'playwright.config.ts', ], extends: [ js.configs.recommended, ...tseslint.configs.recommended, ], languageOptions: { ecmaVersion: 2020, globals: { ...globals.browser, ...globals.node }, }, rules: { '@typescript-eslint/no-unused-vars': ['error', { args: 'none', varsIgnorePattern: '^_' }], '@typescript-eslint/no-explicit-any': 'warn', 'no-console': 'off', }, }, ])