From a31e1067cd7af1deaf0e0a27e0dc8b09ff1c0694 Mon Sep 17 00:00:00 2001
From: Alejandro Celaya <alejandro.celaya@hypothes.is>
Date: Fri, 18 Oct 2024 14:46:02 +0200
Subject: [PATCH] Use TS and JSX shared configs from eslint-config-hypothesis

---
 eslint.config.js                              |  40 +----
 package.json                                  |   4 +-
 scripts/generate-icons.js                     |   4 +-
 src/components/input/Select.tsx               |   2 +
 .../test/use-arrow-key-navigation-test.js     |   4 +-
 src/hooks/test/use-tab-key-navigation-test.js |   4 +-
 yarn.lock                                     | 138 ++++++++++--------
 7 files changed, 93 insertions(+), 103 deletions(-)

diff --git a/eslint.config.js b/eslint.config.js
index f601f7573..a6794a3d2 100644
--- a/eslint.config.js
+++ b/eslint.config.js
@@ -1,40 +1,16 @@
-import hypothesis from 'eslint-config-hypothesis';
-import jsxA11y from 'eslint-plugin-jsx-a11y';
+import hypothesisBase from 'eslint-config-hypothesis/base';
+import hypothesisJSX from 'eslint-config-hypothesis/jsx';
+import hypothesisTS from 'eslint-config-hypothesis/ts';
 import globals from 'globals';
-import tseslint from 'typescript-eslint';
 
-export default tseslint.config(
+export default [
   {
     ignores: ['.yalc/**', 'lib/**', 'build/**'],
   },
-  ...hypothesis,
-  ...tseslint.configs.recommended,
-  jsxA11y.flatConfigs.recommended,
-  {
-    rules: {
-      // Replaced by TypeScript's static checking.
-      'react/prop-types': 'off',
-      // Upgrade TS rules from warning to error.
-      '@typescript-eslint/no-unused-vars': 'error',
-
-      // Disable TS rules that we dislike.
-      '@typescript-eslint/ban-ts-comment': 'off',
-      '@typescript-eslint/no-empty-function': 'off',
-      '@typescript-eslint/no-explicit-any': 'off',
-      '@typescript-eslint/no-non-null-assertion': 'off',
-      '@typescript-eslint/no-this-alias': 'off',
 
-      // Enforce consistency in cases where TypeScript supports old and new
-      // syntaxes for the same thing.
-      //
-      // - Require `<var> as <type>` for casts
-      // - Require `import type` for type imports. The corresponding rule for
-      //   exports is not enabled yet because that requires setting up
-      //   type-aware linting.
-      '@typescript-eslint/consistent-type-assertions': 'error',
-      '@typescript-eslint/consistent-type-imports': 'error',
-    },
-  },
+  ...hypothesisBase,
+  ...hypothesisJSX,
+  ...hypothesisTS,
 
   // Icons
   {
@@ -56,4 +32,4 @@ export default tseslint.config(
       },
     },
   },
-);
+];
diff --git a/package.json b/package.json
index 4c1f00943..e1618ef01 100644
--- a/package.json
+++ b/package.json
@@ -28,7 +28,7 @@
     "enzyme": "^3.8.0",
     "enzyme-adapter-preact-pure": "^4.0.1",
     "eslint": "^9.12.0",
-    "eslint-config-hypothesis": "^3.0.0",
+    "eslint-config-hypothesis": "^3.1.0",
     "eslint-plugin-jsx-a11y": "^6.10.0",
     "eslint-plugin-mocha": "^10.5.0",
     "eslint-plugin-react": "^7.37.1",
@@ -56,7 +56,7 @@
     "svgo": "^3.0.0",
     "tailwindcss": "3.4.13",
     "typescript": "^5.0.2",
