@croct/eslint-plugin 0.8.0 → 0.8.2

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/configs/react.js CHANGED
@@ -1,293 +1,120 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.react = void 0;
4
- exports.react = {
5
- extends: [
6
- 'plugin:react/recommended',
7
- 'plugin:testing-library/react',
8
- 'plugin:jest-dom/recommended',
9
- 'plugin:jsx-a11y/recommended',
10
- 'plugin:@croct/javascript',
11
- ],
12
- plugins: [
13
- 'import',
14
- 'react',
15
- 'react-hooks',
16
- 'testing-library',
17
- 'jest-dom',
18
- '@croct',
19
- ],
20
- parserOptions: {
21
- ecmaFeatures: {
22
- jsx: true,
23
- },
24
- },
25
- settings: {
26
- 'import/resolver': {
27
- node: {
28
- extensions: ['.js', '.jsx', '.json'],
29
- },
6
+ exports.createReactConfig = createReactConfig;
7
+ const eslint_plugin_react_1 = __importDefault(require("eslint-plugin-react"));
8
+ const eslint_plugin_react_hooks_1 = __importDefault(require("eslint-plugin-react-hooks"));
9
+ const eslint_plugin_testing_library_1 = __importDefault(require("eslint-plugin-testing-library"));
10
+ const eslint_plugin_jest_dom_1 = __importDefault(require("eslint-plugin-jest-dom"));
11
+ // @ts-expect-error - no types available
12
+ const eslint_plugin_jsx_a11y_1 = __importDefault(require("eslint-plugin-jsx-a11y"));
13
+ // @ts-expect-error - no types available
14
+ const eslint_plugin_1 = __importDefault(require("@stylistic/eslint-plugin"));
15
+ const baseRules = {
16
+ // Custom rule
17
+ '@croct/jsx-attribute-spacing': 'error',
18
+ // React rules (from airbnb, with customizations)
19
+ 'react/display-name': 'off',
20
+ 'react/forbid-prop-types': ['error', {
21
+ forbid: ['any', 'array', 'object'],
22
+ checkContextTypes: true,
23
+ checkChildContextTypes: true,
24
+ }],
25
+ 'react/forbid-dom-props': ['off', { forbid: [] }],
26
+ 'react/jsx-boolean-value': ['error', 'never', { always: [] }],
27
+ 'react/jsx-closing-bracket-location': ['error', 'line-aligned'],
28
+ 'react/jsx-closing-tag-location': 'error',
29
+ 'react/jsx-curly-spacing': ['error', 'never', { allowMultiline: true }],
30
+ 'react/jsx-handler-names': ['off', {
31
+ eventHandlerPrefix: 'handle',
32
+ eventHandlerPropPrefix: 'on',
33
+ }],
34
+ 'react/jsx-indent-props': 'off',
35
+ 'react/jsx-key': 'off',
36
+ 'react/jsx-max-props-per-line': ['error', { maximum: 1, when: 'multiline' }],
37
+ 'react/jsx-no-bind': [
38
+ 'error',
39
+ {
40
+ allowArrowFunctions: true,
41
+ allowBind: false,
42
+ allowFunctions: true,
30
43
  },
31
- react: {
32
- pragma: 'React',
33
- version: 'detect',
44
+ ],
45
+ 'react/jsx-no-duplicate-props': ['error', { ignoreCase: true }],
46
+ 'react/jsx-no-literals': ['off', { noStrings: true }],
47
+ 'react/jsx-no-undef': 'error',
48
+ 'react/jsx-pascal-case': ['error', {
49
+ allowAllCaps: true,
50
+ ignore: [],
51
+ }],
52
+ 'react/sort-prop-types': ['off', {
53
+ ignoreCase: true,
54
+ callbacksLast: false,
55
+ requiredFirst: false,
56
+ sortShapeProp: true,
57
+ }],
58
+ 'react/jsx-sort-prop-types': 'off',
59
+ 'react/jsx-sort-props': [
60
+ 'error',
61
+ {
62
+ noSortAlphabetically: true,
63
+ multiline: 'last',
34
64
  },
35
- propWrapperFunctions: [
36
- 'forbidExtraProps',
37
- 'exact',
38
- 'Object.freeze',
39
- ],
40
- },
41
- rules: {
42
- // Custom rule
43
- '@croct/jsx-attribute-spacing': 'error',
44
- // React rules (from airbnb, with customizations)
45
- 'react/display-name': 'off',
46
- 'react/forbid-prop-types': ['error', {
47
- forbid: ['any', 'array', 'object'],
48
- checkContextTypes: true,
49
- checkChildContextTypes: true,
50
- }],
51
- 'react/forbid-dom-props': ['off', { forbid: [] }],
52
- 'react/jsx-boolean-value': ['error', 'never', { always: [] }],
53
- 'react/jsx-closing-bracket-location': ['error', 'line-aligned'],
54
- 'react/jsx-closing-tag-location': 'error',
55
- 'react/jsx-curly-spacing': ['error', 'never', { allowMultiline: true }],
56
- 'react/jsx-handler-names': ['off', {
57
- eventHandlerPrefix: 'handle',
58
- eventHandlerPropPrefix: 'on',
59
- }],
60
- 'react/jsx-indent-props': 'off',
61
- 'react/jsx-key': 'off',
62
- 'react/jsx-max-props-per-line': ['error', { maximum: 1, when: 'multiline' }],
63
- 'react/jsx-no-bind': [
64
- 'error',
65
- {
66
- allowArrowFunctions: true,
67
- allowBind: false,
68
- allowFunctions: true,
69
- },
70
- ],
71
- 'react/jsx-no-duplicate-props': ['error', { ignoreCase: true }],
72
- 'react/jsx-no-literals': ['off', { noStrings: true }],
73
- 'react/jsx-no-undef': 'error',
74
- 'react/jsx-pascal-case': ['error', {
75
- allowAllCaps: true,
76
- ignore: [],
77
- }],
78
- 'react/sort-prop-types': ['off', {
79
- ignoreCase: true,
80
- callbacksLast: false,
81
- requiredFirst: false,
82
- sortShapeProp: true,
83
- }],
84
- 'react/jsx-sort-prop-types': 'off',
85
- 'react/jsx-sort-props': [
86
- 'error',
87
- {
88
- noSortAlphabetically: true,
89
- multiline: 'last',
90
- },
91
- ],
92
- 'react/jsx-sort-default-props': ['off', {
93
- ignoreCase: true,
94
- }],
95
- 'react/jsx-uses-react': 'off',
96
- 'react/jsx-uses-vars': 'error',
97
- 'react/no-danger': 'warn',
98
- 'react/no-deprecated': ['error'],
99
- 'react/no-did-mount-set-state': 'off',
100
- 'react/no-did-update-set-state': 'error',
101
- 'react/no-will-update-set-state': 'error',
102
- 'react/no-direct-mutation-state': 'off',
103
- 'react/no-is-mounted': 'error',
104
- 'react/no-multi-comp': 'off',
105
- 'react/no-set-state': 'off',
106
- 'react/no-string-refs': 'error',
107
- 'react/no-unknown-property': 'error',
108
- 'react/prefer-es6-class': ['error', 'always'],
109
- 'react/prefer-stateless-function': ['error', { ignorePureComponents: true }],
110
- 'react/prop-types': 'off',
111
- 'react/react-in-jsx-scope': 'off',
112
- 'react/require-render-return': 'error',
113
- 'react/self-closing-comp': 'error',
114
- 'react/sort-comp': ['error', {
115
- order: [
116
- 'static-variables',
117
- 'static-methods',
118
- 'instance-variables',
119
- 'lifecycle',
120
- '/^handle.+$/',
121
- '/^on.+$/',
122
- 'getters',
123
- 'setters',
124
- '/^(get|set)(?!(InitialState$|DefaultProps$|ChildContext$)).+$/',
125
- 'instance-methods',
126
- 'everything-else',
127
- 'rendering',
128
- ],
129
- groups: {
130
- lifecycle: [
131
- 'displayName',
132
- 'propTypes',
133
- 'contextTypes',
134
- 'childContextTypes',
135
- 'mixins',
136
- 'statics',
137
- 'defaultProps',
138
- 'constructor',
139
- 'getDefaultProps',
140
- 'getInitialState',
141
- 'state',
142
- 'getChildContext',
143
- 'getDerivedStateFromProps',
144
- 'componentWillMount',
145
- 'UNSAFE_componentWillMount',
146
- 'componentDidMount',
147
- 'componentWillReceiveProps',
148
- 'UNSAFE_componentWillReceiveProps',
149
- 'shouldComponentUpdate',
150
- 'componentWillUpdate',
151
- 'UNSAFE_componentWillUpdate',
152
- 'getSnapshotBeforeUpdate',
153
- 'componentDidUpdate',
154
- 'componentDidCatch',
155
- 'componentWillUnmount',
156
- ],
157
- rendering: [
158
- '/^render.+$/',
159
- 'render',
160
- ],
161
- },
162
- }],
163
- 'react/jsx-wrap-multilines': 'error',
164
- 'react/jsx-first-prop-new-line': ['error', 'multiline-multiprop'],
165
- 'react/jsx-equals-spacing': ['error', 'never'],
166
- 'react/jsx-indent': ['error', 4],
167
- 'react/jsx-no-target-blank': ['error', { enforceDynamicLinks: 'always' }],
168
- 'react/jsx-filename-extension': [
169
- 1,
170
- {
171
- extensions: ['.tsx'],
172
- },
173
- ],
174
- 'react/jsx-no-comment-textnodes': 'error',
175
- 'react/no-render-return-value': 'error',
176
- 'react/require-optimization': ['off', { allowDecorators: [] }],
177
- 'react/no-find-dom-node': 'error',
178
- 'react/forbid-component-props': ['off', { forbid: [] }],
179
- 'react/forbid-elements': ['off', { forbid: [] }],
180
- 'react/no-danger-with-children': 'error',
181
- 'react/no-unused-prop-types': ['error', {
182
- customValidators: [],
183
- skipShapeProps: true,
184
- }],
185
- 'react/style-prop-object': 'error',
186
- 'react/no-unescaped-entities': 'error',
187
- 'react/no-children-prop': 'error',
188
- 'react/jsx-tag-spacing': ['error', {
189
- closingSlash: 'never',
190
- beforeSelfClosing: 'always',
191
- afterOpening: 'never',
192
- beforeClosing: 'never',
193
- }],
194
- 'react/jsx-space-before-closing': ['off', 'always'],
195
- 'react/no-array-index-key': 'error',
196
- 'react/require-default-props': 'off',
197
- 'react/forbid-foreign-prop-types': ['warn', { allowInPropTypes: true }],
198
- 'react/void-dom-elements-no-children': 'error',
199
- 'react/default-props-match-prop-types': ['error', { allowRequiredDefaults: false }],
200
- 'react/no-redundant-should-component-update': 'error',
201
- 'react/no-unused-state': 'error',
202
- 'react/boolean-prop-naming': ['off', {
203
- propTypeNames: ['bool', 'mutuallyExclusiveTrueProps'],
204
- rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+',
205
- message: '',
206
- }],
207
- 'react/no-typos': 'error',
208
- 'react/jsx-curly-brace-presence': ['error', { props: 'never', children: 'never' }],
209
- 'react/jsx-one-expression-per-line': 'off',
210
- 'react/destructuring-assignment': 'off',
211
- 'react/no-access-state-in-setstate': 'error',
212
- 'react/button-has-type': ['error', {
213
- button: true,
214
- submit: true,
215
- reset: false,
216
- }],
217
- 'react/jsx-child-element-spacing': 'off',
218
- 'react/no-this-in-sfc': 'error',
219
- 'react/jsx-max-depth': 'off',
220
- 'react/jsx-props-no-multi-spaces': 'error',
221
- 'react/no-unsafe': 'off',
222
- 'react/jsx-fragments': ['error', 'element'],
223
- 'react/jsx-curly-newline': ['error', {
224
- multiline: 'consistent',
225
- singleline: 'consistent',
226
- }],
227
- 'react/state-in-constructor': ['error', 'always'],
228
- 'react/static-property-placement': ['error', 'property assignment'],
229
- 'react/jsx-props-no-spreading': 'off',
230
- 'react/prefer-read-only-props': 'off',
231
- 'react/jsx-no-script-url': ['error', [
232
- {
233
- name: 'Link',
234
- props: ['to'],
235
- },
236
- ]],
237
- 'react/jsx-no-useless-fragment': [
238
- 'error',
239
- {
240
- allowExpressions: true,
241
- },
242
- ],
243
- 'react/no-adjacent-inline-elements': 'off',
244
- 'react/function-component-definition': 'off',
245
- 'react/jsx-newline': [
246
- 'error',
247
- {
248
- prevent: true,
249
- },
250
- ],
251
- 'react/jsx-no-constructed-context-values': 'error',
252
- 'react/no-unstable-nested-components': [
253
- 'error',
254
- {
255
- allowAsProps: true,
256
- },
257
- ],
258
- 'react/no-namespace': 'error',
259
- 'react/prefer-exact-props': 'error',
260
- 'react/no-arrow-function-lifecycle': 'error',
261
- 'react/no-invalid-html-attribute': 'error',
262
- 'react/no-unused-class-component-methods': 'error',
263
- // React Hooks rules
264
- 'react-hooks/rules-of-hooks': 'error',
265
- 'react-hooks/exhaustive-deps': 'warn',
266
- // Testing Library rules (overrides)
267
- 'testing-library/no-container': 'off',
268
- 'testing-library/no-node-access': 'off',
269
- 'testing-library/await-async-utils': 'off',
270
- // JSX A11y rules (overrides)
271
- 'jsx-a11y/aria-role': [
272
- 'error',
273
- {
274
- ignoreNonDOM: true,
275
- },
276
- ],
277
- // Underscore dangle override for Redux DevTools
278
- 'no-underscore-dangle': ['error', {
279
- allow: ['__REDUX_DEVTOOLS_EXTENSION_COMPOSE__'],
280
- allowAfterThis: false,
281
- allowAfterSuper: false,
282
- enforceInMethodNames: true,
283
- }],
284
- // Class methods use this override for React lifecycle methods
285
- 'class-methods-use-this': ['error', {
286
- exceptMethods: [
287
- 'render',
288
- 'getInitialState',
65
+ ],
66
+ 'react/jsx-sort-default-props': ['off', {
67
+ ignoreCase: true,
68
+ }],
69
+ 'react/jsx-uses-react': 'off',
70
+ 'react/jsx-uses-vars': 'error',
71
+ 'react/no-danger': 'warn',
72
+ 'react/no-deprecated': ['error'],
73
+ 'react/no-did-mount-set-state': 'off',
74
+ 'react/no-did-update-set-state': 'error',
75
+ 'react/no-will-update-set-state': 'error',
76
+ 'react/no-direct-mutation-state': 'off',
77
+ 'react/no-is-mounted': 'error',
78
+ 'react/no-multi-comp': 'off',
79
+ 'react/no-set-state': 'off',
80
+ 'react/no-string-refs': 'error',
81
+ 'react/no-unknown-property': 'error',
82
+ 'react/prefer-es6-class': ['error', 'always'],
83
+ 'react/prefer-stateless-function': ['error', { ignorePureComponents: true }],
84
+ 'react/prop-types': 'off',
85
+ 'react/react-in-jsx-scope': 'off',
86
+ 'react/require-render-return': 'error',
87
+ 'react/self-closing-comp': 'error',
88
+ 'react/sort-comp': ['error', {
89
+ order: [
90
+ 'static-variables',
91
+ 'static-methods',
92
+ 'instance-variables',
93
+ 'lifecycle',
94
+ '/^handle.+$/',
95
+ '/^on.+$/',
96
+ 'getters',
97
+ 'setters',
98
+ '/^(get|set)(?!(InitialState$|DefaultProps$|ChildContext$)).+$/',
99
+ 'instance-methods',
100
+ 'everything-else',
101
+ 'rendering',
102
+ ],
103
+ groups: {
104
+ lifecycle: [
105
+ 'displayName',
106
+ 'propTypes',
107
+ 'contextTypes',
108
+ 'childContextTypes',
109
+ 'mixins',
110
+ 'statics',
111
+ 'defaultProps',
112
+ 'constructor',
289
113
  'getDefaultProps',
114
+ 'getInitialState',
115
+ 'state',
290
116
  'getChildContext',
117
+ 'getDerivedStateFromProps',
291
118
  'componentWillMount',
292
119
  'UNSAFE_componentWillMount',
293
120
  'componentDidMount',
@@ -296,45 +123,233 @@ exports.react = {
296
123
  'shouldComponentUpdate',
297
124
  'componentWillUpdate',
298
125
  'UNSAFE_componentWillUpdate',
126
+ 'getSnapshotBeforeUpdate',
299
127
  'componentDidUpdate',
300
- 'componentWillUnmount',
301
128
  'componentDidCatch',
302
- 'getSnapshotBeforeUpdate',
129
+ 'componentWillUnmount',
130
+ ],
131
+ rendering: [
132
+ '/^render.+$/',
133
+ 'render',
303
134
  ],
304
- }],
305
- // Import restrictions
306
- 'no-restricted-imports': [
307
- 'error',
308
- {
309
- name: 'react',
310
- importNames: ['default'],
311
- message: 'The React runtime is automatically imported, '
312
- + 'you can simply omit the import declaration in this case.',
313
135
  },
314
- ],
315
- // Import order for React
316
- 'import/order': [
317
- 'error',
136
+ }],
137
+ 'react/jsx-wrap-multilines': 'error',
138
+ 'react/jsx-first-prop-new-line': ['error', 'multiline-multiprop'],
139
+ 'react/jsx-equals-spacing': ['error', 'never'],
140
+ 'react/jsx-indent': ['error', 4],
141
+ 'react/jsx-no-target-blank': ['error', { enforceDynamicLinks: 'always' }],
142
+ 'react/jsx-filename-extension': [
143
+ 1,
144
+ {
145
+ extensions: ['.tsx'],
146
+ },
147
+ ],
148
+ 'react/jsx-no-comment-textnodes': 'error',
149
+ 'react/no-render-return-value': 'error',
150
+ 'react/require-optimization': ['off', { allowDecorators: [] }],
151
+ 'react/no-find-dom-node': 'error',
152
+ 'react/forbid-component-props': ['off', { forbid: [] }],
153
+ 'react/forbid-elements': ['off', { forbid: [] }],
154
+ 'react/no-danger-with-children': 'error',
155
+ 'react/no-unused-prop-types': ['error', {
156
+ customValidators: [],
157
+ skipShapeProps: true,
158
+ }],
159
+ 'react/style-prop-object': 'error',
160
+ 'react/no-unescaped-entities': 'error',
161
+ 'react/no-children-prop': 'error',
162
+ 'react/jsx-tag-spacing': ['error', {
163
+ closingSlash: 'never',
164
+ beforeSelfClosing: 'always',
165
+ afterOpening: 'never',
166
+ beforeClosing: 'never',
167
+ }],
168
+ 'react/jsx-space-before-closing': ['off', 'always'],
169
+ 'react/no-array-index-key': 'error',
170
+ 'react/require-default-props': 'off',
171
+ 'react/forbid-foreign-prop-types': ['warn', { allowInPropTypes: true }],
172
+ 'react/void-dom-elements-no-children': 'error',
173
+ 'react/default-props-match-prop-types': ['error', { allowRequiredDefaults: false }],
174
+ 'react/no-redundant-should-component-update': 'error',
175
+ 'react/no-unused-state': 'error',
176
+ 'react/boolean-prop-naming': ['off', {
177
+ propTypeNames: ['bool', 'mutuallyExclusiveTrueProps'],
178
+ rule: '^(is|has)[A-Z]([A-Za-z0-9]?)+',
179
+ message: '',
180
+ }],
181
+ 'react/no-typos': 'error',
182
+ 'react/jsx-curly-brace-presence': ['error', { props: 'never', children: 'never' }],
183
+ 'react/jsx-one-expression-per-line': 'off',
184
+ 'react/destructuring-assignment': 'off',
185
+ 'react/no-access-state-in-setstate': 'error',
186
+ 'react/button-has-type': ['error', {
187
+ button: true,
188
+ submit: true,
189
+ reset: false,
190
+ }],
191
+ 'react/jsx-child-element-spacing': 'off',
192
+ 'react/no-this-in-sfc': 'error',
193
+ 'react/jsx-max-depth': 'off',
194
+ 'react/jsx-props-no-multi-spaces': 'error',
195
+ 'react/no-unsafe': 'off',
196
+ 'react/jsx-fragments': ['error', 'element'],
197
+ 'react/jsx-curly-newline': ['error', {
198
+ multiline: 'consistent',
199
+ singleline: 'consistent',
200
+ }],
201
+ 'react/state-in-constructor': ['error', 'always'],
202
+ 'react/static-property-placement': ['error', 'property assignment'],
203
+ 'react/jsx-props-no-spreading': 'off',
204
+ 'react/prefer-read-only-props': 'off',
205
+ 'react/jsx-no-script-url': ['error', [
318
206
  {
319
- groups: [
320
- 'builtin',
321
- 'external',
322
- 'internal',
323
- ],
324
- pathGroups: [
325
- {
326
- pattern: 'react',
327
- group: 'external',
328
- position: 'before',
329
- },
330
- ],
331
- pathGroupsExcludedImportTypes: ['react'],
332
- 'newlines-between': 'never',
333
- alphabetize: {
334
- order: 'asc',
335
- caseInsensitive: true,
207
+ name: 'Link',
208
+ props: ['to'],
209
+ },
210
+ ]],
211
+ 'react/jsx-no-useless-fragment': [
212
+ 'error',
213
+ {
214
+ allowExpressions: true,
215
+ },
216
+ ],
217
+ 'react/no-adjacent-inline-elements': 'off',
218
+ 'react/function-component-definition': 'off',
219
+ 'react/jsx-newline': [
220
+ 'error',
221
+ {
222
+ prevent: true,
223
+ },
224
+ ],
225
+ 'react/jsx-no-constructed-context-values': 'error',
226
+ 'react/no-unstable-nested-components': [
227
+ 'error',
228
+ {
229
+ allowAsProps: true,
230
+ },
231
+ ],
232
+ 'react/no-namespace': 'error',
233
+ 'react/prefer-exact-props': 'error',
234
+ 'react/no-arrow-function-lifecycle': 'error',
235
+ 'react/no-invalid-html-attribute': 'error',
236
+ 'react/no-unused-class-component-methods': 'error',
237
+ // React Hooks rules
238
+ 'react-hooks/rules-of-hooks': 'error',
239
+ 'react-hooks/exhaustive-deps': 'warn',
240
+ // Testing Library rules (overrides)
241
+ 'testing-library/no-container': 'off',
242
+ 'testing-library/no-node-access': 'off',
243
+ 'testing-library/await-async-utils': 'off',
244
+ // JSX A11y rules (overrides)
245
+ 'jsx-a11y/aria-role': [
246
+ 'error',
247
+ {
248
+ ignoreNonDOM: true,
249
+ },
250
+ ],
251
+ // Underscore dangle override for Redux DevTools
252
+ 'no-underscore-dangle': ['error', {
253
+ allow: ['__REDUX_DEVTOOLS_EXTENSION_COMPOSE__'],
254
+ allowAfterThis: false,
255
+ allowAfterSuper: false,
256
+ enforceInMethodNames: true,
257
+ }],
258
+ // Class methods use this override for React lifecycle methods
259
+ 'class-methods-use-this': ['error', {
260
+ exceptMethods: [
261
+ 'render',
262
+ 'getInitialState',
263
+ 'getDefaultProps',
264
+ 'getChildContext',
265
+ 'componentWillMount',
266
+ 'UNSAFE_componentWillMount',
267
+ 'componentDidMount',
268
+ 'componentWillReceiveProps',
269
+ 'UNSAFE_componentWillReceiveProps',
270
+ 'shouldComponentUpdate',
271
+ 'componentWillUpdate',
272
+ 'UNSAFE_componentWillUpdate',
273
+ 'componentDidUpdate',
274
+ 'componentWillUnmount',
275
+ 'componentDidCatch',
276
+ 'getSnapshotBeforeUpdate',
277
+ ],
278
+ }],
279
+ // Import restrictions
280
+ 'no-restricted-imports': [
281
+ 'error',
282
+ {
283
+ name: 'react',
284
+ importNames: ['default'],
285
+ message: 'The React runtime is automatically imported, '
286
+ + 'you can simply omit the import declaration in this case.',
287
+ },
288
+ ],
289
+ // Import order for React (using import-x)
290
+ 'import-x/order': [
291
+ 'error',
292
+ {
293
+ groups: [
294
+ 'builtin',
295
+ 'external',
296
+ 'internal',
297
+ ],
298
+ pathGroups: [
299
+ {
300
+ pattern: 'react',
301
+ group: 'external',
302
+ position: 'before',
336
303
  },
304
+ ],
305
+ pathGroupsExcludedImportTypes: ['react'],
306
+ 'newlines-between': 'never',
307
+ alphabetize: {
308
+ order: 'asc',
309
+ caseInsensitive: true,
337
310
  },
338
- ],
339
- },
311
+ },
312
+ ],
340
313
  };
314
+ // Factory function to create React config with the plugin reference
315
+ function createReactConfig(plugin, javascriptConfig) {
316
+ return [
317
+ ...javascriptConfig,
318
+ eslint_plugin_react_1.default.configs.flat.recommended,
319
+ eslint_plugin_testing_library_1.default.configs['flat/react'],
320
+ eslint_plugin_jest_dom_1.default.configs['flat/recommended'],
321
+ eslint_plugin_jsx_a11y_1.default.flatConfigs.recommended,
322
+ {
323
+ name: '@croct/react',
324
+ plugins: {
325
+ 'react-hooks': eslint_plugin_react_hooks_1.default,
326
+ '@stylistic': eslint_plugin_1.default,
327
+ '@croct': plugin,
328
+ },
329
+ languageOptions: {
330
+ parserOptions: {
331
+ ecmaFeatures: {
332
+ jsx: true,
333
+ },
334
+ },
335
+ },
336
+ settings: {
337
+ 'import-x/resolver': {
338
+ node: {
339
+ extensions: ['.js', '.jsx', '.json'],
340
+ },
341
+ },
342
+ react: {
343
+ pragma: 'React',
344
+ version: 'detect',
345
+ },
346
+ propWrapperFunctions: [
347
+ 'forbidExtraProps',
348
+ 'exact',
349
+ 'Object.freeze',
350
+ ],
351
+ },
352
+ rules: baseRules,
353
+ },
354
+ ];
355
+ }