From 23625cd7cd7301dcede0e9b97bc9b6f0a4d90825 Mon Sep 17 00:00:00 2001 From: heswell Date: Thu, 7 Mar 2024 14:38:20 +0000 Subject: [PATCH 1/2] first cut table selection API --- vuu-ui/packages/vuu-data-types/index.d.ts | 8 +++ vuu-ui/packages/vuu-table-types/index.d.ts | 12 +++-- vuu-ui/packages/vuu-table/src/Row.tsx | 2 +- vuu-ui/packages/vuu-table/src/Table.tsx | 4 +- vuu-ui/packages/vuu-table/src/useSelection.ts | 2 +- vuu-ui/packages/vuu-table/src/useTable.ts | 9 ++-- vuu-ui/packages/vuu-utils/src/row-utils.ts | 33 ++++++++++-- .../CrossTableFiltering.examples.tsx | 53 ++++++++++++++----- .../src/examples/AppPatterns/index.ts | 1 + vuu-ui/showcase/src/examples/Apps/index.ts | 1 - vuu-ui/showcase/src/examples/index.ts | 1 + 11 files changed, 99 insertions(+), 27 deletions(-) rename vuu-ui/showcase/src/examples/{Apps => AppPatterns}/CrossTableFiltering.examples.tsx (82%) create mode 100644 vuu-ui/showcase/src/examples/AppPatterns/index.ts diff --git a/vuu-ui/packages/vuu-data-types/index.d.ts b/vuu-ui/packages/vuu-data-types/index.d.ts index 5015af7c8..d340286db 100644 --- a/vuu-ui/packages/vuu-data-types/index.d.ts +++ b/vuu-ui/packages/vuu-data-types/index.d.ts @@ -62,6 +62,14 @@ export type DataSourceRow = [ ...VuuRowDataItemType[] ]; +export type DataSourceRowObject = { + index: number; + key: string; + isGroupRow: boolean; + isSelected: boolean; + data: VuuDataRowDto; +}; + export type DataSourceRowPredicate = (row: DataSourceRow) => boolean; export interface ContextMenuItemBase { diff --git a/vuu-ui/packages/vuu-table-types/index.d.ts b/vuu-ui/packages/vuu-table-types/index.d.ts index ca136e6e3..0c90ccffe 100644 --- a/vuu-ui/packages/vuu-table-types/index.d.ts +++ b/vuu-ui/packages/vuu-table-types/index.d.ts @@ -6,10 +6,9 @@ import type { VuuSortType, VuuTable, } from "@finos/vuu-protocol-types"; -import type { VuuDataRow } from "@finos/vuu-protocol-types"; import type { ClientSideValidationChecker } from "@finos/vuu-ui-controls"; import type { DateTimePattern } from "@finos/vuu-utils"; -import { DataSourceRow } from "@finos/vuu-data-types"; +import { DataSourceRow, DataSourceRowObject } from "@finos/vuu-data-types"; import type { FunctionComponent, MouseEvent } from "react"; import type { HTMLAttributes } from "react"; @@ -45,9 +44,16 @@ export type DataItemCommitHandler< T extends VuuRowDataItemType = VuuRowDataItemType > = (value: T) => CommitResponse; -export type TableRowClickHandler = (row: VuuDataRow) => void; +/** + * Fired when user clicks a row, returning the row object (DataSourceRowObject) + */ +export type TableRowClickHandler = ( + evt: MouseEvent, + row: DataSourceRowObject +) => void; export type RowClickHandler = ( + evt: MouseEvent, row: DataSourceRow, rangeSelect: boolean, keepExistingSelection: boolean diff --git a/vuu-ui/packages/vuu-table/src/Row.tsx b/vuu-ui/packages/vuu-table/src/Row.tsx index aa8a22117..e7bc09c5b 100644 --- a/vuu-ui/packages/vuu-table/src/Row.tsx +++ b/vuu-ui/packages/vuu-table/src/Row.tsx @@ -89,7 +89,7 @@ export const Row = memo( (evt: MouseEvent) => { const rangeSelect = evt.shiftKey; const keepExistingSelection = evt.ctrlKey || evt.metaKey; /* mac only */ - onClick?.(row, rangeSelect, keepExistingSelection); + onClick?.(evt, row, rangeSelect, keepExistingSelection); }, [onClick, row] ); diff --git a/vuu-ui/packages/vuu-table/src/Table.tsx b/vuu-ui/packages/vuu-table/src/Table.tsx index 8510b9cbc..962e31357 100644 --- a/vuu-ui/packages/vuu-table/src/Table.tsx +++ b/vuu-ui/packages/vuu-table/src/Table.tsx @@ -1,6 +1,7 @@ import { DataSource, DataSourceRow, + DataSourceRowObject, SchemaColumn, SelectionChangeHandler, VuuFeatureInvocationMessage, @@ -44,8 +45,7 @@ const classBase = "vuuTable"; const { IDX, RENDER_IDX } = metadataKeys; -// TODO implement a Model object to represent a row data for better API -export type TableRowSelectHandler = (row: DataSourceRow) => void; +export type TableRowSelectHandler = (row: DataSourceRowObject) => void; export type TableNavigationStyle = "none" | "cell" | "row"; export interface TableProps diff --git a/vuu-ui/packages/vuu-table/src/useSelection.ts b/vuu-ui/packages/vuu-table/src/useSelection.ts index 658d2e81e..c2047f740 100644 --- a/vuu-ui/packages/vuu-table/src/useSelection.ts +++ b/vuu-ui/packages/vuu-table/src/useSelection.ts @@ -50,7 +50,7 @@ export const useSelection = ({ ); const handleRowClick = useCallback( - (row, rangeSelect, keepExistingSelection) => { + (evt, row, rangeSelect, keepExistingSelection) => { const { [IDX]: idx } = row; const { current: active } = lastActiveRef; const { current: selected } = selectedRef; diff --git a/vuu-ui/packages/vuu-table/src/useTable.ts b/vuu-ui/packages/vuu-table/src/useTable.ts index aa083e69a..b1f6db8b1 100644 --- a/vuu-ui/packages/vuu-table/src/useTable.ts +++ b/vuu-ui/packages/vuu-table/src/useTable.ts @@ -22,6 +22,7 @@ import { } from "@finos/vuu-ui-controls"; import { applySort, + asDataSourceRowObject, buildColumnMap, getIndexFromRowElement, isGroupColumn, @@ -581,11 +582,11 @@ export const useTable = ({ ); const handleRowClick = useCallback( - (row, rangeSelect, keepExistingSelection) => { - selectionHookOnRowClick(row, rangeSelect, keepExistingSelection); - onRowClickProp?.(row); + (evt, row, rangeSelect, keepExistingSelection) => { + selectionHookOnRowClick(evt, row, rangeSelect, keepExistingSelection); + onRowClickProp?.(evt, asDataSourceRowObject(row, columnMap)); }, - [onRowClickProp, selectionHookOnRowClick] + [columnMap, onRowClickProp, selectionHookOnRowClick] ); const onMoveColumn = useCallback( diff --git a/vuu-ui/packages/vuu-utils/src/row-utils.ts b/vuu-ui/packages/vuu-utils/src/row-utils.ts index 3191c0495..d7dcfc69c 100644 --- a/vuu-ui/packages/vuu-utils/src/row-utils.ts +++ b/vuu-ui/packages/vuu-utils/src/row-utils.ts @@ -1,9 +1,9 @@ //TODO this all probably belongs in vuu-table -import type { DataSourceRow } from "@finos/vuu-data-types"; +import type { DataSourceRow, DataSourceRowObject } from "@finos/vuu-data-types"; import type { MutableRefObject } from "react"; -import { metadataKeys } from "./column-utils"; +import { ColumnMap, metadataKeys } from "./column-utils"; -const { IDX } = metadataKeys; +const { IS_LEAF, KEY, IDX, SELECTED } = metadataKeys; export type RowOffsetFunc = ( row: DataSourceRow, @@ -90,3 +90,30 @@ export const getIndexFromRowElement = (rowElement: HTMLElement) => { ); } }; + +export const asDataSourceRowObject = ( + row: DataSourceRow, + columnMap: ColumnMap +): DataSourceRowObject => { + console.log({ columnMap }); + const { + [IS_LEAF]: isLeaf, + [KEY]: key, + [IDX]: index, + [SELECTED]: selected, + } = row; + + const rowObject: DataSourceRowObject = { + key, + index, + isGroupRow: !isLeaf, + isSelected: selected > 0, + data: {}, + }; + + for (const [colName, colIdx] of Object.entries(columnMap)) { + rowObject.data[colName] = row[colIdx]; + } + + return rowObject; +}; diff --git a/vuu-ui/showcase/src/examples/Apps/CrossTableFiltering.examples.tsx b/vuu-ui/showcase/src/examples/AppPatterns/CrossTableFiltering.examples.tsx similarity index 82% rename from vuu-ui/showcase/src/examples/Apps/CrossTableFiltering.examples.tsx rename to vuu-ui/showcase/src/examples/AppPatterns/CrossTableFiltering.examples.tsx index a47ed48bb..c0dfd0bf6 100644 --- a/vuu-ui/showcase/src/examples/Apps/CrossTableFiltering.examples.tsx +++ b/vuu-ui/showcase/src/examples/AppPatterns/CrossTableFiltering.examples.tsx @@ -2,14 +2,14 @@ import { Table as DataTable, TickingArrayDataSource, } from "@finos/vuu-data-test"; -import { TableSchema } from "@finos/vuu-data-types"; +import { SelectionChangeHandler, TableSchema } from "@finos/vuu-data-types"; import { FlexboxLayout, LayoutProvider, StackLayout, View, } from "@finos/vuu-layout"; -import { Table } from "@finos/vuu-table"; +import { Table, TableRowSelectHandler } from "@finos/vuu-table"; import { TableConfig, TableRowClickHandler } from "@finos/vuu-table-types"; import { buildColumnMap } from "@finos/vuu-utils"; import { useCallback, useMemo } from "react"; @@ -82,7 +82,10 @@ const parentTable = new DataTable( const childTable = new DataTable( ChildTableSchema, [ - ["child-001", "row 1","1 val 2","1 val 3","1 val 4","1 val 5", "parent-001"], + ["child-001.1", "row 1","1 val 2","1 val 3","1 val 4","1 val 5", "parent-001"], + ["child-001.2", "row 1","1 val 2","1 val 3","1 val 4","1 val 5", "parent-001"], + ["child-001.3", "row 1","1 val 2","1 val 3","1 val 4","1 val 5", "parent-001"], + ["child-001.4", "row 1","1 val 2","1 val 3","1 val 4","1 val 5", "parent-001"], ["child-002", "row 2","1 val 2","1 val 3","1 val 4","1 val 5", "parent-002"], ["child-003", "row 3","1 val 2","1 val 3","1 val 4","1 val 5", "parent-003"], ["child-004", "row 4","1 val 2","1 val 3","1 val 4","1 val 5", "parent-004"], @@ -98,7 +101,7 @@ const childTable = new DataTable( const grandchildTable = new DataTable( ChildTableSchema, [ - ["grandchild-001", "row 1","1 val 2","1 val 3","1 val 4","1 val 5", "child-001"], + ["grandchild-001", "row 1","1 val 2","1 val 3","1 val 4","1 val 5", "child-001.1"], ["grandchild-002", "row 2","1 val 2","1 val 3","1 val 4","1 val 5", "child-002"], ["grandchild-003", "row 3","1 val 2","1 val 3","1 val 4","1 val 5", "child-003"], ["grandchild-004", "row 4","1 val 2","1 val 3","1 val 4","1 val 5", "child-004"], @@ -129,6 +132,12 @@ export const SimpleCrossTableFiltering = () => { [] ); + const dataSourceAll = useMemo(() => { + return new TickingArrayDataSource({ + columnDescriptors: ParentTableSchema.columns, + table: parentTable, + }); + }, []); const dataSource1 = useMemo(() => { return new TickingArrayDataSource({ columnDescriptors: ParentTableSchema.columns, @@ -180,21 +189,30 @@ export const SimpleCrossTableFiltering = () => { }, []); const handleParentRowClick = useCallback( - (row) => { - const map = buildColumnMap(dataSource1.columns); - const parentId = row[map.id]; + (_evt, row) => { + console.log({ rowClick: row }); + const parentId = row.data.id; dataSource4.filter = { filter: `parentId = "${parentId}"` }; }, - [dataSource1.columns, dataSource4] + [dataSource4] + ); + + const handleParentRowSelect = useCallback((row) => { + console.log({ rowSelect: row }); + }, []); + const handleParentRowSelectionChange = useCallback( + (selection) => { + console.log({ selection }); + }, + [] ); const handleChildRowClick = useCallback( - (row) => { - const map = buildColumnMap(dataSource4.columns); - const parentId = row[map.id]; + (_evt, row) => { + const parentId = row.data.id; dataSource5.filter = { filter: `parentId = "${parentId}"` }; }, - [dataSource4.columns, dataSource5] + [dataSource5] ); return ( @@ -208,11 +226,22 @@ export const SimpleCrossTableFiltering = () => { }} > + + +
diff --git a/vuu-ui/showcase/src/examples/AppPatterns/index.ts b/vuu-ui/showcase/src/examples/AppPatterns/index.ts new file mode 100644 index 000000000..fbf73c38d --- /dev/null +++ b/vuu-ui/showcase/src/examples/AppPatterns/index.ts @@ -0,0 +1 @@ +export * from "./CrossTableFiltering.examples"; diff --git a/vuu-ui/showcase/src/examples/Apps/index.ts b/vuu-ui/showcase/src/examples/Apps/index.ts index a7aca8920..1effbe1f8 100644 --- a/vuu-ui/showcase/src/examples/Apps/index.ts +++ b/vuu-ui/showcase/src/examples/Apps/index.ts @@ -1,2 +1 @@ export * from "./NewTheme.examples"; -export * from "./CrossTableFiltering.examples"; diff --git a/vuu-ui/showcase/src/examples/index.ts b/vuu-ui/showcase/src/examples/index.ts index 24e406a24..4dd26eb21 100644 --- a/vuu-ui/showcase/src/examples/index.ts +++ b/vuu-ui/showcase/src/examples/index.ts @@ -1,3 +1,4 @@ +export * as AppPatterns from "./AppPatterns"; export * as Apps from "./Apps"; export * as TableExtras from "./TableExtras"; export * as DataTable from "./DataTable"; From 8dad78e3a69cf7bb09a3e937a72dd7920a3f5d11 Mon Sep 17 00:00:00 2001 From: heswell Date: Sun, 17 Mar 2024 14:14:03 +0000 Subject: [PATCH 2/2] update all types for table selection --- vuu-ui/packages/vuu-table-types/index.d.ts | 5 +++- vuu-ui/packages/vuu-table/src/Row.tsx | 4 +-- vuu-ui/packages/vuu-table/src/Table.tsx | 4 +-- vuu-ui/packages/vuu-table/src/useSelection.ts | 16 +++++----- vuu-ui/packages/vuu-table/src/useTable.ts | 30 ++++++++++++------- .../instrument-picker/InstrumentPicker.tsx | 10 +++---- .../instrument-picker/useInstrumentPicker.ts | 24 ++++++--------- .../src/basket-selector/BasketSelectorRow.tsx | 2 +- .../src/basket-selector/useBasketSelector.ts | 12 ++------ .../src/new-basket-panel/NewBasketPanel.tsx | 10 ++++--- .../src/new-basket-panel/useNewBasketPanel.ts | 17 +++++------ .../CrossTableFiltering.examples.tsx | 10 +++++-- .../UiControls/InstrumentPicker.examples.tsx | 28 +++++++++-------- 13 files changed, 90 insertions(+), 82 deletions(-) diff --git a/vuu-ui/packages/vuu-table-types/index.d.ts b/vuu-ui/packages/vuu-table-types/index.d.ts index 0c90ccffe..bdec94020 100644 --- a/vuu-ui/packages/vuu-table-types/index.d.ts +++ b/vuu-ui/packages/vuu-table-types/index.d.ts @@ -44,6 +44,9 @@ export type DataItemCommitHandler< T extends VuuRowDataItemType = VuuRowDataItemType > = (value: T) => CommitResponse; +export type TableRowSelectHandler = (row: DataSourceRowObject | null) => void; +export type TableRowSelectHandlerInternal = (row: DataSourceRow | null) => void; + /** * Fired when user clicks a row, returning the row object (DataSourceRowObject) */ @@ -52,7 +55,7 @@ export type TableRowClickHandler = ( row: DataSourceRowObject ) => void; -export type RowClickHandler = ( +export type TableRowClickHandlerInternal = ( evt: MouseEvent, row: DataSourceRow, rangeSelect: boolean, diff --git a/vuu-ui/packages/vuu-table/src/Row.tsx b/vuu-ui/packages/vuu-table/src/Row.tsx index e7bc09c5b..abd23000e 100644 --- a/vuu-ui/packages/vuu-table/src/Row.tsx +++ b/vuu-ui/packages/vuu-table/src/Row.tsx @@ -2,7 +2,7 @@ import { DataSourceRow } from "@finos/vuu-data-types"; import { DataCellEditHandler, RuntimeColumnDescriptor, - RowClickHandler, + TableRowClickHandlerInternal, } from "@finos/vuu-table-types"; import { ColumnMap, @@ -34,7 +34,7 @@ export interface RowProps { highlighted?: boolean; row: DataSourceRow; offset: number; - onClick?: RowClickHandler; + onClick?: TableRowClickHandlerInternal; onDataEdited?: DataCellEditHandler; onToggleGroup?: (row: DataSourceRow, column: RuntimeColumnDescriptor) => void; style?: CSSProperties; diff --git a/vuu-ui/packages/vuu-table/src/Table.tsx b/vuu-ui/packages/vuu-table/src/Table.tsx index 962e31357..7c25aaf84 100644 --- a/vuu-ui/packages/vuu-table/src/Table.tsx +++ b/vuu-ui/packages/vuu-table/src/Table.tsx @@ -1,7 +1,5 @@ import { DataSource, - DataSourceRow, - DataSourceRowObject, SchemaColumn, SelectionChangeHandler, VuuFeatureInvocationMessage, @@ -11,6 +9,7 @@ import { TableConfig, TableConfigChangeHandler, TableRowClickHandler, + TableRowSelectHandler, TableSelectionModel, } from "@finos/vuu-table-types"; import { @@ -45,7 +44,6 @@ const classBase = "vuuTable"; const { IDX, RENDER_IDX } = metadataKeys; -export type TableRowSelectHandler = (row: DataSourceRowObject) => void; export type TableNavigationStyle = "none" | "cell" | "row"; export interface TableProps diff --git a/vuu-ui/packages/vuu-table/src/useSelection.ts b/vuu-ui/packages/vuu-table/src/useSelection.ts index c2047f740..dc6ed8363 100644 --- a/vuu-ui/packages/vuu-table/src/useSelection.ts +++ b/vuu-ui/packages/vuu-table/src/useSelection.ts @@ -1,4 +1,8 @@ -import { RowClickHandler, TableSelectionModel } from "@finos/vuu-table-types"; +import { + TableRowClickHandlerInternal, + TableRowSelectHandlerInternal, + TableSelectionModel, +} from "@finos/vuu-table-types"; import { deselectItem, dispatchMouseEvent, @@ -6,11 +10,7 @@ import { metadataKeys, selectItem, } from "@finos/vuu-utils"; -import { - DataSourceRow, - Selection, - SelectionChangeHandler, -} from "@finos/vuu-data-types"; +import { Selection, SelectionChangeHandler } from "@finos/vuu-data-types"; import { KeyboardEvent, KeyboardEventHandler, @@ -29,7 +29,7 @@ export interface SelectionHookProps { highlightedIndexRef: MutableRefObject; selectionKeys?: string[]; selectionModel: TableSelectionModel; - onSelect?: (row: DataSourceRow) => void; + onSelect?: TableRowSelectHandlerInternal; onSelectionChange: SelectionChangeHandler; } @@ -49,7 +49,7 @@ export const useSelection = ({ [selectionKeys] ); - const handleRowClick = useCallback( + const handleRowClick = useCallback( (evt, row, rangeSelect, keepExistingSelection) => { const { [IDX]: idx } = row; const { current: active } = lastActiveRef; diff --git a/vuu-ui/packages/vuu-table/src/useTable.ts b/vuu-ui/packages/vuu-table/src/useTable.ts index b1f6db8b1..b8ed11141 100644 --- a/vuu-ui/packages/vuu-table/src/useTable.ts +++ b/vuu-ui/packages/vuu-table/src/useTable.ts @@ -7,11 +7,12 @@ import { import { ColumnDescriptor, DataCellEditHandler, - RowClickHandler, + TableRowClickHandlerInternal, RuntimeColumnDescriptor, TableColumnResizeHandler, TableConfig, TableSelectionModel, + TableRowSelectHandlerInternal, } from "@finos/vuu-table-types"; import { VuuRange, VuuSortType } from "@finos/vuu-protocol-types"; import { @@ -558,16 +559,33 @@ export const useTable = ({ [dataSource, onSelectionChange] ); + const handleSelect = useCallback( + (row) => { + if (onSelect) { + onSelect(row === null ? null : asDataSourceRowObject(row, columnMap)); + } + }, + [columnMap, onSelect] + ); + const { onKeyDown: selectionHookKeyDown, onRowClick: selectionHookOnRowClick, } = useSelection({ highlightedIndexRef, - onSelect, + onSelect: handleSelect, onSelectionChange: handleSelectionChange, selectionModel, }); + const handleRowClick = useCallback( + (evt, row, rangeSelect, keepExistingSelection) => { + selectionHookOnRowClick(evt, row, rangeSelect, keepExistingSelection); + onRowClickProp?.(evt, asDataSourceRowObject(row, columnMap)); + }, + [columnMap, onRowClickProp, selectionHookOnRowClick] + ); + const handleKeyDown = useCallback( (e: KeyboardEvent) => { navigationKeyDown(e); @@ -581,14 +599,6 @@ export const useTable = ({ [navigationKeyDown, editingKeyDown, selectionHookKeyDown] ); - const handleRowClick = useCallback( - (evt, row, rangeSelect, keepExistingSelection) => { - selectionHookOnRowClick(evt, row, rangeSelect, keepExistingSelection); - onRowClickProp?.(evt, asDataSourceRowObject(row, columnMap)); - }, - [columnMap, onRowClickProp, selectionHookOnRowClick] - ); - const onMoveColumn = useCallback( (columns: ColumnDescriptor[]) => { const newTableConfig = { diff --git a/vuu-ui/packages/vuu-ui-controls/src/instrument-picker/InstrumentPicker.tsx b/vuu-ui/packages/vuu-ui-controls/src/instrument-picker/InstrumentPicker.tsx index 503cefc45..b598c255a 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/instrument-picker/InstrumentPicker.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/instrument-picker/InstrumentPicker.tsx @@ -1,5 +1,5 @@ -import { DataSourceRow, TableSchema } from "@finos/vuu-data-types"; -import { Table, TableProps, TableRowSelectHandler } from "@finos/vuu-table"; +import { DataSourceRowObject, TableSchema } from "@finos/vuu-data-types"; +import { Table, TableProps } from "@finos/vuu-table"; import { ColumnMap, useId } from "@finos/vuu-utils"; import { Input } from "@salt-ds/core"; import { ForwardedRef, forwardRef, HTMLAttributes, useMemo } from "react"; @@ -16,7 +16,8 @@ if (typeof SearchCell !== "function") { } export interface InstrumentPickerProps - extends Omit, "onSelect"> { + extends Omit, "onSelect">, + Pick { TableProps: Pick; columnMap: ColumnMap; disabled?: boolean; @@ -27,10 +28,9 @@ export interface InstrumentPickerProps * @param row DataSourceRow * @returns string */ - itemToString?: (row: DataSourceRow) => string; + itemToString?: (row: DataSourceRowObject) => string; onClose?: () => void; onOpenChange?: OpenChangeHandler; - onSelect: TableRowSelectHandler; schema: TableSchema; searchColumns: string[]; width?: number; diff --git a/vuu-ui/packages/vuu-ui-controls/src/instrument-picker/useInstrumentPicker.ts b/vuu-ui/packages/vuu-ui-controls/src/instrument-picker/useInstrumentPicker.ts index 309bc2508..d4dcf9737 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/instrument-picker/useInstrumentPicker.ts +++ b/vuu-ui/packages/vuu-ui-controls/src/instrument-picker/useInstrumentPicker.ts @@ -1,10 +1,9 @@ -import { DataSource, DataSourceRow } from "@finos/vuu-data-types"; -import { ColumnDescriptor } from "@finos/vuu-table-types"; +import { DataSource, DataSourceRowObject } from "@finos/vuu-data-types"; import { + ColumnDescriptor, TableRowSelectHandler, - useControlledTableNavigation, -} from "@finos/vuu-table"; -import { ColumnMap } from "@finos/vuu-utils"; +} from "@finos/vuu-table-types"; +import { useControlledTableNavigation } from "@finos/vuu-table"; import { ChangeEvent, useCallback, useMemo, useState } from "react"; import { useControlled } from "../common-hooks"; import { OpenChangeHandler } from "../dropdown"; @@ -21,19 +20,14 @@ export interface InstrumentPickerHookProps isOpen?: boolean; } -const defaultItemToString = - (columns: ColumnDescriptor[], columnMap: ColumnMap) => - (row: DataSourceRow) => { - return columns.map(({ name }) => row[columnMap[name]]).join(" "); - }; +const defaultItemToString = (row: DataSourceRowObject) => + Object.values(row.data).join(" "); export const useInstrumentPicker = ({ - columnMap, - columns, dataSource, defaultIsOpen, isOpen: isOpenProp, - itemToString = defaultItemToString(columns, columnMap), + itemToString = defaultItemToString, onOpenChange, onSelect, searchColumns, @@ -85,9 +79,9 @@ export const useInstrumentPicker = ({ const handleSelectRow = useCallback( (row) => { - const value = itemToString(row); + const value = row === null ? "" : itemToString(row); setValue(value); - onSelect(row); + onSelect?.(row); handleOpenChange?.(false, "select"); }, [handleOpenChange, itemToString, onSelect] diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/BasketSelectorRow.tsx b/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/BasketSelectorRow.tsx index edfc2189d..e3a2dcbf0 100644 --- a/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/BasketSelectorRow.tsx +++ b/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/BasketSelectorRow.tsx @@ -30,7 +30,7 @@ export const BasketSelectorRow = ({ (evt: MouseEvent) => { const rangeSelect = evt.shiftKey; const keepExistingSelection = evt.ctrlKey || evt.metaKey; /* mac only */ - onClick?.(row, rangeSelect, keepExistingSelection); + onClick?.(evt, row, rangeSelect, keepExistingSelection); }, [onClick, row] ); diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/useBasketSelector.ts b/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/useBasketSelector.ts index f46d1d529..1a92cdd66 100644 --- a/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/useBasketSelector.ts +++ b/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/useBasketSelector.ts @@ -1,7 +1,6 @@ import { TableRowClickHandler } from "@finos/vuu-table-types"; import { TableProps } from "@finos/vuu-table"; import { OpenChangeHandler, useControlled } from "@finos/vuu-ui-controls"; -import { buildColumnMap } from "@finos/vuu-utils"; import { useCallback, useMemo, useRef } from "react"; import { BasketSelectorProps } from "./BasketSelector"; import { BasketSelectorRow } from "./BasketSelectorRow"; @@ -33,11 +32,6 @@ export const useBasketSelector = ({ name: "useDropdownList", }); - const columnMap = useMemo( - () => buildColumnMap(dataSourceBasketTradingSearch.columns), - [dataSourceBasketTradingSearch.columns] - ); - const handleOpenChange = useCallback( (open, closeReason) => { setIsOpen(open); @@ -55,12 +49,12 @@ export const useBasketSelector = ({ ); const handleRowClick = useCallback( - (row) => { - const instanceId = row[columnMap.instanceId] as string; + (_evt, row) => { + const instanceId = row.data.instanceId as string; handleOpenChange(false, "select"); onSelectBasket?.(instanceId); }, - [columnMap.instanceId, handleOpenChange, onSelectBasket] + [handleOpenChange, onSelectBasket] ); const handleClickAddBasket = useCallback(() => { diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/new-basket-panel/NewBasketPanel.tsx b/vuu-ui/sample-apps/feature-basket-trading/src/new-basket-panel/NewBasketPanel.tsx index 7db552648..07ae2dc98 100644 --- a/vuu-ui/sample-apps/feature-basket-trading/src/new-basket-panel/NewBasketPanel.tsx +++ b/vuu-ui/sample-apps/feature-basket-trading/src/new-basket-panel/NewBasketPanel.tsx @@ -1,4 +1,8 @@ -import { DataSource, DataSourceRow, TableSchema } from "@finos/vuu-data-types"; +import { + DataSource, + DataSourceRowObject, + TableSchema, +} from "@finos/vuu-data-types"; import { DialogHeader, PopupComponent as Popup, @@ -18,8 +22,6 @@ import "./NewBasketPanel.css"; const classBase = "vuuBasketNewBasketPanel"; -const displayName = (key: number) => (row: DataSourceRow) => String(row[key]); - export type BasketCreatedHandler = ( basketName: string, basketId: string, @@ -74,7 +76,7 @@ export const NewBasketPanel = ({ [basketDataSource] ); - const itemToString = displayName(columnMap.name); + const itemToString = (row: DataSourceRowObject) => row.data.name as string; const inputCallbackRef = useCallback>((el) => { setTimeout(() => { diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/new-basket-panel/useNewBasketPanel.ts b/vuu-ui/sample-apps/feature-basket-trading/src/new-basket-panel/useNewBasketPanel.ts index 9c5dcb5c6..e332fce7b 100644 --- a/vuu-ui/sample-apps/feature-basket-trading/src/new-basket-panel/useNewBasketPanel.ts +++ b/vuu-ui/sample-apps/feature-basket-trading/src/new-basket-panel/useNewBasketPanel.ts @@ -1,12 +1,10 @@ import { ViewportRpcResponse } from "@finos/vuu-data-types"; -import { TableRowSelectHandler } from "@finos/vuu-table"; import { Commithandler, OpenChangeHandler } from "@finos/vuu-ui-controls"; -import { buildColumnMap, metadataKeys } from "@finos/vuu-utils"; +import { buildColumnMap } from "@finos/vuu-utils"; +import { TableRowSelectHandler } from "packages/vuu-table-types"; import { useCallback, useRef, useState } from "react"; import { NewBasketPanelProps } from "./NewBasketPanel"; -const { KEY } = metadataKeys; - export type NewBasketHookProps = Pick< NewBasketPanelProps, "basketDataSource" | "basketSchema" | "onBasketCreated" @@ -47,11 +45,12 @@ export const useNewBasketPanel = ({ }, [basketDataSource, basketId, basketName, onBasketCreated]); const handleSelectBasket = useCallback((row) => { - const basketId = row[KEY] as string; - setBasketId(basketId); - setTimeout(() => { - saveButtonRef.current?.focus(); - }, 60); + if (row) { + setBasketId(row.key); + setTimeout(() => { + saveButtonRef.current?.focus(); + }, 60); + } }, []); const handleChangeBasketName = useCallback>( diff --git a/vuu-ui/showcase/src/examples/AppPatterns/CrossTableFiltering.examples.tsx b/vuu-ui/showcase/src/examples/AppPatterns/CrossTableFiltering.examples.tsx index c0dfd0bf6..2c1a8fc2b 100644 --- a/vuu-ui/showcase/src/examples/AppPatterns/CrossTableFiltering.examples.tsx +++ b/vuu-ui/showcase/src/examples/AppPatterns/CrossTableFiltering.examples.tsx @@ -9,9 +9,12 @@ import { StackLayout, View, } from "@finos/vuu-layout"; -import { Table, TableRowSelectHandler } from "@finos/vuu-table"; -import { TableConfig, TableRowClickHandler } from "@finos/vuu-table-types"; -import { buildColumnMap } from "@finos/vuu-utils"; +import { Table } from "@finos/vuu-table"; +import { + TableConfig, + TableRowClickHandler, + TableRowSelectHandler, +} from "@finos/vuu-table-types"; import { useCallback, useMemo } from "react"; let displaySequence = 1; @@ -200,6 +203,7 @@ export const SimpleCrossTableFiltering = () => { const handleParentRowSelect = useCallback((row) => { console.log({ rowSelect: row }); }, []); + const handleParentRowSelectionChange = useCallback( (selection) => { console.log({ selection }); diff --git a/vuu-ui/showcase/src/examples/UiControls/InstrumentPicker.examples.tsx b/vuu-ui/showcase/src/examples/UiControls/InstrumentPicker.examples.tsx index a9b43dad1..70eee410f 100644 --- a/vuu-ui/showcase/src/examples/UiControls/InstrumentPicker.examples.tsx +++ b/vuu-ui/showcase/src/examples/UiControls/InstrumentPicker.examples.tsx @@ -4,9 +4,12 @@ import { SimulTableName, vuuModule, } from "@finos/vuu-data-test"; -import type { DataSourceRow } from "@finos/vuu-data-types"; -import type { TableProps, TableRowSelectHandler } from "@finos/vuu-table"; -import type { ColumnDescriptor } from "@finos/vuu-table-types"; +import type { DataSourceRowObject } from "@finos/vuu-data-types"; +import type { TableProps } from "@finos/vuu-table"; +import type { + ColumnDescriptor, + TableRowSelectHandler, +} from "@finos/vuu-table-types"; import { InstrumentPicker } from "@finos/vuu-ui-controls"; import { buildColumnMap, ColumnMap } from "@finos/vuu-utils"; import { useCallback, useMemo } from "react"; @@ -36,15 +39,14 @@ export const DefaultInstrumentPicker = () => { ]; }, [schema.columns]); - const itemToString = useCallback( - (row: DataSourceRow) => { - return String([row[columnMap.description]]); - }, - [columnMap.description] - ); + const itemToString = useCallback((row: DataSourceRowObject) => { + return String(row.data.description); + }, []); - const handleSelect = useCallback((index) => { - console.log(`row selected ${index}`); + const handleSelect = useCallback((row) => { + if (row) { + console.log(`row selected ${row.key}`); + } }, []); return ( @@ -91,7 +93,9 @@ export const InstrumentPickerVuuInstruments = () => { ); const handleSelect = useCallback((row) => { - console.log(`row selected ${row.join(",")}`); + if (row) { + console.log(`row selected ${Object.values(row.data).join(",")}`); + } }, []); if (error) {