From b98653792552286d0777792c1ff2bdb6702105cd Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Feb 2026 15:22:45 +0000 Subject: [PATCH 1/5] Bump eslint-plugin-sonarjs from 3.0.7 to 4.0.0 (#3972) * Bump eslint-plugin-sonarjs from 3.0.7 to 4.0.0 Bumps [eslint-plugin-sonarjs](https://github.com/SonarSource/SonarJS) from 3.0.7 to 4.0.0. - [Release notes](https://github.com/SonarSource/SonarJS/releases) - [Commits](https://github.com/SonarSource/SonarJS/commits) --- updated-dependencies: - dependency-name: eslint-plugin-sonarjs dependency-version: 4.0.0 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * update sonar rules --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Nicolas Stepien --- eslint.config.js | 40 ++++++++++++++++++++-------------------- package.json | 2 +- 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index eb89182be5..c6824df61e 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -412,6 +412,24 @@ export default defineConfig([ // SonarJS rules // https://github.com/SonarSource/SonarJS/blob/master/packages/jsts/src/rules/README.md#rules + /* +// copy all the rules from the rules table for easy pasting +copy( + Iterator.from( + document + // selecto rules table + .querySelector('.markdown-heading:has(> a[href="#rules"]) ~ markdown-accessiblity-table') + // select all rows with a rule + .querySelectorAll('tr:has(a)') + ) + // filter out deprecated rules + .filter((row) => row.lastElementChild.textContent === '') + // map row to rule declaration + .map((row) => `'sonarjs/${row.firstElementChild.textContent}': 1,`) + .toArray() + .join('\n') +); + */ 'sonarjs/anchor-precedence': 1, 'sonarjs/argument-type': 1, 'sonarjs/arguments-order': 1, @@ -434,7 +452,6 @@ export default defineConfig([ 'sonarjs/aws-s3-bucket-granted-access': 0, 'sonarjs/aws-s3-bucket-insecure-http': 0, 'sonarjs/aws-s3-bucket-public-access': 0, - 'sonarjs/aws-s3-bucket-server-encryption': 0, 'sonarjs/aws-s3-bucket-versioning': 0, 'sonarjs/aws-sagemaker-unencrypted-notebook': 0, 'sonarjs/aws-sns-unencrypted-topics': 0, @@ -443,40 +460,33 @@ export default defineConfig([ 'sonarjs/block-scoped-var': 1, 'sonarjs/bool-param-default': 0, 'sonarjs/call-argument-line': 1, - 'sonarjs/certificate-transparency': 1, 'sonarjs/chai-determinate-assertion': 1, 'sonarjs/class-name': 1, 'sonarjs/class-prototype': 1, - 'sonarjs/code-eval': 1, 'sonarjs/cognitive-complexity': 0, 'sonarjs/comma-or-logical-or-case': 1, 'sonarjs/comment-regex': 1, 'sonarjs/concise-regex': 1, - 'sonarjs/conditional-indentation': 1, 'sonarjs/confidential-information-logging': 1, 'sonarjs/constructor-for-side-effects': 1, 'sonarjs/content-length': 1, 'sonarjs/content-security-policy': 1, 'sonarjs/cookie-no-httponly': 1, - 'sonarjs/cookies': 1, 'sonarjs/cors': 1, 'sonarjs/csrf': 1, 'sonarjs/cyclomatic-complexity': 0, 'sonarjs/declarations-in-global-scope': 0, 'sonarjs/deprecation': 0, 'sonarjs/destructuring-assignment-syntax': 1, - 'sonarjs/different-types-comparison': 0, + 'sonarjs/different-types-comparison': 1, 'sonarjs/disabled-auto-escaping': 1, 'sonarjs/disabled-resource-integrity': 1, 'sonarjs/disabled-timeout': 1, - 'sonarjs/dns-prefetching': 1, 'sonarjs/duplicates-in-character-class': 1, 'sonarjs/dynamically-constructed-templates': 1, 'sonarjs/elseif-without-else': 0, 'sonarjs/empty-string-repetition': 1, - 'sonarjs/encryption': 1, 'sonarjs/encryption-secure-mode': 1, - 'sonarjs/enforce-trailing-comma': 0, 'sonarjs/existing-groups': 1, 'sonarjs/expression-complexity': 0, 'sonarjs/file-header': 0, @@ -586,7 +596,6 @@ export default defineConfig([ 'sonarjs/no-redundant-boolean': 1, 'sonarjs/no-redundant-jump': 1, 'sonarjs/no-redundant-optional': 1, - 'sonarjs/no-redundant-parentheses': 1, 'sonarjs/no-reference-error': 0, 'sonarjs/no-referrer-policy': 1, 'sonarjs/no-regex-spaces': 1, @@ -595,10 +604,10 @@ export default defineConfig([ 'sonarjs/no-same-argument-assert': 1, 'sonarjs/no-same-line-conditional': 1, 'sonarjs/no-selector-parameter': 0, + 'sonarjs/no-session-cookies-on-static-assets': 1, 'sonarjs/no-skipped-tests': 1, 'sonarjs/no-small-switch': 1, 'sonarjs/no-sonar-comments': 1, - 'sonarjs/no-tab': 1, 'sonarjs/no-table-as-layout': 1, 'sonarjs/no-try-promise': 1, 'sonarjs/no-undefined-argument': 1, @@ -616,7 +625,6 @@ export default defineConfig([ 'sonarjs/no-useless-intersection': 1, 'sonarjs/no-useless-react-setstate': 1, 'sonarjs/no-variable-usage-before-declaration': 1, - 'sonarjs/no-vue-bypass-sanitization': 1, 'sonarjs/no-weak-cipher': 1, 'sonarjs/no-weak-keys': 1, 'sonarjs/no-wildcard-import': 0, @@ -636,7 +644,6 @@ export default defineConfig([ 'sonarjs/prefer-single-boolean-return': 1, 'sonarjs/prefer-type-guard': 1, 'sonarjs/prefer-while': 1, - 'sonarjs/process-argv': 1, 'sonarjs/production-debug': 1, 'sonarjs/pseudo-random': 0, 'sonarjs/public-static-readonly': 1, @@ -644,21 +651,17 @@ export default defineConfig([ 'sonarjs/reduce-initial-value': 1, 'sonarjs/redundant-type-aliases': 0, 'sonarjs/regex-complexity': 1, - 'sonarjs/regular-expr': 1, 'sonarjs/review-blockchain-mnemonic': 1, 'sonarjs/session-regeneration': 1, 'sonarjs/shorthand-property-grouping': 0, 'sonarjs/single-char-in-character-classes': 1, 'sonarjs/single-character-alternation': 1, 'sonarjs/slow-regex': 1, - 'sonarjs/sockets': 1, 'sonarjs/sql-queries': 1, 'sonarjs/stable-tests': 1, - 'sonarjs/standard-input': 1, 'sonarjs/stateful-regex': 1, 'sonarjs/strict-transport-security': 1, 'sonarjs/strings-comparison': 1, - 'sonarjs/super-invocation': 1, 'sonarjs/table-header': 1, 'sonarjs/table-header-reference': 1, 'sonarjs/test-check-exception': 1, @@ -672,15 +675,12 @@ export default defineConfig([ 'sonarjs/updated-const-var': 1, 'sonarjs/updated-loop-counter': 0, 'sonarjs/use-type-alias': 1, - 'sonarjs/useless-string-operation': 1, 'sonarjs/values-not-convertible-to-numbers': 1, 'sonarjs/variable-name': 1, 'sonarjs/void-use': 1, 'sonarjs/weak-ssl': 1, - 'sonarjs/web-sql-database': 1, 'sonarjs/x-powered-by': 1, 'sonarjs/xml-parser-xxe': 1, - 'sonarjs/xpath': 1, // @typescript-eslint/eslint-plugin rules // https://typescript-eslint.io/rules/#supported-rules diff --git a/package.json b/package.json index 339fd4da9b..0b7a99eb33 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "eslint-plugin-jest-dom": "^5.5.0", "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-hooks": "^7.0.1", - "eslint-plugin-sonarjs": "^3.0.6", + "eslint-plugin-sonarjs": "^4.0.0", "eslint-plugin-testing-library": "^7.13.5", "jspdf": "^4.0.0", "jspdf-autotable": "^5.0.2", From 440f35d617c8e5a7ea227dd2e5926f4f9a81a004 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien <567105+nstepien@users.noreply.github.com> Date: Mon, 23 Feb 2026 16:13:42 +0000 Subject: [PATCH 2/5] Remove biome (#3974) --- .github/workflows/ci.yml | 3 - .github/workflows/publish.yml | 3 - .vscode/extensions.json | 2 +- AGENTS.md | 5 +- biome.json | 395 ---------------------------------- package.json | 3 - 6 files changed, 3 insertions(+), 408 deletions(-) delete mode 100644 biome.json diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 13458f53b1..5e30dbf2fe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,9 +19,6 @@ jobs: - name: Install dependencies run: npm i - - name: Biome - run: node --run biome:ci - - name: Typecheck run: node --run typecheck diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index fe4d4c1f53..5861d171bd 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -30,9 +30,6 @@ jobs: - name: Install dependencies run: npm i - - name: Biome - run: node --run biome:ci - - name: Typecheck run: node --run typecheck diff --git a/.vscode/extensions.json b/.vscode/extensions.json index d1bb4a7e2b..0d4efacdc9 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -1,3 +1,3 @@ { - "recommendations": ["dbaeumer.vscode-eslint", "oxc.oxc-vscode", "biomejs.biome"] + "recommendations": ["dbaeumer.vscode-eslint", "oxc.oxc-vscode"] } diff --git a/AGENTS.md b/AGENTS.md index 71f2698b28..e6775ffa51 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -6,7 +6,6 @@ npm install # setup (requires Node.js ≥ 22 for `node --run`) node --run build # library → lib/ node --run typecheck # tsc --build -node --run check # biome check (warnings are errors) node --run eslint # eslint --max-warnings 0 node --run eslint:fix # eslint --fix node --run format # oxfmt @@ -48,7 +47,7 @@ website/ # demo site (Vite + TanStack Router) - **Dual classnames** — components apply both a semantic class (`rdg-cell`) and a generated hash. Preserve both. - **Light/dark mode** — handled via CSS `light-dark()` + `color-scheme`, not JS. - **Accessibility first** — ARIA attributes (e.g. `aria-colindex`, `aria-rowindex`, `aria-selected`, roles) are required. Tests query by role. -- **Formatting** — oxfmt (not Prettier). **Linting** — Biome + ESLint (both must pass with zero warnings). +- **Formatting** — oxfmt (not Prettier). **Linting** — ESLint (must pass with zero warnings). - **Build** — Rolldown bundles library to `lib/`; `ecij` plugin prefixes classes with `rdg-{version}-` (dots→dashes) to avoid cross-version conflicts. ## Testing @@ -60,4 +59,4 @@ website/ # demo site (Vite + TanStack Router) ## Validation -Run before submitting changes: `node --run typecheck`, `node --run check`, `node --run eslint`, `node --run format`, `node --run test`. +Run before submitting changes: `node --run typecheck`, `node --run eslint`, `node --run format`, `node --run test`. diff --git a/biome.json b/biome.json deleted file mode 100644 index 681707c749..0000000000 --- a/biome.json +++ /dev/null @@ -1,395 +0,0 @@ -{ - "$schema": "./node_modules/@biomejs/biome/configuration_schema.json", - "assist": { "actions": { "source": { "organizeImports": "off" } } }, - "files": { - "includes": [ - "**", - "!.cache/**/*", - "!.cache/**/*", - "!.nitro/**/*", - "!.output/**/*", - "!.tanstack/**/*", - "!coverage/**/*", - "!dist/**/*", - "!lib/**/*", - "!node_modules/**/*", - "!website/routeTree.gen.ts" - ] - }, - "formatter": { - "enabled": false - }, - "json": { - "parser": { - "allowComments": true, - "allowTrailingCommas": true - } - }, - "linter": { - "domains": { - "project": "recommended" - }, - "rules": { - "a11y": { - "noAccessKey": "warn", - "noAriaHiddenOnFocusable": "warn", - "noAriaUnsupportedElements": "warn", - "noAutofocus": "off", - "noDistractingElements": "warn", - "noHeaderScope": "warn", - "noInteractiveElementToNoninteractiveRole": "warn", - "noLabelWithoutControl": "off", - "noNoninteractiveElementToInteractiveRole": "warn", - "noNoninteractiveTabindex": "warn", - "noPositiveTabindex": "warn", - "noRedundantAlt": "warn", - "noRedundantRoles": "warn", - "noStaticElementInteractions": "off", - "noSvgWithoutTitle": "off", - "useAltText": "warn", - "useAnchorContent": "warn", - "useAriaActivedescendantWithTabindex": "warn", - "useAriaPropsForRole": "warn", - "useAriaPropsSupportedByRole": "off", - "useButtonType": "warn", - "useFocusableInteractive": "off", - "useGenericFontNames": "warn", - "useHeadingContent": "warn", - "useHtmlLang": "warn", - "useIframeTitle": "warn", - "useKeyWithClickEvents": "off", - "useKeyWithMouseEvents": "warn", - "useMediaCaption": "off", - "useSemanticElements": "off", - "useValidAnchor": "warn", - "useValidAriaProps": "warn", - "useValidAriaRole": "warn", - "useValidAriaValues": "warn", - "useValidAutocomplete": "warn", - "useValidLang": "warn" - }, - "complexity": { - "noAdjacentSpacesInRegex": "warn", - "noArguments": "warn", - "noBannedTypes": "warn", - "noCommaOperator": "warn", - "noEmptyTypeParameters": "warn", - "noExcessiveCognitiveComplexity": "off", - "noExcessiveLinesPerFunction": "off", - "noExcessiveNestedTestSuites": "off", - "noExtraBooleanCast": "warn", - "noFlatMapIdentity": "warn", - "noForEach": "warn", - "noImplicitCoercions": "warn", - "noStaticOnlyClass": "warn", - "noThisInStatic": "warn", - "noUselessCatch": "warn", - "noUselessConstructor": "warn", - "noUselessContinue": "warn", - "noUselessEmptyExport": "warn", - "noUselessEscapeInRegex": "warn", - "noUselessFragments": "warn", - "noUselessLabel": "warn", - "noUselessLoneBlockStatements": "warn", - "noUselessRename": "warn", - "noUselessStringConcat": "warn", - "noUselessStringRaw": "warn", - "noUselessSwitchCase": "warn", - "noUselessTernary": "warn", - "noUselessThisAlias": "warn", - "noUselessTypeConstraint": "warn", - "noUselessUndefinedInitialization": "warn", - "noVoid": "warn", - "useArrowFunction": "warn", - "useDateNow": "warn", - "useFlatMap": "warn", - "useIndexOf": "warn", - "useLiteralKeys": "warn", - "useNumericLiterals": "warn", - "useOptionalChain": "warn", - "useRegexLiterals": "warn", - "useSimpleNumberKeys": "warn", - "useSimplifiedLogicExpression": "off", - "useWhile": "warn" - }, - "correctness": { - "noChildrenProp": "off", - "noConstAssign": "warn", - "noConstantCondition": "warn", - "noConstantMathMinMaxClamp": "warn", - "noConstructorReturn": "warn", - "noEmptyCharacterClassInRegex": "warn", - "noEmptyPattern": "warn", - "noGlobalDirnameFilename": "warn", - "noGlobalObjectCalls": "warn", - "noInnerDeclarations": "warn", - "noInvalidBuiltinInstantiation": "warn", - "noInvalidConstructorSuper": "warn", - "noInvalidDirectionInLinearGradient": "warn", - "noInvalidGridAreas": "warn", - "noInvalidPositionAtImportRule": "warn", - "noInvalidUseBeforeDeclaration": "warn", - "noNestedComponentDefinitions": "warn", - "noNodejsModules": "warn", - "noNonoctalDecimalEscape": "warn", - "noPrecisionLoss": "warn", - "noPrivateImports": "warn", - "noProcessGlobal": "off", - "noReactPropAssignments": "warn", - "noRenderReturnValue": "warn", - "noRestrictedElements": "off", - "noSelfAssign": "warn", - "noSetterReturn": "warn", - "noStringCaseMismatch": "warn", - "noSwitchDeclarations": "warn", - "noUndeclaredDependencies": "warn", - "noUndeclaredVariables": "off", - "noUnknownFunction": "warn", - "noUnknownMediaFeatureName": "warn", - "noUnknownProperty": "warn", - "noUnknownUnit": "warn", - "noUnmatchableAnbSelector": "warn", - "noUnreachable": "warn", - "noUnreachableSuper": "warn", - "noUnsafeFinally": "warn", - "noUnsafeOptionalChaining": "warn", - "noUnusedFunctionParameters": { - "level": "warn", - "options": { - "ignoreRestSiblings": true - } - }, - "noUnusedImports": "warn", - "noUnusedLabels": "warn", - "noUnusedPrivateClassMembers": "warn", - "noUnusedVariables": { - "level": "warn", - "options": { - "ignoreRestSiblings": true - } - }, - "noVoidElementsWithChildren": "warn", - "noVoidTypeReturn": "warn", - "useExhaustiveDependencies": "off", - "useHookAtTopLevel": "warn", - "useImportExtensions": "off", - "useIsNan": "warn", - "useJsonImportAttributes": "warn", - "useJsxKeyInIterable": "off", - "useParseIntRadix": "warn", - "useSingleJsDocAsterisk": "warn", - "useUniqueElementIds": "off", - "useValidForDirection": "warn", - "useValidTypeof": "warn", - "useYield": "warn" - }, - "performance": { - "noAccumulatingSpread": "warn", - "noAwaitInLoops": "off", - "noBarrelFile": "off", - "noDelete": "warn", - "noDynamicNamespaceImportAccess": "warn", - "noNamespaceImport": "warn", - "noReExportAll": "off", - "useTopLevelRegex": "warn" - }, - "recommended": false, - "security": { - "noBlankTarget": "warn", - "noDangerouslySetInnerHtml": "warn", - "noDangerouslySetInnerHtmlWithChildren": "warn", - "noGlobalEval": "warn" - }, - "style": { - "noDefaultExport": "off", - "noDoneCallback": "warn", - "noEnum": "off", - "noExportedImports": "off", - "noImplicitBoolean": "off", - "noInferrableTypes": "warn", - "noNamespace": "warn", - "noNegationElse": "warn", - "noNonNullAssertion": "off", - "noParameterAssign": "off", - "noParameterProperties": "warn", - "noRestrictedGlobals": "warn", - "noRestrictedImports": { - "level": "warn", - "options": { - "paths": { - "react": { - "importNames": ["default"], - "message": "Use named imports instead." - }, - "react-dom": { - "importNames": ["default"], - "message": "Use named imports instead." - } - } - } - }, - "noShoutyConstants": "warn", - "noSubstr": "off", - "noUnusedTemplateLiteral": "warn", - "noUselessElse": "warn", - "noYodaExpression": "warn", - "useArrayLiterals": "warn", - "useAsConstAssertion": "warn", - "useAtIndex": "off", - "useBlockStatements": "off", - "useCollapsedElseIf": "warn", - "useCollapsedIf": "warn", - "useComponentExportOnlyModules": "off", - "useConsistentArrayType": "warn", - "useConsistentBuiltinInstantiation": "warn", - "useConsistentObjectDefinitions": "warn", - "useConst": "warn", - "useDefaultParameterLast": "off", - "useDefaultSwitchClause": "warn", - "useEnumInitializers": "warn", - "useExplicitLengthCheck": "off", - "useExponentiationOperator": "warn", - "useExportType": "warn", - "useFilenamingConvention": "off", - "useForOf": "off", - "useFragmentSyntax": "warn", - "useImportType": "warn", - "useLiteralEnumMembers": "warn", - "useNamingConvention": "off", - "useNodeAssertStrict": "warn", - "useNodejsImportProtocol": "warn", - "useNumberNamespace": "warn", - "useNumericSeparators": "off", - "useObjectSpread": "warn", - "useSelfClosingElements": "warn", - "useShorthandAssign": "warn", - "useShorthandFunctionType": "warn", - "useSingleVarDeclarator": "warn", - "useSymbolDescription": "warn", - "useTemplate": "warn", - "useThrowNewError": "warn", - "useThrowOnlyError": "warn", - "useTrimStartEnd": "warn" - }, - "suspicious": { - "noApproximativeNumericConstant": "warn", - "noArrayIndexKey": "off", - "noAssignInExpressions": "warn", - "noAsyncPromiseExecutor": "warn", - "noCatchAssign": "warn", - "noClassAssign": "warn", - "noCommentText": "warn", - "noCompareNegZero": "warn", - "noConfusingLabels": "warn", - "noConfusingVoidType": "warn", - "noConsole": "warn", - "noConstantBinaryExpressions": "warn", - "noConstEnum": "warn", - "noControlCharactersInRegex": "warn", - "noDebugger": "warn", - "noDoubleEquals": "warn", - "noDuplicateAtImportRules": "warn", - "noDuplicateCase": "warn", - "noDuplicateClassMembers": "warn", - "noDuplicateElseIf": "warn", - "noDuplicateFontNames": "warn", - "noDuplicateJsxProps": "warn", - "noDuplicateObjectKeys": "warn", - "noDuplicateParameters": "warn", - "noDuplicateSelectorsKeyframeBlock": "warn", - "noDuplicateTestHooks": "warn", - "noEmptyBlock": "warn", - "noEmptyBlockStatements": "off", - "noEmptyInterface": "warn", - "noEvolvingTypes": "off", - "noExplicitAny": "off", - "noExportsInTest": "warn", - "noExtraNonNullAssertion": "warn", - "noFallthroughSwitchClause": "warn", - "noFocusedTests": "warn", - "noFunctionAssign": "warn", - "noGlobalAssign": "warn", - "noGlobalIsFinite": "warn", - "noGlobalIsNan": "warn", - "noImplicitAnyLet": "off", - "noImportAssign": "warn", - "noImportantInKeyframe": "warn", - "noLabelVar": "warn", - "noMisleadingCharacterClass": "warn", - "noMisleadingInstantiator": "warn", - "noMisplacedAssertion": "off", - "noMisrefactoredShorthandAssign": "warn", - "noOctalEscape": "warn", - "noPrototypeBuiltins": "warn", - "noReactSpecificProps": "off", - "noRedeclare": "warn", - "noRedundantUseStrict": "warn", - "noSelfCompare": "warn", - "noShadowRestrictedNames": "warn", - "noShorthandPropertyOverrides": "warn", - "noSkippedTests": "warn", - "noSparseArray": "warn", - "noSuspiciousSemicolonInJsx": "warn", - "noTemplateCurlyInString": "warn", - "noThenProperty": "warn", - "noTsIgnore": "warn", - "noUnsafeDeclarationMerging": "warn", - "noUnsafeNegation": "warn", - "noUselessEscapeInString": "warn", - "noUselessRegexBackrefs": "warn", - "noVar": "warn", - "noWith": "warn", - "useAwait": "warn", - "useDefaultSwitchClauseLast": "warn", - "useErrorMessage": "warn", - "useGetterReturn": "warn", - "useIsArray": "warn", - "useNamespaceKeyword": "warn", - "useNumberToFixedDigitsArgument": "warn" - } - } - }, - "overrides": [ - { - "includes": ["**/*.test.*"], - "linter": { - "rules": { - "performance": { - "useTopLevelRegex": "off" - } - } - } - }, - { - "includes": ["test/failOnConsole.ts"], - "linter": { - "rules": { - "suspicious": { - "noConsole": "off" - } - } - } - }, - { - "includes": ["**/*.js", "**/rolldown.config.ts"], - "linter": { - "rules": { - "correctness": { - "noNodejsModules": "off" - }, - "suspicious": { - "noConsole": "off" - } - } - } - }, - { - "assist": { - "actions": { - "source": { "useSortedKeys": "on" } - } - }, - "includes": ["./biome.json"] - } - ] -} diff --git a/package.json b/package.json index 0b7a99eb33..3763bcf1a1 100644 --- a/package.json +++ b/package.json @@ -42,14 +42,11 @@ "visual:update": "vitest run --project visual --update", "format": "oxfmt", "format:check": "oxfmt --check", - "check": "biome check --error-on-warnings", - "biome:ci": "biome ci --error-on-warnings", "eslint": "eslint --max-warnings 0 --cache --cache-location .cache/eslint --cache-strategy content", "eslint:fix": "node --run eslint -- --fix", "typecheck": "tsc --build" }, "devDependencies": { - "@biomejs/biome": "2.4.0", "@eslint-react/eslint-plugin": "^2.3.12", "@eslint/markdown": "^7.5.1", "@faker-js/faker": "^10.0.0", From 52c1762c8ba76090594f48740a8f29cb1a48d851 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien <567105+nstepien@users.noreply.github.com> Date: Mon, 23 Feb 2026 16:17:52 +0000 Subject: [PATCH 3/5] Remove eslint-plugin-react (#3975) --- eslint.config.js | 125 ----------------------------------------------- package.json | 1 - 2 files changed, 126 deletions(-) diff --git a/eslint.config.js b/eslint.config.js index c6824df61e..06ef93e052 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -4,7 +4,6 @@ import typescriptEslint from '@typescript-eslint/eslint-plugin'; import tsParser from '@typescript-eslint/parser'; import vitest from '@vitest/eslint-plugin'; import jestDom from 'eslint-plugin-jest-dom'; -import react from 'eslint-plugin-react'; import reactHooks from 'eslint-plugin-react-hooks'; import sonarjs from 'eslint-plugin-sonarjs'; import testingLibrary from 'eslint-plugin-testing-library'; @@ -24,7 +23,6 @@ export default defineConfig([ files: ['**/*.{js,ts,tsx}'], plugins: { - react, // @ts-expect-error 'react-hooks': reactHooks, 'react-x': reactX, @@ -44,12 +42,6 @@ export default defineConfig([ } }, - settings: { - react: { - version: 'detect' - } - }, - rules: { // Possible Problems // https://eslint.org/docs/latest/rules/#possible-problems @@ -266,123 +258,6 @@ export default defineConfig([ // https://eslint.org/docs/latest/rules/#layout--formatting 'unicode-bom': 1, - // React rules - // https://github.com/jsx-eslint/eslint-plugin-react#list-of-supported-rules - 'react/boolean-prop-naming': 0, - 'react/button-has-type': 0, - 'react/checked-requires-onchange-or-readonly': 1, - 'react/default-props-match-prop-types': 0, - 'react/destructuring-assignment': 0, - 'react/display-name': 0, - 'react/forbid-component-props': 0, - 'react/forbid-dom-props': 0, - 'react/forbid-elements': 0, - 'react/forbid-foreign-prop-types': 0, - 'react/forbid-prop-types': 0, - 'react/forward-ref-uses-ref': 1, - 'react/function-component-definition': [ - 1, - { - namedComponents: 'function-declaration', - unnamedComponents: 'function-expression' - } - ], - 'react/hook-use-state': 0, - 'react/iframe-missing-sandbox': 1, - 'react/jsx-boolean-value': 1, - 'react/jsx-child-element-spacing': 0, - 'react/jsx-closing-bracket-location': 0, - 'react/jsx-closing-tag-location': 0, - 'react/jsx-curly-brace-presence': 1, - 'react/jsx-curly-newline': 0, - 'react/jsx-curly-spacing': 0, - 'react/jsx-equals-spacing': 0, - 'react/jsx-filename-extension': [1, { extensions: ['.tsx'] }], - 'react/jsx-first-prop-new-line': 0, - 'react/jsx-fragments': 1, - 'react/jsx-handler-names': 0, - 'react/jsx-indent': 0, - 'react/jsx-indent-props': 0, - 'react/jsx-key': [ - 1, - { - checkFragmentShorthand: true, - checkKeyMustBeforeSpread: true, - warnOnDuplicates: true - } - ], - 'react/jsx-max-depth': 0, - 'react/jsx-max-props-per-line': 0, - 'react/jsx-newline': 0, - 'react/jsx-no-bind': 0, - 'react/jsx-no-comment-textnodes': 1, - 'react/jsx-no-constructed-context-values': 1, - 'react/jsx-no-duplicate-props': 0, - 'react/jsx-no-leaked-render': 0, - 'react/jsx-no-literals': 0, - 'react/jsx-no-script-url': 1, - 'react/jsx-no-target-blank': 1, - 'react/jsx-no-undef': 0, - 'react/jsx-no-useless-fragment': 1, - 'react/jsx-one-expression-per-line': 0, - 'react/jsx-pascal-case': 1, - 'react/jsx-props-no-multi-spaces': 0, - 'react/jsx-props-no-spread-multi': 1, - 'react/jsx-props-no-spreading': 0, - 'react/jsx-sort-props': 0, - 'react/jsx-tag-spacing': 0, - 'react/jsx-uses-react': 0, - 'react/jsx-uses-vars': 1, - 'react/jsx-wrap-multilines': 0, - 'react/no-access-state-in-setstate': 1, - 'react/no-adjacent-inline-elements': 0, - 'react/no-array-index-key': 0, - 'react/no-arrow-function-lifecycle': 0, - 'react/no-children-prop': 0, - 'react/no-danger': 1, - 'react/no-danger-with-children': 1, - 'react/no-deprecated': 1, - 'react/no-did-mount-set-state': 1, - 'react/no-did-update-set-state': 1, - 'react/no-direct-mutation-state': 1, - 'react/no-find-dom-node': 0, - 'react/no-invalid-html-attribute': 1, - 'react/no-is-mounted': 1, - 'react/no-multi-comp': 0, - 'react/no-namespace': 0, - 'react/no-object-type-as-default-prop': 1, - 'react/no-redundant-should-component-update': 1, - 'react/no-render-return-value': 0, - 'react/no-set-state': 0, - 'react/no-string-refs': [1, { noTemplateLiterals: true }], - 'react/no-this-in-sfc': 0, - 'react/no-typos': 1, - 'react/no-unescaped-entities': 0, - 'react/no-unknown-property': 0, - 'react/no-unsafe': 1, - 'react/no-unstable-nested-components': [1, { allowAsProps: true }], - 'react/no-unused-class-component-methods': 0, - 'react/no-unused-prop-types': 0, - 'react/no-unused-state': 0, - 'react/no-will-update-set-state': 1, - 'react/prefer-es6-class': 1, - 'react/prefer-exact-props': 0, - 'react/prefer-read-only-props': 0, - 'react/prefer-stateless-function': 0, - 'react/prop-types': 0, - 'react/react-in-jsx-scope': 0, - 'react/require-default-props': 0, - 'react/require-optimization': 0, - 'react/require-render-return': 1, - 'react/self-closing-comp': 1, - 'react/sort-comp': 0, - 'react/sort-default-props': 0, - 'react/sort-prop-types': 0, - 'react/state-in-constructor': 0, - 'react/static-property-placement': 1, - 'react/style-prop-object': 0, - 'react/void-dom-elements-no-children': 1, - // React Hooks // https://www.npmjs.com/package/eslint-plugin-react-hooks 'react-hooks/rules-of-hooks': 1, diff --git a/package.json b/package.json index 3763bcf1a1..146466b557 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,6 @@ "ecij": "^0.3.0", "eslint": "^9.39.1", "eslint-plugin-jest-dom": "^5.5.0", - "eslint-plugin-react": "^7.37.5", "eslint-plugin-react-hooks": "^7.0.1", "eslint-plugin-sonarjs": "^4.0.0", "eslint-plugin-testing-library": "^7.13.5", From 536fe13e6c397d0095e68286248a81b71a1200f6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Feb 2026 16:24:48 +0000 Subject: [PATCH 4/5] Bump eslint from 9.39.3 to 10.0.1 (#3970) * Bump eslint from 9.39.3 to 10.0.1 Bumps [eslint](https://github.com/eslint/eslint) from 9.39.3 to 10.0.1. - [Release notes](https://github.com/eslint/eslint/releases) - [Commits](https://github.com/eslint/eslint/compare/v9.39.3...v10.0.1) --- updated-dependencies: - dependency-name: eslint dependency-version: 10.0.1 dependency-type: direct:development update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] * ignore type issue --------- Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Nicolas Stepien Co-authored-by: Nicolas Stepien <567105+nstepien@users.noreply.github.com> --- eslint.config.js | 1 + package.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/eslint.config.js b/eslint.config.js index 06ef93e052..b54b57633c 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -885,6 +885,7 @@ copy( name: 'markdown', files: ['**/*.md'], plugins: { + // @ts-expect-error markdown }, language: 'markdown/commonmark', diff --git a/package.json b/package.json index 146466b557..d23272787d 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "@vitest/eslint-plugin": "^1.6.4", "clsx": "^2.1.1", "ecij": "^0.3.0", - "eslint": "^9.39.1", + "eslint": "^10.0.1", "eslint-plugin-jest-dom": "^5.5.0", "eslint-plugin-react-hooks": "^7.0.1", "eslint-plugin-sonarjs": "^4.0.0", From 793929e4a5d2c4fe5c35f545cdd934006ad4641a Mon Sep 17 00:00:00 2001 From: Nicolas Stepien <567105+nstepien@users.noreply.github.com> Date: Mon, 23 Feb 2026 19:13:58 +0000 Subject: [PATCH 5/5] Update typescript-eslint config (#3977) * Update typescript-eslint config * update * fix --- .github/dependabot.yml | 3 - eslint.config.js | 237 ++++++++++++------ package.json | 3 +- src/TreeDataGrid.tsx | 5 +- src/hooks/useCalculatedColumns.ts | 2 +- src/types.ts | 2 +- test/browser/TreeDataGrid.test.tsx | 1 - test/browser/column/renderHeaderCell.test.tsx | 2 +- test/visual/treeGrid.test.tsx | 1 - website/Nav.tsx | 3 +- website/routes/CellNavigation.tsx | 2 +- website/routes/ColumnsReordering.tsx | 3 +- website/routes/RowGrouping.tsx | 1 - website/routes/RowsReordering.tsx | 3 +- website/routes/index.tsx | 1 - website/utils.tsx | 9 - 16 files changed, 166 insertions(+), 112 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 3e6e2480c6..d21b977622 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -11,9 +11,6 @@ updates: patterns: - 'react' - 'react-dom' - typescript-eslint: - patterns: - - '@typescript-eslint/*' vitest: patterns: - 'vitest' diff --git a/eslint.config.js b/eslint.config.js index b54b57633c..93c1f26bd8 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -1,13 +1,12 @@ import reactX from '@eslint-react/eslint-plugin'; import markdown from '@eslint/markdown'; -import typescriptEslint from '@typescript-eslint/eslint-plugin'; -import tsParser from '@typescript-eslint/parser'; import vitest from '@vitest/eslint-plugin'; import jestDom from 'eslint-plugin-jest-dom'; import reactHooks from 'eslint-plugin-react-hooks'; import sonarjs from 'eslint-plugin-sonarjs'; import testingLibrary from 'eslint-plugin-testing-library'; import { defineConfig, globalIgnores } from 'eslint/config'; +import tseslint from 'typescript-eslint'; export default defineConfig([ globalIgnores(['.cache', '.nitro', '.output', '.tanstack', 'coverage', 'dist', 'lib']), @@ -27,12 +26,11 @@ export default defineConfig([ 'react-hooks': reactHooks, 'react-x': reactX, sonarjs, - // @ts-expect-error - '@typescript-eslint': typescriptEslint + '@typescript-eslint': tseslint.plugin }, languageOptions: { - parser: tsParser, + parser: tseslint.parser, parserOptions: { ecmaVersion: 'latest', @@ -61,7 +59,7 @@ export default defineConfig([ 'no-control-regex': 1, 'no-debugger': 1, 'no-dupe-args': 1, - 'no-dupe-class-members': 0, + 'no-dupe-class-members': 0, // replaced by @typescript-eslint/no-dupe-class-members 'no-dupe-else-if': 1, 'no-dupe-keys': 1, 'no-duplicate-case': 1, @@ -98,7 +96,7 @@ export default defineConfig([ 'no-unsafe-optional-chaining': [1, { disallowArithmeticOperators: true }], 'no-unused-private-class-members': 0, // replaced by @typescript-eslint/no-unused-private-class-members 'no-unused-vars': 0, // replaced by @typescript-eslint/no-unused-vars - 'no-use-before-define': 0, + 'no-use-before-define': 0, // replaced by @typescript-eslint/no-use-before-define 'no-useless-backreference': 1, 'require-atomic-updates': 1, 'use-isnan': [1, { enforceForIndexOf: true }], @@ -111,14 +109,14 @@ export default defineConfig([ 'block-scoped-var': 1, camelcase: 0, 'capitalized-comments': 0, - 'class-methods-use-this': 1, + 'class-methods-use-this': 0, // replaced by @typescript-eslint/class-methods-use-this complexity: 0, - 'consistent-return': 0, + 'consistent-return': 0, // replaced by @typescript-eslint/consistent-return 'consistent-this': 0, curly: 0, 'default-case': 1, 'default-case-last': 1, - 'default-param-last': 0, + 'default-param-last': 0, // replaced by @typescript-eslint/default-param-last 'dot-notation': 0, // replaced by @typescript-eslint/dot-notation eqeqeq: [1, 'always', { null: 'ignore' }], 'func-name-matching': 0, @@ -129,19 +127,19 @@ export default defineConfig([ 'id-denylist': 0, 'id-length': 0, 'id-match': 0, - 'init-declarations': 0, + 'init-declarations': 0, // replaced by @typescript-eslint/init-declarations 'logical-assignment-operators': [1, 'always', { enforceForIfStatements: true }], 'max-classes-per-file': 0, 'max-depth': 0, 'max-lines': 0, 'max-lines-per-function': 0, 'max-nested-callbacks': 0, - 'max-params': 0, + 'max-params': 0, // replaced by @typescript-eslint/max-params 'max-statements': 0, 'multiline-comment-style': 0, 'new-cap': 0, 'no-alert': 0, - 'no-array-constructor': 1, + 'no-array-constructor': 0, // replaced by @typescript-eslint/no-array-constructor 'no-bitwise': 0, 'no-caller': 1, 'no-case-declarations': 1, @@ -151,7 +149,7 @@ export default defineConfig([ 'no-div-regex': 0, 'no-else-return': [1, { allowElseIf: false }], 'no-empty': [1, { allowEmptyCatch: true }], - 'no-empty-function': 0, + 'no-empty-function': 0, // replaced by @typescript-eslint/no-empty-function 'no-empty-static-block': 1, 'no-eq-null': 0, 'no-eval': 1, @@ -164,14 +162,14 @@ export default defineConfig([ 'no-implicit-globals': 0, 'no-implied-eval': 0, // replaced by @typescript-eslint/no-implied-eval 'no-inline-comments': 0, - 'no-invalid-this': 0, + 'no-invalid-this': 0, // replaced by @typescript-eslint/no-invalid-this 'no-iterator': 1, 'no-label-var': 1, 'no-labels': 1, 'no-lone-blocks': 1, 'no-lonely-if': 1, - 'no-loop-func': 0, - 'no-magic-numbers': 0, + 'no-loop-func': 0, // replaced by @typescript-eslint/no-loop-func + 'no-magic-numbers': 0, // replaced by @typescript-eslint/no-magic-numbers 'no-multi-assign': 0, 'no-multi-str': 1, 'no-negated-condition': 0, @@ -203,7 +201,7 @@ export default defineConfig([ 'no-return-await': 0, // replaced by @typescript-eslint/return-await 'no-script-url': 1, 'no-sequences': [1, { allowInParentheses: false }], - 'no-shadow': 0, + 'no-shadow': 0, // replaced by @typescript-eslint/no-shadow 'no-shadow-restricted-names': 1, 'no-ternary': 0, 'no-throw-literal': 0, // replaced by @typescript-eslint/only-throw-error @@ -211,13 +209,13 @@ export default defineConfig([ 'no-undefined': 0, 'no-underscore-dangle': 0, 'no-unneeded-ternary': [1, { defaultAssignment: false }], - 'no-unused-expressions': [1, { allowTaggedTemplates: true, enforceForJSX: true }], + 'no-unused-expressions': 0, // replaced by @typescript-eslint/no-unused-expressions 'no-unused-labels': 1, 'no-useless-call': 1, 'no-useless-catch': 1, 'no-useless-computed-key': 1, 'no-useless-concat': 1, - 'no-useless-constructor': 1, + 'no-useless-constructor': 0, // replaced by @typescript-eslint/no-useless-constructor 'no-useless-escape': 1, 'no-useless-rename': 1, 'no-useless-return': 1, @@ -408,7 +406,7 @@ copy( 'sonarjs/no-code-after-done': 1, 'sonarjs/no-collapsible-if': 1, 'sonarjs/no-collection-size-mischeck': 1, - 'sonarjs/no-commented-code': 1, + 'sonarjs/no-commented-code': 0, 'sonarjs/no-control-regex': 1, 'sonarjs/no-dead-store': 1, 'sonarjs/no-delete-var': 1, @@ -558,48 +556,93 @@ copy( 'sonarjs/xml-parser-xxe': 1, // @typescript-eslint/eslint-plugin rules - // https://typescript-eslint.io/rules/#supported-rules + // https://typescript-eslint.io/rules/ + /* +// copy all the rules from the rules table for easy pasting +copy( + Iterator.from( + document + // select all rows with a rule + .querySelectorAll('tr:has(a)') + ) + // filter out deprecated rules + .filter((row) => row.lastElementChild.textContent === '') + // map row to rule declaration + .map((row) => `'${row.querySelector('a').textContent}': 1,`) + .toArray() + .join('\n') +); + */ '@typescript-eslint/adjacent-overload-signatures': 1, - '@typescript-eslint/array-type': 0, + '@typescript-eslint/array-type': 1, '@typescript-eslint/await-thenable': 1, '@typescript-eslint/ban-ts-comment': [1, { 'ts-expect-error': false }], '@typescript-eslint/ban-tslint-comment': 0, '@typescript-eslint/class-literal-property-style': 0, - '@typescript-eslint/class-methods-use-this': 0, + '@typescript-eslint/class-methods-use-this': 1, '@typescript-eslint/consistent-generic-constructors': 1, '@typescript-eslint/consistent-indexed-object-style': 1, '@typescript-eslint/consistent-return': 0, '@typescript-eslint/consistent-type-assertions': [ 1, - { assertionStyle: 'as', objectLiteralTypeAssertions: 'never' } + { + arrayLiteralTypeAssertions: 'never', + objectLiteralTypeAssertions: 'never' + } ], '@typescript-eslint/consistent-type-definitions': 1, - '@typescript-eslint/consistent-type-exports': 0, + '@typescript-eslint/consistent-type-exports': [ + 1, + { fixMixedExportsWithInlineTypeSpecifier: true } + ], '@typescript-eslint/consistent-type-imports': [1, { fixStyle: 'inline-type-imports' }], + '@typescript-eslint/default-param-last': 0, + '@typescript-eslint/dot-notation': 1, '@typescript-eslint/explicit-function-return-type': 0, '@typescript-eslint/explicit-member-accessibility': 0, '@typescript-eslint/explicit-module-boundary-types': 0, + '@typescript-eslint/init-declarations': 0, + '@typescript-eslint/max-params': 0, '@typescript-eslint/member-ordering': 0, '@typescript-eslint/method-signature-style': 1, - '@typescript-eslint/naming-convention': 0, + '@typescript-eslint/naming-convention': [ + 1, + { + selector: ['class', 'interface'], + format: ['PascalCase'] + } + ], + '@typescript-eslint/no-array-constructor': 1, '@typescript-eslint/no-array-delete': 1, '@typescript-eslint/no-base-to-string': 0, '@typescript-eslint/no-confusing-non-null-assertion': 0, - '@typescript-eslint/no-confusing-void-expression': [1, { ignoreArrowShorthand: true }], + '@typescript-eslint/no-confusing-void-expression': [ + 1, + { + ignoreArrowShorthand: true, + ignoreVoidReturningFunctions: true + } + ], '@typescript-eslint/no-deprecated': 1, + '@typescript-eslint/no-dupe-class-members': 0, '@typescript-eslint/no-duplicate-enum-values': 1, '@typescript-eslint/no-duplicate-type-constituents': 1, '@typescript-eslint/no-dynamic-delete': 0, + '@typescript-eslint/no-empty-function': 0, '@typescript-eslint/no-empty-object-type': 1, '@typescript-eslint/no-explicit-any': [1, { fixToUnknown: true }], '@typescript-eslint/no-extra-non-null-assertion': 1, '@typescript-eslint/no-extraneous-class': 1, '@typescript-eslint/no-floating-promises': 0, '@typescript-eslint/no-for-in-array': 1, - '@typescript-eslint/no-import-type-side-effects': 0, + '@typescript-eslint/no-implied-eval': 1, + '@typescript-eslint/no-import-type-side-effects': 1, '@typescript-eslint/no-inferrable-types': 1, + '@typescript-eslint/no-invalid-this': 0, '@typescript-eslint/no-invalid-void-type': 1, - '@typescript-eslint/no-meaningless-void-operator': 0, + '@typescript-eslint/no-loop-func': 0, + '@typescript-eslint/no-magic-numbers': 0, + '@typescript-eslint/no-meaningless-void-operator': 1, '@typescript-eslint/no-misused-new': 1, '@typescript-eslint/no-misused-promises': 0, '@typescript-eslint/no-misused-spread': 1, @@ -608,13 +651,33 @@ copy( '@typescript-eslint/no-non-null-asserted-nullish-coalescing': 1, '@typescript-eslint/no-non-null-asserted-optional-chain': 1, '@typescript-eslint/no-non-null-assertion': 0, + '@typescript-eslint/no-redeclare': 1, '@typescript-eslint/no-redundant-type-constituents': 1, '@typescript-eslint/no-require-imports': 1, + '@typescript-eslint/no-restricted-imports': [ + 1, + { + name: 'react', + importNames: ['default'], + message: 'Use named imports instead.' + }, + { + name: 'react-dom', + importNames: ['default'], + message: 'Use named imports instead.' + } + ], '@typescript-eslint/no-restricted-types': 0, - '@typescript-eslint/no-this-alias': 0, - '@typescript-eslint/no-type-alias': 0, + '@typescript-eslint/no-shadow': 0, + '@typescript-eslint/no-this-alias': 1, '@typescript-eslint/no-unnecessary-boolean-literal-compare': 1, - '@typescript-eslint/no-unnecessary-condition': [1, { checkTypePredicates: true }], + '@typescript-eslint/no-unnecessary-condition': [ + 1, + { + allowConstantLoopConditions: 'only-allowed-literals', + checkTypePredicates: true + } + ], '@typescript-eslint/no-unnecessary-parameter-property-assignment': 1, '@typescript-eslint/no-unnecessary-qualifier': 0, '@typescript-eslint/no-unnecessary-template-expression': 1, @@ -630,86 +693,98 @@ copy( '@typescript-eslint/no-unsafe-enum-comparison': 1, '@typescript-eslint/no-unsafe-function-type': 1, '@typescript-eslint/no-unsafe-member-access': 0, - '@typescript-eslint/no-unsafe-return': 1, + '@typescript-eslint/no-unsafe-return': 0, '@typescript-eslint/no-unsafe-type-assertion': 0, '@typescript-eslint/no-unsafe-unary-minus': 1, + '@typescript-eslint/no-unused-expressions': [1, { enforceForJSX: true }], + '@typescript-eslint/no-unused-private-class-members': 1, + '@typescript-eslint/no-unused-vars': [ + 1, + { + enableAutofixRemoval: { imports: true }, + ignoreRestSiblings: true + } + ], + '@typescript-eslint/no-use-before-define': 0, + '@typescript-eslint/no-useless-constructor': 1, + '@typescript-eslint/no-useless-default-assignment': 1, '@typescript-eslint/no-useless-empty-export': 1, - '@typescript-eslint/no-var-requires': 0, '@typescript-eslint/no-wrapper-object-types': 1, '@typescript-eslint/non-nullable-type-assertion-style': 1, + '@typescript-eslint/only-throw-error': [ + 1, + { + allow: [ + { + from: 'package', + package: '@tanstack/router-core', + name: ['NotFoundError', 'Redirect'] + } + ] + } + ], '@typescript-eslint/parameter-properties': 1, '@typescript-eslint/prefer-as-const': 1, - '@typescript-eslint/prefer-destructuring': [1, { array: false, object: true }], - '@typescript-eslint/prefer-enum-initializers': 0, + '@typescript-eslint/prefer-destructuring': [ + 1, + { + VariableDeclarator: { + array: false, + object: true + }, + AssignmentExpression: { + array: false, + object: false + } + } + ], + '@typescript-eslint/prefer-enum-initializers': 1, '@typescript-eslint/prefer-find': 1, '@typescript-eslint/prefer-for-of': 1, '@typescript-eslint/prefer-function-type': 1, '@typescript-eslint/prefer-includes': 1, '@typescript-eslint/prefer-literal-enum-member': 1, - '@typescript-eslint/prefer-namespace-keyword': 0, + '@typescript-eslint/prefer-namespace-keyword': 1, '@typescript-eslint/prefer-nullish-coalescing': [ 1, - { ignorePrimitives: { boolean: true, string: true } } + { + ignoreConditionalTests: false, + ignorePrimitives: true + } ], '@typescript-eslint/prefer-optional-chain': 1, - '@typescript-eslint/prefer-promise-reject-errors': [1, { allowEmptyReject: true }], + '@typescript-eslint/prefer-promise-reject-errors': 1, '@typescript-eslint/prefer-readonly': 1, '@typescript-eslint/prefer-readonly-parameter-types': 0, '@typescript-eslint/prefer-reduce-type-parameter': 1, '@typescript-eslint/prefer-regexp-exec': 1, - '@typescript-eslint/prefer-return-this-type': 0, + '@typescript-eslint/prefer-return-this-type': 1, '@typescript-eslint/prefer-string-starts-ends-with': 1, '@typescript-eslint/promise-function-async': 0, + '@typescript-eslint/related-getter-setter-pairs': 0, '@typescript-eslint/require-array-sort-compare': 1, - '@typescript-eslint/restrict-plus-operands': 0, + '@typescript-eslint/require-await': 1, + '@typescript-eslint/restrict-plus-operands': [ + 1, + { + allowAny: false, + allowBoolean: false, + allowNullish: false, + allowNumberAndString: false, + allowRegExp: false + } + ], '@typescript-eslint/restrict-template-expressions': 0, - '@typescript-eslint/sort-type-constituents': 0, + '@typescript-eslint/return-await': 1, '@typescript-eslint/strict-boolean-expressions': 0, + '@typescript-eslint/strict-void-return': 0, '@typescript-eslint/switch-exhaustiveness-check': 1, '@typescript-eslint/triple-slash-reference': [ 1, { path: 'never', types: 'never', lib: 'never' } ], - '@typescript-eslint/typedef': 0, '@typescript-eslint/unbound-method': 0, '@typescript-eslint/unified-signatures': 0, - - // @typescript-eslint/eslint-plugin Extension Rules - // https://typescript-eslint.io/rules/#extension-rules - '@typescript-eslint/default-param-last': 0, - '@typescript-eslint/dot-notation': 1, - '@typescript-eslint/init-declarations': 0, - '@typescript-eslint/max-params': 0, - '@typescript-eslint/no-array-constructor': 0, - '@typescript-eslint/no-dupe-class-members': 0, - '@typescript-eslint/no-empty-function': 0, - '@typescript-eslint/no-implied-eval': 1, - '@typescript-eslint/no-invalid-this': 0, - '@typescript-eslint/no-loop-func': 0, - '@typescript-eslint/no-magic-numbers': 0, - '@typescript-eslint/no-redeclare': 1, - '@typescript-eslint/no-restricted-imports': [ - 1, - { - name: 'react', - importNames: ['default'], - message: 'Use named imports instead.' - }, - { - name: 'react-dom', - importNames: ['default'], - message: 'Use named imports instead.' - } - ], - '@typescript-eslint/no-shadow': 0, - '@typescript-eslint/no-unused-expressions': 0, - '@typescript-eslint/no-unused-private-class-members': 0, - '@typescript-eslint/no-unused-vars': [1, { ignoreRestSiblings: true }], - '@typescript-eslint/no-use-before-define': 0, - '@typescript-eslint/no-useless-constructor': 0, - '@typescript-eslint/only-throw-error': 1, - '@typescript-eslint/require-await': 1, - '@typescript-eslint/return-await': 1, '@typescript-eslint/use-unknown-in-catch-callback-variable': 1 } }, diff --git a/package.json b/package.json index d23272787d..da78680b9d 100644 --- a/package.json +++ b/package.json @@ -55,8 +55,6 @@ "@types/node": "^25.0.2", "@types/react": "^19.2.0", "@types/react-dom": "^19.2.0", - "@typescript-eslint/eslint-plugin": "^8.48.1", - "@typescript-eslint/parser": "^8.48.1", "@vitejs/plugin-react": "^5.1.1", "@vitest/browser-playwright": "^4.0.16", "@vitest/coverage-istanbul": "^4.0.16", @@ -78,6 +76,7 @@ "rolldown": "^1.0.0-rc.3", "rolldown-plugin-dts": "^0.22.1", "typescript": "~5.9.2", + "typescript-eslint": "^8.56.0", "vite": "^8.0.0-beta.13", "vitest": "^4.0.17", "vitest-browser-react": "^2.0.2" diff --git a/src/TreeDataGrid.tsx b/src/TreeDataGrid.tsx index 9f6845cad5..bafb2e0f10 100644 --- a/src/TreeDataGrid.tsx +++ b/src/TreeDataGrid.tsx @@ -139,13 +139,13 @@ export function TreeDataGrid({ }, [groupBy, rowGrouper, rawRows]); const [rows, isGroupRow] = useMemo((): [ - ReadonlyArray>, + readonly (R | GroupRow)[], (row: R | GroupRow) => row is GroupRow ] => { const allGroupRows = new Set(); if (!groupedRows) return [rawRows, isGroupRow]; - const flattenedRows: Array> = []; + const flattenedRows: (R | GroupRow)[] = []; const expandGroup = ( rows: GroupByDictionary | readonly R[], @@ -298,7 +298,6 @@ export function TreeDataGrid({ if (args.mode === 'EDIT') return; const { column, rowIdx, selectCell } = args; - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition const idx = column?.idx ?? -1; const row = rows[rowIdx]; diff --git a/src/hooks/useCalculatedColumns.ts b/src/hooks/useCalculatedColumns.ts index 0bbc33d0c9..9929d91a17 100644 --- a/src/hooks/useCalculatedColumns.ts +++ b/src/hooks/useCalculatedColumns.ts @@ -8,7 +8,7 @@ import type { DataGridProps } from '../DataGrid'; import renderHeaderCell from '../renderHeaderCell'; type Mutable = { - -readonly [P in keyof T]: T[P] extends ReadonlyArray ? Mutable[] : T[P]; + -readonly [P in keyof T]: T[P] extends readonly (infer V)[] ? Mutable[] : T[P]; }; interface WithParent { diff --git a/src/types.ts b/src/types.ts index 53d4f4b019..3eb61268aa 100644 --- a/src/types.ts +++ b/src/types.ts @@ -203,7 +203,7 @@ export interface CellMouseArgs { interface SelectCellKeyDownArgs { mode: 'SELECT'; - column: CalculatedColumn; + column: CalculatedColumn | undefined; row: TRow; rowIdx: number; selectCell: (position: Position, options?: SelectCellOptions) => void; diff --git a/test/browser/TreeDataGrid.test.tsx b/test/browser/TreeDataGrid.test.tsx index b141c6dff6..3689661e96 100644 --- a/test/browser/TreeDataGrid.test.tsx +++ b/test/browser/TreeDataGrid.test.tsx @@ -124,7 +124,6 @@ function TestGrid({ function rowGrouper(rows: readonly Row[], columnKey: string) { // @ts-expect-error - // eslint-disable-next-line @typescript-eslint/no-unsafe-return return Object.groupBy(rows, (r) => r[columnKey]) as Record; } diff --git a/test/browser/column/renderHeaderCell.test.tsx b/test/browser/column/renderHeaderCell.test.tsx index bf3a7ff0f1..a22af61a5c 100644 --- a/test/browser/column/renderHeaderCell.test.tsx +++ b/test/browser/column/renderHeaderCell.test.tsx @@ -14,7 +14,7 @@ test('renderHeaderCell is either undefined or a component', async () => { { key: 'name', name: 'Name', - renderHeaderCell: ({ column }) => `Fancy! ${column.name}` + renderHeaderCell: ({ column }) => `Fancy! ${column.name as string}` } ]; diff --git a/test/visual/treeGrid.test.tsx b/test/visual/treeGrid.test.tsx index 8d60a3cbad..f87a4863b6 100644 --- a/test/visual/treeGrid.test.tsx +++ b/test/visual/treeGrid.test.tsx @@ -85,6 +85,5 @@ function rowKeyGetter(row: Row) { function rowGrouper(rows: readonly Row[], columnKey: string) { // @ts-expect-error - // eslint-disable-next-line @typescript-eslint/no-unsafe-return return Object.groupBy(rows, (r) => r[columnKey]) as Record; } diff --git a/website/Nav.tsx b/website/Nav.tsx index b1ad6508a8..42731a3144 100644 --- a/website/Nav.tsx +++ b/website/Nav.tsx @@ -3,7 +3,6 @@ import { Link } from '@tanstack/react-router'; import { css } from 'ecij'; import type { Direction } from '../src/types'; -import { startViewTransition } from './utils'; const headerClassname = css` border-inline-start: 4px solid light-dark(hsl(210deg 50% 80%), hsl(210deg 50% 40%)); @@ -64,7 +63,7 @@ export default function Nav({ direction, onDirectionChange }: Props) { const [theme, setTheme] = useState('system'); function onThemeChange(theme: Theme) { - startViewTransition(() => { + document.startViewTransition(() => { setTheme(theme); }); } diff --git a/website/routes/CellNavigation.tsx b/website/routes/CellNavigation.tsx index ffc391329f..2dd2938975 100644 --- a/website/routes/CellNavigation.tsx +++ b/website/routes/CellNavigation.tsx @@ -85,7 +85,7 @@ function CellNavigation() { function handleCellKeyDown(args: CellKeyDownArgs, event: CellKeyboardEvent) { if (args.mode === 'EDIT') return; const { column, rowIdx, selectCell } = args; - const { idx } = column; + const idx = column?.idx ?? -1; const { key, shiftKey } = event; const preventDefault = () => { diff --git a/website/routes/ColumnsReordering.tsx b/website/routes/ColumnsReordering.tsx index 17004ec25f..2986a04135 100644 --- a/website/routes/ColumnsReordering.tsx +++ b/website/routes/ColumnsReordering.tsx @@ -1,7 +1,6 @@ import { useCallback, useMemo, useState } from 'react'; import { DataGrid, type Column, type ColumnWidths, type SortColumn } from '../../src'; -import { startViewTransition } from '../utils'; import { useDirection } from '../directionContext'; export const Route = createFileRoute({ @@ -120,7 +119,7 @@ function ColumnsReordering() { }); } - startViewTransition(reorderColumns); + document.startViewTransition(reorderColumns); } function resetOrderAndWidths() { diff --git a/website/routes/RowGrouping.tsx b/website/routes/RowGrouping.tsx index d260902718..7a62cf80f6 100644 --- a/website/routes/RowGrouping.tsx +++ b/website/routes/RowGrouping.tsx @@ -206,6 +206,5 @@ function RowGrouping() { function rowGrouper(rows: readonly Row[], columnKey: string) { // @ts-expect-error - // eslint-disable-next-line @typescript-eslint/no-unsafe-return return Object.groupBy(rows, (r) => r[columnKey]) as Record; } diff --git a/website/routes/RowsReordering.tsx b/website/routes/RowsReordering.tsx index 8382faf053..48c924c446 100644 --- a/website/routes/RowsReordering.tsx +++ b/website/routes/RowsReordering.tsx @@ -2,7 +2,6 @@ import { useCallback, useState } from 'react'; import { DataGrid, renderTextEditor, type Column, type RenderRowProps } from '../../src'; import { DraggableRowRenderer } from '../components'; -import { startViewTransition } from '../utils'; import { useDirection } from '../directionContext'; export const Route = createFileRoute({ @@ -73,7 +72,7 @@ function RowsReordering() { }); } - startViewTransition(reorderRows); + document.startViewTransition(reorderRows); } return key={key} {...props} onRowReorder={onRowReorder} />; diff --git a/website/routes/index.tsx b/website/routes/index.tsx index 6191d381ab..297b37e9b2 100644 --- a/website/routes/index.tsx +++ b/website/routes/index.tsx @@ -2,7 +2,6 @@ import { redirect } from '@tanstack/react-router'; export const Route = createFileRoute({ beforeLoad() { - // eslint-disable-next-line @typescript-eslint/only-throw-error throw redirect({ to: '/CommonFeatures' }); } }); diff --git a/website/utils.tsx b/website/utils.tsx index 6748007b41..072eca749d 100644 --- a/website/utils.tsx +++ b/website/utils.tsx @@ -61,12 +61,3 @@ function downloadFile(fileName: string, data: Blob) { downloadLink.click(); URL.revokeObjectURL(url); } - -export function startViewTransition(fn: ViewTransitionUpdateCallback) { - // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition - if (document.startViewTransition) { - document.startViewTransition(fn); - } else { - fn(); - } -}