-    "typescript-eslint": "^8.9.0",
+    "typescript-eslint": "^8.10.0",
     "yalc": "^1.0.0-pre.50"
   },
   "peerDependencies": {
diff --git a/scripts/generate-icons.js b/scripts/generate-icons.js
index 610299201..1602ec34a 100644
--- a/scripts/generate-icons.js
+++ b/scripts/generate-icons.js
@@ -112,7 +112,7 @@ function generateIconIndex(componentDir) {
     file => file.endsWith('.tsx') && !file.includes('index'),
   );
   let outputSrc = `${AUTO_GENERATED_COMMENT}\n`;
-  for (let componentFile of iconComponents) {
+  for (const componentFile of iconComponents) {
     const componentModule = path.basename(componentFile, '.tsx');
     const componentName = `${componentModule}Icon`;
     outputSrc += `export { default as ${componentName} } from './${componentModule}';\n`;
@@ -133,7 +133,7 @@ const inputDir = argv[2] ?? 'images/icons';
 const outputDir = argv[3] ?? 'src/components/icons';
 
 const svgFiles = readdirSync(inputDir).filter(file => file.endsWith('.svg'));
-for (let file of svgFiles) {
+for (const file of svgFiles) {
   await generateIconFromFile(`${inputDir}/${file}`, outputDir);
 }
 
diff --git a/src/components/input/Select.tsx b/src/components/input/Select.tsx
index 8216ed27f..21b6f8066 100644
--- a/src/components/input/Select.tsx
+++ b/src/components/input/Select.tsx
@@ -588,6 +588,7 @@ function SelectMain<T>({
 }
 
 export const Select = Object.assign(
+  // eslint-disable-next-line prefer-arrow-callback
   function <T>(props: SelectProps<T>) {
     // Calling the function directly instead of returning a JSX element, to
     // avoid an unnecessary extra layer in the component tree
@@ -598,6 +599,7 @@ export const Select = Object.assign(
 );
 
 export const MultiSelect = Object.assign(
+  // eslint-disable-next-line prefer-arrow-callback
   function <T>(props: MultiSelectProps<T>) {
     // Calling the function directly instead of returning a JSX element, to
     // avoid an unnecessary extra layer in the component tree
diff --git a/src/hooks/test/use-arrow-key-navigation-test.js b/src/hooks/test/use-arrow-key-navigation-test.js
index 55c9b1174..b26a129ea 100644
--- a/src/hooks/test/use-arrow-key-navigation-test.js
+++ b/src/hooks/test/use-arrow-key-navigation-test.js
@@ -119,14 +119,14 @@ describe('useArrowKeyNavigation', () => {
         ['Home', 'Bold'],
       ];
 
-      for (let [key, expectedItem] of steps) {
+      for (const [key, expectedItem] of steps) {
         pressKey(key);
 
         const currentElement = document.activeElement;
         assert.equal(currentElement.innerText, expectedItem);
 
         const toolbarButtons = toolbar.querySelectorAll('a,button');
-        for (let element of toolbarButtons) {
+        for (const element of toolbarButtons) {
           if (element === currentElement) {
             assert.equal(element.tabIndex, 0);
           } else {
diff --git a/src/hooks/test/use-tab-key-navigation-test.js b/src/hooks/test/use-tab-key-navigation-test.js
index 0371104b5..b8194daed 100644
--- a/src/hooks/test/use-tab-key-navigation-test.js
+++ b/src/hooks/test/use-tab-key-navigation-test.js
@@ -122,14 +122,14 @@ describe('useTabKeyNavigation', () => {
       [backKey, 'Bold'],
     ];
 
-    for (let [key, expectedItem] of steps) {
+    for (const [key, expectedItem] of steps) {
       pressKey(key);
 
       const currentElement = document.activeElement;
       assert.equal(currentElement.innerText, expectedItem);
 
       const toolbarButtons = toolbar.querySelectorAll('a,button');
-      for (let element of toolbarButtons) {
+      for (const element of toolbarButtons) {
         if (element === currentElement) {
           assert.equal(element.tabIndex, 0);
         } else {
diff --git a/yarn.lock b/yarn.lock
index 955739c1e..36807d41f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1813,7 +1813,7 @@ __metadata:
     enzyme: ^3.8.0
     enzyme-adapter-preact-pure: ^4.0.1
     eslint: ^9.12.0
-    eslint-config-hypothesis: ^3.0.0
+    eslint-config-hypothesis: ^3.1.0
     eslint-plugin-jsx-a11y: ^6.10.0
     eslint-plugin-mocha: ^10.5.0
     eslint-plugin-react: ^7.37.1
@@ -1842,7 +1842,7 @@ __metadata:
     svgo: ^3.0.0
     tailwindcss: 3.4.13
     typescript: ^5.0.2
-    typescript-eslint: ^8.9.0
+    typescript-eslint: ^8.10.0
     wouter-preact: ^3.0.0
     yalc: ^1.0.0-pre.50
   peerDependencies:
@@ -2580,15 +2580,15 @@ __metadata:
   languageName: node
   linkType: hard
 
-"@typescript-eslint/eslint-plugin@npm:8.9.0":
-  version: 8.9.0
-  resolution: "@typescript-eslint/eslint-plugin@npm:8.9.0"
+"@typescript-eslint/eslint-plugin@npm:8.10.0":
+  version: 8.10.0
+  resolution: "@typescript-eslint/eslint-plugin@npm:8.10.0"
   dependencies:
     "@eslint-community/regexpp": ^4.10.0
-    "@typescript-eslint/scope-manager": 8.9.0
-    "@typescript-eslint/type-utils": 8.9.0
-    "@typescript-eslint/utils": 8.9.0
-    "@typescript-eslint/visitor-keys": 8.9.0
+    "@typescript-eslint/scope-manager": 8.10.0
+    "@typescript-eslint/type-utils": 8.10.0
+    "@typescript-eslint/utils": 8.10.0
+    "@typescript-eslint/visitor-keys": 8.10.0
     graphemer: ^1.4.0
     ignore: ^5.3.1
     natural-compare: ^1.4.0
@@ -2599,66 +2599,66 @@ __metadata:
   peerDependenciesMeta:
     typescript:
       optional: true
-  checksum: d72bda52eb26d184286e67ceaebff17d177bf021cfcf1c31d316385f4965c60620fd3ec7178c30092faa3f30d81c4cf54ef2563c4bb0fd361e9967d2e6e64d22
+  checksum: 2bb311eb9a882d530fc94f790f3e1f4745cd4e3523fd8d62ee0ed14d65c4230dc0c797c490c3421c1456fd71349e9bfa146c0b78f63860b75aae6e2a32a6c27c
   languageName: node
   linkType: hard
 
-"@typescript-eslint/parser@npm:8.9.0":
-  version: 8.9.0
-  resolution: "@typescript-eslint/parser@npm:8.9.0"
+"@typescript-eslint/parser@npm:8.10.0":
+  version: 8.10.0
+  resolution: "@typescript-eslint/parser@npm:8.10.0"
   dependencies:
-    "@typescript-eslint/scope-manager": 8.9.0
-    "@typescript-eslint/types": 8.9.0
-    "@typescript-eslint/typescript-estree": 8.9.0
-    "@typescript-eslint/visitor-keys": 8.9.0
+    "@typescript-eslint/scope-manager": 8.10.0
+    "@typescript-eslint/types": 8.10.0
+    "@typescript-eslint/typescript-estree": 8.10.0
+    "@typescript-eslint/visitor-keys": 8.10.0
     debug: ^4.3.4
   peerDependencies:
     eslint: ^8.57.0 || ^9.0.0
   peerDependenciesMeta:
     typescript:
       optional: true
-  checksum: b7d899cca2834ab030c672693e9bdbc442b8026710af0e06cb89c162d81c43a5c777f90568cd9ea3ac5b689bbf161c8f7fcecd58989e0238bb45aec10567c26a
+  checksum: 2e38f34d9d044e251450116cc081a8f84ba13183e9c3e1dda919ddc00eebe634a37d4dfd785998f259b64cdd770e863ecc6c5cf7c8f422baf3d2bc2a0f9241cf
   languageName: node
   linkType: hard
 
-"@typescript-eslint/scope-manager@npm:8.9.0":
-  version: 8.9.0
-  resolution: "@typescript-eslint/scope-manager@npm:8.9.0"
+"@typescript-eslint/scope-manager@npm:8.10.0":
+  version: 8.10.0
+  resolution: "@typescript-eslint/scope-manager@npm:8.10.0"
   dependencies:
-    "@typescript-eslint/types": 8.9.0
-    "@typescript-eslint/visitor-keys": 8.9.0
-  checksum: 56b71993f3b8da3fe6947710d1ead8afb128d194994e0d82052799c2b05a017735649d4dcf897d2ea63b28c8633336342d3efd269c2910d6d06e2784f248a22c
+    "@typescript-eslint/types": 8.10.0
+    "@typescript-eslint/visitor-keys": 8.10.0
+  checksum: 3df8df342e227b80514dcc9151774dea9a71bc649204f702d5b4a1b76a54b4814c5d5a970a6a9213462dd4df0d42342796fab35549e8663d4c0e5d84bd902bba
   languageName: node
   linkType: hard
 
-"@typescript-eslint/type-utils@npm:8.9.0":
-  version: 8.9.0
-  resolution: "@typescript-eslint/type-utils@npm:8.9.0"
+"@typescript-eslint/type-utils@npm:8.10.0":
+  version: 8.10.0
+  resolution: "@typescript-eslint/type-utils@npm:8.10.0"
   dependencies:
-    "@typescript-eslint/typescript-estree": 8.9.0
-    "@typescript-eslint/utils": 8.9.0
+    "@typescript-eslint/typescript-estree": 8.10.0
+    "@typescript-eslint/utils": 8.10.0
     debug: ^4.3.4
     ts-api-utils: ^1.3.0
   peerDependenciesMeta:
     typescript:
       optional: true
-  checksum: e4422ad2da0e73c1d503fd5cc72f873b20329c4fa55e4a88f201b7d02a6946b08a62d3a2ce53f6020d52db76c321b927b8e06a68e44b2a4f50b26967c75a27ff
+  checksum: 8b0cec8cff1926a08c2bd675b24b2ccff36e59a8d9169eed38343f70c4e3bba18796fc39f30a9307ded3f345881aded80dbd6dc1d78b9ae76cff04fbe8708788
   languageName: node
   linkType: hard
 
-"@typescript-eslint/types@npm:8.9.0":
-  version: 8.9.0
-  resolution: "@typescript-eslint/types@npm:8.9.0"
-  checksum: bb79e8774b2c521d738d76efe6c61f5aa7f700765cf025410a5c37ca0449ed436c500a5c8cd3a4343edd5257301d4b0cfcd56275cc9bca992585e9dac76612bf
+"@typescript-eslint/types@npm:8.10.0":
+  version: 8.10.0
+  resolution: "@typescript-eslint/types@npm:8.10.0"
+  checksum: 3839fd43b0f21b432a9f6090a39d5b2254ee48c1eecf14f8f66bea0cbaba9f2f33a7fc78aea37dfe8841442332d0a8f99cc65cd2d01ca43db99550d30d6f7fe8
   languageName: node
   linkType: hard
 
-"@typescript-eslint/typescript-estree@npm:8.9.0":
-  version: 8.9.0
-  resolution: "@typescript-eslint/typescript-estree@npm:8.9.0"
+"@typescript-eslint/typescript-estree@npm:8.10.0":
+  version: 8.10.0
+  resolution: "@typescript-eslint/typescript-estree@npm:8.10.0"
   dependencies:
-    "@typescript-eslint/types": 8.9.0
-    "@typescript-eslint/visitor-keys": 8.9.0
+    "@typescript-eslint/types": 8.10.0
+    "@typescript-eslint/visitor-keys": 8.10.0
     debug: ^4.3.4
     fast-glob: ^3.3.2
     is-glob: ^4.0.3
@@ -2668,31 +2668,31 @@ __metadata:
   peerDependenciesMeta:
     typescript:
       optional: true
-  checksum: 307b317c2ac45b83cbf2e5f45b6fd3615279c7ad8b105fa09004d6e415187d9ad1647ec205fcee017fdf2985192c469f9bad738f70cc754da4ba807d8d0d90ae
+  checksum: 3fc774f51d0a891a5e09bc77f5544b6aa268abec9c01cd9ec831f92dde9c9d61a5c818ca2800c124fb5d61d40ce7ac34740b347c21ba3493e756c052084afd65
   languageName: node
   linkType: hard
 
-"@typescript-eslint/utils@npm:8.9.0":
-  version: 8.9.0
-  resolution: "@typescript-eslint/utils@npm:8.9.0"
+"@typescript-eslint/utils@npm:8.10.0":
+  version: 8.10.0
+  resolution: "@typescript-eslint/utils@npm:8.10.0"
   dependencies:
     "@eslint-community/eslint-utils": ^4.4.0
-    "@typescript-eslint/scope-manager": 8.9.0
-    "@typescript-eslint/types": 8.9.0
-    "@typescript-eslint/typescript-estree": 8.9.0
+    "@typescript-eslint/scope-manager": 8.10.0
+    "@typescript-eslint/types": 8.10.0
+    "@typescript-eslint/typescript-estree": 8.10.0
   peerDependencies:
     eslint: ^8.57.0 || ^9.0.0
-  checksum: 23bb2a054fcad2e5a3bb2ab9173614b2257f42a5a704434de3d81e478ca5444f1989e317a8044d6e39ef000a938316c7bc175286d595e17933e35e573a430f4c
+  checksum: db67603baacba9cccbbc625801a44e5320bc558be846646ff9962818c64a9ab07edcfdcad98b15a3f8954d3e398e3a41f085c1ec458f7169a1ce7b3674032d59
   languageName: node
   linkType: hard
 
-"@typescript-eslint/visitor-keys@npm:8.9.0":
-  version: 8.9.0
-  resolution: "@typescript-eslint/visitor-keys@npm:8.9.0"
+"@typescript-eslint/visitor-keys@npm:8.10.0":
+  version: 8.10.0
+  resolution: "@typescript-eslint/visitor-keys@npm:8.10.0"
   dependencies:
-    "@typescript-eslint/types": 8.9.0
+    "@typescript-eslint/types": 8.10.0
     eslint-visitor-keys: ^3.4.3
-  checksum: 9afb7eabfc6d279e714b80e283e062f0c2a90e2adbde1c2d2fbc6cecd6444c6e76867599f6a781b847981d02f7956748bd3ecb7abc4770ab7e77c6709693b530
+  checksum: 0b3060a036dd3b6acacc32b1d81b3ada1ac5523cc2d16a369ecffd3ab5b389cd98802b248bf65ee8a266a166125a9e38acd7e917d4dd26044bdf2c805537b7e3
   languageName: node
   linkType: hard
 
@@ -5171,14 +5171,26 @@ __metadata:
   languageName: node
   linkType: hard
 
-"eslint-config-hypothesis@npm:^3.0.0":
-  version: 3.0.0
-  resolution: "eslint-config-hypothesis@npm:3.0.0"
+"eslint-config-hypothesis@npm:^3.1.0":
+  version: 3.1.0
+  resolution: "eslint-config-hypothesis@npm:3.1.0"
   peerDependencies:
+    eslint-plugin-jsx-a11y: ">=6.10.0"
     eslint-plugin-mocha: ">=10.4.0"
     eslint-plugin-react: ">=7.34.0"
     eslint-plugin-react-hooks: ">=5.0.0"
-  checksum: 1194156f2d043ed866afe9ccd88d7364cdf8635cb9d762d24beffb03ee02a25d44081b58d95c5b1a658e686053948d8b2493e65f4de540e14d72ae83c35c31fe
+    globals: ">=15.11.0"
+    typescript-eslint: ">=8.10.0"
+  peerDependenciesMeta:
+    eslint-plugin-jsx-a11y:
+      optional: true
+    eslint-plugin-react:
+      optional: true
+    eslint-plugin-react-hooks:
+      optional: true
+    typescript-eslint:
+      optional: true
+  checksum: 12e17da643a306fec1c8121bf5f172f2132f816d85b2b6f626dc16d353f5cbac8bee0cce080a9df829c5eab3e4bcc007bb611ec6f5d9deebd627e530802c05f6
   languageName: node
   linkType: hard
 
@@ -11324,17 +11336,17 @@ __metadata:
   languageName: node
   linkType: hard
 
-"typescript-eslint@npm:^8.9.0":
-  version: 8.9.0
-  resolution: "typescript-eslint@npm:8.9.0"
+"typescript-eslint@npm:^8.10.0":
+  version: 8.10.0
+  resolution: "typescript-eslint@npm:8.10.0"
   dependencies:
-    "@typescript-eslint/eslint-plugin": 8.9.0
-    "@typescript-eslint/parser": 8.9.0
-    "@typescript-eslint/utils": 8.9.0
+    "@typescript-eslint/eslint-plugin": 8.10.0
+    "@typescript-eslint/parser": 8.10.0
+    "@typescript-eslint/utils": 8.10.0
   peerDependenciesMeta:
     typescript:
       optional: true
-  checksum: 6c54e7360e51fdbf1bc0d00f592949bb72e9c85d1b93145e9e7ad4e8259bf11784ebe035210c8f0a29e4f137ad268e22714d09bf82db1917258626d526a117a9
+  checksum: cf0ead50af444a887097f2ed6cf854c318082e5cebde92c218b7616086b844af0a8e80e8b9e946de7f582ed8ed96934c91d27a816130611217c1e9d34d59f20d
   languageName: node
   linkType: hard