void;
-
export type TableNavigationStyle = "none" | "cell" | "row";
export interface TableProps
@@ -55,6 +54,10 @@ export interface TableProps
* required if a fully featured column picker is to be available
*/
availableColumns?: SchemaColumn[];
+ /**
+ * Provide configuration settings for Table. At minimun, column
+ * descriptors must be provided.
+ */
config: TableConfig;
dataSource: DataSource;
disableFocus?: boolean;
@@ -76,7 +79,7 @@ export interface TableProps
* is changed. By persisting this value and providing it to the Table as a
* prop, table state can be persisted across sessions.
*/
- onConfigChange?: (config: TableConfig) => void;
+ onConfigChange?: TableConfigChangeHandler;
onDragStart?: DragStartHandler;
onDrop?: (dragDropState: DragDropState) => void;
/**
@@ -229,6 +232,7 @@ const TableCore = ({
{showColumnHeaders ? (
@@ -304,6 +308,15 @@ export const Table = forwardRef(function TableNext(
const [size, setSize] = useState
();
+ if (config === undefined) {
+ throw Error(
+ "vuu Table requires config prop. Minimum config is list of Column Descriptors"
+ );
+ }
+ if (dataSource === undefined) {
+ throw Error("vuu Table requires dataSource prop");
+ }
+
return (
p.column === p1.column &&
- p.row[p.columnMap[p.column.name]] === p1.row[p1.columnMap[p1.column.name]];
+ p.column.valueFormatter(p.row[p.columnMap[p.column.name]]) ===
+ p1.column.valueFormatter(p1.row[p1.columnMap[p1.column.name]]);
diff --git a/vuu-ui/packages/vuu-table/src/cell-renderers/checkbox-cell/CheckboxCell.tsx b/vuu-ui/packages/vuu-table/src/cell-renderers/checkbox-cell/CheckboxCell.tsx
index a5a6f9c5d..ad09492df 100644
--- a/vuu-ui/packages/vuu-table/src/cell-renderers/checkbox-cell/CheckboxCell.tsx
+++ b/vuu-ui/packages/vuu-table/src/cell-renderers/checkbox-cell/CheckboxCell.tsx
@@ -21,7 +21,7 @@ export const CheckboxCell: React.FC = memo(
[onCommit]
);
- return !!column.editable ? (
+ return column.editable ? (
) : (
diff --git a/vuu-ui/packages/vuu-table/src/cell-renderers/index.ts b/vuu-ui/packages/vuu-table/src/cell-renderers/index.ts
index dfa5e7706..5c65fcf6a 100644
--- a/vuu-ui/packages/vuu-table/src/cell-renderers/index.ts
+++ b/vuu-ui/packages/vuu-table/src/cell-renderers/index.ts
@@ -1,5 +1,4 @@
export * from "./checkbox-cell";
-export * from "./dropdown-cell";
export * from "./input-cell";
-export * from "./lookup-cell";
export * from "./toggle-cell";
+export * from "./cell-utils";
diff --git a/vuu-ui/packages/vuu-table/src/cell-renderers/input-cell/InputCell.tsx b/vuu-ui/packages/vuu-table/src/cell-renderers/input-cell/InputCell.tsx
index 97e69e160..54c716f84 100644
--- a/vuu-ui/packages/vuu-table/src/cell-renderers/input-cell/InputCell.tsx
+++ b/vuu-ui/packages/vuu-table/src/cell-renderers/input-cell/InputCell.tsx
@@ -2,10 +2,7 @@ import { TableCellRendererProps } from "@finos/vuu-table-types";
import { registerComponent } from "@finos/vuu-utils";
import { Input } from "@salt-ds/core";
import { useEditableText } from "@finos/vuu-ui-controls";
-import cx from "classnames";
-// make sure all validators are loaded - how do we manage this ?
-// eslint-disable-next-line @typescript-eslint/no-unused-vars
-import { CaseValidator, PatternValidator } from "@finos/vuu-table-extras";
+import cx from "clsx";
import "./InputCell.css";
@@ -24,14 +21,10 @@ export const InputCell = ({
row,
}: TableCellRendererProps) => {
const dataIdx = columnMap[column.name];
- const {
- align = "left",
- clientSideEditValidationCheck,
- valueFormatter,
- } = column;
+ const { align = "left", clientSideEditValidationCheck } = column;
const { warningMessage, ...editProps } = useEditableText({
- initialValue: valueFormatter(row[dataIdx]),
+ initialValue: row[dataIdx],
onCommit,
clientSideEditValidationCheck,
});
diff --git a/vuu-ui/packages/vuu-table/src/cell-renderers/toggle-cell/ToggleCell.tsx b/vuu-ui/packages/vuu-table/src/cell-renderers/toggle-cell/ToggleCell.tsx
index ad3d8006a..a7e76742e 100644
--- a/vuu-ui/packages/vuu-table/src/cell-renderers/toggle-cell/ToggleCell.tsx
+++ b/vuu-ui/packages/vuu-table/src/cell-renderers/toggle-cell/ToggleCell.tsx
@@ -9,7 +9,7 @@ import {
isValueListRenderer,
registerComponent,
} from "@finos/vuu-utils";
-import cx from "classnames";
+import cx from "clsx";
import { memo, useCallback } from "react";
import { dataAndColumnUnchanged } from "../cell-utils";
diff --git a/vuu-ui/packages/vuu-table/src/column-header-pill/ColumnHeaderPill.tsx b/vuu-ui/packages/vuu-table/src/column-header-pill/ColumnHeaderPill.tsx
index 7fc41e808..37d7660ea 100644
--- a/vuu-ui/packages/vuu-table/src/column-header-pill/ColumnHeaderPill.tsx
+++ b/vuu-ui/packages/vuu-table/src/column-header-pill/ColumnHeaderPill.tsx
@@ -1,4 +1,4 @@
-import cx from "classnames";
+import cx from "clsx";
import { RuntimeColumnDescriptor } from "@finos/vuu-table-types";
import { HTMLAttributes, MouseEvent, useCallback } from "react";
diff --git a/vuu-ui/packages/vuu-table/src/column-menu/ColumnMenu.tsx b/vuu-ui/packages/vuu-table/src/column-menu/ColumnMenu.tsx
index a000fd237..7bc1204ab 100644
--- a/vuu-ui/packages/vuu-table/src/column-menu/ColumnMenu.tsx
+++ b/vuu-ui/packages/vuu-table/src/column-menu/ColumnMenu.tsx
@@ -1,6 +1,6 @@
import { RuntimeColumnDescriptor } from "@finos/vuu-table-types";
import { useContextMenu } from "@finos/vuu-popups";
-import cx from "classnames";
+import cx from "clsx";
import {
HTMLAttributes,
MouseEvent,
diff --git a/vuu-ui/packages/vuu-table/src/column-resizing/useTableColumnResize.tsx b/vuu-ui/packages/vuu-table/src/column-resizing/useTableColumnResize.tsx
index ac8f16928..cac7f5f3c 100644
--- a/vuu-ui/packages/vuu-table/src/column-resizing/useTableColumnResize.tsx
+++ b/vuu-ui/packages/vuu-table/src/column-resizing/useTableColumnResize.tsx
@@ -1,12 +1,9 @@
-import { Heading, RuntimeColumnDescriptor } from "@finos/vuu-table-types";
+import {
+ Heading,
+ ResizePhase,
+ RuntimeColumnDescriptor,
+} from "@finos/vuu-table-types";
import { RefObject, useCallback, useRef, useState } from "react";
-import { ResizePhase } from "../useTableModel";
-
-export type TableColumnResizeHandler = (
- phase: ResizePhase,
- columnName: string,
- width?: number
-) => void;
export type ResizeHandler = (evt: MouseEvent, moveBy: number) => void;
export interface CellResizeHookProps {
diff --git a/vuu-ui/packages/vuu-table/src/context-menu/buildContextMenuDescriptors.ts b/vuu-ui/packages/vuu-table/src/context-menu/buildContextMenuDescriptors.ts
index 72ffffcdf..38d9744dd 100644
--- a/vuu-ui/packages/vuu-table/src/context-menu/buildContextMenuDescriptors.ts
+++ b/vuu-ui/packages/vuu-table/src/context-menu/buildContextMenuDescriptors.ts
@@ -1,5 +1,8 @@
-import { DataSource } from "@finos/vuu-data";
-import { ContextMenuItemDescriptor, MenuBuilder } from "@finos/vuu-data-types";
+import {
+ ContextMenuItemDescriptor,
+ DataSource,
+ MenuBuilder,
+} from "@finos/vuu-data-types";
import { RuntimeColumnDescriptor, PinLocation } from "@finos/vuu-table-types";
import { isNumericColumn } from "@finos/vuu-utils";
diff --git a/vuu-ui/packages/vuu-table/src/context-menu/useHandleTableContextMenu.ts b/vuu-ui/packages/vuu-table/src/context-menu/useHandleTableContextMenu.ts
index 4f7ee9364..a250b68cc 100644
--- a/vuu-ui/packages/vuu-table/src/context-menu/useHandleTableContextMenu.ts
+++ b/vuu-ui/packages/vuu-table/src/context-menu/useHandleTableContextMenu.ts
@@ -1,10 +1,13 @@
/* eslint-disable no-sequences */
-import { DataSource } from "@finos/vuu-data";
import { RuntimeColumnDescriptor } from "@finos/vuu-table-types";
import { Filter } from "@finos/vuu-filter-types";
import { removeColumnFromFilter } from "@finos/vuu-utils";
import { VuuFilter } from "@finos/vuu-protocol-types";
-import { DataSourceFilter, MenuActionHandler } from "@finos/vuu-data-types";
+import {
+ DataSource,
+ DataSourceFilter,
+ MenuActionHandler,
+} from "@finos/vuu-data-types";
import { PersistentColumnAction } from "../useTableModel";
import {
addGroupColumn,
diff --git a/vuu-ui/packages/vuu-table/src/header-cell/GroupHeaderCellNext.tsx b/vuu-ui/packages/vuu-table/src/header-cell/GroupHeaderCellNext.tsx
index 333bbaaf0..b28b4e1de 100644
--- a/vuu-ui/packages/vuu-table/src/header-cell/GroupHeaderCellNext.tsx
+++ b/vuu-ui/packages/vuu-table/src/header-cell/GroupHeaderCellNext.tsx
@@ -1,15 +1,16 @@
+import { OverflowContainer } from "@finos/vuu-layout";
import {
ColumnDescriptor,
GroupColumnDescriptor,
+ HeaderCellProps,
RuntimeColumnDescriptor,
} from "@finos/vuu-table-types";
-import cx from "classnames";
+import { useLayoutEffectSkipFirst } from "@finos/vuu-utils";
+import cx from "clsx";
import { useCallback, useRef, useState } from "react";
+import { ColumnHeaderPill, GroupColumnPill } from "../column-header-pill";
import { ColumnResizer, useTableColumnResize } from "../column-resizing";
-import { HeaderCellProps } from "./HeaderCell";
import { useCell } from "../useCell";
-import { ColumnHeaderPill, GroupColumnPill } from "../column-header-pill";
-import { OverflowContainer, useLayoutEffectSkipFirst } from "@finos/vuu-layout";
import "./GroupHeaderCell.css";
diff --git a/vuu-ui/packages/vuu-table/src/header-cell/HeaderCell.tsx b/vuu-ui/packages/vuu-table/src/header-cell/HeaderCell.tsx
index 828e439cd..45a570acf 100644
--- a/vuu-ui/packages/vuu-table/src/header-cell/HeaderCell.tsx
+++ b/vuu-ui/packages/vuu-table/src/header-cell/HeaderCell.tsx
@@ -1,25 +1,15 @@
-import { RuntimeColumnDescriptor } from "@finos/vuu-table-types";
-import { HTMLAttributes, MouseEventHandler, useCallback, useRef } from "react";
-import { useCell } from "../useCell";
-import { ColumnMenu } from "../column-menu";
+import { HeaderCellProps } from "@finos/vuu-table-types";
+import cx from "clsx";
+import { MouseEventHandler, useCallback, useRef } from "react";
import { SortIndicator } from "../column-header-pill";
-import cx from "classnames";
-import {
- ColumnResizer,
- TableColumnResizeHandler,
- useTableColumnResize,
-} from "../column-resizing";
+import { ColumnMenu } from "../column-menu";
+import { ColumnResizer, useTableColumnResize } from "../column-resizing";
+import { useCell } from "../useCell";
import "./HeaderCell.css";
const classBase = "vuuTableHeaderCell";
-export interface HeaderCellProps extends HTMLAttributes {
- classBase?: string;
- column: RuntimeColumnDescriptor;
- onResize?: TableColumnResizeHandler;
-}
-
export const HeaderCell = ({
className: classNameProp,
column,
diff --git a/vuu-ui/packages/vuu-table/src/index.ts b/vuu-ui/packages/vuu-table/src/index.ts
index f9e796339..558444450 100644
--- a/vuu-ui/packages/vuu-table/src/index.ts
+++ b/vuu-ui/packages/vuu-table/src/index.ts
@@ -1,6 +1,7 @@
export { GroupHeaderCellNext } from "./header-cell";
export * from "./header-cell";
export * from "./Table";
+export * from "./table-cell";
export * from "./table-config";
export * from "./cell-renderers";
export type { RowProps } from "./Row";
diff --git a/vuu-ui/packages/vuu-table/src/table-cell/TableCell.css b/vuu-ui/packages/vuu-table/src/table-cell/TableCell.css
index be1a1fa67..3c0852460 100644
--- a/vuu-ui/packages/vuu-table/src/table-cell/TableCell.css
+++ b/vuu-ui/packages/vuu-table/src/table-cell/TableCell.css
@@ -2,27 +2,27 @@
border-right-color: var(--cell-borderColor);
border-right-style: solid;
border-right-width: 1px;
- display: inline-block;
- height: 100%;
- overflow:hidden;
- padding: 0 11px 0 12px;
- text-overflow: ellipsis;
- vertical-align: top;
- }
+ display: inline-block;
+ height: 100%;
+ overflow:hidden;
+ padding: var(--vuuTableCell-padding, 0 11px 0 12px);
+ text-overflow: ellipsis;
+ vertical-align: top;
+}
- .vuuTableCell-right {
+.vuuTableCell-right {
text-align: right;
- }
+}
- .vuuTableCell-editable {
+.vuuTableCell-editable {
display: inline-flex;
line-height: 18px;
padding-bottom: 1px;
padding-top: 1px;
text-overflow: unset;
- }
+}
- .vuuTableCell:focus {
+.vuuTableCell:focus {
outline: var(--vuuTableCell-outline, solid var(--vuu-color-purple-10) 2px);
outline-offset: -2px;
/** This is to achieve a white background to outline dashes */
diff --git a/vuu-ui/packages/vuu-table/src/table-cell/TableGroupCell.tsx b/vuu-ui/packages/vuu-table/src/table-cell/TableGroupCell.tsx
index 1d72534ac..ecfd39455 100644
--- a/vuu-ui/packages/vuu-table/src/table-cell/TableGroupCell.tsx
+++ b/vuu-ui/packages/vuu-table/src/table-cell/TableGroupCell.tsx
@@ -2,7 +2,7 @@ import { GroupColumnDescriptor, TableCellProps } from "@finos/vuu-table-types";
import { getGroupValueAndOffset, metadataKeys } from "@finos/vuu-utils";
import { MouseEvent, useCallback } from "react";
import { useCell } from "../useCell";
-import cx from "classnames";
+import cx from "clsx";
import "./TableGroupCell.css";
diff --git a/vuu-ui/packages/vuu-table/src/table-dom-utils.ts b/vuu-ui/packages/vuu-table/src/table-dom-utils.ts
index 798b4373a..da10cb990 100644
--- a/vuu-ui/packages/vuu-table/src/table-dom-utils.ts
+++ b/vuu-ui/packages/vuu-table/src/table-dom-utils.ts
@@ -40,7 +40,7 @@ export function getRowIndex(rowEl?: HTMLElement) {
if (rowEl) {
const idx: string | null = rowEl.ariaRowIndex;
if (idx !== null) {
- return parseInt(idx, 10);
+ return parseInt(idx, 10) - 1;
}
}
return -1;
diff --git a/vuu-ui/packages/vuu-table/src/table-header/TableHeader.tsx b/vuu-ui/packages/vuu-table/src/table-header/TableHeader.tsx
index dc45e0de2..8ec2dfbe8 100644
--- a/vuu-ui/packages/vuu-table/src/table-header/TableHeader.tsx
+++ b/vuu-ui/packages/vuu-table/src/table-header/TableHeader.tsx
@@ -1,13 +1,13 @@
+import { VuuSortType } from "@finos/vuu-protocol-types";
import {
ColumnDescriptor,
RuntimeColumnDescriptor,
+ TableColumnResizeHandler,
TableConfig,
TableHeadings,
} from "@finos/vuu-table-types";
import { isGroupColumn, isNotHidden } from "@finos/vuu-utils";
-import cx from "classnames";
-import { VuuSortType } from "packages/vuu-protocol-types";
-import { TableColumnResizeHandler } from "../column-resizing";
+import cx from "clsx";
import { GroupHeaderCellNext, HeaderCell } from "../header-cell";
import { useTableHeader } from "./useTableHeader";
diff --git a/vuu-ui/packages/vuu-table/src/table-header/useTableHeader.ts b/vuu-ui/packages/vuu-table/src/table-header/useTableHeader.ts
index 12e965742..3792f8d68 100644
--- a/vuu-ui/packages/vuu-table/src/table-header/useTableHeader.ts
+++ b/vuu-ui/packages/vuu-table/src/table-header/useTableHeader.ts
@@ -43,7 +43,11 @@ export const useTableHeader = ({
? tableConfig.columns.findIndex(ofColumn(nextColumn))
: -1;
- onMoveColumn(moveColumnTo(tableConfig.columns, column, insertPos));
+ if (moveTo > moveFrom && insertPos !== -1) {
+ onMoveColumn(moveColumnTo(tableConfig.columns, column, insertPos - 1));
+ } else {
+ onMoveColumn(moveColumnTo(tableConfig.columns, column, insertPos));
+ }
},
[columns, onMoveColumn, tableConfig.columns]
);
diff --git a/vuu-ui/packages/vuu-table/src/useCell.ts b/vuu-ui/packages/vuu-table/src/useCell.ts
index dfbad9cf4..b5c23be13 100644
--- a/vuu-ui/packages/vuu-table/src/useCell.ts
+++ b/vuu-ui/packages/vuu-table/src/useCell.ts
@@ -1,6 +1,6 @@
import { RuntimeColumnDescriptor } from "@finos/vuu-table-types";
import { getColumnStyle } from "@finos/vuu-utils";
-import cx from "classnames";
+import cx from "clsx";
import { useMemo } from "react";
export const useCell = (
diff --git a/vuu-ui/packages/vuu-table/src/useDataSource.ts b/vuu-ui/packages/vuu-table/src/useDataSource.ts
index d02def46b..d220b00a9 100644
--- a/vuu-ui/packages/vuu-table/src/useDataSource.ts
+++ b/vuu-ui/packages/vuu-table/src/useDataSource.ts
@@ -1,13 +1,13 @@
import {
DataSource,
+ DataSourceRow,
DataSourceSubscribedMessage,
- isVuuFeatureInvocation,
SubscribeCallback,
VuuFeatureInvocationMessage,
-} from "@finos/vuu-data";
-import { DataSourceRow } from "@finos/vuu-data-types";
+} from "@finos/vuu-data-types";
import { VuuRange } from "@finos/vuu-protocol-types";
import { getFullRange, NULL_RANGE } from "@finos/vuu-utils";
+import { GridAction } from "@finos/vuu-table-types";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { MovingWindow } from "./moving-window";
@@ -21,6 +21,11 @@ export interface DataSourceHookProps {
renderBufferSize?: number;
}
+export const isVuuFeatureInvocation = (
+ action: GridAction
+): action is VuuFeatureInvocationMessage =>
+ action.type === "vuu-link-created" || action.type === "vuu-link-removed";
+
export const useDataSource = ({
dataSource,
onFeatureInvocation,
diff --git a/vuu-ui/packages/vuu-table/src/useSelection.ts b/vuu-ui/packages/vuu-table/src/useSelection.ts
index cd202317b..658d2e81e 100644
--- a/vuu-ui/packages/vuu-table/src/useSelection.ts
+++ b/vuu-ui/packages/vuu-table/src/useSelection.ts
@@ -1,9 +1,4 @@
-import {
- RowClickHandler,
- Selection,
- SelectionChangeHandler,
- TableSelectionModel,
-} from "@finos/vuu-table-types";
+import { RowClickHandler, TableSelectionModel } from "@finos/vuu-table-types";
import {
deselectItem,
dispatchMouseEvent,
@@ -11,7 +6,11 @@ import {
metadataKeys,
selectItem,
} from "@finos/vuu-utils";
-import { DataSourceRow } from "packages/vuu-data-types";
+import {
+ DataSourceRow,
+ Selection,
+ SelectionChangeHandler,
+} from "@finos/vuu-data-types";
import {
KeyboardEvent,
KeyboardEventHandler,
diff --git a/vuu-ui/packages/vuu-table/src/useTable.ts b/vuu-ui/packages/vuu-table/src/useTable.ts
index 599ee316e..b336aa318 100644
--- a/vuu-ui/packages/vuu-table/src/useTable.ts
+++ b/vuu-ui/packages/vuu-table/src/useTable.ts
@@ -1,25 +1,20 @@
import {
DataSourceConfig,
+ DataSourceRow,
DataSourceSubscribedMessage,
- JsonDataSource,
-} from "@finos/vuu-data";
-import { DataSourceRow } from "@finos/vuu-data-types";
+ SelectionChangeHandler,
+} from "@finos/vuu-data-types";
import {
ColumnDescriptor,
DataCellEditHandler,
RowClickHandler,
RuntimeColumnDescriptor,
- SelectionChangeHandler,
+ TableColumnResizeHandler,
TableConfig,
TableSelectionModel,
} from "@finos/vuu-table-types";
-import {
- MeasuredProps,
- MeasuredSize,
- useLayoutEffectSkipFirst,
-} from "@finos/vuu-layout";
+import { MeasuredProps, MeasuredSize } from "@finos/vuu-layout";
import { VuuRange, VuuSortType } from "@finos/vuu-protocol-types";
-import { useTableAndColumnSettings } from "@finos/vuu-table-extras";
import {
DragStartHandler,
useDragDropNext as useDragDrop,
@@ -32,6 +27,7 @@ import {
isValidNumber,
metadataKeys,
updateColumn,
+ useLayoutEffectSkipFirst,
} from "@finos/vuu-utils";
import {
FocusEvent,
@@ -42,7 +38,6 @@ import {
useMemo,
useState,
} from "react";
-import { TableColumnResizeHandler } from "./column-resizing";
import {
buildContextMenuDescriptors,
useHandleTableContextMenu,
@@ -66,6 +61,7 @@ import {
import { useTableScroll } from "./useTableScroll";
import { useTableViewport } from "./useTableViewport";
import { useVirtualViewport } from "./useVirtualViewport";
+import { useTableAndColumnSettings } from "./useTableAndColumnSettings";
const stripInternalProperties = (tableConfig: TableConfig): TableConfig => {
return tableConfig;
@@ -249,6 +245,7 @@ export const useTable = ({
const { data, dataRef, getSelectedRows, range, setRange } = useDataSource({
dataSource,
+ // We need to factor this out of Table
onFeatureInvocation,
renderBufferSize,
onSizeChange: onDataRowcountChange,
@@ -436,11 +433,11 @@ export const useTable = ({
const key = row[KEY];
if (row[IS_EXPANDED]) {
- (dataSource as JsonDataSource).closeTreeNode(key, true);
+ dataSource.closeTreeNode(key, true);
if (isJson) {
const idx = columns.indexOf(column);
- const rows = (dataSource as JsonDataSource).getRowsAtDepth(idx + 1);
- if (!rows.some((row) => row[IS_EXPANDED] || row[IS_LEAF])) {
+ const rows = dataSource.getRowsAtDepth?.(idx + 1);
+ if (rows && !rows.some((row) => row[IS_EXPANDED] || row[IS_LEAF])) {
dispatchColumnAction({
type: "hideColumns",
columns: columns.slice(idx + 2),
@@ -450,10 +447,10 @@ export const useTable = ({
} else {
dataSource.openTreeNode(key);
if (isJson) {
- const childRows = (dataSource as JsonDataSource).getChildRows(key);
+ const childRows = dataSource.getChildRows?.(key);
const idx = columns.indexOf(column) + 1;
const columnsToShow = [columns[idx]];
- if (childRows.some((row) => row[IS_LEAF])) {
+ if (childRows && childRows.some((row) => row[IS_LEAF])) {
columnsToShow.push(columns[idx + 1]);
}
if (columnsToShow.some((col) => col.hidden)) {
@@ -606,6 +603,9 @@ export const useTable = ({
const onMoveColumn = useCallback(
(columns: ColumnDescriptor[]) => {
+ console.log(`useTable onMoveColumn`, {
+ columns,
+ });
const newTableConfig = {
...tableConfig,
columns,
diff --git a/vuu-ui/packages/vuu-table-extras/src/useTableAndColumnSettings.ts b/vuu-ui/packages/vuu-table/src/useTableAndColumnSettings.ts
similarity index 95%
rename from vuu-ui/packages/vuu-table-extras/src/useTableAndColumnSettings.ts
rename to vuu-ui/packages/vuu-table/src/useTableAndColumnSettings.ts
index 17229d727..8c7ad6ba7 100644
--- a/vuu-ui/packages/vuu-table-extras/src/useTableAndColumnSettings.ts
+++ b/vuu-ui/packages/vuu-table/src/useTableAndColumnSettings.ts
@@ -1,13 +1,14 @@
-import { DataSourceConfig, SchemaColumn } from "@finos/vuu-data";
-import { ColumnDescriptor, TableConfig } from "@finos/vuu-table-types";
+import { DataSourceConfig, SchemaColumn } from "@finos/vuu-data-types";
import { useLayoutProviderDispatch } from "@finos/vuu-layout";
import {
+ ColumnDescriptor,
ColumnSettingsProps,
+ TableConfig,
TableSettingsProps,
-} from "@finos/vuu-table-extras";
-import { ColumnActionColumnSettings } from "@finos/vuu-table";
+} from "@finos/vuu-table-types";
import { getCalculatedColumnType } from "@finos/vuu-utils";
import { useCallback, useRef, useState } from "react";
+import { ColumnActionColumnSettings } from "./useTableModel";
export interface TableAndColumnSettingsHookProps {
availableColumns: SchemaColumn[];
diff --git a/vuu-ui/packages/vuu-table/src/useTableContextMenu.ts b/vuu-ui/packages/vuu-table/src/useTableContextMenu.ts
index 6c715ffdd..24c6a0a38 100644
--- a/vuu-ui/packages/vuu-table/src/useTableContextMenu.ts
+++ b/vuu-ui/packages/vuu-table/src/useTableContextMenu.ts
@@ -1,5 +1,4 @@
-import { DataSource } from "@finos/vuu-data";
-import { DataSourceRow } from "@finos/vuu-data-types";
+import { DataSource, DataSourceRow } from "@finos/vuu-data-types";
import { RuntimeColumnDescriptor } from "@finos/vuu-table-types";
import { useContextMenu as usePopupContextMenu } from "@finos/vuu-popups";
import { buildColumnMap } from "@finos/vuu-utils";
diff --git a/vuu-ui/packages/vuu-table/src/useTableModel.ts b/vuu-ui/packages/vuu-table/src/useTableModel.ts
index de734cf38..d20e8fcba 100644
--- a/vuu-ui/packages/vuu-table/src/useTableModel.ts
+++ b/vuu-ui/packages/vuu-table/src/useTableModel.ts
@@ -1,7 +1,8 @@
import {
ColumnDescriptor,
- RuntimeColumnDescriptor,
PinLocation,
+ ResizePhase,
+ RuntimeColumnDescriptor,
TableAttributes,
TableConfig,
TableHeadings,
@@ -11,6 +12,8 @@ import {
applyGroupByToColumns,
applySortToColumns,
getCellRenderer,
+ getColumnHeaderContentRenderer,
+ getColumnHeaderLabelRenderer,
getColumnLabel,
getTableHeadings,
getValueFormatter,
@@ -26,8 +29,11 @@ import {
subscribedOnly,
} from "@finos/vuu-utils";
-import { DataSource, DataSourceConfig } from "@finos/vuu-data";
-import { TableSchema } from "@finos/vuu-data/src/message-utils";
+import {
+ DataSource,
+ DataSourceConfig,
+ TableSchema,
+} from "@finos/vuu-data-types";
import { VuuColumnDataType, VuuTable } from "@finos/vuu-protocol-types";
import { buildValidationChecker } from "@finos/vuu-ui-controls";
import { Reducer, useReducer } from "react";
@@ -108,8 +114,6 @@ export interface ColumnActionPin {
pin?: PinLocation;
}
-export type ResizePhase = "begin" | "resize" | "end";
-
export interface ColumnActionResize {
type: "resizeColumn";
column: RuntimeColumnDescriptor;
@@ -240,7 +244,6 @@ type InitialConfig = {
function init({ dataSource, tableConfig }: InitialConfig): InternalTableModel {
const { columns, ...tableAttributes } = tableConfig;
- console.log(JSON.stringify(tableAttributes, null, 2));
const { config: dataSourceConfig, tableSchema } = dataSource;
const runtimeColumns = columns
.filter(subscribedOnly(dataSourceConfig?.columns))
@@ -297,12 +300,12 @@ const columnDescriptorToRuntimeColumDescriptor =
...rest
} = column;
- const runtimeColumnWithDefaults = {
+ const runtimeColumnWithDefaults: RuntimeColumnDescriptor = {
...rest,
align,
CellRenderer: getCellRenderer(column),
- HeaderCellLabelRenderer: getCellRenderer(column, "col-label"),
- HeaderCellContentRenderer: getCellRenderer(column, "col-content"),
+ HeaderCellContentRenderer: getColumnHeaderContentRenderer(column),
+ HeaderCellLabelRenderer: getColumnHeaderLabelRenderer(column),
clientSideEditValidationCheck: hasValidationRules(column.type)
? buildValidationChecker(column.type.renderer.rules)
: undefined,
diff --git a/vuu-ui/packages/vuu-table/src/useVirtualViewport.ts b/vuu-ui/packages/vuu-table/src/useVirtualViewport.ts
index c57a40f75..b95486ccf 100644
--- a/vuu-ui/packages/vuu-table/src/useVirtualViewport.ts
+++ b/vuu-ui/packages/vuu-table/src/useVirtualViewport.ts
@@ -2,7 +2,7 @@ import { RuntimeColumnDescriptor } from "@finos/vuu-table-types";
import { VuuRange } from "@finos/vuu-protocol-types";
import { RowAtPositionFunc } from "@finos/vuu-utils";
import { useCallback, useEffect, useRef } from "react";
-import { ViewportMeasurements } from "@finos/vuu-table";
+import { ViewportMeasurements } from "./useTableViewport";
export interface VirtualViewportHookProps {
columns: RuntimeColumnDescriptor[];
@@ -12,13 +12,12 @@ export interface VirtualViewportHookProps {
}
export const useVirtualViewport = ({
- columns,
getRowAtPosition,
setRange,
viewportMeasurements,
}: VirtualViewportHookProps) => {
const firstRowRef = useRef(0);
- const { contentWidth, rowCount: viewportRowCount } = viewportMeasurements;
+ const { rowCount: viewportRowCount } = viewportMeasurements;
const handleVerticalScroll = useCallback(
(scrollTop: number) => {
diff --git a/vuu-ui/packages/vuu-theme/css/components/checkbox.css b/vuu-ui/packages/vuu-theme/css/components/checkbox.css
index 68d813b98..a1c3cf0a5 100644
--- a/vuu-ui/packages/vuu-theme/css/components/checkbox.css
+++ b/vuu-ui/packages/vuu-theme/css/components/checkbox.css
@@ -42,8 +42,8 @@
background-color: var(--vuu-icon-color);
left: var(--vuu-icon-left, auto);
height: var(--vuu-icon-height, var(--vuu-icon-size, 12px));
+ mask: var(--vuu-svg-tick) center center/var(--vuu-icon-size) var(--vuu-icon-size);
-webkit-mask: var(--vuu-svg-tick) center center/var(--vuu-icon-size) var(--vuu-icon-size);
- mask: var(--vuu-icon-svg) center center/var(--vuu-icon-size) var(--vuu-icon-size);
mask-repeat: no-repeat;
-webkit-mask-repeat: no-repeat;
position: absolute;
diff --git a/vuu-ui/packages/vuu-theme/css/components/switch.css b/vuu-ui/packages/vuu-theme/css/components/switch.css
index c40cde19a..e032d64e8 100644
--- a/vuu-ui/packages/vuu-theme/css/components/switch.css
+++ b/vuu-ui/packages/vuu-theme/css/components/switch.css
@@ -1,7 +1,6 @@
.saltSwitch {
--switch-color: var(--vuu-color-gray-45);
--vuu-icon-left: -1px;
-
}
.saltSwitch-track {
@@ -13,7 +12,7 @@
width: 26px;
}
-.saltSwitch:hover .saltSwitch-track {
+.saltSwitch:not(.saltSwitch-disabled):hover .saltSwitch-track {
--switch-color: var(--vuu-color-pink-10);
}
@@ -30,6 +29,10 @@
--switch-color: var(--vuu-color-purple-10);
}
+.saltSwitch-disabled {
+ --switch-color: var(--vuu-color-gray-30);
+}
+
.saltSwitch-checked .saltSwitch-thumb,
.saltSwitch-checked:hover .saltSwitch-thumb {
background-color: white;
@@ -42,8 +45,8 @@
content: "";
left: var(--vuu-icon-left, auto);
height: var(--vuu-icon-height, var(--vuu-icon-size, 12px));
+ mask: var(--vuu-svg-tick) center center/var(--vuu-icon-size) var(--vuu-icon-size);
-webkit-mask: var(--vuu-svg-tick) center center/var(--vuu-icon-size) var(--vuu-icon-size);
- mask: var(--vuu-icon-svg) center center/var(--vuu-icon-size) var(--vuu-icon-size);
mask-repeat: no-repeat;
-webkit-mask-repeat: no-repeat;
position: absolute;
diff --git a/vuu-ui/packages/vuu-theme/css/palette/neutral.css b/vuu-ui/packages/vuu-theme/css/palette/neutral.css
index d5ed43163..db95dd59c 100644
--- a/vuu-ui/packages/vuu-theme/css/palette/neutral.css
+++ b/vuu-ui/packages/vuu-theme/css/palette/neutral.css
@@ -1,6 +1,6 @@
.vuu-theme[data-mode="light"] {
--salt-palette-neutral-primary-background: var(--salt-color-white);
- --salt-palette-neutral-primary-background-disabled: var(--salt-color-white-fade-background);
+ --salt-palette-neutral-primary-background-disabled: var(--vuu-color-gray-30);
--salt-palette-neutral-primary-background-readonly: var(--salt-color-white-fade-background-readonly);
--salt-palette-neutral-primary-foreground: var(--vuu-color-gray-80);
--salt-palette-neutral-primary-foreground-disabled: var(--salt-color-gray-900-fade-foreground);
diff --git a/vuu-ui/packages/vuu-ui-controls/package.json b/vuu-ui/packages/vuu-ui-controls/package.json
index 9bbf380eb..02ccb0c13 100644
--- a/vuu-ui/packages/vuu-ui-controls/package.json
+++ b/vuu-ui/packages/vuu-ui-controls/package.json
@@ -10,8 +10,7 @@
"type-defs": "node ../../scripts/build-type-defs.mjs"
},
"dependencies": {
- "@salt-ds/core": "1.8.0",
- "@finos/vuu-data": "0.0.26",
+ "@salt-ds/core": "1.13.2",
"@finos/vuu-data-types": "0.0.26",
"@finos/vuu-table-types": "0.0.26",
"@finos/vuu-layout": "0.0.26",
@@ -20,8 +19,9 @@
"@finos/vuu-utils": "0.0.26"
},
"peerDependencies": {
- "classnames": "^2.2.6",
- "react": "^17.0.2",
- "react-dom": "^17.0.2"
- }
+ "clsx": "^2.0.0",
+ "react": ">=17.0.2",
+ "react-dom": ">=17.0.2"
+ },
+ "sideEffects": false
}
diff --git a/vuu-ui/packages/vuu-ui-controls/src/combo-box/ComboBox.tsx b/vuu-ui/packages/vuu-ui-controls/src/combo-box/ComboBox.tsx
index 84618f28b..dd328424d 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/combo-box/ComboBox.tsx
+++ b/vuu-ui/packages/vuu-ui-controls/src/combo-box/ComboBox.tsx
@@ -1,4 +1,4 @@
-import { useId } from "@finos/vuu-layout";
+import { useId } from "@finos/vuu-utils";
import { Input, InputProps } from "@salt-ds/core";
import {
ForwardedRef,
@@ -16,8 +16,8 @@ import {
} from "../common-hooks";
import { DropdownBase, DropdownBaseProps } from "../dropdown";
import { List, ListProps } from "../list";
-import { useCombobox } from "./useCombobox";
import { ChevronIcon } from "../list/ChevronIcon";
+import { useCombobox } from "./useCombobox";
//TODO why do we need onSelect from input ?
export interface ComboBoxProps<
diff --git a/vuu-ui/packages/vuu-ui-controls/src/combo-box/useCombobox.ts b/vuu-ui/packages/vuu-ui-controls/src/combo-box/useCombobox.ts
index a5063293b..10bb9aa73 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/combo-box/useCombobox.ts
+++ b/vuu-ui/packages/vuu-ui-controls/src/combo-box/useCombobox.ts
@@ -1,5 +1,5 @@
+import { useLayoutEffectSkipFirst } from "@finos/vuu-utils";
import { InputProps, useControlled } from "@salt-ds/core";
-import { useLayoutEffectSkipFirst } from "@finos/vuu-layout";
import {
ChangeEvent,
FocusEvent,
@@ -107,7 +107,7 @@ export const useCombobox = - ({
}: ComboboxHookProps
- ): ComboboxHookResult
- => {
const isMultiSelect = isMultiSelection(selectionStrategy);
- const { data, setFilterPattern } = collectionHook;
+ const { setFilterPattern } = collectionHook;
const setHighlightedIndexRef = useRef void)>(null);
// used to track multi selection
const selectedRef = useRef
- (isMultiSelect ? [] : null);
diff --git a/vuu-ui/packages/vuu-ui-controls/src/common-hooks/use-resize-observer.ts b/vuu-ui/packages/vuu-ui-controls/src/common-hooks/use-resize-observer.ts
index fe088d564..9e5bb6999 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/common-hooks/use-resize-observer.ts
+++ b/vuu-ui/packages/vuu-ui-controls/src/common-hooks/use-resize-observer.ts
@@ -62,11 +62,6 @@ const getTargetSize = (
}
};
-const isScrollAttribute = {
- scrollHeight: true,
- scrollWidth: true,
-};
-
// TODO should we make this create-on-demand
const resizeObserver = new ResizeObserver((entries: ResizeObserverEntry[]) => {
for (const entry of entries) {
@@ -78,7 +73,7 @@ const resizeObserver = new ResizeObserver((entries: ResizeObserverEntry[]) => {
contentBoxSize;
const { onResize, measurements } = observedTarget;
let sizeChanged = false;
- for (let [dimension, size] of Object.entries(measurements)) {
+ for (const [dimension, size] of Object.entries(measurements)) {
const newSize = getTargetSize(
target as HTMLElement,
{ height, width, contentHeight, contentWidth },
diff --git a/vuu-ui/packages/vuu-ui-controls/src/cycle-state-button/CycleStateButton.tsx b/vuu-ui/packages/vuu-ui-controls/src/cycle-state-button/CycleStateButton.tsx
index 9f9de984c..8dd90fd7a 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/cycle-state-button/CycleStateButton.tsx
+++ b/vuu-ui/packages/vuu-ui-controls/src/cycle-state-button/CycleStateButton.tsx
@@ -1,10 +1,10 @@
import { Button, ButtonProps } from "@salt-ds/core";
-import cx from "classnames";
-import { CommitResponse } from "packages/vuu-table-types";
-import {
+import cx from "clsx";
+import type { CommitResponse } from "@finos/vuu-table-types";
+import type {
VuuColumnDataType,
VuuRowDataItemType,
-} from "packages/vuu-protocol-types";
+} from "@finos/vuu-protocol-types";
import { ForwardedRef, forwardRef, SyntheticEvent, useCallback } from "react";
const classBase = "vuuCycleStateButton";
diff --git a/vuu-ui/packages/vuu-ui-controls/src/drag-drop/Draggable.tsx b/vuu-ui/packages/vuu-ui-controls/src/drag-drop/Draggable.tsx
index 1e8d3be34..75a79cd1a 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/drag-drop/Draggable.tsx
+++ b/vuu-ui/packages/vuu-ui-controls/src/drag-drop/Draggable.tsx
@@ -1,5 +1,5 @@
import { useForkRef } from "@salt-ds/core";
-import cx from "classnames";
+import cx from "clsx";
import {
CSSProperties,
forwardRef,
diff --git a/vuu-ui/packages/vuu-ui-controls/src/drag-drop/index.ts b/vuu-ui/packages/vuu-ui-controls/src/drag-drop/index.ts
index a39d84e65..2267fde99 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/drag-drop/index.ts
+++ b/vuu-ui/packages/vuu-ui-controls/src/drag-drop/index.ts
@@ -1,4 +1,6 @@
export * from "./dragDropTypesNext";
export * from "./DragDropProvider";
+export * from "./DragDropState";
export * from "./useDragDropNext";
export * from "./drop-target-utils";
+export * from "./useGlobalDragDrop";
diff --git a/vuu-ui/packages/vuu-ui-controls/src/dropdown/Dropdown.tsx b/vuu-ui/packages/vuu-ui-controls/src/dropdown/Dropdown.tsx
index fa04c1bca..f6ff75c0c 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/dropdown/Dropdown.tsx
+++ b/vuu-ui/packages/vuu-ui-controls/src/dropdown/Dropdown.tsx
@@ -8,7 +8,7 @@ import {
useRef,
} from "react";
-import { useId } from "@finos/vuu-layout";
+import { useId } from "@finos/vuu-utils";
import {
CollectionProvider,
itemToString as defaultItemToString,
@@ -17,10 +17,10 @@ import {
useCollectionItems,
} from "../common-hooks";
import { List, ListProps } from "../list";
+import { forwardCallbackProps } from "../utils";
import { DropdownBase, MaybeChildProps } from "./DropdownBase";
import { DropdownButton } from "./DropdownButton";
import { DropdownBaseProps } from "./dropdownTypes";
-import { forwardCallbackProps } from "../utils";
import { useDropdown } from "./useDropdown";
export interface DropdownProps<
diff --git a/vuu-ui/packages/vuu-ui-controls/src/dropdown/DropdownBase.tsx b/vuu-ui/packages/vuu-ui-controls/src/dropdown/DropdownBase.tsx
index 3e932f2af..bb71b5655 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/dropdown/DropdownBase.tsx
+++ b/vuu-ui/packages/vuu-ui-controls/src/dropdown/DropdownBase.tsx
@@ -1,11 +1,11 @@
-import cx from "classnames";
+import { PopupComponent as Popup, Portal } from "@finos/vuu-popups";
+import { useId } from "@finos/vuu-utils";
import { useForkRef } from "@salt-ds/core";
+import cx from "clsx";
import { Children, cloneElement, forwardRef, useRef } from "react";
import { forwardCallbackProps } from "../utils";
import { DropdownBaseProps } from "./dropdownTypes";
import { useDropdownBase } from "./useDropdownBase";
-import { useId } from "@finos/vuu-layout";
-import { PopupComponent as Popup, Portal } from "@finos/vuu-popups";
import "./Dropdown.css";
diff --git a/vuu-ui/packages/vuu-ui-controls/src/dropdown/DropdownButton.tsx b/vuu-ui/packages/vuu-ui-controls/src/dropdown/DropdownButton.tsx
index 6ea5fc8b8..5c7b62434 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/dropdown/DropdownButton.tsx
+++ b/vuu-ui/packages/vuu-ui-controls/src/dropdown/DropdownButton.tsx
@@ -1,5 +1,5 @@
import { Button, ButtonProps } from "@salt-ds/core";
-import cx from "classnames";
+import cx from "clsx";
import { AriaAttributes, ForwardedRef, forwardRef } from "react";
import "./DropdownButton.css";
diff --git a/vuu-ui/packages/vuu-ui-controls/src/editable-label/EditableLabel.tsx b/vuu-ui/packages/vuu-ui-controls/src/editable-label/EditableLabel.tsx
index f7cace02f..67f55d2a3 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/editable-label/EditableLabel.tsx
+++ b/vuu-ui/packages/vuu-ui-controls/src/editable-label/EditableLabel.tsx
@@ -1,4 +1,4 @@
-import cx from "classnames";
+import cx from "clsx";
import {
ChangeEvent,
KeyboardEvent,
diff --git a/vuu-ui/packages/vuu-ui-controls/src/editable/useEditableText.ts b/vuu-ui/packages/vuu-ui-controls/src/editable/useEditableText.ts
index 274905063..1e49c84bf 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/editable/useEditableText.ts
+++ b/vuu-ui/packages/vuu-ui-controls/src/editable/useEditableText.ts
@@ -1,5 +1,5 @@
import { DataItemCommitHandler } from "@finos/vuu-table-types";
-import { useLayoutEffectSkipFirst } from "@finos/vuu-layout";
+import { useLayoutEffectSkipFirst } from "@finos/vuu-utils";
import { VuuRowDataItemType } from "@finos/vuu-protocol-types";
import { dispatchCustomEvent } from "@finos/vuu-utils";
import {
diff --git a/vuu-ui/packages/vuu-ui-controls/src/expando-input/ExpandoInput.tsx b/vuu-ui/packages/vuu-ui-controls/src/expando-input/ExpandoInput.tsx
index 54fa022bd..ee9abafdd 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/expando-input/ExpandoInput.tsx
+++ b/vuu-ui/packages/vuu-ui-controls/src/expando-input/ExpandoInput.tsx
@@ -1,6 +1,6 @@
-import { VuuInput, VuuInputProps } from "@finos/vuu-ui-controls";
-import cx from "classnames";
+import cx from "clsx";
import { ForwardedRef, forwardRef } from "react";
+import { VuuInput, VuuInputProps } from "../vuu-input";
import "./ExpandoInput.css";
diff --git a/vuu-ui/packages/vuu-ui-controls/src/inputs/Checkbox.tsx b/vuu-ui/packages/vuu-ui-controls/src/inputs/Checkbox.tsx
index 85eda99c2..889a5921f 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/inputs/Checkbox.tsx
+++ b/vuu-ui/packages/vuu-ui-controls/src/inputs/Checkbox.tsx
@@ -1,16 +1,16 @@
-import { CheckboxIcon } from "@finos/vuu-ui-controls/src/list/CheckboxIcon";
+import { CheckboxIcon } from "../list/CheckboxIcon";
import "./Checkbox.css";
type CheckboxProps = {
- onToggle: () => void,
- className?: string,
- checked: boolean,
- label: string
-}
+ onToggle: () => void;
+ className?: string;
+ checked: boolean;
+ label: string;
+};
export const Checkbox = (props: CheckboxProps): JSX.Element => {
- const {onToggle, checked, label} = props;
+ const { onToggle, checked, label } = props;
return (
{
{label}
- )
-}
+ );
+};
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 5398cefe9..503cefc45 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,18 +1,20 @@
-import { TableSchema } from "@finos/vuu-data";
-import { DataSourceRow } from "@finos/vuu-data-types";
-import { useId } from "@finos/vuu-layout";
+import { DataSourceRow, TableSchema } from "@finos/vuu-data-types";
import { Table, TableProps, TableRowSelectHandler } from "@finos/vuu-table";
-import { ColumnMap } from "@finos/vuu-utils";
+import { ColumnMap, useId } from "@finos/vuu-utils";
import { Input } from "@salt-ds/core";
import { ForwardedRef, forwardRef, HTMLAttributes, useMemo } from "react";
import { DropdownBase, OpenChangeHandler } from "../dropdown";
-import "./SearchCell";
+import { SearchCell } from "./SearchCell";
import { useInstrumentPicker } from "./useInstrumentPicker";
import "./InstrumentPicker.css";
const classBase = "vuuInstrumentPicker";
+if (typeof SearchCell !== "function") {
+ console.warn("Instrument Picker: SearchCell module not loaded ");
+}
+
export interface InstrumentPickerProps
extends Omit, "onSelect"> {
TableProps: Pick;
diff --git a/vuu-ui/packages/vuu-ui-controls/src/instrument-picker/useDataSource.ts b/vuu-ui/packages/vuu-ui-controls/src/instrument-picker/useDataSource.ts
index 4fe080729..9dafe4575 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/instrument-picker/useDataSource.ts
+++ b/vuu-ui/packages/vuu-ui-controls/src/instrument-picker/useDataSource.ts
@@ -1,7 +1,10 @@
//TODO stansardise this
-import { DataSource, SubscribeCallback } from "@finos/vuu-data";
-import { DataSourceRow } from "@finos/vuu-data-types";
+import {
+ DataSource,
+ DataSourceRow,
+ SubscribeCallback,
+} from "@finos/vuu-data-types";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { MovingWindow } from "./moving-window";
export interface DataSourceHookProps {
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 37f03a6ba..309bc2508 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,5 +1,4 @@
-import { DataSource } from "@finos/vuu-data";
-import { DataSourceRow } from "@finos/vuu-data-types";
+import { DataSource, DataSourceRow } from "@finos/vuu-data-types";
import { ColumnDescriptor } from "@finos/vuu-table-types";
import {
TableRowSelectHandler,
diff --git a/vuu-ui/packages/vuu-ui-controls/src/instrument-search/InstrumentSearch.tsx b/vuu-ui/packages/vuu-ui-controls/src/instrument-search/InstrumentSearch.tsx
index f38449ad4..20a885b01 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/instrument-search/InstrumentSearch.tsx
+++ b/vuu-ui/packages/vuu-ui-controls/src/instrument-search/InstrumentSearch.tsx
@@ -1,4 +1,4 @@
-import { DataSource } from "@finos/vuu-data";
+import { DataSource } from "@finos/vuu-data-types";
import { TableConfig } from "@finos/vuu-table-types";
import { registerComponent } from "@finos/vuu-layout";
@@ -8,16 +8,19 @@ import {
useControlledTableNavigation,
} from "@finos/vuu-table";
import { Input } from "@salt-ds/core";
-import cx from "classnames";
+import cx from "clsx";
import { HTMLAttributes, RefCallback, useCallback } from "react";
-import "./SearchCell";
+import { SearchCell } from "./SearchCell";
import "./InstrumentSearch.css";
-import { VuuTable } from "packages/vuu-protocol-types";
import { useInstrumentSearch } from "./useInstrumentSearch";
const classBase = "vuuInstrumentSearch";
+if (typeof SearchCell !== "function") {
+ console.warn("Instrument Search: SearchCell module not loaded ");
+}
+
const defaultTableConfig: TableConfig = {
columns: [
{ name: "bbg", hidden: true },
@@ -38,10 +41,9 @@ const defaultTableConfig: TableConfig = {
export interface InstrumentSearchProps extends HTMLAttributes {
TableProps?: Partial;
autoFocus?: boolean;
- dataSource?: DataSource;
+ dataSource: DataSource;
placeHolder?: string;
searchColumns?: string[];
- table?: VuuTable;
}
const searchIcon = ;
@@ -53,13 +55,11 @@ export const InstrumentSearch = ({
dataSource: dataSourceProp,
placeHolder,
searchColumns,
- table,
...htmlAttributes
}: InstrumentSearchProps) => {
const { dataSource, onChange, searchState } = useInstrumentSearch({
dataSource: dataSourceProp,
searchColumns,
- table,
});
const { highlightedIndexRef, onHighlight, onKeyDown, tableRef } =
diff --git a/vuu-ui/packages/vuu-ui-controls/src/instrument-search/useDataSource.ts b/vuu-ui/packages/vuu-ui-controls/src/instrument-search/useDataSource.ts
index 4fe080729..9dafe4575 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/instrument-search/useDataSource.ts
+++ b/vuu-ui/packages/vuu-ui-controls/src/instrument-search/useDataSource.ts
@@ -1,7 +1,10 @@
//TODO stansardise this
-import { DataSource, SubscribeCallback } from "@finos/vuu-data";
-import { DataSourceRow } from "@finos/vuu-data-types";
+import {
+ DataSource,
+ DataSourceRow,
+ SubscribeCallback,
+} from "@finos/vuu-data-types";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { MovingWindow } from "./moving-window";
export interface DataSourceHookProps {
diff --git a/vuu-ui/packages/vuu-ui-controls/src/instrument-search/useInstrumentSearch.ts b/vuu-ui/packages/vuu-ui-controls/src/instrument-search/useInstrumentSearch.ts
index 3f90ca8e0..237ba5557 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/instrument-search/useInstrumentSearch.ts
+++ b/vuu-ui/packages/vuu-ui-controls/src/instrument-search/useInstrumentSearch.ts
@@ -1,25 +1,15 @@
-import { DataSource, RemoteDataSource } from "@finos/vuu-data";
-import { getVuuTableSchema } from "@finos/vuu-data-react";
-import { useViewContext } from "@finos/vuu-layout";
import { FormEventHandler, useCallback, useMemo, useState } from "react";
import { InstrumentSearchProps } from "./InstrumentSearch";
export interface InstrumentSearchHookProps
- extends Pick<
- InstrumentSearchProps,
- "dataSource" | "searchColumns" | "table"
- > {
+ extends Pick {
label?: string;
}
export const useInstrumentSearch = ({
- dataSource: dataSourceProp,
+ dataSource,
searchColumns = ["description"],
- table,
}: InstrumentSearchHookProps) => {
- const [dataSource, setDataSource] = useState(dataSourceProp);
- const { loadSession, saveSession } = useViewContext();
-
const [searchState, setSearchState] = useState<{
searchText: string;
filter: string;
@@ -31,32 +21,6 @@ export const useInstrumentSearch = ({
[searchColumns]
);
- useMemo(() => {
- if (dataSourceProp === undefined) {
- if (table) {
- const sessionKey = `instrument-search-${table.module}-${table.table}`;
- const dataSource = loadSession?.(sessionKey) as DataSource;
- if (dataSource) {
- setDataSource(dataSource);
- } else {
- getVuuTableSchema(table).then((tableSchema) => {
- const newDataSource = new RemoteDataSource({
- columns: tableSchema.columns.map((col) => col.name),
- // sort: { sortDefs: [{ column: "description", sortType: "A" }] },
- table: tableSchema.table,
- });
- setDataSource(newDataSource);
- saveSession?.(newDataSource, sessionKey);
- });
- }
- } else {
- throw Error(
- `useInstrumentSearch, if dataSource ismnot provided as prop, Vuu table must be provided`
- );
- }
- }
- }, [dataSourceProp, loadSession, saveSession, table]);
-
const handleChange = useCallback(
(evt) => {
const { value } = evt.target as HTMLInputElement;
diff --git a/vuu-ui/packages/vuu-ui-controls/src/list/CheckboxIcon.tsx b/vuu-ui/packages/vuu-ui-controls/src/list/CheckboxIcon.tsx
index 4521b67e6..ab0701a16 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/list/CheckboxIcon.tsx
+++ b/vuu-ui/packages/vuu-ui-controls/src/list/CheckboxIcon.tsx
@@ -1,7 +1,7 @@
// TODO why do we need explicit React import - its not needed anywhere else
// but we see a 'React is not defined' issue in showcase without it
import React, { HTMLAttributes } from "react";
-import cx from "classnames";
+import cx from "clsx";
import "./CheckboxIcon.css";
diff --git a/vuu-ui/packages/vuu-ui-controls/src/list/ChevronIcon.tsx b/vuu-ui/packages/vuu-ui-controls/src/list/ChevronIcon.tsx
index 25e060d61..851849b80 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/list/ChevronIcon.tsx
+++ b/vuu-ui/packages/vuu-ui-controls/src/list/ChevronIcon.tsx
@@ -1,4 +1,4 @@
-import cx from "classnames";
+import cx from "clsx";
import { HTMLAttributes } from "react";
import "./ChevronIcon.css";
@@ -13,7 +13,5 @@ interface ChevronProps extends HTMLAttributes {
export const ChevronIcon = (props: ChevronProps) => {
const { direction, ...htmlAttributes } = props;
- return (
-
- )
+ return ;
};
diff --git a/vuu-ui/packages/vuu-ui-controls/src/list/List.tsx b/vuu-ui/packages/vuu-ui-controls/src/list/List.tsx
index 18e56040e..ad2b5d9a2 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/list/List.tsx
+++ b/vuu-ui/packages/vuu-ui-controls/src/list/List.tsx
@@ -1,6 +1,7 @@
-import { MeasuredContainer, MeasuredSize, useId } from "@finos/vuu-layout";
+import { MeasuredContainer, MeasuredSize } from "@finos/vuu-layout";
+import { useId } from "@finos/vuu-utils";
import { useForkRef } from "@salt-ds/core";
-import cx from "classnames";
+import cx from "clsx";
import {
cloneElement,
ForwardedRef,
@@ -11,18 +12,18 @@ import {
useRef,
useState,
} from "react";
-import {
- isSelected,
- LIST_FOCUS_VISIBLE,
- useCollectionItems,
- useImperativeScrollingAPI,
-} from "./common-hooks";
import {
CollectionIndexer,
CollectionItem,
itemToString as defaultItemToString,
SelectionStrategy,
} from "../common-hooks";
+import {
+ isSelected,
+ LIST_FOCUS_VISIBLE,
+ useCollectionItems,
+ useImperativeScrollingAPI,
+} from "./common-hooks";
import { ListItem as DefaultListItem, ListItemProxy } from "./ListItem";
import { ListItemProps, ListProps } from "./listTypes";
diff --git a/vuu-ui/packages/vuu-ui-controls/src/list/ListItem.tsx b/vuu-ui/packages/vuu-ui-controls/src/list/ListItem.tsx
index cafbbfbc2..745071a93 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/list/ListItem.tsx
+++ b/vuu-ui/packages/vuu-ui-controls/src/list/ListItem.tsx
@@ -1,5 +1,5 @@
import { ForwardedRef, forwardRef, HTMLAttributes } from "react";
-import cx from "classnames";
+import cx from "clsx";
import { ListItemProps, ListItemType } from "./listTypes";
import { Highlighter } from "./Highlighter";
import { CheckboxIcon } from "./CheckboxIcon";
diff --git a/vuu-ui/packages/vuu-ui-controls/src/list/RadioIcon.tsx b/vuu-ui/packages/vuu-ui-controls/src/list/RadioIcon.tsx
index db2423404..0b514a7ba 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/list/RadioIcon.tsx
+++ b/vuu-ui/packages/vuu-ui-controls/src/list/RadioIcon.tsx
@@ -1,13 +1,10 @@
-import cx from "classnames";
+import cx from "clsx";
import "./RadioIcon.css";
const classBase = "vuuRadioIcon";
-export const RadioIcon = ({
- checked = false,
- ...htmlAttributes
-}) => (
+export const RadioIcon = ({ checked = false, ...htmlAttributes }) => (
) =>
Array.isArray(item.childNodes);
// TODO how do we determine this and where does this function belong = in the collectionHook ?
-const canSelectItem = (item: CollectionItem) => true;
+const canSelectItem = (_: CollectionItem) => true;
const toggleIconClicked = (el: HTMLElement) => {
const closestToggle = el.closest(
diff --git a/vuu-ui/packages/vuu-ui-controls/src/list/common-hooks/utils/collection-item-utils.ts b/vuu-ui/packages/vuu-ui-controls/src/list/common-hooks/utils/collection-item-utils.ts
index 68782b4a3..511005e04 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/list/common-hooks/utils/collection-item-utils.ts
+++ b/vuu-ui/packages/vuu-ui-controls/src/list/common-hooks/utils/collection-item-utils.ts
@@ -154,7 +154,7 @@ export const sourceItems = (
];
} else {
return source.map(
- (item: { description?: string; expanded?: boolean }, index) =>
+ (item: { description?: string; expanded?: boolean }) =>
({
childNodes: sourceItems(
(item as unknown as SourceGroup).childNodes,
diff --git a/vuu-ui/packages/vuu-ui-controls/src/list/useList.ts b/vuu-ui/packages/vuu-ui-controls/src/list/useList.ts
index cfe5d99cd..4e34c13ac 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/list/useList.ts
+++ b/vuu-ui/packages/vuu-ui-controls/src/list/useList.ts
@@ -1,4 +1,4 @@
-import { useLayoutEffectSkipFirst } from "@finos/vuu-layout";
+import { useLayoutEffectSkipFirst } from "@finos/vuu-utils";
import {
KeyboardEvent,
MouseEvent,
diff --git a/vuu-ui/packages/vuu-ui-controls/src/price-ticker/PriceTicker.tsx b/vuu-ui/packages/vuu-ui-controls/src/price-ticker/PriceTicker.tsx
index 454b13c67..8d9cd57ae 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/price-ticker/PriceTicker.tsx
+++ b/vuu-ui/packages/vuu-ui-controls/src/price-ticker/PriceTicker.tsx
@@ -5,7 +5,7 @@ import {
valueChangeDirection,
} from "@finos/vuu-utils";
import { HTMLAttributes, memo, useMemo, useRef } from "react";
-import cx from "classnames";
+import cx from "clsx";
const classBase = "vuuPriceTicker";
diff --git a/vuu-ui/packages/vuu-ui-controls/src/tabstrip/Tab.tsx b/vuu-ui/packages/vuu-ui-controls/src/tabstrip/Tab.tsx
index dc6276f79..195d00d2d 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/tabstrip/Tab.tsx
+++ b/vuu-ui/packages/vuu-ui-controls/src/tabstrip/Tab.tsx
@@ -1,6 +1,6 @@
// TODO close button needs to be a button. Hence tab needs to include 2 buttons
import { useForkRef } from "@salt-ds/core";
-import cx from "classnames";
+import cx from "clsx";
import { MenuActionHandler } from "@finos/vuu-data-types";
import {
FocusEvent,
diff --git a/vuu-ui/packages/vuu-ui-controls/src/tabstrip/TabMenu.tsx b/vuu-ui/packages/vuu-ui-controls/src/tabstrip/TabMenu.tsx
index e4d1bfe94..41e4a9703 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/tabstrip/TabMenu.tsx
+++ b/vuu-ui/packages/vuu-ui-controls/src/tabstrip/TabMenu.tsx
@@ -5,7 +5,7 @@ import {
MenuBuilder,
} from "@finos/vuu-data-types";
import { useMemo } from "react";
-import cx from "classnames";
+import cx from "clsx";
import { closeCommand, MenuOptions, renameCommand } from "./TabMenuOptions";
import "./TabMenu.css";
@@ -57,7 +57,13 @@ export const TabMenu = ({
tabIndex: index,
},
],
- [allowClose, allowRename, controlledComponentId, index]
+ [
+ allowClose,
+ allowRename,
+ controlledComponentId,
+ controlledComponentTitle,
+ index,
+ ]
);
return (
@@ -69,6 +75,7 @@ export const TabMenu = ({
menuOptions={menuOptions}
onMenuClose={onMenuClose}
tabIndex={-1}
+ aria-label="context menu"
/>
);
};
diff --git a/vuu-ui/packages/vuu-ui-controls/src/tabstrip/Tabstrip.tsx b/vuu-ui/packages/vuu-ui-controls/src/tabstrip/Tabstrip.tsx
index 1ebb1a1f8..fa84d4214 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/tabstrip/Tabstrip.tsx
+++ b/vuu-ui/packages/vuu-ui-controls/src/tabstrip/Tabstrip.tsx
@@ -1,6 +1,7 @@
-import { asReactElements, OverflowContainer, useId } from "@finos/vuu-layout";
+import { asReactElements, OverflowContainer } from "@finos/vuu-layout";
+import { useId } from "@finos/vuu-utils";
import { Button } from "@salt-ds/core";
-import cx from "classnames";
+import cx from "clsx";
import React, { useMemo, useRef } from "react";
import { TabProps, TabstripProps } from "./TabsTypes";
import { useTabstrip } from "./useTabstrip";
@@ -142,6 +143,7 @@ export const Tabstrip = ({
overflowIcon="more-horiz"
ref={rootRef}
style={style}
+ role="tablist"
>
{tabs}
diff --git a/vuu-ui/packages/vuu-ui-controls/src/tree/Tree.tsx b/vuu-ui/packages/vuu-ui-controls/src/tree/Tree.tsx
index e03b44012..ceb61922b 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/tree/Tree.tsx
+++ b/vuu-ui/packages/vuu-ui-controls/src/tree/Tree.tsx
@@ -1,5 +1,5 @@
import { useForkRef, useIdMemo as useId } from "@salt-ds/core";
-import cx from "classnames";
+import cx from "clsx";
import {
ForwardedRef,
forwardRef,
diff --git a/vuu-ui/packages/vuu-ui-controls/src/vuu-input/VuuInput.tsx b/vuu-ui/packages/vuu-ui-controls/src/vuu-input/VuuInput.tsx
index 00c3444d6..cd1ab740e 100644
--- a/vuu-ui/packages/vuu-ui-controls/src/vuu-input/VuuInput.tsx
+++ b/vuu-ui/packages/vuu-ui-controls/src/vuu-input/VuuInput.tsx
@@ -1,7 +1,8 @@
+import { Tooltip, useTooltip } from "@finos/vuu-popups";
import { VuuRowDataItemType } from "@finos/vuu-protocol-types";
-import { isValidNumber } from "@finos/vuu-utils";
+import { isValidNumber, useId } from "@finos/vuu-utils";
import { Input, InputProps } from "@salt-ds/core";
-import cx from "classnames";
+import cx from "clsx";
import {
FocusEventHandler,
ForwardedRef,
@@ -11,8 +12,6 @@ import {
SyntheticEvent,
useCallback,
} from "react";
-import { Tooltip, useTooltip } from "@finos/vuu-popups";
-import { useId } from "@finos/vuu-layout";
import "./VuuInput.css";
diff --git a/vuu-ui/packages/vuu-utils/package.json b/vuu-ui/packages/vuu-utils/package.json
index 9302ed323..6c16269d7 100644
--- a/vuu-ui/packages/vuu-utils/package.json
+++ b/vuu-ui/packages/vuu-utils/package.json
@@ -11,12 +11,14 @@
"type-defs": "node ../../scripts/build-type-defs.mjs"
},
"devDependencies": {
+ "@finos/vuu-data-types": "0.0.26",
"@finos/vuu-table-types": "0.0.26",
"@finos/vuu-filter-types": "0.0.26",
"@finos/vuu-protocol-types": "0.0.26"
},
"peerDependencies": {
- "react": "^17.0.2",
- "react-dom": "^17.0.2"
- }
+ "react": ">=17.0.2",
+ "react-dom": ">=17.0.2"
+ },
+ "sideEffects": false
}
diff --git a/vuu-ui/packages/vuu-shell/src/theme-provider/ThemeProvider.tsx b/vuu-ui/packages/vuu-utils/src/ThemeProvider.tsx
similarity index 97%
rename from vuu-ui/packages/vuu-shell/src/theme-provider/ThemeProvider.tsx
rename to vuu-ui/packages/vuu-utils/src/ThemeProvider.tsx
index 660e95bc7..10a322d72 100644
--- a/vuu-ui/packages/vuu-shell/src/theme-provider/ThemeProvider.tsx
+++ b/vuu-ui/packages/vuu-utils/src/ThemeProvider.tsx
@@ -6,7 +6,7 @@ import React, {
cloneElement,
useContext,
} from "react";
-import cx from "classnames";
+import cx from "clsx";
export const DEFAULT_DENSITY: Density = "medium";
export const DEFAULT_THEME = "salt-theme";
@@ -83,7 +83,7 @@ const createThemedChildren = (
} else {
console.warn(
`\nThemeProvider can only apply CSS classes for theming to a single nested child element of the ThemeProvider.
- Wrap elements with a single container`
+ Wrap elements with a single container`
);
return children;
}
diff --git a/vuu-ui/packages/vuu-utils/src/column-utils.ts b/vuu-ui/packages/vuu-utils/src/column-utils.ts
index f61cddd1e..2e9ccb66a 100644
--- a/vuu-ui/packages/vuu-utils/src/column-utils.ts
+++ b/vuu-ui/packages/vuu-utils/src/column-utils.ts
@@ -1,34 +1,39 @@
-import type { SchemaColumn, TableSchema } from "@finos/vuu-data";
-import type { DataSourceFilter, DataSourceRow } from "@finos/vuu-data-types";
+import type {
+ DataSourceFilter,
+ DataSourceRow,
+ SchemaColumn,
+ TableSchema,
+} from "@finos/vuu-data-types";
+import type { Filter, MultiClauseFilter } from "@finos/vuu-filter-types";
+import type {
+ VuuAggregation,
+ VuuAggType,
+ VuuColumnDataType,
+ VuuDataRow,
+ VuuGroupBy,
+ VuuRowRecord,
+ VuuSort,
+} from "@finos/vuu-protocol-types";
import type {
ColumnAlignment,
ColumnDescriptor,
ColumnType,
ColumnTypeDescriptor,
+ ColumnTypeFormatting,
ColumnTypeRendering,
+ ColumnTypeSimple,
ColumnTypeWithValidationRules,
+ DefaultColumnConfiguration,
GroupColumnDescriptor,
- RuntimeColumnDescriptor,
+ LookupRenderer,
MappedValueTypeRenderer,
PinLocation,
+ RuntimeColumnDescriptor,
TableHeading,
TableHeadings,
- ColumnTypeFormatting,
- LookupRenderer,
ValueListRenderer,
- DateTimeColumnTypeSimple,
+ DateTimeColumnDescriptor,
} from "@finos/vuu-table-types";
-import type { Filter, MultiClauseFilter } from "@finos/vuu-filter-types";
-import type {
- VuuAggregation,
- VuuAggType,
- VuuColumnDataType,
- VuuDataRow,
- VuuGroupBy,
- VuuRowRecord,
- VuuSort,
-} from "@finos/vuu-protocol-types";
-import { DefaultColumnConfiguration } from "@finos/vuu-shell";
import type { CSSProperties } from "react";
import { moveItem } from "./array-utils";
import { isFilterClause, isMultiClauseFilter } from "./filter-utils";
@@ -127,22 +132,11 @@ export const isNumericColumn = ({ serverDataType, type }: ColumnDescriptor) => {
return false;
};
-type DateTimeColumnType =
- | DateTimeColumnTypeSimple
- | (Omit & { name: DateTimeColumnTypeSimple });
-
-export type DateTimeColumnDescriptor = Omit & {
- type: DateTimeColumnType;
-};
-
-export const isDateColumn = ({ type }: ColumnDescriptor) =>
- (isTypeDescriptor(type) ? type.name : type) === "date";
-export const isTimeColumn = ({ type }: ColumnDescriptor) =>
- (isTypeDescriptor(type) ? type.name : type) === "time";
export const isDateTimeColumn = (
column: ColumnDescriptor
): column is DateTimeColumnDescriptor =>
- isDateColumn(column) || isTimeColumn(column);
+ (isTypeDescriptor(column.type) ? column.type.name : column.type) ===
+ "date/time";
export const isPinned = (column: ColumnDescriptor) =>
typeof column.pin === "string";
@@ -161,21 +155,6 @@ export const toColumnDescriptor = (name: string): ColumnDescriptor => ({
name,
});
-export const isSimpleColumnType = (value: unknown): value is ColumnTypeSimple =>
- typeof value === "string" &&
- ["string", "number", "boolean", "json", "date", "time", "checkbox"].includes(
- value
- );
-
-export declare type ColumnTypeSimple =
- | "string"
- | "number"
- | "boolean"
- | "json"
- | "date"
- | "time"
- | "checkbox";
-
/**
*
*/
@@ -773,56 +752,41 @@ export const getDefaultColumnType = (
}
};
-export const updateColumnType = (
+export const updateColumnFormatting = <
+ T extends ColumnDescriptor = ColumnDescriptor
+>(
column: T,
formatting: ColumnTypeFormatting
): T => {
const { serverDataType, type = getDefaultColumnType(serverDataType) } =
column;
- if (typeof type === "string" || type === undefined) {
- return {
- ...column,
- type: {
- name: type,
- formatting,
- },
- } as T;
+ if (isTypeDescriptor(type)) {
+ return { ...column, type: { ...type, formatting } };
} else {
- return {
- ...column,
- type: {
- ...type,
- formatting,
- },
- } as T;
+ return { ...column, type: { name: type, formatting } };
}
};
+export function updateColumnType(
+ column: T,
+ type: ColumnTypeSimple
+): T {
+ return isTypeDescriptor(column.type)
+ ? { ...column, type: { ...column.type, name: type } }
+ : { ...column, type };
+}
+
export const updateColumnRenderProps = <
T extends ColumnDescriptor = ColumnDescriptor
>(
column: T,
renderer: ColumnTypeRendering
): T => {
- const { serverDataType, type } = column;
- if (type === undefined) {
- return {
- ...column,
- type: {
- name: getDefaultColumnType(serverDataType),
- renderer,
- },
- };
- } else if (isSimpleColumnType(type)) {
- return {
- ...column,
- type: {
- name: type,
- renderer,
- },
- };
- } else {
+ const { serverDataType, type = getDefaultColumnType(serverDataType) } =
+ column;
+
+ if (isTypeDescriptor(type)) {
return {
...column,
type: {
@@ -831,6 +795,8 @@ export const updateColumnRenderProps = <
renderer,
},
};
+ } else {
+ return { ...column, type: { name: type, renderer } };
}
};
diff --git a/vuu-ui/packages/vuu-utils/src/component-registry.ts b/vuu-ui/packages/vuu-utils/src/component-registry.ts
index cafc01cf7..5cc986061 100644
--- a/vuu-ui/packages/vuu-utils/src/component-registry.ts
+++ b/vuu-ui/packages/vuu-utils/src/component-registry.ts
@@ -4,6 +4,7 @@ import {
ColumnDescriptorCustomRenderer,
ColumnTypeRendering,
EditValidationRule,
+ HeaderCellProps,
TableCellRendererProps,
} from "@finos/vuu-table-types";
import {
@@ -11,7 +12,6 @@ import {
VuuRowDataItemType,
} from "@finos/vuu-protocol-types";
import { isTypeDescriptor, isColumnTypeRenderer } from "./column-utils";
-import { HeaderCellProps } from "@finos/vuu-table";
export interface CellConfigPanelProps extends HTMLAttributes {
onConfigChange: () => void;
@@ -33,6 +33,7 @@ export interface ConfigurationEditorProps {
export type ConfigEditorComponent = FC;
const cellRenderersMap = new Map>();
+const columnHeaderRenderersMap = new Map>();
const configEditorsMap = new Map>();
const cellConfigPanelsMap = new Map();
const editRuleValidatorsMap = new Map();
@@ -45,6 +46,8 @@ export type EditRuleValidator = (
export type ComponentType =
| "cell-renderer"
+ | "column-header-content-renderer"
+ | "column-header-label-renderer"
| "cell-config-panel"
| "data-edit-validator";
@@ -83,6 +86,16 @@ const isCellRenderer = (
component: unknown
): component is FC => type === "cell-renderer";
+const isColumnHeaderContentRenderer = (
+ type: ComponentType,
+ component: unknown
+): component is FC =>
+ type === "column-header-content-renderer";
+const isColumnHeaderLabelRenderer = (
+ type: ComponentType,
+ component: unknown
+): component is FC => type === "column-header-label-renderer";
+
const isCellConfigPanel = (
type: ComponentType,
component: unknown
@@ -107,6 +120,10 @@ export function registerComponent<
): void {
if (isCellRenderer(type, component)) {
cellRenderersMap.set(componentName, component);
+ } else if (isColumnHeaderContentRenderer(type, component)) {
+ columnHeaderRenderersMap.set(componentName, component);
+ } else if (isColumnHeaderLabelRenderer(type, component)) {
+ columnHeaderRenderersMap.set(componentName, component);
} else if (isCellConfigPanel(type, component)) {
cellConfigPanelsMap.set(componentName, component);
} else if (isEditRuleValidator(type, component)) {
@@ -144,16 +161,17 @@ export const getRegisteredCellRenderers = (
export const getCellRendererOptions = (renderName: string) =>
optionsMap.get(renderName);
-export function getCellRenderer(
- column: ColumnDescriptor,
- cellType: "cell" | "col-content" | "col-label" = "cell"
-) {
- if (cellType === "cell") {
- return dataCellRenderer(column);
- } else if (cellType === "col-label" && column.colHeaderLabelRenderer) {
- return cellRenderersMap.get(column.colHeaderLabelRenderer);
- } else if (cellType === "col-content" && column.colHeaderContentRenderer) {
- return cellRenderersMap.get(column.colHeaderContentRenderer);
+export function getCellRenderer(column: ColumnDescriptor) {
+ return dataCellRenderer(column);
+}
+export function getColumnHeaderContentRenderer(column: ColumnDescriptor) {
+ if (column.colHeaderContentRenderer) {
+ return columnHeaderRenderersMap.get(column.colHeaderContentRenderer);
+ }
+}
+export function getColumnHeaderLabelRenderer(column: ColumnDescriptor) {
+ if (column.colHeaderLabelRenderer) {
+ return columnHeaderRenderersMap.get(column.colHeaderLabelRenderer);
}
}
diff --git a/vuu-ui/packages/vuu-utils/src/datasource-action-utils.ts b/vuu-ui/packages/vuu-utils/src/datasource-action-utils.ts
new file mode 100644
index 000000000..09ac3f2ef
--- /dev/null
+++ b/vuu-ui/packages/vuu-utils/src/datasource-action-utils.ts
@@ -0,0 +1,31 @@
+import {
+ DataSourceMenusMessage,
+ DataSourceVisualLinkCreatedMessage,
+ DataSourceVisualLinkRemovedMessage,
+ DataSourceVisualLinksMessage,
+ VuuFeatureMessage,
+} from "@finos/vuu-data-types";
+import { GridAction } from "@finos/vuu-table-types";
+
+export const isVisualLinksAction = (
+ action: GridAction
+): action is DataSourceVisualLinksMessage => action.type === "vuu-links";
+
+export const isVisualLinkCreatedAction = (
+ action: GridAction
+): action is DataSourceVisualLinkCreatedMessage =>
+ action.type === "vuu-link-created";
+
+export const isVisualLinkRemovedAction = (
+ action: GridAction
+): action is DataSourceVisualLinkRemovedMessage =>
+ action.type === "vuu-link-removed";
+
+export const isViewportMenusAction = (
+ action: GridAction
+): action is DataSourceMenusMessage => action.type === "vuu-menu";
+
+export const isVuuFeatureAction = (
+ action: GridAction
+): action is VuuFeatureMessage =>
+ isViewportMenusAction(action) || isVisualLinksAction(action);
diff --git a/vuu-ui/packages/vuu-utils/src/datasource-utils.ts b/vuu-ui/packages/vuu-utils/src/datasource-utils.ts
new file mode 100644
index 000000000..5cf1f9939
--- /dev/null
+++ b/vuu-ui/packages/vuu-utils/src/datasource-utils.ts
@@ -0,0 +1,257 @@
+import {
+ ConnectionQualityMetrics,
+ ConnectionStatusMessage,
+ DataSourceConfig,
+ MenuRpcResponse,
+ RpcResponse,
+ TypeaheadSuggestionProvider,
+ VuuUIMessageIn,
+ VuuUIMessageInRPC,
+ VuuUIMessageInRPCEditReject,
+ VuuUIMessageInRPCEditResponse,
+ VuuUIMessageInTableMeta,
+ VuuUIMessageOutViewport,
+ WithFilter,
+ WithFullConfig,
+ WithGroupBy,
+ WithSort,
+} from "@finos/vuu-data-types";
+import {
+ LinkDescriptorWithLabel,
+ VuuFilter,
+ VuuSort,
+} from "@finos/vuu-protocol-types";
+
+export const NoFilter: VuuFilter = { filter: "" };
+export const NoSort: VuuSort = { sortDefs: [] };
+
+export const vanillaConfig: WithFullConfig = {
+ aggregations: [],
+ columns: [],
+ filter: NoFilter,
+ groupBy: [],
+ sort: NoSort,
+};
+
+type DataConfigPredicate = (
+ config: DataSourceConfig,
+ newConfig: DataSourceConfig
+) => boolean;
+
+const equivalentAggregations: DataConfigPredicate = (
+ { aggregations: agg1 },
+ { aggregations: agg2 }
+) =>
+ (agg1 === undefined && agg2?.length === 0) ||
+ (agg2 === undefined && agg1?.length === 0);
+
+const equivalentColumns: DataConfigPredicate = (
+ { columns: cols1 },
+ { columns: cols2 }
+) =>
+ (cols1 === undefined && cols2?.length === 0) ||
+ (cols2 === undefined && cols1?.length === 0);
+
+const equivalentFilter: DataConfigPredicate = (
+ { filter: f1 },
+ { filter: f2 }
+) =>
+ (f1 === undefined && f2?.filter === "") ||
+ (f2 === undefined && f1?.filter === "");
+
+const equivalentGroupBy: DataConfigPredicate = (
+ { groupBy: val1 },
+ { groupBy: val2 }
+) =>
+ (val1 === undefined && val2?.length === 0) ||
+ (val2 === undefined && val1?.length === 0);
+
+const equivalentSort: DataConfigPredicate = ({ sort: s1 }, { sort: s2 }) =>
+ (s1 === undefined && s2?.sortDefs.length === 0) ||
+ (s2 === undefined && s1?.sortDefs.length === 0);
+
+const exactlyTheSame = (a: unknown, b: unknown) => {
+ if (a === b) {
+ return true;
+ } else if (a === undefined && b === undefined) {
+ return true;
+ } else {
+ return false;
+ }
+};
+
+const aggregationsChanged: DataConfigPredicate = (config, newConfig) => {
+ const { aggregations: agg1 } = config;
+ const { aggregations: agg2 } = newConfig;
+ if (exactlyTheSame(agg1, agg2) || equivalentAggregations(config, newConfig)) {
+ return false;
+ } else if (agg1 === undefined || agg2 === undefined) {
+ return true;
+ } else if (agg1.length !== agg2.length) {
+ return true;
+ }
+ return agg1.some(
+ ({ column, aggType }, i) =>
+ column !== agg2[i].column || aggType !== agg2[i].aggType
+ );
+};
+
+export const columnsChanged: DataConfigPredicate = (config, newConfig) => {
+ const { columns: cols1 } = config;
+ const { columns: cols2 } = newConfig;
+
+ if (exactlyTheSame(cols1, cols2) || equivalentColumns(config, newConfig)) {
+ return false;
+ } else if (cols1 === undefined || cols2 === undefined) {
+ return true;
+ } else if (cols1?.length !== cols2?.length) {
+ return true;
+ }
+ return cols1.some((column, i) => column !== cols2?.[i]);
+};
+
+export const filterChanged: DataConfigPredicate = (c1, c2) => {
+ if (equivalentFilter(c1, c2)) {
+ return false;
+ } else {
+ return c1.filter?.filter !== c2.filter?.filter;
+ }
+};
+
+export const groupByChanged: DataConfigPredicate = (config, newConfig) => {
+ const { groupBy: g1 } = config;
+ const { groupBy: g2 } = newConfig;
+ if (exactlyTheSame(g1, g2) || equivalentGroupBy(config, newConfig)) {
+ return false;
+ } else if (g1 === undefined || g2 === undefined) {
+ return true;
+ } else if (g1?.length !== g2?.length) {
+ return true;
+ }
+ return g1.some((column, i) => column !== g2?.[i]);
+};
+
+const sortChanged: DataConfigPredicate = (config, newConfig) => {
+ const { sort: s1 } = config;
+ const { sort: s2 } = newConfig;
+ if (exactlyTheSame(s1, s2) || equivalentSort(config, newConfig)) {
+ return false;
+ } else if (s1 === undefined || s2 === undefined) {
+ return true;
+ } else if (s1?.sortDefs.length !== s2?.sortDefs.length) {
+ return true;
+ }
+ return s1.sortDefs.some(
+ ({ column, sortType }, i) =>
+ column !== s2.sortDefs[i].column || sortType !== s2.sortDefs[i].sortType
+ );
+};
+
+const visualLinkChanged: DataConfigPredicate = () => {
+ // TODO
+ return false;
+};
+
+export const configChanged = (
+ config: DataSourceConfig | undefined,
+ newConfig: DataSourceConfig | undefined
+) => {
+ if (exactlyTheSame(config, newConfig)) {
+ return false;
+ }
+
+ if (config === undefined || newConfig === undefined) {
+ return true;
+ }
+
+ return (
+ aggregationsChanged(config, newConfig) ||
+ columnsChanged(config, newConfig) ||
+ filterChanged(config, newConfig) ||
+ groupByChanged(config, newConfig) ||
+ sortChanged(config, newConfig) ||
+ visualLinkChanged(config, newConfig)
+ );
+};
+
+export const hasGroupBy = (config?: DataSourceConfig): config is WithGroupBy =>
+ config !== undefined &&
+ config.groupBy !== undefined &&
+ config.groupBy.length > 0;
+
+export const hasFilter = (config?: DataSourceConfig): config is WithFilter =>
+ config?.filter !== undefined && config.filter.filter.length > 0;
+
+export const hasSort = (config?: DataSourceConfig): config is WithSort =>
+ config?.sort !== undefined &&
+ Array.isArray(config.sort?.sortDefs) &&
+ config.sort.sortDefs.length > 0;
+
+export const isTypeaheadSuggestionProvider = (
+ source: unknown
+): source is TypeaheadSuggestionProvider =>
+ typeof (source as TypeaheadSuggestionProvider)["getTypeaheadSuggestions"] ===
+ "function";
+
+export const isTableSchema = (
+ message: VuuUIMessageIn
+): message is VuuUIMessageInTableMeta => message.type === "TABLE_META_RESP";
+
+export const isConnectionStatusMessage = (
+ msg: object | ConnectionStatusMessage
+): msg is ConnectionStatusMessage =>
+ (msg as ConnectionStatusMessage).type === "connection-status";
+
+export const isConnectionQualityMetrics = (
+ msg: object
+): msg is ConnectionQualityMetrics =>
+ (msg as ConnectionQualityMetrics).type === "connection-metrics";
+
+export const messageHasResult = (msg: object): msg is VuuUIMessageInRPC =>
+ typeof (msg as VuuUIMessageInRPC).result !== "undefined";
+
+export const isErrorResponse = (
+ response?: RpcResponse
+): response is VuuUIMessageInRPCEditReject =>
+ response !== undefined && "error" in response;
+
+export const hasAction = (
+ response?: RpcResponse
+): response is MenuRpcResponse | VuuUIMessageInRPCEditResponse =>
+ response != undefined && "action" in response;
+
+export const isViewporttMessage = (
+ msg: object
+): msg is VuuUIMessageOutViewport => "viewport" in msg;
+
+export const withConfigDefaults = (
+ config: DataSourceConfig
+): WithFullConfig & { visualLink?: LinkDescriptorWithLabel } => {
+ if (
+ config.aggregations &&
+ config.columns &&
+ config.filter &&
+ config.groupBy &&
+ config.sort
+ ) {
+ return config as WithFullConfig;
+ } else {
+ const {
+ aggregations = [],
+ columns = [],
+ filter = { filter: "" },
+ groupBy = [],
+ sort = { sortDefs: [] },
+ visualLink,
+ } = config;
+
+ return {
+ aggregations,
+ columns,
+ filter,
+ groupBy,
+ sort,
+ visualLink,
+ };
+ }
+};
diff --git a/vuu-ui/packages/vuu-utils/src/date/formatter.ts b/vuu-ui/packages/vuu-utils/src/date/formatter.ts
index 7228f1359..f661ab850 100644
--- a/vuu-ui/packages/vuu-utils/src/date/formatter.ts
+++ b/vuu-ui/packages/vuu-utils/src/date/formatter.ts
@@ -1,9 +1,9 @@
+import { isNotNullOrUndefined } from "../ts-utils";
import { DatePattern, DateTimePattern, TimePattern } from "./types";
type DateTimeFormatConfig = {
locale?: string;
options: Intl.DateTimeFormatOptions;
- postProcessor?: (s: string) => string;
};
// Time format config
@@ -31,9 +31,8 @@ const baseDateFormatOptions: Intl.DateTimeFormatOptions = {
};
const formatConfigByDatePatterns: Record = {
"dd.mm.yyyy": {
- locale: "en-GB",
+ locale: "de-De",
options: { ...baseDateFormatOptions },
- postProcessor: (s) => s.replaceAll("/", "."),
},
"dd/mm/yyyy": { locale: "en-GB", options: { ...baseDateFormatOptions } },
"dd MMM yyyy": {
@@ -55,19 +54,17 @@ const formatConfigByDatePatterns: Record = {
},
};
-const formatConfigByDateTimePatterns: Record<
- DateTimePattern,
- DateTimeFormatConfig
-> = { ...formatConfigByDatePatterns, ...formatConfigByTimePatterns };
+function getFormatConfigs(pattern: DateTimePattern) {
+ return [
+ pattern.date ? formatConfigByDatePatterns[pattern.date] : null,
+ pattern.time ? formatConfigByTimePatterns[pattern.time] : null,
+ ];
+}
export function formatDate(pattern: DateTimePattern): (d: Date) => string {
- const { locale, options, postProcessor } =
- formatConfigByDateTimePatterns[pattern];
- const dateTimeFormat = Intl.DateTimeFormat(locale, options);
+ const dateTimeFormats = getFormatConfigs(pattern)
+ .filter(isNotNullOrUndefined)
+ .map((c) => Intl.DateTimeFormat(c.locale, c.options));
- return (d) => {
- const dateStr = dateTimeFormat.format(d);
- console.log({ dateStr });
- return postProcessor ? postProcessor(dateStr) : dateStr;
- };
+ return (d) => dateTimeFormats.map((dtf) => dtf.format(d)).join(" ");
}
diff --git a/vuu-ui/packages/vuu-utils/src/date/helpers.ts b/vuu-ui/packages/vuu-utils/src/date/helpers.ts
index f78eeae28..23a735d13 100644
--- a/vuu-ui/packages/vuu-utils/src/date/helpers.ts
+++ b/vuu-ui/packages/vuu-utils/src/date/helpers.ts
@@ -1,11 +1,15 @@
-import { DateTimeColumnTypeSimple } from "@finos/vuu-table-types";
-import { DateTimeColumnDescriptor, isTypeDescriptor } from "../column-utils";
+import { DateTimeColumnDescriptor } from "@finos/vuu-table-types";
+import { isTypeDescriptor } from "../column-utils";
import { DateTimePattern, isDateTimePattern } from "./types";
-export const defaultPatternByTypes: Record<
- DateTimeColumnTypeSimple,
- DateTimePattern
-> = { time: "hh:mm:ss", date: "dd.mm.yyyy" };
+export const defaultPatternsByType = {
+ time: "hh:mm:ss",
+ date: "dd.mm.yyyy",
+} as const;
+
+export const fallbackDateTimePattern: DateTimePattern = {
+ date: defaultPatternsByType["date"],
+};
export function dateTimePattern(
type: DateTimeColumnDescriptor["type"]
@@ -14,9 +18,7 @@ export function dateTimePattern(
if (type.formatting && isDateTimePattern(type.formatting.pattern)) {
return type.formatting.pattern;
}
-
- return defaultPatternByTypes[type.name];
- } else {
- return defaultPatternByTypes[type];
}
+
+ return fallbackDateTimePattern;
}
diff --git a/vuu-ui/packages/vuu-utils/src/date/index.ts b/vuu-ui/packages/vuu-utils/src/date/index.ts
index a7c31af09..a6d6412df 100644
--- a/vuu-ui/packages/vuu-utils/src/date/index.ts
+++ b/vuu-ui/packages/vuu-utils/src/date/index.ts
@@ -1,2 +1,7 @@
export * from "./formatter";
-export { isDateTimePattern, type DateTimePattern } from "./types";
+export {
+ isDateTimePattern,
+ type DateTimePattern,
+ supportedDateTimePatterns,
+} from "./types";
+export { defaultPatternsByType, fallbackDateTimePattern } from "./helpers";
diff --git a/vuu-ui/packages/vuu-utils/src/date/types.ts b/vuu-ui/packages/vuu-utils/src/date/types.ts
index 71727a8c4..f5ae5f6dc 100644
--- a/vuu-ui/packages/vuu-utils/src/date/types.ts
+++ b/vuu-ui/packages/vuu-utils/src/date/types.ts
@@ -1,3 +1,5 @@
+import { ColumnTypeFormatting } from "@finos/vuu-table-types";
+
const supportedDatePatterns = [
"dd.mm.yyyy",
"dd/mm/yyyy",
@@ -10,17 +12,25 @@ const supportedDatePatterns = [
const supportedTimePatterns = ["hh:mm:ss", "hh:mm:ss a"] as const;
+export const supportedDateTimePatterns = {
+ date: supportedDatePatterns,
+ time: supportedTimePatterns,
+};
+
export type DatePattern = (typeof supportedDatePatterns)[number];
export type TimePattern = (typeof supportedTimePatterns)[number];
-export type DateTimePattern = DatePattern | TimePattern;
-const isDatePattern = (pattern: string): pattern is DatePattern =>
+export type DateTimePattern =
+ | { date?: DatePattern; time: TimePattern }
+ | { date: DatePattern; time?: TimePattern };
+
+const isDatePattern = (pattern?: string): pattern is DatePattern =>
supportedDatePatterns.includes(pattern as DatePattern);
-const isTimePattern = (pattern: string): pattern is TimePattern =>
+const isTimePattern = (pattern?: string): pattern is TimePattern =>
supportedTimePatterns.includes(pattern as TimePattern);
export const isDateTimePattern = (
- pattern?: string
+ pattern?: ColumnTypeFormatting["pattern"]
): pattern is DateTimePattern =>
- pattern !== undefined && (isDatePattern(pattern) || isTimePattern(pattern));
+ isDatePattern(pattern?.date) || isTimePattern(pattern?.time);
diff --git a/vuu-ui/packages/vuu-utils/src/event-emitter.ts b/vuu-ui/packages/vuu-utils/src/event-emitter.ts
index 1cd4b6b3c..7b3a5176e 100644
--- a/vuu-ui/packages/vuu-utils/src/event-emitter.ts
+++ b/vuu-ui/packages/vuu-utils/src/event-emitter.ts
@@ -13,7 +13,17 @@ function isOnlyListener(
return !Array.isArray(listeners);
}
-export class EventEmitter {
+export interface IEventEmitter {
+ addListener(event: E, listener: Events[E]): void;
+ emit(event: E, ...args: Parameters): void;
+ on(event: E, listener: Events[E]): void;
+ removeListener(event: E, listener: Events[E]): void;
+ removeAllListeners(event?: E): void;
+}
+
+export class EventEmitter
+ implements IEventEmitter
+{
#events: Map = new Map();
addListener(event: E, listener: Events[E]) {
diff --git a/vuu-ui/packages/vuu-utils/src/formatting-utils.ts b/vuu-ui/packages/vuu-utils/src/formatting-utils.ts
index 7d9e5aeac..eaa3f4d91 100644
--- a/vuu-ui/packages/vuu-utils/src/formatting-utils.ts
+++ b/vuu-ui/packages/vuu-utils/src/formatting-utils.ts
@@ -2,13 +2,13 @@ import {
ColumnDescriptor,
ColumnTypeValueMap,
ColumnTypeFormatting,
+ DateTimeColumnDescriptor,
} from "@finos/vuu-table-types";
import { roundDecimal } from "./round-decimal";
import {
isDateTimeColumn,
isTypeDescriptor,
isMappedValueTypeRenderer,
- DateTimeColumnDescriptor,
} from "./column-utils";
import { formatDate } from "./date";
import { dateTimePattern } from "./date/helpers";
diff --git a/vuu-ui/packages/vuu-utils/src/index.ts b/vuu-ui/packages/vuu-utils/src/index.ts
index bd8193117..217485db8 100644
--- a/vuu-ui/packages/vuu-utils/src/index.ts
+++ b/vuu-ui/packages/vuu-utils/src/index.ts
@@ -6,6 +6,8 @@ export * from "./component-registry";
export * from "./DataWindow";
export * from "./common-types";
export * from "./data-utils";
+export * from "./datasource-action-utils";
+export * from "./datasource-utils";
export * from "./date";
export * from "./debug-utils";
export * from "./filter-utils";
@@ -30,5 +32,8 @@ export * from "./row-utils";
export * from "./selection-utils";
export * from "./sort-utils";
export * from "./text-utils";
+export * from "./ThemeProvider";
+export * from "./ts-utils";
export * from "./url-utils";
-export * from "./screenshot-utils";
+export * from "./useId";
+export * from "./useLayoutEffectSkipFirst";
diff --git a/vuu-ui/packages/vuu-utils/src/invariant.ts b/vuu-ui/packages/vuu-utils/src/invariant.ts
index 7ead61252..9472bd841 100644
--- a/vuu-ui/packages/vuu-utils/src/invariant.ts
+++ b/vuu-ui/packages/vuu-utils/src/invariant.ts
@@ -1,8 +1,9 @@
export function invariant(condition: boolean, message: string) {
if (!condition) {
const error = new Error(message);
- error.name = 'Invariant Violation';
+ error.name = "Invariant Violation";
// TODO what is framesToPop?
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
error.framesToPop = 1; // we don't care about invariant's own frame
throw error;
diff --git a/vuu-ui/packages/vuu-utils/src/nanoid/index.ts b/vuu-ui/packages/vuu-utils/src/nanoid/index.ts
index ecee1daa5..1149dd377 100644
--- a/vuu-ui/packages/vuu-utils/src/nanoid/index.ts
+++ b/vuu-ui/packages/vuu-utils/src/nanoid/index.ts
@@ -2,9 +2,9 @@
// couldn't get original code to work as npm import without crypro warnings -
// seemed to be picking up node version, not browser version
-export const uuid = (size: number = 21): string => {
- let id: string = '';
- let bytes = crypto.getRandomValues(new Uint8Array(size));
+export const uuid = (size = 21): string => {
+ let id = '';
+ const bytes = crypto.getRandomValues(new Uint8Array(size));
// A compact alternative for `for (var i = 0; i < step; i++)`.
while (size--) {
@@ -13,7 +13,7 @@ export const uuid = (size: number = 21): string => {
// range to the 0-63 value range. Therefore, adding hacks, such
// as empty string fallback or magic numbers, is unneccessary because
// the bitmask trims bytes down to the alphabet size.
- let byte = bytes[size] & 63;
+ const byte = bytes[size] & 63;
if (byte < 36) {
// `0-9a-z`
id += byte.toString(36);
diff --git a/vuu-ui/packages/vuu-utils/src/row-utils.ts b/vuu-ui/packages/vuu-utils/src/row-utils.ts
index e2762e073..74079eb97 100644
--- a/vuu-ui/packages/vuu-utils/src/row-utils.ts
+++ b/vuu-ui/packages/vuu-utils/src/row-utils.ts
@@ -1,6 +1,6 @@
import { DataSourceRow } from "@finos/vuu-data-types";
-import { metadataKeys } from "@finos/vuu-utils";
import { MutableRefObject } from "react";
+import { metadataKeys } from "./column-utils";
const { IDX } = metadataKeys;
diff --git a/vuu-ui/packages/vuu-utils/src/screenshot-utils.ts b/vuu-ui/packages/vuu-utils/src/screenshot-utils.ts
deleted file mode 100644
index 1cee30205..000000000
--- a/vuu-ui/packages/vuu-utils/src/screenshot-utils.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { toPng } from "html-to-image";
-
-/**
- * Takes a screenshot of the given node and returns the base64 encoded image url
- * @param node Node to take screenshot of
- * @returns Base64 encoded image url
- */
-export async function takeScreenshot(node: HTMLElement) {
-
- const screenshot = await toPng(node, { cacheBust: true })
- .then((dataUrl) => {
- return dataUrl;
- })
- .catch((err) => {
- console.error("Error taking screenshot", err);
- return undefined;
- });
-
- if (!screenshot) {
- return undefined;
- }
- return screenshot;
-}
diff --git a/vuu-ui/packages/vuu-utils/src/selection-utils.ts b/vuu-ui/packages/vuu-utils/src/selection-utils.ts
index 71c433546..7f0a70eb8 100644
--- a/vuu-ui/packages/vuu-utils/src/selection-utils.ts
+++ b/vuu-ui/packages/vuu-utils/src/selection-utils.ts
@@ -1,10 +1,10 @@
-import { DataSourceRow } from "@finos/vuu-data-types";
import {
+ DataSourceRow,
RangeTuple,
Selection,
SelectionItem,
- TableSelectionModel,
-} from "@finos/vuu-table-types";
+} from "@finos/vuu-data-types";
+import { TableSelectionModel } from "@finos/vuu-table-types";
import { metadataKeys } from "./column-utils";
const NO_SELECTION: number[] = [];
diff --git a/vuu-ui/packages/vuu-utils/src/ts-utils.ts b/vuu-ui/packages/vuu-utils/src/ts-utils.ts
new file mode 100644
index 000000000..dcbb12e4c
--- /dev/null
+++ b/vuu-ui/packages/vuu-utils/src/ts-utils.ts
@@ -0,0 +1,5 @@
+export function isNotNullOrUndefined(
+ value: T | undefined | null
+): value is NonNullable {
+ return value !== undefined && value !== null;
+}
diff --git a/vuu-ui/packages/vuu-utils/src/useId.ts b/vuu-ui/packages/vuu-utils/src/useId.ts
new file mode 100644
index 000000000..e930329aa
--- /dev/null
+++ b/vuu-ui/packages/vuu-utils/src/useId.ts
@@ -0,0 +1,6 @@
+import { useMemo } from "react";
+
+let vuuComponentIdCount = 0;
+
+export const useId = (id?: string) =>
+ useMemo(() => id ?? `vuu-${++vuuComponentIdCount}`, [id]);
diff --git a/vuu-ui/packages/vuu-utils/src/useLayoutEffectSkipFirst.ts b/vuu-ui/packages/vuu-utils/src/useLayoutEffectSkipFirst.ts
new file mode 100644
index 000000000..eb7284f8b
--- /dev/null
+++ b/vuu-ui/packages/vuu-utils/src/useLayoutEffectSkipFirst.ts
@@ -0,0 +1,16 @@
+import { DependencyList, EffectCallback, useLayoutEffect, useRef } from "react";
+
+export const useLayoutEffectSkipFirst = (
+ func: EffectCallback,
+ deps: DependencyList
+) => {
+ const goodToGo = useRef(false);
+ useLayoutEffect(() => {
+ if (goodToGo.current) {
+ func();
+ } else {
+ goodToGo.current = true;
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, deps);
+};
diff --git a/vuu-ui/packages/vuu-utils/test/date/formatter.test.ts b/vuu-ui/packages/vuu-utils/test/date/formatter.test.ts
index 68df33b8a..95da9f534 100644
--- a/vuu-ui/packages/vuu-utils/test/date/formatter.test.ts
+++ b/vuu-ui/packages/vuu-utils/test/date/formatter.test.ts
@@ -6,15 +6,23 @@ const testDate = new Date(2010, 5, 12, 15, 50, 37);
describe("formatDate", () => {
it.each<{ pattern: DateTimePattern; expected: string }>([
- { pattern: "dd.mm.yyyy", expected: "12.06.2010" },
- { pattern: "dd/mm/yyyy", expected: "12/06/2010" },
- { pattern: "dd MMM yyyy", expected: "12 Jun 2010" },
- { pattern: "dd MMMM yyyy", expected: "12 June 2010" },
- { pattern: "mm/dd/yyyy", expected: "06/12/2010" },
- { pattern: "MMM dd, yyyy", expected: "Jun 12, 2010" },
- { pattern: "MMMM dd, yyyy", expected: "June 12, 2010" },
- { pattern: "hh:mm:ss", expected: "15:50:37" },
- { pattern: "hh:mm:ss a", expected: "03:50:37 pm" },
+ { pattern: { date: "dd.mm.yyyy" }, expected: "12.06.2010" },
+ { pattern: { date: "dd/mm/yyyy" }, expected: "12/06/2010" },
+ { pattern: { date: "dd MMM yyyy" }, expected: "12 Jun 2010" },
+ { pattern: { date: "dd MMMM yyyy" }, expected: "12 June 2010" },
+ { pattern: { date: "mm/dd/yyyy" }, expected: "06/12/2010" },
+ { pattern: { date: "MMM dd, yyyy" }, expected: "Jun 12, 2010" },
+ { pattern: { date: "MMMM dd, yyyy" }, expected: "June 12, 2010" },
+ { pattern: { time: "hh:mm:ss" }, expected: "15:50:37" },
+ { pattern: { time: "hh:mm:ss a" }, expected: "03:50:37 pm" },
+ {
+ pattern: { date: "dd.mm.yyyy", time: "hh:mm:ss a" },
+ expected: "12.06.2010 03:50:37 pm",
+ },
+ {
+ pattern: { date: "MMMM dd, yyyy", time: "hh:mm:ss a" },
+ expected: "June 12, 2010 03:50:37 pm",
+ },
])(
"can correctly format date with the given pattern $pattern",
({ pattern, expected }) => {
diff --git a/vuu-ui/packages/vuu-utils/test/date/helpers.test.ts b/vuu-ui/packages/vuu-utils/test/date/helpers.test.ts
index ab6974055..8a34cf6d4 100644
--- a/vuu-ui/packages/vuu-utils/test/date/helpers.test.ts
+++ b/vuu-ui/packages/vuu-utils/test/date/helpers.test.ts
@@ -1,28 +1,31 @@
import { describe, expect, it } from "vitest";
-import { dateTimePattern, defaultPatternByTypes } from "../../src/date/helpers";
+import {
+ dateTimePattern,
+ fallbackDateTimePattern,
+} from "../../src/date/helpers";
import { DateTimePattern } from "../../src/date/types";
-const testPattern: DateTimePattern = "mm/dd/yyyy";
+const testPattern: DateTimePattern = { date: "mm/dd/yyyy" };
describe("dateTimePattern", () => {
it("returns exact pattern when found in descriptor type", () => {
const type = {
- name: "date" as const,
+ name: "date/time" as const,
formatting: { pattern: testPattern },
};
const actualPattern = dateTimePattern(type);
expect(actualPattern).toEqual(testPattern);
});
- it("falls back to default when pattern not found in descriptor type", () => {
- const type = { name: "time" as const, formatting: {} };
+ it("fallback pattern when pattern not found in descriptor type", () => {
+ const type = { name: "date/time" as const, formatting: {} };
const actualPattern = dateTimePattern(type);
- expect(actualPattern).toEqual(defaultPatternByTypes["time"]);
+ expect(actualPattern).toEqual(fallbackDateTimePattern);
});
- it("falls back to default when simple type", () => {
- const type = "date";
+ it("fallback pattern when simple type", () => {
+ const type = "date/time";
const actualPattern = dateTimePattern(type);
- expect(actualPattern).toEqual(defaultPatternByTypes["date"]);
+ expect(actualPattern).toEqual(fallbackDateTimePattern);
});
});
diff --git a/vuu-ui/packages/vuu-utils/test/date/types.test.ts b/vuu-ui/packages/vuu-utils/test/date/types.test.ts
index 3f35da7d5..33e094f9a 100644
--- a/vuu-ui/packages/vuu-utils/test/date/types.test.ts
+++ b/vuu-ui/packages/vuu-utils/test/date/types.test.ts
@@ -1,13 +1,15 @@
import { describe, expect, it } from "vitest";
import { isDateTimePattern } from "../../src/date/types";
+import { ColumnTypeFormatting } from "@finos/vuu-table-types";
describe("isDateTimePattern", () => {
- it.each<{ pattern: string | undefined; expected: boolean }>([
- { pattern: "dd MMM yyyy", expected: true },
- { pattern: "not-a-date-time-pattern", expected: false },
+ it.each<{ pattern: ColumnTypeFormatting["pattern"]; expected: boolean }>([
+ { pattern: { date: "dd MMM yyyy" }, expected: true },
+ { pattern: { time: "hh:mm:ss a" }, expected: true },
+ { pattern: { date: "dd/mm/yyyy", time: "hh:mm:ss" }, expected: true },
{ pattern: undefined, expected: false },
])(
- "returns $expected when pattern is a DateTimePattern",
+ "returns true only when pattern is a DateTimePattern",
({ pattern, expected }) => {
const actual = isDateTimePattern(pattern);
expect(actual).toEqual(expected);
diff --git a/vuu-ui/packages/vuu-utils/test/row-utils.test.ts b/vuu-ui/packages/vuu-utils/test/row-utils.test.ts
index 848bae578..01c1a536c 100644
--- a/vuu-ui/packages/vuu-utils/test/row-utils.test.ts
+++ b/vuu-ui/packages/vuu-utils/test/row-utils.test.ts
@@ -1,4 +1,4 @@
-import { DataSourceRow } from "@finos/vuu-data";
+import { DataSourceRow } from "@finos/vuu-data-types";
import { describe, expect, it } from "vitest";
import { actualRowPositioning, virtualRowPositioning } from "../src/row-utils";
diff --git a/vuu-ui/packages/vuu-utils/test/utils.ts b/vuu-ui/packages/vuu-utils/test/utils.ts
new file mode 100644
index 000000000..1dff87194
--- /dev/null
+++ b/vuu-ui/packages/vuu-utils/test/utils.ts
@@ -0,0 +1,8 @@
+import { expect } from "vitest";
+
+export const expectPromiseRejectsWithError = (
+ f: () => Promise,
+ message: string
+) => {
+ expect(f).rejects.toStrictEqual(new Error(message));
+};
diff --git a/vuu-ui/sample-apps/app-vuu-example/demo.tsx b/vuu-ui/sample-apps/app-vuu-example/demo.tsx
index f82aa7fc9..00bbff9cc 100644
--- a/vuu-ui/sample-apps/app-vuu-example/demo.tsx
+++ b/vuu-ui/sample-apps/app-vuu-example/demo.tsx
@@ -1,7 +1,7 @@
+import { LoginPanel } from "@finos/vuu-shell";
+import { ThemeProvider, uuid } from "@finos/vuu-utils";
import React from "react";
import ReactDOM from "react-dom";
-import { LoginPanel, ThemeProvider } from "@finos/vuu-shell";
-import { uuid } from "@finos/vuu-utils";
import "@finos/vuu-icons/index.css";
import "@finos/vuu-theme/index.css";
diff --git a/vuu-ui/sample-apps/app-vuu-example/login.tsx b/vuu-ui/sample-apps/app-vuu-example/login.tsx
index 925da5457..e208f0a97 100644
--- a/vuu-ui/sample-apps/app-vuu-example/login.tsx
+++ b/vuu-ui/sample-apps/app-vuu-example/login.tsx
@@ -1,11 +1,11 @@
+import { authenticate } from "@finos/vuu-data-remote";
+import { LoginPanel } from "@finos/vuu-shell";
+import { ThemeProvider } from "@finos/vuu-utils";
import React from "react";
import ReactDOM from "react-dom";
-import { LoginPanel, ThemeProvider } from "@finos/vuu-shell";
-import { authenticate } from "@finos/vuu-data";
import "@finos/vuu-icons/index.css";
import "@finos/vuu-theme/index.css";
-
import "./login.css";
async function login(username: string, password = "password") {
diff --git a/vuu-ui/sample-apps/app-vuu-example/package.json b/vuu-ui/sample-apps/app-vuu-example/package.json
index c95685008..a0781411f 100644
--- a/vuu-ui/sample-apps/app-vuu-example/package.json
+++ b/vuu-ui/sample-apps/app-vuu-example/package.json
@@ -17,7 +17,7 @@
"devDependencies": {},
"dependencies": {
"@fontsource/open-sans": "^4.5.13",
- "@salt-ds/core": "1.8.0",
+ "@salt-ds/core": "1.13.2",
"@salt-ds/lab": "1.0.0-alpha.15",
"@finos/vuu-data": "0.0.26",
"@finos/vuu-table-types": "0.0.26",
@@ -26,9 +26,9 @@
"@finos/vuu-popups": "0.0.26",
"@finos/vuu-shell": "0.0.26",
"@finos/vuu-utils": "0.0.26",
- "classnames": "^2.3.1",
- "react": "^17.0.2",
- "react-dom": "^17.0.2"
+ "clsx": "^2.0.0",
+ "react": ">=17.0.2",
+ "react-dom": ">=17.0.2"
},
"engines": {
"node": ">=16.0.0"
diff --git a/vuu-ui/sample-apps/app-vuu-example/src/columnMetaData.ts b/vuu-ui/sample-apps/app-vuu-example/src/columnMetaData.ts
index 888487e2a..881d66b9a 100644
--- a/vuu-ui/sample-apps/app-vuu-example/src/columnMetaData.ts
+++ b/vuu-ui/sample-apps/app-vuu-example/src/columnMetaData.ts
@@ -132,7 +132,7 @@ const columnMetaData: { [key: string]: Partial } = {
label: "Created",
name: "created",
type: {
- name: "time",
+ name: "date/time",
},
},
currency: {
@@ -196,7 +196,7 @@ const columnMetaData: { [key: string]: Partial } = {
label: "Last Update",
name: "lastUpdate",
type: {
- name: "time",
+ name: "date/time",
},
},
lotSize: {
diff --git a/vuu-ui/sample-apps/app-vuu-example/src/session-editing/session-table-config.ts b/vuu-ui/sample-apps/app-vuu-example/src/session-editing/session-table-config.ts
index 91dc3cb01..3d036a6e3 100644
--- a/vuu-ui/sample-apps/app-vuu-example/src/session-editing/session-table-config.ts
+++ b/vuu-ui/sample-apps/app-vuu-example/src/session-editing/session-table-config.ts
@@ -2,7 +2,7 @@ import {
MenuRpcResponse,
OpenDialogAction,
TableSchema,
-} from "@finos/vuu-data";
+} from "@finos/vuu-data-types";
import { FormConfig, FormFieldDescriptor } from "@finos/vuu-shell";
const static_config: { [key: string]: Partial } = {
diff --git a/vuu-ui/sample-apps/app-vuu-example/src/useFeatures.ts b/vuu-ui/sample-apps/app-vuu-example/src/useFeatures.ts
index 81fe3da34..43f4f04ef 100644
--- a/vuu-ui/sample-apps/app-vuu-example/src/useFeatures.ts
+++ b/vuu-ui/sample-apps/app-vuu-example/src/useFeatures.ts
@@ -1,4 +1,5 @@
import { useVuuTables } from "@finos/vuu-data-react";
+import { TableSchema } from "@finos/vuu-data-types";
import {
FeatureProps,
Features,
@@ -6,7 +7,6 @@ import {
isWildcardSchema,
} from "@finos/vuu-shell";
import { wordify } from "@finos/vuu-utils";
-import { TableSchema } from "@finos/vuu-data";
import { useMemo } from "react";
export interface FeaturesHookProps {
@@ -27,7 +27,7 @@ export const useFeatures = ({
leftNavLocation = "vuu-tables",
...feature
} of Object.values(featuresProp)) {
- const { schema, schemas } = featureProps;
+ const { schema, schemas, ViewProps } = featureProps;
const target =
leftNavLocation === "vuu-tables" ? tableFeatures : features;
if (isWildcardSchema(schema) && tables) {
@@ -50,6 +50,7 @@ export const useFeatures = ({
ComponentProps: {
tableSchema,
},
+ ViewProps,
});
} else if (Array.isArray(schemas)) {
target.push({
@@ -63,6 +64,7 @@ export const useFeatures = ({
},
{}
),
+ ViewProps,
});
} else {
target.push(feature);
diff --git a/vuu-ui/sample-apps/app-vuu-example/src/useRpcResponseHandler.tsx b/vuu-ui/sample-apps/app-vuu-example/src/useRpcResponseHandler.tsx
index 15b6292b0..11b147d7f 100644
--- a/vuu-ui/sample-apps/app-vuu-example/src/useRpcResponseHandler.tsx
+++ b/vuu-ui/sample-apps/app-vuu-example/src/useRpcResponseHandler.tsx
@@ -1,10 +1,11 @@
import { RpcResponseHandler, useVuuTables } from "@finos/vuu-data-react";
-import { hasAction, MenuRpcResponse, TableSchema } from "@finos/vuu-data";
+import { MenuRpcResponse, TableSchema } from "@finos/vuu-data-types";
+import { SetDialog } from "@finos/vuu-popups";
+import { VuuTable } from "@finos/vuu-protocol-types";
+import { Feature, SessionEditingForm } from "@finos/vuu-shell";
+import { hasAction } from "@finos/vuu-utils";
import { useCallback } from "react";
import { getFormConfig } from "./session-editing";
-import { Feature, SessionEditingForm } from "@finos/vuu-shell";
-import { VuuTable } from "@finos/vuu-protocol-types";
-import { SetDialog } from "@finos/vuu-popups";
const withTable = (action: unknown): action is { table: VuuTable } =>
action !== null && typeof action === "object" && "table" in action;
diff --git a/vuu-ui/sample-apps/feature-basket-trading/package.json b/vuu-ui/sample-apps/feature-basket-trading/package.json
index 74fefb227..23f691808 100644
--- a/vuu-ui/sample-apps/feature-basket-trading/package.json
+++ b/vuu-ui/sample-apps/feature-basket-trading/package.json
@@ -14,28 +14,30 @@
"sideEffects": [
"**/*.css"
],
- "devDependencies": {},
+ "devDependencies": {
+ "@finos/vuu-data-types": "0.0.26",
+ "@finos/vuu-filter-types": "0.0.26",
+ "@finos/vuu-protocol-types": "0.0.26",
+ "@finos/vuu-table-types": "0.0.26"
+ },
"dependencies": {
"@finos/vuu-data": "0.0.26",
"@finos/vuu-data-react": "0.0.26",
- "@finos/vuu-table-types": "0.0.26",
"@finos/vuu-filters": "0.0.26",
- "@finos/vuu-filter-types": "0.0.26",
"@finos/vuu-layout": "0.0.26",
"@finos/vuu-popups": "0.0.26",
- "@finos/vuu-protocol-types": "0.0.26",
"@finos/vuu-shell": "0.0.26",
"@finos/vuu-table": "0.0.26",
"@finos/vuu-table-extras": "0.0.26",
"@finos/vuu-theme": "0.0.26",
"@finos/vuu-utils": "0.0.26",
- "@salt-ds/core": "1.8.0",
+ "@salt-ds/core": "1.13.2",
"@salt-ds/lab": "1.0.0-alpha.15"
},
"peerDependencies": {
- "classnames": "^2.3.1",
- "react": "^17.0.2",
- "react-dom": "^17.0.2"
+ "clsx": "^2.0.0",
+ "react": ">=17.0.2",
+ "react-dom": ">=17.0.2"
},
"engines": {
"node": ">=16.0.0"
diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/VuuBasketTradingFeature.tsx b/vuu-ui/sample-apps/feature-basket-trading/src/VuuBasketTradingFeature.tsx
index ae371c12a..3e60d8efc 100644
--- a/vuu-ui/sample-apps/feature-basket-trading/src/VuuBasketTradingFeature.tsx
+++ b/vuu-ui/sample-apps/feature-basket-trading/src/VuuBasketTradingFeature.tsx
@@ -1,4 +1,4 @@
-import { TableSchema } from "@finos/vuu-data";
+import { TableSchema } from "@finos/vuu-data-types";
import { FlexboxLayout, Stack } from "@finos/vuu-layout";
import { BasketTableEdit } from "./basket-table-edit";
import { BasketTableLive } from "./basket-table-live";
@@ -35,8 +35,12 @@ const VuuBasketTradingFeature = (props: BasketTradingFeatureProps) => {
basketSelectorProps,
dataSourceBasketTradingConstituentJoin,
dialog,
+ editConfig,
+ liveConfig,
onClickAddBasket,
onCommitBasketChange,
+ onConfigChangeEdit,
+ onConfigChangeLive,
onDropInstrument,
onSendToMarket,
onTakeOffMarket,
@@ -78,19 +82,22 @@ const VuuBasketTradingFeature = (props: BasketTradingFeatureProps) => {
diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/BasketSelector.css b/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/BasketSelector.css
index 7b309f74e..5922af5da 100644
--- a/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/BasketSelector.css
+++ b/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/BasketSelector.css
@@ -1,10 +1,8 @@
.vuuBasketSelector {
- --basket-selector-height: var(--vuuBasketSelector-height, 61px);
+ --basket-selector-height: 61px;
align-items: center;
border: solid 1px var(--vuu-color-gray-45);
border-radius: 6px;
- container-name: basket-selector;
- container-type: size;
display: inline-block;
height: var(--basket-selector-height);
min-width: 450px;
@@ -101,14 +99,3 @@
flex: 0 0 36px;
justify-content: center;
}
-
-@container basket-selector (height < 59px) {
- .vuuBasketSelector-basketDetails {
- grid-template-columns: max-content min-content min-content 1fr;
- grid-template-rows: 1fr;
- padding: 4px 8px;
- }
- label {
- display: none;
- }
-}
\ No newline at end of file
diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/BasketSelector.tsx b/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/BasketSelector.tsx
index 7b23b2d50..8b1414b3b 100644
--- a/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/BasketSelector.tsx
+++ b/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/BasketSelector.tsx
@@ -1,13 +1,17 @@
-import { DropdownBase, PriceTicker } from "@finos/vuu-ui-controls";
+import { DataSource } from "@finos/vuu-data-types";
+import {
+ DropdownBase,
+ DropdownBaseProps,
+ InstrumentSearch,
+ PriceTicker,
+} from "@finos/vuu-ui-controls";
+import { useId } from "@finos/vuu-utils";
import { Button } from "@salt-ds/core";
-import { DataSource } from "@finos/vuu-data";
-import { useId } from "@finos/vuu-layout";
-import { DropdownBaseProps, InstrumentSearch } from "@finos/vuu-ui-controls";
import { HTMLAttributes, useRef } from "react";
+import { Basket } from "../useBasketTrading";
import "./BasketSelector.css";
import { useBasketSelector } from "./useBasketSelector";
-import { Basket } from "../useBasketTrading";
const classBase = "vuuBasketSelector";
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 706d7ed0e..fa2cdf6cc 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
@@ -1,4 +1,4 @@
-import cx from "classnames";
+import cx from "clsx";
import { RowProps } from "@finos/vuu-table";
import { MouseEvent, useCallback } from "react";
diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-edit/BasketTableEdit.tsx b/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-edit/BasketTableEdit.tsx
index 0202d08bc..1c424cb57 100644
--- a/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-edit/BasketTableEdit.tsx
+++ b/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-edit/BasketTableEdit.tsx
@@ -1,12 +1,8 @@
-import { TableSchema } from "@finos/vuu-data";
-import { TableConfig } from "@finos/vuu-table-types";
import { Table, TableProps } from "@finos/vuu-table";
import {
ContextMenuConfiguration,
ContextMenuProvider,
} from "@finos/vuu-popups";
-import { useMemo } from "react";
-import columns from "./basketConstituentEditColumns";
import { ColHeaderAddSymbol } from "../cell-renderers";
import "./BasketTableEdit.css";
@@ -17,35 +13,22 @@ if (typeof ColHeaderAddSymbol !== "function") {
console.warn("BasketTableEdit not all custom cell renderers are available");
}
-export interface BasketTableEditProps extends Omit {
+export interface BasketTableEditProps extends TableProps {
contextMenuConfig: ContextMenuConfiguration;
- tableSchema: TableSchema;
}
export const BasketTableEdit = ({
contextMenuConfig,
- dataSource,
- tableSchema,
...props
}: BasketTableEditProps) => {
- const tableConfig = useMemo(
- () => ({
- columns,
- rowSeparators: true,
- }),
- []
- );
-
return (
diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-edit/basketConstituentEditColumns.ts b/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-edit/basketConstituentEditColumns.ts
index 21f5319c3..6dbaa8f37 100644
--- a/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-edit/basketConstituentEditColumns.ts
+++ b/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-edit/basketConstituentEditColumns.ts
@@ -1,4 +1,4 @@
-import { ColumnDescriptor } from "packages/vuu-table-types";
+import type { ColumnDescriptor } from "@finos/vuu-table-types";
const editable = true;
const hidden = true;
diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-live/BasketTableLive.tsx b/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-live/BasketTableLive.tsx
index e4f40c1c3..eeb1b3635 100644
--- a/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-live/BasketTableLive.tsx
+++ b/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-live/BasketTableLive.tsx
@@ -1,9 +1,5 @@
-import { TableSchema } from "@finos/vuu-data";
-import { TableConfig } from "@finos/vuu-table-types";
import { Table, TableProps } from "@finos/vuu-table";
-import { useMemo } from "react";
import { ProgressCell, SpreadCell, StatusCell } from "../cell-renderers";
-import columns from "./basketConstituentLiveColumns";
if (
typeof ProgressCell !== "function" ||
@@ -17,28 +13,12 @@ import "./BasketTableLive.css";
const classBase = "vuuBasketTableLive";
-export interface BasketTableLiveProps extends Omit {
- tableSchema: TableSchema;
-}
-
-export const BasketTableLive = ({
- tableSchema,
- ...props
-}: BasketTableLiveProps) => {
- const tableConfig = useMemo(
- () => ({
- columns,
- rowSeparators: true,
- }),
- []
- );
-
+export const BasketTableLive = ({ ...props }: TableProps) => {
return (
);
diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-live/basketConstituentLiveColumns.ts b/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-live/basketConstituentLiveColumns.ts
index 8041aba72..76048e1a1 100644
--- a/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-live/basketConstituentLiveColumns.ts
+++ b/vuu-ui/sample-apps/feature-basket-trading/src/basket-table-live/basketConstituentLiveColumns.ts
@@ -1,4 +1,4 @@
-import { ColumnDescriptor } from "packages/vuu-table-types";
+import type { ColumnDescriptor } from "@finos/vuu-table-types";
const hidden = true;
const ticking = {
diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/basket-toolbar/BasketMenu.tsx b/vuu-ui/sample-apps/feature-basket-trading/src/basket-toolbar/BasketMenu.tsx
index a63ff956f..e229aa8c9 100644
--- a/vuu-ui/sample-apps/feature-basket-trading/src/basket-toolbar/BasketMenu.tsx
+++ b/vuu-ui/sample-apps/feature-basket-trading/src/basket-toolbar/BasketMenu.tsx
@@ -5,7 +5,7 @@ import {
MenuBuilder,
} from "@finos/vuu-data-types";
import { useMemo } from "react";
-import cx from "classnames";
+import cx from "clsx";
import "./BasketMenu.css";
diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/basket-toolbar/BasketToolbar.css b/vuu-ui/sample-apps/feature-basket-trading/src/basket-toolbar/BasketToolbar.css
index a42da233b..db94ffbf3 100644
--- a/vuu-ui/sample-apps/feature-basket-trading/src/basket-toolbar/BasketToolbar.css
+++ b/vuu-ui/sample-apps/feature-basket-trading/src/basket-toolbar/BasketToolbar.css
@@ -15,7 +15,9 @@
--saltFormField-width: fit-content;
- flex: 0 0 var(--basket-toolbar-height, 75px);
+ border-bottom: solid 1px var(--vuu-color-gray-05);
+ flex: 0 0 var(--basket-toolbar-height, 110px);
+ margin-bottom: 8px;
padding: 8px 16px;
}
@@ -36,10 +38,10 @@
column-gap: 24px;
row-gap: 0px;
grid-template-columns: auto auto auto auto auto 1fr;
- grid-template-rows: 18px 18px 18px 18px;
+ grid-template-rows: 15px 15px 15px 16px 32px;
}
-.vuuBasketToolbar-on-market .vuuBasketToolbar-inner {
+.vuuBasketToolbar-on-market {
--basket-status-gridColumn: 2;
--basket-status-gridRow: 1/5;
--basket-side-gridColumn: 3;
@@ -185,234 +187,22 @@
white-space: nowrap;
}
-
@container basket-toolbar (width < 1200px) {
.vuuBasketToolbar-inner {
- grid-template-columns: auto auto auto 1fr;
- }
-
- .saltFormField-labelTop {
- align-self: center;
- grid-template-areas: "label content";
- }
- .vuuBasketToolbar-inner {
- --basket-side-gridColumn: 2;
- --basket-side-gridRow: 1/3;
- --basket-units-gridColumn: 2;
- --basket-units-gridRow: 3/5;
- --basket-notionalUsd-gridColumn: 3;
- --basket-notionalUsd-gridRow: 1/3;
- --basket-notional-gridColumn: 3;
- --basket-notional-gridRow: 3/5;
- --basket-sendtomarket-gridColumn: 4;
- }
-
- .vuuBasketToolbar-sideField {
- align-self: end;
- }
-
- .vuuBasketToolbar-sideField .saltFormFieldLabel,
- .vuuBasketToolbar-unitsField .saltFormFieldLabel {
- align-self: center;
- width: 28px;
- }
-
- .vuuBasketToolbar-side {
- --saltButton-height: 24px;
- }
- .vuuBasketToolbar-units {
- --vuuExpandoInput-height: 24px;
- }
-
- .vuuBasketToolbar-notionalUsdField {
- align-self: end;
- }
-
- .vuuBasketToolbar-notionalField {
- margin: 0;
- }
-
- .vuuBasketToolbar-notionalUsdField .saltFormFieldLabel,
- .vuuBasketToolbar-notionalField .saltFormFieldLabel {
- align-self: center;
-
- width: 70px;
- }
-
- .vuuBasketToolbar-notionalField:before {
- content: none;
- }
-
-}
-
-
-@container basket-toolbar (width < 1080px) {
- .vuuBasketToolbar-inner {
- --vuuBasketSelector-height: 36px;
- grid-template-columns: auto auto auto;
- }
-
- .saltFormField-labelTop {
- grid-template-areas: "label content";
- }
- .vuuBasketToolbar-inner {
- --basket-selector-gridRow: 1/3;
- --basket-side-gridColumn: 2;
- --basket-side-gridRow: 1/3;
- --basket-units-gridColumn: 2;
- --basket-units-gridRow: 3/5;
- --basket-notionalUsd-gridColumn: 3;
- --basket-notionalUsd-gridRow: 1/3;
- --basket-notional-gridColumn: 3;
- --basket-notional-gridRow: 3/5;
--basket-sendtomarket-gridColumn: 1;
- --basket-sendtomarket-gridRow: 3/5;
- }
-
- .vuuBasketToolbar-sideField {
- align-self: end;
- }
-
- .vuuBasketToolbar-sideField .saltFormFieldLabel,
- .vuuBasketToolbar-unitsField .saltFormFieldLabel {
- width: 28px;
- }
-
- .vuuBasketToolbar-side {
- --saltButton-height: 24px;
- }
- .vuuBasketToolbar-units {
- --vuuExpandoInput-height: 24px;
- }
-
- .vuuBasketToolbar-notionalUsdField {
- align-self: end;
- }
-
- .vuuBasketToolbar-notionalField {
- margin: 0;
- }
-
- .vuuBasketToolbar-notionalUsdField .saltFormFieldLabel,
- .vuuBasketToolbar-notionalField .saltFormFieldLabel {
- width: 70px;
- }
-
- .vuuBasketToolbar-notionalField:before {
- content: none;
- }
+ --basket-sendtomarket-gridRow: 5/6;
- .vuuBasketToolbar-sendToMarket {
- justify-self: end;
+ grid-template-columns: auto auto auto auto 1fr;
}
-
-}
-
-@container basket-toolbar-live (width < 1660px) {
-
- .vuuBasketToolbar-on-market .vuuBasketToolbar-inner {
- --basket-actions-gridColumn: 8;
- --basket-actions-gridRow: 1/3;
- --basket-takeoffmarket-gridColumn: 8;
- --basket-takeoffmarket-gridRow: 3/5;
-
- grid-template-columns: auto auto auto auto auto 1fr;
- }
-
- .vuuBasketToolbar-actions {
- align-self: end;;
- }
-
}
-
-@container basket-toolbar-live (width < 1500px) {
-
- .vuuBasketToolbar-on-market .vuuBasketToolbar-inner {
-
- --basket-side-gridColumn: 3;
- --basket-side-gridRow: 1/3;
- --basket-units-gridColumn: 3;
- --basket-units-gridRow: 3/5;
- --basket-notionalUsd-gridColumn: 4;
- --basket-notionalUsd-gridRow: 1/5;
- --basket-notional-gridColumn: 5;
- --basket-notional-gridRow: 1/5;
- --basket-pctfilled-gridColumn: 6;
- --basket-pctfilled-gridRow: 1/5;
- --basket-actions-gridColumn: 7;
- --basket-actions-gridRow: 1/5;
- --basket-takeoffmarket-gridColumn: 7;
- --basket-takeoffmarket-gridRow: 1/5;
-
-
- grid-template-columns: auto auto auto auto auto auto 1fr;
- }
-
- .vuuBasketToolbar-sideField.saltFormField-labelTop,
- .vuuBasketToolbar-unitsField.saltFormField-labelTop {
- grid-template-areas: "label content";
- }
-
- .vuuBasketToolbar-sideField {
- align-self: end;
- }
- .vuuBasketToolbar-sideField .saltFormFieldLabel,
- .vuuBasketToolbar-unitsField .saltFormFieldLabel {
- width: 28px;
- }
-
- .vuuBasketToolbar-side {
- --saltButton-height: 24px;
- }
- .vuuBasketToolbar-units {
- --vuuExpandoInput-height: 24px;
- }
-
-
-}
-
@container basket-toolbar-live (width < 1450px) {
- .vuuBasketToolbar-on-market .vuuBasketToolbar-inner {
- --vuuBasketSelector-height: 36px;
- --basket-selector-gridRow: 1/3;
- --basket-notionalUsd-gridColumn: 4;
- --basket-notionalUsd-gridRow: 1/3;
- --basket-notional-gridColumn: 4;
- --basket-notional-gridRow: 3/5;
- --basket-pctfilled-gridColumn: 5;
- --basket-pctfilled-gridRow: 1/5;
-
- --basket-actions-gridColumn: 6;
- --basket-actions-gridRow: 1/5;
+ .vuuBasketToolbar-inner {
--basket-takeoffmarket-gridColumn: 1;
- --basket-takeoffmarket-gridRow: 3/5;
-
+ --basket-takeoffmarket-gridRow: 5/6;
+
grid-template-columns: auto auto auto auto auto 1fr;
-
- }
-
- .saltFormField-labelTop {
- grid-template-areas: "label content";
- }
-
- .vuuBasketToolbar-notionalField .saltFormFieldLabel,
- .vuuBasketToolbar-notionalUsdField .saltFormFieldLabel {
- align-self: center;
- width: 70px;
- }
-
- .vuuBasketToolbar-notionalField {
- margin: 0;
}
-
- .vuuBasketToolbar-notionalField:before {
- content: none;
- }
-
- .vuuBasketToolbar-actions {
- align-self: center;
- }
-
-
+
}
+
diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/basket-toolbar/BasketToolbar.tsx b/vuu-ui/sample-apps/feature-basket-trading/src/basket-toolbar/BasketToolbar.tsx
index 2f0b4895b..0da37b7f1 100644
--- a/vuu-ui/sample-apps/feature-basket-trading/src/basket-toolbar/BasketToolbar.tsx
+++ b/vuu-ui/sample-apps/feature-basket-trading/src/basket-toolbar/BasketToolbar.tsx
@@ -6,17 +6,17 @@ import {
useEditableText,
} from "@finos/vuu-ui-controls";
import { Button, FormField, FormFieldLabel } from "@salt-ds/core";
-import {
+import type {
CommitResponse,
DataItemCommitHandler,
-} from "packages/vuu-table-types";
-import { VuuRowDataItemType } from "packages/vuu-protocol-types";
+} from "@finos/vuu-table-types";
+import type { VuuRowDataItemType } from "@finos/vuu-protocol-types";
import { HTMLAttributes, useCallback } from "react";
import { BasketSelector, BasketSelectorProps } from "../basket-selector";
import { Basket } from "../useBasketTrading";
-import { BasketStatus } from "../VuuBasketTradingFeature";
+import type { BasketStatus } from "../VuuBasketTradingFeature";
import { BasketMenu } from "./BasketMenu";
-import cx from "classnames";
+import cx from "clsx";
import "./BasketToolbar.css";
diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/cell-renderers/col-header-add-symbol/ColHeaderAddSymbol.tsx b/vuu-ui/sample-apps/feature-basket-trading/src/cell-renderers/col-header-add-symbol/ColHeaderAddSymbol.tsx
index 98e122ddf..bc8b3fa20 100644
--- a/vuu-ui/sample-apps/feature-basket-trading/src/cell-renderers/col-header-add-symbol/ColHeaderAddSymbol.tsx
+++ b/vuu-ui/sample-apps/feature-basket-trading/src/cell-renderers/col-header-add-symbol/ColHeaderAddSymbol.tsx
@@ -1,14 +1,32 @@
+import {
+ SetPropsAction,
+ useLayoutProviderDispatch,
+ useViewContext,
+} from "@finos/vuu-layout";
import { registerComponent } from "@finos/vuu-utils";
import { Button } from "@salt-ds/core";
-import { SetPropsAction, useLayoutProviderDispatch } from "@finos/vuu-layout";
-import { MouseEventHandler, useCallback } from "react";
+import type { DataSource } from "@finos/vuu-data-types";
+import type { InstrumentSearchProps } from "@finos/vuu-ui-controls/src";
+import { MouseEventHandler, useCallback, useMemo } from "react";
+
import "./ColHeaderAddSymbol.css";
-import { InstrumentSearchProps } from "packages/vuu-ui-controls/src";
const classBase = "vuuColHeaderAddSymbol";
export const ColHeaderAddSymbol = () => {
const dispatchLayoutAction = useLayoutProviderDispatch();
+ const { loadSession } = useViewContext();
+
+ const dataSource = useMemo(() => {
+ const ds = loadSession?.("data-source-basket-constituent") as DataSource;
+ if (ds) {
+ return ds;
+ } else {
+ throw Error(
+ "ColHeaderAddSymbol expects Basket Constituent datasource to be available in session store"
+ );
+ }
+ }, [loadSession]);
const handleClick = useCallback(
(e) => {
@@ -25,14 +43,14 @@ export const ColHeaderAddSymbol = () => {
allowDragDrop: "drag-copy",
id: "basket-instruments",
},
- table: { module: "BASKET", table: "basketConstituent" },
+ dataSource,
} as InstrumentSearchProps,
},
title: "Add Ticker",
},
} as SetPropsAction);
},
- [dispatchLayoutAction]
+ [dataSource, dispatchLayoutAction]
);
return (
@@ -45,6 +63,6 @@ export const ColHeaderAddSymbol = () => {
registerComponent(
"col-header-add-symbol",
ColHeaderAddSymbol,
- "cell-renderer",
+ "column-header-content-renderer",
{}
);
diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/cell-renderers/progress-cell/ProgressCell.tsx b/vuu-ui/sample-apps/feature-basket-trading/src/cell-renderers/progress-cell/ProgressCell.tsx
index 59752c338..89d73d899 100644
--- a/vuu-ui/sample-apps/feature-basket-trading/src/cell-renderers/progress-cell/ProgressCell.tsx
+++ b/vuu-ui/sample-apps/feature-basket-trading/src/cell-renderers/progress-cell/ProgressCell.tsx
@@ -5,7 +5,7 @@ import {
isValidNumber,
registerComponent,
} from "@finos/vuu-utils";
-import cx from "classnames";
+import cx from "clsx";
import { CSSProperties } from "react";
import "./ProgressCell.css";
diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/cell-renderers/status-cell/StatusCell.tsx b/vuu-ui/sample-apps/feature-basket-trading/src/cell-renderers/status-cell/StatusCell.tsx
index e5c754296..ffabfa186 100644
--- a/vuu-ui/sample-apps/feature-basket-trading/src/cell-renderers/status-cell/StatusCell.tsx
+++ b/vuu-ui/sample-apps/feature-basket-trading/src/cell-renderers/status-cell/StatusCell.tsx
@@ -1,6 +1,6 @@
import { TableCellRendererProps } from "@finos/vuu-table-types";
import { registerComponent } from "@finos/vuu-utils";
-import cx from "classnames";
+import cx from "clsx";
import "./StatusCell.css";
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 a205b28bd..1ed45b2da 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,4 @@
-import { DataSource, TableSchema } from "@finos/vuu-data";
+import { DataSource, TableSchema } from "@finos/vuu-data-types";
import {
DialogHeader,
PopupComponent as Popup,
@@ -10,7 +10,7 @@ import {
VuuInput,
} from "@finos/vuu-ui-controls";
import { Button, FormField, FormFieldLabel } from "@salt-ds/core";
-import cx from "classnames";
+import cx from "clsx";
import { DataSourceRow } from "@finos/vuu-data-types";
import { HTMLAttributes, RefCallback, useCallback, useMemo } from "react";
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 61178ca34..49ba76c1c 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,8 +1,3 @@
-import {
- ClientToServerMenuRPC,
- VuuMenu,
- VuuMenuItem,
-} from "@finos/vuu-protocol-types";
import { TableRowSelectHandler } from "@finos/vuu-table";
import { Commithandler, OpenChangeHandler } from "@finos/vuu-ui-controls";
import { buildColumnMap, metadataKeys } from "@finos/vuu-utils";
@@ -11,25 +6,6 @@ import { NewBasketPanelProps } from "./NewBasketPanel";
const { KEY } = metadataKeys;
-type Menu = VuuMenu | VuuMenuItem;
-const isMenu = (menu: Menu): menu is VuuMenu => "menus" in menu;
-const flatten = (menus: Menu[], menuItems: VuuMenuItem[] = []) => {
- menus.forEach((m) =>
- isMenu(m) ? flatten(m.menus, menuItems) : menuItems.push(m)
- );
- return menuItems;
-};
-const getRpcCommand = (menus: Menu[], selectRpcCommand?: string) => {
- const selectionMenuItems = flatten(menus).filter(
- (m) => m.context === "selected-rows"
- );
- if (selectRpcCommand) {
- return selectionMenuItems.find((m) => m.rpcName === selectRpcCommand);
- } else if (selectionMenuItems.length === 1) {
- return selectionMenuItems[0];
- }
-};
-
export type NewBasketHookProps = Pick<
NewBasketPanelProps,
"basketDataSource" | "basketSchema" | "onSaveBasket"
@@ -44,46 +20,29 @@ export const useNewBasketPanel = ({
const [basketName, setBasketName] = useState("");
const [basketId, setBasketId] = useState();
const saveButtonRef = useRef(null);
-
const saveBasket = useCallback(() => {
if (basketName && basketId) {
onSaveBasket(basketName, basketId);
- if (basketDataSource?.menu) {
- const rpcCommand = getRpcCommand(
- basketDataSource?.menu?.menus,
- "CREATE_NEW_BASKET"
- );
- if (rpcCommand) {
- basketDataSource
- .rpcCall?.({
- namedParams: {},
- params: [basketId, basketName],
- rpcName: "createBasket",
- type: "VIEW_PORT_RPC_CALL",
- })
- .then((response) => {
- console.log(`rpcResponse`, { response });
- });
- }
- } else {
- throw Error(
- "useNewBasketPanel cannot create basket, datasource has no menu"
- );
- }
+ basketDataSource
+ .rpcCall?.({
+ namedParams: {},
+ params: [basketId, basketName],
+ rpcName: "createBasket",
+ type: "VIEW_PORT_RPC_CALL",
+ })
+ .then((response) => {
+ console.log(`rpcResponse`, { response });
+ });
}
}, [basketDataSource, basketId, basketName, onSaveBasket]);
- const handleSelectBasket = useCallback(
- (row) => {
- const basketId = row[KEY] as string;
- console.log({ basketId, columnMap });
- setBasketId(basketId);
- setTimeout(() => {
- saveButtonRef.current?.focus();
- }, 60);
- },
- [columnMap]
- );
+ const handleSelectBasket = useCallback((row) => {
+ const basketId = row[KEY] as string;
+ setBasketId(basketId);
+ setTimeout(() => {
+ saveButtonRef.current?.focus();
+ }, 60);
+ }, []);
const handleChangeBasketName = useCallback>(
(evt, value) => {
diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/useBasketTrading.tsx b/vuu-ui/sample-apps/feature-basket-trading/src/useBasketTrading.tsx
index e36dcccec..c07dea64f 100644
--- a/vuu-ui/sample-apps/feature-basket-trading/src/useBasketTrading.tsx
+++ b/vuu-ui/sample-apps/feature-basket-trading/src/useBasketTrading.tsx
@@ -1,20 +1,25 @@
import { useVuuMenuActions } from "@finos/vuu-data-react";
-import { DataSourceRow } from "@finos/vuu-data-types";
+import {
+ DataSourceRow,
+ SubscribeCallback,
+ ViewportRpcResponse,
+} from "@finos/vuu-data-types";
import { useViewContext } from "@finos/vuu-layout";
-import { buildColumnMap, ColumnMap } from "@finos/vuu-utils";
import {
ContextMenuConfiguration,
NotificationLevel,
useNotifications,
} from "@finos/vuu-popups";
+import { buildColumnMap, ColumnMap } from "@finos/vuu-utils";
+import { TableConfig, TableConfigChangeHandler } from "@finos/vuu-table-types";
import { useCallback, useEffect, useMemo, useState } from "react";
import { BasketSelectorProps } from "./basket-selector";
import { BasketChangeHandler } from "./basket-toolbar";
import { NewBasketPanel } from "./new-basket-panel";
import { useBasketTradingDataSources } from "./useBasketTradingDatasources";
import { BasketTradingFeatureProps } from "./VuuBasketTradingFeature";
-import { VuuDataRow, VuuDataRowDto } from "packages/vuu-protocol-types";
-import { SubscribeCallback, ViewportRpcResponse } from "packages/vuu-data/src";
+import defaultEditColumns from "./basket-table-edit/basketConstituentEditColumns";
+import defaultLiveColumns from "./basket-table-live/basketConstituentLiveColumns";
export class Basket {
basketId: string;
@@ -52,13 +57,6 @@ export type BasketTradingHookProps = Pick<
| "basketTradingConstituentJoinSchema"
>;
-const toDataDto = (dataSourceRow: VuuDataRow, columnMap: ColumnMap) => {
- Object.entries(columnMap).reduce((dto, [colName, index]) => {
- dto[colName] = dataSourceRow[index];
- return dto;
- }, {});
-};
-
type BasketState = {
basketInstanceId?: string;
dialog?: JSX.Element;
@@ -75,6 +73,26 @@ export const useBasketTrading = ({
const { load, save } = useViewContext();
const { notify } = useNotifications();
+ const editConfig = useMemo(() => {
+ const config = load?.("basket-edit-table-config") as TableConfig;
+ return (
+ config ?? {
+ columns: defaultEditColumns,
+ rowSeparators: true,
+ }
+ );
+ }, [load]);
+
+ const liveConfig = useMemo(() => {
+ const config = load?.("basket-live-table-config") as TableConfig;
+ return (
+ config ?? {
+ columns: defaultLiveColumns,
+ rowSeparators: true,
+ }
+ );
+ }, [load]);
+
const basketConstituentMap = useMemo(
() => buildColumnMap(basketConstituentSchema.columns),
[basketConstituentSchema]
@@ -95,6 +113,7 @@ export const useBasketTrading = ({
} = useBasketTradingDataSources({
basketInstanceId,
basketSchema,
+ basketConstituentSchema,
basketTradingSchema,
basketTradingConstituentJoinSchema,
});
@@ -148,12 +167,15 @@ export const useBasketTrading = ({
}));
}, []);
- const handleSaveNewBasket = useCallback((basketName, basketId) => {
- setBasketState((state) => ({
- ...state,
- dialog: undefined,
- }));
- }, []);
+ const handleSaveNewBasket = useCallback(
+ (/*basketName, basketId*/) => {
+ setBasketState((state) => ({
+ ...state,
+ dialog: undefined,
+ }));
+ },
+ []
+ );
const handleSelectBasket = useCallback(
(basketInstanceId: string) => {
@@ -251,13 +273,13 @@ export const useBasketTrading = ({
params: [ric],
})
.then((response) => {
- if (response?.action.type === "VP_RCP_SUCCESS") {
+ if (response?.action.type === "VP_RPC_SUCCESS") {
notify?.({
type: NotificationLevel.Success,
header: "Add Constituent to Basket",
body: `${ric} added to basket`,
});
- } else if (response?.action.type === "VP_RCP_FAILURE") {
+ } else if (response?.action.type === "VP_RPC_FAILURE") {
notify?.({
type: NotificationLevel.Error,
header: "Add Constituent to Basket",
@@ -270,6 +292,27 @@ export const useBasketTrading = ({
[basketConstituentMap.ric, dataSourceBasketTradingConstituentJoin, notify]
);
+ // const handleTableConfigChange = useCallback(
+ // (config) => {
+ // save?.(config, "table-config");
+ // },
+ // [save]
+ // );
+
+ const handleConfigChangeEdit = useCallback(
+ (config) => {
+ save?.(config, "basket-edit-table-config");
+ },
+ [save]
+ );
+
+ const handleConfigChangeLive = useCallback(
+ (config) => {
+ save?.(config, "basket-live-table-config");
+ },
+ [save]
+ );
+
useEffect(() => {
dataSourceBasketTradingControl.resume?.();
return () => {
@@ -284,8 +327,12 @@ export const useBasketTrading = ({
basketDesignContextMenuConfig,
basketSelectorProps,
dataSourceBasketTradingConstituentJoin,
+ editConfig,
+ liveConfig,
onClickAddBasket: handleAddBasket,
onCommitBasketChange: handleCommitBasketChange,
+ onConfigChangeEdit: handleConfigChangeEdit,
+ onConfigChangeLive: handleConfigChangeLive,
onDropInstrument: handleDropInstrument,
onSendToMarket,
onTakeOffMarket,
diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/useBasketTradingDatasources.ts b/vuu-ui/sample-apps/feature-basket-trading/src/useBasketTradingDatasources.ts
index b58a5c9f6..cb45f1804 100644
--- a/vuu-ui/sample-apps/feature-basket-trading/src/useBasketTradingDatasources.ts
+++ b/vuu-ui/sample-apps/feature-basket-trading/src/useBasketTradingDatasources.ts
@@ -1,11 +1,11 @@
import { useViewContext } from "@finos/vuu-layout";
+import { VuuDataSource } from "@finos/vuu-data-remote";
import {
DataSource,
DataSourceConfig,
- RemoteDataSource,
TableSchema,
ViewportRpcResponse,
-} from "@finos/vuu-data";
+} from "@finos/vuu-data-types";
import { useCallback, useMemo } from "react";
import { BasketTradingFeatureProps } from "./VuuBasketTradingFeature";
import { NotificationLevel, useNotifications } from "@finos/vuu-popups";
@@ -14,16 +14,18 @@ export type basketDataSourceKey =
| "data-source-basket"
| "data-source-basket-trading-control"
| "data-source-basket-trading-search"
- | "data-source-basket-trading-constituent-join";
+ | "data-source-basket-trading-constituent-join"
+ | "data-source-basket-constituent";
const NO_CONFIG = {};
export const useBasketTradingDataSources = ({
+ basketConstituentSchema,
basketSchema,
basketInstanceId,
basketTradingSchema,
basketTradingConstituentJoinSchema,
-}: Omit & {
+}: BasketTradingFeatureProps & {
basketInstanceId: string;
}) => {
const { notify } = useNotifications();
@@ -63,13 +65,14 @@ export const useBasketTradingDataSources = ({
100,
basketFilter,
],
+ ["data-source-basket-constituent", basketConstituentSchema, 100],
];
const dataSources: DataSource[] = [];
for (const [key, schema, bufferSize, config] of dataSourceConfig) {
- let dataSource = loadSession?.(key) as RemoteDataSource;
+ let dataSource = loadSession?.(key) as VuuDataSource;
if (dataSource === undefined) {
- dataSource = new RemoteDataSource({
+ dataSource = new VuuDataSource({
...config,
bufferSize,
viewport: `${id}-${key}`,
@@ -83,10 +86,11 @@ export const useBasketTradingDataSources = ({
}
return dataSources;
}, [
+ basketInstanceId,
basketSchema,
basketTradingSchema,
- basketInstanceId,
basketTradingConstituentJoinSchema,
+ basketConstituentSchema,
loadSession,
id,
title,
@@ -103,7 +107,7 @@ export const useBasketTradingDataSources = ({
type: "VIEW_PORT_RPC_CALL",
})
.then((response) => {
- if (response?.action.type === "VP_RCP_FAILURE") {
+ if (response?.action.type === "VP_RPC_FAILURE") {
notify({
type: NotificationLevel.Error,
header: "Failed to Send to market",
@@ -116,26 +120,32 @@ export const useBasketTradingDataSources = ({
[dataSourceBasketTradingControl, notify]
);
- const handleTakeOffMarket = useCallback((basketInstanceId: string) => {
- dataSourceBasketTradingControl
- .rpcCall?.({
- namedParams: {},
- params: [basketInstanceId],
- rpcName: "takeOffMarket",
- type: "VIEW_PORT_RPC_CALL",
- })
- .then((response) => {
- if (response?.action.type === "VP_RCP_FAILURE") {
- notify({
- type: NotificationLevel.Error,
- header: "Failed to take off market",
- body: "Please contact your support team",
- });
- console.error(response.action.msg);
- }
- });
- }, []);
+ const handleTakeOffMarket = useCallback(
+ (basketInstanceId: string) => {
+ dataSourceBasketTradingControl
+ .rpcCall?.({
+ namedParams: {},
+ params: [basketInstanceId],
+ rpcName: "takeOffMarket",
+ type: "VIEW_PORT_RPC_CALL",
+ })
+ .then((response) => {
+ if (response?.action.type === "VP_RPC_FAILURE") {
+ notify({
+ type: NotificationLevel.Error,
+ header: "Failed to take off market",
+ body: "Please contact your support team",
+ });
+ console.error(response.action.msg);
+ }
+ });
+ },
+ [dataSourceBasketTradingControl, notify]
+ );
+ // Note: we do not need to return the BasketConstituent dataSource, we just stash it
+ // in session state from where it will be used by the AddInstrument button in Col
+ // Header
return {
dataSourceBasket,
dataSourceBasketTradingControl,
diff --git a/vuu-ui/sample-apps/feature-filter-table/package.json b/vuu-ui/sample-apps/feature-filter-table/package.json
index 4bb804700..56e16a730 100644
--- a/vuu-ui/sample-apps/feature-filter-table/package.json
+++ b/vuu-ui/sample-apps/feature-filter-table/package.json
@@ -29,13 +29,13 @@
"@finos/vuu-table-extras": "0.0.26",
"@finos/vuu-theme": "0.0.26",
"@finos/vuu-utils": "0.0.26",
- "@salt-ds/core": "1.8.0",
+ "@salt-ds/core": "1.13.2",
"@salt-ds/lab": "1.0.0-alpha.15"
},
"peerDependencies": {
- "classnames": "^2.3.1",
- "react": "^17.0.2",
- "react-dom": "^17.0.2"
+ "clsx": "^2.0.0",
+ "react": ">=17.0.2",
+ "react-dom": ">=17.0.2"
},
"engines": {
"node": ">=16.0.0"
diff --git a/vuu-ui/sample-apps/feature-filter-table/src/VuuFilterTableFeature.tsx b/vuu-ui/sample-apps/feature-filter-table/src/VuuFilterTableFeature.tsx
index f3a600af2..d7364af1f 100644
--- a/vuu-ui/sample-apps/feature-filter-table/src/VuuFilterTableFeature.tsx
+++ b/vuu-ui/sample-apps/feature-filter-table/src/VuuFilterTableFeature.tsx
@@ -1,9 +1,9 @@
-import { TableSchema } from "@finos/vuu-data";
+import { TableSchema } from "@finos/vuu-data-types";
import { FilterTable } from "@finos/vuu-datatable";
import { FlexboxLayout } from "@finos/vuu-layout";
-import { DataSourceStats } from "@finos/vuu-table-extras";
-import cx from "classnames";
import { ContextMenuProvider } from "@finos/vuu-popups";
+import { DataSourceStats } from "@finos/vuu-table-extras";
+import cx from "clsx";
import { useFilterTable } from "./useFilterTable";
import "./VuuFilterTableFeature.css";
diff --git a/vuu-ui/sample-apps/feature-filter-table/src/useFilterTable.tsx b/vuu-ui/sample-apps/feature-filter-table/src/useFilterTable.tsx
index 53940d3af..7ce8937d6 100644
--- a/vuu-ui/sample-apps/feature-filter-table/src/useFilterTable.tsx
+++ b/vuu-ui/sample-apps/feature-filter-table/src/useFilterTable.tsx
@@ -1,24 +1,29 @@
import {
+ MenuActionConfig,
+ SuggestionFetcher,
+ useVuuMenuActions,
+} from "@finos/vuu-data-react";
+import {
+ DataSourceFilter,
DataSourceVisualLinkCreatedMessage,
- isTypeaheadSuggestionProvider,
SchemaColumn,
TypeaheadSuggestionProvider,
VuuFeatureInvocationMessage,
-} from "@finos/vuu-data";
-import { MenuActionConfig, useVuuMenuActions } from "@finos/vuu-data-react";
-import { DataSourceFilter } from "@finos/vuu-data-types";
-import { SuggestionFetcher } from "@finos/vuu-data-react";
-import { TableConfig } from "@finos/vuu-table-types";
+} from "@finos/vuu-data-types";
import { Filter } from "@finos/vuu-filter-types";
import { FilterBarProps } from "@finos/vuu-filters";
import { ActiveItemChangeHandler, useViewContext } from "@finos/vuu-layout";
+import { TypeaheadParams } from "@finos/vuu-protocol-types";
import { useShellContext } from "@finos/vuu-shell";
-import { applyDefaultColumnConfig } from "@finos/vuu-utils";
+import { TableConfig, TableConfigChangeHandler } from "@finos/vuu-table-types";
+import {
+ applyDefaultColumnConfig,
+ isTypeaheadSuggestionProvider,
+} from "@finos/vuu-utils";
import { Button } from "@salt-ds/core";
import { useCallback, useMemo, useRef, useState } from "react";
import { useSessionDataSource } from "./useSessionDataSource";
import { FilterTableFeatureProps } from "./VuuFilterTableFeature";
-import { TypeaheadParams } from "packages/vuu-protocol-types";
const NO_CONFIG: FilterTableConfig = {};
@@ -103,8 +108,8 @@ export const useFilterTable = ({ tableSchema }: FilterTableFeatureProps) => {
[save]
);
- const handleTableConfigChange = useCallback(
- (config: TableConfig) => {
+ const handleTableConfigChange = useCallback