diff --git a/.changeset/big-kangaroos-enjoy.md b/.changeset/big-kangaroos-enjoy.md new file mode 100644 index 000000000..00e777956 --- /dev/null +++ b/.changeset/big-kangaroos-enjoy.md @@ -0,0 +1,5 @@ +--- +"@ensembleui/react-runtime": patch +--- + +enhance DataGrid with rowHoverBg and rowSelectedHoverBg styles diff --git a/apps/kitchen-sink/src/ensemble/screens/widgets.yaml b/apps/kitchen-sink/src/ensemble/screens/widgets.yaml index 5946ea866..f1fe97ae0 100644 --- a/apps/kitchen-sink/src/ensemble/screens/widgets.yaml +++ b/apps/kitchen-sink/src/ensemble/screens/widgets.yaml @@ -540,6 +540,9 @@ View: name: dummyData template: DataRow: + styles: + backgroundColor: lime + rowHoverBg: yellow children: - Text: id: ${'x_'+index} @@ -1131,6 +1134,8 @@ View: size: small value: true leadingText: Set to true and requred + htmlAttributes: + title: tooltip text - Card: styles: width: unset diff --git a/packages/runtime/src/widgets/Collapsible.tsx b/packages/runtime/src/widgets/Collapsible.tsx index 30b3843bf..19ce3913e 100644 --- a/packages/runtime/src/widgets/Collapsible.tsx +++ b/packages/runtime/src/widgets/Collapsible.tsx @@ -233,6 +233,12 @@ export const Collapsible: React.FC = (props) => { expandIconPosition={props.expandIconPosition} items={[...collapsibleItems, ...templateItems]} onChange={handleCollapsibleChange} + style={{ + ...values?.styles, + ...(values?.styles?.visible === false + ? { display: "none" } + : undefined), + }} /> ); diff --git a/packages/runtime/src/widgets/DataGrid/DataGrid.tsx b/packages/runtime/src/widgets/DataGrid/DataGrid.tsx index ce90bc336..49cbef07c 100644 --- a/packages/runtime/src/widgets/DataGrid/DataGrid.tsx +++ b/packages/runtime/src/widgets/DataGrid/DataGrid.tsx @@ -1,4 +1,4 @@ -import { Table, type TableProps } from "antd"; +import { Table, type TableProps, ConfigProvider } from "antd"; import type { SorterResult } from "antd/es/table/interface"; import isEqual from "react-fast-compare"; import { @@ -40,6 +40,7 @@ import type { EnsembleWidgetStyles, HasItemTemplate, } from "../../shared/types"; +import { getComponentStyles } from "../../shared/styles"; import { useEnsembleAction } from "../../runtime/hooks/useEnsembleAction"; import { EnsembleRuntime } from "../../runtime"; import { DataCell } from "./DataCell"; @@ -64,7 +65,13 @@ interface DataColumn { visible?: boolean; } -export interface DataGridStyles extends Partial { +export interface DataGridStyles + extends Partial< + EnsembleWidgetStyles & { + rowHoverBg?: Expression; + rowSelectedHoverBg?: Expression; + } + > { headerStyle?: { backgroundColor?: Expression; fontSize?: Expression; @@ -512,139 +519,158 @@ export const DataGrid: React.FC = (props) => { return (
- ({ - "data-index": recordIndex, - "data-record": record, - "data-styles": itemTemplate.template.properties.styles, - onClick: itemTemplate.template.properties.onTap - ? (): unknown => onTapActionCallback(record, recordIndex) - : undefined, - })} - pagination={paginationObject} - rowKey={(data: unknown) => { - const identifier: string = evaluate( - defaultScreenContext, - itemTemplate.key, - { - [itemTemplate.name]: get(data, itemTemplate.name) as unknown, + { - setRowsKey(selectedRowKeys); - setRowsSelected(selectedRows); - if (rest.onRowsSelected) { - onRowsSelectedCallback(selectedRowKeys, selectedRows); - } - }, - getCheckboxProps: (record) => { - return { - disabled: handleRowSelectableOrNot(record), - }; - }, - defaultSelectedRowKeys: values?.defaultSelectedRowKeys, - selectedRowKeys: rowsKey.length ? rowsKey : undefined, - } - : undefined - } - scroll={ - values?.scroll - ? { - y: values.scroll.scrollHeight, - x: values.scroll.scrollWidth || "max-content", - } - : undefined - } - style={{ - width: "100%", - ...values?.styles, - ...(values?.styles?.visible === false - ? { display: "none" } - : undefined), - }} - tableLayout="auto" - virtual={values?.virtual} > - {dataColumns.map((col, colIndex) => { - return ( - ({ - text: label, - value, - }))} - hidden={col.visible === false} - key={colIndex} - minWidth={col.width ?? 100} - onFilter={ - col.filter?.onFilter - ? (value, record): boolean => - Boolean( - evaluate(defaultScreenContext, col.filter?.onFilter, { - value, - record, - [itemTemplate.name]: get( - record, - itemTemplate.name, - ) as unknown, - }), - ) - : undefined - } - onHeaderCell={ - values?.allowResizableColumns - ? () => ({ - width: col.width, - onResize: handleResize( - colIndex, - ) as ReactEventHandler, - }) - : undefined - } - render={(_, record, rowIndex): ReactElement => { - return ( - - ); - }} - shouldCellUpdate={(record, prev) => !isEqual(record, prev)} - sorter={ - col.sort?.compareFn - ? (a, b): number => - Number( - evaluate(defaultScreenContext, col.sort?.compareFn, { - a, - b, - }), - ) - : undefined - } - title={col.label as string | React.ReactNode} - width={col.width} - /> - ); - })} -
+ ({ + "data-index": recordIndex, + "data-record": record, + "data-styles": itemTemplate.template.properties.styles, + onClick: itemTemplate.template.properties.onTap + ? (): unknown => onTapActionCallback(record, recordIndex) + : undefined, + })} + pagination={paginationObject} + rowKey={(data: unknown) => { + const identifier: string = evaluate( + defaultScreenContext, + itemTemplate.key, + { + [itemTemplate.name]: get(data, itemTemplate.name) as unknown, + }, + ); + if (identifier) { + return identifier; + } + const res = djb2Hash(JSON.stringify(data)); + return String(res); + }} + rowSelection={ + allowSelection + ? { + columnWidth: values?.selectionColWidth, + type: selectionType, + onChange: (selectedRowKeys, selectedRows): void => { + setRowsKey(selectedRowKeys); + setRowsSelected(selectedRows); + if (rest.onRowsSelected) { + onRowsSelectedCallback(selectedRowKeys, selectedRows); + } + }, + getCheckboxProps: (record) => { + return { + disabled: handleRowSelectableOrNot(record), + }; + }, + defaultSelectedRowKeys: values?.defaultSelectedRowKeys, + selectedRowKeys: rowsKey.length ? rowsKey : undefined, + } + : undefined + } + scroll={ + values?.scroll + ? { + y: values.scroll.scrollHeight, + x: values.scroll.scrollWidth || "max-content", + } + : undefined + } + style={{ + width: "100%", + ...values?.styles, + ...(values?.styles?.visible === false + ? { display: "none" } + : undefined), + }} + tableLayout="auto" + virtual={values?.virtual} + > + {dataColumns.map((col, colIndex) => { + return ( + ({ + text: label, + value, + }))} + hidden={col.visible === false} + key={colIndex} + minWidth={col.width ?? 100} + onFilter={ + col.filter?.onFilter + ? (value, record): boolean => + Boolean( + evaluate( + defaultScreenContext, + col.filter?.onFilter, + { + value, + record, + [itemTemplate.name]: get( + record, + itemTemplate.name, + ) as unknown, + }, + ), + ) + : undefined + } + onHeaderCell={ + values?.allowResizableColumns + ? () => ({ + width: col.width, + onResize: handleResize( + colIndex, + ) as ReactEventHandler, + }) + : undefined + } + render={(_, record, rowIndex): ReactElement => { + return ( + + ); + }} + shouldCellUpdate={(record, prev) => !isEqual(record, prev)} + sorter={ + col.sort?.compareFn + ? (a, b): number => + Number( + evaluate( + defaultScreenContext, + col.sort?.compareFn, + { + a, + b, + }, + ), + ) + : undefined + } + title={col.label as string | React.ReactNode} + width={col.width} + /> + ); + })} +
+