From df04533aa56157985792e1ceb8aaf965a77a193d Mon Sep 17 00:00:00 2001 From: Andrei Zhaleznichenka Date: Mon, 4 Sep 2023 15:47:53 +0200 Subject: [PATCH] refactor: Table selection reduce coupling with table (#1496) --- .../table-fragments/selection-custom.page.tsx | 135 ++++++++++++++++++ pages/table-fragments/styles.scss | 5 + src/cards/index.tsx | 11 +- src/table/__integ__/sticky-header.test.ts | 2 +- src/table/internal.tsx | 5 +- .../selection/__integ__/selection.test.ts | 66 +++++++++ .../__tests__/use-selection.test.tsx | 4 +- src/table/selection/index.ts | 8 ++ src/table/selection/interfaces.ts | 12 ++ .../selection-control.tsx} | 4 +- .../styles.scss | 0 .../selection/use-selection-focus-move.ts | 57 ++++++++ src/table/{ => selection}/use-selection.ts | 96 ++----------- src/table/selection/utils.ts | 27 ++++ src/table/thead.tsx | 3 +- src/test-utils/dom/table/index.ts | 2 +- 16 files changed, 335 insertions(+), 102 deletions(-) create mode 100644 pages/table-fragments/selection-custom.page.tsx create mode 100644 src/table/selection/__integ__/selection.test.ts rename src/table/{ => selection}/__tests__/use-selection.test.tsx (81%) create mode 100644 src/table/selection/index.ts create mode 100644 src/table/selection/interfaces.ts rename src/table/{selection-control/index.tsx => selection/selection-control.tsx} (97%) rename src/table/{selection-control => selection}/styles.scss (100%) create mode 100644 src/table/selection/use-selection-focus-move.ts rename src/table/{ => selection}/use-selection.ts (63%) create mode 100644 src/table/selection/utils.ts diff --git a/pages/table-fragments/selection-custom.page.tsx b/pages/table-fragments/selection-custom.page.tsx new file mode 100644 index 0000000000..176ba85c04 --- /dev/null +++ b/pages/table-fragments/selection-custom.page.tsx @@ -0,0 +1,135 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 +import React, { useContext, useState } from 'react'; +import { ColumnLayout, Container, ContentLayout, FormField, Header, Link, Select } from '~components'; +import { SelectionControl, focusMarkers, useSelectionFocusMove, useSelection } from '~components/table/selection'; +import styles from './styles.scss'; +import { generateItems, Instance } from '../table/generate-data'; +import AppContext, { AppContextType } from '../app/app-context'; +import ScreenreaderOnly from '~components/internal/components/screenreader-only'; +import clsx from 'clsx'; + +type PageContext = React.Context< + AppContextType<{ + selectionType: 'single' | 'multi'; + }> +>; + +const items = generateItems(25); + +const selectionTypeOptions = [{ value: 'single' }, { value: 'multi' }]; + +export default function Page() { + const { urlParams, setUrlParams } = useContext(AppContext as PageContext); + const selectionType = urlParams.selectionType ?? 'single'; + + const [selectedItems, setSelectedItems] = useState([]); + const { getSelectAllProps, getItemSelectionProps, updateShiftToggle } = useSelection({ + items, + selectedItems, + selectionType, + onSelectionChange: event => setSelectedItems(event.detail.selectedItems), + ariaLabels: { + selectionGroupLabel: 'group label', + allItemsSelectionLabel: ({ selectedItems }) => `${selectedItems.length} item selected`, + itemSelectionLabel: ({ selectedItems }, item) => + `${item.id} is ${selectedItems.indexOf(item) < 0 ? 'not ' : ''}selected`, + }, + }); + + const { moveFocusDown, moveFocusUp, moveFocus } = useSelectionFocusMove(selectionType, items.length); + + const columnDefinitions = [ + { + key: 'selection', + header: + selectionType === 'multi' ? ( + moveFocus?.(event.target as HTMLElement, -1, +1)} + {...getSelectAllProps()} + /> + ) : ( + selection cell + ), + cell: (item: Instance) => ( + + ), + }, + { + key: 'id', + header: 'ID', + cell: (item: Instance) => item.id, + }, + { + key: 'imageId', + header: 'Image ID', + cell: (item: Instance) => {item.imageId}, + }, + { + key: 'state', + header: 'State', + cell: (item: Instance) => item.state, + }, + { key: 'dnsName', header: 'DNS name', cell: (item: Instance) => item.dnsName ?? '?' }, + { key: 'type', header: 'Type', cell: (item: Instance) => item.type }, + ]; + + return ( + Rows selection with a custom table}> + + +