From b4d7f10e668fb27801414fe68a780d5310ce2b81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=A0=97=E5=98=89=E7=94=B7?= <574980606@qq.com> Date: Tue, 7 Mar 2023 15:10:16 +0800 Subject: [PATCH] Refactoring: js => ts --- src/{KeyCode.js => KeyCode.ts} | 4 +- src/{Options.jsx => Options.tsx} | 58 ++++--- src/Pager.jsx | 34 ---- src/Pager.tsx | 65 +++++++ src/{Pagination.jsx => Pagination.tsx} | 225 ++++++++++++++++--------- src/{index.js => index.ts} | 0 src/locale/{am.js => am.ts} | 0 src/locale/{ar_EG.js => ar_EG.ts} | 0 src/locale/{az_AZ.js => az_AZ.ts} | 0 src/locale/{bg_BG.js => bg_BG.ts} | 0 src/locale/{bn_BD.js => bn_BD.ts} | 0 src/locale/{by_BY.js => by_BY.ts} | 0 src/locale/{ca_ES.js => ca_ES.ts} | 0 src/locale/{cs_CZ.js => cs_CZ.ts} | 0 src/locale/{da_DK.js => da_DK.ts} | 0 src/locale/{de_DE.js => de_DE.ts} | 0 src/locale/{el_GR.js => el_GR.ts} | 0 src/locale/{en_GB.js => en_GB.ts} | 0 src/locale/{en_US.js => en_US.ts} | 0 src/locale/{es_ES.js => es_ES.ts} | 0 src/locale/{et_EE.js => et_EE.ts} | 0 src/locale/{eu_ES.js => eu_ES.ts} | 0 src/locale/{fa_IR.js => fa_IR.ts} | 0 src/locale/{fi_FI.js => fi_FI.ts} | 0 src/locale/{fr_BE.js => fr_BE.ts} | 0 src/locale/{fr_CA.js => fr_CA.ts} | 0 src/locale/{fr_FR.js => fr_FR.ts} | 0 src/locale/{ga_IE.js => ga_IE.ts} | 0 src/locale/{gl_ES.tsx => gl_ES.ts} | 0 src/locale/{he_IL.js => he_IL.ts} | 0 src/locale/{hi_IN.js => hi_IN.ts} | 0 src/locale/{hr_HR.js => hr_HR.ts} | 0 src/locale/{hu_HU.js => hu_HU.ts} | 0 src/locale/{id_ID.js => id_ID.ts} | 0 src/locale/{is_IS.js => is_IS.ts} | 0 src/locale/{it_IT.js => it_IT.ts} | 0 src/locale/{ja_JP.js => ja_JP.ts} | 0 src/locale/{ka_GE.js => ka_GE.ts} | 0 src/locale/{kk_KZ.js => kk_KZ.ts} | 0 src/locale/{km_KH.js => km_KH.ts} | 0 src/locale/{kmr_IQ.js => kmr_IQ.ts} | 0 src/locale/{kn_IN.js => kn_IN.ts} | 0 src/locale/{ko_KR.js => ko_KR.ts} | 0 src/locale/{lt_LT.js => lt_LT.ts} | 0 src/locale/{lv_LV.js => lv_LV.ts} | 0 src/locale/{mk_MK.js => mk_MK.ts} | 0 src/locale/{ml_IN.js => ml_IN.ts} | 0 src/locale/{mm_MM.js => mm_MM.ts} | 0 src/locale/{mn_MN.js => mn_MN.ts} | 0 src/locale/{ms_MY.js => ms_MY.ts} | 0 src/locale/{nb_NO.js => nb_NO.ts} | 0 src/locale/{nl_BE.js => nl_BE.ts} | 0 src/locale/{nl_NL.js => nl_NL.ts} | 0 src/locale/{pa_IN.js => pa_IN.ts} | 0 src/locale/{pb_IN.js => pb_IN.ts} | 0 src/locale/{pl_PL.js => pl_PL.ts} | 0 src/locale/{pt_BR.js => pt_BR.ts} | 0 src/locale/{pt_PT.js => pt_PT.ts} | 0 src/locale/{ro_RO.js => ro_RO.ts} | 0 src/locale/{ru_RU.js => ru_RU.ts} | 0 src/locale/{sk_SK.js => sk_SK.ts} | 0 src/locale/{sl_SI.js => sl_SI.ts} | 0 src/locale/{sr_RS.js => sr_RS.ts} | 0 src/locale/{sv_SE.js => sv_SE.ts} | 0 src/locale/{ta_IN.js => ta_IN.ts} | 0 src/locale/{th_TH.js => th_TH.ts} | 0 src/locale/{tk_TK.js => tk_TK.ts} | 0 src/locale/{tr_TR.js => tr_TR.ts} | 0 src/locale/{ug_CN.js => ug_CN.ts} | 0 src/locale/{uk_UA.js => uk_UA.ts} | 0 src/locale/{ur_PK.js => ur_PK.ts} | 0 src/locale/{uz_UZ.js => uz_UZ.ts} | 0 src/locale/{vi_VN.js => vi_VN.ts} | 0 src/locale/{zh_CN.js => zh_CN.ts} | 0 src/locale/{zh_TW.js => zh_TW.ts} | 0 75 files changed, 256 insertions(+), 130 deletions(-) rename src/{KeyCode.js => KeyCode.ts} (77%) rename src/{Options.jsx => Options.tsx} (76%) delete mode 100644 src/Pager.jsx create mode 100644 src/Pager.tsx rename src/{Pagination.jsx => Pagination.tsx} (79%) rename src/{index.js => index.ts} (100%) rename src/locale/{am.js => am.ts} (100%) rename src/locale/{ar_EG.js => ar_EG.ts} (100%) rename src/locale/{az_AZ.js => az_AZ.ts} (100%) rename src/locale/{bg_BG.js => bg_BG.ts} (100%) rename src/locale/{bn_BD.js => bn_BD.ts} (100%) rename src/locale/{by_BY.js => by_BY.ts} (100%) rename src/locale/{ca_ES.js => ca_ES.ts} (100%) rename src/locale/{cs_CZ.js => cs_CZ.ts} (100%) rename src/locale/{da_DK.js => da_DK.ts} (100%) rename src/locale/{de_DE.js => de_DE.ts} (100%) rename src/locale/{el_GR.js => el_GR.ts} (100%) rename src/locale/{en_GB.js => en_GB.ts} (100%) rename src/locale/{en_US.js => en_US.ts} (100%) rename src/locale/{es_ES.js => es_ES.ts} (100%) rename src/locale/{et_EE.js => et_EE.ts} (100%) rename src/locale/{eu_ES.js => eu_ES.ts} (100%) rename src/locale/{fa_IR.js => fa_IR.ts} (100%) rename src/locale/{fi_FI.js => fi_FI.ts} (100%) rename src/locale/{fr_BE.js => fr_BE.ts} (100%) rename src/locale/{fr_CA.js => fr_CA.ts} (100%) rename src/locale/{fr_FR.js => fr_FR.ts} (100%) rename src/locale/{ga_IE.js => ga_IE.ts} (100%) rename src/locale/{gl_ES.tsx => gl_ES.ts} (100%) rename src/locale/{he_IL.js => he_IL.ts} (100%) rename src/locale/{hi_IN.js => hi_IN.ts} (100%) rename src/locale/{hr_HR.js => hr_HR.ts} (100%) rename src/locale/{hu_HU.js => hu_HU.ts} (100%) rename src/locale/{id_ID.js => id_ID.ts} (100%) rename src/locale/{is_IS.js => is_IS.ts} (100%) rename src/locale/{it_IT.js => it_IT.ts} (100%) rename src/locale/{ja_JP.js => ja_JP.ts} (100%) rename src/locale/{ka_GE.js => ka_GE.ts} (100%) rename src/locale/{kk_KZ.js => kk_KZ.ts} (100%) rename src/locale/{km_KH.js => km_KH.ts} (100%) rename src/locale/{kmr_IQ.js => kmr_IQ.ts} (100%) rename src/locale/{kn_IN.js => kn_IN.ts} (100%) rename src/locale/{ko_KR.js => ko_KR.ts} (100%) rename src/locale/{lt_LT.js => lt_LT.ts} (100%) rename src/locale/{lv_LV.js => lv_LV.ts} (100%) rename src/locale/{mk_MK.js => mk_MK.ts} (100%) rename src/locale/{ml_IN.js => ml_IN.ts} (100%) rename src/locale/{mm_MM.js => mm_MM.ts} (100%) rename src/locale/{mn_MN.js => mn_MN.ts} (100%) rename src/locale/{ms_MY.js => ms_MY.ts} (100%) rename src/locale/{nb_NO.js => nb_NO.ts} (100%) rename src/locale/{nl_BE.js => nl_BE.ts} (100%) rename src/locale/{nl_NL.js => nl_NL.ts} (100%) rename src/locale/{pa_IN.js => pa_IN.ts} (100%) rename src/locale/{pb_IN.js => pb_IN.ts} (100%) rename src/locale/{pl_PL.js => pl_PL.ts} (100%) rename src/locale/{pt_BR.js => pt_BR.ts} (100%) rename src/locale/{pt_PT.js => pt_PT.ts} (100%) rename src/locale/{ro_RO.js => ro_RO.ts} (100%) rename src/locale/{ru_RU.js => ru_RU.ts} (100%) rename src/locale/{sk_SK.js => sk_SK.ts} (100%) rename src/locale/{sl_SI.js => sl_SI.ts} (100%) rename src/locale/{sr_RS.js => sr_RS.ts} (100%) rename src/locale/{sv_SE.js => sv_SE.ts} (100%) rename src/locale/{ta_IN.js => ta_IN.ts} (100%) rename src/locale/{th_TH.js => th_TH.ts} (100%) rename src/locale/{tk_TK.js => tk_TK.ts} (100%) rename src/locale/{tr_TR.js => tr_TR.ts} (100%) rename src/locale/{ug_CN.js => ug_CN.ts} (100%) rename src/locale/{uk_UA.js => uk_UA.ts} (100%) rename src/locale/{ur_PK.js => ur_PK.ts} (100%) rename src/locale/{uz_UZ.js => uz_UZ.ts} (100%) rename src/locale/{vi_VN.js => vi_VN.ts} (100%) rename src/locale/{zh_CN.js => zh_CN.ts} (100%) rename src/locale/{zh_TW.js => zh_TW.ts} (100%) diff --git a/src/KeyCode.js b/src/KeyCode.ts similarity index 77% rename from src/KeyCode.js rename to src/KeyCode.ts index 69b0c880..a85d600c 100644 --- a/src/KeyCode.js +++ b/src/KeyCode.ts @@ -1,4 +1,4 @@ -export default { +const KeyCode = { ZERO: 48, NINE: 57, @@ -12,3 +12,5 @@ export default { ARROW_UP: 38, ARROW_DOWN: 40, }; + +export default KeyCode; \ No newline at end of file diff --git a/src/Options.jsx b/src/Options.tsx similarity index 76% rename from src/Options.jsx rename to src/Options.tsx index c3249895..f89b17dc 100644 --- a/src/Options.jsx +++ b/src/Options.tsx @@ -2,7 +2,28 @@ import React from 'react'; import KEYCODE from './KeyCode'; -class Options extends React.Component { +interface Props { + disabled: boolean; + locale: any; + rootPrefixCls: string; + selectPrefixCls: string; + current: number; + pageSize: number; + pageSizeOptions: (string | number)[]; + goButton: boolean | string; + changeSize: (size: number) => void; + quickGo: (value: number) => void; + buildOptionText?: (value: string | number) => string; + selectComponentClass: React.ComponentType & { + Option?: React.ComponentType; + }; +} + +interface State { + goInputText: string; +} + +class Options extends React.Component { static defaultProps = { pageSizeOptions: ['10', '20', '50', '100'], }; @@ -11,33 +32,32 @@ class Options extends React.Component { goInputText: '', }; - getValidValue() { + getValidValue = () => { const { goInputText } = this.state; // eslint-disable-next-line no-restricted-globals - return !goInputText || isNaN(goInputText) ? undefined : Number(goInputText); - } + return !goInputText || Number.isNaN(goInputText) + ? undefined + : Number(goInputText); + }; - buildOptionText = (value) => `${value} ${this.props.locale.items_per_page}`; + buildOptionText = (value: string) => + `${value} ${this.props.locale.items_per_page}`; - changeSize = (value) => { + changeSize = (value: number) => { this.props.changeSize(Number(value)); }; - handleChange = (e) => { - this.setState({ - goInputText: e.target.value, - }); + handleChange = (e: React.ChangeEvent) => { + this.setState({ goInputText: e.target.value }); }; - handleBlur = (e) => { + handleBlur = (e: React.FocusEvent) => { const { goButton, quickGo, rootPrefixCls } = this.props; const { goInputText } = this.state; if (goButton || goInputText === '') { return; } - this.setState({ - goInputText: '', - }); + this.setState({ goInputText: '' }); if ( e.relatedTarget && (e.relatedTarget.className.indexOf(`${rootPrefixCls}-item-link`) >= 0 || @@ -48,15 +68,13 @@ class Options extends React.Component { quickGo(this.getValidValue()); }; - go = (e) => { + go = (e: any) => { const { goInputText } = this.state; if (goInputText === '') { return; } if (e.keyCode === KEYCODE.ENTER || e.type === 'click') { - this.setState({ - goInputText: '', - }); + this.setState({ goInputText: '' }); this.props.quickGo(this.getValidValue()); } }; @@ -72,9 +90,9 @@ class Options extends React.Component { } return pageSizeOptions.concat([pageSize.toString()]).sort((a, b) => { // eslint-disable-next-line no-restricted-globals - const numberA = isNaN(Number(a)) ? 0 : Number(a); + const numberA = Number.isNaN(Number(a)) ? 0 : Number(a); // eslint-disable-next-line no-restricted-globals - const numberB = isNaN(Number(b)) ? 0 : Number(b); + const numberB = Number.isNaN(Number(b)) ? 0 : Number(b); return numberA - numberB; }); } diff --git a/src/Pager.jsx b/src/Pager.jsx deleted file mode 100644 index 1a7a15ec..00000000 --- a/src/Pager.jsx +++ /dev/null @@ -1,34 +0,0 @@ -/* eslint react/prop-types: 0 */ -import React from 'react'; -import classNames from 'classnames'; - -const Pager = (props) => { - const prefixCls = `${props.rootPrefixCls}-item`; - const cls = classNames(prefixCls, `${prefixCls}-${props.page}`, { - [`${prefixCls}-active`]: props.active, - [`${prefixCls}-disabled`]: !props.page, - [props.className]: !!props.className, - }); - - const handleClick = () => { - props.onClick(props.page); - }; - - const handleKeyPress = (e) => { - props.onKeyPress(e, props.onClick, props.page); - }; - - return ( -
  • - {props.itemRender(props.page, 'page', {props.page})} -
  • - ); -}; - -export default Pager; diff --git a/src/Pager.tsx b/src/Pager.tsx new file mode 100644 index 00000000..ed9475cf --- /dev/null +++ b/src/Pager.tsx @@ -0,0 +1,65 @@ +/* eslint react/prop-types: 0 */ +import classNames from 'classnames'; +import React from 'react'; + +interface Props { + last?: boolean; + locale?: any; + rootPrefixCls: string; + page: number; + active?: boolean; + className?: string; + showTitle: boolean; + onClick?: (page: number) => void; + onKeyPress?: ( + e: React.KeyboardEvent, + onClick: Props['onClick'], + page: Props['page'], + ) => void; + itemRender?: ( + page: number, + type: 'page' | 'prev' | 'next' | 'jump-prev' | 'jump-next', + element: React.ReactNode, + ) => React.ReactNode; +} + +const Pager: React.FC = (props) => { + const { + rootPrefixCls, + page, + active, + className, + showTitle, + onClick, + onKeyPress, + itemRender, + } = props; + const prefixCls = `${rootPrefixCls}-item`; + const cls = classNames(prefixCls, `${prefixCls}-${page}`, { + [`${prefixCls}-active`]: active, + [`${prefixCls}-disabled`]: !page, + [props.className]: className, + }); + + const handleClick = () => { + onClick(page); + }; + + const handleKeyPress = (e: React.KeyboardEvent) => { + onKeyPress(e, onClick, page); + }; + + return ( +
  • + {itemRender(page, 'page', {page})} +
  • + ); +}; + +export default Pager; diff --git a/src/Pagination.jsx b/src/Pagination.tsx similarity index 79% rename from src/Pagination.jsx rename to src/Pagination.tsx index dc0e6b94..45f992b2 100644 --- a/src/Pagination.jsx +++ b/src/Pagination.tsx @@ -1,34 +1,108 @@ /* eslint react/prop-types: 0 */ -import React, { cloneElement, isValidElement } from 'react'; import classNames from 'classnames'; -import Pager from './Pager'; -import Options from './Options'; +import React, { cloneElement, isValidElement } from 'react'; import KEYCODE from './KeyCode'; import LOCALE from './locale/zh_CN'; +import Options from './Options'; +import Pager from './Pager'; + +export interface PaginationLocale { + // Options.jsx + items_per_page?: string; + jump_to?: string; + jump_to_confirm?: string; + page?: string; + + // Pagination.jsx + prev_page?: string; + next_page?: string; + prev_5?: string; + next_5?: string; + prev_3?: string; + next_3?: string; +} + +export interface PaginationData { + className: string; + selectPrefixCls: string; + prefixCls: string; + pageSizeOptions: string[] | number[]; + + current: number; + defaultCurrent: number; + total: number; + totalBoundaryShowSizeChanger?: number; + pageSize: number; + defaultPageSize: number; + + hideOnSinglePage: boolean; + showSizeChanger: boolean; + showLessItems: boolean; + showPrevNextJumpers: boolean; + showQuickJumper: boolean | object; + showTitle: boolean; + simple: boolean; + disabled: boolean; + + locale: PaginationLocale; + + style: React.CSSProperties; + + selectComponentClass: React.ComponentType; + prevIcon: React.ComponentType | React.ReactNode; + nextIcon: React.ComponentType | React.ReactNode; + jumpPrevIcon: React.ComponentType | React.ReactNode; + jumpNextIcon: React.ComponentType | React.ReactNode; +} + +export interface PaginationProps extends Partial { + onChange?: (page: number, pageSize: number) => void; + onShowSizeChange?: (current: number, size: number) => void; + itemRender?: ( + page: number, + type: 'page' | 'prev' | 'next' | 'jump-prev' | 'jump-next', + element: React.ReactNode, + ) => React.ReactNode; + showTotal?: (total: number, range: [number, number]) => React.ReactNode; +} + +interface PaginationState { + current: number; + currentInputValue: number; + pageSize: number; +} function noop() {} -function isInteger(v) { +function isInteger(v: number) { const value = Number(v); return ( // eslint-disable-next-line no-restricted-globals typeof value === 'number' && - !isNaN(value) && + !Number.isNaN(value) && isFinite(value) && Math.floor(value) === value ); } -function defaultItemRender(page, type, element) { +const defaultItemRender: PaginationProps['itemRender'] = ( + page, + type, + element, +) => { return element; -} +}; -function calculatePage(p, state, props) { +function calculatePage( + p: number | undefined, + state: PaginationState, + props: PaginationProps, +) { const pageSize = typeof p === 'undefined' ? state.pageSize : p; return Math.floor((props.total - 1) / pageSize) + 1; } -class Pagination extends React.Component { +class Pagination extends React.Component { static defaultProps = { defaultCurrent: 1, total: 0, @@ -49,8 +123,8 @@ class Pagination extends React.Component { itemRender: defaultItemRender, totalBoundaryShowSizeChanger: 50, }; - - constructor(props) { + paginationNode = React.createRef(); + constructor(props: PaginationProps) { super(props); const hasOnChange = props.onChange !== noop; @@ -83,22 +157,29 @@ class Pagination extends React.Component { }; } - componentDidUpdate(prevProps, prevState) { + componentDidUpdate(_: PaginationProps, prevState: PaginationState) { // When current page change, fix focused style of prev item // A hacky solution of https://github.com/ant-design/ant-design/issues/8948 const { prefixCls } = this.props; - if (prevState.current !== this.state.current && this.paginationNode) { - const lastCurrentNode = this.paginationNode.querySelector( - `.${prefixCls}-item-${prevState.current}`, - ); + if ( + prevState.current !== this.state.current && + this.paginationNode.current + ) { + const lastCurrentNode = + this.paginationNode.current.querySelector( + `.${prefixCls}-item-${prevState.current}`, + ); if (lastCurrentNode && document.activeElement === lastCurrentNode) { - lastCurrentNode.blur(); + lastCurrentNode?.blur?.(); } } } - static getDerivedStateFromProps(props, prevState) { - const newState = {}; + static getDerivedStateFromProps( + props: PaginationProps, + prevState: PaginationState, + ) { + const newState: Partial = {}; if ('current' in props) { newState.current = props.current; @@ -132,12 +213,10 @@ class Pagination extends React.Component { this.state.current + (this.props.showLessItems ? 3 : 5), ); - /** - * computed icon node that need to be rendered. - * @param {React.ReactNode | React.ComponentType} icon received icon. - * @returns {React.ReactNode} - */ - getItemIcon = (icon, label) => { + getItemIcon = ( + icon: React.ReactNode | React.ComponentType, + label: string, + ) => { const { prefixCls } = this.props; let iconNode = icon || (