diff --git a/vuu-ui/package-lock.json b/vuu-ui/package-lock.json index 15c18686b..ead0139b7 100644 --- a/vuu-ui/package-lock.json +++ b/vuu-ui/package-lock.json @@ -1248,10 +1248,6 @@ "resolved": "packages/vuu-datagrid", "link": true }, - "node_modules/@finos/vuu-datagrid-types": { - "resolved": "packages/vuu-datagrid-types", - "link": true - }, "node_modules/@finos/vuu-datatable": { "resolved": "packages/vuu-datatable", "link": true @@ -1296,6 +1292,10 @@ "resolved": "packages/vuu-table-extras", "link": true }, + "node_modules/@finos/vuu-table-types": { + "resolved": "packages/vuu-table-types", + "link": true + }, "node_modules/@finos/vuu-theme": { "resolved": "packages/vuu-theme", "link": true @@ -5232,10 +5232,6 @@ "resolved": "sample-apps/feature-basket-trading", "link": true }, - "node_modules/feature-vuu-blotter": { - "resolved": "sample-apps/feature-vuu-blotter", - "link": true - }, "node_modules/feature-vuu-filter-table": { "resolved": "sample-apps/feature-filter-table", "link": true @@ -5244,10 +5240,6 @@ "resolved": "sample-apps/feature-instrument-tiles", "link": true }, - "node_modules/feature-vuu-table": { - "resolved": "sample-apps/feature-vuu-table", - "link": true - }, "node_modules/feature-vuu-template": { "resolved": "sample-apps/feature-template", "link": true @@ -11754,9 +11746,9 @@ }, "devDependencies": { "@finos/vuu-data-types": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26", "@finos/vuu-filter-types": "0.0.26", - "@finos/vuu-protocol-types": "0.0.26" + "@finos/vuu-protocol-types": "0.0.26", + "@finos/vuu-table-types": "0.0.26" } }, "packages/vuu-data-ag-grid": { @@ -11767,9 +11759,9 @@ "@finos/vuu-data": "0.0.26", "@finos/vuu-data-react": "0.0.26", "@finos/vuu-data-types": "0.0.26", - "@finos/vuu-datagrid-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", "@finos/vuu-utils": "0.0.26" }, "peerDependencies": { @@ -11787,10 +11779,10 @@ "@finos/vuu-utils": "0.0.26" }, "devDependencies": { - "@finos/vuu-datagrid-types": "0.0.26", "@finos/vuu-filter-types": "0.0.26", "@finos/vuu-popups": "0.0.26", - "@finos/vuu-protocol-types": "0.0.26" + "@finos/vuu-protocol-types": "0.0.26", + "@finos/vuu-table-types": "0.0.26" }, "peerDependencies": { "react": "^17.0.2" @@ -11802,7 +11794,7 @@ "license": "Apache-2.0", "devDependencies": { "@finos/vuu-data": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26" + "@finos/vuu-table-types": "0.0.26" } }, "packages/vuu-data-types": { @@ -11819,15 +11811,15 @@ "version": "0.0.26", "license": "Apache-2.0", "devDependencies": { - "@finos/vuu-datagrid-types": "0.0.26", "@finos/vuu-filter-types": "0.0.26", - "@finos/vuu-protocol-types": "0.0.26" + "@finos/vuu-protocol-types": "0.0.26", + "@finos/vuu-table-types": "0.0.26" }, "peerDependencies": { "@finos/vuu-data-types": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26", "@finos/vuu-filters": "0.0.26", "@finos/vuu-popups": "0.0.26", + "@finos/vuu-table-types": "0.0.26", "@finos/vuu-utils": "0.0.26", "@salt-ds/core": "1.8.0", "@salt-ds/lab": "1.0.0-alpha.15", @@ -11839,6 +11831,7 @@ "packages/vuu-datagrid-types": { "name": "@finos/vuu-datagrid-types", "version": "0.0.26", + "extraneous": true, "license": "Apache-2.0", "devDependencies": { "@finos/vuu-protocol-types": "0.0.26" @@ -11850,12 +11843,12 @@ "license": "Apache-2.0", "dependencies": { "@finos/vuu-data": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26", "@finos/vuu-filters": "0.0.26", "@finos/vuu-layout": "0.0.26", "@finos/vuu-popups": "0.0.26", "@finos/vuu-table": "0.0.26", "@finos/vuu-table-extras": "0.0.26", + "@finos/vuu-table-types": "0.0.26", "@finos/vuu-ui-controls": "0.0.26", "@finos/vuu-utils": "0.0.26" }, @@ -11899,8 +11892,8 @@ }, "devDependencies": { "@finos/vuu-data-types": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26", "@finos/vuu-filter-types": "0.0.26", + "@finos/vuu-table-types": "0.0.26", "@types/uuid": "^9.0.2" }, "peerDependencies": { @@ -12019,9 +12012,9 @@ "@finos/vuu-codemirror": "0.0.26", "@finos/vuu-data": "0.0.26", "@finos/vuu-data-react": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26", "@finos/vuu-layout": "0.0.26", "@finos/vuu-popups": "0.0.26", + "@finos/vuu-table-types": "0.0.26", "@finos/vuu-ui-controls": "0.0.26", "@finos/vuu-utils": "0.0.26", "@lezer/lr": "1.3.4", @@ -12045,6 +12038,13 @@ "@lezer/common": "^1.0.0" } }, + "packages/vuu-table-types": { + "version": "0.0.26", + "license": "Apache-2.0", + "devDependencies": { + "@finos/vuu-protocol-types": "0.0.26" + } + }, "packages/vuu-theme": { "name": "@finos/vuu-theme", "version": "0.0.26", @@ -12057,10 +12057,10 @@ "dependencies": { "@finos/vuu-data": "0.0.26", "@finos/vuu-data-types": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26", "@finos/vuu-layout": "0.0.26", "@finos/vuu-popups": "0.0.26", "@finos/vuu-table": "0.0.26", + "@finos/vuu-table-types": "0.0.26", "@finos/vuu-utils": "0.0.26", "@salt-ds/core": "1.8.0" }, @@ -12075,9 +12075,9 @@ "version": "0.0.26", "license": "Apache-2.0", "devDependencies": { - "@finos/vuu-datagrid-types": "0.0.26", "@finos/vuu-filter-types": "0.0.26", - "@finos/vuu-protocol-types": "0.0.26" + "@finos/vuu-protocol-types": "0.0.26", + "@finos/vuu-table-types": "0.0.26" }, "peerDependencies": { "react": "^17.0.2", @@ -12114,10 +12114,10 @@ "dependencies": { "@finos/vuu-data": "0.0.26", "@finos/vuu-data-react": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26", "@finos/vuu-layout": "0.0.26", "@finos/vuu-popups": "0.0.26", "@finos/vuu-shell": "0.0.26", + "@finos/vuu-table-types": "0.0.26", "@finos/vuu-utils": "0.0.26", "@fontsource/open-sans": "^4.5.13", "@salt-ds/core": "1.8.0", @@ -12137,7 +12137,6 @@ "dependencies": { "@finos/vuu-data": "0.0.26", "@finos/vuu-data-react": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26", "@finos/vuu-filter-types": "0.0.26", "@finos/vuu-filters": "0.0.26", "@finos/vuu-layout": "0.0.26", @@ -12146,6 +12145,7 @@ "@finos/vuu-shell": "0.0.26", "@finos/vuu-table": "0.0.26", "@finos/vuu-table-extras": "0.0.26", + "@finos/vuu-table-types": "0.0.26", "@finos/vuu-theme": "0.0.26", "@finos/vuu-utils": "0.0.26", "@salt-ds/core": "1.8.0", @@ -12168,7 +12168,6 @@ "dependencies": { "@finos/vuu-data": "0.0.26", "@finos/vuu-data-react": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26", "@finos/vuu-filter-types": "0.0.26", "@finos/vuu-filters": "0.0.26", "@finos/vuu-layout": "0.0.26", @@ -12177,6 +12176,7 @@ "@finos/vuu-shell": "0.0.26", "@finos/vuu-table": "0.0.26", "@finos/vuu-table-extras": "0.0.26", + "@finos/vuu-table-types": "0.0.26", "@finos/vuu-theme": "0.0.26", "@finos/vuu-utils": "0.0.26", "@salt-ds/core": "1.8.0", @@ -12199,7 +12199,6 @@ "dependencies": { "@finos/vuu-data": "0.0.26", "@finos/vuu-data-react": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26", "@finos/vuu-filter-types": "0.0.26", "@finos/vuu-filters": "0.0.26", "@finos/vuu-layout": "0.0.26", @@ -12208,6 +12207,7 @@ "@finos/vuu-shell": "0.0.26", "@finos/vuu-table": "0.0.26", "@finos/vuu-table-extras": "0.0.26", + "@finos/vuu-table-types": "0.0.26", "@finos/vuu-theme": "0.0.26", "@finos/vuu-utils": "0.0.26", "@salt-ds/core": "1.8.0", @@ -12230,7 +12230,6 @@ "dependencies": { "@finos/vuu-data": "0.0.26", "@finos/vuu-data-react": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26", "@finos/vuu-filter-types": "0.0.26", "@finos/vuu-filters": "0.0.26", "@finos/vuu-layout": "0.0.26", @@ -12239,6 +12238,7 @@ "@finos/vuu-shell": "0.0.26", "@finos/vuu-table": "0.0.26", "@finos/vuu-table-extras": "0.0.26", + "@finos/vuu-table-types": "0.0.26", "@finos/vuu-theme": "0.0.26", "@finos/vuu-utils": "0.0.26", "@salt-ds/core": "1.8.0", @@ -12256,6 +12256,7 @@ }, "sample-apps/feature-vuu-blotter": { "version": "0.0.26", + "extraneous": true, "license": "Apache-2.0", "dependencies": { "@finos/vuu-data": "0.0.26", @@ -12284,6 +12285,7 @@ }, "sample-apps/feature-vuu-table": { "version": "0.0.26", + "extraneous": true, "license": "Apache-2.0", "dependencies": { "@finos/vuu-data": "0.0.26", @@ -13099,10 +13101,10 @@ "version": "file:packages/vuu-data", "requires": { "@finos/vuu-data-types": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26", "@finos/vuu-filter-parser": "0.0.26", "@finos/vuu-filter-types": "0.0.26", "@finos/vuu-protocol-types": "0.0.26", + "@finos/vuu-table-types": "0.0.26", "@finos/vuu-utils": "0.0.26" } }, @@ -13112,9 +13114,9 @@ "@finos/vuu-data": "0.0.26", "@finos/vuu-data-react": "0.0.26", "@finos/vuu-data-types": "0.0.26", - "@finos/vuu-datagrid-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", "@finos/vuu-utils": "0.0.26" } }, @@ -13123,11 +13125,11 @@ "requires": { "@finos/vuu-data": "0.0.26", "@finos/vuu-data-types": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26", "@finos/vuu-filter-parser": "0.0.26", "@finos/vuu-filter-types": "0.0.26", "@finos/vuu-popups": "0.0.26", "@finos/vuu-protocol-types": "0.0.26", + "@finos/vuu-table-types": "0.0.26", "@finos/vuu-utils": "0.0.26" } }, @@ -13135,7 +13137,7 @@ "version": "file:packages/vuu-data-test", "requires": { "@finos/vuu-data": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26" + "@finos/vuu-table-types": "0.0.26" } }, "@finos/vuu-data-types": { @@ -13148,27 +13150,21 @@ "@finos/vuu-datagrid": { "version": "file:packages/vuu-datagrid", "requires": { - "@finos/vuu-datagrid-types": "0.0.26", "@finos/vuu-filter-types": "0.0.26", - "@finos/vuu-protocol-types": "0.0.26" - } - }, - "@finos/vuu-datagrid-types": { - "version": "file:packages/vuu-datagrid-types", - "requires": { - "@finos/vuu-protocol-types": "0.0.26" + "@finos/vuu-protocol-types": "0.0.26", + "@finos/vuu-table-types": "0.0.26" } }, "@finos/vuu-datatable": { "version": "file:packages/vuu-datatable", "requires": { "@finos/vuu-data": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26", "@finos/vuu-filters": "0.0.26", "@finos/vuu-layout": "0.0.26", "@finos/vuu-popups": "0.0.26", "@finos/vuu-table": "0.0.26", "@finos/vuu-table-extras": "0.0.26", + "@finos/vuu-table-types": "0.0.26", "@finos/vuu-ui-controls": "0.0.26", "@finos/vuu-utils": "0.0.26" } @@ -13193,9 +13189,9 @@ "@finos/vuu-data": "0.0.26", "@finos/vuu-data-react": "0.0.26", "@finos/vuu-data-types": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26", "@finos/vuu-filter-types": "0.0.26", "@finos/vuu-popups": "0.0.26", + "@finos/vuu-table-types": "0.0.26", "@finos/vuu-ui-controls": "0.0.26", "@finos/vuu-utils": "0.0.26", "@salt-ds/core": "1.8.0", @@ -13279,11 +13275,11 @@ "@finos/vuu-codemirror": "0.0.26", "@finos/vuu-data": "0.0.26", "@finos/vuu-data-react": "0.0.26", - "@finos/vuu-datagrid-types": "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-table-types": "0.0.26", "@finos/vuu-ui-controls": "0.0.26", "@finos/vuu-utils": "0.0.26", "@lezer/lr": "1.3.4", @@ -13299,6 +13295,12 @@ } } }, + "@finos/vuu-table-types": { + "version": "file:packages/vuu-table-types", + "requires": { + "@finos/vuu-protocol-types": "0.0.26" + } + }, "@finos/vuu-theme": { "version": "file:packages/vuu-theme" }, @@ -13307,10 +13309,10 @@ "requires": { "@finos/vuu-data": "0.0.26", "@finos/vuu-data-types": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26", "@finos/vuu-layout": "0.0.26", "@finos/vuu-popups": "0.0.26", "@finos/vuu-table": "0.0.26", + "@finos/vuu-table-types": "0.0.26", "@finos/vuu-utils": "0.0.26", "@salt-ds/core": "1.8.0" } @@ -13318,9 +13320,9 @@ "@finos/vuu-utils": { "version": "file:packages/vuu-utils", "requires": { - "@finos/vuu-datagrid-types": "0.0.26", "@finos/vuu-filter-types": "0.0.26", - "@finos/vuu-protocol-types": "0.0.26" + "@finos/vuu-protocol-types": "0.0.26", + "@finos/vuu-table-types": "0.0.26" } }, "@floating-ui/core": { @@ -14607,10 +14609,10 @@ "requires": { "@finos/vuu-data": "0.0.26", "@finos/vuu-data-react": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26", "@finos/vuu-layout": "0.0.26", "@finos/vuu-popups": "0.0.26", "@finos/vuu-shell": "0.0.26", + "@finos/vuu-table-types": "0.0.26", "@finos/vuu-utils": "0.0.26", "@fontsource/open-sans": "^4.5.13", "@salt-ds/core": "1.8.0", @@ -16225,7 +16227,6 @@ "requires": { "@finos/vuu-data": "0.0.26", "@finos/vuu-data-react": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26", "@finos/vuu-filter-types": "0.0.26", "@finos/vuu-filters": "0.0.26", "@finos/vuu-layout": "0.0.26", @@ -16234,36 +16235,18 @@ "@finos/vuu-shell": "0.0.26", "@finos/vuu-table": "0.0.26", "@finos/vuu-table-extras": "0.0.26", + "@finos/vuu-table-types": "0.0.26", "@finos/vuu-theme": "0.0.26", "@finos/vuu-utils": "0.0.26", "@salt-ds/core": "1.8.0", "@salt-ds/lab": "1.0.0-alpha.15" } }, - "feature-vuu-blotter": { - "version": "file:sample-apps/feature-vuu-blotter", - "requires": { - "@finos/vuu-data": "0.0.26", - "@finos/vuu-data-react": "0.0.26", - "@finos/vuu-datagrid": "0.0.26", - "@finos/vuu-filters": "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-theme": "0.0.26", - "@finos/vuu-utils": "0.0.26", - "@salt-ds/core": "1.8.0", - "@salt-ds/icons": "1.5.1", - "@salt-ds/lab": "1.0.0-alpha.15" - } - }, "feature-vuu-filter-table": { "version": "file:sample-apps/feature-filter-table", "requires": { "@finos/vuu-data": "0.0.26", "@finos/vuu-data-react": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26", "@finos/vuu-filter-types": "0.0.26", "@finos/vuu-filters": "0.0.26", "@finos/vuu-layout": "0.0.26", @@ -16272,6 +16255,7 @@ "@finos/vuu-shell": "0.0.26", "@finos/vuu-table": "0.0.26", "@finos/vuu-table-extras": "0.0.26", + "@finos/vuu-table-types": "0.0.26", "@finos/vuu-theme": "0.0.26", "@finos/vuu-utils": "0.0.26", "@salt-ds/core": "1.8.0", @@ -16283,7 +16267,6 @@ "requires": { "@finos/vuu-data": "0.0.26", "@finos/vuu-data-react": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26", "@finos/vuu-filter-types": "0.0.26", "@finos/vuu-filters": "0.0.26", "@finos/vuu-layout": "0.0.26", @@ -16292,39 +16275,18 @@ "@finos/vuu-shell": "0.0.26", "@finos/vuu-table": "0.0.26", "@finos/vuu-table-extras": "0.0.26", + "@finos/vuu-table-types": "0.0.26", "@finos/vuu-theme": "0.0.26", "@finos/vuu-utils": "0.0.26", "@salt-ds/core": "1.8.0", "@salt-ds/lab": "1.0.0-alpha.15" } }, - "feature-vuu-table": { - "version": "file:sample-apps/feature-vuu-table", - "requires": { - "@finos/vuu-data": "0.0.26", - "@finos/vuu-data-react": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26", - "@finos/vuu-filter-types": "0.0.26", - "@finos/vuu-filters": "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/icons": "1.5.1", - "@salt-ds/lab": "1.0.0-alpha.15" - } - }, "feature-vuu-template": { "version": "file:sample-apps/feature-template", "requires": { "@finos/vuu-data": "0.0.26", "@finos/vuu-data-react": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26", "@finos/vuu-filter-types": "0.0.26", "@finos/vuu-filters": "0.0.26", "@finos/vuu-layout": "0.0.26", @@ -16333,6 +16295,7 @@ "@finos/vuu-shell": "0.0.26", "@finos/vuu-table": "0.0.26", "@finos/vuu-table-extras": "0.0.26", + "@finos/vuu-table-types": "0.0.26", "@finos/vuu-theme": "0.0.26", "@finos/vuu-utils": "0.0.26", "@salt-ds/core": "1.8.0", diff --git a/vuu-ui/packages/vuu-codemirror/src/suggestion-utils.ts b/vuu-ui/packages/vuu-codemirror/src/suggestion-utils.ts index 20860c04a..f902c86e5 100644 --- a/vuu-ui/packages/vuu-codemirror/src/suggestion-utils.ts +++ b/vuu-ui/packages/vuu-codemirror/src/suggestion-utils.ts @@ -1,5 +1,5 @@ import { AnnotationType, Completion, EditorView } from "@finos/vuu-codemirror"; -import { ColumnDescriptor } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor } from "@finos/vuu-table-types"; import { isNumericColumn } from "@finos/vuu-utils"; export interface VuuCompletion extends Completion { diff --git a/vuu-ui/packages/vuu-data-ag-grid/package.json b/vuu-ui/packages/vuu-data-ag-grid/package.json index 60226a4e9..f179ce0a4 100644 --- a/vuu-ui/packages/vuu-data-ag-grid/package.json +++ b/vuu-ui/packages/vuu-data-ag-grid/package.json @@ -12,7 +12,7 @@ "@finos/vuu-data": "0.0.26", "@finos/vuu-data-react": "0.0.26", "@finos/vuu-data-types": "0.0.26", - "@finos/vuu-datagrid-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", "@finos/vuu-utils": "0.0.26" diff --git a/vuu-ui/packages/vuu-data-ag-grid/src/AgGridColumnUtils.ts b/vuu-ui/packages/vuu-data-ag-grid/src/AgGridColumnUtils.ts index 92444a129..5bee40070 100644 --- a/vuu-ui/packages/vuu-data-ag-grid/src/AgGridColumnUtils.ts +++ b/vuu-ui/packages/vuu-data-ag-grid/src/AgGridColumnUtils.ts @@ -1,4 +1,4 @@ -import { ColumnDescriptor } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor } from "@finos/vuu-table-types"; import { VuuGroupBy } from "@finos/vuu-protocol-types"; import { FilterDataProvider } from "./FilterDataProvider"; diff --git a/vuu-ui/packages/vuu-data-ag-grid/src/useViewportRowModel.ts b/vuu-ui/packages/vuu-data-ag-grid/src/useViewportRowModel.ts index e793185d2..36fd4f937 100644 --- a/vuu-ui/packages/vuu-data-ag-grid/src/useViewportRowModel.ts +++ b/vuu-ui/packages/vuu-data-ag-grid/src/useViewportRowModel.ts @@ -4,6 +4,7 @@ import { isVisualLinksAction, MenuRpcResponse, RemoteDataSource, + RpcResponseHandler, VuuFeatureMessage, VuuUIMessageInRPCEditReject, VuuUIMessageInRPCEditResponse, @@ -18,7 +19,7 @@ import { VuuServerMenuOptions, } from "@finos/vuu-data-react"; -import { ColumnDescriptor } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor } from "@finos/vuu-table-types"; import { VuuGroupBy, VuuMenu, VuuTable } from "@finos/vuu-protocol-types"; import { buildColumnMap, itemsOrOrderChanged } from "@finos/vuu-utils"; import { useCallback, useEffect, useMemo, useRef, useState } from "react"; @@ -92,12 +93,7 @@ export interface ViewportRowModelHookProps { columns?: ColumnDescriptor[]; dataSource: RemoteDataSource; onFeatureEnabled?: (message: VuuFeatureMessage) => void; - onRpcResponse?: ( - response: - | MenuRpcResponse - | VuuUIMessageInRPCEditReject - | VuuUIMessageInRPCEditResponse - ) => void; + onRpcResponse?: RpcResponseHandler; vuuMenuActionHandler?: VuuMenuActionHandler; } @@ -144,15 +140,8 @@ export const useViewportRowModel = ({ }), [] ); - const handleRpcResponse = useCallback( - ( - response: - | MenuRpcResponse - | VuuUIMessageInRPCEditReject - | VuuUIMessageInRPCEditResponse - ) => { - onRpcResponse?.(response); - }, + const handleRpcResponse = useCallback( + (response) => onRpcResponse?.(response) ?? false, [onRpcResponse] ); diff --git a/vuu-ui/packages/vuu-data-react/package.json b/vuu-ui/packages/vuu-data-react/package.json index 538cafa52..048d88a6c 100644 --- a/vuu-ui/packages/vuu-data-react/package.json +++ b/vuu-ui/packages/vuu-data-react/package.json @@ -10,7 +10,7 @@ "type-defs": "node ../../scripts/build-type-defs.mjs" }, "devDependencies": { - "@finos/vuu-datagrid-types": "0.0.26", + "@finos/vuu-table-types": "0.0.26", "@finos/vuu-filter-types": "0.0.26", "@finos/vuu-popups": "0.0.26", "@finos/vuu-protocol-types": "0.0.26" diff --git a/vuu-ui/packages/vuu-data-react/src/hooks/useLookupValues.ts b/vuu-ui/packages/vuu-data-react/src/hooks/useLookupValues.ts index 607e10c5e..750535edc 100644 --- a/vuu-ui/packages/vuu-data-react/src/hooks/useLookupValues.ts +++ b/vuu-ui/packages/vuu-data-react/src/hooks/useLookupValues.ts @@ -2,7 +2,7 @@ import { ColumnDescriptor, ListOption, LookupTableDetails, -} from "@finos/vuu-datagrid-types"; +} from "@finos/vuu-table-types"; import { RemoteDataSource } from "@finos/vuu-data"; import { useShellContext } from "@finos/vuu-shell"; import { diff --git a/vuu-ui/packages/vuu-data-react/src/hooks/useVuuMenuActions.ts b/vuu-ui/packages/vuu-data-react/src/hooks/useVuuMenuActions.ts index c36ca2d9f..1c23861f1 100644 --- a/vuu-ui/packages/vuu-data-react/src/hooks/useVuuMenuActions.ts +++ b/vuu-ui/packages/vuu-data-react/src/hooks/useVuuMenuActions.ts @@ -2,6 +2,7 @@ import { DataSource, DataSourceVisualLinkCreatedMessage, MenuRpcResponse, + ViewportRpcResponse, VuuUIMessageInRPCEditReject, VuuUIMessageInRPCEditResponse, } from "@finos/vuu-data"; @@ -152,6 +153,7 @@ export type RpcResponseHandler = ( | MenuRpcResponse | VuuUIMessageInRPCEditReject | VuuUIMessageInRPCEditResponse + | ViewportRpcResponse ) => void; export interface VuuMenuActionHookProps { diff --git a/vuu-ui/packages/vuu-data-test/package.json b/vuu-ui/packages/vuu-data-test/package.json index 9204184cf..094ba2513 100644 --- a/vuu-ui/packages/vuu-data-test/package.json +++ b/vuu-ui/packages/vuu-data-test/package.json @@ -10,6 +10,6 @@ }, "devDependencies": { "@finos/vuu-data": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26" + "@finos/vuu-table-types": "0.0.26" } } diff --git a/vuu-ui/packages/vuu-data-test/src/TickingArrayDataSource.ts b/vuu-ui/packages/vuu-data-test/src/TickingArrayDataSource.ts index 522b4fb23..291d5aa8d 100644 --- a/vuu-ui/packages/vuu-data-test/src/TickingArrayDataSource.ts +++ b/vuu-ui/packages/vuu-data-test/src/TickingArrayDataSource.ts @@ -17,6 +17,7 @@ import { VuuRange, VuuRowDataItemType, } from "@finos/vuu-protocol-types"; +import { SelectionItem } from "@finos/vuu-table-types"; import { metadataKeys } from "@finos/vuu-utils"; import { Table } from "./Table"; @@ -82,22 +83,25 @@ export class TickingArrayDataSource extends ArrayDataSource { } private getSelectedRows() { - return this.selectedRows.reduce((rows, selected) => { - if (Array.isArray(selected)) { - selected.forEach((sel) => { - const row = this.data[sel]; + return this.selectedRows.reduce( + (rows: DataSourceRow[], selected: SelectionItem) => { + if (Array.isArray(selected)) { + selected.forEach((sel) => { + const row = this.data[sel]; + if (row) { + rows.push(row); + } + }); + } else { + const row = this.data[selected]; if (row) { rows.push(row); } - }); - } else { - const row = this.data[selected]; - if (row) { - rows.push(row); } - } - return rows; - }, []); + return rows; + }, + [] + ); } applyEdit( @@ -113,7 +117,7 @@ export class TickingArrayDataSource extends ArrayDataSource { async rpcCall( rpcRequest: Omit - ) { + ): Promise { const rpcService = this.#rpcServices?.find( (service) => service.rpcName === diff --git a/vuu-ui/packages/vuu-data-test/src/basket/basket-module.ts b/vuu-ui/packages/vuu-data-test/src/basket/basket-module.ts index 35df97c21..812496f02 100644 --- a/vuu-ui/packages/vuu-data-test/src/basket/basket-module.ts +++ b/vuu-ui/packages/vuu-data-test/src/basket/basket-module.ts @@ -3,7 +3,7 @@ import { VuuMenu, VuuRowDataItemType, } from "@finos/vuu-protocol-types"; -import { ColumnMap, metadataKeys } from "@finos/vuu-utils"; +import { ColumnMap } from "@finos/vuu-utils"; import pricesTable from "./reference-data/prices"; import { joinTables, Table } from "../Table"; import { TickingArrayDataSource } from "../TickingArrayDataSource"; @@ -33,8 +33,6 @@ const tableMaps: Record = { priceStrategyType: buildDataColumnMap("priceStrategyType"), }; -const { KEY } = metadataKeys; - /** * BasketConstituent */ @@ -266,8 +264,11 @@ const createDataSource = (tableName: BasketsTableName) => { }); }; +const nullTypeaheadHook = async () => []; + const basketModule: VuuModule = { createDataSource, + typeaheadHook: () => nullTypeaheadHook, }; export default basketModule; diff --git a/vuu-ui/packages/vuu-data-test/src/basket/reference-data/prices.ts b/vuu-ui/packages/vuu-data-test/src/basket/reference-data/prices.ts index a11c566aa..47de3de81 100644 --- a/vuu-ui/packages/vuu-data-test/src/basket/reference-data/prices.ts +++ b/vuu-ui/packages/vuu-data-test/src/basket/reference-data/prices.ts @@ -60,7 +60,7 @@ for (const [,,,lastTrade,ric] of basketConstituentData) { last, open, phase, - ric, + ric as string, scenario, ]); diff --git a/vuu-ui/packages/vuu-data-test/src/createArrayDataSource.ts b/vuu-ui/packages/vuu-data-test/src/createArrayDataSource.ts deleted file mode 100644 index f095db3f7..000000000 --- a/vuu-ui/packages/vuu-data-test/src/createArrayDataSource.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { getColumnAndRowGenerator, populateArray } from "@finos/vuu-data-test"; -import { VuuTable } from "@finos/vuu-protocol-types"; -import { TickingArrayDataSource } from "./TickingArrayDataSource"; - -export const createArrayDataSource = ({ - count = 1000, - table, -}: { - count?: number; - table: VuuTable; -}) => { - const [columnGenerator, rowGenerator, createUpdateGenerator] = - getColumnAndRowGenerator(table); - - const columns = columnGenerator([]); - - const dataArray = populateArray(count, columnGenerator, rowGenerator); - - return new TickingArrayDataSource({ - columnDescriptors: columns, - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore yes we know an ArrayProxy is not a real Array, but don't tell the DataSource that - data: dataArray, - updateGenerator: createUpdateGenerator?.(), - }); -}; diff --git a/vuu-ui/packages/vuu-data-test/src/generatorTemplate.ts b/vuu-ui/packages/vuu-data-test/src/generatorTemplate.ts index 01c76e1a7..91e86850e 100644 --- a/vuu-ui/packages/vuu-data-test/src/generatorTemplate.ts +++ b/vuu-ui/packages/vuu-data-test/src/generatorTemplate.ts @@ -1,4 +1,4 @@ -import { ColumnDescriptor } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor } from "@finos/vuu-table-types"; import { ColumnMap } from "@finos/vuu-utils"; import { VuuDataRow } from "@finos/vuu-protocol-types"; import { ColumnGeneratorFn, RowGeneratorFactory } from "./vuu-row-generator"; diff --git a/vuu-ui/packages/vuu-data-test/src/index.ts b/vuu-ui/packages/vuu-data-test/src/index.ts index 5acf00475..6efd6cf1b 100644 --- a/vuu-ui/packages/vuu-data-test/src/index.ts +++ b/vuu-ui/packages/vuu-data-test/src/index.ts @@ -1,4 +1,3 @@ -export * from "./createArrayDataSource"; export * from "./schemas"; export * from "./TickingArrayDataSource"; export * from "./vuu-row-generator"; diff --git a/vuu-ui/showcase/src/examples/utils/makeSuggestions.ts b/vuu-ui/packages/vuu-data-test/src/makeSuggestions.ts similarity index 55% rename from vuu-ui/showcase/src/examples/utils/makeSuggestions.ts rename to vuu-ui/packages/vuu-data-test/src/makeSuggestions.ts index ae104b692..842ac2cb8 100644 --- a/vuu-ui/showcase/src/examples/utils/makeSuggestions.ts +++ b/vuu-ui/packages/vuu-data-test/src/makeSuggestions.ts @@ -1,21 +1,16 @@ -import { ArrayDataSource } from "@finos/vuu-data"; -import { buildColumnMap, DataItem } from "@finos/vuu-utils"; +import { DataItem } from "@finos/vuu-utils"; +import { Table } from "./Table"; -const cachedValues = new Map>(); +const cachedValues = new Map>(); -const getUniqueValues = ( - dataSource: ArrayDataSource, - column: string, - pattern = "" -) => { +const getUniqueValues = (table: Table, column: string, pattern = "") => { let uniqueValues; - const cachedEntry = cachedValues.get(dataSource); + const cachedEntry = cachedValues.get(table); if (cachedEntry && cachedEntry.has(column)) { uniqueValues = cachedEntry.get(column) as DataItem[]; } else { - const { columns, data } = dataSource; - const columnMap = buildColumnMap(columns); - const key = columnMap[column]; + const { data, map } = table; + const key = map[column]; uniqueValues = []; const set = new Set(); for (const row of data) { @@ -28,7 +23,7 @@ const getUniqueValues = ( if (cachedEntry) { cachedEntry.set(column, uniqueValues); } else { - cachedValues.set(dataSource, new Map([[column, uniqueValues]])); + cachedValues.set(table, new Map([[column, uniqueValues]])); } } return pattern @@ -37,11 +32,11 @@ const getUniqueValues = ( }; export const makeSuggestions = ( - dataSource: ArrayDataSource, + table: Table, column: string, pattern?: string ) => { - const uniqueValues = getUniqueValues(dataSource, column, pattern); + const uniqueValues = getUniqueValues(table, column, pattern); if (uniqueValues.length > 20) { return uniqueValues?.slice(0, 20).map((v) => v.toString()); } else { diff --git a/vuu-ui/packages/vuu-data-test/src/simul/OrderUpdateGenerator.ts b/vuu-ui/packages/vuu-data-test/src/simul/OrderUpdateGenerator.ts deleted file mode 100644 index 84d8f79b5..000000000 --- a/vuu-ui/packages/vuu-data-test/src/simul/OrderUpdateGenerator.ts +++ /dev/null @@ -1,143 +0,0 @@ -import { ArrayDataSource } from "@finos/vuu-data"; -import { VuuRange, VuuRowDataItemType } from "@finos/vuu-protocol-types"; -import { buildColumnMap, ColumnMap } from "@finos/vuu-utils"; -import type { - RowDelete, - RowInsert, - RowUpdates, - UpdateGenerator, - UpdateHandler, -} from "../rowUpdates"; -import { metadataKeys } from "@finos/vuu-utils"; - -let _orderId = 1; -const orderId = () => `0000000${_orderId++}`.slice(-3); -const createOrder = (): ["I", ...VuuRowDataItemType[]] => { - const createTime = Date.now(); - return [ - "I", - "EUR", - createTime, - 0, - createTime, - orderId(), - 1000, - "AAPL.L", - "buy", - "trader-x", - ]; -}; - -type OrderPhase = "create-order" | "fill-order" | "remove-order"; - -export class OrderUpdateGenerator implements UpdateGenerator { - private dataSource: ArrayDataSource | undefined; - private range: VuuRange | undefined; - private updateHandler: UpdateHandler | undefined; - private updating = false; - private timer: number | undefined; - private phase: OrderPhase = "create-order"; - private orderCount: number; - private columnMap?: ColumnMap; - - constructor(orderCount = 20) { - this.orderCount = orderCount; - } - - setRange(range: VuuRange) { - this.range = range; - if (!this.updating && this.updateHandler) { - this.startUpdating(); - } - } - - setDataSource(dataSource: ArrayDataSource) { - this.dataSource = dataSource; - this.columnMap = buildColumnMap(dataSource.columns); - } - - setUpdateHandler(updateHandler: UpdateHandler) { - this.updateHandler = updateHandler; - if (!this.updating && this.range) { - this.startUpdating(); - } - } - - private startUpdating() { - this.updating = true; - this.update(); - } - - private stopUpdating() { - this.updating = false; - if (this.timer) { - window.clearTimeout(this.timer); - this.timer = undefined; - } - } - - update = () => { - const updates: (RowUpdates | RowInsert | RowDelete)[] = []; - - switch (this.phase) { - case "create-order": { - updates.push(createOrder()); - - const data = this.dataSource?.data; - if (data && data.length >= this.orderCount) { - console.log("phase >>> fill"); - this.phase = "fill-order"; - } - - break; - } - - case "fill-order": { - console.log("fill-order"); - const data = this.dataSource?.data; - let filledCount = 0; - if (data && this.columnMap) { - const count = data.length; - const { IDX } = metadataKeys; - const { filledQuantity: filledKey, quantity: qtyKey } = - this.columnMap; - for (const order of data) { - const { - [IDX]: rowIdx, - [filledKey]: filledQty, - [qtyKey]: quantity, - } = order; - if (filledQty < quantity) { - const newFilledQty = Math.min( - quantity as number, - Math.max(100, (filledQty as number) * 1.1) - ); - updates.push(["U", rowIdx, filledKey, newFilledQty]); - } else { - filledCount += 1; - // schedule for delete - } - } - if (filledCount === count) { - console.log(">>> remove phase "); - this.phase = "remove-order"; - } - } - - break; - } - - case "remove-order": { - break; - } - } - - if (updates.length > 0) { - this.updateHandler?.(updates); - } - - if (this.updating) { - this.timer = window.setTimeout(this.update, 50); - } - }; -} diff --git a/vuu-ui/packages/vuu-data-test/src/simul/reference-data/instruments-extended.ts b/vuu-ui/packages/vuu-data-test/src/simul/reference-data/instruments-extended.ts new file mode 100644 index 000000000..228455dc4 --- /dev/null +++ b/vuu-ui/packages/vuu-data-test/src/simul/reference-data/instruments-extended.ts @@ -0,0 +1,19 @@ +import { VuuRowDataItemType } from "@finos/vuu-protocol-types"; +import { random } from "../../data-utils"; +import { buildDataColumnMap, Table } from "../../Table"; +import { schemas } from "../simul-schemas"; +import { instrumentsData } from "./instruments"; + +const instrumentsExtendedData = instrumentsData.map((row) => + (row as VuuRowDataItemType[]) + .slice(0, -1) + .concat([random(0, 1) === 1, random(0, 1) === 1]) +); + +const instrumentsExtendedTable = new Table( + schemas.instrumentsExtended, + instrumentsExtendedData, + buildDataColumnMap(schemas.instrumentsExtended) +); + +export default instrumentsExtendedTable; diff --git a/vuu-ui/packages/vuu-data-test/src/simul/reference-data/instruments.ts b/vuu-ui/packages/vuu-data-test/src/simul/reference-data/instruments.ts index 9beb7eeec..e818d9d42 100644 --- a/vuu-ui/packages/vuu-data-test/src/simul/reference-data/instruments.ts +++ b/vuu-ui/packages/vuu-data-test/src/simul/reference-data/instruments.ts @@ -13,8 +13,6 @@ export type description = string; export type exchange = string; // seed for price generation export type price = number; -type supported = boolean; -type wishlist = boolean; export type InstrumentsDataRow = [ bbg, @@ -24,8 +22,6 @@ export type InstrumentsDataRow = [ string, number, ric, - supported, - wishlist, price ]; @@ -37,9 +33,7 @@ export const InstrumentColumnMap = { string: 4, number: 5, ric: 6, - supported: 7, - wishlist: 8, - price: 9, + price: 7, } as const; const instrumentsData: InstrumentsDataRow[] = []; @@ -52,10 +46,10 @@ const randomPrice = () => { return price / multiplier; }; -// const start = performance.now(); -// Create 100_000 Instruments +const start = performance.now(); +// Create 10_000 Instruments for (const char of chars) { - for (let i = 0; i < 5_000; i++) { + for (let i = 0; i < 10_000; i++) { const char2 = chars[random(0, chars.length - 1)]; const char3 = chars[random(0, chars.length - 1)]; const char4 = chars[random(0, chars.length - 1)]; @@ -70,8 +64,6 @@ for (const char of chars) { const exchange = locations[suffix][1]; const price = randomPrice(); - const supported = random(0, 1) === 1; - const wishlist = random(0, 1) === 1; instrumentsData.push([ bbg, @@ -81,14 +73,12 @@ for (const char of chars) { String(isin), lotSize, ric, - supported, - wishlist, price, ]); } } -// const end = performance.now(); -// console.log(`generating 100,000 instruments took ${end - start} ms`); +const end = performance.now(); +console.log(`generating 10,000 instruments took ${end - start} ms`); const instrumentsTable = new Table( schemas.instruments, diff --git a/vuu-ui/packages/vuu-data-test/src/simul/simul-module.ts b/vuu-ui/packages/vuu-data-test/src/simul/simul-module.ts index 6f52d1415..4369ea277 100644 --- a/vuu-ui/packages/vuu-data-test/src/simul/simul-module.ts +++ b/vuu-ui/packages/vuu-data-test/src/simul/simul-module.ts @@ -1,9 +1,13 @@ import { TickingArrayDataSource } from "../TickingArrayDataSource"; import { VuuModule } from "../vuu-modules"; import instrumentsTable from "./reference-data/instruments"; +import instrumentsExtendedTable from "./reference-data/instruments-extended"; import pricesTable from "./reference-data/prices"; import { schemas, SimulTableName } from "./simul-schemas"; import { buildDataColumnMap, joinTables, Table } from "../Table"; +import { TypeaheadParams } from "@finos/vuu-protocol-types"; +import { SuggestionFetcher } from "@finos/vuu-data-react"; +import { makeSuggestions } from "../makeSuggestions"; const tables: Record = { childOrders: new Table( @@ -12,6 +16,7 @@ const tables: Record = { buildDataColumnMap(schemas.childOrders) ), instruments: instrumentsTable, + instrumentsExtended: instrumentsExtendedTable, instrumentPrices: joinTables( { module: "SIMUL", table: "instrumentPrices" }, instrumentsTable, @@ -27,24 +32,12 @@ const tables: Record = { prices: pricesTable, }; -// export const populateArray = (tableName: SimulTableName, count: number) => { -// const table = tables[tableName]; -// const data: Array = []; -// for (let i = 0; i < count; i++) { -// if (i >= table.data.length) { -// break; -// } -// data[i] = table.data[i]; -// } -// return data; -// }; - const getColumnDescriptors = (tableName: SimulTableName) => { const schema = schemas[tableName]; if (schema) { return schema.columns; } else { - console.error(`simul-module no schema found for table SIMUL ${tableName}`); + throw Error(`simul-module no schema found for table SIMUL ${tableName}`); } }; @@ -59,8 +52,24 @@ const createDataSource = (tableName: SimulTableName) => { }); }; +const suggestionFetcher: SuggestionFetcher = async ([ + vuuTable, + column, + pattern, +]: TypeaheadParams) => { + const table = tables[vuuTable.table as SimulTableName]; + if (table) { + return makeSuggestions(table, column, pattern); + } else { + throw Error( + `SIMUL suggestionFetcher, unknown table ${vuuTable.module} ${vuuTable.table}` + ); + } +}; + const simulModule: VuuModule = { createDataSource, + typeaheadHook: () => suggestionFetcher, }; export default simulModule; diff --git a/vuu-ui/packages/vuu-data-test/src/simul/simul-schemas.ts b/vuu-ui/packages/vuu-data-test/src/simul/simul-schemas.ts index 3f429cbef..35f4f29e9 100644 --- a/vuu-ui/packages/vuu-data-test/src/simul/simul-schemas.ts +++ b/vuu-ui/packages/vuu-data-test/src/simul/simul-schemas.ts @@ -1,8 +1,9 @@ import type { TableSchema } from "@finos/vuu-data"; -import type { ColumnDescriptor } from "@finos/vuu-datagrid-types"; +import type { ColumnDescriptor } from "@finos/vuu-table-types"; export type SimulTableName = | "instruments" + | "instrumentsExtended" | "instrumentPrices" | "orders" | "childOrders" @@ -14,6 +15,19 @@ export type SimulTableName = export const schemas: Readonly>> = { instruments: { + columns: [ + { name: "bbg", serverDataType: "string" }, + { name: "currency", serverDataType: "string" }, + { name: "description", serverDataType: "string" }, + { name: "exchange", serverDataType: "string" }, + { name: "isin", serverDataType: "string" }, + { name: "lotSize", serverDataType: "int" }, + { name: "ric", serverDataType: "string" }, + ], + key: "ric", + table: { module: "SIMUL", table: "instruments" }, + }, + instrumentsExtended: { columns: [ { name: "bbg", serverDataType: "string" }, { name: "currency", serverDataType: "string" }, diff --git a/vuu-ui/packages/vuu-data-test/src/vuu-modules.ts b/vuu-ui/packages/vuu-data-test/src/vuu-modules.ts index 06bffa98f..2e8386293 100644 --- a/vuu-ui/packages/vuu-data-test/src/vuu-modules.ts +++ b/vuu-ui/packages/vuu-data-test/src/vuu-modules.ts @@ -1,4 +1,5 @@ import { DataSource } from "@finos/vuu-data"; +import { SuggestionFetcher } from "packages/vuu-data-react/src"; import basketModule from "./basket/basket-module"; import { BasketsTableName } from "./basket/basket-schemas"; import simulModule from "./simul/simul-module"; @@ -8,6 +9,7 @@ export type VuuModuleName = "BASKET" | "SIMUL"; export interface VuuModule { createDataSource: (tableName: T) => DataSource; + typeaheadHook: () => SuggestionFetcher; } const vuuModules: Record< diff --git a/vuu-ui/packages/vuu-data-test/src/vuu-row-generator.ts b/vuu-ui/packages/vuu-data-test/src/vuu-row-generator.ts index 91615e1d0..389ef1806 100644 --- a/vuu-ui/packages/vuu-data-test/src/vuu-row-generator.ts +++ b/vuu-ui/packages/vuu-data-test/src/vuu-row-generator.ts @@ -1,4 +1,4 @@ -import { ColumnDescriptor } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor } from "@finos/vuu-table-types"; import { VuuRowDataItemType, VuuTable } from "@finos/vuu-protocol-types"; import { UpdateGenerator } from "./rowUpdates"; diff --git a/vuu-ui/packages/vuu-data/package.json b/vuu-ui/packages/vuu-data/package.json index 8736313a5..cea774552 100644 --- a/vuu-ui/packages/vuu-data/package.json +++ b/vuu-ui/packages/vuu-data/package.json @@ -11,7 +11,7 @@ }, "devDependencies": { "@finos/vuu-data-types": "0.0.26", - "@finos/vuu-datagrid-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" }, diff --git a/vuu-ui/packages/vuu-data/src/array-data-source/array-data-source.ts b/vuu-ui/packages/vuu-data/src/array-data-source/array-data-source.ts index 27dc728ca..16a219642 100644 --- a/vuu-ui/packages/vuu-data/src/array-data-source/array-data-source.ts +++ b/vuu-ui/packages/vuu-data/src/array-data-source/array-data-source.ts @@ -1,5 +1,5 @@ import { DataSourceFilter, DataSourceRow } from "@finos/vuu-data-types"; -import { ColumnDescriptor, Selection } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor, Selection } from "@finos/vuu-table-types"; import { filterPredicate, parseFilter } from "@finos/vuu-filter-parser"; import { ClientToServerEditRpc, @@ -440,7 +440,7 @@ export class ArrayDataSource } }; - protected update = (row: VuuRowDataItemType[], columnName?: string) => { + protected update = (row: VuuRowDataItemType[], columnName: string) => { // TODO take sorting, filtering. grouping into account const keyValue = row[this.key]; const colIndex = this.#columnMap[columnName]; @@ -663,13 +663,14 @@ export class ArrayDataSource switch (type) { case "VP_EDIT_CELL_RPC": { - const { rowKey, field, value } = rpcRequest; - try { - this.update(rowKey, field, value); - resolve(undefined); - } catch (error) { - resolve({ error: String(error), type: "VP_EDIT_RPC_REJECT" }); - } + // TODO + // const { rowKey, field, value } = rpcRequest; + // try { + // this.update(rowKey, field, value); + // resolve(undefined); + // } catch (error) { + // resolve({ error: String(error), type: "VP_EDIT_RPC_REJECT" }); + // } } break; diff --git a/vuu-ui/packages/vuu-data/src/array-data-source/array-data-utils.ts b/vuu-ui/packages/vuu-data/src/array-data-source/array-data-utils.ts index 94b160251..f38c81ff1 100644 --- a/vuu-ui/packages/vuu-data/src/array-data-source/array-data-utils.ts +++ b/vuu-ui/packages/vuu-data/src/array-data-source/array-data-utils.ts @@ -1,5 +1,5 @@ import { DataSourceRow } from "@finos/vuu-data-types"; -import { Selection } from "@finos/vuu-datagrid-types"; +import { Selection } from "@finos/vuu-table-types"; import { ColumnMap, getSelectionStatus, diff --git a/vuu-ui/packages/vuu-data/src/array-data-source/group-utils.ts b/vuu-ui/packages/vuu-data/src/array-data-source/group-utils.ts index 94fc0a0de..9c265728f 100644 --- a/vuu-ui/packages/vuu-data/src/array-data-source/group-utils.ts +++ b/vuu-ui/packages/vuu-data/src/array-data-source/group-utils.ts @@ -75,6 +75,7 @@ const dataRowsFromGroups2 = ( rows: DataSourceRow[] = [], processedData: readonly DataSourceRow[] ) => { + console.log(`dataRowsFromGroups2 1)`); const keys = Object.keys(groupMap).sort(); for (const key of keys) { const idx = rows.length; @@ -108,6 +109,7 @@ const dataRowsFromGroups2 = ( } } } + console.log(`dataRowsFromGroups2 2)`); for (const key in rows) { for (const index in rows) { @@ -126,6 +128,8 @@ const dataRowsFromGroups2 = ( } } } + console.log(`dataRowsFromGroups2 3)`); + return rows; }; diff --git a/vuu-ui/packages/vuu-data/src/data-source.ts b/vuu-ui/packages/vuu-data/src/data-source.ts index 423db1258..3752de6d3 100644 --- a/vuu-ui/packages/vuu-data/src/data-source.ts +++ b/vuu-ui/packages/vuu-data/src/data-source.ts @@ -2,7 +2,7 @@ import { DataSourceFilter, DataSourceRow } from "@finos/vuu-data-types"; import { ColumnDescriptor, SelectionChangeHandler, -} from "@finos/vuu-datagrid-types"; +} from "@finos/vuu-table-types"; import { ClientToServerEditRpc, ClientToServerMenuRPC, diff --git a/vuu-ui/packages/vuu-data/src/json-data-source.ts b/vuu-ui/packages/vuu-data/src/json-data-source.ts index d28baec86..aa3ca64f0 100644 --- a/vuu-ui/packages/vuu-data/src/json-data-source.ts +++ b/vuu-ui/packages/vuu-data/src/json-data-source.ts @@ -1,4 +1,4 @@ -import { ColumnDescriptor, Selection } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor, Selection } from "@finos/vuu-table-types"; import { LinkDescriptorWithLabel, VuuGroupBy, diff --git a/vuu-ui/packages/vuu-data/src/remote-data-source.ts b/vuu-ui/packages/vuu-data/src/remote-data-source.ts index 589fbd4e9..e64a9b613 100644 --- a/vuu-ui/packages/vuu-data/src/remote-data-source.ts +++ b/vuu-ui/packages/vuu-data/src/remote-data-source.ts @@ -1,5 +1,5 @@ import { DataSourceFilter, DataSourceRow } from "@finos/vuu-data-types"; -import { Selection } from "@finos/vuu-datagrid-types"; +import { Selection } from "@finos/vuu-table-types"; import { ClientToServerEditRpc, ClientToServerMenuRPC, diff --git a/vuu-ui/packages/vuu-data/src/server-proxy/viewport.ts b/vuu-ui/packages/vuu-data/src/server-proxy/viewport.ts index de2995210..286c38ca9 100644 --- a/vuu-ui/packages/vuu-data/src/server-proxy/viewport.ts +++ b/vuu-ui/packages/vuu-data/src/server-proxy/viewport.ts @@ -1,5 +1,5 @@ import { DataSourceFilter, DataSourceRow } from "@finos/vuu-data-types"; -import { Selection } from "@finos/vuu-datagrid-types"; +import { Selection } from "@finos/vuu-table-types"; import { ClientToServerChangeViewPort, ClientToServerCloseTreeNode, diff --git a/vuu-ui/packages/vuu-data/src/vuuUIMessageTypes.ts b/vuu-ui/packages/vuu-data/src/vuuUIMessageTypes.ts index 1ca9331b4..b603d8f9c 100644 --- a/vuu-ui/packages/vuu-data/src/vuuUIMessageTypes.ts +++ b/vuu-ui/packages/vuu-data/src/vuuUIMessageTypes.ts @@ -20,11 +20,12 @@ import { DataSourceVisualLinkCreatedMessage, DataSourceVisualLinkRemovedMessage, DataSourceVisualLinksMessage, + RpcResponse, VuuFeatureInvocationMessage, VuuFeatureMessage, WithFullConfig, } from "./data-source"; -import { GridAction, Selection } from "@finos/vuu-datagrid-types"; +import { GridAction, Selection } from "@finos/vuu-table-types"; import { WebSocketProtocol } from "./websocket-connection"; export interface OpenDialogAction { @@ -176,18 +177,12 @@ export type VuuUIMessageIn = | VuuUIMessageInRPCEditResponse; export const isErrorResponse = ( - response?: - | MenuRpcResponse - | VuuUIMessageInRPCEditReject - | VuuUIMessageInRPCEditResponse + response?: RpcResponse ): response is VuuUIMessageInRPCEditReject => response !== undefined && "error" in response; export const hasAction = ( - response?: - | MenuRpcResponse - | VuuUIMessageInRPCEditReject - | VuuUIMessageInRPCEditResponse + response?: RpcResponse ): response is MenuRpcResponse | VuuUIMessageInRPCEditResponse => response != undefined && "action" in response; diff --git a/vuu-ui/packages/vuu-datagrid/README.md b/vuu-ui/packages/vuu-datagrid/README.md deleted file mode 100644 index 6a335aa3a..000000000 --- a/vuu-ui/packages/vuu-datagrid/README.md +++ /dev/null @@ -1 +0,0 @@ -This is a regular package diff --git a/vuu-ui/packages/vuu-datagrid/package.json b/vuu-ui/packages/vuu-datagrid/package.json deleted file mode 100644 index cbcee912c..000000000 --- a/vuu-ui/packages/vuu-datagrid/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "@finos/vuu-datagrid", - "version": "0.0.26", - "author": "heswell", - "main": "src/index.ts", - "license": "Apache-2.0", - "scripts": { - "build": "node ../../scripts/run-build.mjs", - "type-defs": "node ../../scripts/build-type-defs.mjs" - }, - "devDependencies": { - "@finos/vuu-filter-types": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26", - "@finos/vuu-protocol-types": "0.0.26" - }, - "peerDependencies": { - "@finos/vuu-data-types": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26", - "@finos/vuu-filters": "0.0.26", - "@finos/vuu-popups": "0.0.26", - "@finos/vuu-utils": "0.0.26", - "@salt-ds/core": "1.8.0", - "@salt-ds/lab": "1.0.0-alpha.15", - "classnames": "^2.2.6", - "react": "^17.0.2", - "react-dom": "^17.0.2" - } -} diff --git a/vuu-ui/packages/vuu-datagrid/src/ColumnBearer.tsx b/vuu-ui/packages/vuu-datagrid/src/ColumnBearer.tsx deleted file mode 100644 index 69af245e7..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/ColumnBearer.tsx +++ /dev/null @@ -1,385 +0,0 @@ -import React, { - ForwardedRef, - forwardRef, - HTMLAttributes, - useCallback, - useEffect, - useImperativeHandle, - useMemo, - useRef, -} from "react"; -import cx from "classnames"; -import { GridCell, HeaderCell } from "./grid-cells"; -import useDrag, { DRAG, DRAG_END } from "./use-drag"; -import { getColumnGroup } from "./grid-model/gridModelUtils"; - -import "./column-bearer.css"; -import { GridModelType } from "./grid-model"; -import { ColumnDragState, dragPhase } from "./gridTypes"; -import { buildColumnMap } from "@finos/vuu-utils"; -import { RuntimeColumnDescriptor } from "@finos/vuu-datagrid-types"; -import { DataSourceRow } from "@finos/vuu-data-types"; - -const LEFT = "left"; -const RIGHT = "right"; - -export interface ColumnBearerAPI { - setFinalPosition: (position: number) => void; -} - -// Identify a single dropPosition, no matter the width of the dragged column or the widths -// of target columns. -function getBestDropTarget( - columnPositions: number[][], - dragPosition: number, - columnWidth: number, - scrollPosition: number -) { - const columnStart = dragPosition + scrollPosition; - const columnEnd = columnStart + columnWidth; - // console.log(`getClosestPosition ${columnPositions} columnStart: ${columnStart} columnEnd ${columnEnd}`) - const results = []; - const visited = []; - let idx; - for (const groupPositions of columnPositions) { - for (const position of groupPositions) { - visited.push(position); - if (columnStart <= position && columnEnd >= position) { - results.push(position); - } else if (columnEnd < position) { - break; - } - } - } - - if (results.length === 1) { - idx = results[0]; - } else if (results.length === 0) { - const p2 = visited.pop() as number; - const p1 = visited.pop() as number; - idx = columnStart - p1 < p2 - columnEnd ? p1 : p2; - } else { - const mid = columnEnd - columnStart; - idx = results.reduce( - (p1, p2) => (Math.abs(p1 - mid) < Math.abs(p2 - mid) ? p1 : p2), - 99999 - ); - } - - return idx; -} - -function getTargetColumn( - { column, columnPositions }: ColumnDragState, - dragPosition: number, - scrollPosition: number -) { - const targetPosition = getBestDropTarget( - columnPositions, - dragPosition, - column.width, - scrollPosition - ); - const columnStart = dragPosition + scrollPosition; - const [[offsetLeft]] = columnPositions; - // This must be more sensitive detecting moves over another columnGroup - for (let i = 0, idx = 0; i < columnPositions.length; i++) { - const positions = columnPositions[i]; - for (let j = 0; j < positions.length; j++, idx++) { - if (positions[j] === targetPosition) { - const position = targetPosition - offsetLeft; - let groupIdx = i; - if (i > 0 && j === 0) { - // break between 2 groups - const centerPoint = columnStart + column.width / 2; - if (centerPoint < position) { - groupIdx -= 1; - } - } - return [idx, position - scrollPosition, groupIdx]; - } - } - } - return [-1, -1, -1]; -} - -function getScrollBounds( - gridModel: GridModelType, - column: RuntimeColumnDescriptor -) { - const { columnGroups, width } = gridModel; - if (!columnGroups || width === undefined) { - throw Error( - "ColumnBearer getScrollBounds no columnGroups or width is not defined" - ); - } - - let scrollableLeft = 0; - let scrollableRight = 0; - for (const columnGroup of columnGroups) { - if (columnGroup.locked && scrollableLeft === 0) { - scrollableLeft += columnGroup.width; - scrollableRight += columnGroup.width; - } else if (!columnGroup.locked) { - scrollableRight += columnGroup.width; - } - } - - return { - left: 0, - right: width - column.width, - scrollableLeft: scrollableLeft, - scrollableRight: scrollableRight - column.width, - }; -} - -function useScrollBounds( - gridModel: GridModelType, - column: RuntimeColumnDescriptor -) { - const scrollBounds = useRef(getScrollBounds(gridModel, column)); - - const withinScrollZone = useCallback( - (pos: number): "left" | "right" | null => { - const { - current: { scrollableLeft, scrollableRight }, - } = scrollBounds; - if (pos >= scrollableLeft - 20 && pos < scrollableLeft) { - return LEFT; - } else if (pos > scrollableRight && pos <= scrollableRight + 20) { - return RIGHT; - } else { - return null; - } - }, - [] - ); - - return { scrollBounds: scrollBounds.current, withinScrollZone }; -} - -export interface ColumnBearerProps - extends Omit, "onScroll" | "onDrag"> { - columnDragData: ColumnDragState; - gridModel: GridModelType; - onDrag: ( - phase: dragPhase, - column: RuntimeColumnDescriptor, - insertIdx: number, - insertPos: number, - columnPosition?: number - ) => void; - onScroll: (distance: number) => number; - initialScrollPosition: number; - rows: DataSourceRow[]; -} - -export const ColumnBearer = forwardRef( - ( - { - columnDragData, - gridModel, - onDrag, - onScroll, - rows, - initialScrollPosition, - }: ColumnBearerProps, - ref: ForwardedRef - ) => { - const { - headerHeight, - headingDepth = 1, - rowHeight, - viewportHeight, - } = gridModel; - - const top = headerHeight * (headingDepth - 1); - const columnPosition = useRef(columnDragData.initialColumnPosition); - const columnGroupIdx = useRef(columnDragData.columnGroupIdx); - const { scrollBounds, withinScrollZone } = useScrollBounds( - gridModel, - columnDragData.column - ); - const el = useRef(null); - const disableDragRef = useRef<() => void>(); // avoid circular ref - const scrollTimeout = useRef(null); - const scrollPosition = useRef(initialScrollPosition); - const prevPosition = useRef(-1); - const columnMap = useMemo( - () => buildColumnMap(gridModel.columnNames), - [gridModel.columnNames] - ); - - const { column } = columnDragData; - - const style = { - top: top + 15, - left: columnPosition.current, - height: (gridModel.height ?? 200) - top - 15, - width: column.width, - }; - - const scroll = useCallback( - (scrollDistance) => () => { - const distanceScrolled = onScroll(scrollDistance); - scrollPosition.current += distanceScrolled; - if ( - distanceScrolled !== 0 && - withinScrollZone(columnPosition.current) - ) { - scrollTimeout.current = requestAnimationFrame(scroll(scrollDistance)); - } - }, - [onScroll, withinScrollZone] - ); - - const cancelScroll = () => { - if (scrollTimeout.current) { - cancelAnimationFrame(scrollTimeout.current); - } - scrollTimeout.current = null; - }; - - useEffect(() => { - return () => console.log(`columnbearer unmount`); - }, []); - - useImperativeHandle(ref, () => ({ - setFinalPosition: (pos) => { - if (el.current) { - console.log(`ColumnBearer finalPosition `); - el.current.style.transition = "left, top ease .3s"; - el.current.style.top = `0px`; - el.current.style.left = pos + `px`; - } - }, - })); - - const setColumnBearerClassName = useCallback( - (columnGroupIdx) => { - const { columnGroups } = gridModel; - if (el.current && columnGroups) { - const columnGroup = columnGroups[columnGroupIdx]; - if (columnGroup.locked) { - el.current.classList.add("fixed"); - } else { - el.current.classList.remove("fixed"); - } - } - }, - [gridModel] - ); - - const dragCallback = useCallback( - (dragPhase, delta) => { - if (dragPhase === "drag" && el.current) { - const newPosition = Math.max( - scrollBounds.left, - Math.min(columnPosition.current + delta, scrollBounds.right + 5) - ); - - if (newPosition !== columnPosition.current) { - columnPosition.current = newPosition; - el.current.style.left = columnPosition.current + "px"; - } - - const [insertIdx, insertPos, groupIdx] = getTargetColumn( - columnDragData, - columnPosition.current, - scrollPosition.current - ); - if (groupIdx !== columnGroupIdx.current) { - setColumnBearerClassName(groupIdx); - columnGroupIdx.current = groupIdx; - } - if (insertPos !== prevPosition.current) { - onDrag?.("drag", column, insertIdx, insertPos); - } - prevPosition.current = insertPos; - - // We should probably just fire onDrag and let Viewport worry about this - const direction = withinScrollZone(columnPosition.current); - if (direction && !scrollTimeout.current) { - scrollTimeout.current = requestAnimationFrame( - scroll(direction === "right" ? 10 : -10) - ); - } else if (!direction && scrollTimeout.current) { - cancelScroll(); - } - } else { - if (scrollTimeout.current) { - cancelScroll(); - } - disableDragRef.current?.(); - const [insertIdx] = getTargetColumn( - columnDragData, - columnPosition.current, - scrollPosition.current - ); - onDrag( - "drag-end", - column, - insertIdx, - prevPosition.current, - columnPosition.current - ); - } - }, - [ - column, - columnDragData, - onDrag, - scroll, - scrollBounds, - setColumnBearerClassName, - withinScrollZone, - ] - ); - - const [, disableDrag] = useDrag( - dragCallback, - DRAG + DRAG_END, - columnDragData.mousePosition - ); - disableDragRef.current = disableDrag; - - const columnGroup = getColumnGroup(gridModel, column); - - return ( -
-
- -
-
- {rows.map((row, idx) => ( -
- -
- ))} -
-
- ); - } -); - -ColumnBearer.displayName = "ColumnBearer"; diff --git a/vuu-ui/packages/vuu-datagrid/src/ColumnGroupHeader.css b/vuu-ui/packages/vuu-datagrid/src/ColumnGroupHeader.css deleted file mode 100644 index 306184d2e..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/ColumnGroupHeader.css +++ /dev/null @@ -1,5 +0,0 @@ -.hwColumnGroupHeader { - vertical-align: top; - overflow: hidden; - background-color: var(--grid-header-background, var(--grid-background)); -} diff --git a/vuu-ui/packages/vuu-datagrid/src/ColumnGroupHeader.tsx b/vuu-ui/packages/vuu-datagrid/src/ColumnGroupHeader.tsx deleted file mode 100644 index 9ae739844..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/ColumnGroupHeader.tsx +++ /dev/null @@ -1,215 +0,0 @@ -import cx from "classnames"; -import React, { - ForwardedRef, - forwardRef, - HTMLAttributes, - useCallback, - useImperativeHandle, - useRef, -} from "react"; -import { Heading } from "@finos/vuu-datagrid-types"; -import { VuuSort } from "../../vuu-protocol-types"; -import ColumnGroupContext from "./column-group-context"; -import { SortType } from "./constants"; -import { GroupHeaderCell, HeaderCell, HeadingCell } from "./grid-cells"; -import { useGridContext } from "./grid-context"; -import { ColumnGroupType } from "./grid-model/gridModelTypes"; -import { GridModel } from "./grid-model/gridModelUtils"; -import { ColumnDragStartHandler, resizePhase } from "./gridTypes"; - -import { RuntimeColumnDescriptor } from "@finos/vuu-datagrid-types"; -import { isGroupColumn } from "@finos/vuu-utils"; -import "./ColumnGroupHeader.css"; - -const classBase = "hwColumnGroupHeader"; - -export interface ColumnGroupHeaderAPI { - beginHorizontalScroll: (width: number) => void; - endHorizontalScroll: (scrollLeft: number, width: number) => void; -} - -export interface ColumnGroupHeaderProps extends HTMLAttributes { - columnGroup: ColumnGroupType; - columnGroupIdx: number; - onColumnDragStart?: ColumnDragStartHandler; -} - -const ColumnGroupHeader = React.memo( - forwardRef(function ColumnGroupHeader( - { columnGroup, columnGroupIdx, onColumnDragStart }: ColumnGroupHeaderProps, - ref: ForwardedRef - ) { - const columns = columnGroup.columns; - const columnGroupHeader = useRef(null); - const scrollingHeaderWrapper = useRef(null); - const { custom, dispatchGridAction, dispatchGridModelAction, gridModel } = - useGridContext(); - // TODO add a param to useGridContext so it will throw if gridModel missing - if (!gridModel) { - throw Error("no grid model"); - } - - const sortIndicator = ( - sort: VuuSort | undefined, - column: RuntimeColumnDescriptor - ) => { - if (!sort || sort.sortDefs.length === 0) { - return undefined; - } else { - const { sortDefs } = sort; - const multiColumnSort = sortDefs.length > 1; - const sortEntry = sortDefs.find((item) => item.column === column.name); - return sortEntry === undefined - ? undefined - : multiColumnSort - ? (sortDefs.indexOf(sortEntry) + 1) * - (sortEntry.sortType === SortType.DSC ? -1 : 1) - : sortEntry.sortType === SortType.ASC - ? "asc" - : "dsc"; - } - }; - - useImperativeHandle(ref, () => ({ - beginHorizontalScroll: (width) => { - if (columnGroupHeader.current && scrollingHeaderWrapper.current) { - columnGroupHeader.current.style.width = width + "px"; - scrollingHeaderWrapper.current.style.transform = `translate3d(0px, 0px, 0px)`; - } - }, - endHorizontalScroll: (scrollLeft, width) => { - if (columnGroupHeader.current && scrollingHeaderWrapper.current) { - scrollingHeaderWrapper.current.style.transform = `translate3d(-${scrollLeft}px, 0px, 0px)`; - columnGroupHeader.current.style.width = width + "px"; - } - }, - })); - - const handleColumnResize = useCallback( - (phase, columnName, width) => { - dispatchGridAction?.({ type: "resize-col", phase, columnName, width }); - }, - [dispatchGridAction] - ); - - const handleHeadingResize = useCallback( - (phase: resizePhase, headingName: string, width?: number) => { - dispatchGridModelAction?.({ - type: "resize-heading", - phase, - headingName, - width, - }); - }, - [dispatchGridModelAction] - ); - - const handleDrag = useCallback( - (phase, column, columnPosition, mousePosition) => { - onColumnDragStart?.( - phase, - columnGroupIdx, - column, - columnPosition, - mousePosition - ); - }, - [columnGroupIdx, onColumnDragStart] - ); - - const handleRemoveGroup = useCallback( - (column) => { - if (gridModel) { - dispatchGridAction?.({ - type: "group", - key: GridModel.removeGroupColumn(gridModel, column), - }); - } - }, - [dispatchGridAction, gridModel] - ); - - const handleHeaderClick = useCallback( - (_groupColumn, column: RuntimeColumnDescriptor) => { - if (gridModel) { - dispatchGridAction?.({ - type: "sort", - sort: GridModel.setSortColumn(gridModel, column), - }); - } - }, - [dispatchGridAction, gridModel] - ); - - const { - customHeaderHeight: top, - customInlineHeaderHeight, - headerHeight, - headingDepth = 1, - } = gridModel; - const height = headerHeight * headingDepth; - - const renderColHeadings = (heading: Heading[]) => - heading.map((item, idx) => ( - - )); - - const { contentWidth, headings = [], width } = columnGroup; - return ( -
-
- {headings - .map((heading, idx) => ( -
- {renderColHeadings(heading)} -
- )) - .reverse()} - -
- {columns.map((column) => - isGroupColumn(column) ? ( - console.log("onToggleGroupState")} - onRemoveColumn={handleRemoveGroup} - /> - ) : ( - - ) - )} -
-
- - {custom?.inlineHeader.component} - -
- ); - }) -); - -export default ColumnGroupHeader; - -ColumnGroupHeader.displayName = "ColumnGroupHeader"; diff --git a/vuu-ui/packages/vuu-datagrid/src/DataGrid.css b/vuu-ui/packages/vuu-datagrid/src/DataGrid.css deleted file mode 100644 index 70fde278c..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/DataGrid.css +++ /dev/null @@ -1,101 +0,0 @@ -.vuuDataGrid { - --grid-background: var(--salt-container-tertiary-background, inherit); - --grid-row-background: inherit; - --grid-row-height: var(--grid-row-height, 20px); - --grid-row-line-height: 19px; - --grid-row-background-selected: var(--salt-selectable-background-selected); - --grid-header-cell-highlight-bg: var(--surface3); - - --hw-activation-indicator-thumb-bg: #2c2c2c; - --grid-flex-align: stretch; - --grid-cell-bg: var(--grid-cell-bg, var(--background)); - --cell-border-top-color: transparent; - --cell-border-bottom-color: transparent; - --cell-border-right-color: var(--grid-cell-border-color, var(--salt-separable-tertiary-borderColor)); - --cell-border-style: var(--hwDataGridCell-border-style, solid); - --cell-highlight-bg: var(--grid-cell-highlight-bg); - --drag-column-bg: var(--grid-drag-column-bg, 'ivory'); - --cell-padding: 0 9px; - --header-background: var(--grid-header-background, var(--background, white)); - --header-cell-height: 24px; - --header-cell-highlight-bg: var(--grid-header-cell-highlight-bg); - --heading-border-color: var(--grid-heading-border-color, var(--salt-separable-primary-borderColor)); - --line-number-bg: var(--salt-actionable-primary-background); - --line-number-border-color: #ccc; - --text-color: var(--grid-text-color, var(--text2)); - --focus-visible-border-color: var(--hw-focus-visible-border-color, rgb(141, 154, 179)); - - background-color: var(--grid-background); - box-sizing: border-box; - align-self: var(--grid-flex-align); - flex: var(--hwDataGrid-flex, 1 1 0px); - position: relative; - font-size: var(--vuuDataGrid-font-size, 10px); - outline: none; - overflow: hidden; -} - -.vuuDataGrid.scrolling-x .vuuDataGrid-Viewport { - overflow-y: hidden !important; - height: 100% !important; -} - -.vuuDataGrid.scrolling-x .vuuDataGridCanvas .hwColumnGroupHeader { - position: relative; -} - -.vuuDataGrid-Viewport { - background-color: var(--surface2); - - outline: none; - overflow-x: hidden; - overflow-y: auto; -} - -.vuuDataGrid-scrollingCanvasContainer { - overflow: hidden; - white-space: nowrap; -} - -/* Canvas */ -.vuuDataGridCanvas { - display: inline-block; - top: 0; - vertical-align: top; -} - -.Canvas-fixed { - overflow: hidden; -} - -.Canvas-fixed .vuuDataGridCell { - background-color: #efeded; -} - -.Canvas-scrollable { - overflow-x: auto; - overscroll-behavior-x: contain; - overflow-y: hidden; -} - -.vuuDataGridCanvas-canvasContent { - position: relative; -} - -.vuuDataGridCanvas .hwColumnGroupHeader { - position: absolute; - top: 0; -} - -.DraggedColumn { - background-color: var(--drag-column-bg); - opacity: 0.4; -} - -.Vanishing { - border-style: none; - color: transparent; - padding: 0; - transition: width ease 0.3s; - width: 0 !important; -} diff --git a/vuu-ui/packages/vuu-datagrid/src/DataGrid.tsx b/vuu-ui/packages/vuu-datagrid/src/DataGrid.tsx deleted file mode 100644 index e73fb733d..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/DataGrid.tsx +++ /dev/null @@ -1,285 +0,0 @@ -import { ConfigChangeMessage } from "@finos/vuu-data"; -import { ContextMenuProvider } from "@finos/vuu-popups"; -import { useForkRef } from "@salt-ds/core"; -import cx from "classnames"; -import { - ForwardedRef, - forwardRef, - useCallback, - useMemo, - useRef, - useState, -} from "react"; -import { ComponentProvider } from "./component-context"; -import { buildContextMenuDescriptors, useContextMenu } from "./context-menu"; -import { Footer, GridAdornment, Header, InlineHeader } from "./grid-adornments"; -import { GridProvider } from "./grid-context"; -import { - useGridActionDispatcher, - useHorizonatlScrollSync, - useKeyboardNavigation, - useSelection, -} from "./grid-hooks"; -import { measureColumns, useGridModel } from "./grid-model"; -import { GridModelType } from "./grid-model/gridModelTypes"; -import { ColumnDragState, GridProps } from "./gridTypes"; -import { RowHeightCanary } from "./RowHeightCanary"; -import components from "./standard-renderers"; -import { Viewport } from "./Viewport"; - -import "./DataGrid.css"; - -// TODO use a null datasource and empty columns defs -// display a warning if loaded with no dataSource - -const noop = () => undefined; -const DEFAULT_COLUMN_WIDTH = 100; -const MIN_COLUMN_WIDTH = 80; - -const baseClass = "vuuDataGrid"; - -export const Grid = forwardRef(function Grid( - { - aggregations, - cellSelectionModel = "none", - className, - columns, - columnSizing = "static", - dataSource: dataSourceProp, - defaultColumnWidth = DEFAULT_COLUMN_WIDTH, - filter, - groupBy, - headerHeight = 24, - height: heightProp, - minColumnWidth = MIN_COLUMN_WIDTH, - noColumnHeaders = false, - onConfigChange = noop, - onRowClick, - renderBufferSize = 0, - rowHeight = 20, - selectionModel = "none", // default should be none - showLineNumbers = false, - sort, - style: styleProp, - width: widthProp, - ...htmlAttributes - }: GridProps, - forwardedRef: ForwardedRef -) { - const viewportRef = useRef(null); - const gridModelRef = useRef(); - const [columnDragData, setColumnDragData] = useState(); - const [rootRef, gridModel, dataSource, dispatchGridModelAction, custom] = - useGridModel({ - aggregations, - cellSelectionModel, - columns, - columnSizing, - dataSource: dataSourceProp, - defaultColumnWidth, - filter, - groupBy, - headerHeight, - height: heightProp, - minColumnWidth, - noColumnHeaders, - renderBufferSize, - rowHeight, - selectionModel, // default should be none - showLineNumbers, - sort, - style: styleProp, - width: widthProp, - }); - - gridModelRef.current = gridModel; - - const onChangeCallDatasourceSelect = useCallback( - (selected) => { - dataSource.select(selected); - }, - [dataSource] - ); - - const handleSelectionChange = useSelection({ - onChange: onChangeCallDatasourceSelect, - selection: gridModel.selectionModel, - }); - - const invokeScrollAction = useHorizonatlScrollSync({ - gridModel, - rootRef, - viewportRef, - }); - - const invokeDataSourceAction = useCallback( - (operation) => { - switch (operation.type) { - case "openTreeNode": - return dataSource.openTreeNode(operation.key); - case "closeTreeNode": - return dataSource.closeTreeNode(operation.key); - case "group": - return (dataSource.groupBy = operation.key); - case "sort": - return (dataSource.sort = operation.sort); - default: - console.log( - `[GridBase] dataSourceOperation: unknown operation ${operation.type}` - ); - } - }, - [dataSource] - ); - - const handleConfigChange = useCallback( - ({ type }: ConfigChangeMessage) => { - if (onConfigChange && gridModelRef.current) { - switch (type) { - case "columns": { - const { - current: { columns }, - } = gridModelRef; - return onConfigChange({ - type, - columns, - }); - } - default: - } - } - }, - [onConfigChange] - ); - - const dispatchGridAction = useGridActionDispatcher({ - dispatchGridModelAction, - invokeDataSourceAction, - handleSelectionChange, - invokeScrollAction, - onConfigChange: handleConfigChange, - }); - - const handleContextMenuAction = useContextMenu({ - dataSource, - gridModel, - dispatchGridModelAction, - }); - - // useDataSourceModelBindings(dataSource, gridModel); - const handleChangeRange = useKeyboardNavigation(rootRef, gridModel); - - const handleColumnDragStart = useCallback( - (phase, ...args) => { - if (rootRef.current && gridModel) { - const [columnGroupIdx, column, columnPosition, mousePosition] = args; - const { left } = rootRef.current.getBoundingClientRect(); - const columnGroup = gridModel.columnGroups?.[columnGroupIdx]; - invokeScrollAction({ type: "scroll-start-horizontal" }); - const columnIdx = columnGroup?.columns.findIndex( - (col) => col.key === column.key - ); - if (columnIdx !== undefined && columnIdx !== -1) { - setColumnDragData({ - column, - columnGroupIdx, - columnIdx, - initialColumnPosition: columnPosition - left, - columnPositions: measureColumns(gridModel, left), - mousePosition, - }); - } - } - }, - [gridModel, invokeScrollAction, rootRef] - ); - const handleColumnDrop = useCallback( - (phase, ...args) => { - const [column, insertIdx] = args; - setColumnDragData(undefined); - // TODO we need the final scrollLeft here - invokeScrollAction({ type: "scroll-end-horizontal" }); - dispatchGridModelAction({ - type: "add-col", - column, - insertIdx, - }); - setTimeout(() => handleConfigChange({ type: "columns" }), 0); - }, - [dispatchGridModelAction, handleConfigChange, invokeScrollAction] - ); - - const { width = "100%", height = "100%", totalHeaderHeight } = gridModel; - const style = { - ...styleProp, - width, - height, - paddingTop: totalHeaderHeight, - "--grid-row-height": `${gridModel.rowHeight}px`, - }; - - const gridContextData = useMemo( - () => ({ - custom, - dataSource, - dispatchGridAction, - dispatchGridModelAction, - gridModel, - }), - [custom, dataSource, dispatchGridAction, dispatchGridModelAction, gridModel] - ); - - const readyToRender = gridModel.status === "ready"; - - return ( - // Question, how much overhead are we introducing be adding gridModel to GridContext ? Perhaps it belongs in it's own context - - - -
- - {readyToRender ? ( - <> - {custom.header.component} - - {custom.footer.component} - - ) : null} -
-
-
-
- ); -}) as React.ForwardRefExoticComponent & { - Header: GridAdornment; - InlineHeader: GridAdornment; - Footer: GridAdornment; -}; - -Grid.Header = Header; -Grid.InlineHeader = InlineHeader; -Grid.Footer = Footer; - -Grid.displayName = "Grid"; diff --git a/vuu-ui/packages/vuu-datagrid/src/InsertIndicator.css b/vuu-ui/packages/vuu-datagrid/src/InsertIndicator.css deleted file mode 100644 index a34454f8e..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/InsertIndicator.css +++ /dev/null @@ -1,8 +0,0 @@ -.vuuInsertIndicator { - background-color: green; - height: 100%; - position: absolute; - top: 0; - transition: left ease-in-out 0.2s; - width: 4px; -} diff --git a/vuu-ui/packages/vuu-datagrid/src/InsertIndicator.tsx b/vuu-ui/packages/vuu-datagrid/src/InsertIndicator.tsx deleted file mode 100644 index 0dee2d779..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/InsertIndicator.tsx +++ /dev/null @@ -1,12 +0,0 @@ -import { ForwardedRef, forwardRef, HTMLAttributes } from "react"; - -import "./InsertIndicator.css"; - -const InsertIndicator = forwardRef(function InsertIndicator( - props: HTMLAttributes, - forwardedRef: ForwardedRef -) { - return
; -}); - -export default InsertIndicator; diff --git a/vuu-ui/packages/vuu-datagrid/src/RowHeightCanary.css b/vuu-ui/packages/vuu-datagrid/src/RowHeightCanary.css deleted file mode 100644 index 590db8476..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/RowHeightCanary.css +++ /dev/null @@ -1,6 +0,0 @@ -.Grid-rowHeightCanary { - position: absolute; - height: var(--grid-row-height, 24px); - width: 100%; - z-index: -1; -} diff --git a/vuu-ui/packages/vuu-datagrid/src/RowHeightCanary.tsx b/vuu-ui/packages/vuu-datagrid/src/RowHeightCanary.tsx deleted file mode 100644 index 99b28176f..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/RowHeightCanary.tsx +++ /dev/null @@ -1,7 +0,0 @@ -import { useRowHeight } from "./use-row-height"; -import "./RowHeightCanary.css"; - -export const RowHeightCanary = () => { - const rowHeightCanary = useRowHeight(); - return
; -}; diff --git a/vuu-ui/packages/vuu-datagrid/src/Viewport.tsx b/vuu-ui/packages/vuu-datagrid/src/Viewport.tsx deleted file mode 100644 index 79398ef93..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/Viewport.tsx +++ /dev/null @@ -1,449 +0,0 @@ -import { DataSourceRow } from "@finos/vuu-data-types"; -import { useContextMenu } from "@finos/vuu-popups"; -import { buildColumnMap, metadataKeys } from "@finos/vuu-utils"; -import { - createRef, - ForwardedRef, - forwardRef, - MouseEvent, - RefObject, - useCallback, - useEffect, - useImperativeHandle, - useLayoutEffect, - useRef, -} from "react"; -import { Canvas, CanvasAPI } from "./canvas"; -import { ColumnBearer, ColumnBearerAPI } from "./ColumnBearer"; -import { SubscriptionDetails, useDataSource } from "./grid-hooks"; -import { getColumnGroupColumnIdx } from "./grid-model/gridModelUtils.js"; -import { ViewportProps } from "./gridTypes"; -import InsertIndicator from "./InsertIndicator"; -import useScroll from "./use-scroll"; -import useUpdate from "./use-update"; -import { useEffectSkipFirst } from "./utils"; - -export interface ViewportScrollApi { - beginHorizontalScroll: () => void; - endHorizontalScroll: () => void; -} - -// Temp, until we manage selection properly -const getSelectedRows = (data: DataSourceRow[]) => { - return data.filter((d) => d[metadataKeys.SELECTED] !== 0); -}; - -export const Viewport = forwardRef(function Viewport( - { - columnDragData, - gridModel, - onColumnDragStart, - onColumnDrop, - onConfigChange, - onChangeRange, - onRowClick, - }: ViewportProps, - forwardedRef: ForwardedRef -) { - const viewportEl = useRef(null); - const scrollingEl = useRef(null); - const canvasRefs = useRef[]>([]); - const columnBearer = useRef(null); - const horizontalScrollbarHeight = useRef(gridModel.horizontalScrollbarHeight); - const verticalScrollbarWidth = useRef(0); - const firstVisibleRow = useRef(0); - const insertIndicatorRef = useRef(null); - - const { rowHeight, viewportHeight, viewportRowCount } = gridModel; - - useEffect(() => { - horizontalScrollbarHeight.current = gridModel.horizontalScrollbarHeight; - }, [gridModel.horizontalScrollbarHeight]); - - // TODO we could get gridModel here as well. Or would it be better to split gridModel into it's own context ? - - const getRoundedRange = useCallback( - (from: number) => { - const newFrom = Math.floor(from); - const newTo = newFrom + Math.ceil(viewportRowCount); - if (newFrom === newFrom && newTo < viewportRowCount) { - return { from: newFrom, to: newTo + 1 }; - } else { - return { from: newFrom, to: newTo }; - } - }, - [viewportRowCount] - ); - - const gridModelRef = useRef(gridModel); - if (gridModelRef.current !== gridModel) { - // Is there a better way to do this - the dataSource effect needs to get the latest gridModel - // but changes to gridModel should not trigger re-subscription - gridModelRef.current = gridModel; - } - - const showColumnBearer = useRef(columnDragData !== null); - showColumnBearer.current = columnDragData !== null; - - const canvasCount = gridModel.columnGroups - ? gridModel.columnGroups.length - : 0; - if (canvasRefs.current.length !== canvasCount) { - // add or remove refs - canvasRefs.current = Array(canvasCount) - .fill(null) - .map((_, i) => canvasRefs.current[i] || createRef()); - } - const scrollableCanvasIdx = gridModel.columnGroups - ? gridModel.columnGroups.findIndex((group) => !group.locked) - : -1; - - const handleColumnBearerScroll = (scrollDistance: number): number => { - const canvas = canvasRefs.current[scrollableCanvasIdx].current; - return canvas ? canvas.scrollBy(scrollDistance) : 0; - }; - - const handleColumnDrag = useCallback( - async (dragPhase, draggedColumn, insertIdx, insertPos, columnLeft) => { - if ( - columnDragData && - insertIndicatorRef.current && - columnBearer.current - ) { - const { columnGroupIdx, columnIdx } = columnDragData; - const { current: canvas } = canvasRefs.current[columnGroupIdx]; - if (dragPhase === "drag") { - // only called when we cross onto next targetColumn - insertIndicatorRef.current.style.left = insertPos + "px"; - } else if (dragPhase === "drag-end" && canvas && columnBearer.current) { - insertIndicatorRef.current.style.transition = "left ease .3s"; - if (canvas.isWithinScrollWindow(draggedColumn)) { - if (insertIdx > columnIdx) { - insertIndicatorRef.current.style.left = - insertPos - draggedColumn.width + "px"; - columnBearer.current.setFinalPosition( - insertPos - draggedColumn.width - ); - } else { - insertIndicatorRef.current.style.left = insertPos + "px"; - columnBearer.current.setFinalPosition(insertPos); - } - } - const groupInsertIdx = getColumnGroupColumnIdx(gridModel, insertIdx); - await canvas.endDrag(columnDragData, groupInsertIdx, columnLeft); - onColumnDrop?.(dragPhase, draggedColumn, insertIdx); - } - } - }, - [gridModel, onColumnDrop, columnDragData] - ); - - // we should not take columnNames from gridModel - they will not yet have been recomputed if - // dataSource has changed - const { columnNames, sort } = gridModelRef.current; - const subscriptionDetails = useRef({ - columnNames, - range: getRoundedRange(0), - sort, - }); - - const handleSizeChange = useCallback( - (newSize) => { - // How do we handle this withoput having this dependency on gridModel ? - // This is the important one, it comes with every rowSet - if ( - newSize >= Math.ceil(viewportRowCount) && - verticalScrollbarWidth.current === 0 - ) { - verticalScrollbarWidth.current = 15; - } else if ( - newSize < Math.ceil(viewportRowCount) && - verticalScrollbarWidth.current === 15 - ) { - verticalScrollbarWidth.current = 0; - } - }, - [viewportRowCount] - ); - - const { - data, - setRange: _setRange, - dataSource, - } = useDataSource( - subscriptionDetails.current, - gridModel, - onConfigChange, - handleSizeChange - ); - // Keep a ref to current data. We use it to provide row for context menu actions. - // We don't want to introduce data as a dependency on the context menu handler, just - // needs to be correct at runtime when the row is right clicked. - const dataRef = useRef(); - dataRef.current = data; - - const rowCount = dataSource?.size ?? 0; - - const previousRange = useRef({ from: 0, to: 0 }); - const setRange = useCallback( - (from, to) => { - const { from: newFrom, to: newTo } = getRoundedRange(from); - const { - current: { from: previousFrom, to: previousTo }, - } = previousRange; - if (newFrom !== previousFrom || newTo !== previousTo) { - _setRange(newFrom, newTo); - onChangeRange && onChangeRange({ from, to }); - previousRange.current.from = newFrom; - previousRange.current.to = newTo; - } - }, - [getRoundedRange, _setRange, onChangeRange] - ); - - useUpdate(() => { - setRange( - firstVisibleRow.current, - firstVisibleRow.current + viewportRowCount - ); - }, [viewportRowCount]); - - const scrollCallback = useCallback( - (scrollEvent, scrollTop) => { - if (scrollEvent === "scroll") { - const firstRow = scrollTop / rowHeight; - if (firstRow !== firstVisibleRow.current) { - firstVisibleRow.current = firstRow; - const lastRow = firstRow + viewportRowCount; - - // const lastRow = firstRow + Math.ceil(gridModel.viewportRowCount); - if (lastRow > rowCount) { - setRange(rowCount - viewportRowCount, rowCount); - } else { - setRange(firstRow, firstRow + viewportRowCount); - } - } - } else if (scrollEvent === "scroll-start") { - canvasRefs.current.forEach(({ current }) => - current?.beginVerticalScroll() - ); - } else { - canvasRefs.current.forEach(({ current }) => - current?.endVerticalScroll(scrollTop) - ); - } - }, - [rowHeight, viewportRowCount, rowCount, setRange] - ); - - useEffectSkipFirst(() => { - if (viewportEl.current) { - viewportEl.current.scrollTop = 0; - } - }, [dataSource]); - - useLayoutEffect(() => { - if (columnDragData && viewportEl.current && insertIndicatorRef.current) { - const { column, columnGroupIdx } = columnDragData; - const canvas = canvasRefs.current[columnGroupIdx].current; - if (canvas) { - const columnOffset = canvas.beginDrag(column) ?? 0; - const { left } = viewportEl.current.getBoundingClientRect(); - insertIndicatorRef.current.style.left = columnOffset - left + "px"; - } - } - }, [columnDragData]); - - const [handleVerticalScroll, suspendScrollHandling] = useScroll( - "scrollTop", - scrollCallback - ); - - const [showContextMenu] = useContextMenu(); - const onContextMenu = useCallback( - (evt: MouseEvent) => { - const { current: currentData } = dataRef; - - const target = evt.target as HTMLElement; - const cellEl = target?.closest(".vuuDataGridCell") as HTMLElement; - const rowEl = target?.closest(".vuuDataGridRow") as HTMLElement; - - if (cellEl && rowEl && currentData && dataSource) { - const { columns, selectedRowsCount, viewport } = dataSource; - const columnMap = buildColumnMap(columns); - const rowIndex = parseInt(rowEl.dataset.idx ?? "-1"); - const cellIndex = Array.from(rowEl.childNodes).indexOf(cellEl); - const row = currentData.find(([idx]) => idx === rowIndex); - // Hack: +1 to allow for line no - const columnName = dataSource.columns[cellIndex - 1]; - console.log({ columnName }); - - showContextMenu(evt, "grid", { - columnMap, - columnName, - row, - selectedRows: getSelectedRows(data), - selectedRowsCount, - viewport, - }); - } - }, - [data, dataSource, showContextMenu] - ); - - useImperativeHandle(forwardedRef, () => ({ - beginHorizontalScroll: () => { - if (!showColumnBearer.current && scrollingEl.current) { - const header = - gridModel.headerHeight * (gridModel.headingDepth ?? 1) + - gridModel.customInlineHeaderHeight; - scrollingEl.current.style.height = `${ - header + - Math.max( - rowCount * rowHeight + (horizontalScrollbarHeight.current ?? 0), - gridModel.viewportHeight - ) - }px`; - canvasRefs.current.forEach(({ current }) => - current?.beginHorizontalScroll() - ); - } - }, - endHorizontalScroll: () => { - if (!showColumnBearer.current) { - canvasRefs.current.forEach(({ current }) => { - current && current.endHorizontalScroll(); - }); - if (scrollingEl.current) { - scrollingEl.current.style.height = `${Math.max( - rowCount * rowHeight + (horizontalScrollbarHeight.current ?? 0), - gridModel.viewportHeight - )}px`; - return canvasRefs.current[scrollableCanvasIdx].current?.scrollLeft; - } - } - }, - })); - - const scrollBy = useCallback( - (rows) => { - if (viewportEl.current) { - const { scrollTop } = viewportEl.current; - const scrollAmt = - rows === 1 - ? rowHeight - ((viewportHeight + scrollTop) % rowHeight) || - rowHeight - : rows === -1 - ? -(scrollTop % rowHeight) || -rowHeight - : scrollTop + rows * rowHeight - (scrollTop % rowHeight); - viewportEl.current.scrollTop = scrollTop + scrollAmt; - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, - [rowHeight, viewportHeight] - ); - - const scrollEnd = useCallback( - (startOrEnd) => { - if (viewportEl.current) { - suspendScrollHandling(true); - const scrollPos = - startOrEnd === "start" ? 0 : rowCount * rowHeight - viewportHeight; - viewportEl.current.scrollTop = scrollPos; - suspendScrollHandling(false); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, - [rowCount, rowHeight, viewportHeight, suspendScrollHandling] - ); - - const handleKeyDown = useCallback( - (evt) => { - switch (evt.key) { - case "ArrowDown": - evt.preventDefault(); - scrollBy(1); - break; - case "ArrowUp": - evt.preventDefault(); - scrollBy(-1); - break; - case "Home": - evt.preventDefault(); - scrollEnd("start"); - break; - case "End": - evt.preventDefault(); - scrollEnd("end"); - break; - default: - } - }, - [scrollBy, scrollEnd] - ); - - // Rowcount is only available after first data response is received from dataSource - const contentRowCount = rowCount ?? Math.floor(gridModel.viewportRowCount); - - return ( - <> -
-
- {gridModel.columnGroups - ? gridModel.columnGroups.map((columnGroup, idx) => ( - - )) - : null} -
-
- {columnDragData && ( - <> - - - - )} - - ); -}); diff --git a/vuu-ui/packages/vuu-datagrid/src/actions.js b/vuu-ui/packages/vuu-datagrid/src/actions.js deleted file mode 100644 index baf4eb7d1..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/actions.js +++ /dev/null @@ -1,25 +0,0 @@ -export const COLUMN_COLLAPSE = 'COLUMN_COLLAPSE'; -export const COLUMN_EXPAND = 'COLUMN_EXPAND'; -export const COLUMNS_CHANGE = 'COLUMNS_CHANGE'; -export const INITIALIZE = 'INITIALIZE'; -export const ROWCOUNT = 'ROWCOUNT'; -export const SUBSCRIBED = 'SUBSCRIBED'; -export const GROUP = 'GROUP'; -export const SORT = 'SORT'; -export const SORT_GROUP = 'SORT_GROUP'; -export const GRID_RESIZE = 'GRID_RESIZE'; -export const COLUMN_RESIZE_BEGIN = 'COLUMN_RESIZE_BEGIN'; -export const COLUMN_RESIZE = 'COLUMN_RESIZE'; -export const COLUMN_RESIZE_END = 'COLUMN_RESIZE_END'; -export const GROUP_COLUMN_WIDTH = 'GROUP_COLUMN_WIDTH'; -export const RESIZE_HEADING = 'RESIZE_HEADING'; -export const MOVE_BEGIN = 'MOVE_BEGIN'; -export const MOVE = 'MOVE'; -export const MOVE_END = 'MOVE_END'; -export const TOGGLE = 'TOGGLE'; -export const TOGGLE_FILTERS = 'TOGGLE_FILTERS'; -export const SCROLLLEFT = 'SCROLLLEFT'; -export const SCROLL_LEFT = 'SCROLL_LEFT'; -export const SCROLL_RIGHT = 'SCROLL_RIGHT'; -export const RANGE = 'RANGE'; -export const groupExtend = 'GROUP_EXTEND'; diff --git a/vuu-ui/packages/vuu-datagrid/src/canvas/Canvas.tsx b/vuu-ui/packages/vuu-datagrid/src/canvas/Canvas.tsx deleted file mode 100644 index 189c1308b..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/canvas/Canvas.tsx +++ /dev/null @@ -1,496 +0,0 @@ -import { RuntimeColumnDescriptor } from "@finos/vuu-datagrid-types"; -import { buildColumnMap, DataRow, metadataKeys } from "@finos/vuu-utils"; -import cx from "classnames"; -import { - ForwardedRef, - forwardRef, - MutableRefObject, - useCallback, - useImperativeHandle, - useMemo, - useReducer, - useRef, -} from "react"; -import ColumnGroupHeader, { ColumnGroupHeaderAPI } from "../ColumnGroupHeader"; -import { useGridContext } from "../grid-context"; -import { ColumnGroupType, GridModelType } from "../grid-model/gridModelTypes"; -import { getColumnOffset } from "../grid-model/gridModelUtils"; -import Row from "../grid-row"; -import { - ColumnDragStartHandler, - ColumnDragState, - RowClickHandler, -} from "../gridTypes"; -import useScroll from "../use-scroll"; -import useUpdate from "../use-update"; -import { - CanvasReducer, - canvasReducer, - initCanvasReducer, -} from "./canvas-reducer"; - -const { IDX, RENDER_IDX, SELECTED } = metadataKeys; - -const classBase = "vuuDataGridCanvas"; - -interface EffectWithIdx { - idx: number; -} -interface AddClassEffect extends EffectWithIdx { - type: "addClass"; -} -interface AddClassEffect extends EffectWithIdx { - type: "addClass"; -} -interface CloseSpaceLeftEffect extends EffectWithIdx { - type: "closeSpaceLeft"; -} -interface OpenSpaceLeftEffect extends EffectWithIdx { - type: "openSpaceLeft"; -} -interface RemoveClassEffect extends EffectWithIdx { - type: "removeClass"; - className: string; -} -interface ReplaceClassEffect extends EffectWithIdx { - type: "replaceClass"; - className: string; - newClassName: string; -} - -type Effect = - | AddClassEffect - | CloseSpaceLeftEffect - | OpenSpaceLeftEffect - | RemoveClassEffect - | ReplaceClassEffect; - -export interface CanvasProps { - columnGroupIdx: number; - contentHeight: number; - firstVisibleRow: number; - gridModel: GridModelType; - height: number; - horizontalScrollbarHeight: number; - onColumnDragStart?: ColumnDragStartHandler; - ref?: MutableRefObject; - data: DataRow[]; - onRowClick?: RowClickHandler; -} - -export interface CanvasAPI { - beginDrag: (column: RuntimeColumnDescriptor) => number | undefined; - beginHorizontalScroll: () => void; - beginVerticalScroll: () => void; - endDrag: ( - columnDragData: ColumnDragState, - insertIdx: number, - columnLeft: number - ) => void; - endHorizontalScroll: () => void; - isWithinScrollWindow: (column: RuntimeColumnDescriptor) => boolean; - endVerticalScroll: (scrollTol: number) => void; - scrollBy: (distance: number) => number; - scrollLeft: number; -} - -export const Canvas = forwardRef(function Canvas( - { - columnGroupIdx, - contentHeight, - gridModel, - height, - horizontalScrollbarHeight, - onColumnDragStart, - onRowClick, - data: rows, - }: CanvasProps, - forwardedRef: ForwardedRef -) { - const canvasEl = useRef(null); - const contentEl = useRef(null); - const columnGroupHeader = useRef(null); - const { dispatchGridAction } = useGridContext(); - const columnGroup = gridModel.columnGroups?.[ - columnGroupIdx - ] as ColumnGroupType; - const scrollbarHeightAdjustment = columnGroup.locked - ? horizontalScrollbarHeight - : 0; - - const [[columns], dispatchCanvasAction] = useReducer< - CanvasReducer, - ColumnGroupType - >(canvasReducer, columnGroup, initCanvasReducer); - - const columnMap = useMemo( - () => buildColumnMap(gridModel.columnNames), - [gridModel.columnNames] - ); - - useUpdate(() => { - dispatchCanvasAction({ type: "refresh", columnGroup }); - }, [columnGroup.width, columnGroup.columns]); - - const getColumnIdx = (column: RuntimeColumnDescriptor) => - columns.findIndex((col) => col.key === column.key); - - useImperativeHandle(forwardedRef, () => ({ - beginHorizontalScroll: () => { - if (canvasEl.current && gridModel.height) { - const canvasHeight = columnGroup.locked - ? gridModel.height - horizontalScrollbarHeight - : gridModel.height; - canvasEl.current.style.height = `${ - canvasHeight - - gridModel.customHeaderHeight - - gridModel.customFooterHeight - }px`; - } - }, - endHorizontalScroll: () => { - if (canvasEl.current) { - const canvasHeight = columnGroup.locked - ? height - horizontalScrollbarHeight - : height; - canvasEl.current.style.height = `${canvasHeight}px`; - } - }, - beginVerticalScroll: () => { - if (canvasEl.current && contentEl.current) { - canvasEl.current.style.marginTop = "0px"; - canvasEl.current.style.height = `${ - contentHeight + horizontalScrollbarHeight - }px`; - contentEl.current.style.transform = "translate3d(0px, 0px, 0px)"; - } - }, - - endVerticalScroll: (scrollTop) => { - if (canvasEl.current && contentEl.current) { - canvasEl.current.style.marginTop = scrollTop + "px"; - canvasEl.current.style.height = `${ - height - scrollbarHeightAdjustment - }px`; - contentEl.current.style.transform = `translate3d(0px, -${scrollTop}px, 0px)`; - } - }, - - beginDrag: (column) => { - if (canvasEl.current && contentEl.current) { - const idx = columns.findIndex((col) => col.key === column.key); - const rows = Array.from(contentEl.current.childNodes) as HTMLElement[]; - const headerCells = getHeaderCells(canvasEl.current); - const effect: Effect = { type: "addClass", idx }; - applyOperationToHeaderCells([effect], headerCells, column.width); - applyOperationToRows([effect], rows, column.width); - const { left } = headerCells[idx].getBoundingClientRect(); - return left; - } - }, - - endDrag: ( - columnDragData, - insertIdx, - columnLeft - ): Promise | undefined => { - if (canvasEl.current && contentEl.current) { - const { column } = columnDragData; - const idx = getColumnIdx(column); - const rows = Array.from(contentEl.current.childNodes) as HTMLElement[]; - const headerCells = getHeaderCells(canvasEl.current); - if (idx === -1) { - // we're going to reposition the scrolling canvas, such that the inserted column ends up - // exactly where we drop it - let scrollLeft = canvasEl.current.scrollLeft; - // get the onscreen offset (relative to grid) of the insertion point - const insertionPointLeft = - getColumnOffset(gridModel, columnGroupIdx, insertIdx) - scrollLeft; - // recompute scrollLeft to line up the insertion point with left edge of dragged column. - scrollLeft += insertionPointLeft - columnLeft; - if (columnDragData.columnIdx < insertIdx) { - // if column was originally offscreen to the left, we can remove it's width from the scrollLeft - scrollLeft -= column.width ?? 0; - } - canvasEl.current.scrollLeft = scrollLeft; - } else { - // We only need this if the original column position is still inside the scroll window - const effects: Effect[] = [ - { - type: "replaceClass", - idx, - className: "DraggedColumn", - newClassName: "Vanishing", - }, - { type: "openSpaceLeft", idx: insertIdx }, - ]; - applyOperationToHeaderCells(effects, headerCells, column.width); - applyOperationToRows(effects, rows, column.width); - return new Promise((resolve) => { - headerCells[idx].addEventListener("transitionend", () => { - const effects: Effect[] = [ - { - type: "removeClass", - idx, - className: "Vanishing", - }, - { type: "closeSpaceLeft", idx: -insertIdx }, - ]; - applyOperationToHeaderCells(effects, headerCells); - applyOperationToRows(effects, rows); - resolve(); - }); - }); - } - } - }, - - isWithinScrollWindow: (column: RuntimeColumnDescriptor) => - getColumnIdx(column) !== -1, - - scrollBy: (scrollDistance: number) => scrollBy(scrollDistance), - - get scrollLeft() { - return canvasEl.current?.scrollLeft ?? 0; - }, - })); - - // TODO memoize - function applyOperationToHeaderCells( - effects: Effect[], - headerCells: HTMLElement[], - width = 0 - ) { - effects.forEach((effect) => { - const suppressTransition = effect.idx < 0; - const idx = Math.abs(effect.idx); - for (let i = 0; i < headerCells.length; i++) { - if (idx !== -1 && idx < headerCells.length) { - switch (effect.type) { - case "openSpaceLeft": - openSpaceLeft(headerCells[idx], width, suppressTransition); - break; - case "closeSpaceLeft": - closeSpaceLeft(headerCells[idx], suppressTransition); - break; - case "addClass": - headerCells[idx].classList.add("DraggedColumn"); - break; - case "removeClass": - headerCells[idx].classList.remove(effect.className); - break; - case "replaceClass": - headerCells[idx].classList.replace( - effect.className, - effect.newClassName - ); - break; - default: - } - } - } - }); - } - function applyOperationToRows( - effects: Effect[], - rows: HTMLElement[], - width = 0 - ) { - effects.forEach((effect) => { - const suppressTransition = effect.idx < 0; - const idx = Math.abs(effect.idx); - for (let i = 0; i < rows.length; i++) { - const cells = Array.from(rows[i].childNodes) as HTMLElement[]; - if (idx !== -1 && idx < cells.length) { - switch (effect.type) { - case "openSpaceLeft": - openSpaceLeft(cells[idx], width, suppressTransition); - break; - case "closeSpaceLeft": - closeSpaceLeft(cells[idx], suppressTransition); - break; - case "addClass": - cells[idx].classList.add("DraggedColumn"); - break; - case "removeClass": - cells[idx].classList.remove(effect.className); - break; - case "replaceClass": - cells[idx].classList.replace( - effect.className, - effect.newClassName - ); - break; - default: - } - } - } - }); - } - - const scrollBy = useCallback( - (scrollDistance: number): number => { - if (canvasEl.current) { - const scrollLeft = canvasEl.current.scrollLeft; - let newScrollLeft = 0; - - if (scrollDistance < 0) { - if (scrollLeft === 0) { - return 0; - } else { - newScrollLeft = Math.max(0, scrollLeft + scrollDistance); - } - } else { - // need to read this once, at start - const maxScroll = - canvasEl.current.scrollWidth - canvasEl.current.clientWidth; - if (scrollLeft === maxScroll) { - return 0; - } else { - newScrollLeft = Math.min(maxScroll, scrollLeft + scrollDistance); - } - } - canvasEl.current.scrollLeft = newScrollLeft; - // return the distance actually scrolled - return newScrollLeft - scrollLeft; - } else { - return 0; - } - }, - [canvasEl] - ); - - const { contentWidth, width } = columnGroup; - - const horizontalScrollHandler = useCallback( - (scrollEvent, scrollLeft) => { - if (scrollEvent === "scroll") { - dispatchCanvasAction({ type: "scroll-left", scrollLeft }); - } else if (scrollEvent === "scroll-start" && columnGroupHeader.current) { - dispatchGridAction?.({ type: "scroll-start-horizontal", scrollLeft }); - columnGroupHeader.current.beginHorizontalScroll( - columnGroup.contentWidth - ); - } else if (canvasEl.current && columnGroupHeader.current) { - canvasEl.current.style.height = `${ - height - scrollbarHeightAdjustment - }px`; - columnGroupHeader.current.endHorizontalScroll( - scrollLeft, - columnGroup.width - ); - dispatchGridAction?.({ type: "scroll-end-horizontal", scrollLeft }); - } - }, - [ - columnGroup.contentWidth, - columnGroup.width, - dispatchCanvasAction, - dispatchGridAction, - height, - scrollbarHeightAdjustment, - ] - ); - - const handleRowClick = useCallback( - (idx, row, rangeSelect, keepExistingSelection) => { - // This poses an interesting question. If selection is server side - // at what point can we fire a selectionChange event - we have to do that clientSide - - // need to watch for the selectionACK - if (onRowClick) { - onRowClick(row); - } - - dispatchGridAction?.({ - type: "selection", - idx, - row, - rangeSelect, - keepExistingSelection, - }); - }, - [dispatchGridAction, onRowClick] - ); - - const [onHorizontalScroll] = useScroll( - "scrollLeft", - horizontalScrollHandler, - 5 - ); - - const rootClassName = cx(classBase, { - "Canvas-fixed": columnGroup.locked, - "Canvas-scrollable": !columnGroup.locked, - }); - - const canvasHeight = columnGroup.locked - ? height - horizontalScrollbarHeight - : height; - - return ( -
- {/* Dont need to render header if noColumnHeaders specified */} - - -
- {rows.map((row, i) => { - if (row[SELECTED] === 1 && rows[i + 1]?.[SELECTED] === 0) { - row = row.slice() as DataRow; - row[SELECTED] = 2; - } - return ( - - ); - })} -
-
- ); -}); - -const getHeaderCells = (canvasEl: HTMLElement): HTMLElement[] => - Array.from(canvasEl.querySelectorAll("[role='columnheader']")); - -const closeSpaceLeft = (el: HTMLElement, suppressTransition: boolean) => { - el.style.marginLeft = "0px"; - if (suppressTransition === true) { - el.style.transition = ""; - } else { - el.style.transition = "margin .15s ease-in-out"; - } -}; - -const openSpaceLeft = ( - el: HTMLElement, - size: number, - suppressTransition: boolean -) => { - el.style.marginLeft = size - 1 + "px"; - if (suppressTransition !== true) { - el.style.transition = "margin .3s ease"; - } -}; diff --git a/vuu-ui/packages/vuu-datagrid/src/canvas/canvas-reducer.ts b/vuu-ui/packages/vuu-datagrid/src/canvas/canvas-reducer.ts deleted file mode 100644 index 541f11210..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/canvas/canvas-reducer.ts +++ /dev/null @@ -1,151 +0,0 @@ -import { RuntimeColumnDescriptor } from "@finos/vuu-datagrid-types"; -import { Reducer } from "react"; -import { ColumnGroupType } from "../grid-model/gridModelTypes"; - -const VIRTUALIZATION_THRESHOLD = 0.66; - -export const initCanvasReducer = ( - columnGroup: ColumnGroupType -): CanvasState => { - const renderColumns = getRenderColumns(columnGroup); - return [renderColumns, initialKeys(renderColumns), columnGroup, 0]; -}; - -export interface CanvasActionScrollLeft { - type: "scroll-left"; - scrollLeft: number; -} -export interface CanvasActionRefresh { - type: "refresh"; - columnGroup: ColumnGroupType; -} - -export type CanvasAction = CanvasActionRefresh | CanvasActionScrollLeft; - -export type CanvasState = [ - RuntimeColumnDescriptor[], - Map, - ColumnGroupType, - number -]; - -export type CanvasReducer = Reducer; - -export const canvasReducer: CanvasReducer = (state, action) => { - const [, keys, columnGroup, scrollLeft] = state; - switch (action.type) { - case "scroll-left": { - const nextColumns = getRenderColumns(columnGroup, action.scrollLeft); - return [ - nextColumns, - nextKeys(nextColumns, keys), - columnGroup, - action.scrollLeft, - ]; - } - case "refresh": { - const nextColumns = getRenderColumns(action.columnGroup, scrollLeft); - return [ - nextColumns, - nextKeys(nextColumns, keys), - action.columnGroup, - scrollLeft, - ]; - } - default: - return state; - } -}; - -function initialKeys(columns: RuntimeColumnDescriptor[]) { - return new Map(columns.map((column, idx) => [column.key, idx])); -} - -function nextKeys( - columns: RuntimeColumnDescriptor[], - prevKeys: Map -): Map { - if (columns.every(({ key }) => prevKeys.has(key))) { - return prevKeys; - } else { - const remainingKeys = new Map(prevKeys); - const nextKeys = new Map(); - const columnsAwaitingKeys: number[] = []; - - const nextKey = () => { - const usedKeys = new Map( - Array.from(initialKeys(columns).entries()).map(([k, v]) => [v, k]) - ); - - nextKeys.forEach((value) => { - if (usedKeys.has(value)) { - usedKeys.delete(value); - } - }); - - if (usedKeys.size > 0) { - return usedKeys.keys().next().value; - } else { - return columns.length; - } - }; - - columns.forEach((column) => { - if (remainingKeys.has(column.key)) { - nextKeys.set(column.key, remainingKeys.get(column.key)); - remainingKeys.delete(column.key); - } else { - columnsAwaitingKeys.push(column.key); - } - }); - - const freeKeys = Array.from(remainingKeys.values()); - columnsAwaitingKeys.forEach((columnKey) => { - nextKeys.set(columnKey, freeKeys.length ? freeKeys.shift() : nextKey()); - }); - - return nextKeys; - } -} - -function getRenderColumns( - columnGroup: ColumnGroupType, - scrollLeft = 0 -): RuntimeColumnDescriptor[] { - if (!isVirtualizationRequired(columnGroup)) { - return columnGroup.columns; - } - const { columns, width } = columnGroup; - let firstIdx = -1; - let lastIdx = columns.length - 1; - let offset = 0; - const defaultWidth = 200; - - for (let i = 0, currentPosition = 0; i < columns.length; i++) { - currentPosition += columns[i].width || defaultWidth; - if (currentPosition <= scrollLeft) { - offset += columns[i].width ?? defaultWidth; - } else if (currentPosition > scrollLeft + width) { - lastIdx = i; - break; - } else if (firstIdx === -1 && currentPosition > scrollLeft) { - firstIdx = i; - } - } - - const renderColumns = columns - .slice(firstIdx, lastIdx + 1) - .map((column, idx) => ({ - ...column, - marginLeft: idx === 0 ? offset : 0, - })); - return renderColumns; -} - -const isVirtualizationRequired = ({ - contentWidth, - locked, - width, -}: ColumnGroupType) => { - return !locked && width / contentWidth < VIRTUALIZATION_THRESHOLD; -}; diff --git a/vuu-ui/packages/vuu-datagrid/src/canvas/index.ts b/vuu-ui/packages/vuu-datagrid/src/canvas/index.ts deleted file mode 100644 index 90dc254d4..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/canvas/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from "./Canvas"; diff --git a/vuu-ui/packages/vuu-datagrid/src/cell-renderers/background-cell.css b/vuu-ui/packages/vuu-datagrid/src/cell-renderers/background-cell.css deleted file mode 100644 index 58801cd97..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/cell-renderers/background-cell.css +++ /dev/null @@ -1,215 +0,0 @@ -@-webkit-keyframes reactbgup1 { - from { - background-color: var(--salt-differential-positive-background); - } - to { - background-color: transparent; - } -} - -@-webkit-keyframes reactbgup2 { - from { - background-color: var(--salt-differential-positive-background); - } - to { - background-color: transparent; - } -} - -@-webkit-keyframes reactbgdown1 { - from { - background-color: var(--salt-differential-negative-background); - } - to { - background-color: transparent; - } -} - -@-webkit-keyframes reactbgdown2 { - from { - background-color: var(--salt-differential-negative-background); - } - to { - background-color: transparent; - } -} - -@-webkit-keyframes reactarrowup1 { - from { - color: var(--salt-differential-positive-foreground); - } - to { - color: transparent; - } -} - -@-webkit-keyframes reactarrowup2 { - from { - color: var(--salt-differential-positive-foreground); - } - to { - color: transparent; - } -} - -@-webkit-keyframes reactarrowdown1 { - from { - color: var(--salt-differential-negative-foreground); - } - to { - color: transparent; - } -} - -@-webkit-keyframes reactarrowdown2 { - from { - color: var(--salt-differential-negative-foreground); - } - to { - color: transparent; - } -} - -@-webkit-keyframes reactbgarrowup1 { - 0% { - color: var(--salt-differential-positive-foreground); - background-color: var(--salt-differential-positive-background); - } - 20% { - color: var(--salt-differential-positive-foreground); - background-color: transparent; - } - 100% { - color: transparent; - background-color: transparent; - } -} - -@-webkit-keyframes reactbgarrowup2 { - 0% { - color: var(--salt-differential-positive-foreground); - background-color: var(--salt-differential-positive-background); - } - 20% { - color: var(--salt-differential-positive-foreground); - background-color: transparent; - } - 100% { - color: transparent; - background-color: transparent; - } -} - -@-webkit-keyframes reactbgarrowdown1 { - 0% { - color: var(--salt-differential-negative-foreground); - background-color: var(--salt-differential-negative-background); - } - 20% { - color: var(--salt-differential-negative-foreground); - background-color: transparent; - } - 100% { - color: transparent; - background-color: transparent; - } -} - -@-webkit-keyframes reactbgarrowdown2 { - 0% { - color: var(--salt-differential-negative-foreground); - background-color: var(--salt-differential-negative-background); - } - 20% { - color: var(--salt-differential-negative-foreground); - background-color: transparent; - } - 100% { - color: transparent; - background-color: transparent; - } -} - -.flasher { - color: transparent; - position: absolute; - left: 0; - right: 0; - top: 0; - bottom: 0; - z-index: -1; -} - -.vuuDataGridCell .flasher { - text-align: left; -} -.vuuDataGridCell .flasher + .num { - padding-left: 8px; -} - -.vuuDataGridCell.right .flasher { - text-align: right; -} -.vuuDataGridCell.right .flasher + .num { - padding-right: 8px; -} - -.up1 > .flasher { - -webkit-animation-duration: 3s; - -webkit-animation-name: reactbgup1; -} - -.up2 > .flasher { - -webkit-animation-duration: 3s; - -webkit-animation-name: reactbgup2; -} - -.down1 > .flasher { - -webkit-animation-duration: 3s; - -webkit-animation-name: reactbgdown1; -} - -.down2 > .flasher { - -webkit-animation-duration: 3s; - -webkit-animation-name: reactbgdown2; -} - -.up1.arrow-only > .flasher { - -webkit-animation-duration: 30s; - -webkit-animation-name: reactarrowup1; -} - -.up2.arrow-only > .flasher { - -webkit-animation-duration: 30s; - -webkit-animation-name: reactarrowup2; -} - -.down1.arrow-only > .flasher { - -webkit-animation-duration: 30s; - -webkit-animation-name: reactarrowdown1; -} - -.down2.arrow-only > .flasher { - -webkit-animation-duration: 30s; - -webkit-animation-name: reactarrowdown2; -} - -.up1.arrow > .flasher { - -webkit-animation-duration: 30s; - -webkit-animation-name: reactbgarrowup1; -} - -.up2.arrow > .flasher { - -webkit-animation-duration: 30s; - -webkit-animation-name: reactbgarrowup2; -} - -.down1.arrow > .flasher { - -webkit-animation-duration: 30s; - -webkit-animation-name: reactbgarrowdown1; -} - -.down2.arrow > .flasher { - -webkit-animation-duration: 30s; - -webkit-animation-name: reactbgarrowdown2; -} diff --git a/vuu-ui/packages/vuu-datagrid/src/cell-renderers/background-cell.tsx b/vuu-ui/packages/vuu-datagrid/src/cell-renderers/background-cell.tsx deleted file mode 100644 index 773b86b3d..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/cell-renderers/background-cell.tsx +++ /dev/null @@ -1,76 +0,0 @@ -import { DOWN1, DOWN2, metadataKeys, UP1, UP2 } from "@finos/vuu-utils"; -import cx from "classnames"; -import React from "react"; -import { useCellFormatter } from "../grid-cells/useCellFormatter"; -import { useDirection } from "./use-direction"; - -import { ColumnType } from "@finos/vuu-datagrid-types"; -import { GridCellProps } from "../grid-cells"; -import "./background-cell.css"; - -const CHAR_ARROW_UP = String.fromCharCode(11014); -const CHAR_ARROW_DOWN = String.fromCharCode(11015); - -const { KEY } = metadataKeys; - -// TODO these sre repeated from PriceFormatter - where shoud they live ? -const FlashStyle = { - ArrowOnly: "arrow", - BackgroundOnly: "bg-only", - ArrowBackground: "arrow-bg", -}; - -const getFlashStyle = (colType?: ColumnType) => { - if (typeof colType === "string") { - return FlashStyle.BackgroundOnly; - } else if (colType) { - const { renderer } = colType; - if (renderer && "flashStyle" in renderer) { - return renderer.flashStyle; - } else { - return FlashStyle.BackgroundOnly; - } - } -}; - -const BackgroundCell = React.memo(function BackgroundCell({ - column, - row, -}: GridCellProps) { - //TODO what about click handling - const { key, width, type } = column; - const value = row[key]; - const [format] = useCellFormatter(column); - const flashStyle = getFlashStyle(type); - const direction = useDirection(row[KEY], value, column); - const arrow = - flashStyle === FlashStyle.ArrowOnly || - flashStyle === FlashStyle.ArrowBackground - ? direction === UP1 || direction === UP2 - ? CHAR_ARROW_UP - : direction === DOWN1 || direction === DOWN2 - ? CHAR_ARROW_DOWN - : null - : null; - - const dirClass = direction ? ` ` + direction : ""; - const arrowClass = - flashStyle === FlashStyle.ArrowOnly - ? " arrow-only" - : flashStyle === FlashStyle.ArrowBackground - ? " arrow" - : ""; - - return ( -
-
{arrow}
- {format(row[column.key])} -
- ); -}); - -export default BackgroundCell; diff --git a/vuu-ui/packages/vuu-datagrid/src/cell-renderers/checkbox-cell.css b/vuu-ui/packages/vuu-datagrid/src/cell-renderers/checkbox-cell.css deleted file mode 100644 index 84fe571cf..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/cell-renderers/checkbox-cell.css +++ /dev/null @@ -1,19 +0,0 @@ -.Checkbox { - width: 18px; - height: 100%; - background-image: url('data:image/svg+xml;utf8,'); - background-repeat: no-repeat; - background-position: 3px 2px; -} - -.empty.GridRow .vuuDataGridCell.Checkbox { - background: none; -} - -.vuuDataGridCell.Checkbox.checked { - background-image: url('data:image/svg+xml;utf8,'); -} - -.vuuDataGridCell.Checkbox.indeterminate { - background-image: url('data:image/svg+xml;utf8,'); -} diff --git a/vuu-ui/packages/vuu-datagrid/src/cell-renderers/checkbox-cell.tsx b/vuu-ui/packages/vuu-datagrid/src/cell-renderers/checkbox-cell.tsx deleted file mode 100644 index a32d51ce6..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/cell-renderers/checkbox-cell.tsx +++ /dev/null @@ -1,18 +0,0 @@ -// @ts-nocheck -import React from "react"; -import cx from "classnames"; -import { metadataKeys } from "@finos/vuu-utils"; - -import "./checkbox-cell.css"; - -const CheckboxCell = function CheckboxCell({ column, row }) { - const className = cx("vuuDataGridCell", "Checkbox", { - checked: row[metadataKeys.SELECTED] === 1, - emptyRow: row[metadataKeys.KEY] === undefined, - }); - return ( -
- ); -}; - -export default CheckboxCell; diff --git a/vuu-ui/packages/vuu-datagrid/src/cell-renderers/progress-cell.css b/vuu-ui/packages/vuu-datagrid/src/cell-renderers/progress-cell.css deleted file mode 100644 index bf57879ce..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/cell-renderers/progress-cell.css +++ /dev/null @@ -1,32 +0,0 @@ -.vuuProgressCell { - --saltLinearProgress-minWidth: 100px; - --saltLinearProgress-width: 100%; -} - -.vuuProgressCell-progress-container { - position: absolute; - top: 2px; - bottom: 2px; - left: 3px; - right: 3px; -} - -.vuuProgressCell-progress-bar { - background-color: cornflowerblue; - height: 100%; - position: absolute; - top: 0; - left: 0; - width: 0; - transition: width; - transition-duration: 0.1s; -} - -.vuuProgressCell .num { - position: absolute; - top: 2px; - bottom: 2px; - left: 3px; - right: 6px; - width: auto; -} diff --git a/vuu-ui/packages/vuu-datagrid/src/cell-renderers/progress-cell.tsx b/vuu-ui/packages/vuu-datagrid/src/cell-renderers/progress-cell.tsx deleted file mode 100644 index 923695046..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/cell-renderers/progress-cell.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { LinearProgress } from "@salt-ds/lab"; -import cx from "classnames"; -import React from "react"; - -import { isTypeDescriptor } from "@finos/vuu-utils"; -import { GridCellProps } from "../grid-cells"; -import "./progress-cell.css"; -import { ColumnTypeRendering } from "@finos/vuu-datagrid-types"; - -const ProgressCell = React.memo(function ProgressCell({ - column, - columnMap, - row, -}: GridCellProps) { - const { width, type } = column; - let showProgress = false; - let percentage = -1; - const value = row[column.key]; - if ( - isTypeDescriptor(type) && - (type.renderer as ColumnTypeRendering)?.associatedField - ) { - const associatedField = (type.renderer as ColumnTypeRendering) - .associatedField as string; - const associatedValue = row[columnMap[associatedField]]; - if (typeof value === "number" && typeof associatedValue === "number") { - percentage = Math.min(Math.round((value / associatedValue) * 100), 100); - showProgress = isFinite(percentage); - } else { - // Temp workaround for bug on server that sends aggregated values as strings - const floatValue = parseFloat(value as string); - if (Number.isFinite(floatValue)) { - const floatOtherValue = parseFloat(associatedValue as string); - if (Number.isFinite(floatOtherValue)) { - percentage = Math.min( - Math.round((floatValue / floatOtherValue) * 100), - 100 - ); - showProgress = isFinite(percentage); - } - } - } - } - - return ( -
- {showProgress ? : value} -
- ); -}); - -export default ProgressCell; diff --git a/vuu-ui/packages/vuu-datagrid/src/cell-renderers/use-direction.ts b/vuu-ui/packages/vuu-datagrid/src/cell-renderers/use-direction.ts deleted file mode 100644 index 1b3b71d0b..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/cell-renderers/use-direction.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { RuntimeColumnDescriptor } from "@finos/vuu-datagrid-types"; -import { - getMovingValueDirection, - isTypeDescriptor, - isValidNumber, - valueChangeDirection, -} from "@finos/vuu-utils"; -import { useEffect, useRef } from "react"; - -const INITIAL_VALUE = [undefined, undefined, undefined, undefined]; - -type State = [string, unknown, RuntimeColumnDescriptor, valueChangeDirection]; - -export function useDirection( - key: string, - value: unknown, - column: RuntimeColumnDescriptor -) { - const ref = useRef(); - const [prevKey, prevValue, prevColumn, prevDirection] = - ref.current || INITIAL_VALUE; - - const { type: dataType } = column; - const decimals = isTypeDescriptor(dataType) - ? dataType.formatting?.decimals - : undefined; - - const direction = - key === prevKey && - isValidNumber(value) && - isValidNumber(prevValue) && - column === prevColumn - ? getMovingValueDirection(value, prevDirection, prevValue, decimals) - : ""; - - useEffect(() => { - ref.current = [key, value, column, direction]; - }); - - return direction; -} diff --git a/vuu-ui/packages/vuu-datagrid/src/column-bearer.css b/vuu-ui/packages/vuu-datagrid/src/column-bearer.css deleted file mode 100644 index 3352ae8e9..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/column-bearer.css +++ /dev/null @@ -1,11 +0,0 @@ -.ColumnBearer { - background-color: white; - box-shadow: 0 6px 12px rgba(0, 0, 0, 0.275); - position: absolute; - overflow: hidden; - z-index: 150; -} - -.ColumnBearer .HeaderCell { - background-color: var(--header-cell-highlight-bg); -} diff --git a/vuu-ui/packages/vuu-datagrid/src/column-group-context.ts b/vuu-ui/packages/vuu-datagrid/src/column-group-context.ts deleted file mode 100644 index 68c1b11df..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/column-group-context.ts +++ /dev/null @@ -1,4 +0,0 @@ -import React from "react"; -import { ColumnGroupType } from "./grid-model"; -const columnGroupContext = React.createContext(null); -export default columnGroupContext; diff --git a/vuu-ui/packages/vuu-datagrid/src/component-context.tsx b/vuu-ui/packages/vuu-datagrid/src/component-context.tsx deleted file mode 100644 index 5679278fe..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/component-context.tsx +++ /dev/null @@ -1,27 +0,0 @@ -import React, { ReactNode } from "react"; - -type ComponentsType = { [key: string]: unknown }; - -const ComponentContext = React.createContext(null); - -export interface ComponentProviderProps { - children: ReactNode; - components: ComponentsType; -} - -export const ComponentProvider = ({ - children, - components = {}, -}: ComponentProviderProps) => { - return ( - - {(parentContext) => ( - - {children} - - )} - - ); -}; - -export default ComponentContext; diff --git a/vuu-ui/packages/vuu-datagrid/src/constants.ts b/vuu-ui/packages/vuu-datagrid/src/constants.ts deleted file mode 100644 index 6dba038d5..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/constants.ts +++ /dev/null @@ -1,16 +0,0 @@ -import { VuuAggType } from "@finos/vuu-protocol-types"; - -// Note: flipped because of VUU -export const AggregationType: { [key: string]: VuuAggType } = { - Average: 2, - Count: 3, - Sum: 1, - High: 4, - Low: 5, - Distinct: 6, -}; - -export const SortType = { - ASC: "A", - DSC: "D", -}; diff --git a/vuu-ui/packages/vuu-datagrid/src/context-menu/build-context-menu-descriptors.ts b/vuu-ui/packages/vuu-datagrid/src/context-menu/build-context-menu-descriptors.ts deleted file mode 100644 index de0111188..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/context-menu/build-context-menu-descriptors.ts +++ /dev/null @@ -1,243 +0,0 @@ -import { RuntimeColumnDescriptor } from "@finos/vuu-datagrid-types"; -import { isNumericColumn } from "@finos/vuu-utils"; -import { - ContextMenuGroupItemDescriptor, - ContextMenuItemDescriptor, - MenuBuilder, -} from "@finos/vuu-data-types"; -import { - VuuAggregation, - VuuGroupBy, - VuuSort, - VuuSortCol, -} from "../../../vuu-protocol-types"; -import { GridModelType } from "../grid-model/gridModelTypes"; -import { ContextMenuOptions } from "./contextMenuTypes"; - -export type ContextMenuLocation = "header" | "filter" | "grid"; - -export type GridContextMenuAction = - | "agg-avg" - | "agg-count" - | "agg-distinct" - | "agg-high" - | "agg-low" - | "agg-sum" - | "group" - | "group-add" - | "sort-add-asc" - | "sort-add-dsc" - | "sort-asc" - | "sort-dsc" - | "sort-remove"; - -export const buildContextMenuDescriptors = - (gridModel: GridModelType): MenuBuilder => - (location: string, options?: unknown) => { - const descriptors = []; - if (location === "header") { - descriptors.push( - ...buildSortMenuItems(gridModel.sort, options as ContextMenuOptions) - ); - descriptors.push( - ...buildGroupMenuItems(gridModel.groupBy, options as ContextMenuOptions) - ); - descriptors.push( - ...buildAggregationMenuItems( - gridModel.aggregations, - options as ContextMenuOptions - ) - ); - descriptors.push({ - label: "Hide Column", - action: "column-hide", - options, - }); - } else if (location === "filter") { - const { column, filter } = options as ContextMenuOptions; - const colIsOnlyFilter = filter?.column === column?.name; - descriptors.push({ - label: "Edit filter", - action: "filter-edit", - options, - }); - - descriptors.push({ - label: "Remove filter", - action: "filter-remove-column", - options, - }); - - if (column && !colIsOnlyFilter) { - // TODO col might still be the only column in the filter if it is - // involved in all clauses - descriptors.push({ - label: `Remove all filters`, - action: "remove-filters", - options, - }); - } - } - - // if (options?.selectedRowCount){ - // // TODO pass the table name - // const rpcActions = getRpcActions(); - // for (let {label, method} of rpcActions){ - // descriptors.push({action: Action.RpcCall, label, options: {method}}) - // } - // } - - return descriptors; - }; - -function buildAggregationMenuItems( - aggregations?: VuuAggregation[], - options?: ContextMenuOptions -) { - const menuOptions: ContextMenuItemDescriptor[] = []; - if (options?.column) { - const { - column: { name, label = name }, - } = options; - - const menu: ContextMenuGroupItemDescriptor = { - children: [], - label: `Aggregate ${label}`, - }; - - const childMenuOptions: ContextMenuItemDescriptor[] = [ - { label: "Count", action: "agg-count", options }, - ]; - - if (isNumericColumn(options.column)) { - childMenuOptions.push( - { label: "Sum", action: "agg-sum", options }, - { label: "Avg", action: "agg-avg", options }, - { label: "High", action: "agg-high", options }, - { label: "Low", action: "agg-low", options } - ); - } - - menu.children = childMenuOptions; - menuOptions.push(menu); - } - return menuOptions; -} - -const getSortType = ( - sortCols?: VuuSortCol[], - column?: RuntimeColumnDescriptor -): "A" | "D" | void => { - if (sortCols && column) { - const sortCol = sortCols.find((sortDef) => sortDef.column === column.name); - return sortCol?.sortType; - } -}; - -function buildSortMenuItems( - sort?: VuuSort, - options?: ContextMenuOptions -): ContextMenuItemDescriptor[] { - const sortCols = sort ? sort.sortDefs : undefined; - const menuItems: ContextMenuItemDescriptor[] = []; - const column = options?.column; - const existingColumnSort = getSortType(sortCols, column); - if (existingColumnSort === "A") { - menuItems.push({ - label: "Reverse Sort (DSC)", - action: "sort-dsc", - options, - }); - } else if (existingColumnSort === "D") { - menuItems.push({ - label: "Reverse Sort (ASC)", - action: "sort-asc", - options, - }); - } else if (typeof existingColumnSort === "number") { - // TODO this is never a number, identify from position on sortCols - // offer to remove if it isn't the lowest sort - if (existingColumnSort > 0) { - menuItems.push({ - label: "Reverse Sort (DSC)", - action: "sort-add-dsc", - options, - }); - } else { - menuItems.push({ - label: "Reverse Sort (ASC)", - action: "sort-add-asc", - options, - }); - } - // removing the last column from a sort would be a no-op, so pointless - if (sortCols && Math.abs(existingColumnSort) < sortCols.length) { - menuItems.push({ - label: "Remove from sort", - action: "sort-remove", - options, - }); - } - - menuItems.push({ - label: "New Sort", - children: [ - { label: "Ascending", action: "sort-asc", options }, - { label: "Descending", action: "sort-dsc", options }, - ], - }); - } else if (sortCols) { - menuItems.push({ - label: "Add to sort", - children: [ - { label: "Ascending", action: "sort-add-asc", options }, - { label: "Descending", action: "sort-add-dsc", options }, - ], - }); - menuItems.push({ - label: "New Sort", - children: [ - { label: "Ascending", action: "sort-asc", options }, - { label: "Descending", action: "sort-dsc", options }, - ], - }); - } else { - menuItems.push({ - label: "Sort", - children: [ - { label: "Ascending", action: "sort-asc", options }, - { label: "Descending", action: "sort-dsc", options }, - ], - }); - } - return menuItems; -} - -function buildGroupMenuItems( - groupBy?: VuuGroupBy, - options?: ContextMenuOptions -): ContextMenuItemDescriptor[] { - const menuItems: ContextMenuItemDescriptor[] = []; - - if (options?.column) { - const { - column: { name, label = name }, - } = options; - - if (!groupBy || groupBy.length === 0) { - menuItems.push({ - label: `Group by ${label}`, - action: "group", - options, - }); - } else { - menuItems.push({ - label: `Add ${label} to group by`, - action: "group-add", - options, - }); - } - } - - return menuItems; -} diff --git a/vuu-ui/packages/vuu-datagrid/src/context-menu/context-menu-actions.ts b/vuu-ui/packages/vuu-datagrid/src/context-menu/context-menu-actions.ts deleted file mode 100644 index 711a03fb7..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/context-menu/context-menu-actions.ts +++ /dev/null @@ -1,21 +0,0 @@ -export const AggregateAvg = "agg-avg"; -export const AggregateCount = "agg-count"; -export const AggregateHigh = "agg-high"; -export const AggregateLow = "agg-low"; -export const AggregateSum = "agg-sum"; -export const ColumnHide = "column-hide"; -export const FilterEdit = "filter-edit"; -export const FilterRemove = "filter-remove"; -export const FilterRemoveColumn = "filter-remove-column"; -export const Group = "group"; -export const GroupAdd = "group-add"; -export const LinkTable = "link-table"; -export const Pivot = "pivot"; -export const PivotAdd = "pivot-add"; -export const Sort = "sort"; -export const SortAscending = "sort-asc"; -export const SortDescending = "sort-dsc"; -export const SortAddAscending = "sort-add-asc"; -export const SortAddDescending = "sort-add-dsc"; -export const SortRemove = "sort-remove"; -export const SortReverse = "sort-reverse"; diff --git a/vuu-ui/packages/vuu-datagrid/src/context-menu/contextMenuTypes.ts b/vuu-ui/packages/vuu-datagrid/src/context-menu/contextMenuTypes.ts deleted file mode 100644 index 397db40c5..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/context-menu/contextMenuTypes.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { Filter } from "@finos/vuu-filter-types"; -import { VuuFilter } from "@finos/vuu-protocol-types"; -import { RuntimeColumnDescriptor } from "@finos/vuu-datagrid-types"; - -export interface ContextMenuOptions { - column?: RuntimeColumnDescriptor; - filter?: Filter; - sort?: VuuFilter; -} diff --git a/vuu-ui/packages/vuu-datagrid/src/context-menu/index.ts b/vuu-ui/packages/vuu-datagrid/src/context-menu/index.ts deleted file mode 100644 index 940ec8a82..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/context-menu/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from "./context-menu-actions"; -export * from "./build-context-menu-descriptors"; -export * from "./useContextMenu"; diff --git a/vuu-ui/packages/vuu-datagrid/src/context-menu/useContextMenu.ts b/vuu-ui/packages/vuu-datagrid/src/context-menu/useContextMenu.ts deleted file mode 100644 index 417fb7b3b..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/context-menu/useContextMenu.ts +++ /dev/null @@ -1,74 +0,0 @@ -/* eslint-disable no-sequences */ -import { DataSource } from "@finos/vuu-data"; -import { DataSourceFilter, MenuActionHandler } from "@finos/vuu-data-types"; -import { RuntimeColumnDescriptor } from "@finos/vuu-datagrid-types"; -import { MenuActionClosePopup } from "@finos/vuu-popups"; -import { removeColumnFromFilter, setAggregations } from "@finos/vuu-utils"; -import { AggregationType } from "../constants"; -import { GridModelDispatch } from "../grid-context"; -import { GridModelType } from "../grid-model/gridModelTypes"; -import { GridModel } from "../grid-model/gridModelUtils"; -import { ContextMenuOptions } from "./contextMenuTypes"; - -const { Average, High, Low, Count, Sum } = AggregationType; -export interface ContextMenuHookProps { - dataSource: DataSource; - gridModel: GridModelType; - dispatchGridModelAction: GridModelDispatch; -} - -const removeFilterColumn = ( - dataSourceFilter: DataSourceFilter, - column: RuntimeColumnDescriptor -) => { - if (dataSourceFilter.filterStruct && column) { - const [filterStruct, filter] = removeColumnFromFilter( - column, - dataSourceFilter.filterStruct - ); - return { - filter, - filterStruct, - }; - } else { - return dataSourceFilter; - } -}; - -export const useContextMenu = ({ - dataSource, - gridModel, - dispatchGridModelAction, -}: ContextMenuHookProps) => { - /** return {boolean} used by caller to determine whether to forward to additional installed context menu handlers */ - const handleContextMenuAction: MenuActionHandler = ({ - menuId, - options, - }: MenuActionClosePopup): boolean => { - const gridOptions = options as ContextMenuOptions; - if (gridOptions.column) { - const { column } = gridOptions; - // prettier-ignore - switch(menuId){ - case "sort-asc": return (dataSource.sort = GridModel.setSortColumn(gridModel, column, "A")), true; - case "sort-dsc": return (dataSource.sort = GridModel.setSortColumn(gridModel, column, "D")), true; - case "sort-add-asc": return (dataSource.sort = GridModel.addSortColumn(gridModel, column, "A")), true; - case "sort-add-dsc": return (dataSource.sort = GridModel.addSortColumn(gridModel, column, "D")), true; - case "group": return (dataSource.groupBy = GridModel.addGroupColumn({}, column)), true; - case "group-add": return (dataSource.groupBy = GridModel.addGroupColumn(gridModel, column)), true; - case "column-hide": return dispatchGridModelAction({type: menuId, column}),true; - case "filter-remove-column": return (dataSource.filter = removeFilterColumn(dataSource.filter, column)), true; - case "remove-filters": return (dataSource.filter = {filter:""}), true; - case "agg-avg": return dataSource.aggregations = (setAggregations(dataSource.aggregations, column, Average)), true; - case "agg-high": return dataSource.aggregations = (setAggregations(dataSource.aggregations, column, High)), true; - case "agg-low": return dataSource.aggregations = (setAggregations(dataSource.aggregations, column, Low)), true; - case "agg-count": return dataSource.aggregations = (setAggregations(dataSource.aggregations, column, Count)), true; - case "agg-sum": return dataSource.aggregations = (setAggregations(dataSource.aggregations, column, Sum)), true; - default: - } - } - return false; - }; - - return handleContextMenuAction; -}; diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-adornments/gridAdornments.tsx b/vuu-ui/packages/vuu-datagrid/src/grid-adornments/gridAdornments.tsx deleted file mode 100644 index 0eb3a6c5a..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-adornments/gridAdornments.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import React, { ReactNode } from "react"; - -export interface GridAdornmentProps { - children: ReactNode; - height?: number; -} - -export type GridAdornment = React.FunctionComponent; - -export const Header: GridAdornment = ({ children, height }) => { - return ( -
- {children} -
- ); -}; - -export const Footer: GridAdornment = ({ children, height }) => { - return ( -
- {children} -
- ); -}; - -export const InlineHeader: GridAdornment = ({ children, height }) => { - return ( -
- {children} -
- ); -}; diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-adornments/index.ts b/vuu-ui/packages/vuu-datagrid/src/grid-adornments/index.ts deleted file mode 100644 index f6613b1c8..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-adornments/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./gridAdornments"; -export * from "./useAdornments"; diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-adornments/useAdornments.ts b/vuu-ui/packages/vuu-datagrid/src/grid-adornments/useAdornments.ts deleted file mode 100644 index bc75d5f01..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-adornments/useAdornments.ts +++ /dev/null @@ -1,84 +0,0 @@ -import React, { ReactElement, ReactNode, useState } from "react"; -import { Footer, Header, InlineHeader } from "./gridAdornments"; -const NO_ADORNMENTS = { - header: { height: 0, component: null }, - inlineHeader: { height: 0, component: null }, - footer: { height: 0, component: null }, -}; - -type adornmentType = "header" | "inlineHeader" | "footer"; - -export type AdornmentsDescriptor = { - header: { - height: number; - component: null | ReactElement; - }; - inlineHeader: { - height: number; - component: null | ReactElement; - }; - footer: { - height: number; - component: null | ReactElement; - }; -}; - -export const useAdornments = (children: ReactNode): AdornmentsDescriptor => { - const [adornments] = useState( - children ? getAdornments(children) : NO_ADORNMENTS - ); - return adornments; -}; - -function getAdornments(children: ReactNode) { - const adornments = { ...NO_ADORNMENTS }; - - if (Array.isArray(children)) { - children.forEach((child) => { - addAdornment(adornments, child); - }); - } else if (React.isValidElement(children)) { - addAdornment(adornments, children); - } - - return adornments; -} - -function addAdornment(adornments: AdornmentsDescriptor, child: ReactElement) { - const [type, height, component] = getAdornment(child); - if (type) { - if (adornments[type]) { - console.error( - `Grid only supports one child of any type: multiple ${type}s` - ); - } else { - adornments[type] = { height, component }; - } - } else { - console.error(`unable to identify child element`); - } -} - -function getAdornment( - child: ReactElement -): [adornmentType, number, ReactElement] | [null] { - if ( - child.type === Header || - child.type === Footer || - child.type === InlineHeader - ) { - const type = - child.type === Header - ? "header" - : child.type === Footer - ? "footer" - : "inlineHeader"; - const { height } = child.props; - if (height === undefined) { - console.error(`${type} must provide height`); - } - return [type, height, child]; - } else { - return [null]; - } -} diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-cells/ColResizer.tsx b/vuu-ui/packages/vuu-datagrid/src/grid-cells/ColResizer.tsx deleted file mode 100644 index 84421791f..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-cells/ColResizer.tsx +++ /dev/null @@ -1,70 +0,0 @@ -//TODO use useDrag -import React, { useCallback, useRef } from "react"; - -const NOOP = () => undefined; - -export interface ColResizerProps { - onDrag: (evt: MouseEvent, moveBy: number) => void; - onDragEnd: (evt: MouseEvent) => void; - onDragStart: (evt: React.MouseEvent) => void; -} - -export const ColResizer = (allProps: ColResizerProps) => { - const { onDrag, onDragEnd = NOOP, onDragStart = NOOP, ...props } = allProps; - - const position = useRef(0); - - const onMouseMove = useCallback( - (e: MouseEvent) => { - if (e.stopPropagation) { - e.stopPropagation(); - } - - if (e.preventDefault) { - e.preventDefault(); - } - - const x = Math.round(e.clientX); - const moveBy = x - position.current; - position.current = x; - - if (moveBy !== 0) { - onDrag(e, moveBy); - } - }, - [onDrag] - ); - - const onMouseUp = useCallback( - (e: MouseEvent) => { - window.removeEventListener("mouseup", onMouseUp); - window.removeEventListener("mousemove", onMouseMove); - onDragEnd(e); - }, - [onDragEnd, onMouseMove] - ); - - const handleMouseDown = useCallback( - (e: React.MouseEvent) => { - onDragStart(e); - - position.current = Math.round(e.clientX); - - window.addEventListener("mouseup", onMouseUp); - window.addEventListener("mousemove", onMouseMove); - - if (e.stopPropagation) { - e.stopPropagation(); - } - - if (e.preventDefault) { - e.preventDefault(); - } - }, - [onDragStart, onMouseMove, onMouseUp] - ); - - return ( -
- ); -}; diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-cells/GridCell.css b/vuu-ui/packages/vuu-datagrid/src/grid-cells/GridCell.css deleted file mode 100644 index f1dfede7e..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-cells/GridCell.css +++ /dev/null @@ -1,51 +0,0 @@ -.vuuDataGridCell { - align-items: center; - background-color: var(--grid-cell-bg, inherit); - box-sizing: border-box; - border-color: var(--vuuDataGridCell-borderColor, var(--cell-border-top-color) var(--cell-border-right-color) var(--cell-border-bottom-color) transparent); - border-style: var(--cell-border-style, solid); - border-width: 1px; - color: var(--text-color); - cursor: default; - display: inline-flex; - height: 100%; - outline: 0; - overflow: hidden; - padding: var(--cell-padding); - position: relative; - text-overflow: ellipsis; - user-select: none; - vertical-align: top; - white-space: nowrap; - z-index: 0; -} - -.vuuDataGridCell.noBottomBorder { - border-bottom: solid 1px transparent; -} -.vuuDataGridCell.resizing { - background-color: var(--header-cell-highlight-bg); -} - -.vuuDataGridCell .num { - display: inline-block; - text-align: right; - width: 100%; -} - -.vuuLineNumber { - background-color: var(--line-number-bg); - border-bottom-color: var(--line-number-border-color); - border-top-color: transparent; -} - -.vuuDataGridCell:focus:before, -.vuuDataGridCell:focus-visible:before { - content: ''; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0px; - border: dotted var(--focus-visible-border-color) 2px; -} diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-cells/GridCell.tsx b/vuu-ui/packages/vuu-datagrid/src/grid-cells/GridCell.tsx deleted file mode 100644 index 22f6543cf..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-cells/GridCell.tsx +++ /dev/null @@ -1,84 +0,0 @@ -import { - ColumnTypeRendering, - RuntimeColumnDescriptor, -} from "@finos/vuu-datagrid-types"; -import { ColumnMap, DataRow, isTypeDescriptor } from "@finos/vuu-utils"; -import cx from "classnames"; -import React, { HTMLAttributes, useContext } from "react"; -import ComponentContext from "../component-context"; -import { useCellFormatter } from "./useCellFormatter"; - -import "./GridCell.css"; - -const columnType = (column: RuntimeColumnDescriptor) => - !column.type - ? null - : typeof column.type === "string" - ? column.type - : column.type.name; - -// TODO we want to allow css class to be determined by value -function useGridCellClassName(column: RuntimeColumnDescriptor) { - // const count = getInstanceCount(classes); - // console.log(`instance count = ${JSON.stringify(count)}`) - - return cx( - "vuuDataGridCell", - column.className, - columnType(column), - column.resizing ? "resizing" : null, - column.moving ? "moving" : null - ); -} - -const cellValuesAreEqual = (prev: GridCellProps, next: GridCellProps) => { - return ( - prev.column === next.column && - prev.row[prev.column.key] === next.row[next.column.key] - ); -}; - -export interface GridCellProps extends HTMLAttributes { - column: RuntimeColumnDescriptor; - columnMap: ColumnMap; - row: DataRow; -} - -// perhaps context would be more appropriate for columnMap -export const GridCell = React.memo(function GridCell({ - column, - columnMap, - row, -}: GridCellProps) { - const components = useContext(ComponentContext); - const [format] = useCellFormatter(column); - const className = useGridCellClassName(column); - const { type } = column; - const rendererName = isTypeDescriptor(type) - ? (type?.renderer as ColumnTypeRendering)?.name - : null; - const Cell = - rendererName && - (components?.[rendererName] as React.FunctionComponent); - if (Cell) { - return ( - - ); - } else { - return ( -
- {format(row[column.key])} -
- ); - } -}, -cellValuesAreEqual); diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-cells/GroupCell.tsx b/vuu-ui/packages/vuu-datagrid/src/grid-cells/GroupCell.tsx deleted file mode 100644 index cc5f7e187..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-cells/GroupCell.tsx +++ /dev/null @@ -1,55 +0,0 @@ -import { GroupColumnDescriptor } from "@finos/vuu-datagrid-types"; -import { DataRow, metadataKeys } from "@finos/vuu-utils"; -import React, { useCallback } from "react"; -import { useGridContext } from "../grid-context"; -import { getGroupValueAndOffset } from "../grid-model/gridModelUtils"; - -import "./grid-group-cell.css"; - -const { KEY, IS_EXPANDED, COUNT } = metadataKeys; - -export interface GroupCellProps { - column: GroupColumnDescriptor; - row: DataRow; -} - -export const GroupCell = React.memo(function GroupCell({ - column, - row, -}: GroupCellProps) { - const { dispatchGridAction } = useGridContext(); - - const handleClick = useCallback( - (e) => { - e.preventDefault(); - e.stopPropagation(); - const type = row[IS_EXPANDED] ? "closeTreeNode" : "openTreeNode"; - dispatchGridAction?.({ type, key: row[KEY] }); - }, - [dispatchGridAction, row] - ); - - const count = row[COUNT]; - const [value, offset] = getGroupValueAndOffset(column.columns, row); - - return ( -
- {offset !== null ? ( -
- - {value} - ({count}) -
- ) : null} -
- ); -}); diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-cells/GroupHeaderCell.css b/vuu-ui/packages/vuu-datagrid/src/grid-cells/GroupHeaderCell.css deleted file mode 100644 index d0f94c95e..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-cells/GroupHeaderCell.css +++ /dev/null @@ -1,79 +0,0 @@ -.hwGroupHeaderCell { - --menu-icon-size: 18px; - --menu-item-icon-color: black; - --highlight-background: rgb(66, 139, 202); - --highlight-color: white; - - overflow: hidden; -} - -.hwGroupHeaderCell-inner-container { - overflow: hidden; - height: 100%; - width: 100%; - display: inline-flex; - align-items: stretch; -} - -.hwGroupHeaderCell-col { - align-items: center; - background-color: inherit; - display: inline-flex; - flex: 0 1 auto; - justify-content: space-between; - padding-right: 8px; - position: relative; -} - -.hwGroupHeaderCell-col:first-child { - clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 50%, calc(100% - 8px) 100%, 0 100%); - z-index: 1; -} - -.hwGroupHeaderCell-col:not(:first-child) { - margin-left: -6px; - padding-left: 6px; - clip-path: polygon(0 0, calc(100% - 8px) 0, 100% 50%, calc(100% - 8px) 100%, 0 100%, 8px 50%); -} - -.hwGroupHeaderCell-resizing { - background-color: var(--header-cell-highlight-bg); -} - -.hwGroupHeaderCell-col:nth-child(odd) { - background-color: #d4d4d4; -} -.hwGroupHeaderCell-col:nth-child(even) { - background-color: rgba(160, 160, 160, 0.3); -} -.hwGroupHeaderCell-col:hover { - --vuu-icon-color: white; - --menu-item-icon-color: var(--highlight-background); - --menu-item-icon-color: var(--highlight-color); - --remove-icon-color: var(--highlight-color); - --remove-icon-visibility: visible; - background-color: var(--highlight-background); - color: var(--highlight-color); -} -.hwGroupHeaderCell-label { - height: 100%; - line-height: 25px; -} - -.hwGroupHeaderCell *[data-icon] { - cursor: pointer; -} - -.remove-group-column { - --menu-icon-size: 12px; - --menu-icon: var(--svg-close-circle); - visibility: var(--remove-icon-visibility, hidden); - background-color: var(--menu-item-icon-color); - -webkit-mask: var(--menu-icon) center center/var(--menu-icon-size) var(--menu-icon-size); - mask: var(--menu-icon) center center/var(--menu-icon-size) var(--menu-icon-size); -} - -.hwGroupHeaderCell-col *[data-icon='arrow-right'] { - left: 2px; - position: relative; -} diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-cells/GroupHeaderCell.tsx b/vuu-ui/packages/vuu-datagrid/src/grid-cells/GroupHeaderCell.tsx deleted file mode 100644 index b308ac813..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-cells/GroupHeaderCell.tsx +++ /dev/null @@ -1,128 +0,0 @@ -import { - GroupColumnDescriptor, - RuntimeColumnDescriptor, -} from "@finos/vuu-datagrid-types"; -import { useContextMenu } from "@finos/vuu-popups"; -import cx from "classnames"; -import React, { HTMLAttributes, useCallback, useEffect, useRef } from "react"; -import { expandStatesfromGroupState } from "../grid-model/gridModelUtils"; -import { ColResizer } from "./ColResizer"; -import { HeaderCellProps } from "./HeaderCell"; -import { useCellResize } from "./useCellResize"; - -import "./GroupHeaderCell.css"; - -const classBase = "hwGroupHeaderCell"; - -export interface ColHeaderProps - extends Omit, "onClick"> { - column: RuntimeColumnDescriptor; - expandState: 0 | 1 | -1; - onClick: (column: RuntimeColumnDescriptor) => void; - onRemoveColumn: (column: RuntimeColumnDescriptor) => void; - onToggle: (column: RuntimeColumnDescriptor, expandState: number) => void; -} -const ColHeader = (props: ColHeaderProps) => { - const { column, className, onClick, onRemoveColumn, expandState, onToggle } = - props; - const expanded = expandState === 1; - return ( -
- onToggle(column, -expandState)} - /> - - onClick(column)}> - {column.name} - - onRemoveColumn(column)} - /> -
- ); -}; - -export interface GroupHeaderCellProps - extends Omit { - column: GroupColumnDescriptor; - groupState?: any; - onClick: ( - groupCol: GroupColumnDescriptor, - column: RuntimeColumnDescriptor - ) => void; - onRemoveColumn: (column: RuntimeColumnDescriptor) => void; - onToggleGroupState: () => void; -} - -export const GroupHeaderCell = ({ - className: classNameProp, - column: groupCol, - groupState = {}, - onClick, - onRemoveColumn, - onResize, - onToggleGroupState, -}: GroupHeaderCellProps) => { - const rootRef = useRef(null); - const column = useRef(groupCol); - - useEffect(() => { - column.current = groupCol; - }, [groupCol]); - - const { isResizing, ...resizeProps } = useCellResize({ - column: groupCol, - onResize, - rootRef, - }); - - const handleClick = useCallback( - (column: RuntimeColumnDescriptor) => { - onClick(groupCol, column); - }, - [groupCol, onClick] - ); - - const [showContextMenu] = useContextMenu(); - const handleContextMenu = (e: React.MouseEvent) => { - showContextMenu(e, "header", { column }); - }; - - const { columns, resizing, width } = groupCol; - const className = cx("hwHeaderCell", classBase, classNameProp, { - [`${classBase}-resizing`]: resizing, - }); - const expandStates = expandStatesfromGroupState(groupCol, groupState); - return ( -
-
- {columns.map((column, idx) => ( - - ))} -
- -
- ); -}; diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-cells/HeaderCell.css b/vuu-ui/packages/vuu-datagrid/src/grid-cells/HeaderCell.css deleted file mode 100644 index 8297897c4..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-cells/HeaderCell.css +++ /dev/null @@ -1,65 +0,0 @@ -.hwHeaderCell { - --justify-text: flex-start; - align-items: stretch; - border-bottom: solid 1px var(--heading-border-color); - border-right: 1px solid var(--heading-border-color); - box-sizing: border-box; - color: var(--salt-text-secondary-foreground); - cursor: default; - display: inline-flex; - font-weight: bold; - height: 100%; - outline: 0; - position: relative; - vertical-align: top; -} - -.hwHeaderCell:focus-visible:before { - content: ''; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0px; - border: dotted var(--focus-visible-border-color) 2px; -} - -.hwHeaderCell-number { - --justify-text: flex-end; - --cell-padding: 0 1px 0 9px; -} - -.hwHeaderCell.noBottomBorder { - border-bottom: solid 1px transparent; -} - -.hwHeaderCell-resizing { - background-color: var(--grid-header-cell-highlight-bg); -} - -.innerHeaderCell { - flex: 1 1 100%; - overflow: hidden; - padding: var(--cell-padding); - position: relative; - text-overflow: ellipsis; - white-space: nowrap; -} - -.cellWrapper { - align-items: center; - justify-content: var(--justify-text); - display: flex; - height: 100%; - vertical-align: top; - white-space: nowrap; -} - -.resizeHandle { - background-color: rgba(180, 180, 180, 0.05); - cursor: col-resize; - flex: 0 0 8px; - position: relative; - right: -5px; - z-index: 1; -} diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-cells/HeaderCell.tsx b/vuu-ui/packages/vuu-datagrid/src/grid-cells/HeaderCell.tsx deleted file mode 100644 index 0036e4c9f..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-cells/HeaderCell.tsx +++ /dev/null @@ -1,138 +0,0 @@ -import { useContextMenu } from "@finos/vuu-popups"; -import { RuntimeColumnDescriptor } from "@finos/vuu-datagrid-types"; -import cx from "classnames"; -import { MouseEvent, useCallback, useRef } from "react"; -import { AggregationType } from "../constants"; -import { useGridContext } from "../grid-context"; -import { GridModel } from "../grid-model/gridModelUtils"; -import { dragPhase, resizePhase } from "../gridTypes"; -import { useDragStart } from "../use-drag"; -import { ColResizer } from "./ColResizer"; -import { FilterIndicator } from "./filter-indicator"; -import { GridCellProps } from "./GridCell"; -import { SortIndicator, sortStatus } from "./sort-indicator"; -import { useCellResize } from "./useCellResize"; - -import "./HeaderCell.css"; -import { DataSourceFilter } from "@finos/vuu-data-types"; - -const classBase = "hwHeaderCell"; -const NO_AGGREGATION = { aggType: -1 }; - -const AggTypeLabel = { - [AggregationType.Average]: "Avg", - [AggregationType.Count]: "count", - [AggregationType.Sum]: "\u03A3", - [AggregationType.High]: "High", - [AggregationType.Low]: "Low", - [AggregationType.Distinct]: "Distinct", - none: "", -}; - -export interface HeaderCellProps - extends Omit { - filter?: DataSourceFilter; - onDrag?: ( - phase: dragPhase, - column: RuntimeColumnDescriptor, - columnPosition: number, - mousePosition: number - ) => void; - onResize?: (phase: resizePhase, columnName: string, width?: number) => void; - sorted?: sortStatus; -} - -export const HeaderCell = function HeaderCell({ - className: classNameProp, - column, - filter, - onDrag, - onResize, - sorted, -}: HeaderCellProps) { - const rootRef = useRef(null); - const col = useRef(column); - // const isResizing = useRef(false); - const { dispatchGridAction, gridModel } = useGridContext(); - - const { isResizing, ...resizeProps } = useCellResize({ - column, - onResize, - rootRef, - }); - - // essential that handlers for resize do not use stale column - // we could mitigate this by only passing column key and passing delta, - // so we don't rely on current width in column - col.current = column; - - const [handleMouseDown] = useDragStart( - useCallback( - (phase: dragPhase, delta: number, mousePosition: number) => { - if (rootRef.current) { - const { left } = rootRef.current.getBoundingClientRect(); - onDrag && onDrag(phase, col.current, left + delta, mousePosition); - } - }, - [onDrag, col] - ) - ); - - const handleClick = useCallback(() => { - if (!isResizing && gridModel) { - dispatchGridAction?.({ - type: "sort", - sort: GridModel.setSortColumn(gridModel, column), - }); - } - }, [column, dispatchGridAction, gridModel, isResizing]); - - const [showContextMenu] = useContextMenu(); - - const handleContextMenu = (e: MouseEvent) => { - showContextMenu(e, "header", { column }); - }; - - const groupBy = gridModel?.groupBy; - const { aggType } = - groupBy && groupBy?.length > 0 - ? gridModel.aggregations.find((agg) => agg.column === column.name) || - NO_AGGREGATION - : NO_AGGREGATION; - const aggLabel = AggTypeLabel[aggType] ?? ""; - - // TODO could we just wrap the whole header in a draggable ? - const { - name, - label = name, - resizing, - width, - marginLeft = undefined, - type, - } = column; - - const typeName = typeof type === "string" ? type : type?.name; - - return ( -
- -
-
{`${aggLabel} ${label}`}
-
- - {column.resizeable !== false && } -
- ); -}; diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-cells/HeadingCell.tsx b/vuu-ui/packages/vuu-datagrid/src/grid-cells/HeadingCell.tsx deleted file mode 100644 index f2bfe4a3f..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-cells/HeadingCell.tsx +++ /dev/null @@ -1,75 +0,0 @@ -import React, { HTMLAttributes, useRef } from "react"; -import cx from "classnames"; -import { ColResizer } from "./ColResizer"; -import { Heading } from "@finos/vuu-datagrid-types"; -import { resizePhase } from "../gridTypes"; -import { useCellResize } from "./useCellResize"; - -export interface HeadingCellProps extends HTMLAttributes { - heading: Heading; - onResize: (phase: resizePhase, headingName: string, width?: number) => void; -} - -export const HeadingCell = function HeaderCell({ - className, - heading, - onResize, -}: HeadingCellProps) { - const rootRef = useRef(null); - const col = useRef(heading); - - // essential that handlers for resize do not use stale column - // we could mitigate this by only passing column key and passing delta, - // so we don't rely on current width in column - col.current = heading; - - const { isResizing, ...resizeProps } = useCellResize({ - column: heading, - onResize, - rootRef, - }); - - // const handleResizeStart = useCallback(() => { - // console.log({ heading }); - // onResize("begin", heading); - // }, [heading, onResize]); - - // const handleResize = useCallback( - // (e) => { - // if (rootRef.current) { - // const width = getWidthFromMouseEvent(e, rootRef.current); - // if (width > 0 && width !== col.current.width) { - // onResize("resize", col.current, width); - // } - // } - // }, - // [onResize] - // ); - - // const handleResizeEnd = (e) => { - // if (rootRef.current) { - // onResize("end", col.current, getWidthFromMouseEvent(e, rootRef.current)); - // } - // }; - - // const getWidthFromMouseEvent = (e, el: HTMLDivElement) => { - // const right = e.pageX; - // const left = el.getBoundingClientRect().left; - // return right - left; - // }; - - // TODO could we just wrap the whole header in a draggable ? - const { label, resizing, width } = heading; - return ( -
-
-
{label}
-
- {heading.resizeable !== false && } -
- ); -}; diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-cells/filter-indicator.css b/vuu-ui/packages/vuu-datagrid/src/grid-cells/filter-indicator.css deleted file mode 100644 index 2517df952..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-cells/filter-indicator.css +++ /dev/null @@ -1,15 +0,0 @@ -.hwFilterIndicator { - --menu-icon-size: 12px; - --menu-item-icon-color: black; - align-items: center; - cursor: pointer; - display: flex; - flex: 0 0 18px; - flex-direction: column; - justify-content: center; - position: relative; -} - -.hwFilterIndicator + .innerHeaderCell { - padding-left: 0; -} diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-cells/filter-indicator.tsx b/vuu-ui/packages/vuu-datagrid/src/grid-cells/filter-indicator.tsx deleted file mode 100644 index cfe17715f..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-cells/filter-indicator.tsx +++ /dev/null @@ -1,50 +0,0 @@ -import { useContextMenu } from "@finos/vuu-popups"; -import { Filter } from "@finos/vuu-filter-types"; -import { filterIncludesColumn } from "@finos/vuu-filters"; -import cx from "classnames"; -import { HTMLAttributes, useCallback, useMemo } from "react"; - -import "./filter-indicator.css"; -import { RuntimeColumnDescriptor } from "@finos/vuu-datagrid-types"; - -export const Direction = { - ASC: "asc", - DSC: "dsc", -}; - -export interface FilterIndicatorProps extends HTMLAttributes { - column: RuntimeColumnDescriptor; - filter?: Filter; -} - -export const FilterIndicator = ({ column, filter }: FilterIndicatorProps) => { - const hasFilter = useMemo( - () => filter && filterIncludesColumn(filter, column), - [filter, column] - ); - //TODO handle this at header level - const [showContextMenu] = useContextMenu(); - - const handleClick = useCallback( - (evt) => { - // if we do this through keyboard, need to get co-ords - evt.stopPropagation(); - showContextMenu(evt, "filter", { column, filter }); - }, - [column, filter, showContextMenu] - ); - - if (!filter || !hasFilter) { - return null; - } - - return ( -
- -
- ); -}; diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-cells/grid-group-cell.css b/vuu-ui/packages/vuu-datagrid/src/grid-cells/grid-group-cell.css deleted file mode 100644 index ab8b715d4..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-cells/grid-group-cell.css +++ /dev/null @@ -1,35 +0,0 @@ -.GridGroupCell { - --menu-icon-size: 16px; - --menu-item-icon-color: black; - --toggle-icon-transform: var(--row-toggle-icon-transform, none); - - display: flex; - align-items: center; - flex-grow: 1; - overflow: hidden; -} - -.GridGroupCell .group-value { - cursor: default; - display: inline-block; - max-width: calc(100% - 30px); - overflow: hidden; - padding-right: 3px; - text-overflow: ellipsis; - vertical-align: top; - white-space: nowrap; -} - -/* does this make sense ? */ -.noToggle .GridGroupCell:first-child { - margin-left: 12px; -} - -*[data-icon='arrow-right'] { - --menu-icon: var(--svg-caret-right); - background-color: var(--menu-item-icon-color); - -webkit-mask: var(--menu-icon) center center/var(--menu-icon-size) var(--menu-icon-size); - mask: var(--menu-icon) center center/var(--menu-icon-size) var(--menu-icon-size); - transition: transform 0.25s; - transform: var(--toggle-icon-transform); -} diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-cells/index.js b/vuu-ui/packages/vuu-datagrid/src/grid-cells/index.js deleted file mode 100644 index ebaf34354..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-cells/index.js +++ /dev/null @@ -1,6 +0,0 @@ -export * from "./GridCell"; -export * from "./GroupCell"; -export * from "./HeaderCell"; -export * from "./GroupHeaderCell"; -export * from "./HeadingCell"; -export * from "./useCellFormatter"; diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-cells/sort-indicator.css b/vuu-ui/packages/vuu-datagrid/src/grid-cells/sort-indicator.css deleted file mode 100644 index 876a1aa57..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-cells/sort-indicator.css +++ /dev/null @@ -1,19 +0,0 @@ -.hwSortIndicator { - --menu-icon-size: 18px; - --menu-item-icon-color: black; - display: flex; - flex-direction: column; - position: relative; - width: 18px; -} - -.hwSortPosition { - font-size: 10px; - line-height: 10px; - text-align: center; -} - -.hwSortIndicator .hwIconContainer { - height: 12px; -} - diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-cells/sort-indicator.tsx b/vuu-ui/packages/vuu-datagrid/src/grid-cells/sort-indicator.tsx deleted file mode 100644 index f6ce8a57b..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-cells/sort-indicator.tsx +++ /dev/null @@ -1,43 +0,0 @@ -import cx from "classnames"; - -import "./sort-indicator.css"; - -export const Direction = { - ASC: "asc", - DSC: "dsc", -}; - -export type sortStatus = number | "asc" | "dsc"; -export interface SortIndicatorProps { - sorted?: sortStatus; -} - -export const SortIndicator = ({ sorted }: SortIndicatorProps) => { - if (!sorted) { - return null; - } - - const direction = - typeof sorted === "number" - ? sorted < 0 - ? Direction.DSC - : Direction.ASC - : sorted; - - return typeof sorted === "number" ? ( -
- - {Math.abs(sorted)} -
- ) : ( -
- -
- ); -}; diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-cells/useCellFormatter.ts b/vuu-ui/packages/vuu-datagrid/src/grid-cells/useCellFormatter.ts deleted file mode 100644 index 7be5df7aa..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-cells/useCellFormatter.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { isTypeDescriptor, roundDecimal } from "@finos/vuu-utils"; -import { - RuntimeColumnDescriptor, - ColumnTypeFormatting, -} from "@finos/vuu-datagrid-types"; -import { createElement, useRef } from "react"; - -const defaultFormatter = (value: unknown) => - value == null ? "" : typeof value === "string" ? value : value.toString(); - -const getFormatter = (column: RuntimeColumnDescriptor) => { - if (isTypeDescriptor(column.type)) { - const { name, formatting } = column.type; - if (name === "number") { - return numericFormatter(formatting, column.align); - } - } - return defaultFormatter; -}; - -export const useCellFormatter = (column: RuntimeColumnDescriptor) => { - const formatter = useRef(getFormatter(column)); - return [formatter.current]; -}; - -const DEFAULT_NUMERIC_FORMATTING = {}; - -function numericFormatter( - { - alignOnDecimals = false, - decimals = 4, - zeroPad = false, - }: ColumnTypeFormatting = DEFAULT_NUMERIC_FORMATTING, - align: "left" | "right" = "right" -) { - const props = { className: "num" }; - // eslint-disable-next-line react/display-name - return (value: unknown) => { - if ( - typeof value === "string" && - (value.startsWith("Σ") || value.startsWith("[")) - ) { - return value; - } - const number = - typeof value === "number" - ? value - : typeof value === "string" - ? parseFloat(value) - : undefined; - return createElement( - "div", - props, - roundDecimal(number, align, decimals, zeroPad, alignOnDecimals) - ); - }; -} diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-cells/useCellResize.tsx b/vuu-ui/packages/vuu-datagrid/src/grid-cells/useCellResize.tsx deleted file mode 100644 index ff6d2ac7a..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-cells/useCellResize.tsx +++ /dev/null @@ -1,66 +0,0 @@ -import { RefObject, useCallback, useRef } from "react"; -import { Heading, RuntimeColumnDescriptor } from "@finos/vuu-datagrid-types"; -import { resizePhase } from "../gridTypes"; - -export type ResizeHandler = (evt: MouseEvent, moveBy: number) => void; -export interface CellResizeHookProps { - column: RuntimeColumnDescriptor | Heading; - onResize?: (phase: resizePhase, columnName: string, width?: number) => void; - rootRef: RefObject; -} - -export interface CellResizeHookResult { - isResizing: boolean; - onDrag: (evt: MouseEvent, moveBy: number) => void; - onDragStart: (evt: React.MouseEvent) => void; - onDragEnd: (evt: MouseEvent) => void; -} - -export const useCellResize = ({ - column, - onResize, - rootRef, -}: CellResizeHookProps): CellResizeHookResult => { - const widthRef = useRef(0); - const isResizing = useRef(false); - const { name } = column; - - const handleResizeStart = useCallback(() => { - if (onResize && rootRef.current) { - const { width } = rootRef.current.getBoundingClientRect(); - widthRef.current = Math.round(width); - isResizing.current = true; - onResize?.("begin", name); - } - }, [name, onResize, rootRef]); - - const handleResize = useCallback( - (_evt: MouseEvent, moveBy: number) => { - if (rootRef.current) { - if (onResize) { - const { width } = rootRef.current.getBoundingClientRect(); - const newWidth = Math.round(width) + moveBy; - if (newWidth !== widthRef.current && newWidth > 0) { - onResize("resize", name, newWidth); - widthRef.current = newWidth; - } - } - } - }, - [name, onResize, rootRef] - ); - - const handleResizeEnd = useCallback(() => { - if (onResize) { - onResize("end", name, widthRef.current); - isResizing.current = false; - } - }, [name, onResize]); - - return { - isResizing: isResizing.current, - onDrag: handleResize, - onDragStart: handleResizeStart, - onDragEnd: handleResizeEnd, - }; -}; diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-context.tsx b/vuu-ui/packages/vuu-datagrid/src/grid-context.tsx deleted file mode 100644 index 869e89343..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-context.tsx +++ /dev/null @@ -1,222 +0,0 @@ -import { DataSource } from "@finos/vuu-data"; -import { DataRow } from "@finos/vuu-utils"; -import React, { ReactNode, useContext, useMemo } from "react"; -import { VuuAggregation, VuuGroupBy, VuuSort } from "../../vuu-protocol-types"; -import { AdornmentsDescriptor } from "./grid-adornments"; -import { - GridModelReducerInitializerProps, - GridModelType, -} from "./grid-model/gridModelTypes"; -import { MeasuredSize, Size } from "./grid-model/useMeasuredSize"; -import { resizePhase } from "./gridTypes"; -import { - ColumnDescriptor, - GridAction, - RuntimeColumnDescriptor, -} from "@finos/vuu-datagrid-types"; -import { DataSourceFilter } from "@finos/vuu-data-types"; - -export interface GridActionGroup { - type: "group"; - key?: VuuGroupBy; -} -export interface GridActionScrollEndHorizontal { - type: "scroll-end-horizontal"; - scrollLeft: number; -} - -export interface GridActionScrollStartHorizontal { - type: "scroll-start-horizontal"; - scrollLeft: number; -} - -export interface GridActionCloseTreeNode { - type: "closeTreeNode"; - key: string; -} - -export interface GridActionOpenTreeNode { - type: "openTreeNode"; - key: string; -} - -export interface GridActionResizeCol { - columnName: string; - phase: resizePhase; - type: "resize-col"; - width: number; -} -export interface GridActionSelection { - type: "selection"; - idx: number; - row: DataRow; - rangeSelect: boolean; - keepExistingSelection: boolean; -} -export interface GridActionSort { - type: "sort"; - sort: VuuSort; -} - -export interface GridModelActionAddCol { - type: "add-col"; - column: RuntimeColumnDescriptor; - insertIdx: number; -} - -// also a DataSourceMessage -export interface GridModelActionAggregate { - type: "aggregate"; - aggregations: VuuAggregation[]; -} - -export interface GridModelActionHideColumn { - type: "column-hide"; - column: RuntimeColumnDescriptor; -} -export interface GridModelActionGridConfig { - type: "grid-config"; - filter?: DataSourceFilter; - groupBy?: VuuGroupBy; - sort?: VuuSort; -} -export interface GridModelActionSetColumns { - type: "set-columns"; - columns: ColumnDescriptor[]; -} - -export interface GridModelActionFilter { - type: "filter"; - filter: DataSourceFilter; -} -export interface GridModelActionInitialize { - type: "initialize"; - props: GridModelReducerInitializerProps; - size: Size; -} - -export interface GridModelActionGroupBy { - type: "groupBy"; - groupBy: VuuGroupBy | undefined; -} - -export interface GridModelActionResize { - size: MeasuredSize; - type: "resize"; -} -export interface GridModelActionResizeColumn { - columnName: string; - phase: resizePhase; - type: "resize-col"; - width: number; -} -export interface GridModelActionResizeHeading { - type: "resize-heading"; - phase: resizePhase; - headingName: string; - width?: number; -} -export interface GridModelActionRowHeight { - type: "ROW_HEIGHT"; - rowHeight: number; -} -export interface GridModelActionShowColumn { - type: "column-show"; - column: RuntimeColumnDescriptor; -} -export interface GridModelActionSort { - type: "sort"; - sort: VuuSort; -} - -export interface GridModelActionSetAvailableColumns { - type: "set-available-columns"; - columns: ColumnDescriptor[]; -} - -export type GridModelAction = - | GridModelActionAddCol - | GridModelActionFilter - | GridModelActionGridConfig - | GridModelActionGroupBy - | GridModelActionHideColumn - | GridModelActionInitialize - | GridModelActionSetColumns - | GridModelActionResize - | GridModelActionResizeColumn - | GridModelActionResizeHeading - | GridModelActionSetAvailableColumns - | GridModelActionRowHeight - | GridModelActionAggregate - | GridModelActionShowColumn - | GridModelActionSort; - -export type GridModelDispatch = (action: GridModelAction) => void; - -export interface GridContext { - custom?: AdornmentsDescriptor; - dataSource?: DataSource; - dispatchGridAction?: (action: GridAction) => undefined | boolean; - dispatchGridModelAction?: GridModelDispatch; - gridModel?: GridModelType; -} -const NO_CONTEXT = {}; - -const GridContext = React.createContext(NO_CONTEXT); - -const chainInheritedContextValues = ( - localContext: GridContext, - inheritedContext: GridContext -) => { - const { dispatchGridAction: localDispatch, ...localContextValues } = - localContext; - const { dispatchGridAction: inheritedDispatch, ...inheritedContextValues } = - inheritedContext; - - const dispatchGridAction = (action: GridAction) => - localDispatch?.(action) || inheritedDispatch?.(action) || false; - - return { - ...inheritedContextValues, - ...localContextValues, - dispatchGridAction, - }; -}; - -interface GridProviderProps { - children: ReactNode; - value?: GridContext; -} - -interface ProviderProps extends GridProviderProps { - context?: GridContext; -} - -const Provider = ({ - children, - context = NO_CONTEXT, - value = NO_CONTEXT, -}: ProviderProps) => { - const contextValue = useMemo(() => { - return chainInheritedContextValues(value, context); - }, [context, value]); - return ( - {children} - ); -}; - -export const GridProvider = ({ children, value }: GridProviderProps) => { - return ( - - {(parentContext) => ( - - {children} - - )} - - ); -}; - -export const useGridContext = () => { - return useContext(GridContext); -}; diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-data-actions.ts b/vuu-ui/packages/vuu-datagrid/src/grid-data-actions.ts deleted file mode 100644 index 0eb725838..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-data-actions.ts +++ /dev/null @@ -1,25 +0,0 @@ -export const COLUMN_COLLAPSE = 'COLUMN_COLLAPSE'; -export const COLUMN_EXPAND = 'COLUMN_EXPAND'; -export const COLUMN_RESIZE_BEGIN = 'COLUMN_RESIZE_BEGIN'; -export const COLUMN_RESIZE = 'COLUMN_RESIZE'; -export const COLUMN_RESIZE_END = 'COLUMN_RESIZE_END'; -export const COLUMNS_CHANGE = 'COLUMNS_CHANGE'; -export const GRID_RESIZE = 'GRID_RESIZE'; -export const GROUP = 'GROUP'; -export const INITIALIZE = 'INITIALIZE'; -export const ROWCOUNT = 'ROWCOUNT'; -export const SUBSCRIBED = 'SUBSCRIBED'; -export const SORT = 'SORT'; -export const SORT_GROUP = 'SORT_GROUP'; -export const GROUP_COLUMN_WIDTH = 'GROUP_COLUMN_WIDTH'; -export const RESIZE_HEADING = 'RESIZE_HEADING'; -export const MOVE_BEGIN = 'MOVE_BEGIN'; -export const MOVE = 'MOVE'; -export const MOVE_END = 'MOVE_END'; -export const SCROLLLEFT = 'SCROLLLEFT'; -export const SCROLL_LEFT = 'SCROLL_LEFT'; -export const SCROLL_RIGHT = 'SCROLL_RIGHT'; -export const RANGE = 'RANGE'; -export const groupExtend = 'GROUP_EXTEND'; -export const TOGGLE = 'TOGGLE'; -export const TOGGLE_FILTERS = 'TOGGLE_FILTERS'; diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-hooks/index.ts b/vuu-ui/packages/vuu-datagrid/src/grid-hooks/index.ts deleted file mode 100644 index 4fa021de2..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-hooks/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from "./use-data-source"; -export * from "./useGridActionDispatcher"; -export * from "./useKeyboardNavigation"; -export * from "./useHorizontalScrollSync"; -export * from "./use-selection"; diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-hooks/use-data-source.ts b/vuu-ui/packages/vuu-datagrid/src/grid-hooks/use-data-source.ts deleted file mode 100644 index 4f5bfd144..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-hooks/use-data-source.ts +++ /dev/null @@ -1,240 +0,0 @@ -import { ConfigChangeHandler, SubscribeCallback } from "@finos/vuu-data"; -import { useViewContext } from "@finos/vuu-layout"; -import { VuuRange, VuuSort } from "@finos/vuu-protocol-types"; -import { - getFullRange, - metadataKeys, - toColumnDescriptor, - WindowRange, -} from "@finos/vuu-utils"; -import { DataSourceRow } from "@finos/vuu-data-types"; -import { useCallback, useEffect, useMemo, useRef, useState } from "react"; -import { useGridContext } from "../grid-context"; -import { GridModelType } from "../grid-model/gridModelTypes"; - -const { RENDER_IDX } = metadataKeys; - -const byKey = (row1: DataSourceRow, row2: DataSourceRow) => - row1[RENDER_IDX] - row2[RENDER_IDX]; - -export type SubscriptionDetails = { - columnNames?: string[]; - range: { from: number; to: number }; - sort?: VuuSort; -}; - -//TODO allow subscription details to be set before subscribe call -export function useDataSource( - subscriptionDetails: SubscriptionDetails, - gridModel: GridModelType, - onConfigChange?: ConfigChangeHandler, - onSizeChange?: (size: number) => void -) { - const { dataSource, dispatchGridAction, dispatchGridModelAction } = - useGridContext(); - const { title } = useViewContext(); - const [, forceUpdate] = useState(null); - const isMounted = useRef(true); - const hasUpdated = useRef(false); - const rafHandle = useRef(null); - const data = useRef([]); - - const dataWindow = useMemo( - () => - new MovingWindow( - getFullRange(subscriptionDetails.range, gridModel.renderBufferSize) - ), - // eslint-disable-next-line react-hooks/exhaustive-deps - [gridModel.renderBufferSize] - ); - - const setData = useCallback( - (updates: DataSourceRow[]) => { - // onsole.log(`%c[useDataSource] setData - // [${updates.map(d => d[0]).join(',')}]`,'color:blue') - for (const row of updates) { - dataWindow.add(row); - } - - // Why bother with the slice ? - data.current = dataWindow.data.slice().sort(byKey); - // onsole.log(`%c[useDataSource] data.current has ${data.current.length} records - // [${data.current.map(d => d[0]).join(',')}] - // `, 'color:blue;') - hasUpdated.current = true; - }, - [dataWindow] - ); - - const datasourceMessageHandler: SubscribeCallback = useCallback( - (message) => { - if (message.type === "subscribed") { - const { filter, groupBy, sort } = message; - dispatchGridModelAction?.({ - type: "set-available-columns", - columns: message.columns.map(toColumnDescriptor), - }); - - dispatchGridModelAction?.({ - type: "grid-config", - filter, - groupBy, - sort, - }); - } else if (message.type === "viewport-update") { - if (typeof message.size === "number") { - onSizeChange?.(message.size); - dataWindow.setRowCount(message.size); - } - if (message.rows) { - setData(message.rows); - } else if (typeof message.size === "number") { - // TODO is this right ?????? - data.current = dataWindow.data.slice().sort(byKey); - hasUpdated.current = true; - } - } else if ( - message.type === "sort" || - message.type === "aggregate" || - message.type === "filter" || - message.type === "groupBy" - ) { - dispatchGridModelAction?.(message); - onConfigChange?.(message); - } else { - // TODO - dispatchGridAction?.(message as any); - } - }, - [ - dataWindow, - dispatchGridAction, - dispatchGridModelAction, - onConfigChange, - onSizeChange, - setData, - ] - ); - - useEffect( - () => () => { - if (rafHandle.current) { - cancelAnimationFrame(rafHandle.current); - rafHandle.current = null; - } - isMounted.current = false; - }, - [] - ); - - const refreshIfUpdated = useCallback(() => { - if (isMounted.current) { - if (hasUpdated.current) { - forceUpdate({}); - hasUpdated.current = false; - } - rafHandle.current = requestAnimationFrame(refreshIfUpdated); - } - }, [forceUpdate]); - - useEffect(() => { - rafHandle.current = requestAnimationFrame(refreshIfUpdated); - }, [refreshIfUpdated]); - - const setRange = useCallback( - (from, to) => { - if (dataSource) { - const range = getFullRange( - { from, to }, - gridModel.renderBufferSize, - dataSource?.size - ); - dataSource.range = range; - dataWindow.setRange(range.from, range.to); - } - }, - [dataSource, dataWindow, gridModel.renderBufferSize] - ); - - useEffect(() => { - const { range, ...rest } = subscriptionDetails; - const { from, to } = getFullRange(range, gridModel.renderBufferSize); - dataSource?.subscribe( - { - ...rest, - range: { from, to }, - title, - }, - datasourceMessageHandler - ); - }, [ - dataSource, - datasourceMessageHandler, - gridModel.renderBufferSize, - subscriptionDetails, - title, - ]); - - return { - data: data.current, - setRange, - dataSource, - }; -} - -export class MovingWindow { - public data: DataSourceRow[]; - public rowCount = 0; - private range: WindowRange; - - constructor({ from, to }: VuuRange) { - this.range = new WindowRange(from, to); - //internal data is always 0 based, we add range.from to determine an offset - this.data = new Array(to - from); - this.rowCount = 0; - } - - setRowCount = (rowCount: number) => { - if (rowCount < this.data.length) { - this.data.length = rowCount; - } - - this.rowCount = rowCount; - }; - - add(data: DataSourceRow) { - const [index] = data; - if (this.isWithinRange(index)) { - const internalIndex = index - this.range.from; - this.data[internalIndex] = data; - } - } - - getAtIndex(index: number) { - return this.range.isWithin(index) && - this.data[index - this.range.from] != null - ? this.data[index - this.range.from] - : undefined; - } - - isWithinRange(index: number) { - return this.range.isWithin(index); - } - - setRange(from: number, to: number) { - if (from !== this.range.from || to !== this.range.to) { - const [overlapFrom, overlapTo] = this.range.overlap(from, to); - const newData = new Array(to - from); - for (let i = overlapFrom; i < overlapTo; i++) { - const data = this.getAtIndex(i); - if (data) { - const index = i - from; - newData[index] = data; - } - } - this.data = newData; - this.range.from = from; - this.range.to = to; - } - } -} diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-hooks/use-selection.ts b/vuu-ui/packages/vuu-datagrid/src/grid-hooks/use-selection.ts deleted file mode 100644 index f667528ad..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-hooks/use-selection.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { useCallback, useRef } from "react"; -import { metadataKeys } from "@finos/vuu-utils"; - -const { IDX, SELECTED } = metadataKeys; - -export const SINGLE = "single"; -export const CHECKBOX = "checkbox"; -export const MULTI = "multi"; -export const EXTENDED = "extended"; - -export interface SelectionHookProps { - onChange: (selected: number[] | undefined) => void; - selection: "none" | "single" | "multi" | "checkbox" | "extended"; -} - -export const useSelection = ({ - onChange, - selection = SINGLE, -}: SelectionHookProps) => { - const singleSelect = selection === SINGLE; - const multiSelect = selection === MULTI || selection.startsWith(CHECKBOX); - const extendedSelect = selection === EXTENDED; - const lastActive = useRef(-1); - const selected = useRef([]); - - const handleSelectionChange = useCallback( - ({ - row, - rangeSelect, - keepExistingSelection: preserveExistingSelection, - }) => { - const { [IDX]: idx, [SELECTED]: isSelected } = row; - const { current: active } = lastActive; - const { current: currentSelected } = selected; - const inactiveRange = active === -1; - const actsLikeSingleSelect = - singleSelect || - (extendedSelect && - !preserveExistingSelection && - (!rangeSelect || inactiveRange)); - const actsLikeMultiSelect = - multiSelect || - (extendedSelect && preserveExistingSelection && !rangeSelect); - - let newSelected; - if (actsLikeSingleSelect && isSelected) { - newSelected = []; - } else if (actsLikeSingleSelect) { - newSelected = [idx]; - } else if (actsLikeMultiSelect && isSelected) { - newSelected = currentSelected?.filter((i) => i !== idx); - } else if (actsLikeMultiSelect) { - newSelected = currentSelected?.concat(idx); - } else if (extendedSelect) { - const [from, to] = idx > active ? [active, idx] : [idx, active]; - newSelected = currentSelected?.slice(); - for (let i = from; i <= to; i++) { - if (!currentSelected?.includes(i)) { - newSelected.push(i); - } - } - } - - selected.current = newSelected ?? []; - lastActive.current = idx; - - if (onChange) { - onChange(newSelected); - } - }, - [extendedSelect, multiSelect, onChange, singleSelect] - ); - - return handleSelectionChange; -}; diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-hooks/useGridActionDispatcher.ts b/vuu-ui/packages/vuu-datagrid/src/grid-hooks/useGridActionDispatcher.ts deleted file mode 100644 index 945c29065..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-hooks/useGridActionDispatcher.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { ConfigChangeHandler } from "@finos/vuu-data"; -import { - DataSourceAction, - GridAction, - ScrollAction, -} from "@finos/vuu-datagrid-types"; -import { useCallback } from "react"; -import { GridActionSelection, GridModelDispatch } from "../grid-context"; - -export interface GridActionHookProps { - dispatchGridModelAction: GridModelDispatch; - invokeDataSourceAction: (action: DataSourceAction) => void; - handleSelectionChange: (action: GridActionSelection) => void; - invokeScrollAction: (action: ScrollAction) => void; - onConfigChange: ConfigChangeHandler; -} - -export const useGridActionDispatcher = ({ - dispatchGridModelAction, - invokeDataSourceAction, - handleSelectionChange, - invokeScrollAction, - onConfigChange, -}: GridActionHookProps) => { - const dispatchAction = useCallback( - (action: GridAction) => { - switch (action.type) { - case "sort": - case "group": - case "openTreeNode": - case "closeTreeNode": - return invokeDataSourceAction(action), true; - case "selection": - return handleSelectionChange(action), true; - case "scroll-start-horizontal": - case "scroll-end-horizontal": - return invokeScrollAction(action), true; - case "resize-col": - { - dispatchGridModelAction(action); - if (action.phase === "end") { - onConfigChange?.({ type: "columns" }); - } - } - - break; - - default: - return false; - } - }, - [ - invokeDataSourceAction, - handleSelectionChange, - invokeScrollAction, - dispatchGridModelAction, - onConfigChange, - ] - ); - - return dispatchAction; -}; diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-hooks/useHorizontalScrollSync.ts b/vuu-ui/packages/vuu-datagrid/src/grid-hooks/useHorizontalScrollSync.ts deleted file mode 100644 index ca479be08..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-hooks/useHorizontalScrollSync.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { MutableRefObject, useCallback } from "react"; -import { GridModelType } from "../grid-model"; -import { ViewportScrollApi } from "../Viewport"; - -export interface HorizontalScrollSynvHookProps { - gridModel: GridModelType; - rootRef: MutableRefObject; - viewportRef: MutableRefObject; -} - -// TODO get rid of this entirely if we can establish a suitable html structure -export const useHorizonatlScrollSync = ({ - gridModel, - rootRef, - viewportRef, -}: HorizontalScrollSynvHookProps) => { - const handleHorizontalScrollStart = useCallback(() => { - if (rootRef.current && viewportRef.current) { - viewportRef.current.beginHorizontalScroll(); - rootRef.current.classList.add("scrolling-x"); - rootRef.current.style.paddingTop = gridModel.customHeaderHeight + "px"; - } - }, [gridModel.customHeaderHeight, rootRef, viewportRef]); - - const handleHorizontalScrollEnd = useCallback(() => { - if (rootRef.current && viewportRef.current) { - viewportRef.current.endHorizontalScroll(); - rootRef.current.classList.remove("scrolling-x"); - const { - headerHeight, - headingDepth = 1, - customHeaderHeight, - customInlineHeaderHeight, - } = gridModel; - const totalHeaderHeight = - headerHeight * headingDepth + - customHeaderHeight + - customInlineHeaderHeight; - rootRef.current.style.paddingTop = totalHeaderHeight + "px"; - } - }, [gridModel, rootRef, viewportRef]); - - const invokeScrollAction = useCallback( - (action) => { - if (action.type === "scroll-start-horizontal") { - handleHorizontalScrollStart(); - return true; - } else if (action.type === "scroll-end-horizontal") { - handleHorizontalScrollEnd(); - return true; - } - return false; - }, - [handleHorizontalScrollEnd, handleHorizontalScrollStart] - ); - - return invokeScrollAction; -}; diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-hooks/useKeyboardNavigation.ts b/vuu-ui/packages/vuu-datagrid/src/grid-hooks/useKeyboardNavigation.ts deleted file mode 100644 index 91a3cfc58..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-hooks/useKeyboardNavigation.ts +++ /dev/null @@ -1,271 +0,0 @@ -import { VuuRange } from "@finos/vuu-protocol-types"; -import { getFullRange } from "@finos/vuu-utils"; -import { MutableRefObject, useCallback, useEffect, useRef } from "react"; -import { GridModelType } from "../grid-model"; - -type RowNavKey = "ArrowUp" | "ArrowDown"; -type ColNavKey = "ArrowLeft" | "ArrowRight"; - -const isRowNavKey = (key: string): key is RowNavKey => - key === "ArrowUp" || key === "ArrowDown"; - -const isColNavKey = (key: string): key is ColNavKey => - key === "ArrowLeft" || key === "ArrowRight"; - -const RowNavKey = { - ArrowUp: true, - ArrowDown: true, -}; - -const ColNavKey = { - ArrowLeft: true, - ArrowRight: true, -}; - -const NavKey = { - Tab: true, - ...RowNavKey, - ...ColNavKey, -}; - -const isInteger = (num: number) => Math.floor(num) === num; - -type FocusState = { - cell: number; - col: number; - hasFocus: boolean; - isHeaderCell: boolean; - row: number; -}; - -export const useKeyboardNavigation = ( - rootRef: MutableRefObject, - gridModel: GridModelType -) => { - const headerRows = 1; - const range = useRef(null); - const focusState = useRef({ - hasFocus: false, - isHeaderCell: false, - row: -1, - cell: -1, - col: -1, - }); - const allowCellSelection = gridModel.cellSelectionModel !== "none"; - - useEffect(() => { - if (gridModel.viewportRowCount) { - range.current = { from: 0, to: gridModel.viewportRowCount }; - } - }, [gridModel.viewportRowCount]); - - const setRange = useCallback( - (value) => { - // remove focus from cell out of window - range.current = value; - if ( - focusState.current.row < value.from || - focusState.current.row >= value.to - ) { - // shift focus to placehgolder - rootRef.current?.focus(); - } - }, - [rootRef] - ); - - const focusHeaderCell = useCallback( - (row, col = focusState.current.col) => { - const focus = focusState.current; - const { col: currentCol, row: currentRow } = focus; - - focus.isHeaderCell = true; - focus.row = row; - focus.col = col; - if (currentCol !== -1 && currentRow !== -1) { - const currentTarget = - currentRow === 0 - ? rootRef.current?.querySelector( - `.hwHeaderCell:nth-child(${currentCol + 1})` - ) - : rootRef.current - ?.querySelector(`.GridRow[data-idx="${currentRow}"]`) - ?.querySelector( - `.vuuDataGridCell:nth-child(${currentCol + 1})` - ); - if (currentTarget) { - currentTarget.setAttribute("tabindex", "-1"); - } - } - - const target = rootRef.current?.querySelector( - `.hwHeaderCell:nth-child(${col + 1})` - ) as HTMLElement; - if (target) { - target?.focus(); - target.setAttribute("tabindex", "0"); - } - }, - [rootRef] - ); - - const focusCell = useCallback( - (row, col = focusState.current.col) => { - const focus = focusState.current; - focus.isHeaderCell = false; - focus.row = row; - focus.col = col; - const target = rootRef.current - ?.querySelector(`.GridRow[data-idx="${row}"]`) - ?.querySelector( - `.vuuDataGridCell:nth-child(${col + 1})` - ) as HTMLElement; - if (target) { - target?.focus(); - } - }, - [rootRef] - ); - - const handleKeyDown = useCallback( - (e) => { - if (NavKey && range.current) { - const { isHeaderCell, row, col } = focusState.current; - if (isRowNavKey(e.key)) { - const { from, to } = range.current; - const fullRange = getFullRange( - range.current, - gridModel.renderBufferSize - ); - - if (e.key === "ArrowDown") { - if (row === -1) { - focusHeaderCell(0, 0); - } else if (isHeaderCell && row + 1 < headerRows) { - focusHeaderCell(row + 1, col); - } else { - const nextRow = Math.max(from, isHeaderCell ? 0 : row + 1); - const nextRowIdx = nextRow; - if (nextRowIdx < fullRange.to) { - if (nextRowIdx < Math.floor(to) && isInteger(nextRow)) { - focusCell(nextRow); - e.stopPropagation(); - e.preventDefault(); - } else { - if (!isInteger(nextRow)) { - console.log( - "how do we tell viewport to scroll up to align row, not down ?" - ); - } - requestAnimationFrame(() => { - focusCell(Math.floor(nextRow)); - }); - } - } - } - } else if (e.key === "ArrowUp") { - if (isHeaderCell && row === 0) { - // do nothing - } else if (isHeaderCell) { - focusHeaderCell(row - 1); - } else if (!isHeaderCell && row === 0) { - focusHeaderCell(headerRows - 1); - } else { - const nextRow = row - 1; - if (nextRow >= fullRange.from) { - if (nextRow >= from && isInteger(nextRow)) { - focusCell(nextRow); - e.stopPropagation(); - e.preventDefault(); - } else { - requestAnimationFrame(() => { - focusCell(nextRow); - }); - } - } - } - } - } else if (isColNavKey(e.key)) { - const focusNextCell = isHeaderCell ? focusHeaderCell : focusCell; - e.stopPropagation(); - e.preventDefault(); - - if (e.key === "ArrowRight" && col + 1 < gridModel.columns.length) { - focusNextCell(row, col + 1); - } else if (e.key === "ArrowLeft" && col > 0) { - focusNextCell(row, col - 1); - } - } else if (e.key === "Enter") { - console.log("enter pressed, is there a valid action ?"); - } - } - }, - [focusCell, focusHeaderCell, gridModel.columns, gridModel.renderBufferSize] - ); - - const handleClick = useCallback( - (e) => { - const cellEl = e.target.closest(".vuuDataGridCell, .hwHeaderCell"); - if (cellEl) { - // what about row selection - // somehow need to determine whether we're in 'row select'mode or edit mode - // e.stopPropagation(); - const rowEl = cellEl.parentNode; - const col = Array.from(rowEl.childNodes).indexOf(cellEl); - const row = parseInt(rowEl.dataset.idx); - focusCell(row, col); - } - }, - [focusCell] - ); - - const handleFocus = useCallback(() => { - const { - current: { hasFocus }, - } = focusState; - if (!hasFocus) { - focusState.current.hasFocus = true; - // do this in a timeout, so we can cancel it if it turns out to have been a click - focusHeaderCell(0, 0); - } - }, [focusHeaderCell]); - - const handleBlur = useCallback( - (e) => { - if (rootRef.current?.contains(e.relatedTarget)) { - // do nothing - } else { - focusState.current.hasFocus = false; - } - }, - [rootRef] - ); - - useEffect(() => { - const rootEl = rootRef.current; - if (allowCellSelection) { - rootEl?.addEventListener("blur", handleBlur, true); - rootEl?.addEventListener("click", handleClick, true); - rootEl?.addEventListener("keydown", handleKeyDown, true); - rootEl?.addEventListener("focus", handleFocus, true); - } - - return () => { - if (allowCellSelection) { - rootEl?.removeEventListener("blur", handleBlur, true); - rootEl?.removeEventListener("click", handleClick, true); - rootEl?.removeEventListener("focus", handleFocus, true); - rootEl?.removeEventListener("keydown", handleKeyDown, true); - } - }; - }, [ - allowCellSelection, - handleBlur, - handleClick, - handleFocus, - handleKeyDown, - rootRef, - ]); - - return setRange; -}; diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-model/GridModelReducer.ts b/vuu-ui/packages/vuu-datagrid/src/grid-model/GridModelReducer.ts deleted file mode 100644 index e52c34fa2..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-model/GridModelReducer.ts +++ /dev/null @@ -1,1027 +0,0 @@ -import { isSimpleColumnType, metadataKeys } from "@finos/vuu-utils"; -import { - ColumnDescriptor, - ColumnTypeSimple, - RuntimeColumnDescriptor, -} from "@finos/vuu-datagrid-types"; -import { - ColumnGroupType, - GridModelReducerInitializerTuple, - GridModelType, - GroupColumnIndices, - Headings, - HeadingResizeState, -} from "./gridModelTypes"; -import { - assignKeysToColumns, - columnKeysToIndices, - extractGroupColumn, - getColumnHeading, - getHeadingPosition, - getHorizontalScrollbarHeight, - GridModel, - splitKeys, -} from "./gridModelUtils"; - -import { - GridModelAction, - GridModelActionAggregate, - GridModelActionFilter, - GridModelActionGridConfig, - GridModelActionGroupBy, - GridModelActionHideColumn, - GridModelActionInitialize, - GridModelActionResize, - GridModelActionResizeColumn, - GridModelActionResizeHeading, - GridModelActionRowHeight, - GridModelActionSetAvailableColumns, - GridModelActionShowColumn, - GridModelActionSort, -} from "../grid-context"; -import { isMeasured, MeasuredSize } from "./useMeasuredSize"; -import { Reducer } from "react"; - -const DEFAULT_COLUMN_MIN_WIDTH = 30; -const DEFAULT_COLUMN_WIDTH = 80; -const DEFAULT_COLUMN_TYPE = { name: "string" as ColumnTypeSimple }; -const CHECKBOX_COLUMN: RuntimeColumnDescriptor = { - label: "", - name: "", - key: metadataKeys.SELECTED, - width: 25, - sortable: false, - isSystemColumn: true, - type: { - name: "checkbox", - renderer: { - name: "checkbox-cell", - }, - }, - valueFormatter: undefined, -}; - -const LINE_NUMBER_COLUMN: RuntimeColumnDescriptor = { - className: "vuuLineNumber", - flex: 0, - isSystemColumn: true, - label: " ", - name: "line", - key: metadataKeys.IDX, - valueFormatter: undefined, - width: 30, -}; - -const RESIZING = { resizing: true, flex: 0 }; -const NOT_RESIZING = { resizing: false }; - -type isResizing = typeof RESIZING | typeof NOT_RESIZING; - -export type GridModelReducer = Reducer; - -export const gridModelReducer: GridModelReducer = (state, action) => { - // console.log( - // `%cGridModelReducer ${action.type}`, - // "color:red;font-weight:bold;" - // ); - - // prettier-ignore - switch (action.type) { - case "resize": return resizeGrid(state, action); - case "resize-col": return resizeColumn(state, action); - case "resize-heading": return resizeHeading(state, action); - // case "add-col": return addColumn(state, action); - case "initialize": return initialize(state, action); - case "filter": return addFilter(state, action); - case "sort": return sortRows(state, action); - case "groupBy": return groupRows(state, action); - case "set-available-columns": return setAvailableColumns(state, action); - case "aggregate": return setAggregations(state, action); - case "column-hide": return hideColumn(state, action); - case "column-show": return showColumn(state, action); - case "ROW_HEIGHT": return setRowHeight(state, action); - case "grid-config": return setGridConfig(state, action) - default: - console.log(`unknown action dispatched to GridModelReducer ${action['type']}`); - return state; - } -}; - -export type initModelProps = []; - -export const initModel = ([ - gridProps, - size, - custom, -]: GridModelReducerInitializerTuple): GridModelType => { - const { - aggregations = [], - cellSelectionModel, - columns, - columnSizing, - defaultColumnWidth = DEFAULT_COLUMN_WIDTH, - filter, - groupBy, - headerHeight, - minColumnWidth = DEFAULT_COLUMN_MIN_WIDTH, - noColumnHeaders, - renderBufferSize, - rowHeight, - selectionModel = "none", // default should be none - showLineNumbers, - sort, - } = gridProps; - - // The custom support is all new ... still under review - const { - footer: { height: customFooterHeight }, - header: { height: customHeaderHeight }, - inlineHeader: { height: customInlineHeaderHeight }, - } = custom; - - const state: GridModelType = { - ...size, - aggregations, - cellSelectionModel, - columnNames: undefined, - columnGroups: undefined, - columns, - columnSizing, - customFooterHeight, - customHeaderHeight, - customInlineHeaderHeight, - defaultColumnWidth, - filter, - groupBy, - headerHeight: noColumnHeaders ? 0 : headerHeight, - headingDepth: undefined, - horizontalScrollbarHeight: undefined, - minColumnWidth, - noColumnHeaders, - renderBufferSize, - rowHeight, - selectionModel, - showLineNumbers, - sort, - status: "pending", - totalHeaderHeight: 0, - viewportHeight: 0, - viewportRowCount: 0, - visualLinks: undefined, - }; - if (isMeasured(size)) { - return buildColumnsAndApplyMeasurements(state, size); - } else { - return state; - } -}; - -function buildColumnsAndApplyMeasurements( - state: GridModelType, - size: MeasuredSize -): GridModelType { - const { - columns, - customFooterHeight, - customInlineHeaderHeight, - customHeaderHeight, - headerHeight, - noColumnHeaders, - rowHeight, - } = state; - - // client height and width are always measured, width and height may come from props - // const { - // height: fullHeight, - // clientHeight: height = fullHeight, - // width: fullWidth, - // clientWidth: width = fullWidth, - // } = size; - - const { columnNames, columnGroups, headingDepth } = buildColumnGroups( - state, - columns, - size - ); - const totalHeaderHeight = noColumnHeaders - ? customHeaderHeight - : headerHeight * headingDepth + customHeaderHeight; - - const viewportHeight = - size.clientHeight - - totalHeaderHeight - - customFooterHeight - - customInlineHeaderHeight; - - return { - ...state, - ...size, - columnGroups, - columnNames, - headingDepth, - horizontalScrollbarHeight: getHorizontalScrollbarHeight(columnGroups), - status: "ready", - totalHeaderHeight, - viewportHeight, - viewportRowCount: (size.clientHeight - totalHeaderHeight) / rowHeight, - }; -} - -function initialize( - state: GridModelType, - { props, size }: GridModelActionInitialize -) { - const custom = { - inlineHeader: { height: state.customInlineHeaderHeight }, - header: { height: state.customHeaderHeight }, - footer: { height: state.customFooterHeight }, - }; - return initModel([props, size, custom]); -} - -function setGridConfig( - state: GridModelType, - { filter, groupBy, sort }: GridModelActionGridConfig -) { - let result = state; - - const hasFilter = filter !== undefined; - const hasGroupBy = groupBy && groupBy.length > 0; - const hasSort = sort && sort?.sortDefs.length > 0; - if (hasFilter || hasSort) { - result = { - ...state, - filter: filter ?? state.filter, - sort: hasSort ? sort : state.sort, - }; - } - - if (hasGroupBy) { - return groupRows(result, { type: "groupBy", groupBy }); - } else { - return result; - } - - return result; -} - -function resizeGrid( - state: GridModelType, - { size }: GridModelActionResize -): GridModelType { - let { columnGroups } = state; - if (state.clientWidth === undefined || state.clientHeight === undefined) { - return buildColumnsAndApplyMeasurements(state, size); - } else { - const { - columnSizing, - customFooterHeight, - customInlineHeaderHeight, - rowHeight, - totalHeaderHeight, - } = state; - const viewportHeight = - size.clientHeight - - totalHeaderHeight - - customFooterHeight - - customInlineHeaderHeight; - const widthDiff = size.clientWidth - state.clientWidth; - - if (widthDiff === 0) { - columnGroups = state.columnGroups; - } else if (columnSizing === "fill") { - ({ columnGroups } = buildColumnGroups( - state, - GridModel.columns(state), - size - )); - } else { - columnGroups = state.columnGroups?.map((columnGroup) => { - if (columnGroup.locked) { - return columnGroup; - } else { - return { - ...columnGroup, - width: columnGroup.width + widthDiff, - }; - } - }); - } - const actualRowCount = (size.clientHeight - totalHeaderHeight) / rowHeight; - return { - ...state, - ...size, - columnGroups, - status: "ready", - viewportHeight, - viewportRowCount: actualRowCount, - }; - } -} - -function setAvailableColumns( - state: GridModelType, - action: GridModelActionSetAvailableColumns -) { - if (!state.columnGroups && isMeasured(state)) { - const { columnNames, columnGroups, headingDepth } = buildColumnGroups( - state, - action.columns - ); - if (columnGroups) { - const totalHeaderHeight = state.headerHeight * headingDepth; - return { - ...state, - columnGroups, - columnNames, - headingDepth, - horizontalScrollbarHeight: getHorizontalScrollbarHeight(columnGroups), - viewportHeight: state.height - totalHeaderHeight, - viewportRowCount: (state.height - totalHeaderHeight) / state.rowHeight, - }; - } - } - return state; -} - -function setAggregations( - state: GridModelType, - { aggregations }: GridModelActionAggregate -) { - return { - ...state, - aggregations, - }; -} - -function sortRows( - state: GridModelType, - { sort }: GridModelActionSort -): GridModelType { - return { - ...state, - sort, - }; -} - -function addFilter(state: GridModelType, { filter }: GridModelActionFilter) { - return { - ...state, - filter, - }; -} - -function groupRows(state: GridModelType, { groupBy }: GridModelActionGroupBy) { - const { columnGroups } = buildColumnGroups( - { ...state, groupBy }, - GridModel.columns(state) - ); - - return { - ...state, - groupBy, - columnGroups, - }; -} - -function resizeHeading( - state: GridModelType, - { phase, headingName, width }: GridModelActionResizeHeading -) { - if (state.columnGroups === undefined) { - throw Error("GridModelReducer resizeHeading, columnGroups in undefined"); - } - - const heading = getColumnHeading(state.columnGroups, headingName); - - if (phase === "begin") { - const { columnGroups } = updateGroupHeadings( - state.columnGroups, - headingName, - RESIZING, - RESIZING, - RESIZING - ); - - const headingResizeState: HeadingResizeState = { - lastSizedCol: 0, - ...getColumnPositions(columnGroups, splitKeys(heading.key)), - }; - resizeColumnHeaderHeading = ( - state: GridModelType, - headingName: string, - width: number - ) => resizeColumnHeading(state, headingName, width, headingResizeState); - return { ...state, columnGroups }; - } else if (phase === "resize") { - return ( - resizeColumnHeaderHeading?.(state, headingName, width as number) || state - ); - } else { - const { columnGroups } = updateGroupHeadings( - state.columnGroups, - headingName, - NOT_RESIZING, - NOT_RESIZING, - NOT_RESIZING - ); - resizeColumnHeaderHeading = undefined; - return { - ...state, - columnGroups, - }; - } -} - -let resizeColumnHeaderHeading: - | undefined - | ((state: GridModelType, headingName: string, width: number) => void); - -function resizeColumnHeading( - state: GridModelType, - headingName: string, - width: number, - headingResizeState: HeadingResizeState -) { - if (state.columnGroups) { - const heading = getColumnHeading(state.columnGroups, headingName); - const diff = width - heading.width; - const { lastSizedCol: pos, groupIdx, groupColIdx } = headingResizeState; - const [lastSizedCol, diffs] = getColumnAdjustments( - pos, - groupColIdx.length, - diff - ); - - headingResizeState.lastSizedCol = lastSizedCol; - - let newState = state; - for (let i = 0; i < diffs.length; i++) { - if (typeof diffs[i] === "number" && diffs[i] !== 0) { - const targetCol = state.columnGroups[groupIdx].columns[groupColIdx[i]]; - newState = resizeColumn( - { ...newState, headingResizeState }, - { - type: "resize-col", - phase: "resize", - columnName: targetCol.name, - width: targetCol.width + diffs[i], - } - ); - } - } - return newState; - } else { - return state; - } -} - -function hideColumn( - state: GridModelType, - { column }: GridModelActionHideColumn -) { - const columns = GridModel.columns(state).filter( - (col: RuntimeColumnDescriptor) => col.name !== column.name - ); - // const groupBy = GridModel.groupBy(state); - const { columnNames, columnGroups } = buildColumnGroups( - state, - columns - // groupBy - ); - return { - ...state, - columnGroups, - columnNames, - }; -} - -function showColumn(state: GridModelType, action: GridModelActionShowColumn) { - console.log(`show column ${action.column.name}}`); - return state; -} - -// function addColumn( -// state: GridModelType, -// { insertIdx: absInsertIdx, targetColumnGroup, column }: GridModelActionAddCol -// ) { -// if (absInsertIdx !== -1) { -// targetColumnGroup = getColumnGroup(state, absInsertIdx); -// } -// const insertIdx = getColumnGroupColumnIdx(state, absInsertIdx); - -// const targetIdx = state.columnGroups?.indexOf(targetColumnGroup); -// const sourceColumnGroup = getColumnGroup(state, column); -// const sourceIdx = state.columnGroups?.indexOf(sourceColumnGroup); -// const sourceColumn = state.columnGroups?.[sourceIdx].columns.find( -// (col) => col.key === column.key -// ); -// const columns = state.columnGroups?.flatMap((columnGroup, idx) => { -// if (idx === sourceIdx && sourceIdx !== targetIdx) { -// return columnGroup.columns.filter((col) => col.key !== column.key); -// } else if (idx === sourceIdx) { -// if (sourceIdx === targetIdx) { -// const sourceColumnIdx = sourceColumnGroup.columns.findIndex( -// (col) => col.key === sourceColumn.key -// ); -// if (insertIdx > sourceColumnIdx) { -// return ColumnGroup.moveColumnTo(columnGroup, sourceColumn, insertIdx); -// } else { -// return ColumnGroup.moveColumnTo(columnGroup, sourceColumn, insertIdx); -// } -// } else { -// return ColumnGroup.insertColumnAt(columnGroup, sourceColumn, insertIdx); -// } -// } else if (idx === targetIdx) { -// return ColumnGroup.insertColumnAt(columnGroup, sourceColumn, insertIdx); -// } else { -// return columnGroup.columns; -// } -// }); - -// const { columnGroups } = buildColumnGroups( -// state, -// columns.filter((col) => !col.isSystemColumn) -// ); - -// const { key: _, ...columnProps } = column; -// const leadingSystemColumns = GridModel.countLeadingSystemColumns(columns); - -// return { -// ...state, -// columnGroups, -// columns: GridModel.addColumnToColumns( -// columnProps, -// state.columns, -// absInsertIdx - leadingSystemColumns -// ), -// }; -// } - -function resizeColumn( - state: GridModelType, - { phase, columnName, width }: GridModelActionResizeColumn -): GridModelType { - if (phase === "resize") { - const columnGroups = GridModel.updateGroupColumnWidth( - state, - columnName, - width - ); - return { ...state, columnGroups }; - } else if (phase === "begin") { - const [columnGroups] = GridModel.updateGroupColumn( - state, - columnName, - RESIZING - ); - return { ...state, columnGroups }; - } else { - const [columnGroups] = GridModel.updateGroupColumn( - state, - columnName, - NOT_RESIZING - ); - return { - ...state, - columnGroups, - columns: state.columns.map((c) => - c.name === columnName - ? { - ...c, - width, - flex: 0, - } - : c - ), - }; - } -} - -function setRowHeight( - state: GridModelType, - { rowHeight }: GridModelActionRowHeight -) { - if (rowHeight === state.rowHeight) { - return state; - } else if (typeof state.height === "undefined") { - return { - ...state, - rowHeight, - }; - } else { - const { height, totalHeaderHeight } = state; - return { - ...state, - rowHeight, - viewportRowCount: (height - totalHeaderHeight) / rowHeight, - }; - } - - //TODO what abl=our scroll bar calculations -} - -const NO_COLUMN_GROUPS = { - columnGroups: undefined, - columnNames: undefined, - headingDepth: 0, -}; - -function buildColumnGroups( - state: GridModelType, - columns: ColumnDescriptor[], - size?: MeasuredSize -) { - if (!columns) { - return NO_COLUMN_GROUPS; - } - - const gridWidth = size?.clientWidth ?? state.width ?? state.clientWidth; - - if (gridWidth === undefined) { - throw Error( - `GridModelReducer ColumnGroups cannot be built before grid has been measured` - ); - } - const { - columnSizing, - defaultColumnWidth, - groupBy, - minColumnWidth, - selectionModel, - showLineNumbers, - } = state; - let column = null; - let columnGroup = null; - const columnGroups: ColumnGroupType[] = []; - const gridContentWidth = gridWidth - 17; // how do we know about vertical scrollbar - let availableWidth = gridContentWidth; - const preCols: RuntimeColumnDescriptor[] = - selectionModel === "checkbox" - ? [CHECKBOX_COLUMN] - : showLineNumbers - ? [LINE_NUMBER_COLUMN] - : []; - - const headingDepth = getMaxHeadingDepth(columns); - // TODO separate keys from columns - const keyedColumns = assignKeysToColumns(columns, defaultColumnWidth); - const columnNames: string[] = keyedColumns.map((col) => col.name); - - const [groupColumn, nonGroupedColumns] = extractGroupColumn( - keyedColumns, - groupBy - ); - if (groupColumn) { - const headings: Headings | undefined = - headingDepth > 1 ? ([] as Headings) : undefined; - columnGroups.push( - (columnGroup = { - columns: preCols.concat(groupColumn), - contentWidth: 0, - headings, - isGroup: true as const, - locked: false, - width: 0, - }) - ); - if (headings) { - addColumnToHeadings(headingDepth, groupColumn, headings); - } - preCols.length = 0; - } - - // TODO we need a min Width on the group column as well - let minTotalColumnWidth = groupColumn ? groupColumn.width : 0; - let totalColumnWidth = minTotalColumnWidth; - let flexTotal = 0; - let flexCount = 0; - const initialFlex: { [key: string]: number } = { $count: 0, $total: 0 }; - - for (const { - className, - flex = undefined, - isSystemColumn, - key, - name, - heading = [name], - label, - locked = false, - minWidth = minColumnWidth, - type, // normalize this here - width = defaultColumnWidth, - } of preCols.concat(nonGroupedColumns)) { - if (columnGroup === null || columnGroup.locked !== locked) { - const headings = headingDepth > 1 ? [] : undefined; - - columnGroups.push( - (columnGroup = { - headings, - isGroup: true as const, - locked, - columns: [] as RuntimeColumnDescriptor[], - left: totalColumnWidth, // TODO this won't be right if we introduce more than one locked group - width: 0, - contentWidth: 0, - }) - ); - } - - // TODO we are losing a lot of column information here - columnGroup.columns.push( - (column = { - className, - flex, - heading, - isSystemColumn, - label, - locked, - name, - key, - type: isSimpleColumnType(type) - ? { name: type } - : type - ? type - : DEFAULT_COLUMN_TYPE, - valueFormatter: undefined, - width, - }) - ); - - if (columnGroup.headings) { - addColumnToHeadings(headingDepth, column, columnGroup.headings); - } - - columnGroup.contentWidth += width; - minTotalColumnWidth += minWidth; - totalColumnWidth += width; - - if (flex) { - initialFlex.$count += 1; - initialFlex.$total += flex; - initialFlex[name] = flex; - } - - if (flex) { - flexTotal += flex; - } - - if (flex !== 0) { - flexCount += 1; - } - - // TODO fixed width may exceed available width. This assumes single fixed width followed by - // single scrollable - if (columnGroup.locked) { - columnGroup.width = columnGroup.contentWidth; - availableWidth -= width; - } else { - columnGroup.width = availableWidth; - } - } - - const noInitialFlex = initialFlex.$count === 0; - - if (columnSizing === "fill") { - // spread the diff ... - const diff = gridContentWidth - totalColumnWidth; - if ((diff < 0 && minTotalColumnWidth <= gridContentWidth) || diff > 0) { - const columnWidthAdjustment = - initialFlex.$total > 0 - ? diff / initialFlex.$total - : flexTotal > 0 - ? diff / flexTotal - : diff / flexCount; - - for (const columnGroup of columnGroups) { - for (const column of columnGroup.columns) { - let columnAdjustment = 0; - if (initialFlex[column.name]) { - columnAdjustment = columnWidthAdjustment * initialFlex[column.name]; - } else if (noInitialFlex && column.flex === undefined) { - columnAdjustment = columnWidthAdjustment; - } else if (noInitialFlex && (column?.flex ?? 0) > 0) { - columnAdjustment = columnWidthAdjustment * (column.flex as number); - } - column.width += Math.floor(columnAdjustment); - columnGroup.contentWidth += Math.floor(columnAdjustment); - } - } - } - } - - return { columnNames, columnGroups, headingDepth }; -} - -const getMaxHeadingDepth = (columns: ColumnDescriptor[]) => { - if (columns.length === 0) { - return 0; - } - let max = 1; - for (let i = 0; i < columns.length; i++) { - const { heading } = columns[i]; - if (Array.isArray(heading) && heading.length > max) { - max = heading.length; - } - } - return max; -}; - -function addColumnToHeadings( - maxHeadingDepth: number, - column: RuntimeColumnDescriptor, - headings: Headings, - collapsedColumns?: string[] -) { - const isHeading = true; - - const { key, heading: colHeader, width } = column; - const colKey = `${key}`; - for (let depth = 1; depth < maxHeadingDepth; depth++) { - const heading = headings[depth - 1] || (headings[depth - 1] = []); - const colHeaderLabel = colHeader?.[depth]; - const lastHeading = heading.length > 0 ? heading[heading.length - 1] : null; - - if (colHeaderLabel !== undefined) { - if (lastHeading && lastHeading.label === colHeaderLabel) { - lastHeading.width += width; - lastHeading.key += `:${colKey}`; - lastHeading.name = lastHeading.key; - } else { - const collapsed = - collapsedColumns && collapsedColumns.indexOf(colHeaderLabel) !== -1; - let hide = false; - if (collapsed) { - // lower depth headings are subheadings, nested subheadings below a collapsed heading - // will be hidden. Q: would it be better to iterate higher to lower ? When we encounter - // a collapsed heading for a given column, the first subheading at any lower level - // will already have been created, so we need to hide them. - for (let d = 0; d < depth - 1; d++) { - const head = headings[d]; - head[head.length - 1].hidden = true; - } - } else if (depth < maxHeadingDepth - 1) { - // ...likewise if we encounter a subheading, which is not the first for a given - // higher -level heading, and that higher-level heading is collapsed, we need to hide it. - for (let d = depth; d < maxHeadingDepth; d++) { - const head = headings[d]; - const colHeadingLabel = colHeader?.[d + 1]; - if (head && head.length && colHeaderLabel) { - const { - collapsed: isCollapsed, - hidden, - label, - } = head[head.length - 1]; - if ((isCollapsed || hidden) && label === colHeadingLabel) { - hide = true; - } - } - } - } - heading.push({ - key: `${key}`, - label: colHeaderLabel, - name: `${key}`, - width, - collapsed, - hidden: hide, - isHeading, - }); - } - } else { - const lowerDepth = headings[depth - 2]; - const lastLowerDepth = lowerDepth - ? lowerDepth[lowerDepth.length - 1] - : null; - - if (lastLowerDepth && lastLowerDepth.key === colKey) { - // Need to check whether a heading at level below is collapsed - heading.push({ - key: colKey, - label: "", - name: colKey, - width, - collapsed: lastLowerDepth.collapsed, - isHeading, - }); - } else if ( - lastHeading && - lastLowerDepth && - endsWith(lastLowerDepth.key, `:${key}`) - ) { - lastHeading.width += width; - lastHeading.key += `:${colKey}`; - lastHeading.name = lastHeading.key; - } else { - heading.push({ - key: colKey, - label: "", - name: colKey, - width, - isHeading, - }); - } - } - } -} - -function updateGroupHeadings( - groups: ColumnGroupType[], - headingName: string, - headingUpdates: isResizing, - subHeadingUpdates: isResizing, - columnUpdates: isResizing -) { - const { groupIdx, groupHeadingIdx, headingColIdx } = getHeadingPosition( - groups, - headingName - ); - const heading = getColumnHeading(groups, headingName); - const keys = splitKeys(heading.key); - - const group = groups[groupIdx]; - const clonedGroup = { - ...group, - headings: Array.isArray(group.headings) ? [...group.headings] : [], - }; - - // 1) Apply changes to the target heading ... - const updatedHeading = clonedGroup.headings[groupHeadingIdx].slice(); - clonedGroup.headings[groupHeadingIdx] = updatedHeading; - updatedHeading[headingColIdx] = { ...heading, ...headingUpdates }; - - // 2) Optionally, apply updates to nested sub-headings ... - if (subHeadingUpdates) { - for (let i = 0; i < groupHeadingIdx; i++) { - const h = clonedGroup.headings[i]; - let updatedH = null; - for (let j = 0; j < h.length; j++) { - if (heading.key.indexOf(h[j].key) !== -1) { - updatedH = updatedH || [...h]; - updatedH[j] = { ...h[j], ...subHeadingUpdates }; - } - } - if (updatedH !== null) { - clonedGroup.headings[i] = updatedH; - } - } - } - - // 3) Optionally, apply updates to underlying columns ... - if (columnUpdates) { - const { groupColIdx } = getColumnPositions(groups, keys); - clonedGroup.columns = [...group.columns]; - groupColIdx.forEach((idx: number) => { - const updatedColumn = { ...clonedGroup.columns[idx], ...columnUpdates }; - clonedGroup.columns[idx] = updatedColumn; - }); - } - - const columnGroups = [...groups]; - columnGroups[groupIdx] = clonedGroup; - return { columnGroups, updatedGroup: clonedGroup }; -} - -function getColumnPositions( - groups: ColumnGroupType[], - keys: number[] -): GroupColumnIndices { - for (let i = 0; i < groups.length; i++) { - const indices = columnKeysToIndices(keys, groups[i].columns); - if (indices.every((key) => key !== -1)) { - return { groupIdx: i, groupColIdx: indices }; - } - } - return { groupIdx: -1, groupColIdx: [] }; -} - -function getColumnAdjustments( - pos: number, - numCols: number, - diff: number -): [number, number[]] { - const sign = diff < 0 ? -1 : 1; - const absDiff = diff * sign; - const numSlotsToFill = Math.min(absDiff, numCols); - const each = Math.floor(absDiff / numCols); - let diffs = absDiff % numCols; - const results = []; - - for (let i = 0; i < numSlotsToFill; i++, pos++) { - if (pos === numCols) { - pos = 0; - } - results[pos] = sign * (each + (diffs ? 1 : 0)); - if (diffs) { - diffs -= 1; - } - } - return [pos, results]; -} - -function endsWith(value: string | number, subString: string) { - const str = typeof value === "string" ? value : value.toString(); - return subString.length >= str.length - ? false - : str.slice(-subString.length) === subString; -} diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-model/gridModelActions.ts b/vuu-ui/packages/vuu-datagrid/src/grid-model/gridModelActions.ts deleted file mode 100644 index 00f5868a8..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-model/gridModelActions.ts +++ /dev/null @@ -1,3 +0,0 @@ -export const ADD_COL = 'add-col'; -export const COL_RESIZE = 'resize-col'; -export const ROW_HEIGHT = 'ROW_HEIGHT'; diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-model/gridModelTypes.ts b/vuu-ui/packages/vuu-datagrid/src/grid-model/gridModelTypes.ts deleted file mode 100644 index 01146d7ca..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-model/gridModelTypes.ts +++ /dev/null @@ -1,133 +0,0 @@ -import { DataSource } from "@finos/vuu-data"; -import { MutableRefObject } from "react"; -import { VuuAggregation, VuuLinkDescriptor } from "@finos/vuu-protocol-types"; -import { AdornmentsDescriptor } from "../grid-adornments"; -import { GridModelDispatch } from "../grid-context"; -import { GridProps } from "../gridTypes"; -import { Size } from "./useMeasuredSize"; -import { Heading, RuntimeColumnDescriptor } from "@finos/vuu-datagrid-types"; - -export type Headings = Heading[][]; - -export type GridModelStatus = "pending" | "ready"; - -export type ColumnGroupType = { - columns: RuntimeColumnDescriptor[]; - contentWidth: number; - headings?: Headings; - isGroup: true; - left?: number; - locked: boolean; - width: number; -}; - -export interface GroupColumnIndices { - groupIdx: number; - groupColIdx: number[]; -} -export interface HeadingResizeState extends GroupColumnIndices { - lastSizedCol: number; -} - -export interface GridModelType - extends Pick< - GridProps, - | "cellSelectionModel" - | "columns" - | "columnSizing" - | "filter" - | "groupBy" - | "height" - | "noColumnHeaders" - | "renderBufferSize" - | "showLineNumbers" - | "sort" - | "width" - > { - // Note: we override some GridProps to remove optionality - aggregations: VuuAggregation[]; - clientHeight?: number; - clientWidth?: number; - columnNames?: string[]; - columnGroups?: ColumnGroupType[]; - customFooterHeight: number; - customHeaderHeight: number; - customInlineHeaderHeight: number; - defaultColumnWidth: number; - headerHeight: number; - headingDepth: number | undefined; - /** a transient state managed during a header resize operation */ - headingResizeState?: HeadingResizeState; - horizontalScrollbarHeight: undefined | number; - minColumnWidth: number; - rowHeight: number; - selectionModel: "none" | "checkbox" | "single" | "extended" | "multi"; - status: GridModelStatus; - totalHeaderHeight: number; - viewportHeight: number; - viewportRowCount: number; - visualLinks?: VuuLinkDescriptor[]; -} - -export interface GridModelHookProps - extends Pick< - GridProps, - | "aggregations" - | "cellSelectionModel" - | "children" - | "columns" - | "columnSizing" - | "dataSource" - | "defaultColumnWidth" - | "filter" - | "groupBy" - | "height" - | "minColumnWidth" - | "noColumnHeaders" - | "renderBufferSize" - | "selectionModel" - | "showLineNumbers" - | "sort" - | "style" - | "width" - > { - headerHeight: number; - rowHeight: number; -} - -export type GridModelHookResult = [ - MutableRefObject, - GridModelType, - DataSource, - GridModelDispatch, - AdornmentsDescriptor -]; - -export type GridModelReducerInitializerProps = Pick< - GridModelHookProps, - | "aggregations" - | "cellSelectionModel" - | "columns" - | "columnSizing" - | "defaultColumnWidth" - | "filter" - | "groupBy" - | "headerHeight" - | "minColumnWidth" - | "noColumnHeaders" - | "renderBufferSize" - | "rowHeight" - | "selectionModel" - | "showLineNumbers" - | "sort" ->; - -export type GridModelReducerInitializerTuple = [ - GridModelReducerInitializerProps, - Size, - { - header: { height: number }; - inlineHeader: { height: number }; - footer: { height: number }; - } -]; diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-model/gridModelUtils.ts b/vuu-ui/packages/vuu-datagrid/src/grid-model/gridModelUtils.ts deleted file mode 100644 index 04c143294..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-model/gridModelUtils.ts +++ /dev/null @@ -1,661 +0,0 @@ -import { DataRow, metadataKeys } from "@finos/vuu-utils"; -import { - VuuAggType, - VuuGroupBy, - VuuSort, - VuuSortCol, -} from "@finos/vuu-protocol-types"; -import { - ColumnDescriptor, - GroupColumnDescriptor, - Heading, - RuntimeColumnDescriptor, -} from "@finos/vuu-datagrid-types"; -import { ColumnGroupType, GridModelType } from "./gridModelTypes"; - -// 15px works on Mac, Windows requires 17, unless we style the scrollbars -export const getHorizontalScrollbarHeight = ( - columnGroups?: ColumnGroupType[] -) => - columnGroups - ? columnGroups.some(({ width, contentWidth }) => width < contentWidth) - ? 17 - : 0 - : 0; - -export function getHeadingPosition( - groups: ColumnGroupType[], - headingName: string -) { - for (let i = 0; i < groups.length; i++) { - const { headings = null } = groups[i]; - for (let j = 0; headings && j < headings.length; j++) { - const idx = headings[j].findIndex((h) => h.name === headingName); - if (idx !== -1) { - return { groupIdx: i, groupHeadingIdx: j, headingColIdx: idx }; - } - } - } - return { groupIdx: -1, groupHeadingIdx: -1, headingColIdx: -1 }; -} - -export const getColumnHeading = ( - columnGroups: ColumnGroupType[], - headingName: string -): Heading => { - const { groupIdx, groupHeadingIdx, headingColIdx } = getHeadingPosition( - columnGroups, - headingName - ); - - const heading = - columnGroups[groupIdx].headings?.[groupHeadingIdx][headingColIdx]; - if (!heading) { - throw Error("GridModelReducer updateGroupHeadings heading not found"); - } - - return heading; -}; - -export function getColumnGroup( - { columnGroups }: GridModelType, - target: number | RuntimeColumnDescriptor -) { - const isNumber = typeof target === "number"; - if (isNumber && columnGroups) { - // this can be simplified, dom\t need to iterate columns - const lastGroup = columnGroups.length - 1; - for (let i = 0, idx = 0; i <= lastGroup; i++) { - const columnGroup = columnGroups[i]; - const columnCount = columnGroup.columns.length; - for (let j = 0; j < columnCount; j++, idx++) { - if (target === idx) { - return columnGroup; - } else if ( - i === lastGroup && - target === idx + 1 && - j === columnCount - 1 - ) { - return columnGroup; - } - } - } - } else if (!isNumber && columnGroups) { - for (const columnGroup of columnGroups) { - if (columnGroup.columns.some(({ key }) => key === target.key)) { - return columnGroup; - } - } - } - return null; -} - -export function getColumnGroupIdx( - { columnGroups }: GridModelType, - column: RuntimeColumnDescriptor -) { - if (columnGroups) { - for (let i = 0; i < columnGroups.length; i++) { - if (columnGroups[i].columns.some(({ key }) => key === column.key)) { - return i; - } - } - } - return -1; -} - -const cloneColumn = ( - column: RuntimeColumnDescriptor, - { locked }: { locked?: boolean } -) => { - return { ...column, locked }; -}; - -export const ColumnGroup = { - insertColumnAt: ( - columnGroup: ColumnGroupType, - column: RuntimeColumnDescriptor, - idx: number - ) => { - const columns = columnGroup.columns.slice(); - columns.splice(idx, 0, cloneColumn(column, columnGroup)); - return columns; - }, - moveColumnTo: ( - columnGroup: ColumnGroupType, - column: RuntimeColumnDescriptor, - idx: number - ) => { - const sourceIdx = columnGroup.columns.findIndex( - (col) => col.key === column.key - ); - const columns = columnGroup.columns.slice(); - if (sourceIdx < idx) { - columns.splice(idx, 0, column); - columns.splice(sourceIdx, 1); - } else { - columns.splice(sourceIdx, 1); - columns.splice(idx, 0, column); - } - return columns; - }, -}; - -export const measureColumns = (gridModel: GridModelType, left: number) => { - if (gridModel.columnGroups === undefined) { - throw Error( - "gridModelUtils cannot measure columns, gridModel has no columnGroups" - ); - } - let position = left; - const lastGroup = gridModel.columnGroups.length - 1; - return gridModel.columnGroups.map((columnGroup, groupIdx) => - columnGroup.columns.reduce((sizes, column, i, columns) => { - sizes.push(position); - position += column.width; - if (groupIdx === lastGroup && i === columns.length - 1) { - sizes.push(position); - } - return sizes; - }, []) - ); -}; - -export const getColumnGroupColumnIdx = ( - { columnGroups }: GridModelType, - idx: number -) => { - if (columnGroups) { - let relativeIdx = idx; - const lastGroup = columnGroups.length - 1; - for (let i = 0; i <= lastGroup; i++) { - const { columns } = columnGroups[i]; - if (relativeIdx < columns.length) { - break; - } else if (i === lastGroup && relativeIdx === columns.length) { - break; - } - relativeIdx -= columns.length; - } - return relativeIdx; - } else { - return -1; - } -}; - -export const getColumnGroupOffset = ( - { columnGroups }: GridModelType, - columnGroupIdx: number -) => { - if (columnGroups) { - let offset = 0; - for (let i = 0; i < columnGroupIdx; i++) { - offset += columnGroups[i].width; - } - return offset; - } else { - return -1; - } -}; - -export const getColumnOffset = ( - gridModel: GridModelType, - columnGroupIdx: number, - columnIdx: number -) => { - if (gridModel.columnGroups) { - let offset = getColumnGroupOffset(gridModel, columnGroupIdx); - const cols = gridModel.columnGroups[columnGroupIdx].columns; - for (let i = 0; i < columnIdx; i++) { - offset += cols[i].width; - } - return offset; - } else { - return -1; - } -}; - -function updateGroupColumnWidth( - state: GridModelType, - columnName: string, - width: number -): ColumnGroupType[] { - if (state.columnSizing === "fill") { - return updateGroupFillColumnWidth(state, columnName, width); - } - - const [columnGroups, groupIdx] = GridModel.updateGroupColumn( - state, - columnName, - { - width, - } - ); - const updatedGroup = columnGroups[groupIdx]; - updateColumnHeading(updatedGroup); - const resizedColumn = updatedGroup.columns.find( - (col) => col.name === columnName - ) as RuntimeColumnDescriptor; - const widthAdjustment = width - resizedColumn.width; - - // why isn't this done already ? - updatedGroup.contentWidth += widthAdjustment; - - if (updatedGroup.locked) { - updatedGroup.width += widthAdjustment; - for (let i = groupIdx + 1; i < columnGroups.length; i++) { - const { locked, width } = columnGroups[i]; - columnGroups[i] = { - ...columnGroups[i], - width: locked ? width : width - widthAdjustment, - }; - } - } - return columnGroups; -} - -/** - * Column Sizing mode === 'fill' - * if we are resizing a fill column and there are other fill columns to our right - * 1) adjust the width of these fill columns according to their flex values - * 2) adjust the flex of resized column, distribute diff to the flex columns to right - * if we are resizing and there are other fill columns, but none to our right - * 1) adjust the width of all other fill columns according to their flex values - * 2) adjust the flex of resized column, distribute diff to the other flex columns - * if we are resizing a non-flex column - * 1) adjust the width of all other fill columns according to their flex values - * if we try to adjust the width of a flex column and it is the only flex column - * disallow the resize - */ -function updateGroupFillColumnWidth( - state: GridModelType, - columnName: string, - width: number -): ColumnGroupType[] { - const { columnGroups } = state; - if (columnGroups === undefined) { - throw Error("updateGroupFillColumnWidth GridModel has no ColumnGroup"); - } - const columns = columnGroups.flatMap( - (columnGroup: ColumnGroupType) => columnGroup.columns - ); - const resizedColumn = columns?.find((col) => col.name === columnName); - if (resizedColumn === undefined) { - throw Error("updateGroupFillColumnWidth column to be resized not found"); - } - const columnIndex = columns.indexOf(resizedColumn); - const affectedColumn = columns[columnIndex + 1]; - const widthDiff = resizedColumn.width - width; - - const applyChanges = (columnGroup: ColumnGroupType) => { - if ( - columnGroup.columns.some( - (column) => - column.name === resizedColumn.name || - column.name === affectedColumn.name - ) - ) { - return { - ...columnGroup, - columns: columnGroup.columns.map((column) => { - if (column.name === resizedColumn.name) { - return { - ...resizedColumn, - width, - }; - } else if (column.name === affectedColumn.name) { - return { - ...affectedColumn, - width: affectedColumn.width + widthDiff, - }; - } else { - return column; - } - }), - }; - } else { - return columnGroup; - } - }; - - return columnGroups.map(applyChanges); -} - -function updateColumnHeading(columnGroup: ColumnGroupType) { - if (columnGroup.headings) { - const columns = columnGroup.columns; - columnGroup.headings = columnGroup.headings.map((heading) => - heading.map((colHeading) => { - const indices = columnKeysToIndices(splitKeys(colHeading.key), columns); - const colWidth = indices.reduce( - (sum, idx) => sum + columns[idx].width, - 0 - ); - return colWidth === colHeading.width - ? colHeading - : { ...colHeading, width: colWidth }; - }) - ); - } -} - -function updateGroupColumn( - { columnGroups }: GridModelType, - columnName: string, - updates: { - resizing?: boolean; - flex?: number; - width?: number; - } -): [ColumnGroupType[], number] { - if (columnGroups === undefined) { - throw Error("GridModel updateGroupColumn, no columnGroups"); - } - const { groupIdx: idx, groupColIdx: colIdx } = getColumnPosition( - columnGroups, - columnName - ); - const { columns, ...rest } = columnGroups[idx]; - const updatedGroups = columnGroups.map((group, i) => - i === idx - ? { - ...rest, - columns: columns.map((col, i) => - i === colIdx ? { ...col, ...updates } : col - ), - } - : group - ); - return [updatedGroups, idx]; -} - -export const columnKeysToIndices = ( - keys: number[], - columns: RuntimeColumnDescriptor[] -) => keys.map((key) => columns.findIndex((c) => c.key === key)); - -function addGroupColumn( - { groupBy }: { groupBy?: VuuGroupBy }, - column: RuntimeColumnDescriptor -) { - if (groupBy) { - return groupBy.concat(column.name); - } else { - return [column.name]; - } -} - -function addSortColumn( - { sort }: GridModelType, - { name: columnName }: { name: string }, - sortType: "A" | "D" = "A" -): VuuSort { - const sortEntry: VuuSortCol = { column: columnName, sortType }; - if (sort) { - return { - sortDefs: sort.sortDefs.concat(sortEntry), - }; - } else { - return { sortDefs: [sortEntry] }; - } -} - -function setSortColumn( - gridModel: GridModelType, - column: RuntimeColumnDescriptor, - sortType?: "A" | "D" -): VuuSort { - if (sortType === undefined) { - const columnSort = gridModel.sort?.sortDefs.find( - (item) => item.column === column.name - ); - if (columnSort) { - return { - sortDefs: [ - { - column: column.name, - sortType: columnSort.sortType === "A" ? "D" : "A", - }, - ], - }; - } - } - return { sortDefs: [{ column: column.name, sortType: sortType ?? "A" }] }; -} - -function removeGroupColumn( - { groupBy }: { groupBy?: VuuGroupBy }, - column: RuntimeColumnDescriptor -): VuuGroupBy | undefined { - if (Array.isArray(groupBy)) { - if (groupBy.length === 1) { - return undefined; - } else { - return groupBy.filter((columnName) => columnName !== column.name); - } - } else { - throw Error( - `GridModel.removeColumnGroups: cannot remove column ${column.name}, no grouping in place` - ); - } -} - -const omitSystemColumns = (column: RuntimeColumnDescriptor) => - !column.isSystemColumn; - -const addColumnToColumns = ( - column: RuntimeColumnDescriptor, - columns: RuntimeColumnDescriptor[], - index: number -) => { - const currentIndex = columns.findIndex((col) => col.name === column.name); - if (currentIndex === index) { - return columns; - } else { - const newColumns: RuntimeColumnDescriptor[] = - currentIndex !== -1 - ? columns.filter((_, i) => i !== currentIndex) - : columns.slice(); - newColumns.splice(index, 0, column); - return newColumns; - } -}; - -const countLeadingSystemColumns = (columns: RuntimeColumnDescriptor[]) => { - let count = 0; - for (let i = 0; i < columns.length; i++) { - if (!columns[i].isSystemColumn) { - break; - } else { - count += 1; - } - } - return count; -}; - -const setAggregation = ( - { aggregations }: GridModelType, - column: RuntimeColumnDescriptor, - aggType: VuuAggType -) => { - return aggregations - .filter((agg) => agg.column !== column.name) - .concat({ column: column.name, aggType }); -}; - -export const GridModel = { - addColumnToColumns, - addGroupColumn, - addSortColumn, - countLeadingSystemColumns, - columns: ({ columnGroups }: GridModelType) => - columnGroups - ? flattenColumnGroup( - columnGroups.flatMap((columnGroup) => - columnGroup.columns.filter(omitSystemColumns) - ) - ) - : [], - columnNames: (gridModel: GridModelType) => - GridModel.columns(gridModel).map((column) => column.name), - removeGroupColumn, - setAggregation, - setSortColumn, - updateGroupColumn, - updateGroupColumnWidth, -}; - -function getColumnPosition(groups: ColumnGroupType[], columnName: string) { - for (let i = 0; i < groups.length; i++) { - const idx = groups[i].columns.findIndex((c) => c.name === columnName); - if (idx !== -1) { - return { groupIdx: i, groupColIdx: idx }; - } - } - return { groupIdx: -1, groupColIdx: -1 }; -} - -export type GroupState = { - "*"?: boolean | GroupState; -}; -export function expandStatesfromGroupState( - { columns }: GroupColumnDescriptor, - groupState?: GroupState -) { - const results = Array(columns.length).fill(-1); - let all: GroupState | boolean | undefined = groupState && groupState["*"]; - const idx = 0; - while (all) { - results[idx] = 1; - all = typeof all === "object" ? all["*"] : undefined; - } - return results; -} - -const flattenColumnGroup = (columns: RuntimeColumnDescriptor[]) => { - if (columns.length === 0 || !columns[0].isGroup) { - return columns; - } - - const [groupColumn, ...nonGroupColumns] = columns as [ - GroupColumnDescriptor, - ...RuntimeColumnDescriptor[] - ]; - // traverse the group columns in reverse, but do not reverse (mutate) the original array - for (let i = groupColumn.columns.length - 1; i >= 0; i--) { - const column = groupColumn.columns[i]; - const { originalIdx = -1, ...nonGroupedColumn } = column; - if (originalIdx !== -1) { - nonGroupColumns.splice(originalIdx, 0, nonGroupedColumn); - } - } - - return nonGroupColumns; -}; - -export function extractGroupColumn( - columns: RuntimeColumnDescriptor[], - groupBy?: VuuGroupBy -): [GroupColumnDescriptor | null, RuntimeColumnDescriptor[]] { - if (groupBy && groupBy.length > 0) { - // Note: groupedColumns will be in column order, not groupBy order - const [groupedColumns, rest] = columns.reduce( - (result, column, i) => { - const [g, r] = result; - if (groupBy.includes(column.name)) { - g.push({ - ...column, - originalIdx: i, - }); - } else { - r.push(column); - } - - return result; - }, - [[], []] as [RuntimeColumnDescriptor[], RuntimeColumnDescriptor[]] - ); - if (groupedColumns.length !== groupBy.length) { - throw Error( - `extractGroupColumn: no column definition found for all groupBy cols ${JSON.stringify( - groupBy - )} ` - ); - } - const groupCount = groupBy.length; - const groupCols: RuntimeColumnDescriptor[] = groupBy.map((name, idx) => { - // Keep the cols in same order defined on groupBy - const column = groupedColumns.find( - (col) => col.name === name - ) as RuntimeColumnDescriptor; - return { - ...column, - groupLevel: groupCount - idx, - }; - }); - - const groupCol = { - key: -1, - name: "group-col", - heading: ["group-col"], - isGroup: true, - columns: groupCols, - width: groupCols.map((c) => c.width).reduce((a, b) => a + b) + 100, - } as GroupColumnDescriptor; - - return [groupCol, rest]; - } - return [null, columns]; -} - -export const splitKeys = (compositeKey: string): number[] => - `${compositeKey}`.split(":").map((k) => parseInt(k, 10)); - -const isKeyedColumn = (column: unknown): column is RuntimeColumnDescriptor => - typeof (column as RuntimeColumnDescriptor).key === "number"; - -export const assignKeysToColumns = ( - columns: (ColumnDescriptor | RuntimeColumnDescriptor | string)[], - defaultWidth: number -): RuntimeColumnDescriptor[] => { - const start = metadataKeys.count; - return columns.map((column, i) => - typeof column === "string" - ? { - name: column, - key: start + i, - label: column, - width: defaultWidth, - valueFormatter: undefined, - } - : isKeyedColumn(column) - ? column - : { - ...column, - label: column.label ?? column.name, - key: start + i, - width: column.width || defaultWidth, - valueFormatter: undefined, - } - ); -}; - -const { DEPTH, IS_LEAF } = metadataKeys; - -export const getGroupValueAndOffset = ( - columns: RuntimeColumnDescriptor[], - row: DataRow -): [unknown, number | null] => { - const { [DEPTH]: depth, [IS_LEAF]: isLeaf } = row; - // Depth can be greater tha group columns when we have just removed a column from groupby - // but new data has not yet been received. - if (isLeaf || depth > columns.length) { - return [null, null]; - } else if (depth === 0) { - return ["$root", 0]; - } else { - // offset 1 for now to allow for $root - const column = columns[depth - 1]; - return [row[column.key], depth]; - } -}; diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-model/index.ts b/vuu-ui/packages/vuu-datagrid/src/grid-model/index.ts deleted file mode 100644 index ffd44da37..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-model/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from "./GridModelReducer"; -export * from "./gridModelActions"; -export * from "./gridModelTypes"; -export * from "./gridModelUtils"; -export * from "./useGridModel"; diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-model/useGridModel.ts b/vuu-ui/packages/vuu-datagrid/src/grid-model/useGridModel.ts deleted file mode 100644 index 61eb033ab..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-model/useGridModel.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { useEffect, useReducer, useRef, useState } from "react"; -import { useAdornments } from "../grid-adornments"; -import { useEffectSkipFirst } from "../utils"; -import { ROW_HEIGHT } from "./gridModelActions"; -import { - GridModelReducer, - gridModelReducer, - initModel, -} from "./GridModelReducer"; -import { - GridModelHookProps, - GridModelHookResult, - GridModelReducerInitializerTuple, -} from "./gridModelTypes"; -import { isMeasured, useMeasuredSize } from "./useMeasuredSize"; - -export const useGridModel = ({ - children, - dataSource: dataSourceProp, - style, - height, - width, - ...props -}: GridModelHookProps): GridModelHookResult => { - const rootRef = useRef(null); - const firstRender = useRef(true); - const [dataSource, setDataSource] = useState(dataSourceProp); - const custom = useAdornments(children); - const size = useMeasuredSize(rootRef, height, width); - const [gridModel, dispatchGridModel] = useReducer< - GridModelReducer, - GridModelReducerInitializerTuple - >(gridModelReducer, [props, size, custom], initModel); - - useEffect(() => { - if (firstRender.current && rootRef.current) { - if (typeof props.rowHeight === "number") { - dispatchGridModel({ type: ROW_HEIGHT, rowHeight: props.rowHeight }); - } else { - const rowHeight = parseInt( - getComputedStyle(rootRef.current).getPropertyValue( - "--grid-row-height" - ) - ); - if (!isNaN(rowHeight) && rowHeight !== gridModel.rowHeight) { - dispatchGridModel({ type: ROW_HEIGHT, rowHeight }); - } - } - firstRender.current = false; - } - }, [props.rowHeight, gridModel.rowHeight]); - - useEffect(() => { - if (isMeasured(size)) { - dispatchGridModel({ - size, - type: "resize", - }); - } - }, [size]); - - //TODO do we need to useCallback here - can we ever send stale props ? - useEffectSkipFirst(() => { - // onsole.log(`dispatchGridModel initialize`) - // This is not correct. We will lose modifications applies to gridModel since initial load - // eg sort, groupBy - dispatchGridModel({ type: "initialize", props, size }); - if (dataSourceProp !== dataSource) { - dataSource.unsubscribe(); - setDataSource(dataSourceProp); - } - }, [props.columns, props.columnSizing, dataSourceProp, props.groupBy]); - - return [rootRef, gridModel, dataSource, dispatchGridModel, custom]; -}; diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-model/useMeasuredSize.ts b/vuu-ui/packages/vuu-datagrid/src/grid-model/useMeasuredSize.ts deleted file mode 100644 index efa00535f..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-model/useMeasuredSize.ts +++ /dev/null @@ -1,59 +0,0 @@ -import { RefObject, useCallback, useState } from "react"; -import { useResizeObserver, ResizeHandler } from "../utils"; - -const FullAndClientWidthHeight = ["clientHeight", "clientWidth"]; - -export type Size = { - clientHeight?: number; - clientWidth?: number; - height?: number; - width?: number; -}; - -export type MeasuredSize = { - clientHeight: number; - clientWidth: number; - height: number; - width: number; -}; - -export const isMeasured = (size: Size | MeasuredSize): size is MeasuredSize => - typeof size.clientHeight === "number" && typeof size.clientWidth === "number"; - -export const useMeasuredSize = ( - containerRef: RefObject, - height?: number, - width?: number -): Size => { - const [size, setSize] = useState({ height, width }); - const onResize: ResizeHandler = useCallback( - ({ - clientWidth, - clientHeight, - }: { - clientWidth?: number; - clientHeight?: number; - }) => { - console.log(`onResize ${clientHeight}`); - // Note: we know here that these values will be returned as numbers, we can enforce - // this by typing useResizeObserver with generics - setSize((currentSize) => - typeof clientHeight === "number" && - typeof clientWidth === "number" && - (clientWidth !== currentSize.clientWidth || - clientHeight !== currentSize.clientHeight) - ? { - ...currentSize, - clientWidth: Math.floor(clientWidth), - clientHeight: Math.floor(clientHeight), - } - : currentSize - ); - }, - [setSize] - ); - - useResizeObserver(containerRef, FullAndClientWidthHeight, onResize, true); - - return size; -}; diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-row.css b/vuu-ui/packages/vuu-datagrid/src/grid-row.css deleted file mode 100644 index 95dc5b258..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-row.css +++ /dev/null @@ -1,37 +0,0 @@ -.vuuDataGridRow { - background: var(--row-background); - box-sizing: border-box; - height: var(--grid-row-height); - left: 0; - line-height: var(--grid-row-line-height); - outline: 0; - position: absolute; - top: 0; - white-space: nowrap; - width: 100%; -} - -.vuuDataGridRow-even { - --row-background: var(--salt-container-secondary-background); -} - -.vuuDataGridRow:not(.vuuDataGridRow-even) { - --row-background: var(--hwDataGridRow-background-odd, inherit); -} - -.vuuDataGridRow .group .vuuDataGridCell:first-child { - padding: 0 6px 0 3px; -} - -.vuuDataGridRow[aria-selected='true'] { - background-color: var(--grid-row-background-selected); - --cell-border-top-color: var(--salt-selectable-borderColor-selected); -} - -.vuuDataGridRow-lastSelected { - --cell-border-bottom-color: var(--salt-selectable-borderColor-selected); -} - -.vuuDataGridRow.expanded { - --row-toggle-icon-transform: rotate(90deg); -} diff --git a/vuu-ui/packages/vuu-datagrid/src/grid-row.tsx b/vuu-ui/packages/vuu-datagrid/src/grid-row.tsx deleted file mode 100644 index 757d1b921..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/grid-row.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import { HTMLAttributes, memo, useCallback } from "react"; -import cx from "classnames"; -import { - ColumnMap, - DataRow, - isGroupColumn, - metadataKeys, -} from "@finos/vuu-utils"; -import { GridCell, GroupCell } from "./grid-cells"; - -import "./grid-row.css"; -import { RuntimeColumnDescriptor } from "@finos/vuu-datagrid-types"; - -const classBase = "vuuDataGridRow"; - -const { KEY, SELECTED, IS_LEAF, IS_EXPANDED } = metadataKeys; - -export interface RowProps - extends Omit, "onClick"> { - columnMap: ColumnMap; - columns: RuntimeColumnDescriptor[]; - height: number; - idx: number; - onClick: ( - idx: number, - row: DataRow, - rangeSelect: boolean, - keepExistingSelection: boolean - ) => void; - row: DataRow; -} - -const Row = memo(function Row({ - columnMap, - columns, - height, - idx, - row, - onClick, -}: RowProps) { - const { [IS_LEAF]: isLeaf, [IS_EXPANDED]: expanded } = row; - const isEmptyRow = row[KEY] === undefined; - const isGroup = !isEmptyRow && !isLeaf; - const isLastSelected = row[SELECTED] === 2; - const isSelected = isLastSelected || row[SELECTED] === 1; - - const className = cx(classBase, { - group: isGroup, - collapsed: !isLeaf && !expanded, - expanded, - empty: isEmptyRow, - [`${classBase}-even`]: idx % 2 === 0, - [`${classBase}-lastSelected`]: isLastSelected, - }); - - const handleClick = useCallback( - (e) => { - const rangeSelect = e.shiftKey; - const keepExistingSelection = e.ctrlKey || e.metaKey; /* mac only */ - onClick(idx, row, rangeSelect, keepExistingSelection); - }, - [idx, onClick, row] - ); - - return ( -
- {columns.map((column) => - isGroupColumn(column) ? ( - - ) : ( - - ) - )} -
- ); -}); - -export default Row; diff --git a/vuu-ui/packages/vuu-datagrid/src/gridTypes.ts b/vuu-ui/packages/vuu-datagrid/src/gridTypes.ts deleted file mode 100644 index 746014964..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/gridTypes.ts +++ /dev/null @@ -1,96 +0,0 @@ -import { ConfigChangeHandler, DataSource } from "@finos/vuu-data"; -import { DataSourceFilter } from "@finos/vuu-data-types"; -import { - ColumnDescriptor, - RuntimeColumnDescriptor, -} from "@finos/vuu-datagrid-types"; -import { - VuuAggregation, - VuuGroupBy, - VuuRange, - VuuSort, -} from "@finos/vuu-protocol-types"; -import { HTMLAttributes } from "react"; -import { AdornmentsDescriptor } from "./grid-adornments"; -import { GridModelType } from "./grid-model/gridModelTypes"; - -export type dragPhase = "drag-start" | "drag" | "drag-end"; -export type resizePhase = "begin" | "resize" | "end"; - -export type ColumnDragState = { - column: RuntimeColumnDescriptor; - columnGroupIdx: number; - columnIdx: number; - initialColumnPosition: number; - columnPositions: number[][]; - mousePosition: number; -}; - -export type ColumnDragStartHandler = ( - phase: dragPhase, - columnGroupIdx: number, - column: unknown, - columnPosition: number, - mousePosition: number -) => void; - -export type RowClickHandler = (row: HTMLElement) => void; - -export interface GridProps extends HTMLAttributes { - aggregations?: VuuAggregation[]; - cellSelectionModel?: "none"; - columns: ColumnDescriptor[]; - columnSizing?: "fill" | "static"; - dataSource: DataSource; - defaultColumnWidth?: number; - filter?: DataSourceFilter; - groupBy?: VuuGroupBy; - /** - * Set height for column headers. If not provided, row height will be determined - * by CSS. With default styles, this will vary by density, 24px in High Density - * mode. - */ - headerHeight?: number; - /** - * Height of the Grid. Must be a pixel value. If not supplied, Grid will fill 100% of - * container height - */ - height?: number; - /** - * The minimum width resizeable columns can be reduced to. If not provided, the default will be 30. - */ - minColumnWidth?: number; - noColumnHeaders?: boolean; - onConfigChange?: ConfigChangeHandler; - onRowClick?: RowClickHandler; - renderBufferSize?: number; - /** - * Set row height. If not provided, row height will be determined by CSS, With - * default styles, this will vary by density, 20px in High Density mode. - */ - rowHeight?: number; - selectionModel?: "none" | "single" | "checkbox" | "extended"; // there are others - showLineNumbers?: boolean; - sort?: VuuSort; - /** - * Width of the Grid. Must be a pixel value. If not supplied, Grid will fill 100% of - * container widths - */ - width?: number; -} - -export interface ViewportProps { - columnDragData?: ColumnDragState; - custom: AdornmentsDescriptor; - dataSource: DataSource; - gridModel: GridModelType; - onChangeRange: (range: VuuRange) => void; - onColumnDrop?: ( - phase: dragPhase, - column: RuntimeColumnDescriptor, - index: number - ) => void; - onColumnDragStart?: ColumnDragStartHandler; - onConfigChange?: ConfigChangeHandler; - onRowClick?: RowClickHandler; -} diff --git a/vuu-ui/packages/vuu-datagrid/src/index.ts b/vuu-ui/packages/vuu-datagrid/src/index.ts deleted file mode 100644 index 893567252..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -export * from "./DataGrid"; -export * from "./grid-context"; -export * from "./grid-model"; -export { default as ColumnGroupContext } from "./column-group-context"; -export { default as ComponentContext } from "./component-context"; -export * from "./grid-cells"; -export { default as Measure } from "./measure"; -export * from "./measure"; diff --git a/vuu-ui/packages/vuu-datagrid/src/measure.jsx b/vuu-ui/packages/vuu-datagrid/src/measure.jsx deleted file mode 100644 index a9454a80a..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/measure.jsx +++ /dev/null @@ -1,34 +0,0 @@ -// TODO deal with percentage values -import React, { useLayoutEffect, useRef, useState } from 'react'; - -const size = (value) => - value === null || value === undefined || value === 'auto' ? '100%' : value; - -export const useMeasure = (props) => { - return useState({ - height: size(props.style?.height ?? props.height), - measuredHeight: null, - width: size(props.style?.width ?? props.width), - measuredWidth: null - }); -}; - -// TODO need to listen for resize events if size is auto in any direction -const Measure = ({ height, width, onMeasure }) => { - const el = useRef(null); - const [{ h, w }, setSize] = useState({ h: height, w: width }); - useLayoutEffect(() => { - console.log(`Grid Measure Size`); - const { height: measuredHeight, width: measuredWidth } = el.current.getBoundingClientRect(); - if (measuredHeight === 0) { - const bodyHeight = document.body.clientHeight; - setSize({ h: `calc(100vh - ${bodyHeight}px)`, w }); - } else { - console.log({ measuredHeight, measuredWidth }); - onMeasure({ height: measuredHeight, width: measuredWidth }); - } - }, [h, w, onMeasure]); - return
; -}; - -export default Measure; diff --git a/vuu-ui/packages/vuu-datagrid/src/prop-helper/GridPropHelper.jsx b/vuu-ui/packages/vuu-datagrid/src/prop-helper/GridPropHelper.jsx deleted file mode 100644 index c77d585dd..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/prop-helper/GridPropHelper.jsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react'; - -const GridPropHelper = (props) => { - return ( -
- Looks like we are missing a few required props here -
- ); -}; - -export default GridPropHelper; diff --git a/vuu-ui/packages/vuu-datagrid/src/prop-helper/index.jsx b/vuu-ui/packages/vuu-datagrid/src/prop-helper/index.jsx deleted file mode 100644 index fe531aace..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/prop-helper/index.jsx +++ /dev/null @@ -1,2 +0,0 @@ -// We really want to lazy load thius but modular doesn't support it -export { default as PropHelper } from './GridPropHelper'; diff --git a/vuu-ui/packages/vuu-datagrid/src/standard-renderers.tsx b/vuu-ui/packages/vuu-datagrid/src/standard-renderers.tsx deleted file mode 100644 index f53947ed4..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/standard-renderers.tsx +++ /dev/null @@ -1,11 +0,0 @@ -import BackgroundCell from './cell-renderers/background-cell'; -import CheckboxCell from './cell-renderers/checkbox-cell'; -import ProgressCell from './cell-renderers/progress-cell'; - -const renderers = { - background: BackgroundCell, - progress: ProgressCell, - 'checkbox-cell': CheckboxCell -}; - -export default renderers; diff --git a/vuu-ui/packages/vuu-datagrid/src/use-drag.js b/vuu-ui/packages/vuu-datagrid/src/use-drag.js deleted file mode 100644 index b4d899f82..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/use-drag.js +++ /dev/null @@ -1,144 +0,0 @@ -import { useCallback, useRef, useEffect } from 'react'; - -const DRAG_THRESHOLD = 3; - -export const DRAG_START = 1; -export const DRAG = 4; -export const DRAG_PAUSE = 8; -export const DRAG_END = 2; - -const DRAG_DEFAULT = DRAG_START + DRAG + DRAG_END; - -export function useDragStart(callback) { - return useDrag(callback, DRAG_START); -} - -/** @type {DragHook} */ -export default function useDrag(callback, dragPhase = DRAG_DEFAULT, initialDragPosition = -1) { - // Note: If user is not tracking 'drag-start', it's assumed that we're already dragging - - let cleanUp; - const disabled = useRef(false); - const dragging = useRef(false); - const position = useRef({ x: initialDragPosition, y: -1 }); - const onMouseMove = useRef(null); - const onMouseUp = useRef(null); - const timeoutHandle = useRef(null); - - onMouseUp.current = useCallback(() => { - if (dragging.current) { - callback('drag-end'); - } - cleanUp(); - }, [callback, cleanUp]); - - const pauseListener = useCallback(() => { - callback('drag-pause'); - }, [callback]); - - onMouseMove.current = useCallback( - (e) => { - if (e.stopPropagation) { - e.stopPropagation(); - } - - if (e.preventDefault) { - e.preventDefault(); - } - const x = e.clientX; - const y = e.clientY; - const deltaX = x - position.current.x; - - if (dragging.current) { - position.current.x = x; - position.current.y = y; - callback('drag', deltaX, position.current.x); - } else if (dragPhase & DRAG_START) { - if (Math.abs(deltaX) > DRAG_THRESHOLD) { - dragging.current = true; - position.current.x = x; - position.current.y = y; - - callback('drag-start', deltaX, position.current.x); - if (dragPhase === DRAG_START) { - cleanUp(); - } - } - } else { - // if we are tracking drag only, we're going to miss the first drag callback as we have to - // establish our start point before we can begin to derive deltas. - dragging.current = true; - position.current.x = x; - position.current.y = y; - } - - if (dragPhase & DRAG_PAUSE) { - if (timeoutHandle.current) { - clearTimeout(timeoutHandle.current); - timeoutHandle.current = null; - } - - timeoutHandle.current = setTimeout(pauseListener, 300); - } - }, - [callback, cleanUp, dragPhase, pauseListener] - ); - - // Important that these never change for the lifetime of the hook, as they are - // used to register and register window listeners. - const mouseMoveHandler = useCallback((e) => onMouseMove.current(e), []); - const mouseUpHandler = useCallback((e) => onMouseUp.current(e), []); - - function leftMouseButton(e) { - if ('buttons' in e) { - return e.buttons == 1; - } - var button = e.which || e.button; - return button == 1; - } - const handleMouseDown = useCallback( - (e) => { - if (leftMouseButton(e)) { - position.current = { x: e.clientX, y: e.clientY }; - window.addEventListener('mouseup', mouseUpHandler); - window.addEventListener('mousemove', mouseMoveHandler); - } - }, - [mouseMoveHandler, mouseUpHandler] - ); - - useEffect(() => { - // We don't normally expect the callback to change during the lifetime of a drag operation. - // Because the drag takes immediate effect if drag-start is not being monitored, we provide - // a way to disable drag under clients control, in case callback does change under - // circumstances that should not trigger immediate drag monitoring. - if (!(dragPhase & DRAG_START)) { - if (dragPhase & DRAG && !dragging.current && !disabled.current) { - window.addEventListener('mousemove', mouseMoveHandler); - - if (dragPhase & DRAG_END) { - window.addEventListener('mouseup', mouseUpHandler); - } - dragging.current = true; - } - if (dragPhase & DRAG_END && !dragging.current && !disabled.current) { - window.addEventListener('mouseup', mouseUpHandler); - dragging.current = true; - } - } - }, [callback, dragPhase, mouseMoveHandler, mouseUpHandler]); - - // TODO extend cleanup to rest references, but careful of order of operations in handlers - cleanUp = useCallback(() => { - window.removeEventListener('mouseup', mouseUpHandler); - window.removeEventListener('mousemove', mouseMoveHandler); - dragging.current = false; - }, [mouseMoveHandler, mouseUpHandler]); - - const disable = useCallback(() => { - cleanUp(); - disabled.current = true; - }, [cleanUp]); - - return [handleMouseDown, disable]; -} diff --git a/vuu-ui/packages/vuu-datagrid/src/use-row-height.ts b/vuu-ui/packages/vuu-datagrid/src/use-row-height.ts deleted file mode 100644 index 6cc2bc240..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/use-row-height.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { useCallback, useRef } from "react"; -import { useResizeObserver } from "./utils"; -import { ROW_HEIGHT } from "./grid-model/gridModelActions"; -import { useGridContext } from "./grid-context"; - -const dimensions = ["height"]; - -export const useRowHeight = () => { - const { dispatchGridModelAction } = useGridContext(); - const ref = useRef(null); - - const onResize = useCallback( - ({ height }) => { - dispatchGridModelAction?.({ type: ROW_HEIGHT, rowHeight: height }); - }, - [dispatchGridModelAction] - ); - - useResizeObserver(ref, dimensions, onResize); - - return ref; -}; diff --git a/vuu-ui/packages/vuu-datagrid/src/use-scroll.ts b/vuu-ui/packages/vuu-datagrid/src/use-scroll.ts deleted file mode 100644 index bbcd78823..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/use-scroll.ts +++ /dev/null @@ -1,49 +0,0 @@ -import { useCallback, useRef } from "react"; - -export type scrollPhase = "scroll" | "scroll-start" | "scroll-end"; - -export default function useScroll( - scrollPos: "scrollLeft" | "scrollTop", - callback: (scrollPhase: scrollPhase, scrollPos: number) => void, - scrollThreshold = 0 -) { - const timeoutHandle = useRef(null); - const pos = useRef(0); - const scrollHandlingSuspended = useRef(false); - const checkPos = useRef(0); - const onScrollEnd = useCallback(() => { - callback("scroll-end", pos.current); - timeoutHandle.current = null; - }, [callback]); - - const suspendScrollHandling = useCallback( - (suspended) => (scrollHandlingSuspended.current = suspended), - [] - ); - - const onScroll = useCallback( - (e) => { - // important for the horizontal scroll on Canvas - e.stopPropagation(); - if (!scrollHandlingSuspended.current) { - const scrollPosition = e.target[scrollPos]; - if (scrollPosition !== pos.current) { - pos.current = scrollPosition; - if (timeoutHandle.current === null) { - callback("scroll-start", scrollPosition); - } else { - clearTimeout(timeoutHandle.current); - } - if (Math.abs(scrollPosition - checkPos.current) > scrollThreshold) { - checkPos.current = scrollPosition; - callback("scroll", scrollPosition); - } - timeoutHandle.current = window.setTimeout(onScrollEnd, 100); - } - } - }, - [callback, onScrollEnd, scrollPos, scrollThreshold] - ); - - return [onScroll, suspendScrollHandling]; -} diff --git a/vuu-ui/packages/vuu-datagrid/src/use-update.ts b/vuu-ui/packages/vuu-datagrid/src/use-update.ts deleted file mode 100644 index fd8e59106..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/use-update.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { useLayoutEffect, useRef } from "react"; - -export default function useUpdate( - callback: () => void, - dependencies: unknown[] -) { - const initialRender = useRef(true); - - /* eslint-disable react-hooks/exhaustive-deps */ - useLayoutEffect(() => { - if (initialRender.current) { - initialRender.current = false; - } else { - callback(); - } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, dependencies); -} diff --git a/vuu-ui/packages/vuu-datagrid/src/utils/index.ts b/vuu-ui/packages/vuu-datagrid/src/utils/index.ts deleted file mode 100644 index 1fa3daf82..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/utils/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from "./useEffectSkipFirst"; -export * from "./useResizeObserver"; diff --git a/vuu-ui/packages/vuu-datagrid/src/utils/useEffectSkipFirst.ts b/vuu-ui/packages/vuu-datagrid/src/utils/useEffectSkipFirst.ts deleted file mode 100644 index 2f0fbdfb4..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/utils/useEffectSkipFirst.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { useEffect, useRef } from 'react'; - -export const useEffectSkipFirst = (func: (...args: unknown[]) => void, deps: unknown[]) => { - const goodToGo = useRef(false); - useEffect(() => { - if (goodToGo.current) { - func(); - } else { - goodToGo.current = true; - } - }, deps); -}; diff --git a/vuu-ui/packages/vuu-datagrid/src/utils/useResizeObserver.ts b/vuu-ui/packages/vuu-datagrid/src/utils/useResizeObserver.ts deleted file mode 100644 index 8022582c1..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/utils/useResizeObserver.ts +++ /dev/null @@ -1,183 +0,0 @@ -import { RefObject, useCallback, useEffect, useRef } from "react"; - -export const WidthHeight = ["height", "width"]; -export const WidthOnly = ["width"]; - -export type measurements = { - height?: T; - clientHeight?: number; - clientWidth?: number; - contentHeight?: number; - contentWidth?: number; - scrollHeight?: number; - scrollWidth?: number; - width?: T; -}; -type measuredDimension = keyof measurements; - -export type ResizeHandler = (measurements: measurements) => void; - -type observedDetails = { - onResize?: ResizeHandler; - measurements: measurements; -}; -const observedMap = new Map(); - -const getTargetSize = ( - element: HTMLElement, - size: { - height: number; - width: number; - contentHeight: number; - contentWidth: number; - }, - dimension: measuredDimension -): number => { - switch (dimension) { - case "height": - return size.height; - case "clientHeight": - return element.clientHeight; - case "clientWidth": - return element.clientWidth; - case "contentHeight": - return size.contentHeight; - case "contentWidth": - return size.contentWidth; - case "scrollHeight": - return Math.ceil(element.scrollHeight); - case "scrollWidth": - return Math.ceil(element.scrollWidth); - case "width": - return size.width; - default: - return 0; - } -}; - -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) { - const { target, borderBoxSize, contentBoxSize } = entry; - const observedTarget = observedMap.get(target as HTMLElement); - if (observedTarget) { - const [{ blockSize: height, inlineSize: width }] = borderBoxSize; - const [{ blockSize: contentHeight, inlineSize: contentWidth }] = - contentBoxSize; - const { onResize, measurements } = observedTarget; - let sizeChanged = false; - for (let [dimension, size] of Object.entries(measurements)) { - const newSize = getTargetSize( - target as HTMLElement, - { height, width, contentHeight, contentWidth }, - dimension as measuredDimension - ); - - if (newSize !== size) { - sizeChanged = true; - measurements[dimension as measuredDimension] = newSize; - } - } - if (sizeChanged) { - // TODO only return measured sizes - onResize && onResize(measurements); - } - } - } -}); - -// TODO use an optional lag (default to false) to ask to fire onResize -// with initial size -export function useResizeObserver( - ref: RefObject, - dimensions: string[], - onResize: ResizeHandler, - reportInitialSize = false -) { - const dimensionsRef = useRef(dimensions); - - const measure = useCallback((target: HTMLElement): measurements => { - const { width, height } = target.getBoundingClientRect(); - const { clientWidth: contentWidth, clientHeight: contentHeight } = target; - return dimensionsRef.current.reduce( - (map: { [key: string]: number }, dim) => { - map[dim] = getTargetSize( - target, - { width, height, contentHeight, contentWidth }, - dim as measuredDimension - ); - return map; - }, - {} - ); - }, []); - - // TODO use ref to store resizeHandler here - // resize handler registered with REsizeObserver will never change - // use ref to store user onResize callback here - // resizeHandler will call user callback.current - - // Keep this effect separate in case user inadvertently passes different - // dimensions or callback instance each time - we only ever want to - // initiate new observation when ref changes. - useEffect(() => { - const target = ref.current as HTMLElement; - async function registerObserver() { - // Create the map entry immediately. useEffect may fire below - // before fonts are ready and attempt to update entry - observedMap.set(target, { measurements: {} as measurements }); - await document.fonts.ready; - const observedTarget = observedMap.get(target); - if (observedTarget) { - const measurements = measure(target); - observedTarget.measurements = measurements; - resizeObserver.observe(target); - if (reportInitialSize) { - onResize(measurements); - } - } else { - console.log( - `%cuseResizeObserver an target expected to be under observation wa snot found. This warrants investigation`, - "font-weight:bold; color:red;" - ); - } - } - - if (target) { - // TODO might we want multiple callers to attach a listener to the same element ? - if (observedMap.has(target)) { - throw Error( - "useResizeObserver attemping to observe same element twice" - ); - } - // TODO set a pending entry on map - registerObserver(); - } - return () => { - if (target && observedMap.has(target)) { - resizeObserver.unobserve(target); - observedMap.delete(target); - } - }; - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [measure, ref]); - - useEffect(() => { - const target = ref.current as HTMLElement; - const record = observedMap.get(target); - if (record) { - if (dimensionsRef.current !== dimensions) { - dimensionsRef.current = dimensions; - const measurements = measure(target); - record.measurements = measurements; - } - // Might not have changed, but no harm ... - record.onResize = onResize; - } - }, [dimensions, measure, ref, onResize]); -} diff --git a/vuu-ui/packages/vuu-datagrid/src/vuu-messages/index.js b/vuu-ui/packages/vuu-datagrid/src/vuu-messages/index.js deleted file mode 100644 index 115c7b43a..000000000 --- a/vuu-ui/packages/vuu-datagrid/src/vuu-messages/index.js +++ /dev/null @@ -1,4 +0,0 @@ -export const RpcResp = 'RPC_RESP'; -export const VisualLinksResp = 'VP_VISUAL_LINKS_RESP'; -export const ViewPortMenusResp = 'VIEW_PORT_MENUS_RESP'; -export const ViewPortMenuResp = 'VIEW_PORT_MENU_RESP'; diff --git a/vuu-ui/packages/vuu-datagrid/tsconfig.json b/vuu-ui/packages/vuu-datagrid/tsconfig.json deleted file mode 100644 index db9582a16..000000000 --- a/vuu-ui/packages/vuu-datagrid/tsconfig.json +++ /dev/null @@ -1,6 +0,0 @@ -{ -"extends": "../../tsconfig.json", -"compilerOptions":{ - "composite": true -}, -} diff --git a/vuu-ui/packages/vuu-datatable/package.json b/vuu-ui/packages/vuu-datatable/package.json index 736175a7e..f2edaae4c 100644 --- a/vuu-ui/packages/vuu-datatable/package.json +++ b/vuu-ui/packages/vuu-datatable/package.json @@ -10,7 +10,7 @@ }, "dependencies": { "@finos/vuu-data": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26", + "@finos/vuu-table-types": "0.0.26", "@finos/vuu-filters": "0.0.26", "@finos/vuu-layout": "0.0.26", "@finos/vuu-popups": "0.0.26", diff --git a/vuu-ui/packages/vuu-datatable/src/json-table/JsonTable.tsx b/vuu-ui/packages/vuu-datatable/src/json-table/JsonTable.tsx index c25049cd5..4a59bf2b4 100644 --- a/vuu-ui/packages/vuu-datatable/src/json-table/JsonTable.tsx +++ b/vuu-ui/packages/vuu-datatable/src/json-table/JsonTable.tsx @@ -3,7 +3,7 @@ import { JsonData } from "@finos/vuu-utils"; import { Table } from "@finos/vuu-table"; import { JsonDataSource } from "@finos/vuu-data"; import { useEffect, useMemo, useRef } from "react"; -import { TableConfig } from "@finos/vuu-datagrid-types"; +import { TableConfig } from "@finos/vuu-table-types"; export interface JsonTableProps extends Omit { diff --git a/vuu-ui/packages/vuu-filters/package.json b/vuu-ui/packages/vuu-filters/package.json index df7173354..e7e0ab976 100644 --- a/vuu-ui/packages/vuu-filters/package.json +++ b/vuu-ui/packages/vuu-filters/package.json @@ -11,7 +11,7 @@ }, "devDependencies": { "@finos/vuu-data-types": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26", + "@finos/vuu-table-types": "0.0.26", "@finos/vuu-filter-types": "0.0.26", "@types/uuid": "^9.0.2" }, diff --git a/vuu-ui/packages/vuu-filters/src/filter-clause/FilterClauseEditor.tsx b/vuu-ui/packages/vuu-filters/src/filter-clause/FilterClauseEditor.tsx index 55dc9cbed..cee99e55e 100644 --- a/vuu-ui/packages/vuu-filters/src/filter-clause/FilterClauseEditor.tsx +++ b/vuu-ui/packages/vuu-filters/src/filter-clause/FilterClauseEditor.tsx @@ -1,6 +1,6 @@ import { TableSchema } from "@finos/vuu-data"; import { SuggestionFetcher } from "@finos/vuu-data-react"; -import { ColumnDescriptor } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor } from "@finos/vuu-table-types"; import { FilterClause } from "@finos/vuu-filter-types"; import cx from "classnames"; import { HTMLAttributes, useCallback } from "react"; diff --git a/vuu-ui/packages/vuu-filters/src/filter-clause/filterClauseTypes.ts b/vuu-ui/packages/vuu-filters/src/filter-clause/filterClauseTypes.ts index d7621d31f..0eff89b5c 100644 --- a/vuu-ui/packages/vuu-filters/src/filter-clause/filterClauseTypes.ts +++ b/vuu-ui/packages/vuu-filters/src/filter-clause/filterClauseTypes.ts @@ -1,4 +1,4 @@ -import { ColumnDescriptor } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor } from "@finos/vuu-table-types"; import { FilterClause } from "@finos/vuu-filter-types"; import { VuuTable } from "@finos/vuu-protocol-types"; import { InputProps } from "@salt-ds/core"; diff --git a/vuu-ui/packages/vuu-filters/src/filter-clause/operator-utils.ts b/vuu-ui/packages/vuu-filters/src/filter-clause/operator-utils.ts index 0ad99acd5..86a38e0c2 100644 --- a/vuu-ui/packages/vuu-filters/src/filter-clause/operator-utils.ts +++ b/vuu-ui/packages/vuu-filters/src/filter-clause/operator-utils.ts @@ -1,4 +1,4 @@ -import { ColumnDescriptor } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor } from "@finos/vuu-table-types"; import { isNumericColumn, isTextColumn } from "@finos/vuu-utils"; export const textOperators = ["=", "in", "!=", "starts", "ends"]; diff --git a/vuu-ui/packages/vuu-filters/src/filter-clause/useFilterClauseEditor.ts b/vuu-ui/packages/vuu-filters/src/filter-clause/useFilterClauseEditor.ts index 880f2d916..be98462c9 100644 --- a/vuu-ui/packages/vuu-filters/src/filter-clause/useFilterClauseEditor.ts +++ b/vuu-ui/packages/vuu-filters/src/filter-clause/useFilterClauseEditor.ts @@ -1,4 +1,4 @@ -import { ColumnDescriptor } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor } from "@finos/vuu-table-types"; import { FilterClause, FilterClauseOp } from "@finos/vuu-filter-types"; import { isMultiValueFilter, diff --git a/vuu-ui/packages/vuu-filters/src/filter-input/useFilterSuggestionProvider.ts b/vuu-ui/packages/vuu-filters/src/filter-input/useFilterSuggestionProvider.ts index 8aabecdd7..75ccd5902 100644 --- a/vuu-ui/packages/vuu-filters/src/filter-input/useFilterSuggestionProvider.ts +++ b/vuu-ui/packages/vuu-filters/src/filter-input/useFilterSuggestionProvider.ts @@ -12,7 +12,7 @@ import { SuggestionFetcher, useTypeaheadSuggestions, } from "@finos/vuu-data-react"; -import { ColumnDescriptor } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor } from "@finos/vuu-table-types"; import { Filter } from "@finos/vuu-filter-types"; import { VuuTable } from "@finos/vuu-protocol-types"; // import { isMappedValueTypeRenderer, isTypeDescriptor } from "@finos/vuu-utils"; diff --git a/vuu-ui/packages/vuu-filters/src/filter-utils.ts b/vuu-ui/packages/vuu-filters/src/filter-utils.ts index decac8a2a..253d510eb 100644 --- a/vuu-ui/packages/vuu-filters/src/filter-utils.ts +++ b/vuu-ui/packages/vuu-filters/src/filter-utils.ts @@ -1,4 +1,4 @@ -import { ColumnDescriptor } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor } from "@finos/vuu-table-types"; import { AndFilter, Filter, diff --git a/vuu-ui/packages/vuu-layout/src/layout-persistence/useLayoutContextMenuItems.tsx b/vuu-ui/packages/vuu-layout/src/layout-persistence/useLayoutContextMenuItems.tsx index 264d7bb45..b2cc99407 100644 --- a/vuu-ui/packages/vuu-layout/src/layout-persistence/useLayoutContextMenuItems.tsx +++ b/vuu-ui/packages/vuu-layout/src/layout-persistence/useLayoutContextMenuItems.tsx @@ -59,8 +59,10 @@ export const useLayoutContextMenuItems = (setDialogState: SetDialog) => { ), title: "Save Layout", diff --git a/vuu-ui/packages/vuu-layout/src/layout-provider/LayoutProvider.tsx b/vuu-ui/packages/vuu-layout/src/layout-provider/LayoutProvider.tsx index ebe37f8e6..d7b930091 100644 --- a/vuu-ui/packages/vuu-layout/src/layout-provider/LayoutProvider.tsx +++ b/vuu-ui/packages/vuu-layout/src/layout-provider/LayoutProvider.tsx @@ -127,7 +127,10 @@ export const LayoutProvider = (props: LayoutProviderProps): ReactElement => { break; } case "query": - return layoutQuery(action.query, action.path, state.current); + if (action.query === "PARENT_CONTAINER") { + return layoutQuery(action.query, action.path, state.current); + } + break; default: { dispatchLayoutAction(action); diff --git a/vuu-ui/packages/vuu-shell/src/ShellContextProvider.tsx b/vuu-ui/packages/vuu-shell/src/ShellContextProvider.tsx index 270aa2be5..6bdb0c67f 100644 --- a/vuu-ui/packages/vuu-shell/src/ShellContextProvider.tsx +++ b/vuu-ui/packages/vuu-shell/src/ShellContextProvider.tsx @@ -1,4 +1,4 @@ -import { ColumnDescriptor, ListOption } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor, ListOption } from "@finos/vuu-table-types"; import { RpcResponseHandler } from "@finos/vuu-data-react"; import { createContext, ReactElement, ReactNode, useContext } from "react"; import { VuuTable } from "@finos/vuu-protocol-types"; diff --git a/vuu-ui/packages/vuu-table-extras/package.json b/vuu-ui/packages/vuu-table-extras/package.json index ddf963827..cb033461e 100644 --- a/vuu-ui/packages/vuu-table-extras/package.json +++ b/vuu-ui/packages/vuu-table-extras/package.json @@ -17,7 +17,7 @@ "@finos/vuu-codemirror": "0.0.26", "@finos/vuu-data": "0.0.26", "@finos/vuu-data-react": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26", + "@finos/vuu-table-types": "0.0.26", "@finos/vuu-layout": "0.0.26", "@finos/vuu-popups": "0.0.26", "@finos/vuu-utils": "0.0.26", diff --git a/vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/BackgroundCell.tsx b/vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/BackgroundCell.tsx index 0ed98b641..0354e64e4 100644 --- a/vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/BackgroundCell.tsx +++ b/vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/BackgroundCell.tsx @@ -1,4 +1,4 @@ -import { ColumnType, TableCellProps } from "@finos/vuu-datagrid-types"; +import { ColumnType, TableCellProps } from "@finos/vuu-table-types"; import { DOWN1, DOWN2, diff --git a/vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/BackgroundCellConfigurationEditor.tsx b/vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/BackgroundCellConfigurationEditor.tsx index 2f98442d0..611492243 100644 --- a/vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/BackgroundCellConfigurationEditor.tsx +++ b/vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/BackgroundCellConfigurationEditor.tsx @@ -7,7 +7,7 @@ import { Dropdown, SingleSelectionHandler } from "@finos/vuu-ui-controls"; import "./BackgroundCellConfigurationEditor.css"; import { useCallback, useState } from "react"; -import { ColumnDescriptorCustomRenderer } from "packages/vuu-datagrid-types"; +import { ColumnDescriptorCustomRenderer } from "packages/vuu-table-types"; const classBase = "vuuBackgroundCellConfiguration"; diff --git a/vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/useDirection.ts b/vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/useDirection.ts index 1b3b71d0b..64de482be 100644 --- a/vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/useDirection.ts +++ b/vuu-ui/packages/vuu-table-extras/src/cell-renderers-next/background-cell/useDirection.ts @@ -1,4 +1,4 @@ -import { RuntimeColumnDescriptor } from "@finos/vuu-datagrid-types"; +import { RuntimeColumnDescriptor } from "@finos/vuu-table-types"; import { getMovingValueDirection, isTypeDescriptor, diff --git a/vuu-ui/packages/vuu-table-extras/src/cell-renderers/progress-cell/ProgressCell.tsx b/vuu-ui/packages/vuu-table-extras/src/cell-renderers/progress-cell/ProgressCell.tsx index aea656793..3667f80d7 100644 --- a/vuu-ui/packages/vuu-table-extras/src/cell-renderers/progress-cell/ProgressCell.tsx +++ b/vuu-ui/packages/vuu-table-extras/src/cell-renderers/progress-cell/ProgressCell.tsx @@ -1,4 +1,4 @@ -import { TableCellProps } from "@finos/vuu-datagrid-types"; +import { TableCellProps } from "@finos/vuu-table-types"; import { isColumnTypeRenderer, isTypeDescriptor, diff --git a/vuu-ui/packages/vuu-table-extras/src/column-expression-input/useColumnExpressionSuggestionProvider.ts b/vuu-ui/packages/vuu-table-extras/src/column-expression-input/useColumnExpressionSuggestionProvider.ts index 653ca9c1e..051da9733 100644 --- a/vuu-ui/packages/vuu-table-extras/src/column-expression-input/useColumnExpressionSuggestionProvider.ts +++ b/vuu-ui/packages/vuu-table-extras/src/column-expression-input/useColumnExpressionSuggestionProvider.ts @@ -11,7 +11,7 @@ import { getTypeaheadParams, useTypeaheadSuggestions, } from "@finos/vuu-data-react"; -import { ColumnDescriptor } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor } from "@finos/vuu-table-types"; import { VuuTable } from "@finos/vuu-protocol-types"; import { ColumnExpressionOperator, diff --git a/vuu-ui/packages/vuu-table-extras/src/column-expression-panel/ColumnExpressionPanel.tsx b/vuu-ui/packages/vuu-table-extras/src/column-expression-panel/ColumnExpressionPanel.tsx index f9eb926a1..4cb2ec51f 100644 --- a/vuu-ui/packages/vuu-table-extras/src/column-expression-panel/ColumnExpressionPanel.tsx +++ b/vuu-ui/packages/vuu-table-extras/src/column-expression-panel/ColumnExpressionPanel.tsx @@ -1,4 +1,4 @@ -import { ColumnDescriptor } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor } from "@finos/vuu-table-types"; import { Dropdown } from "@finos/vuu-ui-controls"; import { getCalculatedColumnExpression, diff --git a/vuu-ui/packages/vuu-table-extras/src/column-expression-panel/useColumnExpression.ts b/vuu-ui/packages/vuu-table-extras/src/column-expression-panel/useColumnExpression.ts index 7345c6e75..cc05874e7 100644 --- a/vuu-ui/packages/vuu-table-extras/src/column-expression-panel/useColumnExpression.ts +++ b/vuu-ui/packages/vuu-table-extras/src/column-expression-panel/useColumnExpression.ts @@ -1,4 +1,4 @@ -import { ColumnDescriptor } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor } from "@finos/vuu-table-types"; import { getCalculatedColumnDetails, setCalculatedColumnExpression, diff --git a/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/ColumnFormattingPanel.tsx b/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/ColumnFormattingPanel.tsx index efd4d2a43..66487bb75 100644 --- a/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/ColumnFormattingPanel.tsx +++ b/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/ColumnFormattingPanel.tsx @@ -3,7 +3,7 @@ import { ColumnDescriptorCustomRenderer, ColumnTypeFormatting, ColumnTypeRendering, -} from "@finos/vuu-datagrid-types"; +} from "@finos/vuu-table-types"; import { Dropdown, SingleSelectionHandler } from "@finos/vuu-ui-controls"; import { CellRendererDescriptor, diff --git a/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/NumericFormattingSettings.tsx b/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/NumericFormattingSettings.tsx index 12286c388..83ba314e6 100644 --- a/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/NumericFormattingSettings.tsx +++ b/vuu-ui/packages/vuu-table-extras/src/column-formatting-settings/NumericFormattingSettings.tsx @@ -1,9 +1,6 @@ import { FormField, FormFieldLabel, Input } from "@salt-ds/core"; import { Switch } from "@salt-ds/lab"; -import { - ColumnDescriptor, - ColumnTypeFormatting, -} from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor, ColumnTypeFormatting } from "@finos/vuu-table-types"; import { getTypeFormattingFromColumn } from "@finos/vuu-utils"; import { ChangeEvent, diff --git a/vuu-ui/packages/vuu-table-extras/src/column-list/ColumnList.tsx b/vuu-ui/packages/vuu-table-extras/src/column-list/ColumnList.tsx index 8831f89f8..572ef49ff 100644 --- a/vuu-ui/packages/vuu-table-extras/src/column-list/ColumnList.tsx +++ b/vuu-ui/packages/vuu-table-extras/src/column-list/ColumnList.tsx @@ -7,7 +7,7 @@ import { import { Checkbox } from "@salt-ds/core"; import { Switch } from "@salt-ds/lab"; import cx from "classnames"; -import { ColumnDescriptor } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor } from "@finos/vuu-table-types"; import { HTMLAttributes, MouseEventHandler, diff --git a/vuu-ui/packages/vuu-table-extras/src/column-settings/ColumnNameLabel.tsx b/vuu-ui/packages/vuu-table-extras/src/column-settings/ColumnNameLabel.tsx index 95847da2f..088eab448 100644 --- a/vuu-ui/packages/vuu-table-extras/src/column-settings/ColumnNameLabel.tsx +++ b/vuu-ui/packages/vuu-table-extras/src/column-settings/ColumnNameLabel.tsx @@ -1,4 +1,4 @@ -import { ColumnDescriptor } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor } from "@finos/vuu-table-types"; import cx from "classnames"; import { diff --git a/vuu-ui/packages/vuu-table-extras/src/column-settings/ColumnSettingsPanel.tsx b/vuu-ui/packages/vuu-table-extras/src/column-settings/ColumnSettingsPanel.tsx index a23638de1..c0cb8e6f3 100644 --- a/vuu-ui/packages/vuu-table-extras/src/column-settings/ColumnSettingsPanel.tsx +++ b/vuu-ui/packages/vuu-table-extras/src/column-settings/ColumnSettingsPanel.tsx @@ -1,4 +1,4 @@ -import { ColumnDescriptor, TableConfig } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor, TableConfig } from "@finos/vuu-table-types"; import { VuuTable } from "@finos/vuu-protocol-types"; import { VuuInput } from "@finos/vuu-ui-controls"; import { diff --git a/vuu-ui/packages/vuu-table-extras/src/column-settings/useColumnSettings.ts b/vuu-ui/packages/vuu-table-extras/src/column-settings/useColumnSettings.ts index 14eb667fa..0ac991b6c 100644 --- a/vuu-ui/packages/vuu-table-extras/src/column-settings/useColumnSettings.ts +++ b/vuu-ui/packages/vuu-table-extras/src/column-settings/useColumnSettings.ts @@ -2,7 +2,7 @@ import { ColumnDescriptor, TableConfig, ColumnTypeFormatting, -} from "@finos/vuu-datagrid-types"; +} from "@finos/vuu-table-types"; import { CellRendererDescriptor, diff --git a/vuu-ui/packages/vuu-table-extras/src/table-settings/TableSettingsPanel.tsx b/vuu-ui/packages/vuu-table-extras/src/table-settings/TableSettingsPanel.tsx index 8db16df6f..2662cf925 100644 --- a/vuu-ui/packages/vuu-table-extras/src/table-settings/TableSettingsPanel.tsx +++ b/vuu-ui/packages/vuu-table-extras/src/table-settings/TableSettingsPanel.tsx @@ -7,7 +7,7 @@ import { ToggleButtonGroup, } from "@salt-ds/core"; import { DataSourceConfig, SchemaColumn } from "@finos/vuu-data"; -import { TableConfig } from "@finos/vuu-datagrid-types"; +import { TableConfig } from "@finos/vuu-table-types"; import { HTMLAttributes } from "react"; import { ColumnList } from "../column-list"; import { useTableSettings } from "./useTableSettings"; diff --git a/vuu-ui/packages/vuu-table-extras/src/table-settings/useTableSettings.ts b/vuu-ui/packages/vuu-table-extras/src/table-settings/useTableSettings.ts index 88fe0ba85..fb856aa90 100644 --- a/vuu-ui/packages/vuu-table-extras/src/table-settings/useTableSettings.ts +++ b/vuu-ui/packages/vuu-table-extras/src/table-settings/useTableSettings.ts @@ -1,5 +1,5 @@ import { SchemaColumn } from "@finos/vuu-data"; -import { ColumnDescriptor, TableConfig } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor, TableConfig } from "@finos/vuu-table-types"; import { useLayoutEffectSkipFirst } from "@finos/vuu-layout"; import { updateTableConfig } from "@finos/vuu-table"; import { diff --git a/vuu-ui/packages/vuu-table-extras/src/useTableAndColumnSettings.ts b/vuu-ui/packages/vuu-table-extras/src/useTableAndColumnSettings.ts index 444e7a5f2..17229d727 100644 --- a/vuu-ui/packages/vuu-table-extras/src/useTableAndColumnSettings.ts +++ b/vuu-ui/packages/vuu-table-extras/src/useTableAndColumnSettings.ts @@ -1,11 +1,11 @@ import { DataSourceConfig, SchemaColumn } from "@finos/vuu-data"; -import { ColumnDescriptor, TableConfig } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor, TableConfig } from "@finos/vuu-table-types"; import { useLayoutProviderDispatch } from "@finos/vuu-layout"; import { ColumnSettingsProps, TableSettingsProps, } from "@finos/vuu-table-extras"; -import { ColumnActionColumnSettings } from "@finos/vuu-table/src/table-next/useTableModel"; +import { ColumnActionColumnSettings } from "@finos/vuu-table"; import { getCalculatedColumnType } from "@finos/vuu-utils"; import { useCallback, useRef, useState } from "react"; diff --git a/vuu-ui/packages/vuu-datagrid-types/index.d.ts b/vuu-ui/packages/vuu-table-types/index.d.ts similarity index 100% rename from vuu-ui/packages/vuu-datagrid-types/index.d.ts rename to vuu-ui/packages/vuu-table-types/index.d.ts diff --git a/vuu-ui/packages/vuu-datagrid-types/package.json b/vuu-ui/packages/vuu-table-types/package.json similarity index 89% rename from vuu-ui/packages/vuu-datagrid-types/package.json rename to vuu-ui/packages/vuu-table-types/package.json index 194c0698d..978782825 100644 --- a/vuu-ui/packages/vuu-datagrid-types/package.json +++ b/vuu-ui/packages/vuu-table-types/package.json @@ -1,5 +1,5 @@ { - "name": "@finos/vuu-datagrid-types", + "name": "@finos/vuu-table-types", "version": "0.0.26", "main": "", "scripts": { diff --git a/vuu-ui/packages/vuu-datagrid-types/tsconfig.json b/vuu-ui/packages/vuu-table-types/tsconfig.json similarity index 100% rename from vuu-ui/packages/vuu-datagrid-types/tsconfig.json rename to vuu-ui/packages/vuu-table-types/tsconfig.json diff --git a/vuu-ui/packages/vuu-table/src/Row.tsx b/vuu-ui/packages/vuu-table/src/Row.tsx index 68efbbda7..29a4f45ec 100644 --- a/vuu-ui/packages/vuu-table/src/Row.tsx +++ b/vuu-ui/packages/vuu-table/src/Row.tsx @@ -3,14 +3,14 @@ import { DataCellEditHandler, RuntimeColumnDescriptor, RowClickHandler, -} from "@finos/vuu-datagrid-types"; +} from "@finos/vuu-table-types"; import { ColumnMap, isGroupColumn, isJsonColumn, isJsonGroup, metadataKeys, - notHidden, + isNotHidden, RowSelected, } from "@finos/vuu-utils"; import cx from "classnames"; @@ -100,7 +100,7 @@ export const Row = memo( style={style} > - {columns.filter(notHidden).map((column) => { + {columns.filter(isNotHidden).map((column) => { const isGroup = isGroupColumn(column); const isJsonCell = isJsonColumn(column); const Cell = isGroup ? TableGroupCell : TableCell; diff --git a/vuu-ui/packages/vuu-table/src/Table.css b/vuu-ui/packages/vuu-table/src/Table.css index a84208737..de6c9940c 100644 --- a/vuu-ui/packages/vuu-table/src/Table.css +++ b/vuu-ui/packages/vuu-table/src/Table.css @@ -18,11 +18,11 @@ } .vuuTable-colLines { - --cell-borderColor: var(--salt-separable-tertiary-borderColor); + --cell-borderColor: var(--vuu-color-gray-03); } .vuuTable-rowLines { - --row-borderColor: var(--salt-separable-tertiary-borderColor); + --row-borderColor: var(--vuu-color-gray-03); } .vuuTable-highlight .vuuTableRow:hover { diff --git a/vuu-ui/packages/vuu-table/src/Table.tsx b/vuu-ui/packages/vuu-table/src/Table.tsx index 922f2612a..268c0b226 100644 --- a/vuu-ui/packages/vuu-table/src/Table.tsx +++ b/vuu-ui/packages/vuu-table/src/Table.tsx @@ -8,7 +8,7 @@ import { TableConfig, TableRowClickHandler, TableSelectionModel, -} from "@finos/vuu-datagrid-types"; +} from "@finos/vuu-table-types"; import { DataSourceRow } from "@finos/vuu-data-types"; import { MeasuredContainer, @@ -18,7 +18,7 @@ import { } from "@finos/vuu-layout"; import { ContextMenuProvider } from "@finos/vuu-popups"; import { DragStartHandler, dragStrategy } from "@finos/vuu-ui-controls"; -import { isGroupColumn, metadataKeys, notHidden } from "@finos/vuu-utils"; +import { metadataKeys } from "@finos/vuu-utils"; import { useForkRef } from "@salt-ds/core"; import cx from "classnames"; import { @@ -30,14 +30,12 @@ import { useRef, useState, } from "react"; -import { - GroupHeaderCellNext as GroupHeaderCell, - HeaderCell, -} from "./header-cell"; import { Row as DefaultRow, RowProps } from "./Row"; import { useTable } from "./useTable"; +import { TableHeader } from "./table-header/TableHeader"; import "./Table.css"; +import { DragDropState } from "packages/vuu-ui-controls/src/drag-drop/DragDropState"; const classBase = "vuuTable"; @@ -80,7 +78,7 @@ export interface TableProps */ onConfigChange?: (config: TableConfig) => void; onDragStart?: DragStartHandler; - onDrop?: () => void; + onDrop?: (dragDropState: DragDropState) => void; /** * When a Vuu feature e.g. context menu action, has been invoked, the Vuu server * response must be handled. This callback provides that response. @@ -146,21 +144,22 @@ const TableCore = ({ columnMap, columns, data, - draggableColumn, draggableRow, - dragDropHook, handleContextMenuAction, - headerProps, + headings, highlightedIndex, onDataEdited, + onMoveColumn, onMoveGroupColumn, onRemoveGroupColumn, - onResize, + onResizeColumn, onRowClick, + onSortColumn, onToggleGroup, menuBuilder, scrollProps, tableAttributes, + tableConfig, viewportMeasurements, ...tableProps } = useTable({ @@ -189,6 +188,14 @@ const TableCore = ({ size, }); + const className = cx(`${classBase}-contentContainer`, { + [`${classBase}-colLines`]: tableAttributes.columnSeparators, + [`${classBase}-rowLines`]: tableAttributes.rowSeparators, + // [`${classBase}-highlight`]: tableAttributes.showHighlightedRow, + [`${classBase}-zebra`]: tableAttributes.zebraStripes, + // [`${classBase}-loading`]: isDataLoading(tableProps.columns), + }); + const cssVariables = { "--content-height": `${viewportMeasurements.contentHeight}px`, "--content-width": `${viewportMeasurements.contentWidth}px`, @@ -215,7 +222,7 @@ const TableCore = ({
@@ -225,35 +232,17 @@ const TableCore = ({ tabIndex={disableFocus ? undefined : -1} > {showColumnHeaders ? ( -
-
- {columns.filter(notHidden).map((col, i) => - isGroupColumn(col) ? ( - - ) : ( - - ) - )} - {draggableColumn} -
-
+ ) : null}
{data.map((data) => ( @@ -265,7 +254,9 @@ const TableCore = ({ onClick={onRowClick} onDataEdited={onDataEdited} row={data} - offset={rowHeight * data[IDX] + headerHeight} + offset={ + rowHeight * data[IDX] + viewportMeasurements.totalHeaderHeight + } onToggleGroup={onToggleGroup} zebraStripes={tableAttributes.zebraStripes} /> @@ -313,18 +304,10 @@ export const Table = forwardRef(function TableNext( const [size, setSize] = useState(); - const className = cx(classBase, classNameProp, { - [`${classBase}-colLines`]: config.columnSeparators, - [`${classBase}-rowLines`]: config.rowSeparators, - // [`${classBase}-highlight`]: tableAttributes.showHighlightedRow, - [`${classBase}-zebra`]: config.zebraStripes, - // [`${classBase}-loading`]: isDataLoading(tableProps.columns), - }); - return ( ) => { - console.log(`click isResizing ${isResizing}`); + const handleClick = useCallback>( + (evt) => { !isResizing && onClick?.(evt); }, [isResizing, onClick] diff --git a/vuu-ui/packages/vuu-table/src/table-cell/TableCell.tsx b/vuu-ui/packages/vuu-table/src/table-cell/TableCell.tsx index 8c1e1d2b5..daaa681ff 100644 --- a/vuu-ui/packages/vuu-table/src/table-cell/TableCell.tsx +++ b/vuu-ui/packages/vuu-table/src/table-cell/TableCell.tsx @@ -1,7 +1,4 @@ -import { - DataItemCommitHandler, - TableCellProps, -} from "@finos/vuu-datagrid-types"; +import { DataItemCommitHandler, TableCellProps } from "@finos/vuu-table-types"; import { isNumericColumn } from "@finos/vuu-utils"; import { MouseEventHandler, useCallback } from "react"; import { useCell } from "../useCell"; 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 3ce852e2c..1d72534ac 100644 --- a/vuu-ui/packages/vuu-table/src/table-cell/TableGroupCell.tsx +++ b/vuu-ui/packages/vuu-table/src/table-cell/TableGroupCell.tsx @@ -1,7 +1,4 @@ -import { - GroupColumnDescriptor, - TableCellProps, -} from "@finos/vuu-datagrid-types"; +import { GroupColumnDescriptor, TableCellProps } from "@finos/vuu-table-types"; import { getGroupValueAndOffset, metadataKeys } from "@finos/vuu-utils"; import { MouseEvent, useCallback } from "react"; import { useCell } from "../useCell"; diff --git a/vuu-ui/packages/vuu-table/src/table-config.ts b/vuu-ui/packages/vuu-table/src/table-config.ts index 751b9debc..ad486a672 100644 --- a/vuu-ui/packages/vuu-table/src/table-config.ts +++ b/vuu-ui/packages/vuu-table/src/table-config.ts @@ -1,4 +1,4 @@ -import { ColumnDescriptor, TableConfig } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor, TableConfig } from "@finos/vuu-table-types"; export type MoveColumnTableConfigAction = { type: "col-move"; diff --git a/vuu-ui/packages/vuu-table/src/table-header/TableHeader.tsx b/vuu-ui/packages/vuu-table/src/table-header/TableHeader.tsx new file mode 100644 index 000000000..dc45e0de2 --- /dev/null +++ b/vuu-ui/packages/vuu-table/src/table-header/TableHeader.tsx @@ -0,0 +1,99 @@ +import { + ColumnDescriptor, + RuntimeColumnDescriptor, + 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 { GroupHeaderCellNext, HeaderCell } from "../header-cell"; +import { useTableHeader } from "./useTableHeader"; + +export type ColumnSortHandler = ( + column: ColumnDescriptor, + addToExistingSort: boolean, + sortType?: VuuSortType +) => void; + +export interface TableHeaderProps { + classBase?: string; + columns: RuntimeColumnDescriptor[]; + headings: TableHeadings; + onResizeColumn: TableColumnResizeHandler; + onMoveColumn: (columns: ColumnDescriptor[]) => void; + onMoveGroupColumn: (columns: ColumnDescriptor[]) => void; + onRemoveGroupColumn: (column: RuntimeColumnDescriptor) => void; + onSortColumn: ColumnSortHandler; + tableConfig: TableConfig; + tableId: string; +} + +export const TableHeader = ({ + classBase = "vuuTable", + columns, + headings, + onMoveColumn, + onMoveGroupColumn, + onRemoveGroupColumn, + onResizeColumn, + onSortColumn, + tableConfig, + tableId, +}: TableHeaderProps) => { + const { + containerRef, + draggableColumn, + draggedColumnIndex, + onClick, + onMouseDown, + } = useTableHeader({ + columns, + onMoveColumn, + onSortColumn, + tableConfig, + }); + + return ( +
+ {headings.map((colHeaders, i) => ( +
+ {colHeaders.map(({ label, width }, j) => ( +
+ {label} +
+ ))} +
+ ))} +
+ {columns.filter(isNotHidden).map((col, i) => + isGroupColumn(col) ? ( + + ) : ( + + ) + )} + {draggableColumn} +
+
+ ); +}; diff --git a/vuu-ui/packages/vuu-table/src/table-header/useTableHeader.ts b/vuu-ui/packages/vuu-table/src/table-header/useTableHeader.ts new file mode 100644 index 000000000..12e965742 --- /dev/null +++ b/vuu-ui/packages/vuu-table/src/table-header/useTableHeader.ts @@ -0,0 +1,88 @@ +import { ColumnDescriptor } from "@finos/vuu-table-types"; +import { useDragDropNext as useDragDrop } from "@finos/vuu-ui-controls"; +import { moveColumnTo, visibleColumnAtIndex } from "@finos/vuu-utils"; +import { MouseEventHandler, useCallback, useRef } from "react"; +import { TableHeaderProps } from "./TableHeader"; + +export interface TableHeaderHookProps + extends Pick< + TableHeaderProps, + "columns" | "onMoveColumn" | "onSortColumn" | "tableConfig" + > { + label?: string; + onMoveColumn: (columns: ColumnDescriptor[]) => void; + onSortColumn: (column: ColumnDescriptor, addToExistingSort: boolean) => void; +} + +export const useTableHeader = ({ + columns, + onMoveColumn, + onSortColumn, + tableConfig, +}: TableHeaderHookProps) => { + const containerRef = useRef(null); + + const handleDropColumnHeader = useCallback( + (moveFrom: number, moveTo: number) => { + const column = columns[moveFrom]; + // columns are what get rendered, so these are the columns that + // the drop operation relates to. We must translate these into + // columns within the table config. Grouping complicates this + // as the group columns are not present in columns but ARE in + // config.columns + const orderedColumns = moveColumnTo(columns, column, moveTo); + + const ofColumn = + ({ name }: ColumnDescriptor) => + (col: ColumnDescriptor) => + col.name === name; + + const targetIndex = orderedColumns.findIndex(ofColumn(column)); + const nextColumn = orderedColumns[targetIndex + 1]; + const insertPos = nextColumn + ? tableConfig.columns.findIndex(ofColumn(nextColumn)) + : -1; + + onMoveColumn(moveColumnTo(tableConfig.columns, column, insertPos)); + }, + [columns, onMoveColumn, tableConfig.columns] + ); + + const handleColumnHeaderClick = useCallback< + MouseEventHandler + >( + (evt) => { + const targetElement = evt.target as HTMLElement; + const headerCell = targetElement.closest( + ".vuuTableHeaderCell" + ) as HTMLElement; + const colIdx = parseInt(headerCell?.dataset.index ?? "-1"); + const column = visibleColumnAtIndex(columns, colIdx); + const isAdditive = evt.shiftKey; + column && onSortColumn(column, isAdditive); + }, + [columns, onSortColumn] + ); + + // Drag Drop column headers + const { + onMouseDown: columnHeaderDragMouseDown, + draggable: draggableColumn, + ...dragDropHook + } = useDragDrop({ + allowDragDrop: true, + containerRef, + draggableClassName: `vuuTable`, + onDrop: handleDropColumnHeader, + orientation: "horizontal", + itemQuery: ".vuuTableHeaderCell", + }); + + return { + containerRef, + draggableColumn, + draggedColumnIndex: dragDropHook.draggedItemIndex, + onClick: handleColumnHeaderClick, + onMouseDown: columnHeaderDragMouseDown, + }; +}; diff --git a/vuu-ui/packages/vuu-table/src/useCell.ts b/vuu-ui/packages/vuu-table/src/useCell.ts index 81148f010..dfbad9cf4 100644 --- a/vuu-ui/packages/vuu-table/src/useCell.ts +++ b/vuu-ui/packages/vuu-table/src/useCell.ts @@ -1,4 +1,4 @@ -import { RuntimeColumnDescriptor } from "@finos/vuu-datagrid-types"; +import { RuntimeColumnDescriptor } from "@finos/vuu-table-types"; import { getColumnStyle } from "@finos/vuu-utils"; import cx from "classnames"; import { useMemo } from "react"; diff --git a/vuu-ui/packages/vuu-table/src/useKeyboardNavigation.ts b/vuu-ui/packages/vuu-table/src/useKeyboardNavigation.ts index 8170b2ed9..48861ec3d 100644 --- a/vuu-ui/packages/vuu-table/src/useKeyboardNavigation.ts +++ b/vuu-ui/packages/vuu-table/src/useKeyboardNavigation.ts @@ -16,7 +16,7 @@ import { getTableCell, headerCellQuery, } from "./table-dom-utils"; -import { TableNavigationStyle } from "../table/dataTableTypes"; +import { TableNavigationStyle } from "./Table"; const rowNavigationKeys = new Set([ "Home", diff --git a/vuu-ui/packages/vuu-table/src/useSelection.ts b/vuu-ui/packages/vuu-table/src/useSelection.ts index 7248b5d9f..cd202317b 100644 --- a/vuu-ui/packages/vuu-table/src/useSelection.ts +++ b/vuu-ui/packages/vuu-table/src/useSelection.ts @@ -3,7 +3,7 @@ import { Selection, SelectionChangeHandler, TableSelectionModel, -} from "@finos/vuu-datagrid-types"; +} from "@finos/vuu-table-types"; import { deselectItem, dispatchMouseEvent, diff --git a/vuu-ui/packages/vuu-table/src/useTable.ts b/vuu-ui/packages/vuu-table/src/useTable.ts index de9532ff9..599ee316e 100644 --- a/vuu-ui/packages/vuu-table/src/useTable.ts +++ b/vuu-ui/packages/vuu-table/src/useTable.ts @@ -7,16 +7,16 @@ import { DataSourceRow } from "@finos/vuu-data-types"; import { ColumnDescriptor, DataCellEditHandler, - RuntimeColumnDescriptor, RowClickHandler, + RuntimeColumnDescriptor, SelectionChangeHandler, TableConfig, TableSelectionModel, -} from "@finos/vuu-datagrid-types"; +} from "@finos/vuu-table-types"; import { + MeasuredProps, MeasuredSize, useLayoutEffectSkipFirst, - MeasuredProps, } from "@finos/vuu-layout"; import { VuuRange, VuuSortType } from "@finos/vuu-protocol-types"; import { useTableAndColumnSettings } from "@finos/vuu-table-extras"; @@ -24,7 +24,6 @@ import { DragStartHandler, useDragDropNext as useDragDrop, } from "@finos/vuu-ui-controls"; -import { useKeyboardNavigation } from "./useKeyboardNavigation"; import { applySort, buildColumnMap, @@ -32,32 +31,30 @@ import { isJsonGroup, isValidNumber, metadataKeys, - moveColumnTo, updateColumn, - visibleColumnAtIndex, } from "@finos/vuu-utils"; import { FocusEvent, KeyboardEvent, - MouseEvent, RefObject, useCallback, useEffect, useMemo, useState, } from "react"; -import { TableProps } from "./Table"; import { TableColumnResizeHandler } from "./column-resizing"; -import { updateTableConfig } from "./table-config"; -import { useDataSource } from "./useDataSource"; -import { useInitialValue } from "./useInitialValue"; -import { useSelection } from "./useSelection"; -import { useTableContextMenu } from "./useTableContextMenu"; import { buildContextMenuDescriptors, useHandleTableContextMenu, } from "./context-menu"; +import { TableProps } from "./Table"; +import { updateTableConfig } from "./table-config"; import { useCellEditing } from "./useCellEditing"; +import { useDataSource } from "./useDataSource"; +import { useInitialValue } from "./useInitialValue"; +import { useKeyboardNavigation } from "./useKeyboardNavigation"; +import { useSelection } from "./useSelection"; +import { useTableContextMenu } from "./useTableContextMenu"; import { ColumnActionHide, ColumnActionPin, @@ -67,8 +64,8 @@ import { useTableModel, } from "./useTableModel"; import { useTableScroll } from "./useTableScroll"; -import { useVirtualViewport } from "./useVirtualViewport"; import { useTableViewport } from "./useTableViewport"; +import { useVirtualViewport } from "./useVirtualViewport"; const stripInternalProperties = (tableConfig: TableConfig): TableConfig => { return tableConfig; @@ -261,6 +258,7 @@ export const useTable = ({ const handleConfigEditedInSettingsPanel = useCallback( (tableConfig: TableConfig) => { + console.log(`settings changed`); dispatchColumnAction({ type: "init", tableConfig, @@ -374,11 +372,7 @@ export const useTable = ({ }); const handleSort = useCallback( - ( - column: RuntimeColumnDescriptor, - extendSort = false, - sortType?: VuuSortType - ) => { + (column: ColumnDescriptor, extendSort = false, sortType?: VuuSortType) => { if (dataSource) { dataSource.sort = applySort( dataSource.sort, @@ -391,7 +385,7 @@ export const useTable = ({ [dataSource] ); - const onHeaderResize: TableColumnResizeHandler = useCallback( + const onResizeColumn: TableColumnResizeHandler = useCallback( (phase, columnName, width) => { const column = columns.find((column) => column.name === columnName); if (column) { @@ -541,20 +535,6 @@ export const useTable = ({ getSelectedRows, }); - const onHeaderClick = useCallback( - (evt: MouseEvent) => { - const targetElement = evt.target as HTMLElement; - const headerCell = targetElement.closest( - ".vuuTableHeaderCell" - ) as HTMLElement; - const colIdx = parseInt(headerCell?.dataset.index ?? "-1"); - const column = visibleColumnAtIndex(columns, colIdx); - const isAdditive = evt.shiftKey; - column && handleSort(column, isAdditive); - }, - [columns, handleSort] - ); - const onMoveGroupColumn = useCallback( (columns: ColumnDescriptor[]) => { dataSource.groupBy = columns.map((col) => col.name); @@ -624,30 +604,11 @@ export const useTable = ({ }); }, [config, dataSource, dispatchColumnAction]); - const handleDropColumnHeader = useCallback( - (moveFrom: number, moveTo: number) => { - const column = columns[moveFrom]; - // columns are what get rendered, so these are the columns that - // the drop operation relates to. We must translate these into - // columns within the table config. Grouping complicates this - // as the group columns are not present in columns but ARE in - // config.columns - const orderedColumns = moveColumnTo(columns, column, moveTo); - - const ofColumn = - ({ name }: ColumnDescriptor) => - (col: ColumnDescriptor) => - col.name === name; - - const targetIndex = orderedColumns.findIndex(ofColumn(column)); - const nextColumn = orderedColumns[targetIndex + 1]; - const insertPos = nextColumn - ? tableConfig.columns.findIndex(ofColumn(nextColumn)) - : -1; - + const onMoveColumn = useCallback( + (columns: ColumnDescriptor[]) => { const newTableConfig = { ...tableConfig, - columns: moveColumnTo(tableConfig.columns, column, insertPos), + columns, }; dispatchColumnAction({ @@ -657,7 +618,7 @@ export const useTable = ({ }); onConfigChange?.(stripInternalProperties(newTableConfig)); }, - [columns, dataSource, dispatchColumnAction, onConfigChange, tableConfig] + [dataSource, dispatchColumnAction, onConfigChange, tableConfig] ); const handleDropRow = useCallback( @@ -673,22 +634,6 @@ export const useTable = ({ [dataSource] ); - // Drag Drop column headers - const { - onMouseDown: columnHeaderDragMouseDown, - draggable: draggableColumn, - ...dragDropHook - } = useDragDrop({ - allowDragDrop: true, - containerRef, - // this is for useDragDropNext - draggableClassName: `vuuTable`, - // extendedDropZone: overflowedItems.length > 0, - onDrop: handleDropColumnHeader, - orientation: "horizontal", - itemQuery: ".vuuTableHeaderCell", - }); - const handleDragStartRow = useCallback( (dragDropState) => { const { initialDragElement } = dragDropState; @@ -720,15 +665,13 @@ export const useTable = ({ itemQuery: ".vuuTableRow", }); - const headerProps = { - onClick: onHeaderClick, - onMouseDown: columnHeaderDragMouseDown, - onResize: onHeaderResize, - }; + // console.log({ + // tableAttributes, + // config: tableConfig, + // }); return { ...containerProps, - draggableColumn, draggableRow, onBlur: editingBlur, onDoubleClick: editingDoubleClick, @@ -739,18 +682,22 @@ export const useTable = ({ columns, data, handleContextMenuAction, - headerProps, + headings, highlightedIndex: highlightedIndexRef.current, menuBuilder, onContextMenu, onDataEdited: handleDataEdited, + onMoveColumn, onMoveGroupColumn, onRemoveGroupColumn, onRowClick: handleRowClick, + onSortColumn: handleSort, + onResizeColumn, onToggleGroup, scrollProps, + // TODO don't think we need these ... tableAttributes, + tableConfig, viewportMeasurements, - dragDropHook, }; }; diff --git a/vuu-ui/packages/vuu-table/src/useTableContextMenu.ts b/vuu-ui/packages/vuu-table/src/useTableContextMenu.ts index 22293f38a..6c715ffdd 100644 --- a/vuu-ui/packages/vuu-table/src/useTableContextMenu.ts +++ b/vuu-ui/packages/vuu-table/src/useTableContextMenu.ts @@ -1,6 +1,6 @@ import { DataSource } from "@finos/vuu-data"; import { DataSourceRow } from "@finos/vuu-data-types"; -import { RuntimeColumnDescriptor } from "@finos/vuu-datagrid-types"; +import { RuntimeColumnDescriptor } from "@finos/vuu-table-types"; import { useContextMenu as usePopupContextMenu } from "@finos/vuu-popups"; import { buildColumnMap } from "@finos/vuu-utils"; import { MouseEvent, useCallback } from "react"; diff --git a/vuu-ui/packages/vuu-table/src/useTableModel.ts b/vuu-ui/packages/vuu-table/src/useTableModel.ts index 6cbae6d95..de734cf38 100644 --- a/vuu-ui/packages/vuu-table/src/useTableModel.ts +++ b/vuu-ui/packages/vuu-table/src/useTableModel.ts @@ -5,7 +5,7 @@ import { TableAttributes, TableConfig, TableHeadings, -} from "@finos/vuu-datagrid-types"; +} from "@finos/vuu-table-types"; import { applyFilterToColumns, applyGroupByToColumns, @@ -240,6 +240,7 @@ 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)) diff --git a/vuu-ui/packages/vuu-table/src/useTableViewport.ts b/vuu-ui/packages/vuu-table/src/useTableViewport.ts index 4f51d0a78..18f7e6f2d 100644 --- a/vuu-ui/packages/vuu-table/src/useTableViewport.ts +++ b/vuu-ui/packages/vuu-table/src/useTableViewport.ts @@ -3,10 +3,7 @@ * and virtualisation of the table. This includes measurements required * to support pinned columns. */ -import { - RuntimeColumnDescriptor, - TableHeadings, -} from "@finos/vuu-datagrid-types"; +import { RuntimeColumnDescriptor, TableHeadings } from "@finos/vuu-table-types"; import { useCallback, useMemo, useRef } from "react"; import { MeasuredSize } from "@finos/vuu-layout"; import { diff --git a/vuu-ui/packages/vuu-table/src/useVirtualViewport.ts b/vuu-ui/packages/vuu-table/src/useVirtualViewport.ts index 60db1f181..c57a40f75 100644 --- a/vuu-ui/packages/vuu-table/src/useVirtualViewport.ts +++ b/vuu-ui/packages/vuu-table/src/useVirtualViewport.ts @@ -1,4 +1,4 @@ -import { RuntimeColumnDescriptor } from "@finos/vuu-datagrid-types"; +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"; diff --git a/vuu-ui/packages/vuu-ui-controls/package.json b/vuu-ui/packages/vuu-ui-controls/package.json index 23401c151..9bbf380eb 100644 --- a/vuu-ui/packages/vuu-ui-controls/package.json +++ b/vuu-ui/packages/vuu-ui-controls/package.json @@ -13,7 +13,7 @@ "@salt-ds/core": "1.8.0", "@finos/vuu-data": "0.0.26", "@finos/vuu-data-types": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26", + "@finos/vuu-table-types": "0.0.26", "@finos/vuu-layout": "0.0.26", "@finos/vuu-table": "0.0.26", "@finos/vuu-popups": "0.0.26", 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 679230cee..9f9de984c 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,6 +1,6 @@ import { Button, ButtonProps } from "@salt-ds/core"; import cx from "classnames"; -import { CommitResponse } from "packages/vuu-datagrid-types"; +import { CommitResponse } from "packages/vuu-table-types"; import { VuuColumnDataType, VuuRowDataItemType, diff --git a/vuu-ui/packages/vuu-ui-controls/src/drag-drop/useDragDropNext.tsx b/vuu-ui/packages/vuu-ui-controls/src/drag-drop/useDragDropNext.tsx index a97fe2701..5aea4b058 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/drag-drop/useDragDropNext.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/drag-drop/useDragDropNext.tsx @@ -622,6 +622,8 @@ export const useDragDropNext: DragDropHook = ({ useEffect(() => { if (id && (isDragSource || isDropTarget)) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + //@ts-ignore TODO drah drop WIP register(id, allowDragDrop === "drop-only" ? false : resumeDrag, onDrop); } }, [ diff --git a/vuu-ui/packages/vuu-ui-controls/src/editable/editable-utils.ts b/vuu-ui/packages/vuu-ui-controls/src/editable/editable-utils.ts index 3fd94aa4d..8432a81f5 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/editable/editable-utils.ts +++ b/vuu-ui/packages/vuu-ui-controls/src/editable/editable-utils.ts @@ -1,4 +1,4 @@ -import { EditValidationRule } from "@finos/vuu-datagrid-types"; +import { EditValidationRule } from "@finos/vuu-table-types"; import { VuuRowDataItemType } from "@finos/vuu-protocol-types"; import { getEditRuleValidator } from "@finos/vuu-utils"; 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 513687bbc..274905063 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/editable/useEditableText.ts +++ b/vuu-ui/packages/vuu-ui-controls/src/editable/useEditableText.ts @@ -1,4 +1,4 @@ -import { DataItemCommitHandler } from "@finos/vuu-datagrid-types"; +import { DataItemCommitHandler } from "@finos/vuu-table-types"; import { useLayoutEffectSkipFirst } from "@finos/vuu-layout"; import { VuuRowDataItemType } from "@finos/vuu-protocol-types"; import { dispatchCustomEvent } from "@finos/vuu-utils"; diff --git a/vuu-ui/packages/vuu-ui-controls/src/instrument-picker/SearchCell.tsx b/vuu-ui/packages/vuu-ui-controls/src/instrument-picker/SearchCell.tsx index af4a06eb2..8d2b1fa74 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/instrument-picker/SearchCell.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/instrument-picker/SearchCell.tsx @@ -1,4 +1,4 @@ -import { TableCellRendererProps } from "@finos/vuu-datagrid-types"; +import { TableCellRendererProps } from "@finos/vuu-table-types"; import { registerComponent } from "@finos/vuu-utils"; import "./SearchCell.css"; 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 e9cbec1d6..37f03a6ba 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,6 +1,6 @@ import { DataSource } from "@finos/vuu-data"; import { DataSourceRow } from "@finos/vuu-data-types"; -import { ColumnDescriptor } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor } from "@finos/vuu-table-types"; import { TableRowSelectHandler, useControlledTableNavigation, 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 21d30af86..f38449ad4 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,5 +1,5 @@ import { DataSource } from "@finos/vuu-data"; -import { TableConfig } from "@finos/vuu-datagrid-types"; +import { TableConfig } from "@finos/vuu-table-types"; import { registerComponent } from "@finos/vuu-layout"; import { diff --git a/vuu-ui/packages/vuu-ui-controls/src/instrument-search/SearchCell.tsx b/vuu-ui/packages/vuu-ui-controls/src/instrument-search/SearchCell.tsx index af4a06eb2..8d2b1fa74 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/instrument-search/SearchCell.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/instrument-search/SearchCell.tsx @@ -1,4 +1,4 @@ -import { TableCellRendererProps } from "@finos/vuu-datagrid-types"; +import { TableCellRendererProps } from "@finos/vuu-table-types"; import { registerComponent } from "@finos/vuu-utils"; import "./SearchCell.css"; diff --git a/vuu-ui/packages/vuu-utils/package.json b/vuu-ui/packages/vuu-utils/package.json index 3f61202e0..9302ed323 100644 --- a/vuu-ui/packages/vuu-utils/package.json +++ b/vuu-ui/packages/vuu-utils/package.json @@ -11,7 +11,7 @@ "type-defs": "node ../../scripts/build-type-defs.mjs" }, "devDependencies": { - "@finos/vuu-datagrid-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" }, diff --git a/vuu-ui/packages/vuu-utils/src/column-utils.ts b/vuu-ui/packages/vuu-utils/src/column-utils.ts index 4e587aa6c..c5d193f53 100644 --- a/vuu-ui/packages/vuu-utils/src/column-utils.ts +++ b/vuu-ui/packages/vuu-utils/src/column-utils.ts @@ -16,7 +16,7 @@ import type { ColumnTypeFormatting, LookupRenderer, ValueListRenderer, -} from "@finos/vuu-datagrid-types"; +} from "@finos/vuu-table-types"; import type { Filter, MultiClauseFilter } from "@finos/vuu-filter-types"; import type { VuuAggregation, @@ -133,8 +133,6 @@ export const isTimeColumn = ({ type }: ColumnDescriptor) => export const isDateTimeColumn = (column: ColumnDescriptor) => isDateColumn(column) || isTimeColumn(column); -export const notHidden = (column: ColumnDescriptor) => column.hidden !== true; - export const isPinned = (column: ColumnDescriptor) => typeof column.pin === "string"; @@ -714,7 +712,8 @@ export const getColumnsInViewport = ( return [visibleColumns, preSpan]; }; -const isNotHidden = (column: RuntimeColumnDescriptor) => column.hidden !== true; +export const isNotHidden = (column: RuntimeColumnDescriptor) => + column.hidden !== true; export const visibleColumnAtIndex = ( columns: RuntimeColumnDescriptor[], diff --git a/vuu-ui/packages/vuu-utils/src/component-registry.ts b/vuu-ui/packages/vuu-utils/src/component-registry.ts index 3264f0c68..cafc01cf7 100644 --- a/vuu-ui/packages/vuu-utils/src/component-registry.ts +++ b/vuu-ui/packages/vuu-utils/src/component-registry.ts @@ -5,7 +5,7 @@ import { ColumnTypeRendering, EditValidationRule, TableCellRendererProps, -} from "@finos/vuu-datagrid-types"; +} from "@finos/vuu-table-types"; import { VuuColumnDataType, VuuRowDataItemType, diff --git a/vuu-ui/packages/vuu-utils/src/filter-utils.ts b/vuu-ui/packages/vuu-utils/src/filter-utils.ts index 2fdea55af..da6aaf722 100644 --- a/vuu-ui/packages/vuu-utils/src/filter-utils.ts +++ b/vuu-ui/packages/vuu-utils/src/filter-utils.ts @@ -1,6 +1,6 @@ //Note these are duplicated in vuu-filter, those should probably be removed. -import { RuntimeColumnDescriptor } from "@finos/vuu-datagrid-types"; +import { RuntimeColumnDescriptor } from "@finos/vuu-table-types"; import { AndFilter, Filter, diff --git a/vuu-ui/packages/vuu-utils/src/formatting-utils.ts b/vuu-ui/packages/vuu-utils/src/formatting-utils.ts index 96deca1d4..fc4fbcd24 100644 --- a/vuu-ui/packages/vuu-utils/src/formatting-utils.ts +++ b/vuu-ui/packages/vuu-utils/src/formatting-utils.ts @@ -2,7 +2,7 @@ import { ColumnDescriptor, ColumnTypeValueMap, ColumnTypeFormatting, -} from "@finos/vuu-datagrid-types"; +} from "@finos/vuu-table-types"; import { roundDecimal } from "./round-decimal"; import { isDateTimeColumn, diff --git a/vuu-ui/packages/vuu-utils/src/group-utils.ts b/vuu-ui/packages/vuu-utils/src/group-utils.ts index d5af5b775..42e5b55ae 100644 --- a/vuu-ui/packages/vuu-utils/src/group-utils.ts +++ b/vuu-ui/packages/vuu-utils/src/group-utils.ts @@ -1,4 +1,4 @@ -import { RuntimeColumnDescriptor } from "@finos/vuu-datagrid-types"; +import { RuntimeColumnDescriptor } from "@finos/vuu-table-types"; import { VuuGroupBy } from "@finos/vuu-protocol-types"; export function addGroupColumn( diff --git a/vuu-ui/packages/vuu-utils/src/json-utils.ts b/vuu-ui/packages/vuu-utils/src/json-utils.ts index 0ddc5f1ac..7adbe689f 100644 --- a/vuu-ui/packages/vuu-utils/src/json-utils.ts +++ b/vuu-ui/packages/vuu-utils/src/json-utils.ts @@ -1,8 +1,5 @@ import { DataSourceRow } from "@finos/vuu-data-types"; -import { - ColumnDescriptor, - ColumnTypeDescriptor, -} from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor, ColumnTypeDescriptor } from "@finos/vuu-table-types"; import { VuuRowDataItemType } from "@finos/vuu-protocol-types"; import { metadataKeys } from "./column-utils"; diff --git a/vuu-ui/packages/vuu-utils/src/selection-utils.ts b/vuu-ui/packages/vuu-utils/src/selection-utils.ts index 0daabf20c..71c433546 100644 --- a/vuu-ui/packages/vuu-utils/src/selection-utils.ts +++ b/vuu-ui/packages/vuu-utils/src/selection-utils.ts @@ -4,7 +4,7 @@ import { Selection, SelectionItem, TableSelectionModel, -} from "@finos/vuu-datagrid-types"; +} from "@finos/vuu-table-types"; import { metadataKeys } from "./column-utils"; const NO_SELECTION: number[] = []; diff --git a/vuu-ui/packages/vuu-utils/src/sort-utils.ts b/vuu-ui/packages/vuu-utils/src/sort-utils.ts index 4546d2d2a..e383d1f55 100644 --- a/vuu-ui/packages/vuu-utils/src/sort-utils.ts +++ b/vuu-ui/packages/vuu-utils/src/sort-utils.ts @@ -1,7 +1,7 @@ import { ColumnDescriptor, RuntimeColumnDescriptor, -} from "@finos/vuu-datagrid-types"; +} from "@finos/vuu-table-types"; import { VuuSort, VuuSortCol, VuuSortType } from "@finos/vuu-protocol-types"; const toggle = (sortType: VuuSortType) => (sortType === "A" ? "D" : "A"); diff --git a/vuu-ui/sample-apps/app-vuu-example/package.json b/vuu-ui/sample-apps/app-vuu-example/package.json index 4367ff480..c95685008 100644 --- a/vuu-ui/sample-apps/app-vuu-example/package.json +++ b/vuu-ui/sample-apps/app-vuu-example/package.json @@ -20,7 +20,7 @@ "@salt-ds/core": "1.8.0", "@salt-ds/lab": "1.0.0-alpha.15", "@finos/vuu-data": "0.0.26", - "@finos/vuu-datagrid-types": "0.0.26", + "@finos/vuu-table-types": "0.0.26", "@finos/vuu-data-react": "0.0.26", "@finos/vuu-layout": "0.0.26", "@finos/vuu-popups": "0.0.26", 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 9fe83b886..888487e2a 100644 --- a/vuu-ui/sample-apps/app-vuu-example/src/columnMetaData.ts +++ b/vuu-ui/sample-apps/app-vuu-example/src/columnMetaData.ts @@ -1,4 +1,4 @@ -import { ColumnDescriptor } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor } from "@finos/vuu-table-types"; const Average = 2; diff --git a/vuu-ui/sample-apps/feature-basket-trading/package.json b/vuu-ui/sample-apps/feature-basket-trading/package.json index 767557344..74fefb227 100644 --- a/vuu-ui/sample-apps/feature-basket-trading/package.json +++ b/vuu-ui/sample-apps/feature-basket-trading/package.json @@ -18,7 +18,7 @@ "dependencies": { "@finos/vuu-data": "0.0.26", "@finos/vuu-data-react": "0.0.26", - "@finos/vuu-datagrid-types": "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", diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/useBasketSelector.ts b/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/useBasketSelector.ts index dcbf06ac6..f46d1d529 100644 --- a/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/useBasketSelector.ts +++ b/vuu-ui/sample-apps/feature-basket-trading/src/basket-selector/useBasketSelector.ts @@ -1,4 +1,4 @@ -import { TableRowClickHandler } from "@finos/vuu-datagrid-types"; +import { TableRowClickHandler } from "@finos/vuu-table-types"; import { TableProps } from "@finos/vuu-table"; import { OpenChangeHandler, useControlled } from "@finos/vuu-ui-controls"; import { buildColumnMap } from "@finos/vuu-utils"; 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 a35442f55..0202d08bc 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,5 +1,5 @@ import { TableSchema } from "@finos/vuu-data"; -import { TableConfig } from "@finos/vuu-datagrid-types"; +import { TableConfig } from "@finos/vuu-table-types"; import { Table, TableProps } from "@finos/vuu-table"; import { ContextMenuConfiguration, 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 e107b636d..21f5319c3 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-datagrid-types"; +import { ColumnDescriptor } from "packages/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 fac40bd6a..e4f40c1c3 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,5 +1,5 @@ import { TableSchema } from "@finos/vuu-data"; -import { TableConfig } from "@finos/vuu-datagrid-types"; +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"; 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 6eb0aa986..8041aba72 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-datagrid-types"; +import { ColumnDescriptor } from "packages/vuu-table-types"; const hidden = true; const ticking = { 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 fe8a460c7..2f0b4895b 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 @@ -9,7 +9,7 @@ import { Button, FormField, FormFieldLabel } from "@salt-ds/core"; import { CommitResponse, DataItemCommitHandler, -} from "packages/vuu-datagrid-types"; +} from "packages/vuu-table-types"; import { VuuRowDataItemType } from "packages/vuu-protocol-types"; import { HTMLAttributes, useCallback } from "react"; import { BasketSelector, BasketSelectorProps } from "../basket-selector"; 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 e1db44aba..59752c338 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 @@ -1,4 +1,4 @@ -import { TableCellProps } from "@finos/vuu-datagrid-types"; +import { TableCellProps } from "@finos/vuu-table-types"; import { isColumnTypeRenderer, isTypeDescriptor, diff --git a/vuu-ui/sample-apps/feature-basket-trading/src/cell-renderers/spread-cell/SpreadCell.tsx b/vuu-ui/sample-apps/feature-basket-trading/src/cell-renderers/spread-cell/SpreadCell.tsx index 60eb8b788..bd197e16b 100644 --- a/vuu-ui/sample-apps/feature-basket-trading/src/cell-renderers/spread-cell/SpreadCell.tsx +++ b/vuu-ui/sample-apps/feature-basket-trading/src/cell-renderers/spread-cell/SpreadCell.tsx @@ -1,4 +1,4 @@ -import { TableCellProps } from "@finos/vuu-datagrid-types"; +import { TableCellProps } from "@finos/vuu-table-types"; import { registerComponent } from "@finos/vuu-utils"; import { CSSProperties } from "react"; 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 36affddd0..e5c754296 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,4 +1,4 @@ -import { TableCellRendererProps } from "@finos/vuu-datagrid-types"; +import { TableCellRendererProps } from "@finos/vuu-table-types"; import { registerComponent } from "@finos/vuu-utils"; import cx from "classnames"; diff --git a/vuu-ui/sample-apps/feature-filter-table/package.json b/vuu-ui/sample-apps/feature-filter-table/package.json index fc3226622..4bb804700 100644 --- a/vuu-ui/sample-apps/feature-filter-table/package.json +++ b/vuu-ui/sample-apps/feature-filter-table/package.json @@ -18,7 +18,7 @@ "dependencies": { "@finos/vuu-data": "0.0.26", "@finos/vuu-data-react": "0.0.26", - "@finos/vuu-datagrid-types": "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", 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 3659e1630..df41bdc08 100644 --- a/vuu-ui/sample-apps/feature-filter-table/src/useFilterTable.tsx +++ b/vuu-ui/sample-apps/feature-filter-table/src/useFilterTable.tsx @@ -5,7 +5,7 @@ import { } from "@finos/vuu-data"; import { MenuActionConfig, useVuuMenuActions } from "@finos/vuu-data-react"; import { DataSourceFilter } from "@finos/vuu-data-types"; -import { TableConfig } from "@finos/vuu-datagrid-types"; +import { TableConfig } from "@finos/vuu-table-types"; import { Filter } from "@finos/vuu-filter-types"; import { FilterBarProps } from "@finos/vuu-filters"; import { ActiveItemChangeHandler, useViewContext } from "@finos/vuu-layout"; diff --git a/vuu-ui/sample-apps/feature-instrument-tiles/package.json b/vuu-ui/sample-apps/feature-instrument-tiles/package.json index f13325c2d..19b1c2d69 100644 --- a/vuu-ui/sample-apps/feature-instrument-tiles/package.json +++ b/vuu-ui/sample-apps/feature-instrument-tiles/package.json @@ -18,7 +18,7 @@ "dependencies": { "@finos/vuu-data": "0.0.26", "@finos/vuu-data-react": "0.0.26", - "@finos/vuu-datagrid-types": "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", diff --git a/vuu-ui/sample-apps/feature-template/package.json b/vuu-ui/sample-apps/feature-template/package.json index 456fd94de..5a07fbb94 100644 --- a/vuu-ui/sample-apps/feature-template/package.json +++ b/vuu-ui/sample-apps/feature-template/package.json @@ -18,7 +18,7 @@ "dependencies": { "@finos/vuu-data": "0.0.26", "@finos/vuu-data-react": "0.0.26", - "@finos/vuu-datagrid-types": "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", diff --git a/vuu-ui/scripts/build-all.mjs b/vuu-ui/scripts/build-all.mjs index c7e38bb88..65e124171 100644 --- a/vuu-ui/scripts/build-all.mjs +++ b/vuu-ui/scripts/build-all.mjs @@ -11,7 +11,7 @@ export const buildAll = async () => { const wave1 = [ "vuu-data-test", "vuu-data-types", - "vuu-datagrid-types", + "vuu-table-types", "vuu-filter-types", "vuu-filter-parser", "vuu-protocol-types", diff --git a/vuu-ui/scripts/publish.mjs b/vuu-ui/scripts/publish.mjs index 433c3c330..8e4d6bd90 100644 --- a/vuu-ui/scripts/publish.mjs +++ b/vuu-ui/scripts/publish.mjs @@ -11,7 +11,7 @@ const packages = [ "vuu-data-test", "vuu-data-types", "vuu-table-extras", - "vuu-datagrid-types", + "vuu-table-types", "vuu-table", "vuu-filter-types", "vuu-filter-parser", diff --git a/vuu-ui/showcase/src/examples/DataTable/FilterTable.examples.tsx b/vuu-ui/showcase/src/examples/DataTable/FilterTable.examples.tsx index fd71a4839..c3928a789 100644 --- a/vuu-ui/showcase/src/examples/DataTable/FilterTable.examples.tsx +++ b/vuu-ui/showcase/src/examples/DataTable/FilterTable.examples.tsx @@ -1,16 +1,22 @@ import { FilterTable } from "@finos/vuu-datatable"; -import { TableConfig } from "@finos/vuu-datagrid-types"; +import { TableConfig } from "@finos/vuu-table-types"; import { Filter } from "@finos/vuu-filter-types"; -import { useCallback, useState } from "react"; -import { useTableConfig, useTestDataSource } from "../utils"; +import { useCallback, useMemo, useState } from "react"; +import { useTestDataSource } from "../utils"; import { DataSourceFilter } from "@finos/vuu-data-types"; -import { getAllSchemas, getSchema } from "@finos/vuu-data-test"; +import { + getAllSchemas, + getSchema, + SimulTableName, + vuuModule, +} from "@finos/vuu-data-test"; import { ActiveItemChangeHandler } from "packages/vuu-layout/src"; +import { TableProps } from "packages/vuu-table/src"; let displaySequence = 1; +const schemas = getAllSchemas(); export const DefaultFilterTable = () => { - const schemas = getAllSchemas(); const { config, dataSource, error, tableSchema } = useTestDataSource({ // bufferSize: 1000, schemas, @@ -73,14 +79,21 @@ export const DefaultFilterTable = () => { DefaultFilterTable.displaySequence = displaySequence++; export const FilterTableArrayDataInstruments = () => { - const { - typeaheadHook: _, - config: configProp, - dataSource, - ...props - } = useTableConfig({ - table: { module: "SIMUL", table: "instruments" }, - }); + const schema = schemas.instruments; + const { dataSource, ...restTableProps } = useMemo< + Pick + >( + () => ({ + config: { + columns: schema.columns, + rowSeparators: true, + zebraStripes: true, + }, + dataSource: + vuuModule("SIMUL").createDataSource("instruments"), + }), + [schema] + ); const handleApplyFilter = useCallback( (filter: DataSourceFilter) => { @@ -107,9 +120,8 @@ export const FilterTableArrayDataInstruments = () => { }; const tableProps = { - config: configProp, + ...restTableProps, dataSource, - ...props, height: 645, renderBufferSize: 20, width: 715, diff --git a/vuu-ui/showcase/src/examples/Filters/FilterBar/FilterBar.examples.tsx b/vuu-ui/showcase/src/examples/Filters/FilterBar/FilterBar.examples.tsx index b48976fc0..4c6f49892 100644 --- a/vuu-ui/showcase/src/examples/Filters/FilterBar/FilterBar.examples.tsx +++ b/vuu-ui/showcase/src/examples/Filters/FilterBar/FilterBar.examples.tsx @@ -1,10 +1,9 @@ import { FilterBar } from "@finos/vuu-filters"; import { Filter } from "@finos/vuu-filter-types"; import { useCallback, useEffect, useRef, useState } from "react"; -import { useTableConfig } from "../../utils"; import { DataSourceFilter } from "@finos/vuu-data-types"; import { Input } from "@salt-ds/core"; -import { getSchema } from "@finos/vuu-data-test"; +import { getSchema, vuuModule } from "@finos/vuu-data-test"; import { ActiveItemChangeHandler } from "packages/vuu-layout/src"; let displaySequence = 1; @@ -18,10 +17,7 @@ export const DefaultFilterBar = ({ const [filterStruct, setFilterStruct] = useState(null); const inputRef = useRef(null); const tableSchema = getSchema("instruments"); - const { typeaheadHook } = useTableConfig({ - rangeChangeRowset: "full", - table: { module: "SIMUL", table: "instruments" }, - }); + const { typeaheadHook } = vuuModule("SIMUL"); const handleApplyFilter = useCallback((filter: DataSourceFilter) => { setFilterStruct(filter.filterStruct ?? null); diff --git a/vuu-ui/showcase/src/examples/Filters/FilterBar/FilterClause.examples.tsx b/vuu-ui/showcase/src/examples/Filters/FilterBar/FilterClause.examples.tsx index 79fdb6454..c530ba3e8 100644 --- a/vuu-ui/showcase/src/examples/Filters/FilterBar/FilterClause.examples.tsx +++ b/vuu-ui/showcase/src/examples/Filters/FilterBar/FilterClause.examples.tsx @@ -1,5 +1,5 @@ -import { getSchema } from "@finos/vuu-data-test"; -import { ColumnDescriptor } from "@finos/vuu-datagrid-types"; +import { getSchema, vuuModule } from "@finos/vuu-data-test"; +import { ColumnDescriptor } from "@finos/vuu-table-types"; import { FilterClause } from "@finos/vuu-filter-types"; import { ExpandoCombobox, @@ -13,7 +13,7 @@ import { SingleSelectionHandler, } from "@finos/vuu-ui-controls"; import { ChangeEvent, useCallback, useMemo, useState } from "react"; -import { useAutoLoginToVuuServer, useTableConfig } from "../../utils"; +import { useAutoLoginToVuuServer } from "../../utils"; import "./FilterClause.examples.css"; @@ -82,10 +82,7 @@ DefaultExpandoComboBoxHighlightFirstRow.displaySequence = displaySequence++; export const DataBoundTextInputEmpty = () => { const tableSchema = getSchema("instruments"); - const { typeaheadHook } = useTableConfig({ - rangeChangeRowset: "full", - table: { module: "SIMUL", table: "instruments" }, - }); + const { typeaheadHook } = vuuModule("SIMUL"); const column: ColumnDescriptor = useMemo( () => ({ name: "currency", serverDataType: "string" }), @@ -119,10 +116,7 @@ DataBoundTextInputEmpty.displaySequence = displaySequence++; export const DataBoundTextInputLoaded = () => { const tableSchema = getSchema("instruments"); - const { typeaheadHook } = useTableConfig({ - rangeChangeRowset: "full", - table: { module: "SIMUL", table: "instruments" }, - }); + const { typeaheadHook } = vuuModule("SIMUL"); const column: ColumnDescriptor = useMemo( () => ({ name: "currency", serverDataType: "string" }), @@ -182,11 +176,7 @@ MultiSelectExpandoComboBox.displaySequence = displaySequence++; export const NewFilterClause = () => { const tableSchema = getSchema("instruments"); - const { typeaheadHook } = useTableConfig({ - count: 100_000, - rangeChangeRowset: "full", - table: { module: "SIMUL", table: "instruments" }, - }); + const { typeaheadHook } = vuuModule("SIMUL"); const onChange = (filterClause: Partial) => console.log("Filter Change", filterClause); diff --git a/vuu-ui/showcase/src/examples/Filters/FilterInput/FilterInput.examples.tsx b/vuu-ui/showcase/src/examples/Filters/FilterInput/FilterInput.examples.tsx index 202b2fc32..4f1274a47 100644 --- a/vuu-ui/showcase/src/examples/Filters/FilterInput/FilterInput.examples.tsx +++ b/vuu-ui/showcase/src/examples/Filters/FilterInput/FilterInput.examples.tsx @@ -15,20 +15,11 @@ import { Dropdown, SelectionChangeHandler } from "@salt-ds/lab"; import { Button } from "@salt-ds/core"; import { useCallback, useMemo, useState } from "react"; import { useAutoLoginToVuuServer } from "../../utils/useAutoLoginToVuuServer"; +import { getSchema } from "@finos/vuu-data-test"; let displaySequence = 1; -const table = { module: "SIMUL", table: "instruments" }; - -const schemaColumns = [ - { name: "bbg", serverDataType: "string" } as const, - { name: "description", serverDataType: "string" } as const, - { name: "currency", serverDataType: "string" } as const, - { name: "exchange", serverDataType: "string" } as const, - { name: "lotSize", serverDataType: "int" } as const, - { name: "isin", serverDataType: "string" } as const, - { name: "ric", serverDataType: "string" } as const, -]; +const { columns, table } = getSchema("instruments"); export const DefaultFilterInput = () => { const namedFilters = useMemo(() => new Map(), []); @@ -37,7 +28,7 @@ export const DefaultFilterInput = () => { filterQuery: "", }); const suggestionProvider = useFilterSuggestionProvider({ - columns: schemaColumns, + columns, namedFilters, table, }); @@ -107,7 +98,7 @@ export const DefaultFilterInputWithPersistence = () => { filterQuery: "", }); const suggestionProvider = useFilterSuggestionProvider({ - columns: schemaColumns, + columns, namedFilters, table, }); @@ -209,7 +200,7 @@ export const FilterInputTabs = () => { filterQuery: "", }); const suggestionProvider = useFilterSuggestionProvider({ - columns: schemaColumns, + columns, namedFilters, saveOptions, table, diff --git a/vuu-ui/showcase/src/examples/Shell/SessionTableEditing.examples.tsx b/vuu-ui/showcase/src/examples/Shell/SessionTableEditing.examples.tsx index 6c2e3063e..3f950a9d4 100644 --- a/vuu-ui/showcase/src/examples/Shell/SessionTableEditing.examples.tsx +++ b/vuu-ui/showcase/src/examples/Shell/SessionTableEditing.examples.tsx @@ -7,7 +7,7 @@ import { import { VuuColumnDataType } from "@finos/vuu-protocol-types"; import { HTMLAttributes, MouseEventHandler, useMemo, useState } from "react"; import { SessionEditingForm } from "@finos/vuu-shell"; -import { ColumnDescriptor } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor } from "@finos/vuu-table-types"; import { ArrayDataSource, DataSource } from "@finos/vuu-data"; import { ContextMenuItemDescriptor, diff --git a/vuu-ui/showcase/src/examples/Table/BasketTables.examples.tsx b/vuu-ui/showcase/src/examples/Table/BASKET.examples.tsx similarity index 100% rename from vuu-ui/showcase/src/examples/Table/BasketTables.examples.tsx rename to vuu-ui/showcase/src/examples/Table/BASKET.examples.tsx diff --git a/vuu-ui/showcase/src/examples/Table/DemoTableContainer.tsx b/vuu-ui/showcase/src/examples/Table/DemoTableContainer.tsx new file mode 100644 index 000000000..a0ec8f914 --- /dev/null +++ b/vuu-ui/showcase/src/examples/Table/DemoTableContainer.tsx @@ -0,0 +1,35 @@ +import { Flexbox, LayoutProvider, View } from "@finos/vuu-layout"; +import { ContextPanel } from "@finos/vuu-shell"; +import { Table } from "@finos/vuu-table"; +import { ReactElement } from "react"; +import { registerComponent } from "@finos/vuu-layout"; + +import { + ColumnSettingsPanel, + TableSettingsPanel, +} from "@finos/vuu-table-extras"; + +if ( + typeof ColumnSettingsPanel !== "function" || + typeof TableSettingsPanel !== "function" +) { + console.warn("unable to load all required components"); +} else { + registerComponent("ColumnSettings", ColumnSettingsPanel, "view"); + registerComponent("TableSettings", TableSettingsPanel, "view"); +} + +export const DemoTableContainer = ({ + children, +}: { + children: ReactElement; +}) => { + return ( + + + {children} + + + + ); +}; diff --git a/vuu-ui/showcase/src/examples/Table/SIMUL.examples.tsx b/vuu-ui/showcase/src/examples/Table/SIMUL.examples.tsx index d227f72c8..200ef5887 100644 --- a/vuu-ui/showcase/src/examples/Table/SIMUL.examples.tsx +++ b/vuu-ui/showcase/src/examples/Table/SIMUL.examples.tsx @@ -4,11 +4,16 @@ import { ContextMenuProvider } from "@finos/vuu-popups"; import { DefaultColumnConfiguration } from "@finos/vuu-shell"; import { Table, TableProps } from "@finos/vuu-table"; import { applyDefaultColumnConfig } from "@finos/vuu-utils"; +import { ColumnDescriptor } from "packages/vuu-table-types"; import { useCallback, useMemo } from "react"; +import { DemoTableContainer } from "./DemoTableContainer"; let displaySequence = 1; -const getDefaultColumnConfig = (tableName: string, columnName: string) => { +const getDefaultColumnConfig = ( + tableName: string, + columnName: string +): Partial | undefined => { switch (columnName) { case "ask": case "bid": @@ -81,11 +86,13 @@ const SimulTable = ({ menuActionHandler={handleMenuAction} menuBuilder={buildViewserverMenuOptions} > - + +
+ ); }; @@ -93,6 +100,11 @@ const SimulTable = ({ export const Instruments = () => ; Instruments.displaySequence = displaySequence++; +export const InstrumentsExtended = () => ( + +); +InstrumentsExtended.displaySequence = displaySequence++; + export const Prices = () => { return ( { ); const tableProps = useMemo>(() => { - const tableName: SimulTableName = "instruments"; + const tableName: SimulTableName = "instrumentsExtended"; return { config: { columns: applyDefaultColumnConfig( @@ -215,7 +220,7 @@ export const EditableTableNextArrayData = () => { }, [getDefaultColumnConfig]); return ( -
+
); }; EditableTableNextArrayData.displaySequence = displaySequence++; @@ -246,18 +251,23 @@ export const TableNextVuuInstruments = () => { TableNextVuuInstruments.displaySequence = displaySequence++; export const FlexLayoutTables = () => { - const { typeaheadHook: _1, ...config1 } = useTableConfig({ - renderBufferSize: 0, - }); - const { typeaheadHook: _2, ...config2 } = useTableConfig({ - renderBufferSize: 20, - }); - const { typeaheadHook: _3, ...config3 } = useTableConfig({ - renderBufferSize: 50, - }); - const { typeaheadHook: _4, ...config4 } = useTableConfig({ - renderBufferSize: 100, - }); + const tableConfig = useMemo(() => { + return { + columns: getSchema("instruments").columns, + rowSeparators: true, + zebraStripes: true, + }; + }, []); + + const [ds1, ds2, ds3, ds4] = useMemo(() => { + return [ + vuuModule("SIMUL").createDataSource("instruments"), + vuuModule("SIMUL").createDataSource("instruments"), + vuuModule("SIMUL").createDataSource("instruments"), + vuuModule("SIMUL").createDataSource("instruments"), + ]; + }, []); + return ( { > -
+
-
+
-
+
-
+
@@ -292,19 +302,26 @@ export const TableNextInLayoutWithContextPanel = () => { registerComponent("ColumnSettings", ColumnSettingsPanel, "view"); registerComponent("TableSettings", TableSettingsPanel, "view"); }, []); - const { - typeaheadHook: _, - config, - ...props - } = useTableConfig({ - rangeChangeRowset: "full", - table: { module: "SIMUL", table: "instruments" }, - }); + const tableConfig = useMemo(() => { + return { + columns: getSchema("instruments").columns, + rowSeparators: true, + zebraStripes: true, + }; + }, []); + const dataSource = useMemo(() => { + return vuuModule("SIMUL").createDataSource("instruments"); + }, []); return ( -
+
@@ -313,44 +330,34 @@ export const TableNextInLayoutWithContextPanel = () => { TableNextInLayoutWithContextPanel.displaySequence = displaySequence++; export const AutoTableNext = () => { - const { - typeaheadHook: _, - config: configProp, - ...props - } = useTableConfig({ - rangeChangeRowset: "full", - table: { module: "SIMUL", table: "instruments" }, - }); - - const [config] = useState(configProp); + const tableConfig = useMemo(() => { + return { + columns: getSchema("instruments").columns, + rowSeparators: true, + zebraStripes: true, + }; + }, []); + const dataSource = useMemo(() => { + return vuuModule("SIMUL").createDataSource("instruments"); + }, []); return ( -
+
); }; AutoTableNext.displaySequence = displaySequence++; export const AutoTableNextAsFlexChild = () => { - const { - typeaheadHook: _, - config: configProp, - ...props - } = useTableConfig({ - rangeChangeRowset: "full", - table: { module: "SIMUL", table: "instruments" }, - }); - - const [config, setConfig] = useState(configProp); - - const handleConfigChange = (config: TableConfig) => { - setConfig(config); - }; + const tableConfig = useMemo(() => { + return { + columns: getSchema("instruments").columns, + rowSeparators: true, + zebraStripes: true, + }; + }, []); + const dataSource = useMemo(() => { + return vuuModule("SIMUL").createDataSource("instruments"); + }, []); return (
{ >
@@ -378,99 +382,7 @@ export const AutoTableNextAsFlexChild = () => { }; AutoTableNextAsFlexChild.displaySequence = displaySequence++; -// export const AutoTableNextBasketDesign = () => { -// const { -// typeaheadHook: _, -// config: configProp, -// ...props -// } = useTableConfig({ -// rangeChangeRowset: "delta", -// table: { module: "BASKET", table: "basketDesign" }, -// }); - -// const [config, setConfig] = useState(configProp); - -// const handleConfigChange = (config: TableConfig) => { -// setConfig(config); -// }; - -// return ( -// -// ); -// }; -// AutoTableNextBasketDesign.displaySequence = displaySequence++; - -export const AutoTableNextBasketOrders = () => { - const { - typeaheadHook: _, - config: configProp, - ...props - } = useTableConfig({ - table: { module: "SIMUL", table: "basketOrders" }, - }); - - const [config, setConfig] = useState(configProp); - - const handleConfigChange = (config: TableConfig) => { - setConfig(config); - }; - - return ( -
- ); -}; -AutoTableNextBasketOrders.displaySequence = displaySequence++; - -export const AutoTableNextBasketDefinitions = () => { - const { - typeaheadHook: _, - config: configProp, - ...props - } = useTableConfig({ - count: 5, - table: { module: "SIMUL", table: "basketDefinitions" }, - }); - - const [config, setConfig] = useState(configProp); - - const handleConfigChange = (config: TableConfig) => { - setConfig(config); - }; - - return ( -
- ); -}; -AutoTableNextBasketDefinitions.displaySequence = displaySequence++; - -export const vuuTableCalculatedColumns = () => { +export const VuuTableCalculatedColumns = () => { const calculatedColumns: ColumnDescriptor[] = useMemo( () => [ { @@ -549,7 +461,7 @@ export const vuuTableCalculatedColumns = () => { /> ); }; -vuuTableCalculatedColumns.displaySequence = displaySequence++; +VuuTableCalculatedColumns.displaySequence = displaySequence++; export const GroupHeaderCellNextOneColumn = () => { const column: GroupColumnDescriptor = useMemo(() => { diff --git a/vuu-ui/showcase/src/examples/Table/TableLayout.examples.tsx b/vuu-ui/showcase/src/examples/Table/TableLayout.examples.tsx new file mode 100644 index 000000000..0eb9edba2 --- /dev/null +++ b/vuu-ui/showcase/src/examples/Table/TableLayout.examples.tsx @@ -0,0 +1,136 @@ +import { + Selection, + SelectionChangeHandler, + TableConfig, +} from "@finos/vuu-table-types"; +import { Table, TableProps } from "@finos/vuu-table"; +import { DockLayout, Drawer } from "@finos/vuu-layout"; +import { useCallback, useMemo, useRef, useState } from "react"; +import { List, ListItem } from "@salt-ds/lab"; +import { getSchema, SimulTableName, vuuModule } from "@finos/vuu-data-test"; +import { applyDefaultColumnConfig } from "@finos/vuu-utils"; +import { DefaultColumnConfiguration } from "@finos/vuu-shell"; + +let displaySequence = 1; + +export const DataTable = (props: Partial) => { + const tableConfig = useMemo(() => { + return { + columns: getSchema("instruments").columns, + rowSeparators: true, + zebraStripes: true, + }; + }, []); + const dataSource = useMemo(() => { + return vuuModule("SIMUL").createDataSource("instruments"); + }, []); + return ( + <> +
+ + ); +}; + +DataTable.displaySequence = displaySequence++; + +type InlineDrawerProps = { + inline?: boolean; + position: "left" | "right" | "top" | "bottom"; + peekaboo?: boolean; +}; + +const InlineDrawer = ({ + inline = false, + position, + peekaboo = false, +}: InlineDrawerProps) => { + const list = useRef(null); + const [open, setOpen] = useState(false); + + const handleSelectionChange: SelectionChangeHandler = useCallback( + (selection: Selection) => { + if (selection.length > 0) { + setOpen(true); + } else { + setOpen(false); + } + }, + [] + ); + + return ( + + +
+ + Item 1 + Item 2 + Item 3 + Item 4 + Item 5 + Item 6 + +
+
+ +
+ ); +}; + +export const RightInlineDrawerPeek = () => ( + +); +RightInlineDrawerPeek.displaySequence = displaySequence++; + +export const SingleHeadingRow = () => { + const tableProps = useMemo>(() => { + const tableName: SimulTableName = "instruments"; + return { + // prettier-ignore + config: { + columns: [ + // { name: "bbg", serverDataType: "string" }, + // { name: "isin", serverDataType: "string" }, + // { name: "ric", serverDataType: "string" }, + // { name: "description", serverDataType: "string" }, + // { name: "currency", serverDataType: "string" }, + // { name: "exchange", serverDataType: "string" }, + // { name: "lotSize", serverDataType: "int" }, + { name: "bbg", heading: ["Instrument"], serverDataType: "string" }, + { name: "isin", heading: ["Instrument"], serverDataType: "string" }, + { name: "ric", heading: ["Instrument"], serverDataType: "string" }, + { name: "description", heading: ["Instrument"], serverDataType: "string" }, + { name: "currency", heading: ["Exchange Details"], serverDataType: "string" }, + { name: "exchange", heading: ["Exchange Details"], serverDataType: "string" }, + { name: "lotSize", heading: ["Exchange Details"], serverDataType: "int" }, + ], + rowSeparators: true, + zebraStripes: true, + }, + dataSource: + vuuModule("SIMUL").createDataSource(tableName), + }; + }, []); + + return ( +
+ ); +}; +SingleHeadingRow.displaySequence = displaySequence++; diff --git a/vuu-ui/showcase/src/examples/Table/TableList.examples.tsx b/vuu-ui/showcase/src/examples/Table/TableList.examples.tsx index f5bcfa9eb..723f99c90 100644 --- a/vuu-ui/showcase/src/examples/Table/TableList.examples.tsx +++ b/vuu-ui/showcase/src/examples/Table/TableList.examples.tsx @@ -1,7 +1,7 @@ import { Table } from "@finos/vuu-table"; import { ArrayDataSource } from "@finos/vuu-data"; import { useMemo } from "react"; -import { ColumnDescriptor } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor } from "@finos/vuu-table-types"; let displaySequence = 1; diff --git a/vuu-ui/showcase/src/examples/Table/index.ts b/vuu-ui/showcase/src/examples/Table/index.ts index d64594512..55ccc428b 100644 --- a/vuu-ui/showcase/src/examples/Table/index.ts +++ b/vuu-ui/showcase/src/examples/Table/index.ts @@ -1,4 +1,5 @@ export * as TableList from "./TableList.examples"; -export * as TableNext from "./TableNext.examples"; -export * as BasketTables from "./BasketTables.examples"; +export * as Table from "./Table.examples"; +export * as BASKET from "./BASKET.examples"; export * as SIMUL from "./SIMUL.examples"; +export * as TableLayout from "./TableLayout.examples"; diff --git a/vuu-ui/showcase/src/examples/TableExtras/ColumnExpressionPanel.examples.tsx b/vuu-ui/showcase/src/examples/TableExtras/ColumnExpressionPanel.examples.tsx index 0e6abed1b..c2ade4fbb 100644 --- a/vuu-ui/showcase/src/examples/TableExtras/ColumnExpressionPanel.examples.tsx +++ b/vuu-ui/showcase/src/examples/TableExtras/ColumnExpressionPanel.examples.tsx @@ -1,37 +1,25 @@ -import { - ColumnExpressionPanel, - ColumnExpressionSubmitHandler, -} from "@finos/vuu-table-extras"; -import { useCallback } from "react"; -import { useTableConfig } from "../utils"; +import { ColumnExpressionPanel } from "@finos/vuu-table-extras"; +import { getSchema } from "@finos/vuu-data-test"; +import { TableConfig } from "@finos/vuu-table-types"; +import { useMemo } from "react"; const instrumentPrices = { module: "SIMUL", table: "instrumentPrices" }; let displaySequence = 1; export const DefaultColumnExpressionPanel = () => { - const { config: tableConfig } = useTableConfig({ - rangeChangeRowset: "full", - table: instrumentPrices, - }); - - const handleChange = useCallback((columnName: string) => { - console.log(columnName); + const tableConfig = useMemo(() => { + return { + columns: getSchema("instrumentPrices").columns, + rowSeparators: true, + zebraStripes: true, + }; }, []); - const handleSubmitExpression = useCallback( - (columnName: string) => { - console.log(columnName); - }, - [] - ); - return (
diff --git a/vuu-ui/showcase/src/examples/TableExtras/ColumnSettings/ColumnSettings.examples.tsx b/vuu-ui/showcase/src/examples/TableExtras/ColumnSettings/ColumnSettings.examples.tsx index d0d1f17c7..ed0672e09 100644 --- a/vuu-ui/showcase/src/examples/TableExtras/ColumnSettings/ColumnSettings.examples.tsx +++ b/vuu-ui/showcase/src/examples/TableExtras/ColumnSettings/ColumnSettings.examples.tsx @@ -1,5 +1,5 @@ import { getSchema } from "@finos/vuu-data-test"; -import { ColumnDescriptor, TableConfig } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor, TableConfig } from "@finos/vuu-table-types"; import { ColumnFormattingPanel, ColumnSettingsPanel, @@ -37,8 +37,7 @@ export const ColumnFormattingPanelDouble = () => { setColumn((col) => ({ ...col, type: { - // TODO - ...col.type, + ...(typeof col.type === "object" ? col.type : { name: col.type }), renderer, }, })); diff --git a/vuu-ui/showcase/src/examples/TableExtras/TableSettings/TableSettings.examples.tsx b/vuu-ui/showcase/src/examples/TableExtras/TableSettings/TableSettings.examples.tsx index f076b5141..6774d4e71 100644 --- a/vuu-ui/showcase/src/examples/TableExtras/TableSettings/TableSettings.examples.tsx +++ b/vuu-ui/showcase/src/examples/TableExtras/TableSettings/TableSettings.examples.tsx @@ -4,7 +4,7 @@ import { TableSettingsPanel, } from "@finos/vuu-table-extras"; import { SchemaColumn } from "@finos/vuu-data"; -import { TableConfig } from "@finos/vuu-datagrid-types"; +import { TableConfig } from "@finos/vuu-table-types"; import { useMemo } from "react"; let displaySequence = 1; diff --git a/vuu-ui/showcase/src/examples/UiControls/InstrumentPicker.examples.tsx b/vuu-ui/showcase/src/examples/UiControls/InstrumentPicker.examples.tsx index d56eb2e5a..1c3ed4f6e 100644 --- a/vuu-ui/showcase/src/examples/UiControls/InstrumentPicker.examples.tsx +++ b/vuu-ui/showcase/src/examples/UiControls/InstrumentPicker.examples.tsx @@ -8,7 +8,7 @@ import { import { buildColumnMap, ColumnMap } from "@finos/vuu-utils"; import { useCallback, useMemo } from "react"; import { TableProps, TableRowSelectHandler } from "@finos/vuu-table"; -import { ColumnDescriptor } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor } from "@finos/vuu-table-types"; import { useTestDataSource } from "../utils"; import { DataSourceRow } from "packages/vuu-data-types"; diff --git a/vuu-ui/showcase/src/examples/VuuFeatures/NewBasketPanel.examples.tsx b/vuu-ui/showcase/src/examples/VuuFeatures/NewBasketPanel.examples.tsx index 2b553320c..4e22998b2 100644 --- a/vuu-ui/showcase/src/examples/VuuFeatures/NewBasketPanel.examples.tsx +++ b/vuu-ui/showcase/src/examples/VuuFeatures/NewBasketPanel.examples.tsx @@ -1,4 +1,4 @@ -import { createArrayDataSource, getSchema } from "@finos/vuu-data-test"; +import { BasketsTableName, getSchema, vuuModule } from "@finos/vuu-data-test"; import { NewBasketPanel } from "feature-basket-trading"; import { useCallback, useMemo } from "react"; @@ -8,8 +8,8 @@ export const DefaultNewBasketPanel = () => { const schema = getSchema("basket"); const dataSource = useMemo( - () => createArrayDataSource({ count: 4, table: schema.table }), - [schema.table] + () => vuuModule("BASKET").createDataSource("basket"), + [] ); const saveBasket = useCallback((basketName: string, basketId: string) => { diff --git a/vuu-ui/showcase/src/examples/utils/index.ts b/vuu-ui/showcase/src/examples/utils/index.ts index cf42024c2..a71de83f3 100644 --- a/vuu-ui/showcase/src/examples/utils/index.ts +++ b/vuu-ui/showcase/src/examples/utils/index.ts @@ -2,5 +2,4 @@ export * from "./ArrayLike"; export * from "./ArrayProxy"; export * from "./ErrorDisplay"; export * from "./useAutoLoginToVuuServer"; -export * from "./useTableConfig"; export * from "./useTestDataSource"; diff --git a/vuu-ui/showcase/src/examples/utils/useTableConfig.ts b/vuu-ui/showcase/src/examples/utils/useTableConfig.ts deleted file mode 100644 index 0e7f898ce..000000000 --- a/vuu-ui/showcase/src/examples/utils/useTableConfig.ts +++ /dev/null @@ -1,159 +0,0 @@ -import { DataSourceConfig } from "@finos/vuu-data"; -import { SuggestionFetcher } from "@finos/vuu-data-react"; -import { ColumnDescriptor } from "@finos/vuu-datagrid-types"; -import { - TypeaheadParams, - VuuRowDataItemType, - VuuTable, -} from "@finos/vuu-protocol-types"; -import { useMemo } from "react"; -import { ArrayProxy } from "./ArrayProxy"; -import { makeSuggestions } from "./makeSuggestions"; -import { TickingArrayDataSource } from "@finos/vuu-data-test"; -import { getColumnAndRowGenerator, populateArray } from "@finos/vuu-data-test"; - -const NO_CONFIG = {} as const; -const NO_COLUMNS: number[] = []; - -export type ExtendedColumnConfig = { [key: string]: Partial }; - -export interface TableConfigHookProps { - /** - * Additional column configuration to be applied to the base SchemaColumn - * SchemaColumn provides just name and serverDataType. ANy of the attributes - * defined on ColumnDescriptor can be added here e.g width, label, type - */ - columnConfig?: ExtendedColumnConfig; - /** - * When simple column generation is in effect - number of columns to generate - */ - columnCount?: number; - /** - * number of rows to generate - */ - count?: number; - /** - * Only intended to generate large datasets to test extreme scrolling (in the - * millions of rows). Generates rows of data on demand, no internal state, so - * cannot support sorting, grouping etc. Uses an ArrayProxy - */ - dataSourceConfig?: DataSourceConfig; - lazyData?: boolean; - leftPinnedColumns?: number[]; - rightPinnedColumns?: number[]; - /** - * should a range request respond with the full set of rows for the viewport or - * just those rows which have nor previously been returned, the delta, Delta is - * the default. - */ - rangeChangeRowset?: "delta" | "full"; - /** - * How many rows to render offscreen for better scroll render performance, without - * whiteout - */ - renderBufferSize?: number; - /** - * An alternative to columnCount, must be a known table, for which a custom data- - * generator is available. - */ - table?: VuuTable; -} - -export const useTableConfig = ({ - columnConfig = NO_CONFIG, - columnCount, - count = 1000, - dataSourceConfig, - lazyData = false, - leftPinnedColumns = NO_COLUMNS, - rangeChangeRowset = "delta", - rightPinnedColumns = NO_COLUMNS, - renderBufferSize = 0, - table, -}: TableConfigHookProps = {}) => { - return useMemo(() => { - if (typeof columnCount === "number" && table) { - throw Error( - `If a VuuTable is passed, columnCount should not be provided. - Only pass a Vuu table if a custom data generator is available - for that table` - ); - } - // Get custom data and column generators (if a table is available) otw the default - // data generators will be returned - const [columnGenerator, rowGenerator, createUpdateGenerator] = - getColumnAndRowGenerator(table); - - // colCount is only used by the default generators - const colCount = - typeof columnCount === "number" - ? columnCount - : typeof table === "undefined" - ? 10 - : undefined; - - const columns = table - ? columnGenerator(dataSourceConfig?.columns ?? [], columnConfig) - : columnGenerator(colCount, columnConfig); - - // We use an ArrayProxy in the rare scenario that we want a large dataset with no - // support for sorting etc. Normally, we want to use a data generator to produce - // test data to populate an ArrayDataSource - const dataArray = lazyData - ? new ArrayProxy( - count, - rowGenerator(columns?.map((col) => col.name)) - ) - : populateArray( - count, - columnGenerator, - rowGenerator, - colCount ?? columns?.map((col) => col.name) - ); - - leftPinnedColumns.forEach((index) => (columns[index].pin = "left")); - rightPinnedColumns.forEach((index) => (columns[index].pin = "right")); - - const dataSource = new TickingArrayDataSource({ - ...dataSourceConfig, - columnDescriptors: columns, - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore yes we know an ArrayProxy is not a real Array, but don't tell the DataSource that - data: dataArray, - rangeChangeRowset, - updateGenerator: createUpdateGenerator?.(), - }); - - /* We omit the first array argument, table, not needed here but we must - preserve the function signature. This function will be passed to - another hook which will call it at the right time and will pass three - arguments in the array - */ - const suggestionFetcher: SuggestionFetcher = async ([ - , - column, - pattern, - ]: TypeaheadParams) => { - if (lazyData) { - return []; - } else { - return makeSuggestions(dataSource, column, pattern); - } - }; - - const typeaheadHook = () => suggestionFetcher; - - return { config: { columns }, dataSource, renderBufferSize, typeaheadHook }; - }, [ - columnConfig, - columnCount, - count, - dataSourceConfig, - lazyData, - leftPinnedColumns, - rangeChangeRowset, - renderBufferSize, - rightPinnedColumns, - table, - ]); -}; diff --git a/vuu-ui/showcase/src/examples/utils/useTestDataSource.ts b/vuu-ui/showcase/src/examples/utils/useTestDataSource.ts index f160c00fa..601559bb1 100644 --- a/vuu-ui/showcase/src/examples/utils/useTestDataSource.ts +++ b/vuu-ui/showcase/src/examples/utils/useTestDataSource.ts @@ -1,5 +1,5 @@ import { RemoteDataSource, TableSchema } from "@finos/vuu-data"; -import { ColumnDescriptor } from "@finos/vuu-datagrid-types"; +import { ColumnDescriptor } from "@finos/vuu-table-types"; import { VuuGroupBy, VuuSort } from "@finos/vuu-protocol-types"; import { DataSourceFilter } from "@finos/vuu-data-types"; import { useMemo, useRef } from "react";