diff --git a/.eslintignore b/.eslintignore deleted file mode 100644 index 18e9f7cb20..0000000000 --- a/.eslintignore +++ /dev/null @@ -1,16 +0,0 @@ -snapshot* -dist/ -esm/ -lib/ -cjs/ -lib/ -es/ -node_modules/ -static -cypress -script/test/cypress -_site -temp* -static/ -packages/common -packages/ai-core diff --git a/.eslintrc.js b/.eslintrc.js deleted file mode 100644 index 2ae538404a..0000000000 --- a/.eslintrc.js +++ /dev/null @@ -1,143 +0,0 @@ -module.exports = { - extends: [ - 'airbnb-base', - 'prettier', // eslint-config-prettier 处理冲突 - 'plugin:react/recommended', - 'plugin:@typescript-eslint/recommended', - ], - parser: '@typescript-eslint/parser', - plugins: ['@typescript-eslint', 'react-hooks', 'simple-import-sort'], - env: { - browser: true, - node: true, - jest: true, - }, - settings: { - react: { - pragma: 'React', - version: 'detect', - }, - }, - parserOptions: { - ecmaVersion: 2019, - sourceType: 'module', - ecmaFeatures: { - jsx: true, - }, - }, - rules: { - 'no-console': [ - 'warn', - { - allow: ['info', 'warn', 'error'], - }, - ], - - // code style config - 'no-param-reassign': 'off', - 'guard-for-in': 'off', - 'no-use-before-define': 'off', - 'no-throw-literal': 'off', - 'no-unused-expressions': 'off', - 'no-bitwise': 'off', - 'no-useless-return': 'off', - 'no-plusplus': [ - 'error', - { - allowForLoopAfterthoughts: true, - }, - ], - 'no-continue': 'off', - 'no-return-assign': 'off', - 'no-restricted-syntax': 'off', - 'no-restricted-globals': 'off', - 'no-unneeded-ternary': 'off', - 'eol-last': 'error', - 'func-names': 'off', - 'consistent-return': 'off', - 'default-case': 'off', - 'no-restricted-imports': [ - 'error', - { - paths: [ - { - name: 'lodash', - message: 'Please use lodash-es instead.', - }, - ], - }, - ], - 'max-len': 'off', - 'no-shadow': 'off', - - // import config - 'import/order': 'off', - 'import/extensions': 'off', - 'import/no-named-as-default': 'off', - 'import/prefer-default-export': 'off', - 'import/no-extraneous-dependencies': 'off', - 'import/no-cycle': 'off', - 'import/no-unresolved': 'off', - 'import/no-relative-packages': 'off', - 'simple-import-sort/imports': [ - 'error', - { - groups: [ - // NodeJS 内置模块 - [ - '^(assert|buffer|child_process|cluster|console|constants|crypto|dgram|dns|domain|events|fs|http|https|module|net|os|path|punycode|querystring|readline|repl|stream|string_decoder|sys|timers|tls|tty|url|util|vm|zlib)(/.*|$)', - ], - // 副作用导入(例如 "dotenv/config" - ['^\\u0000'], - // 第三方包 - ['^react', '^\\w', '^@\\w'], - // 内部路径别名 - ['^@/'], - // 相对路径 - ['^\\.'], - // 类型 - ['^react\\u0000$', '^@?\\w.*\\u0000$', '^@/.*\\u0000$', '^\\..*\\u0000$'], - // css - ['\\.css$', '\\.less$'], - ], - }, - ], - 'simple-import-sort/exports': 'error', - - // typescript config - '@typescript-eslint/explicit-module-boundary-types': 'off', - '@typescript-eslint/ban-types': 'off', - '@typescript-eslint/explicit-function-return-type': 'off', - '@typescript-eslint/indent': ['off', 2], - '@typescript-eslint/ban-ts-comment': 'off', - '@typescript-eslint/camelcase': 'off', - '@typescript-eslint/no-empty-interface': 'error', - '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/no-use-before-define': ['error', { functions: false }], - '@typescript-eslint/no-var-requires': 'off', - '@typescript-eslint/no-unused-vars': 'error', - 'import/consistent-type-specifier-style': ['error', 'prefer-top-level'], - '@typescript-eslint/consistent-type-imports': [ - 'error', - { - prefer: 'type-imports', - fixStyle: 'separate-type-imports', - disallowTypeAnnotations: false, - }, - ], - - // react config - 'react/display-name': 'off', - 'react-hooks/exhaustive-deps': 'warn', - 'react-hooks/rules-of-hooks': 'error', - 'react/prop-types': 'off', - }, - overrides: [ - { - files: ['**/_example/**/*', '**/__tests__/**/*'], - rules: { - 'no-console': 'off', - }, - }, - ], -}; diff --git a/.prettierignore b/.prettierignore deleted file mode 100644 index fa9c16338e..0000000000 --- a/.prettierignore +++ /dev/null @@ -1 +0,0 @@ -site/engineering/static \ No newline at end of file diff --git a/.prettierrc.js b/.prettierrc.js deleted file mode 100644 index 5e922325a3..0000000000 --- a/.prettierrc.js +++ /dev/null @@ -1,39 +0,0 @@ -module.exports = { - // 一行最多 120 字符 - printWidth: 120, - // 使用 2 个空格缩进 - tabWidth: 2, - // 不使用缩进符,而使用空格 - useTabs: false, - // 行尾需要有分号 - semi: true, - // 使用单引号 - singleQuote: true, - // 对象的 key 仅在必要时用引号 - quoteProps: 'as-needed', - // jsx 不使用单引号,而使用双引号 - jsxSingleQuote: false, - // 末尾需要有逗号 - trailingComma: 'all', - // 大括号内的首尾需要空格 - bracketSpacing: true, - // jsx 标签的反尖括号需要换行 - jsxBracketSameLine: false, - // 箭头函数,只有一个参数的时候,也需要括号 - arrowParens: 'always', - // 每个文件格式化的范围是文件的全部内容 - rangeStart: 0, - rangeEnd: Infinity, - // 不需要写文件开头的 @prettier - requirePragma: false, - // 不需要自动在文件开头插入 @prettier - insertPragma: false, - // 使用默认的折行标准 - proseWrap: 'preserve', - // 根据显示样式决定 html 要不要折行 - htmlWhitespaceSensitivity: 'css', - // vue 文件中的 script 和 style 内不用缩进 - vueIndentScriptAndStyle: false, - // 换行符使用 lf - endOfLine: 'lf', -}; diff --git a/.vscode/settings.json b/.vscode/settings.json index 5612f155f8..eff4ee73d0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,25 +1,30 @@ { "typescript.preferences.importModuleSpecifier": "relative", - "eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"], + "eslint.validate": [ + "javascript", + "javascriptreact", + "typescript", + "typescriptreact" + ], "[html]": { "editor.formatOnSave": true, - "editor.defaultFormatter": "esbenp.prettier-vscode" + "editor.defaultFormatter": "dbaeumer.vscode-eslint" }, "[typescriptreact]": { "editor.formatOnSave": true, - "editor.defaultFormatter": "esbenp.prettier-vscode" + "editor.defaultFormatter": "dbaeumer.vscode-eslint" }, "[javascriptreact]": { "editor.formatOnSave": true, - "editor.defaultFormatter": "esbenp.prettier-vscode" + "editor.defaultFormatter": "dbaeumer.vscode-eslint" }, "[typescript]": { "editor.formatOnSave": true, - "editor.defaultFormatter": "esbenp.prettier-vscode" + "editor.defaultFormatter": "dbaeumer.vscode-eslint" }, "[javascript]": { "editor.formatOnSave": true, - "editor.defaultFormatter": "esbenp.prettier-vscode" + "editor.defaultFormatter": "dbaeumer.vscode-eslint" }, "editor.codeActionsOnSave": { "source.fixAll.eslint": "explicit" @@ -71,5 +76,6 @@ "*.xaml": "$(capture).xaml.cs", "tsconfig.json": "tsconfig.*.json", "vitest.config.ts": "babel.config.js, postcss.config.js" - } + }, + "js/ts.tsdk.path": "node_modules/typescript/lib" } diff --git a/eslint.config.ts b/eslint.config.ts new file mode 100644 index 0000000000..0a536c5f7a --- /dev/null +++ b/eslint.config.ts @@ -0,0 +1,235 @@ +import importPlugin from 'eslint-plugin-import'; +import prettierPlugin from 'eslint-plugin-prettier'; +import simpleImportSort from 'eslint-plugin-simple-import-sort'; +import globals from 'globals'; +import eslintReact from '@eslint-react/eslint-plugin'; +import tsPlugin from '@typescript-eslint/eslint-plugin'; +import tsParser from '@typescript-eslint/parser'; + +import type { Linter } from 'eslint'; + +const eslintConfig: Linter.Config[] = [ + { + ignores: [ + 'snapshot*', + '**/dist/**', + '**/esm/**', + '**/lib/**', + '**/cjs/**', + '**/es/**', + '**/node_modules/**', + '**/static/**', + '**/cypress/**', + 'script/test/cypress/**', + '**/_site/**', + 'temp*', + 'packages/common/**', + 'packages/ai-core/**', + '**/_usage/**', + '**/_example-js/**', + // auto-generated file + '**/site/test-coverage.js', + ], + }, + { + ...eslintReact.configs['recommended-typescript'], + files: ['**/*.{ts,tsx,js,jsx}'], + }, + { + files: ['**/*.{ts,tsx,js,jsx}'], + plugins: { + // @ts-ignore + '@typescript-eslint': tsPlugin, + 'simple-import-sort': simpleImportSort, + import: importPlugin, + prettier: prettierPlugin, + }, + languageOptions: { + parser: tsParser, + parserOptions: { + ecmaVersion: 2019, + sourceType: 'module', + ecmaFeatures: { + jsx: true, + }, + }, + globals: { + ...globals.browser, + ...globals.node, + ...globals.jest, + }, + }, + rules: { + ...tsPlugin.configs.recommended.rules, + 'no-console': [ + 'warn', + { + allow: ['info', 'warn', 'error'], + }, + ], + 'no-param-reassign': 'off', + 'guard-for-in': 'off', + 'no-use-before-define': 'off', + 'no-throw-literal': 'off', + 'no-bitwise': 'off', + 'no-useless-return': 'off', + 'no-plusplus': [ + 'error', + { + allowForLoopAfterthoughts: true, + }, + ], + 'no-continue': 'off', + 'no-return-assign': 'off', + 'no-restricted-syntax': 'off', + 'no-restricted-globals': 'off', + 'no-unneeded-ternary': 'off', + 'eol-last': 'error', + 'func-names': 'off', + 'consistent-return': 'off', + 'default-case': 'off', + 'no-restricted-imports': [ + 'error', + { + paths: [ + { + name: 'lodash', + message: 'Please use lodash-es instead.', + }, + ], + }, + ], + 'max-len': 'off', + 'no-shadow': 'off', + // Import + 'simple-import-sort/imports': [ + 'error', + { + groups: [ + // NodeJS 内置模块 + [ + '^(assert|buffer|child_process|cluster|console|constants|crypto|dgram|dns|domain|events|fs|http|https|module|net|os|path|punycode|querystring|readline|repl|stream|string_decoder|sys|timers|tls|tty|url|util|vm|zlib)(/.*|$)', + ], + // 副作用导入(例如 "dotenv/config" + ['^\\u0000'], + // 第三方包 + ['^react', '^\\w', '^@\\w'], + // 内部路径别名 + ['^@/'], + // 相对路径 + ['^\\.'], + // 类型 + ['^react\\u0000$', '^@?\\w.*\\u0000$', '^@/.*\\u0000$', '^\\..*\\u0000$'], + // css + ['\\.css$', '\\.less$'], + ], + }, + ], + 'simple-import-sort/exports': 'error', + // TS + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/ban-types': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/ban-ts-comment': 'off', + '@typescript-eslint/camelcase': 'off', + '@typescript-eslint/no-empty-interface': 'error', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-var-requires': 'off', + '@typescript-eslint/no-unsafe-function-type': 'warn', + '@typescript-eslint/no-use-before-define': ['error', { functions: false }], + '@typescript-eslint/no-unused-vars': [ + 'error', + { + argsIgnorePattern: '^_', + varsIgnorePattern: '^_', + caughtErrorsIgnorePattern: '^_', + }, + ], + '@typescript-eslint/consistent-type-imports': [ + 'error', + { + prefer: 'type-imports', + fixStyle: 'separate-type-imports', + disallowTypeAnnotations: false, + }, + ], + '@typescript-eslint/no-unused-expressions': [ + 'error', + { + allowShortCircuit: true, + allowTernary: true, + }, + ], + // React + '@eslint-react/naming-convention-ref-name': 'off', + '@eslint-react/set-state-in-effect': 'off', + '@eslint-react/static-components': 'off', + '@eslint-react/no-clone-element': 'off', + '@eslint-react/web-api-no-leaked-timeout': 'off', + '@eslint-react/exhaustive-deps': 'warn', + '@eslint-react/no-nested-component-definitions': 'warn', + '@eslint-react/no-missing-key': 'error', + '@eslint-react/no-direct-mutation-state': 'error', + '@eslint-react/rules-of-hooks': 'error', + // Prettier + 'prettier/prettier': [ + 'error', + { + // 一行最多 120 字符 + printWidth: 120, + // 使用 2 个空格缩进 + tabWidth: 2, + // 不使用缩进符,而使用空格 + useTabs: false, + // 行尾需要有分号 + semi: true, + // 使用单引号 + singleQuote: true, + // 对象的 key 仅在必要时用引号 + quoteProps: 'as-needed', + // jsx 不使用单引号,而使用双引号 + jsxSingleQuote: false, + // 末尾需要有逗号 + trailingComma: 'all', + // 大括号内的首尾需要空格 + bracketSpacing: true, + // jsx 标签的反尖括号需要换行 + jsxBracketSameLine: false, + // 箭头函数,只有一个参数的时候,也需要括号 + arrowParens: 'always', + // 每个文件格式化的范围是文件的全部内容 + rangeStart: 0, + rangeEnd: Infinity, + // 不需要写文件开头的 @prettier + requirePragma: false, + // 不需要自动在文件开头插入 @prettier + insertPragma: false, + // 使用默认的折行标准 + proseWrap: 'preserve', + // 根据显示样式决定 html 要不要折行 + htmlWhitespaceSensitivity: 'css', + // vue 文件中的 script 和 style 内不用缩进 + vueIndentScriptAndStyle: false, + // 换行符使用 lf + endOfLine: 'lf', + }, + ], + }, + }, + // Override for example and test files + { + files: ['**/_example/**/*', '**/__tests__/**/*'], + rules: { + 'no-console': 'off', + }, + }, + // Override for script files + { + files: ['script/**/*', 'test/**/*'], + rules: { + '@typescript-eslint/no-require-imports': 'off', + }, + }, +]; + +export default eslintConfig; diff --git a/package.json b/package.json index c13cf64f4c..04d5626300 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "lint-staged": { "packages/**/*.{ts,tsx}": [ "prettier --write", - "pnpm run lint:fix" + "eslint --ext .ts,.tsx --ignore-pattern ./packages/components/__tests__ --fix" ] }, "keywords": [ @@ -73,6 +73,7 @@ "@babel/preset-typescript": "^7.16.5", "@commitlint/cli": "^16.1.0", "@commitlint/config-conventional": "^17.1.0", + "@eslint-react/eslint-plugin": "^5.8.18", "@istanbuljs/nyc-config-typescript": "^1.0.2", "@rollup/plugin-babel": "^5.3.0", "@rollup/plugin-commonjs": "^21.0.2", @@ -88,8 +89,8 @@ "@types/react-dom": "^18.2.0", "@types/rimraf": "^4.0.5", "@types/testing-library__jest-dom": "5.14.2", - "@typescript-eslint/eslint-plugin": "^5.13.0", - "@typescript-eslint/parser": "^5.13.0", + "@typescript-eslint/eslint-plugin": "^8.61.0", + "@typescript-eslint/parser": "^8.61.0", "@vitejs/plugin-react": "^5.1.1", "@vitest/coverage-istanbul": "^2.1.1", "@vitest/coverage-v8": "^2.1.1", @@ -101,11 +102,8 @@ "cz-conventional-changelog": "^3.3.0", "dom-parser": "^0.1.6", "esbuild": "^0.14.9", - "eslint": "^7.32.0", + "eslint": "^10.4.1", "eslint-config-airbnb-base": "^14.2.1", - "eslint-config-prettier": "^8.3.0", - "eslint-plugin-react": "~7.28.0", - "eslint-plugin-react-hooks": "^4.0.0", "eslint-plugin-simple-import-sort": "^13.0.0", "fs-extra": "^11.3.0", "glob": "^9.0.3", diff --git a/packages/components/_util/createHookContext.tsx b/packages/components/_util/createHookContext.tsx index 5e6a8a2780..e9d342a9b8 100644 --- a/packages/components/_util/createHookContext.tsx +++ b/packages/components/_util/createHookContext.tsx @@ -19,7 +19,6 @@ export function createHookContext(hook: (value: P) => T) { } function use() { - // eslint-disable-next-line react-hooks/rules-of-hooks return useContext(Context); } diff --git a/packages/components/_util/easing.ts b/packages/components/_util/easing.ts index 8e608af21e..c8e62fb3d5 100644 --- a/packages/components/_util/easing.ts +++ b/packages/components/_util/easing.ts @@ -37,6 +37,5 @@ export const easeInOutCubic: EasingFunction = function (current, start, end, dur return change * time * time * time + start; } time -= 2; - // eslint-disable-next-line no-return-assign return change * (time * time * time + 2) + start; }; diff --git a/packages/components/_util/forwardRefWithStatics.ts b/packages/components/_util/forwardRefWithStatics.ts index c61ae93b70..00a9cbcd4f 100644 --- a/packages/components/_util/forwardRefWithStatics.ts +++ b/packages/components/_util/forwardRefWithStatics.ts @@ -3,7 +3,7 @@ import hoistNonReactStatics from 'hoist-non-react-statics'; import type { FC, ForwardRefRenderFunction, RefAttributes } from 'react'; -export default function forwardRefWithStatics( +export default function forwardRefWithStatics( component: ForwardRefRenderFunction, statics?: S, ): FC

> & S { diff --git a/packages/components/_util/noop.ts b/packages/components/_util/noop.ts index 25ad2f7911..77787df8dd 100644 --- a/packages/components/_util/noop.ts +++ b/packages/components/_util/noop.ts @@ -1,4 +1,3 @@ -// eslint-disable-next-line @typescript-eslint/no-empty-function const noop = () => {}; export default noop; diff --git a/packages/components/_util/parseTNode.ts b/packages/components/_util/parseTNode.ts index 18b04d580f..e39bd0245e 100644 --- a/packages/components/_util/parseTNode.ts +++ b/packages/components/_util/parseTNode.ts @@ -34,7 +34,7 @@ export function parseContentTNode(tnode: TNode, props: T) { if (!tnode || ['string', 'number', 'boolean'].includes(typeof tnode)) return tnode as ReactNode; try { return React.cloneElement(tnode as ReactElement, { ...props }); - } catch (e) { + } catch (_) { log.warn('parseContentTNode', `${tnode} is not a valid ReactNode`); return null; } diff --git a/packages/components/_util/react-render.ts b/packages/components/_util/react-render.ts index 6a1e9669ea..57ca4df68c 100644 --- a/packages/components/_util/react-render.ts +++ b/packages/components/_util/react-render.ts @@ -25,7 +25,7 @@ try { if (mainVersion >= 18 && mainVersion < 19) { legacyCreateRoot = fullClone.createRoot; } -} catch (e) { +} catch (_) { // Do nothing; } @@ -62,7 +62,6 @@ function modernRender(node: React.ReactElement, container: ContainerType) { root.render(node); - // eslint-disable-next-line container[MARK] = root; } @@ -87,7 +86,6 @@ async function modernUnmount(container: ContainerType) { return Promise.resolve().then(() => { container[MARK]?.unmount(); - // eslint-disable-next-line delete container[MARK]; }); } diff --git a/packages/components/_util/ref.ts b/packages/components/_util/ref.ts index 4e9aae2022..2d045233e6 100644 --- a/packages/components/_util/ref.ts +++ b/packages/components/_util/ref.ts @@ -13,7 +13,6 @@ export const supportRef = (nodeOrComponent: any): boolean => { } // React 19 no need `forwardRef` anymore. So just pass if is a React element. - // eslint-disable-next-line no-prototype-builtins if (isReactElement(nodeOrComponent) && (nodeOrComponent as any).props.propertyIsEnumerable('ref')) { return true; } @@ -67,7 +66,7 @@ export const getNodeRef: (node: React.ReactNode) => React.Ref | null // Source from: // https://github.com/mui/material-ui/blob/master/packages/mui-utils/src/getReactNodeRef/getReactNodeRef.ts - // eslint-disable-next-line no-prototype-builtins + return ele.props.propertyIsEnumerable('ref') ? ele.props.ref : ele.ref; } return null; @@ -75,7 +74,6 @@ export const getNodeRef: (node: React.ReactNode) => React.Ref | null export function composeRefs(...refs: React.Ref[]) { return (instance: T) => { - // eslint-disable-next-line no-restricted-syntax for (const ref of refs) { if (typeof ref === 'function') { ref(instance); diff --git a/packages/components/_util/style.ts b/packages/components/_util/style.ts index 03b7001069..b9027a0f06 100644 --- a/packages/components/_util/style.ts +++ b/packages/components/_util/style.ts @@ -27,7 +27,6 @@ export const addClass = function (el: Element, cls: string) { } } if (!el.classList) { - // eslint-disable-next-line el.className = curClass; } }; @@ -48,7 +47,6 @@ export const removeClass = function (el: Element, cls: string) { } } if (!el.classList) { - // eslint-disable-next-line el.className = trim(curClass); } }; diff --git a/packages/components/alert/_example/close.tsx b/packages/components/alert/_example/close.tsx index 7b323d6652..a498679d8b 100644 --- a/packages/components/alert/_example/close.tsx +++ b/packages/components/alert/_example/close.tsx @@ -2,7 +2,6 @@ import React from 'react'; import { Alert, Space, Tag } from 'tdesign-react'; export default function AlertClose() { - // eslint-disable-next-line no-alert const beforeClose = () => window.confirm('确认关闭吗?'); const handleClosed = () => { diff --git a/packages/components/anchor/Anchor.tsx b/packages/components/anchor/Anchor.tsx index 9e67a1e620..84426ddef4 100644 --- a/packages/components/anchor/Anchor.tsx +++ b/packages/components/anchor/Anchor.tsx @@ -53,7 +53,11 @@ const Anchor = forwardRefWithStatics( const { classPrefix } = useConfig(); const [activeItem, setActiveItem] = useState(''); - const [cursorStyle, setCursorStyle] = useState<{ top: string; height?: string; opacity: number }>({ + const [cursorStyle, setCursorStyle] = useState<{ + top: string; + height?: string; + opacity: number; + }>({ top: '0px', height: '0px', opacity: 0, @@ -168,7 +172,7 @@ const Anchor = forwardRefWithStatics( className, ); - const CursorCmp = () => { + const renderCursor = () => { if (isFunction(cursor)) return cursor(); if (isEmpty(cursor)) return

; return cursor; @@ -186,7 +190,7 @@ const Anchor = forwardRefWithStatics(
- {CursorCmp()} + {renderCursor()}
{children} diff --git a/packages/components/anchor/AnchorTarget.tsx b/packages/components/anchor/AnchorTarget.tsx index 09115458d9..ab16954989 100644 --- a/packages/components/anchor/AnchorTarget.tsx +++ b/packages/components/anchor/AnchorTarget.tsx @@ -34,7 +34,7 @@ const AnchorTarget: FunctionComponent = (props) => { MessagePlugin.success('链接复制成功', 1000); }; - const Content = () => ( + const content = () => ( <> {children} @@ -43,7 +43,7 @@ const AnchorTarget: FunctionComponent = (props) => { ); - return React.createElement(tag, { id, className: tagClassName, style }, React.createElement(Content)); + return React.createElement(tag, { id, className: tagClassName, style }, React.createElement(content)); }; AnchorTarget.displayName = 'AnchorTarget'; diff --git a/packages/components/auto-complete/AutoComplete.tsx b/packages/components/auto-complete/AutoComplete.tsx index 2b308fd08a..14e96a0cac 100644 --- a/packages/components/auto-complete/AutoComplete.tsx +++ b/packages/components/auto-complete/AutoComplete.tsx @@ -17,8 +17,7 @@ import type { OptionsListProps } from './OptionList'; import type { AutoCompleteOption, TdAutoCompleteProps } from './type'; export interface AutoCompleteProps - extends TdAutoCompleteProps, - StyledProps {} + extends TdAutoCompleteProps, StyledProps {} export interface AutoCompleteRef { inputRef: InputRef; diff --git a/packages/components/auto-complete/__tests__/vitest-auto-complete.test.jsx b/packages/components/auto-complete/__tests__/vitest-auto-complete.test.jsx index 59b4af2314..0cdb8ca466 100644 --- a/packages/components/auto-complete/__tests__/vitest-auto-complete.test.jsx +++ b/packages/components/auto-complete/__tests__/vitest-auto-complete.test.jsx @@ -1,11 +1,11 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ /** * 该文件由脚本自动生成,如需修改请联系 PMC * This file generated by scripts of tdesign-api. `npm run api:docs AutoComplete React(PC) vitest,finalProject` * If you need to modify this file, contact PMC first please. */ import React from 'react'; -import { fireEvent, vi, render, mockDelay, simulateKeydownEvent } from '@test/utils'; +import { fireEvent, mockDelay, render, simulateKeydownEvent, vi } from '@test/utils'; + import { AutoComplete } from '..'; import { getNormalAutoCompleteMount, getOptionSlotAutoCompleteMount } from './mount'; diff --git a/packages/components/avatar/__tests__/mount.jsx b/packages/components/avatar/__tests__/mount.jsx index c67879db71..fe6669973c 100644 --- a/packages/components/avatar/__tests__/mount.jsx +++ b/packages/components/avatar/__tests__/mount.jsx @@ -1,5 +1,6 @@ import React from 'react'; import { render } from '@test/utils'; + import { Avatar } from '..'; // Avatar 数量变化会影响测试用例结果 @@ -11,7 +12,7 @@ export function getAvatarGroupDefaultMount(AvatarGroup, props, events) { } /> TD ME - + , ); } diff --git a/packages/components/avatar/__tests__/vitest-avatar.test.jsx b/packages/components/avatar/__tests__/vitest-avatar.test.jsx index 206935472c..9652d46c76 100644 --- a/packages/components/avatar/__tests__/vitest-avatar.test.jsx +++ b/packages/components/avatar/__tests__/vitest-avatar.test.jsx @@ -5,7 +5,8 @@ * If you need to modify this file, contact PMC first please. */ import React from 'react'; -import { fireEvent, vi, render, mockDelay, simulateImageEvent } from '@test/utils'; +import { fireEvent, mockDelay, render, simulateImageEvent, vi } from '@test/utils'; + import { Avatar, AvatarGroup } from '..'; import { getAvatarGroupDefaultMount } from './mount'; diff --git a/packages/components/back-top/BackTop.tsx b/packages/components/back-top/BackTop.tsx index c7e9738922..1373dfa111 100644 --- a/packages/components/back-top/BackTop.tsx +++ b/packages/components/back-top/BackTop.tsx @@ -8,11 +8,12 @@ import useDefaultProps from '../hooks/useDefaultProps'; import { backTopDefaultProps } from './defaultProps'; import useScroll from './useScroll'; +import type { AttachNodeReturnValue } from '../common'; import type { TdBackTopProps } from './type'; export type BackTopProps = TdBackTopProps; -const getContainer = (container: string | Function) => { +const getContainer = (container: string | ((triggerNode?: HTMLElement) => AttachNodeReturnValue)) => { if (typeof container === 'string') { if (typeof document !== 'undefined') { return document.querySelector(container); @@ -42,7 +43,14 @@ const InternalBackTop: React.ForwardRefRenderFunction getContainer(container), [container]); + const scrollContainer = useMemo(() => { + const node = getContainer(container); + // scrollTo only accepts HTMLElement | Window | Document, not Element + if (node instanceof Element && !(node instanceof HTMLElement)) { + return document.documentElement; + } + return node; + }, [container]); const { scrollTop } = useScroll({ target: scrollContainer }); const defaultContent = ( <> @@ -87,8 +95,8 @@ const InternalBackTop: React.ForwardRefRenderFunction { if (!target) return 0; const targetNode = getContainer(target); - if (!targetNode) return 0; - const rect = targetNode.getBoundingClientRect(); + if (!targetNode || targetNode instanceof Document) return 0; + const rect = (targetNode as Element).getBoundingClientRect(); const { y } = rect; return y; }, [target]); diff --git a/packages/components/back-top/__tests__/vitest-back-top.test.jsx b/packages/components/back-top/__tests__/vitest-back-top.test.jsx index b967865792..19126e51aa 100644 --- a/packages/components/back-top/__tests__/vitest-back-top.test.jsx +++ b/packages/components/back-top/__tests__/vitest-back-top.test.jsx @@ -1,11 +1,11 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ /** * 该文件由脚本自动生成,如需修改请联系 PMC * This file generated by scripts of tdesign-api. `npm run api:docs BackTop React(PC) vitest,finalProject` * If you need to modify this file, contact PMC first please. */ import React from 'react'; -import { fireEvent, vi, render } from '@test/utils'; +import { fireEvent, render, vi } from '@test/utils'; + import { BackTop } from '..'; describe('BackTop Component', () => { diff --git a/packages/components/breadcrumb/Breadcrumb.tsx b/packages/components/breadcrumb/Breadcrumb.tsx index f7e60210be..ad45c174a6 100644 --- a/packages/components/breadcrumb/Breadcrumb.tsx +++ b/packages/components/breadcrumb/Breadcrumb.tsx @@ -43,8 +43,8 @@ const Breadcrumb = forwardRefWithStatics( } return ( , 'content' | 'shape' | 'size' | 'type'> {} + extends TdButtonProps, Omit, 'content' | 'shape' | 'size' | 'type'> {} const Button = forwardRef((originProps: ButtonProps, ref: React.RefObject) => { const props = useDefaultProps(originProps, buttonDefaultProps); diff --git a/packages/components/button/__tests__/vitest-button.test.jsx b/packages/components/button/__tests__/vitest-button.test.jsx index d4e7bba212..7c90b65168 100644 --- a/packages/components/button/__tests__/vitest-button.test.jsx +++ b/packages/components/button/__tests__/vitest-button.test.jsx @@ -1,11 +1,11 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ /** * 该文件由脚本自动生成,如需修改请联系 PMC * This file generated by scripts of tdesign-api. `npm run api:docs Button React(PC) vitest,finalProject` * If you need to modify this file, contact PMC first please. */ import React from 'react'; -import { fireEvent, vi, render } from '@test/utils'; +import { fireEvent, render, vi } from '@test/utils'; + import { Button } from '..'; describe('Button Component', () => { diff --git a/packages/components/calendar/Calendar.tsx b/packages/components/calendar/Calendar.tsx index d269f24581..3b98670100 100644 --- a/packages/components/calendar/Calendar.tsx +++ b/packages/components/calendar/Calendar.tsx @@ -344,10 +344,7 @@ const Calendar = forwardRef((props, ref) => { {visible && (
- {(() => { - if (head && typeof head === 'function') return head(controllerOptions); - if (head && typeof head !== 'function') return head; - })()} + {head && typeof head === 'function' ? head(controllerOptions) : (head as React.ReactNode)}
{/* 年份选择框 */} diff --git a/packages/components/calendar/CalendarCellComp.tsx b/packages/components/calendar/CalendarCellComp.tsx index b773b4d5ef..f66899140b 100644 --- a/packages/components/calendar/CalendarCellComp.tsx +++ b/packages/components/calendar/CalendarCellComp.tsx @@ -8,8 +8,9 @@ import usePrefixClass from './hooks/usePrefixClass'; import type { MouseEvent } from 'react'; import type { CalendarCell, TdCalendarProps } from './type'; -type extendType = Required>; -interface CalendarCellProps extends extendType { +type ExtendType = Required>; + +interface CalendarCellProps extends ExtendType { cellData: CalendarCell; isCurrent: boolean; isNow: boolean; @@ -46,6 +47,7 @@ const CalendarCellComp: React.FC = (props) => { const getMonthCN = (month: number): string => monthLabelList[month]; const { calendar: calendarConfig } = useConfig(); + const fix0 = (num: number) => { const fillZero = num < 10 && (fillWithZero ?? calendarConfig.fillWithZero ?? true); return fillZero ? `0${num}` : num; @@ -53,6 +55,34 @@ const CalendarCellComp: React.FC = (props) => { const prefixCls = usePrefixClass(); + const cellValue = mode === 'month' ? createCalendarCell(cellData) : cellData; + + function renderCellContent() { + if (typeof cell === 'function') return cell(cellValue); + if (cell) return cell; + + if (mode === 'year') { + const monthIndex = cellData.date.getMonth(); + return ( +
+ {theme === 'full' + ? getMonthCN(monthIndex) + : t(local.monthSelection, { + month: `${monthIndex + 1}`, + })} +
+ ); + } + + return
{fix0(cellData.date.getDate())}
; + } + + function renderAppendContent() { + if (!cellAppend) return null; + const appendValue = typeof cellAppend === 'function' ? cellAppend(cellValue) : cellAppend; + return
{appendValue}
; + } + return ( = (props) => { onDoubleClick={onCellDoubleClick} onContextMenu={onCellRightClick} > - {(() => { - if (cell && typeof cell === 'function') return cell(mode === 'month' ? createCalendarCell(cellData) : cellData); - if (cell && typeof cell !== 'function') return cell; - let cellCtx: React.ReactNode; - if (mode === 'year') { - // year mode:输出月 - const mIndex = cellData.date.getMonth(); - cellCtx = theme === 'full' ? getMonthCN(mIndex) : t(local.monthSelection, { month: `${mIndex + 1}` }); - } else { - // month mode:输出天 - cellCtx = fix0(cellData.date.getDate()); - } - return
{cellCtx}
; - })()} - {(() => { - let cellCtx: React.ReactNode; - if (cellAppend && typeof cellAppend === 'function') { - cellCtx = cellAppend(mode === 'month' ? createCalendarCell(cellData) : cellData); - } - if (cellAppend && typeof cellAppend !== 'function') { - cellCtx = cellAppend; - } - return cellAppend &&
{cellCtx}
; - })()} + {renderCellContent()} + {renderAppendContent()} ); }; diff --git a/packages/components/cascader/Cascader.tsx b/packages/components/cascader/Cascader.tsx index 6c80fff423..c57496678b 100644 --- a/packages/components/cascader/Cascader.tsx +++ b/packages/components/cascader/Cascader.tsx @@ -140,7 +140,6 @@ const Cascader: React.FC = (originalProps) => { const maxScrollTop = menu.scrollHeight - menuHeight; targetScrollTop = Math.max(0, Math.min(targetScrollTop, maxScrollTop)); - // eslint-disable-next-line no-param-reassign menu.scrollTop = targetScrollTop; }); }); @@ -175,7 +174,10 @@ const Cascader: React.FC = (originalProps) => { overlayInnerStyle: panels.length && !props.loading ? { width: 'auto' } : {}, overlayClassName: [`${classPrefix}-cascader__popup`, props.popupProps?.overlayClassName], }} - inputProps={{ size: props.size, ...(props.inputProps as TdCascaderProps['inputProps']) }} + inputProps={{ + size: props.size, + ...(props.inputProps as TdCascaderProps['inputProps']), + }} tagInputProps={{ size: props.size, ...(props.tagInputProps as TdCascaderProps['tagInputProps']), diff --git a/packages/components/cascader/components/Item.tsx b/packages/components/cascader/components/Item.tsx index 2a750e2d36..b518b541cf 100644 --- a/packages/components/cascader/components/Item.tsx +++ b/packages/components/cascader/components/Item.tsx @@ -36,7 +36,9 @@ const Item = forwardRef( cascaderContext, } = props; const { classPrefix: prefix } = useConfig(); - const { ChevronRightIcon } = useGlobalIcon({ ChevronRightIcon: TdChevronRightIcon }); + const { ChevronRightIcon } = useGlobalIcon({ + ChevronRightIcon: TdChevronRightIcon, + }); const COMPONENT_NAME = `${prefix}-cascader__item`; // 暂时去掉动画效果 长列表在safari中有异常 // eslint-disable-next-line @typescript-eslint/no-unused-vars @@ -59,7 +61,7 @@ const Item = forwardRef( [prefix, node, STATUS, cascaderContext], ); - const RenderLabelInner = (node: TreeNode, cascaderContext: CascaderContextType) => { + const renderLabelInner = (node: TreeNode, cascaderContext: CascaderContextType) => { const { inputVal } = cascaderContext; if (!inputVal && optionChild) { @@ -86,8 +88,8 @@ const Item = forwardRef( return labelText; }; - const RenderLabelContent = (node: TreeNode, cascaderContext: CascaderContextType) => { - const label = RenderLabelInner(node, cascaderContext); + const renderLabelContent = (node: TreeNode, cascaderContext: CascaderContextType) => { + const label = renderLabelInner(node, cascaderContext); const labelCont = ( { + const renderCheckBox = (node: TreeNode, cascaderContext: CascaderContextType) => { const { checkProps, value, max, inputVal, isParentFilterable } = cascaderContext; - const label = RenderLabelInner(node, cascaderContext); + const label = renderLabelInner(node, cascaderContext); return ( - {multiple ? RenderCheckBox(node, cascaderContext) : RenderLabelContent(node, cascaderContext)} + {multiple ? renderCheckBox(node, cascaderContext) : renderLabelContent(node, cascaderContext)} {node.children && !cascaderContext.isParentFilterable && (node.loading ? ( diff --git a/packages/components/cascader/components/Panel.tsx b/packages/components/cascader/components/Panel.tsx index 5b973b526d..edee3fd667 100644 --- a/packages/components/cascader/components/Panel.tsx +++ b/packages/components/cascader/components/Panel.tsx @@ -13,8 +13,7 @@ import type { CascaderContextType, TreeNode } from '../interface'; import type { TdCascaderProps } from '../type'; export interface CascaderPanelProps - extends StyledProps, - Pick { + extends StyledProps, Pick { cascaderContext: CascaderContextType; } diff --git a/packages/components/cascader/hooks.tsx b/packages/components/cascader/hooks.tsx index f8d74ce1e9..bb285f1061 100644 --- a/packages/components/cascader/hooks.tsx +++ b/packages/components/cascader/hooks.tsx @@ -111,7 +111,7 @@ export const useCascaderContext = (originalProps: TdCascaderProps) => { // eslint-disable-next-line @typescript-eslint/no-use-before-define handleTreeStore(); } - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [options]); const handleTreeStore = () => { @@ -177,7 +177,7 @@ export const useCascaderContext = (originalProps: TdCascaderProps) => { if (multiple && !reserveKeyword) { setInputVal(''); } - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [innerValue, multiple, reserveKeyword]); useEffect(() => { @@ -223,7 +223,7 @@ export const useCascaderContext = (originalProps: TdCascaderProps) => { useEffect(() => { const { inputVal, treeStore, setTreeNodes } = cascaderContext; treeNodesEffect(inputVal, treeStore, setTreeNodes, props.filter, isParentFilterable); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [inputVal, scopeVal, isParentFilterable]); const getCascaderItems = ( diff --git a/packages/components/cascader/interface.ts b/packages/components/cascader/interface.ts index ee13e287cc..c927779301 100644 --- a/packages/components/cascader/interface.ts +++ b/packages/components/cascader/interface.ts @@ -5,24 +5,23 @@ import type { TdSelectInputProps } from '../select-input/type'; import type { CascaderChangeSource, CascaderValue, TdCascaderProps } from './type'; export * from './type'; -export interface CascaderContextType - extends Pick< - TdCascaderProps, - | 'size' - | 'disabled' - | 'checkStrictly' - | 'lazy' - | 'multiple' - | 'filterable' - | 'filter' - | 'clearable' - | 'checkProps' - | 'showAllLevels' - | 'max' - | 'value' - | 'minCollapsedNum' - | 'valueType' - > { +export interface CascaderContextType extends Pick< + TdCascaderProps, + | 'size' + | 'disabled' + | 'checkStrictly' + | 'lazy' + | 'multiple' + | 'filterable' + | 'filter' + | 'clearable' + | 'checkProps' + | 'showAllLevels' + | 'max' + | 'value' + | 'minCollapsedNum' + | 'valueType' +> { treeStore: TreeStore; setValue: (val: CascaderValue, source: CascaderChangeSource, node?: TreeNodeModel) => void; visible: boolean; diff --git a/packages/components/checkbox/CheckboxGroup.tsx b/packages/components/checkbox/CheckboxGroup.tsx index db464f5ebf..0a1babfe70 100644 --- a/packages/components/checkbox/CheckboxGroup.tsx +++ b/packages/components/checkbox/CheckboxGroup.tsx @@ -22,8 +22,7 @@ import type { } from './type'; export interface CheckboxGroupProps - extends TdCheckboxGroupProps, - StyledProps { + extends TdCheckboxGroupProps, StyledProps { children?: React.ReactNode; } @@ -218,11 +217,11 @@ const CheckboxGroup = (props: const vs = v as CheckboxOptionObj; // CheckAll 的 checkBox 不存在 value,故用 checkAll_index 来保证尽量不和用户的 value 冲突. return vs.checkAll ? ( - + ) : ( diff --git a/packages/components/collapse/CollapsePanel.tsx b/packages/components/collapse/CollapsePanel.tsx index 93929a6bfc..fa5a864e8e 100644 --- a/packages/components/collapse/CollapsePanel.tsx +++ b/packages/components/collapse/CollapsePanel.tsx @@ -54,7 +54,7 @@ const CollapsePanel: React.FC = (props) => { if (defaultExpandAll) { updateCollapseValue(innerValue); } - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); const isActive = Array.isArray(collapseValue) ? collapseValue.includes(innerValue) : collapseValue === innerValue; diff --git a/packages/components/color-picker/components/panel/alpha.tsx b/packages/components/color-picker/components/panel/alpha.tsx index bf9c524cfc..dcb6ed71ab 100644 --- a/packages/components/color-picker/components/panel/alpha.tsx +++ b/packages/components/color-picker/components/panel/alpha.tsx @@ -5,7 +5,7 @@ import ColorSlider from './slider'; import type { TdColorBaseProps } from '../../interface'; -const Alpha = (props: TdColorBaseProps) => { +const Alpha = (props: TdColorBaseProps) => { const { color, baseClassName, onChange, ...rest } = props; const handleChange = (v: number) => { diff --git a/packages/components/color-picker/components/panel/format/inputs.tsx b/packages/components/color-picker/components/panel/format/inputs.tsx index c29722e853..b1e1e75fba 100644 --- a/packages/components/color-picker/components/panel/format/inputs.tsx +++ b/packages/components/color-picker/components/panel/format/inputs.tsx @@ -73,7 +73,7 @@ const FormatInputs = (props: TdColorFormatProps) => { const throttleUpdate = throttle(updateModelValue, 100); throttleUpdate(); return () => throttleUpdate.cancel(); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [color.saturation, color.hue, color.value, color.alpha, format]); return ( @@ -100,9 +100,9 @@ const FormatInputs = (props: TdColorFormatProps) => { > {config.type === 'input' ? ( ) : ( diff --git a/packages/components/color-picker/components/panel/hue.tsx b/packages/components/color-picker/components/panel/hue.tsx index 57e618fa8c..6582e62131 100644 --- a/packages/components/color-picker/components/panel/hue.tsx +++ b/packages/components/color-picker/components/panel/hue.tsx @@ -4,7 +4,7 @@ import ColorSlider from './slider'; import type { TdColorBaseProps } from '../../interface'; -const HueSlider = (props: TdColorBaseProps) => { +const HueSlider = (props: TdColorBaseProps) => { const { color, baseClassName, disabled, onChange } = props; return ( ((props, ref) => { } = useDefaultProps(props, colorPickerDefaultProps); const [innerValue, setInnerValue] = useControlled(props, 'value', onChange); + // eslint-disable-next-line @eslint-react/use-state const [, setUpdateId] = useState(0); // 确保 UI 同步更新 const getModeByColor = (input: string) => { @@ -97,7 +98,8 @@ const Panel = forwardRef((props, ref) => { setMode(newMode); colorInstanceRef.current.isGradient = newMode === 'linear-gradient'; updateColor(innerValue); - }, [innerValue]); // eslint-disable-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps + }, [innerValue]); const handleModeChange = (newMode: TdColorModes) => { setMode(newMode); @@ -214,18 +216,16 @@ const Panel = forwardRef((props, ref) => { emitColorChange('input'); }; - const SwatchesArea = React.memo(() => { - // 只支持渐变模式 + const renderSwatchesArea = () => { const onlySupportGradient = colorModes.length === 1 && colorModes.includes('linear-gradient'); - // 最近使用颜色 let recentColors = recentlyUsedColors; if (onlySupportGradient && Array.isArray(recentColors)) { recentColors = recentColors.filter((color) => Color.isGradientColor(color)); } + const showUsedColors = Array.isArray(recentColors) || recentColors === true; - // 系统预设颜色 let systemColors = swatchColors; if (systemColors === undefined) { systemColors = [...DEFAULT_SYSTEM_SWATCH_COLORS]; @@ -233,46 +233,46 @@ const Panel = forwardRef((props, ref) => { if (onlySupportGradient) { systemColors = systemColors?.filter((color) => Color.isGradientColor(color)); } + const showSystemColors = Array.isArray(systemColors); + if (!showSystemColors && !showUsedColors) return null; - // 色块点击 const handleSetColor = (value: string, trigger: ColorPickerChangeTrigger) => { const newMode = getModeByColor(value); + setMode(newMode); // 确保在渐变模式下选择纯色块,能切换回单色模式 colorInstanceRef.current.isGradient = newMode === 'linear-gradient'; + updateColor(value); emitColorChange(trigger); }; - if (!showSystemColors && !showUsedColors) return null; - return ( - <> -
- {showUsedColors && ( - handleSetColor(color, 'recent')} - onChange={handleRecentlyUsedColorsChange} - /> - )} - {showSystemColors && ( - handleSetColor(color, 'preset')} - /> - )} -
- +
+ {showUsedColors && ( + handleSetColor(color, 'recent')} + onChange={handleRecentlyUsedColorsChange} + /> + )} + + {showSystemColors && ( + handleSetColor(color, 'preset')} + /> + )} +
); - }); + }; return (
((props, ref) => {
- + {renderSwatchesArea()}
); diff --git a/packages/components/color-picker/components/panel/linear-gradient.tsx b/packages/components/color-picker/components/panel/linear-gradient.tsx index 12169684b8..9c625c32fe 100644 --- a/packages/components/color-picker/components/panel/linear-gradient.tsx +++ b/packages/components/color-picker/components/panel/linear-gradient.tsx @@ -136,7 +136,6 @@ const LinearGradient = (props) => { if (DELETE_KEYS.includes(e.key.toLocaleLowerCase()) && length > 2 && pos >= 0 && pos <= length - 1) { points.splice(pos, 1); if (!points[pos]) { - // eslint-disable-next-line no-nested-ternary pos = points[pos + 1] ? pos + 1 : points[pos - 1] ? pos - 1 : 0; } const current = points[pos]; diff --git a/packages/components/color-picker/components/panel/saturation.tsx b/packages/components/color-picker/components/panel/saturation.tsx index dd37fb5703..6ef9afaa86 100644 --- a/packages/components/color-picker/components/panel/saturation.tsx +++ b/packages/components/color-picker/components/panel/saturation.tsx @@ -7,9 +7,9 @@ import { import useMouseEvent from '../../../hooks/useMouseEvent'; import type { MouseCoordinate } from '../../../hooks/useMouseEvent'; -import type { TdColorBaseProps } from '../../interface'; +import type { TdColorBaseProps, TdColorSaturationData } from '../../interface'; -const Saturation = (props: TdColorBaseProps) => { +const Saturation = (props: TdColorBaseProps) => { const { color, disabled, onChange, baseClassName } = props; const panelRef = useRef(null); const panelRectRef = useRef({ diff --git a/packages/components/color-picker/components/panel/slider.tsx b/packages/components/color-picker/components/panel/slider.tsx index 9cbe68bbc4..90592ca38b 100644 --- a/packages/components/color-picker/components/panel/slider.tsx +++ b/packages/components/color-picker/components/panel/slider.tsx @@ -9,10 +9,10 @@ import type { CSSProperties } from 'react'; import type { MouseCoordinate } from '../../../hooks/useMouseEvent'; import type { TdColorBaseProps } from '../../interface'; -export interface TdColorSliderProps extends TdColorBaseProps { +export interface TdColorSliderProps extends TdColorBaseProps { className?: string; - value?: Number; - maxValue?: Number; + value?: number; + maxValue?: number; railStyle?: CSSProperties; type: 'hue' | 'alpha'; } diff --git a/packages/components/color-picker/components/panel/swatches.tsx b/packages/components/color-picker/components/panel/swatches.tsx index 2078571ea4..56cfe74923 100644 --- a/packages/components/color-picker/components/panel/swatches.tsx +++ b/packages/components/color-picker/components/panel/swatches.tsx @@ -8,17 +8,20 @@ import useGlobalIcon from '../../../hooks/useGlobalIcon'; import type { TdColorBaseProps } from '../../interface'; -export interface TdColorSwathcesProps extends TdColorBaseProps { +export interface TdColorSwathcesProps extends TdColorBaseProps { colors?: string[]; - title?: String; - editable?: Boolean; - onSetColor?: Function; - handleAddColor?: Function; + title?: string; + editable?: boolean; + onSetColor?: (color: string) => void; + handleAddColor?: () => void; } const Swatches = (props: TdColorSwathcesProps) => { const { baseClassName, colors = [], editable = false, title, onChange, disabled, onSetColor, handleAddColor } = props; - const { DeleteIcon, AddIcon } = useGlobalIcon({ DeleteIcon: TdDeleteIcon, AddIcon: TdAddIcon }); + const { DeleteIcon, AddIcon } = useGlobalIcon({ + DeleteIcon: TdDeleteIcon, + AddIcon: TdAddIcon, + }); const swatchesClass = `${baseClassName}__swatches`; const { STATUS: statusClassNames } = useCommonClassName(); const isEqualCurrentColor = (color: string) => Color.compare(color, props.color.css); diff --git a/packages/components/color-picker/components/trigger.tsx b/packages/components/color-picker/components/trigger.tsx index 2de05b647f..81d49804bd 100644 --- a/packages/components/color-picker/components/trigger.tsx +++ b/packages/components/color-picker/components/trigger.tsx @@ -9,10 +9,12 @@ import useClassName from '../hooks/useClassNames'; import type { TdColorPickerProps } from '..'; import type { TdColorContext } from '../interface'; -export interface ColorTriggerProps - extends Pick { +export interface ColorTriggerProps extends Pick< + TdColorPickerProps, + 'disabled' | 'inputProps' | 'borderless' | 'clearable' | 'onClear' +> { value?: string; - onChange?: (v?: string, context?: TdColorContext) => {}; + onChange?: (v?: string, context?: TdColorContext) => void; } const ColorPickerTrigger = (props: ColorTriggerProps) => { diff --git a/packages/components/color-picker/hooks/useStyles.ts b/packages/components/color-picker/hooks/useStyles.ts index 7282a7157b..da1a047cf0 100644 --- a/packages/components/color-picker/hooks/useStyles.ts +++ b/packages/components/color-picker/hooks/useStyles.ts @@ -5,8 +5,8 @@ import type { Color } from '@tdesign/common-js/color-picker/color'; export interface TdColorSliderStyleParams { color: Color; - value: Number; - maxValue: Number; + value: number; + maxValue: number; type: 'hue' | 'alpha'; } diff --git a/packages/components/color-picker/interface.ts b/packages/components/color-picker/interface.ts index 0d2034e2dd..699a8ffb24 100644 --- a/packages/components/color-picker/interface.ts +++ b/packages/components/color-picker/interface.ts @@ -14,10 +14,10 @@ export interface TdColorContext { } // 控件通用属性 -export interface TdColorBaseProps { - disabled: Boolean; +export interface TdColorBaseProps { + disabled: boolean; color: Color; - onChange?: Function; + onChange?: (value: T) => void; baseClassName: string; } diff --git a/packages/components/common/Check.tsx b/packages/components/common/Check.tsx index c20ee652b3..a2f58622e6 100644 --- a/packages/components/common/Check.tsx +++ b/packages/components/common/Check.tsx @@ -15,7 +15,7 @@ export interface CheckProps extends TdCheckboxProps, StyledProps { allowUncheck?: boolean; title?: string; children?: React.ReactNode; - stopLabelTrigger?: Boolean; + stopLabelTrigger?: boolean; } /** diff --git a/packages/components/common/Portal.tsx b/packages/components/common/Portal.tsx index 74dd01c2bc..873aea0b4e 100644 --- a/packages/components/common/Portal.tsx +++ b/packages/components/common/Portal.tsx @@ -54,7 +54,7 @@ const Portal = forwardRef((props: PortalProps, ref) => { Object.assign(el.style, style); } return el; - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [classPrefix]); useIsomorphicLayoutEffect(() => { @@ -71,7 +71,7 @@ const Portal = forwardRef((props: PortalProps, ref) => { if (!mounted) { setMounted(true); } - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); useImperativeHandle(ref, () => container); diff --git a/packages/components/config-provider/_example/global.tsx b/packages/components/config-provider/_example/global.tsx index 9bd04c72e7..d534b13d76 100644 --- a/packages/components/config-provider/_example/global.tsx +++ b/packages/components/config-provider/_example/global.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react/no-unescaped-entities */ import React from 'react'; import { ConfigProvider, Space } from 'tdesign-react'; import enConfig from 'tdesign-react/es/locale/en_US'; @@ -21,23 +20,28 @@ export default function GlobalDemo() {

- 使用ConfigProvider包裹业务功能的最外层组件,点击下方图标查看示例代码 + 使用ConfigProvider + 包裹业务功能的最外层组件,点击下方图标查看示例代码

- 英文语言包引入路径:import enConfig from 'tdesign-react/es/locale/en_US'; + 英文语言包引入路径: + import enConfig from 'tdesign-react/es/locale/en_US';

- 中文语言包引入路径:import zhConfig from 'tdesign-react/es/locale/zh_CN'; + 中文语言包引入路径: + import zhConfig from 'tdesign-react/es/locale/zh_CN';

- 日文语言包引入路径:import jpConfig from 'tdesign-react/es/locale/ja_JP'; + 日文语言包引入路径: + import jpConfig from 'tdesign-react/es/locale/ja_JP';

- 韩文语言包引入路径:import koConfig from 'tdesign-react/es/locale/ko_KR'; + 韩文语言包引入路径: + import koConfig from 'tdesign-react/es/locale/ko_KR';

diff --git a/packages/components/date-picker/DatePicker.tsx b/packages/components/date-picker/DatePicker.tsx index 9fd357837e..9efef345b5 100644 --- a/packages/components/date-picker/DatePicker.tsx +++ b/packages/components/date-picker/DatePicker.tsx @@ -148,7 +148,7 @@ const DatePicker = forwardRef((originalProps, r setIsHoverCell(false); } // eslint-disable-next-line - }, [popupVisible]); + }, [popupVisible]); // 日期 hover function onCellMouseEnter(date: Date) { @@ -199,7 +199,13 @@ const DatePicker = forwardRef((originalProps, r // 头部快速切换 const onJumperClick = React.useCallback( ({ trigger }) => { - const monthCountMap = { date: 1, week: 1, month: 12, quarter: 12, year: 120 }; + const monthCountMap = { + date: 1, + week: 1, + month: 12, + quarter: 12, + year: 120, + }; const monthCount = monthCountMap[mode] || 0; const current = new Date(year, month); @@ -233,7 +239,7 @@ const DatePicker = forwardRef((originalProps, r }); } }, - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps [year, month, mode, setYear, setMonth, value], ); @@ -276,7 +282,10 @@ const DatePicker = forwardRef((originalProps, r if (typeof preset === 'function') { presetValue = preset(); } - const formattedPreset = formatDate(presetValue, { format, targetFormat: valueType }); + const formattedPreset = formatDate(presetValue, { + format, + targetFormat: valueType, + }); const formattedInput = formatDate(presetValue, { format }); setInputValue(formattedInput); @@ -305,7 +314,7 @@ const DatePicker = forwardRef((originalProps, r trigger: 'year-select', }); }, - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps [value], ); @@ -318,7 +327,7 @@ const DatePicker = forwardRef((originalProps, r trigger: 'month-select', }); }, - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps [value], ); diff --git a/packages/components/date-picker/base/Cell.tsx b/packages/components/date-picker/base/Cell.tsx index 87f5ac8ec3..73ceaf3095 100644 --- a/packages/components/date-picker/base/Cell.tsx +++ b/packages/components/date-picker/base/Cell.tsx @@ -25,8 +25,8 @@ export interface DatePickerCellProps { now: boolean; firstDayOfMonth: boolean; lastDayOfMonth: boolean; - onClick: Function; - onMouseEnter: Function; + onClick: (value: DateValue, context: { e: React.MouseEvent }) => void; + onMouseEnter: (value: DateValue) => void; cell?: TNode<{ value: DateValue }>; } diff --git a/packages/components/date-picker/base/Footer.tsx b/packages/components/date-picker/base/Footer.tsx index 6fdfc9e50c..e94e8809de 100644 --- a/packages/components/date-picker/base/Footer.tsx +++ b/packages/components/date-picker/base/Footer.tsx @@ -10,8 +10,11 @@ import type { DateMultipleValue, DateValue, TdDatePickerProps, TdDateRangePicker interface DatePickerFooterProps extends Pick { presets?: TdDatePickerProps['presets'] | TdDateRangePickerProps['presets']; - onPresetClick?: Function; - onConfirmClick?: Function; + onPresetClick?: ( + value: DateValue | DateMultipleValue, + context: { e: React.MouseEvent; preset: Record }, + ) => void; + onConfirmClick?: (context: { e: React.MouseEvent }) => void; selectedValue?: DateValue | DateMultipleValue; onTimePanelChange?: () => void; enableTimePicker?: TdDateRangePickerProps['enableTimePicker'] | TdDatePickerProps['enableTimePicker']; diff --git a/packages/components/date-picker/base/Header.tsx b/packages/components/date-picker/base/Header.tsx index a59f2e3a0e..dfa8ddde9e 100644 --- a/packages/components/date-picker/base/Header.tsx +++ b/packages/components/date-picker/base/Header.tsx @@ -16,8 +16,8 @@ export interface DatePickerHeaderProps extends Pick { range?: SinglePanelProps['range']; internalYear: Array; partial: 'start' | 'end'; - onMonthChange?: Function; - onYearChange?: Function; + onMonthChange?: (month: number) => void; + onYearChange?: (year: number) => void; onJumperClick?: TdPaginationMiniProps['onChange']; } @@ -70,7 +70,11 @@ const DatePickerHeader = (props: DatePickerHeaderProps) => { const end = i + 9; // 仅加入可选的年代 if (decadeHasAnyAllowed(end)) { - options.push({ label: `${i} - ${end}`, value: i + 9, disabled: false }); + options.push({ + label: `${i} - ${end}`, + value: i + 9, + disabled: false, + }); } } } else { @@ -78,14 +82,24 @@ const DatePickerHeader = (props: DatePickerHeaderProps) => { yearHasAnyAllowed(year) && options.push({ label: `${year}`, value: year, disabled: false }); for (let i = 1; i <= 10; i++) { - yearHasAnyAllowed(year + i) && options.push({ label: `${year + i}`, value: year + i, disabled: false }); - yearHasAnyAllowed(year - i) && options.unshift({ label: `${year - i}`, value: year - i, disabled: false }); + yearHasAnyAllowed(year + i) && + options.push({ + label: `${year + i}`, + value: year + i, + disabled: false, + }); + yearHasAnyAllowed(year - i) && + options.unshift({ + label: `${year - i}`, + value: year - i, + disabled: false, + }); } } return options; }, - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps [mode], ); @@ -134,7 +148,12 @@ const DatePickerHeader = (props: DatePickerHeaderProps) => { } } else { for (let i = year - extraYear - 1; i > year - extraYear - 50; i -= 10) { - decadeHasAnyAllowed(i) && options.unshift({ label: `${i - 9} - ${i}`, value: i, disabled: false }); + decadeHasAnyAllowed(i) && + options.unshift({ + label: `${i - 9} - ${i}`, + value: i, + disabled: false, + }); } } } else if (type === 'add') { @@ -203,10 +222,8 @@ const DatePickerHeader = (props: DatePickerHeaderProps) => { function handleUpdateScrollTop(content: HTMLElement) { if (scrollAnchorRef.current === 'top') { - // eslint-disable-next-line no-param-reassign content.scrollTop = 30 * 10; } else if (scrollAnchorRef.current === 'bottom') { - // eslint-disable-next-line no-param-reassign content.scrollTop = content.scrollHeight - 30 * 10; } else { const firstSelectedNode: HTMLDivElement = content?.querySelector(`.${classPrefix}-is-selected`); @@ -221,7 +238,7 @@ const DatePickerHeader = (props: DatePickerHeaderProps) => { content.offsetTop - (content.clientHeight - firstSelectedNode.clientHeight) + elementBottomHeight; - // eslint-disable-next-line no-param-reassign + content.scrollTop = updateValue; } } @@ -240,7 +257,7 @@ const DatePickerHeader = (props: DatePickerHeaderProps) => { className={`${headerClassName}-controller-month`} value={month} options={monthOptions} - onChange={(val) => onMonthChange(val)} + onChange={(val) => onMonthChange(val as number)} popupProps={{ attach: (triggerElement: HTMLElement) => triggerElement.parentNode as HTMLElement, overlayClassName: `${headerClassName}-controller-month-popup`, @@ -251,7 +268,7 @@ const DatePickerHeader = (props: DatePickerHeaderProps) => { className={`${headerClassName}-controller-year`} value={mode === 'year' ? nearestYear : year} options={yearOptions} - onChange={(val) => onYearChange(val)} + onChange={(val) => onYearChange(val as number)} onPopupVisibleChange={(visible) => { if (!visible) scrollAnchorRef.current = 'default'; }} diff --git a/packages/components/date-picker/base/Table.tsx b/packages/components/date-picker/base/Table.tsx index c2abc3f746..ec94000796 100644 --- a/packages/components/date-picker/base/Table.tsx +++ b/packages/components/date-picker/base/Table.tsx @@ -16,7 +16,8 @@ import type { DateMultipleValue, DateRangeValue, DateValue, TdDatePickerProps } dayjs.extend(isoWeek); export interface DatePickerTableProps - extends Pick, + extends + Pick, Pick, Pick { data?: Array; @@ -60,7 +61,7 @@ const DatePickerTable = (props: DatePickerTableProps) => { const valueObj = parseToDayjs(value, format).locale(local.dayjsLocale); return { year: valueObj.year(), week: valueObj.week() }; - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [mode, value, format]); // 高亮周区间 @@ -130,8 +131,8 @@ const DatePickerTable = (props: DatePickerTableProps) => { > {row.map((col: any, j: number) => ( { +export interface ExtraContentProps extends Pick< + SinglePanelProps, + 'enableTimePicker' | 'presetsPlacement' | 'onPresetClick' | 'onConfirmClick' | 'needConfirm' +> { selectedValue?: DateValue | DateMultipleValue; presets?: TdDatePickerProps['presets'] | TdDateRangePickerProps['presets']; onTimeModeChange?: () => void; diff --git a/packages/components/date-picker/panel/PanelContent.tsx b/packages/components/date-picker/panel/PanelContent.tsx index 1240a2da6a..607f5b05c8 100644 --- a/packages/components/date-picker/panel/PanelContent.tsx +++ b/packages/components/date-picker/panel/PanelContent.tsx @@ -132,7 +132,7 @@ export default function PanelContent(props: PanelContentProps) { position={partial} format={timeFormat} value={time || defaultTime} - onChange={onTimePickerChange} + onChange={(value) => onTimePickerChange?.(value)} isShowPanel={props.popupVisible} {...timePickerProps} /> diff --git a/packages/components/date-picker/panel/SinglePanel.tsx b/packages/components/date-picker/panel/SinglePanel.tsx index 5976f72421..9dd6dc3a47 100644 --- a/packages/components/date-picker/panel/SinglePanel.tsx +++ b/packages/components/date-picker/panel/SinglePanel.tsx @@ -16,8 +16,7 @@ import type { TdTimePickerProps } from '../../time-picker'; import type { DateValue, TdDatePickerProps, TdDateRangePickerProps } from '../type'; export interface SinglePanelProps - extends Omit, - StyledProps { + extends Omit, StyledProps { year?: number; month?: number; time?: string; @@ -65,7 +64,11 @@ const SinglePanel = forwardRef((originalProps, enableTimePicker: props.enableTimePicker, }); - const disableDateOptions = useDisableDate({ disableDate: props.disableDate, mode: props.mode, format }); + const disableDateOptions = useDisableDate({ + disableDate: props.disableDate, + mode: props.mode, + format, + }); const disableTimeOptions: TdTimePickerProps['disableTime'] = (h: number, m: number, s: number, ms: number) => { if (!isFunction(disableTime) || !value) { diff --git a/packages/components/date-picker/utils.ts b/packages/components/date-picker/utils.ts index 11b4f9786e..8e49bfe1d3 100644 --- a/packages/components/date-picker/utils.ts +++ b/packages/components/date-picker/utils.ts @@ -9,7 +9,6 @@ export function dateCorrection(partialIndex: number, preYear: Array, pre if (nextYear[1] <= nextYear[0]) { if (onlyYearSelect) nextYear[1] = nextYear[0] + 1; else { - // eslint-disable-next-line prefer-destructuring nextYear[1] = nextYear[0]; if (nextMonth[1] <= nextMonth[0]) { nextMonth[1] = nextMonth[0] + 1; @@ -29,7 +28,6 @@ export function dateCorrection(partialIndex: number, preYear: Array, pre // 年/季度/月份场景下,头部只有年选择器,直接 - 1 if (onlyYearSelect) nextYear[0] = nextYear[1] - 1; else { - // eslint-disable-next-line prefer-destructuring nextYear[0] = nextYear[1]; if (nextMonth[0] >= nextMonth[1]) { nextMonth[0] = nextMonth[1] - 1; diff --git a/packages/components/dialog/Dialog.tsx b/packages/components/dialog/Dialog.tsx index c33a1b68ac..be3bec84f4 100644 --- a/packages/components/dialog/Dialog.tsx +++ b/packages/components/dialog/Dialog.tsx @@ -40,7 +40,10 @@ const Dialog = forwardRef((originalProps, ref) => { const dialogPosition = useRef(null); const portalRef = useRef(null); - const [state, setState] = useSetState({ isPlugin: false, ...restProps }); + const [state, setState] = useSetState({ + isPlugin: false, + ...restProps, + }); const [local] = useLocaleReceiver('dialog'); const { @@ -104,7 +107,7 @@ const Dialog = forwardRef((originalProps, ref) => { activateDialog(); applyTransform(); } - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [dialogAnimationVisible]); useImperativeHandle(ref, () => ({ @@ -248,7 +251,9 @@ const Dialog = forwardRef((originalProps, ref) => { [`${componentCls}--center`]: !isFullScreen && props.placement === 'center' && !props.top, }, )} - style={{ paddingTop: isFullScreen ? undefined : pxCompat(props.top) }} + style={{ + paddingTop: isFullScreen ? undefined : pxCompat(props.top), + }} onClick={onMaskClick} > { if (!canDraggable) return; window.addEventListener('resize', clampPosition); return () => window.removeEventListener('resize', clampPosition); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [canDraggable]); return { diff --git a/packages/components/dialog/hooks/useDialogEsc.ts b/packages/components/dialog/hooks/useDialogEsc.ts index c42e678520..9b121f63f3 100644 --- a/packages/components/dialog/hooks/useDialogEsc.ts +++ b/packages/components/dialog/hooks/useDialogEsc.ts @@ -40,7 +40,7 @@ const useDialogEsc = (visible: boolean, dialog: MutableRefObject } } }; - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [visible]); return { activateDialog }; diff --git a/packages/components/divider/__tests__/vitest-divider.test.jsx b/packages/components/divider/__tests__/vitest-divider.test.jsx index 18b0080107..ac52383856 100644 --- a/packages/components/divider/__tests__/vitest-divider.test.jsx +++ b/packages/components/divider/__tests__/vitest-divider.test.jsx @@ -5,6 +5,7 @@ */ import React from 'react'; import { render } from '@test/utils'; + import { Divider } from '..'; describe('Divider Component', () => { diff --git a/packages/components/drawer/Drawer.tsx b/packages/components/drawer/Drawer.tsx index 7643fd6528..891b0fc6c7 100644 --- a/packages/components/drawer/Drawer.tsx +++ b/packages/components/drawer/Drawer.tsx @@ -42,7 +42,10 @@ const Drawer = forwardRef((originalProps, ref) => { const props = useDefaultProps(originalProps, drawerDefaultProps); const { body, children, header, footer, ...restProps } = props; - const [state, setState] = useSetState({ isPlugin: false, ...restProps }); + const [state, setState] = useSetState({ + isPlugin: false, + ...restProps, + }); const { className, style, @@ -98,7 +101,11 @@ const Drawer = forwardRef((originalProps, ref) => { return dragSizeValue || sizeMap[size] || size; }, [dragSizeValue, size]); - useLockStyle({ ...state, sizeValue, drawerWrapper: drawerWrapperRef.current }); + useLockStyle({ + ...state, + sizeValue, + drawerWrapper: drawerWrapperRef.current, + }); useImperativeHandle(ref, () => ({ show() { setState({ visible: true }); @@ -159,7 +166,7 @@ const Drawer = forwardRef((originalProps, ref) => { } else if (isValidElement(btn)) { result = btn; } else if (isObject(btn)) { - result =
, ); } @@ -66,18 +67,18 @@ export function getGuideMultipleStepsMount(Guide, props, events) {
-
+ , ); } // custom step props export function getCustomGuideStepMount(Guide, props) { - const steps = [{ ...STEPS[0], ...props}] + const steps = [{ ...STEPS[0], ...props }]; return render(
-
+ , ); } @@ -90,8 +91,8 @@ export function getCustomMultipleGuideStepMount(Guide, props) {
-
+ , ); } -export default {} +export default {}; diff --git a/packages/components/guide/__tests__/vitest-guide.test.jsx b/packages/components/guide/__tests__/vitest-guide.test.jsx index 7db3285870..0eaa6915bc 100644 --- a/packages/components/guide/__tests__/vitest-guide.test.jsx +++ b/packages/components/guide/__tests__/vitest-guide.test.jsx @@ -5,13 +5,14 @@ * If you need to modify this file, contact PMC first please. */ import React from 'react'; -import { fireEvent, vi, render, mockDelay } from '@test/utils'; +import { fireEvent, mockDelay, render, vi } from '@test/utils'; + import { Guide } from '..'; import { - getGuideDefaultMount, - getGuideMultipleStepsMount, getCustomGuideStepMount, getCustomMultipleGuideStepMount, + getGuideDefaultMount, + getGuideMultipleStepsMount, } from './mount'; describe('Guide Component', () => { diff --git a/packages/components/hooks/useClickOutside.ts b/packages/components/hooks/useClickOutside.ts index 3723bc0c52..1054a642d9 100644 --- a/packages/components/hooks/useClickOutside.ts +++ b/packages/components/hooks/useClickOutside.ts @@ -42,6 +42,6 @@ export default function useClickOutside( document.removeEventListener('mousedown', listener); document.removeEventListener('touchstart', listener); }; - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [refs, handler, includePopup]); } diff --git a/packages/components/hooks/useDebounce.ts b/packages/components/hooks/useDebounce.ts index 65446a50a9..91e2b46ef9 100644 --- a/packages/components/hooks/useDebounce.ts +++ b/packages/components/hooks/useDebounce.ts @@ -22,7 +22,7 @@ const useDebounce = unknown>( ): DebouncedFuncLeading => { const callback = usePersistFn(func); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps const debounced = useCallback(debounce(callback, delay, options), [callback, delay, options]); useEffect(() => debounced.cancel, [debounced]); diff --git a/packages/components/hooks/useDefaultProps.ts b/packages/components/hooks/useDefaultProps.ts index 9bb02b43f7..f3b2b0506e 100644 --- a/packages/components/hooks/useDefaultProps.ts +++ b/packages/components/hooks/useDefaultProps.ts @@ -4,7 +4,6 @@ import { useMemo } from 'react'; // https://github.com/facebook/react/pull/16210 export default function useDefaultProps(originalProps: T, defaultProps: Record): T { return useMemo(() => { - // eslint-disable-next-line const props = Object.assign({}, originalProps); Object.keys(defaultProps).forEach((key) => { // https://github.com/facebook/react/blob/main/packages/react/src/jsx/ReactJSXElement.js#L733-L740 diff --git a/packages/components/hooks/useDomRefCallback.ts b/packages/components/hooks/useDomRefCallback.ts index d3c7c2a768..1d8e971404 100644 --- a/packages/components/hooks/useDomRefCallback.ts +++ b/packages/components/hooks/useDomRefCallback.ts @@ -6,8 +6,6 @@ export default function useDomRefCallback(): [HTMLElement, React.Dispatch { if (dom) setRefCurrent(dom); - - // eslint-disable-next-line react-hooks/exhaustive-deps }, []); return [refCurrent, setRefCurrent]; diff --git a/packages/components/hooks/useDomRefMount.ts b/packages/components/hooks/useDomRefMount.ts index 38bf7a7a43..70736ce83c 100644 --- a/packages/components/hooks/useDomRefMount.ts +++ b/packages/components/hooks/useDomRefMount.ts @@ -18,7 +18,6 @@ function useDomRefMount(ref: React.MutableR // 更新 ref if (ref) { - // eslint-disable-next-line no-param-reassign ref.current = node; } @@ -38,7 +37,8 @@ function useDomRefMount(ref: React.MutableR return node; }, - [], // eslint-disable-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps + [], ); const onUnmount = useCallback((callback: () => void) => { diff --git a/packages/components/hooks/useInnerPopupVisible.tsx b/packages/components/hooks/useInnerPopupVisible.tsx index dad41e02ce..b429432f3b 100644 --- a/packages/components/hooks/useInnerPopupVisible.tsx +++ b/packages/components/hooks/useInnerPopupVisible.tsx @@ -29,7 +29,7 @@ function useInnerPopupVisible(handler: (visible: boolean, ctx: PopupVisibleChang // 执行原函数 handler(visible, ctx); }, - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps [handler], ); } diff --git a/packages/components/hooks/useMouseEvent.ts b/packages/components/hooks/useMouseEvent.ts index 83b8f632b9..30437d7c14 100644 --- a/packages/components/hooks/useMouseEvent.ts +++ b/packages/components/hooks/useMouseEvent.ts @@ -132,7 +132,7 @@ const useMouseEvent = (elementRef: React.RefObject, options: MouseE el.removeEventListener('touchend', handleMouseUp); } }; - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [options, enabled, enableTouch]); return { diff --git a/packages/components/hooks/useMutationObserver.ts b/packages/components/hooks/useMutationObserver.ts index 504ced4828..e1eccd7c07 100644 --- a/packages/components/hooks/useMutationObserver.ts +++ b/packages/components/hooks/useMutationObserver.ts @@ -59,6 +59,6 @@ export default function useMutationObservable( observer = null; } }; - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [targetEl, signalRef.current]); } diff --git a/packages/components/hooks/usePopper.ts b/packages/components/hooks/usePopper.ts index 151b255caa..7b7f768b80 100644 --- a/packages/components/hooks/usePopper.ts +++ b/packages/components/hooks/usePopper.ts @@ -75,6 +75,7 @@ const usePopper = ( fn: ({ state }) => { const elements = Object.keys(state.elements); + // eslint-disable-next-line @eslint-react/dom-no-flush-sync flushSync(() => { setState({ styles: fromEntries(elements.map((element) => [element, state.styles[element] || {}])), diff --git a/packages/components/hooks/useResizeObserver.ts b/packages/components/hooks/useResizeObserver.ts index dd8508e268..9d0aa04604 100644 --- a/packages/components/hooks/useResizeObserver.ts +++ b/packages/components/hooks/useResizeObserver.ts @@ -33,6 +33,5 @@ export default function useResizeObserver( observerRef.current = null; } }; - // eslint-disable-next-line }, [container, enabled]); } diff --git a/packages/components/hooks/useRipple.ts b/packages/components/hooks/useRipple.ts index f8f857d389..03e303f1c0 100644 --- a/packages/components/hooks/useRipple.ts +++ b/packages/components/hooks/useRipple.ts @@ -115,7 +115,6 @@ export default function useRipple(el: HTMLElement, fixedRippleColor?: string): v // fix position const initPosition = el.style.position ? el.style.position : getComputedStyle(el).position; if (initPosition === '' || initPosition === 'static') { - // eslint-disable-next-line no-param-reassign el.style.position = 'relative'; } rippleContainer.insertBefore(ripple, rippleContainer.firstChild); @@ -132,10 +131,13 @@ export default function useRipple(el: HTMLElement, fixedRippleColor?: string): v el.removeEventListener('pointerup', handleClearRipple, false); el.removeEventListener('pointerleave', handleClearRipple, false); - setTimeout(() => { - ripple.remove(); - if (rippleContainer.children.length === 0) rippleContainer.remove(); - }, period * 2 + 100); + setTimeout( + () => { + ripple.remove(); + if (rippleContainer.children.length === 0) rippleContainer.remove(); + }, + period * 2 + 100, + ); }; el.addEventListener('pointerup', handleClearRipple, false); diff --git a/packages/components/hooks/useUpdateEffect.ts b/packages/components/hooks/useUpdateEffect.ts index 19388fe667..a226f8d392 100644 --- a/packages/components/hooks/useUpdateEffect.ts +++ b/packages/components/hooks/useUpdateEffect.ts @@ -11,7 +11,7 @@ const useUpdateEffect = (callback: EffectCallback, dependency: DependencyList) = if (isFirstRender) return; return callback(); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, dependency); }; diff --git a/packages/components/hooks/useUpdateLayoutEffect.ts b/packages/components/hooks/useUpdateLayoutEffect.ts index 43a0b6a7fd..847ed6c1d4 100644 --- a/packages/components/hooks/useUpdateLayoutEffect.ts +++ b/packages/components/hooks/useUpdateLayoutEffect.ts @@ -10,7 +10,6 @@ const useUpdateLayoutEffect = (callback: EffectCallback, dependency: DependencyL if (isFirstRender) return; return callback(); - // eslint-disable-next-line react-hooks/exhaustive-deps }, dependency); }; diff --git a/packages/components/hooks/useVariables.ts b/packages/components/hooks/useVariables.ts index db9640f435..3ad1d1de42 100644 --- a/packages/components/hooks/useVariables.ts +++ b/packages/components/hooks/useVariables.ts @@ -30,10 +30,10 @@ function useVariables>( variables: T, targetElement?: HTMLElement, ): Record { + // eslint-disable-next-line @eslint-react/use-state const [, forceUpdate] = useState>({}); if (canUseDocument && !targetElement) { - // eslint-disable-next-line no-param-reassign targetElement = document?.documentElement; } diff --git a/packages/components/hooks/useVirtualScroll.ts b/packages/components/hooks/useVirtualScroll.ts index a163b2cfa0..38e044f11b 100644 --- a/packages/components/hooks/useVirtualScroll.ts +++ b/packages/components/hooks/useVirtualScroll.ts @@ -1,4 +1,3 @@ -/* eslint-disable no-underscore-dangle */ /** * 通用虚拟滚动,可支持 Select/List/Table/TreeSelect/Cascader 等组件 */ @@ -255,7 +254,7 @@ const useVirtualScroll = (container: React.MutableRefObject, params }, 1); }, // eslint-disable-next-line - [container, data, tScroll, isVirtualScroll, startAndEndIndex, trHeightList], + [container, data, tScroll, isVirtualScroll, startAndEndIndex, trHeightList] ); return { diff --git a/packages/components/image-viewer/__tests__/transform.test.ts b/packages/components/image-viewer/__tests__/transform.test.ts index 1b669c47db..b359beb1eb 100644 --- a/packages/components/image-viewer/__tests__/transform.test.ts +++ b/packages/components/image-viewer/__tests__/transform.test.ts @@ -291,7 +291,10 @@ describe('zoomIn 放大', () => { currentTranslate: { translateX: 100, translateY: 50 }, }); expect(newScale).toBeCloseTo(1.2); - expect(zoomResult.newTranslate).toEqual({ translateX: 120, translateY: 60 }); + expect(zoomResult.newTranslate).toEqual({ + translateX: 120, + translateY: 60, + }); }); test('已达最大值时只返回 newScale', () => { @@ -338,7 +341,7 @@ describe('isImageExceedsViewport 图片是否超出视口', () => { height: 600, x: 0, y: 0, - // eslint-disable-next-line @typescript-eslint/no-empty-function + toJSON: () => {}, ...rect, }); @@ -346,68 +349,178 @@ describe('isImageExceedsViewport 图片是否超出视口', () => { }; test('图片在视口内', () => { - const container = createMockElement({ left: 0, right: 800, top: 0, bottom: 600 }); - const modalBox = createMockElement({ left: 100, right: 700, top: 50, bottom: 550 }); + const container = createMockElement({ + left: 0, + right: 800, + top: 0, + bottom: 600, + }); + const modalBox = createMockElement({ + left: 100, + right: 700, + top: 50, + bottom: 550, + }); expect(isImageExceedsViewport(container, modalBox)).toBe(false); }); test('图片超出左侧', () => { - const container = createMockElement({ left: 0, right: 800, top: 0, bottom: 600 }); - const modalBox = createMockElement({ left: -50, right: 700, top: 50, bottom: 550 }); + const container = createMockElement({ + left: 0, + right: 800, + top: 0, + bottom: 600, + }); + const modalBox = createMockElement({ + left: -50, + right: 700, + top: 50, + bottom: 550, + }); expect(isImageExceedsViewport(container, modalBox)).toBe(true); }); test('图片超出右侧', () => { - const container = createMockElement({ left: 0, right: 800, top: 0, bottom: 600 }); - const modalBox = createMockElement({ left: 100, right: 900, top: 50, bottom: 550 }); + const container = createMockElement({ + left: 0, + right: 800, + top: 0, + bottom: 600, + }); + const modalBox = createMockElement({ + left: 100, + right: 900, + top: 50, + bottom: 550, + }); expect(isImageExceedsViewport(container, modalBox)).toBe(true); }); test('图片超出顶部', () => { - const container = createMockElement({ left: 0, right: 800, top: 0, bottom: 600 }); - const modalBox = createMockElement({ left: 100, right: 700, top: -10, bottom: 550 }); + const container = createMockElement({ + left: 0, + right: 800, + top: 0, + bottom: 600, + }); + const modalBox = createMockElement({ + left: 100, + right: 700, + top: -10, + bottom: 550, + }); expect(isImageExceedsViewport(container, modalBox)).toBe(true); }); test('图片超出底部', () => { - const container = createMockElement({ left: 0, right: 800, top: 0, bottom: 600 }); - const modalBox = createMockElement({ left: 100, right: 700, top: 50, bottom: 650 }); + const container = createMockElement({ + left: 0, + right: 800, + top: 0, + bottom: 600, + }); + const modalBox = createMockElement({ + left: 100, + right: 700, + top: 50, + bottom: 650, + }); expect(isImageExceedsViewport(container, modalBox)).toBe(true); }); test('图片四边均超出', () => { - const container = createMockElement({ left: 0, right: 800, top: 0, bottom: 600 }); - const modalBox = createMockElement({ left: -100, right: 900, top: -100, bottom: 700 }); + const container = createMockElement({ + left: 0, + right: 800, + top: 0, + bottom: 600, + }); + const modalBox = createMockElement({ + left: -100, + right: 900, + top: -100, + bottom: 700, + }); expect(isImageExceedsViewport(container, modalBox)).toBe(true); }); test('图片与视口完全重合', () => { - const container = createMockElement({ left: 0, right: 800, top: 0, bottom: 600 }); - const modalBox = createMockElement({ left: 0, right: 800, top: 0, bottom: 600 }); + const container = createMockElement({ + left: 0, + right: 800, + top: 0, + bottom: 600, + }); + const modalBox = createMockElement({ + left: 0, + right: 800, + top: 0, + bottom: 600, + }); expect(isImageExceedsViewport(container, modalBox)).toBe(false); }); test('图片左边与容器左边对齐(边界不超出)', () => { - const container = createMockElement({ left: 0, right: 800, top: 0, bottom: 600 }); - const modalBox = createMockElement({ left: 0, right: 700, top: 50, bottom: 550 }); + const container = createMockElement({ + left: 0, + right: 800, + top: 0, + bottom: 600, + }); + const modalBox = createMockElement({ + left: 0, + right: 700, + top: 50, + bottom: 550, + }); expect(isImageExceedsViewport(container, modalBox)).toBe(false); }); test('图片右边与容器右边对齐(边界不超出)', () => { - const container = createMockElement({ left: 0, right: 800, top: 0, bottom: 600 }); - const modalBox = createMockElement({ left: 100, right: 800, top: 50, bottom: 550 }); + const container = createMockElement({ + left: 0, + right: 800, + top: 0, + bottom: 600, + }); + const modalBox = createMockElement({ + left: 100, + right: 800, + top: 50, + bottom: 550, + }); expect(isImageExceedsViewport(container, modalBox)).toBe(false); }); test('图片上边与容器上边对齐(边界不超出)', () => { - const container = createMockElement({ left: 0, right: 800, top: 0, bottom: 600 }); - const modalBox = createMockElement({ left: 100, right: 700, top: 0, bottom: 550 }); + const container = createMockElement({ + left: 0, + right: 800, + top: 0, + bottom: 600, + }); + const modalBox = createMockElement({ + left: 100, + right: 700, + top: 0, + bottom: 550, + }); expect(isImageExceedsViewport(container, modalBox)).toBe(false); }); test('图片下边与容器下边对齐(边界不超出)', () => { - const container = createMockElement({ left: 0, right: 800, top: 0, bottom: 600 }); - const modalBox = createMockElement({ left: 100, right: 700, top: 50, bottom: 600 }); + const container = createMockElement({ + left: 0, + right: 800, + top: 0, + bottom: 600, + }); + const modalBox = createMockElement({ + left: 100, + right: 700, + top: 50, + bottom: 600, + }); expect(isImageExceedsViewport(container, modalBox)).toBe(false); }); }); diff --git a/packages/components/image/Image.tsx b/packages/components/image/Image.tsx index 4768dd0971..286cc76d78 100644 --- a/packages/components/image/Image.tsx +++ b/packages/components/image/Image.tsx @@ -77,7 +77,7 @@ const InternalImage: React.ForwardRefRenderFunction const tmpUrl = isFunction(local.replaceImageSrc) ? local.replaceImageSrc(props) : src; if (tmpUrl === imageSrc && imageSrc) return; setImageSrc(tmpUrl); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [src, local, props]); const { previewUrl } = useImagePreviewUrl(imageSrc); @@ -141,7 +141,7 @@ const InternalImage: React.ForwardRefRenderFunction }, 0); }); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [previewUrl]); useEffect(() => { @@ -153,7 +153,7 @@ const InternalImage: React.ForwardRefRenderFunction handleLoad(imgRef.current); } } - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); const hasMouseEvent = overlayTrigger === 'hover'; diff --git a/packages/components/image/__tests__/lazy.test.jsx b/packages/components/image/__tests__/lazy.test.jsx index f095c77f0f..c3400b858d 100644 --- a/packages/components/image/__tests__/lazy.test.jsx +++ b/packages/components/image/__tests__/lazy.test.jsx @@ -1,7 +1,8 @@ import React from 'react'; -import { fireEvent, render, mockIntersectionObserver } from '@test/utils'; -import { Image } from '..'; +import { fireEvent, mockIntersectionObserver, render } from '@test/utils'; + import Space from '../../space'; +import { Image } from '..'; describe('Image Component', () => { beforeAll(() => { @@ -17,7 +18,7 @@ describe('Image Component', () => { callback([{ isIntersecting: true }]); } }); - } + }; mockIntersectionObserver({}, { observe }); }); @@ -26,24 +27,21 @@ describe('Image Component', () => { const { container } = render( - { - Array.from({ length: 16 }).map((_, index) => ( - - )) - } - + {Array.from({ length: 16 }).map((_, index) => ( + + ))} + , ); const spaceElement = container.querySelector('.t-space'); fireEvent.scroll(spaceElement, { target: { scrollY: 400 } }); // 滚动后,第一张图片会加载,但后面的图片不会加载 - expect(spaceElement.firstChild.querySelector('img')).not.toBeNull() - expect(spaceElement.lastChild.querySelector('img')).toBeNull() - + expect(spaceElement.firstChild.querySelector('img')).not.toBeNull(); + expect(spaceElement.lastChild.querySelector('img')).toBeNull(); }); }); diff --git a/packages/components/image/__tests__/mount.jsx b/packages/components/image/__tests__/mount.jsx index 5aa239efb4..748821dd0b 100644 --- a/packages/components/image/__tests__/mount.jsx +++ b/packages/components/image/__tests__/mount.jsx @@ -2,16 +2,16 @@ import React from 'react'; import { render } from '@test/utils'; function ImageOverlay() { - return
预览
+ return
预览
; } export function getOverlayImageMount(Image, props, events) { return render( } {...props} {...events} - > + >, ); } diff --git a/packages/components/image/__tests__/vitest-image.test.jsx b/packages/components/image/__tests__/vitest-image.test.jsx index 8607aca52e..19948638b3 100644 --- a/packages/components/image/__tests__/vitest-image.test.jsx +++ b/packages/components/image/__tests__/vitest-image.test.jsx @@ -1,11 +1,11 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ /** * 该文件由脚本自动生成,如需修改请联系 PMC * This file generated by scripts of tdesign-api. `npm run api:docs Image React(PC) vitest,finalProject` * If you need to modify this file, contact PMC first please. */ import React from 'react'; -import { fireEvent, vi, render, mockDelay, simulateImageEvent } from '@test/utils'; +import { fireEvent, mockDelay, render, simulateImageEvent, vi } from '@test/utils'; + import { Image } from '..'; import { getOverlayImageMount } from './mount'; diff --git a/packages/components/index-lib.ts b/packages/components/index-lib.ts index a35874d0b9..19cafb2a32 100644 --- a/packages/components/index-lib.ts +++ b/packages/components/index-lib.ts @@ -5,10 +5,9 @@ if ( ENV !== 'test' && ENV !== 'production' && typeof console !== 'undefined' && - console.warn && // eslint-disable-line no-console + console.warn && typeof window !== 'undefined' ) { - // eslint-disable-next-line no-console console.warn('You are using a whole package of TDesign!'); } diff --git a/packages/components/input/Input.tsx b/packages/components/input/Input.tsx index e2c77d0f4d..c6dc5c2573 100644 --- a/packages/components/input/Input.tsx +++ b/packages/components/input/Input.tsx @@ -123,8 +123,8 @@ const Input = forwardRefWithStatics( // inputPreRef 用于预存输入框宽度,应用在 auto width 模式中 const inputPreRef: React.RefObject = useRef(null); const wrapperRef: React.RefObject = useRef(null); - const [isHover, toggleIsHover] = useState(false); - const [isFocused, toggleIsFocused] = useState(false); + const [isHover, setIsHover] = useState(false); + const [isFocused, setIsFocused] = useState(false); const [renderType, setRenderType] = useState(type); const [composingValue, setComposingValue] = useState(''); @@ -211,16 +211,16 @@ const Input = forwardRefWithStatics( onChange?.(limitedValue, { trigger: 'initial' }); } } - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); - const innerValue = composingRef.current ? composingValue : value ?? ''; + const innerValue = composingRef.current ? composingValue : (value ?? ''); const formatDisplayValue = format && !isFocused ? format(innerValue) : innerValue; const renderInput = ( ) { @@ -371,7 +371,7 @@ const Input = forwardRefWithStatics( } = e; onBlur?.(value, { e }); if (isInnerInputReadonly) return; - toggleIsFocused(false); + setIsFocused(false); } function handlePaste(e: React.ClipboardEvent) { @@ -381,12 +381,12 @@ const Input = forwardRefWithStatics( } function handleMouseEnter(e: React.MouseEvent) { - !readOnly && toggleIsHover(true); + !readOnly && setIsHover(true); onMouseenter?.({ e }); } function handleMouseLeave(e: React.MouseEvent) { - !readOnly && toggleIsHover(false); + !readOnly && setIsHover(false); onMouseleave?.({ e }); } diff --git a/packages/components/input/__tests__/mount.jsx b/packages/components/input/__tests__/mount.jsx index 99d2567571..68bb9aa314 100644 --- a/packages/components/input/__tests__/mount.jsx +++ b/packages/components/input/__tests__/mount.jsx @@ -1,5 +1,6 @@ import React from 'react'; import { render } from '@test/utils'; + import { Input } from '..'; export function getInputGroupDefaultMount(InputGroup, props) { diff --git a/packages/components/input/__tests__/vitest-input.test.jsx b/packages/components/input/__tests__/vitest-input.test.jsx index d8962729a7..cd56b32324 100644 --- a/packages/components/input/__tests__/vitest-input.test.jsx +++ b/packages/components/input/__tests__/vitest-input.test.jsx @@ -5,7 +5,8 @@ * If you need to modify this file, contact PMC first please. */ import React from 'react'; -import { fireEvent, vi, render, mockDelay, simulateInputChange } from '@test/utils'; +import { fireEvent, mockDelay, render, simulateInputChange, vi } from '@test/utils'; + import { Input, InputGroup } from '..'; import { getInputGroupDefaultMount } from './mount'; diff --git a/packages/components/link/__tests__/vitest-link.test.jsx b/packages/components/link/__tests__/vitest-link.test.jsx index 49bc1d3fde..a5a6731652 100644 --- a/packages/components/link/__tests__/vitest-link.test.jsx +++ b/packages/components/link/__tests__/vitest-link.test.jsx @@ -1,11 +1,11 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ /** * 该文件由脚本自动生成,如需修改请联系 PMC * This file generated by scripts of tdesign-api. `npm run api:docs Link React(PC) vitest,finalProject` * If you need to modify this file, contact PMC first please. */ import React from 'react'; -import { fireEvent, vi, render } from '@test/utils'; +import { fireEvent, render, vi } from '@test/utils'; + import { Link } from '..'; describe('Link Component', () => { diff --git a/packages/components/list/_example/scroll.tsx b/packages/components/list/_example/scroll.tsx index 4878789d81..b6e25576cc 100644 --- a/packages/components/list/_example/scroll.tsx +++ b/packages/components/list/_example/scroll.tsx @@ -41,7 +41,7 @@ export default function BasicList() { setPageNum(pageNum); setIsLoading(false); }, 300); - } catch (err) { + } catch (_) { setListData([]); } }; @@ -54,7 +54,7 @@ export default function BasicList() { useEffect(() => { fetchData({ pageNum, pageSize }); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); return ( diff --git a/packages/components/list/hooks/useListVirtualScroll.ts b/packages/components/list/hooks/useListVirtualScroll.ts index b74f06a74b..86f86e0af2 100644 --- a/packages/components/list/hooks/useListVirtualScroll.ts +++ b/packages/components/list/hooks/useListVirtualScroll.ts @@ -45,7 +45,7 @@ export const useListVirtualScroll = ( msTransform: `translate(0, ${virtualConfig.scrollHeight}px)`, MozTransform: `translate(0, ${virtualConfig.scrollHeight}px)`, WebkitTransform: `translate(0, ${virtualConfig.scrollHeight}px)`, - } as Styles), + }) as Styles, [virtualConfig.scrollHeight], ); @@ -56,13 +56,13 @@ export const useListVirtualScroll = ( msTransform: `translate(0, ${virtualConfig.translateY}px)`, MozTransform: `translate(0, ${virtualConfig.translateY}px)`, WebkitTransform: `translate(0, ${virtualConfig.translateY}px)`, - } as Styles), + }) as Styles, [virtualConfig.translateY], ); const handleScrollTo = (params: ComponentScrollToElementParams) => { const { index, key } = params; - const targetIndex = index === 0 ? index : index ?? Number(key); + const targetIndex = index === 0 ? index : (index ?? Number(key)); if (!targetIndex && targetIndex !== 0) { log.error('List', 'scrollTo: `index` or `key` must exist.'); return; diff --git a/packages/components/menu/MenuContext.ts b/packages/components/menu/MenuContext.ts index 1330d2e163..3b5f4f332c 100644 --- a/packages/components/menu/MenuContext.ts +++ b/packages/components/menu/MenuContext.ts @@ -14,8 +14,10 @@ export type SetMenuState = React.Dispatch>; export type MenuMode = 'title' | 'accordion' | 'popup'; -interface MenuContextType - extends Pick { +interface MenuContextType extends Pick< + TdMenuProps, + 'onChange' | 'value' | 'expanded' | 'expandMutex' | 'expandType' | 'theme' | 'collapsed' +> { /** * 修改非受控组件状态 */ diff --git a/packages/components/message/MessageComponent.tsx b/packages/components/message/MessageComponent.tsx index e2e62e0f3d..c112609d58 100644 --- a/packages/components/message/MessageComponent.tsx +++ b/packages/components/message/MessageComponent.tsx @@ -53,7 +53,7 @@ const MessageComponent = forwardRef((prop if (ref && 'current' in ref && ref.current && placement) { fadeIn(ref.current, placement); } - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); // Only run on mount useEffect(() => { diff --git a/packages/components/message/__tests__/message.test.jsx b/packages/components/message/__tests__/message.test.jsx index de705013eb..06e56c0df9 100644 --- a/packages/components/message/__tests__/message.test.jsx +++ b/packages/components/message/__tests__/message.test.jsx @@ -1,5 +1,4 @@ import React from 'react'; -import { fireEvent, mockTimeout, render, vi, waitFor } from '@test/utils'; import { CheckCircleFilledIcon, ErrorCircleFilledIcon, @@ -8,6 +7,8 @@ import { InfoCircleFilledIcon, LoadingIcon, } from 'tdesign-icons-react'; +import { fireEvent, mockTimeout, render, vi, waitFor } from '@test/utils'; + import Message, { MessagePlugin } from '../index'; const defaultMessage = '默认的message'; diff --git a/packages/components/notification/Notification.tsx b/packages/components/notification/Notification.tsx index 713f193316..a67bcc75bb 100644 --- a/packages/components/notification/Notification.tsx +++ b/packages/components/notification/Notification.tsx @@ -49,7 +49,6 @@ export const Notification = forwardRef( React.useImperativeHandle(ref, () => ({ close: () => remove(id) })); - /* eslint-disable react-hooks/exhaustive-deps */ React.useEffect(() => { let timer: NodeJS.Timeout; if (duration > 0) { @@ -63,6 +62,7 @@ export const Notification = forwardRef( clearTimeout(timer); } }; + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); const renderIcon = () => { diff --git a/packages/components/notification/NotificationList.tsx b/packages/components/notification/NotificationList.tsx index be90bc0915..4eced42be3 100644 --- a/packages/components/notification/NotificationList.tsx +++ b/packages/components/notification/NotificationList.tsx @@ -34,7 +34,7 @@ interface NotificationListProps { attach: HTMLElement; zIndex: number; placement: NotificationPlacementList; - renderCallback: Function; + renderCallback: (instance: NotificationListInstance) => void; } let seed = 0; @@ -74,7 +74,7 @@ const NotificationList = forwardRef(); + const ref: React.RefObject = { current: null }; setList((oldList) => [ ...oldList, @@ -113,9 +113,9 @@ const NotificationList = forwardRef { remove(props.key); onDurationEnd(); diff --git a/packages/components/pagination/_example/more.tsx b/packages/components/pagination/_example/more.tsx index 42f61aecdc..ae049986f3 100644 --- a/packages/components/pagination/_example/more.tsx +++ b/packages/components/pagination/_example/more.tsx @@ -4,7 +4,7 @@ import { Pagination } from 'tdesign-react'; import type { PaginationProps } from 'tdesign-react'; export default function PaginationExample() { - const [pageSize, changePageSize] = useState(5); + const [pageSize, setPageSize] = useState(5); const onChange: PaginationProps['onChange'] = (pageInfo) => { console.log(pageInfo); @@ -13,14 +13,14 @@ export default function PaginationExample() { return (
展示首尾页码省略 - changePageSize(v)} /> + setPageSize(v)} /> 不展示首尾页码省略 changePageSize(v)} + onPageSizeChange={(v) => setPageSize(v)} />
); diff --git a/packages/components/pagination/hooks/usePageNumber.tsx b/packages/components/pagination/hooks/usePageNumber.tsx index dcde5a9b26..775b06d232 100644 --- a/packages/components/pagination/hooks/usePageNumber.tsx +++ b/packages/components/pagination/hooks/usePageNumber.tsx @@ -18,8 +18,8 @@ export default function usePageNumber(props) { }); const name = `${classPrefix}-pagination`; - const [hoverPreMore, toggleHoverPreMore] = useState(false); // 处理 left ellipsis 展示逻辑 - const [hoverNextMore, toggleHoverNextMore] = useState(false); // 处理 right ellipsis 展示逻辑 + const [hoverPreMore, setHoverPreMore] = useState(false); // 处理 left ellipsis 展示逻辑 + const [hoverNextMore, setHoverNextMore] = useState(false); // 处理 right ellipsis 展示逻辑 const { showPageNumber, @@ -70,8 +70,8 @@ export default function usePageNumber(props) { // 当省略图标消失时,需要还原hover标记 useEffect(() => { - if (!showPrevMore) toggleHoverPreMore(false); - if (!showNextMore) toggleHoverNextMore(false); + if (!showPrevMore) setHoverPreMore(false); + if (!showNextMore) setHoverNextMore(false); }, [showNextMore, showPrevMore]); const pageNumberControl = showPageNumber && ( @@ -93,8 +93,8 @@ export default function usePageNumber(props) { className={classNames(`${name}__number`, `${name}__number--more`, { [`${classPrefix}-is-disabled`]: disabled, })} - onMouseEnter={() => toggleHoverPreMore(true)} - onMouseLeave={() => toggleHoverPreMore(false)} + onMouseEnter={() => setHoverPreMore(true)} + onMouseLeave={() => setHoverPreMore(false)} onClick={() => changeCurrent(current - foldedMaxPageBtn)} > {!hoverPreMore ? : } @@ -121,8 +121,8 @@ export default function usePageNumber(props) { className={classNames(`${name}__number`, `${name}__number--more`, { [`${classPrefix}-is-disabled`]: disabled, })} - onMouseEnter={() => toggleHoverNextMore(true)} - onMouseLeave={() => toggleHoverNextMore(false)} + onMouseEnter={() => setHoverNextMore(true)} + onMouseLeave={() => setHoverNextMore(false)} onClick={() => changeCurrent(current + foldedMaxPageBtn)} > {!hoverNextMore ? : } diff --git a/packages/components/popup/Popup.tsx b/packages/components/popup/Popup.tsx index 4c00cbf5d8..6e827ac616 100644 --- a/packages/components/popup/Popup.tsx +++ b/packages/components/popup/Popup.tsx @@ -211,7 +211,6 @@ const Popup = forwardRef((originalProps, ref popperRef.current?.update?.(); }); } - // eslint-disable-next-line react-hooks/exhaustive-deps }, [visible, content, windowHeight, windowWidth]); // 下拉展开或内容变化时,调整箭头位置 @@ -221,7 +220,7 @@ const Popup = forwardRef((originalProps, ref updateArrowPosition(); }); } - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [visible, content, popupElement]); // 下拉展开时,触发滚动回调 @@ -231,7 +230,7 @@ const Popup = forwardRef((originalProps, ref updateScrollTop?.(contentRef.current); }); } - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [visible, popupElement]); function handleExited() { @@ -300,7 +299,11 @@ const Popup = forwardRef((originalProps, ref setPopupElement(node); } }} - style={{ ...styles.popper, zIndex, ...getOverlayStyle(overlayStyle) }} + style={{ + ...styles.popper, + zIndex, + ...getOverlayStyle(overlayStyle), + }} className={classNames(`${classPrefix}-popup`, overlayClassName)} {...attributes.popper} onClick={(e) => props.onOverlayClick?.({ e })} @@ -369,7 +372,7 @@ const Popup = forwardRef((originalProps, ref onVisibleChange(false, { trigger: 'document' }); } } - } catch (e) { + } catch (_) { // 直接尝试更新 popper.update(); } diff --git a/packages/components/popup/PopupPlugin.tsx b/packages/components/popup/PopupPlugin.tsx index e8d9fbd962..b1e5890133 100644 --- a/packages/components/popup/PopupPlugin.tsx +++ b/packages/components/popup/PopupPlugin.tsx @@ -141,8 +141,6 @@ const Overlay: React.FC = (originalProps) => { // mounted useLayoutEffect(() => { setVisibleState(true); - - // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const eventProps = hasTrigger.hover && { diff --git a/packages/components/popup/_example/dynamic.tsx b/packages/components/popup/_example/dynamic.tsx index 4f182d2d04..c49fae0507 100644 --- a/packages/components/popup/_example/dynamic.tsx +++ b/packages/components/popup/_example/dynamic.tsx @@ -2,7 +2,7 @@ import React, { useRef, useState } from 'react'; import { Button, Popup } from 'tdesign-react'; export default function Controlled() { - const [spanVisible, setVisible] = useState(false); + const [visible, setVisible] = useState(false); const [content, setContent] = useState('这是popup内容'); const btnClicksRef = useRef(0); @@ -15,7 +15,7 @@ export default function Controlled() { return ( - + ); } diff --git a/packages/components/popup/hooks/useTrigger.tsx b/packages/components/popup/hooks/useTrigger.tsx index c5cb5ae478..8d11af4907 100644 --- a/packages/components/popup/hooks/useTrigger.tsx +++ b/packages/components/popup/hooks/useTrigger.tsx @@ -114,7 +114,11 @@ export default function useTrigger({ if (trigger === 'mousedown') { callFuncWithDelay({ delay: visible ? appearDelay : exitDelay, - callback: () => onVisibleChange(!visible, { e, trigger: 'trigger-element-mousedown' }), + callback: () => + onVisibleChange(!visible, { + e, + trigger: 'trigger-element-mousedown', + }), }); } }; @@ -193,7 +197,7 @@ export default function useTrigger({ off(element, 'touchstart', handleTouchStart, { passive: true }); off(element, 'keydown', handleKeyDown); }; - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [classPrefix, shouldToggle, appearDelay, exitDelay, trigger, visible, onVisibleChange]); useEffect(() => { diff --git a/packages/components/popup/utils/transition.ts b/packages/components/popup/utils/transition.ts index db0836e6c8..ef5e7f5a8c 100644 --- a/packages/components/popup/utils/transition.ts +++ b/packages/components/popup/utils/transition.ts @@ -1,5 +1,5 @@ export interface IAnimationTransitionParams { - classPrefix: String; + classPrefix: string; expandAnimation?: boolean; fadeAnimation?: boolean; } diff --git a/packages/components/progress/__tests__/progress.test.tsx b/packages/components/progress/__tests__/progress.test.tsx index 1ed6826623..0710dd1915 100644 --- a/packages/components/progress/__tests__/progress.test.tsx +++ b/packages/components/progress/__tests__/progress.test.tsx @@ -1,4 +1,3 @@ -/* eslint-disable prefer-destructuring */ /* * @Author: Bin * @Date: 2022-04-07 diff --git a/packages/components/qrcode/QRCode.tsx b/packages/components/qrcode/QRCode.tsx index 506ef00487..91dfb6cb1e 100644 --- a/packages/components/qrcode/QRCode.tsx +++ b/packages/components/qrcode/QRCode.tsx @@ -52,8 +52,8 @@ const QRCode: React.FC = (props) => { src: icon as string, x: undefined, y: undefined, - height: typeof iconSize === 'number' ? iconSize : iconSize?.height ?? 40, - width: typeof iconSize === 'number' ? iconSize : iconSize?.width ?? 40, + height: typeof iconSize === 'number' ? iconSize : (iconSize?.height ?? 40), + width: typeof iconSize === 'number' ? iconSize : (iconSize?.width ?? 40), excavate: true, crossOrigin: 'anonymous', }; diff --git a/packages/components/qrcode/QRCodeCanvas.tsx b/packages/components/qrcode/QRCodeCanvas.tsx index afe96c6533..348bf9a96d 100644 --- a/packages/components/qrcode/QRCodeCanvas.tsx +++ b/packages/components/qrcode/QRCodeCanvas.tsx @@ -40,13 +40,13 @@ const QRCodeCanvas = React.forwardRef((props, if (typeof ref === 'function') { ref(node); } else if (ref) { - // eslint-disable-next-line no-param-reassign ref.current = node; } }, [ref], ); + // eslint-disable-next-line @eslint-react/use-state const [, setIsImageLoaded] = React.useState(false); const { margin, cells, numCells, calculatedImageSettings } = useQRCode({ diff --git a/packages/components/qrcode/QRCodeSVG.tsx b/packages/components/qrcode/QRCodeSVG.tsx index 234fe8a863..ec5c7e1f50 100644 --- a/packages/components/qrcode/QRCodeSVG.tsx +++ b/packages/components/qrcode/QRCodeSVG.tsx @@ -57,7 +57,6 @@ const QRCodeSVG = React.forwardRef((props, ref) => { opacity={calculatedImageSettings.opacity} // when crossOrigin is not set, the image will be tainted // and the canvas cannot be exported to an image - // eslint-disable-next-line react/no-unknown-property crossOrigin={calculatedImageSettings.crossOrigin} /> ); diff --git a/packages/components/radio/RadioGroup.tsx b/packages/components/radio/RadioGroup.tsx index b24c55ac5a..6e21b16031 100644 --- a/packages/components/radio/RadioGroup.tsx +++ b/packages/components/radio/RadioGroup.tsx @@ -66,7 +66,10 @@ const RadioGroup: React.FC = (originalProps) => { if (typeof checkProps.onChange === 'function') { checkProps.onChange(checked, { e }); } - setInternalValue(checked ? checkValue : undefined, { e, name: props.name }); + setInternalValue(checked ? checkValue : undefined, { + e, + name: props.name, + }); }, }; }, @@ -98,7 +101,7 @@ const RadioGroup: React.FC = (originalProps) => { return () => { observer?.disconnect(); }; - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); useDeepEffect(() => { diff --git a/packages/components/radio/__tests__/mount.jsx b/packages/components/radio/__tests__/mount.jsx index 4190bce676..62ae9340a6 100644 --- a/packages/components/radio/__tests__/mount.jsx +++ b/packages/components/radio/__tests__/mount.jsx @@ -1,5 +1,6 @@ import React from 'react'; import { render } from '@test/utils'; + import { Radio } from '..'; // options 写法 diff --git a/packages/components/radio/__tests__/vitest-radio.test.jsx b/packages/components/radio/__tests__/vitest-radio.test.jsx index 6fe2edf469..43a60decda 100644 --- a/packages/components/radio/__tests__/vitest-radio.test.jsx +++ b/packages/components/radio/__tests__/vitest-radio.test.jsx @@ -1,13 +1,13 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ /** * 该文件由脚本自动生成,如需修改请联系 PMC * This file generated by scripts of tdesign-api. `npm run api:docs Radio React(PC) vitest,finalProject` * If you need to modify this file, contact PMC first please. */ import React from 'react'; -import { fireEvent, vi, render } from '@test/utils'; +import { fireEvent, render, vi } from '@test/utils'; + import { Radio, RadioGroup } from '..'; -import { getRadioGroupKidsMount, getRadioGroupDefaultMount } from './mount'; +import { getRadioGroupDefaultMount, getRadioGroupKidsMount } from './mount'; describe('Radio Component', () => { it('props.allowUncheck works fine', () => { diff --git a/packages/components/radio/_example/group.tsx b/packages/components/radio/_example/group.tsx index ad8580d917..2a592e8186 100644 --- a/packages/components/radio/_example/group.tsx +++ b/packages/components/radio/_example/group.tsx @@ -22,7 +22,7 @@ const objOptions: RadioOption[] = [ label: '深圳', }, ]; -// eslint-disable-next-line prefer-const + let itemOptions = ['北京', '上海', '广州', '深圳']; type ValueType = '北京' | '上海' | '广州' | '深圳'; diff --git a/packages/components/radio/useKeyboard.ts b/packages/components/radio/useKeyboard.ts index e449d6c2e2..2c5fe7cfdb 100644 --- a/packages/components/radio/useKeyboard.ts +++ b/packages/components/radio/useKeyboard.ts @@ -30,9 +30,9 @@ export default function useKeyboard( useEffect(() => { on(radioGroupRef.current, 'keydown', checkRadioInGroup); return () => { - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps off(radioGroupRef.current, 'keydown', checkRadioInGroup); }; - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); } diff --git a/packages/components/range-input/RangeInput.tsx b/packages/components/range-input/RangeInput.tsx index fa970a6719..e8bdf9609d 100644 --- a/packages/components/range-input/RangeInput.tsx +++ b/packages/components/range-input/RangeInput.tsx @@ -83,8 +83,8 @@ const RangeInput = React.forwardRef(null), }; - const [isFocused, toggleIsFocused] = useState(false); - const [isHover, toggleIsHover] = useState(false); + const [isFocused, setIsFocused] = useState(false); + const [isHover, setIsHover] = useState(false); const [firstFormat, secondFormat] = calcArrayValue(format); const [firstPlaceholder = '请输入内容', secondPlaceholder = '请输入内容'] = calcArrayValue(placeholder); const [firstInputProps, secondInputProps] = calcArrayValue(inputProps); @@ -115,23 +115,23 @@ const RangeInput = React.forwardRef) { - toggleIsHover(true); + setIsHover(true); onMouseenter?.({ e }); // @ts-ignore props.onMouseEnter?.({ e }); } function handleMouseLeave(e: React.MouseEvent) { - toggleIsHover(false); + setIsHover(false); onMouseleave?.({ e }); // @ts-ignore props.onMouseLeave?.({ e }); @@ -192,7 +192,13 @@ const RangeInput = React.forwardRef handleEnter([val, secondValue], { e, position: 'first' })} onFocus={(val, { e }) => handleFocus([val, secondValue], { e, position: 'first' })} onBlur={(val, { e }) => handleBlur([val, secondValue], { e, position: 'first' })} - onChange={(val, { e }) => onChange?.([val, secondValue], { e, position: 'first', trigger: 'input' })} + onChange={(val, { e }) => + onChange?.([val, secondValue], { + e, + position: 'first', + trigger: 'input', + }) + } {...firstInputProps} /> @@ -214,7 +220,13 @@ const RangeInput = React.forwardRef handleEnter([firstValue, val], { e, position: 'second' })} onFocus={(val, { e }) => handleFocus([firstValue, val], { e, position: 'second' })} onBlur={(val, { e }) => handleBlur([firstValue, val], { e, position: 'second' })} - onChange={(val, { e }) => onChange?.([firstValue, val], { e, position: 'second', trigger: 'input' })} + onChange={(val, { e }) => + onChange?.([firstValue, val], { + e, + position: 'second', + trigger: 'input', + }) + } {...secondInputProps} /> {suffixContent ?
{suffixContent}
: null} diff --git a/packages/components/select-input/__tests__/mount.jsx b/packages/components/select-input/__tests__/mount.jsx index e26b14b3ed..02cab580df 100644 --- a/packages/components/select-input/__tests__/mount.jsx +++ b/packages/components/select-input/__tests__/mount.jsx @@ -13,7 +13,7 @@ const OPTIONS = [ function Panel() { return (
    - {OPTIONS.map(item => ( + {OPTIONS.map((item) => (
  • {item.label} @@ -33,15 +33,5 @@ const value = [ // single select export function getSelectInputMultipleMount(SelectInput, props, events) { - return render( - - )} - {...props} - {...events} - > - ); + return render(} {...props} {...events}>); } diff --git a/packages/components/select-input/__tests__/vitest-select-input.test.jsx b/packages/components/select-input/__tests__/vitest-select-input.test.jsx index f6b3408f4b..1385b3431c 100644 --- a/packages/components/select-input/__tests__/vitest-select-input.test.jsx +++ b/packages/components/select-input/__tests__/vitest-select-input.test.jsx @@ -1,11 +1,11 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ /** * 该文件由脚本自动生成,如需修改请联系 PMC * This file generated by scripts of tdesign-api. `npm run api:docs SelectInput React(PC) vitest,finalProject` * If you need to modify this file, contact PMC first please. */ import React from 'react'; -import { fireEvent, vi, render, mockDelay } from '@test/utils'; +import { fireEvent, mockDelay, render, vi } from '@test/utils'; + import { SelectInput } from '..'; import { getSelectInputMultipleMount } from './mount'; diff --git a/packages/components/select-input/useOverlayInnerStyle.ts b/packages/components/select-input/useOverlayInnerStyle.ts index 85404697a9..aec3f9c50f 100644 --- a/packages/components/select-input/useOverlayInnerStyle.ts +++ b/packages/components/select-input/useOverlayInnerStyle.ts @@ -42,7 +42,6 @@ export default function useOverlayInnerStyle( const prevDisplay = popupElement.style.display; // 设置display来可以获取popupElement的宽度 - // eslint-disable-next-line no-param-reassign popupElement.style.display = ''; // popupElement的scrollBar宽度 const overlayScrollWidth = popupElement.offsetWidth - popupElement.scrollWidth; @@ -62,7 +61,6 @@ export default function useOverlayInnerStyle( : triggerElement.offsetWidth - overlayScrollWidth; if (prevDisplay === 'none') { - // eslint-disable-next-line no-param-reassign popupElement.style.display = 'none'; } let otherOverlayInnerStyle: React.CSSProperties = {}; @@ -98,7 +96,7 @@ export default function useOverlayInnerStyle( result = matchWidthFunc; } return result; - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [autoWidth, popupProps?.overlayInnerStyle]); return { diff --git a/packages/components/select/_example/collapsed.tsx b/packages/components/select/_example/collapsed.tsx index 04367dd4a9..89b6226408 100644 --- a/packages/components/select/_example/collapsed.tsx +++ b/packages/components/select/_example/collapsed.tsx @@ -13,7 +13,7 @@ const MultipleSelect = () => { const [value, setValue] = useState(['1', '3']); const [size, setSize] = useState<'small' | 'medium' | 'large'>('medium'); const [disabled, setDisabled] = useState(false); - const [readonly, setReadOnly] = useState(false); + const [readOnly, setReadOnly] = useState(false); const [minCollapsedNum] = useState(1); const onChange = (value: string[]) => { @@ -33,7 +33,7 @@ const MultipleSelect = () => { key={index} size={size} disabled={disabled} - closable={!readonly && !disabled} + closable={!readOnly && !disabled} onClose={(context) => onClose({ e: context.e, index: minCollapsedNum + index })} > {item.label} @@ -75,7 +75,7 @@ const MultipleSelect = () => { readonly control: - setReadOnly(value)} /> + setReadOnly(value)} /> } onChange={onSearch}> @@ -113,7 +114,7 @@ const TransferList: React.FunctionComponent = (props) => { return data; }, [currentPage, data, pagination]); - const EmptyCmp = () => + const renderEmpty = () => isString(empty) ? (
    {empty || '暂无数据'} @@ -124,7 +125,11 @@ const TransferList: React.FunctionComponent = (props) => { const contentCmp = () => { if (typeof treeNode === 'function') { - return treeNode({ data: viewData, value: checked, onChange: handleCheckbox }); + return treeNode({ + data: viewData, + value: checked, + onChange: handleCheckbox, + }); } if (typeof content === 'function') { return content({ data: viewData }); @@ -132,27 +137,33 @@ const TransferList: React.FunctionComponent = (props) => { return ( {viewData.map((item, index) => ( - + - {transferItem ? parseContentTNode(transferItem, { data: item, index, type: listType }) : item.label} + {transferItem + ? parseContentTNode(transferItem, { + data: item, + index, + type: listType, + }) + : item.label} ))} ); }; - const BodyCmp = () => ( + const renderBody = () => (
    - {SearchCmp()} -
    {viewData.length ? contentCmp() : EmptyCmp()}
    + {renderSearch()} +
    {viewData.length ? contentCmp() : renderEmpty()}
    ); - const PaginationCmp = () => { + const renderPagination = () => { const handleCurrentPagination = (current: number) => { setCurrentPage(current); if (isFunction(pagination.onPageChange)) { @@ -161,7 +172,7 @@ const TransferList: React.FunctionComponent = (props) => { }; return pagination ? ( -
    +
    = (props) => { const footerCmp = () => (!isEmpty(footer) ?
    {footer}
    : null); return ( -
    - {HeaderCmp()} - {BodyCmp()} - {PaginationCmp()} +
    + {renderHeader()} + {renderBody()} + {renderPagination()} {footerCmp()}
    ); diff --git a/packages/components/transfer/__tests__/transfer.test.tsx b/packages/components/transfer/__tests__/transfer.test.tsx index 0bf929781d..83fe78082a 100644 --- a/packages/components/transfer/__tests__/transfer.test.tsx +++ b/packages/components/transfer/__tests__/transfer.test.tsx @@ -6,6 +6,9 @@ import Transfer from '../index'; import type { DataOption, TransferValue } from '../index'; +const TreeNode = (props) => ; +const TransferItem = ({ data }: { data?: DataOption }) =>
    {data.label}
    ; + describe('Transfer 测试', () => { test('Transfer default加入测试', async () => { const InputPlaceholder = '请输入关键词搜索'; @@ -47,7 +50,9 @@ describe('Transfer 测试', () => { const transContainerR = await waitFor(() => document.querySelector('.t-transfer__list-target')); expect(transContainerR).toHaveTextContent('点击test2'); // 测试搜索框 - fireEvent.change(queryAllByPlaceholderText(InputPlaceholder)[0], { target: { value: InputValue } }); + fireEvent.change(queryAllByPlaceholderText(InputPlaceholder)[0], { + target: { value: InputValue }, + }); const transContainerSL = await waitFor(() => document.querySelector('.t-transfer__list-source')); expect(transContainerSL).not.toHaveTextContent('点击test1'); }); @@ -79,26 +84,25 @@ describe('Transfer 测试', () => { }); test('Transfer tree进入测试', async () => { - const TestComponent2 = () => { - const list = [ - { - value: '2', - label: '2', - children: [ - { - value: 'test2.1', - label: 'test2.1', - }, - { - value: '2.2', - label: '2.2', - }, - ], - }, - ]; - const TreeNode = (props) => ; - return ; - }; + const treeList = [ + { + value: '2', + label: '2', + children: [ + { + value: 'test2.1', + label: 'test2.1', + }, + { + value: '2.2', + label: '2.2', + }, + ], + }, + ]; + const TestComponent2 = () => ( + + ); const { getByText } = render(); // expect(document.querySelector('.t-transfer__list-source')).toHaveTextContent('test2.1'); @@ -134,8 +138,6 @@ describe('Transfer 测试', () => { }, ]; - const TransferItem = ({ data }: { data?: DataOption }) =>
    {data.label}
    ; - function TestComponent() { const [value, setValue] = useState(['1']); return setValue(v)} transferItem={} />; @@ -158,8 +160,6 @@ describe('Transfer 测试', () => { }, ]; - const TransferItem = ({ data }: { data?: DataOption }) =>
    {data.label}
    ; - function TestComponent() { const [value, setValue] = useState(['1']); return setValue(v)} transferItem={TransferItem} />; diff --git a/packages/components/transfer/_example/custom.tsx b/packages/components/transfer/_example/custom.tsx index b6c13f3d3a..97367d8b1a 100644 --- a/packages/components/transfer/_example/custom.tsx +++ b/packages/components/transfer/_example/custom.tsx @@ -21,20 +21,15 @@ export default function BaseExample() { return ( -
    目标
    - , - ]} + title={['来源',
    目标
    ]} operation={['加入', '移除']} footer={[ - <> -
    选中并加入
    - , - <> -
    选中并移除
    - , +
    + 选中并加入 +
    , +
    + 选中并加入 +
    , ]} >
    ); diff --git a/packages/components/tree-select/TreeSelect.tsx b/packages/components/tree-select/TreeSelect.tsx index 562377e2ed..6082142d7c 100644 --- a/packages/components/tree-select/TreeSelect.tsx +++ b/packages/components/tree-select/TreeSelect.tsx @@ -26,8 +26,7 @@ import type { TreeInstanceFunctions, TreeProps } from '../tree'; import type { TdTreeSelectProps, TreeSelectValue } from './type'; export interface TreeSelectProps - extends TdTreeSelectProps, - StyledProps {} + extends TdTreeSelectProps, StyledProps {} export interface NodeOptions { label: string; @@ -145,7 +144,7 @@ const TreeSelect = forwardRef((originalProps return result; }, []); // data 发生变更时,normalizedValue 也需要更新 - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [normalizeValue, value, data]); const internalInputValue = useMemo(() => { @@ -210,7 +209,10 @@ const TreeSelect = forwardRef((originalProps }); } // 单选选择后收起弹框 - setPopupVisible(false, { ...context, trigger: 'trigger-element-click' }); + setPopupVisible(false, { + ...context, + trigger: 'trigger-element-click', + }); }); const handleMultiChange = usePersistFn((value, context) => { @@ -284,7 +286,11 @@ const TreeSelect = forwardRef((originalProps const handleEnter = usePersistFn((_, ctx) => { onSearch?.(ctx.inputValue, { e: ctx.e }); - onEnter?.({ inputValue: ctx.inputValue, e: ctx.e, value: getTreeSelectEventValue() }); + onEnter?.({ + inputValue: ctx.inputValue, + e: ctx.e, + value: getTreeSelectEventValue(), + }); }); const handleFilterChange = usePersistFn((value, ctx) => { @@ -343,7 +349,12 @@ const TreeSelect = forwardRef((originalProps panel={renderTree()} allowInput={filterable} inputProps={{ ...inputProps, size }} - tagInputProps={{ size, excessTagsDisplayType: 'break-line', inputProps, tagProps: props.tagProps }} + tagInputProps={{ + size, + excessTagsDisplayType: 'break-line', + inputProps, + tagProps: props.tagProps, + }} placeholder={inputPlaceholder} popupVisible={popupVisible && !disabled} onInputChange={handleFilterChange} diff --git a/packages/components/tree-select/__tests__/mount.jsx b/packages/components/tree-select/__tests__/mount.jsx index 28e1d0c199..919ab5f650 100644 --- a/packages/components/tree-select/__tests__/mount.jsx +++ b/packages/components/tree-select/__tests__/mount.jsx @@ -18,25 +18,11 @@ const OPTIONS = [ ]; export function getTreeSelectDefaultMount(TreeSelect, props, events) { - return render( - - ); + return render(); } // single select export function getTreeSelectMultipleMount(TreeSelect, props, events) { const value = [1, 2, 3, '4', '5']; - return render( - - ); + return render(); } diff --git a/packages/components/tree-select/__tests__/vitest-tree-select.test.jsx b/packages/components/tree-select/__tests__/vitest-tree-select.test.jsx index ae5d317782..4e69e03ca8 100644 --- a/packages/components/tree-select/__tests__/vitest-tree-select.test.jsx +++ b/packages/components/tree-select/__tests__/vitest-tree-select.test.jsx @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ /** * 该文件由脚本自动生成,如需修改请联系 PMC * This file generated by scripts of tdesign-api. `npm run api:docs TreeSelect React(PC) vitest,finalProject` @@ -7,13 +6,14 @@ import React from 'react'; import { fireEvent, - vi, - render, mockDelay, - simulateInputChange, + render, simulateDocumentMouseEvent, + simulateInputChange, simulateInputEnter, + vi, } from '@test/utils'; + import { TreeSelect } from '..'; import { getTreeSelectDefaultMount, getTreeSelectMultipleMount } from './mount'; @@ -164,7 +164,6 @@ describe('TreeSelect Component', () => { it('props.filter: priority of onSearch is higher than props.filter, props.filter is forbidden to work in this scene', async () => { const { container } = getTreeSelectMultipleMount(TreeSelect, { - // eslint-disable-next-line @typescript-eslint/no-empty-function onSearch: () => {}, filter: (filterWord, option) => !filterWord || option.label === filterWord, }); diff --git a/packages/components/tree/Tree.tsx b/packages/components/tree/Tree.tsx index 928cb4ab91..f047919db9 100644 --- a/packages/components/tree/Tree.tsx +++ b/packages/components/tree/Tree.tsx @@ -89,7 +89,10 @@ const Tree = forwardRef, TreeProps>((origi ( node: TreeNode, isExpanded: boolean, - ctx: { e?: MouseEvent; trigger: 'node-click' | 'icon-click' | 'setItem' }, + ctx: { + e?: MouseEvent; + trigger: 'node-click' | 'icon-click' | 'setItem'; + }, ) => { const { e, trigger } = ctx; const expanded = node.setExpanded(isExpanded); @@ -104,7 +107,10 @@ const Tree = forwardRef, TreeProps>((origi ( node: TreeNode, isIndeterminate: boolean, - ctx: { e?: MouseEvent; trigger: 'node-click' | 'icon-click' | 'setItem' }, + ctx: { + e?: MouseEvent; + trigger: 'node-click' | 'icon-click' | 'setItem'; + }, ) => { // eslint-disable-next-line @typescript-eslint/no-unused-vars const { e, trigger } = ctx; @@ -133,7 +139,10 @@ const Tree = forwardRef, TreeProps>((origi ( node: TreeNode, isActived: boolean, - ctx: { e?: MouseEvent; trigger: 'node-click' | 'setItem' }, + ctx: { + e?: MouseEvent; + trigger: 'node-click' | 'setItem'; + }, ) => { const actived = node.setActived(isActived); const treeNodeModel = node?.getModel(); @@ -174,7 +183,11 @@ const Tree = forwardRef, TreeProps>((origi if (!node || disabled || node.disabled) return; const checked = node.toggleChecked(); const treeNodeModel = node?.getModel(); - onChange?.(checked, { node: treeNodeModel, ...ctx, trigger: 'node-click' }); + onChange?.(checked, { + node: treeNodeModel, + ...ctx, + trigger: 'node-click', + }); }; const handleScrollToElement = useCallback( @@ -268,7 +281,9 @@ const Tree = forwardRef, TreeProps>((origi if ('indeterminate' in options) { // @ts-ignore setTreeIndeterminate((prevIndeterminate: TreeNodeValue[]) => [...prevIndeterminate, value]); - setIndeterminate(node, spec.indeterminate, { trigger: 'setItem' }); + setIndeterminate(node, spec.indeterminate, { + trigger: 'setItem', + }); delete spec.indeterminate; } node.set(spec); @@ -284,7 +299,7 @@ const Tree = forwardRef, TreeProps>((origi // 因为 CSSTransition 是个数组,与 visibleNodes 对应,所以这里根据 visibleNodes 的长度创建 ref 用来保存 dom // visibleNodes 改变的时候,释放上一个 nodeList,防止内存泄漏 const nodeList = useMemo[]>( - () => visibleNodes.map(() => React.createRef()), + () => visibleNodes.map(() => ({ current: null })), [visibleNodes], ); diff --git a/packages/components/tree/TreeItem.tsx b/packages/components/tree/TreeItem.tsx index f115906697..db1aba648a 100644 --- a/packages/components/tree/TreeItem.tsx +++ b/packages/components/tree/TreeItem.tsx @@ -207,6 +207,7 @@ const TreeItem = forwardRef( useRipple(labelDom); // setData需要强制刷新组件来更新数据 + // eslint-disable-next-line @eslint-react/use-state const [, updateRender] = useState({}); const renderLabel = () => { @@ -311,7 +312,7 @@ const TreeItem = forwardRef( try { // ie throw error firefox-need-it evt.dataTransfer?.setData('text/plain', ''); - } catch (e) { + } catch (_) { // empty } }; diff --git a/packages/components/tree/__tests__/vitest-tree.test.jsx b/packages/components/tree/__tests__/vitest-tree.test.jsx index cf7ebfb2ac..10a6686b03 100644 --- a/packages/components/tree/__tests__/vitest-tree.test.jsx +++ b/packages/components/tree/__tests__/vitest-tree.test.jsx @@ -5,7 +5,8 @@ * If you need to modify this file, contact PMC first please. */ import React from 'react'; -import { fireEvent, vi, mockDelay } from '@test/utils'; +import { fireEvent, mockDelay, vi } from '@test/utils'; + import { Tree } from '..'; import { getTreeDefaultMount } from './mount'; diff --git a/packages/components/tree/hooks/useStore.ts b/packages/components/tree/hooks/useStore.ts index ec1ce367ca..00cb57e8ed 100644 --- a/packages/components/tree/hooks/useStore.ts +++ b/packages/components/tree/hooks/useStore.ts @@ -50,7 +50,7 @@ export function useStore( useEffect(() => { if (!allowFoldNodeOnFilter) return; toggleFilterChanged(JSON.stringify(preFilter) !== JSON.stringify(filter)); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [filter, allowFoldNodeOnFilter]); // 在 update 之后检查,如果之前 filter 有变更,则检查路径节点是否需要展开 diff --git a/packages/components/tree/hooks/useTreeVirtualScroll.ts b/packages/components/tree/hooks/useTreeVirtualScroll.ts index 1489c3c97e..68ac91b805 100644 --- a/packages/components/tree/hooks/useTreeVirtualScroll.ts +++ b/packages/components/tree/hooks/useTreeVirtualScroll.ts @@ -35,7 +35,7 @@ export default function useTreeVirtualScroll({ rowHeight: scroll?.rowHeight || 34, bufferSize: scroll?.bufferSize || 20, threshold: scrollThreshold, - } as const), + }) as const, [scroll, scrollThreshold], ); @@ -62,7 +62,6 @@ export default function useTreeVirtualScroll({ const top = target.scrollTop; if (lastScrollY !== top) { handleVirtualScroll(); - // eslint-disable-next-line react-hooks/exhaustive-deps } else { lastScrollY = -1; } diff --git a/packages/components/tree/interface.ts b/packages/components/tree/interface.ts index e4cd775d30..50a91729fe 100644 --- a/packages/components/tree/interface.ts +++ b/packages/components/tree/interface.ts @@ -9,21 +9,20 @@ export interface TypeEventState extends TypeTreeEventState { path?: TreeNode[]; } -export interface TreeItemProps - extends Pick< - TreeProps, - | 'empty' - | 'activable' - | 'icon' - | 'label' - | 'line' - | 'transition' - | 'expandOnClickNode' - | 'activable' - | 'operations' - | 'checkProps' - | 'disableCheck' - > { +export interface TreeItemProps extends Pick< + TreeProps, + | 'empty' + | 'activable' + | 'icon' + | 'label' + | 'line' + | 'transition' + | 'expandOnClickNode' + | 'activable' + | 'operations' + | 'checkProps' + | 'disableCheck' +> { /** * 树节点数据对象 */ @@ -34,7 +33,12 @@ export interface TreeItemProps */ onClick?: ( node: TreeNode, - options: { e: MouseEvent; expand: boolean; active: boolean; trigger: 'node-click' | 'icon-click' }, + options: { + e: MouseEvent; + expand: boolean; + active: boolean; + trigger: 'node-click' | 'icon-click'; + }, ) => void; /** diff --git a/packages/components/typography/ellipsis/Truncate.tsx b/packages/components/typography/ellipsis/Truncate.tsx index ab26cc1488..4dbf2c08f4 100644 --- a/packages/components/typography/ellipsis/Truncate.tsx +++ b/packages/components/typography/ellipsis/Truncate.tsx @@ -67,11 +67,9 @@ export default class Truncate extends React.Component { this.replacedLinks.forEach((item) => { - // eslint-disable-next-line no-param-reassign content = content.replace(item.key, item[0]); }); diff --git a/packages/components/typography/ellipsis/useEllipsis.tsx b/packages/components/typography/ellipsis/useEllipsis.tsx index 6a5202c396..216be0080e 100644 --- a/packages/components/typography/ellipsis/useEllipsis.tsx +++ b/packages/components/typography/ellipsis/useEllipsis.tsx @@ -1,4 +1,3 @@ -/* eslint-disable no-nested-ternary */ import React, { useState } from 'react'; import { isFunction } from 'lodash-es'; @@ -31,10 +30,10 @@ export default function useEllipsis(ellipsis: boolean | TypographyEllipsis) { typeof ellipsis?.suffix === 'function' ? ellipsis?.suffix({ expanded }) : expanded - ? collapseText - : ellipsis?.expandable - ? `${expandText}` - : '...', + ? collapseText + : ellipsis?.expandable + ? `${expandText}` + : '...', collapsible: ellipsis?.collapsible ?? false, }; } diff --git a/packages/components/upload/__tests__/request/index.js b/packages/components/upload/__tests__/request/index.js index 5f1e87c016..d1ad7774fe 100644 --- a/packages/components/upload/__tests__/request/index.js +++ b/packages/components/upload/__tests__/request/index.js @@ -1,37 +1,48 @@ -import { setupServer } from 'msw/node'; import { rest } from 'msw'; +import { setupServer } from 'msw/node'; export function getUploadServer() { - return setupServer(...[ - // mock file upload success - rest.post('https://tdesign.test.com/upload/file_success', (req, res, ctx) => { - return res(ctx.status(200), ctx.json({ - ret: 0, - data: { - name: 'tdesign.min.js', - url: 'https://tdesign.gtimg.com/site/spline/script/tdesign.min.js' - } - })) - }), - // mock image upload success - rest.post('https://tdesign.test.com/upload/image_success', (req, res, ctx) => { - return res(ctx.status(200), ctx.json({ - code: 200, - name: 'demo-image-1.png', - url: 'https://tdesign.gtimg.com/demo/demo-image-1.png' - })) - }), - // mock upload failed on status - rest.post('https://tdesign.test.com/upload/fail/status_error', (req, res, ctx) => { - return res(ctx.status(500), ctx.json({})) - }), - // mock upload failed in response - rest.post('https://tdesign.test.com/upload/fail/response_error', (req, res, ctx) => { - return res(ctx.status(200), ctx.json({ - code: 1001, - name: 'file-name.txt', - error: 'upload failed' - })) - }), - ]) + return setupServer( + ...[ + // mock file upload success + rest.post('https://tdesign.test.com/upload/file_success', (req, res, ctx) => { + return res( + ctx.status(200), + ctx.json({ + ret: 0, + data: { + name: 'tdesign.min.js', + url: 'https://tdesign.gtimg.com/site/spline/script/tdesign.min.js', + }, + }), + ); + }), + // mock image upload success + rest.post('https://tdesign.test.com/upload/image_success', (req, res, ctx) => { + return res( + ctx.status(200), + ctx.json({ + code: 200, + name: 'demo-image-1.png', + url: 'https://tdesign.gtimg.com/demo/demo-image-1.png', + }), + ); + }), + // mock upload failed on status + rest.post('https://tdesign.test.com/upload/fail/status_error', (req, res, ctx) => { + return res(ctx.status(500), ctx.json({})); + }), + // mock upload failed in response + rest.post('https://tdesign.test.com/upload/fail/response_error', (req, res, ctx) => { + return res( + ctx.status(200), + ctx.json({ + code: 1001, + name: 'file-name.txt', + error: 'upload failed', + }), + ); + }), + ], + ); } diff --git a/packages/components/upload/__tests__/vitest-upload.test.jsx b/packages/components/upload/__tests__/vitest-upload.test.jsx index c1ab14f9cf..df37da3e8b 100644 --- a/packages/components/upload/__tests__/vitest-upload.test.jsx +++ b/packages/components/upload/__tests__/vitest-upload.test.jsx @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-unused-vars */ /** * 该文件由脚本自动生成,如需修改请联系 PMC * This file generated by scripts of tdesign-api. `npm run api:docs Upload React(PC) vitest,finalProject` @@ -7,13 +6,14 @@ import React from 'react'; import { fireEvent, - vi, - render, - mockDelay, - simulateFileChange, getFakeFileList, + mockDelay, + render, simulateDragFileChange, + simulateFileChange, + vi, } from '@test/utils'; + import { Upload } from '..'; import { getUploadServer } from './request'; diff --git a/packages/components/upload/_example/base.tsx b/packages/components/upload/_example/base.tsx index e60a12a69e..3b60695244 100644 --- a/packages/components/upload/_example/base.tsx +++ b/packages/components/upload/_example/base.tsx @@ -93,7 +93,6 @@ export default function UploadExample() { }; // 仅自定义文件列表所需 - // eslint-disable-next-line const outsideRemove = (index: number) => { const tmpFiles = [...files3]; tmpFiles.splice(index, 1); @@ -127,7 +126,11 @@ export default function UploadExample() { }; // 用于格式化接口响应值,error 会被用于上传失败的提示文字;url 表示文件/图片地址 - const formatResponse: UploadProps['formatResponse'] = (res) => ({ ...res, error: '上传失败,请重试', url: res?.url }); + const formatResponse: UploadProps['formatResponse'] = (res) => ({ + ...res, + error: '上传失败,请重试', + url: res?.url, + }); /** 单个文件校验方法,示例代码有效,勿删 */ // const beforeUpload = (file) => { diff --git a/packages/components/upload/_example/img-flow-list.tsx b/packages/components/upload/_example/img-flow-list.tsx index 3f65e00c06..a6c9636092 100644 --- a/packages/components/upload/_example/img-flow-list.tsx +++ b/packages/components/upload/_example/img-flow-list.tsx @@ -19,8 +19,16 @@ export default function TUploadImageFlow() { const [showImageFileName, setShowImageFileName] = useState(true); const [showUploadButton, setShowUploadButton] = useState(true); const [files, setFiles] = useState([ - { url: 'https://tdesign.gtimg.com/demo/demo-image-1.png', status: 'success', name: 'demo-image-1.png' }, - { url: 'https://tdesign.gtimg.com/site/avatar.jpg', status: 'success', name: 'avatar.jpg' }, + { + url: 'https://tdesign.gtimg.com/demo/demo-image-1.png', + status: 'success', + name: 'demo-image-1.png', + }, + { + url: 'https://tdesign.gtimg.com/site/avatar.jpg', + status: 'success', + name: 'avatar.jpg', + }, ]); // eslint-disable-next-line const [files2, setFiles2] = useState([]); @@ -50,7 +58,6 @@ export default function TUploadImageFlow() { ]; // 示例代码:自定义上传方法,一个请求上传一个文件 - // eslint-disable-next-line const requestMethod1 = () => { return new Promise((resolve) => { resolve(FILE_EXAMPLE); @@ -61,8 +68,16 @@ export default function TUploadImageFlow() { // eslint-disable-next-line const requestMethod2 = () => { const files = [ - { name: files2[0].name, status: 'success', url: 'https://tdesign.gtimg.com/site/avatar.jpg' }, - { name: files2[1].name, status: 'success', url: 'https://avatars.githubusercontent.com/u/11605702?v=4' }, + { + name: files2[0].name, + status: 'success', + url: 'https://tdesign.gtimg.com/site/avatar.jpg', + }, + { + name: files2[1].name, + status: 'success', + url: 'https://avatars.githubusercontent.com/u/11605702?v=4', + }, ]; return new Promise((resolve) => { resolve({ diff --git a/packages/components/upload/hooks/useUpload.ts b/packages/components/upload/hooks/useUpload.ts index d689d80454..bbdc17e56b 100644 --- a/packages/components/upload/hooks/useUpload.ts +++ b/packages/components/upload/hooks/useUpload.ts @@ -33,6 +33,8 @@ export default function useUpload(props: TdUploadProps) { const xhrReq = useRef<{ files: UploadFile[]; xhrReq: XMLHttpRequest }[]>([]); const [toUploadFiles, setToUploadFiles] = useState([]); const [sizeOverLimitMessage, setSizeOverLimitMessage] = useState(''); + + // eslint-disable-next-line @eslint-react/use-state const [update, forceUpdate] = useState({}); const locale = useMemo(() => merge({}, globalLocale, props.locale), [globalLocale, props.locale]); @@ -163,7 +165,9 @@ export default function useUpload(props: TdUploadProps) { const onFileChange = (files: File[]) => { if (disabled) return; // @ts-ignore - props.onSelectChange?.([...files], { currentSelectedFiles: formatToUploadFile([...files], props.format) }); + props.onSelectChange?.([...files], { + currentSelectedFiles: formatToUploadFile([...files], props.format), + }); validateFile({ uploadValue, // @ts-ignore @@ -179,17 +183,26 @@ export default function useUpload(props: TdUploadProps) { }).then((args) => { // 自定义全文件校验不通过 if (args.validateResult?.type === 'BEFORE_ALL_FILES_UPLOAD') { - props.onValidate?.({ type: 'BEFORE_ALL_FILES_UPLOAD', files: args.files }); + props.onValidate?.({ + type: 'BEFORE_ALL_FILES_UPLOAD', + files: args.files, + }); return; } // 文件数量校验不通过 if (args.lengthOverLimit) { - props.onValidate?.({ type: 'FILES_OVER_LENGTH_LIMIT', files: args.files }); + props.onValidate?.({ + type: 'FILES_OVER_LENGTH_LIMIT', + files: args.files, + }); if (!args.files.length) return; } // 过滤相同的文件名 if (args.hasSameNameFile) { - props.onValidate?.({ type: 'FILTER_FILE_SAME_NAME', files: args.files }); + props.onValidate?.({ + type: 'FILTER_FILE_SAME_NAME', + files: args.files, + }); } // 文件大小校验结果处理(已过滤超出限制的文件) if (args.fileValidateList instanceof Array) { @@ -198,16 +211,25 @@ export default function useUpload(props: TdUploadProps) { getSizeLimitError, ); const tmpWaitingFiles = autoUpload ? toFiles : toUploadFiles.concat(toFiles); - props.onWaitingUploadFilesChange?.({ files: tmpWaitingFiles, trigger: 'validate' }); + props.onWaitingUploadFilesChange?.({ + files: tmpWaitingFiles, + trigger: 'validate', + }); // 文件大小处理 if (sizeLimitErrors[0]) { setSizeOverLimitMessage(sizeLimitErrors[0].file.response.error); - props.onValidate?.({ type: 'FILE_OVER_SIZE_LIMIT', files: sizeLimitErrors.map((t) => t.file) }); + props.onValidate?.({ + type: 'FILE_OVER_SIZE_LIMIT', + files: sizeLimitErrors.map((t) => t.file), + }); } else { setSizeOverLimitMessage(''); // 自定义方法 beforeUpload 拦截的文件 if (beforeUploadErrorFiles.length) { - props.onValidate?.({ type: 'CUSTOM_BEFORE_UPLOAD', files: beforeUploadErrorFiles }); + props.onValidate?.({ + type: 'CUSTOM_BEFORE_UPLOAD', + files: beforeUploadErrorFiles, + }); } } // 如果是自动上传 @@ -321,7 +343,10 @@ export default function useUpload(props: TdUploadProps) { if (autoUpload) { setToUploadFiles(failedFiles); - props.onWaitingUploadFilesChange?.({ files: failedFiles, trigger: 'uploaded' }); + props.onWaitingUploadFilesChange?.({ + files: failedFiles, + trigger: 'uploaded', + }); } }); }) @@ -356,7 +381,10 @@ export default function useUpload(props: TdUploadProps) { tmpFiles.splice(p.index - uploadValue.length, 1); // toUploadFiles.current = [...tmpFiles]; setToUploadFiles([...tmpFiles]); - props.onWaitingUploadFilesChange?.({ files: [...tmpFiles], trigger: 'remove' }); + props.onWaitingUploadFilesChange?.({ + files: [...tmpFiles], + trigger: 'remove', + }); } props.onRemove?.(p); } @@ -403,7 +431,7 @@ export default function useUpload(props: TdUploadProps) { setToUploadFiles([]); props.onWaitingUploadFilesChange?.({ files: [], trigger: 'remove' }); } - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [uploadValue]); return { diff --git a/packages/components/watermark/Watermark.tsx b/packages/components/watermark/Watermark.tsx index 15834f5126..a67777fe12 100644 --- a/packages/components/watermark/Watermark.tsx +++ b/packages/components/watermark/Watermark.tsx @@ -1,4 +1,3 @@ -/* eslint-disable no-nested-ternary */ import React, { useCallback, useEffect, useRef, useState } from 'react'; import classNames from 'classnames'; import injectStyle from '@tdesign/common-js/utils/injectStyle'; diff --git a/packages/pro-components/chat/_util/useDynamicStyle.ts b/packages/pro-components/chat/_util/useDynamicStyle.ts index b76ecfc77e..6b4ca488ae 100644 --- a/packages/pro-components/chat/_util/useDynamicStyle.ts +++ b/packages/pro-components/chat/_util/useDynamicStyle.ts @@ -36,10 +36,10 @@ export const useDynamicStyle = (elementRef: MutableRefObject return () => { document.head.removeChild(styleElement); if (currentElement) { - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps currentElement.classList.remove(styleId.current); } }; - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [cssVariables]); }; diff --git a/packages/pro-components/chat/chat-engine/_example/agui-basic.tsx b/packages/pro-components/chat/chat-engine/_example/agui-basic.tsx index 0babb0964f..70c2a4f847 100644 --- a/packages/pro-components/chat/chat-engine/_example/agui-basic.tsx +++ b/packages/pro-components/chat/chat-engine/_example/agui-basic.tsx @@ -64,7 +64,7 @@ export default function AguiBasicExample() { }; loadHistoryMessages(); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); const handleSend = async (e: CustomEvent) => { diff --git a/packages/pro-components/chat/chat-engine/_example/agui-videoclip.tsx b/packages/pro-components/chat/chat-engine/_example/agui-videoclip.tsx index 8da259acee..b024295bdf 100644 --- a/packages/pro-components/chat/chat-engine/_example/agui-videoclip.tsx +++ b/packages/pro-components/chat/chat-engine/_example/agui-videoclip.tsx @@ -43,10 +43,26 @@ const { StepItem } = Steps; // 状态映射 const statusMap: Record = { - pending: { theme: 'default', status: 'default', icon: }, - running: { theme: 'primary', status: 'process', icon: }, - completed: { theme: 'success', status: 'finish', icon: }, - failed: { theme: 'danger', status: 'error', icon: }, + pending: { + theme: 'default', + status: 'default', + icon: , + }, + running: { + theme: 'primary', + status: 'process', + icon: , + }, + completed: { + theme: 'success', + status: 'finish', + icon: , + }, + failed: { + theme: 'danger', + status: 'error', + icon: , + }, }; // 自定义Hook:状态跟踪 @@ -254,7 +270,7 @@ export const VideoClipSteps: React.FC = ({ boundStateKey }) const [isManualSelection, setIsManualSelection] = useState(false); // 可点击的状态 - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps const canClickState = ['completed', 'running']; // 提取当前组件关心的状态数据 @@ -495,6 +511,7 @@ export default function VideoClipAgentChatWithSubscription() { const { chatEngine, messages, status } = useChat({ defaultMessages: [], + // @ts-ignore chatServiceConfig: createChatServiceConfig(), }); @@ -540,6 +557,7 @@ export default function VideoClipAgentChatWithSubscription() { const handleToolCallRespond = async (toolcall: ToolCall, response: T) => { try { // 构造新的请求参数 + // @ts-ignore const tools = chatEngine.getToolcallByName(toolcall.toolCallName) || {}; const newRequestParams: ChatRequestParams = { prompt: inputValue, @@ -570,6 +588,7 @@ export default function VideoClipAgentChatWithSubscription() { // 使用统一的 ToolCallRenderer 处理所有工具调用 return (
    + {/* @ts-ignore */}
    ); @@ -595,7 +614,7 @@ export default function VideoClipAgentChatWithSubscription() { isLast && message.status !== 'stop' && (
    - +
    ) )} @@ -628,6 +647,7 @@ export default function VideoClipAgentChatWithSubscription() {
    {/* 聊天区域 */} + {/* @ts-ignore */} {messages.map((message, idx) => ( diff --git a/packages/pro-components/chat/chat-engine/hooks/useAgentToolcall.ts b/packages/pro-components/chat/chat-engine/hooks/useAgentToolcall.ts index 790fb1a82d..1a7b09625e 100644 --- a/packages/pro-components/chat/chat-engine/hooks/useAgentToolcall.ts +++ b/packages/pro-components/chat/chat-engine/hooks/useAgentToolcall.ts @@ -92,7 +92,7 @@ export function useAgentToolcall { configs.forEach((cfg) => { agentToolcallRegistry.unregister(cfg.name); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps autoRegisteredNamesRef.current.delete(cfg.name); }); }; @@ -118,5 +118,9 @@ export interface ToolConfigWithStateOptions; subscribeKey?: (props: ToolcallComponentProps) => string | undefined; - component: React.ComponentType & { agentState?: Record }>; + component: React.ComponentType< + ToolcallComponentProps & { + agentState?: Record; + } + >; } diff --git a/packages/pro-components/chat/chat-engine/hooks/useChat.ts b/packages/pro-components/chat/chat-engine/hooks/useChat.ts index e8344bdc39..b02460ee83 100644 --- a/packages/pro-components/chat/chat-engine/hooks/useChat.ts +++ b/packages/pro-components/chat/chat-engine/hooks/useChat.ts @@ -43,7 +43,7 @@ export const useChat = ({ defaultMessages: initialMessages, chatServiceConfig }: useEffect(() => { initChat(); return () => msgSubscribeRef.current?.(); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); // 监听 defaultMessages 变化 diff --git a/packages/pro-components/chat/chatbot/_example/basic.tsx b/packages/pro-components/chat/chatbot/_example/basic.tsx index 0d6fce85d4..214ae3a02c 100644 --- a/packages/pro-components/chat/chatbot/_example/basic.tsx +++ b/packages/pro-components/chat/chatbot/_example/basic.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react-hooks/rules-of-hooks */ import React, { useEffect, useRef, useState } from 'react'; import { InternetIcon } from 'tdesign-icons-react'; import { Button, Space } from 'tdesign-react'; @@ -43,12 +42,15 @@ const mockData: ChatMessagesData[] = [ }, ]; -export default function chatSample() { +export default function ChatSample() { const chatRef = useRef(null); const [activeR1, setR1Active] = useState(false); const [activeSearch, setSearchActive] = useState(false); const [ready, setReady] = useState(false); - const reqParamsRef = useRef<{ think: boolean; search: boolean }>({ think: false, search: false }); + const reqParamsRef = useRef<{ think: boolean; search: boolean }>({ + think: false, + search: false, + }); // 消息属性配置 const messageProps = (msg: ChatMessagesData): TdChatMessageConfigItem => { diff --git a/packages/pro-components/chat/chatbot/_example/code.tsx b/packages/pro-components/chat/chatbot/_example/code.tsx index 1484000dd6..eddcbdc20f 100644 --- a/packages/pro-components/chat/chatbot/_example/code.tsx +++ b/packages/pro-components/chat/chatbot/_example/code.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react-hooks/rules-of-hooks */ import React, { useRef } from 'react'; import { Card, DialogPlugin, Space } from 'tdesign-react'; import { ChatBot } from '@tdesign-react/chat'; @@ -91,7 +90,7 @@ const PreviewCard = ({ header, desc, loading, code }) => { ); }; -export default function chatSample() { +export default function ChatSample() { const chatRef = useRef(null); const [mockMessage, setMockMessage] = React.useState(mockData); @@ -119,6 +118,7 @@ export default function chatSample() { breaks: true, typographer: true, }, + // @ts-ignore pluginConfig: [ // 按需加载,开启插件 { diff --git a/packages/pro-components/chat/chatbot/_example/comprehensive.tsx b/packages/pro-components/chat/chatbot/_example/comprehensive.tsx index 8deae48260..0a3193b765 100644 --- a/packages/pro-components/chat/chatbot/_example/comprehensive.tsx +++ b/packages/pro-components/chat/chatbot/_example/comprehensive.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react-hooks/rules-of-hooks */ import React, { useEffect, useRef, useState } from 'react'; import { SystemSumIcon } from 'tdesign-icons-react'; import { Button, Select, Space } from 'tdesign-react'; @@ -57,11 +56,14 @@ const selectOptions = [ }, ]; -export default function chatSample() { +export default function ChatSample() { const chatRef = useRef(null); const [activeSearch, setSearchActive] = useState(false); const [ready, setReady] = useState(false); - const reqParamsRef = useRef<{ think: boolean; search: boolean }>({ think: false, search: false }); + const reqParamsRef = useRef<{ think: boolean; search: boolean }>({ + think: false, + search: false, + }); // 消息属性配置 const messageProps = (msg: ChatMessagesData): TdChatMessageConfigItem => { diff --git a/packages/pro-components/chat/chatbot/_example/docs.tsx b/packages/pro-components/chat/chatbot/_example/docs.tsx index dfba531c1c..4c7bca18dd 100644 --- a/packages/pro-components/chat/chatbot/_example/docs.tsx +++ b/packages/pro-components/chat/chatbot/_example/docs.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react-hooks/rules-of-hooks */ import React, { useRef, useState } from 'react'; import { ChatBot } from '@tdesign-react/chat'; @@ -28,7 +27,7 @@ const mockData: ChatMessagesData[] = [ }, ]; -export default function chatSample() { +export default function ChatSample() { const chatRef = useRef(null); const [files, setFiles] = useState([]); diff --git a/packages/pro-components/chat/chatbot/_example/image.tsx b/packages/pro-components/chat/chatbot/_example/image.tsx index e50ec71f37..983af615f1 100644 --- a/packages/pro-components/chat/chatbot/_example/image.tsx +++ b/packages/pro-components/chat/chatbot/_example/image.tsx @@ -1,4 +1,3 @@ -/* eslint-disable react-hooks/rules-of-hooks */ import React, { useEffect, useRef, useState } from 'react'; import { BrowseIcon, Filter3Icon, ImageAddIcon, Transform1Icon } from 'tdesign-icons-react'; import { Button, Dropdown, Image, ImageViewer, Skeleton, Space } from 'tdesign-react'; @@ -94,7 +93,7 @@ const BasicImageViewer = ({ images }) => { alignItems: 'center', justifyContent: 'center', }} - onClick={open} + onClick={() => open()} > 预览 @@ -127,11 +126,14 @@ const BasicImageViewer = ({ images }) => { ); }; -export default function chatSample() { +export default function ChatSample() { const chatRef = useRef(null); const [ratio, setRatio] = useState(0); const [style, setStyle] = useState(''); - const reqParamsRef = useRef<{ ratio: number; style: string; file?: string }>({ ratio: 0, style: '' }); + const reqParamsRef = useRef<{ ratio: number; style: string; file?: string }>({ + ratio: 0, + style: '', + }); const [files, setFiles] = useState([]); const [mockMessage, setMockMessage] = React.useState(mockData); diff --git a/packages/pro-components/chat/chatbot/_example/nostream.tsx b/packages/pro-components/chat/chatbot/_example/nostream.tsx index 8c1d42a6bf..df2da5231e 100644 --- a/packages/pro-components/chat/chatbot/_example/nostream.tsx +++ b/packages/pro-components/chat/chatbot/_example/nostream.tsx @@ -1,15 +1,17 @@ /* eslint-disable @typescript-eslint/no-unused-vars */ -/* eslint-disable react-hooks/rules-of-hooks */ import React, { useEffect, useRef, useState } from 'react'; import { ChatBot } from '@tdesign-react/chat'; import type { ChatRequestParams, ChatServiceConfig, TdChatbotApi } from '@tdesign-react/chat'; -export default function chatSample() { +export default function ChatSample() { const chatRef = useRef(null); const [activeR1, setR1Active] = useState(false); const [activeSearch, setSearchActive] = useState(false); - const reqParamsRef = useRef<{ think: boolean; search: boolean }>({ think: false, search: false }); + const reqParamsRef = useRef<{ think: boolean; search: boolean }>({ + think: false, + search: false, + }); // 聊天服务配置 const chatServiceConfig: ChatServiceConfig = { diff --git a/packages/tdesign-react-aigc/site/plugin-tdoc/index.js b/packages/tdesign-react-aigc/site/plugin-tdoc/index.js index 23740e9eb8..38dd613750 100644 --- a/packages/tdesign-react-aigc/site/plugin-tdoc/index.js +++ b/packages/tdesign-react-aigc/site/plugin-tdoc/index.js @@ -1,25 +1,26 @@ import vitePluginTdoc from 'vite-plugin-tdoc'; -import transforms from './transforms'; import renderDemo from './demo'; +import transforms from './transforms'; -export default () => vitePluginTdoc({ - transforms, // 解析 markdown 数据 - markdown: { - anchor: { - tabIndex: false, - config: (anchor) => ({ - permalink: anchor.permalink.linkInsideHeader({ symbol: '' }), - }), - }, - toc: { - listClass: 'tdesign-toc_list', - itemClass: 'tdesign-toc_list_item', - linkClass: 'tdesign-toc_list_item_a', - containerClass: 'tdesign-toc_container', - }, - container(md, container) { - renderDemo(md, container); +export default () => + vitePluginTdoc({ + transforms, // 解析 markdown 数据 + markdown: { + anchor: { + tabIndex: false, + config: (anchor) => ({ + permalink: anchor.permalink.linkInsideHeader({ symbol: '' }), + }), + }, + toc: { + listClass: 'tdesign-toc_list', + itemClass: 'tdesign-toc_list_item', + linkClass: 'tdesign-toc_list_item_a', + containerClass: 'tdesign-toc_container', + }, + container(md, container) { + renderDemo(md, container); + }, }, - }, -}); + }); diff --git a/packages/tdesign-react-aigc/site/public/sw.js b/packages/tdesign-react-aigc/site/public/sw.js index 67150b319c..1ddee17055 100644 --- a/packages/tdesign-react-aigc/site/public/sw.js +++ b/packages/tdesign-react-aigc/site/public/sw.js @@ -1,8 +1,7 @@ -import { precacheAndRoute } from 'workbox-precaching' +import { precacheAndRoute } from 'workbox-precaching'; -precacheAndRoute(self.__WB_MANIFEST) +precacheAndRoute(self.__WB_MANIFEST); self.addEventListener('message', (event) => { - if (event.data && event.data.type === 'SKIP_WAITING') - self.skipWaiting() + if (event.data && event.data.type === 'SKIP_WAITING') self.skipWaiting(); }); diff --git a/packages/tdesign-react-aigc/site/src/App.jsx b/packages/tdesign-react-aigc/site/src/App.jsx index 8a8dae9f4f..7266d4a71c 100644 --- a/packages/tdesign-react-aigc/site/src/App.jsx +++ b/packages/tdesign-react-aigc/site/src/App.jsx @@ -1,5 +1,5 @@ -import React, { useEffect, useRef, lazy, Suspense } from 'react'; -import { BrowserRouter, Routes, Navigate, Route, useLocation, useNavigate, Outlet } from 'react-router-dom'; +import { lazy, Suspense, useEffect, useRef } from 'react'; +import { BrowserRouter, Navigate, Outlet, Route, Routes, useLocation, useNavigate } from 'react-router-dom'; import Loading from '@tdesign/components/loading'; import * as siteConfig from '../site.config'; @@ -60,7 +60,7 @@ function Components() { if (isDev) return; - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); useEffect(() => { diff --git a/packages/tdesign-react-aigc/site/src/components/BaseUsage.jsx b/packages/tdesign-react-aigc/site/src/components/BaseUsage.jsx index 9c422ca7a9..68db601746 100644 --- a/packages/tdesign-react-aigc/site/src/components/BaseUsage.jsx +++ b/packages/tdesign-react-aigc/site/src/components/BaseUsage.jsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState, useRef } from 'react'; +import { useEffect, useRef, useState } from 'react'; export function useConfigChange(configList) { const defaultProps = configList.reduce((prev, curr) => { diff --git a/packages/tdesign-react-aigc/site/src/components/Playground.jsx b/packages/tdesign-react-aigc/site/src/components/Playground.jsx index 6c93d01816..7999123103 100644 --- a/packages/tdesign-react-aigc/site/src/components/Playground.jsx +++ b/packages/tdesign-react-aigc/site/src/components/Playground.jsx @@ -1,8 +1,9 @@ +import '@tdesign/components/style/index.js'; + import React from 'react'; -import { HashRouter, Routes, Navigate, Route, useLocation, Link } from 'react-router-dom'; -import ReactDOM from 'react-dom'; +import { createRoot } from 'react-dom/client'; +import { HashRouter, Link, Navigate, Route, Routes, useLocation } from 'react-router-dom'; import { Button } from '@tdesign/components'; -import '@tdesign/components/style/index.js'; const demoFiles = import.meta.glob('../../../src/**/_example/*.jsx', { eager: true }); const demoObject = {}; @@ -77,9 +78,8 @@ function App() { ); } -ReactDOM.render( +createRoot(document.getElementById('app')).render( , - document.getElementById('app'), ); diff --git a/packages/tdesign-react-aigc/site/src/components/stackblitz/index.jsx b/packages/tdesign-react-aigc/site/src/components/stackblitz/index.jsx index 8cb9c331a4..e325220ae3 100644 --- a/packages/tdesign-react-aigc/site/src/components/stackblitz/index.jsx +++ b/packages/tdesign-react-aigc/site/src/components/stackblitz/index.jsx @@ -1,14 +1,14 @@ -import React, { useRef, useState } from 'react'; +import { useRef, useState } from 'react'; import { Tooltip } from '@tdesign/components'; import { htmlContent, mainJsContent, + packageJSONContent, + stackblitzRc, styleContent, tsconfigContent, viteConfigContent, - packageJSONContent, - stackblitzRc, } from './content'; const TypeScriptType = 0; diff --git a/packages/tdesign-react-aigc/site/src/main.jsx b/packages/tdesign-react-aigc/site/src/main.jsx index 4091c5db1d..27d41ad7d1 100644 --- a/packages/tdesign-react-aigc/site/src/main.jsx +++ b/packages/tdesign-react-aigc/site/src/main.jsx @@ -1,17 +1,17 @@ +// import tdesign style; +import '@tdesign/pro-components-chat/style/index.js'; +import '@tdesign/theme-generator'; + import React from 'react'; import { createRoot } from 'react-dom/client'; import { registerLocaleChange } from '@tdesign/site-components'; -import App from './App'; -// import tdesign style; -import '@tdesign/pro-components-chat/style/index.js'; -import '@tdesign/common-style/web/docs.less'; +import App from './App'; import '@tdesign/site-components/lib/styles/style.css'; -import '@tdesign/site-components/lib/styles/prism-theme.less'; +import '@tdesign/common-style/web/docs.less'; import '@tdesign/site-components/lib/styles/prism-theme-dark.less'; - -import '@tdesign/theme-generator'; +import '@tdesign/site-components/lib/styles/prism-theme.less'; const rootElement = document.getElementById('app'); const root = createRoot(rootElement); diff --git a/packages/tdesign-react-aigc/site/vite.config.js b/packages/tdesign-react-aigc/site/vite.config.js index 2b593a03a0..95cb6e7ba9 100644 --- a/packages/tdesign-react-aigc/site/vite.config.js +++ b/packages/tdesign-react-aigc/site/vite.config.js @@ -1,12 +1,13 @@ import path, { dirname } from 'path'; import { fileURLToPath } from 'url'; + import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; + import pkg from '../package.json'; import tdocPlugin from './plugin-tdoc'; import changelog2Json from './plugins/changelog-to-json'; -// eslint-disable-next-line no-underscore-dangle const __dirname = dirname(fileURLToPath(import.meta.url)); const publicPathMap = { diff --git a/packages/tdesign-react/site/plugins/plugin-tdoc/transforms.js b/packages/tdesign-react/site/plugins/plugin-tdoc/transforms.js index 540e5bf51e..4a6974b953 100644 --- a/packages/tdesign-react/site/plugins/plugin-tdoc/transforms.js +++ b/packages/tdesign-react/site/plugins/plugin-tdoc/transforms.js @@ -1,11 +1,9 @@ -/* eslint-disable indent */ -/* eslint-disable no-param-reassign */ import fs from 'fs'; import path, { dirname } from 'path'; import { fileURLToPath } from 'url'; + import mdToReact from './md-to-react'; -// eslint-disable-next-line no-underscore-dangle const __dirname = dirname(fileURLToPath(import.meta.url)); let demoImports = {}; diff --git a/packages/tdesign-react/site/public/sw.js b/packages/tdesign-react/site/public/sw.js index 67150b319c..1ddee17055 100644 --- a/packages/tdesign-react/site/public/sw.js +++ b/packages/tdesign-react/site/public/sw.js @@ -1,8 +1,7 @@ -import { precacheAndRoute } from 'workbox-precaching' +import { precacheAndRoute } from 'workbox-precaching'; -precacheAndRoute(self.__WB_MANIFEST) +precacheAndRoute(self.__WB_MANIFEST); self.addEventListener('message', (event) => { - if (event.data && event.data.type === 'SKIP_WAITING') - self.skipWaiting() + if (event.data && event.data.type === 'SKIP_WAITING') self.skipWaiting(); }); diff --git a/packages/tdesign-react/site/src/App.jsx b/packages/tdesign-react/site/src/App.jsx index 624416a349..2cd1c3f9a2 100644 --- a/packages/tdesign-react/site/src/App.jsx +++ b/packages/tdesign-react/site/src/App.jsx @@ -1,7 +1,6 @@ -import React, { lazy, Suspense, useEffect, useRef, useState } from 'react'; +import { lazy, Suspense, useEffect, useRef, useState } from 'react'; import { BrowserRouter, Navigate, Outlet, Route, Routes, useLocation, useNavigate } from 'react-router-dom'; import semver from 'semver'; - import ConfigProvider from '@tdesign/components/config-provider'; import Loading from '@tdesign/components/loading'; import enConfig from '@tdesign/components/locale/en_US'; @@ -10,9 +9,8 @@ import { getLang } from '@tdesign/site-components'; import packageJson from '../../package.json'; import * as siteConfig from '../site.config'; -import { filterVersions, getRoute } from './utils'; - import Demo from './components/Demo'; +import { filterVersions, getRoute } from './utils'; const isDev = import.meta.env.DEV; const LazyDemo = isDev ? Demo : lazy(() => import('./components/Demo')); @@ -128,7 +126,7 @@ function Components() { if (isDev) return; initHistoryVersions(); - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, []); useEffect(() => { diff --git a/packages/tdesign-react/site/src/components/BaseUsage.jsx b/packages/tdesign-react/site/src/components/BaseUsage.jsx index 9c422ca7a9..68db601746 100644 --- a/packages/tdesign-react/site/src/components/BaseUsage.jsx +++ b/packages/tdesign-react/site/src/components/BaseUsage.jsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState, useRef } from 'react'; +import { useEffect, useRef, useState } from 'react'; export function useConfigChange(configList) { const defaultProps = configList.reduce((prev, curr) => { diff --git a/packages/tdesign-react/site/src/components/Demo.jsx b/packages/tdesign-react/site/src/components/Demo.jsx index 59765b29f5..dcd2837a0e 100644 --- a/packages/tdesign-react/site/src/components/Demo.jsx +++ b/packages/tdesign-react/site/src/components/Demo.jsx @@ -1,7 +1,7 @@ -import React, { useEffect, useState } from 'react'; +import { useEffect, useState } from 'react'; import { Link, useLocation } from 'react-router-dom'; - import { Button } from '@tdesign/components'; + import DraggableButton from './DraggableButton'; export const demoFiles = import.meta.glob('../../../../components/**/_example/*.tsx'); diff --git a/packages/tdesign-react/site/src/components/DraggableButton.jsx b/packages/tdesign-react/site/src/components/DraggableButton.jsx index 330c31c71e..de696b5394 100644 --- a/packages/tdesign-react/site/src/components/DraggableButton.jsx +++ b/packages/tdesign-react/site/src/components/DraggableButton.jsx @@ -1,4 +1,4 @@ -import React, { useCallback, useEffect, useRef, useState } from 'react'; +import { useCallback, useEffect, useRef, useState } from 'react'; import { Button } from '@tdesign/components'; const DraggableButton = ({ children, onClick }) => { diff --git a/packages/tdesign-react/site/src/components/Playground.jsx b/packages/tdesign-react/site/src/components/Playground.jsx index 6c93d01816..7999123103 100644 --- a/packages/tdesign-react/site/src/components/Playground.jsx +++ b/packages/tdesign-react/site/src/components/Playground.jsx @@ -1,8 +1,9 @@ +import '@tdesign/components/style/index.js'; + import React from 'react'; -import { HashRouter, Routes, Navigate, Route, useLocation, Link } from 'react-router-dom'; -import ReactDOM from 'react-dom'; +import { createRoot } from 'react-dom/client'; +import { HashRouter, Link, Navigate, Route, Routes, useLocation } from 'react-router-dom'; import { Button } from '@tdesign/components'; -import '@tdesign/components/style/index.js'; const demoFiles = import.meta.glob('../../../src/**/_example/*.jsx', { eager: true }); const demoObject = {}; @@ -77,9 +78,8 @@ function App() { ); } -ReactDOM.render( +createRoot(document.getElementById('app')).render( , - document.getElementById('app'), ); diff --git a/packages/tdesign-react/site/src/components/codesandbox/content.js b/packages/tdesign-react/site/src/components/codesandbox/content.js index 64fc9cb042..e080985d7a 100644 --- a/packages/tdesign-react/site/src/components/codesandbox/content.js +++ b/packages/tdesign-react/site/src/components/codesandbox/content.js @@ -1,5 +1,5 @@ -import orgPkg from '../../../package.json'; import tdesignReactPkg from '../../../../package.json'; +import orgPkg from '../../../package.json'; export const htmlContent = '
    '; diff --git a/packages/tdesign-react/site/src/components/codesandbox/index.jsx b/packages/tdesign-react/site/src/components/codesandbox/index.jsx index 43938e80b6..3e6a464d43 100644 --- a/packages/tdesign-react/site/src/components/codesandbox/index.jsx +++ b/packages/tdesign-react/site/src/components/codesandbox/index.jsx @@ -1,7 +1,8 @@ -import React, { useState } from 'react'; -import { Tooltip, Loading } from '@tdesign/components'; +import { useState } from 'react'; +import { Loading, Tooltip } from '@tdesign/components'; + +import { htmlContent, mainJsContent, pkgContent, styleContent, tsconfigContent } from './content'; -import { mainJsContent, htmlContent, pkgContent, styleContent, tsconfigContent } from './content'; import '../../styles/Codesandbox.less'; const TypeScriptType = 0; diff --git a/packages/tdesign-react/site/src/components/newwindow/index.jsx b/packages/tdesign-react/site/src/components/newwindow/index.jsx index aa9220a987..4c29f9bf17 100644 --- a/packages/tdesign-react/site/src/components/newwindow/index.jsx +++ b/packages/tdesign-react/site/src/components/newwindow/index.jsx @@ -1,4 +1,3 @@ -import React from 'react'; import { Tooltip } from '@tdesign/components'; const SPECIAL_PATH_MAP = { diff --git a/packages/tdesign-react/site/src/components/stackblitz/content.js b/packages/tdesign-react/site/src/components/stackblitz/content.js index 40689e12c5..895483d9a4 100644 --- a/packages/tdesign-react/site/src/components/stackblitz/content.js +++ b/packages/tdesign-react/site/src/components/stackblitz/content.js @@ -1,5 +1,5 @@ -import orgPkg from '../../../package.json'; import tdesignReactPkg from '../../../../package.json'; +import orgPkg from '../../../package.json'; export const htmlContent = ` diff --git a/packages/tdesign-react/site/src/components/stackblitz/index.jsx b/packages/tdesign-react/site/src/components/stackblitz/index.jsx index 356f56a5d2..9987831860 100644 --- a/packages/tdesign-react/site/src/components/stackblitz/index.jsx +++ b/packages/tdesign-react/site/src/components/stackblitz/index.jsx @@ -1,14 +1,14 @@ -import React, { useRef, useState } from 'react'; +import { useRef, useState } from 'react'; import { Tooltip } from '@tdesign/components'; import { htmlContent, mainJsContent, + packageJSONContent, + stackblitzRc, styleContent, tsconfigContent, viteConfigContent, - packageJSONContent, - stackblitzRc, } from './content'; const TypeScriptType = 0; diff --git a/packages/tdesign-react/site/src/pwa.js b/packages/tdesign-react/site/src/pwa.js index 3c1442b732..9abf896189 100644 --- a/packages/tdesign-react/site/src/pwa.js +++ b/packages/tdesign-react/site/src/pwa.js @@ -1,6 +1,6 @@ import { registerSW } from 'virtual:pwa-register'; -const updateSW = registerSW({ +registerSW({ onNeedRefresh() { console.log('onNeedRefresh'); }, diff --git a/packages/tdesign-react/site/vite.config.js b/packages/tdesign-react/site/vite.config.js index 950fdb2c6a..5e26d77620 100644 --- a/packages/tdesign-react/site/vite.config.js +++ b/packages/tdesign-react/site/vite.config.js @@ -1,16 +1,15 @@ -import react from '@vitejs/plugin-react'; import path, { dirname } from 'path'; import { fileURLToPath } from 'url'; + import { defineConfig } from 'vite'; import { VitePWA } from 'vite-plugin-pwa'; -import pkg from '../package.json'; - -import pwaConfig from './pwaConfig'; +import react from '@vitejs/plugin-react'; +import pkg from '../package.json'; import changelog2Json from './plugins/changelog-to-json'; import tdocPlugin from './plugins/plugin-tdoc'; +import pwaConfig from './pwaConfig'; -// eslint-disable-next-line no-underscore-dangle const __dirname = dirname(fileURLToPath(import.meta.url)); const publicPathMap = { diff --git a/script/generate-usage/config.js b/script/generate-usage/config.js index 7d3497798f..38206721fc 100644 --- a/script/generate-usage/config.js +++ b/script/generate-usage/config.js @@ -723,7 +723,7 @@ module.exports = { onConfigChange({ detail: { name: 'fullscreen', value: false } }); }, 2000); } - // eslint-disable-next-line react-hooks/exhaustive-deps + // eslint-disable-next-line @eslint-react/exhaustive-deps }, [fullscreen]); useEffect(() => { diff --git a/test/snap/ssr.test.jsx b/test/snap/ssr.test.jsx index 9fb4f47782..a523647896 100644 --- a/test/snap/ssr.test.jsx +++ b/test/snap/ssr.test.jsx @@ -1,8 +1,7 @@ +import { renderToString } from 'react-dom/server'; import glob from 'glob'; import MockDate from 'mockdate'; import { vi } from 'vitest'; -import React from 'react'; -import { renderToString } from 'react-dom/server'; // 固定时间,当使用 new Date() 时,返回固定时间,防止“当前时间”的副作用影响,导致 snapshot 变更,mockdate 插件见 https://github.com/boblauer/MockDate MockDate.set('2020-12-28 00:00:00'); diff --git a/test/utils/events.js b/test/utils/events.js index 1dd436fdf6..885f39132b 100644 --- a/test/utils/events.js +++ b/test/utils/events.js @@ -1,21 +1,21 @@ export const EVENTS_MAP = { - 'mousedown': 'mouseDown', - 'mouseenter': 'mouseEnter', - 'mouseleave': 'mouseLeave', - 'mousemove': 'mouseMove', - 'mouseout': 'mouseOut', - 'mouseover': 'mouseOver', - 'mouseup': 'mouseUp', - 'keydown': 'keyDown', - 'keypress': 'keyPress', - 'keyup': 'keyUp', - 'dragend': 'dragEnd', - 'dragenter': 'dragEnter', - 'dragexit': 'dragExit', - 'dragleave': 'dragLeave', - 'dragover': 'dragOver', - 'dragstart': 'dragStart', - 'compositionend': 'compositionEnd', - 'compositionstart': 'compositionStart', - 'compositionupdate': 'compositionUpdate', + mousedown: 'mouseDown', + mouseenter: 'mouseEnter', + mouseleave: 'mouseLeave', + mousemove: 'mouseMove', + mouseout: 'mouseOut', + mouseover: 'mouseOver', + mouseup: 'mouseUp', + keydown: 'keyDown', + keypress: 'keyPress', + keyup: 'keyUp', + dragend: 'dragEnd', + dragenter: 'dragEnter', + dragexit: 'dragExit', + dragleave: 'dragLeave', + dragover: 'dragOver', + dragstart: 'dragStart', + compositionend: 'compositionEnd', + compositionstart: 'compositionStart', + compositionupdate: 'compositionUpdate', };