From 6babe77a283c8ac0e30ee36380cd666e7ab0ad32 Mon Sep 17 00:00:00 2001 From: Ryan Albrecht Date: Thu, 14 May 2026 14:12:21 -0700 Subject: [PATCH 1/3] ref(eslint): Make @eslint-react the source of truth over eslint-plugin-react MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Make @eslint-react/eslint-plugin the authoritative React linting plugin, demoting eslint-plugin-react to a supplement for rules that have no @eslint-react equivalent. ## What changed ### eslint-plugin-react (demoted) - Stopped extending `recommended` and `jsx-runtime` configs - Registered the plugin manually and kept only 16 rules that have no @eslint-react equivalent: function-component-definition, jsx-boolean-value, jsx-fragments, jsx-curly-brace-presence, jsx-no-duplicate-props, jsx-no-target-blank, no-deprecated, no-is-mounted, no-redundant-should- component-update, no-string-refs, no-typos, no-unknown-property (with css ignore for Emotion), require-render-return, self-closing-comp, sort-comp, jsx-handler-names (off/TODO) - Removed 9 rules now covered by @eslint-react: jsx-key, jsx-no-comment- textnodes, no-children-prop, no-danger-with-children, no-direct-mutation- state, no-find-dom-node, no-render-return-value, no-did-mount-set-state, no-did-update-set-state ### eslint-plugin-react-hooks (removed) - Removed entirely — rules-of-hooks and exhaustive-deps (with the additionalHooks config for useEffectAfterFirstRender and useMemoWithPrevious) are now provided by @eslint-react - Removed from package.json dependencies ### @eslint-react/eslint-plugin (promoted) - Extended `strict-typescript` config (was `recommended`) - Added conditional `strict-type-checked` config when type-aware linting is enabled (ignores MDX files) - All NEW strict rules are explicitly disabled until violations are fixed: dom-no-missing-button-type, dom-no-missing-iframe-sandbox, dom-no-unsafe-target-blank, jsx-no-useless-fragment, no-class-component, no-misused-capture-owner-stack, no-unstable-context-value, no-unstable-default-props, no-leaked-conditional-rendering (type-checked), no-unused-props (type-checked) - Configured exhaustive-deps at error level with additionalHooks to match the previous react-hooks behavior --- eslint.config.ts | 66 ++++-- package.json | 2 +- pnpm-lock.yaml | 517 ++++++++++++++++++++++++++++++++++++----------- 3 files changed, 447 insertions(+), 138 deletions(-) diff --git a/eslint.config.ts b/eslint.config.ts index 392386460ee0..db76dce45b3a 100644 --- a/eslint.config.ts +++ b/eslint.config.ts @@ -25,6 +25,7 @@ * - Examples: preventing sentry from importing getsentry, core isolation, test boundaries */ import * as emotion from '@emotion/eslint-plugin'; +import eslintReact from '@eslint-react/eslint-plugin'; import eslint from '@eslint/js'; import pluginQuery from '@tanstack/eslint-plugin-query'; import prettier from 'eslint-config-prettier'; @@ -35,7 +36,6 @@ import jestDom from 'eslint-plugin-jest-dom'; import * as mdx from 'eslint-plugin-mdx'; import noRelativeImportPaths from 'eslint-plugin-no-relative-import-paths'; import react from 'eslint-plugin-react'; -import reactHooks from 'eslint-plugin-react-hooks'; import reactYouMightNotNeedAnEffect from 'eslint-plugin-react-you-might-not-need-an-effect'; import regexp from 'eslint-plugin-regexp'; import testingLibrary from 'eslint-plugin-testing-library'; @@ -53,8 +53,6 @@ import * as sentryScrapsPlugin from './static/eslint/eslintPluginScraps/index'; import * as sentryPlugin from './static/eslint/eslintPluginSentry/index'; invariant(react.configs.flat, 'For typescript'); -invariant(react.configs.flat.recommended, 'For typescript'); -invariant(react.configs.flat['jsx-runtime'], 'For typescript'); // Some rules can be enabled/disabled via env vars. // This is useful for CI, where we want to run the linter with the most strict @@ -547,16 +545,26 @@ export default typescript.config([ { name: 'plugin/react', // https://github.com/jsx-eslint/eslint-plugin-react/tree/master/docs/rules - extends: [react.configs.flat.recommended, react.configs.flat['jsx-runtime']], + // Only rules without an @eslint-react equivalent are listed here. + // Overlapping rules (jsx-key, no-children-prop, no-danger-with-children, + // no-direct-mutation-state, no-find-dom-node, no-render-return-value, + // no-did-mount-set-state, no-did-update-set-state, jsx-no-comment-textnodes) + // are handled by @eslint-react. + plugins: {react}, rules: { 'react/function-component-definition': 'error', 'react/jsx-boolean-value': ['error', 'never'], 'react/jsx-fragments': ['error', 'element'], 'react/jsx-handler-names': 'off', // TODO(ryan953): Fix violations and enable this rule - 'react/no-did-mount-set-state': 'error', - 'react/no-did-update-set-state': 'error', + 'react/jsx-no-duplicate-props': 'error', + 'react/jsx-no-target-blank': 'error', + 'react/no-deprecated': 'error', + 'react/no-is-mounted': 'error', 'react/no-redundant-should-component-update': 'error', + 'react/no-string-refs': 'error', 'react/no-typos': 'error', + 'react/no-unknown-property': ['error', {ignore: ['css']}], + 'react/require-render-return': 'error', 'react/self-closing-comp': 'error', 'react/sort-comp': 'error', @@ -564,24 +572,52 @@ export default typescript.config([ 'error', {props: 'never', children: 'ignore', propElementValues: 'always'}, ], - 'react/display-name': 'off', // TODO(ryan953): Fix violations and delete this line - 'react/no-unescaped-entities': 'off', - 'react/no-unknown-property': ['error', {ignore: ['css']}], - 'react/prop-types': 'off', // TODO(ryan953): Fix violations and delete this line }, }, { - name: 'plugin/react-hooks', - // https://github.com/facebook/react/tree/main/packages/eslint-plugin-react-hooks - plugins: {'react-hooks': reactHooks}, + name: 'plugin/eslint-react', + extends: [eslintReact.configs['strict-typescript']], rules: { - 'react-hooks/exhaustive-deps': [ + '@eslint-react/exhaustive-deps': [ 'error', {additionalHooks: '(useEffectAfterFirstRender|useMemoWithPrevious)'}, ], - 'react-hooks/rules-of-hooks': 'error', + // New rules in strict-typescript not in recommended — disabled until violations are fixed + '@eslint-react/dom-no-missing-button-type': 'off', + '@eslint-react/dom-no-missing-iframe-sandbox': 'off', + '@eslint-react/dom-no-unsafe-target-blank': 'off', + '@eslint-react/jsx-no-useless-fragment': 'off', + '@eslint-react/no-class-component': 'off', + '@eslint-react/no-misused-capture-owner-stack': 'off', + '@eslint-react/no-unstable-context-value': 'off', + '@eslint-react/no-unstable-default-props': 'off', }, }, + { + name: 'plugin/eslint-react/type-checked', + ignores: [globMDX], + extends: enableTypeAwareLinting ? [eslintReact.configs['strict-type-checked']] : [], + rules: enableTypeAwareLinting + ? { + '@eslint-react/exhaustive-deps': [ + 'error', + {additionalHooks: '(useEffectAfterFirstRender|useMemoWithPrevious)'}, + ], + // Re-apply strict rule disables (strict-type-checked re-sets them via cascading) + '@eslint-react/dom-no-missing-button-type': 'off', + '@eslint-react/dom-no-missing-iframe-sandbox': 'off', + '@eslint-react/dom-no-unsafe-target-blank': 'off', + '@eslint-react/jsx-no-useless-fragment': 'off', + '@eslint-react/no-class-component': 'off', + '@eslint-react/no-misused-capture-owner-stack': 'off', + '@eslint-react/no-unstable-context-value': 'off', + '@eslint-react/no-unstable-default-props': 'off', + // Type-checked only strict rules — disabled until violations are fixed + '@eslint-react/no-leaked-conditional-rendering': 'off', + '@eslint-react/no-unused-props': 'off', + } + : {}, + }, { extends: enableTypeAwareLinting ? [typescript.configs.strictTypeChecked, typescript.configs.stylisticTypeChecked] diff --git a/package.json b/package.json index 894f8289e591..56cd8fe9df43 100644 --- a/package.json +++ b/package.json @@ -230,6 +230,7 @@ "devDependencies": { "@emotion/eslint-plugin": "^11.12.0", "@emotion/server": "^11.11.0", + "@eslint-react/eslint-plugin": "^5.7.8", "@eslint/js": "9.32.0", "@figma/code-connect": "^1.3.13", "@jest/environment": "30.3.0", @@ -265,7 +266,6 @@ "eslint-plugin-mdx": "3.6.2", "eslint-plugin-no-relative-import-paths": "^1.6.1", "eslint-plugin-react": "7.37.5", - "eslint-plugin-react-hooks": "6.1.0", "eslint-plugin-react-you-might-not-need-an-effect": "0.5.3", "eslint-plugin-regexp": "^3.0.0", "eslint-plugin-testing-library": "^7.16.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dd43601d13fd..384a96815fee 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -549,6 +549,9 @@ importers: '@emotion/server': specifier: ^11.11.0 version: 11.11.0(@emotion/css@11.13.5) + '@eslint-react/eslint-plugin': + specifier: ^5.7.8 + version: 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) '@eslint/js': specifier: 9.32.0 version: 9.32.0 @@ -654,9 +657,6 @@ importers: eslint-plugin-react: specifier: 7.37.5 version: 7.37.5(eslint@9.34.0(jiti@2.6.1)) - eslint-plugin-react-hooks: - specifier: 6.1.0 - version: 6.1.0(eslint@9.34.0(jiti@2.6.1)) eslint-plugin-react-you-might-not-need-an-effect: specifier: 0.5.3 version: 0.5.3(eslint@9.34.0(jiti@2.6.1)) @@ -832,28 +832,14 @@ packages: resolution: {integrity: sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==} engines: {node: '>=6.9.0'} - '@babel/helper-annotate-as-pure@7.27.3': - resolution: {integrity: sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==} - engines: {node: '>=6.9.0'} - '@babel/helper-compilation-targets@7.28.6': resolution: {integrity: sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==} engines: {node: '>=6.9.0'} - '@babel/helper-create-class-features-plugin@7.27.1': - resolution: {integrity: sha512-QwGAmuvM17btKU5VqXfb+Giw4JcN0hjuufz3DYnpeVDvZLAObloM77bhMXiqry3Iio+Ai4phVRDwl6WU10+r5A==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - '@babel/helper-globals@7.28.0': resolution: {integrity: sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==} engines: {node: '>=6.9.0'} - '@babel/helper-member-expression-to-functions@7.27.1': - resolution: {integrity: sha512-E5chM8eWjTp/aNoVpcbfM7mLxu9XGLWYise2eBKGQomAk/Mb4XoxyqXTZbuTohbsl8EKqdlMhnDI2CCLfcs9wA==} - engines: {node: '>=6.9.0'} - '@babel/helper-module-imports@7.25.9': resolution: {integrity: sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==} engines: {node: '>=6.9.0'} @@ -868,10 +854,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-optimise-call-expression@7.27.1': - resolution: {integrity: sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==} - engines: {node: '>=6.9.0'} - '@babel/helper-plugin-utils@7.27.1': resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} engines: {node: '>=6.9.0'} @@ -880,16 +862,6 @@ packages: resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} engines: {node: '>=6.9.0'} - '@babel/helper-replace-supers@7.27.1': - resolution: {integrity: sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - - '@babel/helper-skip-transparent-expression-wrappers@7.27.1': - resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==} - engines: {node: '>=6.9.0'} - '@babel/helper-string-parser@7.27.1': resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} @@ -920,13 +892,6 @@ packages: engines: {node: '>=6.0.0'} hasBin: true - '@babel/plugin-proposal-private-methods@7.18.6': - resolution: {integrity: sha512-nutsvktDItsNn4rpGItSNV2sz1XwS+nfU0Rg8aCx3W3NOKVzdMjJRu0O5OkgDp3ZGICSTbgRpxZoWsxoKRvbeA==} - engines: {node: '>=6.9.0'} - deprecated: This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-methods instead. - peerDependencies: - '@babel/core': ^7.0.0-0 - '@babel/plugin-syntax-async-generators@7.8.4': resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} peerDependencies: @@ -1419,6 +1384,55 @@ packages: resolution: {integrity: sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + '@eslint-react/ast@5.7.8': + resolution: {integrity: sha512-AmMqth2ryBXU6B8aM940sxO1oWo7Vs1H/taoudflNOpuv5WPLvI4mF+GuIy6+uRC78BqwZlGU1wjLoAxpOHj3A==} + engines: {node: '>=22.0.0'} + peerDependencies: + eslint: ^10.3.0 + typescript: '*' + + '@eslint-react/core@5.7.8': + resolution: {integrity: sha512-7F56PDcjxWorkWTdFnbnLae73VvWFeh61x74NjtSM82Io3iJ0V5b/UC5L1ixmgpd2AuaEAq0hSKu4dPHlQ3ZdQ==} + engines: {node: '>=22.0.0'} + peerDependencies: + eslint: ^10.3.0 + typescript: '*' + + '@eslint-react/eslint-plugin@5.7.8': + resolution: {integrity: sha512-AtqdzdZ+WGJ2JgSuCBUz6Xrdi4gEHEvfKuZ40leFU04wc8G4LOx6UOStTZfNCnmWZO2FrSl47wmz/WWOdRHK1w==} + engines: {node: '>=22.0.0'} + peerDependencies: + eslint: ^10.3.0 + typescript: '*' + + '@eslint-react/eslint@5.7.8': + resolution: {integrity: sha512-OTRtnMzfaAObDiMnOYLBfzed8HSIIHPt3sNzQEj0OG4HgG/XgugzxsXpp38ZHpfVLacCKimlvKCwcckYyb947w==} + engines: {node: '>=22.0.0'} + peerDependencies: + eslint: ^10.3.0 + typescript: '*' + + '@eslint-react/jsx@5.7.8': + resolution: {integrity: sha512-bf4J4mzF0gnOHsMW5voEGcCZ0HJnKp59Xgr5uBsSVahtxcRLSikK1fBnmdiZ00fMpPVWIK5SZjGBYTHUH/xvRQ==} + engines: {node: '>=22.0.0'} + peerDependencies: + eslint: ^10.3.0 + typescript: '*' + + '@eslint-react/shared@5.7.8': + resolution: {integrity: sha512-J/lP9ZEXoO9plx8eXsYIsf4EnSodQkYzKJub8/Tpps6rFMktLhnlQFTm3MeYkAoOxVBIRC450vce23/D1A9ViQ==} + engines: {node: '>=22.0.0'} + peerDependencies: + eslint: ^10.3.0 + typescript: '*' + + '@eslint-react/var@5.7.8': + resolution: {integrity: sha512-p2QG1rhSJ3NK66ck6GG/XjceO86TbPewpJHZygEKBGadSPXCiNPMza7F0TAYA8SzAorOeNb5Ayl7rUTgnHWrPw==} + engines: {node: '>=22.0.0'} + peerDependencies: + eslint: ^10.3.0 + typescript: '*' + '@eslint/config-array@0.21.0': resolution: {integrity: sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -3819,6 +3833,12 @@ packages: peerDependencies: typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/project-service@8.59.3': + resolution: {integrity: sha512-ECiUWa/KYRGDFUqTNehaRgzDshnJfkTABJxVemHk4ko22gcr0ukloKjWvyQ64g8YCV/UI47kN1dbmjf/GaQYng==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/rule-tester@8.58.0': resolution: {integrity: sha512-a/J72Cxeo5ug5sbey7+Dcna6tMBc4Z4eYwBEKM6MVuBqbxnROpLm8yn/j00lPZc75joPZJVR5oiTZxbK95zp+w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -3837,6 +3857,10 @@ packages: resolution: {integrity: sha512-W1Lur1oF50FxSnNdGp3Vs6P+yBRSmZiw4IIjEeYxd8UQJwhUF0gDgDD/W/Tgmh73mxgEU3qX0Bzdl/NGuSPEpQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/scope-manager@8.59.3': + resolution: {integrity: sha512-t2LvZnoEfzKtnPjgeEu41xw5gxq9mQVfYy4OoZ4Vlt0sk3JwxmhCca/AR7DwOiHrjWgjAj6as4AhRLKSDfvZIA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/tsconfig-utils@8.56.1': resolution: {integrity: sha512-qOtCYzKEeyr3aR9f28mPJqBty7+DBqsdd63eO0yyDwc6vgThj2UjWfJIcsFeSucYydqcuudMOprZ+x1SpF3ZuQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -3849,6 +3873,12 @@ packages: peerDependencies: typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/tsconfig-utils@8.59.3': + resolution: {integrity: sha512-PcIJHjmaREXLgIAIzLnSY9VucEzz8FKXsRgFa1DmdGCK/5tJpW03TKJF01Q6VZd1lLdz2sIKPWaDUZN9dp//dw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/type-utils@8.58.0': resolution: {integrity: sha512-aGsCQImkDIqMyx1u4PrVlbi/krmDsQUs4zAcCV6M7yPcPev+RqVlndsJy9kJ8TLihW9TZ0kbDAzctpLn5o+lOg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -3856,6 +3886,13 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/type-utils@8.59.3': + resolution: {integrity: sha512-g71d8QD8UaiHGvrJwyIS1hCX5r63w6Jll+4VEYhEAHXTDIqX1JgxhTAbEHtKntL9kuc4jRo7/GWw5xfCepSccQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/types@5.62.0': resolution: {integrity: sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3868,6 +3905,10 @@ packages: resolution: {integrity: sha512-O9CjxypDT89fbHxRfETNoAnHj/i6IpRK0CvbVN3qibxlLdo5p5hcLmUuCCrHMpxiWSwKyI8mCP7qRNYuOJ0Uww==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/types@8.59.3': + resolution: {integrity: sha512-ePFoH0g4ludssdRFqqDxQePCxU4WQyRa9+XVwjm7yLn0FKhMeoetC+qBEEI1Eyb1pGSDveTIT09Bvw2WhlGayg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@5.62.0': resolution: {integrity: sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3889,6 +3930,12 @@ packages: peerDependencies: typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/typescript-estree@8.59.3': + resolution: {integrity: sha512-CbRjVRAf7Lr9Kr8RopKcbY45p2VfmmHrm0ygOCYFi7oU8q19m0Fs/6iHS7kNOmwpp+ob07ZVcAqlxUod9lYdmg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/utils@5.62.0': resolution: {integrity: sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3909,6 +3956,13 @@ packages: eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/utils@8.59.3': + resolution: {integrity: sha512-JAvT14goBzRzzzZyqq3P9BLArIxTtQURUtFgQ/V7FO+eU+Gg6ES+5ymOPP1wRxXcxAYeivCk4uS3jCKWI1K8Zg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 || ^10.0.0 + typescript: '>=4.8.4 <6.1.0' + '@typescript-eslint/visitor-keys@5.62.0': resolution: {integrity: sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -3921,6 +3975,10 @@ packages: resolution: {integrity: sha512-XJ9UD9+bbDo4a4epraTwG3TsNPeiB9aShrUneAVXy8q4LuwowN+qu89/6ByLMINqvIMeI9H9hOHQtg/ijrYXzQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/visitor-keys@8.59.3': + resolution: {integrity: sha512-f1UQF7ggd42YiwI5wGrRaPsa+P0CINBlrkLPmGfpq/u/I/oVtecoEIfFR9ag/oa1sLOsRNZ6xehf6qMZhQGBDg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript/native-preview-darwin-arm64@7.0.0-dev.20260513.1': resolution: {integrity: sha512-ACX4oq23lGy3w9OstNspV8tH36DLFJ7Oe1vepGLrnhocnLJ58VGw3LAL9ObB4T1EB9H0M7fsgMIY4IEDRo8j8g==} engines: {node: '>=16.20.0'} @@ -4392,6 +4450,9 @@ packages: resolution: {integrity: sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==} engines: {node: '>=8'} + birecord@0.1.1: + resolution: {integrity: sha512-VUpsf/qykW0heRlC8LooCq28Kxn3mAqKohhDG/49rrsQ1dT1CXyj/pgXS+5BSRzFTR/3DyIBOqQOrGyZOh71Aw==} + bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} @@ -5427,11 +5488,47 @@ packages: eslint-plugin-no-relative-import-paths@1.6.1: resolution: {integrity: sha512-YZNeOnsOrJcwhFw0X29MXjIzu2P/f5X2BZDPWw1R3VUYBRFxNIh77lyoL/XrMU9ewZNQPcEvAgL/cBOT1P330A==} - eslint-plugin-react-hooks@6.1.0: - resolution: {integrity: sha512-72mucw/WLzEqGvL2vwE6fWR6geO6UbmDjz3eAb3pezxTpFzgbfyUeFKzmZKr9LhwUWMXfTVh1g0rKEJoyKNdoA==} - engines: {node: '>=18'} + eslint-plugin-react-dom@5.7.8: + resolution: {integrity: sha512-83JXHVbfm+w4RaqGD76BV1ZHlD8WizgRKMloWz5nv+11tz8i3KF7Xbi0nhWpUp86I+VUDhZZL6BSCHfs63HHkA==} + engines: {node: '>=22.0.0'} + peerDependencies: + eslint: ^10.3.0 + typescript: '*' + + eslint-plugin-react-jsx@5.7.8: + resolution: {integrity: sha512-ItC1Z52V/fa6Rr/mBBD0T2OmvktrHx5XEr4SpdTaH1wATpbdHMi7GGHBANggOzDcaEmvJRxfZpzzu2rrCESE4g==} + engines: {node: '>=22.0.0'} + peerDependencies: + eslint: ^10.3.0 + typescript: '*' + + eslint-plugin-react-naming-convention@5.7.8: + resolution: {integrity: sha512-Hxuw1zjMor6IaAlUQbFxH/0qT1Gv9uVQQA5ayQGXij/4sdgD85apCwKXRfVf02p76VnVboJXrxXNOEx1BjtuOg==} + engines: {node: '>=22.0.0'} + peerDependencies: + eslint: ^10.3.0 + typescript: '*' + + eslint-plugin-react-rsc@5.7.8: + resolution: {integrity: sha512-b2NFpOCAdE2MTggofthnhom0qlYGh+fgNwdpjvxGEMVA9Rt0xjhKiNvtxnOrDLWdHVVBigP9Ilr7jzqInfufEg==} + engines: {node: '>=22.0.0'} peerDependencies: - eslint: ^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 + eslint: ^10.3.0 + typescript: '*' + + eslint-plugin-react-web-api@5.7.8: + resolution: {integrity: sha512-vfnbkJwOInykYqnoGSbiab+3yXdr6bcLwVwO3mJFrKPcJMqPGDS1gur9C4xhK3nB9ZV78ch8yP8CnsmFasq2lQ==} + engines: {node: '>=22.0.0'} + peerDependencies: + eslint: ^10.3.0 + typescript: '*' + + eslint-plugin-react-x@5.7.8: + resolution: {integrity: sha512-Oia7nSq+F+ezgKYPQ73CnipWRlLUBqAt8JQVi34dylN3seSW6coaSZb8CkRdu/JaGBgntyD0u2RYHgaXGol4Fg==} + engines: {node: '>=22.0.0'} + peerDependencies: + eslint: ^10.3.0 + typescript: '*' eslint-plugin-react-you-might-not-need-an-effect@0.5.3: resolution: {integrity: sha512-/tkUN71PIp5+LVSDb9y3MA4zMyjVGJojfWCeC2NSWhRRBbc0NRR8WnFXe2h3bw6tTcYMack/dlHME5YVu/0Fmw==} @@ -6024,12 +6121,6 @@ packages: resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} hasBin: true - hermes-estree@0.25.1: - resolution: {integrity: sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==} - - hermes-parser@0.25.1: - resolution: {integrity: sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==} - hoist-non-react-statics@3.3.2: resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} @@ -8407,6 +8498,9 @@ packages: resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} engines: {node: '>=10'} + string-ts@2.3.1: + resolution: {integrity: sha512-xSJq+BS52SaFFAVxuStmx6n5aYZU571uYUnUrPXkPFCfdHyZMMlbP2v2Wx5sNBnAVzq/2+0+mcBLBa3Xa5ubYw==} + string-width@4.2.3: resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} engines: {node: '>=8'} @@ -8721,6 +8815,9 @@ packages: '@swc/wasm': optional: true + ts-pattern@5.9.0: + resolution: {integrity: sha512-6s5V71mX8qBUmlgbrfL33xDUwO0fq48rxAu2LBE11WBeGdpCPOsXksQbZJHvHwhrd3QjUusd3mAOM5Gg0mFBLg==} + tsconfig-paths@3.15.0: resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} @@ -9289,12 +9386,12 @@ packages: zod@3.25.58: resolution: {integrity: sha512-DVLmMQzSZwNYzQoMaM3MQWnxr2eq+AtM9Hx3w1/Yl0pH8sLTSjN4jGP7w6f7uand6Hw44tsnSu1hz1AOA6qI2Q==} - zod@3.25.76: - resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} - zod@4.3.5: resolution: {integrity: sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==} + zod@4.4.3: + resolution: {integrity: sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ==} + zrender@6.0.0: resolution: {integrity: sha512-41dFXEEXuJpNecuUQq6JlbybmnHaqqpGlbH1yxnA5V9MMP4SbohSVZsJIwz+zdjQXSSlR1Vc34EgH1zxyTDvhg==} @@ -9473,10 +9570,6 @@ snapshots: '@jridgewell/trace-mapping': 0.3.31 jsesc: 3.1.0 - '@babel/helper-annotate-as-pure@7.27.3': - dependencies: - '@babel/types': 7.29.0 - '@babel/helper-compilation-targets@7.28.6': dependencies: '@babel/compat-data': 7.29.0 @@ -9485,28 +9578,8 @@ snapshots: lru-cache: 5.1.1 semver: 6.3.1 - '@babel/helper-create-class-features-plugin@7.27.1(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-annotate-as-pure': 7.27.3 - '@babel/helper-member-expression-to-functions': 7.27.1 - '@babel/helper-optimise-call-expression': 7.27.1 - '@babel/helper-replace-supers': 7.27.1(@babel/core@7.29.0) - '@babel/helper-skip-transparent-expression-wrappers': 7.27.1 - '@babel/traverse': 7.29.0 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - '@babel/helper-globals@7.28.0': {} - '@babel/helper-member-expression-to-functions@7.27.1': - dependencies: - '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 - transitivePeerDependencies: - - supports-color - '@babel/helper-module-imports@7.25.9': dependencies: '@babel/traverse': 7.27.4 @@ -9530,30 +9603,10 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-optimise-call-expression@7.27.1': - dependencies: - '@babel/types': 7.29.0 - '@babel/helper-plugin-utils@7.27.1': {} '@babel/helper-plugin-utils@7.28.6': {} - '@babel/helper-replace-supers@7.27.1(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-member-expression-to-functions': 7.27.1 - '@babel/helper-optimise-call-expression': 7.27.1 - '@babel/traverse': 7.29.0 - transitivePeerDependencies: - - supports-color - - '@babel/helper-skip-transparent-expression-wrappers@7.27.1': - dependencies: - '@babel/traverse': 7.29.0 - '@babel/types': 7.29.0 - transitivePeerDependencies: - - supports-color - '@babel/helper-string-parser@7.27.1': {} '@babel/helper-validator-identifier@7.27.1': {} @@ -9575,14 +9628,6 @@ snapshots: dependencies: '@babel/types': 7.29.0 - '@babel/plugin-proposal-private-methods@7.18.6(@babel/core@7.29.0)': - dependencies: - '@babel/core': 7.29.0 - '@babel/helper-create-class-features-plugin': 7.27.1(@babel/core@7.29.0) - '@babel/helper-plugin-utils': 7.27.1 - transitivePeerDependencies: - - supports-color - '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 @@ -10055,6 +10100,93 @@ snapshots: '@eslint-community/regexpp@4.12.2': {} + '@eslint-react/ast@5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2)': + dependencies: + '@typescript-eslint/types': 8.59.3 + '@typescript-eslint/typescript-estree': 8.59.3(typescript@6.0.2) + '@typescript-eslint/utils': 8.59.3(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + eslint: 9.34.0(jiti@2.6.1) + string-ts: 2.3.1 + typescript: 6.0.2 + transitivePeerDependencies: + - supports-color + + '@eslint-react/core@5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2)': + dependencies: + '@eslint-react/ast': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/eslint': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/jsx': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/shared': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/var': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@typescript-eslint/scope-manager': 8.59.3 + '@typescript-eslint/types': 8.59.3 + '@typescript-eslint/utils': 8.59.3(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + eslint: 9.34.0(jiti@2.6.1) + ts-pattern: 5.9.0 + typescript: 6.0.2 + transitivePeerDependencies: + - supports-color + + '@eslint-react/eslint-plugin@5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2)': + dependencies: + '@eslint-react/shared': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + eslint: 9.34.0(jiti@2.6.1) + eslint-plugin-react-dom: 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + eslint-plugin-react-jsx: 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + eslint-plugin-react-naming-convention: 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + eslint-plugin-react-rsc: 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + eslint-plugin-react-web-api: 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + eslint-plugin-react-x: 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + typescript: 6.0.2 + transitivePeerDependencies: + - supports-color + + '@eslint-react/eslint@5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2)': + dependencies: + '@typescript-eslint/utils': 8.59.3(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + eslint: 9.34.0(jiti@2.6.1) + typescript: 6.0.2 + transitivePeerDependencies: + - supports-color + + '@eslint-react/jsx@5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2)': + dependencies: + '@eslint-react/ast': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/eslint': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/shared': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/var': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@typescript-eslint/types': 8.59.3 + '@typescript-eslint/utils': 8.59.3(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + eslint: 9.34.0(jiti@2.6.1) + ts-pattern: 5.9.0 + typescript: 6.0.2 + transitivePeerDependencies: + - supports-color + + '@eslint-react/shared@5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2)': + dependencies: + '@eslint-react/eslint': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@typescript-eslint/utils': 8.59.3(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + eslint: 9.34.0(jiti@2.6.1) + ts-pattern: 5.9.0 + typescript: 6.0.2 + zod: 4.4.3 + transitivePeerDependencies: + - supports-color + + '@eslint-react/var@5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2)': + dependencies: + '@eslint-react/ast': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/eslint': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@typescript-eslint/scope-manager': 8.59.3 + '@typescript-eslint/types': 8.59.3 + '@typescript-eslint/utils': 8.59.3(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + eslint: 9.34.0(jiti@2.6.1) + ts-pattern: 5.9.0 + typescript: 6.0.2 + transitivePeerDependencies: + - supports-color + '@eslint/config-array@0.21.0': dependencies: '@eslint/object-schema': 2.1.6 @@ -13012,6 +13144,15 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/project-service@8.59.3(typescript@6.0.2)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.59.3(typescript@6.0.2) + '@typescript-eslint/types': 8.59.3 + debug: 4.4.3 + typescript: 6.0.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/rule-tester@8.58.0(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2)': dependencies: '@typescript-eslint/parser': 8.58.0(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) @@ -13041,6 +13182,11 @@ snapshots: '@typescript-eslint/types': 8.58.0 '@typescript-eslint/visitor-keys': 8.58.0 + '@typescript-eslint/scope-manager@8.59.3': + dependencies: + '@typescript-eslint/types': 8.59.3 + '@typescript-eslint/visitor-keys': 8.59.3 + '@typescript-eslint/tsconfig-utils@8.56.1(typescript@6.0.2)': dependencies: typescript: 6.0.2 @@ -13049,6 +13195,10 @@ snapshots: dependencies: typescript: 6.0.2 + '@typescript-eslint/tsconfig-utils@8.59.3(typescript@6.0.2)': + dependencies: + typescript: 6.0.2 + '@typescript-eslint/type-utils@8.58.0(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2)': dependencies: '@typescript-eslint/types': 8.58.0 @@ -13061,12 +13211,26 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/type-utils@8.59.3(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2)': + dependencies: + '@typescript-eslint/types': 8.59.3 + '@typescript-eslint/typescript-estree': 8.59.3(typescript@6.0.2) + '@typescript-eslint/utils': 8.59.3(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + debug: 4.4.3 + eslint: 9.34.0(jiti@2.6.1) + ts-api-utils: 2.5.0(typescript@6.0.2) + typescript: 6.0.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/types@5.62.0': {} '@typescript-eslint/types@8.56.1': {} '@typescript-eslint/types@8.58.0': {} + '@typescript-eslint/types@8.59.3': {} + '@typescript-eslint/typescript-estree@5.62.0(typescript@6.0.2)': dependencies: '@typescript-eslint/types': 5.62.0 @@ -13111,6 +13275,21 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@8.59.3(typescript@6.0.2)': + dependencies: + '@typescript-eslint/project-service': 8.59.3(typescript@6.0.2) + '@typescript-eslint/tsconfig-utils': 8.59.3(typescript@6.0.2) + '@typescript-eslint/types': 8.59.3 + '@typescript-eslint/visitor-keys': 8.59.3 + debug: 4.4.3 + minimatch: 10.2.3 + semver: 7.7.4 + tinyglobby: 0.2.16 + ts-api-utils: 2.5.0(typescript@6.0.2) + typescript: 6.0.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/utils@5.62.0(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2)': dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@9.34.0(jiti@2.6.1)) @@ -13148,6 +13327,17 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/utils@8.59.3(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2)': + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.34.0(jiti@2.6.1)) + '@typescript-eslint/scope-manager': 8.59.3 + '@typescript-eslint/types': 8.59.3 + '@typescript-eslint/typescript-estree': 8.59.3(typescript@6.0.2) + eslint: 9.34.0(jiti@2.6.1) + typescript: 6.0.2 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/visitor-keys@5.62.0': dependencies: '@typescript-eslint/types': 5.62.0 @@ -13163,6 +13353,11 @@ snapshots: '@typescript-eslint/types': 8.58.0 eslint-visitor-keys: 5.0.1 + '@typescript-eslint/visitor-keys@8.59.3': + dependencies: + '@typescript-eslint/types': 8.59.3 + eslint-visitor-keys: 5.0.1 + '@typescript/native-preview-darwin-arm64@7.0.0-dev.20260513.1': optional: true @@ -13654,6 +13849,8 @@ snapshots: binary-extensions@2.1.0: {} + birecord@0.1.1: {} + bl@4.1.0: dependencies: buffer: 5.7.1 @@ -14822,15 +15019,97 @@ snapshots: eslint-plugin-no-relative-import-paths@1.6.1: {} - eslint-plugin-react-hooks@6.1.0(eslint@9.34.0(jiti@2.6.1)): + eslint-plugin-react-dom@5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2): dependencies: - '@babel/core': 7.29.0 - '@babel/parser': 7.28.0 - '@babel/plugin-proposal-private-methods': 7.18.6(@babel/core@7.29.0) + '@eslint-react/ast': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/eslint': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/jsx': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/shared': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@typescript-eslint/types': 8.59.3 + '@typescript-eslint/utils': 8.59.3(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + compare-versions: 6.1.1 + eslint: 9.34.0(jiti@2.6.1) + typescript: 6.0.2 + transitivePeerDependencies: + - supports-color + + eslint-plugin-react-jsx@5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2): + dependencies: + '@eslint-react/ast': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/core': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/eslint': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/jsx': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/shared': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@typescript-eslint/types': 8.59.3 + '@typescript-eslint/utils': 8.59.3(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + eslint: 9.34.0(jiti@2.6.1) + typescript: 6.0.2 + transitivePeerDependencies: + - supports-color + + eslint-plugin-react-naming-convention@5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2): + dependencies: + '@eslint-react/ast': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/core': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/eslint': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/var': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@typescript-eslint/types': 8.59.3 + '@typescript-eslint/utils': 8.59.3(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + eslint: 9.34.0(jiti@2.6.1) + ts-pattern: 5.9.0 + typescript: 6.0.2 + transitivePeerDependencies: + - supports-color + + eslint-plugin-react-rsc@5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2): + dependencies: + '@eslint-react/ast': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/core': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/eslint': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/shared': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/var': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@typescript-eslint/types': 8.59.3 + '@typescript-eslint/utils': 8.59.3(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + eslint: 9.34.0(jiti@2.6.1) + typescript: 6.0.2 + transitivePeerDependencies: + - supports-color + + eslint-plugin-react-web-api@5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2): + dependencies: + '@eslint-react/ast': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/core': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/eslint': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/shared': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/var': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@typescript-eslint/types': 8.59.3 + '@typescript-eslint/utils': 8.59.3(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + birecord: 0.1.1 + eslint: 9.34.0(jiti@2.6.1) + ts-pattern: 5.9.0 + typescript: 6.0.2 + transitivePeerDependencies: + - supports-color + + eslint-plugin-react-x@5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2): + dependencies: + '@eslint-react/ast': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/core': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/eslint': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/jsx': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/shared': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@eslint-react/var': 5.7.8(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@typescript-eslint/scope-manager': 8.59.3 + '@typescript-eslint/type-utils': 8.59.3(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + '@typescript-eslint/types': 8.59.3 + '@typescript-eslint/typescript-estree': 8.59.3(typescript@6.0.2) + '@typescript-eslint/utils': 8.59.3(eslint@9.34.0(jiti@2.6.1))(typescript@6.0.2) + compare-versions: 6.1.1 eslint: 9.34.0(jiti@2.6.1) - hermes-parser: 0.25.1 - zod: 3.25.76 - zod-validation-error: 3.4.0(zod@3.25.76) + string-ts: 2.3.1 + ts-api-utils: 2.5.0(typescript@6.0.2) + ts-pattern: 5.9.0 + typescript: 6.0.2 transitivePeerDependencies: - supports-color @@ -15619,12 +15898,6 @@ snapshots: he@1.2.0: {} - hermes-estree@0.25.1: {} - - hermes-parser@0.25.1: - dependencies: - hermes-estree: 0.25.1 - hoist-non-react-statics@3.3.2: dependencies: react-is: 19.2.1 @@ -18712,6 +18985,8 @@ snapshots: char-regex: 1.0.2 strip-ansi: 6.0.1 + string-ts@2.3.1: {} + string-width@4.2.3: dependencies: emoji-regex: 8.0.0 @@ -19068,6 +19343,8 @@ snapshots: '@swc/core': 1.15.24 optional: true + ts-pattern@5.9.0: {} + tsconfig-paths@3.15.0: dependencies: '@types/json5': 0.0.29 @@ -19743,16 +20020,12 @@ snapshots: dependencies: zod: 3.25.58 - zod-validation-error@3.4.0(zod@3.25.76): - dependencies: - zod: 3.25.76 - zod@3.25.58: {} - zod@3.25.76: {} - zod@4.3.5(patch_hash=2bb6d33b2c713a7a2c559c18ad0aa6cfb261f01d935ee1288dfec6c84411aa76): {} + zod@4.4.3: {} + zrender@6.0.0: dependencies: tslib: 2.3.0 From 6dd8330c17e847b9050084db68bafcaec4056a91 Mon Sep 17 00:00:00 2001 From: Ryan Albrecht Date: Fri, 15 May 2026 14:39:08 -0700 Subject: [PATCH 2/3] keep old config to start, add in @eslint-react on top --- eslint.config.ts | 103 ++++++++------- pnpm-lock.yaml | 123 ++++-------------- .../commandPalette/ui/collection.tsx | 2 +- .../useCommandPaletteAnalytics.tsx | 2 +- .../components/core/compactSelect/control.tsx | 2 +- .../core/compactSelect/gridList/option.tsx | 2 +- .../core/compactSelect/listBox/option.tsx | 2 +- static/app/components/core/tabs/tabList.tsx | 2 +- .../components/events/interfaces/threads.tsx | 2 +- .../components/events/rrwebReplayer/index.tsx | 2 +- static/app/components/exports/dataExport.tsx | 2 +- .../externalIssues/externalIssueForm.tsx | 2 +- .../forms/controls/rangeSlider/index.tsx | 2 +- static/app/components/forms/jsonForm.tsx | 2 +- .../modals/dataWidgetViewerModal.tsx | 2 +- .../gettingStartedDoc/onboardingLayout.tsx | 2 +- .../app/components/pageFilters/container.tsx | 4 +- .../app/components/performance/searchBar.tsx | 2 +- .../teamKeyTransactionsManager.tsx | 2 +- .../flamegraph/continuousFlamegraph.tsx | 2 +- .../profiling/flamegraph/flamegraph.tsx | 2 +- .../flamegraphToolbar/flamegraphSearch.tsx | 2 +- static/app/components/resultGrid.tsx | 2 +- .../filter/useFrozenSuggestionSectionItems.ts | 2 +- .../tokens/filter/valueCombobox.tsx | 2 +- .../utils/list/useListItemCheckboxState.tsx | 4 +- .../flamegraphQueryParamSync.tsx | 2 +- .../app/utils/replays/hooks/useReplayData.tsx | 2 +- .../playback/hooks/useReplayCurrentTime.tsx | 2 +- .../useRouteAnalyticsParams.tsx | 2 +- static/app/utils/url/useLocationQuery.tsx | 2 +- static/app/utils/useDispatchingReducer.tsx | 2 +- static/app/utils/useEffectAfterFirstRender.ts | 2 +- static/app/utils/useLocalStorageState.ts | 2 +- static/app/utils/useMemoWithPrevious.spec.tsx | 2 +- static/app/utils/useMemoWithPrevious.ts | 2 +- static/app/utils/useOwners.tsx | 2 +- static/app/utils/useProjects.tsx | 4 +- static/app/utils/useResizableDrawer.tsx | 2 +- static/app/utils/useSessionStorage.tsx | 2 +- .../app/views/alerts/list/incidents/index.tsx | 2 +- .../alerts/rules/issue/previewIssues.tsx | 2 +- .../app/views/alerts/rules/issue/ruleNode.tsx | 2 +- .../alerts/rules/metric/eapMetricsField.tsx | 2 +- .../alerts/rules/uptime/formErrors.spec.tsx | 2 +- static/app/views/dashboards/dashboard.tsx | 2 +- static/app/views/dashboards/filtersBar.tsx | 2 +- .../metricsEquationVisualize/index.tsx | 2 +- .../components/widgetBuilderSlideout.tsx | 2 +- .../components/widgetTemplatesList.tsx | 4 +- .../widgetBuilder/hooks/useIsEquationMode.tsx | 2 +- .../categoricalSeriesWidgetVisualization.tsx | 2 +- .../forms/metric/metricsEquationVisualize.tsx | 2 +- .../forms/metric/metricsVisualize.tsx | 2 +- .../explore/logs/tables/logsInfiniteTable.tsx | 2 +- .../logs/useLogsAutoRefreshInterval.tsx | 2 +- .../app/views/explore/logs/useLogsQuery.tsx | 2 +- .../profiling/continuousProfileFlamegraph.tsx | 2 +- .../explore/profiling/profileFlamechart.tsx | 2 +- .../explore/releases/list/releasesPromo.tsx | 2 +- .../replays/detail/layout/splitPanel.tsx | 2 +- .../app/views/feedback/feedbackEmptyState.tsx | 2 +- .../common/components/agentSelector.tsx | 4 +- .../common/components/spanDescription.tsx | 2 +- .../pages/agents/components/drawer.tsx | 2 +- .../issueDetails/groupMerged/mergedItem.tsx | 2 +- .../groupReplays/groupReplays.tsx | 2 +- static/app/views/issueList/overview.tsx | 4 +- .../widgets/components/performanceWidget.tsx | 4 +- .../widgets/components/queryHandler.tsx | 4 +- .../widgets/widgets/histogramWidget.tsx | 2 +- .../widgets/widgets/lineChartListWidget.tsx | 4 +- .../mobileReleaseComparisonListWidget.tsx | 4 +- .../widgets/widgets/singleFieldAreaWidget.tsx | 4 +- .../widgets/stackedAreaChartListWidget.tsx | 4 +- .../landing/widgets/widgets/trendsWidget.tsx | 2 +- .../performance/newTraceDetails/trace.tsx | 2 +- .../traceApi/useIssuesTraceTree.tsx | 2 +- .../newTraceDetails/traceApi/useTrace.tsx | 2 +- .../newTraceDetails/traceApi/useTraceTree.tsx | 2 +- .../traceDrawer/traceDrawer.tsx | 4 +- .../usePassiveResizeableDrawer.tsx | 2 +- .../newTraceDetails/traceWaterfall.tsx | 4 +- .../useTraceWaterfallModels.tsx | 2 +- static/app/views/permissionDenied.tsx | 2 +- static/app/views/relocation/relocation.tsx | 4 +- static/app/views/routeError.tsx | 2 +- .../dynamicSampling/projectSampling.tsx | 2 +- .../integrationServerlessFunctions.tsx | 2 +- .../project/tempest/PlayStationSettings.tsx | 2 +- .../components/extendProductTrialAction.tsx | 2 +- static/gsApp/hooks/useRouteActivatedHook.tsx | 2 +- .../views/amCheckout/components/cart.tsx | 2 +- tests/js/setup.ts | 4 +- 94 files changed, 189 insertions(+), 253 deletions(-) diff --git a/eslint.config.ts b/eslint.config.ts index db76dce45b3a..221c0a9d6bfb 100644 --- a/eslint.config.ts +++ b/eslint.config.ts @@ -36,6 +36,7 @@ import jestDom from 'eslint-plugin-jest-dom'; import * as mdx from 'eslint-plugin-mdx'; import noRelativeImportPaths from 'eslint-plugin-no-relative-import-paths'; import react from 'eslint-plugin-react'; +// import reactHooks from 'eslint-plugin-react-hooks'; import reactYouMightNotNeedAnEffect from 'eslint-plugin-react-you-might-not-need-an-effect'; import regexp from 'eslint-plugin-regexp'; import testingLibrary from 'eslint-plugin-testing-library'; @@ -53,6 +54,8 @@ import * as sentryScrapsPlugin from './static/eslint/eslintPluginScraps/index'; import * as sentryPlugin from './static/eslint/eslintPluginSentry/index'; invariant(react.configs.flat, 'For typescript'); +invariant(react.configs.flat.recommended, 'For typescript'); +invariant(react.configs.flat['jsx-runtime'], 'For typescript'); // Some rules can be enabled/disabled via env vars. // This is useful for CI, where we want to run the linter with the most strict @@ -545,26 +548,16 @@ export default typescript.config([ { name: 'plugin/react', // https://github.com/jsx-eslint/eslint-plugin-react/tree/master/docs/rules - // Only rules without an @eslint-react equivalent are listed here. - // Overlapping rules (jsx-key, no-children-prop, no-danger-with-children, - // no-direct-mutation-state, no-find-dom-node, no-render-return-value, - // no-did-mount-set-state, no-did-update-set-state, jsx-no-comment-textnodes) - // are handled by @eslint-react. - plugins: {react}, + extends: [react.configs.flat.recommended, react.configs.flat['jsx-runtime']], rules: { 'react/function-component-definition': 'error', 'react/jsx-boolean-value': ['error', 'never'], 'react/jsx-fragments': ['error', 'element'], 'react/jsx-handler-names': 'off', // TODO(ryan953): Fix violations and enable this rule - 'react/jsx-no-duplicate-props': 'error', - 'react/jsx-no-target-blank': 'error', - 'react/no-deprecated': 'error', - 'react/no-is-mounted': 'error', + 'react/no-did-mount-set-state': 'error', + 'react/no-did-update-set-state': 'error', 'react/no-redundant-should-component-update': 'error', - 'react/no-string-refs': 'error', 'react/no-typos': 'error', - 'react/no-unknown-property': ['error', {ignore: ['css']}], - 'react/require-render-return': 'error', 'react/self-closing-comp': 'error', 'react/sort-comp': 'error', @@ -572,52 +565,68 @@ export default typescript.config([ 'error', {props: 'never', children: 'ignore', propElementValues: 'always'}, ], + 'react/display-name': 'off', // TODO(ryan953): Fix violations and delete this line + 'react/no-unescaped-entities': 'off', + 'react/no-unknown-property': ['error', {ignore: ['css']}], + 'react/prop-types': 'off', // TODO(ryan953): Fix violations and delete this line }, }, { name: 'plugin/eslint-react', extends: [eslintReact.configs['strict-typescript']], rules: { + '@eslint-react/dom-no-dangerously-set-innerhtml': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/dom-no-flush-sync': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/dom-no-missing-button-type': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/dom-no-missing-iframe-sandbox': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/dom-no-unsafe-iframe-sandbox': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/dom-no-unsafe-target-blank': 'off', // TODO(ryan953): Fix violations and delete this line '@eslint-react/exhaustive-deps': [ 'error', {additionalHooks: '(useEffectAfterFirstRender|useMemoWithPrevious)'}, ], - // New rules in strict-typescript not in recommended — disabled until violations are fixed - '@eslint-react/dom-no-missing-button-type': 'off', - '@eslint-react/dom-no-missing-iframe-sandbox': 'off', - '@eslint-react/dom-no-unsafe-target-blank': 'off', - '@eslint-react/jsx-no-useless-fragment': 'off', - '@eslint-react/no-class-component': 'off', - '@eslint-react/no-misused-capture-owner-stack': 'off', - '@eslint-react/no-unstable-context-value': 'off', - '@eslint-react/no-unstable-default-props': 'off', + '@eslint-react/jsx-no-children-prop': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/jsx-no-children-prop-with-children': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/jsx-no-key-after-spread': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/jsx-no-leaked-dollar': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/jsx-no-leaked-semicolon': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/jsx-no-useless-fragment': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/naming-convention-context-name': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/naming-convention-id-name': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/naming-convention-ref-name': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/no-access-state-in-setstate': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/no-array-index-key': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/no-children-count': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/no-children-map': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/no-children-to-array': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/no-class-component': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/no-clone-element': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/no-context-provider': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/no-create-ref': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/no-forward-ref': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/no-missing-key': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/no-misused-capture-owner-stack': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/no-nested-component-definitions': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/no-set-state-in-component-did-mount': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/no-set-state-in-component-did-update': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/no-unnecessary-use-prefix': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/no-unsafe-component-will-receive-props': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/no-unstable-context-value': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/no-unstable-default-props': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/no-unused-class-component-members': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/no-use-context': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/purity': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/set-state-in-effect': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/static-components': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/unsupported-syntax': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/use-state': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/web-api-no-leaked-event-listener': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/web-api-no-leaked-fetch': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/web-api-no-leaked-interval': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/web-api-no-leaked-resize-observer': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/web-api-no-leaked-timeout': 'off', // TODO(ryan953): Fix violations and delete this line }, }, - { - name: 'plugin/eslint-react/type-checked', - ignores: [globMDX], - extends: enableTypeAwareLinting ? [eslintReact.configs['strict-type-checked']] : [], - rules: enableTypeAwareLinting - ? { - '@eslint-react/exhaustive-deps': [ - 'error', - {additionalHooks: '(useEffectAfterFirstRender|useMemoWithPrevious)'}, - ], - // Re-apply strict rule disables (strict-type-checked re-sets them via cascading) - '@eslint-react/dom-no-missing-button-type': 'off', - '@eslint-react/dom-no-missing-iframe-sandbox': 'off', - '@eslint-react/dom-no-unsafe-target-blank': 'off', - '@eslint-react/jsx-no-useless-fragment': 'off', - '@eslint-react/no-class-component': 'off', - '@eslint-react/no-misused-capture-owner-stack': 'off', - '@eslint-react/no-unstable-context-value': 'off', - '@eslint-react/no-unstable-default-props': 'off', - // Type-checked only strict rules — disabled until violations are fixed - '@eslint-react/no-leaked-conditional-rendering': 'off', - '@eslint-react/no-unused-props': 'off', - } - : {}, - }, { extends: enableTypeAwareLinting ? [typescript.configs.strictTypeChecked, typescript.configs.stylisticTypeChecked] diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 384a96815fee..cf424abcedc6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -854,10 +854,6 @@ packages: peerDependencies: '@babel/core': ^7.0.0 - '@babel/helper-plugin-utils@7.27.1': - resolution: {integrity: sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==} - engines: {node: '>=6.9.0'} - '@babel/helper-plugin-utils@7.28.6': resolution: {integrity: sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==} engines: {node: '>=6.9.0'} @@ -882,11 +878,6 @@ packages: resolution: {integrity: sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==} engines: {node: '>=6.9.0'} - '@babel/parser@7.28.0': - resolution: {integrity: sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==} - engines: {node: '>=6.0.0'} - hasBin: true - '@babel/parser@7.29.0': resolution: {integrity: sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==} engines: {node: '>=6.0.0'} @@ -991,10 +982,6 @@ packages: resolution: {integrity: sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==} engines: {node: '>=6.9.0'} - '@babel/template@7.27.2': - resolution: {integrity: sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==} - engines: {node: '>=6.9.0'} - '@babel/template@7.28.6': resolution: {integrity: sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==} engines: {node: '>=6.9.0'} @@ -1007,14 +994,6 @@ packages: resolution: {integrity: sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==} engines: {node: '>=6.9.0'} - '@babel/types@7.27.6': - resolution: {integrity: sha512-ETyHEk2VHHvl9b9jZP5IHPavHYk57EhanlRRuae9XCpb/j5bDCbPPMOBfCWhnl/7EDJz0jEMCi/RhccCE8r1+Q==} - engines: {node: '>=6.9.0'} - - '@babel/types@7.28.0': - resolution: {integrity: sha512-jYnje+JyZG5YThjHiF28oT4SIZLnYOcSBb6+SDaFIyzDVSkXQmQQYclJ2R+YxcdmK0AX6x1E5OQNtuh3jHDrUg==} - engines: {node: '>=6.9.0'} - '@babel/types@7.29.0': resolution: {integrity: sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==} engines: {node: '>=6.9.0'} @@ -4490,11 +4469,6 @@ packages: browserslist-to-es-version@1.2.0: resolution: {integrity: sha512-wZpJM7QUP33yPzWDzMLgTFZzb3WC6f7G13gnJ5p8PlFz3Xm9MUwArRh9jgE0y4/Sqo6CKtsNxyGpVf5zLWgAhg==} - browserslist@4.27.0: - resolution: {integrity: sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==} - engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} - hasBin: true - browserslist@4.28.1: resolution: {integrity: sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} @@ -5196,9 +5170,6 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} - electron-to-chromium@1.5.245: - resolution: {integrity: sha512-rdmGfW47ZhL/oWEJAY4qxRtdly2B98ooTJ0pdEI4jhVLZ6tNf8fPtov2wS1IRKwFJT92le3x4Knxiwzl7cPPpQ==} - electron-to-chromium@1.5.313: resolution: {integrity: sha512-QBMrTWEf00GXZmJyx2lbYD45jpI3TUFnNIzJ5BBc8piGUDwMPa1GV6HJWTZVvY/eiN3fSopl7NRbgGp9sZ9LTA==} @@ -8980,12 +8951,6 @@ packages: unrs-resolver@1.7.13: resolution: {integrity: sha512-QUjCYKAgrdJpf3wA73zWjOrO7ra19lfnwQ8HRkNOLah5AVDqOS38UunnyhzsSL8AE+2/AGnAHxlr8cGshCP35A==} - update-browserslist-db@1.1.4: - resolution: {integrity: sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==} - hasBin: true - peerDependencies: - browserslist: '>= 4.21.0' - update-browserslist-db@1.2.3: resolution: {integrity: sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==} hasBin: true @@ -9574,7 +9539,7 @@ snapshots: dependencies: '@babel/compat-data': 7.29.0 '@babel/helper-validator-option': 7.27.1 - browserslist: 4.27.0 + browserslist: 4.28.2 lru-cache: 5.1.1 semver: 6.3.1 @@ -9583,7 +9548,7 @@ snapshots: '@babel/helper-module-imports@7.25.9': dependencies: '@babel/traverse': 7.27.4 - '@babel/types': 7.27.6 + '@babel/types': 7.29.0 transitivePeerDependencies: - supports-color @@ -9603,8 +9568,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/helper-plugin-utils@7.27.1': {} - '@babel/helper-plugin-utils@7.28.6': {} '@babel/helper-string-parser@7.27.1': {} @@ -9620,10 +9583,6 @@ snapshots: '@babel/template': 7.28.6 '@babel/types': 7.29.0 - '@babel/parser@7.28.0': - dependencies: - '@babel/types': 7.28.0 - '@babel/parser@7.29.0': dependencies: '@babel/types': 7.29.0 @@ -9631,82 +9590,82 @@ snapshots: '@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-syntax-import-attributes@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-syntax-jsx@7.27.1(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.29.0)': dependencies: '@babel/core': 7.29.0 - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@babel/plugin-syntax-typescript@7.28.6(@babel/core@7.29.0)': dependencies: @@ -9717,12 +9676,6 @@ snapshots: '@babel/runtime@7.28.6': {} - '@babel/template@7.27.2': - dependencies: - '@babel/code-frame': 7.27.1 - '@babel/parser': 7.29.0 - '@babel/types': 7.29.0 - '@babel/template@7.28.6': dependencies: '@babel/code-frame': 7.29.0 @@ -9731,10 +9684,10 @@ snapshots: '@babel/traverse@7.27.4': dependencies: - '@babel/code-frame': 7.27.1 + '@babel/code-frame': 7.29.0 '@babel/generator': 7.29.1 '@babel/parser': 7.29.0 - '@babel/template': 7.27.2 + '@babel/template': 7.28.6 '@babel/types': 7.29.0 debug: 4.4.3 globals: 11.12.0 @@ -9753,16 +9706,6 @@ snapshots: transitivePeerDependencies: - supports-color - '@babel/types@7.27.6': - dependencies: - '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.28.5 - - '@babel/types@7.28.0': - dependencies: - '@babel/helper-string-parser': 7.27.1 - '@babel/helper-validator-identifier': 7.27.1 - '@babel/types@7.29.0': dependencies: '@babel/helper-string-parser': 7.27.1 @@ -12773,8 +12716,8 @@ snapshots: '@types/babel__core@7.20.5': dependencies: - '@babel/parser': 7.28.0 - '@babel/types': 7.28.0 + '@babel/parser': 7.29.0 + '@babel/types': 7.29.0 '@types/babel__generator': 7.6.2 '@types/babel__template': 7.0.3 '@types/babel__traverse': 7.0.15 @@ -13780,7 +13723,7 @@ snapshots: babel-plugin-istanbul@7.0.1: dependencies: - '@babel/helper-plugin-utils': 7.27.1 + '@babel/helper-plugin-utils': 7.28.6 '@istanbuljs/load-nyc-config': 1.1.0 '@istanbuljs/schema': 0.1.3 istanbul-lib-instrument: 6.0.2 @@ -13913,15 +13856,7 @@ snapshots: browserslist-to-es-version@1.2.0: dependencies: - browserslist: 4.27.0 - - browserslist@4.27.0: - dependencies: - baseline-browser-mapping: 2.10.7 - caniuse-lite: 1.0.30001760 - electron-to-chromium: 1.5.245 - node-releases: 2.0.27 - update-browserslist-db: 1.1.4(browserslist@4.27.0) + browserslist: 4.28.2 browserslist@4.28.1: dependencies: @@ -14563,8 +14498,6 @@ snapshots: ee-first@1.1.1: {} - electron-to-chromium@1.5.245: {} - electron-to-chromium@1.5.313: {} electron-to-chromium@1.5.349: {} @@ -17953,7 +17886,7 @@ snapshots: parse-json@7.1.1: dependencies: - '@babel/code-frame': 7.27.1 + '@babel/code-frame': 7.29.0 error-ex: 1.3.2 json-parse-even-better-errors: 3.0.2 lines-and-columns: 2.0.4 @@ -19580,12 +19513,6 @@ snapshots: '@unrs/resolver-binding-win32-ia32-msvc': 1.7.13 '@unrs/resolver-binding-win32-x64-msvc': 1.7.13 - update-browserslist-db@1.1.4(browserslist@4.27.0): - dependencies: - browserslist: 4.27.0 - escalade: 3.2.0 - picocolors: 1.1.1 - update-browserslist-db@1.2.3(browserslist@4.28.1): dependencies: browserslist: 4.28.1 diff --git a/static/app/components/commandPalette/ui/collection.tsx b/static/app/components/commandPalette/ui/collection.tsx index a4105dec3f74..600817631fd5 100644 --- a/static/app/components/commandPalette/ui/collection.tsx +++ b/static/app/components/commandPalette/ui/collection.tsx @@ -135,7 +135,7 @@ export function makeCollection(): CollectionInstance { // bind so that this.tree() works correctly in recursive calls tree: store.tree.bind(store), }), - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps [snapshot, store] ); } diff --git a/static/app/components/commandPalette/useCommandPaletteAnalytics.tsx b/static/app/components/commandPalette/useCommandPaletteAnalytics.tsx index 4409476e2820..faa1585cf01d 100644 --- a/static/app/components/commandPalette/useCommandPaletteAnalytics.tsx +++ b/static/app/components/commandPalette/useCommandPaletteAnalytics.tsx @@ -127,7 +127,7 @@ export function useCommandPaletteAnalytics(filteredActionCount: number): { max_drill_depth: s.maxDrillDepth, }); }; - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); return useMemo( diff --git a/static/app/components/core/compactSelect/control.tsx b/static/app/components/core/compactSelect/control.tsx index 0091352c2eea..2e1a6ea9e594 100644 --- a/static/app/components/core/compactSelect/control.tsx +++ b/static/app/components/core/compactSelect/control.tsx @@ -387,7 +387,7 @@ export function Control({ } updateOverlay?.(); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [menuBody, hideOptions]); const wasRefAvailable = useRef(false); diff --git a/static/app/components/core/compactSelect/gridList/option.tsx b/static/app/components/core/compactSelect/gridList/option.tsx index 3cedc056b9cf..f477907c8a48 100644 --- a/static/app/components/core/compactSelect/gridList/option.tsx +++ b/static/app/components/core/compactSelect/gridList/option.tsx @@ -100,7 +100,7 @@ export function GridListOption({node, listState, size}: GridListOptionProps) { {leading ? {leading} : null} ); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [multiple, isSelected, isDisabled, isFocused, size, leadingItems, hideCheck]); return ( diff --git a/static/app/components/core/compactSelect/listBox/option.tsx b/static/app/components/core/compactSelect/listBox/option.tsx index 583faaec7bd2..7f3f24219621 100644 --- a/static/app/components/core/compactSelect/listBox/option.tsx +++ b/static/app/components/core/compactSelect/listBox/option.tsx @@ -62,7 +62,7 @@ export function ListBoxOption({ const labelPropsMemo = useMemo( () => ({...labelProps, as: typeof label === 'string' ? 'p' : 'div'}) as const, - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps [labelProps.id, label] ); diff --git a/static/app/components/core/tabs/tabList.tsx b/static/app/components/core/tabs/tabList.tsx index e70364b91067..7cb14c43baf3 100644 --- a/static/app/components/core/tabs/tabList.tsx +++ b/static/app/components/core/tabs/tabList.tsx @@ -229,7 +229,7 @@ function BaseTabList({outerWrapStyles, variant = 'flat', ...props}: BaseTabListP const {tabListProps} = useTabList({orientation, ...ariaProps}, state, tabListRef); useEffect(() => { setTabListState(state); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [state.disabledKeys, state.selectedItem, state.selectedKey, props.children]); // Detect tabs that overflow from the wrapper and put them in an overflow menu diff --git a/static/app/components/events/interfaces/threads.tsx b/static/app/components/events/interfaces/threads.tsx index 8a50b30e458d..50ad6afec62a 100644 --- a/static/app/components/events/interfaces/threads.tsx +++ b/static/app/components/events/interfaces/threads.tsx @@ -101,7 +101,7 @@ const useActiveThreadState = ( useEffect(() => { setActiveThread(bestThread); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [event.id]); return [activeThread, setActiveThread]; diff --git a/static/app/components/events/rrwebReplayer/index.tsx b/static/app/components/events/rrwebReplayer/index.tsx index 1a4a7a745ffb..ef8c11a1b0c1 100644 --- a/static/app/components/events/rrwebReplayer/index.tsx +++ b/static/app/components/events/rrwebReplayer/index.tsx @@ -46,7 +46,7 @@ function RRWebReplayer({urls}: Props) { } }; - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps useEffect(() => void loadEvents(), [urls]); return ; diff --git a/static/app/components/exports/dataExport.tsx b/static/app/components/exports/dataExport.tsx index 9cd3da303d79..a94bfb1a154a 100644 --- a/static/app/components/exports/dataExport.tsx +++ b/static/app/components/exports/dataExport.tsx @@ -58,7 +58,7 @@ export function DataExport({ // call and would have immediately turned off the value giving users no feedback on their click action. // An alternative way to handle this would have probably been to key the component by payload/queryType, // but that seems like it can be a complex object so tracking changes could result in very brittle behavior. - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [payload.queryType, payload.queryInfo]); // Tracking unmounting of the component to prevent setState call on unmounted component diff --git a/static/app/components/externalIssues/externalIssueForm.tsx b/static/app/components/externalIssues/externalIssueForm.tsx index 615ebb874599..8ace9617a19c 100644 --- a/static/app/components/externalIssues/externalIssueForm.tsx +++ b/static/app/components/externalIssues/externalIssueForm.tsx @@ -231,7 +231,7 @@ export function ExternalIssueForm({ return () => { span?.end(); }; - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); // End the span for the load request diff --git a/static/app/components/forms/controls/rangeSlider/index.tsx b/static/app/components/forms/controls/rangeSlider/index.tsx index 1329be916f35..0a7b72f8a5e2 100644 --- a/static/app/components/forms/controls/rangeSlider/index.tsx +++ b/static/app/components/forms/controls/rangeSlider/index.tsx @@ -106,7 +106,7 @@ export function RangeSlider({ useEffect(() => { updateSliderValue(); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [value]); function updateSliderValue() { diff --git a/static/app/components/forms/jsonForm.tsx b/static/app/components/forms/jsonForm.tsx index 43c18a1f38ce..d067d35e5295 100644 --- a/static/app/components/forms/jsonForm.tsx +++ b/static/app/components/forms/jsonForm.tsx @@ -93,7 +93,7 @@ function JsonForm({ useEffect(() => { const hash = location?.hash; scrollToHash(hash); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [location?.hash]); const shouldDisplayForm = (fieldList: FieldObject[]): boolean => { diff --git a/static/app/components/modals/dataWidgetViewerModal.tsx b/static/app/components/modals/dataWidgetViewerModal.tsx index b96490e26796..cf78cb8eb705 100644 --- a/static/app/components/modals/dataWidgetViewerModal.tsx +++ b/static/app/components/modals/dataWidgetViewerModal.tsx @@ -461,7 +461,7 @@ function DataWidgetViewerModal(props: Props) { getDiscoverTotals(); // Disabling this for now since this effect should only run on initial load and query index changes // Including all exhaustive deps would cause fetchDiscoverTotal on nearly every update - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [selectedQueryIndex]); function onLegendSelectChanged({selected}: {selected: Record}) { diff --git a/static/app/components/onboarding/gettingStartedDoc/onboardingLayout.tsx b/static/app/components/onboarding/gettingStartedDoc/onboardingLayout.tsx index a6469de88461..313f6e03edf7 100644 --- a/static/app/components/onboarding/gettingStartedDoc/onboardingLayout.tsx +++ b/static/app/components/onboarding/gettingStartedDoc/onboardingLayout.tsx @@ -170,7 +170,7 @@ export function OnboardingLayout({ useEffect(() => { onPageLoad?.(); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); const handleProductSelectionChange = useCallback( diff --git a/static/app/components/pageFilters/container.tsx b/static/app/components/pageFilters/container.tsx index 2b1d73b87cc3..ec931ceb81b3 100644 --- a/static/app/components/pageFilters/container.tsx +++ b/static/app/components/pageFilters/container.tsx @@ -129,7 +129,7 @@ export function PageFiltersContainer({ } doInitialization(); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [projectsLoaded]); // Handle dynamic maxPickableDays changes (e.g., switching between pages with different limits). @@ -243,7 +243,7 @@ export function PageFiltersContainer({ } lastQuery.current = location.query; - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [location.query]); // Wait for global selection to be ready before rendering children diff --git a/static/app/components/performance/searchBar.tsx b/static/app/components/performance/searchBar.tsx index 19c6db2a2682..dced36f57812 100644 --- a/static/app/components/performance/searchBar.tsx +++ b/static/app/components/performance/searchBar.tsx @@ -136,7 +136,7 @@ export function SearchBar(props: SearchBarProps) { } }; - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps const getSuggestedTransactions = useCallback( debounce( async query => { diff --git a/static/app/components/performance/teamKeyTransactionsManager.tsx b/static/app/components/performance/teamKeyTransactionsManager.tsx index f288dfb52078..37e815af1e4d 100644 --- a/static/app/components/performance/teamKeyTransactionsManager.tsx +++ b/static/app/components/performance/teamKeyTransactionsManager.tsx @@ -99,7 +99,7 @@ export function Provider({ // This component receives referentially new selectedTeams and selectedProjects // on many renders. Ideally fetchTeamKeyTransactions should be refactored to use // `useApiQuery` or `useMutation` with `fetchDataQuery` and `fetchMutation`. - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [api, organization.slug, refetchKey]); useEffect(() => { diff --git a/static/app/components/profiling/flamegraph/continuousFlamegraph.tsx b/static/app/components/profiling/flamegraph/continuousFlamegraph.tsx index df0a54ec5147..00a704625857 100644 --- a/static/app/components/profiling/flamegraph/continuousFlamegraph.tsx +++ b/static/app/components/profiling/flamegraph/continuousFlamegraph.tsx @@ -683,7 +683,7 @@ export function ContinuousFlamegraph(): ReactElement { }, // We skip position.view dependency because it will go into an infinite loop - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps [flamegraph, flamegraphCanvas, flamegraphTheme, profile, configSpaceQueryParam] ); diff --git a/static/app/components/profiling/flamegraph/flamegraph.tsx b/static/app/components/profiling/flamegraph/flamegraph.tsx index 1aa6b6e08cc7..b5d3b85d17cf 100644 --- a/static/app/components/profiling/flamegraph/flamegraph.tsx +++ b/static/app/components/profiling/flamegraph/flamegraph.tsx @@ -651,7 +651,7 @@ function Flamegraph(): ReactElement { }, // We skip position.view dependency because it will go into an infinite loop - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps [flamegraph, flamegraphCanvas, flamegraphTheme, profileOffsetFromTransaction] ); diff --git a/static/app/components/profiling/flamegraph/flamegraphToolbar/flamegraphSearch.tsx b/static/app/components/profiling/flamegraph/flamegraphToolbar/flamegraphSearch.tsx index 13d238d3496a..2f3febac29c6 100644 --- a/static/app/components/profiling/flamegraph/flamegraphToolbar/flamegraphSearch.tsx +++ b/static/app/components/profiling/flamegraph/flamegraphToolbar/flamegraphSearch.tsx @@ -369,7 +369,7 @@ function FlamegraphSearch({ handleChange(search.query); // Dont fire on query changes, we just want this to fire on initial load // as the spans and frames eventually get loaded into the view - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [handleChange, allFlamegraphFrames, spans]); const onNextSearchClick = useCallback(() => { diff --git a/static/app/components/resultGrid.tsx b/static/app/components/resultGrid.tsx index 1e937f2efc84..aaf96e62852b 100644 --- a/static/app/components/resultGrid.tsx +++ b/static/app/components/resultGrid.tsx @@ -242,7 +242,7 @@ export function ResultGrid(props: Props) { })); }, }); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [location, endpoint, method, defaultSort, JSON.stringify(defaultParams)]); const onSearch = (e: React.FormEvent) => { diff --git a/static/app/components/searchQueryBuilder/tokens/filter/useFrozenSuggestionSectionItems.ts b/static/app/components/searchQueryBuilder/tokens/filter/useFrozenSuggestionSectionItems.ts index 821f324a36e0..b195650e3f30 100644 --- a/static/app/components/searchQueryBuilder/tokens/filter/useFrozenSuggestionSectionItems.ts +++ b/static/app/components/searchQueryBuilder/tokens/filter/useFrozenSuggestionSectionItems.ts @@ -162,6 +162,6 @@ export function useFrozenSuggestionSectionItems({ }) ), })); - // eslint-disable-next-line react-hooks/exhaustive-deps -- frozenVersion forces recomputation when the render-time check resets frozenOrderRef + // eslint-disable-next-line @eslint-react/exhaustive-deps -- frozenVersion forces recomputation when the render-time check resets frozenOrderRef }, [createItem, suggestionGroups, frozenVersion]); } diff --git a/static/app/components/searchQueryBuilder/tokens/filter/valueCombobox.tsx b/static/app/components/searchQueryBuilder/tokens/filter/valueCombobox.tsx index 660c19633d2c..27c3c4e0881c 100644 --- a/static/app/components/searchQueryBuilder/tokens/filter/valueCombobox.tsx +++ b/static/app/components/searchQueryBuilder/tokens/filter/valueCombobox.tsx @@ -688,7 +688,7 @@ export function SearchQueryBuilderValueCombobox({ setSelectionIndex(newInputValue.length); } // We want to avoid resetting the input value if the token text doesn't actually change - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [canSelectMultipleValues, token.text]); // On mount, scroll to the end of the input diff --git a/static/app/utils/list/useListItemCheckboxState.tsx b/static/app/utils/list/useListItemCheckboxState.tsx index a99f1529e51b..001694b59f8a 100644 --- a/static/app/utils/list/useListItemCheckboxState.tsx +++ b/static/app/utils/list/useListItemCheckboxState.tsx @@ -148,7 +148,7 @@ export function ListItemCheckboxProvider({ useEffect(() => { queryKeyRef.current = queryKey; setState({ids: new Set()}); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [serializedQueryKey]); return ( @@ -174,7 +174,7 @@ export function useListItemCheckboxContext(props?: PublicProps) { localQueryKeyRef.current = props.queryKey; setState({ids: new Set()}); } - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [serializedPropsKey]); return useListItemCheckboxState({ diff --git a/static/app/utils/profiling/flamegraph/flamegraphStateProvider/flamegraphQueryParamSync.tsx b/static/app/utils/profiling/flamegraph/flamegraphStateProvider/flamegraphQueryParamSync.tsx index eb4683852226..15342a0b9acf 100644 --- a/static/app/utils/profiling/flamegraph/flamegraphStateProvider/flamegraphQueryParamSync.tsx +++ b/static/app/utils/profiling/flamegraph/flamegraphStateProvider/flamegraphQueryParamSync.tsx @@ -187,7 +187,7 @@ export function FlamegraphStateQueryParamSync() { {replace: true} ); // We only want to sync the query params when the state changes - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [state]); return null; diff --git a/static/app/utils/replays/hooks/useReplayData.tsx b/static/app/utils/replays/hooks/useReplayData.tsx index 4e816ef76bf7..448d9f6d9dbd 100644 --- a/static/app/utils/replays/hooks/useReplayData.tsx +++ b/static/app/utils/replays/hooks/useReplayData.tsx @@ -327,7 +327,7 @@ export function useReplayData({ // the only thing we care about. const feedbackEvents = useMemo(() => { return rawFeedbackEvents; - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [rawFeedbackEvents?.length]); const allStatuses = [ diff --git a/static/app/utils/replays/playback/hooks/useReplayCurrentTime.tsx b/static/app/utils/replays/playback/hooks/useReplayCurrentTime.tsx index 21af0b533f53..689ea7795f9f 100644 --- a/static/app/utils/replays/playback/hooks/useReplayCurrentTime.tsx +++ b/static/app/utils/replays/playback/hooks/useReplayCurrentTime.tsx @@ -40,7 +40,7 @@ export function useReplayCurrentTime(props: Props) { () => ({ timeMs: () => replayers.at(0)?.getCurrentTime(), }), - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps [] ); } diff --git a/static/app/utils/routeAnalytics/useRouteAnalyticsParams.tsx b/static/app/utils/routeAnalytics/useRouteAnalyticsParams.tsx index 66c8a6eb0c1f..c1889a6c80cd 100644 --- a/static/app/utils/routeAnalytics/useRouteAnalyticsParams.tsx +++ b/static/app/utils/routeAnalytics/useRouteAnalyticsParams.tsx @@ -13,6 +13,6 @@ export function useRouteAnalyticsParams(params: Record) { setRouteAnalyticsParams(params); // use the object values and keys as dependencies to re-trigger rendering // if the underlying parameters change - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [jsonParams, previousUrl]); } diff --git a/static/app/utils/url/useLocationQuery.tsx b/static/app/utils/url/useLocationQuery.tsx index 3832d734c0b5..a37feec2b1d8 100644 --- a/static/app/utils/url/useLocationQuery.tsx +++ b/static/app/utils/url/useLocationQuery.tsx @@ -81,7 +81,7 @@ export function useLocationQuery< ...(forwardedFields as any), ...(locationFields as any), }), - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps [stringyForwardedFields, stringyLocationFields] ); } diff --git a/static/app/utils/useDispatchingReducer.tsx b/static/app/utils/useDispatchingReducer.tsx index be8e1f5b3f51..bacd71671da4 100644 --- a/static/app/utils/useDispatchingReducer.tsx +++ b/static/app/utils/useDispatchingReducer.tsx @@ -132,7 +132,7 @@ export function useDispatchingReducer>( }); }, // Emitter is stable and can be ignored - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps [] ); diff --git a/static/app/utils/useEffectAfterFirstRender.ts b/static/app/utils/useEffectAfterFirstRender.ts index 94284c02f8bf..a7051ccc089c 100644 --- a/static/app/utils/useEffectAfterFirstRender.ts +++ b/static/app/utils/useEffectAfterFirstRender.ts @@ -14,7 +14,7 @@ const useEffectAfterFirstRender = ( cb(); // Dependencies are explicitly managed and the deps warning is enabled for the custom hook. - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, deps); }; diff --git a/static/app/utils/useLocalStorageState.ts b/static/app/utils/useLocalStorageState.ts index 33709906b3d0..d1cc063a2e0e 100644 --- a/static/app/utils/useLocalStorageState.ts +++ b/static/app/utils/useLocalStorageState.ts @@ -117,7 +117,7 @@ export function useLocalStorageState( setValue(initializeStorage(key, initialState)); // We only want to update the value when the key changes - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [key]); const setStoredValue = useCallback( diff --git a/static/app/utils/useMemoWithPrevious.spec.tsx b/static/app/utils/useMemoWithPrevious.spec.tsx index f85aef4ddf1f..157083cae37e 100644 --- a/static/app/utils/useMemoWithPrevious.spec.tsx +++ b/static/app/utils/useMemoWithPrevious.spec.tsx @@ -21,7 +21,7 @@ describe('useMemoWithPrevious', () => { const secondDependency: unknown[] = []; const {rerender, result} = renderHook( - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps ({fact, dep}) => useMemoWithPrevious(fact, [dep]), { initialProps: { diff --git a/static/app/utils/useMemoWithPrevious.ts b/static/app/utils/useMemoWithPrevious.ts index 614a854f01d1..7d1bc2d39bb5 100644 --- a/static/app/utils/useMemoWithPrevious.ts +++ b/static/app/utils/useMemoWithPrevious.ts @@ -13,7 +13,7 @@ const useMemoWithPrevious = ( useEffectAfterFirstRender(() => { setValue(factory(previous)); // Dependencies are explicitly managed and the deps warning is enabled for the custom hook. - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, deps); return value; diff --git a/static/app/utils/useOwners.tsx b/static/app/utils/useOwners.tsx index 4ed69e3add91..784788e1f315 100644 --- a/static/app/utils/useOwners.tsx +++ b/static/app/utils/useOwners.tsx @@ -69,7 +69,7 @@ export function useOwners({currentValue}: Options) { loadMoreTeams(); }, // Only ensure things are loaded at mount - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps [] ); diff --git a/static/app/utils/useProjects.tsx b/static/app/utils/useProjects.tsx index 7bcdf2c97ae3..28f251be7b79 100644 --- a/static/app/utils/useProjects.tsx +++ b/static/app/utils/useProjects.tsx @@ -279,7 +279,7 @@ export function useProjects({limit, slugs, orgId: propOrgId}: Options = {}) { loadProjectsBySlug(); return; } - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [slugsRef.current]); // Update initiallyLoaded when we finish loading within the projectStore @@ -295,7 +295,7 @@ export function useProjects({limit, slugs, orgId: propOrgId}: Options = {}) { } setState(prev => ({...prev, initiallyLoaded: storeLoaded})); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [store.loading]); const {initiallyLoaded, fetching, fetchError, hasMore} = state; diff --git a/static/app/utils/useResizableDrawer.tsx b/static/app/utils/useResizableDrawer.tsx index 76176641a7ca..96f95b920d6e 100644 --- a/static/app/utils/useResizableDrawer.tsx +++ b/static/app/utils/useResizableDrawer.tsx @@ -88,7 +88,7 @@ export function useResizableDrawer(options: UseResizableDrawerOptions): { useLayoutEffect(() => { options.onResize(options.initialSize ?? 0, size, false); setSize(options.initialSize ?? 0); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [options.direction]); const sizeRef = useRef(size); diff --git a/static/app/utils/useSessionStorage.tsx b/static/app/utils/useSessionStorage.tsx index 2aadde457c5d..5853bc485f06 100644 --- a/static/app/utils/useSessionStorage.tsx +++ b/static/app/utils/useSessionStorage.tsx @@ -32,7 +32,7 @@ export function useSessionStorage( useEffect(() => { setState(readStorageValue(key, initialValue)); // We want to re-initialized the storage value only when the key changes. - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [key]); const wrappedSetState = useCallback( diff --git a/static/app/views/alerts/list/incidents/index.tsx b/static/app/views/alerts/list/incidents/index.tsx index af4d84bef2e0..306b6e7ebfb0 100644 --- a/static/app/views/alerts/list/incidents/index.tsx +++ b/static/app/views/alerts/list/incidents/index.tsx @@ -302,7 +302,7 @@ export default function IncidentsListContainer() { trackAnalytics('alert_stream.viewed', { organization, }); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); const renderDisabled = () => ( diff --git a/static/app/views/alerts/rules/issue/previewIssues.tsx b/static/app/views/alerts/rules/issue/previewIssues.tsx index 67fe3e18f4e3..15db6fff5a8c 100644 --- a/static/app/views/alerts/rules/issue/previewIssues.tsx +++ b/static/app/views/alerts/rules/issue/previewIssues.tsx @@ -145,7 +145,7 @@ export function PreviewIssues({members, rule, project}: PreviewIssuesProps) { useEffect(() => { debouncedFetchApiData(relevantRuleData, null, true); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [JSON.stringify(relevantRuleData), debouncedFetchApiData]); useEffect(() => { diff --git a/static/app/views/alerts/rules/issue/ruleNode.tsx b/static/app/views/alerts/rules/issue/ruleNode.tsx index f53b852227a9..3feea4a42bea 100644 --- a/static/app/views/alerts/rules/issue/ruleNode.tsx +++ b/static/app/views/alerts/rules/issue/ruleNode.tsx @@ -114,7 +114,7 @@ function InlineField({ onPropertyChange(index, name, String(placeholder)); } // Value omitted on purpose to avoid overwriting user changes - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [onPropertyChange, index, name, placeholder, data.id]); switch (field.type) { diff --git a/static/app/views/alerts/rules/metric/eapMetricsField.tsx b/static/app/views/alerts/rules/metric/eapMetricsField.tsx index f8945c4111f7..f5d6e5476ae0 100644 --- a/static/app/views/alerts/rules/metric/eapMetricsField.tsx +++ b/static/app/views/alerts/rules/metric/eapMetricsField.tsx @@ -135,7 +135,7 @@ export function EAPMetricsField({ ]; }, [metricOptionsData, optionFromTraceMetric, traceMetric.name, hasMetricUnitsUI]); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps const debouncedSetSearch = useCallback( debounce(newSearch => { setSearch(newSearch); diff --git a/static/app/views/alerts/rules/uptime/formErrors.spec.tsx b/static/app/views/alerts/rules/uptime/formErrors.spec.tsx index 44f4f39f491b..89c3c6f23c24 100644 --- a/static/app/views/alerts/rules/uptime/formErrors.spec.tsx +++ b/static/app/views/alerts/rules/uptime/formErrors.spec.tsx @@ -198,7 +198,7 @@ describe('AssertionFormError', () => { previewCheckResult?.setPreviewCheckData(initial.data ?? null); if ('error' in initial) previewCheckResult?.setPreviewCheckError(initial.error ?? null); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); return null; } diff --git a/static/app/views/dashboards/dashboard.tsx b/static/app/views/dashboards/dashboard.tsx index 1e24f7ee253b..ac1c815441aa 100644 --- a/static/app/views/dashboards/dashboard.tsx +++ b/static/app/views/dashboards/dashboard.tsx @@ -212,7 +212,7 @@ function DashboardInner({ window.removeEventListener('resize', debouncedHandleResize); window.clearTimeout(forceCheckTimeout.current); }; - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); // Handle newWidget parsed from Add to Dashboard flows diff --git a/static/app/views/dashboards/filtersBar.tsx b/static/app/views/dashboards/filtersBar.tsx index 1113d027ada2..b5b25d4641c0 100644 --- a/static/app/views/dashboards/filtersBar.tsx +++ b/static/app/views/dashboards/filtersBar.tsx @@ -228,7 +228,7 @@ export function FiltersBar({ [DashboardFilterKeys.GLOBAL_FILTER]: activeGlobalFilters, }); } - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); const updateGlobalFilters = (newGlobalFilters: GlobalFilter[]) => { diff --git a/static/app/views/dashboards/widgetBuilder/components/visualize/traceMetrics/metricsEquationVisualize/index.tsx b/static/app/views/dashboards/widgetBuilder/components/visualize/traceMetrics/metricsEquationVisualize/index.tsx index 4c0d1be5ef87..dd416757c2a9 100644 --- a/static/app/views/dashboards/widgetBuilder/components/visualize/traceMetrics/metricsEquationVisualize/index.tsx +++ b/static/app/views/dashboards/widgetBuilder/components/visualize/traceMetrics/metricsEquationVisualize/index.tsx @@ -71,7 +71,7 @@ export function MetricsEquationVisualize({ } metricQueries.push(defaultMetricQuery({type: 'equation'})); return metricQueries; - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); const [selectedLabel, setSelectedLabel] = useState(() => { diff --git a/static/app/views/dashboards/widgetBuilder/components/widgetBuilderSlideout.tsx b/static/app/views/dashboards/widgetBuilder/components/widgetBuilderSlideout.tsx index 54e1b8bded8a..6c87878d1849 100644 --- a/static/app/views/dashboards/widgetBuilder/components/widgetBuilderSlideout.tsx +++ b/static/app/views/dashboards/widgetBuilder/components/widgetBuilderSlideout.tsx @@ -162,7 +162,7 @@ function WidgetBuilderSlideoutInner({ // Ignore isEditing because it won't change during the // useful lifetime of the widget builder, but it // flickers when an edited widget is saved. - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [openWidgetTemplates, organization]); const title = openWidgetTemplates diff --git a/static/app/views/dashboards/widgetBuilder/components/widgetTemplatesList.tsx b/static/app/views/dashboards/widgetBuilder/components/widgetTemplatesList.tsx index fd115d5570cb..3e116e58b410 100644 --- a/static/app/views/dashboards/widgetBuilder/components/widgetTemplatesList.tsx +++ b/static/app/views/dashboards/widgetBuilder/components/widgetTemplatesList.tsx @@ -62,7 +62,7 @@ export function WidgetTemplatesList({ }); } } - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); useEffect(() => { @@ -70,7 +70,7 @@ export function WidgetTemplatesList({ organization, }); // We only want to track this once when the component is mounted - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); const handleSave = async (widget: Widget) => { diff --git a/static/app/views/dashboards/widgetBuilder/hooks/useIsEquationMode.tsx b/static/app/views/dashboards/widgetBuilder/hooks/useIsEquationMode.tsx index cf17adca8636..e72e41d67555 100644 --- a/static/app/views/dashboards/widgetBuilder/hooks/useIsEquationMode.tsx +++ b/static/app/views/dashboards/widgetBuilder/hooks/useIsEquationMode.tsx @@ -50,7 +50,7 @@ export function useIsEquationMode(): [boolean, (next: boolean) => void] { } // We only run this effect when the dataset changes to tracemetrics to // detect if we show the tracemetrics equations UI when restoring dataset state - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [state.dataset]); return [isEquationMode, setIsEquationMode]; diff --git a/static/app/views/dashboards/widgets/categoricalSeriesWidget/categoricalSeriesWidgetVisualization.tsx b/static/app/views/dashboards/widgets/categoricalSeriesWidget/categoricalSeriesWidgetVisualization.tsx index ebd0f8ae4c8b..172e2be3412e 100644 --- a/static/app/views/dashboards/widgets/categoricalSeriesWidget/categoricalSeriesWidgetVisualization.tsx +++ b/static/app/views/dashboards/widgets/categoricalSeriesWidget/categoricalSeriesWidgetVisualization.tsx @@ -159,7 +159,7 @@ export function CategoricalSeriesWidgetVisualization( truncationFormatter(trimmed[i]!, truncateLength, false), ]) ); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [allCategories.join(','), props.truncateCategoryLabels]); // Configure the X axis (category axis) diff --git a/static/app/views/detectors/components/forms/metric/metricsEquationVisualize.tsx b/static/app/views/detectors/components/forms/metric/metricsEquationVisualize.tsx index 6b7f3755c4a4..91769024a9f1 100644 --- a/static/app/views/detectors/components/forms/metric/metricsEquationVisualize.tsx +++ b/static/app/views/detectors/components/forms/metric/metricsEquationVisualize.tsx @@ -99,7 +99,7 @@ export function MetricsEquationVisualize({ return parsed.equationRow ? [...parsed.metricQueries, parsed.equationRow] : parsed.metricQueries; - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); return ( diff --git a/static/app/views/detectors/components/forms/metric/metricsVisualize.tsx b/static/app/views/detectors/components/forms/metric/metricsVisualize.tsx index ec34b68f434e..899fefb54210 100644 --- a/static/app/views/detectors/components/forms/metric/metricsVisualize.tsx +++ b/static/app/views/detectors/components/forms/metric/metricsVisualize.tsx @@ -139,7 +139,7 @@ export function MetricsVisualize() { ]; }, [metricOptionsData, optionFromTraceMetric, traceMetric.name, hasMetricUnitsUI]); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps const debouncedSetSearch = useCallback( debounce((newSearch: string) => { setSearch(newSearch); diff --git a/static/app/views/explore/logs/tables/logsInfiniteTable.tsx b/static/app/views/explore/logs/tables/logsInfiniteTable.tsx index 2a01f2662e58..a2f5589c89c7 100644 --- a/static/app/views/explore/logs/tables/logsInfiniteTable.tsx +++ b/static/app/views/explore/logs/tables/logsInfiniteTable.tsx @@ -258,7 +258,7 @@ export function LogsInfiniteTable({ terms.push(localOnlyItemFilters.filterText); } return terms; - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [searchString, localOnlyItemFilters?.filterText]); const isContainedVirtualizer = expanded !== undefined; diff --git a/static/app/views/explore/logs/useLogsAutoRefreshInterval.tsx b/static/app/views/explore/logs/useLogsAutoRefreshInterval.tsx index b1ee46d1a99e..057eabc0461f 100644 --- a/static/app/views/explore/logs/useLogsAutoRefreshInterval.tsx +++ b/static/app/views/explore/logs/useLogsAutoRefreshInterval.tsx @@ -164,6 +164,6 @@ export function useLogsAutoRefreshInterval({ return () => { resetTrackingState(); }; - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [autoRefresh, refreshInterval]); } diff --git a/static/app/views/explore/logs/useLogsQuery.tsx b/static/app/views/explore/logs/useLogsQuery.tsx index c077c4c0ed1a..f0cea3eade1a 100644 --- a/static/app/views/explore/logs/useLogsQuery.tsx +++ b/static/app/views/explore/logs/useLogsQuery.tsx @@ -649,7 +649,7 @@ export function useInfiniteLogsQuery({ {fields: {}, units: {}} ) ?? {fields: {}, units: {}} ); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [pageCount]); const _fetchPreviousPage = useCallback(() => { diff --git a/static/app/views/explore/profiling/continuousProfileFlamegraph.tsx b/static/app/views/explore/profiling/continuousProfileFlamegraph.tsx index 5ddbd119e261..4a61146d5db0 100644 --- a/static/app/views/explore/profiling/continuousProfileFlamegraph.tsx +++ b/static/app/views/explore/profiling/continuousProfileFlamegraph.tsx @@ -95,7 +95,7 @@ export default function ContinuousProfileFlamegraphWrapper() { }, }; // We only want to decode this when our component mounts - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); return ( diff --git a/static/app/views/explore/profiling/profileFlamechart.tsx b/static/app/views/explore/profiling/profileFlamechart.tsx index ccd290da263c..f41ce239a0a6 100644 --- a/static/app/views/explore/profiling/profileFlamechart.tsx +++ b/static/app/views/explore/profiling/profileFlamechart.tsx @@ -98,7 +98,7 @@ export default function ProfileFlamegraphWrapper() { }, }; // We only want to decode this when our component mounts - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); return ( diff --git a/static/app/views/explore/releases/list/releasesPromo.tsx b/static/app/views/explore/releases/list/releasesPromo.tsx index 75b881190ffa..7127110f8e5c 100644 --- a/static/app/views/explore/releases/list/releasesPromo.tsx +++ b/static/app/views/explore/releases/list/releasesPromo.tsx @@ -129,7 +129,7 @@ export function ReleasesPromo({organization, project}: Props) { organization, project_id: project.id, }); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); const getMarkdown = useCallback(() => { diff --git a/static/app/views/explore/replays/detail/layout/splitPanel.tsx b/static/app/views/explore/replays/detail/layout/splitPanel.tsx index ae4bcf4027a9..6dbeb9101be4 100644 --- a/static/app/views/explore/replays/detail/layout/splitPanel.tsx +++ b/static/app/views/explore/replays/detail/layout/splitPanel.tsx @@ -26,7 +26,7 @@ export function ReplaySplitPanel({ }, }); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps const handleResize = useCallback( debounce(newSize => logEndPosition(`${(newSize / availableSize) * 100}%`), 750), [logEndPosition, availableSize] diff --git a/static/app/views/feedback/feedbackEmptyState.tsx b/static/app/views/feedback/feedbackEmptyState.tsx index d9301bd3266a..b644c128a410 100644 --- a/static/app/views/feedback/feedbackEmptyState.tsx +++ b/static/app/views/feedback/feedbackEmptyState.tsx @@ -48,7 +48,7 @@ export function FeedbackEmptyState({projectIds, issueTab = false}: Props) { if (issueTab) { setProjId(); } - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); useEffect(() => { diff --git a/static/app/views/insights/common/components/agentSelector.tsx b/static/app/views/insights/common/components/agentSelector.tsx index 82f82308aac9..24dc5d082007 100644 --- a/static/app/views/insights/common/components/agentSelector.tsx +++ b/static/app/views/insights/common/components/agentSelector.tsx @@ -59,7 +59,7 @@ export function AgentSelector({storageKeyPrefix, referrer}: AgentSelectorProps) setQueryStates({[AGENT_URL_PARAM]: storedAgents}); } } - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); // Reset when project changes @@ -81,7 +81,7 @@ export function AgentSelector({storageKeyPrefix, referrer}: AgentSelectorProps) const [searchQuery, setSearchQuery] = useState(''); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps const debouncedSetSearch = useCallback( debounce(newSearch => { setSearchQuery(newSearch); diff --git a/static/app/views/insights/common/components/spanDescription.tsx b/static/app/views/insights/common/components/spanDescription.tsx index 68829d4dd607..258222a28169 100644 --- a/static/app/views/insights/common/components/spanDescription.tsx +++ b/static/app/views/insights/common/components/spanDescription.tsx @@ -106,7 +106,7 @@ export function DatabaseSpanDescription({ ); // Skip the `location` dependency because it will cause this effect to trigger infinitely, since // `navigate` will update the location within this effect - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [navigate]); const system = indexedSpan?.['db.system']; diff --git a/static/app/views/insights/pages/agents/components/drawer.tsx b/static/app/views/insights/pages/agents/components/drawer.tsx index 19485618879c..54ba5cc7eef0 100644 --- a/static/app/views/insights/pages/agents/components/drawer.tsx +++ b/static/app/views/insights/pages/agents/components/drawer.tsx @@ -141,7 +141,7 @@ export function useTraceViewDrawer({onClose}: UseTraceViewDrawerProps = {}) { drawerUrlState.timestamp ?? undefined ); } - // eslint-disable-next-line react-hooks/exhaustive-deps -- only run on mount + // eslint-disable-next-line @eslint-react/exhaustive-deps -- only run on mount }, []); return { diff --git a/static/app/views/issueDetails/groupMerged/mergedItem.tsx b/static/app/views/issueDetails/groupMerged/mergedItem.tsx index c968ccb83592..c7609bc6cbad 100644 --- a/static/app/views/issueDetails/groupMerged/mergedItem.tsx +++ b/static/app/views/issueDetails/groupMerged/mergedItem.tsx @@ -90,7 +90,7 @@ export function MergedItem({fingerprint, totalFingerprint}: Props) { return () => { teardown(); }; - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); const {latestEvent, id, label} = fingerprint; diff --git a/static/app/views/issueDetails/groupReplays/groupReplays.tsx b/static/app/views/issueDetails/groupReplays/groupReplays.tsx index 55385ac3e894..4e035a350f7e 100644 --- a/static/app/views/issueDetails/groupReplays/groupReplays.tsx +++ b/static/app/views/issueDetails/groupReplays/groupReplays.tsx @@ -107,7 +107,7 @@ function GroupReplaysContent({group}: Props) { organization, }); // we only want to fire this event once - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); const {getReplayCountForIssue} = useReplayCountForIssues({ diff --git a/static/app/views/issueList/overview.tsx b/static/app/views/issueList/overview.tsx index 7a61f80a062e..b052f5ccd7e6 100644 --- a/static/app/views/issueList/overview.tsx +++ b/static/app/views/issueList/overview.tsx @@ -174,7 +174,7 @@ function IssueListOverviewInner({ if (!isEqual(groupIds, storeGroupIds)) { setGroupIds(storeGroupIds); } - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [groups]); useIssuesINPObserver(); @@ -544,7 +544,7 @@ function IssueListOverviewInner({ // request will be repeated in componentDidUpdate fetchData(); } - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); const previousSelection = usePrevious(selection); diff --git a/static/app/views/performance/landing/widgets/components/performanceWidget.tsx b/static/app/views/performance/landing/widgets/components/performanceWidget.tsx index 9194f4e04e39..0b9247875777 100644 --- a/static/app/views/performance/landing/widgets/components/performanceWidget.tsx +++ b/static/app/views/performance/landing/widgets/components/performanceWidget.tsx @@ -43,7 +43,7 @@ export function GenericPerformanceWidget( widgetDataRef.current = newWidgetData; setWidgetData({[props.chartSetting]: newWidgetData}); }, - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps [allWidgetData, setWidgetData] ); const removeWidgetDataForKey = useCallback( @@ -54,7 +54,7 @@ export function GenericPerformanceWidget( widgetDataRef.current = newWidgetData; setWidgetData({[props.chartSetting]: newWidgetData}); }, - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps [allWidgetData, setWidgetData] ); const widgetProps = {widgetData, setWidgetDataForKey, removeWidgetDataForKey}; diff --git a/static/app/views/performance/landing/widgets/components/queryHandler.tsx b/static/app/views/performance/landing/widgets/components/queryHandler.tsx index adf013402706..a1f7dfa38383 100644 --- a/static/app/views/performance/landing/widgets/components/queryHandler.tsx +++ b/static/app/views/performance/landing/widgets/components/queryHandler.tsx @@ -59,7 +59,7 @@ function SingleQueryHandler( // Destroy previous data on unmount, in case enabled value changes and unmounts the query component. props.removeWidgetDataForKey(query.queryKey); }, - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps [] ); @@ -110,7 +110,7 @@ function QueryResultSaver( ); mepContext.setIsMetricsData(isMetricsData); props.setWidgetDataForKey(query.queryKey, transformed); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [transformed?.hasData, transformed?.isLoading, transformed?.isErrored]); return ; } diff --git a/static/app/views/performance/landing/widgets/widgets/histogramWidget.tsx b/static/app/views/performance/landing/widgets/widgets/histogramWidget.tsx index 18dbff9d533a..d16d4a7e53d1 100644 --- a/static/app/views/performance/landing/widgets/widgets/histogramWidget.tsx +++ b/static/app/views/performance/landing/widgets/widgets/histogramWidget.tsx @@ -46,7 +46,7 @@ export function HistogramWidget(props: PerformanceWidgetProps) { transform: transformHistogramQuery, }, }; - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [props.chartSetting, mepSetting.memoizationKey, location]); const onFilterChange = () => {}; diff --git a/static/app/views/performance/landing/widgets/widgets/lineChartListWidget.tsx b/static/app/views/performance/landing/widgets/widgets/lineChartListWidget.tsx index 9cdf00876f63..fc5354d72094 100644 --- a/static/app/views/performance/landing/widgets/widgets/lineChartListWidget.tsx +++ b/static/app/views/performance/landing/widgets/widgets/lineChartListWidget.tsx @@ -345,7 +345,7 @@ export function LineChartListWidget(props: PerformanceWidgetProps) { }, transform: transformDiscoverToList, }), - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps [props.chartSetting, mepSetting.memoizationKey] ); @@ -527,7 +527,7 @@ export function LineChartListWidget(props: PerformanceWidgetProps) { transform: transformEventsRequestToArea, }; }, - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps [props.chartSetting, selectedListIndex, mepSetting.memoizationKey] ); diff --git a/static/app/views/performance/landing/widgets/widgets/mobileReleaseComparisonListWidget.tsx b/static/app/views/performance/landing/widgets/widgets/mobileReleaseComparisonListWidget.tsx index 472daa2b515b..5b1285ea6cdf 100644 --- a/static/app/views/performance/landing/widgets/widgets/mobileReleaseComparisonListWidget.tsx +++ b/static/app/views/performance/landing/widgets/widgets/mobileReleaseComparisonListWidget.tsx @@ -171,7 +171,7 @@ export function MobileReleaseComparisonListWidget(props: PerformanceWidgetProps) }, transform: transformDiscoverToList, }), - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps [props.chartSetting, mepSetting.memoizationKey, primaryRelease] ); @@ -244,7 +244,7 @@ export function MobileReleaseComparisonListWidget(props: PerformanceWidgetProps) transform: transformEventsChartRequest, }; }, - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps [props.chartSetting, selectedListIndex, mepSetting.memoizationKey, primaryRelease] ); diff --git a/static/app/views/performance/landing/widgets/widgets/singleFieldAreaWidget.tsx b/static/app/views/performance/landing/widgets/widgets/singleFieldAreaWidget.tsx index ed66c80958d5..b15d26f40aaf 100644 --- a/static/app/views/performance/landing/widgets/widgets/singleFieldAreaWidget.tsx +++ b/static/app/views/performance/landing/widgets/widgets/singleFieldAreaWidget.tsx @@ -83,7 +83,7 @@ export function SingleFieldAreaWidget(props: PerformanceWidgetProps) { ), transform: transformEventsRequestToArea, }), - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps [props.chartSetting, mepSetting.memoizationKey] ); @@ -108,7 +108,7 @@ export function SingleFieldAreaWidget(props: PerformanceWidgetProps) { }, transform: transformDiscoverToSingleValue, }), - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps [props.chartSetting, mepSetting.memoizationKey] ); diff --git a/static/app/views/performance/landing/widgets/widgets/stackedAreaChartListWidget.tsx b/static/app/views/performance/landing/widgets/widgets/stackedAreaChartListWidget.tsx index 1f7190d7ff11..1e6921601f40 100644 --- a/static/app/views/performance/landing/widgets/widgets/stackedAreaChartListWidget.tsx +++ b/static/app/views/performance/landing/widgets/widgets/stackedAreaChartListWidget.tsx @@ -115,7 +115,7 @@ export function StackedAreaChartListWidget(props: PerformanceWidgetProps) { }, transform: transformDiscoverToList, }), - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps [props.chartSetting, mepSetting.memoizationKey] ); @@ -178,7 +178,7 @@ export function StackedAreaChartListWidget(props: PerformanceWidgetProps) { transform: transformEventsRequestToStackedArea, }; }, - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps [props.chartSetting, selectedListIndex, mepSetting.memoizationKey] ); diff --git a/static/app/views/performance/landing/widgets/widgets/trendsWidget.tsx b/static/app/views/performance/landing/widgets/widgets/trendsWidget.tsx index 17a7b558add1..129f663d4919 100644 --- a/static/app/views/performance/landing/widgets/widgets/trendsWidget.tsx +++ b/static/app/views/performance/landing/widgets/widgets/trendsWidget.tsx @@ -107,7 +107,7 @@ export function TrendsWidget(props: PerformanceWidgetProps) { ), transform: transformTrendsDiscover, }), - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps [props.chartSetting, derivedTrendChangeType] ); diff --git a/static/app/views/performance/newTraceDetails/trace.tsx b/static/app/views/performance/newTraceDetails/trace.tsx index 1bff1bcfe916..16f3e9b5a7fb 100644 --- a/static/app/views/performance/newTraceDetails/trace.tsx +++ b/static/app/views/performance/newTraceDetails/trace.tsx @@ -314,7 +314,7 @@ export function Trace({ ); }, // we add forceRerender as a "unnecessary" dependency to trigger the virtualized list rerender - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps [ onNodeExpand, onNodeZoomIn, diff --git a/static/app/views/performance/newTraceDetails/traceApi/useIssuesTraceTree.tsx b/static/app/views/performance/newTraceDetails/traceApi/useIssuesTraceTree.tsx index 737075c073e4..b805472a1de0 100644 --- a/static/app/views/performance/newTraceDetails/traceApi/useIssuesTraceTree.tsx +++ b/static/app/views/performance/newTraceDetails/traceApi/useIssuesTraceTree.tsx @@ -93,7 +93,7 @@ export function useIssuesTraceTree({ return; } - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [api, organization, projects, replay, trace.status, trace.data, traceSlug]); return tree; diff --git a/static/app/views/performance/newTraceDetails/traceApi/useTrace.tsx b/static/app/views/performance/newTraceDetails/traceApi/useTrace.tsx index f8933a449d7e..987c7e6af79f 100644 --- a/static/app/views/performance/newTraceDetails/traceApi/useTrace.tsx +++ b/static/app/views/performance/newTraceDetails/traceApi/useTrace.tsx @@ -260,7 +260,7 @@ export function useTrace(options: UseTraceOptions): TraceQueryResult { // Only re-run this if the view query param changes, otherwise if we pass location.search // as a dependency, the query will re-run every time we perform actions on the trace view; like // clicking on a span, that updates the url. - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [ options.limit, options.timestamp, diff --git a/static/app/views/performance/newTraceDetails/traceApi/useTraceTree.tsx b/static/app/views/performance/newTraceDetails/traceApi/useTraceTree.tsx index 5a281139fb69..c7ffbbf9e543 100644 --- a/static/app/views/performance/newTraceDetails/traceApi/useTraceTree.tsx +++ b/static/app/views/performance/newTraceDetails/traceApi/useTraceTree.tsx @@ -74,7 +74,7 @@ export function useTraceTree({trace, replay, traceSlug}: UseTraceTreeParams): Tr return; } - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [api, organization, projects, replay, trace.status, trace.data, traceSlug]); return tree; diff --git a/static/app/views/performance/newTraceDetails/traceDrawer/traceDrawer.tsx b/static/app/views/performance/newTraceDetails/traceDrawer/traceDrawer.tsx index c37aae3c9b39..e1eaffa26464 100644 --- a/static/app/views/performance/newTraceDetails/traceDrawer/traceDrawer.tsx +++ b/static/app/views/performance/newTraceDetails/traceDrawer/traceDrawer.tsx @@ -181,7 +181,7 @@ export function TraceDrawer(props: TraceDrawerProps) { initialSize, ref: drawerRef, }; - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [props.traceGridRef, traceState.preferences.layout, drawerRef, isDrawerMinimized]); const resizableDrawerOptions: UsePassiveResizableDrawerOptions = useMemo(() => { @@ -301,7 +301,7 @@ export function TraceDrawer(props: TraceDrawerProps) { } initializedRef.current = true; } - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [props.traceGridRef, minimizedBottomDrawerSize]); // Syncs the height of the tabs with the trace indicators diff --git a/static/app/views/performance/newTraceDetails/traceDrawer/usePassiveResizeableDrawer.tsx b/static/app/views/performance/newTraceDetails/traceDrawer/usePassiveResizeableDrawer.tsx index aa6e1d772c58..583aa91be379 100644 --- a/static/app/views/performance/newTraceDetails/traceDrawer/usePassiveResizeableDrawer.tsx +++ b/static/app/views/performance/newTraceDetails/traceDrawer/usePassiveResizeableDrawer.tsx @@ -29,7 +29,7 @@ export function usePassiveResizableDrawer(options: UsePassiveResizableDrawerOpti useLayoutEffect(() => { sizeRef.current = initialSize; onResize(initialSize, options.min, false); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [initialSize, direction, onResize]); const onMouseMove = useCallback( diff --git a/static/app/views/performance/newTraceDetails/traceWaterfall.tsx b/static/app/views/performance/newTraceDetails/traceWaterfall.tsx index 60f7eeb4036c..5a0e98e4114f 100644 --- a/static/app/views/performance/newTraceDetails/traceWaterfall.tsx +++ b/static/app/views/performance/newTraceDetails/traceWaterfall.tsx @@ -149,7 +149,7 @@ export function TraceWaterfall(props: TraceWaterfallProps) { }); return () => cleanup(); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [props.tree, props.replayTraces]); // Initialize the tabs reducer when the tree initializes @@ -175,7 +175,7 @@ export function TraceWaterfall(props: TraceWaterfallProps) { }, }); // We only want to update the tabs when the tree changes - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [props.tree]); const searchingRaf = useRef<{id: number | null} | null>(null); diff --git a/static/app/views/performance/newTraceDetails/useTraceWaterfallModels.tsx b/static/app/views/performance/newTraceDetails/useTraceWaterfallModels.tsx index b07d2de7d359..43b5564f30cd 100644 --- a/static/app/views/performance/newTraceDetails/useTraceWaterfallModels.tsx +++ b/static/app/views/performance/newTraceDetails/useTraceWaterfallModels.tsx @@ -24,7 +24,7 @@ export function useTraceWaterfallModels() { theme ); // We only care about initial state when we initialize the view manager - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); return {traceView, traceScheduler, viewManager}; diff --git a/static/app/views/permissionDenied.tsx b/static/app/views/permissionDenied.tsx index 2513aa3c186d..cbe3bd390162 100644 --- a/static/app/views/permissionDenied.tsx +++ b/static/app/views/permissionDenied.tsx @@ -21,7 +21,7 @@ export function PermissionDenied() { message: `${ERROR_NAME}${route ? ` : ${route}` : ''}`, level: 'error', }); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); return ( diff --git a/static/app/views/relocation/relocation.tsx b/static/app/views/relocation/relocation.tsx index 5976ed56c76a..0644657a089f 100644 --- a/static/app/views/relocation/relocation.tsx +++ b/static/app/views/relocation/relocation.tsx @@ -145,7 +145,7 @@ export function RelocationOnboarding() { }, [api, navigate, regions, relocationState, stepId]); useEffect(() => { fetchExistingRelocation(); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); const fetchPublicKeys = useCallback(() => { @@ -173,7 +173,7 @@ export function RelocationOnboarding() { }, [api, regions]); useEffect(() => { fetchPublicKeys(); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); // Called onExitComplete diff --git a/static/app/views/routeError.tsx b/static/app/views/routeError.tsx index 04f5d3200bde..80d2c9814998 100644 --- a/static/app/views/routeError.tsx +++ b/static/app/views/routeError.tsx @@ -83,7 +83,7 @@ export function RouteError({error, disableLogSentry, disableReport}: RouteErrorP return function cleanup() { window.clearTimeout(reportDialogTimeout); }; - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [error, disableLogSentry]); // Remove the report dialog on unmount diff --git a/static/app/views/settings/dynamicSampling/projectSampling.tsx b/static/app/views/settings/dynamicSampling/projectSampling.tsx index fe83a6997ae8..ae0d40324882 100644 --- a/static/app/views/settings/dynamicSampling/projectSampling.tsx +++ b/static/app/views/settings/dynamicSampling/projectSampling.tsx @@ -101,7 +101,7 @@ export function ProjectSampling() { useEffect(() => { form.reset({projectRates}); setSavedProjectRates(projectRates); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [projectRates]); const initialTargetRate = useMemo(() => { diff --git a/static/app/views/settings/organizationIntegrations/integrationServerlessFunctions.tsx b/static/app/views/settings/organizationIntegrations/integrationServerlessFunctions.tsx index e095b87d9bdf..5a9ebd0fbc3d 100644 --- a/static/app/views/settings/organizationIntegrations/integrationServerlessFunctions.tsx +++ b/static/app/views/settings/organizationIntegrations/integrationServerlessFunctions.tsx @@ -47,7 +47,7 @@ export function IntegrationServerlessFunctions({ organization, }); } - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [isSuccess]); return ( diff --git a/static/app/views/settings/project/tempest/PlayStationSettings.tsx b/static/app/views/settings/project/tempest/PlayStationSettings.tsx index 1d17ba7ab6eb..a6e07cb0eca6 100644 --- a/static/app/views/settings/project/tempest/PlayStationSettings.tsx +++ b/static/app/views/settings/project/tempest/PlayStationSettings.tsx @@ -85,7 +85,7 @@ export function PlayStationSettings({organization, project}: Props) { error_count: credentialErrors.length, }); } - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [credentialErrors]); const isSetupInstructionsOpen = location.query.setupInstructions === 'true'; diff --git a/static/gsAdmin/components/extendProductTrialAction.tsx b/static/gsAdmin/components/extendProductTrialAction.tsx index 092308380d6a..4ae4d43e5400 100644 --- a/static/gsAdmin/components/extendProductTrialAction.tsx +++ b/static/gsAdmin/components/extendProductTrialAction.tsx @@ -44,7 +44,7 @@ export function ExtendProductTrialAction({ }); }); // Only set up the callback once on mount, using ref for latest value - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); const handleDaysChange = (value: string) => { diff --git a/static/gsApp/hooks/useRouteActivatedHook.tsx b/static/gsApp/hooks/useRouteActivatedHook.tsx index bd854fcb5315..2b42f6c92980 100644 --- a/static/gsApp/hooks/useRouteActivatedHook.tsx +++ b/static/gsApp/hooks/useRouteActivatedHook.tsx @@ -97,7 +97,7 @@ export function useRouteActivatedHook({location, matches}: Props) { setEventName(undefined); setMountTime(Date.now()); // this hook should only fire when the route changes and nothing else - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [currentRoute]); // This hook is in charge of sending analytics after DELAY_TIME_MS has passed diff --git a/static/gsApp/views/amCheckout/components/cart.tsx b/static/gsApp/views/amCheckout/components/cart.tsx index 50aa52156fc3..c98edfa61ed3 100644 --- a/static/gsApp/views/amCheckout/components/cart.tsx +++ b/static/gsApp/views/amCheckout/components/cart.tsx @@ -848,7 +848,7 @@ export function Cart({ }, // NOTE: We add `billingDetails` to the dependencies since it affects tax calculations // on the preview endpoint - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps [ api, formDataForPreview, diff --git a/tests/js/setup.ts b/tests/js/setup.ts index 77a32989090d..704b4b0e878d 100644 --- a/tests/js/setup.ts +++ b/tests/js/setup.ts @@ -122,7 +122,7 @@ jest.mock('@stripe/react-stripe-js', () => { // Use setTimeout to allow initial render assertions to run setTimeout(() => onReady(), 0); } - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); return null; }), @@ -139,7 +139,7 @@ jest.mock('@stripe/react-stripe-js', () => { onChange({complete: true}); } }, 0); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); return null; }), From 8879849b78a9749ac70423adfd312f09d44e4ac7 Mon Sep 17 00:00:00 2001 From: Ryan Albrecht Date: Fri, 15 May 2026 15:32:07 -0700 Subject: [PATCH 3/3] disable some react/* rules in favor of @eslint-react/* --- eslint.config.ts | 48 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 38 insertions(+), 10 deletions(-) diff --git a/eslint.config.ts b/eslint.config.ts index 221c0a9d6bfb..4d51686b794b 100644 --- a/eslint.config.ts +++ b/eslint.config.ts @@ -554,8 +554,8 @@ export default typescript.config([ 'react/jsx-boolean-value': ['error', 'never'], 'react/jsx-fragments': ['error', 'element'], 'react/jsx-handler-names': 'off', // TODO(ryan953): Fix violations and enable this rule - 'react/no-did-mount-set-state': 'error', - 'react/no-did-update-set-state': 'error', + // 'react/no-did-mount-set-state': 'error', + // 'react/no-did-update-set-state': 'error', 'react/no-redundant-should-component-update': 'error', 'react/no-typos': 'error', 'react/self-closing-comp': 'error', @@ -567,8 +567,21 @@ export default typescript.config([ ], 'react/display-name': 'off', // TODO(ryan953): Fix violations and delete this line 'react/no-unescaped-entities': 'off', - 'react/no-unknown-property': ['error', {ignore: ['css']}], + // 'react/no-unknown-property': ['error', {ignore: ['css']}], 'react/prop-types': 'off', // TODO(ryan953): Fix violations and delete this line + + 'react/jsx-key': 'off', // Replaced by @eslint-react/no-missing-key + @eslint-react/no-duplicate-key + @eslint-react/no-implicit-key + 'react/jsx-no-comment-textnodes': 'off', // Replaced by @eslint-react/jsx-no-comment-textnodes + 'react/no-children-prop': 'off', // Replaced by @eslint-react/jsx-no-children-prop + 'react/no-danger-with-children': 'off', // Replaced by @eslint-react/dom-no-dangerously-set-innerhtml-with-children + 'react/no-deprecated': 'off', // Replaced by no-component-will-mount + no-component-will-receive-props + no-component-will-update + no-create-ref + no-forward-ref + dom-no-render + dom-no-render-return-value + dom-no-hydrate + dom-no-find-dom-node + 'react/no-did-mount-set-state': 'off', // Replaced by @eslint-react/no-set-state-in-component-did-mount + 'react/no-did-update-set-state': 'off', // Replaced by @eslint-react/no-set-state-in-component-did-update + 'react/no-direct-mutation-state': 'off', // Replaced by @eslint-react/no-direct-mutation-state + 'react/no-find-dom-node': 'off', // Replaced by @eslint-react/dom-no-find-dom-node + 'react/no-render-return-value': 'off', // Replaced by @eslint-react/dom-no-render-return-value + 'react/no-target-blank': 'off', // Replaced by @eslint-react/dom-no-unsafe-target-blank + 'react/no-unknown-property': 'off', // Replaced by @eslint-react/dom-no-unknown-property }, }, { @@ -580,12 +593,11 @@ export default typescript.config([ '@eslint-react/dom-no-missing-button-type': 'off', // TODO(ryan953): Fix violations and delete this line '@eslint-react/dom-no-missing-iframe-sandbox': 'off', // TODO(ryan953): Fix violations and delete this line '@eslint-react/dom-no-unsafe-iframe-sandbox': 'off', // TODO(ryan953): Fix violations and delete this line - '@eslint-react/dom-no-unsafe-target-blank': 'off', // TODO(ryan953): Fix violations and delete this line '@eslint-react/exhaustive-deps': [ 'error', {additionalHooks: '(useEffectAfterFirstRender|useMemoWithPrevious)'}, ], - '@eslint-react/jsx-no-children-prop': 'off', // TODO(ryan953): Fix violations and delete this line + '@eslint-react/jsx-no-children-prop-with-children': 'off', // TODO(ryan953): Fix violations and delete this line '@eslint-react/jsx-no-key-after-spread': 'off', // TODO(ryan953): Fix violations and delete this line '@eslint-react/jsx-no-leaked-dollar': 'off', // TODO(ryan953): Fix violations and delete this line @@ -602,13 +614,8 @@ export default typescript.config([ '@eslint-react/no-class-component': 'off', // TODO(ryan953): Fix violations and delete this line '@eslint-react/no-clone-element': 'off', // TODO(ryan953): Fix violations and delete this line '@eslint-react/no-context-provider': 'off', // TODO(ryan953): Fix violations and delete this line - '@eslint-react/no-create-ref': 'off', // TODO(ryan953): Fix violations and delete this line - '@eslint-react/no-forward-ref': 'off', // TODO(ryan953): Fix violations and delete this line - '@eslint-react/no-missing-key': 'off', // TODO(ryan953): Fix violations and delete this line '@eslint-react/no-misused-capture-owner-stack': 'off', // TODO(ryan953): Fix violations and delete this line '@eslint-react/no-nested-component-definitions': 'off', // TODO(ryan953): Fix violations and delete this line - '@eslint-react/no-set-state-in-component-did-mount': 'off', // TODO(ryan953): Fix violations and delete this line - '@eslint-react/no-set-state-in-component-did-update': 'off', // TODO(ryan953): Fix violations and delete this line '@eslint-react/no-unnecessary-use-prefix': 'off', // TODO(ryan953): Fix violations and delete this line '@eslint-react/no-unsafe-component-will-receive-props': 'off', // TODO(ryan953): Fix violations and delete this line '@eslint-react/no-unstable-context-value': 'off', // TODO(ryan953): Fix violations and delete this line @@ -625,6 +632,27 @@ export default typescript.config([ '@eslint-react/web-api-no-leaked-interval': 'off', // TODO(ryan953): Fix violations and delete this line '@eslint-react/web-api-no-leaked-resize-observer': 'off', // TODO(ryan953): Fix violations and delete this line '@eslint-react/web-api-no-leaked-timeout': 'off', // TODO(ryan953): Fix violations and delete this line + + '@eslint-react/dom-no-dangerously-set-innerhtml-with-children': 'error', + '@eslint-react/dom-no-find-dom-node': 'error', + '@eslint-react/dom-no-hydrate': 'error', + '@eslint-react/dom-no-render': 'error', + '@eslint-react/dom-no-render-return-value': 'error', + '@eslint-react/dom-no-unknown-property': ['error', {ignore: ['css']}], + '@eslint-react/dom-no-unsafe-target-blank': 'error', + '@eslint-react/jsx-no-children-prop': 'error', + '@eslint-react/jsx-no-comment-textnodes': 'error', + '@eslint-react/no-component-will-mount': 'error', + '@eslint-react/no-component-will-receive-props': 'error', + '@eslint-react/no-component-will-update': 'error', + '@eslint-react/no-create-ref': 'error', + '@eslint-react/no-direct-mutation-state': 'error', + '@eslint-react/no-duplicate-key': 'error', + '@eslint-react/no-forward-ref': 'error', + // '@eslint-react/no-implicit-key': 'error', // needs type info + '@eslint-react/no-missing-key': 'error', + '@eslint-react/no-set-state-in-component-did-mount': 'error', + '@eslint-react/no-set-state-in-component-did-update': 'error', }, }, {