@nihalgonsalves/esconfig 0.15.0 → 0.16.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/.oxlintrc.json CHANGED
@@ -8,14 +8,6 @@
8
8
  "env": {
9
9
  "builtin": true
10
10
  },
11
- "overrides": [
12
- {
13
- "files": ["**/*.config.*"],
14
- "rules": {
15
- "import/no-default-export": "off"
16
- }
17
- }
18
- ],
19
11
  "plugins": ["typescript", "import", "unicorn"],
20
12
  "rules": {
21
13
  // 2026-02-16 migration from eslint skipped 15 unsupported rules
@@ -280,5 +272,37 @@
280
272
  "typescript/use-unknown-in-catch-callback-variable": "error",
281
273
  "use-isnan": "error",
282
274
  "valid-typeof": "error"
283
- }
275
+ },
276
+ "overrides": [
277
+ {
278
+ "files": ["**/*.config.*", "**/.storybook/**/*", "**/*.stories.tsx"],
279
+ "rules": {
280
+ "import/no-default-export": "off"
281
+ }
282
+ },
283
+ {
284
+ "files": ["**/*.test.ts"],
285
+ "rules": {
286
+ "eslint/no-await-in-loop": "off",
287
+ "typescript/ban-ts-comment": [
288
+ "error",
289
+ {
290
+ "ts-expect-error": false,
291
+ "ts-ignore": true,
292
+ "ts-nocheck": true,
293
+ "ts-check": false
294
+ }
295
+ ]
296
+ }
297
+ },
298
+ {
299
+ "files": ["**/*.d.ts"],
300
+ "rules": {
301
+ "typescript/no-empty-object-type": "off",
302
+ "typescript/consistent-type-definitions": "off",
303
+ "typescript/consistent-indexed-object-style": "off",
304
+ "unicorn/require-module-specifiers": "off"
305
+ }
306
+ }
307
+ ]
284
308
  }
