Skip to content

Commit 616e496

Browse files
committed
Eslint flat config
1 parent eb56301 commit 616e496

16 files changed

+1070
-607
lines changed

.eslintrc.js

Lines changed: 0 additions & 26 deletions
This file was deleted.

eslint.config.mjs

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
import eslint from "@eslint/js";
2+
import { defineConfig } from "eslint/config";
3+
import jsxA11y from "eslint-plugin-jsx-a11y";
4+
import prettier from "eslint-plugin-prettier/recommended";
5+
import react from "eslint-plugin-react";
6+
import reactHooks from "eslint-plugin-react-hooks";
7+
import importSort from "eslint-plugin-simple-import-sort";
8+
import ts from "typescript-eslint";
9+
import R from "react/package.json" with { type: "json" };
10+
import jest from "eslint-plugin-jest";
11+
import reactNative from "@react-native/eslint-config";
12+
import testingLibrary from "eslint-plugin-testing-library";
13+
14+
export default defineConfig(
15+
{
16+
// Note: there should be no other properties in this object
17+
// docs: https://eslint.org/docs/latest/use/configure/migration-guide#ignore-files
18+
ignores: [
19+
"examples/",
20+
"coverage/",
21+
".yarn/",
22+
"node_modules/",
23+
"eslint.config.mjs",
24+
],
25+
},
26+
eslint.configs.recommended,
27+
ts.configs.strict,
28+
ts.configs.stylistic,
29+
react.configs.flat.recommended,
30+
react.configs.flat["jsx-runtime"],
31+
{
32+
settings: {
33+
react: { version: R.version },
34+
},
35+
},
36+
reactHooks.configs.flat.recommended,
37+
jsxA11y.flatConfigs.recommended,
38+
{
39+
...jest.configs["flat/recommended"],
40+
...jest.configs["flat/style"],
41+
files: ["**/*.test.{ts,tsx,js,jsx}"],
42+
},
43+
{
44+
...testingLibrary.configs["flat/react"],
45+
files: ["**/*.test.{ts,tsx,js,jsx}"],
46+
},
47+
{
48+
rules: {
49+
"react-hooks/immutability": "off",
50+
},
51+
files: ["**/*.test.{ts,tsx,js,jsx}"],
52+
},
53+
prettier, // Have to be in the end
54+
{
55+
plugins: {
56+
"simple-import-sort": importSort,
57+
},
58+
rules: {
59+
"simple-import-sort/imports": [
60+
"error",
61+
{
62+
// https://github.com/lydell/eslint-plugin-simple-import-sort#custom-grouping
63+
groups: [
64+
// Packages. `react` related packages come first.
65+
["^react", "^@?\\w"],
66+
// Side effect imports.
67+
["^\\u0000"],
68+
// Parent imports. Put `..` last.
69+
["^\\.\\.(?!/?$)", "^\\.\\./?$"],
70+
// Other relative imports. Put same-folder imports and `.` last.
71+
["^\\./(?=.*/)(?!/?$)", "^\\.(?!/?$)", "^\\./?$"],
72+
],
73+
},
74+
],
75+
},
76+
},
77+
{
78+
files: ["**/*.{js,ts,tsx}"],
79+
languageOptions: {
80+
globals: reactNative.globals,
81+
},
82+
rules: {
83+
"@typescript-eslint/no-require-imports": "off", // allow to use `require()`
84+
"@typescript-eslint/no-unused-vars": [
85+
"error",
86+
{
87+
argsIgnorePattern: "^_",
88+
varsIgnorePattern: "^_",
89+
},
90+
],
91+
},
92+
},
93+
{
94+
files: ["**/*.{js,ts,tsx}"],
95+
rules: {
96+
"@typescript-eslint/no-explicit-any": "off",
97+
},
98+
},
99+
);

