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 7b6dc0f6a4..1a46889acf 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,10 @@ 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 = [ +type InstrumentsDataRow = [ bbg, currency, description, @@ -22,7 +24,9 @@ export type InstrumentsDataRow = [ string, number, ric, - price + price, + supported, + wishlist ]; export const InstrumentColumnMap = { @@ -34,6 +38,8 @@ export const InstrumentColumnMap = { number: 5, ric: 6, price: 7, + supported: 8, + wishlist: 9, }; const instruments: InstrumentsDataRow[] = []; @@ -63,8 +69,9 @@ for (const char of chars) { const lotSize = lotsizes[random(0, lotsizes.length - 1)]; const exchange = locations[suffix][1]; - const price = randomPrice(); + const supported = random(0, 1) === 1; + const wishlist = random(0, 1) === 1; instruments.push([ bbg, @@ -75,6 +82,8 @@ for (const char of chars) { lotSize, ric, price, + supported, + wishlist, ]); } } 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 b15bab971b..8ffcebd63c 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 @@ -22,6 +22,9 @@ export const schemas: Readonly>> = { name: "isin", serverDataType: "string" }, { name: "lotSize", serverDataType: "int" }, { name: "ric", serverDataType: "string" }, + { name: "price", serverDataType: "double" }, + { name: "supported", serverDataType: "boolean" }, + { name: "wishlist", serverDataType: "boolean" }, ], key: "ric", table: { module: "SIMUL", table: "instruments" }, diff --git a/vuu-ui/packages/vuu-table/src/table-next/cell-renderers/checkbox-cell/CheckboxCell.tsx b/vuu-ui/packages/vuu-table/src/table-next/cell-renderers/checkbox-cell/CheckboxCell.tsx new file mode 100644 index 0000000000..4a5fe65475 --- /dev/null +++ b/vuu-ui/packages/vuu-table/src/table-next/cell-renderers/checkbox-cell/CheckboxCell.tsx @@ -0,0 +1,39 @@ +import React, { memo, useCallback } from "react"; +import { TableCellRendererProps } from "@finos/vuu-datagrid-types"; +import { CheckboxIcon, WarnCommit } from "@finos/vuu-ui-controls"; +import { Checkbox } from "@salt-ds/core"; +import { dataAndColumnUnchanged } from "../cell-utils"; +import { dispatchCustomEvent, registerComponent } from "@finos/vuu-utils"; + +export const CheckboxCell: React.FC = memo( + ({ column, columnMap, onCommit = WarnCommit, row }) => { + const dataIdx = columnMap[column.name]; + const isChecked = row[dataIdx]; + + const handleCommit = useCallback( + (value) => async (evt: React.MouseEvent) => { + const res = await onCommit(value); + if (res === true) { + dispatchCustomEvent(evt.target as HTMLElement, "vuu-commit"); + } + return res; + }, + [onCommit] + ); + + return ( + + {!!column.editable ? ( + + ) : ( + + )} + + ); + }, + dataAndColumnUnchanged +); + +registerComponent("checkbox-cell", CheckboxCell, "cell-renderer", { + serverDataType: "boolean", +}); diff --git a/vuu-ui/packages/vuu-table/src/table-next/cell-renderers/checkbox-cell/index.ts b/vuu-ui/packages/vuu-table/src/table-next/cell-renderers/checkbox-cell/index.ts new file mode 100644 index 0000000000..00f2fba367 --- /dev/null +++ b/vuu-ui/packages/vuu-table/src/table-next/cell-renderers/checkbox-cell/index.ts @@ -0,0 +1 @@ +export * from "./CheckboxCell"; diff --git a/vuu-ui/packages/vuu-table/src/table-next/cell-renderers/index.ts b/vuu-ui/packages/vuu-table/src/table-next/cell-renderers/index.ts index a7636d1ad3..dfa5e7706d 100644 --- a/vuu-ui/packages/vuu-table/src/table-next/cell-renderers/index.ts +++ b/vuu-ui/packages/vuu-table/src/table-next/cell-renderers/index.ts @@ -1,3 +1,4 @@ +export * from "./checkbox-cell"; export * from "./dropdown-cell"; export * from "./input-cell"; export * from "./lookup-cell"; diff --git a/vuu-ui/packages/vuu-ui-controls/src/list/CheckboxIcon.css b/vuu-ui/packages/vuu-ui-controls/src/list/CheckboxIcon.css index 1a17570745..2de9bef6b7 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/list/CheckboxIcon.css +++ b/vuu-ui/packages/vuu-ui-controls/src/list/CheckboxIcon.css @@ -1,33 +1,59 @@ .vuuCheckboxIcon { - --vuu-icon-size: 12px; - --vuu-icon-left: -1px; - --vuu-icon-top: -1px; - --vuu-icon-svg: var(--vuu-svg-tick); - border-style: solid; - border-color: var(--vuuCheckboxIcon-borderColor, var(--salt-selectable-borderColor)); - border-radius: var(--vuuCheckboxIcon-borderRadius, 3px); - border-width: 1px; - display: inline-block; - height: var(--vuuCheckboxIcon-size, 12px); - position: relative; - width: var(--vuuCheckboxIcon-size, 12px); + --vuuCheckboxIcon-background-checked: var(--vuu-color-purple-10); + --vuu-icon-size: 12px; + --vuu-icon-left: -1px; + --vuu-icon-top: -1px; + --vuu-icon-svg: var(--vuu-svg-tick); + border-style: solid; + border-color: var( + --vuuCheckboxIcon-borderColor, + var(--salt-selectable-borderColor) + ); + border-radius: var(--vuuCheckboxIcon-borderRadius, 3px); + border-width: 1px; + display: inline-block; + height: var(--vuuCheckboxIcon-size, 12px); + position: relative; + width: var(--vuuCheckboxIcon-size, 12px); } -.vuuCheckboxIcon-checked { - background-color: var(--vuuCheckboxIcon-background-checked, var(--salt-selectable-background-selected)); - border-color: var(--vuuCheckboxIcon-borderColor-checked, var(--salt-selectable-borderColor-selected)); +.vuuCheckboxIcon-checked-enabled { + background-color: var( + --vuuCheckboxIcon-background-checked, + var(--salt-selectable-background-selected) + ); + border-color: var( + --vuuCheckboxIcon-borderColor-checked, + var(--salt-selectable-borderColor-selected) + ); } -.vuuCheckboxIcon-checked:after { - content: ""; - background-color: white; - left: var(--vuu-icon-left, auto); - height: var(--vuu-icon-height, var(--vuu-icon-size, 12px)); - -webkit-mask: var(--vuu-icon-svg) center center/var(--vuu-icon-size) var(--vuu-icon-size); - mask: var(--vuu-icon-svg) center center/var(--vuu-icon-size) var(--vuu-icon-size); - mask-repeat: no-repeat; - -webkit-mask-repeat: no-repeat; - position: absolute; - top: var(--vuu-icon-top, auto); - width: var(--vuu-icon-width, var(--vuu-icon-size, 12px)); -} \ No newline at end of file +.vuuCheckboxIcon-checked-enabled::after, +.vuuCheckboxIcon-checked-disabled::after { + content: ""; + background-color: white; + left: var(--vuu-icon-left, auto); + height: var(--vuu-icon-height, var(--vuu-icon-size, 12px)); + -webkit-mask: var(--vuu-icon-svg) center center/var(--vuu-icon-size) + var(--vuu-icon-size); + mask: var(--vuu-icon-svg) center center/var(--vuu-icon-size) + var(--vuu-icon-size); + mask-repeat: no-repeat; + -webkit-mask-repeat: no-repeat; + position: absolute; + top: var(--vuu-icon-top, auto); + width: var(--vuu-icon-width, var(--vuu-icon-size, 12px)); +} + +.vuuCheckboxIcon-checked-disabled { + --vuuCheckboxIcon-background-disabled: var( + --vuuCheckboxIcon-background-disbaled, + var(--salt-selectable-background-disabled) + ); + background-color: var(--vuuCheckboxIcon-background-disabled); + border-color: var(--vuuCheckboxIcon-background-disabled); +} + +.vuuCheckboxIcon-checked-disabled::after { + background-color: var(--vuu-color-gray-30); +} diff --git a/vuu-ui/packages/vuu-ui-controls/src/list/CheckboxIcon.tsx b/vuu-ui/packages/vuu-ui-controls/src/list/CheckboxIcon.tsx index 786107c484..4521b67e6b 100644 --- a/vuu-ui/packages/vuu-ui-controls/src/list/CheckboxIcon.tsx +++ b/vuu-ui/packages/vuu-ui-controls/src/list/CheckboxIcon.tsx @@ -9,13 +9,17 @@ const classBase = "vuuCheckboxIcon"; export interface CheckboxIconProps extends HTMLAttributes { checked?: boolean; + disabled?: boolean; } export const CheckboxIcon = ({ checked = false, + disabled = false, ...htmlAttributes }: CheckboxIconProps) => ( ); diff --git a/vuu-ui/packages/vuu-utils/src/component-registry.ts b/vuu-ui/packages/vuu-utils/src/component-registry.ts index cbb98a52c4..3264f0c681 100644 --- a/vuu-ui/packages/vuu-utils/src/component-registry.ts +++ b/vuu-ui/packages/vuu-utils/src/component-registry.ts @@ -149,18 +149,7 @@ export function getCellRenderer( cellType: "cell" | "col-content" | "col-label" = "cell" ) { if (cellType === "cell") { - if (isTypeDescriptor(column.type)) { - const { renderer } = column.type; - if (isColumnTypeRenderer(renderer)) { - return cellRenderersMap.get(renderer.name); - } - } - if (column.editable) { - // we can only offer a text input edit as a generic editor. - // If a more specialised editor is required, user must configure - // it in column config. - return cellRenderersMap.get("input-cell"); - } + return dataCellRenderer(column); } else if (cellType === "col-label" && column.colHeaderLabelRenderer) { return cellRenderersMap.get(column.colHeaderLabelRenderer); } else if (cellType === "col-content" && column.colHeaderContentRenderer) { @@ -168,6 +157,22 @@ export function getCellRenderer( } } +function dataCellRenderer(column: ColumnDescriptor) { + if (isTypeDescriptor(column.type)) { + const { renderer } = column.type; + if (isColumnTypeRenderer(renderer)) { + return cellRenderersMap.get(renderer.name); + } + } else if (column.serverDataType === "boolean") { + return cellRenderersMap.get("checkbox-cell"); + } else if (column.editable) { + // we can only offer a text input edit as a generic editor. + // If a more specialised editor is required, user must configure + // it in column config. + return cellRenderersMap.get("input-cell"); + } +} + export function getConfigurationEditor(configEditor = "") { return configEditorsMap.get(configEditor); } diff --git a/vuu-ui/showcase/src/examples/Table/TableNext.examples.tsx b/vuu-ui/showcase/src/examples/Table/TableNext.examples.tsx index d24afa0249..37001b38a0 100644 --- a/vuu-ui/showcase/src/examples/Table/TableNext.examples.tsx +++ b/vuu-ui/showcase/src/examples/Table/TableNext.examples.tsx @@ -191,6 +191,8 @@ export const EditableTableNextArrayData = () => { }, }, }; + case "wishlist": + return { editable: true }; } }, []