diff --git a/change/@fluentui-react-components-751955cf-f7fb-477a-9ea1-537da4c2754b.json b/change/@fluentui-react-components-751955cf-f7fb-477a-9ea1-537da4c2754b.json new file mode 100644 index 00000000000000..1c8f3e9af3b0a5 --- /dev/null +++ b/change/@fluentui-react-components-751955cf-f7fb-477a-9ea1-537da4c2754b.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "BREAKING: rename useTable->useTableFeatures, useSelection->useTableSelection, useSort->useTableSort", + "packageName": "@fluentui/react-components", + "email": "lingfangao@hotmail.com", + "dependentChangeType": "patch" +} diff --git a/change/@fluentui-react-table-d05cfee5-5a24-46f8-99a4-05010ebfdc30.json b/change/@fluentui-react-table-d05cfee5-5a24-46f8-99a4-05010ebfdc30.json new file mode 100644 index 00000000000000..828b38950fa26c --- /dev/null +++ b/change/@fluentui-react-table-d05cfee5-5a24-46f8-99a4-05010ebfdc30.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "BREAKING: rename useTable->useTableFeatures, useSelection->useTableSelection, useSort->useTableSort", + "packageName": "@fluentui/react-table", + "email": "lingfangao@hotmail.com", + "dependentChangeType": "patch" +} diff --git a/packages/react-components/react-components/etc/react-components.unstable.api.md b/packages/react-components/react-components/etc/react-components.unstable.api.md index 1ccd052427e840..279fe65305bd94 100644 --- a/packages/react-components/react-components/etc/react-components.unstable.api.md +++ b/packages/react-components/react-components/etc/react-components.unstable.api.md @@ -320,10 +320,7 @@ import { usePersonaStyles_unstable } from '@fluentui/react-persona'; import { useProgress_unstable } from '@fluentui/react-progress'; import { useProgressStyles_unstable } from '@fluentui/react-progress'; import { useSelect_unstable } from '@fluentui/react-select'; -import { useSelection } from '@fluentui/react-table'; import { useSelectStyles_unstable } from '@fluentui/react-select'; -import { useSort } from '@fluentui/react-table'; -import { useTable } from '@fluentui/react-table'; import { useTable_unstable } from '@fluentui/react-table'; import { useTableBody_unstable } from '@fluentui/react-table'; import { useTableBodyStyles_unstable } from '@fluentui/react-table'; @@ -334,6 +331,7 @@ import { useTableCellLayout_unstable } from '@fluentui/react-table'; import { useTableCellLayoutStyles_unstable } from '@fluentui/react-table'; import { useTableCellStyles_unstable } from '@fluentui/react-table'; import { useTableContext } from '@fluentui/react-table'; +import { useTableFeatures } from '@fluentui/react-table'; import { useTableHeader_unstable } from '@fluentui/react-table'; import { useTableHeaderCell_unstable } from '@fluentui/react-table'; import { useTableHeaderCellStyles_unstable } from '@fluentui/react-table'; @@ -341,8 +339,10 @@ import { useTableHeaderStyles_unstable } from '@fluentui/react-table'; import { UseTableOptions } from '@fluentui/react-table'; import { useTableRow_unstable } from '@fluentui/react-table'; import { useTableRowStyles_unstable } from '@fluentui/react-table'; +import { useTableSelection } from '@fluentui/react-table'; import { useTableSelectionCell_unstable } from '@fluentui/react-table'; import { useTableSelectionCellStyles_unstable } from '@fluentui/react-table'; +import { useTableSort } from '@fluentui/react-table'; import { useTableStyles_unstable } from '@fluentui/react-table'; import { useToolbar_unstable } from '@fluentui/react-toolbar'; import { useToolbarDividerStyles_unstable } from '@fluentui/react-toolbar'; @@ -981,14 +981,8 @@ export { useProgressStyles_unstable } export { useSelect_unstable } -export { useSelection } - export { useSelectStyles_unstable } -export { useSort } - -export { useTable } - export { useTable_unstable } export { useTableBody_unstable } @@ -1009,6 +1003,8 @@ export { useTableCellStyles_unstable } export { useTableContext } +export { useTableFeatures } + export { useTableHeader_unstable } export { useTableHeaderCell_unstable } @@ -1023,10 +1019,14 @@ export { useTableRow_unstable } export { useTableRowStyles_unstable } +export { useTableSelection } + export { useTableSelectionCell_unstable } export { useTableSelectionCellStyles_unstable } +export { useTableSort } + export { useTableStyles_unstable } export { useToolbar_unstable } diff --git a/packages/react-components/react-components/src/unstable/index.ts b/packages/react-components/react-components/src/unstable/index.ts index 35045e48736bac..9d12886c06de72 100644 --- a/packages/react-components/react-components/src/unstable/index.ts +++ b/packages/react-components/react-components/src/unstable/index.ts @@ -208,6 +208,10 @@ export { useTableCellLayoutStyles_unstable, renderTableCellLayout_unstable, tableCellLayoutClassNames, + useTableFeatures, + useTableSelection, + useTableSort, + createColumn, DataGridCell, dataGridCellClassNames, useDataGridCellStyles_unstable, @@ -243,10 +247,6 @@ export { useDataGridSelectionCell_unstable, renderDataGridSelectionCell_unstable, dataGridSelectionCellClassNames, - useTable, - useSelection, - useSort, - createColumn, } from '@fluentui/react-table'; export type { diff --git a/packages/react-components/react-table/etc/react-table.api.md b/packages/react-components/react-table/etc/react-table.api.md index d790bbc2797863..8879d6fa16025b 100644 --- a/packages/react-components/react-table/etc/react-table.api.md +++ b/packages/react-components/react-table/etc/react-table.api.md @@ -133,7 +133,7 @@ export type DataGridHeaderSlots = TableHeaderSlots; export type DataGridHeaderState = TableHeaderState; // @public -export type DataGridProps = TableProps & Pick & Pick, 'focusMode' | 'subtleSelection' | 'selectionAppearance'> & Pick & Pick & { +export type DataGridProps = TableProps & Pick & Pick, 'focusMode' | 'subtleSelection' | 'selectionAppearance'> & Pick & Pick & { onSortChange?: (e: React_2.MouseEvent, sortState: SortState) => void; onSelectionChange?: (e: React_2.MouseEvent | React_2.KeyboardEvent, data: OnSelectionChangeData) => void; selectionMode?: SelectionMode_2; @@ -533,15 +533,6 @@ export const useDataGridSelectionCellStyles_unstable: (state: DataGridSelectionC // @public export const useDataGridStyles_unstable: (state: DataGridState) => DataGridState; -// @public (undocumented) -export function useSelection(options: UseSelectionOptions): (tableState: HeadlessTableState) => HeadlessTableState; - -// @public (undocumented) -export function useSort(options: UseSortOptions): (tableState: HeadlessTableState) => HeadlessTableState; - -// @public (undocumented) -export function useTable(options: UseTableOptions, plugins?: TableStatePlugin[]): HeadlessTableState; - // @public export const useTable_unstable: (props: TableProps, ref: React_2.Ref) => TableState; @@ -572,6 +563,9 @@ export const useTableCellStyles_unstable: (state: TableCellState) => TableCellSt // @public (undocumented) export const useTableContext: () => TableContextValue; +// @public (undocumented) +export function useTableFeatures(options: UseTableOptions, plugins?: TableStatePlugin[]): HeadlessTableState; + // @public export const useTableHeader_unstable: (props: TableHeaderProps, ref: React_2.Ref) => TableHeaderState; @@ -600,12 +594,18 @@ export const useTableRow_unstable: (props: TableRowProps, ref: React_2.Ref TableRowState; +// @public (undocumented) +export function useTableSelection(options: UseTableSelectionOptions): (tableState: HeadlessTableState) => HeadlessTableState; + // @public export const useTableSelectionCell_unstable: (props: TableSelectionCellProps, ref: React_2.Ref) => TableSelectionCellState; // @public export const useTableSelectionCellStyles_unstable: (state: TableSelectionCellState) => TableSelectionCellState; +// @public (undocumented) +export function useTableSort(options: UseTableSortOptions): (tableState: HeadlessTableState) => HeadlessTableState; + // @public export const useTableStyles_unstable: (state: TableState) => TableState; diff --git a/packages/react-components/react-table/src/components/DataGrid/DataGrid.types.ts b/packages/react-components/react-table/src/components/DataGrid/DataGrid.types.ts index 10ea38fdda9653..870686c44f1fee 100644 --- a/packages/react-components/react-table/src/components/DataGrid/DataGrid.types.ts +++ b/packages/react-components/react-table/src/components/DataGrid/DataGrid.types.ts @@ -3,9 +3,9 @@ import type { TableContextValues, TableProps, TableSlots, TableState } from '../ import type { SortState, TableState as HeadlessTableState, - UseSortOptions, + UseTableSortOptions, SelectionMode, - UseSelectionOptions, + UseTableSelectionOptions, OnSelectionChangeData, } from '../../hooks'; import { TableRowProps } from '../TableRow/TableRow.types'; @@ -53,8 +53,8 @@ export type DataGridContextValue = HeadlessTableState & { export type DataGridProps = TableProps & Pick & Pick, 'focusMode' | 'subtleSelection' | 'selectionAppearance'> & - Pick & - Pick & { + Pick & + Pick & { onSortChange?: (e: React.MouseEvent, sortState: SortState) => void; onSelectionChange?: (e: React.MouseEvent | React.KeyboardEvent, data: OnSelectionChangeData) => void; /** diff --git a/packages/react-components/react-table/src/components/DataGrid/useDataGrid.ts b/packages/react-components/react-table/src/components/DataGrid/useDataGrid.ts index 35f85feffec0d3..44c7e2febe4a54 100644 --- a/packages/react-components/react-table/src/components/DataGrid/useDataGrid.ts +++ b/packages/react-components/react-table/src/components/DataGrid/useDataGrid.ts @@ -2,7 +2,7 @@ import * as React from 'react'; import { useArrowNavigationGroup } from '@fluentui/react-tabster'; import type { DataGridProps, DataGridState } from './DataGrid.types'; import { useTable_unstable } from '../Table/useTable'; -import { useTable, useSort, useSelection } from '../../hooks'; +import { useTableFeatures, useTableSort, useTableSelection } from '../../hooks'; /** * Create the state required to render DataGrid. @@ -32,13 +32,13 @@ export const useDataGrid_unstable = (props: DataGridProps, ref: React.Ref extends Pick, 'items' columns: ColumnDefinition[]; } -export interface UseSortOptions { +export interface UseTableSortOptions { /** * Used to control sorting */ @@ -148,7 +148,7 @@ export interface UseSortOptions { onSortChange?(e: React.SyntheticEvent, state: SortState): void; } -export interface UseSelectionOptions { +export interface UseTableSelectionOptions { /** * Can be multi or single select */ diff --git a/packages/react-components/react-table/src/hooks/useTable.test.ts b/packages/react-components/react-table/src/hooks/useTableFeatures.test.ts similarity index 85% rename from packages/react-components/react-table/src/hooks/useTable.test.ts rename to packages/react-components/react-table/src/hooks/useTableFeatures.test.ts index aaa7647fd00cb3..cbd61bfd9ac559 100644 --- a/packages/react-components/react-table/src/hooks/useTable.test.ts +++ b/packages/react-components/react-table/src/hooks/useTableFeatures.test.ts @@ -1,18 +1,18 @@ import { renderHook } from '@testing-library/react-hooks'; import { createColumn } from './createColumn'; -import { defaultTableSelectionState, useSelection } from './useSelection'; -import { defaultTableSortState, useSort } from './useSort'; -import { useTable } from './useTable'; +import { defaultTableSelectionState, useTableSelection } from './useTableSelection'; +import { defaultTableSortState, useTableSort } from './useTableSort'; +import { useTableFeatures } from './useTableFeatures'; -describe('useTable', () => { +describe('useTableFeatures', () => { it('should return sort state', () => { const { result } = renderHook(() => - useTable( + useTableFeatures( { columns: [createColumn({ columnId: 1 })], items: [{}, {}, {}], }, - [useSort({})], + [useTableSort({})], ), ); @@ -31,12 +31,12 @@ describe('useTable', () => { it('should return selection state', () => { const { result } = renderHook(() => - useTable( + useTableFeatures( { columns: [createColumn({ columnId: 1 })], items: [{}, {}, {}], }, - [useSelection({ selectionMode: 'multiselect' })], + [useTableSelection({ selectionMode: 'multiselect' })], ), ); @@ -56,7 +56,7 @@ describe('useTable', () => { describe('getRows', () => { it('should enahnce rows', () => { const { result } = renderHook(() => - useTable({ + useTableFeatures({ columns: [createColumn({ columnId: 1 })], items: [{}, {}, {}], }), @@ -90,7 +90,7 @@ describe('useTable', () => { it('should use custom rowId', () => { const { result } = renderHook(() => - useTable({ + useTableFeatures({ columns: [createColumn({ columnId: 1 })], items: [{ value: 'a' }, { value: 'b' }, { value: 'c' }], getRowId: item => item.value, @@ -103,7 +103,7 @@ describe('useTable', () => { it('should return original items', () => { const { result } = renderHook(() => - useTable({ + useTableFeatures({ columns: [createColumn({ columnId: 1 })], items: [{ value: 1 }, { value: 2 }, { value: 3 }], }), diff --git a/packages/react-components/react-table/src/hooks/useTable.ts b/packages/react-components/react-table/src/hooks/useTableFeatures.ts similarity index 78% rename from packages/react-components/react-table/src/hooks/useTable.ts rename to packages/react-components/react-table/src/hooks/useTableFeatures.ts index 8347a3b067822d..ef91e78a5a5e11 100644 --- a/packages/react-components/react-table/src/hooks/useTable.ts +++ b/packages/react-components/react-table/src/hooks/useTableFeatures.ts @@ -1,6 +1,6 @@ import type { UseTableOptions, TableState, RowState, RowEnhancer, TableStatePlugin, TableSortState } from './types'; -import { defaultTableSelectionState } from './useSelection'; -import { defaultTableSortState } from './useSort'; +import { defaultTableSelectionState } from './useTableSelection'; +import { defaultTableSortState } from './useTableSort'; const defaultRowEnhancer: RowEnhancer> = row => row; @@ -13,7 +13,10 @@ export const defaultTableState: TableState = { columns: [], }; -export function useTable(options: UseTableOptions, plugins: TableStatePlugin[] = []): TableState { +export function useTableFeatures( + options: UseTableOptions, + plugins: TableStatePlugin[] = [], +): TableState { const { items, getRowId, columns } = options; const getRows = >( diff --git a/packages/react-components/react-table/src/hooks/useSelection.test.ts b/packages/react-components/react-table/src/hooks/useTableSelection.test.ts similarity index 82% rename from packages/react-components/react-table/src/hooks/useSelection.test.ts rename to packages/react-components/react-table/src/hooks/useTableSelection.test.ts index 06cf9d86a17474..9c27e90e47d7ca 100644 --- a/packages/react-components/react-table/src/hooks/useSelection.test.ts +++ b/packages/react-components/react-table/src/hooks/useTableSelection.test.ts @@ -1,14 +1,14 @@ import { renderHook, act } from '@testing-library/react-hooks'; -import { useSelectionState } from './useSelection'; +import { useTableSelectionState } from './useTableSelection'; import { mockTableState } from '../testing/mockTableState'; import { mockSyntheticEvent } from '../testing/mockSyntheticEvent'; -describe('useSelectionState', () => { +describe('useTableSelectionState', () => { const items = [{ value: 'a' }, { value: 'b' }, { value: 'c' }, { value: 'd' }]; it('should use default selected state', () => { const { result } = renderHook(() => - useSelectionState(mockTableState({ items }), { + useTableSelectionState(mockTableState({ items }), { selectionMode: 'multiselect', defaultSelectedItems: new Set([1]), }), @@ -19,7 +19,7 @@ describe('useSelectionState', () => { it('should use user selected state', () => { const { result } = renderHook(() => - useSelectionState(mockTableState({ items }), { selectionMode: 'multiselect', selectedItems: new Set([1]) }), + useTableSelectionState(mockTableState({ items }), { selectionMode: 'multiselect', selectedItems: new Set([1]) }), ); expect(Array.from(result.current.selection.selectedRows)).toEqual([1]); @@ -28,7 +28,7 @@ describe('useSelectionState', () => { describe('multiselect', () => { it('should use custom row id', () => { const { result } = renderHook(() => - useSelectionState( + useTableSelectionState( mockTableState({ getRowId: (item: { value: string }) => item.value, items, @@ -49,7 +49,7 @@ describe('useSelectionState', () => { it('should select all rows', () => { const onSelectionChange = jest.fn(); const { result } = renderHook(() => - useSelectionState(mockTableState({ items }), { selectionMode: 'multiselect', onSelectionChange }), + useTableSelectionState(mockTableState({ items }), { selectionMode: 'multiselect', onSelectionChange }), ); act(() => { @@ -64,7 +64,7 @@ describe('useSelectionState', () => { it('should deselect all rows', () => { const onSelectionChange = jest.fn(); const { result } = renderHook(() => - useSelectionState(mockTableState({ items }), { selectionMode: 'multiselect', onSelectionChange }), + useTableSelectionState(mockTableState({ items }), { selectionMode: 'multiselect', onSelectionChange }), ); act(() => { @@ -84,7 +84,7 @@ describe('useSelectionState', () => { it('should clear selection', () => { const onSelectionChange = jest.fn(); const { result } = renderHook(() => - useSelectionState(mockTableState({ items }), { selectionMode: 'multiselect', onSelectionChange }), + useTableSelectionState(mockTableState({ items }), { selectionMode: 'multiselect', onSelectionChange }), ); act(() => { @@ -104,7 +104,7 @@ describe('useSelectionState', () => { it('should select row', () => { const onSelectionChange = jest.fn(); const { result } = renderHook(() => - useSelectionState(mockTableState({ items }), { selectionMode: 'multiselect', onSelectionChange }), + useTableSelectionState(mockTableState({ items }), { selectionMode: 'multiselect', onSelectionChange }), ); act(() => { @@ -119,7 +119,7 @@ describe('useSelectionState', () => { it('should select multiple rows', () => { const onSelectionChange = jest.fn(); const { result } = renderHook(() => - useSelectionState(mockTableState({ items }), { selectionMode: 'multiselect', onSelectionChange }), + useTableSelectionState(mockTableState({ items }), { selectionMode: 'multiselect', onSelectionChange }), ); act(() => { @@ -142,7 +142,7 @@ describe('useSelectionState', () => { it('should make row unselected', () => { const onSelectionChange = jest.fn(); const { result } = renderHook(() => - useSelectionState(mockTableState({ items }), { selectionMode: 'multiselect', onSelectionChange }), + useTableSelectionState(mockTableState({ items }), { selectionMode: 'multiselect', onSelectionChange }), ); act(() => { @@ -163,7 +163,7 @@ describe('useSelectionState', () => { it('should select unselected row', () => { const onSelectionChange = jest.fn(); const { result } = renderHook(() => - useSelectionState(mockTableState({ items }), { selectionMode: 'multiselect', onSelectionChange }), + useTableSelectionState(mockTableState({ items }), { selectionMode: 'multiselect', onSelectionChange }), ); act(() => { @@ -179,7 +179,7 @@ describe('useSelectionState', () => { it('should deselect selected row', () => { const onSelectionChange = jest.fn(); const { result } = renderHook(() => - useSelectionState(mockTableState({ items }), { selectionMode: 'multiselect', onSelectionChange }), + useTableSelectionState(mockTableState({ items }), { selectionMode: 'multiselect', onSelectionChange }), ); act(() => { @@ -199,7 +199,7 @@ describe('useSelectionState', () => { it('should select another unselected row', () => { const onSelectionChange = jest.fn(); const { result } = renderHook(() => - useSelectionState(mockTableState({ items }), { selectionMode: 'multiselect', onSelectionChange }), + useTableSelectionState(mockTableState({ items }), { selectionMode: 'multiselect', onSelectionChange }), ); act(() => { @@ -221,7 +221,7 @@ describe('useSelectionState', () => { describe('allRowsSelected', () => { it('should return true if all rows are selected', () => { const { result } = renderHook(() => - useSelectionState(mockTableState({ items }), { selectionMode: 'multiselect' }), + useTableSelectionState(mockTableState({ items }), { selectionMode: 'multiselect' }), ); act(() => { @@ -233,7 +233,7 @@ describe('useSelectionState', () => { it('should return false if there is no selected row', () => { const { result } = renderHook(() => - useSelectionState(mockTableState({ items }), { selectionMode: 'multiselect' }), + useTableSelectionState(mockTableState({ items }), { selectionMode: 'multiselect' }), ); expect(result.current.selection.selectedRows.size).toBe(0); @@ -242,7 +242,7 @@ describe('useSelectionState', () => { it('should return false if not all rows are selected', () => { const { result } = renderHook(() => - useSelectionState(mockTableState({ items }), { selectionMode: 'multiselect' }), + useTableSelectionState(mockTableState({ items }), { selectionMode: 'multiselect' }), ); act(() => { @@ -261,7 +261,7 @@ describe('useSelectionState', () => { describe('someRowsSelected', () => { it('should return true if there is a selected row', () => { const { result } = renderHook(() => - useSelectionState(mockTableState({ items }), { selectionMode: 'multiselect' }), + useTableSelectionState(mockTableState({ items }), { selectionMode: 'multiselect' }), ); act(() => { @@ -274,7 +274,7 @@ describe('useSelectionState', () => { it('should return false if there is no selected row', () => { const { result } = renderHook(() => - useSelectionState(mockTableState({ items }), { selectionMode: 'multiselect' }), + useTableSelectionState(mockTableState({ items }), { selectionMode: 'multiselect' }), ); expect(result.current.selection.selectedRows.size).toBe(0); @@ -288,7 +288,7 @@ describe('useSelectionState', () => { it('should throw when not in production', () => { const onSelectionChange = jest.fn(); const { result } = renderHook(() => - useSelectionState(mockTableState({ items }), { selectionMode: 'single', onSelectionChange }), + useTableSelectionState(mockTableState({ items }), { selectionMode: 'single', onSelectionChange }), ); expect(result.current.selection.toggleAllRows).toThrowErrorMatchingInlineSnapshot( @@ -301,7 +301,7 @@ describe('useSelectionState', () => { const nodeEnv = (process.env.NODE_ENV = 'production'); const onSelectionChange = jest.fn(); const { result } = renderHook(() => - useSelectionState(mockTableState({ items }), { selectionMode: 'single', onSelectionChange }), + useTableSelectionState(mockTableState({ items }), { selectionMode: 'single', onSelectionChange }), ); result.current.selection.toggleAllRows; @@ -315,7 +315,7 @@ describe('useSelectionState', () => { it('should clear selection', () => { const onSelectionChange = jest.fn(); const { result } = renderHook(() => - useSelectionState(mockTableState({ items }), { selectionMode: 'single', onSelectionChange }), + useTableSelectionState(mockTableState({ items }), { selectionMode: 'single', onSelectionChange }), ); act(() => { @@ -335,7 +335,7 @@ describe('useSelectionState', () => { it('should select row', () => { const onSelectionChange = jest.fn(); const { result } = renderHook(() => - useSelectionState(mockTableState({ items }), { selectionMode: 'single', onSelectionChange }), + useTableSelectionState(mockTableState({ items }), { selectionMode: 'single', onSelectionChange }), ); act(() => { @@ -350,7 +350,7 @@ describe('useSelectionState', () => { it('should select another row', () => { const onSelectionChange = jest.fn(); const { result } = renderHook(() => - useSelectionState(mockTableState({ items }), { selectionMode: 'single', onSelectionChange }), + useTableSelectionState(mockTableState({ items }), { selectionMode: 'single', onSelectionChange }), ); act(() => { @@ -372,7 +372,7 @@ describe('useSelectionState', () => { it('should make row unselected', () => { const onSelectionChange = jest.fn(); const { result } = renderHook(() => - useSelectionState(mockTableState({ items }), { selectionMode: 'single', onSelectionChange }), + useTableSelectionState(mockTableState({ items }), { selectionMode: 'single', onSelectionChange }), ); act(() => { @@ -393,7 +393,7 @@ describe('useSelectionState', () => { it('should select unselected row', () => { const onSelectionChange = jest.fn(); const { result } = renderHook(() => - useSelectionState(mockTableState({ items }), { selectionMode: 'single', onSelectionChange }), + useTableSelectionState(mockTableState({ items }), { selectionMode: 'single', onSelectionChange }), ); act(() => { @@ -409,7 +409,7 @@ describe('useSelectionState', () => { it('should deselect selected row', () => { const onSelectionChange = jest.fn(); const { result } = renderHook(() => - useSelectionState(mockTableState({ items }), { selectionMode: 'single', onSelectionChange }), + useTableSelectionState(mockTableState({ items }), { selectionMode: 'single', onSelectionChange }), ); act(() => { @@ -429,7 +429,7 @@ describe('useSelectionState', () => { it('should select another unselected row', () => { const onSelectionChange = jest.fn(); const { result } = renderHook(() => - useSelectionState(mockTableState({ items }), { selectionMode: 'single', onSelectionChange }), + useTableSelectionState(mockTableState({ items }), { selectionMode: 'single', onSelectionChange }), ); act(() => { @@ -450,7 +450,9 @@ describe('useSelectionState', () => { describe('allRowsSelected', () => { it('should return true if there is a selected row', () => { - const { result } = renderHook(() => useSelectionState(mockTableState({ items }), { selectionMode: 'single' })); + const { result } = renderHook(() => + useTableSelectionState(mockTableState({ items }), { selectionMode: 'single' }), + ); act(() => { result.current.selection.selectRow(mockSyntheticEvent(), 1); @@ -461,7 +463,9 @@ describe('useSelectionState', () => { }); it('should return false if there is no selected row', () => { - const { result } = renderHook(() => useSelectionState(mockTableState({ items }), { selectionMode: 'single' })); + const { result } = renderHook(() => + useTableSelectionState(mockTableState({ items }), { selectionMode: 'single' }), + ); expect(result.current.selection.selectedRows.size).toBe(0); expect(result.current.selection.allRowsSelected).toBe(false); @@ -470,7 +474,9 @@ describe('useSelectionState', () => { describe('someRowsSelected', () => { it('should return true if there is a selected row', () => { - const { result } = renderHook(() => useSelectionState(mockTableState({ items }), { selectionMode: 'single' })); + const { result } = renderHook(() => + useTableSelectionState(mockTableState({ items }), { selectionMode: 'single' }), + ); act(() => { result.current.selection.selectRow(mockSyntheticEvent(), 1); @@ -481,7 +487,9 @@ describe('useSelectionState', () => { }); it('should return false if there is no selected row', () => { - const { result } = renderHook(() => useSelectionState(mockTableState({ items }), { selectionMode: 'single' })); + const { result } = renderHook(() => + useTableSelectionState(mockTableState({ items }), { selectionMode: 'single' }), + ); expect(result.current.selection.selectedRows.size).toBe(0); expect(result.current.selection.someRowsSelected).toBe(false); diff --git a/packages/react-components/react-table/src/hooks/useSelection.ts b/packages/react-components/react-table/src/hooks/useTableSelection.ts similarity index 88% rename from packages/react-components/react-table/src/hooks/useSelection.ts rename to packages/react-components/react-table/src/hooks/useTableSelection.ts index 202578bbfb825f..3a288cd99c87d3 100644 --- a/packages/react-components/react-table/src/hooks/useSelection.ts +++ b/packages/react-components/react-table/src/hooks/useTableSelection.ts @@ -1,7 +1,7 @@ import * as React from 'react'; import { useControllableState, useEventCallback } from '@fluentui/react-utilities'; import { createSelectionManager } from './selectionManager'; -import type { RowId, TableSelectionState, TableState, UseSelectionOptions } from './types'; +import type { RowId, TableSelectionState, TableState, UseTableSelectionOptions } from './types'; const noop = () => undefined; @@ -18,15 +18,15 @@ export const defaultTableSelectionState: TableSelectionState = { selectionMode: 'multiselect', }; -export function useSelection(options: UseSelectionOptions) { +export function useTableSelection(options: UseTableSelectionOptions) { // False positive, these plugin hooks are intended to be run on every render // eslint-disable-next-line react-hooks/rules-of-hooks - return (tableState: TableState) => useSelectionState(tableState, options); + return (tableState: TableState) => useTableSelectionState(tableState, options); } -export function useSelectionState( +export function useTableSelectionState( tableState: TableState, - options: UseSelectionOptions, + options: UseTableSelectionOptions, ): TableState { const { items, getRowId } = tableState; const { selectionMode, defaultSelectedItems, selectedItems, onSelectionChange } = options; diff --git a/packages/react-components/react-table/src/hooks/useSort.test.ts b/packages/react-components/react-table/src/hooks/useTableSort.test.ts similarity index 85% rename from packages/react-components/react-table/src/hooks/useSort.test.ts rename to packages/react-components/react-table/src/hooks/useTableSort.test.ts index aeda41df527ba0..5738cc93f68863 100644 --- a/packages/react-components/react-table/src/hooks/useSort.test.ts +++ b/packages/react-components/react-table/src/hooks/useTableSort.test.ts @@ -1,11 +1,11 @@ import { renderHook, act } from '@testing-library/react-hooks'; import { ColumnDefinition } from './types'; -import { useSortState } from './useSort'; +import { useTableSortState } from './useTableSort'; import { mockTableState } from '../testing/mockTableState'; import { createColumn } from './createColumn'; import { mockSyntheticEvent } from '../testing/mockSyntheticEvent'; -describe('useSortState', () => { +describe('useTableSortState', () => { it('should use default sort state', () => { const columnDefinition = [ createColumn({ columnId: 1 }), @@ -13,7 +13,7 @@ describe('useSortState', () => { createColumn({ columnId: 3 }), ]; const { result } = renderHook(() => - useSortState(mockTableState({ columns: columnDefinition }), { + useTableSortState(mockTableState({ columns: columnDefinition }), { defaultSortState: { sortColumn: 2, sortDirection: 'descending' }, }), ); @@ -29,7 +29,7 @@ describe('useSortState', () => { createColumn({ columnId: 3 }), ]; const { result } = renderHook(() => - useSortState(mockTableState({ columns: columnDefinition }), { + useTableSortState(mockTableState({ columns: columnDefinition }), { sortState: { sortColumn: 2, sortDirection: 'descending' }, }), ); @@ -47,7 +47,7 @@ describe('useSortState', () => { ]; const onSortChange = jest.fn(); const { result } = renderHook(() => - useSortState(mockTableState({ columns: columnDefinition }), { onSortChange }), + useTableSortState(mockTableState({ columns: columnDefinition }), { onSortChange }), ); act(() => { result.current.sort.toggleColumnSort(mockSyntheticEvent(), 1); @@ -67,7 +67,7 @@ describe('useSortState', () => { ]; const onSortChange = jest.fn(); const { result } = renderHook(() => - useSortState(mockTableState({ columns: columnDefinition }), { onSortChange }), + useTableSortState(mockTableState({ columns: columnDefinition }), { onSortChange }), ); act(() => { result.current.sort.toggleColumnSort(mockSyntheticEvent(), 1); @@ -93,7 +93,7 @@ describe('useSortState', () => { ]; const onSortChange = jest.fn(); const { result } = renderHook(() => - useSortState(mockTableState({ columns: columnDefinition }), { onSortChange }), + useTableSortState(mockTableState({ columns: columnDefinition }), { onSortChange }), ); act(() => { result.current.sort.setColumnSort(mockSyntheticEvent(), 1, 'ascending'); @@ -113,7 +113,7 @@ describe('useSortState', () => { ]; const onSortChange = jest.fn(); const { result } = renderHook(() => - useSortState(mockTableState({ columns: columnDefinition }), { onSortChange }), + useTableSortState(mockTableState({ columns: columnDefinition }), { onSortChange }), ); act(() => { result.current.sort.setColumnSort(mockSyntheticEvent(), 1, 'descending'); @@ -136,7 +136,7 @@ describe('useSortState', () => { createColumn({ columnId: 3, compare: createMockCompare() }), ]; - const { result } = renderHook(() => useSortState(mockTableState({ columns: columnDefinition }), {})); + const { result } = renderHook(() => useTableSortState(mockTableState({ columns: columnDefinition }), {})); act(() => { result.current.sort.toggleColumnSort(mockSyntheticEvent(), 2); }); @@ -153,7 +153,7 @@ describe('useSortState', () => { createColumn({ columnId: 1, compare: (a, b) => a.value - b.value }), ]; - const { result } = renderHook(() => useSortState(mockTableState({ columns: columnDefinition }), {})); + const { result } = renderHook(() => useTableSortState(mockTableState({ columns: columnDefinition }), {})); act(() => { result.current.sort.toggleColumnSort(mockSyntheticEvent(), 1); }); @@ -175,7 +175,7 @@ describe('useSortState', () => { ]; const items = [{ value: 1 }, { value: 2 }]; - const { result } = renderHook(() => useSortState(mockTableState({ items, columns: columnDefinition }), {})); + const { result } = renderHook(() => useTableSortState(mockTableState({ items, columns: columnDefinition }), {})); act(() => { result.current.sort.toggleColumnSort(mockSyntheticEvent(), 1); }); @@ -199,7 +199,7 @@ describe('useSortState', () => { it('should return sort direction for the sorted column', () => { const columnDefinition: ColumnDefinition<{ value: number }>[] = [createColumn({ columnId: 1 })]; - const { result } = renderHook(() => useSortState(mockTableState({ columns: columnDefinition }), {})); + const { result } = renderHook(() => useTableSortState(mockTableState({ columns: columnDefinition }), {})); act(() => { result.current.sort.setColumnSort(mockSyntheticEvent(), 1, 'descending'); }); @@ -213,7 +213,7 @@ describe('useSortState', () => { createColumn({ columnId: 2 }), ]; - const { result } = renderHook(() => useSortState(mockTableState({ columns: columnDefinition }), {})); + const { result } = renderHook(() => useTableSortState(mockTableState({ columns: columnDefinition }), {})); act(() => { result.current.sort.setColumnSort(mockSyntheticEvent(), 1, 'descending'); }); diff --git a/packages/react-components/react-table/src/hooks/useSort.ts b/packages/react-components/react-table/src/hooks/useTableSort.ts similarity index 88% rename from packages/react-components/react-table/src/hooks/useSort.ts rename to packages/react-components/react-table/src/hooks/useTableSort.ts index 2ad8e46ea31f05..1e5a1b350de1e2 100644 --- a/packages/react-components/react-table/src/hooks/useSort.ts +++ b/packages/react-components/react-table/src/hooks/useTableSort.ts @@ -1,6 +1,6 @@ import * as React from 'react'; import { useControllableState } from '@fluentui/react-utilities'; -import type { ColumnId, RowState, SortState, TableSortState, TableState, UseSortOptions } from './types'; +import type { ColumnId, RowState, SortState, TableSortState, TableState, UseTableSortOptions } from './types'; const noop = () => undefined; @@ -13,13 +13,16 @@ export const defaultTableSortState: TableSortState = { toggleColumnSort: noop, }; -export function useSort(options: UseSortOptions) { +export function useTableSort(options: UseTableSortOptions) { // False positive, these plugin hooks are intended to be run on every render // eslint-disable-next-line react-hooks/rules-of-hooks - return (tableState: TableState) => useSortState(tableState, options); + return (tableState: TableState) => useTableSortState(tableState, options); } -export function useSortState(tableState: TableState, options: UseSortOptions): TableState { +export function useTableSortState( + tableState: TableState, + options: UseTableSortOptions, +): TableState { const { columns } = tableState; const { sortState, defaultSortState, onSortChange } = options; diff --git a/packages/react-components/react-table/src/index.ts b/packages/react-components/react-table/src/index.ts index f2aaa2844a794d..a9bd968656b8b8 100644 --- a/packages/react-components/react-table/src/index.ts +++ b/packages/react-components/react-table/src/index.ts @@ -1,4 +1,4 @@ -export { useTable, useSelection, useSort, createColumn } from './hooks'; +export { useTableFeatures, useTableSelection, useTableSort, createColumn } from './hooks'; export type { UseTableOptions, TableState as HeadlessTableState, diff --git a/packages/react-components/react-table/stories/Table/DataGrid.stories.tsx b/packages/react-components/react-table/stories/Table/DataGrid.stories.tsx index a59145151ae634..50df8cec3f9412 100644 --- a/packages/react-components/react-table/stories/Table/DataGrid.stories.tsx +++ b/packages/react-components/react-table/stories/Table/DataGrid.stories.tsx @@ -18,10 +18,10 @@ import { TableHeaderCell, TableSelectionCell, TableCellLayout, - useTable, + useTableFeatures, ColumnDefinition, - useSelection, - useSort, + useTableSelection, + useTableSort, createColumn, ColumnId, } from '@fluentui/react-components/unstable'; @@ -127,17 +127,17 @@ export const DataGrid = () => { getRows, selection: { allRowsSelected, someRowsSelected, toggleAllRows, toggleRow, isRowSelected }, sort: { getSortDirection, toggleColumnSort, sort }, - } = useTable( + } = useTableFeatures( { columns, items, }, [ - useSelection({ + useTableSelection({ selectionMode: 'multiselect', defaultSelectedItems: new Set([0, 1]), }), - useSort({ defaultSortState: { sortColumn: 'file', sortDirection: 'ascending' } }), + useTableSort({ defaultSortState: { sortColumn: 'file', sortDirection: 'ascending' } }), ], ); @@ -217,7 +217,7 @@ DataGrid.parameters = { docs: { description: { story: [ - 'The `DataGrid` component is simply a composition of hook and primitive `Table` components', + 'The `DataGrid` component is a composition of the `useTableFeatures` hook and primitive `Table` components', 'along with some convenience features such as accessible markup and event handlers.', 'Any feature of the `DataGrid` is achievable with the primitive components and hook', ].join('\n'), diff --git a/packages/react-components/react-table/stories/Table/MultipleSelect.stories.tsx b/packages/react-components/react-table/stories/Table/MultipleSelect.stories.tsx index dccf74ca5839b4..5d35663cddccfc 100644 --- a/packages/react-components/react-table/stories/Table/MultipleSelect.stories.tsx +++ b/packages/react-components/react-table/stories/Table/MultipleSelect.stories.tsx @@ -18,9 +18,9 @@ import { TableHeaderCell, TableSelectionCell, TableCellLayout, - useTable, + useTableFeatures, ColumnDefinition, - useSelection, + useTableSelection, createColumn, } from '@fluentui/react-components/unstable'; @@ -112,13 +112,13 @@ export const MultipleSelect = () => { const { getRows, selection: { allRowsSelected, someRowsSelected, toggleAllRows, toggleRow, isRowSelected }, - } = useTable( + } = useTableFeatures( { columns, items, }, [ - useSelection({ + useTableSelection({ selectionMode: 'multiselect', defaultSelectedItems: new Set([0, 1]), }), @@ -193,7 +193,8 @@ MultipleSelect.parameters = { description: { story: [ 'Selection can be achieved easily by combining the `TableSelectionCell` component along with', - 'other primitive components. The hook can handle state management for selection, although its use is not', + 'other primitive components. `useTableFeatures` can handle state management for selection,', + 'although its use is not', 'necessary if users already have their own state management.', ].join('\n'), }, diff --git a/packages/react-components/react-table/stories/Table/MultipleSelectControlled.stories.tsx b/packages/react-components/react-table/stories/Table/MultipleSelectControlled.stories.tsx index 1a27b55abf1d58..4c1f75eea44e4a 100644 --- a/packages/react-components/react-table/stories/Table/MultipleSelectControlled.stories.tsx +++ b/packages/react-components/react-table/stories/Table/MultipleSelectControlled.stories.tsx @@ -18,10 +18,10 @@ import { TableHeaderCell, TableSelectionCell, TableCellLayout, - useTable, + useTableFeatures, ColumnDefinition, RowId, - useSelection, + useTableSelection, createColumn, } from '@fluentui/react-components/unstable'; @@ -117,13 +117,13 @@ export const MultipleSelectControlled = () => { const { getRows, selection: { allRowsSelected, someRowsSelected, toggleAllRows, toggleRow, isRowSelected }, - } = useTable( + } = useTableFeatures( { columns, items, }, [ - useSelection({ + useTableSelection({ selectionMode: 'multiselect', selectedItems: selectedRows, onSelectionChange: (e, data) => setSelectedRows(data.selectedItems), diff --git a/packages/react-components/react-table/stories/Table/SingleSelect.stories.tsx b/packages/react-components/react-table/stories/Table/SingleSelect.stories.tsx index c010b8ac60d110..01d8109b7a0367 100644 --- a/packages/react-components/react-table/stories/Table/SingleSelect.stories.tsx +++ b/packages/react-components/react-table/stories/Table/SingleSelect.stories.tsx @@ -17,9 +17,9 @@ import { TableHeader, TableHeaderCell, TableSelectionCell, - useTable, + useTableFeatures, ColumnDefinition, - useSelection, + useTableSelection, TableCellLayout, createColumn, } from '@fluentui/react-components/unstable'; @@ -112,13 +112,13 @@ export const SingleSelect = () => { const { getRows, selection: { toggleRow, isRowSelected }, - } = useTable( + } = useTableFeatures( { columns, items, }, [ - useSelection({ + useTableSelection({ selectionMode: 'single', defaultSelectedItems: new Set([1]), }), diff --git a/packages/react-components/react-table/stories/Table/SingleSelectControlled.stories.tsx b/packages/react-components/react-table/stories/Table/SingleSelectControlled.stories.tsx index 759fdcad48d193..6d2a0559dc2639 100644 --- a/packages/react-components/react-table/stories/Table/SingleSelectControlled.stories.tsx +++ b/packages/react-components/react-table/stories/Table/SingleSelectControlled.stories.tsx @@ -17,10 +17,10 @@ import { TableHeader, TableHeaderCell, TableSelectionCell, - useTable, + useTableFeatures, ColumnDefinition, RowId, - useSelection, + useTableSelection, TableCellLayout, createColumn, } from '@fluentui/react-components/unstable'; @@ -116,13 +116,13 @@ export const SingleSelectControlled = () => { const { getRows, selection: { toggleRow, isRowSelected }, - } = useTable( + } = useTableFeatures( { columns, items, }, [ - useSelection({ + useTableSelection({ selectionMode: 'single', selectedItems: selectedRows, onSelectionChange: (e, data) => setSelectedRows(data.selectedItems), @@ -192,7 +192,8 @@ SingleSelectControlled.parameters = { docs: { description: { story: [ - 'By default our hook is uncontrolled. However, it is possible to control selection features with external', + 'By default the `useTableFeatures` hook is uncontrolled. ', + 'However, it is possible to control selection features with external', 'user state.', ].join('\n'), }, diff --git a/packages/react-components/react-table/stories/Table/Sort.stories.tsx b/packages/react-components/react-table/stories/Table/Sort.stories.tsx index 86116e587ac3ee..13f57ad3dcf6f0 100644 --- a/packages/react-components/react-table/stories/Table/Sort.stories.tsx +++ b/packages/react-components/react-table/stories/Table/Sort.stories.tsx @@ -16,10 +16,10 @@ import { Table, TableHeader, TableHeaderCell, - useTable, + useTableFeatures, ColumnDefinition, ColumnId, - useSort, + useTableSort, TableCellLayout, createColumn, } from '@fluentui/react-components/unstable'; @@ -124,12 +124,12 @@ export const Sort = () => { const { getRows, sort: { getSortDirection, toggleColumnSort, sort }, - } = useTable( + } = useTableFeatures( { columns, items, }, - [useSort({ defaultSortState: { sortColumn: 'file', sortDirection: 'ascending' } })], + [useTableSort({ defaultSortState: { sortColumn: 'file', sortDirection: 'ascending' } })], ); const keyboardNavAttr = useArrowNavigationGroup({ axis: 'grid' }); @@ -185,7 +185,7 @@ Sort.parameters = { story: [ 'Using the `sortable` prop will configure all header cells to be buttons and add extra styles.', 'The `TableHeaderCell` component accepts a `sortDirection` prop that will indicate whether the', - 'header is sorted. Handling the sort of data and column state is handled by our hook.', + 'header is sorted. Handling the sort of data and column state is handled by `useTableFeatures`.', ].join('\n'), }, }, diff --git a/packages/react-components/react-table/stories/Table/SortControlled.stories.tsx b/packages/react-components/react-table/stories/Table/SortControlled.stories.tsx index 55be1a3560f43d..cb15c1e1949e9d 100644 --- a/packages/react-components/react-table/stories/Table/SortControlled.stories.tsx +++ b/packages/react-components/react-table/stories/Table/SortControlled.stories.tsx @@ -16,10 +16,10 @@ import { Table, TableHeader, TableHeaderCell, - useTable, + useTableFeatures, ColumnDefinition, ColumnId, - useSort, + useTableSort, TableCellLayout, createColumn, } from '@fluentui/react-components/unstable'; @@ -132,12 +132,12 @@ export const SortControlled = () => { const { getRows, sort: { getSortDirection, toggleColumnSort, sort }, - } = useTable( + } = useTableFeatures( { columns, items, }, - [useSort({ sortState, onSortChange: (e, nextSortState) => setSortState(nextSortState) })], + [useTableSort({ sortState, onSortChange: (e, nextSortState) => setSortState(nextSortState) })], ); const keyboardNavAttr = useArrowNavigationGroup({ axis: 'grid' }); diff --git a/packages/react-components/react-table/stories/Table/SubtleSelection.stories.tsx b/packages/react-components/react-table/stories/Table/SubtleSelection.stories.tsx index 92b3a51d4fe7ca..9b230824ca8bf9 100644 --- a/packages/react-components/react-table/stories/Table/SubtleSelection.stories.tsx +++ b/packages/react-components/react-table/stories/Table/SubtleSelection.stories.tsx @@ -18,9 +18,9 @@ import { TableHeaderCell, TableSelectionCell, TableCellLayout, - useTable, + useTableFeatures, ColumnDefinition, - useSelection, + useTableSelection, createColumn, } from '@fluentui/react-components/unstable'; @@ -112,13 +112,13 @@ export const SubtleSelection = () => { const { getRows, selection: { allRowsSelected, someRowsSelected, toggleAllRows, toggleRow, isRowSelected }, - } = useTable( + } = useTableFeatures( { columns, items, }, [ - useSelection({ + useTableSelection({ selectionMode: 'multiselect', defaultSelectedItems: new Set([0, 1]), }), diff --git a/packages/react-components/react-table/stories/Table/TableDescription.md b/packages/react-components/react-table/stories/Table/TableDescription.md index 4c0a261989ba12..c7d4000add7c2a 100644 --- a/packages/react-components/react-table/stories/Table/TableDescription.md +++ b/packages/react-components/react-table/stories/Table/TableDescription.md @@ -17,5 +17,10 @@ > from first class Microsoft design and accessibility support. A Table displays sets of two-dimensional data. The primitive components can be fully customized to support different -feature sets. The library provides a default hook that handles the business logic and state management of common +feature sets. The library provides a default `useTableFeatures` hook that handles the business logic and state management of common features. There is no obligation to use our hook with these components, we've created it for convenience. + +The `useTableFeatures` hook was designed with feature composition in mind. This means that are composed using +plugins hooks such as `useTableSort` and `useTableSelection` as a part of `useTableFeatures`. This means +that as the feature set expands, users will not need to pay the bundle size price for features that they do not intend +to use. Please consult the usage examples below for more details.