From 95d40f7272a71033f058a881327fee42b2ab6842 Mon Sep 17 00:00:00 2001 From: Hao Cheng Date: Thu, 24 Aug 2023 20:40:07 +0200 Subject: [PATCH] refactor(typescript): add types for TableBatchActions (#14390) Co-authored-by: TJ Egan --- ...eBatchActions.js => TableBatchActions.tsx} | 89 ++++++++++++++++--- .../DataTable-batch-actions.stories.js | 9 +- .../components/MultiSelect/MultiSelect.tsx | 5 +- packages/react/src/types/common.ts | 11 +++ 4 files changed, 99 insertions(+), 15 deletions(-) rename packages/react/src/components/DataTable/{TableBatchActions.js => TableBatchActions.tsx} (59%) diff --git a/packages/react/src/components/DataTable/TableBatchActions.js b/packages/react/src/components/DataTable/TableBatchActions.tsx similarity index 59% rename from packages/react/src/components/DataTable/TableBatchActions.js rename to packages/react/src/components/DataTable/TableBatchActions.tsx index cd9fac394d69..6eb6e9d26af8 100644 --- a/packages/react/src/components/DataTable/TableBatchActions.js +++ b/packages/react/src/components/DataTable/TableBatchActions.tsx @@ -7,30 +7,99 @@ import cx from 'classnames'; import PropTypes from 'prop-types'; -import React from 'react'; +import React, { type MouseEventHandler } from 'react'; import Button from '../Button'; import TableActionList from './TableActionList'; import { Text } from '../Text'; import { usePrefix } from '../../internal/usePrefix'; +import type { InternationalProps } from '../../types/common'; + +const TableBatchActionsTranslationKeys = [ + 'carbon.table.batch.cancel', + 'carbon.table.batch.items.selected', + 'carbon.table.batch.item.selected', + 'carbon.table.batch.selectAll', +] as const; + +export type TableBatchActionsTranslationKey = + (typeof TableBatchActionsTranslationKeys)[number]; + +export interface TableBatchActionsTranslationArgs { + totalSelected?: number; + totalCount?: number; +} + +export interface TableBatchActionsProps + extends React.HTMLAttributes, + InternationalProps< + TableBatchActionsTranslationKey, + TableBatchActionsTranslationArgs + > { + /** + * Provide elements to be rendered inside of the component. + */ + children?: React.ReactNode; + + /** + * Hook required to listen for when the user initiates a cancel request + * through this component. + */ + onCancel: MouseEventHandler; + + /** + * Hook to listen for when the user initiates a select all + * request through this component. This _only_ controls the rendering + * of the `Select All` button and does not include built in functionality + */ + onSelectAll?: MouseEventHandler; + + /** + * Boolean specifier for whether or not the batch action bar should be + * displayed. + */ + shouldShowBatchActions?: boolean; + + /** + * Numeric representation of the total number of items selected in a table. + * This number is used to derive the selection message. + */ + totalSelected: number; + + /** + * Numeric representation of the total number of items in a table. + * This number is used in the select all button text + */ + totalCount?: number; +} + +export interface TableBatchActionsComponent + extends React.FC { + translationKeys: ReadonlyArray; +} -const translationKeys = { +const translationKeys: Readonly< + Record +> = { 'carbon.table.batch.cancel': 'Cancel', 'carbon.table.batch.items.selected': 'items selected', 'carbon.table.batch.item.selected': 'item selected', 'carbon.table.batch.selectAll': 'Select all', }; -const translateWithId = (id, state) => { +const translateWithId: TableBatchActionsProps['translateWithId'] = ( + id, + { totalSelected, totalCount } = { totalSelected: 0, totalCount: 0 } +) => { if (id === 'carbon.table.batch.cancel') { return translationKeys[id]; } if (id === 'carbon.table.batch.selectAll') { - return `${translationKeys[id]} (${state.totalCount})`; + return `${translationKeys[id]} (${totalCount})`; } - return `${state.totalSelected} ${translationKeys[id]}`; + return `${totalSelected} ${translationKeys[id]}`; }; -const TableBatchActions = ({ +const TableBatchActions: TableBatchActionsComponent = ({ className, children, shouldShowBatchActions, @@ -38,10 +107,10 @@ const TableBatchActions = ({ totalCount, onCancel, onSelectAll, - translateWithId: t, + translateWithId: t = translateWithId, ...rest }) => { - const [isScrolling, setIsScrolling] = React.useState(); + const [isScrolling, setIsScrolling] = React.useState(false); const prefix = usePrefix(); const batchActionsClasses = cx( { @@ -95,7 +164,7 @@ const TableBatchActions = ({ ); }; -TableBatchActions.translationKeys = Object.keys(translationKeys); +TableBatchActions.translationKeys = TableBatchActionsTranslationKeys; TableBatchActions.propTypes = { children: PropTypes.node, @@ -108,7 +177,7 @@ TableBatchActions.propTypes = { onCancel: PropTypes.func.isRequired, /** - * Hook required to listen for when the user initiates a select all + * Hook to listen for when the user initiates a select all * request through this component. This _only_ controls the rendering * of the `Select All` button and does not include built in functionality */ diff --git a/packages/react/src/components/DataTable/stories/DataTable-batch-actions.stories.js b/packages/react/src/components/DataTable/stories/DataTable-batch-actions.stories.js index a9b0f9a57b49..27d7642f7624 100644 --- a/packages/react/src/components/DataTable/stories/DataTable-batch-actions.stories.js +++ b/packages/react/src/components/DataTable/stories/DataTable-batch-actions.stories.js @@ -72,10 +72,17 @@ export const Default = () => ( selectedRows, getTableProps, getTableContainerProps, + selectRow, }) => { const batchActionProps = { ...getBatchActionProps({ - onSelectAll: action('Select all rows across all pages'), + onSelectAll: () => { + rows.map((row) => { + if (!row.isSelected) { + selectRow(row.id); + } + }); + }, }), }; diff --git a/packages/react/src/components/MultiSelect/MultiSelect.tsx b/packages/react/src/components/MultiSelect/MultiSelect.tsx index 40f06d6637cc..45df6ad4644f 100644 --- a/packages/react/src/components/MultiSelect/MultiSelect.tsx +++ b/packages/react/src/components/MultiSelect/MultiSelect.tsx @@ -32,6 +32,7 @@ import { usePrefix } from '../../internal/usePrefix'; import { FormContext } from '../FluidForm'; import { ListBoxProps } from '../ListBox/ListBox'; import { OnChangeData } from '../Dropdown'; +import type { InternationalProps } from '../../types/common'; const noop = () => {}; const getInstanceId = setupGetInstanceId(); @@ -77,10 +78,6 @@ interface DownshiftTypedProps { itemToString?(item: ItemType): string; } -interface InternationalProps> { - translateWithId?(messageId: MID, args?: ARGS): string; -} - interface SortItemsOptions extends SharedOptions, DownshiftTypedProps { diff --git a/packages/react/src/types/common.ts b/packages/react/src/types/common.ts index 4f47374b0350..b1cc97b3e7a2 100644 --- a/packages/react/src/types/common.ts +++ b/packages/react/src/types/common.ts @@ -18,3 +18,14 @@ export type PolymorphicProps = Props & Omit, 'as'> & { as?: Element; }; + +export interface InternationalProps< + MID = string, + ARGS = Record +> { + /** + * Supply a method to translate internal strings with your i18n tool of + * choice. + */ + translateWithId?(messageId: MID, args?: ARGS): string; +}