@@ -0,0 +1,392 @@
1
+ {
2
+ "$schema": "./node_modules/oxlint/configuration_schema.json",
3
+ "categories": {
4
+ "correctness": "error",
5
+ "suspicious": "error",
6
+ "perf": "error"
7
+ },
8
+ "env": {
9
+ "builtin": true
10
+ },
11
+ "plugins": ["react", "jsx-a11y"],
12
+ "jsPlugins": [{ "name": "react-hooks-js", "specifier": "eslint-plugin-react-hooks" }],
13
+ "rules": {
14
+ "no-restricted-globals": [
15
+ "error",
16
+ {
17
+ "name": "React",
18
+ "message": "import { ... } from \"react\" instead"
19
+ },
20
+ {
21
+ "name": "location",
22
+ "message": "useLocation from your router package, or access window.location"
23
+ }
24
+ ],
25
+ "no-restricted-imports": [
26
+ "error",
27
+ {
28
+ "paths": [
29
+ {
30
+ "name": "react",
31
+ "importNames": ["default"],
32
+ "message": "import { ... } from \"react\" instead"
33
+ },
34
+ {
35
+ "name": "react",
36
+ "importNames": ["useContext"],
37
+ "message": "Use `use()` instead"
38
+ },
39
+ {
40
+ "name": "react",
41
+ "importNames": ["forwardRef"],
42
+ "message": "Use a ref prop instead"
43
+ }
44
+ ]
45
+ }
46
+ ],
47
+
48
+ // eslint-plugin-react recommended + jsx-runtime rules
49
+ "react/display-name": "error",
50
+ // "react/jsx-key": "error",
51
+ "react/jsx-no-comment-textnodes": "error",
52
+ "react/jsx-no-duplicate-props": "error",
53
+ "react/jsx-no-target-blank": "error",
54
+ "react/jsx-no-undef": "error",
55
+ "react/no-children-prop": "error",
56
+ "react/no-danger-with-children": "error",
57
+ "react/no-direct-mutation-state": "error",
58
+ "react/no-find-dom-node": "error",
59
+ "react/no-is-mounted": "error",
60
+ "react/no-render-return-value": "error",
61
+ "react/no-string-refs": "error",
62
+ "react/no-unescaped-entities": "error",
63
+ "react/no-unknown-property": "error",
64
+ "react/require-render-return": "error",
65
+ "react-hooks/rules-of-hooks": "error",
66
+ // "react-hooks/exhaustive-deps": "warn",
67
+
68
+ // custom react
69
+ "react/jsx-boolean-value": [
70
+ "error",
71
+ "never",
72
+ {
73
+ "always": []
74
+ }
75
+ ],
76
+ "react/jsx-pascal-case": [
77
+ "error",
78
+ {
79
+ "allowAllCaps": true,
80
+ "ignore": []
81
+ }
82
+ ],
83
+ "react/no-danger": "warn",
84
+ "react/no-will-update-set-state": "error",
85
+ "react/prefer-es6-class": ["error", "always"],
86
+ "react/self-closing-comp": "error",
87
+ "react/jsx-filename-extension": [
88
+ "error",
89
+ {
90
+ "extensions": [".jsx", ".tsx"]
91
+ }
92
+ ],
93
+ "react/style-prop-object": "error",
94
+ "react/no-array-index-key": "error",
95
+ "react/void-dom-elements-no-children": "error",
96
+ "react/no-redundant-should-component-update": "error",
97
+ "react/jsx-curly-brace-presence": [
98
+ "error",
99
+ {
100
+ "props": "never",
101
+ "children": "never"
102
+ }
103
+ ],
104
+ "react/button-has-type": [
105
+ "error",
106
+ {
107
+ "button": true,
108
+ "submit": true,
109
+ "reset": false
110
+ }
111
+ ],
112
+ "react/no-this-in-sfc": "error",
113
+ "react/jsx-fragments": ["error", "syntax"],
114
+ "react/state-in-constructor": ["error", "never"],
115
+ "react/jsx-no-script-url": [
116
+ "error",
117
+ [
118
+ {
119
+ "name": "Link",
120
+ "props": ["to"]
121
+ }
122
+ ]
123
+ ],
124
+ "react/jsx-no-useless-fragment": [
125
+ "error",
126
+ {
127
+ "allowExpressions": true
128
+ }
129
+ ],
130
+ "react/jsx-no-constructed-context-values": "error",
131
+ "react/no-namespace": "error",
132
+ "react/iframe-missing-sandbox": "error",
133
+ "react-hooks/exhaustive-deps": "error",
134
+ "react/jsx-key": [
135
+ "error",
136
+ {
137
+ "checkFragmentShorthand": true,
138
+ "checkKeyMustBeforeSpread": true,
139
+ "warnOnDuplicates": true
140
+ }
141
+ ],
142
+ // not implemented in oxlint yet:
143
+ // - react/jsx-no-bind
144
+ // - react/no-did-update-set-state
145
+ // - react/prefer-stateless-function
146
+ // - react/destructuring-assignment
147
+ // - react/no-unstable-nested-components
148
+ // - react/no-arrow-function-lifecycle
149
+ // - react/no-invalid-html-attribute
150
+ // - react/hook-use-state
151
+ // - react/jsx-no-leaked-render
152
+
153
+ // react-compiler
154
+ // https://github.com/oxc-project/oxc/issues/10048
155
+ "react-hooks-js/set-state-in-effect": "error",
156
+ "react-hooks-js/preserve-manual-memoization": "error",
157
+ "react-hooks-js/refs": "error",
158
+ "react-hooks-js/immutability": "error",
159
+ "react-hooks-js/error-boundaries": "error",
160
+
161
+ // custom jsx-a11y rules
162
+ "jsx-a11y/alt-text": [
163
+ "error",
164
+ {
165
+ "elements": ["img", "object", "area", "input[type=\"image\"]"],
166
+ "img": [],
167
+ "object": [],
168
+ "area": [],
169
+ "input[type=\"image\"]": []
170
+ }
171
+ ],
172
+ "jsx-a11y/anchor-has-content": "error",
173
+ "jsx-a11y/anchor-is-valid": [
174
+ "error",
175
+ {
176
+ "components": ["Link"],
177
+ "specialLink": ["to"],
178
+ "aspects": ["noHref", "invalidHref", "preferButton"]
179
+ }
180
+ ],
181
+ "jsx-a11y/aria-activedescendant-has-tabindex": "error",
182
+ "jsx-a11y/aria-props": "error",
183
+ "jsx-a11y/aria-proptypes": "error",
184
+ "jsx-a11y/aria-role": [
185
+ "error",
186
+ {
187
+ "ignoreNonDOM": false
188
+ }
189
+ ],
190
+ "jsx-a11y/aria-unsupported-elements": "error",
191
+ "jsx-a11y/autocomplete-valid": [
192
+ "error",
193
+ {
194
+ "inputComponents": []
195
+ }
196
+ ],
197
+ "jsx-a11y/click-events-have-key-events": "error",
198
+ "jsx-a11y/heading-has-content": [
199
+ "error",
200
+ {
201
+ "components": [""]
202
+ }
203
+ ],
204
+ "jsx-a11y/html-has-lang": "error",
205
+ "jsx-a11y/iframe-has-title": "error",
206
+ "jsx-a11y/img-redundant-alt": "error",
207
+ "jsx-a11y/label-has-associated-control": [
208
+ "error",
209
+ {
210
+ "labelComponents": [],
211
+ "labelAttributes": [],
212
+ "controlComponents": [],
213
+ "assert": "both",
214
+ "depth": 25
215
+ }
216
+ ],
217
+ "jsx-a11y/lang": "error",
218
+ "jsx-a11y/media-has-caption": [
219
+ "error",
220
+ {
221
+ "audio": [],
222
+ "video": [],
223
+ "track": []
224
+ }
225
+ ],
226
+ "jsx-a11y/mouse-events-have-key-events": "error",
227
+ "jsx-a11y/no-access-key": "error",
228
+ "jsx-a11y/no-autofocus": [
229
+ "error",
230
+ {
231
+ "ignoreNonDOM": true
232
+ }
233
+ ],
234
+ "jsx-a11y/no-distracting-elements": [
235
+ "error",
236
+ {
237
+ "elements": ["marquee", "blink"]
238
+ }
239
+ ],
240
+ "jsx-a11y/no-noninteractive-tabindex": [
241
+ "error",
242
+ {
243
+ "tags": [],
244
+ "roles": ["tabpanel"],
245
+ "allowExpressionValues": true
246
+ }
247
+ ],
248
+ "jsx-a11y/no-redundant-roles": "error",
249
+ "jsx-a11y/no-static-element-interactions": [
250
+ "error",
251
+ {
252
+ "handlers": ["onClick", "onMouseDown", "onMouseUp", "onKeyPress", "onKeyDown", "onKeyUp"]
253
+ }
254
+ ],
255
+ "jsx-a11y/role-has-required-aria-props": "error",
256
+ "jsx-a11y/role-supports-aria-props": "error",
257
+ "jsx-a11y/scope": "error",
258
+ "jsx-a11y/tabindex-no-positive": "error"
259
+ // not implemented in oxlint yet:
260
+ // - jsx-a11y/control-has-associated-label
261
+ // - jsx-a11y/interactive-supports-focus
262
+ // - jsx-a11y/no-interactive-element-to-noninteractive-role
263
+ // - jsx-a11y/no-noninteractive-element-interactions
264
+ // - jsx-a11y/no-noninteractive-element-to-interactive-role
265
+ },
266
+ "overrides": [
267
+ {
268
+ "files": ["**/*.test.{ts,tsx,js,jsx,mjs,cjs}", "**/*.stories.{ts,tsx,js,jsx,mjs,cjs}"],
269
+ "plugins": ["vitest"],
270
+ "jsPlugins": ["eslint-plugin-jest-dom", "eslint-plugin-testing-library"],
271
+ "rules": {
272
+ // Vitest recommended
273
+ "vitest/expect-expect": "error",
274
+ "vitest/no-conditional-expect": "error",
275
+ "vitest/no-disabled-tests": "warn",
276
+ "vitest/no-focused-tests": "error",
277
+ "vitest/no-commented-out-tests": "error",
278
+ "vitest/no-identical-title": "error",
279
+ "vitest/no-import-node-test": "error",
280
+ "vitest/no-interpolation-in-snapshots": "error",
281
+ "vitest/no-mocks-import": "error",
282
+ "vitest/no-standalone-expect": "error",
283
+ "vitest/no-unneeded-async-expect-function": "error",
284
+ "vitest/require-local-test-context-for-concurrent-snapshots": "error",
285
+ "vitest/valid-describe-callback": "error",
286
+ "vitest/valid-expect": "error",
287
+
288
+ // Vitest custom
289
+ "vitest/consistent-test-filename": "error",
290
+ "vitest/consistent-test-it": [
291
+ "error",
292
+ {
293
+ "fn": "it",
294
+ "withinDescribe": "it"
295
+ }
296
+ ],
297
+ "vitest/no-test-prefixes": "error",
298
+ "vitest/prefer-comparison-matcher": "error",
299
+ "vitest/prefer-each": "error",
300
+ "vitest/prefer-equality-matcher": "error",
301
+ "vitest/prefer-expect-resolves": "error",
302
+ "vitest/prefer-hooks-in-order": "error",
303
+ "vitest/prefer-hooks-on-top": "error",
304
+ "vitest/prefer-mock-promise-shorthand": "error",
305
+ "vitest/prefer-strict-equal": "error",
306
+ "vitest/prefer-to-be": "error",
307
+ "vitest/prefer-to-be-object": "error",
308
+ "vitest/prefer-to-contain": "error",
309
+ "vitest/prefer-to-have-length": "error",
310
+ "vitest/prefer-todo": "error",
311
+ "vitest/require-to-throw-message": "error",
312
+ // not implemented in oxlint yet:
313
+ // - vitest/prefer-called-exactly-once-with
314
+ // - vitest/valid-expect-in-promise
315
+ // - vitest/valid-title
316
+ // - vitest/padding-around-after-all-blocks
317
+ // - vitest/padding-around-after-each-blocks
318
+ // - vitest/padding-around-before-all-blocks
319
+ // - vitest/padding-around-before-each-blocks
320
+ // - vitest/padding-around-describe-blocks
321
+ // - vitest/padding-around-test-blocks
322
+ // - vitest/prefer-vi-mocked
323
+
324
+ // jest-dom recommended
325
+ "jest-dom/prefer-checked": "error",
326
+ "jest-dom/prefer-empty": "error",
327
+ "jest-dom/prefer-enabled-disabled": "error",
328
+ "jest-dom/prefer-focus": "error",
329
+ "jest-dom/prefer-in-document": "error",
330
+ "jest-dom/prefer-required": "error",
331
+ "jest-dom/prefer-to-have-attribute": "error",
332
+ "jest-dom/prefer-to-have-class": "error",
333
+ "jest-dom/prefer-to-have-style": "error",
334
+ "jest-dom/prefer-to-have-text-content": "error",
335
+ "jest-dom/prefer-to-have-value": "error",
336
+
337
+ // testing-library recommended
338
+ "testing-library/await-async-events": [
339
+ "error",
340
+ {
341
+ "eventModule": "userEvent"
342
+ }
343
+ ],
344
+ "testing-library/await-async-queries": "error",
345
+ "testing-library/await-async-utils": "error",
346
+ "testing-library/no-await-sync-events": [
347
+ "error",
348
+ {
349
+ "eventModules": ["fire-event"]
350
+ }
351
+ ],
352
+ "testing-library/no-await-sync-queries": "error",
353
+ "testing-library/no-container": "error",
354
+ "testing-library/no-debugging-utils": "warn",
355
+ "testing-library/no-dom-import": ["error", "react"],
356
+ "testing-library/no-global-regexp-flag-in-query": "error",
357
+ "testing-library/no-manual-cleanup": "error",
358
+ "testing-library/no-node-access": "error",
359
+ "testing-library/no-promise-in-fire-event": "error",
360
+ "testing-library/no-render-in-lifecycle": "error",
361
+ "testing-library/no-unnecessary-act": "error",
362
+ "testing-library/no-wait-for-multiple-assertions": "error",
363
+ "testing-library/no-wait-for-side-effects": "error",
364
+ "testing-library/no-wait-for-snapshot": "error",
365
+ "testing-library/prefer-find-by": "error",
366
+ "testing-library/prefer-presence-queries": "error",
367
+ "testing-library/prefer-query-by-disappearance": "error",
368
+ "testing-library/prefer-screen-queries": "error",
369
+ "testing-library/render-result-naming-convention": "error"
370
+ }
371
+ },
372
+ {
373
+ "files": ["**/*.stories.{ts,tsx,js,jsx,mjs,cjs}"],
374
+ "jsPlugins": ["eslint-plugin-storybook"],
375
+ "rules": {
376
+ // Storybook recommended + csf
377
+ "react-hooks/rules-of-hooks": "off",
378
+ "storybook/await-interactions": "error",
379
+ "storybook/context-in-play-function": "error",
380
+ "storybook/default-exports": "error",
381
+ "storybook/hierarchy-separator": "warn",
382
+ "storybook/no-redundant-story-name": "warn",
383
+ "storybook/no-renderer-packages": "error",
384
+ "storybook/prefer-pascal-case": "warn",
385
+ "storybook/csf-component": "warn",
386
+ "storybook/story-exports": "error",
387
+ "storybook/no-stories-of": "error",
388
+ "storybook/no-title-property-in-meta": "error"
389
+ }
390
+ }
391
+ ]
392
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nihalgonsalves/esconfig",
3
- "version": "0.15.0",
3
+ "version": "0.16.1",
4
4
  "description": "Shared ECMAScript Config (TypeScript, oxlint, oxfmt, eslint)",
5
5
  "license": "MIT",
6
6
  "author": "Nihal Gonsalves <nihal@nihalgonsalves.com>",
@@ -10,9 +10,8 @@
10
10
  },
