From 857a6194d27a45e2130bfc4f1c85690c655ac3c0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 20 Oct 2025 06:52:32 +0000 Subject: [PATCH 1/9] chore(deps): update dependency eslint-plugin-react-hooks to v7 # Conflicts: # examples/react-router-ts/package-lock.json # examples/react-router-ts/package.json # examples/vite-ts/package-lock.json # examples/vite-ts/package.json # package.json # patterns/navigation-layout/package-lock.json # patterns/navigation-layout/package.json # templates/vite-ts/package-lock.json # templates/vite-ts/package.json # yarn.lock --- examples/react-router-ts/package-lock.json | 26 ++++++++++++++++--- examples/react-router-ts/package.json | 2 +- examples/vite-ts/package-lock.json | 26 ++++++++++++++++--- examples/vite-ts/package.json | 2 +- package.json | 2 +- patterns/navigation-layout/package-lock.json | 26 ++++++++++++++++--- patterns/navigation-layout/package.json | 2 +- templates/vite-ts/package-lock.json | 26 ++++++++++++++++--- templates/vite-ts/package.json | 2 +- yarn.lock | 27 ++++++++++++++++---- 10 files changed, 115 insertions(+), 26 deletions(-) diff --git a/examples/react-router-ts/package-lock.json b/examples/react-router-ts/package-lock.json index 07be9c3df4e..e83b1d781e9 100644 --- a/examples/react-router-ts/package-lock.json +++ b/examples/react-router-ts/package-lock.json @@ -27,7 +27,7 @@ "eslint-plugin-import": "2.32.0", "eslint-plugin-jsx-a11y": "6.10.2", "eslint-plugin-react": "7.37.5", - "eslint-plugin-react-hooks": "6.1.1", + "eslint-plugin-react-hooks": "7.0.0", "globals": "16.5.0", "typescript": "5.8.3", "typescript-eslint": "8.46.2", @@ -4390,14 +4390,15 @@ } }, "node_modules/eslint-plugin-react-hooks": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-6.1.1.tgz", - "integrity": "sha512-St9EKZzOAQF704nt2oJvAKZHjhrpg25ClQoaAlHmPZuajFldVLqRDW4VBNAS01NzeiQF0m0qhG1ZA807K6aVaQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.0.tgz", + "integrity": "sha512-fNXaOwvKwq2+pXiRpXc825Vd63+KM4DLL40Rtlycb8m7fYpp6efrTp1sa6ZbP/Ap58K2bEKFXRmhURE+CJAQWw==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.24.4", "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", "zod": "^3.22.4 || ^4.0.0", "zod-validation-error": "^3.0.3 || ^4.0.0" }, @@ -5179,6 +5180,23 @@ "node": ">= 0.4" } }, + "node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true, + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.25.1" + } + }, "node_modules/hosted-git-info": { "version": "6.1.3", "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.3.tgz", diff --git a/examples/react-router-ts/package.json b/examples/react-router-ts/package.json index 9fb002e52f5..26b19d35abf 100644 --- a/examples/react-router-ts/package.json +++ b/examples/react-router-ts/package.json @@ -32,7 +32,7 @@ "eslint-plugin-import": "2.32.0", "eslint-plugin-jsx-a11y": "6.10.2", "eslint-plugin-react": "7.37.5", - "eslint-plugin-react-hooks": "6.1.1", + "eslint-plugin-react-hooks": "7.0.0", "globals": "16.5.0", "typescript": "5.8.3", "typescript-eslint": "8.46.2", diff --git a/examples/vite-ts/package-lock.json b/examples/vite-ts/package-lock.json index b6ae6057d29..009b358ebb9 100644 --- a/examples/vite-ts/package-lock.json +++ b/examples/vite-ts/package-lock.json @@ -24,7 +24,7 @@ "@vitejs/plugin-react": "5.1.0", "cypress": "15.5.0", "eslint": "9.39.0", - "eslint-plugin-react-hooks": "6.1.1", + "eslint-plugin-react-hooks": "7.0.0", "eslint-plugin-react-refresh": "0.4.24", "globals": "16.5.0", "typescript-eslint": "8.46.2", @@ -3297,14 +3297,15 @@ } }, "node_modules/eslint-plugin-react-hooks": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-6.1.1.tgz", - "integrity": "sha512-St9EKZzOAQF704nt2oJvAKZHjhrpg25ClQoaAlHmPZuajFldVLqRDW4VBNAS01NzeiQF0m0qhG1ZA807K6aVaQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.0.tgz", + "integrity": "sha512-fNXaOwvKwq2+pXiRpXc825Vd63+KM4DLL40Rtlycb8m7fYpp6efrTp1sa6ZbP/Ap58K2bEKFXRmhURE+CJAQWw==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.24.4", "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", "zod": "^3.22.4 || ^4.0.0", "zod-validation-error": "^3.0.3 || ^4.0.0" }, @@ -3960,6 +3961,23 @@ "node": ">= 0.4" } }, + "node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true, + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.25.1" + } + }, "node_modules/http-signature": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.4.0.tgz", diff --git a/examples/vite-ts/package.json b/examples/vite-ts/package.json index effbada82c9..c2982be02fb 100644 --- a/examples/vite-ts/package.json +++ b/examples/vite-ts/package.json @@ -30,7 +30,7 @@ "@vitejs/plugin-react": "5.1.0", "cypress": "15.5.0", "eslint": "9.39.0", - "eslint-plugin-react-hooks": "6.1.1", + "eslint-plugin-react-hooks": "7.0.0", "eslint-plugin-react-refresh": "0.4.24", "globals": "16.5.0", "typescript-eslint": "8.46.2", diff --git a/package.json b/package.json index beff56038c3..4eb9e2c0ce8 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "eslint-plugin-no-only-tests": "3.3.0", "eslint-plugin-prettier": "5.5.4", "eslint-plugin-react": "7.37.5", - "eslint-plugin-react-hooks": "6.1.1", + "eslint-plugin-react-hooks": "7.0.0", "eslint-plugin-storybook": "9.1.16", "glob": "11.0.3", "globals": "16.4.0", diff --git a/patterns/navigation-layout/package-lock.json b/patterns/navigation-layout/package-lock.json index a3dd87fcf86..a543684a299 100644 --- a/patterns/navigation-layout/package-lock.json +++ b/patterns/navigation-layout/package-lock.json @@ -21,7 +21,7 @@ "@types/react-dom": "19.2.2", "@vitejs/plugin-react": "5.1.0", "eslint": "9.39.0", - "eslint-plugin-react-hooks": "6.1.1", + "eslint-plugin-react-hooks": "7.0.0", "eslint-plugin-react-refresh": "0.4.24", "globals": "16.5.0", "typescript": "5.8.3", @@ -2488,14 +2488,15 @@ } }, "node_modules/eslint-plugin-react-hooks": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-6.1.1.tgz", - "integrity": "sha512-St9EKZzOAQF704nt2oJvAKZHjhrpg25ClQoaAlHmPZuajFldVLqRDW4VBNAS01NzeiQF0m0qhG1ZA807K6aVaQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.0.tgz", + "integrity": "sha512-fNXaOwvKwq2+pXiRpXc825Vd63+KM4DLL40Rtlycb8m7fYpp6efrTp1sa6ZbP/Ap58K2bEKFXRmhURE+CJAQWw==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.24.4", "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", "zod": "^3.22.4 || ^4.0.0", "zod-validation-error": "^3.0.3 || ^4.0.0" }, @@ -2843,6 +2844,23 @@ "node": ">=8" } }, + "node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true, + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.25.1" + } + }, "node_modules/ignore": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", diff --git a/patterns/navigation-layout/package.json b/patterns/navigation-layout/package.json index e63e55ffd93..31b93aa387a 100644 --- a/patterns/navigation-layout/package.json +++ b/patterns/navigation-layout/package.json @@ -23,7 +23,7 @@ "@types/react-dom": "19.2.2", "@vitejs/plugin-react": "5.1.0", "eslint": "9.39.0", - "eslint-plugin-react-hooks": "6.1.1", + "eslint-plugin-react-hooks": "7.0.0", "eslint-plugin-react-refresh": "0.4.24", "globals": "16.5.0", "typescript": "5.8.3", diff --git a/templates/vite-ts/package-lock.json b/templates/vite-ts/package-lock.json index 5bd744262cb..2d70790307b 100644 --- a/templates/vite-ts/package-lock.json +++ b/templates/vite-ts/package-lock.json @@ -23,7 +23,7 @@ "@vitejs/plugin-react": "5.1.0", "cypress": "15.5.0", "eslint": "9.39.0", - "eslint-plugin-react-hooks": "6.1.1", + "eslint-plugin-react-hooks": "7.0.0", "eslint-plugin-react-refresh": "0.4.24", "globals": "16.5.0", "typescript": "5.8.3", @@ -3228,14 +3228,15 @@ } }, "node_modules/eslint-plugin-react-hooks": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-6.1.1.tgz", - "integrity": "sha512-St9EKZzOAQF704nt2oJvAKZHjhrpg25ClQoaAlHmPZuajFldVLqRDW4VBNAS01NzeiQF0m0qhG1ZA807K6aVaQ==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.0.tgz", + "integrity": "sha512-fNXaOwvKwq2+pXiRpXc825Vd63+KM4DLL40Rtlycb8m7fYpp6efrTp1sa6ZbP/Ap58K2bEKFXRmhURE+CJAQWw==", "dev": true, "license": "MIT", "dependencies": { "@babel/core": "^7.24.4", "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", "zod": "^3.22.4 || ^4.0.0", "zod-validation-error": "^3.0.3 || ^4.0.0" }, @@ -3915,6 +3916,23 @@ "node": ">= 0.4" } }, + "node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true, + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.25.1" + } + }, "node_modules/http-signature": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.4.0.tgz", diff --git a/templates/vite-ts/package.json b/templates/vite-ts/package.json index b4c449f11d0..1a3ec8284d1 100644 --- a/templates/vite-ts/package.json +++ b/templates/vite-ts/package.json @@ -27,7 +27,7 @@ "@ui5/webcomponents-cypress-commands": "2.15.3", "cypress": "15.5.0", "eslint": "9.39.0", - "eslint-plugin-react-hooks": "6.1.1", + "eslint-plugin-react-hooks": "7.0.0", "eslint-plugin-react-refresh": "0.4.24", "globals": "16.5.0", "typescript": "5.8.3", diff --git a/yarn.lock b/yarn.lock index 4a3c4fc50e3..bc3cf9ed52f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -10104,17 +10104,18 @@ __metadata: languageName: node linkType: hard -"eslint-plugin-react-hooks@npm:6.1.1": - version: 6.1.1 - resolution: "eslint-plugin-react-hooks@npm:6.1.1" +"eslint-plugin-react-hooks@npm:7.0.0": + version: 7.0.0 + resolution: "eslint-plugin-react-hooks@npm:7.0.0" dependencies: "@babel/core": "npm:^7.24.4" "@babel/parser": "npm:^7.24.4" + hermes-parser: "npm:^0.25.1" zod: "npm:^3.22.4 || ^4.0.0" zod-validation-error: "npm:^3.0.3 || ^4.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 - checksum: 10c0/579be053bc89c995a6c03996f9ee3f6bac88946b4b1c8b891b42f981e7c05a9c5de46324bbd2a33199855c0a602820c0e3eeb7f840730301b77a9ba3dc7a0ae2 + checksum: 10c0/911c9efdd9b102ce2eabac247dff8c217ecb8d6972aaf3b7eecfb1cfc293d4d902766355993ff7a37a33c0abde3e76971f43bc1c8ff36d6c123310e5680d0423 languageName: node linkType: hard @@ -11936,6 +11937,22 @@ __metadata: languageName: node linkType: hard +"hermes-estree@npm:0.25.1": + version: 0.25.1 + resolution: "hermes-estree@npm:0.25.1" + checksum: 10c0/48be3b2fa37a0cbc77a112a89096fa212f25d06de92781b163d67853d210a8a5c3784fac23d7d48335058f7ed283115c87b4332c2a2abaaccc76d0ead1a282ac + languageName: node + linkType: hard + +"hermes-parser@npm:^0.25.1": + version: 0.25.1 + resolution: "hermes-parser@npm:0.25.1" + dependencies: + hermes-estree: "npm:0.25.1" + checksum: 10c0/3abaa4c6f1bcc25273f267297a89a4904963ea29af19b8e4f6eabe04f1c2c7e9abd7bfc4730ddb1d58f2ea04b6fee74053d8bddb5656ec6ebf6c79cc8d14202c + languageName: node + linkType: hard + "highlight.js@npm:^11.6.0": version: 11.10.0 resolution: "highlight.js@npm:11.10.0" @@ -20919,7 +20936,7 @@ __metadata: eslint-plugin-no-only-tests: "npm:3.3.0" eslint-plugin-prettier: "npm:5.5.4" eslint-plugin-react: "npm:7.37.5" - eslint-plugin-react-hooks: "npm:6.1.1" + eslint-plugin-react-hooks: "npm:7.0.0" eslint-plugin-storybook: "npm:9.1.16" glob: "npm:11.0.3" globals: "npm:16.4.0" From 3964e98d48e9f8b9268cd9612dccbf9cacdca03b Mon Sep 17 00:00:00 2001 From: Marcus Notheis Date: Mon, 20 Oct 2025 12:48:46 +0200 Subject: [PATCH 2/9] Update eslint.config.mjs --- eslint.config.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index c4ce0190e2f..e9221f8c634 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -48,7 +48,7 @@ const config = tseslint.config( reactPlugin.configs.flat.recommended, // This is not a plugin object, but a shareable config object reactPlugin.configs.flat['jsx-runtime'], // Add this if you are using React 17+ // eslint-plugin-react-hooks - ...reactHooksPlugin.configs.recommended, + reactHooks.configs.flat.recommended, { languageOptions: { globals: { From f80916cd70bb0752767cb4f9c846e7d01849aadc Mon Sep 17 00:00:00 2001 From: Marcus Notheis Date: Mon, 20 Oct 2025 12:50:43 +0200 Subject: [PATCH 3/9] Update eslint.config.mjs --- eslint.config.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eslint.config.mjs b/eslint.config.mjs index e9221f8c634..119d9be249a 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -48,7 +48,7 @@ const config = tseslint.config( reactPlugin.configs.flat.recommended, // This is not a plugin object, but a shareable config object reactPlugin.configs.flat['jsx-runtime'], // Add this if you are using React 17+ // eslint-plugin-react-hooks - reactHooks.configs.flat.recommended, + reactHooksPlugin.configs.flat.recommended, { languageOptions: { globals: { From c5282b87c001831f30513336ee5732eb471ed0ec Mon Sep 17 00:00:00 2001 From: Marcus Notheis Date: Mon, 20 Oct 2025 12:54:08 +0200 Subject: [PATCH 4/9] Update eslint.config.mjs --- examples/vite-ts/eslint.config.mjs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/examples/vite-ts/eslint.config.mjs b/examples/vite-ts/eslint.config.mjs index cfd81c9345d..47a84020368 100644 --- a/examples/vite-ts/eslint.config.mjs +++ b/examples/vite-ts/eslint.config.mjs @@ -7,18 +7,16 @@ import tseslint from 'typescript-eslint'; export default tseslint.config( { ignores: ['dist'] }, { - extends: [js.configs.recommended, ...tseslint.configs.recommended], + extends: [js.configs.recommended, ...tseslint.configs.recommended, reactHooks.configs.flat.recommended, ], files: ['**/*.{ts,tsx}'], languageOptions: { ecmaVersion: 2020, globals: globals.browser, }, plugins: { - 'react-hooks': reactHooks, 'react-refresh': reactRefresh, }, rules: { - ...reactHooks.configs.recommended.rules, 'react-refresh/only-export-components': ['warn', { allowConstantExport: true }], }, }, From b843c2cca0923e0a6a4d811ce1a6f441700d50b4 Mon Sep 17 00:00:00 2001 From: Lukas Harbarth Date: Wed, 29 Oct 2025 14:02:27 +0100 Subject: [PATCH 5/9] Update MessageView.cy.tsx --- packages/main/src/components/MessageView/MessageView.cy.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/main/src/components/MessageView/MessageView.cy.tsx b/packages/main/src/components/MessageView/MessageView.cy.tsx index 3def72073e2..ae378f0d815 100644 --- a/packages/main/src/components/MessageView/MessageView.cy.tsx +++ b/packages/main/src/components/MessageView/MessageView.cy.tsx @@ -2,9 +2,9 @@ import WrappingType from '@ui5/webcomponents/dist/types/WrappingType.js'; import ValueState from '@ui5/webcomponents-base/dist/types/ValueState.js'; import { Link } from '@ui5/webcomponents-react'; import { useRef } from 'react'; +import { Dialog } from '../../webComponents/Dialog/index.js'; import { MessageItem } from './MessageItem'; import { MessageView } from './index.js'; -import { Dialog } from '../../webComponents/Dialog/index.js'; describe('MessageView', () => { it('default & grouped', () => { From fbdaed7f94537fcdbf5788ab08b70bb885e0fcdb Mon Sep 17 00:00:00 2001 From: Lukas Harbarth Date: Wed, 29 Oct 2025 14:02:49 +0100 Subject: [PATCH 6/9] Update ProjectTemplate.tsx --- .storybook/components/ProjectTemplate.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.storybook/components/ProjectTemplate.tsx b/.storybook/components/ProjectTemplate.tsx index 4601dc976a7..cc891beaff1 100644 --- a/.storybook/components/ProjectTemplate.tsx +++ b/.storybook/components/ProjectTemplate.tsx @@ -16,7 +16,7 @@ import { import { addCustomCSSWithScoping } from '@ui5/webcomponents-react-base/internal/utils'; import { clsx } from 'clsx'; import type { ReactNode } from 'react'; -import { useRef, useState } from 'react'; +import { useId, useState } from 'react'; import classes from './ProjectTemplate.module.css'; interface ProjectTemplatePropTypes { @@ -58,7 +58,7 @@ export function ProjectTemplate(props: ProjectTemplatePropTypes) { note, } = props; const [popoverOpen, setPopoverOpen] = useState(false); - const linkRef = useRef(null); + const linkId = useId() + '-link'; return ( @@ -68,7 +68,7 @@ export function ProjectTemplate(props: ProjectTemplatePropTypes) { Currently not supported by V2.{' '} { setPopoverOpen(true); @@ -79,7 +79,7 @@ export function ProjectTemplate(props: ProjectTemplatePropTypes) { { setPopoverOpen(false); From 280ab3f1fa2fd49b7a98a0b74cd3ee35859b313f Mon Sep 17 00:00:00 2001 From: Lukas Harbarth Date: Tue, 4 Nov 2025 13:16:27 +0100 Subject: [PATCH 7/9] fix lint errors --- .../base/src/internal/hooks/useSyncRef.ts | 2 + .../internal/wrapper/withWebComponent.cy.tsx | 1 + .../charts/src/components/LineChart/index.tsx | 51 +++++++++---------- .../charts/src/components/PieChart/index.tsx | 11 ++-- .../TimelineChart/TimelineChartHeaders.tsx | 3 +- .../chartbody/TimelineChartBody.tsx | 40 ++++++++------- .../chartbody/TimelineChartRow.tsx | 2 + .../components/Toolbar/OverflowPopover.tsx | 1 + .../compat/src/components/Toolbar/index.tsx | 2 + .../AnalyticalTable/AnalyticalTable.cy.tsx | 3 +- .../AnalyticalTable/ColumnHeader/index.tsx | 4 ++ .../defaults/Column/ColumnHeaderModal.tsx | 8 ++- .../components/AnalyticalTable/types/index.ts | 6 +++ 13 files changed, 78 insertions(+), 56 deletions(-) diff --git a/packages/base/src/internal/hooks/useSyncRef.ts b/packages/base/src/internal/hooks/useSyncRef.ts index f5b99c27010..fd5f79b9fcf 100644 --- a/packages/base/src/internal/hooks/useSyncRef.ts +++ b/packages/base/src/internal/hooks/useSyncRef.ts @@ -35,6 +35,8 @@ export function useSyncRef( ref(node); } if ({}.hasOwnProperty.call(ref, 'current')) { + // React Refs are mutable + // eslint-disable-next-line react-hooks/immutability (ref as MutableRefObject).current = node; } } diff --git a/packages/base/src/internal/wrapper/withWebComponent.cy.tsx b/packages/base/src/internal/wrapper/withWebComponent.cy.tsx index 50f1de7dfdd..c9880aae449 100644 --- a/packages/base/src/internal/wrapper/withWebComponent.cy.tsx +++ b/packages/base/src/internal/wrapper/withWebComponent.cy.tsx @@ -202,6 +202,7 @@ describe('withWebComponent', () => { { setOpen(false); diff --git a/packages/charts/src/components/LineChart/index.tsx b/packages/charts/src/components/LineChart/index.tsx index 5a97a3db7d5..626dc98a29c 100644 --- a/packages/charts/src/components/LineChart/index.tsx +++ b/packages/charts/src/components/LineChart/index.tsx @@ -1,7 +1,7 @@ 'use client'; import { enrichEventWithDetails, ThemingParameters, useIsRTL, useSyncRef } from '@ui5/webcomponents-react-base'; -import { forwardRef, useCallback, useRef } from 'react'; +import { forwardRef, useRef } from 'react'; import type { LineProps, YAxisProps } from 'recharts'; import { Brush, @@ -182,32 +182,29 @@ const LineChart = forwardRef((props, ref) => { const onItemLegendClick = useLegendItemClick(onLegendClick); const preventOnClickCall = useRef(0); - const onDataPointClickInternal = useCallback( - (payload, eventOrIndex) => { - if (eventOrIndex.dataKey && typeof onDataPointClick === 'function') { - preventOnClickCall.current = 2; - onDataPointClick( - enrichEventWithDetails({} as any, { - value: eventOrIndex.value, - dataKey: eventOrIndex.dataKey, - dataIndex: eventOrIndex.index, - payload: eventOrIndex.payload, - }), - ); - } else if (typeof onClick === 'function' && preventOnClickCall.current === 0) { - onClick( - enrichEventWithDetails(eventOrIndex, { - payload: payload?.activePayload?.[0]?.payload, - activePayloads: payload?.activePayload, - }), - ); - } - if (preventOnClickCall.current > 0) { - preventOnClickCall.current -= 1; - } - }, - [onDataPointClick, preventOnClickCall.current], - ); + const onDataPointClickInternal = (payload, eventOrIndex) => { + if (eventOrIndex.dataKey && typeof onDataPointClick === 'function') { + preventOnClickCall.current = 2; + onDataPointClick( + enrichEventWithDetails({} as any, { + value: eventOrIndex.value, + dataKey: eventOrIndex.dataKey, + dataIndex: eventOrIndex.index, + payload: eventOrIndex.payload, + }), + ); + } else if (typeof onClick === 'function' && preventOnClickCall.current === 0) { + onClick( + enrichEventWithDetails(eventOrIndex, { + payload: payload?.activePayload?.[0]?.payload, + activePayloads: payload?.activePayload, + }), + ); + } + if (preventOnClickCall.current > 0) { + preventOnClickCall.current -= 1; + } + }; const isBigDataSet = dataset?.length > 30; const primaryDimensionAccessor = primaryDimension?.accessor; diff --git a/packages/charts/src/components/PieChart/index.tsx b/packages/charts/src/components/PieChart/index.tsx index b7e3f130942..94e043b4e35 100644 --- a/packages/charts/src/components/PieChart/index.tsx +++ b/packages/charts/src/components/PieChart/index.tsx @@ -159,10 +159,9 @@ const PieChart = forwardRef((props, ref) => { ); }; - const tooltipValueFormatter = useCallback( - (value, name) => [measure.formatter(value), dimension.formatter(name)], - [measure.formatter, dimension.formatter], - ); + const tooltipValueFormatter = (value, name) => { + return [measure.formatter(value), dimension.formatter(name)]; + }; const onItemLegendClick = useLegendItemClick(onLegendClick, () => measure.accessor); const onClickInternal = useOnClickInternal(onClick); @@ -248,7 +247,7 @@ const PieChart = forwardRef((props, ref) => { ); }, - [showActiveSegmentDataLabel, chartConfig.activeSegment, isDonutChart], + [showActiveSegmentDataLabel, chartConfig.activeSegment, isDonutChart, chartRef, measure], ); const renderLabelLine = useCallback( @@ -258,7 +257,7 @@ const PieChart = forwardRef((props, ref) => { if (hideDataLabel || chartConfig.activeSegment === props.index) return null; return Pie.renderLabelLineItem({}, props, undefined); }, - [chartConfig.activeSegment, measure.hideDataLabel], + [chartConfig.activeSegment, measure], ); const legendWrapperStyle = useMemo(() => { diff --git a/packages/charts/src/components/TimelineChart/TimelineChartHeaders.tsx b/packages/charts/src/components/TimelineChart/TimelineChartHeaders.tsx index 4f4cdb79744..2eec8437a94 100644 --- a/packages/charts/src/components/TimelineChart/TimelineChartHeaders.tsx +++ b/packages/charts/src/components/TimelineChart/TimelineChartHeaders.tsx @@ -75,6 +75,7 @@ const TimelineChartColumnLabel = ({ const newLabelArray = columnLabels ? columnLabels : Array.from(Array(totalDuration).keys()).map((num) => `${num + start}`); + // eslint-disable-next-line react-hooks/set-state-in-effect setLabelArray(newLabelArray); } }, [isDiscrete, columnLabels, start, totalDuration]); @@ -95,7 +96,7 @@ const TimelineChartColumnLabel = ({ height: `${halfHeaderHeight}px`, lineHeight: `${halfHeaderHeight}px`, }} - > + /> {isDiscrete ? (
{ + evt.preventDefault(); + if (evt.deltaY < 0) { + // Only scale up if scaled width will not exceed MAX_BODY_WIDTH + const msrWidth = bodyRef.current.getBoundingClientRect().width; + if (msrWidth * SCALE_FACTOR < MAX_BODY_WIDTH) { + scaleExpRef.current++; + } + } else { + // Only scale down if scaled width will not be less than original + // width + if (scaleExpRef.current > 0) { + resetScroll(); + scaleExpRef.current--; + } + } + onScale(Math.pow(SCALE_FACTOR, scaleExpRef.current)); + }; + useEffect(() => { const bodyElement = bodyRef.current; bodyElement?.addEventListener('wheel', onMouseWheelEvent); @@ -81,25 +100,6 @@ const TimelineChartBody = ({ }; const hideTooltip = () => tooltipRef.current?.onLeaveItem(); - const onMouseWheelEvent = (evt: WheelEvent) => { - evt.preventDefault(); - if (evt.deltaY < 0) { - // Only scale up if scaled width will not exceed MAX_BODY_WIDTH - const msrWidth = bodyRef.current.getBoundingClientRect().width; - if (msrWidth * SCALE_FACTOR < MAX_BODY_WIDTH) { - scaleExpRef.current++; - } - } else { - // Only scale down if scaled width will not be less than original - // width - if (scaleExpRef.current > 0) { - resetScroll(); - scaleExpRef.current--; - } - } - onScale(Math.pow(SCALE_FACTOR, scaleExpRef.current)); - }; - const showArrows = () => setDisplayArrows(true); return ( @@ -121,6 +121,8 @@ const TimelineChartBody = ({ dataSet={dataset} width={width} rowHeight={rowHeight} + // todo: check side-effect + // eslint-disable-next-line react-hooks/refs bodyRect={bodyRef.current?.getBoundingClientRect()} /> diff --git a/packages/charts/src/components/TimelineChart/chartbody/TimelineChartRow.tsx b/packages/charts/src/components/TimelineChart/chartbody/TimelineChartRow.tsx index 48912dacbac..696e41e52b9 100644 --- a/packages/charts/src/components/TimelineChart/chartbody/TimelineChartRow.tsx +++ b/packages/charts/src/components/TimelineChart/chartbody/TimelineChartRow.tsx @@ -27,6 +27,8 @@ const TimelineChartRow = ({ showTooltip, hideTooltip, }: TimelineChartRowProps) => { + // todo: fix mutation + // eslint-disable-next-line react-hooks/immutability rowData.color = rowData.color ?? `var(--sapChart_OrderedColor_${(rowIndex % 12) + 1})`; return ( diff --git a/packages/compat/src/components/Toolbar/OverflowPopover.tsx b/packages/compat/src/components/Toolbar/OverflowPopover.tsx index 0352f3b25de..95338d95ed7 100644 --- a/packages/compat/src/components/Toolbar/OverflowPopover.tsx +++ b/packages/compat/src/components/Toolbar/OverflowPopover.tsx @@ -164,6 +164,7 @@ export const OverflowPopover: FC = (props: OverflowPopover return ( {overflowButton ? ( + // eslint-disable-next-line react-hooks/refs cloneElement(overflowButton, { onClick: clonedOverflowButtonClick }) ) : ( ((props, ref) => { }, [children]); const childrenWithRef = useMemo(() => { + // eslint-disable-next-line react-hooks/refs controlMetaData.current = []; let hasOnlySpacersOrSeparators = true; + // eslint-disable-next-line react-hooks/refs const enrichedChildren = flatChildren.map((item, index) => { const itemRef: RefObject = createRef(); // @ts-expect-error: if type is not defined, it's not a spacer diff --git a/packages/main/src/components/AnalyticalTable/AnalyticalTable.cy.tsx b/packages/main/src/components/AnalyticalTable/AnalyticalTable.cy.tsx index a8eca144478..559285f3df1 100644 --- a/packages/main/src/components/AnalyticalTable/AnalyticalTable.cy.tsx +++ b/packages/main/src/components/AnalyticalTable/AnalyticalTable.cy.tsx @@ -3724,6 +3724,7 @@ describe('AnalyticalTable', () => { // transform data to the pattern which is accepted by the tree table // NOTES: this algorithm is less likely related to the bug, because in our reality project there is a different algorithm to generate the tree table and the bug still occurs. const data = useMemo(() => { + // eslint-disable-next-line react-hooks/refs raw.forEach((item) => { const newItem = { ...item }; rowById.current[newItem.nodeId] = { @@ -3747,7 +3748,7 @@ describe('AnalyticalTable', () => { rowById.current[newItem.parentId].subRows.push(rowById.current[newItem.nodeId]); } }); - + // eslint-disable-next-line react-hooks/refs return Object.values(rowById.current).filter((row) => !row.parentId); }, [raw]); diff --git a/packages/main/src/components/AnalyticalTable/ColumnHeader/index.tsx b/packages/main/src/components/AnalyticalTable/ColumnHeader/index.tsx index c7535af48ad..4b8f94d6ba1 100644 --- a/packages/main/src/components/AnalyticalTable/ColumnHeader/index.tsx +++ b/packages/main/src/components/AnalyticalTable/ColumnHeader/index.tsx @@ -176,6 +176,7 @@ export const ColumnHeader = (props: ColumnHeaderProps) => { if (!column) return null; return (
{ {hasPopover && popoverOpen && // render the popover and add the props to the table instance + // todo: remove openerRef in v3.0.0 + // eslint-disable-next-line react-hooks/refs column.render(RenderColumnTypes.Popover, { popoverProps: { openerRef: columnHeaderRef, + openerId: `${id}-opener`, setOpen: setPopoverOpen, }, })} diff --git a/packages/main/src/components/AnalyticalTable/defaults/Column/ColumnHeaderModal.tsx b/packages/main/src/components/AnalyticalTable/defaults/Column/ColumnHeaderModal.tsx index e3760e801cf..cd1eba352ed 100644 --- a/packages/main/src/components/AnalyticalTable/defaults/Column/ColumnHeaderModal.tsx +++ b/packages/main/src/components/AnalyticalTable/defaults/Column/ColumnHeaderModal.tsx @@ -34,7 +34,7 @@ import type { TableInstanceWithPopoverProps } from '../../types/index.js'; import { RenderColumnTypes } from '../../types/index.js'; export const ColumnHeaderModal = (instance: TableInstanceWithPopoverProps) => { - const { setOpen, openerRef } = instance.popoverProps; + const { setOpen, openerRef, openerId } = instance.popoverProps; const { column, state, webComponentsReactProperties } = instance; const { isRtl, groupBy } = state; const { onGroup, onSort, classes: classNames } = webComponentsReactProperties; @@ -174,10 +174,14 @@ export const ColumnHeaderModal = (instance: TableInstanceWithPopoverProps) => { ref.current.open = true; }); } - }, []); + }, [openerRef]); return ( >; /** * React Ref that holds the reference to the respective table header element. + * + * @deprecated Use `openerId` instead. */ openerRef: MutableRefObject; + /** + * ID of the respective table header element that opens the popover. + */ + openerId: string; } export interface TableInstanceWithPopoverProps extends TableInstance { From 1b2723a529676144c224c8e88fb9e7a8be76e140 Mon Sep 17 00:00:00 2001 From: Lukas Harbarth Date: Tue, 4 Nov 2025 13:35:23 +0100 Subject: [PATCH 8/9] AT: scrollToRef --- .../TableBody/VirtualTableBody.tsx | 8 -------- .../src/components/AnalyticalTable/index.tsx | 18 ++++++++++-------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/packages/main/src/components/AnalyticalTable/TableBody/VirtualTableBody.tsx b/packages/main/src/components/AnalyticalTable/TableBody/VirtualTableBody.tsx index e3bc018ac38..4315999b79a 100644 --- a/packages/main/src/components/AnalyticalTable/TableBody/VirtualTableBody.tsx +++ b/packages/main/src/components/AnalyticalTable/TableBody/VirtualTableBody.tsx @@ -35,7 +35,6 @@ interface VirtualTableBodyProps { subRowsKey: string; scrollContainerRef?: MutableRefObject; triggerScroll?: TriggerScrollState; - scrollToRef: MutableRefObject; rowVirtualizer: Virtualizer; } @@ -54,7 +53,6 @@ export const VirtualTableBody = (props: VirtualTableBodyProps) => { classes, prepareRow, rows, - scrollToRef, isTreeTable, internalRowHeight, visibleColumns, @@ -76,12 +74,6 @@ export const VirtualTableBody = (props: VirtualTableBodyProps) => { const rowHeight = popInRowHeight !== internalRowHeight ? popInRowHeight : internalRowHeight; const lastNonEmptyRow = useRef(null); - scrollToRef.current = { - ...scrollToRef.current, - scrollToOffset: rowVirtualizer.scrollToOffset, - scrollToIndex: rowVirtualizer.scrollToIndex, - }; - useEffect(() => { if (triggerScroll && triggerScroll.direction === 'vertical') { if (triggerScroll.type === 'offset') { diff --git a/packages/main/src/components/AnalyticalTable/index.tsx b/packages/main/src/components/AnalyticalTable/index.tsx index 2fc54505fcd..ceb970ad45c 100644 --- a/packages/main/src/components/AnalyticalTable/index.tsx +++ b/packages/main/src/components/AnalyticalTable/index.tsx @@ -368,13 +368,6 @@ const AnalyticalTable = forwardRef { if (triggerScroll && triggerScroll.direction === 'horizontal') { if (triggerScroll.type === 'offset') { @@ -726,6 +719,16 @@ const AnalyticalTable = forwardRef Date: Wed, 5 Nov 2025 15:51:08 +0100 Subject: [PATCH 9/9] AT: cleanup & fix more lint errors --- .../AnalyticalTable.stories.tsx | 3 +- .../TableBody/VirtualTableBody.tsx | 3 +- .../TableBody/VirtualTableBodyContainer.tsx | 14 ++-- .../AnalyticalTable/VerticalResizer.tsx | 73 ++++++++----------- .../defaults/FilterComponent/index.tsx | 5 +- .../AnalyticalTable/hooks/useIsFirefox.ts | 2 + .../hooks/useKeyboardNavigation.ts | 8 +- .../src/components/AnalyticalTable/index.tsx | 7 -- .../components/AnalyticalTable/types/index.ts | 7 -- 9 files changed, 54 insertions(+), 68 deletions(-) diff --git a/packages/main/src/components/AnalyticalTable/AnalyticalTable.stories.tsx b/packages/main/src/components/AnalyticalTable/AnalyticalTable.stories.tsx index e9614dcb487..47177114d33 100644 --- a/packages/main/src/components/AnalyticalTable/AnalyticalTable.stories.tsx +++ b/packages/main/src/components/AnalyticalTable/AnalyticalTable.stories.tsx @@ -254,7 +254,8 @@ export const InfiniteScrolling: Story = { const [data, setData] = useState(args.data.slice(0, 50)); const [loading, setLoading] = useState(false); const offset = useRef(50); - const onLoadMore = () => { + const onLoadMore = (e) => { + args.onLoadMore(e); setLoading(true); }; useEffect(() => { diff --git a/packages/main/src/components/AnalyticalTable/TableBody/VirtualTableBody.tsx b/packages/main/src/components/AnalyticalTable/TableBody/VirtualTableBody.tsx index 4315999b79a..17adc190adc 100644 --- a/packages/main/src/components/AnalyticalTable/TableBody/VirtualTableBody.tsx +++ b/packages/main/src/components/AnalyticalTable/TableBody/VirtualTableBody.tsx @@ -6,7 +6,6 @@ import type { AnalyticalTablePropTypes, ClassNames, DivWithCustomScrollProp, - ReactVirtualScrollToMethods, TableInstance, TriggerScrollState, } from '../types/index.js'; @@ -104,6 +103,8 @@ export const VirtualTableBody = (props: VirtualTableBodyProps) => { width: `${columnVirtualizer.getTotalSize()}px`, }} > + {/* Safe to update: lastNonEmptyRow ref holds non-render data only.*/} + {/* eslint-disable-next-line react-hooks/refs */} {rowVirtualizer.getVirtualItems().map((virtualRow, visibleRowIndex) => { const row = rows[virtualRow.index]; const rowIndexWithHeader = virtualRow.index + 1; diff --git a/packages/main/src/components/AnalyticalTable/TableBody/VirtualTableBodyContainer.tsx b/packages/main/src/components/AnalyticalTable/TableBody/VirtualTableBodyContainer.tsx index 0600da74c93..6b94d9928e8 100644 --- a/packages/main/src/components/AnalyticalTable/TableBody/VirtualTableBodyContainer.tsx +++ b/packages/main/src/components/AnalyticalTable/TableBody/VirtualTableBodyContainer.tsx @@ -48,9 +48,11 @@ export const VirtualTableBodyContainer = (props: VirtualTableBodyContainerProps) useEffect(() => { if (parentRef.current) { + // Trigger one-time re-render after first render -> safe to set state here + // eslint-disable-next-line react-hooks/set-state-in-effect setIsMounted(true); } - }, [parentRef.current]); + }, [parentRef]); const dataLength = rows.length; @@ -102,16 +104,16 @@ export const VirtualTableBodyContainer = (props: VirtualTableBodyContainerProps) } }, [ + handleExternalScroll, infiniteScroll, infiniteScrollThreshold, - onLoadMore, - rows, internalRowHeight, - firedInfiniteLoadEvents, - lastScrollTop, - handleExternalScroll, + isGrouped, + onLoadMore, popInRowHeight, + rows, tableBodyHeight, + visibleRows, ], ); diff --git a/packages/main/src/components/AnalyticalTable/VerticalResizer.tsx b/packages/main/src/components/AnalyticalTable/VerticalResizer.tsx index 7351759ef69..192386aa8fe 100644 --- a/packages/main/src/components/AnalyticalTable/VerticalResizer.tsx +++ b/packages/main/src/components/AnalyticalTable/VerticalResizer.tsx @@ -9,7 +9,6 @@ interface VerticalResizerProps { analyticalTableRef: MutableRefObject; dispatch: (e: { type: string; payload?: any }) => void; extensionsHeight: number; - internalRowHeight: number; hasPopInColumns: boolean; popInRowHeight: number; rowsLength: number; @@ -30,7 +29,6 @@ export const VerticalResizer = (props: VerticalResizerProps) => { analyticalTableRef, dispatch, extensionsHeight, - internalRowHeight, hasPopInColumns, popInRowHeight, rowsLength, @@ -47,16 +45,13 @@ export const VerticalResizer = (props: VerticalResizerProps) => { const i18nBundle = useI18nBundle('@ui5/webcomponents-react'); - const handleResizeStart = useCallback( - (e) => { - e.preventDefault(); - const touchEvent = isTouchEvent(e, 'touchstart'); - startY.current = touchEvent ? Math.round(e.touches[0].pageY) : e.pageY; - setMountTouchEvents(touchEvent); - setIsDragging(true); - }, - [startY.current, setIsDragging], - ); + const handleResizeStart = useCallback((e) => { + e.preventDefault(); + const touchEvent = isTouchEvent(e, 'touchstart'); + startY.current = touchEvent ? Math.round(e.touches[0].pageY) : e.pageY; + setMountTouchEvents(touchEvent); + setIsDragging(true); + }, []); const handleMove = useCallback( (e) => { @@ -67,27 +62,27 @@ export const VerticalResizer = (props: VerticalResizerProps) => { }, [setResizerPosition], ); - const handleResizeEnd = useCallback( - (e) => { - setIsDragging(false); - const rowCount = Math.floor( - (analyticalTableRef.current.clientHeight + - (isTouchEvent(e, 'touchend') ? Math.round(e.changedTouches[0].pageY) : e.pageY) - - startY.current - - extensionsHeight - - 5) /*resizer height*/ / - popInRowHeight, - ); - if (hasPopInColumns) { - dispatch({ type: 'INTERACTIVE_ROWS_HAVE_POPIN', payload: true }); - } - dispatch({ - type: 'VISIBLE_ROWS', - payload: { visibleRows: rowCount }, - }); - }, - [analyticalTableRef.current?.clientHeight, startY.current, extensionsHeight, internalRowHeight, dispatch], - ); + const handleResizeEnd = (e: TouchEvent | MouseEvent) => { + setIsDragging(false); + const rowCount = Math.floor( + (analyticalTableRef.current.clientHeight + + (isTouchEvent(e, 'touchend') + ? Math.round((e as TouchEvent).changedTouches[0].pageY) + : (e as MouseEvent).pageY) - + startY.current - + extensionsHeight - + 5) /*resizer height*/ / + popInRowHeight, + ); + if (hasPopInColumns) { + dispatch({ type: 'INTERACTIVE_ROWS_HAVE_POPIN', payload: true }); + } + dispatch({ + type: 'VISIBLE_ROWS', + payload: { visibleRows: rowCount }, + }); + }; + useEffect(() => { const removeEventListeners = () => { if (mountTouchEvents) { @@ -119,15 +114,11 @@ export const VerticalResizer = (props: VerticalResizerProps) => { const resizerPosLeft = verticalResizerRef.current?.getBoundingClientRect()?.left + window.scrollX; const resizerPosWidth = verticalResizerRef.current?.getBoundingClientRect()?.width; if (!isDragging && resizerPosTop > 0) { - setResizerPosition({ left: resizerPosLeft, top: resizerPosTop, width: resizerPosWidth }); + requestAnimationFrame(() => { + setResizerPosition({ left: resizerPosLeft, top: resizerPosTop, width: resizerPosWidth }); + }); } - }, [verticalResizerRef.current?.getBoundingClientRect()?.top, isDragging]); - - useEffect(() => { - return () => { - dispatch({ type: 'WITH_POPIN', payload: false }); - }; - }, []); + }, [isDragging]); const isInitial = useRef(true); useEffect(() => { diff --git a/packages/main/src/components/AnalyticalTable/defaults/FilterComponent/index.tsx b/packages/main/src/components/AnalyticalTable/defaults/FilterComponent/index.tsx index 4949221fd08..52c54aecc40 100644 --- a/packages/main/src/components/AnalyticalTable/defaults/FilterComponent/index.tsx +++ b/packages/main/src/components/AnalyticalTable/defaults/FilterComponent/index.tsx @@ -5,12 +5,13 @@ import { Input } from '../../../../webComponents/Input/index.js'; import type { FilterProps } from '../../types/index.js'; export const DefaultFilterComponent = ({ column, accessibleNameRef }: FilterProps) => { + const { setFilter } = column; const handleInput: InputPropTypes['onInput'] = useCallback( (e) => { // Setting the filter to `undefined` removes it - column.setFilter(e.target.value || undefined); + setFilter(e.target.value || undefined); }, - [column.setFilter], + [setFilter], ); const handleKeyDown: InputPropTypes['onKeyDown'] = (e) => { diff --git a/packages/main/src/components/AnalyticalTable/hooks/useIsFirefox.ts b/packages/main/src/components/AnalyticalTable/hooks/useIsFirefox.ts index 05f1f5fdd41..d95f3e1e628 100644 --- a/packages/main/src/components/AnalyticalTable/hooks/useIsFirefox.ts +++ b/packages/main/src/components/AnalyticalTable/hooks/useIsFirefox.ts @@ -9,6 +9,8 @@ export function useIsFirefox() { const [isFirefox, setIsFirefox] = useState(false); useEffect(() => { + // safe here because we only update state after mount for SSR hydration + // eslint-disable-next-line react-hooks/set-state-in-effect setIsFirefox(isFirefoxFn()); }, []); diff --git a/packages/main/src/components/AnalyticalTable/hooks/useKeyboardNavigation.ts b/packages/main/src/components/AnalyticalTable/hooks/useKeyboardNavigation.ts index 84622d34f74..3b174cfccb7 100644 --- a/packages/main/src/components/AnalyticalTable/hooks/useKeyboardNavigation.ts +++ b/packages/main/src/components/AnalyticalTable/hooks/useKeyboardNavigation.ts @@ -68,6 +68,7 @@ const useGetTableProps = ( { instance: { webComponentsReactProperties, data, columns, state } }: { instance: TableInstance }, ) => { const { showOverlay, tableRef } = webComponentsReactProperties; + const { isRtl } = state; const currentlyFocusedCell = useRef(null); const noData = data.length === 0; @@ -153,12 +154,11 @@ const useGetTableProps = ( } } }, - [currentlyFocusedCell.current, tableRef.current, noData], + [noData, tableRef], ); const onKeyboardNavigation = useCallback( (e) => { - const { isRtl } = state; const isActiveItemInSubComponent = Object.prototype.hasOwnProperty.call( e.target.dataset, 'subcomponentActiveElement', @@ -284,6 +284,8 @@ const useGetTableProps = ( ); if (hasSubcomponent && !currentlyFocusedCell.current?.dataset?.subcomponent) { currentlyFocusedCell.current.tabIndex = -1; + // Happens outside of React's scope + // eslint-disable-next-line react-hooks/immutability firstChildOfParent.tabIndex = 0; firstChildOfParent.dataset.rowIndexSub = `${rowIndex}`; firstChildOfParent.dataset.columnIndexSub = `${columnIndex}`; @@ -325,7 +327,7 @@ const useGetTableProps = ( } } }, - [currentlyFocusedCell.current, tableRef.current, state?.isRtl], + [isRtl, tableRef], ); if (showOverlay) { return tableProps; diff --git a/packages/main/src/components/AnalyticalTable/index.tsx b/packages/main/src/components/AnalyticalTable/index.tsx index ceb970ad45c..aa6b6400c05 100644 --- a/packages/main/src/components/AnalyticalTable/index.tsx +++ b/packages/main/src/components/AnalyticalTable/index.tsx @@ -541,12 +541,6 @@ const AnalyticalTable = forwardRef { - if (tableState?.interactiveRowsHavePopIn && (!tableState?.popInColumns || tableState?.popInColumns?.length === 0)) { - dispatch({ type: 'WITH_POPIN', payload: false }); - } - }, [tableState?.interactiveRowsHavePopIn, tableState?.popInColumns?.length]); - const tableBodyHeight = useMemo(() => { if (typeof tableState.bodyHeight === 'number') { return tableState.bodyHeight; @@ -895,7 +889,6 @@ const AnalyticalTable = forwardRef?]; } -export interface ReactVirtualScrollToMethods { - scrollToOffset?: (offset: number, options?: ScrollToOptions) => void; - scrollToIndex?: (index: number, options?: ScrollToOptions) => void; - horizontalScrollToOffset?: (offset: number, options?: ScrollToOptions) => void; - horizontalScrollToIndex?: (index: number, options?: ScrollToOptions) => void; -} - interface PopInColumnsState { id: string; column: ColumnType;