package.json

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"size": "size-limit",
1313
"format": "prettier --write src/*.{js,ts,tsx}",
1414
"test": "jest --coverage",
15-
"lint": "eslint './src/*.{js,ts,tsx}' --quiet",
15+
"lint": "eslint './src/**/*.{js,ts,tsx}' --quiet",
1616
"ts": "tsc --noEmit",
1717
"build": "rm -rf node_modules/@types/react-native && rm -rf esm && tsc --outDir esm && yarn postbuild",
1818
"postbuild": "prettier --write esm/*.js esm/*.d.ts",
@@ -36,23 +36,25 @@
3636
"@types/react": "^19.0.10"
3737
},
3838
"devDependencies": {
39+
"@eslint/js": "^10.0.1",
40+
"@react-native/eslint-config": "^0.84.1",
3941
"@size-limit/preset-app": "^11.2.0",
40-
"@testing-library/react-hooks": "^8.0.1",
4142
"@testing-library/react-native": "^13.0.1",
4243
"@tsconfig/react-native": "^3.0.5",
44+
"@types/eslint-plugin-jsx-a11y": "^6",
4345
"@types/jest": "^29.5.14",
4446
"@types/react": "^19.0.10",
4547
"@types/react-test-renderer": "^19.0.0",
46-
"@typescript-eslint/eslint-plugin": "^8.24.1",
47-
"@typescript-eslint/parser": "^8.24.1",
4848
"babel-plugin-react-compiler": "^19.1.0-rc.2",
4949
"doctoc": "^2.2.1",
50-
"eslint": "^8.57.1",
51-
"eslint-config-prettier": "^10.0.1",
52-
"eslint-plugin-prettier": "^5.2.3",
53-
"eslint-plugin-react": "^7.37.4",
54-
"eslint-plugin-react-compiler": "^19.1.0-rc.2",
55-
"eslint-plugin-react-hooks": "^6.0.0-rc.1",
50+
"eslint": "^10.1.0",
51+
"eslint-plugin-jest": "^29.15.1",
52+
"eslint-plugin-jsx-a11y": "^6.10.2",
53+
"eslint-plugin-prettier": "^5.5.5",
54+
"eslint-plugin-react": "^7.37.5",
55+
"eslint-plugin-react-hooks": "^7.0.1",
56+
"eslint-plugin-simple-import-sort": "^12.1.1",
57+
"eslint-plugin-testing-library": "^7.16.2",
5658
"jest": "^29.7.0",
5759
"prettier": "^3.5.1",
5860
"react": "^19.0.0",
@@ -61,7 +63,8 @@
6163
"react-native-test-app": "^4.3.10",
6264
"react-test-renderer": "^19.0.0",
6365
"size-limit": "^11.2.0",
64-
"typescript": "^5.7.3"
66+
"typescript": "^5.7.3",
67+
"typescript-eslint": "^8.58.0"
6568
},
6669
"author": "David <4661784+retyui@users.noreply.github.com>",
6770
"description": "A react-native component to input confirmation code for both Android and IOS",

src/CodeField.tsx

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,17 @@
1-
import type {StyleProp, TextStyle, ViewProps} from 'react-native';
2-
import {Platform, View, TextInput} from 'react-native';
31
import {
42
ComponentPropsWithRef,
53
ComponentType,
64
ElementType,
7-
ReactNode,
85
ForwardedRef,
6+
ReactNode,
97
} from 'react';
10-
import React, {forwardRef} from 'react';
11-
12-
import {getSymbols} from './utils';
13-
import {useFocusState} from './useFocusState';
8+
import {forwardRef} from 'react';
9+
import type {StyleProp, TextStyle, ViewProps} from 'react-native';
10+
import {Platform, TextInput, View} from 'react-native';
1411

1512
import {styles} from './CodeField.styles';
13+
import {useFocusState} from './useFocusState';
14+
import {getSymbols} from './utils';
1615