11
11
  "files": [
12
12
  ".oxlintrc.json",
13
+ ".oxlintrc.react.json",
13
14
  ".oxfmt.json",
14
- "eslint.config.react-shared.js",
15
- "eslint.config.react-shared.d.ts",
16
15
  "tsconfig.shared.json"
17
16
  ],
18
17
  "type": "module",
@@ -20,34 +19,41 @@
20
19
  "publishConfig": {
21
20
  "provenance": true
22
21
  },
23
- "dependencies": {
24
- "@vitest/eslint-plugin": "^1.6.9",
25
- "eslint-config-prettier": "^10.1.8",
26
- "eslint-plugin-jest-dom": "^5.5.0",
27
- "eslint-plugin-jsx-a11y": "^6.10.2",
28
- "eslint-plugin-react": "^7.37.5",
29
- "eslint-plugin-react-hooks": "^7.0.1",
30
- "eslint-plugin-storybook": "^10.2.10",
31
- "eslint-plugin-testing-library": "^7.16.0"
32
- },
22
+ "dependencies": {},
33
23
  "devDependencies": {
34
24
  "@commitlint/cli": "^20.4.2",
35
25
  "@commitlint/config-conventional": "^20.4.2",
36
- "@types/node": "^24.10.13",
37
- "eslint": "^10.0.1",
26
+ "@types/node": "^24.11.0",
38
27
  "knip": "^5.85.0",
39
- "lefthook": "^2.1.1",
40
- "oxfmt": "^0.35.0",
41
- "oxlint": "^1.50.0",
42
- "oxlint-tsgolint": "^0.14.2",
28
+ "lefthook": "^2.1.2",
29
+ "oxfmt": "^0.36.0",
30
+ "oxlint": "^1.51.0",
31
+ "oxlint-tsgolint": "^0.15.0",
43
32
  "typescript": "^5.9.3"
44
33
  },
