Skip to content

Commit

Permalink
Instrument picker (finos#923)
Browse files Browse the repository at this point in the history
* make instrument-picker more generic

* refactor Table navigation, preparing for row highlighting

* fix broken import paths

* add empty inlined worker as vitext mocj fails otherwise
  • Loading branch information
heswell authored and pling-scottlogic committed Oct 24, 2023
1 parent 6490a65 commit 7303e99
Show file tree
Hide file tree
Showing 22 changed files with 264 additions and 77 deletions.
2 changes: 1 addition & 1 deletion vuu-ui/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1 @@
inlined-worker.js
# inlined-worker.js
1 change: 1 addition & 0 deletions vuu-ui/packages/vuu-data/src/inlined-worker.js
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const workerSourceCode = "";
1 change: 1 addition & 0 deletions vuu-ui/packages/vuu-datagrid-types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export interface TableAttributes {
columnDefaultWidth?: number;
columnFormatHeader?: "capitalize" | "uppercase";
columnSeparators?: boolean;
showHighlightedRow?: boolean;
rowSeparators?: boolean;
zebraStripes?: boolean;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
} from "@finos/vuu-utils";
import { getIndexOfEditedItem } from "./toolbar-dom-utils";
import { NavigationOutOfBoundsHandler } from "./Toolbar";
import { PopupCloseCallback } from "packages/vuu-popups/src";
import { PopupCloseCallback } from "@finos/vuu-popups";

type directionType = "bwd" | "fwd" | "start" | "end";
type directionMap = { [key: string]: directionType };
Expand Down
2 changes: 1 addition & 1 deletion vuu-ui/packages/vuu-layout/src/toolbar/useToolbar.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { OverflowItem, ToolbarProps } from "@finos/vuu-layout";
import { isValidNumber } from "@finos/vuu-utils";
import { PopupCloseCallback } from "packages/vuu-popups/src";
import { PopupCloseCallback } from "@finos/vuu-popups";
import {
KeyboardEvent,
MouseEvent as ReactMouseEvent,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ColumnDescriptor } from "packages/vuu-datagrid-types";
import { ColumnDescriptor } from "@finos/vuu-datagrid-types";
import cx from "classnames";

import {
Expand Down
4 changes: 4 additions & 0 deletions vuu-ui/packages/vuu-table/src/table-next/TableNext.css
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
--row-borderColor: var(--salt-separable-tertiary-borderColor);
}

.vuuTableNext-highlight .vuuTableNextRow:hover {
background-color: var(--vuu-color-pink-10-fade-20);
}

.vuuTableNext-scrollbarContainer {
--scroll-content-width: 1100px;
border-bottom: none !important;
Expand Down
3 changes: 3 additions & 0 deletions vuu-ui/packages/vuu-table/src/table-next/TableNext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export const TableNext = forwardRef(function TableNext(
config,
dataSource,
id: idProp,
navigationStyle = "cell",
onAvailableColumnsChange,
onConfigChange,
onFeatureEnabled,
Expand Down Expand Up @@ -69,6 +70,7 @@ export const TableNext = forwardRef(function TableNext(
containerRef,
dataSource,
headerHeight,
navigationStyle,
onAvailableColumnsChange,
onConfigChange,
onFeatureEnabled,
Expand Down Expand Up @@ -98,6 +100,7 @@ export const TableNext = forwardRef(function TableNext(
const className = cx(classBase, classNameProp, {
[`${classBase}-colLines`]: tableAttributes.columnSeparators,
[`${classBase}-rowLines`]: tableAttributes.rowSeparators,
[`${classBase}-highlight`]: tableAttributes.showHighlightedRow,
[`${classBase}-zebra`]: tableAttributes.zebraStripes,
// [`${classBase}-loading`]: isDataLoading(tableProps.columns),
});
Expand Down
31 changes: 22 additions & 9 deletions vuu-ui/packages/vuu-table/src/table-next/useKeyboardNavigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,33 @@ import {
getTableCell,
headerCellQuery,
} from "./table-dom-utils";
import { TableNavigationStyle } from "../table/dataTableTypes";

const navigationKeys = new Set<NavigationKey>([
const rowNavigationKeys = new Set<NavigationKey>([
"Home",
"End",
"PageUp",
"PageDown",
"ArrowDown",
"ArrowLeft",
"ArrowRight",
"ArrowUp",
]);

export const isNavigationKey = (key: string): key is NavigationKey => {
return navigationKeys.has(key as NavigationKey);
const cellNavigationKeys = new Set(rowNavigationKeys);
cellNavigationKeys.add("ArrowLeft");
cellNavigationKeys.add("ArrowRight");

export const isNavigationKey = (
key: string,
navigationStyle: TableNavigationStyle
): key is NavigationKey => {
switch (navigationStyle) {
case "cell":
return cellNavigationKeys.has(key as NavigationKey);
case "row":
return rowNavigationKeys.has(key as NavigationKey);
default:
return false;
}
};

type ArrowKey = "ArrowUp" | "ArrowDown" | "ArrowLeft" | "ArrowRight";
Expand Down Expand Up @@ -114,6 +127,7 @@ export interface NavigationHookProps {
columnCount?: number;
disableHighlightOnFocus?: boolean;
label?: string;
navigationStyle: TableNavigationStyle;
viewportRange: VuuRange;
requestScroll?: ScrollRequestHandler;
restoreLastFocus?: boolean;
Expand All @@ -126,6 +140,7 @@ export const useKeyboardNavigation = ({
columnCount = 0,
containerRef,
disableHighlightOnFocus,
navigationStyle,
requestScroll,
rowCount = 0,
viewportRowCount,
Expand Down Expand Up @@ -233,7 +248,6 @@ NavigationHookProps) => {
// click handler.
const focusedCell = getFocusedCell(document.activeElement);
if (focusedCell) {
console.log({ focusedCell });
focusedCellPos.current = getTableCellPos(focusedCell);
}
}
Expand All @@ -242,7 +256,6 @@ NavigationHookProps) => {

const navigateChildItems = useCallback(
async (key: NavigationKey) => {
console.log(`navigate child items ${key}`);
const [nextRowIdx, nextColIdx] = isPagingKey(key)
? await nextPageItemIdx(key, activeCellPos.current)
: nextCellPos(key, activeCellPos.current, columnCount, rowCount);
Expand All @@ -258,13 +271,13 @@ NavigationHookProps) => {

const handleKeyDown = useCallback(
(e: KeyboardEvent) => {
if (rowCount > 0 && isNavigationKey(e.key)) {
if (rowCount > 0 && isNavigationKey(e.key, navigationStyle)) {
e.preventDefault();
e.stopPropagation();
void navigateChildItems(e.key);
}
},
[rowCount, navigateChildItems]
[rowCount, navigationStyle, navigateChildItems]
);

const handleClick = useCallback(
Expand Down
3 changes: 3 additions & 0 deletions vuu-ui/packages/vuu-table/src/table-next/useTableNext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ export interface TableHookProps
| "availableColumns"
| "config"
| "dataSource"
| "navigationStyle"
| "onAvailableColumnsChange"
| "onConfigChange"
| "onFeatureEnabled"
Expand Down Expand Up @@ -98,6 +99,7 @@ export const useTable = ({
containerRef,
dataSource,
headerHeight = 25,
navigationStyle,
onAvailableColumnsChange,
onConfigChange,
onFeatureEnabled,
Expand Down Expand Up @@ -408,6 +410,7 @@ export const useTable = ({
} = useKeyboardNavigation({
columnCount: columns.filter((c) => c.hidden !== true).length,
containerRef,
navigationStyle,
requestScroll,
rowCount: dataSource?.size,
viewportRange: range,
Expand Down
7 changes: 7 additions & 0 deletions vuu-ui/packages/vuu-table/src/table/dataTableTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ export type TableRowClickHandler = (row: VuuDataRow) => void;
// TODO implement a Model object to represent a row data for better API
export type TableRowSelectHandler = (row: DataSourceRow) => void;

export type TableNavigationStyle = "none" | "cell" | "row";

export interface TableProps
extends Omit<HTMLAttributes<HTMLDivElement>, "onSelect"> {
Row?: FC<RowProps>;
Expand All @@ -32,6 +34,11 @@ export interface TableProps
dataSource: DataSource;
headerHeight?: number;
height?: number;
/**
* Defined how focus navigation within data cells will be handled by table.
* Default is cell.
*/
navigationStyle?: TableNavigationStyle;
/**
* required if a fully featured column picker is to be available.
* Available columns can be changed by the addition or removal of
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
import { FocusEvent, KeyboardEvent, RefObject } from "react";
import { CollectionItem } from "./collectionTypes";

export interface NavigationProps<Item = unknown> {
export interface NavigationProps {
cycleFocus?: boolean;
defaultHighlightedIndex?: number;
disableHighlightOnFocus?: boolean;
focusOnHighlight?: boolean;
focusVisible?: number;
highlightedIndex?: number;
indexPositions: CollectionItem<Item>[];
itemCount: number;
onHighlight?: (idx: number) => void;
onKeyboardNavigation?: (evt: KeyboardEvent, idx: number) => void;
restoreLastFocus?: boolean;
viewportItemCount: number;
}

export interface NavigationHookProps<Item> extends NavigationProps<Item> {
export interface NavigationHookProps extends NavigationProps {
containerRef: RefObject<HTMLElement>;
label?: string;
selected?: string[];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { TableSchema } from "@finos/vuu-data";
import { DataSourceRow } from "@finos/vuu-data-types";
import { useId } from "@finos/vuu-layout";
import { TableNext, TableProps, TableRowSelectHandler } from "@finos/vuu-table";
import { ColumnMap } from "@finos/vuu-utils";
Expand All @@ -17,6 +18,14 @@ export interface InstrumentPickerProps
TableProps: Pick<TableProps, "config" | "dataSource">;
columnMap: ColumnMap;
disabled?: boolean;
/**
* Used to form the display value to render in input following selection. If
* not provided, default will be the values from rendered columns.
*
* @param row DataSourceRow
* @returns string
*/
itemToString?: (row: DataSourceRow) => string;
onSelect: TableRowSelectHandler;
schema: TableSchema;
searchColumns: string[];
Expand All @@ -30,6 +39,7 @@ export const InstrumentPicker = forwardRef(function InstrumentPicker(
columnMap,
disabled,
id: idProp,
itemToString,
onSelect,
schema,
searchColumns,
Expand All @@ -47,7 +57,16 @@ export const InstrumentPicker = forwardRef(function InstrumentPicker(
onOpenChange,
tableHandlers,
value,
} = useInstrumentPicker({ columnMap, dataSource, onSelect, searchColumns });
} = useInstrumentPicker({
columnMap,
columns: TableProps.config.columns,
dataSource,
itemToString,
onSelect,
searchColumns,
});

console.log({ value });

const endAdornment = useMemo(() => <span data-icon="chevron-down" />, []);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,36 @@
import { DataSource } from "@finos/vuu-data";
import { DataSourceRow } from "@finos/vuu-data-types";
import { ColumnDescriptor } from "@finos/vuu-datagrid-types";
import { TableRowSelectHandler } from "@finos/vuu-table";
import { ColumnMap } from "@finos/vuu-utils";
import { ChangeEvent, useCallback, useMemo, useState } from "react";
import { useControlled } from "../common-hooks";
import { InstrumentPickerProps } from "./InstrumentPicker";

export interface InstrumentPickerHookProps {
columnMap: ColumnMap;
export interface InstrumentPickerHookProps
extends Pick<
InstrumentPickerProps,
"columnMap" | "itemToString" | "onSelect" | "searchColumns"
> {
columns: ColumnDescriptor[];
dataSource: DataSource;
defaultIsOpen?: boolean;
isOpen?: boolean;
onSelect: TableRowSelectHandler;
searchColumns: string[];
}

const defaultItemToString =
(columns: ColumnDescriptor[], columnMap: ColumnMap) =>
(row: DataSourceRow) => {
return columns.map(({ name }) => row[columnMap[name]]).join(" ");
};

export const useInstrumentPicker = ({
columnMap,
columns,
dataSource,
defaultIsOpen,
isOpen: isOpenProp,
itemToString = defaultItemToString(columns, columnMap),
onSelect,
searchColumns,
}: InstrumentPickerHookProps) => {
Expand Down Expand Up @@ -65,13 +78,12 @@ export const useInstrumentPicker = ({

const handleSelectRow = useCallback<TableRowSelectHandler>(
(row) => {
const { name } = columnMap;
const { [name]: value } = row;
setValue(value as string);
const value = itemToString(row);
setValue(value);
setIsOpen(false);
onSelect(row);
},
[columnMap, onSelect, setIsOpen]
[itemToString, onSelect, setIsOpen]
);

const inputProps = {
Expand Down
5 changes: 3 additions & 2 deletions vuu-ui/packages/vuu-ui-controls/src/list/List.css
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,13 @@
overflow: auto;
}

.vuuListItemHeader {
.vuuListHeader {
--saltList-item-background: var(--list-item-header-background);
color: var(--list-item-header-color);
font-weight: 600;
}

.vuuListItemHeader[data-sticky="true"] {
.vuuListHeader[data-sticky="true"] {
--saltList-item-background: var(--list-background);
position: sticky;
top: 0;
Expand Down
2 changes: 1 addition & 1 deletion vuu-ui/packages/vuu-ui-controls/src/list/List.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -203,12 +203,12 @@ export const List = forwardRef(function List<
focusVisible: collapsibleHeaders && appliedFocusVisible === idx.value,
})}
aria-expanded={expanded}
data-idx={collapsibleHeaders ? idx.value : undefined}
data-index={collapsibleHeaders ? idx.value : undefined}
data-highlighted={idx.value === highlightedIndex || undefined}
data-sticky={stickyHeaders}
data-selectable={false}
id={headerId}
itemHeight={getItemHeight(idx.value)}
key={`header-${idx.value}`}
label={title}
// role="presentation"
Expand Down
Loading

0 comments on commit 7303e99

Please sign in to comment.