1716
export interface RenderCellOptions {
1817
symbol: string;

src/Cursor.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import React, {useState, useCallback} from 'react';
1+
import {useCallback, useState} from 'react';
22

33
import {useInterval} from './useTimer';
44

src/MaskSymbol.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import type {ReactNode} from 'react';
2-
import React, {useCallback, useEffect, useState} from 'react';
2+
import {useCallback, useEffect, useState} from 'react';
33

44
import {useTimeout} from './useTimer';
55

@@ -29,6 +29,7 @@ export function MaskSymbol({
2929

3030
useEffect(() => {
3131
if (isLastFilledCell) {
32+
// eslint-disable-next-line react-hooks/set-state-in-effect
3233
setFlag(false);
3334
}
3435
}, [isLastFilledCell]);

src/__tests__/CodeField.test.tsx

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
import React, {ComponentProps, forwardRef} from 'react';
1+
import {ComponentProps, forwardRef} from 'react';
22
import {Text, TextInput, TextInputProps, View} from 'react-native';
3-
import {act, render} from '@testing-library/react-native';
3+
import {act, render, screen} from '@testing-library/react-native';
4+
45
import {CodeField} from '../CodeField';
56
import {styles} from '../CodeField.styles';
67

@@ -19,38 +20,38 @@ it('should use custom root component', () => {
1920
<View {...p} testID={id} />
2021
);
2122

22-
const {getByTestId} = renderCodeField({RootComponent});
23+
renderCodeField({RootComponent});
2324

24-
expect(getByTestId(id)).toBeTruthy();
25+
expect(screen.getByTestId(id)).toBeTruthy();
2526
});
2627

2728
it('should spread props to root component', () => {
2829
const id = 'root';
2930
const accessible = false;
3031
const RootProps = {testID: id, accessible};
3132

32-
const {getByTestId} = renderCodeField({RootProps});
33+
renderCodeField({RootProps});
3334

34-
expect(getByTestId(id).props.accessible).toEqual(accessible);
35+
expect(screen.getByTestId(id).props.accessible).toEqual(accessible);
3536
});
3637

3738
it('should extends root component style with passed rootStyle', () => {
3839
const id = 'root';
3940
const rootStyle = {backgroundColor: 'black'};
4041
const RootProps = {testID: id};
4142

42-
const {getByTestId} = renderCodeField({RootProps, rootStyle});
43+
renderCodeField({RootProps, rootStyle});
4344

44-
expect(getByTestId(id).props.style).toEqual([styles.root, rootStyle]);
45+
expect(screen.getByTestId(id).props.style).toEqual([styles.root, rootStyle]);
4546
});
4647

4748
it('should render 4 cells', () => {
4849
const cellCount = 4;
4950
const cellId = 'cell';
5051
const renderCell = ({index = 0}) => <Text key={index} testID={cellId} />;
51-
const {getAllByTestId} = renderCodeField({cellCount, renderCell});
52+
renderCodeField({cellCount, renderCell});
5253

53-
expect(getAllByTestId(cellId).length).toEqual(cellCount);
54+
expect(screen.getAllByTestId(cellId)).toHaveLength(cellCount);
5455
});
5556

5657
it('should invoke renderCell for third cell when isFocused and it empty', () => {
@@ -59,7 +60,7 @@ it('should invoke renderCell for third cell when isFocused and it empty', () =>
5960
const onFocusEvent = {};
6061
const renderCell = jest.fn().mockReturnValue(null);
6162

62-
const {getByTestId} = renderCodeField({
63+
renderCodeField({
6364
testID: textInputTestId,
6465
value,
6566
renderCell,
@@ -68,7 +69,7 @@ it('should invoke renderCell for third cell when isFocused and it empty', () =>
6869
act(() => {
6970
// ignore initial render
7071
renderCell.mockReset();
71-
getByTestId(textInputTestId).props.onFocus(onFocusEvent);
72+
screen.getByTestId(textInputTestId).props.onFocus(onFocusEvent);
7273
});
7374

7475
/*

src/__tests__/Cursor.test.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
import React, {ComponentProps} from 'react';
1+
import {ComponentProps} from 'react';
22
import {render} from '@testing-library/react-native';
3+
34
import {Cursor} from '../Cursor';
5+
46
import {delay} from './delay';
57

68
type Props = ComponentProps<typeof Cursor>;
@@ -30,4 +32,3 @@ it('should hide cursor after timeout', async () => {
3032

3133
expect(UNSAFE_getByType(Cursor).children).toEqual([]);
3234
});
33-

src/__tests__/MaskSymbol.test.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
import React, {ComponentProps} from 'react';
1+
import {ComponentProps} from 'react';
22
import {render} from '@testing-library/react-native';
3+
34
import {MaskSymbol} from '../MaskSymbol';
5+
46
import {delay} from './delay';
57

68
type Props = ComponentProps<typeof MaskSymbol>;

src/__tests__/useBlurOnFulfill.test.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
import {renderHook} from '@testing-library/react-native';
2+
13
import {useBlurOnFulfill} from '../useBlurOnFulfill';
2-
import {renderHook} from '@testing-library/react-hooks';
34

45
it('should invoke blur method of ref when value length equal cellCount', () => {
56
const blur = jest.fn();
@@ -22,7 +23,7 @@ it('should invoke blur method of ref when value length equal cellCount', () => {
2223

2324
value = '1234';
2425

25-
rerender();
26+
rerender({});
2627

2728
expect(blur).toHaveBeenCalledTimes(1);
2829
});
@@ -47,6 +48,6 @@ it('should not throw an error when ref null and value length equal cellCount', (
4748
value = '1234';
4849

4950
expect(() => {
50-
rerender();
51+
rerender({});
5152
}).not.toThrow();
5253
});

0 commit comments

Comments
 (0)