45
34
  "peerDependencies": {
46
- "eslint": "^10.0.1",
47
- "oxlint": "^1.50.0",
35
+ "eslint-plugin-jest-dom": "^5.5.0",
36
+ "eslint-plugin-react-hooks": "^7.0.1",
37
+ "eslint-plugin-storybook": "^10.2.12",
38
+ "eslint-plugin-testing-library": "^7.16.0",
39
+ "oxlint": "^1.51.0",
48
40
  "oxlint-tsgolint": "^0.14.2",
49
41
  "typescript": "^5.9.3"
50
42
  },
43
+ "peerDependenciesMeta": {
44
+ "eslint-plugin-jest-dom": {
45
+ "optional": true
46
+ },
47
+ "eslint-plugin-react-hooks": {
48
+ "optional": true
49
+ },
50
+ "eslint-plugin-storybook": {
51
+ "optional": true
52
+ },
53
+ "eslint-plugin-testing-library": {
54
+ "optional": true
55
+ }
56
+ },
51
57
  "scripts": {
52
58
  "typecheck": "tsc --noEmit",
53
59
  "lint": "oxlint --type-aware --report-unused-disable-directives-severity=error && knip",
@@ -1,5 +0,0 @@
1
- import type { defineConfig } from "eslint/config";
2
-
3
- declare const sharedConfig: ReturnType<typeof defineConfig>;
4
-
5
- export default sharedConfig;
@@ -1,430 +0,0 @@
1
- import vitest from "@vitest/eslint-plugin";
2
- import prettierConfig from "eslint-config-prettier";
3
- import jestDom from "eslint-plugin-jest-dom";
4
- // @ts-expect-error no types
5
- import jsxA11y from "eslint-plugin-jsx-a11y";
6
- import react from "eslint-plugin-react";
7
- import reactHooks from "eslint-plugin-react-hooks";
8
- import { configs as storybookConfigs } from "eslint-plugin-storybook";
9
- import testingLibrary from "eslint-plugin-testing-library";
10
- import { defineConfig } from "eslint/config";
11
-
12
- export default defineConfig(
13
- {
14
- ignores: [
15
- // https://github.com/storybookjs/eslint-plugin-storybook?tab=readme-ov-file#installation
16
- "!**/*/.storybook",
17
- ],
18
- },
19
- // @ts-expect-error wrong types
20
- react.configs.flat["recommended-latest"],
21
- react.configs.flat["jsx-runtime"],
22
- reactHooks.configs["recommended-latest"],
23
- {
24
- plugins: {
25
- "react-hooks": reactHooks,
26
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
27
- "jsx-a11y": jsxA11y,
28
- },
29
- settings: {
30
- react: { version: "detect" },
31
- },
32
- rules: {
33
- "no-restricted-globals": [
34
- "error",
35
- {
36
- name: "React",
37
- message: 'import { ... } from "react" instead',
38
- },
39
- {
40
- name: "location",
41
- message: "useLocation from your router package, or access window.location",
42
- },
43
- ],
44
- "no-restricted-imports": [
45
- "error",
46
- {
47
- paths: [
48
- {
49
- name: "react",
50
- importNames: ["default"],
51
- message: 'import { ... } from "react" instead',
52
- },
53
- // TODO: https://eslint-react.xyz has dedicated rules
54
- {
55
- name: "react",
56
- importNames: ["useContext"],
57
- message: "Use `use()` instead",
58
- },
59
- {
60
- name: "react",
61
- importNames: ["forwardRef"],
62
- message: "Use a prop instead",
63
- },
64
- ],
65
- },
66
- ],
67
- "react/react-in-jsx-scope": "off",
68
- "react/checked-requires-onchange-or-readonly": [
69
- "off",
70
- {
71
- ignoreMissingProperties: false,
72
- ignoreExclusiveCheckedAttribute: false,
73
- },
74
- ],
75
- "react/forbid-prop-types": [
76
- "error",
77
- {
78
- forbid: ["any", "array", "object"],
79
- checkContextTypes: true,
80
- checkChildContextTypes: true,
81
- },
82
- ],
83
- "react/jsx-boolean-value": ["error", "never", { always: [] }],
84
- "react/jsx-handler-names": [
85
- "off",
86
- {
87
- eventHandlerPrefix: "handle",
88
- eventHandlerPropPrefix: "on",
89
- },
90
- ],
91
- "react/jsx-no-bind": [
92
- "error",
93
- {
94
- ignoreRefs: true,
95
- allowArrowFunctions: true,
96
- allowFunctions: false,
97
- allowBind: false,
98
- ignoreDOMComponents: true,
99
- },
100
- ],
101
- "react/jsx-no-literals": ["off", { noStrings: true }],
102
- "react/jsx-pascal-case": [
103
- "error",
104
- {
105
- allowAllCaps: true,
106
- ignore: [],
107
- },
108
- ],
109
- "react/sort-prop-types": [
110
- "off",
111
- {
112
- ignoreCase: true,
113
- callbacksLast: false,
114
- requiredFirst: false,
115
- sortShapeProp: true,
116
- },
117
- ],
118
- "react/no-danger": "warn",
119
- "react/no-did-mount-set-state": "off",
120
- "react/no-did-update-set-state": "error",
121
- "react/no-will-update-set-state": "error",
122
- "react/no-multi-comp": "off",
123
- "react/no-set-state": "off",
124
- "react/prefer-es6-class": ["error", "always"],
125
- "react/prefer-stateless-function": ["error", { ignorePureComponents: true }],
126
- // TypeScript
127
- "react/prop-types": ["off"],
128
- "react/require-render-return": "error",
129
- "react/self-closing-comp": "error",
130
- "react/sort-comp": [
131
- "error",
132
- {
133
- order: [
134
- "static-variables",
135
- "static-methods",
136
- "instance-variables",
137
- "lifecycle",
138
- "/^handle.+$/",
139
- "/^on.+$/",
140
- "getters",
141
- "setters",
142
- "/^(get|set)(?!(InitialState$|DefaultProps$|ChildContext$)).+$/",
143
- "instance-methods",
144
- "everything-else",
145
- "rendering",
146
- ],
147
- groups: {
148
- lifecycle: [
149
- "displayName",
150
- "propTypes",
151
- "contextTypes",
152
- "childContextTypes",
153
- "mixins",
154
- "statics",
155
- "defaultProps",
156
- "constructor",
157
- "getDefaultProps",
158
- "getInitialState",
159
- "state",
160
- "getChildContext",
161
- "getDerivedStateFromProps",
162
- "componentWillMount",
163
- "UNSAFE_componentWillMount",
164
- "componentDidMount",
165
- "componentWillReceiveProps",
166
- "UNSAFE_componentWillReceiveProps",
167
- "shouldComponentUpdate",
168
- "componentWillUpdate",
169
- "UNSAFE_componentWillUpdate",
170
- "getSnapshotBeforeUpdate",
171
- "componentDidUpdate",
172
- "componentDidCatch",
173
- "componentWillUnmount",
174
- ],
175
- rendering: ["/^render.+$/", "render"],
176
- },
177
- },
178
- ],
179
- "react/jsx-first-prop-new-line": ["error", "multiline-multiprop"],
180
- "react/jsx-equals-spacing": ["error", "never"],
181
- "react/jsx-indent": ["error", 2],
182
- "react/jsx-filename-extension": ["error", { extensions: [".jsx", ".tsx"] }],
183
- "react/require-optimization": ["off", { allowDecorators: [] }],
184
- "react/forbid-component-props": ["off", { forbid: [] }],
185
- "react/forbid-elements": ["off", { forbid: [] }],
186
- "react/no-unused-prop-types": [
187
- "error",
188
- {
189
- customValidators: [],
190
- skipShapeProps: true,
191
- },
192
- ],
193
- "react/style-prop-object": "error",
194
- "react/no-array-index-key": "error",
195
- "react/void-dom-elements-no-children": "error",
196
- "react/default-props-match-prop-types": ["error", { allowRequiredDefaults: false }],
197
- "react/no-redundant-should-component-update": "error",
198
- "react/no-unused-state": "error",
199
- "react/jsx-curly-brace-presence": ["error", { props: "never", children: "never" }],
200
- "react/destructuring-assignment": ["error", "always"],
201
- "react/no-access-state-in-setstate": "error",
202
- "react/button-has-type": [
203
- "error",
204
- {
205
- button: true,
206
- submit: true,
207
- reset: false,
208
- },
209
- ],
210
- "react/no-this-in-sfc": "error",
211
- "react/jsx-fragments": ["error", "syntax"],
212
- "react/state-in-constructor": ["error", "never"],
213
- "react/static-property-placement": ["error", "static public field"],
214
- "react/jsx-no-script-url": [
215
- "error",
216
- [
217
- {
218
- name: "Link",
219
- props: ["to"],
220
- },
221
- ],
222
- ],
223
- "react/jsx-no-useless-fragment": ["error", { allowExpressions: true }],
224
- "react/jsx-no-constructed-context-values": "error",
225
- "react/no-unstable-nested-components": ["error", { allowAsProps: true }],
226
- "react/no-namespace": "error",
227
- "react/prefer-exact-props": "error",
228
- "react/no-arrow-function-lifecycle": "error",
229
- "react/no-invalid-html-attribute": "error",
230
- "react/no-unused-class-component-methods": "error",
231
- "react/hook-use-state": "error",
232
- "react/iframe-missing-sandbox": "error",
233
- "react/jsx-no-leaked-render": "error",
234
- "react-hooks/rules-of-hooks": "error",
235
- "react-hooks/exhaustive-deps": "error",
236
- "react/require-default-props": "off",
237
- "react/jsx-key": [
238
- "error",
239
- {
240
- checkFragmentShorthand: true,
241
- checkKeyMustBeforeSpread: true,
242
- warnOnDuplicates: true,
243
- },
244
- ],
245
- "jsx-a11y/alt-text": [
246
- "error",
247
- {
248
- elements: ["img", "object", "area", 'input[type="image"]'],
249
- img: [],
250
- object: [],
251
- area: [],
252
- 'input[type="image"]': [],
253
- },
254
- ],
255
- "jsx-a11y/anchor-has-content": ["error", { components: [] }],
256
- "jsx-a11y/anchor-is-valid": [
257
- "error",
258
- {
259
- components: ["Link"],
260
- specialLink: ["to"],
261
- aspects: ["noHref", "invalidHref", "preferButton"],
262
- },
263
- ],
264
- "jsx-a11y/aria-activedescendant-has-tabindex": "error",
265
- "jsx-a11y/aria-props": "error",
266
- "jsx-a11y/aria-proptypes": "error",
267
- "jsx-a11y/aria-role": ["error", { ignoreNonDOM: false }],
268
- "jsx-a11y/aria-unsupported-elements": "error",
269
- "jsx-a11y/autocomplete-valid": [
270
- "error",
271
- {
272
- inputComponents: [],
273
- },
274
- ],
275
- "jsx-a11y/click-events-have-key-events": "error",
276
- "jsx-a11y/control-has-associated-label": [
277
- "error",
278
- {
279
- labelAttributes: ["label"],
280
- controlComponents: [],
281
- ignoreElements: ["audio", "canvas", "embed", "input", "textarea", "tr", "video"],
282
- ignoreRoles: [
283
- "grid",
284
- "listbox",
285
- "menu",
286
- "menubar",
287
- "radiogroup",
288
- "row",
289
- "tablist",
290
- "toolbar",
291
- "tree",
292
- "treegrid",
293
- ],
294
- depth: 5,
295
- },
296
- ],
297
- "jsx-a11y/heading-has-content": ["error", { components: [""] }],
298
- "jsx-a11y/html-has-lang": "error",
299
- "jsx-a11y/iframe-has-title": "error",
300
- "jsx-a11y/img-redundant-alt": "error",
301
- "jsx-a11y/interactive-supports-focus": "error",
302
- "jsx-a11y/label-has-associated-control": [
303
- "error",
304
- {
305
- labelComponents: [],
306
- labelAttributes: [],
307
- controlComponents: [],
308
- assert: "both",
309
- depth: 25,
310
- },
311
- ],
312
- "jsx-a11y/lang": "error",
313
- "jsx-a11y/media-has-caption": [
314
- "error",
315
- {
316
- audio: [],
317
- video: [],
318
- track: [],
319
- },
320
- ],
321
- "jsx-a11y/mouse-events-have-key-events": "error",
322
- "jsx-a11y/no-access-key": "error",
323
- "jsx-a11y/no-autofocus": ["error", { ignoreNonDOM: true }],
324
- "jsx-a11y/no-distracting-elements": [
325
- "error",
326
- {
327
- elements: ["marquee", "blink"],
328
- },
329
- ],
330
- "jsx-a11y/no-interactive-element-to-noninteractive-role": [
331
- "error",
332
- {
333
- tr: ["none", "presentation"],
334
- },
335
- ],
336
- "jsx-a11y/no-noninteractive-element-interactions": [
337
- "error",
338
- {
339
- handlers: ["onClick", "onMouseDown", "onMouseUp", "onKeyPress", "onKeyDown", "onKeyUp"],
340
- },
341
- ],
342
- "jsx-a11y/no-noninteractive-element-to-interactive-role": [
343
- "error",
344
- {
345
- ul: ["listbox", "menu", "menubar", "radiogroup", "tablist", "tree", "treegrid"],
346
- ol: ["listbox", "menu", "menubar", "radiogroup", "tablist", "tree", "treegrid"],
347
- li: ["menuitem", "option", "row", "tab", "treeitem"],
348
- table: ["grid"],
349
- td: ["gridcell"],
350
- },
351
- ],
352
- "jsx-a11y/no-noninteractive-tabindex": [
353
- "error",
354
- {
355
- tags: [],
356
- roles: ["tabpanel"],
357
- allowExpressionValues: true,
358
- },
359
- ],
360
- "jsx-a11y/no-redundant-roles": [
361
- "error",
362
- {
363
- nav: ["navigation"],
364
- },
365
- ],
366
- "jsx-a11y/no-static-element-interactions": [
367
- "error",
368
- {
369
- handlers: ["onClick", "onMouseDown", "onMouseUp", "onKeyPress", "onKeyDown", "onKeyUp"],
370
- },
371
- ],
372
- "jsx-a11y/role-has-required-aria-props": "error",
373
- "jsx-a11y/role-supports-aria-props": "error",
374
- "jsx-a11y/scope": "error",
375
- "jsx-a11y/tabindex-no-positive": "error",
376
- },
377
- },
378
- ...storybookConfigs["flat/recommended"],
379
- ...storybookConfigs["flat/addon-interactions"],
380
- ...storybookConfigs["flat/csf-strict"],
381
- {
382
- files: [
383
- "**/.storybook/**/*",
384
- "**/*.test.@(ts|tsx|js|jsx|mjs|cjs)",
385
- "**/*.stories.@(ts|tsx|js|jsx|mjs|cjs)",
386
- ],
387
- extends: [
388
- testingLibrary.configs["flat/react"],
389
- vitest.configs.recommended,
390
- jestDom.configs["flat/recommended"],
391
- ],
392
- rules: {
393
- "vitest/consistent-test-filename": "error",
394
- "vitest/consistent-test-it": ["error", { fn: "it", withinDescribe: "it" }],
395
- "vitest/no-focused-tests": "error",
396
- "vitest/no-test-prefixes": "error",
397
- "vitest/padding-around-after-all-blocks": "error",
398
- "vitest/padding-around-after-each-blocks": "error",
399
- "vitest/padding-around-before-all-blocks": "error",
400
- "vitest/padding-around-before-each-blocks": "error",
401
- "vitest/padding-around-describe-blocks": "error",
402
- "vitest/padding-around-test-blocks": "error",
403
- "vitest/prefer-comparison-matcher": "error",
404
- "vitest/prefer-each": "error",
405
- "vitest/prefer-equality-matcher": "error",
406
- "vitest/prefer-expect-resolves": "error",
407
- "vitest/prefer-hooks-in-order": "error",
408
- "vitest/prefer-hooks-on-top": "error",
409
- "vitest/prefer-mock-promise-shorthand": "error",
410
- "vitest/prefer-strict-equal": "error",
411
- "vitest/prefer-to-be": "error",
412
- "vitest/prefer-to-be-object": "error",
413
- "vitest/prefer-to-contain": "error",
414
- "vitest/prefer-to-have-length": "error",
415
- "vitest/prefer-todo": "error",
416
- "vitest/prefer-vi-mocked": "error",
417
- "vitest/require-to-throw-message": "error",
418
- "vitest/valid-expect-in-promise": "error",
419
- "vitest/expect-expect": "error",
420
- },
421
- },
422
- {
423
- files: ["**/.storybook/**/*", "**/*.stories.@(ts|tsx|js|jsx|mjs|cjs)"],
424
- rules: {
425
- "import/no-default-export": "off",
426
- },
427
- },
428
- ...storybookConfigs.recommended.overrides,
429
- prettierConfig,
430
- );