From 64349e90e16e182bc4966305ca9d036f785b8f08 Mon Sep 17 00:00:00 2001 From: Nicolas Stepien Date: Tue, 21 Apr 2026 18:50:25 +0100 Subject: [PATCH] target baseline, lightningcss tweaks, eslint updates, `eslint.config.ts`, remove 3 `@ts-expect-error` --- .vscode/settings.json | 4 +++ eslint.config.js => eslint.config.ts | 33 +++++++--------------- package.json | 41 +++++++++++++--------------- src/Cell.tsx | 2 +- src/DataGrid.tsx | 1 + test/browser/TreeDataGrid.test.tsx | 3 +- test/visual/treeGrid.test.tsx | 3 +- tsconfig.base.json | 1 - tsconfig.js.json | 12 -------- tsconfig.json | 2 +- tsconfig.node.json | 8 ++++++ tsdown.config.ts | 8 +++++- vite.config.ts | 22 +++++++++++++-- website/routes/RowGrouping.tsx | 3 +- 14 files changed, 73 insertions(+), 70 deletions(-) rename eslint.config.js => eslint.config.ts (98%) delete mode 100644 tsconfig.js.json create mode 100644 tsconfig.node.json diff --git a/.vscode/settings.json b/.vscode/settings.json index 762045fea0..b3ad807b3d 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -11,6 +11,10 @@ "js/ts.tsdk.promptToUseWorkspaceVersion": true, "js/ts.tsdk.path": "node_modules/typescript/lib", "js/ts.experimental.useTsgo": true, + "eslint.options": { + "flags": ["unstable_native_nodejs_ts_config"] + }, + "eslint.problems.shortenToSingleLine": true, "files.readonlyInclude": { "**/routeTree.gen.ts": true }, diff --git a/eslint.config.js b/eslint.config.ts similarity index 98% rename from eslint.config.js rename to eslint.config.ts index 8ac5d142da..8fae72101a 100644 --- a/eslint.config.js +++ b/eslint.config.ts @@ -255,10 +255,10 @@ export default defineConfig([ 'unicode-bom': 1, // React Hooks - // https://www.npmjs.com/package/eslint-plugin-react-hooks + // https://github.com/facebook/react/tree/main/packages/eslint-plugin-react-hooks + // https://react.dev/reference/eslint-plugin-react-hooks 'react-hooks/rules-of-hooks': 1, 'react-hooks/exhaustive-deps': 1, - 'react-hooks/component-hook-factories': 1, 'react-hooks/config': 1, 'react-hooks/error-boundaries': 1, 'react-hooks/gating': 1, @@ -365,9 +365,11 @@ copy( '@eslint-react/jsx-no-children-prop': 1, '@eslint-react/jsx-no-children-prop-with-children': 1, '@eslint-react/jsx-no-comment-textnodes': 1, - '@eslint-react/jsx-no-useless-fragment': [1, { allowExpressions: false }], '@eslint-react/jsx-no-key-after-spread': 1, + '@eslint-react/jsx-no-leaked-dollar': 1, + '@eslint-react/jsx-no-leaked-semicolon': 1, '@eslint-react/jsx-no-namespace': 1, + '@eslint-react/jsx-no-useless-fragment': [1, { allowExpressions: false }], '@eslint-react/rsc-function-definition': 1, '@eslint-react/dom-no-dangerously-set-innerhtml': 1, '@eslint-react/dom-no-dangerously-set-innerhtml-with-children': 1, @@ -395,7 +397,7 @@ copy( '@eslint-react/naming-convention-ref-name': 1, // SonarJS rules - // https://github.com/SonarSource/SonarJS/blob/master/packages/jsts/src/rules/README.md#rules + // https://github.com/SonarSource/SonarJS/blob/master/packages/analysis/src/jsts/rules/README.md#rules /* // copy all the rules from the rules table for easy pasting copy( @@ -442,11 +444,12 @@ copy( 'sonarjs/aws-sqs-unencrypted-queue': 0, 'sonarjs/bitwise-operators': 1, 'sonarjs/block-scoped-var': 1, - 'sonarjs/bool-param-default': 0, + 'sonarjs/bool-param-default': 1, 'sonarjs/call-argument-line': 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, @@ -466,6 +469,7 @@ copy( 'sonarjs/disabled-auto-escaping': 1, 'sonarjs/disabled-resource-integrity': 1, 'sonarjs/disabled-timeout': 1, + 'sonarjs/dompurify-unsafe-config': 1, 'sonarjs/duplicates-in-character-class': 1, 'sonarjs/dynamically-constructed-templates': 1, 'sonarjs/elseif-without-else': 0, @@ -517,7 +521,7 @@ copy( 'sonarjs/no-code-after-done': 1, 'sonarjs/no-collapsible-if': 1, 'sonarjs/no-collection-size-mischeck': 1, - 'sonarjs/no-commented-code': 0, + 'sonarjs/no-commented-code': 1, 'sonarjs/no-control-regex': 1, 'sonarjs/no-dead-store': 1, 'sonarjs/no-delete-var': 1, @@ -598,7 +602,6 @@ copy( 'sonarjs/no-undefined-assignment': 0, 'sonarjs/no-unenclosed-multiline-block': 1, 'sonarjs/no-uniq-key': 1, - 'sonarjs/no-unsafe-unzip': 1, 'sonarjs/no-unthrown-error': 1, 'sonarjs/no-unused-collection': 1, 'sonarjs/no-unused-function-argument': 1, @@ -617,7 +620,6 @@ copy( 'sonarjs/null-dereference': 1, 'sonarjs/object-alt-content': 1, 'sonarjs/operation-returning-nan': 1, - 'sonarjs/os-command': 1, 'sonarjs/post-message': 1, 'sonarjs/prefer-default-last': 1, 'sonarjs/prefer-immediate-return': 1, @@ -1028,21 +1030,6 @@ copy( } }, - { - name: 'node', - - files: ['**/*.js'], - - rules: { - // Best Practices - 'default-param-last': 1, - // Possible Errors - 'no-console': 0, - 'no-undef': 1, - 'no-use-before-define': [1, { functions: false, classes: false, variables: false }] - } - }, - { name: 'markdown', files: ['**/*.md'], diff --git a/package.json b/package.json index 0bc34f3110..082cc9bd30 100644 --- a/package.json +++ b/package.json @@ -42,49 +42,46 @@ "test:ci:update": "vitest run --project visual --update", "format": "oxfmt", "format:check": "oxfmt --check", - "eslint": "eslint --max-warnings 0 --cache --cache-location .cache/eslint --cache-strategy content", + "eslint": "eslint --max-warnings 0 --cache --cache-location .cache/eslint --cache-strategy content --flag unstable_native_nodejs_ts_config", "eslint:fix": "node --run eslint -- --fix", "typecheck": "tsgo --build" }, "devDependencies": { - "@eslint-react/eslint-plugin": "^4.2.1", + "@eslint-react/eslint-plugin": "^4.2.3", "@eslint/markdown": "^8.0.1", "@faker-js/faker": "^10.3.0", "@tanstack/react-router": "^1.166.7", "@tanstack/router-plugin": "^1.166.7", - "@tsdown/css": "^0.21.7", - "@types/node": "^25.5.0", + "@tsdown/css": "^0.21.9", + "@types/node": "^25.6.0", "@types/react": "^19.2.14", "@types/react-dom": "^19.2.3", - "@typescript/native-preview": "^7.0.0-dev.20260407.1", + "@typescript/native-preview": "^7.0.0-dev.20260421.1", "@vitejs/plugin-react": "^6.0.1", - "@vitest/browser-playwright": "^4.1.3", - "@vitest/coverage-istanbul": "^4.1.3", - "@vitest/eslint-plugin": "^1.6.14", + "@vitest/browser-playwright": "^4.1.5", + "@vitest/coverage-istanbul": "^4.1.5", + "@vitest/eslint-plugin": "^1.6.16", "clsx": "^2.1.1", "ecij": "^0.4.1", - "eslint": "^10.0.3", - "eslint-plugin-react-hooks": "^7.0.1", - "eslint-plugin-sonarjs": "^4.0.2", + "eslint": "^10.2.1", + "eslint-plugin-react-hooks": "^7.1.1", + "eslint-plugin-sonarjs": "^4.0.3", "jspdf": "^4.2.0", "jspdf-autotable": "^5.0.7", - "oxfmt": "0.45.0", + "oxfmt": "0.46.0", "playwright": "~1.59.0", "postcss": "^8.5.2", - "react": "^19.2.4", - "react-dom": "^19.2.4", - "tsdown": "^0.21.7", - "typescript": "~6.0.2", - "typescript-eslint": "^8.58.0", - "vite": "^8.0.6", - "vitest": "^4.1.3", + "react": "^19.2.5", + "react-dom": "^19.2.5", + "tsdown": "^0.21.9", + "typescript": "~6.0.3", + "typescript-eslint": "^8.59.0", + "vite": "^8.0.9", + "vitest": "^4.1.5", "vitest-browser-react": "^2.2.0" }, "peerDependencies": { "react": "^19.2", "react-dom": "^19.2" - }, - "overrides": { - "eslint": "$eslint" } } diff --git a/src/Cell.tsx b/src/Cell.tsx index a71450f0bd..8f631cb607 100644 --- a/src/Cell.tsx +++ b/src/Cell.tsx @@ -45,7 +45,7 @@ function Cell({ ); const isEditable = isCellEditableUtil(column, row); - function setActivePositionWrapper(enableEditor?: boolean) { + function setActivePositionWrapper(enableEditor = false) { setActivePosition({ rowIdx, idx: column.idx }, { enableEditor }); } diff --git a/src/DataGrid.tsx b/src/DataGrid.tsx index e05c7f53cb..e86d33502a 100644 --- a/src/DataGrid.tsx +++ b/src/DataGrid.tsx @@ -504,6 +504,7 @@ export function DataGrid(props: DataGridPr } else { focusCell(gridRef.current!); } + // eslint-disable-next-line react-hooks/set-state-in-effect setShouldFocusPosition(false); } }, [shouldFocusPosition, activePositionIsRow, gridRef]); diff --git a/test/browser/TreeDataGrid.test.tsx b/test/browser/TreeDataGrid.test.tsx index 676548e969..96963dca57 100644 --- a/test/browser/TreeDataGrid.test.tsx +++ b/test/browser/TreeDataGrid.test.tsx @@ -123,8 +123,7 @@ function TestGrid({ } function rowGrouper(rows: readonly Row[], columnKey: string) { - // @ts-expect-error - return Object.groupBy(rows, (r) => r[columnKey]) as Record; + return Object.groupBy(rows, (r) => r[columnKey as keyof Row]) as Record; } function setup(groupBy: string[], groupIdGetter?: (groupKey: string, parentId?: string) => string) { diff --git a/test/visual/treeGrid.test.tsx b/test/visual/treeGrid.test.tsx index f87a4863b6..79dc6e0fa3 100644 --- a/test/visual/treeGrid.test.tsx +++ b/test/visual/treeGrid.test.tsx @@ -84,6 +84,5 @@ function rowKeyGetter(row: Row) { } function rowGrouper(rows: readonly Row[], columnKey: string) { - // @ts-expect-error - return Object.groupBy(rows, (r) => r[columnKey]) as Record; + return Object.groupBy(rows, (r) => r[columnKey as keyof Row]) as Record; } diff --git a/tsconfig.base.json b/tsconfig.base.json index 444fec02db..ef72c0a15f 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -8,7 +8,6 @@ "jsx": "react-jsx", "lib": [], "moduleDetection": "force", - "moduleResolution": "bundler", "noImplicitReturns": true, "noUnusedLocals": true, "outDir": "./.cache/ts", diff --git a/tsconfig.js.json b/tsconfig.js.json deleted file mode 100644 index 86dbf9a660..0000000000 --- a/tsconfig.js.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "extends": "./tsconfig.base.json", - "compilerOptions": { - "allowJs": true, - "checkJs": false, - "lib": ["ESNext"], - "module": "NodeNext", - "moduleResolution": "NodeNext" - }, - "include": ["**/*.js"], - "exclude": ["./coverage/**/*", "./dist/**/*", "./lib/**/*"] -} diff --git a/tsconfig.json b/tsconfig.json index 5e9516892e..a28bee1737 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "include": [], "references": [ - { "path": "tsconfig.js.json" }, + { "path": "tsconfig.node.json" }, { "path": "tsconfig.src.json" }, { "path": "tsconfig.test.json" }, { "path": "tsconfig.vite.json" }, diff --git a/tsconfig.node.json b/tsconfig.node.json new file mode 100644 index 0000000000..1b8b4319e2 --- /dev/null +++ b/tsconfig.node.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.base.json", + "compilerOptions": { + "lib": ["ESNext"], + "module": "NodeNext" + }, + "include": ["eslint.config.ts"] +} diff --git a/tsdown.config.ts b/tsdown.config.ts index ac943e1849..a6dba578f9 100644 --- a/tsdown.config.ts +++ b/tsdown.config.ts @@ -1,17 +1,23 @@ import { ecij } from 'ecij/plugin'; +import { Features } from 'lightningcss'; import { defineConfig } from 'tsdown'; import pkg from './package.json' with { type: 'json' }; export default defineConfig({ outDir: 'lib', + target: ['baseline-widely-available', 'node24.0.0'], platform: 'neutral', sourcemap: true, deps: { skipNodeModulesBundle: true }, css: { - fileName: 'styles.css' + fileName: 'styles.css', + lightningcss: { + // https://github.com/parcel-bundler/lightningcss/issues/873 + exclude: Features.Nesting | Features.LightDark + } }, dts: { build: true, diff --git a/vite.config.ts b/vite.config.ts index eabc6bb119..450f7bdd35 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -2,6 +2,7 @@ import { tanstackRouter } from '@tanstack/router-plugin/vite'; import react from '@vitejs/plugin-react'; import { playwright, type PlaywrightProviderOptions } from '@vitest/browser-playwright'; import { ecij } from 'ecij/plugin'; +import { Features } from 'lightningcss'; import { defineConfig, type ViteUserConfig } from 'vitest/config'; import type { BrowserCommand } from 'vitest/node'; @@ -56,9 +57,24 @@ export default defineConfig( build: { modulePreload: { polyfill: false }, sourcemap: true, - reportCompressedSize: false, - // https://github.com/parcel-bundler/lightningcss/issues/873 - cssTarget: 'esnext' + rolldownOptions: { + output: { + codeSplitting: { + groups: [ + { + name: 'faker', + test: '@faker-js/faker' + } + ] + } + } + } + }, + css: { + lightningcss: { + // https://github.com/parcel-bundler/lightningcss/issues/873 + exclude: Features.Nesting | Features.LightDark + } }, plugins: isPreview ? [] diff --git a/website/routes/RowGrouping.tsx b/website/routes/RowGrouping.tsx index 0d3cc493c0..44c27a64c2 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 - return Object.groupBy(rows, (r) => r[columnKey]) as Record; + return Object.groupBy(rows, (r) => r[columnKey as keyof Row]) as Record; }